cursordoctrine 0.5.1 → 0.5.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/README.md CHANGED
@@ -26,7 +26,7 @@ Cursor hooks that make the agent review its own edits without bolting a static-a
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, and anti-slop 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.
28
28
 
29
- When an implementation finishes, the stop hook runs one final review over everything that changed, then stops. Six axes. The first is **intent trace**: the hook pulls your last user message from the transcript and prepends it to the review so the model has to tie every diff hunk to a concrete request. Anything it can't trace is a hallucinated requirement and gets reverted. That's the only check that catches "clean code, wrong feature" — linters and later axes miss it.
29
+ When an implementation finishes, the stop hook runs one final review over everything that changed, then stops. Seven axes. The first is **intent trace**: the hook pulls your last user message from the transcript and prepends it to the review so the model has to tie every diff hunk to a concrete request. Anything it can't trace is a hallucinated requirement and gets reverted. The last is **mechanics & stack integrity** (N+1, idempotency, transactions, boundary validation, zombie listeners, god components, determinism) — patterns the regex scanner can't catch because they need semantic judgement. That's the only check that catches "clean code, wrong feature" — linters and later axes miss it.
30
30
 
31
31
  Subagents get the same treatment. If a delegated run edited files, it reviews its own work before the result goes back to the parent. Those edits fold into the parent's final review. Every bound is enforced twice: in the script and in `hooks.json`.
32
32
 
