@pmelab/gtd 58.2.0 → 59.0.1

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 (150) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +120 -395
  3. package/dist/chunks/{Schema-B3o6eRNU.mjs → testkit-07Z_ENch.mjs} +13503 -3460
  4. package/dist/chunks/{wire-C12dahrH.mjs → wire-BTUhRGXj.mjs} +1 -1
  5. package/dist/flows.mjs +1 -1
  6. package/dist/gtd.bundle.mjs +484 -497
  7. package/dist/testkit/gherkin.mjs +145 -65
  8. package/dist/testkit.mjs +1 -1
  9. package/dist/wire.mjs +1 -1
  10. package/package.json +3 -42
  11. package/skills/authoring/SKILL.md +34 -27
  12. package/src/cli/Cli.test.ts +148 -71
  13. package/src/cli/Cli.ts +384 -463
  14. package/src/cli/Help.test.ts +47 -0
  15. package/src/cli/Help.ts +70 -0
  16. package/src/cli/Program.test.ts +127 -33
  17. package/src/cli/Program.ts +70 -25
  18. package/src/edge/Edge.ts +4 -4
  19. package/src/emit/Emit.test.ts +1 -1
  20. package/src/emit/Emit.ts +1 -1
  21. package/src/flags/index.test.ts +0 -13
  22. package/src/flags/index.ts +1 -3
  23. package/src/flows/factory.ts +3 -1
  24. package/src/gherkin/index.ts +135 -71
  25. package/src/gherkin/messages.test.ts +90 -0
  26. package/src/gherkin/messages.ts +84 -0
  27. package/src/install/Install.test.ts +14 -11
  28. package/src/install/Install.ts +38 -15
  29. package/src/install/index.ts +1 -2
  30. package/src/replay/Replay.test.ts +1 -1
  31. package/src/replay/index.ts +1 -1
  32. package/src/step/planStart.ts +6 -1
  33. package/src/testkit/TestRepo.test.ts +47 -2
  34. package/src/testkit/TestRepo.ts +51 -6
  35. package/src/twins/EmittedScriptRecognizer.ts +5 -8
  36. package/src/twins/FlowScripts.ts +1 -1
  37. package/src/wire/Land.ts +1 -1
  38. package/src/workflow/index.ts +1 -0
  39. package/src/workflow/load.test.ts +138 -113
  40. package/src/workflow/load.ts +7 -7
  41. package/src/workflow/skills.test.ts +5 -5
  42. package/src/workflow/skills.ts +1 -1
  43. package/src/workflow/vars.test.ts +30 -3
  44. package/src/workflow/vars.ts +34 -2
  45. package/src/workflow-kit/index.ts +1 -1
  46. package/dist/chunks/reserved-lMYCaapY.mjs +0 -1990
  47. package/dist/chunks/review-Bfaror38.mjs +0 -427
  48. package/dist/chunks/tail-Bd7L940p.mjs +0 -355
  49. package/dist/chunks/testkit-JDtpNKyi.mjs +0 -10410
  50. package/dist/workflows/cleanup.mjs +0 -36
  51. package/dist/workflows/feature.mjs +0 -1018
  52. package/dist/workflows/fix.mjs +0 -41
  53. package/dist/workflows/review.mjs +0 -45
  54. package/dist/workflows/rollout.mjs +0 -48
  55. package/dist/workflows.mjs +0 -40651
  56. package/src/install/ConfigScaffold.ts +0 -22
  57. package/src/workflows/cleanup/cleanup-path.feature +0 -94
  58. package/src/workflows/cleanup/cleanup.feature +0 -315
  59. package/src/workflows/cleanup/cleanup.test.ts +0 -276
  60. package/src/workflows/cleanup/cleanup.ts +0 -52
  61. package/src/workflows/cleanup/index.ts +0 -6
  62. package/src/workflows/feature/acceptance-criteria-tier.feature +0 -25
  63. package/src/workflows/feature/acceptance-criteria.feature +0 -389
  64. package/src/workflows/feature/criteria-coverage.feature +0 -102
  65. package/src/workflows/feature/criteria.test.ts +0 -147
  66. package/src/workflows/feature/criteria.ts +0 -267
  67. package/src/workflows/feature/fast-path.feature +0 -93
  68. package/src/workflows/feature/feature.test.ts +0 -338
  69. package/src/workflows/feature/feature.ts +0 -156
  70. package/src/workflows/feature/green.ts +0 -19
  71. package/src/workflows/feature/index.ts +0 -18
  72. package/src/workflows/feature/lens-models.feature +0 -69
  73. package/src/workflows/feature/lens-review.feature +0 -566
  74. package/src/workflows/feature/naive-acceptance.feature +0 -147
  75. package/src/workflows/feature/naive-test.feature +0 -263
  76. package/src/workflows/feature/one-step-land.feature +0 -93
  77. package/src/workflows/feature/planning.ts +0 -41
  78. package/src/workflows/feature/refactor-absorbs.feature +0 -131
  79. package/src/workflows/feature/refactor-first.feature +0 -158
  80. package/src/workflows/feature/refactor-lens-models.feature +0 -79
  81. package/src/workflows/feature/refactor-rebuild.feature +0 -273
  82. package/src/workflows/feature/refactor-review.feature +0 -1528
  83. package/src/workflows/feature/refactor.test.ts +0 -1220
  84. package/src/workflows/feature/refactor.ts +0 -368
  85. package/src/workflows/feature/release-flag.feature +0 -167
  86. package/src/workflows/feature/release-flag.test.ts +0 -49
  87. package/src/workflows/feature/release-flag.ts +0 -46
  88. package/src/workflows/feature/review-gate.feature +0 -241
  89. package/src/workflows/feature/reviewer-walkthrough.feature +0 -142
  90. package/src/workflows/feature/risk-tier.feature +0 -351
  91. package/src/workflows/feature/seam-rejection.feature +0 -146
  92. package/src/workflows/feature/seam.feature +0 -297
  93. package/src/workflows/feature/seam.test.ts +0 -527
  94. package/src/workflows/feature/seam.ts +0 -426
  95. package/src/workflows/feature/standards.feature +0 -354
  96. package/src/workflows/feature/steps.test.ts +0 -65
  97. package/src/workflows/feature/steps.ts +0 -45
  98. package/src/workflows/feature/tier-pin.feature +0 -66
  99. package/src/workflows/feature/tier.test.ts +0 -166
  100. package/src/workflows/feature/tier.ts +0 -56
  101. package/src/workflows/fix/fix-lens-origin.feature +0 -114
  102. package/src/workflows/fix/fix-quality.feature +0 -212
  103. package/src/workflows/fix/fix.feature +0 -79
  104. package/src/workflows/fix/fix.test.ts +0 -74
  105. package/src/workflows/fix/fix.ts +0 -52
  106. package/src/workflows/fix/index.ts +0 -6
  107. package/src/workflows/index.ts +0 -47
  108. package/src/workflows/review/index.ts +0 -6
  109. package/src/workflows/review/review-door.feature +0 -199
  110. package/src/workflows/review/review.test.ts +0 -27
  111. package/src/workflows/review/review.ts +0 -60
  112. package/src/workflows/rollout/index.ts +0 -6
  113. package/src/workflows/rollout/rollout.feature +0 -510
  114. package/src/workflows/rollout/rollout.test.ts +0 -263
  115. package/src/workflows/rollout/rollout.ts +0 -82
  116. package/src/workflows/shared/__fixtures__/feature-collecting-prompt.txt +0 -98
  117. package/src/workflows/shared/access.test.ts +0 -62
  118. package/src/workflows/shared/access.ts +0 -24
  119. package/src/workflows/shared/config.fixture.ts +0 -12
  120. package/src/workflows/shared/fences.ts +0 -24
  121. package/src/workflows/shared/health.test.ts +0 -148
  122. package/src/workflows/shared/health.ts +0 -191
  123. package/src/workflows/shared/learn.test.ts +0 -140
  124. package/src/workflows/shared/learn.ts +0 -201
  125. package/src/workflows/shared/lenses.test.ts +0 -39
  126. package/src/workflows/shared/lenses.ts +0 -294
  127. package/src/workflows/shared/options.test.ts +0 -157
  128. package/src/workflows/shared/options.ts +0 -92
  129. package/src/workflows/shared/progress.feature +0 -124
  130. package/src/workflows/shared/prose.ts +0 -263
  131. package/src/workflows/shared/recheck.feature +0 -60
  132. package/src/workflows/shared/registry.test.ts +0 -345
  133. package/src/workflows/shared/registry.ts +0 -183
  134. package/src/workflows/shared/reserved.ts +0 -11
  135. package/src/workflows/shared/review.test.ts +0 -1062
  136. package/src/workflows/shared/review.ts +0 -446
  137. package/src/workflows/shared/skills.test.ts +0 -121
  138. package/src/workflows/shared/skills.ts +0 -49
  139. package/src/workflows/shared/standards.test.ts +0 -90
  140. package/src/workflows/shared/standards.ts +0 -156
  141. package/src/workflows/shared/steps.test.ts +0 -219
  142. package/src/workflows/shared/steps.ts +0 -201
  143. package/src/workflows/shared/tail.test.ts +0 -454
  144. package/src/workflows/shared/tail.ts +0 -264
  145. package/src/workflows/shared/text.fixture.ts +0 -128
  146. package/src/workflows/shared/text.test.ts +0 -1430
  147. package/src/workflows/shared/text.ts +0 -1700
  148. package/src/workflows/shared/threads.test.ts +0 -129
  149. package/src/workflows/shared/vars.ts +0 -47
  150. package/src/workflows/shared/workflows.steps.ts +0 -54
