@pmelab/gtd 52.0.0 → 52.1.0

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.
Files changed (51) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +5 -2
  3. package/dist/chunks/{reserved-D0MKVFFa.mjs → reserved-DxB5CROj.mjs} +46 -5
  4. package/dist/chunks/{review-ZzUQH1KZ.mjs → review-CKMSdvgW.mjs} +2 -2
  5. package/dist/chunks/{tail-I1-vVq0P.mjs → tail-QZc7Uz2U.mjs} +1 -1
  6. package/dist/workflows/cleanup.mjs +2 -2
  7. package/dist/workflows/feature.mjs +51 -4
  8. package/dist/workflows/fix.mjs +2 -2
  9. package/dist/workflows/review.mjs +3 -3
  10. package/dist/workflows/rollout.mjs +1 -1
  11. package/dist/workflows.mjs +93 -5
  12. package/package.json +5 -4
  13. package/src/testkit/steps.ts +13 -0
  14. package/src/workflows/feature/acceptance-criteria.feature +159 -3
  15. package/src/workflows/feature/continuation-cap.feature +4 -0
  16. package/src/workflows/feature/continuation-rebuild.feature +4 -0
  17. package/src/workflows/feature/continuation-slices.feature +4 -0
  18. package/src/workflows/feature/continuation.feature +4 -0
  19. package/src/workflows/feature/criteria.test.ts +22 -1
  20. package/src/workflows/feature/criteria.ts +66 -1
  21. package/src/workflows/feature/fast-path.feature +4 -0
  22. package/src/workflows/feature/feature.test.ts +6 -5
  23. package/src/workflows/feature/flag-mode.feature +4 -0
  24. package/src/workflows/feature/hands-on-skip.feature +40 -0
  25. package/src/workflows/feature/lens-models.feature +4 -0
  26. package/src/workflows/feature/lens-review.feature +4 -0
  27. package/src/workflows/feature/naive-acceptance.feature +4 -0
  28. package/src/workflows/feature/one-step-land.feature +4 -0
  29. package/src/workflows/feature/planning.ts +2 -1
  30. package/src/workflows/feature/prototype-rounds.feature +4 -0
  31. package/src/workflows/feature/prototype.feature +8 -0
  32. package/src/workflows/feature/refactor-absorbs.feature +4 -0
  33. package/src/workflows/feature/refactor-first.feature +4 -0
  34. package/src/workflows/feature/refactor-lens-models.feature +4 -0
  35. package/src/workflows/feature/refactor-rebuild.feature +4 -0
  36. package/src/workflows/feature/refactor-review.feature +20 -0
  37. package/src/workflows/feature/review-answers.feature +4 -0
  38. package/src/workflows/feature/review-gate.feature +12 -0
  39. package/src/workflows/feature/reviewer-walkthrough.feature +4 -0
  40. package/src/workflows/feature/risk-tier.feature +32 -0
  41. package/src/workflows/feature/seam-rejection.feature +8 -0
  42. package/src/workflows/feature/seam.feature +8 -0
  43. package/src/workflows/feature/seam.test.ts +4 -2
  44. package/src/workflows/feature/severity-budget.feature +4 -0
  45. package/src/workflows/feature/severity-sorted-review.feature +4 -0
  46. package/src/workflows/feature/slice-findings.feature +4 -0
  47. package/src/workflows/feature/slicing.feature +32 -0
  48. package/src/workflows/feature/standards.feature +4 -0
  49. package/src/workflows/feature/tier-pin.feature +4 -0
  50. package/src/workflows/shared/text.test.ts +40 -0
  51. package/src/workflows/shared/text.ts +50 -4
@@ -30,6 +30,10 @@ Feature: every observable criterion is tested by hand before the quality lap
30
30
  """
31
31
  # Requirements
32
32
 
33
+ ## Impact
34
+
35
+ - the greeting module
36
+
33
37
  ## Acceptance Criteria
34
38
 
35
39
  - AC-1: subtract(a, b) returns a - b.
@@ -236,6 +240,10 @@ Feature: every observable criterion is tested by hand before the quality lap
236
240
  """
