@pmelab/gtd 40.0.0 → 42.0.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 (58) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +41 -30
  3. package/dist/chunks/{reserved-Qt5FM6Ia.mjs → reserved-D7MNY9QJ.mjs} +66 -18
  4. package/dist/chunks/{steering-DVILanVf.mjs → steering-oCDdQlpP.mjs} +1 -1
  5. package/dist/chunks/tail-D2o2h5cc.mjs +246 -0
  6. package/dist/flows.mjs +11 -1
  7. package/dist/gtd.bundle.mjs +12 -2
  8. package/dist/steering.mjs +1 -1
  9. package/dist/testkit.mjs +15 -3
  10. package/dist/web/main.js +1 -1
  11. package/dist/workflow-kit.mjs +30 -12
  12. package/dist/workflows/cleanup.mjs +2 -2
  13. package/dist/workflows/feature.mjs +44 -24
  14. package/dist/workflows/fix.mjs +3 -3
  15. package/dist/workflows/review.mjs +2 -2
  16. package/dist/workflows/rollout.mjs +1 -1
  17. package/dist/workflows.mjs +282 -51
  18. package/package.json +1 -1
  19. package/src/flows/scripts.ts +15 -0
  20. package/src/steering/review.test.ts +2 -20
  21. package/src/steering/review.ts +2 -1
  22. package/src/testkit/FlowScripts.test.ts +17 -0
  23. package/src/testkit/FlowScripts.ts +15 -0
  24. package/src/testkit/steps.ts +27 -0
  25. package/src/workflow-kit/health.ts +42 -13
  26. package/src/workflows/feature/coverage.feature +3 -3
  27. package/src/workflows/feature/fast-path.feature +2 -2
  28. package/src/workflows/feature/feature.test.ts +2 -37
  29. package/src/workflows/feature/feature.ts +12 -14
  30. package/src/workflows/feature/flag-mode.feature +2 -2
  31. package/src/workflows/feature/lens-review.feature +234 -0
  32. package/src/workflows/feature/one-step-land.feature +2 -2
  33. package/src/workflows/feature/quality-unresolved.feature +47 -32
  34. package/src/workflows/feature/refactor-absorbs.feature +3 -3
  35. package/src/workflows/feature/refactor-first.feature +5 -5
  36. package/src/workflows/feature/refactor-rebuild.feature +7 -7
  37. package/src/workflows/feature/refactor-review.feature +19 -100
  38. package/src/workflows/feature/refactor.test.ts +12 -27
  39. package/src/workflows/feature/refactor.ts +0 -1
  40. package/src/workflows/feature/review-gate.feature +6 -6
  41. package/src/workflows/feature/review.test.ts +29 -25
  42. package/src/workflows/feature/review.ts +53 -10
  43. package/src/workflows/feature/seam-rejection.feature +2 -2
  44. package/src/workflows/feature/seam.feature +2 -2
  45. package/src/workflows/feature/seam.test.ts +1 -1
  46. package/src/workflows/feature/slicing.feature +6 -6
  47. package/src/workflows/index.ts +1 -0
  48. package/src/workflows/shared/health.test.ts +30 -0
  49. package/src/workflows/shared/health.ts +12 -9
  50. package/src/workflows/shared/lenses.test.ts +39 -0
  51. package/src/workflows/shared/lenses.ts +176 -0
  52. package/src/workflows/shared/options.ts +1 -0
  53. package/src/workflows/shared/progress.feature +124 -0
  54. package/src/workflows/shared/tail.ts +19 -4
  55. package/src/workflows/shared/text.test.ts +68 -1
  56. package/src/workflows/shared/text.ts +126 -13
  57. package/src/workflows/shared/vars.ts +1 -0
  58. package/dist/chunks/tail-tAHx_AHe.mjs +0 -112
@@ -1,14 +1,16 @@
1
1
  @inmem
2
- Feature: quality findings left unresolved hold a feature process short of its review
2
+ Feature: quality findings left unresolved between slices hold the next slice back
3
3
 
