@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.
Files changed (54) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +17 -0
  3. package/dist/chunks/{Schema-CyImoHTj.mjs → Schema-DO5ttJaI.mjs} +1 -1
  4. package/dist/chunks/{reserved-BPdVZkgv.mjs → reserved-Df8GeSHw.mjs} +97 -8
  5. package/dist/chunks/{tail-iLAMoigl.mjs → tail-DmIfEAI4.mjs} +1 -1
  6. package/dist/flows.mjs +20 -2
  7. package/dist/gtd.bundle.mjs +97 -17
  8. package/dist/testkit.mjs +80 -18
  9. package/dist/workflows/cleanup.mjs +2 -2
  10. package/dist/workflows/feature.mjs +193 -66
  11. package/dist/workflows/fix.mjs +2 -2
  12. package/dist/workflows/review.mjs +2 -2
  13. package/dist/workflows/rollout.mjs +1 -1
  14. package/dist/workflows.mjs +447 -114
  15. package/package.json +1 -1
  16. package/src/cli/Cli.test.ts +49 -1
  17. package/src/cli/Cli.ts +20 -3
  18. package/src/edge/Edge.test.ts +156 -1
  19. package/src/edge/Edge.ts +30 -7
  20. package/src/flags/index.test.ts +27 -1
  21. package/src/flags/index.ts +15 -3
  22. package/src/flows/helpers.ts +7 -3
  23. package/src/flows/runtime.test.ts +42 -0
  24. package/src/flows/runtime.ts +36 -0
  25. package/src/replay/Replay.test.ts +43 -0
  26. package/src/replay/Replay.ts +10 -2
  27. package/src/replay/Trailers.test.ts +54 -0
  28. package/src/replay/Trailers.ts +15 -1
  29. package/src/replay/judgeDiffShape.test.ts +43 -0
  30. package/src/step/planStart.ts +3 -2
  31. package/src/testkit/TestRepo.ts +3 -0
  32. package/src/testkit/steps.ts +18 -0
  33. package/src/workflow/index.ts +8 -1
  34. package/src/workflow/vars.test.ts +23 -1
  35. package/src/workflow/vars.ts +24 -0
  36. package/src/workflows/feature/feature.ts +11 -2
  37. package/src/workflows/feature/index.ts +1 -0
  38. package/src/workflows/feature/risk-tier.feature +301 -0
  39. package/src/workflows/feature/seam-pin.feature +52 -0
  40. package/src/workflows/feature/seam.feature +387 -0
  41. package/src/workflows/feature/seam.test.ts +88 -0
  42. package/src/workflows/feature/seam.ts +111 -0
  43. package/src/workflows/feature/steps.ts +3 -2
  44. package/src/workflows/feature/tier.test.ts +164 -0
  45. package/src/workflows/feature/tier.ts +74 -0
  46. package/src/workflows/index.ts +1 -0
  47. package/src/workflows/shared/options.test.ts +17 -1
  48. package/src/workflows/shared/options.ts +1 -0
  49. package/src/workflows/shared/skills.test.ts +20 -2
  50. package/src/workflows/shared/skills.ts +6 -0
  51. package/src/workflows/shared/text.test.ts +188 -0
  52. package/src/workflows/shared/text.ts +139 -5
  53. package/src/workflows/shared/vars.ts +6 -0
  54. 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"