@@ -1,267 +0,0 @@
1
- import {
2
- answered,
3
- changes,
4
- head,
5
- judge,
6
- read,
7
- refuse,
8
- requireProgress,
9
- run,
10
- scope,
11
- type Change,
12
- } from "../../flows/index.js"
13
- import { HEADING, ITEM, markFenced } from "../shared/fences.js"
14
- import { planner, REQUIREMENTS } from "../shared/steps.js"
15
- import * as t from "../shared/text.js"
16
- import { requireReleaseFlag } from "./release-flag.js"
17
-
18
- export interface Criterion {
19
- readonly id: string
20
- readonly text: string
21
- }
22
-
23
- /** Acceptance criteria the human's sketch stated outright, ready to normalise. */
24
- export interface StatedCriteria {
25
- readonly path: string
26
- readonly commit: string
27
- /** The file as the sketch left it: `unwind` reverts it out of the tree. */
28
- readonly text: string
29
- readonly criteria: readonly Criterion[]
30
- }
31
-
32
- /** Below this the judge's `yes` is not trusted: a wrong skip builds against criteria nobody can check. */
33
- const CLEAR_MIN_P = 0.8
34
-
35
- const ID = /^(AC-\d+):\s*(.*)$/
36
-
37
- const criterion = (id: RegExpExecArray, as = id[1]!): Criterion => ({ id: as, text: id[2]! })
38
-
39
- /** The list items under the first heading `title` matches (at `level` when given), up to the next heading; wrapped lines joined, fenced lines ignored. */
40
- const listUnder = (text: string, title: RegExp, level?: number): string[] | undefined => {
41
- const lines = markFenced(text)
42
- const at = lines.findIndex((l) => {
43
- const heading = l.fenced ? null : HEADING.exec(l.line)
44
- return (
45
- heading !== null &&
46
- (level === undefined || heading[1]!.length === level) &&
47
- title.test(heading[2]!)
48
- )
49
- })
50
- if (at === -1) return undefined
51
- const items: string[] = []
52
- let open = false
53
- for (const { line, fenced } of lines.slice(at + 1)) {
54
- if (fenced) {
55
- open = false
56
- continue
57
- }
58
- if (HEADING.test(line)) break
59
- const item = ITEM.exec(line)
60
- if (item !== null) {
61
- items.push(item[1]!.trim())
62
- open = true
63
- } else if (open && line.trim() !== "") {
64
- items[items.length - 1] = `${items.at(-1)!} ${line.trim()}`.trim()
65
- } else open = false
66
- }
67
- return items
68
- }
69
-
70
- /** The `- AC-<n>: …` list of `## Acceptance Criteria`, or `undefined` when the section is missing. */
71
- export const criteriaOf = (text: string): readonly Criterion[] | undefined =>
72
- listUnder(text, /^acceptance criteria$/i, 2)?.map((item) => {
73
- const id = ID.exec(item)
74
- return id === null ? { id: "", text: item } : criterion(id)
75
- })
76
-
77
- /** The ID'd criteria of `text`. */
78
- export const criterionIds = (text: string): string[] =>
79
- (criteriaOf(text) ?? []).map((c) => c.id).filter((id) => id !== "")
80
-
81
- /** Items numbered `AC-1`…, unless every one already carries its own distinct ID. */
82
- const numbered = (items: readonly string[]): Criterion[] => {
83
- const ids = items.map((item) => ID.exec(item))
84
- const own = ids.every((id) => id !== null) && new Set(ids.map((id) => id![1])).size === ids.length
85
- return items.map((item, i) => {
86
- const id = ids[i]
87
- if (own) return criterion(id!)
88
- return id === null ? { id: `AC-${i + 1}`, text: item } : criterion(id!, `AC-${i + 1}`)
89
- })
90
- }
91
-
92
- const STATED = /^acceptance criteria:?$/i
93
-
94
- const statedItems = (text: string | undefined): string[] =>
95
- text === undefined ? [] : (listUnder(text, STATED) ?? []).filter((item) => item !== "")
96
-
97
- /**
98
- * The criteria a `TODO.md` in the sketch `sketch` (the idle turn's changes)
99
- * added or changed under an `Acceptance criteria` heading. More than one such
100
- * file is ambiguous, and any other change in the sketch is input only triage
101
- * folds in, so none.
102
- */
103
- export const statedCriteria = (
104
- sketch: readonly Change[],
105
- commit: string,
106
- ): StatedCriteria | undefined => {
107
- const found = sketch.flatMap((change) => {
108
- if (!/(^|\/)TODO\.md$/.test(change.path) || change.after === undefined) return []
109
- const items = statedItems(change.after)
110
- if (items.length === 0 || items.join("\n") === statedItems(change.before).join("\n")) return []
111
- return [{ path: change.path, commit, text: change.after, criteria: numbered(items) }]
112
- })
113
- return found.length === 1 && sketch.length === 1 ? found[0] : undefined
114
- }
115
-
116
- const listing = (criteria: readonly Criterion[]): string => criteria.map(t.criterionLine).join("\n")
117
-
118
- /** Refuse a turn that leaves `file` without ID'd acceptance criteria. A deleted file is `requireProgress`'s call. */
119
- export const requireCriteria = (file: string): void => {
120
- const text = read(file)
121
- if (text === undefined) return
122
- const criteria = criteriaOf(text) ?? []
123
- const unnamed = criteria.filter((c) => c.id === "")
124
- const ids = criteria.map((c) => c.id).filter((id) => id !== "")
125
- const twice = ids.filter((id, i) => ids.indexOf(id) !== i)
126
- if (criteria.length > 0 && unnamed.length === 0 && twice.length === 0) return
127
- const why =
128
- criteria.length === 0
129
- ? `no "## Acceptance Criteria" list`
130
- : unnamed.length > 0
131
- ? `${unnamed.length} criterion without an ID:\n${unnamed.map((c) => ` - ${c.text}`).join("\n")}`
132
- : `duplicate IDs: ${[...new Set(twice)].join(", ")}`
133
- refuse(
134
- `gtd land: acceptance-criteria: ${file} has ${why} — list every criterion under "## Acceptance Criteria" as "- AC-<n>: <checkable criterion>", each ID unique and never reused`,
135
- )
136
- }
137
-
138
- const isImpactHeading = (h: RegExpExecArray | null): boolean =>
139
- h !== null && h[1]!.length === 2 && /^impact$/i.test(h[2]!.trim())
140
-
141
- // The skip path's impact turn may write both: a sketch can ask for a flag.
142
- const isImpactTurnHeading = (h: RegExpExecArray | null): boolean =>
143
- h !== null && h[1]!.length === 2 && /^(impact|release flag)$/i.test(h[2]!.trim())
144
-
145
- /** Whether `text` has an unfenced, level-2 `## Impact` heading. */
146
- export const hasImpact = (text: string): boolean =>
147
- markFenced(text).some((l) => !l.fenced && isImpactHeading(HEADING.exec(l.line)))
148
-
149
- /** `text` without its `## Impact` and `## Release Flag` sections, whitespace collapsed. */
150
- const withoutImpact = (text: string): string => {
151
- let inImpact = false
152
- const kept = markFenced(text).filter((l) => {
153
- const h = l.fenced ? null : HEADING.exec(l.line)
154
- if (h !== null && h[1]!.length <= 2) inImpact = isImpactTurnHeading(h)
155
- return !inImpact
156
- })
157
- return kept
158
- .map((l) => l.line)
159
- .join(" ")
160
- .replace(/\s+/g, " ")
161
- .trim()
162
- }
163
-
164
- /**
165
- * Refuse a turn that leaves `file` without a `## Impact` section. Only the
166
- * pending turn (`head()` is `""`): a triage lap recorded before Impact existed
167
- * replays without one, and refusing there would fail every in-flight process.
168
- * A human's edit at a later gate is not checked — the human owns that file then.
169
- */
170
- export const requireImpact = (file: string): void => {
171
- if (head() !== "") return
172
- const text = read(file)
173
- if (text === undefined) return
174
- if (hasImpact(text)) return
175
- refuse(
176
- `gtd land: impact: ${file} has no "## Impact" section — explore the codebase and add "## Impact" naming the units, public surfaces and surprises this change touches`,
177
- )
178
- }
179
-
180
- /** Refuse a turn that changed `file` beyond its `## Impact` and `## Release Flag` sections. */
181
- export const requireImpactOnly = (file: string): void => {
182
- const change = changes().get(file)
183
- if (change === undefined) return
184
- if (withoutImpact(change.before ?? "") === withoutImpact(change.after ?? "")) return
185
- refuse(
186
- `gtd land: impact-only: this turn may only add "## Impact" (and "## Release Flag") to ${file} — restore everything else`,
187
- )
188
- }
189
-
190
- /** The IDs a review's feedback lap must respect. */
191
- export interface StableIds {
192
- /** Listed when the build closed: each may stay, reworded or not, or go. */
193
- readonly closed: readonly string[]
194
- /** Every ID handed out so far: any other is numbered above all of them. */
195
- readonly used: readonly string[]
196
- }
197
-
198
- const idNumber = (id: string): number => Number(id.slice("AC-".length))
199
-
200
- /** Why `listed` renumbers or reuses an earlier ID; `undefined` when it does neither. */
201
- export const unstableIds = (listed: readonly string[], ids: StableIds): string | undefined => {
202
- const top = Math.max(0, ...ids.used.map(idNumber))
203
- const reused = listed.filter((id) => !ids.closed.includes(id) && idNumber(id) <= top)
204
- if (reused.length === 0) return undefined
205
- return `numbers ${reused.join(", ")} at or below AC-${top}, an ID already handed out — keep a built criterion's ID (reword it in place when the review changes it), and number new ones from AC-${top + 1}`
206
- }
207
-
208
- /** Refuse criteria in `file` that renumber or reuse an earlier ID. */
209
- export const requireStableIds = (file: string, ids: StableIds): void => {
210
- const why = unstableIds(criterionIds(read(file) ?? ""), ids)
211
- if (why !== undefined) refuse(`gtd land: criteria-ids: ${file} ${why}`)
212
- }
213
-
214
- /** Refuse a turn that changed the acceptance criteria in `file`: after the design gate only another design lap may. */
215
- export const requireCriteriaFrozen = (file: string): void => {
216
- const change = changes().get(file)
217
- if (change === undefined) return
218
- const before = listing(criteriaOf(change.before ?? "") ?? [])
219
- if (before === listing(criteriaOf(change.after ?? "") ?? [])) return
220
- refuse(
221
- `gtd land: criteria-frozen: the acceptance criteria in ${file} are settled — restore them; only a design lap changes them`,
222
- )
223
- }
224
-
225
- /** Whether the judge trusts `stated` as clear and checkable, every criterion of it. Truncated evidence never is. */
226
- const clear = async (stated: StatedCriteria): Promise<boolean> => {
227
- const { answers, truncated } = await judge("clear", {
228
- questions: [t.clearCriteriaQuestion],
229
- evidence: { criteria: listing(stated.criteria), sketch: stated.text },
230
- message: t.clearCriteriaMessage(),
231
- label: "Judging the stated acceptance criteria",
232
- })
233
- return truncated.length === 0 && answered(answers.clear, "yes", CLEAR_MIN_P)
234
- }
235
-
236
- /** The fast path's impact-only turn: add `## Impact`, leave the criteria alone. */
237
- const impact = async (): Promise<void> => {
238
- await t.agentWithSkills("impact", t.designImpactPrompt(), {
239
- label: "Mapping the change's impact",
240
- file: REQUIREMENTS,
241
- model: planner(),
242
- system: t.designSystem(),
243
- })
244
- requireProgress(REQUIREMENTS)
245
- requireCriteriaFrozen(REQUIREMENTS)
246
- requireImpact(REQUIREMENTS)
247
- requireImpactOnly(REQUIREMENTS)
248
- requireReleaseFlag(REQUIREMENTS)
249
- }
250
-
251
- /**
252
- * The skip path: when the sketch stated clear, checkable criteria, write them
253
- * to `.gtd/REQUIREMENTS.md` as they are and resolve `true` — no triage, no
254
- * design gate. `false` when design must run.
255
- */
256
- export const skipDesign = (stated: StatedCriteria | undefined): Promise<boolean> =>
257
- stated === undefined
258
- ? Promise.resolve(false)
259
- : scope("design", async () => {
260
- if (!(await clear(stated))) return false
261
- await run("normalise", t.normaliseCriteriaScript(stated), {
262
- label: "Recording the stated acceptance criteria",
263
- file: REQUIREMENTS,
264
- })
265
- await impact()
266
- return true
267
- })
@@ -1,93 +0,0 @@
1
- @inmem
2
- Feature: a trivial change takes the same few beats at either risk tier
3
-
4
- With GTD_FLAG_RISK_TIER on, a one-line copy fix goes
5
- from idle through the naive pass, the seam judge's land, the applied pass and
6
- the quality lap to the review gate. Low tier walks exactly the steps high does; only
7
- the summary differs.
8
-
9
- Background:
10
- Given the shipped workflows, as gtd install scaffolds them
11
- And an environment variable "GTD_QUALITYREVIEWS" set to "correctness"
12
- And an environment variable "GTD_FLAG_RISK_TIER" set to "1"
13
- And a file "src/greeting.ts" with:
14
- """
15
- export const greeting = "Helo, world"
16
- """
17
- And the working tree is committed as "feat: add greeting"
18
- And a file "TODO.md" with:
19
- """
20
- # Fix the typo
21
-
22
- greeting says "Helo"; make it "Hello".
23
- """
24
- And step "unwind" changes nothing
25
- And step "start-gate.check" changes nothing
26
- And step "design.gate.answer" changes nothing
27
- And step "implement.health.check" changes nothing
28
- And step "implement.closing" runs its script
29
- And step "build.quality.correctness.reviewing" changes nothing
30
-
31
- Scenario Outline: a one-line fix runs from idle to the review gate with the same beats at either tier
32
- Given step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
33
- """
34
- # Requirements
35
-
36
- ## Risk Tier
37
-
38
- <tier> — one-line copy fix
39
-
40
- ## Impact
41
-
42
- - the greeting module
43
-
44
- ## Release Flag
45
-
46
- new
47
-
48
- ## Acceptance Criteria
49
-
50
- - AC-1: the change behaves as described.
51
- """
52
- When the process is driven
53
- Then the process rests at "seam.naive"
54
- And the last commit subject is "gtd(human): design.gate.answer → seam.naive"
55
-
56
- Given step "seam.check" changes nothing
57
- And step "seam.naive" writes "src/acceptance.test.ts" with:
58
- """
59
- it("[AC-1] holds", () => {})
60
- """
61
- And step "seam.naive" writes "src/greeting.ts" with:
62
- """
63
- export const greeting = "Hello, world"
64
- """
65
- And judge step "seam.judge" answers:
66
- """
67
- [{"id":"shape","answer":"land","p":0.9}]
68
- """
69
- And step "implement.applying" runs its script
70
- When the process is driven
71
- Then the process rests at "build.review.reviewing"
72
- And "src/greeting.ts" contains "Hello, world"
73
- And the commit subjects end with:
74
- """
75
- gtd(human): idle → unwind
76
- gtd(check): unwind → start-gate.check
77
- gtd(check): start-gate.check → design.triage
78
- gtd(agent): design.triage → design.gate.answer
79
- gtd(human): design.gate.answer → seam.naive
80
- gtd(agent): seam.naive → seam.check
81
- gtd(check): seam.check → seam.judge
82
- gtd(judge): seam.judge → implement.applying
83
- gtd(check): implement.applying → implement.health.check
84
- gtd(check): implement.health.check → implement.closing
85
- gtd(check): implement.closing → build.quality.correctness.reviewing
86
- gtd(agent): build.quality.correctness.reviewing → build.review.reviewing
87
- """
88
- And the output of gtd "summary" <summary> "needs a human reviewer"
89
-
90
- Examples:
91
- | tier | summary |
92
- | low | does not contain |
93
- | high | contains |