4
- When the quality lap's fix cap leaves `.gtd/QUALITY.md` behind, the process
5
- rests for a person instead of handing findings nobody acted on to the
6
- human review.
4
+ Between slices no review reads the quality lap's leftovers, so when the fix
5
+ cap leaves `.gtd/QUALITY.md` behind the process rests for a person before
6
+ the next slice. The last slice's leftovers become review notes instead (see
7
+ `lens-review.feature`).
7
8
 
8
9
  Background:
9
10
  Given the shipped workflows, as gtd install scaffolds them
10
11
  And an environment variable "GTD_QUALITYREVIEWS" set to "correctness"
11
12
  And an environment variable "GTD_FLAGMODE" set to "false"
13
+ And an environment variable "GTD_SLICEMAXCRITERIA" set to "1"
12
14
  And a file "src/calc.ts" with:
13
15
  """
14
16
  export const add = (a: number, b: number) => a + b
@@ -16,9 +18,9 @@ Feature: quality findings left unresolved hold a feature process short of its re
16
18
  And the working tree is committed as "feat: add calculator"
17
19
  And a file "TODO.md" with:
18
20
  """
19
- # Add subtract
21
+ # More arithmetic
20
22
 
21
- subtract(a, b) returns the difference.
23
+ subtract and multiply.
22
24
  """
23
25
  And step "unwind" changes nothing
24
26
  And step "start-gate.check" changes nothing
@@ -26,41 +28,53 @@ Feature: quality findings left unresolved hold a feature process short of its re
26
28
  """
27
29
  # Requirements
28
30
 
29
- ## Concerns
30
-
31
- ### Subtract
32
-
33
- - `subtract(a, b)` returns `a - b`.
34
-
35
31
  ## Acceptance Criteria
36
32
 
37
33
  - AC-1: subtract(a, b) returns a - b.
34
+ - AC-2: multiply(a, b) returns a * b.
38
35
  """
39
36
  And step "design.gate.answer" changes nothing
40
- And step "seam.naive" writes "src/calc.test.ts" with:
37
+ And step "design.slicing" writes ".gtd/SLICES.md" with:
38
+ """
39
+ # Slices
40
+
41
+ ## Subtract
42
+
43
+ - AC-1
44
+
45
+ ## Multiply
46
+
47
+ - AC-2
48
+ """
49
+ And step "seam.naive", when prompted with "This slice builds AC-1 only", writes "src/sub.test.ts" with:
41
50
  """
42
51
  it("[AC-1] subtracts", () => {})
43
52
  """
44
- And step "seam.naive" writes "src/calc.ts" with:
53
+ And step "seam.naive", when prompted with "This slice builds AC-2 only", writes "src/mul.test.ts" with:
45
54
  """
46
- export const add = (a: number, b: number) => a + b
47
- export const subtract = (a: number, b: number) => a - b
55
+ it("[AC-2] multiplies", () => {})
48
56
  """
49
57
  And step "seam.check" changes nothing
50
58
  And step "implement.applying" runs its script
51
59
  And step "implement.health.check" changes nothing
52
60
  And step "implement.closing" runs its script
53
- And judge step "implement.coverage" answers:
61
+ And judge step "implement.coverage", when its questions contain "AC-1", answers:
54
62
  """
55
63
  [{"id":"AC-1","answer":"yes","p":0.9}]
56
64
  """
65
+ And judge step "implement.coverage", when its questions contain "AC-2", answers:
66
+ """
67
+ [{"id":"AC-2","answer":"yes","p":0.9}]
68
+ """
57
69
 
58
- Scenario: findings the fix cap left unresolved rest at build.quality-unresolved
70
+ Scenario: findings the fix cap left after a slice rest at build.quality-unresolved
59
71
  Given step "build.quality.correctness.reviewing" writes ".gtd/QUALITY.md" with:
60
72
  """
61
73
  # Quality
62
74
 
63
- - subtract has no test
75
+ ## subtract has no negative test
76
+
77
+ Add a test subtracting a larger number.
64
78
  """
65
79
  And step "build.fix.quality.fixing" from now on changes nothing
66
80
  And step "build.health.describe" writes ".gtd/ESCALATION.md" with:
@@ -74,33 +88,34 @@ Feature: quality findings left unresolved hold a feature process short of its re
74
88
  Given step "build.fix" writes "src/calc.ts" with:
75
89
  """