237
241
  # Requirements
238
242
 
243
+ ## Impact
244
+
245
+ - the greeting module
246
+
239
247
  ## Acceptance Criteria
240
248
 
241
249
  - AC-2: add is unchanged.
@@ -37,6 +37,10 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
37
37
 
38
38
  - `subtract(a, b)` returns `a - b`.
39
39
 
40
+ ## Impact
41
+
42
+ - the greeting module
43
+
40
44
  ## Acceptance Criteria
41
45
 
42
46
  - AC-1: the change behaves as described.
@@ -36,6 +36,10 @@ Feature: a refactor-first judgment walks one fixed path to the review gate
36
36
 
37
37
  - `subtract(a, b)` returns `a - b`.
38
38
 
39
+ ## Impact
40
+
41
+ - the greeting module
42
+
39
43
  ## Acceptance Criteria
40
44
 
41
45
  - AC-1: the change behaves as described.
@@ -29,6 +29,10 @@ Feature: the refactor review's lenses take their model hints from refactorQualit
29
29
 
30
30
  - `subtract(a, b)` returns `a - b`.
31
31
 
32
+ ## Impact
33
+
34
+ - the greeting module
35
+
32
36
  ## Acceptance Criteria
33
37
 
34
38
  - AC-1: the change behaves as described.
@@ -37,6 +37,10 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
37
37
 
38
38
  - `subtract(a, b)` returns `a - b`.
39
39
 
40
+ ## Impact
41
+
42
+ - the greeting module
43
+
40
44
  ## Acceptance Criteria
41
45
 
42
46
  - AC-1: subtract returns the difference.
@@ -48,6 +48,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
48
48
 
49
49
  - `subtract(a, b)` returns `a - b`.
50
50
 
51
+ ## Impact
52
+
53
+ - the greeting module
54
+
51
55
  ## Acceptance Criteria
52
56
 
53
57
  - AC-1: the change behaves as described.
@@ -146,6 +150,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
146
150
 
147
151
  - `subtract(a, b)` returns `a - b`.
148
152
 
153
+ ## Impact
154
+
155
+ - the greeting module
156
+
149
157
  ## Acceptance Criteria
150
158
 
151
159
  - AC-1: the change behaves as described.
@@ -245,6 +253,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
245
253
 
246
254
  - `subtract(a, b)` returns `a - b`.
247
255
 
256
+ ## Impact
257
+
258
+ - the greeting module
259
+
248
260
  ## Acceptance Criteria
249
261
 
250
262
  - AC-1: the change behaves as described.
@@ -1210,6 +1222,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1210
1222
 
1211
1223
  - `subtract(a, b)` returns `a - b`.
1212
1224
 
1225
+ ## Impact
1226
+
1227
+ - the greeting module
1228
+
1213
1229
  ## Acceptance Criteria
1214
1230
 
1215
1231
  - AC-1: the change behaves as described.
@@ -1337,6 +1353,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1337
1353
 
1338
1354
  - `subtract(a, b)` returns `a - b`.
1339
1355
 
1356
+ ## Impact
1357
+
1358
+ - the greeting module
1359
+
1340
1360
  ## Acceptance Criteria
1341
1361
 
1342
1362
  - AC-1: the change behaves as described.
@@ -36,6 +36,10 @@ Feature: every note in the review is answered with one tick
36
36
 
37
37
  - `subtract(a, b)` returns `a - b`.
38
38
 
39
+ ## Impact
40
+
41
+ - the greeting module
42
+
39
43
  ## Acceptance Criteria
40
44
 
41
45
  - AC-1: subtract(a, b) returns a - b.
@@ -36,6 +36,10 @@ Feature: a feature process ends at the human review
36
36
 
37
37
  - `subtract(a, b)` returns `a - b`.
38
38
 
39
+ ## Impact
40
+
41
+ - the greeting module
42
+
39
43
  ## Acceptance Criteria
40
44
 
41
45
  - AC-1: subtract(a, b) returns a - b.
@@ -192,6 +196,10 @@ Feature: a feature process ends at the human review
192
196
 
