@pmelab/gtd 36.0.0 → 37.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 +21 -9
- package/claude/hooks/context.ts +66 -0
- package/claude/hooks/drive.ts +3 -0
- package/claude/hooks/register.tsx +69 -6
- package/dist/chunks/{reserved-BAv71I4i.mjs → reserved-zAfoJtR7.mjs} +53 -16
- package/dist/chunks/{tail-kar1zhOb.mjs → tail-BRC4DGdV.mjs} +1 -1
- package/dist/chunks/{wire-D3Rc5r22.mjs → wire-CSsa3Wxd.mjs} +117 -2
- package/dist/gtd.bundle.mjs +498 -56
- package/dist/testkit.mjs +115 -3
- package/dist/wire.mjs +2 -2
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +126 -33
- 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 +174 -44
- package/package.json +1 -1
- package/src/cli/Cli.test.ts +10 -3
- package/src/cli/Cli.ts +76 -1
- package/src/cli/Program.test.ts +1 -0
- package/src/cli/Program.ts +28 -0
- package/src/cli/ToolCommands.ts +3 -0
- package/src/edge/Edge.ts +11 -0
- package/src/flows/runtime.ts +11 -0
- package/src/replay/Replay.ts +51 -2
- package/src/testkit/Layers.ts +1 -0
- package/src/wire/BeatDocument.ts +12 -2
- package/src/wire/BeatStatus.ts +3 -0
- package/src/wire/ContextLimit.fixture.ts +30 -0
- package/src/wire/ContextLimit.test.ts +96 -0
- package/src/wire/ContextLimit.ts +169 -0
- package/src/wire/index.ts +1 -0
- package/src/wire/types.ts +7 -0
- package/src/workflow/Workflow.ts +9 -1
- package/src/workflows/feature/context-limit.feature +37 -0
- package/src/workflows/feature/coverage.ts +8 -2
- package/src/workflows/feature/feature.ts +6 -2
- package/src/workflows/feature/refactor-absorbs.feature +12 -5
- package/src/workflows/feature/refactor-first.feature +11 -2
- package/src/workflows/feature/refactor-lens-models.feature +4 -0
- package/src/workflows/feature/refactor-rebuild.feature +269 -0
- package/src/workflows/feature/refactor-review.feature +45 -1
- package/src/workflows/feature/refactor.ts +9 -3
- package/src/workflows/feature/seam.test.ts +108 -3
- package/src/workflows/feature/seam.ts +120 -19
- package/src/workflows/shared/options.test.ts +11 -2
- package/src/workflows/shared/options.ts +18 -4
- package/src/workflows/shared/steps.ts +1 -0
- package/src/workflows/shared/text.ts +80 -14
|
@@ -4,9 +4,9 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
|
|
|
4
4
|
|
|
5
5
|
With GTD_FLAG_RISK_TIER off, a refactor-first
|
|
6
6
|
refactor can land everything the requirements ask for. The feature slice's
|
|
7
|
-
implement turn then has
|
|
8
|
-
|
|
9
|
-
quality lap covers the whole change, refactor included.
|
|
7
|
+
implement turn then has only the naive pass's acceptance tests to carry
|
|
8
|
+
over, and with no code but tests changed since the refactor the feature
|
|
9
|
+
slice's quality lap covers the whole change, refactor included.
|
|
10
10
|
|
|
11
11
|
Background:
|
|
12
12
|
Given the shipped workflows, as gtd install scaffolds them
|
|
@@ -42,7 +42,7 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
|
|
|
42
42
|
"""
|
|
43
43
|
And step "design.gate.answer" changes nothing
|
|
44
44
|
|
|
45
|
-
Scenario:
|
|
45
|
+
Scenario: a tests-only implement turn after a refactor that did it all reaches the quality lap and idle
|
|
46
46
|
Given step "seam.check" changes nothing
|
|
47
47
|
And step "seam.naive" writes "src/acceptance.test.ts" with:
|
|
48
48
|
"""
|
|
@@ -57,6 +57,10 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
|
|
|
57
57
|
"""
|
|
58
58
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
59
59
|
"""
|
|
60
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
61
|
+
"""
|
|
62
|
+
Seam: the existing code the strays touch.
|
|
63
|
+
"""
|
|
60
64
|
And step "refactor.deriving" runs its script
|
|
61
65
|
And step "refactor.building" writes "src/calc.ts" with:
|
|
62
66
|
"""
|
|
@@ -91,7 +95,10 @@ Feature: a refactor that carried the whole feature still gets a quality lap over
|
|
|
91
95
|
- [x] ./src/calc.ts#1-2
|
|
92
96
|
subtract next to add
|
|
93
97
|
"""
|
|
94
|
-
And step "implement.building"
|
|
98
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
99
|
+
"""
|
|
100
|
+
it("[AC-1] holds", () => {})
|
|
101
|
+
"""
|
|
95
102
|
And step "implement.health.check" changes nothing
|
|
96
103
|
And step "implement.closing" runs its script
|
|
97
104
|
And judge step "implement.coverage" answers:
|
|
@@ -56,6 +56,10 @@ Feature: a refactor-first judgment walks one fixed path to idle
|
|
|
56
56
|
"""
|
|
57
57
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
58
58
|
"""
|
|
59
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
60
|
+
"""
|
|
61
|
+
Seam: the existing code the strays touch.
|
|
62
|
+
"""
|
|
59
63
|
And step "refactor.deriving" runs its script
|
|
60
64
|
When the process is driven
|
|
61
65
|
Then the process rests at "refactor.building"
|
|
@@ -106,6 +110,10 @@ Feature: a refactor-first judgment walks one fixed path to idle
|
|
|
106
110
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
107
111
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
108
112
|
"""
|
|
113
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
114
|
+
"""
|
|
115
|
+
it("[AC-1] holds", () => {})
|
|
116
|
+
"""
|
|
109
117
|
And step "implement.health.check" changes nothing
|
|
110
118
|
And step "implement.closing" runs its script
|
|
111
119
|
And judge step "implement.coverage" answers:
|
|
@@ -125,7 +133,8 @@ Feature: a refactor-first judgment walks one fixed path to idle
|
|
|
125
133
|
gtd(human): design.gate.answer → seam.naive
|
|
126
134
|
gtd(agent): seam.naive → seam.check
|
|
127
135
|
gtd(check): seam.check → seam.judge
|
|
128
|
-
gtd(judge): seam.judge →
|
|
136
|
+
gtd(judge): seam.judge → seam.note
|
|
137
|
+
gtd(agent): seam.note → refactor.deriving
|
|
129
138
|
gtd(check): refactor.deriving → refactor.building
|
|
130
139
|
gtd(agent): refactor.building → refactor.health.check
|
|
131
140
|
gtd(check): refactor.health.check → refactor.closing
|
|
@@ -140,7 +149,7 @@ Feature: a refactor-first judgment walks one fixed path to idle
|
|
|
140
149
|
"""
|
|
141
150
|
And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
|
|
142
151
|
And the commit "gtd(agent): seam.naive → seam.check" has a body containing "Gtd-Kept:"
|
|
143
|
-
And the commit "gtd(judge): seam.judge →
|
|
152
|
+
And the commit "gtd(judge): seam.judge → seam.note" has a body containing "\"answer\":\"refactor-first\""
|
|
144
153
|
And no commit body contains "Gtd-Approved:"
|
|
145
154
|
And the output lines of gtd "slices" start with:
|
|
146
155
|
"""
|
|
@@ -50,6 +50,10 @@ Feature: the refactor review's lenses take their model hints from refactorQualit
|
|
|
50
50
|
"""
|
|
51
51
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
52
52
|
"""
|
|
53
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
54
|
+
"""
|
|
55
|
+
Seam: the existing code the strays touch.
|
|
56
|
+
"""
|
|
53
57
|
And step "refactor.deriving" runs its script
|
|
54
58
|
And step "refactor.building" writes "src/calc.ts" with:
|
|
55
59
|
"""
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# One SDLC path per file, so a changed path reds exactly one fixture — do not merge.
|
|
2
|
+
@inmem
|
|
3
|
+
Feature: refactor-first writes a refactor note, refactors on its own, then rebuilds
|
|
4
|
+
|
|
5
|
+
On a refactor-first judgment the naive pass is never applied. `seam.note`
|
|
6
|
+
reads the whole naive diff and writes `.gtd/REFACTOR-NOTE.md`; the refactor
|
|
7
|
+
lands on its own with the existing suite green; the rebuild re-implements the
|
|
8
|
+
change on the refactored base and lands only once it carries the naive pass's
|
|
9
|
+
acceptance tests and the suite is green. The note reaches both turns.
|
|
10
|
+
|
|
11
|
+
Background:
|
|
12
|
+
Given the shipped workflows, as gtd install scaffolds them
|
|
13
|
+
And an environment variable "GTD_QUALITYREVIEWS" set to ""
|
|
14
|
+
And an environment variable "GTD_REFACTORQUALITYREVIEWS" set to ""
|
|
15
|
+
And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
|
|
16
|
+
And a file "src/calc.ts" with:
|
|
17
|
+
"""
|
|
18
|
+
export const add = (a: number, b: number) => a + b
|
|
19
|
+
"""
|
|
20
|
+
And the working tree is committed as "feat: add calculator"
|
|
21
|
+
And a file "TODO.md" with:
|
|
22
|
+
"""
|
|
23
|
+
# Add subtract
|
|
24
|
+
|
|
25
|
+
subtract(a, b) returns the difference.
|
|
26
|
+
"""
|
|
27
|
+
And step "unwind" changes nothing
|
|
28
|
+
And step "start-gate.check" changes nothing
|
|
29
|
+
And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
30
|
+
"""
|
|
31
|
+
# Requirements
|
|
32
|
+
|
|
33
|
+
## Concerns
|
|
34
|
+
|
|
35
|
+
### Subtract
|
|
36
|
+
|
|
37
|
+
- `subtract(a, b)` returns `a - b`.
|
|
38
|
+
|
|
39
|
+
## Acceptance Criteria
|
|
40
|
+
|
|
41
|
+
- AC-1: subtract returns the difference.
|
|
42
|
+
"""
|
|
43
|
+
And step "design.gate.answer" changes nothing
|
|
44
|
+
And step "seam.check" changes nothing
|
|
45
|
+
And step "seam.naive" writes "src/acceptance.test.ts" with:
|
|
46
|
+
"""
|
|
47
|
+
it("[AC-1] subtracts", () => {})
|
|
48
|
+
"""
|
|
49
|
+
And step "seam.naive" writes "src/calc.ts" with:
|
|
50
|
+
"""
|
|
51
|
+
export const add = (a: number, b: number) => a + b
|
|
52
|
+
export const subtract = (a: number, b: number) => a - b
|
|
53
|
+
"""
|
|
54
|
+
And judge step "seam.judge" answers:
|
|
55
|
+
"""
|
|
56
|
+
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
Scenario: the refactor note reaches the refactor turn and the rebuild turn
|
|
60
|
+
When the process is driven
|
|
61
|
+
Then the process rests at "seam.note"
|
|
62
|
+
And the resting step's content contains "git show"
|
|
63
|
+
And the resting step's content contains ".gtd/REFACTOR-NOTE.md"
|
|
64
|
+
And "src/calc.ts" does not contain "subtract"
|
|
65
|
+
|
|
66
|
+
Given step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
67
|
+
"""
|
|
68
|
+
# Refactor note
|
|
69
|
+
|
|
70
|
+
Seam: route add through a shared `op(a, b, sign)` in src/calc.ts.
|
|
71
|
+
"""
|
|
72
|
+
And step "refactor.deriving" runs its script
|
|
73
|
+
When the process is driven
|
|
74
|
+
Then the process rests at "refactor.building"
|
|
75
|
+
And ".gtd/REFACTOR.md" contains "## Refactor note"
|
|
76
|
+
And ".gtd/REFACTOR.md" contains "shared `op(a, b, sign)`"
|
|
77
|
+
And the resting step's content contains "Refactor note"
|
|
78
|
+
|
|
79
|
+
Given step "refactor.building" writes "src/calc.ts" with:
|
|
80
|
+
"""
|
|
81
|
+
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
82
|
+
export const add = (a: number, b: number) => op(a, b, 1)
|
|
83
|
+
"""
|
|
84
|
+
And step "refactor.health.check" changes nothing
|
|
85
|
+
And step "refactor.closing" runs its script
|
|
86
|
+
And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
|
|
87
|
+
"""
|
|
88
|
+
# Review: abc1234
|
|
89
|
+
|
|
90
|
+
<!-- base: 0000000 -->
|
|
91
|
+
|
|
92
|
+
## calc
|
|
93
|
+
|
|
94
|
+
- [ ] ./src/calc.ts#1-2
|
|
95
|
+
add built on the shared op
|
|
96
|
+
"""
|
|
97
|
+
And step "refactor.build.review.closing" runs its script
|
|
98
|
+
When the process is driven
|
|
99
|
+
Then the process rests at "refactor.build.review.await-review"
|
|
100
|
+
|
|
101
|
+
Given a file ".gtd/REVIEW.md" with:
|
|
102
|
+
"""
|
|
103
|
+
# Review: abc1234
|
|
104
|
+
|
|
105
|
+
<!-- base: 0000000 -->
|
|
106
|
+
|
|
107
|
+
## calc
|
|
108
|
+
|
|
109
|
+
- [x] ./src/calc.ts#1-2
|
|
110
|
+
add built on the shared op
|
|
111
|
+
"""
|
|
112
|
+
When gtd lands
|
|
113
|
+
And the process is driven
|
|
114
|
+
Then the process rests at "implement.building"
|
|
115
|
+
And the resting step's content contains "shared `op(a, b, sign)`"
|
|
116
|
+
And the resting step's content contains "acceptance tests for AC-1"
|
|
117
|
+
|
|
118
|
+
Scenario: a note turn that changes anything but the note is refused
|
|
119
|
+
Given step "seam.note" writes "src/calc.ts" with:
|
|
120
|
+
"""
|
|
121
|
+
export const sub = 1
|
|
122
|
+
"""
|
|
123
|
+
Then driving the process is refused with "refactor-note"
|
|
124
|
+
|
|
125
|
+
Scenario: the refactor lands on its own only with the existing suite green
|
|
126
|
+
Given step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
127
|
+
"""
|
|
128
|
+
Seam: a shared `op` in src/calc.ts.
|
|
129
|
+
"""
|
|
130
|
+
And step "refactor.deriving" runs its script
|
|
131
|
+
And step "refactor.building" writes "src/calc.ts" with:
|
|
132
|
+
"""
|
|
133
|
+
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
134
|
+
export const add = (a: number, b: number) => op(a, b, -1)
|
|
135
|
+
"""
|
|
136
|
+
And step "refactor.health.check" writes ".gtd/FEEDBACK.md" with:
|
|
137
|
+
"""
|
|
138
|
+
FAIL add(1, 2) returned -1
|
|
139
|
+
"""
|
|
140
|
+
When the process is driven
|
|
141
|
+
Then the process rests at "refactor.fix.suite.fixing"
|
|
142
|
+
|
|
143
|
+
Given step "refactor.fix.suite.fixing" writes "src/calc.ts" with:
|
|
144
|
+
"""
|
|
145
|
+
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
146
|
+
export const add = (a: number, b: number) => op(a, b, 1)
|
|
147
|
+
"""
|
|
148
|
+
And step "refactor.health.check" changes nothing
|
|
149
|
+
And step "refactor.closing" runs its script
|
|
150
|
+
And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
|
|
151
|
+
"""
|
|
152
|
+
# Review: abc1234
|
|
153
|
+
|
|
154
|
+
<!-- base: 0000000 -->
|
|
155
|
+
|
|
156
|
+
## calc
|
|
157
|
+
|
|
158
|
+
- [ ] ./src/calc.ts#1-2
|
|
159
|
+
add built on the shared op
|
|
160
|
+
"""
|
|
161
|
+
And step "refactor.build.review.closing" runs its script
|
|
162
|
+
When the process is driven
|
|
163
|
+
Then the process rests at "refactor.build.review.await-review"
|
|
164
|
+
|
|
165
|
+
Given a file ".gtd/REVIEW.md" with:
|
|
166
|
+
"""
|
|
167
|
+
# Review: abc1234
|
|
168
|
+
|
|
169
|
+
<!-- base: 0000000 -->
|
|
170
|
+
|
|
171
|
+
## calc
|
|
172
|
+
|
|
173
|
+
- [x] ./src/calc.ts#1-2
|
|
174
|
+
add built on the shared op
|
|
175
|
+
"""
|
|
176
|
+
When gtd lands
|
|
177
|
+
And the process is driven
|
|
178
|
+
Then the process rests at "implement.building"
|
|
179
|
+
And "src/calc.ts" contains "op(a, b, 1)"
|
|
180
|
+
And "src/calc.ts" does not contain "subtract"
|
|
181
|
+
And the output of gtd "slices" contains "refactor "
|
|
182
|
+
|
|
183
|
+
Scenario: the rebuild lands only once it carries the naive pass's acceptance tests, green
|
|
184
|
+
Given step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
185
|
+
"""
|
|
186
|
+
Seam: a shared `op` in src/calc.ts.
|
|
187
|
+
"""
|
|
188
|
+
And step "refactor.deriving" runs its script
|
|
189
|
+
And step "refactor.building" writes "src/calc.ts" with:
|
|
190
|
+
"""
|
|
191
|
+
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
192
|
+
export const add = (a: number, b: number) => op(a, b, 1)
|
|
193
|
+
"""
|
|
194
|
+
And step "refactor.health.check" changes nothing
|
|
195
|
+
And step "refactor.closing" runs its script
|
|
196
|
+
And step "refactor.build.review.reviewing" writes ".gtd/REVIEW.md" with:
|
|
197
|
+
"""
|
|
198
|
+
# Review: abc1234
|
|
199
|
+
|
|
200
|
+
<!-- base: 0000000 -->
|
|
201
|
+
|
|
202
|
+
## calc
|
|
203
|
+
|
|
204
|
+
- [ ] ./src/calc.ts#1-2
|
|
205
|
+
add built on the shared op
|
|
206
|
+
"""
|
|
207
|
+
And step "refactor.build.review.closing" runs its script
|
|
208
|
+
When the process is driven
|
|
209
|
+
Then the process rests at "refactor.build.review.await-review"
|
|
210
|
+
|
|
211
|
+
Given a file ".gtd/REVIEW.md" with:
|
|
212
|
+
"""
|
|
213
|
+
# Review: abc1234
|
|
214
|
+
|
|
215
|
+
<!-- base: 0000000 -->
|
|
216
|
+
|
|
217
|
+
## calc
|
|
218
|
+
|
|
219
|
+
- [x] ./src/calc.ts#1-2
|
|
220
|
+
add built on the shared op
|
|
221
|
+
"""
|
|
222
|
+
When gtd lands
|
|
223
|
+
And the process is driven
|
|
224
|
+
Then the process rests at "implement.building"
|
|
225
|
+
|
|
226
|
+
Given step "implement.building" writes "src/calc.ts" with:
|
|
227
|
+
"""
|
|
228
|
+
export const op = (a: number, b: number, sign: number) => a + sign * b
|
|
229
|
+
export const add = (a: number, b: number) => op(a, b, 1)
|
|
230
|
+
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
231
|
+
"""
|
|
232
|
+
Then driving the process is refused with "rebuild-acceptance"
|
|
233
|
+
|
|
234
|
+
Given step "implement.building" writes "src/acceptance.test.ts" with:
|
|
235
|
+
"""
|
|
236
|
+
it("[AC-1] subtracts", () => {})
|
|
237
|
+
"""
|
|
238
|
+
And step "implement.health.check" changes nothing
|
|
239
|
+
And step "implement.closing" runs its script
|
|
240
|
+
And judge step "implement.coverage" answers:
|
|
241
|
+
"""
|
|
242
|
+
[{"id":"AC-1","answer":"yes","p":0.9}]
|
|
243
|
+
"""
|
|
244
|
+
When the process is driven
|
|
245
|
+
Then the process rests at "idle"
|
|
246
|
+
And "src/calc.ts" contains "op(a, b, -1)"
|
|
247
|
+
And "src/acceptance.test.ts" contains "[AC-1]"
|
|
248
|
+
And ".gtd/REFACTOR-NOTE.md" does not exist
|
|
249
|
+
And the commit subjects end with:
|
|
250
|
+
"""
|
|
251
|
+
gtd(judge): seam.judge → seam.note
|
|
252
|
+
gtd(agent): seam.note → refactor.deriving
|
|
253
|
+
gtd(check): refactor.deriving → refactor.building
|
|
254
|
+
gtd(agent): refactor.building → refactor.health.check
|
|
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
|
|
258
|
+
gtd(human): refactor.build.review.await-review → refactor.build.review.closing
|
|
259
|
+
gtd(check): refactor.build.review.closing → implement.building
|
|
260
|
+
gtd(agent): implement.building → implement.health.check
|
|
261
|
+
gtd(check): implement.health.check → implement.coverage
|
|
262
|
+
gtd(judge): implement.coverage → implement.closing
|
|
263
|
+
gtd(check): implement.closing → idle
|
|
264
|
+
"""
|
|
265
|
+
And the output lines of gtd "slices" start with:
|
|
266
|
+
"""
|
|
267
|
+
refactor
|
|
268
|
+
feature
|
|
269
|
+
"""
|
|
@@ -66,6 +66,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
66
66
|
"""
|
|
67
67
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
68
68
|
"""
|
|
69
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
70
|
+
"""
|
|
71
|
+
Seam: the existing code the strays touch.
|
|
72
|
+
"""
|
|
69
73
|
And step "refactor.deriving" runs its script
|
|
70
74
|
And step "refactor.building" writes "src/calc.ts" with:
|
|
71
75
|
"""
|
|
@@ -155,6 +159,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
155
159
|
"""
|
|
156
160
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
157
161
|
"""
|
|
162
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
163
|
+
"""
|
|
164
|
+
Seam: the existing code the strays touch.
|
|
165
|
+
"""
|
|
158
166
|
And step "refactor.deriving" runs its script
|
|
159
167
|
And step "refactor.building" writes "src/calc.ts" with:
|
|
160
168
|
"""
|
|
@@ -243,6 +251,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
243
251
|
"""
|
|
244
252
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
245
253
|
"""
|
|
254
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
255
|
+
"""
|
|
256
|
+
Seam: the existing code the strays touch.
|
|
257
|
+
"""
|
|
246
258
|
And step "refactor.deriving" runs its script
|
|
247
259
|
And step "refactor.building" writes "src/calc.ts" with:
|
|
248
260
|
"""
|
|
@@ -345,6 +357,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
345
357
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
346
358
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
347
359
|
"""
|
|
360
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
361
|
+
"""
|
|
362
|
+
it("[AC-1] holds", () => {})
|
|
363
|
+
"""
|
|
348
364
|
And step "implement.health.check" changes nothing
|
|
349
365
|
And step "implement.closing" runs its script
|
|
350
366
|
And judge step "implement.coverage" answers:
|
|
@@ -638,6 +654,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
638
654
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
639
655
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
640
656
|
"""
|
|
657
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
658
|
+
"""
|
|
659
|
+
it("[AC-1] holds", () => {})
|
|
660
|
+
"""
|
|
641
661
|
And step "implement.health.check" changes nothing
|
|
642
662
|
And step "implement.closing" runs its script
|
|
643
663
|
And judge step "implement.coverage" answers:
|
|
@@ -717,6 +737,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
717
737
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
718
738
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
719
739
|
"""
|
|
740
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
741
|
+
"""
|
|
742
|
+
it("[AC-1] holds", () => {})
|
|
743
|
+
"""
|
|
720
744
|
And step "implement.health.check" changes nothing
|
|
721
745
|
And step "implement.closing" runs its script
|
|
722
746
|
And judge step "implement.coverage" answers:
|
|
@@ -983,6 +1007,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
983
1007
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
984
1008
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
985
1009
|
"""
|
|
1010
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
1011
|
+
"""
|
|
1012
|
+
it("[AC-1] holds", () => {})
|
|
1013
|
+
"""
|
|
986
1014
|
And step "implement.health.check" changes nothing
|
|
987
1015
|
And step "implement.closing" runs its script
|
|
988
1016
|
And judge step "implement.coverage" answers:
|
|
@@ -1066,6 +1094,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1066
1094
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
1067
1095
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
1068
1096
|
"""
|
|
1097
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
1098
|
+
"""
|
|
1099
|
+
it("[AC-1] holds", () => {})
|
|
1100
|
+
"""
|
|
1069
1101
|
And step "implement.health.check" changes nothing
|
|
1070
1102
|
And step "implement.closing" runs its script
|
|
1071
1103
|
And judge step "implement.coverage" answers:
|
|
@@ -1212,6 +1244,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1212
1244
|
"""
|
|
1213
1245
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
1214
1246
|
"""
|
|
1247
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
1248
|
+
"""
|
|
1249
|
+
Seam: the existing code the strays touch.
|
|
1250
|
+
"""
|
|
1215
1251
|
And step "refactor.deriving" runs its script
|
|
1216
1252
|
And step "refactor.building" writes "src/calc.ts" with:
|
|
1217
1253
|
"""
|
|
@@ -1236,7 +1272,7 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1236
1272
|
Scenario: each slice's quality lap reviews from that slice's base
|
|
1237
1273
|
When the process is driven
|
|
1238
1274
|
Then the process rests at "refactor.build.quality.correctness.reviewing"
|
|
1239
|
-
And the resting step's content contains the hash of the commit "gtd(
|
|
1275
|
+
And the resting step's content contains the hash of the commit "gtd(agent): seam.note → refactor.deriving"
|
|
1240
1276
|
Given step "refactor.build.quality.correctness.reviewing" changes nothing
|
|
1241
1277
|
And step "implement.building" writes "src/calc.ts" with:
|
|
1242
1278
|
"""
|
|
@@ -1244,6 +1280,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1244
1280
|
export const add = (a: number, b: number) => op(a, b, 1)
|
|
1245
1281
|
export const subtract = (a: number, b: number) => op(a, b, -1)
|
|
1246
1282
|
"""
|
|
1283
|
+
And step "implement.building" writes "src/acceptance.test.ts" with:
|
|
1284
|
+
"""
|
|
1285
|
+
it("[AC-1] holds", () => {})
|
|
1286
|
+
"""
|
|
1247
1287
|
And step "implement.health.check" changes nothing
|
|
1248
1288
|
And step "implement.closing" runs its script
|
|
1249
1289
|
And judge step "implement.coverage" answers:
|
|
@@ -1318,6 +1358,10 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
|
|
|
1318
1358
|
"""
|
|
1319
1359
|
[{"id":"shape","answer":"refactor-first","p":0.9}]
|
|
1320
1360
|
"""
|
|
1361
|
+
And step "seam.note" writes ".gtd/REFACTOR-NOTE.md" with:
|
|
1362
|
+
"""
|
|
1363
|
+
Seam: the existing code the strays touch.
|
|
1364
|
+
"""
|
|
1321
1365
|
|
|
1322
1366
|
Scenario: a test-file stray is dropped from the derived refactor package
|
|
1323
1367
|
Given step "seam.check" changes nothing
|
|
@@ -27,6 +27,8 @@ export const REFACTOR_PACKAGE = REFACTOR
|
|
|
27
27
|
export interface RefactorOptions {
|
|
28
28
|
/** Blank counts as absent: `kept()` reports `""` while the keeping turn is pending. */
|
|
29
29
|
readonly reference?: string | undefined
|
|
30
|
+
/** The refactor note `seam.note` wrote; rides the package as `## Refactor note`. */
|
|
31
|
+
readonly note?: string | undefined
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
const isCode = (path: string): boolean => path !== ".gtd" && !path.startsWith(".gtd/")
|
|
@@ -203,7 +205,7 @@ const packageLines = (
|
|
|
203
205
|
"",
|
|
204
206
|
]
|
|
205
207
|
|
|
206
|
-
// Nested under
|
|
208
|
+
// Nested under a `##` section (review feedback, the refactor note), so every heading drops a level.
|
|
207
209
|
const demoteHeadings = (text: string): string[] => {
|
|
208
210
|
const marked = markFenced(text.trimEnd())
|
|
209
211
|
const lines = marked.map((m) => m.line)
|
|
@@ -230,6 +232,7 @@ interface Plan {
|
|
|
230
232
|
readonly pattern: string
|
|
231
233
|
readonly strays: readonly string[]
|
|
232
234
|
readonly reference: string | undefined
|
|
235
|
+
readonly note: string | undefined
|
|
233
236
|
}
|
|
234
237
|
|
|
235
238
|
/** Undefined for every shape that is not a readable `refactor-first`; throws on a bad flag pattern. */
|
|
@@ -245,7 +248,8 @@ const plan = (shape: DiffShapeResult, options: RefactorOptions): Plan | undefine
|
|
|
245
248
|
`gtd: refactorFlagPattern (${pattern}) produces a zero-length match in:\n${listPaths(zeroLength)}`,
|
|
246
249
|
)
|
|
247
250
|
const reference = options.reference?.trim() ? options.reference : undefined
|
|
248
|
-
|
|
251
|
+
const note = options.note?.trim() ? options.note : undefined
|
|
252
|
+
return { pattern, strays, reference, note }
|
|
249
253
|
}
|
|
250
254
|
|
|
251
255
|
// The in-memory `strays`, never the package file: a hand edit of its list changes nothing.
|
|
@@ -260,11 +264,12 @@ const guardOf =
|
|
|
260
264
|
|
|
261
265
|
/** Derive, build, check and close one refactor lap; `feedback` is the collected review text of the lap before. */
|
|
262
266
|
const refactorLap = async (p: Plan, guard: Guard, feedback?: string): Promise<void> => {
|
|
263
|
-
const { pattern, strays, reference } = p
|
|
267
|
+
const { pattern, strays, reference, note } = p
|
|
264
268
|
await run(
|
|
265
269
|
"deriving",
|
|
266
270
|
deriveScript([
|
|
267
271
|
...packageLines(strays, pattern, reference),
|
|
272
|
+
...(note === undefined ? [] : ["## Refactor note", "", ...demoteHeadings(note), ""]),
|
|
268
273
|
...(feedback === undefined
|
|
269
274
|
? []
|
|
270
275
|
: ["## Review feedback", "", ...demoteHeadings(feedback), ""]),
|
|
@@ -279,6 +284,7 @@ const refactorLap = async (p: Plan, guard: Guard, feedback?: string): Promise<vo
|
|
|
279
284
|
pattern,
|
|
280
285
|
reference,
|
|
281
286
|
feedback: feedback !== undefined,
|
|
287
|
+
note: note !== undefined,
|
|
282
288
|
}),
|
|
283
289
|
{ label: "Refactoring", model: coder(), system: t.builderSystem() },
|
|
284
290
|
)
|