76
90
  export const add = (a: number, b: number) => a + b
77
- export const subtract = (a: number, b: number) => a - b
78
91
  // checked
79
92
  """
80
93
  And step "build.health.check" changes nothing
81
94
  When gtd lands
82
95
  And the process is driven
83
96
  Then the process rests at "build.quality-unresolved"
84
- And ".gtd/QUALITY.md" contains "subtract has no test"
97
+ And ".gtd/QUALITY.md" contains "subtract has no negative test"
85
98
 
86
99
  When gtd lands
87
100
  And the process is driven
88
101
  Then the process rests at "build.quality-unresolved"
89
102
 
90
- Given a file "src/calc.ts" with:
91
- """
92
- export const add = (a: number, b: number) => a + b
93
- export const subtract = (a: number, b: number) => a - b
94
- // checked by hand
95
- """
96
- And the file ".gtd/QUALITY.md" is deleted
97
- And step "build.health.check" changes nothing
103
+ Given the file ".gtd/QUALITY.md" is deleted
104
+ And step "build.quality.correctness.reviewing" from now on changes nothing
105
+ And step "build.review.composing" runs its script
98
106
  When gtd lands
99
107
  And the process is driven
100
- Then the process rests at "build.review.reviewing"
108
+ Then the process rests at "build.review.await-review"
101
109
  And the commit subjects end with:
102
110
  """
103
- gtd(check): build.health.check → build.quality-unresolved
104
111
  gtd(human): build.quality-unresolved → build.health.check
105
- gtd(check): build.health.check → build.review.reviewing
112
+ gtd(check): build.health.check → seam.naive
113
+ gtd(agent): seam.naive → seam.check
114
+ gtd(check): seam.check → implement.applying
115
+ gtd(check): implement.applying → implement.health.check
116
+ gtd(check): implement.health.check → implement.coverage
117
+ gtd(judge): implement.coverage → implement.closing
118
+ gtd(check): implement.closing → build.quality.correctness.reviewing
119
+ gtd(agent): build.quality.correctness.reviewing → build.review.composing
120
+ gtd(check): build.review.composing → build.review.await-review
106
121
  """
@@ -69,7 +69,7 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
69
69
  """
70
70
  And step "refactor.health.check" changes nothing
71
71
  And step "refactor.closing" runs its script
72
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
72
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
73
73
  """
74
74
  # Review: abc1234
75
75
 
@@ -113,7 +113,7 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
113
113
 
114
114
  Given step "build.quality.correctness.reviewing" changes nothing
115
115
  When the process is driven
116
- Then the process rests at "build.review.reviewing"
116
+ Then the process rests at "build.review.composing"
117
117
  And "src/calc.ts" contains "subtract"
118
118
  And the commit subjects end with:
119
119
  """
@@ -123,7 +123,7 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
123
123
  gtd(check): implement.health.check → implement.coverage
124
124
  gtd(judge): implement.coverage → implement.closing
125
125
  gtd(check): implement.closing → build.quality.correctness.reviewing
126
- gtd(agent): build.quality.correctness.reviewing → build.review.reviewing
126
+ gtd(agent): build.quality.correctness.reviewing → build.review.composing
127
127
  """
128
128
  And the output lines of gtd "slices" start with:
129
129
  """
@@ -72,7 +72,7 @@ Feature: a refactor-first judgment walks one fixed path to the review gate
72
72
  """
73
73
  And step "refactor.health.check" changes nothing
74
74
  And step "refactor.closing" runs its script
75
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
75
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
76
76
  """
77
77
  # Review: abc1234
78
78
 
@@ -121,7 +121,7 @@ Feature: a refactor-first judgment walks one fixed path to the review gate
121
121
  [{"id":"AC-1","answer":"yes","p":0.9}]
