Commit Graph

264 Commits

Author SHA1 Message Date
Affaan Mustafa
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
6c67566767 fix: keep gateguard session state alive 2026-04-13 00:58:50 -07:00
Affaan Mustafa
e2b5353fec Merge pull request #1398 from affaan-m/fix/opencode-plugin-version-sync
fix: sync OpenCode hook banner version
2026-04-13 00:52:40 -07:00
Affaan Mustafa
9ae51bc3c1 Merge pull request #1393 from affaan-m/fix/cursor-rule-mdc-install
fix: install Cursor rules as .mdc files
2026-04-13 00:52:03 -07:00
seto
dd2962ee92 fix: 5 bugs + 2 tests from 3-agent deep bughunt
Bugs fixed:
- B1: JS gate messages still said "cat one real record" -> redacted/synthetic
- B2: Destructive bash key used 200-char truncation (collision bypass) -> SHA256 hash
- B3: sanitizePath only stripped \n\r -> now strips null bytes, bidi overrides, all control chars
- B4: Tool name matching was case-sensitive (latent bypass) -> lookup map normalization
- B5: SKILL.md Gate Types missing MultiEdit -> added with explanation

Tests added:
- T1: MultiEdit gate denies first unchecked file (CRITICAL - was untested)
- T2: MultiEdit allows after all files gated

11/11 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:32:46 +09:00
Affaan Mustafa
a0a1eda8fc fix: sync opencode hook banner version 2026-04-13 00:15:55 -07:00
seto
4dbed5ff5b fix: cubic-dev-ai round 2 — 3 issues across SKILL.md + pruning
P1: Gate message asked for raw production data records — changed to
    "redacted or synthetic values" to prevent sensitive data exfiltration

P2: SKILL.md description now includes MultiEdit (was missing after
    MultiEdit gate was added in previous commit)

P2: Session key pruning now caps __prefixed keys at 50 to prevent
    unbounded growth even in theoretical edge cases

9/9 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 16:11:33 +09:00
Affaan Mustafa
9e607ebb30 fix: prefer cursor native hooks during install 2026-04-13 00:07:15 -07:00
Affaan Mustafa
7374ef6a73 fix: normalize cursor rule installs 2026-04-12 23:51:58 -07:00
seto
5540282dcb fix: remove unnecessary disk I/O + fix test cleanup
- isChecked() no longer calls saveState() — read-only operation
  should not write to disk (was causing 3x writes per tool call)
- Test cleanup uses fs.rmSync(recursive) instead of fs.rmdirSync
  which failed with ENOTEMPTY when .tmp files remained

9/9 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:41:58 +09:00
seto
67256194a0 fix: P1 test state-file PID mismatch + P2 session key eviction
P1 (cubic-dev-ai): Test process PID differs from spawned hook PID,
so test was seeding/clearing wrong state file. Fix: pass fixed
CLAUDE_SESSION_ID='gateguard-test-session' to spawned hooks.

P2 (cubic-dev-ai): Pruning checked array could evict __bash_session__
and other session keys, causing gates to re-fire mid-session. Fix:
preserve __prefixed keys during pruning, only evict file-path entries.

9/9 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:40:13 +09:00
seto
6ed1c643e7 fix: MultiEdit gate bypass — handle edits[].file_path correctly
P1 bug reported by greptile-apps: MultiEdit uses toolInput.edits[].file_path,
not toolInput.file_path. The gate was silently allowing all MultiEdit calls.

Fix: separate MultiEdit into its own branch that iterates edits array
and gates on the first unchecked file_path.

9/9 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:37:39 +09:00
Affaan Mustafa
133e881ce0 fix: install Cursor rules as mdc files 2026-04-12 23:32:39 -07:00
seto
45823fcede fix: session-scoped state to prevent cross-session race
Addresses reviewer feedback from @affaan-m:

1. State keyed by CLAUDE_SESSION_ID / ECC_SESSION_ID
   - Falls back to pid-based isolation when env vars absent
   - State file: state-{sessionId}.json (was .session_state.json)

2. Atomic write+rename semantics
   - Write to temp file, then fs.renameSync to final path
   - Prevents partial reads from concurrent hooks

3. Bounded checked list (MAX_CHECKED_ENTRIES = 500)
   - Prunes to last 500 entries when cap exceeded
   - Stale session files auto-deleted after 1 hour

