@pmelab/gtd 32.0.0 → 33.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 (40) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +28 -22
  3. package/dist/chunks/{reserved-CHTJTzpA.mjs → reserved-BU5Zi-nX.mjs} +74 -13
  4. package/dist/chunks/{tail-CCsDBbZe.mjs → tail-DuXanjIY.mjs} +6 -3
  5. package/dist/testkit.mjs +2 -2
  6. package/dist/workflow-kit.mjs +15 -3
  7. package/dist/workflows/cleanup.mjs +2 -2
  8. package/dist/workflows/feature.mjs +158 -34
  9. package/dist/workflows/fix.mjs +2 -2
  10. package/dist/workflows/review.mjs +2 -2
  11. package/dist/workflows/rollout.mjs +1 -1
  12. package/dist/workflows.mjs +246 -46
  13. package/package.json +1 -1
  14. package/src/workflow-kit/quality.test.ts +25 -1
  15. package/src/workflow-kit/quality.ts +22 -4
  16. package/src/workflows/feature/acceptance-criteria.feature +8 -0
  17. package/src/workflows/feature/fast-path.feature +8 -2
  18. package/src/workflows/feature/feature.test.ts +19 -9
  19. package/src/workflows/feature/lens-models.feature +60 -0
  20. package/src/workflows/feature/naive-acceptance.feature +140 -0
  21. package/src/workflows/feature/one-step-land.feature +8 -2
  22. package/src/workflows/feature/refactor-absorbs.feature +6 -1
  23. package/src/workflows/feature/refactor-first.feature +9 -3
  24. package/src/workflows/feature/refactor-lens-models.feature +67 -0
  25. package/src/workflows/feature/refactor-review.feature +50 -5
  26. package/src/workflows/feature/refactor.ts +6 -5
  27. package/src/workflows/feature/risk-tier.feature +10 -0
  28. package/src/workflows/feature/seam-rejection.feature +19 -6
  29. package/src/workflows/feature/seam.feature +70 -16
  30. package/src/workflows/feature/seam.test.ts +189 -3
  31. package/src/workflows/feature/seam.ts +195 -30
  32. package/src/workflows/feature/steps.test.ts +13 -0
  33. package/src/workflows/index.ts +1 -1
  34. package/src/workflows/shared/skills.test.ts +7 -0
  35. package/src/workflows/shared/steps.test.ts +45 -0
  36. package/src/workflows/shared/steps.ts +4 -2
  37. package/src/workflows/shared/tail.test.ts +31 -1
  38. package/src/workflows/shared/tail.ts +6 -3
  39. package/src/workflows/shared/text.test.ts +40 -0
  40. package/src/workflows/shared/text.ts +97 -16
