Commit Graph
402 Commits
Author SHA1 Message Date
affaan-m d0dc1fcb08 fix(install): preserve OpenCode refusal for relative source roots
Keep historical fingerprints independent of source discovery and normalize explicit repository roots at doctor and repair entry points. Preserve unknown user plugins and absolute-only low-level source probing.

Source-PR: https://github.com/affaan-m/ECC/pull/3008
Reviewed-Manifest-SHA256: fe1444b12dfb730524970a51b6bb805271cdfa71d4cc9b247772e6d9b1d1c9d8
2026-09-27 23:40:43 -04:00
affaan-m d2ce0b58dd Merge reviewed contributor PR #3241 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3241
Source-Head: 83f19dee14

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:36:51 -04:00
affaan-m 75dec47278 Merge reviewed contributor PR #3213 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3213
Source-Head: 1394cf6f0a

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:36:51 -04:00
affaan-m e6cd4498ef Merge reviewed contributor PR #3243 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3243
Source-Head: cfe6d90d9f

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:36:51 -04:00
affaan-m 0656f7af0b Merge reviewed contributor PR #3235 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3235
Source-Head: aff9c64560

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:36:51 -04:00
affaan-m b66584c445 Merge reviewed contributor PR #3244 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3244
Source-Head: 5ffe239ee5

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:36:50 -04:00
affaan-m f2835aacf3 Merge reviewed contributor PR #3121 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3121
Source-Head: 9f64ff2c3d

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:35:42 -04:00
affaan-m 3587ba70b9 Merge reviewed contributor PR #3210 into backlog batch
Source-PR: https://github.com/affaan-m/ECC/pull/3210
Source-Head: f5d0fcc7e1

Local integration checkpoint; aggregate review and hosted acceptance pending.
2026-09-27 23:35:42 -04:00
affaan-m cfe6d90d9f fix(control-plane): preserve accessible state across poll races 2026-09-27 22:55:11 -04:00
affaan-m e9911d6668 fix(opencode): preserve primary failures through complete lock cleanup 2026-09-27 22:41:08 -04:00
affaan-m dbeb723218 fix(plan-canvas): bind bounded artifact reads to verified descriptors 2026-09-27 22:23:33 -04:00
affaan-m 429384f80c fix(opencode): refuse known legacy hooks without consent 2026-09-27 22:12:34 -04:00
affaan-m 1394cf6f0a Merge current main and verify PowerShell foreach classification 2026-09-27 22:05:48 -04:00
affaan-m 506f25fb54 fix(plan-canvas): confine artifact assets and sandbox SVG documents
Preserve the contributor security repair and current main. Apply the artifact sandbox to SVG document responses and report unavailable symlink checks separately from passing assertions.

Source-PR: https://github.com/affaan-m/ECC/pull/3241
Source-Head: d237e1972f
Integration-Main: d3b8a3e908
2026-09-27 21:39:24 -04:00
affaan-m f5d0fcc7e1 fix(install): reconcile UTF-8 BOM support with current main
Preserve the contributor commits and current main changes.

Source-PR: https://github.com/affaan-m/ECC/pull/3210
Source-Head: 94ca2de35e
Integration-Main: d3b8a3e908
2026-09-27 21:35:30 -04:00
affaan-m 6dc706fe85 fix(install): distinguish user plugins from ECC aliases
Attribute unrecorded OpenCode aliases only to exact trusted ECC source or build bytes while keeping planned and recorded destinations strict. Pass the trusted source root through repair plans and preserve unrelated user plugin files.
2026-09-27 21:23:11 -04:00
affaan-m aff9c64560 fix(control-pane): preserve snapshot integrity during failed refreshes 2026-09-27 21:03:37 -04:00
affaan-m 5ffe239ee5 fix(tests): reconcile launcher coverage with current main 2026-09-27 21:03:37 -04:00
affaan-m 923019d99f fix(opencode): preserve consent ownership through guarded install and repair 2026-09-27 20:32:22 -04:00
affaan-m 80b9339727 Merge current main into PR #3121, preserving reviewed contribution 2026-09-27 20:26:25 -04:00
haelyra befde0d2cd fix(profiles): bind routing receipts and harden review paths 2026-09-27 18:01:40 -04:00
haelyra 0765f7a2ca feat(profiles): add opt-in Lean/Full and hybrid Auto selection 2026-09-27 16:46:07 -04:00
pasmudandCommandCodeBot d42d918bd3 fix(control-pane): stop a stale poll lowering the staleness mark
The settled-token guard correctly ignored an older poll, but that poll
still set settledPoll to its own token on the way out. With three polls
settling in the order 3, 1, 2, the ignored poll 1 pulled the mark back
to 1, so the even older poll 2 then passed the guard and replaced poll
3's counts, or marked a healthy view offline.