@@ -114,7 +114,7 @@ Crucially, `intent-anchor` carries the **semantic** contract (`intent`/`acceptan
114
114
  | Session | `sessionStart` | `inject-doctrine` reads doctrine + user rules + declared-editing + **pre-compile** and emits them as `additional_context`. |
115
115
  | Every turn | `postToolUse` | **`intent-anchor`** (registered first) re-injects `.scope.json` into `additional_context` at the first tool boundary of each turn — the anti-Salience-Dilution move that keeps `intent` + `acceptance` in the model's attentional focus before edits pile up. If the prompt changed since last turn, it demands the contract be updated. Then `post-tool-use` folds subagent markers and drains the feedback file. |
116
116
  | Shell | `beforeShellExecution` | `permission-gate` checks the command against a deny list. Allow by default, deny by list, fail open. |
117
- | Edit | `afterFileEdit` + `stop` | **Proactive:** `intent-anchor` (`postToolUse`) scaffolds `.scope.json` per prompt and re-injects it each turn. **Reactive:** `self-review-trigger` stashes the review prompt per edit; `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. |
117
+ | Edit | `afterFileEdit` + `stop` | **Proactive:** `intent-anchor` (`postToolUse`) scaffolds `.scope.json` per prompt and re-injects it each turn. **Reactive:** `self-review-trigger` stashes the review prompt per edit; `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 seven-axis pass. |
118
118
  | 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`. |
119
119
 
120
120
  ## Layout
@@ -56,26 +56,18 @@ Step A — mechanical scan (if available):
56
56
  Step B — canonical checklist (always):
57
57
  Read `~/.agents/hooks/anti-slop.md` and apply ALL 13 items to every hunk you
58
58
  changed this session. That file is the single source of truth for slop
59
- detection — items 1–10 are structural/code, 11 is semantic contracts, 12 is
60
- operational slop (retries, await-in-loop, telemetry spam), 13 is change
61
- surface. Fix every hit; consolidate clones to one source of truth.
59
+ detection — it is NOT repeated here. Fix every hit; consolidate clones to one
60
+ source of truth.
62
61
 
63
62
  Step C — session footprint (also in the header above):
64
63
  If "Session footprint" shows >5 files or the request was simple, justify each
65
64
  file or trim. Unjustified files are slop.
66
65
 
67
- Step D — declared scope (closing gate for Compuerta 1):
68
- If `.scope.json` exists in the repo root, run the session's full diff against
69
- the declared contract. In your shell:
70
- for f in $(git diff --name-only HEAD); do
71
- python ~/.cursor/skills/anti-slop/scripts/scope_match.py --path "$f" --patterns-file .scope.json
72
- done
73
- Any file reporting `"in_scope": false` is a scope violation you must justify
74
- (add to .scope.json with a one-line reason) or revert. If `.scope.json` does
75
- not exist, this step is skipped — the declared-editing ladder and the
76
- per-edit scope-gate-audit hook are the opt-in discipline.
77
-
78
66
  Fix with edits now; re-run the scan (if Step A ran) and the tests; then stop.
67
+ (The per-edit `scope-gate-audit` hook already checks `.scope.json` files[] on
68
+ every edit — Step D of older versions ran that loop again here. Removed: it
69
+ duplicated the live hook and burned tokens. If `.scope.json` exists, trust the
70
+ per-edit gate; the intent trace in axis 0 is the whole-session backstop.)
79
71
 
80
72
  ## 5. Wiring completeness
81
73
  For every user-visible behavior you added or changed (button, form submit, API
@@ -97,3 +89,38 @@ faked, either wire it now or remove the dead half so the diff does not ship
97
89
  scaffolding that looks complete but does nothing. Stubs you intend to wire later
98
90
  must be marked with a `TODO(wire):` comment naming what is missing; unmarked
99
91
  dead ends are failures.
92
+
93
+ ## 6. Mechanics & Stack Integrity
94
+ Stateless, cheap mechanical checks. These are patterns the regex scanner CANNOT
95
+ catch (they need semantic/transversal judgement), so do them by reading the
96
+ diff. If a pattern below is present, FIX it — do not explain, delete and write
97
+ the correct pattern.
98
+
99
+ Backend / DB:
100
+ - N+1 query: a query/fetch inside a loop over a list -> batch it or join.
101
+ - Non-idempotent mutation: a POST/PUT that double-applies on retry -> make it
102
+ idempotent (idempotency-key) or wrap in a transaction.
103
+ - Transactional integrity: multi-write ops (DB/API/files) without rollback or
104
+ a compensating action on partial failure -> wrap in a transaction or Saga.
105
+ - Missing boundary validation: external input (API/params/DB/URL) trusted
106
+ without a schema (Zod/Pydantic/Joi) -> validate at the boundary; never
107
+ hand-validate deeper in the logic.
108
+
109
+ Frontend (React / Next / Astro / Tailwind):
110
+ - Zombie listener: a useEffect that adds a listener/subscription/timer
111
+ without a cleanup `return` -> add it.
112
+ - God component: a single file doing fetch + state + business logic + JSX
113
+ (>150 lines) -> split hooks / logic / render.
114
+ - Tailwind soup & magic tokens: a className with >~6 utilities repeated across
115
+ elements, or hardcoded hex / z-[9999] -> extract to a component or cva,
116
+ use design tokens.
117
+ - Index-as-key in non-static lists -> use a unique id.
118
+
119
+ Determinism / purity:
120
+ - Date.now(), Math.random(), process.env read inline in business logic ->
121
+ inject them (param or a context module) so the function is pure & testable.
122
+ - In-place mutation of shared state (arr.push, obj.prop =) when a caller holds
123
+ a reference -> return new structures ([...arr, x], .map/.filter).
124
+
125
+ You do NOT need to run a tool for these — read the diff and apply the named fix.
126
+ If none apply, say so in one line.
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env bash
2
2
  # final-review.sh - stop hook (Cursor, Linux).
3
3
  #
4
- # ONE comprehensive end-of-implementation review across six axes:
5
- # intent, correctness, reliability, coverage, anti-slop, and wiring completeness. When the agent finishes
4
+ # ONE comprehensive end-of-implementation review across seven axes:
5
+ # intent, correctness, reliability, coverage, anti-slop, wiring completeness,
6
+ # and mechanics & stack integrity. When the agent finishes
6
7
  # an implementation that touched files, Cursor auto-submits this hook's
7
8
  # `followup_message` as the next user turn, so the model re-audits everything
8
9
  # it changed this session and FIXES what fails.
@@ -4,7 +4,7 @@
4
4
  # Counterpart of final-review.sh for delegated work. afterFileEdit DOES fire
5
5
  # inside subagents (verified: a subagent run left its edits in
6
6
  # session-edits-<subagent-cid>.txt), but subagents get no `stop` event, so
7
- # that marker is never drained and the six-axis review never fires for
7
+ # that marker is never drained and the seven-axis review never fires for
8
8
  # delegated implementations. This hook closes the loop: when a subagent
9
9
  # finishes and ITS conversation has a session-edits marker, return ONE
10
10
  # followup_message so the subagent audits its own implementation before the
@@ -76,7 +76,7 @@ body=""
76
76
  [ -f "$prompt_file" ] && body="$(cat "$prompt_file")"
77
77
  if [ -z "$body" ]; then
78
78
  body='Audit everything you changed in this run and FIX what fails (do NOT revert the
79
- behaviour the task asked for). Six axes, in order:
79
+ behaviour the task asked for). Seven axes, in order:
80
80
  0. Intent trace - tie every diff hunk back to your original task. Untraceable = hallucinated.