@@ -0,0 +1,140 @@
1
+ @inmem
2
+ Feature: a naive pass ends only when a test names every criterion and the suite is green
3
+
4
+ `seam.naive` writes behaviour-level acceptance tests, each naming its
5
+ criterion's ID. A pass whose tests leave an ID out or import a file the
6
+ pass added is sent back; `seam.check` then runs the suite with the kept
7
+ pass applied, and a red run sends it back too, before the judge sees it.
8
+ Three failed attempts rest at `seam.steer`.
9
+
10
+ Background:
11
+ Given the shipped workflows, as gtd install scaffolds them
12
+ And an environment variable "GTD_QUALITYREVIEWS" set to ""
13
+ And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
14
+ And a file "src/calc.ts" with:
15
+ """
16
+ export const add = (a: number, b: number) => a + b
17
+ """
18
+ And the working tree is committed as "feat: add calculator"
19
+ And a file "TODO.md" with:
20
+ """
21
+ # Add subtract
22
+
23
+ subtract(a, b) returns the difference.
24
+ """
25
+ And step "unwind" changes nothing
26
+ And step "start-gate.check" changes nothing
27
+ And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
28
+ """
29
+ # Requirements
30
+
31
+ ## Acceptance Criteria
32
+
33
+ - AC-1: `subtract(5, 3)` returns 2.
34
+ - AC-2: `add` still adds.
35
+ """
36
+ And step "design.gate.answer" changes nothing
37
+ And step "seam.naive" writes "src/calc.ts" with:
38
+ """
39
+ export const add = (a: number, b: number) => a + b
40
+ export const subtract = (a: number, b: number) => a - b
41
+ """
42
+
43
+ Scenario: a pass whose tests leave a criterion's ID out is sent back, and an overrule runs the check and sticks
44
+ Given step "seam.naive" writes "tests/calc.test.ts" with:
45
+ """
46
+ import { add, subtract } from "../src/calc.js"
47
+ it("[AC-1] subtracts", () => expect(subtract(5, 3)).toBe(2))
48
+ """
49
+ When the process is driven
50
+ Then the process rests at "seam.steer"
51
+ And the resting step's content contains "acceptance-tests: no test of the naive pass names AC-2"
52
+
53
+ Given step "seam.check" changes nothing
54
+ When gtd lands
55
+ And the process is driven
56
+ Then the process rests at "seam.judge"
57
+ And the commit subjects end with:
58
+ """
59
+ gtd(human): design.gate.answer → seam.naive
60
+ gtd(agent): seam.naive
61
+ gtd(agent): seam.naive
62
+ gtd(agent): seam.naive → seam.steer
63
+ gtd(human): seam.steer → seam.check
64
+ gtd(check): seam.check → seam.judge
65
+ """
66
+
67
+ Given judge step "seam.judge" answers:
68
+ """
69
+ [{"id":"shape","answer":"reject","p":0.9}]
70
+ """
71
+ When the process is driven
72
+ Then the process rests at "seam.steer"
73
+ And the resting step's content contains "rejected the last attempt"
74
+ And the commit subjects end with:
75
+ """
76
+ gtd(check): seam.check → seam.judge
77
+ gtd(judge): seam.judge → seam.naive
78
+ gtd(agent): seam.naive → seam.check
79
+ gtd(check): seam.check → seam.judge
80
+ gtd(judge): seam.judge → seam.naive
81
+ gtd(agent): seam.naive → seam.check
82
+ gtd(check): seam.check → seam.judge
83
+ gtd(judge): seam.judge → seam.steer
84
+ """
85
+
86
+ Scenario: a test importing a file the pass added is sent back
87
+ Given step "seam.naive" writes "src/subtract.ts" with:
88
+ """
89
+ export const subtract = (a: number, b: number) => a - b
90
+ """
91
+ And step "seam.naive" writes "src/subtract.test.ts" with:
92
+ """
93
+ import { subtract } from "./subtract.js"
94
+ it("[AC-1] subtracts", () => expect(subtract(5, 3)).toBe(2))
95
+ it("[AC-2] still adds", () => {})
96
+ """
97
+ When the process is driven
98
+ Then the process rests at "seam.steer"
99
+ And the resting step's content contains "src/subtract.test.ts → src/subtract.ts"
100
+
101
+ Scenario: a red suite sends the pass back, and it moves on only once green
102
+ Given step "seam.naive" writes "tests/calc.test.ts" with:
103
+ """
104
+ import { add, subtract } from "../src/calc.js"
105
+ it("[AC-1] subtracts", () => expect(subtract(5, 3)).toBe(2))
106
+ it("[AC-2] still adds", () => expect(add(1, 1)).toBe(2))
107
+ """
108
+ When the process is driven
109
+ Then the process rests at "seam.check"
110
+ And the resting step's content contains "git checkout -q HEAD --"
111
+ And the resting step's content does not contain "'^'"
112
+ And the resting step's content contains "npm test"
113
+
114
+ Given step "seam.naive" is no longer scripted
115
+ And step "seam.check" writes ".gtd/FEEDBACK.md" with:
116
+ """
117
+ FAIL tests/calc.test.ts > [AC-1] subtracts
118
+ """
119
+ When the process is driven
120
+ Then the process rests at "seam.naive"
121
+ And the resting step's content contains "left the suite red"
122
+ And ".gtd/FEEDBACK.md" contains "[AC-1] subtracts"
123
+
124
+ Given step "seam.naive" writes "tests/calc.test.ts" with:
125
+ """
126
+ import { add, subtract } from "../src/calc.js"
127
+ it("[AC-1] subtracts", () => expect(subtract(5, 3)).toBe(2))
128
+ it("[AC-2] still adds", () => expect(add(2, 2)).toBe(4))
129
+ """
130
+ And step "seam.check" from now on changes nothing
131
+ When the process is driven
132
+ Then the process rests at "implement.building"
133
+ And the commit subjects end with:
134
+ """
135
+ gtd(human): design.gate.answer → seam.naive
136
+ gtd(agent): seam.naive → seam.check
137
+ gtd(check): seam.check → seam.naive
138
+ gtd(agent): seam.naive → seam.check
139
+ gtd(check): seam.check → implement.building
140
+ """
@@ -40,6 +40,11 @@ Feature: a naive pass the judge rules land goes straight to implement with no se
40
40
  - AC-1: the change behaves as described.
