Same class of bug as the session_id fix, one field over, found by code-reviewer
before merge: CLAUDE_HOOK_EVENT_NAME is never set for hook subprocesses either
(currently a harmless no-op since the dispatcher only ever calls this hook under
PostToolUse, but a real latent bug if that wiring ever changes). Also runs the
stdin-derived session_id through sanitizeSessionId(), matching the established
pattern already used in cost-tracker.js, ecc-context-monitor.js,
ecc-metrics-bridge.js, and gateguard-fact-force.js.
session-activity-tracker.js is correctly registered in
posttooluse-dispatcher.js's SYNC_HOOKS and fires on every tool call --
but buildActivityRow() only ever read the session id from
ECC_SESSION_ID/CLAUDE_SESSION_ID environment variables, which Claude
Code does not actually set for hook subprocesses. Every row silently
came back null and nothing was ever written to
~/.claude/metrics/tool-usage.jsonl, with no error anywhere.
The session id is available in the hook's own stdin JSON payload
(input.session_id) in real invocations. This prefers that, keeping the
env vars as a fallback. New test added; all 18 existing + new tests
pass.
Also adds a live Activity view to the capabilities dashboard
(scripts/dashboard-web.js) reading that same metrics file, so Skill
vs. Agent vs. raw-tool usage is visible in real time instead of
requiring a manual tail+jq -- verified live against a real session
before this commit. Documents the loopback-only, no-auth design and
the standard SSH-port-forwarding pattern for viewing it from another
device you control.
Adds /api/activity, reading ~/.claude/metrics/tool-usage.jsonl (the
session-activity-tracker hook wired in earlier), plus an Activity tab
polling it every 3s -- Skill/Agent calls visually distinct from raw
Bash/Edit/Write. Turns the tracker's log into an actual live proof
gate with a UI instead of a file someone has to tail and jq by hand.
Verified live: /api/activity already returns real entries from this
session before this commit was even pushed.
The guided installer asks how ECC hooks should run, but that consent
lived only in the wizard path. Running install-apply directly with a
profile that includes hooks-runtime still materialized the hook runtime
with no disclosure and no decision.
Gate the apply layer instead, so every entry point is covered:
- disclose the six hook capability groups when a plan would materialize
the hook runtime, and refuse to apply until the caller decides
- --enable-hooks confirms the hook runtime; --no-hooks installs the rest
of the selection without it and records the reduced module closure in
install-state
- surface the pending decision as a dry-run warning
- show the same capability disclosure in the guided installer's plan
preview, so the wizard's hook question states what it is asking about
Plans that never materialize hooks (Kimi, --profile minimal,
--without baseline:hooks) are unaffected and need no flag. Repair and
uninstall operate on already-recorded state and stay unchanged.
The capability taxonomy and the held-materialization behavior come from
Samarjeet Singh Tomar's PR #2634, reworked to fit the single-decision
consent model that shipped with the guided installer in #2649.
Co-Authored-By: Samarjeet Singh Tomar <samar_tomar@hotmail.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Extends scripts/ci/validate-skills.js to also scan docs/{locale}/skills/
translated mirrors, not just curated skills/. Adds detection for the
YAML defect classes from #2630 without a parser dependency: unquoted
values containing ": " (glued next key / dropped quoting), values
starting with the reserved '@'/'`' indicators, and missing frontmatter
blocks entirely (required only for docs mirrors; curated skills/ keeps
its existing tolerant behavior).
The context signal always rendered "N% of <window> window", including when
the window size was the assumed 200k default rather than a detected value.
On a 1M session whose transcript carries no [1m] marker, that produced
lines like:
[StrategicCompact] Context ~194k tokens (97% of 200k window)
while actual usage was ~19%. The user compacts on a false alarm, loses
context, and the resulting quality drop reads as a model regression.
The gap is structural: the context threshold defaults to 80% of the
window (160k on 200k), so the signal fires precisely in the 160k-200k
band where the size cannot be determined — above 200k the observed-tokens
fallback correctly infers 1M, and below 160k nothing fires.
Model id alone cannot close this. A tier may ship both a 200k and a 1M
variant under one id, so neither the known-family table nor a new entry
can distinguish them, and the transcript records no window field.
So stop asserting what isn't known: resolveContextWindow() now reports
whether the size was detected (env override, [1m] marker, known family,
or observed tokens > 200k) or assumed, and the hook omits the percentage
and window label when it was assumed. The token count, threshold, and
firing behaviour are unchanged.
resolveContextWindowTokens() keeps its existing signature and semantics.
Note: 3 pre-existing failures in tests/hooks/suggest-compact.test.js
reproduce identically on unmodified main and are untouched here.
Following the hermes/openclaw (#2433) and kimi (#2441) adapter recipe.
What's included (adal-project adapter, project kind, ./.adal root, same
shape as kimi-project/joycode-project):
- scripts/lib/install-targets/adal-project.js — 10-line project-kind
adapter targeting ./.adal
- Registry + helpers platform-ownership wiring
- adal target on the 5 shared modules (rules-core, agents-core,
commands-core, platform-configs, workflow-quality) +
SUPPORTED_INSTALL_TARGETS + legacy-compat module
- .adal in platform-configs paths
- Both schema enums (install-modules, ecc-install-config), npm files
allowlist, installer help text, .adal/README.md stub
AdaL (adalagent.ai) is a terminal-based AI coding agent (by SylphAI)
built on AdalFlow, with native MCP support and project-scoped config
under ./.adal/ (skills, custom tools, memory) plus a root-level
AGENTS.md instructions file — matching the shape ECC already installs
into other AGENTS.md-based harnesses (Codex, OpenCode, Kimi).
Verified: full suite matches main's baseline (3334 passed, same
pre-existing failures unrelated to this change — OpenCode build/npm-pack
surface tests requiring build tooling not present in this sandbox);
catalog check passes (67 agents / 94 commands / 281 skills); dry-run
resolves Target: adal / Adapter: adal-project / root ./.adal with all 5
modules planned; doctor reports OK after a real install; uninstall
cleanly reverses all 458 operations.
Co-Authored-By: AdaL <adal@sylph.ai>
Remove the redundant JSON-RPC initialize fallback from the consolidated MCP health-check batch. A routed 404 already proves the endpoint is reachable, and the real authenticated MCP call remains authoritative. Avoiding the fallback also prevents a stalled GET plus stalled POST from consuming twice the configured hook timeout.