81
81
  1. Correctness - logic, edge cases (null/empty/zero/boundary), language traps, security.
82
82
  2. Reliability - error paths handled, no swallowed errors, resources released.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursordoctrine",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Thin self-review hooks for Cursor — the model is the auditor. Pruned + deduplicated: intent-anchor (auto-scaffolded .scope.json per prompt + per-turn re-injection against Salience Dilution), intent-trace final review, unified anti-slop checklist as single source of truth.",
5
5
  "bin": {
6
6
  "cursordoctrine": "bin/cli.mjs"
@@ -228,7 +228,7 @@ The `stop` hook (`~/.agents/hooks/final-review.ps1` on Windows,
228
228
  `~/.agents/hooks/final-review.sh` on Linux) fires after the agent finishes an
229
229
  implementation that edited files. It extracts the last `<user_query>` from the
230
230
  session transcript (Tier 0 intent trace), reports session footprint (Tier 5),
231
- and auto-submits a `followup_message` so the model audits six axes: intent,
231
+ and auto-submits a `followup_message` so the model audits seven axes: intent,
232
232
  correctness, reliability, coverage, anti-slop, wiring completeness. Axis 4 delegates to this skill's
233
233
  scanner (`scan_slop.py --all`) and the canonical checklist at
234
234
  `~/.agents/hooks/anti-slop.md` (13 items, including semantic contracts,
@@ -276,6 +276,6 @@ low-density identifiers per edit — shares `low_density.py` with this scanner's
276
276
  (`scope-gate-audit.ps1` / `.sh`, Compuerta 1 — opt-in declared-scope gate
277
277
  that flags edits outside `.scope.json`; shares `scope_match.py` with the
278
278
  **stop hook** (`final-review.ps1` / `.sh`,
279
- six-axis session review incl. intent trace and wiring completeness), and
279
+ seven-axis session review incl. intent trace, wiring completeness, and mechanics & stack integrity), and
280
280
  **declared-editing** (YAGNI ultra ladder injected at session start).
281
281
  This skill is the active "delete it now" layer those only nudge toward.
@@ -89,3 +89,38 @@ faked, either wire it now or remove the dead half so the diff does not ship
89
89
  scaffolding that looks complete but does nothing. Stubs you intend to wire later
90
90
  must be marked with a `TODO(wire):` comment naming what is missing; unmarked
91
91
  dead ends are failures.
92
+
93
+ ## 6. Mechanics & Stack Integrity
94
+ Stateless, cheap mechanical checks. These are patterns the regex scanner CANNOT
95
+ catch (they need semantic/transversal judgement), so do them by reading the
96
+ diff. If a pattern below is present, FIX it — do not explain, delete and write
97
+ the correct pattern.
98
+
99
+ Backend / DB:
100
+ - N+1 query: a query/fetch inside a loop over a list -> batch it or join.
101
+ - Non-idempotent mutation: a POST/PUT that double-applies on retry -> make it
102
+ idempotent (idempotency-key) or wrap in a transaction.
103
+ - Transactional integrity: multi-write ops (DB/API/files) without rollback or
104
+ a compensating action on partial failure -> wrap in a transaction or Saga.
105
+ - Missing boundary validation: external input (API/params/DB/URL) trusted
106
+ without a schema (Zod/Pydantic/Joi) -> validate at the boundary; never
107
+ hand-validate deeper in the logic.
108
+
109
+ Frontend (React / Next / Astro / Tailwind):
110
+ - Zombie listener: a useEffect that adds a listener/subscription/timer
111
+ without a cleanup `return` -> add it.
112
+ - God component: a single file doing fetch + state + business logic + JSX
113
+ (>150 lines) -> split hooks / logic / render.
114
+ - Tailwind soup & magic tokens: a className with >~6 utilities repeated across
115
+ elements, or hardcoded hex / z-[9999] -> extract to a component or cva,
116
+ use design tokens.
117
+ - Index-as-key in non-static lists -> use a unique id.
118
+
119
+ Determinism / purity:
120
+ - Date.now(), Math.random(), process.env read inline in business logic ->
121
+ inject them (param or a context module) so the function is pure & testable.
122
+ - In-place mutation of shared state (arr.push, obj.prop =) when a caller holds
123
+ a reference -> return new structures ([...arr, x], .map/.filter).
124
+
125
+ You do NOT need to run a tool for these — read the diff and apply the named fix.
126
+ If none apply, say so in one line.
@@ -1,7 +1,8 @@
1
1
  # final-review.ps1 - stop hook (Cursor).
2
2
  #
3
- # ONE comprehensive end-of-implementation review across six axes:
4
- # intent, correctness, reliability, coverage, anti-slop, and wiring completeness. When the agent finishes an
3
+ # ONE comprehensive end-of-implementation review across seven axes:
4
+ # intent, correctness, reliability, coverage, anti-slop, wiring completeness,
5
+ # and mechanics & stack integrity. When the agent finishes an
5
6
  # implementation that touched files, Cursor auto-submits this hook's
6
7
  # `followup_message` as the next user turn, so the model re-audits everything it
7
8
  # changed this session and FIXES what fails - the model-as-auditor pattern over
@@ -3,7 +3,7 @@
3
3
  # Counterpart of final-review.ps1 for delegated work. afterFileEdit DOES fire
4
4
  # inside subagents (verified: a poteto subagent run left ~58 entries in
5
5
  # session-edits-<subagent-cid>.txt), but subagents get no `stop` event, so
6
- # that marker is never drained and the six-axis review never fires for
6
+ # that marker is never drained and the seven-axis review never fires for
7
7
  # delegated implementations. This hook closes the loop: when a subagent
8
8
  # finishes and ITS conversation has a session-edits marker, return ONE
9
9
  # followup_message so the subagent audits its own implementation before the
@@ -76,7 +76,7 @@ if (Test-Path $promptFile) { $body = Get-Content -Raw $promptFile }
76
76
  if (-not $body) {
77
77
  $body = @'
78
78
  Audit everything you changed in this run and FIX what fails (do NOT revert the
79
- behaviour the task asked for). Six axes, in order:
79
+ behaviour the task asked for). Seven axes, in order:
80
80
  0. Intent trace - tie every diff hunk back to your original task. Untraceable = hallucinated.
81
81
  1. Correctness - logic, edge cases (null/empty/zero/boundary), language traps, security.
82
82
  2. Reliability - error paths handled, no swallowed errors, resources released.