41
41
  """
42
42
  And step "design.gate.answer" changes nothing
43
+ And step "seam.check" changes nothing
44
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
45
+ """
46
+ it("[AC-1] holds", () => {})
47
+ """
43
48
  And step "seam.naive" writes "src/greeting.ts" with:
44
49
  """
45
50
  export const greeting = "Hello, world"
@@ -93,7 +98,8 @@ Feature: a naive pass the judge rules land goes straight to implement with no se
93
98
  gtd(check): start-gate.check → design.triage
94
99
  gtd(agent): design.triage → design.gate.answer
95
100
  gtd(human): design.gate.answer → seam.naive
96
- gtd(agent): seam.naive → seam.judge
101
+ gtd(agent): seam.naive → seam.check
102
+ gtd(check): seam.check → seam.judge
97
103
  gtd(judge): seam.judge → implement.building
98
104
  gtd(agent): implement.building → implement.health.check
99
105
  gtd(check): implement.health.check → implement.closing
@@ -104,7 +110,7 @@ Feature: a naive pass the judge rules land goes straight to implement with no se
104
110
  gtd(check): build.review.closing → idle
105
111
  """
106
112
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
107
- And the commit "gtd(agent): seam.naive → seam.judge" has a body containing "Gtd-Kept:"
113
+ And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
108
114
  And the commit "gtd(judge): seam.judge → implement.building" has a body containing "\"answer\":\"land\""
109
115
  And no commit body contains "Gtd-Approved:"
110
116
  And the output lines of gtd "slices" start with:
@@ -43,7 +43,12 @@ Feature: a refactor that carried the whole feature still gets a feature review
43
43
  And step "design.gate.answer" changes nothing
44
44
 
45
45
  Scenario: an empty implement turn after a refactor that did it all reaches review and idle
46
- Given step "seam.naive" writes "src/calc.ts" with:
46
+ Given step "seam.check" changes nothing
47
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
48
+ """
49
+ it("[AC-1] holds", () => {})
50
+ """
51
+ And step "seam.naive" writes "src/calc.ts" with:
47
52
  """
48
53
  export const add = (a: number, b: number) => a + b
49
54
  export const subtract = (a: number, b: number) => a - b
@@ -42,7 +42,12 @@ Feature: a refactor-first judgment walks one fixed path to idle
42
42
  And step "design.gate.answer" changes nothing
43
43
 
44
44
  Scenario: a refactor-first judgment runs refactor, its review, implement and review to idle