193
197
  - `multiply(a, b)` returns `a * b`.
194
198
 
199
+ ## Impact
200
+
201
+ - the greeting module
202
+
195
203
  ## Acceptance Criteria
196
204
 
197
205
  - AC-1: subtract(a, b) returns a - b.
@@ -238,6 +246,10 @@ Feature: a feature process ends at the human review
238
246
 
239
247
  - `multiply(a, b)` returns `a * b`.
240
248
 
249
+ ## Impact
250
+
251
+ - the greeting module
252
+
241
253
  ## Acceptance Criteria
242
254
 
243
255
  - AC-0: multiply(a, b) returns a * b.
@@ -31,6 +31,10 @@ Feature: a reviewer walks the human through the feature's code
31
31
  """
32
32
  # Requirements
33
33
 
34
+ ## Impact
35
+
36
+ - the greeting module
37
+
34
38
  ## Acceptance Criteria
35
39
 
36
40
  - AC-1: subtract(a, b) returns a - b.
@@ -50,6 +50,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
50
50
 
51
51
  low — trivial copy change
52
52
 
53
+ ## Impact
54
+
55
+ - the greeting module
56
+
53
57
  ## Acceptance Criteria
54
58
 
55
59
  - AC-1: the change behaves as described.
@@ -69,6 +73,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
69
73
 
70
74
  high — touches payments
71
75
 
76
+ ## Impact
77
+
78
+ - the greeting module
79
+
72
80
  ## Acceptance Criteria
73
81
 
74
82
  - AC-1: the change behaves as described.
@@ -89,6 +97,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
89
97
 
90
98
  ### Subtract
91
99
 
100
+ ## Impact
101
+
102
+ - the greeting module
103
+
92
104
  ## Acceptance Criteria
93
105
 
94
106
  - AC-1: the change behaves as described.
@@ -118,6 +130,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
118
130
  - error rate on /subtract stays flat
119
131
  - p95 latency
120
132
 
133
+ ## Impact
134
+
135
+ - the greeting module
136
+
121
137
  ## Acceptance Criteria
122
138
 
123
139
  - AC-1: the change behaves as described.
@@ -142,6 +158,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
142
158
 
143
159
  low — trivial copy change
144
160
 
161
+ ## Impact
162
+
163
+ - the greeting module
164
+
145
165
  ## Acceptance Criteria
146
166
 
147
167
  - AC-1: the change behaves as described.
@@ -187,6 +207,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
187
207
 
188
208
  ### Subtract
189
209
 
210
+ ## Impact
211
+
212
+ - the greeting module
213
+
190
214
  ## Acceptance Criteria
191
215
 
192
216
  - AC-1: the change behaves as described.
@@ -233,6 +257,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
233
257
 
234
258
  - error rate stays flat
235
259
 
260
+ ## Impact
261
+
262
+ - the greeting module
263
+
236
264
  ## Acceptance Criteria
237
265
 
238
266
  - AC-1: the change behaves as described.
@@ -258,6 +286,10 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
258
286
 
259
287
  low — trivial
260
288
 
289
+ ## Impact
290
+
291
+ - the greeting module
292
+
261
293
  ## Acceptance Criteria
262
294
 
263
295
  - AC-1: the change behaves as described.
@@ -35,6 +35,10 @@ Feature: rejected naive passes walk one fixed path through the steer gate to the
35
35
 
36
36
  - `subtract(a, b)` returns `a - b`.
37
37
 
38
+ ## Impact
39
+
40
+ - the greeting module
41
+
38
42
  ## Acceptance Criteria
39
43
 
40
44
  - AC-1: the change behaves as described.
@@ -76,6 +80,10 @@ Feature: rejected naive passes walk one fixed path through the steer gate to the
76
80
 
77
81
  - `subtract(a, b)` returns `a - b`, in the calculator module.
78
82
 
83
+ ## Impact
84
+
85
+ - the greeting module
86
+
79
87
  ## Acceptance Criteria
80
88
 
81
89
  - AC-1: the change behaves as described.
@@ -45,6 +45,10 @@ Feature: the naive pass and seam judge decide how a feature is built
45
45
 
46
46
  - `subtract(a, b)` returns `a - b`.
47
47
 
48
+ ## Impact
49
+
50
+ - the greeting module
51
+
48
52
  ## Acceptance Criteria
49
53
 
50
54
  - AC-1: the change behaves as described.
@@ -234,6 +238,10 @@ Feature: the naive pass and seam judge decide how a feature is built
234
238
 
235
239
  - `subtract(a, b)` returns `a - b`, in a new module.
236
240
 
241
+ ## Impact
242
+
243
+ - the greeting module
244
+
237
245
  ## Acceptance Criteria
238
246
 
239
247
  - AC-1: the change behaves as described.
@@ -109,7 +109,8 @@ describe("naivePass", () => {
109
109
  })
110
110
 
111
111
  describe("naiveAcceptance and requireAcceptance", () => {
112
- const requirements = "# R\n\n## Acceptance Criteria\n\n- AC-1: adds.\n- AC-2: subtracts.\n"
112
+ const requirements =
113
+ "# R\n\n## Impact\n\n- the module\n\n## Acceptance Criteria\n\n- AC-1: adds.\n- AC-2: subtracts.\n"
113
114
  const file = (path: string, before: string | undefined, after: string): Change => ({
114
115
  path,
115
116
  status: before === undefined ? "added" : "modified",
@@ -170,7 +171,8 @@ describe("naiveAcceptance and requireAcceptance", () => {
170
171
  })
171
172
 
172
173
  describe("acceptanceFault", () => {
173
- const requirements = "# R\n\n## Acceptance Criteria\n\n- AC-1: adds.\n- AC-2: subtracts.\n"
174
+ const requirements =
175
+ "# R\n\n## Impact\n\n- the module\n\n## Acceptance Criteria\n\n- AC-1: adds.\n- AC-2: subtracts.\n"
174
176
  const file = (path: string, status: Change["status"], after: string): Change => ({
175
177
  path,
176
178
  status,
@@ -28,6 +28,10 @@ Feature: the review's ranking is batched to the judge's budget
28
28
  """