9/9 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 15:30:34 +09:00
Affaan Mustafa
18c90a7a17 fix: document supported claude hook install path 2026-04-12 23:29:45 -07:00
Affaan Mustafa
3792b69a38 fix: block unsafe privileged workflow checkouts 2026-04-12 23:23:01 -07:00
Affaan Mustafa
2b09308224 Merge pull request #1384 from KeWang0622/fix/lint-md028-eqeqeq
fix: resolve markdownlint MD028 + ESLint eqeqeq lint failures
2026-04-12 23:03:19 -07:00
Affaan Mustafa
5f55484fa9 Merge pull request #1385 from KeWang0622/fix/block-no-verify-hook
fix: route block-no-verify hook through run-with-flags.js
2026-04-12 23:02:19 -07:00
Affaan Mustafa
2ece2cfc90 fix: stop injecting managed hooks into claude settings 2026-04-12 22:39:48 -07:00
Affaan Mustafa
28edd197c2 fix: harden release surface version and packaging sync (#1388)
* fix: keep ecc release surfaces version-synced

* fix: keep lockfile release version in sync

* fix: remove release version drift from locks and tests

* fix: keep root release metadata version-synced

* fix: keep codex marketplace metadata version-synced

* fix: gate release workflows on full metadata sync

* fix: ship all versioned release metadata

* fix: harden manual release path

* fix: keep localized release docs version-synced

* fix: sync install architecture version examples

* test: cover shipped plugin metadata in npm pack

* fix: verify final npm payload in release script

* fix: ship opencode lockfile in npm package

* docs: sync localized release highlights

* fix: stabilize windows ci portability

* fix: tighten release script version sync

* fix: prefer repo-relative hook file paths

* fix: make npm pack test shell-safe on windows
2026-04-12 22:33:32 -07:00
Affaan Mustafa
fc5921a521 fix: detach ecc2 background session runners (#1387)
* fix: detach ecc2 background session runners

* fix: stabilize windows ci portability

* fix: persist detached runner startup stderr

* fix: prefer repo-relative hook file paths

* fix: make npm pack test shell-safe on windows
2026-04-12 22:29:05 -07:00
Ke Wang
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
Ke Wang
6a247d4c43 fix: resolve markdownlint MD028 and ESLint eqeqeq warnings
Fix two lint issues that cause `npm run lint` to exit non-zero:

1. README.md (MD028): Two consecutive blockquotes separated by a bare
   blank line. Markdownlint treats this as one blockquote with an
   illegal blank line inside. Replace the blank line with a `>`
   continuation so both paragraphs stay in the same blockquote.

2. session-activity-tracker.js (eqeqeq): Three instances of `== null`
   replaced with explicit `=== null || === undefined` guards to satisfy
   the repo's `eqeqeq: warn` ESLint rule.

Closes #1366
2026-04-12 16:00:55 -05:00
seto
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
seto
b6a290d061 fix: allow destructive bash retry after facts presented
Destructive bash gate previously denied every invocation with no
isChecked call, creating an infinite deny loop. Now gates per-command
on first attempt and allows retry after the model presents the required
facts (targets, rollback plan, user instruction).

Addresses greptile P1: "Destructive bash gate permanently blocks"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 18:08:15 +09:00
seto
96139b2dad fix: address P2 review feedback (coderabbitai, cubic-dev-ai)
- GATEGUARD_STATE_DIR env var for test isolation (hook + tests)
- Exit code assertions on all 9 tests (no vacuous passes)
- Non-vacuous allow-path assertions (verify pass-through preserves input)
- Robust newline-injection assertion
- clearState() now reports errors instead of swallowing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 18:04:09 +09:00
seto
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
seto
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
Affaan Mustafa
b01a300c31 feat(ecc2): persist tool log params and trigger context 2026-04-09 08:04:18 -07:00
Affaan Mustafa
31f672275e feat(ecc2): infer tracked write modifications 2026-04-09 07:48:29 -07:00
Affaan Mustafa
eee9768cd8 feat(ecc2): persist file activity patch previews 2026-04-09 07:45:37 -07:00
Affaan Mustafa
c395b42d2c feat(ecc2): persist file activity diff previews 2026-04-09 07:40:28 -07:00
Affaan Mustafa
edd027edd4 feat(ecc2): classify typed file activity 2026-04-09 07:33:42 -07:00
Affaan Mustafa
48fd68115e feat(ecc2): sync hook activity into session metrics 2026-04-09 07:02:24 -07:00
Affaan Mustafa
08f61f667d feat: sync ecc2 cost tracker metrics 2026-04-09 06:22:20 -07:00
Affaan Mustafa
2e5e94cb7f fix: harden claude plugin manifest surfaces 2026-04-08 16:27:30 -07:00
Affaan Mustafa
86cbe3d616 feat: add c language compatibility 2026-04-08 15:42:49 -07:00
Affaan Mustafa
e226772a72 feat: add gemini agent adapter 2026-04-08 15:38:49 -07:00
Affaan Mustafa
e363c54057 fix: treat oauth mcp 401 probes as reachable 2026-04-08 15:34:34 -07:00
Affaan Mustafa
4967dad08c ci: gate releases on opencode payload verification 2026-04-06 14:08:08 -07:00
Affaan Mustafa
8488811b80 chore: remove legacy insaits integration 2026-04-05 20:19:21 -07:00
Affaan Mustafa
2f0a40a63f fix: prune expired session files on session start 2026-04-05 14:58:10 -07:00
Affaan Mustafa
b9d0e0b04d feat: inject active instincts into session start context 2026-04-05 14:55:31 -07:00
Affaan Mustafa
746d227acd fix: restore ci baseline for opencode packaging 2026-04-05 14:47:26 -07:00
Affaan Mustafa
786f46dad5 feat: support disabling bundled mcp servers 2026-04-05 14:37:28 -07:00
Affaan Mustafa
1346f83b08 fix: shorten plugin slug to ecc 2026-04-05 14:31:30 -07:00
Affaan Mustafa
db6d52e4af fix: ship built opencode plugin assets 2026-04-05 14:09:10 -07:00
Affaan Mustafa
8baffb4ad3 fix: harden install target filtering and MCP health probes 2026-04-05 13:59:42 -07:00
Affaan Mustafa
b10080c7dd fix: respect home overrides in hook utilities 2026-04-02 18:22:07 -07:00