122
122
  """
123
123
  When the process is driven
124
- Then the process rests at "build.review.reviewing"
124
+ Then the process rests at "build.review.composing"
125
125
  And "src/calc.ts" contains "op(a, b, 1)"
126
126
  And "src/calc.ts" contains "subtract"
127
127
  And the commit subjects end with:
@@ -138,14 +138,14 @@ Feature: a refactor-first judgment walks one fixed path to the review gate
138
138
  gtd(check): refactor.deriving → refactor.building
139
139
  gtd(agent): refactor.building → refactor.health.check
140
140
  gtd(check): refactor.health.check → refactor.closing
141
- gtd(check): refactor.closing → refactor.build.review.reviewing
142
- gtd(agent): refactor.build.review.reviewing → refactor.build.review.await-review
141
+ gtd(check): refactor.closing → refactor.build.review.composing
142
+ gtd(check): refactor.build.review.composing → refactor.build.review.await-review
143
143
  gtd(human): refactor.build.review.await-review → refactor.build.review.closing
144
144
  gtd(check): refactor.build.review.closing → implement.building
145
145
  gtd(agent): implement.building → implement.health.check
146
146
  gtd(check): implement.health.check → implement.coverage
147
147
  gtd(judge): implement.coverage → implement.closing
148
- gtd(check): implement.closing → build.review.reviewing
148
+ gtd(check): implement.closing → build.review.composing
149
149
  """
150
150
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
151
151
  And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
@@ -83,7 +83,7 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
83
83
  """
84
84
  And step "refactor.health.check" changes nothing
85
85
  And step "refactor.closing" runs its script
86
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
86
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
87
87
  """
88
88
  # Review: abc1234
89
89
 
@@ -147,7 +147,7 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
147
147
  """
148
148
  And step "refactor.health.check" changes nothing
149
149
  And step "refactor.closing" runs its script
150
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
150
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
151
151
  """
152
152
  # Review: abc1234
153
153
 
@@ -193,7 +193,7 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
193
193
  """
194
194
  And step "refactor.health.check" changes nothing
195
195
  And step "refactor.closing" runs its script
196
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
196
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
197
197
  """
198
198
  # Review: abc1234
199
199
 
@@ -242,7 +242,7 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
242
242
  [{"id":"AC-1","answer":"yes","p":0.9}]
243
243
  """
244
244
  When the process is driven
245
- Then the process rests at "build.review.reviewing"
245
+ Then the process rests at "build.review.composing"
246
246
  And "src/calc.ts" contains "op(a, b, -1)"
247
247
  And "src/acceptance.test.ts" contains "[AC-1]"
248
248
  And ".gtd/REFACTOR-NOTE.md" does not exist
@@ -253,14 +253,14 @@ Feature: refactor-first writes a refactor note, refactors on its own, then rebui
253
253
  gtd(check): refactor.deriving → refactor.building
254
254
  gtd(agent): refactor.building → refactor.health.check
255
255
  gtd(check): refactor.health.check → refactor.closing
256
- gtd(check): refactor.closing → refactor.build.review.reviewing
257
- gtd(agent): refactor.build.review.reviewing → refactor.build.review.await-review
256
+ gtd(check): refactor.closing → refactor.build.review.composing
257
+ gtd(check): refactor.build.review.composing → refactor.build.review.await-review
258
258
  gtd(human): refactor.build.review.await-review → refactor.build.review.closing
259
259
  gtd(check): refactor.build.review.closing → implement.building
260
260
  gtd(agent): implement.building → implement.health.check
261
261
  gtd(check): implement.health.check → implement.coverage
262
262
  gtd(judge): implement.coverage → implement.closing
263
- gtd(check): implement.closing → build.review.reviewing
263
+ gtd(check): implement.closing → build.review.composing
264
264
  """
265
265
  And the output lines of gtd "slices" start with:
266
266
  """
@@ -78,7 +78,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
78
78
  """
79
79
  And step "refactor.health.check" changes nothing
80
80
  And step "refactor.closing" runs its script
81
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
81
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
82
82
  """
83
83
  # Review: abc1234
84
84
 
@@ -171,7 +171,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
171
171
  """
172
172
  And step "refactor.health.check" changes nothing
173
173
  And step "refactor.closing" runs its script
