Commit Graph
946 Commits
Author SHA1 Message Date
Clovis cfca5c8153 fix: session-activity-tracker never records (CLAUDE_SESSION_ID unset)
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.
2026-09-05 16:58:17 -07:00
Clovis-Merovingian ec74a88644 feat: live tool-activity feed in the dashboard (#4)
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.
2026-09-05 16:54:32 -07: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
haelyra 8eeac94af3 fix: preserve PowerShell expansion semantics 2026-09-05 16:32:15 -04:00
haelyra 3ad828db47 fix: address PowerShell review bypasses 2026-09-05 16:12:58 -04:00
5a878131de fix(block-no-verify): split scanner and close quoting bypasses
Merge buildCommentMask into buildScanBoundaries so one pass owns comment mask and scan bounds.
Extract shell-scan primitives to scripts/hooks/lib/shell-scan.js; keep policy in the hook.
Use a sticky heredoc regex instead of copying the remaining input on every <<.
Replace the short-circuiting chain test with clean-leading sequences that exercise checkCommand advance.
Add quoted-executable non-leakage coverage for the scanEnd=length path.
Treat $'…' ANSI-C quoting as a quoted executable word.
Join unquoted backslash-newline for the flag scan and heredoc-line bound.

Co-Authored-By: grok (fleet lane) <noreply@fleet.local>

Co-authored-by: groy75 <groy75@users.noreply.github.com>
2026-09-05 03:32:30 +00:00
b3a2d3586b fix(block-no-verify): bound the flag scan to the enclosing quote/heredoc line
The scanner locked onto a `git commit` literal that sat inside a quoted
string of an OUTER command (a python heredoc's string, a VAR="..."
assignment, a printf JSON payload), then hasNoVerifyFlag() re-tokenized from
that inner offset with a fresh quote state. When quote parity flipped, the
"segment" ran past the enclosing string and picked up an unrelated later
`bash -n` / `sed -n` / `grep -n` as `commit -n`. Two legitimate commands were
blocked this way in one working session.

The first attempt at this PR (d5c428c) fixed the false positive by SKIPPING
`git` tokens judged to be in "data" context. That was the wrong lever: data
becomes executable the moment it is piped to a shell (`echo '...' | bash`,
`bash <<< '...'`, `cat <<EOF | bash`), and no regex list of shell invocations
is complete (`bash --noprofile -c` slipped). Three independent reviewers
(codex, Greptile, CodeRabbit) demonstrated executing bypasses; that commit is
squashed away here and none of its behaviour survives.

This version keeps every `git` candidate visible and keeps main's blocking
surface intact. A single O(n) preprocessing pass (buildScanBoundaries)
records, for each enclosed character, the closing quote or the current
heredoc-body line end. Subcommand discovery and flag tokenization are capped
at that boundary, so tokens after the enclosing data can never leak into a
candidate's argument list. Also: comment detection is a single mask pass
instead of a repeated prefix scan; heredoc parsing accepts quoted hyphenated
delimiters and CRLF terminators and preserves the `<<` vs `<<-` tab
distinction; quote-assembled words (`g''it`) are recognized.

Verified (all payloads run through the hook as JSON on stdin):
- red-list, 24 executing forms incl. every reviewer-reported bypass -> exit 2
  on main AND here (CRLF heredoc trailer: 0 on main, 2 here);
- green-list, 16 leak-class false positives -> exit 2 on main, 0 here;
- tests/hooks/block-no-verify.test.js 84/84 (main's 25 retained verbatim,
  d5c428c's 8 removed, 59 table-driven red/green cases added);
  tests/hooks/cursor-block-no-verify.test.js 14/14;
- 204,807-byte command with 8,905 non-command `git` literals: 8.5 ms.

Co-Authored-By: Codex (GPT) <noreply@openai.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EyuZY1LZNuShHiewExekLT
2026-09-04 22:35:09 -04:00
Brian SwigerandCopilot 682666f40b refactor(install): keep the copilot operation planner under the size limit
AGENTS.md requires functions under 50 lines; planOperations was 54 and mixed
source filtering, destination mapping, and operation construction. Extract the
per-path mapping into planSourcePathOperations and share the prefix test with
supportsCopilotSourcePath. planOperations is now 18 lines. No behaviour change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-04 21:29:47 +01:00
Brian SwigerandCopilot d58441072d feat(install): add a copilot project target for skills and agents
GitHub Copilot CLI discovers SKILL.md skills from .github/skills/ and custom
agents from .github/agents/, so ECC's catalog can be installed there without a
conversion step. This adds a managed-project install target that places both.

Scope is deliberately limited to agents and skills. ECC hooks are written
against Claude Code's event model, and commands rely on slash-command argument
substitution Copilot does not provide, so neither is installed.

Agent frontmatter goes through an allowlist transform rather than a passthrough:
Copilot resolves the session model from user configuration, so a Claude model id
makes it warn and fall back on every invocation; Claude tool names are not
Copilot tool names, and Copilot governs tool access per session via
--allow-tool/--deny-tool. Unknown keys added to ECC agents later therefore
cannot leak into the Copilot copy.

Target selection stays permissive in supportsModule so dependency-anchor modules
still resolve; planOperations is what narrows the install, matching the
convention used by the other adapters.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-09-04 20:58:17 +01:00
haelyra d9f6091ee8 fix: close PowerShell destructive command gate bypass 2026-09-04 15:02:57 -04:00
wellkilo 6f9282af41 fix(gan): require Playwright capability in harness 2026-09-04 20:48:42 +08:00
haelyraandGitHub 005eff40fd fix(install): harden universal setup release path (#2888)
* fix(install): harden universal setup release path

* docs(adal): use ecc-universal doctor command
2026-08-30 18:54:00 -04:00
haelyra 64d0d9436f fix(install): preserve opencode non-hook defaults 2026-08-30 15:35:47 -04:00
6aaa41e028 feat(install): require an explicit hook decision at the apply layer
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>
2026-08-30 15:09:34 -04:00
haelyraandGitHub a89cec9658 Merge pull request #2854 from samartomar/codex/issue-744-pure-plan
refactor(install): expose pure manifest planner
2026-08-30 14:50:53 -04:00
haelyra 1bdda4bdac fix: close validator and path edge cases 2026-08-29 15:36:59 -04:00
haelyra 224da03d01 fix(gateguard): match heredoc tab-strip order 2026-08-29 14:55:14 -04:00
a4d72b2271 fix(gateguard): surface graduated recovery hints
Change-Id: I6ade0a2a54a26bd5721c62edf7efa462e8043a08
Co-authored-by: TRAE CLI <traecli@bytedance.com>
2026-08-29 14:55:14 -04:00
dajiaohuangandhaelyra c40d0e4f7c fix: normalize heredoc line continuations 2026-08-29 14:55:14 -04:00
dajiaohuangandhaelyra 9768c075c3 refactor: keep heredoc scanning linear 2026-08-29 14:55:14 -04:00
dajiaohuangandhaelyra 9a3ee6864a refactor: keep heredoc parser state immutable 2026-08-29 14:55:14 -04:00
dajiaohuangandhaelyra e72191ba74 fix: harden heredoc command filtering 2026-08-29 14:55:14 -04:00
dajiaohuangandhaelyra 962380c452 fix: ignore heredoc prose in GateGuard 2026-08-29 14:55:14 -04:00
haelyra 30c41a9bde fix: close truth and portability review gaps 2026-08-29 14:55:14 -04:00
Juan Pabloandhaelyra 974ccc749f fix(ci): validate SKILL.md frontmatter under docs/{locale}/skills/ mirrors
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).
2026-08-29 14:55:13 -04:00
haelyra 2f8a5a271d test: cover inferred-window hook output 2026-08-29 14:55:13 -04:00
Tanelandhaelyra ecdd517765 fix(suggest-compact): don't quote a percentage against an assumed window
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.
2026-08-29 14:55:13 -04:00
haelyra 4c7e965209 fix(gan): distinguish scores from verdict thresholds 2026-08-29 14:24:16 -04:00
CaoBochunandhaelyra 70eb0f68ae fix: make GAN harness score parsing portable 2026-08-29 13:40:56 -04:00
haelyra 73c29bbd08 fix(install): register AdaL capability metadata 2026-08-29 13:40:56 -04:00
1444239eec feat(install): add AdaL CLI install target
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>
2026-08-29 13:40:56 -04:00
benno0oandhaelyra b48f22f08c fix: address pre-push pnpm review findings 2026-08-29 13:40:53 -04:00
benno0oandhaelyra 03b441792e fix: resolve pnpm in Git Bash pre-push hook 2026-08-29 13:40:53 -04:00
haelyraandGitHub 656d4b5746 Merge pull request #2869 from actus7/consolidate/mcp-health-v3
fix(hooks): consolidate MCP health-check fixes (3 PRs)
2026-08-29 00:22:27 -04:00
haelyra b2ab65d0fb fix(hooks): classify platform-dependent raw prefixes 2026-08-28 22:35:23 -04:00
haelyraandGitHub d5ebac49b1 Merge pull request #2380 from chs0813/fix/plugin-hook-bootstrap-no-echo
fix(hooks): do not echo raw input from plugin-hook-bootstrap.js
2026-08-28 22:24:24 -04:00
haelyraandGitHub 9ff6949798 Merge pull request #2351 from vladyslavTezyk/main
Add ukranian translation of the main Readme.
2026-08-28 21:59:45 -04:00
haelyra 13c476965f fix(hooks): keep MCP reachability probes bounded
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.
2026-08-28 21:09:35 -04:00
haelyra 3702a617db Merge remote-tracking branch 'origin/main' into maint/pr-2866-current 2026-08-28 18:29:35 -04:00
haelyraandGitHub 2aebdd3408 Merge pull request #2870 from actus7/consolidate/hooks-observer-v3
fix(hooks): consolidate hooks and observer fixes (5 PRs)
2026-08-28 18:29:03 -04:00
haelyra e51224697d docs(costs): cite the pricing contract 2026-08-28 16:38:56 -04:00
haelyra 1d19789c75 fix(hooks): preserve metadata-marked human prompts 2026-08-28 16:28:12 -04:00
haelyra 77c358dd3f fix(costs): retain dated Opus 4 legacy pricing 2026-08-28 16:26:13 -04:00
Santhi Prakashandhaelyra 08092276f9 fix(hooks): price Sonnet 5 at the published $2/$10 rate 2026-08-28 16:22:55 -04:00
haelyra 950caaaae1 fix(hooks): preserve short sessions and quote evolved metadata 2026-08-28 16:08:19 -04:00
haelyra b7d6c61b1e Merge remote-tracking branch 'origin/main' into maint/pr-2870-current 2026-08-28 16:03:10 -04:00
haelyra 1953a749a2 Merge remote-tracking branch 'origin/main' into maint/pr-2873-current 2026-08-28 15:59:31 -04:00