cursordoctrine 0.6.1 → 0.6.3

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/bin/cli.mjs CHANGED
@@ -334,22 +334,18 @@ function verify() {
334
334
  JSON.stringify({ role: 'user', message: { content: `<user_query>${q}</user_query>` } }) + '\n',
335
335
  'utf8');
336
336
 
337
- // --- Case 0: no .scope.json + NO transcript -> WRITE scaffold anyway -------
338
- // This is the 0.5.3 regression: creation was gated on $hasQuery, so when
339
- // Cursor didn't surface transcript_path in the first postToolUse fire, the
340
- // scope never appeared. Now creation is unconditional on a real root.
337
+ // --- Case 0: no .scope.json + NO transcript -> do NOT write hollow scaffold
338
+ // 0.6.1: never persist intent=<TODO> when the request is unreadable. Emit the
339
+ // pre-compile demand so the agent authors a real contract from the chat.
341
340
  runHook(hook('intent-anchor'), { conversation_id: anchorCid, cwd: repoDir });
342
341
  let d0 = drainedOf(anchorCid);
343
- if (!existsSync(scopePath)) {
344
- cleanup(); return { ok: false, detail: 'scaffold NOT created without transcript (0.5.3 regression)' };
342
+ if (existsSync(scopePath)) {
343
+ cleanup(); return { ok: false, detail: 'hollow scaffold written without transcript (0.6.1 regression)' };
345
344
  }
346
- let scope0;
347
- try { scope0 = JSON.parse(readFileSync(scopePath, 'utf8')); }
348
- catch { cleanup(); return { ok: false, detail: '.scope.json (no-transcript) is not valid JSON' }; }
349
- if (!scope0.intent || !scope0.intent.includes('TODO')) {
350
- cleanup(); return { ok: false, detail: `no-transcript scaffold should have intent <TODO>, got: ${scope0.intent}` };
345
+ if (!d0.includes('INTENT ANCHOR (pre-compile)')) {
346
+ cleanup(); return { ok: false, detail: 'no-transcript turn did not emit pre-compile demand' };
351
347
  }
352
- // Clear the latch + scope so Case A starts fresh (with a real query this time).
348
+ // Clear the latch so Case A starts fresh (with a real query this time).
353
349
  runHook(hook('final-review'), { conversation_id: anchorCid, status: 'completed' });
354
350
  cleanup();
355
351
 
package/linux/doctrine.md CHANGED
@@ -69,6 +69,10 @@ what the task requires**.
69
69
 
70
70
  The natural order is:
71
71
 
72
+ 0. **Restate** the request in one normalized line (`Understood as: …`) before
73
+ you touch a tool — grammar fixed, ambiguity resolved, meaning preserved.
74
+ It is the user's catch-point for a misread, and it becomes the contract's
75
+ `intent`. Full spec in pre-compile.
72
76
  1. **Read** the relevant file(s) to understand context.
73
77
  2. **Edit** to make the change.
74
78
  3. **Read** the file again (the self-review trigger will remind you).
@@ -9,12 +9,34 @@ This is the proactive phase. The anti-slop checklist, the self-review trigger
9
9
  and the final review are reactive — they audit after the fact. You compile the
10
10
  intent BEFORE the first token of code so they have the right thing to audit.
11
11
 
12
+ ## Step 0 — Restate the request (the user writes fast; you normalize)
13
+
14
+ Before the Anchor Set, in ONE line, play the request back as you understood it:
15
+
16
+ > **Understood as:** _one clean sentence — grammar fixed, pronouns resolved,
17
+ > implicit constraints made explicit, in the language of the request._
18
+
19
+ Mandatory every implementation turn. This line is the user's catch-point: a
20
+ misread surfaces HERE, before you write a line of code, instead of in review.
21
+ The restatement is **meaning-preserving** — you normalize phrasing, you do NOT
22
+ add scope, drop a constraint, or invent a requirement. If normalizing would
23
+ force a guess that changes what "correct" means, you do not bury the guess in
24
+ the restatement — you ask one sharp question (§5) and wait.
25
+
26
+ The user's verbatim words stay the ground truth: `.scope.json`'s `trace.query`
27
+ keeps them exactly as typed, and final-review traces every diff hunk back to
28
+ THAT, not to your paraphrase. Your normalized sentence becomes `intent` (and the
29
+ Anchor Set's OBJECTIVE below). The two must say the same thing in different
30
+ words — if you cannot make `intent` and `trace.query` agree, you have misread
31
+ the request, and that is the bug to fix first.
32
+
12
33
  ## The Anchor Set
13
34
 
14
35
  Answer these four, terse, in your first response. One phrase each, not prose:
15
36
 
16
- 1. OBJECTIVE — one operational sentence. What is *strictly* necessary. Not
17
- "improve X" — "make X return Y when Z".
37
+ 1. OBJECTIVE — your Step 0 restatement, tightened to the operational verb. One
38
+ sentence, what is *strictly* necessary. Not "improve X" — "make X return Y
39
+ when Z".
18
40
  2. CONSTRAINTS (local negations) — what you will NOT do. "NO schema migration.
19
41
  NO new dependency. NO refactor of the surrounding function." Negations bind
20
42
  harder than the objective: a constraint that the task contradicts is a bug
@@ -33,28 +55,36 @@ Answer these four, terse, in your first response. One phrase each, not prose:
33
55
 
34
56
  The `intent-anchor` hook creates and maintains `.scope.json` in the repo root for
35
57
  you, automatically, on the first tool of every turn:
36
- - `intent` is locked from your current request and REFRESHED when the request
58
+ - `intent` is seeded from your verbatim request and REFRESHED when the request
37
59
  changes — a new prompt regenerates the contract and resets `files[]`, so it
38
60
  never carries over between features;
39
61
  - `files[]` is auto-recorded — the scope hook appends every file you edit, so
40
62
  you never maintain it by hand;
41
- - `trace`, `_intent_hash`, `_generated_by` are hook bookkeeping (provenance and
42
- change detection). Leave them alone.
43
-
44
- Your one job on the contract: set **`acceptance`** the single deterministic check
45
- that decides done — which the hook cannot derive. Edit ONLY that field (a targeted
46
- string replace). Do **NOT** rewrite the whole file: overwriting it drops the hook's
47
- `_intent_hash`/`trace`, which disables per-prompt regeneration and brings back the
48
- cross-feature carryover. The scope-gate hook audits every edit against `files[]`,
49
- and final-review axis 0 traces every diff hunk back to `intent`.
63
+ - `trace.query` is the VERBATIM request (the audit anchor), `_intent_hash` and
64
+ `_generated_by` are hook bookkeeping. Leave all three alone.
65
+
66
+ Your two targeted edits on the contract (each a string replace on ONE field, never
67
+ a whole-file rewrite):
68
+ - **`intent`** → replace the verbatim seed with your Step 0 restatement: the
69
+ normalized, meaning-preserving sentence. This is what final-review axis 0
70
+ traces each diff hunk against, so a clean `intent` makes the audit sharp.
71
+ - **`acceptance`** set the single deterministic check that decides done, which
72
+ the hook cannot derive.
73
+
74
+ Do **NOT** touch `trace.query`, `_intent_hash`, or `_generated_by`, and do **NOT**
75
+ rewrite the whole file: `_intent_hash` is computed from the verbatim `trace.query`,
76
+ not from `intent`, so refining `intent` is safe — but dropping the hash/trace
77
+ disables per-prompt regeneration and brings back cross-feature carryover. Keeping
78
+ `trace.query` verbatim is what lets the audit catch a paraphrase that quietly
79
+ changed the meaning: `intent` and `trace.query` must agree.
50
80
 
51
81
  ```json
52
82
  {
53
- "intent": "<locked from your request by the hook>",
83
+ "intent": "<YOU refine this: your normalized Step 0 restatement>",
54
84
  "files": ["<auto-recorded by the hook as you edit>"],
55
85
  "acceptance": "<YOU set this: the deterministic check that decides done>",
56
86
  "allow_growth": false,
57
- "trace": { "query": "<originating request>", "ts": "<when>" },
87
+ "trace": { "query": "<VERBATIM request - the hook owns this, leave it>", "ts": "<when>" },
58
88
  "_intent_hash": "<hook bookkeeping>",
59
89
  "_generated_by":"intent-anchor hook"
60
90
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursordoctrine",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
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"
@@ -67,6 +67,10 @@ what the task requires**.
67
67
 
68
68
  The natural order is:
69
69
 
70
+ 0. **Restate** the request in one normalized line (`Understood as: …`) before
71
+ you touch a tool — grammar fixed, ambiguity resolved, meaning preserved.
72
+ It is the user's catch-point for a misread, and it becomes the contract's
73
+ `intent`. Full spec in pre-compile.
70
74
  1. **Read** the relevant file(s) to understand context.
71
75
  2. **Edit** to make the change.
72
76
  3. **Read** the file again (the self-review trigger will remind you).
@@ -9,12 +9,34 @@ This is the proactive phase. The anti-slop checklist, the self-review trigger
9
9
  and the final review are reactive — they audit after the fact. You compile the
10
10
  intent BEFORE the first token of code so they have the right thing to audit.
11
11
 
12
+ ## Step 0 — Restate the request (the user writes fast; you normalize)
13
+
14
+ Before the Anchor Set, in ONE line, play the request back as you understood it:
15
+
16
+ > **Understood as:** _one clean sentence — grammar fixed, pronouns resolved,
17
+ > implicit constraints made explicit, in the language of the request._
18
+
19
+ Mandatory every implementation turn. This line is the user's catch-point: a
20
+ misread surfaces HERE, before you write a line of code, instead of in review.
21
+ The restatement is **meaning-preserving** — you normalize phrasing, you do NOT
22
+ add scope, drop a constraint, or invent a requirement. If normalizing would
23
+ force a guess that changes what "correct" means, you do not bury the guess in
24
+ the restatement — you ask one sharp question (§5) and wait.
25
+
26
+ The user's verbatim words stay the ground truth: `.scope.json`'s `trace.query`
27
+ keeps them exactly as typed, and final-review traces every diff hunk back to
28
+ THAT, not to your paraphrase. Your normalized sentence becomes `intent` (and the
29
+ Anchor Set's OBJECTIVE below). The two must say the same thing in different
30
+ words — if you cannot make `intent` and `trace.query` agree, you have misread
31
+ the request, and that is the bug to fix first.
32
+
12
33
  ## The Anchor Set
13
34
 
14
35
  Answer these four, terse, in your first response. One phrase each, not prose:
15
36
 
16
- 1. OBJECTIVE — one operational sentence. What is *strictly* necessary. Not
17
- "improve X" — "make X return Y when Z".
37
+ 1. OBJECTIVE — your Step 0 restatement, tightened to the operational verb. One
38
+ sentence, what is *strictly* necessary. Not "improve X" — "make X return Y
39
+ when Z".
18
40
  2. CONSTRAINTS (local negations) — what you will NOT do. "NO schema migration.
19
41
  NO new dependency. NO refactor of the surrounding function." Negations bind
20
42
  harder than the objective: a constraint that the task contradicts is a bug
@@ -33,28 +55,36 @@ Answer these four, terse, in your first response. One phrase each, not prose:
33
55
 
34
56
  The `intent-anchor` hook creates and maintains `.scope.json` in the repo root for
35
57
  you, automatically, on the first tool of every turn:
36
- - `intent` is locked from your current request and REFRESHED when the request
58
+ - `intent` is seeded from your verbatim request and REFRESHED when the request
37
59
  changes — a new prompt regenerates the contract and resets `files[]`, so it
38
60
  never carries over between features;
39
61
  - `files[]` is auto-recorded — the scope hook appends every file you edit, so
40
62
  you never maintain it by hand;
41
- - `trace`, `_intent_hash`, `_generated_by` are hook bookkeeping (provenance and
42
- change detection). Leave them alone.
43
-
44
- Your one job on the contract: set **`acceptance`** the single deterministic check
45
- that decides done — which the hook cannot derive. Edit ONLY that field (a targeted
46
- string replace). Do **NOT** rewrite the whole file: overwriting it drops the hook's
47
- `_intent_hash`/`trace`, which disables per-prompt regeneration and brings back the
48
- cross-feature carryover. The scope-gate hook audits every edit against `files[]`,
49
- and final-review axis 0 traces every diff hunk back to `intent`.
63
+ - `trace.query` is the VERBATIM request (the audit anchor), `_intent_hash` and
64
+ `_generated_by` are hook bookkeeping. Leave all three alone.
65
+
66
+ Your two targeted edits on the contract (each a string replace on ONE field, never
67
+ a whole-file rewrite):
68
+ - **`intent`** → replace the verbatim seed with your Step 0 restatement: the
69
+ normalized, meaning-preserving sentence. This is what final-review axis 0
70
+ traces each diff hunk against, so a clean `intent` makes the audit sharp.
71
+ - **`acceptance`** set the single deterministic check that decides done, which
72
+ the hook cannot derive.
73
+
74
+ Do **NOT** touch `trace.query`, `_intent_hash`, or `_generated_by`, and do **NOT**
75
+ rewrite the whole file: `_intent_hash` is computed from the verbatim `trace.query`,
76
+ not from `intent`, so refining `intent` is safe — but dropping the hash/trace
77
+ disables per-prompt regeneration and brings back cross-feature carryover. Keeping
78
+ `trace.query` verbatim is what lets the audit catch a paraphrase that quietly
79
+ changed the meaning: `intent` and `trace.query` must agree.
50
80
 
51
81
  ```json
52
82
  {
53
- "intent": "<locked from your request by the hook>",
83
+ "intent": "<YOU refine this: your normalized Step 0 restatement>",
54
84
  "files": ["<auto-recorded by the hook as you edit>"],
55
85
  "acceptance": "<YOU set this: the deterministic check that decides done>",
56
86
  "allow_growth": false,
57
- "trace": { "query": "<originating request>", "ts": "<when>" },
87
+ "trace": { "query": "<VERBATIM request - the hook owns this, leave it>", "ts": "<when>" },
58
88
  "_intent_hash": "<hook bookkeeping>",
59
89
  "_generated_by":"intent-anchor hook"
60
90
  }