174
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
174
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
175
175
  """
176
176
  # Review: abc1234
177
177
 
@@ -191,8 +191,8 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
191
191
  And the commit subjects end with:
192
192
  """
193
193
  gtd(check): refactor.closing → refactor.build.quality.correctness.reviewing
194
- gtd(agent): refactor.build.quality.correctness.reviewing → refactor.build.review.reviewing
195
- gtd(agent): refactor.build.review.reviewing → refactor.build.review.await-review
194
+ gtd(agent): refactor.build.quality.correctness.reviewing → refactor.build.review.composing
195
+ gtd(check): refactor.build.review.composing → refactor.build.review.await-review
196
196
  """
197
197
 
198
198
 
@@ -263,7 +263,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
263
263
  """
264
264
  And step "refactor.health.check" changes nothing
265
265
  And step "refactor.closing" runs its script
266
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
266
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
267
267
  """
268
268
  # Review: abc1234
269
269
 
@@ -345,91 +345,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
345
345
  gtd(check): refactor.deriving → refactor.building
346
346
  gtd(agent): refactor.building → refactor.health.check
347
347
  gtd(check): refactor.health.check → refactor.closing
348
- gtd(check): refactor.closing → refactor.build.review.reviewing
349
- gtd(agent): refactor.build.review.reviewing → refactor.build.review.await-review
348
+ gtd(check): refactor.closing → refactor.build.review.composing
349
+ gtd(check): refactor.build.review.composing → refactor.build.review.await-review
350
350
  """
351
351
 
352
- Scenario: the refactor review says the whole refactor on its second round
353
- Given step "refactor.build.review.reviewing" is prompted with "it covers the whole refactor since it started, on every round"
354
- And step "implement.building" writes "src/calc.ts" with:
355
- """
356
- export const op = (a: number, b: number, sign: number) => a + sign * b
357
- export const add = (a: number, b: number) => op(a, b, 1)
358
- export const subtract = (a: number, b: number) => op(a, b, -1)
359
- """
360
- And step "implement.building" writes "src/acceptance.test.ts" with:
361
- """
362
- it("[AC-1] holds", () => {})
363
- """
364
- And step "implement.health.check" changes nothing
365
- And step "implement.closing" runs its script
366
- And judge step "implement.coverage" answers:
367
- """
368
- [{"id":"AC-1","answer":"yes","p":0.9}]
369
- """
370
- When the process is driven
371
- Then the process rests at "refactor.build.review.await-review"
372
- Given a file ".gtd/REVIEW.md" with:
373
- """
374
- # Review: abc1234
375
-
376
- <!-- base: 0000000 -->
377
-
378
- ## calc
379
-
380
- - [ ] ./src/calc.ts#1-2
381
- add built on the shared op[^why]
382
-
383
- [^why]:
384
- - H: name the helper `combine`
385
- """
386
- And step "refactor.build.review.collecting" writes ".gtd/REFACTOR.md" with:
387
- """
388
- Name the shared helper `combine`.
389
- """
390
- And step "refactor.build.review.collecting" writes ".gtd/REVIEW.md" with:
391
- """
392
- # Review: abc1234
393
-
394
- <!-- base: 0000000 -->
395
-
396
- ## calc
397
-
398
- - [ ] ./src/calc.ts#1-2
399
- add built on the shared op[^why]
400
-
401
- [^why]:
402
- - H: name the helper `combine`
403
- - A: noted in the refactor package.
404
- """
405
- When gtd lands
406
- And the process is driven
407
- Then the process rests at "refactor.build.review.await-review"
408
- Given a file ".gtd/REVIEW.md" with:
409
- """
410
- # Review: abc1234
411
-
412
- <!-- base: 0000000 -->
413
-
414
- ## calc
415
-
416
- - [ ] ./src/calc.ts#1-2
417
- add built on the shared op
418
- """
419
- And step "refactor.re-unwind" runs its script
420
- And step "refactor.deriving" runs its script
421
- And step "refactor.building" writes "src/calc.ts" with:
422
- """
423
- export const combine = (a: number, b: number, sign: number) => a + sign * b
424
- export const add = (a: number, b: number) => combine(a, b, 1)
425
- """
426
- When gtd lands
427
- And the process is driven
428
- Then the process rests at "refactor.build.review.await-review"
429
- When gtd lands
430
- And the process is driven
431
- Then the process rests at "build.review.reviewing"
432
-
433
352
  Scenario: a question answered at the refactor review reaches the re-derived package as ### Answered Questions
