Commit Graph
303 Commits
Author SHA1 Message Date
pasmudandCommandCodeBot cee58ba39e fix(control-pane): settle the poll guard against the last settled request
The staleness guard compared a poll against the newest poll STARTED, and
only the failure path used it. Two orderings were wrong.

An older success settling after a newer one had no guard at all, so it
overwrote the newer counts, the canvas label and the announcement with
older data. Both paths now check the token.

An older failure settling while a newer poll was still in flight was
discarded, because a newer poll had merely started. The page then kept
the last successful counts and its no-steering message as if they were
current. Anchoring the guard to the newest poll that has SETTLED fixes
that: the older failure is still the newest thing to have settled, so it
lands, and the pending poll restores the view when it answers.

That single change covers both orderings, so the guard no longer needs
to know which path it is on. Each poll records itself as settled when it
finishes, whatever the outcome.

A poll also had no timeout, so a request that never answered left the
last steering guidance on screen indefinitely. Each poll now aborts
after ten seconds through an AbortController, and that abort is what
wakes the poll, so a timeout is reported as an outage instead of
silently leaving stale guidance.

The test harness can now hold a request open indefinitely and fire
pending timers on demand, so the timeout is exercised without waiting.
New assertions cover an older success losing to a newer one, an older
failure landing while a newer poll is in flight and then being
recovered by it, and a hung poll timing out into the offline state.
Removing the success guard, re-anchoring the guard to the last started
poll, and removing the timeout each fail one of those assertions, and
the unmutated file passes all of them.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-09-27 08:11:44 +00:00
pasmudandCommandCodeBot e97e333040 fix(control-pane): keep the canvas label and live region consistent
Two ways the outage state could mislead an operator reading either
channel.

The failure branch cleared the live region but left the canvas
aria-label holding the counts from the last successful poll, so landing
on the canvas during an outage reported stale counts. It now sets the
same unavailable wording on the canvas. apply() already restores the
count label on the next valid poll, and there is now a test for that.

Polls run every 5000ms and are not sequenced, so a slow older request
can settle after a newer one has succeeded. Its catch block then
announced an outage while the canvas showed the newer counts, and the
two channels contradicted each other. Each poll now takes a monotonic
token and only the newest one may touch the view, so a superseded
failure is dropped.

The runtime test can park a response, which lets it settle an older
failure after a newer success. New assertions cover the canvas label
after an outage, the restored label after recovery, and the
superseded-failure case. Removing the canvas reset, the token guard, or
the restore in apply() each fail an assertion, and the unmutated view
passes all of them.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-09-27 02:44:18 +00:00
pasmudandCommandCodeBot 9e0996c6d6 fix(control-pane): replace stale live-region guidance when a poll fails
The live region announced the advisory and steering state on every
change, but a failed or invalid poll only set the visible status to
offline. The live region kept the last known message, so during an
outage a screen-reader user could still hear "No steering is required"
from a poll that had already failed. That is worse than silence,
because stale guidance reads as current.

Route announcements through a single helper and have the failure path
replace the guidance with a message saying the data is unavailable and
the counts are unknown. The helper still suppresses a repeat of the
same message, so a continuing outage stays quiet and recovery speaks
again.

Cover the success then failure and failure then recovery sequences at
runtime. Reverting just the failure-path announcement fails the new
assertion, and the unmutated view passes all of them.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-09-27 02:01:44 +00:00
pasmudandCommandCodeBot 6744a01748 fix(control-pane): announce polled advisories through a live region
The control-plane view polls every few seconds and rewrites the canvas
aria-label with the new counts, but neither the canvas nor #status is a
live region, so a screen-reader user working elsewhere never hears an
advisory appear.

Add a visually hidden polite live region that speaks only when the
advisory and steering counts actually move. Re-announcing an unchanged
summary every five seconds would talk over the operator without saying
anything new, so the last announced pair is remembered and a no-change
poll writes nothing. The canvas keeps its own label as the on-demand
description.

Also give the runtime test a recording canvas context and a populated
view, so the rendered risk words, the marker shapes, and the live region
are asserted at runtime rather than only against template source. The
risk-level assertion now reads the rendered risk cells instead of the
whole panel, where a level word could be satisfied by a task id.