29
29
  # Requirements
30
30
 
31
+ ## Impact
32
+
33
+ - the greeting module
34
+
31
35
  ## Acceptance Criteria
32
36
 
33
37
  - AC-1: subtract(a, b) returns a - b.
@@ -31,6 +31,10 @@ Feature: the final review lists the findings that matter most first
31
31
  """
32
32
  # Requirements
33
33
 
34
+ ## Impact
35
+
36
+ - the greeting module
37
+
34
38
  ## Acceptance Criteria
35
39
 
36
40
  - AC-1: subtract(a, b) returns a - b.
@@ -30,6 +30,10 @@ Feature: every slice's quality lap is triaged, and its leftovers wait for the re
30
30
  """
31
31
  # Requirements
32
32
 
33
+ ## Impact
34
+
35
+ - the greeting module
36
+
33
37
  ## Acceptance Criteria
34
38
 
35
39
  - AC-1: subtract(a, b) returns a - b.
@@ -36,6 +36,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
36
36
  """
37
37
  # Requirements
38
38
 
39
+ ## Impact
40
+
41
+ - the greeting module
42
+
39
43
  ## Acceptance Criteria
40
44
 
41
45
  - AC-1: subtract(a, b) returns a - b.
@@ -70,6 +74,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
70
74
  """
71
75
  # Requirements
72
76
 
77
+ ## Impact
78
+
79
+ - the greeting module
80
+
73
81
  ## Acceptance Criteria
74
82
 
75
83
  - AC-1: subtract(a, b) returns a - b.
@@ -133,6 +141,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
133
141
  """
134
142
  # Requirements
135
143
 
144
+ ## Impact
145
+
146
+ - the greeting module
147
+
136
148
  ## Acceptance Criteria
137
149
 
138
150
  - AC-1: subtract(a, b) returns a - b.
@@ -156,6 +168,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
156
168
  """
157
169
  # Requirements
158
170
 
