cursordoctrine 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/INSTALL.md CHANGED
@@ -109,7 +109,7 @@ Also validate the config: `~/.cursor/hooks.json` must parse as JSON.
109
109
 
110
110
  1. Restart Cursor (hooks.json is read at startup).
111
111
  2. Open any project and start a new agent chat. The doctrine should be in context — ask the agent "what does your doctrine say about diffs?" and it should answer from §2; ask "what is the Anchor Set?" and it should answer from `pre-compile.md` (Objective / Constraints / Scope / Deterministic success).
112
- 3. Have the agent make a small edit to a tracked file. On the next turn it should receive a `SELF-REVIEW TRIGGER` message, and (if it's the first edit of the implementation) a `PRE-COMPILE NUDGE` reminder to write its Anchor Set to `.scope.json`.
112
+ 3. Have the agent make a small edit to a tracked file. On the next turn it should receive a `SELF-REVIEW TRIGGER` message, and (if it's the first edit of that turn) a `PRE-COMPILE NUDGE` reminder to write its Anchor Set to `.scope.json`. The nudge re-fires on the first edit of each new turn.
113
113
  4. Ask the agent to run `git push --force` (in a throwaway repo). The permission gate must block it.
114
114
  5. Finish a small implementation and stop. A single `FINAL REVIEW` follow-up should fire — exactly once.
115
115
  6. Delegate a small edit to a subagent (e.g. ask the agent to "use a generalPurpose subagent to add a comment to <file>"). The subagent should receive one `SUBAGENT FINAL REVIEW` follow-up before returning, and the parent should see `SUBAGENT WORK DETECTED` at its next tool boundary. (`subagentStop` is only read at startup — if nothing fires, restart Cursor again.)
package/README.md CHANGED
@@ -21,7 +21,7 @@
21
21
 
22
22
  Cursor hooks that make the agent review its own edits without bolting a static-analysis pipeline onto every keystroke. No regex army, no scoring engine. Four jobs:
23
23
 
24
- 1. **Compile intent before coding** (proactive) — at session start the agent gets the doctrine plus the **Anchor Set** discipline (`pre-compile.md`): before writing code it must emit *Objective / Constraints / Scope / Deterministic success*, and write that contract to `.scope.json`. On the first edit of each implementation a `anchor-set-nudge` advisory fires to catch intent dilution at token ~50 instead of waiting for the stop-hook review at token ~5000.
24
+ 1. **Compile intent before coding** (proactive) — at session start the agent gets the doctrine plus the **Anchor Set** discipline (`pre-compile.md`): before writing code it must emit *Objective / Constraints / Scope / Deterministic success*, and write that contract to `.scope.json`. On the first edit of each agent turn a `anchor-set-nudge` advisory fires to catch intent dilution at token ~50 instead of waiting for the stop-hook review at token ~5000.
25
25
  2. **Inject the doctrine** at session start — every chat starts with the same short governing text (`doctrine.md`, `USER-RULES.md`, `declared-editing.md` the YAGNI ultra ladder, and `pre-compile.md` the thin intent-compilation phase).
26
26
  3. **Hand the model its own edits back** (reactive) — after each agent edit, a self-review prompt goes into a pending file (plus semantic-density, scope-gate, anti-slop, and the pre-compile nudge advisories when they trip). Next turn the model reads its diff, fixes real bugs, stays quiet otherwise.
27
27
  4. **Gate blast radius** — one permission gate denies a short explicit list of dangerous commands (`rm -rf /`, `curl | sh`, force-push, `npm publish`, ...). Everything else passes.
@@ -90,7 +90,7 @@ Two machine-checkable consequences:
90
90
  - **`scope-gate-audit`** (afterFileEdit, opt-in via `.scope.json` existing) audits every edit against `files[]` and quotes `intent` + `acceptance` back on a violation. Editing outside the declared set is the textbook scope-creep signal.
91
91
  - **final-review axis 0** (intent trace) traces every diff hunk back to `intent`. Anything untraceable is a hallucinated requirement.
92
92
 
93
- On the **first edit of each implementation**, `anchor-set-nudge` drops a reminder into the feedback bus: *did you write your Anchor Set to `.scope.json`?* One nudge per body of work — the flag is cleared at the same per-implementation boundary where the final-review one-shot brake fires, so a long chat with N implementations gets N nudges.
93
+ On the **first edit of each agent turn**, `anchor-set-nudge` drops a reminder into the feedback bus: *did you write your Anchor Set to `.scope.json`?* One nudge per turn — the latch is armed on that first edit and cleared **unconditionally** by the stop hook on every turn boundary, so the next turn re-earns its nudge. A long chat with N turns gets up to N nudges, and the latch can never get stranded silenced mid-session.
94
94
 
95
95
  The Anchor Set is skipped for trivial one-liners (typo, literal) — the `declared-editing.md` ladder's rung 1 governs when it's overkill.
96
96
 
@@ -101,7 +101,7 @@ The Anchor Set is skipped for trivial one-liners (typo, literal) — the `declar
101
101
  | Session | `sessionStart` | `inject-doctrine` reads doctrine + user rules + declared-editing + **pre-compile** and emits them as `additional_context`. |
102
102
  | Every turn | `postToolUse` | Folds completed subagents' edit markers into this conversation's marker, then drains the conversation's pending feedback file into `additional_context`. One-shot, keyed by conversation id. |
103
103
  | Shell | `beforeShellExecution` | `permission-gate` checks the command against a deny list. Allow by default, deny by list, fail open. |
104
- | Edit | `afterFileEdit` + `stop` | **Proactive:** `anchor-set-nudge` fires once per implementation to push the Anchor Set. **Reactive:** `self-review-trigger` stashes the review prompt per edit; `minimal-edit-audit` (deprecated), `semantic-density-audit`, `scope-gate-audit` (opt-in, audits `.scope.json`), and `anti-slop-audit` append advisories when they trip; `final-review` fires one end-of-implementation six-axis pass. |
104
+ | Edit | `afterFileEdit` + `stop` | **Proactive:** `anchor-set-nudge` fires once per turn (on its first edit) to push the Anchor Set. **Reactive:** `self-review-trigger` stashes the review prompt per edit; `minimal-edit-audit` (deprecated), `semantic-density-audit`, `scope-gate-audit` (opt-in, audits `.scope.json`), and `anti-slop-audit` append advisories when they trip; `final-review` fires one end-of-implementation six-axis pass. |
105
105
  | Subagent | `subagentStop` | `subagent-stop-review` fires one in-subagent final review when a delegated run edited files, before the result returns to the parent. Marker-gated and flag-braked like `final-review`. |
106
106
 
107
107
  ## Layout
@@ -150,7 +150,7 @@ All hooks fail open and always exit 0. Nothing here can block your session.
150
150
 
151
151
  - **State lives under `$HOME`**, in `~/.cursor/.hooks-pending/`, keyed by conversation id. No repo litter. Concurrent sessions can't drain each other's prompts. Stale state older than 7 days gets swept on every stop.
152
152
  - **`afterFileEdit` output isn't consumed by Cursor**, so edit hooks write to a pending file and `post-tool-use` re-emits it at the next tool boundary. That's the whole message bus.
153
- - **One review per implementation.** The stop hook arms a per-conversation flag before emitting its follow-up, so a crash can't re-fire it and a long chat still gets a review after each implementation. The `anchor-set-nudge` flag and the review flag clear together at that boundary one nudge + one review per body of work.
153
+ - **One review per implementation.** The stop hook arms a per-conversation flag before emitting its follow-up, so a crash can't re-fire it and a long chat still gets a review after each implementation. The `anchor-set-nudge` latch is separate and simpler: it's cleared **unconditionally** on every stop, so the nudge re-fires on the first edit of each new turn and can never get stranded silenced mid-session.
154
154
  - **The `.scope.json` contract is opt-in.** No `.scope.json` in the repo root → `scope-gate-audit` stays silent and the system falls back to the `declared-editing` ladder plus the final-review footprint check. Writing the file is how the agent opts into a machine-checked scope.
155
155
  - **Subagents are first-class.** `afterFileEdit` fires inside subagents keyed by the subagent's conversation id. The harness normalizes agent edits (incl. `StrReplace`) to tool type `Write`, and `postToolUse` never fires for the `Task` tool — verified by payload capture. Matchers cover `Write|StrReplace|EditNotebook` defensively. `subagentStop` reviews the subagent in its own context. The parent folds orphaned subagent markers (from the `subagents/` transcript directory) into its own at every tool boundary and at stop.
156
156
 
package/bin/cli.mjs CHANGED
@@ -263,19 +263,40 @@ function verify() {
263
263
  return true;
264
264
  });
265
265
 
266
- check('anchor-set nudge fires on first edit, then goes quiet', () => {
267
- // First edit of the implementation -> the pre-compile nudge stashes its
268
- // advisory in the pending feedback bus and arms the one-shot flag.
269
- const first = runHook(hook('anchor-set-nudge'), { conversation_id: 'npxv3', file_path: join(HOME, 'x.py') });
270
- if (!first.includes('additional_context') || !first.includes('PRE-COMPILE NUDGE')) {
271
- // anchor-set-nudge appends to feedback-<cid>.txt (the shared bus) rather
272
- // than emitting JSON directly; drain it the same way post-tool-use does.
273
- const drained = runHook(hook('post-tool-use'), { conversation_id: 'npxv3' });
274
- if (!drained.includes('PRE-COMPILE NUDGE')) return { ok: false, detail: 'nudge did not reach the feedback bus on first edit' };
266
+ check('anchor-set nudge fires once per turn, stop re-arms it', () => {
267
+ // anchor-set-nudge appends to feedback-<cid>.txt (the shared bus) rather
268
+ // than emitting JSON directly; drain it the same way post-tool-use does.
269
+ const drainedOf = (cidv) => runHook(hook('post-tool-use'), { conversation_id: cidv });
270
+
271
+ // --- Turn 1 -------------------------------------------------------------
272
+ // First edit -> nudge stashes into the feedback bus and arms the latch.
273
+ runHook(hook('anchor-set-nudge'), { conversation_id: 'npxv3', file_path: join(HOME, 'x.py') });
274
+ if (!drainedOf('npxv3').includes('PRE-COMPILE NUDGE')) {
275
+ return { ok: false, detail: 'nudge did not reach the feedback bus on first edit' };
276
+ }
277
+ // Second edit same turn -> latch armed, nudge must stay silent.
278
+ runHook(hook('anchor-set-nudge'), { conversation_id: 'npxv3', file_path: join(HOME, 'y.py') });
279
+ if (drainedOf('npxv3').includes('PRE-COMPILE NUDGE')) {
280
+ return { ok: false, detail: 'nudge re-fired on second edit (latch not gating)' };
281
+ }
282
+ // End of turn: final-review clears the latch unconditionally. Drive a
283
+ // review-less stop (no session-edits marker) so it hits the clear path and
284
+ // exits {}, same as a turn that produced no reviewable edits.
285
+ const stopOut = runHook(hook('final-review'), { conversation_id: 'npxv3', status: 'completed' });
286
+ if (stopOut !== '{}' && stopOut.replace(/\s/g, '') !== '{}') {
287
+ // A review fired (fine - the earlier edit left a session-edits marker via
288
+ // self-review-trigger if one ran). What matters is the latch got cleared;
289
+ // we verify that with the next-turn re-fire below.
290
+ }
291
+ // --- Turn 2 -------------------------------------------------------------
292
+ // First edit of the NEXT turn -> latch was cleared at the stop boundary, so
293
+ // the nudge MUST re-fire. This is the regression that 0.4.0 shipped broken:
294
+ // the latch only cleared on the fragile second-stop path, so it stranded
295
+ // and the nudge went permanently silent mid-session.
296
+ runHook(hook('anchor-set-nudge'), { conversation_id: 'npxv3', file_path: join(HOME, 'z.py') });
297
+ if (!drainedOf('npxv3').includes('PRE-COMPILE NUDGE')) {
298
+ return { ok: false, detail: 'nudge did NOT re-fire on the next turn (latch stranded at the stop boundary)' };
275
299
  }
276
- // Second edit -> flag is armed, nudge must stay silent.
277
- const second = runHook(hook('anchor-set-nudge'), { conversation_id: 'npxv3', file_path: join(HOME, 'y.py') });
278
- if (second.includes('PRE-COMPILE NUDGE')) return { ok: false, detail: 'nudge re-fired on second edit (flag not gating)' };
279
300
  return true;
280
301
  });
281
302
 
@@ -2,20 +2,20 @@
2
2
  # anchor-set-nudge.sh - afterFileEdit "pre-compile" nudge (Cursor, Linux).
3
3
  #
4
4
  # Proactive counterpart to the reactive audits. On the FIRST file edit of an
5
- # implementation (per conversation), remind the agent to compile its Anchor Set
6
- # (pre-compile.md) and write .scope.json BEFORE piling on more code. The
7
- # reactive stack (self-review, anti-slop, final-review) only fires AFTER code
8
- # exists; this nudge catches intent dilution at token ~50, not at the ~5000 of
9
- # the stop-hook axis 0. A clean final review of the wrong feature is still the
10
- # wrong feature - the Anchor Set exists so the right feature is on the rails
11
- # from the first edit.
5
+ # agent turn, remind the agent to compile its Anchor Set (pre-compile.md) and
6
+ # write .scope.json BEFORE piling on more code. The reactive stack (self-review,
7
+ # anti-slop, final-review) only fires AFTER code exists; this nudge catches
8
+ # intent dilution at token ~50, not at the ~5000 of the stop-hook axis 0. A
9
+ # clean final review of the wrong feature is still the wrong feature - the
10
+ # Anchor Set exists so the right feature is on the rails from the first edit.
12
11
  #
13
- # One-shot PER IMPLEMENTATION, not per session: gated by an
14
- # anchor-declared-<cid>.flag in the pending dir. That flag is cleared by
15
- # final-review.sh / subagent-stop-review.sh at the SAME per-implementation
16
- # boundary where they clear session-edits-<cid>.txt and reviewed-<cid>.flag
17
- # (the stop after a review pass). So a long conversation with N implementations
18
- # gets N nudges, not one - every new body of work re-earns the reminder.
12
+ # Fires ONCE PER TURN (per conversation): gated by an anchor-declared-<cid>.flag
13
+ # in the pending dir, armed here on first edit and cleared UNCONDITIONALLY by
14
+ # final-review.sh / subagent-stop-review.sh on every stop. So a long
15
+ # conversation with N turns gets up to N nudges - every new turn re-earns the
16
+ # reminder on its first edit. The clear is unconditional (not gated on the
17
+ # reviewed-flag path) so the latch can never get stranded silenced mid-session,
18
+ # which would silently stop reminding the agent to write .scope.json.
19
19
  #
20
20
  # Advisory only: never blocks, never reads the diff, ALWAYS exits 0. Appends to
21
21
  # the shared feedback-<cid>.txt bus; post-tool-use.sh delivers it next turn.
@@ -41,11 +41,16 @@ anchor_flag="$pending_dir/anchor-declared-$cid.flag"
41
41
  # Sweep state from sessions that died before their stop hook ran.
42
42
  find "$pending_dir" -maxdepth 1 -type f -mtime +7 -delete 2>/dev/null
43
43
 
44
+ # Unconditionally clear the pre-compile nudge's per-turn latch. Every stop is a
45
+ # turn boundary; clearing here (not only inside the reviewed-flag block below)
46
+ # guarantees the nudge re-fires on the first edit of the NEXT turn and can never
47
+ # get stranded silenced. Clearing it only on the SECOND stop left the nudge
48
+ # permanently off for any conversation that never cleanly hit that boundary.
49
+ rm -f "$anchor_flag" 2>/dev/null
50
+
44
51
  # One-shot brake: the previous stop for this conversation emitted the review.
45
- # Also clear anchor-declared-<cid>.flag so the pre-compile nudge re-fires for
46
- # the NEXT implementation (one nudge per body of work, not per session).
47
52
  if [ -f "$flag" ]; then
48
- rm -f "$flag" "$marker" "$anchor_flag" 2>/dev/null
53
+ rm -f "$flag" "$marker" 2>/dev/null
49
54
  emit_none
50
55
  fi
51
56
 
@@ -46,11 +46,14 @@ marker="$pending_dir/session-edits-$cid.txt"
46
46
  flag="$pending_dir/reviewed-$cid.flag"
47
47
  anchor_flag="$pending_dir/anchor-declared-$cid.flag"
48
48
 
49
+ # Unconditionally clear the pre-compile nudge's per-turn latch so it re-fires
50
+ # on the first edit of the next subagent run. Clearing here (not only inside
51
+ # the reviewed-flag block below) can never strand the nudge silenced.
52
+ rm -f "$anchor_flag" 2>/dev/null
53
+
49
54
  # One-shot brake: the previous subagentStop for this id emitted the review.
50
- # Also clear anchor-declared-<cid>.flag so the pre-compile nudge re-fires for
51
- # the next subagent implementation (one nudge per body of work).
52
55
  if [ -f "$flag" ]; then
53
- rm -f "$flag" "$marker" "$anchor_flag" 2>/dev/null
56
+ rm -f "$flag" "$marker" 2>/dev/null
54
57
  emit_none
55
58
  fi
56
59
 
package/linux/hooks.json CHANGED
@@ -43,7 +43,7 @@
43
43
  "command": "bash ~/.agents/hooks/anchor-set-nudge.sh",
44
44
  "timeout": 5,
45
45
  "matcher": "^(Write|StrReplace|EditNotebook)$",
46
- "_comment": "5s: PROACTIVE pre-compile nudge. On the FIRST edit of each implementation (per conversation), remind the agent to compile its Anchor Set (pre-compile.md) into .scope.json BEFORE piling on more code. The reactive audits (self-review / anti-slop / final-review axis 0) only fire after code exists; this catches intent dilution at token ~50 instead of ~5000. One-shot per implementation: gated by anchor-declared-<cid>.flag, which final-review.sh / subagent-stop-review.sh clear at the same per-implementation boundary as reviewed-<cid>.flag. Advisory only; never blocks. Disable: HOOKS_ENFORCE=0 or ANCHOR_NUDGE_ENFORCE=0."
46
+ "_comment": "5s: PROACTIVE pre-compile nudge. On the FIRST edit of each agent turn (per conversation), remind the agent to compile its Anchor Set (pre-compile.md) into .scope.json BEFORE piling on more code. The reactive audits (self-review / anti-slop / final-review axis 0) only fire after code exists; this catches intent dilution at token ~50 instead of ~5000. One-shot per turn: gated by anchor-declared-<cid>.flag, armed here on first edit and cleared UNCONDITIONALLY by final-review.sh / subagent-stop-review.sh on every stop - so it re-fires on the first edit of the next turn and can never get stranded silenced. Advisory only; never blocks. Disable: HOOKS_ENFORCE=0 or ANCHOR_NUDGE_ENFORCE=0."
47
47
  }
48
48
  ],
49
49
  "postToolUse": [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cursordoctrine",
3
- "version": "0.4.1",
4
- "description": "Thin self-review hooks for Cursor — the model is the auditor. Pre-compile Anchor Set phase (proactive intent compilation), intent-trace final review (Tier 0), unified 13-item anti-slop checklist, operational slop detection.",
3
+ "version": "0.4.2",
4
+ "description": "Thin self-review hooks for Cursor — the model is the auditor. Pre-compile Anchor Set phase (proactive intent compilation, fires once per turn), intent-trace final review (Tier 0), unified 13-item anti-slop checklist, operational slop detection.",
5
5
  "bin": {
6
6
  "cursordoctrine": "bin/cli.mjs"
7
7
  },
@@ -1,20 +1,20 @@
1
1
  # anchor-set-nudge.ps1 - afterFileEdit "pre-compile" nudge (Cursor).
2
2
  #
3
3
  # Proactive counterpart to the reactive audits. On the FIRST file edit of an
4
- # implementation (per conversation), remind the agent to compile its Anchor Set
5
- # (pre-compile.md) and write .scope.json BEFORE piling on more code. The
6
- # reactive stack (self-review, anti-slop, final-review) only fires AFTER code
7
- # exists; this nudge catches intent dilution at token ~50, not at the ~5000 of
8
- # the stop-hook axis 0. A clean final review of the wrong feature is still the
9
- # wrong feature - the Anchor Set exists so the right feature is on the rails
10
- # from the first edit.
4
+ # agent turn, remind the agent to compile its Anchor Set (pre-compile.md) and
5
+ # write .scope.json BEFORE piling on more code. The reactive stack (self-review,
6
+ # anti-slop, final-review) only fires AFTER code exists; this nudge catches
7
+ # intent dilution at token ~50, not at the ~5000 of the stop-hook axis 0. A
8
+ # clean final review of the wrong feature is still the wrong feature - the
9
+ # Anchor Set exists so the right feature is on the rails from the first edit.
11
10
  #
12
- # One-shot PER IMPLEMENTATION, not per session: gated by an
13
- # anchor-declared-<cid>.flag in the pending dir. That flag is cleared by
14
- # final-review.ps1 / subagent-stop-review.ps1 at the SAME per-implementation
15
- # boundary where they clear session-edits-<cid>.txt and reviewed-<cid>.flag
16
- # (the stop after a review pass). So a long conversation with N implementations
17
- # gets N nudges, not one - every new body of work re-earns the reminder.
11
+ # Fires ONCE PER TURN (per conversation): gated by an anchor-declared-<cid>.flag
12
+ # in the pending dir, armed here on first edit and cleared UNCONDITIONALLY by
13
+ # final-review.ps1 / subagent-stop-review.ps1 on every stop. So a long
14
+ # conversation with N turns gets up to N nudges - every new turn re-earns the
15
+ # reminder on its first edit. The clear is unconditional (not gated on the
16
+ # reviewed-flag path) so the latch can never get stranded silenced mid-session,
17
+ # which would silently stop reminding the agent to write .scope.json.
18
18
  #
19
19
  # Advisory only: never blocks, never reads the diff, ALWAYS exits 0. Appends to
20
20
  # the shared feedback-<cid>.txt bus; post-tool-use.ps1 delivers it next turn.
@@ -48,12 +48,19 @@ Get-ChildItem $pendingDir -File -ErrorAction SilentlyContinue |
48
48
  Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-7) } |
49
49
  Remove-Item -Force -ErrorAction SilentlyContinue
50
50
 
51
+ # Unconditionally clear the pre-compile nudge's per-turn latch. Every stop is a
52
+ # turn boundary; clearing here (not only inside the reviewed-flag block below)
53
+ # guarantees the nudge re-fires on the first edit of the NEXT turn and can never
54
+ # get stranded silenced. The original design cleared anchor-declared-<cid>.flag
55
+ # only on the SECOND stop (the reviewed-flag path), so any conversation that
56
+ # never cleanly hit that boundary left the nudge permanently off - the agent
57
+ # then stopped being reminded to write .scope.json.
58
+ Remove-Item $anchorFlag -Force -ErrorAction SilentlyContinue
59
+
51
60
  # One-shot brake: the previous stop for this conversation emitted the review.
52
61
  # Clear the flag (and whatever the review pass itself edited) and end the loop.
53
- # Also clear anchor-declared-<cid>.flag so the pre-compile nudge re-fires for
54
- # the NEXT implementation (one nudge per body of work, not per session).
55
62
  if (Test-Path $flag) {
56
- Remove-Item $flag, $marker, $anchorFlag -Force -ErrorAction SilentlyContinue
63
+ Remove-Item $flag, $marker -Force -ErrorAction SilentlyContinue
57
64
  Emit-None
58
65
  }
59
66
 
@@ -45,11 +45,14 @@ $marker = Join-Path $pendingDir "session-edits-$cid.txt"
45
45
  $flag = Join-Path $pendingDir "reviewed-$cid.flag"
46
46
  $anchorFlag = Join-Path $pendingDir "anchor-declared-$cid.flag"
47
47
 
48
+ # Unconditionally clear the pre-compile nudge's per-turn latch so it re-fires
49
+ # on the first edit of the next subagent run. Clearing here (not only inside
50
+ # the reviewed-flag block below) can never strand the nudge silenced.
51
+ Remove-Item $anchorFlag -Force -ErrorAction SilentlyContinue
52
+
48
53
  # One-shot brake: the previous subagentStop for this id emitted the review.
49
- # Also clear anchor-declared-<cid>.flag so the pre-compile nudge re-fires for
50
- # the next subagent implementation (one nudge per body of work).
51
54
  if (Test-Path $flag) {
52
- Remove-Item $flag, $marker, $anchorFlag -Force -ErrorAction SilentlyContinue
55
+ Remove-Item $flag, $marker -Force -ErrorAction SilentlyContinue
53
56
  Emit-None
54
57
  }
55
58
 
@@ -43,7 +43,7 @@
43
43
  "command": "pwsh.exe -NoProfile -File ~/.agents/hooks/anchor-set-nudge.ps1",
44
44
  "timeout": 5,
45
45
  "matcher": "^(Write|StrReplace|EditNotebook)$",
46
- "_comment": "5s: PROACTIVE pre-compile nudge. On the FIRST edit of each implementation (per conversation), remind the agent to compile its Anchor Set (pre-compile.md) into .scope.json BEFORE piling on more code. The reactive audits (self-review / anti-slop / final-review axis 0) only fire after code exists; this catches intent dilution at token ~50 instead of ~5000. One-shot per implementation: gated by anchor-declared-<cid>.flag, which final-review.ps1 / subagent-stop-review.ps1 clear at the same per-implementation boundary as reviewed-<cid>.flag. Advisory only; never blocks. Disable: HOOKS_ENFORCE=0 or ANCHOR_NUDGE_ENFORCE=0."
46
+ "_comment": "5s: PROACTIVE pre-compile nudge. On the FIRST edit of each agent turn (per conversation), remind the agent to compile its Anchor Set (pre-compile.md) into .scope.json BEFORE piling on more code. The reactive audits (self-review / anti-slop / final-review axis 0) only fire after code exists; this catches intent dilution at token ~50 instead of ~5000. One-shot per turn: gated by anchor-declared-<cid>.flag, armed here on first edit and cleared UNCONDITIONALLY by final-review.ps1 / subagent-stop-review.ps1 on every stop - so it re-fires on the first edit of the next turn and can never get stranded silenced. Advisory only; never blocks. Disable: HOOKS_ENFORCE=0 or ANCHOR_NUDGE_ENFORCE=0."
47
47
  }
48
48
  ],
49
49
  "postToolUse": [