The populated assertions were mutation checked: collapsing the marker
shapes, dropping the risk words, freezing the canvas label, announcing
on every poll, emptying the live region, and removing the steering cue
each fail at least one assertion.

Fixes the no-regex-spaces lint error on the riskColor match, which used
two literal spaces in a row.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-09-27 00:46:39 +00:00
pasmudandCommandCodeBot 3052732f28 fix(control-pane): add non-color risk cues to the control-plane view
The control-plane projection encoded risk with hue alone. The clear
green #3fb950 and the resolution red #ff7b72 differ by only 1.01:1 in
relative luminance, so a red-green color-blind operator saw the same
grey for "clear" and "steer now".

Risk now carries a second, non-color channel, matching the pattern
merged for the sibling airspace view in #3193:

- markers are drawn as a circle, square, or triangle per risk level
- the legend shows the matching glyph instead of color-only dots
- the Lanes panel prints the level name next to the percentage
- the canvas gets role="img" and a live aria-label describing counts

The clear green also moves to #2ea043 so it stays separable from the
resolution red by luminance (1.34:1) while keeping 5.73:1 against the
#0b0e14 background.

Adds tests/lib/control-plane-view-ui-a11y.test.js covering the roles,
the shapes, the legend, and the contrast ratios. The existing test
harness needed a setAttribute stub for the new aria-label update.