434
353
  When the process is driven
435
354
  Then the process rests at "refactor.build.review.await-review"
@@ -515,8 +434,8 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
515
434
  gtd(check): refactor.deriving → refactor.building
516
435
  gtd(agent): refactor.building → refactor.health.check
517
436
  gtd(check): refactor.health.check → refactor.closing
518
- gtd(check): refactor.closing → refactor.build.review.reviewing
519
- gtd(agent): refactor.build.review.reviewing → refactor.build.review.await-review
437
+ gtd(check): refactor.closing → refactor.build.review.composing
438
+ gtd(check): refactor.build.review.composing → refactor.build.review.await-review
520
439
  """
521
440
 
522
441
  Scenario: an edit note the collecting turn leaves out refuses the landing and never signs off
@@ -727,7 +646,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
727
646
  """
728
647
  When gtd lands
729
648
  And the process is driven
730
- Then the process rests at "build.review.reviewing"
649
+ Then the process rests at "build.review.composing"
731
650
  And "src/calc.ts" contains "subtract"
732
651
 
733
652
  Scenario: a praise-only one-shot footnote signs off and the feature slice follows
@@ -769,7 +688,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
769
688
  """
770
689
  When gtd lands
771
690
  And the process is driven
772
- Then the process rests at "build.review.reviewing"
691
+ Then the process rests at "build.review.composing"
773
692
  And "src/calc.ts" contains "subtract"
774
693
 
775
694
  Scenario: a one-shot footnote judged edit that collecting leaves out refuses naming its anchor
@@ -1084,7 +1003,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1084
1003
  """
1085
1004
  When gtd lands
1086
1005
  And the process is driven
1087
- Then the process rests at "build.review.reviewing"
1006
+ Then the process rests at "build.review.composing"
1088
1007
  And "src/calc.ts" contains "subtract"
1089
1008
 
1090
1009
  Scenario: a praise-only refactor review still signs off and the feature slice follows
@@ -1119,7 +1038,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1119
1038
  """
1120
1039
  When gtd lands
1121
1040
  And the process is driven
1122
- Then the process rests at "build.review.reviewing"
1041
+ Then the process rests at "build.review.composing"
1123
1042
  And "src/calc.ts" contains "subtract"
1124
1043
 
1125
1044
  Scenario: a nit fix in the refactor slice that changes a non-stray is refused, though a glob stray widens the write access
@@ -1184,8 +1103,8 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1184
1103
  Then the process rests at "refactor.build.review.await-review"
1185
1104
  And the commit subjects end with:
1186
1105
  """
1187
- gtd(check): refactor.closing → refactor.build.review.reviewing
1188
- gtd(agent): refactor.build.review.reviewing → refactor.build.review.await-review
1106
+ gtd(check): refactor.closing → refactor.build.review.composing
1107
+ gtd(check): refactor.build.review.composing → refactor.build.review.await-review
1189
1108
  """
1190
1109
 
1191
1110
  Rule: with a quality lens on both slices
@@ -1256,7 +1175,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1256
1175
  """
1257
1176
  And step "refactor.health.check" changes nothing
1258
1177
  And step "refactor.closing" runs its script
1259
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
1178
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
1260
1179
  """
1261
1180
  # Review: abc1234
1262
1181
 
@@ -1309,11 +1228,11 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1309
1228
  And the resting step's content contains the hash of the commit "gtd(check): refactor.build.review.closing → implement.building"
1310
1229
  Given step "build.quality.correctness.reviewing" changes nothing
1311
1230
  When the process is driven
1312
- Then the process rests at "build.review.reviewing"
1231
+ Then the process rests at "build.review.composing"
1313
1232
  And the commit subjects end with:
1314
1233
  """
