ECC/tests
JongHyeok Park 0071fa5c3c
refactor(hooks): consolidate PostToolUse hooks into sync/async dispatchers (#2494)
* refactor(hooks): consolidate PostToolUse hooks into sync/async dispatchers

Replace 10 individual PostToolUse entries in hooks.json with two
consolidated dispatcher entries (post:dispatcher:sync /
post:dispatcher:async). The dispatcher's internal registry preserves
every hook ID, matcher, and profile, so ECC_DISABLED_HOOKS and
ECC_HOOK_PROFILE gating behave exactly as before.

Performance (Edit event, actual hooks.json commands spawned in
parallel like the harness does, median of 7 runs):
- Blocking hook latency: 81ms -> 49ms (~40% faster; 7 blocking
  processes -> 1 sync dispatcher)
- Node processes per tool call: 10 -> 2 (7 blocking + 3 async
  -> 1 sync + 1 async)
- observe-runner now runs in-process (~370ms) inside the async
  dispatcher, which stays backgrounded (async: true, timeout 45s),
  so it adds no user-facing latency.

Also:
- dashboard-web lists dispatcher-managed child hooks so the hook
  inventory stays complete
- post-edit-console-warn refactored to export run() for in-process
  dispatch while keeping standalone stdin behavior
- dispatcher stdin reading is multi-byte safe (StringDecoder) and
  child hook exit codes propagate to the dispatcher exit code

* test(hooks): replace emoji literal with unicode escape for CI unicode safety check

* fix(hooks): adopt explicit cli() entrypoint and merge multi-hook stdout

Address Greptile review on #2494:

- Replace the non-standard 'require.main === undefined' guard with an
  explicit exported cli(). The hooks.json bootstraps now call
  require(s).cli(), so merely requiring the module (dashboard-web,
  test runners, Jest, worker threads) can never trigger dispatch,
  attach stdin listeners, or set process.exitCode.
- Replace last-writer-wins stdout with mergeHookStdout(): when several
  hooks emit additionalContext envelopes they merge into a single
  PostToolUse envelope; non-mergeable raw stdout keeps the last hook's
  output and emits a stderr warning naming the dropped hook IDs, so
  nothing is lost silently.

Also includes local formatter reformatting of the dispatcher and its
test file (no behavioral changes beyond the above).

* fix(hooks): keep post:bash:dispatcher phase reachable in minimal profile

The Greptile P1 premise was partially incorrect: sub-hooks without
explicit profiles default to standard,strict via parseProfiles()
(scripts/lib/hook-flags.js), so audit/cost logs never ran under the
minimal profile on main either — there is no user-visible regression.

However, main did spawn the bash dispatcher phase unconditionally and
let each sub-hook gate itself. Restore that semantic by opening the
outer registry gate to minimal,standard,strict so a future sub-hook
that opts into minimal is not silently blocked at the phase level.
Adds the previously missing minimal-profile async dry-run test.

* test(hooks): assert failing hook exit code propagates to real process status

Spawns the actual dispatcher subprocess with an injected failing hook
and asserts the OS-level exit status, stderr diagnostic, and suppressed
pass-through — closing the E2E gap CodeRabbit flagged on #2494.

* chore: retrigger CI (flaky windows powershell bootstrap test)
2026-07-19 15:47:10 -04:00
..
ci fix(install): reference all curated skills in modules + reverse-coverage guard (#2431) (#2440) 2026-07-08 17:14:52 -04:00
commands fix: accept crlf command frontmatter 2026-04-30 03:41:18 -04:00
docs release: 2.0.0 — the agent harness operating system 2026-06-09 21:40:40 -04:00
hooks refactor(hooks): consolidate PostToolUse hooks into sync/async dispatchers (#2494) 2026-07-19 15:47:10 -04:00
integration refactor(hooks): consolidate PostToolUse hooks into sync/async dispatchers (#2494) 2026-07-19 15:47:10 -04:00
lib fix(project-detect): parse Python deps pinned with ~ and @ (was losing framework detection on compatible-release pins) (#2498) 2026-07-17 17:11:09 -04:00
scripts refactor(hooks): consolidate PostToolUse hooks into sync/async dispatchers (#2494) 2026-07-19 15:47:10 -04:00
__init__.py Small changes 2026-04-12 12:34:45 +05:30
codex-config.test.js fix(codex): broaden context7 config checks 2026-03-29 00:26:16 -04:00
conftest.py docs: salvage focused stale PR contributions 2026-05-11 05:31:12 -04:00
opencode-config.test.js fix: namespace opencode command agents 2026-04-05 14:21:57 -07:00
opencode-plugin-hooks.test.js feat(opencode): 全面升级OpenCode集成 (#2251) 2026-06-15 14:01:34 -04:00
opencode-tools.test.js feat(opencode): 全面升级OpenCode集成 (#2251) 2026-06-15 14:01:34 -04:00
plugin-manifest.test.js fix: add plugin cache health check (#2249) 2026-06-15 14:01:25 -04:00
run-all.js feat: worktree-lifecycle service (deterministic conflict prediction + safe GC) (#2164) 2026-06-07 13:00:08 +08:00
test_astraflow_provider.py feat: add Astraflow provider support 2026-05-11 23:21:46 -04:00
test_atlas_provider.py feat: add Atlas Cloud as LLM/AI provider (#2279) 2026-06-18 16:29:11 -04:00
test_builder.py fix: docs/COMMAND-REGISTRY.json check fails on fresh Windows clone (missing .gitattributes) (#2437) 2026-07-03 20:14:55 -07:00
test_claude_provider.py fix(llm/providers/claude): attach cache_control to system block, not top-level (#2515) 2026-07-17 16:04:32 -04:00
test_executor.py Small changes 2026-04-12 12:34:45 +05:30
test_invariant_runner.py fix: sanitize subprocess call in runner.py (#2149) 2026-06-15 13:49:45 -04:00
test_provider_tools.py fix: harden openai-compatible provider responses 2026-05-18 01:04:28 -04:00
test_resolver.py feat: add Atlas Cloud as LLM/AI provider (#2279) 2026-06-18 16:29:11 -04:00
test_templates.py docs: salvage focused stale PR contributions 2026-05-11 05:31:12 -04:00
test_types.py feat: add Astraflow provider support 2026-05-11 23:21:46 -04:00