Skip to content

Gate hygiene: Stop-hook gate runs twice in consumer repos; lock-preflight defeats blanked gates; test_affected = full suite on every Stop #129

Description

@robercano-ghbot

Three related defects found while diagnosing reCode#128, all in the gate path:

1. Consumer repos run the Stop gate twice

The scaffolded .claude/settings.json in consumer repos registers gate.sh test_affected as a Stop hook — and the plugin's own hooks.json registers the identical Stop hook again (${CLAUDE_PLUGIN_ROOT}/scripts/gate.sh test_affected). Every turn in a consumer repo pays the gate twice (in reDeploy that's 2 × ~90 s of full build+test). reCode itself only runs it once (local settings, no plugin). Either the plugin's hooks.json or the scaffolded settings hook should own this — not both.

2. gate.sh's pnpm-lock preflight runs before the "empty gate ⇒ skip" branch

In .claude/scripts/gate.sh, the lockfile-sync check (cmp pnpm-lock.yaml node_modules/.pnpm/lock.yamlexit 1) executes before the gates.json lookup that skips empty/unconfigured gates. A deliberately blanked gate ("test_affected": "" — the documented way to mark a gate not-configured) can therefore still fail the hook whenever node_modules is momentarily out of sync. The preflight belongs after the skip branch (or should only run for gates that will actually execute).

3. test_affected = full suite makes the Stop hook unaffordable

The reDeploy adapter's _note already admits test_affected "currently runs the full suite … refine later". In practice that is pnpm -r build && pnpm -r test && forge test (~90 s, all cores) after every turn, doubled by defect 1, plus the same suite burned by each loop-daemon tick. Besides the cost, a multi-minute Stop hook interacts badly with headless sessions (see #128: parents abandon slow children; orphaned gates die of SIGPIPE mid-report). The scaffold should ship an affected-scoped default (changed-package filter) or a hard time budget for Stop-hook gates.

All three were confirmed by direct observation (hooks.json inspection, gate.sh source, strace of a headless session whose gate finished green after its session was already gone).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmodule:harnessOrchestrator machinery under .claudeplannedOwner-approved for the autonomous loop (assigned ONLY by the owner)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions