@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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +28 -22
- package/dist/chunks/{reserved-CHTJTzpA.mjs → reserved-BU5Zi-nX.mjs} +74 -13
- package/dist/chunks/{tail-CCsDBbZe.mjs → tail-DuXanjIY.mjs} +6 -3
- package/dist/testkit.mjs +2 -2
- package/dist/workflow-kit.mjs +15 -3
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +158 -34
- package/dist/workflows/fix.mjs +2 -2
- package/dist/workflows/review.mjs +2 -2
- package/dist/workflows/rollout.mjs +1 -1
- package/dist/workflows.mjs +246 -46
- package/package.json +1 -1
- package/src/workflow-kit/quality.test.ts +25 -1
- package/src/workflow-kit/quality.ts +22 -4
- package/src/workflows/feature/acceptance-criteria.feature +8 -0
- package/src/workflows/feature/fast-path.feature +8 -2
- package/src/workflows/feature/feature.test.ts +19 -9
- package/src/workflows/feature/lens-models.feature +60 -0
- package/src/workflows/feature/naive-acceptance.feature +140 -0
- package/src/workflows/feature/one-step-land.feature +8 -2
- package/src/workflows/feature/refactor-absorbs.feature +6 -1
- package/src/workflows/feature/refactor-first.feature +9 -3
- package/src/workflows/feature/refactor-lens-models.feature +67 -0
- package/src/workflows/feature/refactor-review.feature +50 -5
- package/src/workflows/feature/refactor.ts +6 -5
- package/src/workflows/feature/risk-tier.feature +10 -0
- package/src/workflows/feature/seam-rejection.feature +19 -6
- package/src/workflows/feature/seam.feature +70 -16
- package/src/workflows/feature/seam.test.ts +189 -3
- package/src/workflows/feature/seam.ts +195 -30
- package/src/workflows/feature/steps.test.ts +13 -0
- package/src/workflows/index.ts +1 -1
- package/src/workflows/shared/skills.test.ts +7 -0
- package/src/workflows/shared/steps.test.ts +45 -0
- package/src/workflows/shared/steps.ts +4 -2
- package/src/workflows/shared/tail.test.ts +31 -1
- package/src/workflows/shared/tail.ts +6 -3
- package/src/workflows/shared/text.test.ts +40 -0
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 {
|
|
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 =>
|
|
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:
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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\""
|