@pmelab/gtd 58.1.0 → 59.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 +115 -390
- package/dist/chunks/{Schema-B3o6eRNU.mjs → testkit-CMBAAyRK.mjs} +13409 -3351
- package/dist/gtd.bundle.mjs +76 -59
- package/dist/testkit/gherkin.mjs +30 -2
- package/dist/testkit.mjs +1 -1
- package/package.json +3 -42
- package/skills/authoring/SKILL.md +31 -25
- package/src/cli/Cli.test.ts +15 -19
- package/src/cli/Cli.ts +2 -4
- package/src/cli/Program.test.ts +60 -29
- package/src/cli/Program.ts +5 -7
- package/src/edge/Edge.ts +3 -3
- package/src/flags/index.test.ts +0 -13
- package/src/flags/index.ts +1 -3
- package/src/gherkin/git-control.feature +78 -0
- package/src/gherkin/index.ts +35 -1
- package/src/install/Install.test.ts +14 -11
- package/src/install/Install.ts +38 -15
- package/src/install/index.ts +1 -2
- package/src/replay/Replay.test.ts +1 -1
- package/src/replay/index.ts +1 -1
- package/src/step/planStart.ts +6 -1
- package/src/testkit/TestRepo.test.ts +118 -2
- package/src/testkit/TestRepo.ts +57 -6
- package/src/testkit/index.ts +1 -0
- package/src/twins/EmittedScriptRecognizer.ts +12 -14
- package/src/twins/FlowScripts.ts +10 -9
- package/src/twins/InMemRepo.ts +26 -1
- package/src/twins/Layers.ts +12 -1
- package/src/twins/index.ts +6 -1
- package/src/workflow/index.ts +1 -0
- package/src/workflow/load.test.ts +138 -113
- package/src/workflow/load.ts +1 -1
- package/src/workflow/vars.test.ts +30 -3
- package/src/workflow/vars.ts +34 -2
- package/src/workflow-kit/index.ts +1 -1
- package/dist/chunks/reserved-lMYCaapY.mjs +0 -1990
- package/dist/chunks/review-Bfaror38.mjs +0 -427
- package/dist/chunks/tail-Bd7L940p.mjs +0 -355
- package/dist/chunks/testkit-D1-auYau.mjs +0 -10362
- package/dist/workflows/cleanup.mjs +0 -36
- package/dist/workflows/feature.mjs +0 -1018
- package/dist/workflows/fix.mjs +0 -41
- package/dist/workflows/review.mjs +0 -45
- package/dist/workflows/rollout.mjs +0 -48
- package/dist/workflows.mjs +0 -40651
- package/src/install/ConfigScaffold.ts +0 -22
- package/src/workflows/cleanup/cleanup-path.feature +0 -94
- package/src/workflows/cleanup/cleanup.feature +0 -315
- package/src/workflows/cleanup/cleanup.test.ts +0 -276
- package/src/workflows/cleanup/cleanup.ts +0 -52
- package/src/workflows/cleanup/index.ts +0 -6
- package/src/workflows/feature/acceptance-criteria-tier.feature +0 -25
- package/src/workflows/feature/acceptance-criteria.feature +0 -389
- package/src/workflows/feature/criteria-coverage.feature +0 -102
- package/src/workflows/feature/criteria.test.ts +0 -147
- package/src/workflows/feature/criteria.ts +0 -267
- package/src/workflows/feature/fast-path.feature +0 -93
- package/src/workflows/feature/feature.test.ts +0 -338
- package/src/workflows/feature/feature.ts +0 -156
- package/src/workflows/feature/green.ts +0 -19
- package/src/workflows/feature/index.ts +0 -18
- package/src/workflows/feature/lens-models.feature +0 -69
- package/src/workflows/feature/lens-review.feature +0 -566
- package/src/workflows/feature/naive-acceptance.feature +0 -147
- package/src/workflows/feature/naive-test.feature +0 -263
- package/src/workflows/feature/one-step-land.feature +0 -93
- package/src/workflows/feature/planning.ts +0 -41
- package/src/workflows/feature/refactor-absorbs.feature +0 -131
- package/src/workflows/feature/refactor-first.feature +0 -158
- package/src/workflows/feature/refactor-lens-models.feature +0 -79
- package/src/workflows/feature/refactor-rebuild.feature +0 -273
- package/src/workflows/feature/refactor-review.feature +0 -1528
- package/src/workflows/feature/refactor.test.ts +0 -1220
- package/src/workflows/feature/refactor.ts +0 -368
- package/src/workflows/feature/release-flag.feature +0 -167
- package/src/workflows/feature/release-flag.test.ts +0 -49
- package/src/workflows/feature/release-flag.ts +0 -46
- package/src/workflows/feature/review-gate.feature +0 -241
- package/src/workflows/feature/reviewer-walkthrough.feature +0 -142
- package/src/workflows/feature/risk-tier.feature +0 -351
- package/src/workflows/feature/seam-rejection.feature +0 -146
- package/src/workflows/feature/seam.feature +0 -297
- package/src/workflows/feature/seam.test.ts +0 -527
- package/src/workflows/feature/seam.ts +0 -426
- package/src/workflows/feature/standards.feature +0 -354
- package/src/workflows/feature/steps.test.ts +0 -65
- package/src/workflows/feature/steps.ts +0 -45
- package/src/workflows/feature/tier-pin.feature +0 -66
- package/src/workflows/feature/tier.test.ts +0 -166
- package/src/workflows/feature/tier.ts +0 -56
- package/src/workflows/fix/fix-lens-origin.feature +0 -114
- package/src/workflows/fix/fix-quality.feature +0 -212
- package/src/workflows/fix/fix.feature +0 -79
- package/src/workflows/fix/fix.test.ts +0 -74
- package/src/workflows/fix/fix.ts +0 -52
- package/src/workflows/fix/index.ts +0 -6
- package/src/workflows/index.ts +0 -47
- package/src/workflows/review/index.ts +0 -6
- package/src/workflows/review/review-door.feature +0 -199
- package/src/workflows/review/review.test.ts +0 -27
- package/src/workflows/review/review.ts +0 -60
- package/src/workflows/rollout/index.ts +0 -6
- package/src/workflows/rollout/rollout.feature +0 -510
- package/src/workflows/rollout/rollout.test.ts +0 -263
- package/src/workflows/rollout/rollout.ts +0 -82
- package/src/workflows/shared/__fixtures__/feature-collecting-prompt.txt +0 -98
- package/src/workflows/shared/access.test.ts +0 -62
- package/src/workflows/shared/access.ts +0 -24
- package/src/workflows/shared/config.fixture.ts +0 -12
- package/src/workflows/shared/fences.ts +0 -24
- package/src/workflows/shared/health.test.ts +0 -148
- package/src/workflows/shared/health.ts +0 -191
- package/src/workflows/shared/learn.test.ts +0 -140
- package/src/workflows/shared/learn.ts +0 -201
- package/src/workflows/shared/lenses.test.ts +0 -39
- package/src/workflows/shared/lenses.ts +0 -294
- package/src/workflows/shared/options.test.ts +0 -157
- package/src/workflows/shared/options.ts +0 -92
- package/src/workflows/shared/progress.feature +0 -124
- package/src/workflows/shared/prose.ts +0 -263
- package/src/workflows/shared/recheck.feature +0 -60
- package/src/workflows/shared/registry.test.ts +0 -345
- package/src/workflows/shared/registry.ts +0 -183
- package/src/workflows/shared/reserved.ts +0 -11
- package/src/workflows/shared/review.test.ts +0 -1062
- package/src/workflows/shared/review.ts +0 -446
- package/src/workflows/shared/skills.test.ts +0 -121
- package/src/workflows/shared/skills.ts +0 -49
- package/src/workflows/shared/standards.test.ts +0 -90
- package/src/workflows/shared/standards.ts +0 -156
- package/src/workflows/shared/steps.test.ts +0 -219
- package/src/workflows/shared/steps.ts +0 -201
- package/src/workflows/shared/tail.test.ts +0 -454
- package/src/workflows/shared/tail.ts +0 -264
- package/src/workflows/shared/text.fixture.ts +0 -128
- package/src/workflows/shared/text.test.ts +0 -1430
- package/src/workflows/shared/text.ts +0 -1700
- package/src/workflows/shared/threads.test.ts +0 -129
- package/src/workflows/shared/vars.ts +0 -47
- package/src/workflows/shared/workflows.steps.ts +0 -54
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
@inmem
|
|
2
|
-
Feature: the review learns standards from the human's answers
|
|
3
|
-
|
|
4
|
-
A won't-fix tick or an own answer at the review gate — on a note the human
|
|
5
|
-
added with its own answer boxes — is a candidate standard. A judge asks whether it is reusable; above `standardMinP` it is
|
|
6
|
-
kept in `.gtd/STANDARDS.md` with no further question, and every later agent
|
|
7
|
-
turn — lenses and coder alike — is told to follow it. One that contradicts
|
|
8
|
-
a standard already kept becomes a note in `.gtd/REVIEW.md` the review cannot
|
|
9
|
-
sign off without: keep the new one, keep the old one, or write the merged
|
|
10
|
-
wording.
|
|
11
|
-
|
|
12
|
-
Background:
|
|
13
|
-
Given the shipped workflows, as gtd install scaffolds them
|
|
14
|
-
And an environment variable "GTD_QUALITYREVIEWS" set to ""
|
|
15
|
-
And a file "src/calc.ts" with:
|
|
16
|
-
"""
|
|
17
|
-
export const add = (a: number, b: number) => a + b
|
|
18
|
-
"""
|
|
19
|
-
And the working tree is committed as "feat: add calculator"
|
|
20
|
-
And a file "TODO.md" with:
|
|
21
|
-
"""
|
|
22
|
-
# Add subtract
|
|
23
|
-
|
|
24
|
-
subtract(a, b) returns the difference.
|
|
25
|
-
"""
|
|
26
|
-
And step "unwind" changes nothing
|
|
27
|
-
And step "start-gate.check" changes nothing
|
|
28
|
-
And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
29
|
-
"""
|
|
30
|
-
# Requirements
|
|
31
|
-
|
|
32
|
-
## Concerns
|
|
33
|
-
|
|
34
|
-
### Subtract
|
|
35
|
-
|
|
36
|
-
- `subtract(a, b)` returns `a - b`.
|
|
37
|
-
|
|
38
|
-
## Impact
|
|
39
|
-
|
|
40
|
-
- the greeting module
|
|
41
|
-
|
|
42
|
-
## Acceptance Criteria
|
|
43
|
-
|
|
44
|
-
- AC-1: subtract(a, b) returns a - b.
|
|
45
|
-
"""
|
|
46
|
-
And step "design.gate.answer" changes nothing
|
|
47
|
-
And step "seam.naive" writes "src/calc.test.ts" with:
|
|
48
|
-
"""
|
|
49
|
-
it("[AC-1] subtracts", () => {})
|
|
50
|
-
"""
|
|
51
|
-
And step "seam.naive" writes "src/calc.ts" with:
|
|
52
|
-
"""
|
|
53
|
-
export const add = (a: number, b: number) => a + b
|
|
54
|
-
export const subtract = (a: number, b: number) => a - b
|
|
55
|
-
"""
|
|
56
|
-
And step "seam.check" changes nothing
|
|
57
|
-
And step "implement.applying" runs its script
|
|
58
|
-
And step "implement.health.check" changes nothing
|
|
59
|
-
And step "implement.closing" runs its script
|
|
60
|
-
And step "build.review.reviewing" writes ".gtd/REVIEW.md" with:
|
|
61
|
-
"""
|
|
62
|
-
# Review: abc1234
|
|
63
|
-
|
|
64
|
-
<!-- base: 0000000 -->
|
|
65
|
-
|
|
66
|
-
## Subtract
|
|
67
|
-
|
|
68
|
-
- [ ] ./src/calc.ts#2-2 — subtract(a, b)
|
|
69
|
-
"""
|
|
70
|
-
And step "build.review.carrying" runs its script
|
|
71
|
-
And step "build.review.closing" runs its script
|
|
72
|
-
And step "build.review.standards.recording" runs its script
|
|
73
|
-
And step "build.review.standards.raising" runs its script
|
|
74
|
-
|
|
75
|
-
Scenario: a won't-fix the judge calls reusable is kept, and the review signs off
|
|
76
|
-
Given judge step "build.review.standards.judge" answers:
|
|
77
|
-
"""
|
|
78
|
-
[{"id":"standard-1","answer":"yes","p":0.9}]
|
|
79
|
-
"""
|
|
80
|
-
When the process is driven
|
|
81
|
-
And ".gtd/REVIEW.md" gets appended:
|
|
82
|
-
"""
|
|
83
|
-
## subtract has no class
|
|
84
|
-
|
|
85
|
-
Calculators read better as classes.
|
|
86
|
-
|
|
87
|
-
Tick exactly one:
|
|
88
|
-
|
|
89
|
-
- [ ] fix as suggested
|
|
90
|
-
- [ ] won't fix
|
|
91
|
-
- [ ] _your answer_
|
|
92
|
-
"""
|
|
93
|
-
And the text "- [ ] won't fix" in ".gtd/REVIEW.md" is replaced with "- [x] won't fix"
|
|
94
|
-
And gtd lands
|
|
95
|
-
And the process is driven
|
|
96
|
-
Then the process rests at "idle"
|
|
97
|
-
And ".gtd/STANDARDS.md" contains:
|
|
98
|
-
"""
|
|
99
|
-
- Won't fix: subtract has no class — Calculators read better as classes.
|
|
100
|
-
"""
|
|
101
|
-
And the commit subjects end with:
|
|
102
|
-
"""
|
|
103
|
-
gtd(human): build.review.await-review → build.review.standards.judge
|
|
104
|
-
gtd(judge): build.review.standards.judge → build.review.standards.recording
|
|
105
|
-
gtd(check): build.review.standards.recording → build.review.closing
|
|
106
|
-
gtd(check): build.review.closing → idle
|
|
107
|
-
"""
|
|
108
|
-
|
|
109
|
-
Scenario: the next review lists the standards added
|
|
110
|
-
Given judge step "build.review.standards.judge" answers:
|
|
111
|
-
"""
|
|
112
|
-
[{"id":"standard-1","answer":"yes","p":0.9}]
|
|
113
|
-
"""
|
|
114
|
-
And judge step "build.review.triage" answers:
|
|
115
|
-
"""
|
|
116
|
-
[{"id":"answer-1","answer":"nit","p":0.9}]
|
|
117
|
-
"""
|
|
118
|
-
And step "build.review.fix.nits.fixing" writes "src/calc.ts" with:
|
|
119
|
-
"""
|
|
120
|
-
export function add(a: number, b: number) { return a + b }
|
|
121
|
-
export function subtract(a: number, b: number) { return a - b }
|
|
122
|
-
"""
|
|
123
|
-
And step "build.health.check" changes nothing
|
|
124
|
-
When the process is driven
|
|
125
|
-
And ".gtd/REVIEW.md" gets appended:
|
|
126
|
-
"""
|
|
127
|
-
## subtract has no class
|
|
128
|
-
|
|
129
|
-
Calculators read better as classes.
|
|
130
|
-
|
|
131
|
-
Tick exactly one:
|
|
132
|
-
|
|
133
|
-
- [ ] fix as suggested
|
|
134
|
-
- [ ] won't fix
|
|
135
|
-
- [ ] _your answer_
|
|
136
|
-
"""
|
|
137
|
-
And the text "- [ ] _your answer_" in ".gtd/REVIEW.md" is replaced with "- [x] Calculators are plain functions."
|
|
138
|
-
And gtd lands
|
|
139
|
-
And the process is driven
|
|
140
|
-
Then the process rests at "build.review.await-review"
|
|
141
|
-
And ".gtd/REVIEW.md" contains:
|
|
142
|
-
"""
|
|
143
|
-
## Standards added
|
|
144
|
-
|
|
145
|
-
Learned from your answers and kept in `.gtd/STANDARDS.md`:
|
|
146
|
-
|
|
147
|
-
- Calculators are plain functions. (re: subtract has no class)
|
|
148
|
-
"""
|
|
149
|
-
|
|
150
|
-
Scenario: an answer below the threshold is not kept
|
|
151
|
-
Given judge step "build.review.standards.judge" answers:
|
|
152
|
-
"""
|
|
153
|
-
[{"id":"standard-1","answer":"yes","p":0.6}]
|
|
154
|
-
"""
|
|
155
|
-
When the process is driven
|
|
156
|
-
And ".gtd/REVIEW.md" gets appended:
|
|
157
|
-
"""
|
|
158
|
-
## subtract has no class
|
|
159
|
-
|
|
160
|
-
Calculators read better as classes.
|
|
161
|
-
|
|
162
|
-
Tick exactly one:
|
|
163
|
-
|
|
164
|
-
- [ ] fix as suggested
|
|
165
|
-
- [ ] won't fix
|
|
166
|
-
- [ ] _your answer_
|
|
167
|
-
"""
|
|
168
|
-
And the text "- [ ] won't fix" in ".gtd/REVIEW.md" is replaced with "- [x] won't fix"
|
|
169
|
-
And gtd lands
|
|
170
|
-
And the process is driven
|
|
171
|
-
Then the process rests at "idle"
|
|
172
|
-
And ".gtd/STANDARDS.md" does not exist
|
|
173
|
-
|
|
174
|
-
Scenario: a kept standard reaches the lenses and the coder of a later process
|
|
175
|
-
Given a file ".gtd/STANDARDS.md" with:
|
|
176
|
-
"""
|
|
177
|
-
# Standards
|
|
178
|
-
|
|
179
|
-
- Won't fix: subtract has no class — Calculators read better as classes.
|
|
180
|
-
"""
|
|
181
|
-
And the working tree is committed as "chore: keep a standard"
|
|
182
|
-
And a file "TODO.md" with:
|
|
183
|
-
"""
|
|
184
|
-
# Add subtract
|
|
185
|
-
|
|
186
|
-
Please add subtract(a, b).
|
|
187
|
-
"""
|
|
188
|
-
And step "seam.naive" is prompted with "- Won't fix: subtract has no class"
|
|
189
|
-
And step "build.quality.correctness.reviewing" is prompted with "- Won't fix: subtract has no class"
|
|
190
|
-
When the process is driven
|
|
191
|
-
Then the process rests at "build.review.await-review"
|
|
192
|
-
|
|
193
|
-
Scenario: a contradicting standard blocks sign-off until the human picks one
|
|
194
|
-
Given a file ".gtd/STANDARDS.md" with:
|
|
195
|
-
"""
|
|
196
|
-
# Standards
|
|
197
|
-
|
|
198
|
-
- Calculators are classes.
|
|
199
|
-
"""
|
|
200
|
-
And the working tree is committed as "chore: keep a standard"
|
|
201
|
-
And a file "TODO.md" with:
|
|
202
|
-
"""
|
|
203
|
-
# Add subtract
|
|
204
|
-
|
|
205
|
-
Please add subtract(a, b).
|
|
206
|
-
"""
|
|
207
|
-
And judge step "build.review.standards.judge" answers:
|
|
208
|
-
"""
|
|
209
|
-
[{"id":"standard-1","answer":"yes","p":0.9},{"id":"standard-1.contradicts-1","answer":"yes","p":0.8}]
|
|
210
|
-
"""
|
|
211
|
-
And judge step "build.review.triage" answers:
|
|
212
|
-
"""
|
|
213
|
-
[{"id":"answer-1","answer":"praise","p":0.9}]
|
|
214
|
-
"""
|
|
215
|
-
When the process is driven
|
|
216
|
-
And ".gtd/REVIEW.md" gets appended:
|
|
217
|
-
"""
|
|
218
|
-
## subtract has no class
|
|
219
|
-
|
|
220
|
-
Calculators read better as classes.
|
|
221
|
-
|
|
222
|
-
Tick exactly one:
|
|
223
|
-
|
|
224
|
-
- [ ] fix as suggested
|
|
225
|
-
- [ ] won't fix
|
|
226
|
-
- [ ] _your answer_
|
|
227
|
-
"""
|
|
228
|
-
And the text "- [ ] _your answer_" in ".gtd/REVIEW.md" is replaced with "- [x] Calculators are plain functions."
|
|
229
|
-
And gtd lands
|
|
230
|
-
And the process is driven
|
|
231
|
-
Then the process rests at "build.review.await-review"
|
|
232
|
-
And ".gtd/STANDARDS.md" contains:
|
|
233
|
-
"""
|
|
234
|
-
- Calculators are classes.
|
|
235
|
-
|
|
236
|
-
## Undecided
|
|
237
|
-
|
|
238
|
-
- Calculators are plain functions. (re: subtract has no class)
|
|
239
|
-
- contradicts: Calculators are classes.
|
|
240
|
-
"""
|
|
241
|
-
And ".gtd/REVIEW.md" contains "## Standard conflict "
|
|
242
|
-
And ".gtd/REVIEW.md" contains:
|
|
243
|
-
"""
|
|
244
|
-
New: Calculators are plain functions. (re: subtract has no class)
|
|
245
|
-
|
|
246
|
-
Old:
|
|
247
|
-
|
|
248
|
-
- Calculators are classes.
|
|
249
|
-
|
|
250
|
-
Tick exactly one:
|
|
251
|
-
|
|
252
|
-
- [ ] keep the new one (drop the old)
|
|
253
|
-
- [ ] keep the old one (discard the new)
|
|
254
|
-
- [ ] _your answer_
|
|
255
|
-
"""
|
|
256
|
-
And ".gtd/REVIEW.md" does not contain "## subtract has no class"
|
|
257
|
-
And landing is refused with "answer-completeness: 1 note(s) in .gtd/REVIEW.md not answered"
|
|
258
|
-
When the text "- [ ] keep the new one (drop the old)" in ".gtd/REVIEW.md" is replaced with "- [x] keep the new one (drop the old)"
|
|
259
|
-
And gtd lands
|
|
260
|
-
And the process is driven
|
|
261
|
-
Then the process rests at "idle"
|
|
262
|
-
And ".gtd/STANDARDS.md" contains "- Calculators are plain functions. (re: subtract has no class)"
|
|
263
|
-
And ".gtd/STANDARDS.md" does not contain "Calculators are classes."
|
|
264
|
-
And ".gtd/STANDARDS.md" does not contain "Undecided"
|
|
265
|
-
|
|
266
|
-
Scenario: keeping the old standard discards the new one
|
|
267
|
-
Given a file ".gtd/STANDARDS.md" with:
|
|
268
|
-
"""
|
|
269
|
-
# Standards
|
|
270
|
-
|
|
271
|
-
- Calculators are classes.
|
|
272
|
-
"""
|
|
273
|
-
And the working tree is committed as "chore: keep a standard"
|
|
274
|
-
And a file "TODO.md" with:
|
|
275
|
-
"""
|
|
276
|
-
# Add subtract
|
|
277
|
-
|
|
278
|
-
Please add subtract(a, b).
|
|
279
|
-
"""
|
|
280
|
-
And judge step "build.review.standards.judge" answers:
|
|
281
|
-
"""
|
|
282
|
-
[{"id":"standard-1","answer":"yes","p":0.9},{"id":"standard-1.contradicts-1","answer":"yes","p":0.8}]
|
|
283
|
-
"""
|
|
284
|
-
When the process is driven
|
|
285
|
-
And ".gtd/REVIEW.md" gets appended:
|
|
286
|
-
"""
|
|
287
|
-
## subtract has no class
|
|
288
|
-
|
|
289
|
-
Calculators read better as classes.
|
|
290
|
-
|
|
291
|
-
Tick exactly one:
|
|
292
|
-
|
|
293
|
-
- [ ] fix as suggested
|
|
294
|
-
- [ ] won't fix
|
|
295
|
-
- [ ] _your answer_
|
|
296
|
-
"""
|
|
297
|
-
And the text "- [ ] won't fix" in ".gtd/REVIEW.md" is replaced with "- [x] won't fix"
|
|
298
|
-
And gtd lands
|
|
299
|
-
And the process is driven
|
|
300
|
-
And the text "- [ ] keep the old one (discard the new)" in ".gtd/REVIEW.md" is replaced with "- [x] keep the old one (discard the new)"
|
|
301
|
-
And gtd lands
|
|
302
|
-
And the process is driven
|
|
303
|
-
Then the process rests at "idle"
|
|
304
|
-
And ".gtd/STANDARDS.md" contains:
|
|
305
|
-
"""
|
|
306
|
-
# Standards
|
|
307
|
-
|
|
308
|
-
Kept from your review answers for every agent turn. One standard per bullet.
|
|
309
|
-
|
|
310
|
-
- Calculators are classes.
|
|
311
|
-
"""
|
|
312
|
-
And ".gtd/STANDARDS.md" does not contain "Won't fix"
|
|
313
|
-
|
|
314
|
-
Scenario: an own answer to a conflict replaces both with its wording
|
|
315
|
-
Given a file ".gtd/STANDARDS.md" with:
|
|
316
|
-
"""
|
|
317
|
-
# Standards
|
|
318
|
-
|
|
319
|
-
- Calculators are classes.
|
|
320
|
-
"""
|
|
321
|
-
And the working tree is committed as "chore: keep a standard"
|
|
322
|
-
And a file "TODO.md" with:
|
|
323
|
-
"""
|
|
324
|
-
# Add subtract
|
|
325
|
-
|
|
326
|
-
Please add subtract(a, b).
|
|
327
|
-
"""
|
|
328
|
-
And judge step "build.review.standards.judge" answers:
|
|
329
|
-
"""
|
|
330
|
-
[{"id":"standard-1","answer":"yes","p":0.9},{"id":"standard-1.contradicts-1","answer":"yes","p":0.8}]
|
|
331
|
-
"""
|
|
332
|
-
When the process is driven
|
|
333
|
-
And ".gtd/REVIEW.md" gets appended:
|
|
334
|
-
"""
|
|
335
|
-
## subtract has no class
|
|
336
|
-
|
|
337
|
-
Calculators read better as classes.
|
|
338
|
-
|
|
339
|
-
Tick exactly one:
|
|
340
|
-
|
|
341
|
-
- [ ] fix as suggested
|
|
342
|
-
- [ ] won't fix
|
|
343
|
-
- [ ] _your answer_
|
|
344
|
-
"""
|
|
345
|
-
And the text "- [ ] won't fix" in ".gtd/REVIEW.md" is replaced with "- [x] won't fix"
|
|
346
|
-
And gtd lands
|
|
347
|
-
And the process is driven
|
|
348
|
-
And the text "- [ ] _your answer_" in ".gtd/REVIEW.md" is replaced with "- [x] Calculators with state are classes."
|
|
349
|
-
And gtd lands
|
|
350
|
-
And the process is driven
|
|
351
|
-
Then the process rests at "idle"
|
|
352
|
-
And ".gtd/STANDARDS.md" contains "- Calculators with state are classes."
|
|
353
|
-
And ".gtd/STANDARDS.md" does not contain "- Calculators are classes."
|
|
354
|
-
And ".gtd/STANDARDS.md" does not contain "Won't fix"
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs"
|
|
2
|
-
import { describe, expect, it } from "vitest"
|
|
3
|
-
import type { StepRequest } from "../../flows/index.js"
|
|
4
|
-
import { captureStep } from "../shared/text.fixture.js"
|
|
5
|
-
import * as steps from "./steps.js"
|
|
6
|
-
|
|
7
|
-
const capture = (
|
|
8
|
-
fn: () => Promise<void>,
|
|
9
|
-
scope: string,
|
|
10
|
-
skills?: Readonly<Record<string, readonly string[]>>,
|
|
11
|
-
): Promise<StepRequest> => captureStep(fn, { scope, ...(skills !== undefined ? { skills } : {}) })
|
|
12
|
-
|
|
13
|
-
const agentPrompt = (request: StepRequest): string => {
|
|
14
|
-
if (request.kind !== "agent") throw new Error(`expected an agent step, got ${request.kind}`)
|
|
15
|
-
return request.prompt
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
describe("the feature workflow's own steps declare skills — a step's rendered prompt carries its bundled skills.ts preamble", () => {
|
|
19
|
-
it("triage carries design.triage's bundled skills", async () => {
|
|
20
|
-
const prompt = agentPrompt(await capture(() => steps.triage("base"), "design"))
|
|
21
|
-
expect(prompt).toContain("spec-driven-development, planning-and-task-breakdown")
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it("collecting carries build.review.collecting's bundled skills", async () => {
|
|
25
|
-
const prompt = agentPrompt(await capture(() => steps.collecting("capture"), "build"))
|
|
26
|
-
expect(prompt).toContain("code-review-and-quality")
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it("collecting's prompt is the pinned feature fixture", async () => {
|
|
30
|
-
const prompt = agentPrompt(await capture(() => steps.collecting("capture-text"), "build"))
|
|
31
|
-
expect(prompt).toContain(
|
|
32
|
-
readFileSync(
|
|
33
|
-
new URL("../shared/__fixtures__/feature-collecting-prompt.txt", import.meta.url),
|
|
34
|
-
"utf8",
|
|
35
|
-
),
|
|
36
|
-
)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it("refactorCollecting renders the open variant for the reply round, the closed one otherwise, whatever .gtd/REVIEW.md holds", async () => {
|
|
40
|
-
const at = (round: "reply" | "edits", present: boolean): Promise<StepRequest> =>
|
|
41
|
-
captureStep(() => steps.refactorCollecting("capture", round, ["src/a.ts"]), {
|
|
42
|
-
scope: "refactor.build",
|
|
43
|
-
read: (path) => (present && path === ".gtd/REVIEW.md" ? "# Review" : undefined),
|
|
44
|
-
})
|
|
45
|
-
const open = agentPrompt(await at("reply", false))
|
|
46
|
-
const closed = agentPrompt(await at("edits", true))
|
|
47
|
-
expect(open).toContain("exactly one `- A:` reply")
|
|
48
|
-
expect(open).not.toContain("already closed")
|
|
49
|
-
expect(closed).toContain("already closed")
|
|
50
|
-
expect(closed).not.toContain("exactly one `- A:` reply")
|
|
51
|
-
})
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
describe("the feature workflow's planning steps run on the planner model", () => {
|
|
55
|
-
it("design triage defaults to smart and follows plannerModel", async () => {
|
|
56
|
-
const plain = await captureStep(() => steps.triage("base"), { scope: "design" })
|
|
57
|
-
const set = await captureStep(() => steps.triage("base"), {
|
|
58
|
-
scope: "design",
|
|
59
|
-
env: { plannerModel: "opus" },
|
|
60
|
-
})
|
|
61
|
-
if (plain.kind !== "agent" || set.kind !== "agent") throw new Error("unreachable")
|
|
62
|
-
expect(plain.options.model).toBe("smart")
|
|
63
|
-
expect(set.options.model).toBe("opus")
|
|
64
|
-
})
|
|
65
|
-
})
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { human } from "../../flows/index.js"
|
|
2
|
-
import type { CollectRound } from "../../workflow-kit/index.js"
|
|
3
|
-
import * as t from "../shared/text.js"
|
|
4
|
-
import { riskTierOn } from "./tier.js"
|
|
5
|
-
import { planner, REFACTOR, REQUIREMENTS } from "../shared/steps.js"
|
|
6
|
-
|
|
7
|
-
// Kept on the published feature entry.
|
|
8
|
-
export { answerReviewQuestions, collecting, fixNits } from "../shared/steps.js"
|
|
9
|
-
|
|
10
|
-
/** Turn the sketch since `base` into `.gtd/REQUIREMENTS.md`. */
|
|
11
|
-
export const triage = (base: string): Promise<void> =>
|
|
12
|
-
t.agentWithSkills("triage", t.designTriagePrompt(base, riskTierOn()), {
|
|
13
|
-
label: "Triaging the change",
|
|
14
|
-
file: REQUIREMENTS,
|
|
15
|
-
mode: "qa",
|
|
16
|
-
model: planner(),
|
|
17
|
-
system: t.designSystem(),
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
export const answerProductQuestions = (): Promise<void> =>
|
|
21
|
-
human("gate.answer", {
|
|
22
|
-
message: t.designGateAnswerMessage(riskTierOn()),
|
|
23
|
-
label: "Awaiting your product answers",
|
|
24
|
-
file: REQUIREMENTS,
|
|
25
|
-
mode: "qa",
|
|
26
|
-
acceptClean: true,
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
/** Turn the refactor review round `capture` describes into `.gtd/REFACTOR.md`, or change nothing. */
|
|
30
|
-
export const refactorCollecting = (
|
|
31
|
-
capture: string,
|
|
32
|
-
round: CollectRound,
|
|
33
|
-
strays: readonly string[],
|
|
34
|
-
): Promise<void> =>
|
|
35
|
-
t.agentWithSkills(
|
|
36
|
-
"review.collecting",
|
|
37
|
-
t.buildReviewCollectingPrompt(capture, { strays, round }),
|
|
38
|
-
{
|
|
39
|
-
label: "Collecting your refactor feedback",
|
|
40
|
-
file: REFACTOR,
|
|
41
|
-
model: planner(),
|
|
42
|
-
system: t.reviewerSystem(),
|
|
43
|
-
allowEmpty: true,
|
|
44
|
-
},
|
|
45
|
-
)
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
@inmem
|
|
2
|
-
Feature: a process keeps the risk tier setting it started with when GTD_FLAG_RISK_TIER changes
|
|
3
|
-
|
|
4
|
-
The flag is recorded in the opening commit, so flipping it mid-process never
|
|
5
|
-
changes whether the process asks for and records a risk tier.
|
|
6
|
-
|
|
7
|
-
Background:
|
|
8
|
-
Given the shipped workflows, as gtd install scaffolds them
|
|
9
|
-
And an environment variable "GTD_QUALITYREVIEWS" set to ""
|
|
10
|
-
And a file "src/calc.ts" with:
|
|
11
|
-
"""
|
|
12
|
-
export const add = (a: number, b: number) => a + b
|
|
13
|
-
"""
|
|
14
|
-
And the working tree is committed as "feat: add calculator"
|
|
15
|
-
And a file "TODO.md" with:
|
|
16
|
-
"""
|
|
17
|
-
# Add subtract
|
|
18
|
-
|
|
19
|
-
subtract(a, b) returns the difference.
|
|
20
|
-
"""
|
|
21
|
-
And step "unwind" changes nothing
|
|
22
|
-
And step "start-gate.check" changes nothing
|
|
23
|
-
And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
24
|
-
"""
|
|
25
|
-
# Requirements
|
|
26
|
-
|
|
27
|
-
## Concerns
|
|
28
|
-
|
|
29
|
-
### Subtract
|
|
30
|
-
|
|
31
|
-
- `subtract(a, b)` returns `a - b`.
|
|
32
|
-
|
|
33
|
-
## Risk Tier
|
|
34
|
-
|
|
35
|
-
low — a new pure function
|
|
36
|
-
|
|
37
|
-
## Impact
|
|
38
|
-
|
|
39
|
-
- the greeting module
|
|
40
|
-
|
|
41
|
-
## Acceptance Criteria
|
|
42
|
-
|
|
43
|
-
- AC-1: the change behaves as described.
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
Scenario: a process started with the flag off records no tier after the flag turns on
|
|
47
|
-
Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "0"
|
|
48
|
-
When the process is driven
|
|
49
|
-
Then the process rests at "design.gate.answer"
|
|
50
|
-
Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "1"
|
|
51
|
-
And step "design.gate.answer" changes nothing
|
|
52
|
-
When the process is driven
|
|
53
|
-
Then the process rests at "seam.naive"
|
|
54
|
-
And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
|
|
55
|
-
And no commit body contains "Gtd-Mark:"
|
|
56
|
-
|
|
57
|
-
Scenario: a process started with the flag on records its tier after the flag turns off
|
|
58
|
-
Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "1"
|
|
59
|
-
When the process is driven
|
|
60
|
-
Then the process rests at "design.gate.answer"
|
|
61
|
-
Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "0"
|
|
62
|
-
And step "design.gate.answer" changes nothing
|
|
63
|
-
When the process is driven
|
|
64
|
-
Then the process rests at "seam.naive"
|
|
65
|
-
And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=1"
|
|
66
|
-
And the last commit body contains "Gtd-Mark: risk-tier=low"
|