45
- Given step "seam.naive" writes "src/calc.ts" with:
45
+ Given step "seam.check" changes nothing
46
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
47
+ """
48
+ it("[AC-1] holds", () => {})
49
+ """
50
+ And step "seam.naive" writes "src/calc.ts" with:
46
51
  """
47
52
  export const add = (a: number, b: number) => a + b
48
53
  export const subtract = (a: number, b: number) => a - b
@@ -141,7 +146,8 @@ Feature: a refactor-first judgment walks one fixed path to idle
141
146
  gtd(check): start-gate.check → design.triage
142
147
  gtd(agent): design.triage → design.gate.answer
143
148
  gtd(human): design.gate.answer → seam.naive
144
- gtd(agent): seam.naive → seam.judge
149
+ gtd(agent): seam.naive → seam.check
150
+ gtd(check): seam.check → seam.judge
145
151
  gtd(judge): seam.judge → refactor.deriving
146
152
  gtd(check): refactor.deriving → refactor.building
147
153
  gtd(agent): refactor.building → refactor.health.check
@@ -158,7 +164,7 @@ Feature: a refactor-first judgment walks one fixed path to idle
158
164
  gtd(check): build.review.closing → idle
159
165
  """
160
166
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
161
- And the commit "gtd(agent): seam.naive → seam.judge" has a body containing "Gtd-Kept:"
167
+ And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
162
168
  And the commit "gtd(judge): seam.judge → refactor.deriving" has a body containing "\"answer\":\"refactor-first\""
163
169
  And no commit body contains "Gtd-Approved:"
164
170
  And the output lines of gtd "slices" start with:
@@ -0,0 +1,67 @@
1
+ @inmem
2
+ Feature: the refactor review's lenses take their model hints from refactorQualityReviews alone
3
+
4
+ Background:
5
+ Given the shipped workflows, as gtd install scaffolds them
6
+ And an environment variable "GTD_QUALITYREVIEWS" set to "correctness=base"
7
+ And an environment variable "GTD_REFACTORQUALITYREVIEWS" set to "correctness, conventions=opus"
8
+ And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
9
+ And a file "src/calc.ts" with:
10
+ """
11
+ export const add = (a: number, b: number) => a + b
12
+ """
13
+ And the working tree is committed as "feat: add calculator"
14
+ And a file "TODO.md" with:
15
+ """
16
+ # Add subtract
17
+
18
+ subtract(a, b) returns the difference.
19
+ """
20
+ And step "unwind" changes nothing
21
+ And step "start-gate.check" changes nothing
22
+ And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
23
+ """
24
+ # Requirements
25
+
26
+ ## Concerns
27
+
28
+ ### Subtract
29
+
30
+ - `subtract(a, b)` returns `a - b`.
31
+
32
+ ## Acceptance Criteria
33
+
34
+ - AC-1: the change behaves as described.
35
+ """
36
+ And step "design.gate.answer" changes nothing
37
+
38
+ Scenario: a refactor lens runs on its refactorQualityReviews hint, else its default
39
+ Given step "seam.check" changes nothing
40
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
41
+ """
42
+ it("[AC-1] holds", () => {})
43
+ """
44
+ And step "seam.naive" writes "src/calc.ts" with:
45
+ """
46
+ export const add = (a: number, b: number) => a + b
47
+ export const subtract = (a: number, b: number) => a - b
48
+ """
49
+ And judge step "seam.judge" answers:
50
+ """
51
+ [{"id":"shape","answer":"refactor-first","p":0.9}]
52
+ """
53
+ And step "refactor.deriving" runs its script
54
+ And step "refactor.building" writes "src/calc.ts" with:
55
+ """
56
+ export const op = (a: number, b: number, sign: number) => a + sign * b
57
+ export const add = (a: number, b: number) => op(a, b, 1)
58
+ """
59
+ And step "refactor.health.check" changes nothing
60
+ And step "refactor.closing" runs its script
61
+ When the process is driven
62
+ Then the process rests at "refactor.build.quality.correctness.reviewing"
63
+ And the output of gtd "next --json" contains "\"model\":\"smart\""
64
+ Given step "refactor.build.quality.correctness.reviewing" changes nothing
65
+ When the process is driven
66
+ Then the process rests at "refactor.build.quality.conventions.reviewing"
67
+ And the output of gtd "next --json" contains "\"model\":\"opus\""
@@ -52,6 +52,11 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
52
52
  - AC-1: the change behaves as described.