1315
1234
  gtd(check): implement.closing → build.quality.correctness.reviewing
1316
- gtd(agent): build.quality.correctness.reviewing → build.review.reviewing
1235
+ gtd(agent): build.quality.correctness.reviewing → build.review.composing
1317
1236
  """
1318
1237
 
1319
1238
  Rule: a refactor package never carries a test file, and demoted headings stop at ######
@@ -1463,7 +1382,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1463
1382
  """
1464
1383
  And step "refactor.health.check" changes nothing
1465
1384
  And step "refactor.closing" runs its script
1466
- And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
1385
+ And step "refactor.build.review.composing" writes ".gtd/REVIEW.md" with:
1467
1386
  """
1468
1387
  # Review: abc1234
1469
1388
 
@@ -781,8 +781,6 @@ interface ReviewedScript {
781
781
  /** The collecting turn writes no package. */
782
782
  readonly silentCollect?: boolean
783
783
  readonly collected?: string
784
- /** The note the first `review.reviewing` turn writes; later ones write `add`. */
785
- readonly firstReviewNote?: string
786
784
  }
787
785
 
788
786
  /** Runs `reviewedRefactor` against a scripted context; a third await-review stops the run. */
@@ -797,7 +795,6 @@ const driveReviewed = async (
797
795
  const files = new Map<string, string>()
798
796
  let last = ""
799
797
  let awaits = 0
800
- let reviews = 0
801
798
  let reds = script.reds ?? 0
802
799
  let checking = false
803
800
  let pending: boolean | Error = false
@@ -823,9 +820,7 @@ const driveReviewed = async (
823
820
  ...Object.fromEntries(lensEffects),
824
821
  deriving: () => void files.set(REFACTOR_PACKAGE, "package"),
825
822
  closing: () => void files.delete(REFACTOR_PACKAGE),
826
- "review.reviewing": () => {
827
- files.set(REVIEW, reviewDoc(reviews++ === 0 ? (script.firstReviewNote ?? "add") : "add"))
828
- },
823
+ "review.composing": () => void files.set(REVIEW, reviewDoc("add")),
829
824
  "review.closing": () => void files.delete(REVIEW),
830
825
  "review.collecting": () => {
831
826
  if (!script.silentCollect)
@@ -846,6 +841,14 @@ const driveReviewed = async (
846
841
  if (request.kind === "restart") return Promise.resolve()
847
842
  record(request)
848
843
  effects[request.name]?.()
844
+ // Every lens finding is mechanical, so the fix turn runs.
845
+ if (request.kind === "judge" && request.name === "quality.triage")
846
+ return Promise.resolve({
847
+ answers: Object.fromEntries(
848
+ request.questions.map((q) => [q.id, { answer: "mechanical", p: 0.9 }]),
849
+ ),
850
+ truncated: [],
851
+ })
849
852
  return Promise.resolve(
850
853
  request.kind === "judge" ? { answers: script.answers ?? {}, truncated: [] } : undefined,
851
854
  )
@@ -926,7 +929,7 @@ describe("reviewedRefactor", () => {
926
929
  "refactor.build.quality.correctness.reviewing",
927
930
  "refactor.build.quality.ponytail-review.reviewing",
928
931
  "refactor.build.quality.conventions.reviewing",
929
- "refactor.build.review.reviewing",
932
+ "refactor.build.review.composing",
930
933
  "refactor.build.review.await-review",
931
934
  "refactor.build.review.closing",
932
935
  ])
@@ -934,8 +937,8 @@ describe("reviewedRefactor", () => {
934
937
 
935
938
  it("reviews from HEAD at scope entry", async () => {
936
939
  const h = await driveReviewed(shape())
937
- const reviewing = h.steps.find((s) => s.kind === "agent" && s.name === "review.reviewing")
938
- expect(reviewing?.kind === "agent" ? reviewing.prompt : "").toContain("base: c0")
940
+ const composing = h.steps.find((s) => s.kind === "run" && s.name === "review.composing")
941
+ expect(composing?.kind === "run" ? composing.body : "").toContain("<!-- base: c0 -->")
939
942
  })
940
943
 
941
944
  it("names the entry commit in every lens prompt, on the first lap and after a feedback lap", async () => {
@@ -1192,10 +1195,6 @@ describe("reviewedRefactor's tail prompts", () => {
1192
1195
  it.each([
1193
1196
  ["refactor.build.fix", { findings: true, reds: 2 }],
1194
1197
  ["refactor.build.fix.quality.fixing", { findings: true }],
1195
- [
1196
- "refactor.build.review.fix.risks.fixing",
1197
- { firstReviewNote: "Risk: drops the carry", notes: [undefined] },
1198
- ],
1199
1198
  [
1200
1199
  "refactor.build.review.fix.nits.fixing",
1201
1200
  { notes: ["nit"], answers: { "note-1": { answer: "nit", p: 0.9 } } },
@@ -1211,17 +1210,3 @@ describe("reviewedRefactor's tail prompts", () => {
1211
1210
  },
1212
1211
  )
1213
1212
  })
1214
-
1215
- describe("reviewedRefactor's review lap wording", () => {
1216
- it("says the whole refactor since it started on the first and the second round", async () => {
1217
- const h = await driveReviewed(shape(), { notes: ["add — rename it", undefined] })
1218
- const prompts = h.steps.flatMap((s) =>
1219
- s.kind === "agent" && s.name === "review.reviewing" ? [s.prompt] : [],
1220
- )
1221
- expect(prompts).toHaveLength(2)
1222
- for (const prompt of prompts) {
1223
- expect(prompt).toContain("it covers the whole refactor since it started, on every round")
1224
- expect(prompt).not.toContain("only what is new since the previous review")
1225
- }
1226
- })
1227
- })
@@ -389,7 +389,6 @@ export const reviewedRefactor = async (
389
389
  fixAccess: strayAccess(p.strays),
390
390
  lensBase: entry,
391
391
  rules: t.refactorRules(p.strays, p.pattern),
392
- lap: "refactor",
393
392
  })
394
393
  if (outcome.verdict === "signoff") return true
395
394
  await reUnwind(outcome)
@@ -57,7 +57,7 @@ Feature: a feature process ends at the human review
57
57
  """