171
+ ## Impact
172
+
173
+ - the greeting module
174
+
159
175
  ## Acceptance Criteria
160
176
 
161
177
  - AC-1: subtract(a, b) returns a - b.
@@ -181,6 +197,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
181
197
  """
182
198
  # Requirements
183
199
 
200
+ ## Impact
201
+
202
+ - the greeting module
203
+
184
204
  ## Acceptance Criteria
185
205
 
186
206
  - AC-1: subtract(a, b) returns a - b.
@@ -191,6 +211,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
191
211
  """
192
212
  # Requirements
193
213
 
214
+ ## Impact
215
+
216
+ - the greeting module
217
+
194
218
  ## Acceptance Criteria
195
219
 
196
220
  - AC-1: subtract(a, b) returns a - b.
@@ -215,6 +239,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
215
239
  """
216
240
  # Requirements
217
241
 
242
+ ## Impact
243
+
244
+ - the greeting module
245
+
218
246
  ## Acceptance Criteria
219
247
 
220
248
  - AC-1: subtract(a, b) returns a - b.
@@ -244,6 +272,10 @@ Feature: a change with more criteria than the cap is built in coarse slices
244
272
  """
245
273
  # Requirements
246
274
 
275
+ ## Impact
276
+
277
+ - the greeting module
278
+
247
279
  ## Acceptance Criteria
248
280
 
249
281
  - AC-1: subtract(a, b) returns a - b.
@@ -37,6 +37,10 @@ Feature: the review learns standards from the human's answers
37
37
 
38
38
  - `subtract(a, b)` returns `a - b`.
39
39
 
40
+ ## Impact
41
+
42
+ - the greeting module
43
+
40
44
  ## Acceptance Criteria
41
45
 
42
46
  - AC-1: subtract(a, b) returns a - b.
@@ -34,6 +34,10 @@ Feature: a process keeps the risk tier setting it started with when GTD_FLAG_RIS
34
34
 
35
35
  low — a new pure function
36
36
 
37
+ ## Impact
38
+
39
+ - the greeting module
40
+
37
41
  ## Acceptance Criteria
38
42
 
39
43
  - AC-1: the change behaves as described.
@@ -4,6 +4,8 @@ import { tmpdir } from "node:os"
4
4
  import { join } from "node:path"
5
5
  import { afterEach, describe, expect, it } from "vitest"
6
6
  import {
7
+ designImpactPrompt,
8
+ prototypeFixingPrompt,
7
9
  buildReviewTriageMessage,
8
10
  buildReviewReviewingPrompt,
9
11
  agentWithSkills,
@@ -24,6 +26,7 @@ import {
24
26
  implementBuildingPrompt,
25
27
  implementFixPrompt,
26
28
  naivePassPrompt,
29
+ slicingPrompt,
27
30
  refactorBuildingPrompt,
28
31
  refactorDroppedRefusal,
29
32
  refactorFixPrompt,
@@ -922,6 +925,29 @@ describe("buildReviewReviewingPrompt scenarios", () => {
922
925
  })
923
926
  })
924
927
 
928
+ describe("Impact in prompts", () => {
929
+ it("[AC-4] the slicing prompt slices along the units Impact names", () => {
930
+ const prompt = renderText(() => slicingPrompt(8))
931
+ expect(prompt).toContain("## Impact")
932
+ expect(prompt).toMatch(/slice\s+along\s+the\s+units\s+it\s+names/)
933
+ })
934
+
935
+ it.each([
936
+ ["naive", () => naivePassPrompt()],
937
+ ["implement", () => implementBuildingPrompt(undefined)],
938
+ ["prototype fixing", () => prototypeFixingPrompt(undefined)],
939
+ ])("[AC-5] [AC-7] the %s prompt gives Impact as hints, not allowed files", (_n, prompt) => {
940
+ const p = renderText(prompt).replace(/\s+/g, " ")
941
+ expect(p).toContain("`## Impact`")
942
+ expect(p).toContain("not a list of allowed files")
943
+ })
944
+
945
+ it("the prototype testing prompt, which changes no code, carries no Impact hints", () => {
946
+ const p = renderText(() => prototypeTestingPrompt(undefined, [], false))
947
+ expect(p).not.toContain("not a list of allowed files")
948
+ })
949
+ })
950
+
925
951
  describe("the seam phase's texts", () => {
926
952
  const rejection = { strays: ["src/flows/helpers.ts", "src/flows/runtime.ts"], p: 0.85 }
927
953
 
@@ -1641,3 +1667,17 @@ describe("rankedReview", () => {
1641
1667
  expect(unranked(unranked(review))).toBe(unranked(review))
1642
1668
  })
1643
1669
  })