53
53
  """
54
54
  And step "design.gate.answer" changes nothing
55
+ And step "seam.check" changes nothing
56
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
57
+ """
58
+ it("[AC-1] holds", () => {})
59
+ """
55
60
  And step "seam.naive" writes "src/calc.ts" with:
56
61
  """
57
62
  export const add = (a: number, b: number) => a + b
@@ -136,6 +141,11 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
136
141
  - AC-1: the change behaves as described.
137
142
  """
138
143
  And step "design.gate.answer" changes nothing
144
+ And step "seam.check" changes nothing
145
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
146
+ """
147
+ it("[AC-1] holds", () => {})
148
+ """
139
149
  And step "seam.naive" writes "src/calc.ts" with:
140
150
  """
141
151
  export const add = (a: number, b: number) => a + b
@@ -219,6 +229,11 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
219
229
  - AC-1: the change behaves as described.
220
230
  """
221
231
  And step "design.gate.answer" changes nothing
232
+ And step "seam.check" changes nothing
233
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
234
+ """
235
+ it("[AC-1] holds", () => {})
236
+ """
222
237
  And step "seam.naive" writes "src/calc.ts" with:
223
238
  """
224
239
  export const add = (a: number, b: number) => a + b
@@ -1426,6 +1441,11 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1426
1441
  - AC-1: the change behaves as described.
1427
1442
  """
1428
1443
  And step "design.gate.answer" changes nothing
1444
+ And step "seam.check" changes nothing
1445
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
1446
+ """
1447
+ it("[AC-1] holds", () => {})
1448
+ """
1429
1449
  And step "seam.naive" writes "src/calc.ts" with:
1430
1450
  """
1431
1451
  export const add = (a: number, b: number) => a + b
@@ -1614,7 +1634,12 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1614
1634
  """
1615
1635
 
1616
1636
  Scenario: a test-file stray is dropped from the derived refactor package
1617
- Given step "seam.naive" writes "src/calc.ts" with:
1637
+ Given step "seam.check" changes nothing
1638
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
1639
+ """
1640
+ it("[AC-1] holds", () => {})
1641
+ """
1642
+ And step "seam.naive" writes "src/calc.ts" with:
1618
1643
  """
1619
1644
  export const add = (a: number, b: number) => a + b
1620
1645
  export const subtract = (a: number, b: number) => a - b
@@ -1631,7 +1656,12 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1631
1656
  And ".gtd/REFACTOR.md" does not contain "src/calc.test.ts"
1632
1657
 
1633
1658
  Scenario: the refactor updates an existing test's call sites to the seam's new shape
1634
- Given step "seam.naive" writes "src/calc.ts" with:
1659
+ Given step "seam.check" changes nothing
1660
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
1661
+ """
1662
+ it("[AC-1] holds", () => {})
1663
+ """
1664
+ And step "seam.naive" writes "src/calc.ts" with:
1635
1665
  """
1636
1666
  export const add = ({ a, b }: { a: number; b: number }) => a + b
1637
1667
  export const subtract = ({ a, b }: { a: number; b: number }) => a - b
@@ -1651,7 +1681,12 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1651
1681
  Then the process rests at "refactor.health.check"
1652
1682
 
1653
1683
  Scenario: the refactor may not drop an assertion from an existing test
1654
- Given step "seam.naive" writes "src/calc.ts" with:
1684
+ Given step "seam.check" changes nothing
1685
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
1686
+ """
1687
+ it("[AC-1] holds", () => {})
1688
+ """
1689
+ And step "seam.naive" writes "src/calc.ts" with:
1655
1690
  """
1656
1691
  export const add = (a: number, b: number) => a + b
1657
1692
  export const subtract = (a: number, b: number) => a - b
@@ -1665,7 +1700,12 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1665
1700
  Then driving the process is refused with "refactor-tests"
1666
1701
 