Co-Authored-By: CommandCodeBot <noreply@commandcode.ai>
2026-09-26 22:52:34 +00:00
asp d7cf4584cf fix: restore Claude plugin setup compatibility (#3205)
* fix: stop passing removed Claude plugin config flags

* test: cover current Claude plugin install arguments

* docs: add beginner Windows install walkthrough
2026-09-21 14:32:26 -04:00
Tamer 2b6e839771 Fix/proximity a11y risk cues (#3193)
* fix(control-plane): add non-color airspace risk cues

* test(control-plane): cover airspace accessibility cues
2026-09-20 15:37:57 -04:00
Tamer 651118bd50 Fix/control plane canvas size (#3192)
* fix(control-plane): constrain visualization canvas layout

* fix(control-plane): constrain visualization canvas layout

* test(control-plane): guard bounded canvas layout
2026-09-20 15:37:51 -04:00
Tamer 9606a741af fix(control-pane): handle proximity HTTP errors (#3191) 2026-09-20 15:37:47 -04:00
auyua9andauyua9 9ac593b55c fix(scripts): extract cross-platform openBrowser helper with structured launch result (#3180)
scripts/plan-canvas.js and scripts/control-pane.js both define their own
openBrowser helpers for launching the user's default browser. The two
implementations have diverged:

- plan-canvas.js dispatches across darwin/win32/linux but its
  try/spawn try/catch does not catch async child errors (ENOENT/EACCES
  on hosts without the launcher command). Returns a bare true/false.
- control-pane.js is darwin-only and silently returns early on
  Windows/Linux, so the two scripts behave inconsistently across
  platforms.

When the launcher command is missing (e.g. headless CI without xdg-open)
the JSON output still says 'browser: opened', lying to the agent.

Changes:
- scripts/lib/platform-launch.js: shared openBrowser helper that
  dispatches per platform, wires child 'error' so ENOENT/EACCES
  propagate, and returns {opened, reason} instead of a bare boolean.
- scripts/plan-canvas.js: drops its local helper, imports the shared
  one, and adds browserReason to its JSON output.
- scripts/control-pane.js: replaces its darwin-only branch with the
  shared helper and logs the structured reason on failure.
- tests/lib/platform-launch.test.js: 7 node:test cases covering
  opener-command selection, invalid-URL guard, structured-result
  shape, and a smoke run for the actual spawn.

Verification: node --test tests/lib/platform-launch.test.js → 7/7 pass.

Co-authored-by: auyua9 <auyua9@users.noreply.github.com>
2026-09-20 14:26:52 -04:00
Eastern 95448ad81d fix: isolate Claude project hooks from ESM hosts (#3184)
* fix: isolate Claude project hooks from ESM hosts

* fix: handle user-owned Claude scripts package
2026-09-20 14:26:49 -04:00
Affaan Mustafa fc9273e5e0 Merge pull request #3126 from VarunGore36/fix/reviewer-followups
fix(security): security follow-ups for worker, installer, claw, hooks
2026-09-19 19:58:43 -04:00
Affaan Mustafa b2279eb1d7 Merge pull request #3130 from shoyann/fix/preserve-codex-user-config
fix: preserve edited Codex user configuration during reinstall and repair
2026-09-19 17:09:20 -04:00
Affaan Mustafa 0a5207b6f2 Merge pull request #3102 from wellkilo/perf/metrics-tail-read
perf(metrics): cache cumulative session costs
2026-09-19 17:00:05 -04:00
Affaan Mustafa f6eb800474 fix(session-start): scope summary lookup to repository identity (#3160) (#3168)
Windows: compare repo identity via normalizeRepoPath/sameRepoIdentity (8.3 short names, case, separators; inode fallback). All nine windows-latest jobs green on 52587005.
2026-09-19 02:08:50 -04:00
Affaan Mustafa c023a8e5a7 Merge branch 'main' into fix/3116-home-install-exclusions 2026-09-18 21:03:28 -04:00
Affaan Mustafa 8cfbc26797 fix: reconcile pre-exclusion .agents installs on claude and codex home upgrades 2026-09-18 20:13:11 -04:00
He Dong 8bf16ccfec fix(hooks): keep silent hook paths silent (#2987)
* fix(hooks): keep silent hook paths silent

* fix(hooks): harden stream failure handling

* fix(hooks): settle interrupted input streams

* test(hooks): name stream input limits

* test(hooks): isolate PostToolUse dispatcher fixtures
2026-09-18 18:42:20 -04:00
Affaan Mustafa da214d73b7 fix: stop home installs copying .agents into ~/.claude and ~/.codex 2026-09-18 18:37:05 -04:00
Yann Roberto c0ee747789 fix: preserve edited Codex user configuration 2026-09-15 14:47:27 +08:00
Geronimo a3c24818bb fix(security): provider error taxonomy, tool leak hardening, hook gate, atomic cleanup
- ollama: connection failures -> LLMError(connection_error), unknown -> LLMError(provider_error); auth only on real 401
- executor: generic model-facing tool failure, diagnostics to logs; add execute_async/all_async; ReActAgent returns structured provider_error
- run-with-flags.js: gate require() on concrete run-export syntax, not bare word match
- codex-legacy-sync: remove tmp file on atomicWriteJson failure
- tests: async tool + ReActAgent awaitable regression coverage
2026-09-14 13:49:18 +05:30
wellkilo 76329557c4 test(metrics): derive oversized fixture from scan cap
Export the internal scan budget for regression tests and size the oversized-line fixture as exactly two bounded passes.
2026-09-13 05:14:26 +08:00
wellkilo 987c1e103f fix(metrics): bound incremental snapshot recovery
Cap JSONL line buffering and per-hook catch-up work, persist discard cursors for oversized records, report retention failures, normalize malformed token totals, and strengthen bounded-read regression fixtures.
2026-09-13 04:55:52 +08:00
wellkilo 1b12e19c63 fix(metrics): address incremental snapshot review
Replace global log-signature invalidation with per-session byte-offset cursors, preserve unterminated rows until committed, bound snapshot retention, and persist warning deduplication with atomic cross-process claims. Add regression coverage for concurrent writers, malformed data, rewrites, retention, UTF-8 boundaries, and concurrent warning emission.
2026-09-13 03:41:08 +08:00
wellkilo e1805d7deb perf(metrics): cache cumulative session costs 2026-09-13 01:52:26 +08:00
Affaan Mustafa 8321021c54 fix(memory): classify directory traversal failures 2026-09-12 07:45:40 -04:00
Affaan Mustafa 90ef62cb1d fix(memory): distinguish incomplete reads from missing records
Independent local Codex review PASS at 73b07f8d17, no P0/P1. Independent 66 tests and strict validation of 810 skills passed. CI run 34683976362 passed; all 48 current checks green. Incomplete memory reads fail closed with safe MCP diagnostics; canonical guidance synchronized across harness skill copies. Rollback: revert this squash commit. No deployment or installation claim.
2026-09-12 05:52:29 -04:00
Affaan Mustafa ab1f1a09ba feat: group verified capsules into offline retrospective reports
Independent local Codex review PASS at 472cfa94fb, no P0/P1. Independent retrospective, CLI, envelope and capsule tests: 73 passed. CI run 34664487219 attempt 2 passed all 42 jobs. Read-only offline capsule grouping only; no provenance, scoring, execution or promotion claim. Rollback: revert this squash commit.
2026-09-12 04:35:38 -04:00
Affaan Mustafa 1ed03ecf2e feat(control-pane): live control-plane view with 2D projection and static-threshold advisories
Exact-head independent local Codex review PASS with no P0/P1. CI run 34680860653 attempt 2 passed at 0707cd431c. Includes HTTP/schema failure handling, coalesced sampling cache and regression tests. Disclosed P2 follow-ups remain in the merge-queue receipt. Rollback: revert this squash commit. No deployment or publication claim.
2026-09-12 04:17:37 -04:00
zpearce-2814 1ac07903ec fix(hooks): keep hooks.json within Claude Code's schema
Move stable hook metadata to a validated sidecar while preserving hook commands and installer identity. Reject moved fingerprints and duplicate IDs, and validate before updating metadata. Independent local review passed at c315271624a1fd055b992f2bff889ad2a0ff8a6b; CI run 34678210149 passed. Rollback: revert this squash commit.
2026-09-12 02:59:02 -04:00
Wu Shuwen 3033436dcc fix: filter epic sync issues by label (#3089)
github-coordination sync listed every repo issue and pushed the epic label onto all of them (#3084). Scope the listing to issues carrying the policy's epic label plus issues whose body still holds the coordination marker (label-drift recovery), deduped by number, and reject an empty labels.epic in loadPolicy. Tests cover the filtered path and the recovery path with exact gh argv. Independent exact-head review passed with no P0/P1; CI 44/44 at the head.
2026-09-12 01:46:04 +01:00
Dante d3af582bad fix: handle Windows settings file identity 2026-09-10 15:01:03 -04:00
Affaan MustafaandClaude Fable 5.1 f8640355e4 Consolidate recovered eval framework and operator workflows (#3040)
* feat: consolidate offline eval and operator workflows

Compose the retained framework, operator skill, roadmap and cleanup ranges on current main. Preserve current release dependencies and keep candidate execution disabled pending OS containment. Repair draft/DOCX behavior, obligation uniqueness, trusted send and audience guidance, runner provenance and eval diagnostics.

Source-PR: 2930 0abe3727d2b500c6e4830bdeb47ed67cae3f4785
Source-PR: 2931 992b49c44ed872def49675b791168b8fcd091df6
Source-PR: 2932 4a193dd13041cb7a6bebf4d2e910a0cd32bcc797
Source-PR: 2933 59cdfe500a91949ba1415f1edd7279620f21e804
Source-Base: ca185ef5f7

* fix: repair foundation CI and update js-yaml

* fix: reconcile pending-delete capsule locks after close

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-10 13:20:52 +01:00
Affaan Mustafa c7d62c0c6a Distinguish declared goals, open sessions and overlap risk in coordination inventory (#3028)
* feat: add read-only coordination inventory and overlap evaluation

* test: make coordination process fixtures platform explicit

* test: report bounded Stop wrapper failure diagnostics

* test: clean up failed memory MCP sessions deterministically

* fix: update js-yaml to patched 4.3.2

* feat(coordination): distinguish declared goals from open sessions
2026-09-10 14:11:51 +03:00
haelyra 14e731c6d5 fix: close release review gaps and expose failing CI suites 2026-09-07 17:57:26 -04:00
haelyra ba3a64a2c5 fix(setup): preserve preflight guarantees across ownership filtering 2026-09-07 16:53:53 -04:00
59b74901c4 fix(install): preserve user files and honor uninstall previews
Generalize PR #2981 ownership protection to every managed target. Reject mismatched target state and preserve files that appear during writes or failed-install checkpoints. Keep prior hashes for managed files a failed attempt never writes.

Integrate PR #2980 preview wording and global dry-run propagation, with PR #2956 fail-closed environment validation and CLI/legacy regression coverage.

Fixes #2964. Fixes #2952.

Co-authored-by: ilkmajans-cpu <ilkmajans-cpu@users.noreply.github.com>

Co-authored-by: wellkilo <wellkilo@foxmail.com>
2026-09-07 16:40:47 -04:00
haelyra 967a5fa4ba Merge reviewed Claude hook registration and settings containment fixes 2026-09-07 16:38:41 -04:00
haelyra 17b70f56fc Merge reviewed PowerShell enforcement fixes for 2.2.1
# Conflicts:
#	tests/hooks/gateguard-fact-force.test.js
2026-09-07 16:38:41 -04:00
haelyra dbe8bfbba9 fix(install): pin Claude settings parent during atomic replacement
Reject directory replacement after temporary file creation or staging, preserve unrelated files during cleanup, and retry settings edits observed before the final rename. Add three regression tests for the review findings.
2026-09-07 16:31:33 -04:00
wakqasahmed fe3d82e280 fix(install): derive dependency versions from package.json, harden fixture isolation (#2822)
Addresses Greptile's review on #2994:

- missing-dependency.js no longer hardcodes a second copy of the four
  runtime dependency versions; it reads them from package.json's
  dependencies field instead, so the two can't silently drift apart.
  describeMissingDependencyError() still recognizes a tracked
  dependency even if package.json can't be read for some reason,
  just without a version-pinned install command in that case.
- The regression test now asserts no ancestor directory of its
  temp fixture has a node_modules, so a stray one wouldn't let
  Node resolve ajv/sql.js from there and mask what the test is
  actually meant to exercise. Also copies package.json into the
  fixture, matching a real plugin-marketplace git clone and what
  the version-lookup above now needs.
2026-09-07 16:26:10 -04:00
wakqasahmed ce11e8f690 fix(install): ship ajv/sql.js with the plugin install bundle (#2822)
install-plan.js and install-apply.js both require ./lib/install/config at
load time, and that module required ajv unconditionally at the top of the
file even though ajv is only actually used when validating an
ecc-install.json. When ECC is installed via the Claude Code plugin
marketplace, the marketplace directory is a bare git clone with no
node_modules, so requiring ajv crashes commands like --list-profiles that
never touch install-config validation at all.

Same root cause in scripts/lib/control-pane/state.js: sql.js and
@iarna/toml were required at module scope even though they are only used
inside openSqlDatabase() and readTomlConfig(), so control-pane.js --help
crashed too.

Make both requires lazy so they only load when the feature that actually
needs them runs. For the case where ajv/sql.js/js-yaml/@iarna-toml is
genuinely needed and still missing, add a small helper that turns the raw
MODULE_NOT_FOUND into an actionable message naming the package and the
install command, instead of a stack trace (install-apply.js) or, worse, an
unhandled crash with a usage banner tacked on that reads like a bad
argument (install-plan.js, control-pane.js). Applied the same helper to
memory-mcp.mjs, where ajv is genuinely load-bearing (it compiles every MCP
tool's JSON schema up front) so it can't be made lazy the same way.

Added a regression test that copies just scripts/, schemas/, and
manifests/ into a directory with no node_modules anywhere above it in the
filesystem, which reproduces the plugin-marketplace install exactly, and
asserts install-plan.js and control-pane.js still work.
2026-09-07 16:26:10 -04:00
haelyra bf0ac4e4b3 fix: reject late PowerShell scalar resolution 2026-09-07 16:23:30 -04:00
wellkilo f59cfd57c2 fix(install): harden Claude settings lifecycle 2026-09-07 01:57:04 +08:00
wellkilo 26d3e0038b fix(install): surface Claude settings failures 2026-09-07 01:13:20 +08:00
wellkilo 569e5a36bb feat(install): register manual Claude hooks 2026-09-07 00:53:13 +08:00
haelyra db88758cbd fix: preserve linear PowerShell tokenization 2026-09-05 17:47:26 -04:00
haelyra 99668f0ef5 fix: resolve nested PowerShell command tokens 2026-09-05 17:38:20 -04:00
haelyra cb5311222d fix: scan inline PowerShell command parameters 2026-09-05 17:29:02 -04:00
haelyra f43195a255 fix: expand nested PowerShell command scalars 2026-09-05 16:57:10 -04:00