The mark now only moves forward. A poll that settles late is itself
stale, so it has no business moving the mark at all.

Covered by a new runtime case that settles three polls out of order as
3, 1, 2, once with an older success and once with an older failure. The
success case catches the counts regressing, the failure case catches a
healthy view being marked offline. Reverting the fix trips each of them
independently, and the unmutated file passes all 21.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
2026-09-27 14:03:13 +00:00
Seekers2001 2b35e299ea test: cover launcher error handling 2026-09-27 17:32:44 +08:00
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
WRG d237e1972f fix(scripts): sandbox HTML siblings, link-name MIME, portable fixtures
Review follow-ups: serve text/html sibling assets under the artifact sandbox CSP (direct navigation no longer bypasses it); resolve MIME from the request name first with target extension as fallback; make security fixtures cross-platform (no angle brackets in filenames, skip when symlink creation is denied). Residual check-then-read TOCTOU documented as accepted for the loopback-local threat model. Tests 33/33 GREEN, ESLint clean.
2026-09-26 02:39:42 +10:00
WRG 742395bca7 fix(scripts): confine plan-canvas artifact assets and escape 404 paths
Serve artifact pages with a sandbox-only CSP mirroring the viewer iframe, fail-closed realpath confinement for sibling assets, and escape the artifact path in the missing-artifact 404. TDD: 4 RED failures (CSP header, 404 escaping, symlink escape) before the fix, 31/31 GREEN after; markdown/sessions/hook suites and ESLint clean.
2026-09-26 02:14:24 +10:00
L4XB 217f303713 fix(control-pane): fail a load whose snapshot cannot be shown, and run the shown query
render() ran after load()'s ordered failure path and after shownLoad
had moved on. A snapshot the board could not show (a session whose
detectedHarnesses is stored as an object) threw past the ordering, and
an older valid snapshot could no longer take the board. render() now
runs inside that path, and shownLoad moves only once it returns.

Run posted state.query, the query typed last. When an older load
succeeds after a newer one failed, the board shows the older query's
results and recall command while Run acted on the newer query. Each
load now keeps its query, render() records it for the board, and Run
posts that.

The test harness assigns new arrays instead of pushing onto
page.pending, and records requests the same way.
2026-09-25 06:45:11 +02:00
L4XB a82d587e3f fix(control-pane): order data and outcomes of every load separately
Two cases the finished-load rule got wrong. When the first snapshot was
still loading and a live refresh failed, the first snapshot arrived
late and was dropped, leaving the pane empty. And manual loads, the
Refresh button and a query, reported their failures outside the
ordering, so a late manual failure could cover newer data and an older
success could clear a newer manual failure.

The board now shows the newest data any load brought, and the error
box the outcome of the newest load that has finished. load() reports
its own fetch failures, as a live-refresh failure when the interval
started it and as a plain error otherwise, so every load is ordered the
same way. Data that arrives after a newer failure still shows, and the
failure stays, dated by that data.
2026-09-25 04:59:07 +02:00
L4XB 928a295247 fix(control-pane): let the newest finished load decide the board
A newer refresh that failed was shown, and then an older one that
succeeded cleared the message, so the board looked live although no
load that started after the failed one had succeeded.