1667
1702
  Scenario: a refactor-first whose strays are all test files goes straight to implement
1668
- Given step "seam.naive" writes "src/calc.test.ts" with:
1703
+ Given step "seam.check" changes nothing
1704
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
1705
+ """
1706
+ it("[AC-1] holds", () => {})
1707
+ """
1708
+ And step "seam.naive" writes "src/calc.test.ts" with:
1669
1709
  """
1670
1710
  import { expect, it } from "vitest"
1671
1711
  it("subtracts", () => expect(3 - 1).toBe(2))
@@ -1675,7 +1715,12 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
1675
1715
  And ".gtd/REFACTOR.md" does not exist
1676
1716
 
1677
1717
  Scenario: collected review headings re-derive at ### with the deepest capped at ######
1678
- Given step "seam.naive" writes "src/calc.ts" with:
1718
+ Given step "seam.check" changes nothing
1719
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
1720
+ """
1721
+ it("[AC-1] holds", () => {})
1722
+ """
1723
+ And step "seam.naive" writes "src/calc.ts" with:
1679
1724
  """
1680
1725
  export const add = (a: number, b: number) => a + b
1681
1726
  export const subtract = (a: number, b: number) => a - b
@@ -13,7 +13,7 @@ import {
13
13
  type Change,
14
14
  type DiffShapeResult,
15
15
  } from "../../flows/index.js"
16
- import { lensesOf } from "../../workflow-kit/index.js"
16
+ import { lensEntriesOf } from "../../workflow-kit/index.js"
17
17
  import { markFenced } from "../shared/fences.js"
18
18
  import { healthy, type Guard } from "../shared/health.js"
19
19
  import { coder, FEEDBACK, REFACTOR } from "../shared/steps.js"
@@ -42,7 +42,8 @@ export const requireWithin = (allowed: readonly string[]): void => {
42
42
  }
43
43
 
44
44
  // A fixed list, not `seamAllow`: narrowing that setting must not let a test file through.
45
- const isTestFile = (path: string): boolean => testFileGlobs.some((glob) => matches(path, glob))
45
+ export const isTestFile = (path: string): boolean =>
46
+ testFileGlobs.some((glob) => matches(path, glob))
46
47
 
47
48
  // The bundled refactor uses `requireTestCallSitesOnly`; this stays a public export.
