cursordoctrine 0.6.0 → 0.6.1
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/linux/USER-RULES.md +45 -12
- package/linux/hooks/intent-anchor.sh +53 -37
- package/linux/pre-compile.md +11 -0
- package/package.json +1 -1
- package/windows/USER-RULES.md +45 -12
- package/windows/hooks/intent-anchor.ps1 +52 -31
- package/windows/pre-compile.md +11 -0
package/linux/USER-RULES.md
CHANGED
|
@@ -1,12 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
The user is a senior engineer who reviews every diff before shipping.
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
Change only what the task requires. Preserve existing style and behavior unless
|
|
5
|
+
the task itself is a behavior change. Refactors, renames, cleanup only when
|
|
6
|
+
asked. Leave generated files alone unless explicitly required.
|
|
7
|
+
|
|
8
|
+
## Intent contract (.scope.json)
|
|
9
|
+
The harness auto-creates `.scope.json` in the repo root on your first tool of
|
|
10
|
+
each turn, and re-injects it into your context every turn. Treat it as your
|
|
11
|
+
operating contract, not optional:
|
|
12
|
+
- On a fresh scaffold, FILL the `intent` and `acceptance` TODOs from the user's
|
|
13
|
+
request before editing source. `files[]` is auto-tracked - do not maintain it.
|
|
14
|
+
- When the user's request changes, the scaffold regenerates with a new intent -
|
|
15
|
+
refill it for the new ask.
|
|
16
|
+
- If a hook surfaces the contract, defer to it: it outranks momentum. Edit
|
|
17
|
+
inside the declared scope; if you must grow it, justify it, don't sneak past.
|
|
18
|
+
|
|
19
|
+
## Loop
|
|
20
|
+
1. Read what you need to understand the task.
|
|
21
|
+
2. Make the minimal correct edit.
|
|
22
|
+
3. Review the diff. Fix real issues: broken logic, type errors, unsafe
|
|
23
|
+
behavior, data-loss risk, unrequested API/contract changes, regressions.
|
|
24
|
+
Style and naming taste are not bugs.
|
|
25
|
+
4. Verify proportionally to risk - relevant tests/typechecks for behavior, type,
|
|
26
|
+
API, DB, build, or config changes; nothing for trivial text edits.
|
|
27
|
+
5. Report what changed and what was verified. Stop.
|
|
28
|
+
|
|
29
|
+
## Shell
|
|
30
|
+
Run the smallest command that answers the question. Never print secrets,
|
|
31
|
+
tokens, private keys, or sensitive env vars. Never `curl | sh`, force-push, or
|
|
32
|
+
publish without explicit instruction.
|
|
33
|
+
|
|
34
|
+
## Uncertainty
|
|
35
|
+
If ambiguity affects correctness or safety, ask one sharp question. If
|
|
36
|
+
low-risk, state the assumption and proceed. If a tool returns nothing, say what
|
|
37
|
+
you didn't find - don't fabricate. After two failed attempts at the same
|
|
38
|
+
problem, stop and report observations.
|
|
39
|
+
|
|
40
|
+
## Commits
|
|
41
|
+
Conventional commits: `type(scope): description`. One logical change per
|
|
42
|
+
commit, small and reviewable. Body only when the why isn't obvious from the
|
|
43
|
+
diff. Verify before pushing when applicable. Never push without explicit
|
|
44
|
+
instruction.
|
|
45
|
+
|
|
@@ -15,16 +15,19 @@
|
|
|
15
15
|
# at the START of each turn's work, before edits pile up and dilute the
|
|
16
16
|
# original intent. Works UNCONDITIONALLY - no transcript needed.
|
|
17
17
|
#
|
|
18
|
-
# 2. AUTO-CREATE / REGENERATE .scope.json
|
|
19
|
-
# differs from the contract on disk (no
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
18
|
+
# 2. AUTO-CREATE / REGENERATE .scope.json (only when the request is READABLE):
|
|
19
|
+
# when the current <user_query> differs from the contract on disk (no
|
|
20
|
+
# contract yet, _intent_hash mismatch, OR a hollow <TODO> placeholder), the
|
|
21
|
+
# hook WRITES a scaffold to the REPO ROOT: intent locked from the prompt,
|
|
22
|
+
# files as an EMPTY array (scope-gate-audit.sh fills it mechanically as the
|
|
23
|
+
# agent edits - the agent never maintains files[] by hand), acceptance as a
|
|
24
|
+
# TODO the agent sets. We NEVER persist a hollow `intent: <TODO>` file: that
|
|
25
|
+
# caused "el .scope.json se escribe solo sin nada" - when transcript_path is
|
|
26
|
+
# absent on postToolUse the hook can't read the request, so a placeholder
|
|
27
|
+
# with an empty _intent_hash got written, looked owned, and never gained the
|
|
28
|
+
# real intent. Unreadable request -> write nothing, emit the pre-compile
|
|
29
|
+
# demand so the AGENT authors the contract. Never writes to $HOME (bails if
|
|
30
|
+
# no real root resolves -> no ghost files).
|
|
28
31
|
# 3. RE-INJECT on same-prompt turns: when the query is unchanged (contract
|
|
29
32
|
# already current), the hook re-injects the existing contract into the
|
|
30
33
|
# feedback bus so it stays in the model's attentional focus each turn.
|
|
@@ -113,6 +116,7 @@ scope_acceptance=""
|
|
|
113
116
|
scope_files=""
|
|
114
117
|
scope_stale=0 # 1 when the on-disk contract belongs to a DIFFERENT prompt -> regenerate (resets files[])
|
|
115
118
|
needs_heal=0 # 1 when a model-written contract matches THIS prompt but lacks _intent_hash -> backfill in place
|
|
119
|
+
scope_hollow=0 # 1 when the on-disk contract has no real intent (empty or a <TODO> placeholder) -> unusable
|
|
116
120
|
on_disk_hash=""
|
|
117
121
|
scope_path="$root/.scope.json"
|
|
118
122
|
if [ -f "$scope_path" ]; then
|
|
@@ -146,8 +150,17 @@ EOF
|
|
|
146
150
|
# changed (or a new session) => regenerate and RESET files[] (the "arrastre entre
|
|
147
151
|
# features" fix). Same prompt this session => heal in place (backfill bookkeeping, keep
|
|
148
152
|
# files[]/acceptance) so the NEXT prompt is detected by hash.
|
|
153
|
+
# Hollow = no real intent on disk: empty, or still the hook's <TODO> placeholder.
|
|
154
|
+
# A hollow contract is worse than none (it looks owned, so neither hook nor agent
|
|
155
|
+
# fills it). Treat it as unusable: regenerate when the request is readable, else
|
|
156
|
+
# hand the agent the pre-compile demand to author a real one.
|
|
157
|
+
case "$scope_intent" in
|
|
158
|
+
""|"<TODO"*) scope_hollow=1 ;;
|
|
159
|
+
esac
|
|
149
160
|
if [ "$scope_exists" = "1" ] && [ "$has_query" = "1" ]; then
|
|
150
|
-
if [
|
|
161
|
+
if [ "$scope_hollow" = "1" ]; then
|
|
162
|
+
scope_stale=1
|
|
163
|
+
elif [ -n "$on_disk_hash" ]; then
|
|
151
164
|
[ "$on_disk_hash" != "$current_hash" ] && scope_stale=1
|
|
152
165
|
elif [ "$prompt_changed" = "1" ]; then
|
|
153
166
|
scope_stale=1
|
|
@@ -158,34 +171,29 @@ EOF
|
|
|
158
171
|
fi
|
|
159
172
|
|
|
160
173
|
# --- auto-create / regenerate / heal .scope.json ----------------------------
|
|
161
|
-
# CREATION
|
|
162
|
-
#
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
#
|
|
168
|
-
# prompt, sin arrastre
|
|
174
|
+
# CREATION and REGENERATION both REQUIRE the query. We only ever write a
|
|
175
|
+
# contract whose intent we actually know - never a hollow <TODO> scaffold.
|
|
176
|
+
# Persisting a placeholder (the 0.5.3 "unconditional creation") caused "el
|
|
177
|
+
# .scope.json se escribe solo sin nada": no transcript_path on postToolUse ->
|
|
178
|
+
# the hook can't read the request -> intent=<TODO> with empty _intent_hash, a
|
|
179
|
+
# file that looks owned and never gains the real intent. Unreadable request ->
|
|
180
|
+
# write nothing, emit the pre-compile demand so the AGENT authors the contract.
|
|
181
|
+
# A fresh write resets files[] -> ".scope fresco por prompt, sin arrastre."
|
|
182
|
+
# (Hollow on-disk contracts are folded into $scope_stale above, so a readable
|
|
183
|
+
# request also overwrites them here.)
|
|
169
184
|
regenerated=0
|
|
170
185
|
should_create=0
|
|
171
186
|
should_regen=0
|
|
172
|
-
[ "$scope_exists" != "1" ] && should_create=1
|
|
187
|
+
[ "$scope_exists" != "1" ] && [ "$has_query" = "1" ] && should_create=1
|
|
173
188
|
if [ "$has_query" = "1" ] && [ "$scope_exists" = "1" ] && [ "$scope_stale" = "1" ]; then
|
|
174
189
|
should_regen=1
|
|
175
190
|
fi
|
|
176
191
|
now_ts="$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null)"
|
|
177
192
|
|
|
178
193
|
if [ "$should_create" = "1" ] || [ "$should_regen" = "1" ]; then
|
|
179
|
-
#
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if [ "$has_query" = "1" ]; then
|
|
183
|
-
intent_val="$current_query"
|
|
184
|
-
trace_query="$current_query"
|
|
185
|
-
else
|
|
186
|
-
intent_val="<TODO: state the operational objective - what is strictly necessary>"
|
|
187
|
-
trace_query=""
|
|
188
|
-
fi
|
|
194
|
+
# Both paths require $has_query, so intent is always locked from the request.
|
|
195
|
+
intent_val="$current_query"
|
|
196
|
+
trace_query="$current_query"
|
|
189
197
|
# jq preferred; python3 fallback. Write intent, empty files[], TODO acceptance,
|
|
190
198
|
# trace provenance, and _intent_hash so staleness is self-contained.
|
|
191
199
|
if have_jq; then
|
|
@@ -273,17 +281,25 @@ is locked from what you just asked. files[] is AUTO-TRACKED - the scope hook
|
|
|
273
281
|
records every file you edit, so do not maintain it by hand. Set acceptance to
|
|
274
282
|
the one deterministic check that decides done, THEN proceed. This contract will
|
|
275
283
|
be re-injected every turn until your request changes again."
|
|
276
|
-
elif [ "$scope_exists" != "1" ]; then
|
|
277
|
-
|
|
278
|
-
|
|
284
|
+
elif [ "$scope_exists" != "1" ] || [ "$scope_hollow" = "1" ]; then
|
|
285
|
+
if [ "$scope_hollow" = "1" ]; then
|
|
286
|
+
state="the .scope.json in $root is only a <TODO> placeholder (the hook could not read your request to fill it)"
|
|
287
|
+
else
|
|
288
|
+
state="no .scope.json found in $root, and the current request was unavailable to scaffold from"
|
|
289
|
+
fi
|
|
290
|
+
msg="INTENT ANCHOR (pre-compile) - $state.
|
|
279
291
|
|
|
280
292
|
Current request:
|
|
281
293
|
$query_line
|
|
282
294
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
acceptance: the one deterministic check that decides done
|
|
295
|
+
YOU write the real contract to $scope_path now, from THIS conversation, BEFORE
|
|
296
|
+
editing source. Do not leave the <TODO> placeholder:
|
|
297
|
+
intent: one operational sentence - the ACTUAL request (not \"<TODO>\")
|
|
298
|
+
acceptance: the one deterministic check that decides done
|
|
299
|
+
files: [] (leave empty - the scope hook records every file you edit)
|
|
300
|
+
|
|
301
|
+
This is the one case where you own the file: once intent is real, the hook
|
|
302
|
+
takes over (re-injection + per-prompt regeneration)."
|
|
287
303
|
else
|
|
288
304
|
# Contract exists and matches the current prompt -> re-inject it.
|
|
289
305
|
if [ "$has_query" = "1" ]; then
|
package/linux/pre-compile.md
CHANGED
|
@@ -65,6 +65,17 @@ hook scaffolds on a tool boundary), just proceed — you do not need to hand-wri
|
|
|
65
65
|
it. The declared-editing ladder's rung 1 ("does this need to exist?") still governs
|
|
66
66
|
trivial one-liners.
|
|
67
67
|
|
|
68
|
+
**Exception — a hollow contract is YOURS to write.** The hook can only lock
|
|
69
|
+
`intent` when the harness surfaces your request to it; in some Cursor builds it
|
|
70
|
+
cannot, and the `intent-anchor` hook will then ask YOU to author the contract (or
|
|
71
|
+
you may open `.scope.json` and find `intent` still a `<TODO>` placeholder). In
|
|
72
|
+
that one case, write the whole file yourself from this conversation — a real
|
|
73
|
+
`intent` (the actual request, not `<TODO>`), `acceptance`, and `files: []` — and
|
|
74
|
+
do it BEFORE editing source. Never leave a `<TODO>` intent on disk: a placeholder
|
|
75
|
+
contract looks owned, so nothing ever fills it, and scope-gate/final-review then
|
|
76
|
+
audit your diff against nothing. Once `intent` is real, hand the file back to the
|
|
77
|
+
hook (re-injection + per-prompt regeneration take over).
|
|
78
|
+
|
|
68
79
|
## Regla R3 — Authority
|
|
69
80
|
|
|
70
81
|
If, during execution, you read logs or code that contradict these anchors,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursordoctrine",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
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"
|
package/windows/USER-RULES.md
CHANGED
|
@@ -1,12 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
The user is a senior engineer who reviews every diff before shipping.
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
Change only what the task requires. Preserve existing style and behavior unless
|
|
5
|
+
the task itself is a behavior change. Refactors, renames, cleanup only when
|
|
6
|
+
asked. Leave generated files alone unless explicitly required.
|
|
7
|
+
|
|
8
|
+
## Intent contract (.scope.json)
|
|
9
|
+
The harness auto-creates `.scope.json` in the repo root on your first tool of
|
|
10
|
+
each turn, and re-injects it into your context every turn. Treat it as your
|
|
11
|
+
operating contract, not optional:
|
|
12
|
+
- On a fresh scaffold, FILL the `intent` and `acceptance` TODOs from the user's
|
|
13
|
+
request before editing source. `files[]` is auto-tracked - do not maintain it.
|
|
14
|
+
- When the user's request changes, the scaffold regenerates with a new intent -
|
|
15
|
+
refill it for the new ask.
|
|
16
|
+
- If a hook surfaces the contract, defer to it: it outranks momentum. Edit
|
|
17
|
+
inside the declared scope; if you must grow it, justify it, don't sneak past.
|
|
18
|
+
|
|
19
|
+
## Loop
|
|
20
|
+
1. Read what you need to understand the task.
|
|
21
|
+
2. Make the minimal correct edit.
|
|
22
|
+
3. Review the diff. Fix real issues: broken logic, type errors, unsafe
|
|
23
|
+
behavior, data-loss risk, unrequested API/contract changes, regressions.
|
|
24
|
+
Style and naming taste are not bugs.
|
|
25
|
+
4. Verify proportionally to risk - relevant tests/typechecks for behavior, type,
|
|
26
|
+
API, DB, build, or config changes; nothing for trivial text edits.
|
|
27
|
+
5. Report what changed and what was verified. Stop.
|
|
28
|
+
|
|
29
|
+
## Shell
|
|
30
|
+
Run the smallest command that answers the question. Never print secrets,
|
|
31
|
+
tokens, private keys, or sensitive env vars. Never `curl | sh`, force-push, or
|
|
32
|
+
publish without explicit instruction.
|
|
33
|
+
|
|
34
|
+
## Uncertainty
|
|
35
|
+
If ambiguity affects correctness or safety, ask one sharp question. If
|
|
36
|
+
low-risk, state the assumption and proceed. If a tool returns nothing, say what
|
|
37
|
+
you didn't find - don't fabricate. After two failed attempts at the same
|
|
38
|
+
problem, stop and report observations.
|
|
39
|
+
|
|
40
|
+
## Commits
|
|
41
|
+
Conventional commits: `type(scope): description`. One logical change per
|
|
42
|
+
commit, small and reviewable. Body only when the why isn't obvious from the
|
|
43
|
+
diff. Verify before pushing when applicable. Never push without explicit
|
|
44
|
+
instruction.
|
|
45
|
+
|
|
@@ -14,18 +14,22 @@
|
|
|
14
14
|
# at the START of each turn's work, before edits pile up and dilute the
|
|
15
15
|
# original intent. Works UNCONDITIONALLY - no transcript needed.
|
|
16
16
|
#
|
|
17
|
-
# 2. AUTO-CREATE .scope.json (
|
|
18
|
-
# contract exists
|
|
19
|
-
# query
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
17
|
+
# 2. AUTO-CREATE .scope.json (only when the request is READABLE): if no valid
|
|
18
|
+
# contract exists and we can read <user_query>, WRITE one now with intent
|
|
19
|
+
# locked from the query. We NEVER persist a hollow `intent: <TODO>` file:
|
|
20
|
+
# that 0.5.3 "unconditional creation" caused "el .scope.json se escribe
|
|
21
|
+
# solo sin nada" - when Cursor doesn't surface transcript_path on
|
|
22
|
+
# postToolUse the hook can't read the request, so it wrote a placeholder
|
|
23
|
+
# with an empty _intent_hash. The file then looks owned (pre-compile.md
|
|
24
|
+
# tells the agent to leave it alone) and never gets the real intent. When
|
|
25
|
+
# the request is unreadable we write nothing and emit the pre-compile
|
|
26
|
+
# demand so the AGENT authors a real contract from the chat it already has.
|
|
27
|
+
# 3. REGENERATE on prompt CHANGE or HOLLOW contract: when the current
|
|
28
|
+
# <user_query> hash differs from the contract's _intent_hash, OR the
|
|
29
|
+
# on-disk contract has no real intent (empty / <TODO> placeholder),
|
|
30
|
+
# overwrite it with the new intent + empty files + TODO acceptance.
|
|
31
|
+
# Requires $hasQuery (you can only lock intent if you can read the
|
|
32
|
+
# request). Never writes to $HOME (bails if no real root resolves -> no
|
|
29
33
|
# ghost files).
|
|
30
34
|
# 4. RE-INJECT on same-prompt turns: when the query is unchanged (contract
|
|
31
35
|
# already current), the hook re-injects the existing contract into the
|
|
@@ -112,6 +116,7 @@ $scopeFiles = ''
|
|
|
112
116
|
$scopeStale = $false # true when the on-disk contract belongs to a DIFFERENT prompt -> regenerate (resets files[])
|
|
113
117
|
$needsHeal = $false # true when a model-written contract matches THIS prompt but lacks _intent_hash -> backfill in place
|
|
114
118
|
$scopeHasHash = $false
|
|
119
|
+
$scopeHollow = $false # true when the on-disk contract has no real intent (empty or a <TODO> placeholder) -> unusable
|
|
115
120
|
$scopePath = Join-Path $root '.scope.json'
|
|
116
121
|
if (Test-Path -LiteralPath $scopePath) {
|
|
117
122
|
try {
|
|
@@ -122,6 +127,12 @@ if (Test-Path -LiteralPath $scopePath) {
|
|
|
122
127
|
if ([string]::IsNullOrWhiteSpace($scopeFiles)) { $scopeFiles = '(none yet - auto-tracked as you edit)' }
|
|
123
128
|
$scopeExists = $true
|
|
124
129
|
$scopeHasHash = ($sj.PSObject.Properties['_intent_hash'] -and -not [string]::IsNullOrWhiteSpace([string]$sj._intent_hash))
|
|
130
|
+
# Hollow = no real intent on disk: empty, or still the hook's <TODO> placeholder.
|
|
131
|
+
# A hollow contract is worse than none (it looks owned, so neither hook nor agent
|
|
132
|
+
# fills it; scope-gate appends files to it and final-review audits against <TODO>).
|
|
133
|
+
# Treat it as unusable: regenerate when we can read the request, else hand the agent
|
|
134
|
+
# the pre-compile demand to write a real one.
|
|
135
|
+
$scopeHollow = ([string]::IsNullOrWhiteSpace($scopeIntent) -or $scopeIntent -match '^\s*<TODO')
|
|
125
136
|
# Staleness, hash-agnostic so it survives MODEL-written contracts:
|
|
126
137
|
# - hook-written (has _intent_hash): stale when that hash != current query hash.
|
|
127
138
|
# - model-written (no _intent_hash - the legacy pre-compile.md schema): we cannot
|
|
@@ -133,7 +144,10 @@ if (Test-Path -LiteralPath $scopePath) {
|
|
|
133
144
|
# wrote it for THIS request; heal in place (backfill the bookkeeping, keep its
|
|
134
145
|
# files[]/acceptance) so the NEXT prompt is detected by hash like any hook contract.
|
|
135
146
|
if ($hasQuery) {
|
|
136
|
-
if ($
|
|
147
|
+
if ($scopeHollow) {
|
|
148
|
+
# Hollow + we can read the request -> overwrite with the real intent now.
|
|
149
|
+
$scopeStale = $true
|
|
150
|
+
} elseif ($scopeHasHash) {
|
|
137
151
|
$scopeStale = ([string]$sj._intent_hash -ne $currentHash)
|
|
138
152
|
} elseif ($promptChanged) {
|
|
139
153
|
$scopeStale = $true
|
|
@@ -145,22 +159,25 @@ if (Test-Path -LiteralPath $scopePath) {
|
|
|
145
159
|
}
|
|
146
160
|
|
|
147
161
|
# --- auto-create / regenerate / heal .scope.json ----------------------------
|
|
148
|
-
# CREATION
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
# postToolUse
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
#
|
|
162
|
+
# CREATION and REGENERATION both REQUIRE the query. We only ever write a
|
|
163
|
+
# contract whose intent we actually know - never a hollow <TODO> scaffold.
|
|
164
|
+
# Persisting a placeholder file (the 0.5.3 "unconditional creation") was the
|
|
165
|
+
# bug behind "el .scope.json se escribe solo sin nada": when Cursor doesn't
|
|
166
|
+
# surface transcript_path on postToolUse, the hook can't read the request, so
|
|
167
|
+
# it wrote intent=<TODO> with an empty _intent_hash. That file looks owned, so
|
|
168
|
+
# pre-compile.md tells the agent to leave it alone, and it never gets the real
|
|
169
|
+
# intent. When the request is unreadable we now write NOTHING and instead hand
|
|
170
|
+
# the agent the pre-compile demand to author a real contract from the chat it
|
|
171
|
+
# is already responding to. A fresh write resets files[] -> ".scope fresco por
|
|
172
|
+
# prompt, sin arrastre entre features." (Hollow on-disk contracts are folded
|
|
173
|
+
# into $scopeStale above, so a readable request also overwrites them here.)
|
|
157
174
|
$regenerated = $false
|
|
158
|
-
$shouldCreate = -not $scopeExists
|
|
175
|
+
$shouldCreate = (-not $scopeExists) -and $hasQuery
|
|
159
176
|
$shouldRegen = $hasQuery -and $scopeExists -and $scopeStale
|
|
160
177
|
if ($shouldCreate -or $shouldRegen) {
|
|
161
178
|
try {
|
|
162
|
-
$intentVal =
|
|
163
|
-
$traceQuery =
|
|
179
|
+
$intentVal = $currentQuery
|
|
180
|
+
$traceQuery = $currentQuery
|
|
164
181
|
$scaffold = [ordered]@{
|
|
165
182
|
intent = $intentVal
|
|
166
183
|
files = @()
|
|
@@ -220,18 +237,22 @@ records every file you edit, so do not maintain it by hand. Set acceptance to
|
|
|
220
237
|
the one deterministic check that decides done, THEN proceed. This contract will
|
|
221
238
|
be re-injected every turn until your request changes again.
|
|
222
239
|
"@
|
|
223
|
-
} elseif (-not $scopeExists) {
|
|
240
|
+
} elseif (-not $scopeExists -or $scopeHollow) {
|
|
241
|
+
$state = if ($scopeHollow) { "the .scope.json in $root is only a <TODO> placeholder (the hook could not read your request to fill it)" } else { "no .scope.json found in $root, and the current request was unavailable to scaffold from" }
|
|
224
242
|
$msg = @"
|
|
225
|
-
INTENT ANCHOR (pre-compile) -
|
|
226
|
-
request was unavailable to scaffold from.
|
|
243
|
+
INTENT ANCHOR (pre-compile) - $state.
|
|
227
244
|
|
|
228
245
|
Current request:
|
|
229
246
|
$queryLine
|
|
230
247
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
248
|
+
YOU write the real contract to $scopePath now, from THIS conversation, BEFORE
|
|
249
|
+
editing source. Do not leave the <TODO> placeholder:
|
|
250
|
+
intent: one operational sentence - the ACTUAL request (not "<TODO>")
|
|
234
251
|
acceptance: the one deterministic check that decides done
|
|
252
|
+
files: [] (leave empty - the scope hook records every file you edit)
|
|
253
|
+
|
|
254
|
+
This is the one case where you own the file: once intent is real, the hook
|
|
255
|
+
takes over (re-injection + per-prompt regeneration).
|
|
235
256
|
"@
|
|
236
257
|
} else {
|
|
237
258
|
# Contract exists and matches the current prompt -> re-inject it.
|
package/windows/pre-compile.md
CHANGED
|
@@ -65,6 +65,17 @@ hook scaffolds on a tool boundary), just proceed — you do not need to hand-wri
|
|
|
65
65
|
it. The declared-editing ladder's rung 1 ("does this need to exist?") still governs
|
|
66
66
|
trivial one-liners.
|
|
67
67
|
|
|
68
|
+
**Exception — a hollow contract is YOURS to write.** The hook can only lock
|
|
69
|
+
`intent` when the harness surfaces your request to it; in some Cursor builds it
|
|
70
|
+
cannot, and the `intent-anchor` hook will then ask YOU to author the contract (or
|
|
71
|
+
you may open `.scope.json` and find `intent` still a `<TODO>` placeholder). In
|
|
72
|
+
that one case, write the whole file yourself from this conversation — a real
|
|
73
|
+
`intent` (the actual request, not `<TODO>`), `acceptance`, and `files: []` — and
|
|
74
|
+
do it BEFORE editing source. Never leave a `<TODO>` intent on disk: a placeholder
|
|
75
|
+
contract looks owned, so nothing ever fills it, and scope-gate/final-review then
|
|
76
|
+
audit your diff against nothing. Once `intent` is real, hand the file back to the
|
|
77
|
+
hook (re-injection + per-prompt regeneration take over).
|
|
78
|
+
|
|
68
79
|
## Regla R3 — Authority
|
|
69
80
|
|
|
70
81
|
If, during execution, you read logs or code that contradict these anchors,
|