1670
+
1671
+ describe("impact prompts", () => {
1672
+ it.each([
1673
+ ["triage", () => renderText(() => designTriagePrompt("abc123"))],
1674
+ ["design.impact", () => renderText(() => designImpactPrompt())],
1675
+ ])("[AC-2] the %s prompt asks for a `## Impact` section", (_n, prompt) => {
1676
+ expect(prompt()).toContain("`## Impact`")
1677
+ })
1678
+
1679
+ it("[AC-3] the triage prompt names where a return lap reads the human's Impact edit", () => {
1680
+ const p = renderText(() => designTriagePrompt("abc123")).replace(/\s+/g, " ")
1681
+ expect(p).toContain("`git log -1 -p -- .gtd/REQUIREMENTS.md`")
1682
+ })
1683
+ })
@@ -515,6 +515,20 @@ Leave the tag off whatever a person can see by running the change. A
515
515
  tag the human added or removed at the gate stays as they left it.
516
516
  `
517
517
 
518
+ const impactBlock = `
519
+ ## Impact
520
+
521
+ \`.gtd/REQUIREMENTS.md\` carries a \`## Impact\` section: explore the
522
+ codebase (not just the start diff) and name the units and boundaries
523
+ this change touches, the public surfaces it affects (CLI commands and
524
+ flags, config keys, driver protocol, exported API), and anything
525
+ surprising. Name the project's own declared units first —
526
+ dependency-cruiser rules, workspace packages, module boundaries named
527
+ in its docs or agent instructions (\`AGENTS.md\`, \`CLAUDE.md\`). When
528
+ none is declared, fall back to directories and packages. Landing is
529
+ refused while the section is missing.
530
+ `
531
+
518
532
  const riskTierBlock = `
519
533
  ## Risk tier and production signals
520
534
 
@@ -556,7 +570,14 @@ ${footnoteFoldIn}${codeThreadReplies()}
556
570
  or both
557
571
  - Whichever lap this is, leave \`.gtd/REQUIREMENTS.md\`
558
572
  uncommitted and finish once it reflects this lap's own work
559
- ${acceptanceCriteriaBlock}
573
+ ${acceptanceCriteriaBlock}${impactBlock}
574
+ Every lap re-explores and leaves \`## Impact\` present. On a return
575
+ lap or review loop-back the human may have edited \`## Impact\` (or
576
+ footnoted it): read that edit from history (\`git log -1 -p --
577
+ .gtd/REQUIREMENTS.md\`), keep the human's correction, and
578
+ re-explore from it. A surprise the human must settle becomes an
579
+ entry under \`## Open Questions\`.
580
+
560
581
  ## First lap
561
582
 
562
583
  \`.gtd/REQUIREMENTS.md\` does not exist yet (or holds whatever the
@@ -612,6 +633,23 @@ ${questionBarReturn}
612
633
  everything else — the build assumes the suite started green
613
634
  ${riskTier ? riskTierBlock : ""}`
614
635
 