48
49
  export const requireNoTestFiles = (): void => {
@@ -56,11 +57,11 @@ export const requireNoTestFiles = (): void => {
56
57
  }
57
58
 
58
59
  // Call sites live in code: a `.feature` file or a snapshot holds only expectations.
59
- const holdsCallSites = (path: string): boolean =>
60
+ export const holdsCallSites = (path: string): boolean =>
60
61
  !path.endsWith(".feature") && !path.endsWith(".snap")
61
62
 
62
63
  // `//` after a `:` (a URL) and `/*` after `*` or `/` (a glob) sit in strings, not comments.
63
- const COMMENT = /(?<![*/])\/\*[\s\S]*?\*\/|(?<!:)\/\/.*$/gm
64
+ export const COMMENT = /(?<![*/])\/\*[\s\S]*?\*\/|(?<!:)\/\/.*$/gm
64
65
  const ASSERTION = /\b(?:expect|assert\w*)\s*[.(]/g
65
66
  const TEST_CASE = /(?<![.\w])x?(?:it|test|describe)\s*[.(]/g
66
67
  const MODIFIER =
@@ -343,7 +344,7 @@ export const reviewedRefactor = async (
343
344
  green: true,
344
345
  guard,
345
346
  guardRests: false,
346
- lenses: lensesOf(vars.refactorQualityReviews ?? ""),
347
+ lenses: lensEntriesOf(vars.refactorQualityReviews ?? ""),
347
348
  feedback,
348
349
  fixAccess: strayAccess(p.strays),
349
350
  lensBase: entry,
@@ -146,6 +146,11 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
146
146
 
147
147
  - AC-1: the change behaves as described.
148
148
  """
149
+ And step "seam.check" changes nothing
150
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
151
+ """
152
+ it("[AC-1] holds", () => {})
153
+ """
149
154
  And step "seam.naive" writes "src/calc.ts" with:
150
155
  """
151
156
  export const add = (a: number, b: number) => a + b
@@ -254,6 +259,11 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
254
259
  - AC-1: the change behaves as described.
255
260
  """
256
261
  And step "design.gate.answer" changes nothing
262
+ And step "seam.check" changes nothing
263
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
264
+ """
265
+ it("[AC-1] holds", () => {})
266
+ """
257
267
  And step "seam.naive" writes "src/calc.ts" with:
258
268
  """
259
269
  export const add = (a: number, b: number) => a + b
@@ -41,7 +41,12 @@ Feature: rejected naive passes walk one fixed path through the steer gate to idl
41
41
  And step "design.gate.answer" changes nothing
42
42
 
43
43
  Scenario: three rejects rest at the steer gate, a steered rerun lands and runs to idle
44
- Given step "seam.naive" writes "src/calc.ts" with:
44
+ Given step "seam.check" changes nothing
45
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
46
+ """
47
+ it("[AC-1] holds", () => {})
48
+ """
49
+ And step "seam.naive" writes "src/calc.ts" with:
45
50
  """
46
51
  export const add = (a: number, b: number) => b + a
47
52
  """
@@ -87,6 +92,10 @@ Feature: rejected naive passes walk one fixed path through the steer gate to idl
87
92
  - AC-1: the change behaves as described.
88
93
  """
89
94
  And step "seam.naive" from now on changes nothing
95
+ And step "seam.naive" writes "src/acceptance.test.ts" with:
96
+ """
97
+ it("[AC-1] holds", () => {})
98
+ """
90
99
  And step "seam.naive" writes "src/calc.ts" with:
91
100
  """
92
101
  export const add = (a: number, b: number) => a + b
@@ -127,14 +136,18 @@ Feature: rejected naive passes walk one fixed path through the steer gate to idl
127
136
  gtd(check): start-gate.check → design.triage
128
137
  gtd(agent): design.triage → design.gate.answer
129
138
  gtd(human): design.gate.answer → seam.naive
130
- gtd(agent): seam.naive → seam.judge
139
+ gtd(agent): seam.naive → seam.check
140
+ gtd(check): seam.check → seam.judge
131
141
  gtd(judge): seam.judge → seam.naive
132
- gtd(agent): seam.naive → seam.judge
142
+ gtd(agent): seam.naive → seam.check
143
+ gtd(check): seam.check → seam.judge
133
144
  gtd(judge): seam.judge → seam.naive
134
- gtd(agent): seam.naive → seam.judge
145
+ gtd(agent): seam.naive → seam.check
146
+ gtd(check): seam.check → seam.judge
135
147
  gtd(judge): seam.judge → seam.steer
136
148
  gtd(human): seam.steer → seam.naive
137
- gtd(agent): seam.naive → seam.judge
149
+ gtd(agent): seam.naive → seam.check
150
+ gtd(check): seam.check → seam.judge
138
151
  gtd(judge): seam.judge → implement.building
139
152
  gtd(agent): implement.building → implement.health.check
140
153
  gtd(check): implement.health.check → implement.closing
@@ -144,7 +157,7 @@ Feature: rejected naive passes walk one fixed path through the steer gate to idl
144
157
  gtd(check): build.review.closing → idle
145
158
  """
146
159
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
147
- And the commit "gtd(agent): seam.naive → seam.judge" has a body containing "Gtd-Kept:"
160
+ And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
148
161
  And the commit "gtd(judge): seam.judge → seam.naive" has a body containing "\"answer\":\"reject\""
149
162
  And the commit "gtd(judge): seam.judge → seam.steer" has a body containing "\"answer\":\"reject\""
150
163
  And the commit "gtd(judge): seam.judge → implement.building" has a body containing "\"answer\":\"land\""