The previous fix stopped a throwing hook from aborting the cold replay by
recording it as an allow, matching the warm path. But coldSummary only counted
disagreements, so a failure on a step the worker also allowed was no
disagreement and left no trace: the report showed no failure, a run with no
measured step reported a cold latency of 0 ms because percentile of an empty
list is 0, and the exit status passed. Trading a crash for a clean-looking
success hid exactly the failure the crash had exposed.
coldSummary now counts errors and samples, and reports no latency when nothing
was measured rather than a 0 that reads as a fast hook. The report prints "no
valid sample" in place of a latency and adds a line for steps that failed in a
fresh process, beside the existing disagreement line. The exit check moves into
gateFails, which fails on cold errors as it already did on warm errors and cold
disagreements, and is exported with coldSummary so both can be tested.
The render test builds its report from summarize([]), the real summary shape,
so it keeps working as metrics are added.
measureColdLatency ran each step in a fresh process through execFileSync,
inside try/finally with no catch. A hook that threw made the child exit
non-zero, execFileSync threw, and the error left measureColdLatency and then
evaluate, so neither the report nor the requested SARIF was written for a run
that had hit a single bad step.
The probe now catches a throwing require or run itself and records it the way
workerMain does: the raw payload stands in for the result, so the step reads as
an allow, and the error is kept. Matching the warm path matters because
coldSummary counts every cold decision that differs from the warm one as a
disagreement; any other choice would have reported disagreements that do not
exist. A child that dies without writing parseable output is caught outside the
probe and recorded the same way with no latency, and coldSummary leaves
unmeasured steps out of the percentiles while still counting them.
The new tests run a hook that always throws through both passes. They fail
against the previous code, 2 of 17, and pass against this one.
Brings in the three commits main gained since the branch's merge base: the 2.2.3
release, retiring the Everything Claude Code name for ECC, and the ja-JP sponsor
update. 227 files arrive from main; two conflicted.
CHANGELOG.md: the branch had added an Unreleased section and main a released
2.2.3 section, both at the top. Both are kept verbatim with Unreleased above
2.2.3, since none of the branch's entries shipped in that release.
manifests/context-packs/skill-triggers@1.json: both sides had recomputed
registryDigest from the same earlier value to different results, and neither is
the digest of the merged tree. It is recomputed with loadContextRegistry over the
merged tree and only that field changes; triggers and triggersDigest are
untouched on both sides. validate-context-profiles passes.
All twelve CI validators pass. The full suite reports 44 failures in seven files;
43 of them fail by name and count identically on an unmodified upstream/main, and
the remaining one, plugin-hook-bootstrap, fails only inside run-all and passes in
isolation on both trees. The merge introduces no failing test that main does not
already have.
* chore: retire the Everything Claude Code name, ECC only
Replace the expanded product name and the everything-claude-code slug
with ECC across READMEs, translated docs, harness folders, skills,
commands, scripts and examples. Repo URLs now point at affaan-m/ECC.
Rename repo-internal artifacts to ecc forms (ecc-conventions skill,
ecc-guardrails, ecc-research-playbook, ecc-team-config, ecc-instincts
with ecc-* ids) and update .claude/ecc-tools.json.
Legacy install ids, plugin dirs, package names and MCP prefixes stay
where existing installs resolve against them. The codex global-state
check and harness-audit repo detection accept the new name first and
the legacy one as a fallback. The Discord bot prefers ~/GitHub/ECC and
falls back to the nested legacy checkout path.
Refresh the skill-triggers registryDigest for the changed skill text.
* fix(ecc-tools): drop managed paths to the removed Claude repo skill
.claude/skills/<repo-skill>/SKILL.md was deleted in #2770 but stayed listed in
ecc-tools.json and the team config. Remove those entries and point the Claude
Code adapter at the existing .agents/skills/ecc-conventions/SKILL.md.
Preserve the original contributor histories and apply the exact independently reviewed repair.
Source-Parent: aa0ea42882
Review-Manifest-SHA256: 3d35033783c03f7660b6795e20c1de588fc1cd48850b208e36add955e2446ad7
Keep the original wrapper assertions while supervising owned child groups through pipe closure, reporting failed capability probes, and preserving aggregate counts.
Reviewed-Base: 807f07a687
Source-Manifest-SHA256: 75176a5cfe5345cc93c20fb748ba5a1f159fdeb171b12ae7a8619979fa55edd9
Final-Source-SHA256: 691cb15f7356845a2cc4f84277ff5fd24cd6210ec9995ffefea0ab19509ba076
Preserve current SerpApi terms and release history while moving inactive Mike sponsorship into past sections across affected pages. Add focused document contract coverage.
Source-PR: #3061
Source-Head: 7c1df74a60
Integration-Base: d3b8a3e908
Reviewed-Manifest: bc736b95c8dfd668a89fe256b61c7bd5cc3cb357e30858e93f99260324e26639
Preserve contributor history and current-main behavior while resolving the exact reviewed follow-up.
Source-PR: https://github.com/affaan-m/ECC/pull/3241
Source-Parent: 83f19dee14
Review-Manifest-SHA256: 638af3690929ac4e39066387a87236ddd1ba00e07874b3c2b5b23aa0b22bfbba
Preserve the contributor pin and current main. Keep both default connector declarations at the exact official 1.10.1 release and retain user-managed configuration behavior.
Source-PR: https://github.com/affaan-m/ECC/pull/3233
Source-Head: 62bf2b2910
Integration-Main: d3b8a3e908
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
* fix(install): make install.sh robust to sh/dash invocation
Two related portability fixes so `sh install.sh` behaves correctly
even though the script is written for bash:
- The cygpath detection used the bash-only `&>/dev/null` redirection.
dash misparses `&>`, so `command -v cygpath &>/dev/null` always took
the true branch and tried to run the nonexistent `cygpath` binary,
failing with "cygpath: not found". Switched to the POSIX-portable
`>/dev/null 2>&1` form.
- Some dash builds don't support `set -o pipefail`, so `sh install.sh`
can fail immediately at that line before even reaching the cygpath
check (or the `[[ ... ]]` symlink-resolution logic further down).
Added a guard that re-execs the script under bash when the current
shell lacks bash capabilities, so the rest of the bash-only syntax
always runs under a real bash regardless of the invoking shell. The
guard probes for the `[[` compound command directly (via
`eval '[[ 1 == 1 ]]'`) rather than trusting the $BASH_VERSION
environment variable, since that variable could be inherited or
spoofed under a non-bash shell and cause the guard to be skipped.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019XBaBRjaZgwhrZtYoqcQfp
* test(install): cover the sh install.sh re-exec path
Greptile flagged that the bash re-exec guard added in install.sh has
no automated coverage, since the existing test helper only invoked
the wrapper via `bash`. Adds two regression tests:
- "delegates to the Node installer when invoked via a POSIX sh
wrapper" — runs the script via `sh` and asserts the args/cwd still
reach the Node installer correctly.
- "re-execs into bash under sh even when BASH_VERSION is spoofed in
the environment" — exercises the eval '[[ 1 == 1 ]]' capability
probe directly, guarding against a regression back to trusting the
(spoofable) $BASH_VERSION variable.
CodeRabbit then pointed out that the second test used generic `sh`,
which could trivially pass without exercising the re-exec branch at
all if `sh` ever resolves to bash on some system. Added a
findPosixOnlyShell() helper that prefers `dash` (falling back to
checking `sh`, and skipping with an explicit message if neither
genuinely lacks bash's `[[`), so the test reliably exercises the
branch it claims to cover instead of passing vacuously.
CodeRabbit then flagged that the skip path itself was miscounted as
a pass (the callback returned normally, so `test()` reported success
and `passed` was incremented even though nothing executed). Moved
the findPosixOnlyShell() check outside the test() registration, so
the test is only registered — and only counted — when a genuinely
POSIX-only shell is actually available; otherwise it's excluded from
both the passed and failed counts with an explicit skip line.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019XBaBRjaZgwhrZtYoqcQfp
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
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.
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.
The default chrome-devtools connector is launched with `npx -y` and
`@latest`, so every session start can silently install whatever version
was most recently published to npm. Pinning makes the default connector
reproducible and removes the unpinned-npx finding that /security-scan
(AgentShield) reports against ECC's own .mcp.json.
The same spec is pinned in the Codex merge script so both harnesses
stay in sync, and the Codex merge test is updated to match.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The real-PTY test piped answers on fixed sleeps, typing them ahead of
readline. Under CI load the first answer could land before the interface
listened, shifting every later answer onto the wrong question: the
ubuntu-latest Node 18.x npm job installed Claude only, exited 0, and never
printed the Kimi profile prompt while the sibling yarn, pnpm, and bun jobs
on the same Node version passed. Answer each prompt once it appears on
screen instead; spawned stdio goes through cat because the macOS script(1)
refuses a socket stdin.
Root package.json declared no main or exports, so OpenCode npm plugin
resolution (import.meta.resolve) failed and the plugin was silently
skipped (#3127). The .opencode TypeScript sources imported siblings
with .js specifiers that only exist after compilation, so the home
install, which loads the .ts files in place, crashed the tool registry
with ERR_MODULE_NOT_FOUND (#3112).
Declare main/types/exports on the root package pointing at the
compiled plugin entry, switch the sources to .ts specifiers, and
enable allowImportingTsExtensions with rewriteRelativeImportExtensions
so the emitted dist keeps working .js specifiers. Add smoke tests that
build the package, resolve and import the entry by name from a temp
install, and verify every in-place relative import resolves.
Fixes#3127Fixes#3112