The board now follows the newest load that has finished, with its data
or with its failure. A load that finishes after a newer one leaves the
board alone: its data is not rendered and its failure is not reported.
This also keeps a late response from replacing newer data.
2026-09-25 03:12:40 +02:00
L4XB 9848380309 fix(control-pane): judge a failed refresh by the loads that started after it
A failed refresh was dropped whenever any load finished while it ran.
When two interval refreshes overlapped and the older one succeeded, the
newer one's failure was dropped too, so the board looked live although
its latest refresh had failed.

Loads are now numbered as they start. A failure is dropped only when
the board shows data from a load that started after it.
2026-09-25 02:55:35 +02:00
L4XB 10969f587b fix(control-pane): keep a superseded refresh failure off the board
A live refresh that fails after a newer load has already replaced the
board no longer describes what is shown, so it is only reported while
the data it was meant to replace is still on screen. The time of that
data now includes its date, for a pane left open overnight, and it is
kept in its own binding instead of on the shared state object.
2026-09-25 00:07:08 +02:00
L4XB 0ae2fa06a4 fix(control-pane): report a failed live refresh instead of discarding it
The 15-second refresh caught every error with `load().catch(() => {})`,
so a control pane that had lost its server kept showing the last
snapshot as if it were current. A failed refresh now shows the error box
with "Live refresh failed. The data below is from <time>." and the
error, and the next successful refresh clears it, as load() already
clears the box.

The new test runs the served page script in a vm with a stand-in for the
browser APIs it uses, fails a refresh, and checks both transitions.

Fixes #3176
2026-09-24 23:25:13 +02:00
Dante 306c217729 fix: scan piped foreach grouping blocks 2026-09-23 01:37:51 +08:00
Dante 61c230c163 fix: distinguish PowerShell foreach statements 2026-09-23 00:52:28 +08:00
Varun GoreandGitHub 43a91f66ed Merge branch 'affaan-m:main' into main 2026-09-22 19:58:56 +05:30
Yann Roberto 94ca2de35e fix(install): accept UTF-8 BOM in install configs 2026-09-22 21:04:57 +08:00
Dante 7371f035da merge: reconcile Polish locale with current main 2026-09-22 12:23:52 +08:00
aspandGitHub 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
Md. Kishor MorolandKishor Morol 300694069f chore: merge main into Bengali integration
Resolve the 3 conflicts from 104 upstream commits (2.2.1 -> 2.2.2).

Merge resolution:
- .claude-plugin/plugin.json, .claude-plugin/marketplace.json: take the
  upstream 2.2.2 version bump, keep the catalog counts at 69 agents /
  293 skills. Upstream released 2.2.2 still describing 68/292, so neither
  side could be taken whole.
- docs/ja-JP/README.md: upstream restructured the page, moving the hero
  above the fold and replacing both markdown language selectors with a
  single centered HTML block that also gained Español. Take that structure
  and re-add বাংলা to the new selector.
- rules/common/agents.md: merged clean, but the roster line main added
  reads "68 agents". Resync to 69 alongside the other catalog counts.

Verified: catalog.js reports 69 agents / 293 skills and confirms the
documentation counts match the repository catalog; the nine CI validators
and the command-registry check pass; bengali-language-surface.test.js is
7/7, including the selector and locale-parity assertions.

Co-Authored-By: Kishor Morol <kishormorol@gmail.com>
2026-09-20 19:28:18 -04:00
TamerandGitHub 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
TamerandGitHub 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
TamerandGitHub 9606a741af fix(control-pane): handle proximity HTTP errors (#3191) 2026-09-20 15:37:47 -04:00
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
EasternandGitHub 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
Geronimo 5191a908d1 refactor: split install-lifecycle god-module, harden test runner and lint
Extract contained-fs (TOCTOU-safe fs ops) and json-ops helpers into scripts/lib/install/. install-lifecycle 2453->1957 lines, public API unchanged (66/0 lifecycle tests pass). Harden tests/run-all.js with exit-code-first verdict, TAP fallback, file-level counts and filter arg. Add warn-level eslint guards (prefer-const, complexity, max-depth, max-params). Split test scripts into test:validators/test:js/test:python and coverage:js/coverage:python.
2026-09-20 20:46:45 +05:30