Commit Graph
110 Commits
Author SHA1 Message Date
haelyra 3fa6e30502 fix: preserve rollback version state and bounded runtime workflows 2026-10-11 11:45:41 -04:00
haelyra 4ce5ae0119 fix: preserve search scope and installed cache discovery 2026-10-11 10:25:44 -04:00
haelyra 6233b648f9 fix(hooks): resolve bootstrap from selected Claude config root 2026-10-11 02:03:45 -04:00
haelyra a3e9ddfde7 feat(gateguard): integrate evidence-aware first-touch questions 2026-10-10 17:46:23 -04:00
calm 2d9e6977dc feat: add native Qoder plugin support 2026-10-10 20:11:00 +08:00
montjeffrey 92947a68df Merge upstream/main into feat/gateguard-fewer-round-trips
Resolve six conflicts:
- hooks/hooks.metadata.json: keep this branch's gateguard description and
  fingerprint, add upstream's hookify-runtime entries.
- package.json: keep both gateguard-report.js and github-coordination.js.
- scripts/hooks/gateguard-fact-force.js, tests/hooks/gateguard-fact-force.test.js,
  skills/gateguard/SKILL.md: upstream added a simpler session denial cap; this
  branch already has the fuller one (cap threaded through
  markCheckedAndCountDenial, malformed-value warning, miss and target notes),
  so keep it. Upstream's taskset and su wrapper handling, fail-closed
  recursion limit and soft-hyphen sanitising merged cleanly and their tests pass.
- manifests/context-packs/skill-triggers@1.json: take upstream's file and
  recompute registryDigest for the merged registry.
2026-10-09 20:38:25 -04:00
haelyra 7265b989c4 merge: preserve tested bounded Hookify carry-forward candidate 3055 2026-10-09 16:17:57 -04:00
haelyra 4cb9f29c06 merge: preserve tested Hermes hooks source 3019 2026-10-09 16:12:01 -04:00
wellkiloandhaelyra a50ee13cac feat: execute bounded local Hookify rules in lifecycle hooks
Carry forward PR #3055 at 92f53c4c onto ef648e01, preserving contributor attribution and current main. Focused maintainer fixes reuse shared input ceilings, preserve late root context through outer bootstrap, bound frontmatter before immutable parsing, and assert real oversized input in the limits workflow.
2026-10-09 15:59:20 -04:00
Jeffrey Montoya d4045c7370 docs(gateguard): document NotebookEdit, hard links and exempt precedence 2026-09-29 21:50:27 -04:00
Jeffrey Montoya 10639a0c9e fix(gateguard): gate NotebookEdit and hard-linked targets
NotebookEdit is gated as a first-touch edit of notebook_path.
A file with more than one hard link gets no credit, trivial, sibling or cap allowance.
2026-09-29 21:50:26 -04:00
Jeffrey MontoyaandSulimanAbdulrazzaq e98a9da288 feat(gateguard): improve first-touch signal quality and session efficiency
- Ask class-specific first-touch questions (instruction, test, prose,
  config, code); code questions are unchanged.
- Credit a completed Glob/Grep/LS or shell search from the current human
  turn that covered the target; Read and exclusion globs never count.
