@pmelab/gtd 27.4.0 → 27.6.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 +17 -0
- package/dist/chunks/{Schema-CyImoHTj.mjs → Schema-DO5ttJaI.mjs} +1 -1
- package/dist/chunks/{reserved-BPdVZkgv.mjs → reserved-Df8GeSHw.mjs} +97 -8
- package/dist/chunks/{tail-iLAMoigl.mjs → tail-DmIfEAI4.mjs} +1 -1
- package/dist/flows.mjs +20 -2
- package/dist/gtd.bundle.mjs +97 -17
- package/dist/testkit.mjs +80 -18
- package/dist/workflows/cleanup.mjs +2 -2
- package/dist/workflows/feature.mjs +193 -66
- 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 +447 -114
- package/package.json +1 -1
- package/src/cli/Cli.test.ts +49 -1
- package/src/cli/Cli.ts +20 -3
- package/src/edge/Edge.test.ts +156 -1
- package/src/edge/Edge.ts +30 -7
- package/src/flags/index.test.ts +27 -1
- package/src/flags/index.ts +15 -3
- package/src/flows/helpers.ts +7 -3
- package/src/flows/runtime.test.ts +42 -0
- package/src/flows/runtime.ts +36 -0
- package/src/replay/Replay.test.ts +43 -0
- package/src/replay/Replay.ts +10 -2
- package/src/replay/Trailers.test.ts +54 -0
- package/src/replay/Trailers.ts +15 -1
- package/src/replay/judgeDiffShape.test.ts +43 -0
- package/src/step/planStart.ts +3 -2
- package/src/testkit/TestRepo.ts +3 -0
- package/src/testkit/steps.ts +18 -0
- package/src/workflow/index.ts +8 -1
- package/src/workflow/vars.test.ts +23 -1
- package/src/workflow/vars.ts +24 -0
- package/src/workflows/feature/feature.ts +11 -2
- package/src/workflows/feature/index.ts +1 -0
- package/src/workflows/feature/risk-tier.feature +301 -0
- package/src/workflows/feature/seam-pin.feature +52 -0
- package/src/workflows/feature/seam.feature +387 -0
- package/src/workflows/feature/seam.test.ts +88 -0
- package/src/workflows/feature/seam.ts +111 -0
- package/src/workflows/feature/steps.ts +3 -2
- package/src/workflows/feature/tier.test.ts +164 -0
- package/src/workflows/feature/tier.ts +74 -0
- package/src/workflows/index.ts +1 -0
- package/src/workflows/shared/options.test.ts +17 -1
- package/src/workflows/shared/options.ts +1 -0
- package/src/workflows/shared/skills.test.ts +20 -2
- package/src/workflows/shared/skills.ts +6 -0
- package/src/workflows/shared/text.test.ts +188 -0
- package/src/workflows/shared/text.ts +139 -5
- package/src/workflows/shared/vars.ts +6 -0
- package/src/workflows/shared/workflows.steps.ts +47 -1
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
@inmem
|
|
2
|
+
Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_TIER
|
|
3
|
+
|
|
4
|
+
With GTD_FLAG_NAIVE_PASS and GTD_FLAG_RISK_TIER both on, design.triage asks
|
|
5
|
+
for a risk tier and production signals, and the design gate's exit lands them
|
|
6
|
+
as Gtd-Mark trailers: one `risk-tier=<low|high>`, one `production-signal`
|
|
7
|
+
per signal. A missing or unreadable tier is high. With the flag off, nothing
|
|
8
|
+
is asked and no commit carries a Gtd-Mark.
|
|
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_NAIVE_PASS" set to "1"
|
|
14
|
+
|
|
15
|
+
Rule: with GTD_FLAG_RISK_TIER on
|
|
16
|
+
|
|
17
|
+
Background:
|
|
18
|
+
Given an environment variable "GTD_FLAG_RISK_TIER" set to "1"
|
|
19
|
+
And a file "src/calc.ts" with:
|
|
20
|
+
"""
|
|
21
|
+
export const add = (a: number, b: number) => a + b
|
|
22
|
+
"""
|
|
23
|
+
And a file "src/calc.test.ts" with:
|
|
24
|
+
"""
|
|
25
|
+
import { expect, it } from "vitest"
|
|
26
|
+
it("adds", () => expect(1 + 1).toBe(2))
|
|
27
|
+
"""
|
|
28
|
+
And the working tree is committed as "feat: add calculator"
|
|
29
|
+
And a file "TODO.md" with:
|
|
30
|
+
"""
|
|
31
|
+
# Add subtract
|
|
32
|
+
|
|
33
|
+
subtract(a, b) returns the difference.
|
|
34
|
+
"""
|
|
35
|
+
And step "unwind" changes nothing
|
|
36
|
+
And step "start-gate.check" changes nothing
|
|
37
|
+
|
|
38
|
+
Scenario: with both flags on the triage prompt asks for the tier and the signals
|
|
39
|
+
When the process is driven
|
|
40
|
+
Then the process rests at "design.triage"
|
|
41
|
+
And the resting step's content contains "## Risk Tier"
|
|
42
|
+
And the resting step's content contains "## Production Signals"
|
|
43
|
+
And the resting step's content contains "unsure means `high`"
|
|
44
|
+
|
|
45
|
+
Scenario: a low tier marks risk-tier=low on the design-exit commit
|
|
46
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
47
|
+
"""
|
|
48
|
+
# Requirements
|
|
49
|
+
|
|
50
|
+
## Risk Tier
|
|
51
|
+
|
|
52
|
+
low — trivial copy change
|
|
53
|
+
"""
|
|
54
|
+
And step "design.gate.answer" changes nothing
|
|
55
|
+
When the process is driven
|
|
56
|
+
Then the process rests at "seam.naive"
|
|
57
|
+
And the last commit subject is "gtd(human): design.gate.answer → seam.naive"
|
|
58
|
+
And the last commit body contains "Gtd-Mark: risk-tier=low"
|
|
59
|
+
|
|
60
|
+
Scenario: a high tier marks the design-exit commit
|
|
61
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
62
|
+
"""
|
|
63
|
+
# Requirements
|
|
64
|
+
|
|
65
|
+
## Risk Tier
|
|
66
|
+
|
|
67
|
+
high — touches payments
|
|
68
|
+
"""
|
|
69
|
+
And step "design.gate.answer" changes nothing
|
|
70
|
+
When the process is driven
|
|
71
|
+
Then the process rests at "seam.naive"
|
|
72
|
+
And the last commit subject is "gtd(human): design.gate.answer → seam.naive"
|
|
73
|
+
And the last commit body contains "Gtd-Mark: risk-tier=high"
|
|
74
|
+
|
|
75
|
+
Scenario Outline: a missing section or an unknown word counts as high
|
|
76
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
77
|
+
"""
|
|
78
|
+
# Requirements
|
|
79
|
+
|
|
80
|
+
<tier section>
|
|
81
|
+
## Concerns
|
|
82
|
+
|
|
83
|
+
### Subtract
|
|
84
|
+
"""
|
|
85
|
+
And step "design.gate.answer" changes nothing
|
|
86
|
+
When the process is driven
|
|
87
|
+
Then the process rests at "seam.naive"
|
|
88
|
+
And the last commit body contains "Gtd-Mark: risk-tier=high"
|
|
89
|
+
|
|
90
|
+
Examples:
|
|
91
|
+
| tier section |
|
|
92
|
+
| |
|
|
93
|
+
| ## Risk Tier\n\nmedium — hmm |
|
|
94
|
+
| ```\n## Risk Tier\n\nlow\n```\n |
|
|
95
|
+
|
|
96
|
+
Scenario Outline: signals written at triage land as marks for either tier
|
|
97
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
98
|
+
"""
|
|
99
|
+
# Requirements
|
|
100
|
+
|
|
101
|
+
## Risk Tier
|
|
102
|
+
|
|
103
|
+
<tier> — reason
|
|
104
|
+
|
|
105
|
+
## Production Signals
|
|
106
|
+
|
|
107
|
+
- error rate on /subtract stays flat
|
|
108
|
+
- p95 latency
|
|
109
|
+
"""
|
|
110
|
+
And step "design.gate.answer" changes nothing
|
|
111
|
+
When the process is driven
|
|
112
|
+
Then the process rests at "seam.naive"
|
|
113
|
+
And the last commit body contains "Gtd-Mark: production-signal=error rate on /subtract stays flat"
|
|
114
|
+
And the last commit body contains "Gtd-Mark: production-signal=p95 latency"
|
|
115
|
+
|
|
116
|
+
Examples:
|
|
117
|
+
| tier |
|
|
118
|
+
| low |
|
|
119
|
+
| high |
|
|
120
|
+
|
|
121
|
+
Scenario Outline: low and high processes produce the same commit subjects to implement.building
|
|
122
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
123
|
+
"""
|
|
124
|
+
# Requirements
|
|
125
|
+
|
|
126
|
+
## Risk Tier
|
|
127
|
+
|
|
128
|
+
<tier> — reason
|
|
129
|
+
"""
|
|
130
|
+
And step "design.gate.answer" changes nothing
|
|
131
|
+
And step "seam.naive" writes "src/calc.ts" with:
|
|
132
|
+
"""
|
|
133
|
+
export const add = (a: number, b: number) => a + b
|
|
134
|
+
export const subtract = (a: number, b: number) => a - b
|
|
135
|
+
"""
|
|
136
|
+
And judge step "seam.judge" answers:
|
|
137
|
+
"""
|
|
138
|
+
[{"id":"shape","answer":"land","p":0.9}]
|
|
139
|
+
"""
|
|
140
|
+
When the process is driven
|
|
141
|
+
Then the process rests at "implement.building"
|
|
142
|
+
And the commit subjects end with:
|
|
143
|
+
"""
|
|
144
|
+
gtd(agent): design.triage → design.gate.answer
|
|
145
|
+
gtd(human): design.gate.answer → seam.naive
|
|
146
|
+
gtd(agent): seam.naive → seam.judge
|
|
147
|
+
gtd(judge): seam.judge → implement.building
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
| tier |
|
|
152
|
+
| low |
|
|
153
|
+
| high |
|
|
154
|
+
|
|
155
|
+
Scenario Outline: the implementation prompt demands a flag for high and none for low
|
|
156
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
157
|
+
"""
|
|
158
|
+
# Requirements
|
|
159
|
+
|
|
160
|
+
## Risk Tier
|
|
161
|
+
|
|
162
|
+
<tier> — reason
|
|
163
|
+
"""
|
|
164
|
+
And step "design.gate.answer" changes nothing
|
|
165
|
+
And step "seam.naive" writes "src/calc.ts" with:
|
|
166
|
+
"""
|
|
167
|
+
export const add = (a: number, b: number) => a + b
|
|
168
|
+
export const subtract = (a: number, b: number) => a - b
|
|
169
|
+
"""
|
|
170
|
+
And judge step "seam.judge" answers:
|
|
171
|
+
"""
|
|
172
|
+
[{"id":"shape","answer":"land","p":0.9}]
|
|
173
|
+
"""
|
|
174
|
+
When the process is driven
|
|
175
|
+
Then the process rests at "implement.building"
|
|
176
|
+
And the resting step's content contains "<demand>"
|
|
177
|
+
And the resting step's content does not contain "<absent>"
|
|
178
|
+
|
|
179
|
+
Examples:
|
|
180
|
+
| tier | demand | absent |
|
|
181
|
+
| high | Put the new behaviour behind a new release flag | Add no release flag |
|
|
182
|
+
| low | Add no release flag — this change is low risk tier | new release flag |
|
|
183
|
+
|
|
184
|
+
Scenario: the tier comes from the requirements the final design gate lap accepted
|
|
185
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
186
|
+
"""
|
|
187
|
+
# Requirements
|
|
188
|
+
|
|
189
|
+
## Risk Tier
|
|
190
|
+
|
|
191
|
+
low — trivial copy change
|
|
192
|
+
"""
|
|
193
|
+
And step "seam.naive" writes "src/calc.ts" with:
|
|
194
|
+
"""
|
|
195
|
+
export const add = (a: number, b: number) => a + b
|
|
196
|
+
export const subtract = (a: number, b: number) => a - b
|
|
197
|
+
"""
|
|
198
|
+
And judge step "seam.judge" answers:
|
|
199
|
+
"""
|
|
200
|
+
[{"id":"shape","answer":"land","p":0.9}]
|
|
201
|
+
"""
|
|
202
|
+
When the process is driven
|
|
203
|
+
Then the process rests at "design.gate.answer"
|
|
204
|
+
Given a file ".gtd/REQUIREMENTS.md" with:
|
|
205
|
+
"""
|
|
206
|
+
# Requirements
|
|
207
|
+
|
|
208
|
+
## Risk Tier
|
|
209
|
+
|
|
210
|
+
high — touches payments
|
|
211
|
+
"""
|
|
212
|
+
And step "design.triage" from now on changes nothing
|
|
213
|
+
And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
214
|
+
"""
|
|
215
|
+
# Requirements
|
|
216
|
+
|
|
217
|
+
## Risk Tier
|
|
218
|
+
|
|
219
|
+
high — touches payments
|
|
220
|
+
|
|
221
|
+
## Concerns
|
|
222
|
+
|
|
223
|
+
### Subtract
|
|
224
|
+
"""
|
|
225
|
+
And step "design.gate.answer" changes nothing
|
|
226
|
+
When the process is driven
|
|
227
|
+
Then the process rests at "implement.building"
|
|
228
|
+
And the resting step's content contains "Put the new behaviour behind a new release flag"
|
|
229
|
+
And the resting step's content does not contain "Add no release flag"
|
|
230
|
+
|
|
231
|
+
Rule: with GTD_FLAG_RISK_TIER off
|
|
232
|
+
|
|
233
|
+
Background:
|
|
234
|
+
Given an environment variable "GTD_FLAG_RISK_TIER" set to "0"
|
|
235
|
+
And a file "src/calc.ts" with:
|
|
236
|
+
"""
|
|
237
|
+
export const add = (a: number, b: number) => a + b
|
|
238
|
+
"""
|
|
239
|
+
And a file "src/calc.test.ts" with:
|
|
240
|
+
"""
|
|
241
|
+
import { expect, it } from "vitest"
|
|
242
|
+
it("adds", () => expect(1 + 1).toBe(2))
|
|
243
|
+
"""
|
|
244
|
+
And the working tree is committed as "feat: add calculator"
|
|
245
|
+
And a file "TODO.md" with:
|
|
246
|
+
"""
|
|
247
|
+
# Add subtract
|
|
248
|
+
|
|
249
|
+
subtract(a, b) returns the difference.
|
|
250
|
+
"""
|
|
251
|
+
And step "unwind" changes nothing
|
|
252
|
+
And step "start-gate.check" changes nothing
|
|
253
|
+
|
|
254
|
+
Scenario: the flag-off twin asks for no tier and marks no commit
|
|
255
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
256
|
+
"""
|
|
257
|
+
# Requirements
|
|
258
|
+
|
|
259
|
+
## Risk Tier
|
|
260
|
+
|
|
261
|
+
low — trivial
|
|
262
|
+
|
|
263
|
+
## Production Signals
|
|
264
|
+
|
|
265
|
+
- error rate stays flat
|
|
266
|
+
"""
|
|
267
|
+
And step "design.gate.answer" changes nothing
|
|
268
|
+
When the process is driven
|
|
269
|
+
Then the process rests at "seam.naive"
|
|
270
|
+
And no commit body contains "Gtd-Mark"
|
|
271
|
+
|
|
272
|
+
Scenario: the flag-off twin's triage prompt has no tier section
|
|
273
|
+
When the process is driven
|
|
274
|
+
Then the process rests at "design.triage"
|
|
275
|
+
And the resting step's content does not contain "## Risk Tier"
|
|
276
|
+
And the resting step's content does not contain "## Production Signals"
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
Scenario: the flag-off twin keeps today's flag demand
|
|
280
|
+
Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
|
|
281
|
+
"""
|
|
282
|
+
# Requirements
|
|
283
|
+
|
|
284
|
+
## Risk Tier
|
|
285
|
+
|
|
286
|
+
low — trivial
|
|
287
|
+
"""
|
|
288
|
+
And step "design.gate.answer" changes nothing
|
|
289
|
+
And step "seam.naive" writes "src/calc.ts" with:
|
|
290
|
+
"""
|
|
291
|
+
export const add = (a: number, b: number) => a + b
|
|
292
|
+
export const subtract = (a: number, b: number) => a - b
|
|
293
|
+
"""
|
|
294
|
+
And judge step "seam.judge" answers:
|
|
295
|
+
"""
|
|
296
|
+
[{"id":"shape","answer":"land","p":0.9}]
|
|
297
|
+
"""
|
|
298
|
+
When the process is driven
|
|
299
|
+
Then the process rests at "implement.building"
|
|
300
|
+
And the resting step's content contains "Put the new behaviour behind a new release flag"
|
|
301
|
+
And the resting step's content does not contain "Add no release flag"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
@inmem
|
|
2
|
+
Feature: a process keeps the path it started on when GTD_FLAG_NAIVE_PASS changes
|
|
3
|
+
|
|
4
|
+
The flag is recorded in the opening commit, so flipping it mid-process never
|
|
5
|
+
moves a process between the architecture path and the naive-pass path.
|
|
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
|
+
|
|
34
|
+
Scenario: a process started with the flag off stays on architecture after the flag turns on
|
|
35
|
+
Given the ambient environment variable "GTD_FLAG_NAIVE_PASS" is "0"
|
|
36
|
+
When the process is driven
|
|
37
|
+
Then the process rests at "design.gate.answer"
|
|
38
|
+
Given the ambient environment variable "GTD_FLAG_NAIVE_PASS" is "1"
|
|
39
|
+
And step "design.gate.answer" changes nothing
|
|
40
|
+
When the process is driven
|
|
41
|
+
Then the process rests at "architecture.author"
|
|
42
|
+
And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_naive_pass=0"
|
|
43
|
+
|
|
44
|
+
Scenario: a process started with the flag on stays on the naive pass after the flag turns off
|
|
45
|
+
Given the ambient environment variable "GTD_FLAG_NAIVE_PASS" is "1"
|
|
46
|
+
When the process is driven
|
|
47
|
+
Then the process rests at "design.gate.answer"
|
|
48
|
+
Given the ambient environment variable "GTD_FLAG_NAIVE_PASS" is "0"
|
|
49
|
+
And step "design.gate.answer" changes nothing
|
|
50
|
+
When the process is driven
|
|
51
|
+
Then the process rests at "seam.naive"
|
|
52
|
+
And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_naive_pass=1"
|