58
58
  [{"id":"AC-1","answer":"yes","p":0.9}]
59
59
  """
60
- And step "build.review.reviewing" writes ".gtd/REVIEW.md" with:
60
+ And step "build.review.composing" writes ".gtd/REVIEW.md" with:
61
61
  """
62
62
  # Review: abc1234
63
63
 
@@ -78,8 +78,8 @@ Feature: a feature process ends at the human review
78
78
  And the commit subjects end with:
79
79
  """
80
80
  gtd(judge): implement.coverage → implement.closing
81
- gtd(check): implement.closing → build.review.reviewing
82
- gtd(agent): build.review.reviewing → build.review.await-review
81
+ gtd(check): implement.closing → build.review.composing
82
+ gtd(check): build.review.composing → build.review.await-review
83
83
  """
84
84
 
85
85
  Scenario: a sign-off ends the process at idle
@@ -102,7 +102,7 @@ Feature: a feature process ends at the human review
102
102
  And ".gtd/REVIEW.md" does not exist
103
103
  And the commit subjects end with:
104
104
  """
105
- gtd(agent): build.review.reviewing → build.review.await-review
105
+ gtd(check): build.review.composing → build.review.await-review
106
106
  gtd(human): build.review.await-review → build.review.closing
107
107
  gtd(check): build.review.closing → idle
108
108
  """
@@ -214,8 +214,8 @@ Feature: a feature process ends at the human review
214
214
  gtd(agent): implement.building → implement.health.check
215
215
  gtd(check): implement.health.check → implement.coverage
216
216
  gtd(judge): implement.coverage → implement.closing
217
- gtd(check): implement.closing → build.review.reviewing
218
- gtd(agent): build.review.reviewing → build.review.await-review
217
+ gtd(check): implement.closing → build.review.composing
218
+ gtd(check): build.review.composing → build.review.await-review
219
219
  """
220
220
 
221
221
  Scenario: a design numbering new behaviour at or below an earlier ID is refused