- Collapse same-class new-file creations in one directory within a turn.
- Add opt-in GATEGUARD_FACT_FORCE_MAX_DENIALS session cap (from #2755).
- Always gate sensitive targets, judged on lexical and real paths.
- Canonicalize checked-path keys.

Closes #2608

Co-authored-by: SulimanAbdulrazzaq <suliman9000a@gmail.com>
2026-09-29 21:49:46 -04:00
Santhi PrakashandGitHub bd9402f774 fix(hooks): scope MCP health checks to MCP tools (#2838)
Anchor the PreToolUse and PostToolUseFailure MCP health-check matchers so non-MCP tool calls do not spawn the health hook.
2026-09-29 15:08:37 -04:00
He DongandGitHub 8bf16ccfec fix(hooks): keep silent hook paths silent (#2987)
* fix(hooks): keep silent hook paths silent

* fix(hooks): harden stream failure handling

* fix(hooks): settle interrupted input streams

* test(hooks): name stream input limits

* test(hooks): isolate PostToolUse dispatcher fixtures
2026-09-18 18:42:20 -04:00
Affaan MustafaandGitHub 34de45f210 fix(hooks): enforce loader-documented keys in shipped hooks configs (#3163)
hooks/hooks.json already ships only schema-valid keys with metadata in the
hooks.metadata.json sidecar. Add scripts/ci/check-hooks-schema-keys.js, a
strict allowlist check that fails when hooks/hooks.json or
hooks/codex-hooks.json carry any key outside their loader's documented set,
wire it into the npm test chain, and cover it with fixture tests.

Refs #3138, #3114
2026-09-18 18:37:40 -04:00
zpearce-2814andGitHub 1ac07903ec fix(hooks): keep hooks.json within Claude Code's schema
Move stable hook metadata to a validated sidecar while preserving hook commands and installer identity. Reject moved fingerprints and duplicate IDs, and validate before updating metadata. Independent local review passed at c315271624a1fd055b992f2bff889ad2a0ff8a6b; CI run 34678210149 passed. Rollback: revert this squash commit.
2026-09-12 02:59:02 -04:00
ravitejarenangi b30a8c782a fix(hooks): address review — close bypasses, surface failures, add test suite
Greptile + CodeRabbit review of #3019:

- config-protection: compare basenames case-insensitively (macOS/Windows
  resolve ESLINT.CONFIG.JS to the protected eslint.config.js) and use lstat
  so a dangling symlink to a protected name still blocks (os.path.exists
  follows the link and returns False).
- Both hooks: fail-open stays, silence goes — every swallowed path now
  writes a one-line stderr diagnostic.
- config-protection: sys.stdout.write instead of print() per repo Python
  style; block decisions carry a trailing newline.
- New tests/hermes-hooks.test.js: 13 cases through the real scripts via
  spawnSync — block (all names, case variants, dangling symlink, edits[],
  per-tool), allow (normal source, new config, non-edit tools), fail-open
  with diagnostics (malformed payload, missing path, unreadable file).
- docs: absolute-path copy-paste block via $HOME (CodeRabbit: /Users/YOU
  placeholders were unverifiable), self-contained block-case proof that
  creates its target, pointer to the committed suite.
2026-09-08 12:38:29 +05:30
ravitejarenangi 879a17092c feat(hooks): add Hermes-native config-protection and console-log guards
Hermes ships its own shell-hook system (hooks: block in config.yaml,
Claude-compatible JSON payloads, per-tool matchers, consent allowlist),
and the hermes install target deliberately ships no hook runtime — so
Hermes operators get rules/skills/commands with zero hooks. This ports
the two harness-independent ECC hooks as self-contained Python scripts
with no ECC runtime dependency:

- config-protection: blocks edits to existing lint/format configs and
  ratchet baselines (pre_tool_call)
- check-console-log: warns on console.log() in edited TS/JS (post_tool_call)

Includes install, consent, and verification steps in docs/HERMES-HOOKS.md.
2026-09-08 12:26:52 +05:30
haelyra 967a5fa4ba Merge reviewed Claude hook registration and settings containment fixes 2026-09-07 16:38:41 -04:00
wellkilo f59cfd57c2 fix(install): harden Claude settings lifecycle 2026-09-07 01:57:04 +08:00
wellkilo 569e5a36bb feat(install): register manual Claude hooks 2026-09-07 00:53:13 +08:00
haelyra d9f6091ee8 fix: close PowerShell destructive command gate bypass 2026-09-04 15:02:57 -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
haelyra fab534f924 test(hooks): keep matcher mirrors in sync 2026-08-29 14:55:14 -04:00
Suliman Abdulrazzaqandhaelyra 6fa3efeef7 fix(hooks): use valid wildcard matchers 2026-08-29 14:55:14 -04:00
01e15490f0 fix(skill-evolution): wire Skill PostToolUse tracker so skill-health shows real runs (#2490)
* fix(skill-evolution): wire Skill PostToolUse tracker so skill-health shows real runs (#2463)

recordSkillExecution() had no production callers, so
~/.claude/state/skill-runs.jsonl was never written and
`scripts/skills-health.js --dashboard` always reported 0 runs.

Adds scripts/hooks/skill-run-tracker.js and registers it as an async
PostToolUse hook (matcher: Skill) in posttooluse-dispatcher.js, which is now
the single PostToolUse entrypoint on main.

Addresses the privacy and bounds review on #2555's sibling PR:

- No prompt text is persisted. task_description is synthesized as
  "Skill invocation: <skill_id>"; tool_input.task_description/description/
  prompt are never read.
- Every persisted string is bounded and charset-restricted. A skill id is an
  identifier, so free text, newlines, or an over-long value are dropped rather
  than truncated and written through.
- The JSONL sink is created 0600 and re-tightened on each append, repairing
  files written before this bound existed.
- The sink is capped at MAX_RUN_RECORDS (5000), trimmed oldest-first, so the
  append-only file can no longer grow without limit.

Tests cover the privacy guarantee (no prompt text reaches a record), the
identifier bounds, the file mode on POSIX, and the retention cap.

* fix(skill-evolution): re-register the tracker for PostToolUseFailure

The rebase onto current main dropped the hooks.json entry, which silently
resurrected the P1 from the earlier review round: deriveOutcome() still
branches on hook_event_name === 'PostToolUseFailure', but the PostToolUse
dispatcher does not fan that event out, so the branch was unreachable in
production. Hard Skill failures were dropped from telemetry entirely, which
inflates the dashboard success rate — the opposite of what #2463 asks for.

Restores the dedicated PostToolUseFailure entry (matcher Skill, id
post:skill:track, same run-with-flags wrapper and standard,strict gating as
the dispatcher registration). Verified end-to-end: a PostToolUseFailure
payload piped through run-with-flags now records outcome "failure".

Adds a regression test asserting the registration so a future rebase cannot
quietly drop it again.

---------

Co-authored-by: haelyra <49814733+haelyra@users.noreply.github.com>
2026-08-12 18:12:49 -04:00
ae303fb6c1 fix(plan-canvas): deliver browser chat to the agent every time (#2739)
Feedback sent from the canvas only reached an agent through a live
/api/await long poll. When a turn ended with no await parked,
queueFeedback wrote the message to sessions.json and nothing ever
consumed it, so sending appeared to do nothing at all. The presence pill
made it worse: workingKeys had no expiry and the feedback handler never
broadcast presence, so it froze on "agent working" while nobody was
listening.

Delivery:
- Add the stop:plan-canvas-pending hook. It drains undelivered feedback
  and blocks the Stop, handing the messages to the agent, so a canvas
  message lands even when no await is running. Scoped to sessions under
  cwd so parallel agents cannot swallow each other's feedback; set
  ECC_PLAN_CANVAS_STOP_SCOPE=all to widen. Honors stop_hook_active and
  fails open on every error path.
- run-with-flags.js did not await a hook's run(), so any async hook
  silently degraded to pass-through. Fixed; plan-canvas-pending is the
  only async hook today.

Presence and indicators:
- Presence is now ended/typing/thinking/listening/queued/waiting.
  thinking and typing self-expire (90s/30s) and a 5s sweep pushes the
  decay to an idle browser, so the pill can no longer stick.
- Broadcast presence when feedback is queued, and clear the activity
  state when an agent reply lands.
- Add POST /api/session/:key/typing so agents can drive the indicator.
- Chat shows an animated dots bubble for thinking and typing, plus an
  explicit note when a message is queued with nobody listening.
  Respects prefers-reduced-motion.
- Send status reports what actually happened instead of always claiming
  the agent will pick it up.

CLI and skill:
- Add `ecc-plan-canvas pending` and `typing <file> --state ...`.
- SKILL.md documents background await as the primary pattern and makes
  replying in the canvas mandatory.

Tests: 6 new server cases covering queued presence, the typing endpoint,
state expiry and the sweep, plus a new hook suite covering delivery,
drain-once, stop_hook_active, cwd scoping and fail-open.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 18:15:25 -04:00
28e53a0bc1 feat(install): add guided multi-harness installer (#2649)
* feat(install): add guided Claude plugin setup

* fix: support Claude command shims on Windows

* feat: support safe Claude plugin scope migration

* fix(install): preserve interactive setup terminal

* fix(install): auto-migrate setup scope changes

* feat(install): add guided multi-harness installer

* fix(install): sync Yarn binary metadata

* fix(install): handle wizard EOF on Node 18

* ci: allow installer matrix tests to finish

* test(install): allow slower PowerShell delegation

* fix(install): harden guided provider reconciliation

* test(install): harden packaged and local compatibility

* chore: prepare guided installer release 2.2.0

* fix(install): report refreshed Codex marketplace state

* fix(install): verify managed content provenance

* test(install): allow empty Yarn smoke fixture

* test(install): invoke Windows package shims safely

* fix(install): close cross-platform release gaps

* fix(install): require trusted GitHub origins

* fix(install): preserve hook profile precedence

* refactor(install): centralize trusted GitHub origins

* ci: retrigger workflow run after merge of main

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 15:39:49 -04:00
JongHyeok ParkandGitHub 28b922dee3 fix(hooks): preserve Stop output through lifecycle wrappers (#2493)
Preserve complete Stop-hook stdout through lifecycle wrappers, wait for queued output to flush before exiting, bound child output with a larger explicit buffer, and add end-to-end regressions for large, multibyte, dry-run, and failure cases.
2026-07-26 00:01:57 -07:00
JongHyeok ParkandGitHub 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
a511395613 feat: Plan Canvas, a browser review canvas for plans (#2467)
* feat: add Plan Canvas - browser annotate-and-approve review for plan artifacts

- scripts/plan-canvas.js CLI (open/await/end/stop/server; bin ecc-plan-canvas)
- loopback server + ECC-styled chrome + annotation SDK + zero-dep markdown renderer
- Approve/Request-changes verdicts wired to the /plan confirmation gate
- plan-canvas skill, /plan-canvas command, SessionStart hook surfacing open reviews
- shared scripts/lib/loopback-guard.js extracted from control-pane (API re-exported)
- 121 new tests incl. full-workflow E2E; registered in manifests, catalog, registry

Inspired by lavish-axi (https://github.com/kunchenguid/lavish-axi) by @kunchenguid;
original ECC-native implementation, not a port.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(plan-canvas): invoke via ecc-plan-canvas bin so the skill works from any project

Skill/command referenced a cwd-relative `node scripts/plan-canvas.js`, unusable
outside the ECC root. Switch to the ecc-plan-canvas bin (and $CLAUDE_PLUGIN_ROOT
fallback) and align CLI next_step hints so an agent can run it as a skill in any repo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(plan-canvas): render Mermaid diagrams + ship Codex cross-harness surface

- markdown renderer emits <pre class="mermaid"> for ```mermaid blocks (source
  entity-escaped so the browser decodes it for the renderer while blocking injection)
- artifact template loads a pinned Mermaid build only when a diagram is present,
  themed to ECC dark, securityLevel strict, graceful offline fallback to source
  (ECC_PLAN_CANVAS_MERMAID_URL overrides for a local mirror)
- skill teaches Mermaid-for-diagrams and states the CLI+JSON loop is harness-agnostic
- add .agents/skills/plan-canvas (Codex) with agents/openai.yaml interface manifest
- register in install-modules workflow-quality paths; docs updated

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(plan-canvas): add demo screenshot

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(ci): sync yarn.lock with new bin; add contributor checklist

- yarn.lock records the ecc-plan-canvas bin so Yarn hardened-mode install no
  longer wants to modify the lockfile on public PRs
- PR template + CONTRIBUTING gain a pre-push checklist covering the lockfile
  trap and the full skill/command/CLI registration surfaces

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Haley Chen <2022hachen@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:12:48 -04:00
devin-ai-integration[bot]GitHubDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>affaanDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
3af4676e99 refactor: consolidate duplicated hook-root resolver into shared resolveEccRoot() (#2368) (#2410)
* fix(ci): resync lockfiles with package.json (eslint 10) + migrate yarn.lock to Yarn 4 format

package.json requires eslint@^10.6.0 but the committed locks pinned 9.39.2, so
npm ci aborted and Yarn 4 hardened mode rejected the stale v1-classic yarn.lock
(YN0028). Regenerate package-lock.json and rewrite yarn.lock in Yarn 4 (berry)
format so npm ci and immutable yarn installs both pass.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(ci): require clean probe exit for Windows shell/bash detection; add pyyaml dev dep

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor: consolidate duplicated hook-root resolver into shared resolveEccRoot() (#2368)

The inline node -e resolver blob was duplicated ~60x across hooks.json,
command docs, and translations. Each copy inlined the full ~700-char
plugin-root search using a spread over nested array literals
(p.join(d,'plugins',...s) over [['ecc'],...]), which breaks Windows hook
execution due to shell quoting (#2368).

Collapse every copy to a 250-char locator that loads the committed
resolve-ecc-root module and delegates to resolveEccRoot() — no spread, no
nested array literals, no escaped double quotes. The real search logic now
lives in one tested module. Also route session-start-bootstrap.js through
resolveEccRoot() instead of its own duplicated reimplementation, and fix
the auto-update.md 'marketplace' (singular) typo along the way.

Guard tests updated: discovery behavior is asserted against resolveEccRoot();
the inline is asserted to delegate and to contain no Windows-fragile
constructs.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(resolve-ecc-root): restore full env-unset discovery in inline resolver

Address Greptile review on #2410: when CLAUDE_PLUGIN_ROOT is unset the
delegating inline could only load the resolver module from ~/.claude,
returning ~/.claude without ever reaching the plugin/cache search. Restore
the old inline's discovery breadth (exact plugin roots + versioned cache)
Windows-safely (no spread, nested arrays, or escaped quotes), then delegate
the authoritative decision to resolveEccRoot(). Add regression tests for
plugin-subdir and versioned-cache bootstrap with env unset.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: affaan <affaan@itomarkets.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-07-03 20:01:17 -07:00
Affaan MustafaandAffaan Mustafa 6cb194a3c6 fix(hooks): avoid escaped quotes in plugin bootstrap
Generate the inline hook root resolver with single-quoted JavaScript literals so Windows Git Bash does not choke on nested escaped double quotes before Node starts. Refresh hooks.json and add regression coverage for parsed hook commands and installed hook manifests.
2026-05-19 05:15:42 -04:00
Affaan MustafaandAffaan Mustafa b47dfa95a3 fix: add context monitor cost warning opt-out 2026-05-17 01:53:57 -04:00
Affaan MustafaandAffaan Mustafa 940135ea47 feat: add ECC statusline observability hooks
Salvages the useful statusline/context monitor work from stale PR #1504 while preserving the current continuous-learning hook runner wiring.

Adds the metrics bridge, context monitor, statusline script, shared cost/session bridge utilities, and tests. Fixes the reviewed false loop-detection hash collision for non-file tools, avoids default-session cost inflation, sanitizes statusline task lookup, and records hook payload session IDs in cost-tracker.
2026-05-11 23:44:06 -04:00
Affaan MustafaandAffaan Mustafa 20d862951f docs: close harness audit readiness gaps 2026-05-11 20:23:27 -04:00
Affaan MustafaandGitHub c45aeee57f fix: salvage remaining stale queue fixes (#1754) 2026-05-11 16:41:08 -04:00
Affaan MustafaandAffaan Mustafa cfe770a735 fix: add gateguard recovery escape hatch 2026-04-30 11:26:15 -04:00
Affaan MustafaandAffaan Mustafa b1456bd954 fix: cap session-start context injection 2026-04-30 08:41:52 -04:00
Affaan MustafaandAffaan Mustafa 3fadc37802 fix: route continuous learning observe hooks through node 2026-04-29 21:28:59 -04:00
Affaan Mustafa ccecb0b9f4 fix: restore string hook commands for Claude Code schema 2026-04-15 17:25:33 -07:00
Affaan Mustafa 1fabf4d2cf fix: consolidate bash hooks without fork storms 2026-04-14 21:23:57 -07:00
Affaan Mustafa 1b7c5789fc fix: bootstrap plugin-installed hook commands safely 2026-04-14 20:24:21 -07:00
Affaan MustafaandGitHub e0ddb331f6 Merge pull request #1367 from ozoz5/feat/gateguard
feat(hooks,skills): add gateguard fact-forcing pre-action gate
2026-04-13 01:05:20 -07:00
Affaan Mustafa 18c90a7a17 fix: document supported claude hook install path 2026-04-12 23:29:45 -07:00
Ke WangandClaude Opus 4.6 809e0fa0a9 fix: address PR review comments on block-no-verify hook
- Add `minimal` profile so the security hook runs in all profiles
- Scope -n/--no-verify flag check to the detected subcommand region,
  preventing false positives on chained commands (e.g. `git log -n 10`)
- Guard stdin listeners with `require.main === module` so require()
  from run-with-flags.js does not register unnecessary listeners
- Verify subcommand token is preceded only by flags/flag-args after
  "git", preventing misclassification of argument values as subcommands
- Add integration tests for block-no-verify hook

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:29:01 -05:00
Ke Wang dae663d856 fix: route block-no-verify hook through run-with-flags.js
Replace inline `npx block-no-verify@1.1.2` with a standalone Node.js
script routed through `run-with-flags.js`, matching every other hook.

Fixes two bugs:
1. npx inherits the project cwd and triggers EBADDEVENGINES in
   pnpm-only projects that set devEngines.packageManager.onFail=error.
2. The hook bypassed run-with-flags.js so ECC_DISABLED_HOOKS had no
   effect — the isHookEnabled() check never ran.

The new script replicates the full block-no-verify@1.1.2 detection
logic (--no-verify, -n shorthand for commit, core.hooksPath override)
with zero external dependencies.

Closes #1378
2026-04-12 19:53:15 -05:00
setoandClaude Opus 4.6 9a64e0d271 fix: gate MultiEdit tool alongside Edit/Write
MultiEdit was bypassing the fact-forcing gate because only Edit and
Write were checked. Now MultiEdit triggers the same edit gate (list
importers, public API, data schemas) before allowing file modifications.

Updated both the hook logic and hooks.json matcher pattern.

Addresses coderabbit/greptile/cubic-dev: "MultiEdit bypasses gate"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 18:18:16 +09:00
setoandClaude Opus 4.6 8a2d13187c fix: address P1 review feedback from greptile bot
1. Use run-with-flags.js wrapper (supports ECC_HOOK_PROFILE, ECC_DISABLED_HOOKS)
2. Add session timeout (30min inactivity = state reset, fixes "once ever" bug)
3. Add 9 integration tests (deny/allow/timeout/sanitize/disable)

Refactored hook to module.exports.run() pattern for direct require() by
run-with-flags.js (~50-100ms faster per invocation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 17:42:32 +09:00
setoandClaude Opus 4.6 5a03922934 feat(hooks,skills): add gateguard fact-forcing pre-action gate
A PreToolUse hook that forces Claude to investigate before editing.
Instead of self-evaluation ("are you sure?"), it demands concrete facts:
importers, public API, data schemas, user instruction.

A/B tested: +2.25 quality points (9.0 vs 6.75) across two independent tasks.

- scripts/hooks/gateguard-fact-force.js — standalone Node.js hook
- skills/gateguard/SKILL.md — skill documentation
- hooks/hooks.json — PreToolUse entries for Edit|Write and Bash

Full package with config: pip install gateguard-ai
Repo: https://github.com/zunoworks/gateguard

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 11:41:33 +09:00