636
+ export const designImpactPrompt = (): string =>
637
+ `${styleBlock}
638
+
639
+ ${styleFormatContract}
640
+
641
+ ${stateFileRules}
642
+ - The only state file this turn touches is \`.gtd/REQUIREMENTS.md\`
643
+ — no other files for notes or output
644
+ - \`.gtd/REQUIREMENTS.md\` already holds the settled acceptance
645
+ criteria. Add a \`## Impact\` section and change nothing else — a
646
+ turn that touches anything outside it is refused
647
+ - No human reviews this before the build: put any surprise in the
648
+ Impact prose, never as a question
649
+ ${impactBlock}
650
+ - Leave \`.gtd/REQUIREMENTS.md\` uncommitted and finish once it holds \`## Impact\`
651
+ `
652
+
615
653
  export const clearCriteriaQuestion: JudgeQuestion = {
616
654
  id: "clear",
617
655
  primitive: "noul",
@@ -665,9 +703,9 @@ export const slicingPrompt = (cap: number): string =>
665
703
  - Read \`.gtd/REQUIREMENTS.md\`: its \`## Acceptance Criteria\` are settled
666
704
  and more than ${cap}, too many to build in one slice
667
705
  - Group them into slices in \`.gtd/SLICES.md\`, one \`## <title>\` heading per
668
- slice over a \`- AC-<n>\` list item per criterion it builds. Put criteria of
669
- the same flow or subsystem together; every criterion in exactly one slice,
670
- at most ${cap} per slice
706
+ slice over a \`- AC-<n>\` list item per criterion it builds. Read the
707
+ \`## Impact\` section of \`.gtd/REQUIREMENTS.md\` and slice along the units it
708
+ names; every criterion in exactly one slice, at most ${cap} per slice
671
709
  - Keep it coarse: as few slices as the cap allows, never one per criterion
672
710
  - Order the slices so each builds on the ones before: they run in that order,
673
711
  each from where the previous one landed
@@ -1620,6 +1658,11 @@ const isFault = (retry: NaiveRetry): retry is NaiveFault => "fault" in retry
1620
1658
  const pickUp = (hash: string, exclude?: string): string =>
1621
1659
  `Pick it up — \`git diff --binary --no-color --no-ext-diff --no-textconv ${hash}^ ${hash}${exclude === undefined ? "" : ` -- ${quote(":(top)")} ${quote(`:(top,exclude)${exclude}`)}`} | git apply\``
1622
1660
 
1661
+ // Agent-written without a gate on the stated-criteria path, so never claim a human signed it off.
1662
+ const impactHints = `- Its \`## Impact\` section maps where the change lands — reviewed at the design
1663
+ gate when design ran. A starting point and hints, not a list of allowed files
1664
+ — change whatever the work needs`
1665
+
1623
1666
  const criteriaBinding = (refused: boolean): string =>
1624
1667
  `- Its \`## Acceptance Criteria\` (\`AC-<n>\`) bind this turn: re-read them from
1625
1668
  the file, never from memory, and stop only when each one holds. They are
@@ -1714,6 +1757,7 @@ export const naivePassPrompt = (
1714
1757
  ): string =>
1715
1758
  `${stateFileRules}
1716
1759
  - Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
1760
+ ${impactHints}
1717
1761
  ${sliceLine(slice)}${criteriaBinding(false)}
1718
1762
  - Implement them the quickest way that works — the naive version. Do not
1719
1763
  restructure, abstract or refactor around the change; it may land exactly as
@@ -1853,6 +1897,7 @@ export const implementBuildingPrompt = (
1853
1897
  ): string =>
1854
1898
  `${stateFileRules}
1855
1899
  - Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
1900
+ ${impactHints}
1856
1901
  ${sliceLine(slice)}${criteriaBinding(true)}
1857
1902
  ${afterRefactor === true ? afterRefactorLine(rebuild) : ""}${
1858
1903
  amend === true
@@ -2045,6 +2090,7 @@ ${
2045
2090
  export const prototypeFixingPrompt = (slice: readonly string[] | undefined): string =>
2046
2091
  `${stateFileRules}
2047
2092
  - Read \`.gtd/REQUIREMENTS.md\`: the settled requirements for this change
2093
+ ${impactHints}
2048
2094
  ${sliceLine(slice)}${criteriaBinding(true)}
2049
2095
  - Read \`.gtd/PROTOTYPE.md\`: a hands-on test of the change. Fix every
2050
2096
  \`fail\` chunk of this change's criteria${slice === undefined ? "" : " (this slice's only)"} or a problem found