@pmelab/gtd 29.3.1 → 30.1.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 +64 -63
  3. package/claude/hooks/register.tsx +5 -0
  4. package/dist/chunks/{reserved-Dmpg6dAp.mjs → reserved-DDiiAZ8U.mjs} +35 -239
  5. package/dist/chunks/{tail-CLyE5VFR.mjs → tail-ILPlELuy.mjs} +1 -1
  6. package/dist/gtd.bundle.mjs +0 -5
  7. package/dist/testkit.mjs +0 -5
  8. package/dist/workflows/cleanup.mjs +2 -2
  9. package/dist/workflows/feature.mjs +17 -182
  10. package/dist/workflows/fix.mjs +2 -2
  11. package/dist/workflows/review.mjs +2 -2
  12. package/dist/workflows/rollout.mjs +1 -1
  13. package/dist/workflows.mjs +47 -416
  14. package/package.json +1 -1
  15. package/skills/authoring/SKILL.md +15 -27
  16. package/src/cli/Cli.test.ts +6 -6
  17. package/src/edge/Edge.test.ts +7 -7
  18. package/src/flags/index.test.ts +0 -4
  19. package/src/flags/index.ts +0 -1
  20. package/src/workflow/load.test.ts +1 -1
  21. package/src/workflows/feature/fast-path.feature +1 -2
  22. package/src/workflows/feature/feature.test.ts +115 -63
  23. package/src/workflows/feature/feature.ts +21 -38
  24. package/src/workflows/feature/flag-mode.feature +157 -0
  25. package/src/workflows/feature/index.ts +0 -1
  26. package/src/workflows/feature/one-step-land.feature +4 -6
  27. package/src/workflows/feature/planning.ts +2 -27
  28. package/src/workflows/feature/refactor-absorbs.feature +1 -2
  29. package/src/workflows/feature/refactor-first.feature +1 -3
  30. package/src/workflows/feature/refactor-review.feature +0 -1
  31. package/src/workflows/feature/risk-tier.feature +2 -3
  32. package/src/workflows/feature/seam-rejection.feature +1 -3
  33. package/src/workflows/feature/seam.feature +4 -6
  34. package/src/workflows/feature/seam.ts +2 -0
  35. package/src/workflows/feature/steps.test.ts +0 -20
  36. package/src/workflows/feature/steps.ts +1 -49
  37. package/src/workflows/feature/{seam-pin.feature → tier-pin.feature} +17 -11
  38. package/src/workflows/feature/tier.test.ts +3 -5
  39. package/src/workflows/feature/tier.ts +2 -2
  40. package/src/workflows/index.ts +0 -1
  41. package/src/workflows/shared/access.test.ts +0 -2
  42. package/src/workflows/shared/access.ts +0 -2
  43. package/src/workflows/shared/options.test.ts +14 -3
  44. package/src/workflows/shared/options.ts +17 -2
  45. package/src/workflows/shared/prose.ts +4 -11
  46. package/src/workflows/shared/reserved.ts +2 -2
  47. package/src/workflows/shared/skills.test.ts +0 -11
  48. package/src/workflows/shared/skills.ts +2 -9
  49. package/src/workflows/shared/steps.ts +0 -1
  50. package/src/workflows/shared/text.test.ts +20 -104
  51. package/src/workflows/shared/text.ts +28 -229
  52. package/src/workflows/shared/vars.ts +2 -3
  53. package/src/workflows/feature/packages.test.ts +0 -368
  54. package/src/workflows/feature/packages.ts +0 -173
@@ -0,0 +1,157 @@
1
+ @inmem
2
+ Feature: flag mode off builds a feature with no release flag, seam judge or refactor
3
+
4
+ `flagMode` is a factory option of the shipped workflows, on by default. Off,
5
+ the project ships without feature flags: no seam judge and no refactor run,
6
+ and the naive implementation goes straight through the health loop and the
7
+ quality lap.
8
+
9
+ Background:
10
+ Given a gtd config with:
11
+ """
12
+ import { feature } from "@pmelab/gtd/workflows/feature"
13
+ export { summary, steering, skills, access } from "@pmelab/gtd/workflows/feature"
14
+ export default feature({ flagMode: false })
15
+ """
16
+ And an environment variable "GTD_QUALITYREVIEWS" set to "correctness"
17
+ And a file "src/calc.ts" with:
18
+ """
19
+ export const add = (a: number, b: number) => a + b
20
+ """
21
+ And the working tree is committed as "feat: add calculator"
22
+ And a file "TODO.md" with:
23
+ """
24
+ # Add subtract
25
+
26
+ subtract(a, b) returns the difference.
27
+ """
28
+ And step "unwind" changes nothing
29
+ And step "start-gate.check" changes nothing
30
+ And step "design.triage" writes ".gtd/REQUIREMENTS.md" with:
31
+ """
32
+ # Requirements
33
+
34
+ ## Concerns
35
+
36
+ ### Subtract
37
+
38
+ - `subtract(a, b)` returns `a - b`.
39
+ """
40
+ And step "design.gate.answer" changes nothing
41
+
42
+ Scenario: flag mode off skips the seam judge and the refactor, and asks for no flag
43
+ When the process is driven
44
+ Then the process rests at "implement.building"
45
+ And the resting step's content contains "the quickest way that works"
46
+ And the resting step's content contains "Add no release flag — this project ships without release flags"
47
+ And the resting step's content does not contain "new release flag"
48
+ Given step "implement.building" writes "src/calc.ts" with:
49
+ """
50
+ export const add = (a: number, b: number) => a + b
51
+ export const subtract = (a: number, b: number) => a - b
52
+ """
53
+ And step "implement.health.check" changes nothing
54
+ And step "implement.closing" runs its script
55
+ And step "build.quality.correctness.reviewing" changes nothing
56
+ When the process is driven
57
+ Then the process rests at "build.review.reviewing"
58
+ And "src/calc.ts" contains "subtract"
59
+ And the commit subjects end with:
60
+ """
61
+ chore: initial commit
62
+ feat: add calculator
63
+ gtd(human): idle → unwind
64
+ gtd(check): unwind → start-gate.check
65
+ gtd(check): start-gate.check → design.triage
66
+ gtd(agent): design.triage → design.gate.answer
67
+ gtd(human): design.gate.answer → implement.building
68
+ gtd(agent): implement.building → implement.health.check
69
+ gtd(check): implement.health.check → implement.closing
70
+ gtd(check): implement.closing → build.quality.correctness.reviewing
71
+ gtd(agent): build.quality.correctness.reviewing → build.review.reviewing
72
+ """
73
+
74
+ Scenario: flag mode off asks for no flag on a feedback lap either
75
+ Given step "implement.building" writes "src/calc.ts" with:
76
+ """
77
+ export const add = (a: number, b: number) => a + b
78
+ export const subtract = (a: number, b: number) => a - b
79
+ """
80
+ And step "implement.health.check" changes nothing
81
+ And step "implement.closing" runs its script
82
+ And step "build.quality.correctness.reviewing" changes nothing
83
+ And step "build.review.reviewing" writes ".gtd/REVIEW.md" with:
84
+ """
85
+ # Review: abc1234
86
+
87
+ <!-- base: 0000000 -->
88
+
89
+ ## calc
90
+
91
+ - [ ] ./src/calc.ts#2-2
92
+ new subtract function
93
+ """
94
+ When the process is driven
95
+ Then the process rests at "build.review.await-review"
96
+ Given a file ".gtd/REVIEW.md" with:
97
+ """
98
+ # Review: abc1234
99
+
100
+ <!-- base: 0000000 -->
101
+
102
+ ## calc
103
+
104
+ - [ ] ./src/calc.ts#2-2
105
+ new subtract function[^why]
106
+
107
+ [^why]:
108
+ - H: also export multiply
109
+ """
110
+ And step "build.review.collecting" writes ".gtd/REQUIREMENTS.md" with:
111
+ """
112
+ # Requirements
113
+
114
+ ## Concerns
115
+
116
+ ### Multiply
117
+
118
+ - Export `multiply()`.
119
+ """
120
+ And step "build.review.collecting" writes ".gtd/REVIEW.md" with:
121
+ """
122
+ # Review: abc1234
123
+
124
+ <!-- base: 0000000 -->
125
+
126
+ ## calc
127
+
128
+ - [ ] ./src/calc.ts#2-2
129
+ new subtract function[^why]
130
+
131
+ [^why]:
132
+ - H: also export multiply
133
+ - A: noted in the requirements.
134
+ """
135
+ When gtd lands
136
+ And the process is driven
137
+ Then the process rests at "build.review.await-review"
138
+ Given a file ".gtd/REVIEW.md" with:
139
+ """
140
+ # Review: abc1234
141
+
142
+ <!-- base: 0000000 -->
143
+
144
+ ## calc
145
+
146
+ - [ ] ./src/calc.ts#2-2
147
+ new subtract function
148
+ """
149
+ And step "build.review.closing" runs its script
150
+ And step "re-unwind" runs its script
151
+ And step "implement.building" is no longer scripted
152
+ When gtd lands
153
+ And the process is driven
154
+ Then the process rests at "implement.building"
155
+ And the resting step's content contains "Add no release flag — this project ships without release flags"
156
+ And the resting step's content does not contain "release flag the earlier lap added"
157
+ And no commit body contains "Gtd-Kept:"
@@ -2,7 +2,6 @@ import { feature } from "./feature.js"
2
2
 
3
3
  export * from "./steps.js"
4
4
  export * from "./planning.js"
5
- export * from "./packages.js"
6
5
  export * from "./refactor.js"
7
6
  export * from "./seam.js"
8
7
  export {
@@ -2,16 +2,15 @@
2
2
  @inmem
3
3
  Feature: a naive pass the judge rules land goes straight to implement with no seam gate
4
4
 
5
- With GTD_FLAG_NAIVE_PASS on and GTD_FLAG_RISK_TIER off, a naive pass that
5
+ With GTD_FLAG_RISK_TIER off, a naive pass that
6
6
  edits an existing source file is judged land: the process skips the approval
7
- gate, any refactor and any architecture, and runs implement, quality and
8
- review back to idle. The flags are pinned here so the per-flag test runs never
7
+ gate and any refactor, and runs implement, quality and
8
+ review back to idle. The flag is pinned here so the per-flag test runs never
9
9
  move it off this path.
10
10
 
11
11
  Background:
12
12
  Given the shipped workflows, as gtd install scaffolds them
13
13
  And an environment variable "GTD_QUALITYREVIEWS" set to "correctness"
14
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
15
14
  And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
16
15
  And a file "src/greeting.ts" with:
17
16
  """
@@ -65,7 +64,7 @@ Feature: a naive pass the judge rules land goes straight to implement with no se
65
64
  """
66
65
  And step "build.review.closing" runs its script
67
66
 
68
- Scenario: a land judgment runs idle to idle with no seam gate, refactor or architecture
67
+ Scenario: a land judgment runs idle to idle with no seam gate or refactor
69
68
  When the process is driven
70
69
  Then the process rests at "build.review.await-review"
71
70
  Given a file ".gtd/REVIEW.md" with:
@@ -100,7 +99,6 @@ Feature: a naive pass the judge rules land goes straight to implement with no se
100
99
  gtd(human): build.review.await-review → build.review.closing
101
100
  gtd(check): build.review.closing → idle
102
101
  """
103
- And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_naive_pass=1"
104
102
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
105
103
  And the commit "gtd(agent): seam.naive → seam.judge" has a body containing "Gtd-Kept:"
106
104
  And the commit "gtd(judge): seam.judge → implement.building" has a body containing "\"answer\":\"land\""
@@ -1,21 +1,14 @@
1
1
  import {
2
2
  changes,
3
3
  hasThreadFor,
4
- refuse,
5
4
  requireAnswers,
6
5
  requireReplies,
7
6
  requireThreadsClosed,
8
7
  requireProgress,
9
8
  scope,
10
9
  } from "../../flows/index.js"
11
- import { ARCHITECTURE, REQUIREMENTS } from "../shared/steps.js"
12
- import {
13
- answerProductQuestions,
14
- answerTechnicalQuestions,
15
- author,
16
- decompose,
17
- triage,
18
- } from "./steps.js"
10
+ import { REQUIREMENTS } from "../shared/steps.js"
11
+ import { answerProductQuestions, triage } from "./steps.js"
19
12
 
20
13
  /**
21
14
  * Always stop for the human. Resolves `true` when the round changed anything
@@ -40,21 +33,3 @@ export const design = (base: string): Promise<void> =>
40
33
  requireReplies(REQUIREMENTS)
41
34
  } while (await noteGate(REQUIREMENTS, answerProductQuestions))
42
35
  })
43
-
44
- /** Work out the technical plan, then decompose it into package files. */
45
- export const architecture = (): Promise<void> =>
46
- scope("architecture", async () => {
47
- do {
48
- await author()
49
- requireReplies(ARCHITECTURE)
50
- } while (await noteGate(ARCHITECTURE, answerTechnicalQuestions))
51
- await decompose()
52
- if (changes(".gtd/packages/**").length === 0) {
53
- refuse("gtd land: decompose: write at least one package under .gtd/packages/")
54
- }
55
- if (changes(ARCHITECTURE).some((c) => c.status === "deleted")) {
56
- refuse(
57
- "gtd land: decompose: keep .gtd/ARCHITECTURE.md — the packages are built from it; it is removed with the last package",
58
- )
59
- }
60
- })
@@ -2,7 +2,7 @@
2
2
  @inmem
3
3
  Feature: a refactor that carried the whole feature still gets a feature review
4
4
 
5
- With GTD_FLAG_NAIVE_PASS on and GTD_FLAG_RISK_TIER off, a refactor-first
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
7
  implement turn then has nothing to author: its empty turn completes the
8
8
  step, and with no code changed since the refactor the feature review covers
@@ -12,7 +12,6 @@ Feature: a refactor that carried the whole feature still gets a feature review
12
12
  Given the shipped workflows, as gtd install scaffolds them
13
13
  And an environment variable "GTD_QUALITYREVIEWS" set to ""
14
14
  And an environment variable "GTD_REFACTORQUALITYREVIEWS" set to ""
15
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
16
15
  And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
17
16
  And a file "src/calc.ts" with:
18
17
  """
@@ -2,7 +2,7 @@
2
2
  @inmem
3
3
  Feature: a refactor-first judgment walks one fixed path to idle
4
4
 
5
- With GTD_FLAG_NAIVE_PASS on and GTD_FLAG_RISK_TIER off, a naive pass touching
5
+ With GTD_FLAG_RISK_TIER off, a naive pass touching
6
6
  an existing non-allowlisted file is ruled refactor-first, is refactored and
7
7
  that refactor reviewed, and only then implemented. The flags are
8
8
  pinned so the per-flag test runs never move it off its path.
@@ -11,7 +11,6 @@ Feature: a refactor-first judgment walks one fixed path to idle
11
11
  Given the shipped workflows, as gtd install scaffolds them
12
12
  And an environment variable "GTD_QUALITYREVIEWS" set to ""
13
13
  And an environment variable "GTD_REFACTORQUALITYREVIEWS" set to ""
14
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
15
14
  And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
16
15
  And a file "src/calc.ts" with:
17
16
  """
@@ -154,7 +153,6 @@ Feature: a refactor-first judgment walks one fixed path to idle
154
153
  gtd(human): build.review.await-review → build.review.closing
155
154
  gtd(check): build.review.closing → idle
156
155
  """
157
- And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_naive_pass=1"
158
156
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
159
157
  And the commit "gtd(agent): seam.naive → seam.judge" has a body containing "Gtd-Kept:"
160
158
  And the commit "gtd(judge): seam.judge → refactor.deriving" has a body containing "\"answer\":\"refactor-first\""
@@ -10,7 +10,6 @@ Feature: the refactor slice is reviewed on its own before the feature is impleme
10
10
  Background:
11
11
  Given the shipped workflows, as gtd install scaffolds them
12
12
  And an environment variable "GTD_QUALITYREVIEWS" set to ""
13
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
14
13
  And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
15
14
 
16
15
  Scenario: with a narrowed seamAllow a test file added by the refactor is refused
@@ -1,7 +1,7 @@
1
1
  @inmem
2
2
  Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_TIER
3
3
 
4
- With GTD_FLAG_NAIVE_PASS and GTD_FLAG_RISK_TIER both on, design.triage asks
4
+ With GTD_FLAG_RISK_TIER on, design.triage asks
5
5
  for a risk tier and production signals, and the design gate's exit lands them
6
6
  as Gtd-Mark trailers: one `risk-tier=<low|high>`, one `production-signal`
7
7
  per signal. A missing or unreadable tier is high. With the flag off, nothing
@@ -10,7 +10,6 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
10
10
  Background:
11
11
  Given the shipped workflows, as gtd install scaffolds them
12
12
  And an environment variable "GTD_QUALITYREVIEWS" set to ""
13
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
14
13
 
15
14
  Rule: with GTD_FLAG_RISK_TIER on
16
15
 
@@ -35,7 +34,7 @@ Feature: the risk tier is proposed at triage and recorded behind GTD_FLAG_RISK_T
35
34
  And step "unwind" changes nothing
36
35
  And step "start-gate.check" changes nothing
37
36
 
38
- Scenario: with both flags on the triage prompt asks for the tier and the signals
37
+ Scenario: with the flag on the triage prompt asks for the tier and the signals
39
38
  When the process is driven
40
39
  Then the process rests at "design.triage"
41
40
  And the resting step's content contains "## Risk Tier"
@@ -2,7 +2,7 @@
2
2
  @inmem
3
3
  Feature: rejected naive passes walk one fixed path through the steer gate to idle
4
4
 
5
- With GTD_FLAG_NAIVE_PASS on and GTD_FLAG_RISK_TIER off, three rejected naive
5
+ With GTD_FLAG_RISK_TIER off, three rejected naive
6
6
  passes rest at the steer gate, where a human edit restarts the seam and the
7
7
  steered rerun lands. The flags are pinned so the per-flag test runs never
8
8
  move it off its path.
@@ -10,7 +10,6 @@ Feature: rejected naive passes walk one fixed path through the steer gate to idl
10
10
  Background:
11
11
  Given the shipped workflows, as gtd install scaffolds them
12
12
  And an environment variable "GTD_QUALITYREVIEWS" set to ""
13
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
14
13
  And an environment variable "GTD_FLAG_RISK_TIER" set to "0"
15
14
  And a file "src/calc.ts" with:
16
15
  """
@@ -136,7 +135,6 @@ Feature: rejected naive passes walk one fixed path through the steer gate to idl
136
135
  gtd(human): build.review.await-review → build.review.closing
137
136
  gtd(check): build.review.closing → idle
138
137
  """
139
- And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_naive_pass=1"
140
138
  And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
141
139
  And the commit "gtd(agent): seam.naive → seam.judge" has a body containing "Gtd-Kept:"
142
140
  And the commit "gtd(judge): seam.judge → seam.naive" has a body containing "\"answer\":\"reject\""
@@ -1,10 +1,9 @@
1
1
  @inmem
2
- Feature: the naive pass and seam judge replace architecture behind GTD_FLAG_NAIVE_PASS
2
+ Feature: the naive pass and seam judge decide how a feature is built
3
3
 
4
- With the flag on, after design a naive pass is set aside under a kept ref, the
5
- judge reads its diff, and the process either implements straight away, refactors
6
- the seam first behind a human approval, or retries the naive pass. With the flag
7
- off nothing changes: architecture and packages run as before.
4
+ After design a naive pass is set aside under a kept ref, the judge reads its
5
+ diff, and the process either implements straight away, refactors the seam
6
+ first behind a human approval, or retries the naive pass.
8
7
 
9
8
  Background:
10
9
  Given the shipped workflows, as gtd install scaffolds them
@@ -17,7 +16,6 @@ Feature: the naive pass and seam judge replace architecture behind GTD_FLAG_NAIV
17
16
  }
18
17
  """
19
18
  And an environment variable "GTD_QUALITYREVIEWS" set to ""
20
- And an environment variable "GTD_FLAG_NAIVE_PASS" set to "1"
21
19
  And a file "src/calc.ts" with:
22
20
  """
23
21
  export const add = (a: number, b: number) => a + b
@@ -17,6 +17,7 @@ import { coder, FEEDBACK, REQUIREMENTS } from "../shared/steps.js"
17
17
  import * as t from "../shared/text.js"
18
18
  import { defaults } from "../shared/vars.js"
19
19
  import { refactorStrays, reviewedRefactor } from "./refactor.js"
20
+ import { flagModeOn } from "../shared/options.js"
20
21
  import type { RiskTier } from "./tier.js"
21
22
 
22
23
  /** Naive-pass retries after a `reject`; the next `reject` rests at `seam.steer`. */
@@ -71,6 +72,7 @@ export function implement(
71
72
  options.tier,
72
73
  options.amend,
73
74
  options.afterRefactor,
75
+ flagModeOn(),
74
76
  ),
75
77
  {
76
78
  label: "Implementing",
@@ -21,26 +21,6 @@ describe("the feature workflow's own steps declare skills — a step's rendered
21
21
  expect(prompt).toContain("spec-driven-development, planning-and-task-breakdown")
22
22
  })
23
23
 
24
- it("author carries architecture.author's bundled skills", async () => {
25
- const prompt = agentPrompt(await capture(() => steps.author(), "architecture"))
26
- expect(prompt).toContain("api-and-interface-design, documentation-and-adrs, ponytail")
27
- })
28
-
29
- it("decompose carries architecture.decompose's bundled skills", async () => {
30
- const prompt = agentPrompt(await capture(() => steps.decompose(), "architecture"))
31
- expect(prompt).toContain("incremental-implementation, planning-and-task-breakdown")
32
- })
33
-
34
- it("build carries packages.item.building's bundled skills", async () => {
35
- const prompt = agentPrompt(await capture(() => steps.build("pkg"), "packages.item"))
36
- expect(prompt).toContain("test-driven-development, incremental-implementation")
37
- })
38
-
39
- it("fixSuite carries packages.item.fix.suite's bundled skills", async () => {
40
- const prompt = agentPrompt(await capture(() => steps.fixSuite(), "packages.item"))
41
- expect(prompt).toContain("debugging-and-error-recovery")
42
- })
43
-
44
24
  it("collecting carries build.review.collecting's bundled skills", async () => {
45
25
  const prompt = agentPrompt(await capture(() => steps.collecting("capture"), "build"))
46
26
  expect(prompt).toContain("code-review-and-quality")
@@ -2,15 +2,7 @@ import { human, run, scope, type ScopeAccess } from "../../flows/index.js"
2
2
  import type { CollectRound } from "../../workflow-kit/index.js"
3
3
  import * as t from "../shared/text.js"
4
4
  import { riskTierOn } from "./tier.js"
5
- import {
6
- ARCHITECTURE,
7
- coder,
8
- FEEDBACK,
9
- planner,
10
- REFACTOR,
11
- REQUIREMENTS,
12
- REVIEW,
13
- } from "../shared/steps.js"
5
+ import { planner, REFACTOR, REQUIREMENTS, REVIEW } from "../shared/steps.js"
14
6
 
15
7
  /** Turn the sketch since `base` into `.gtd/REQUIREMENTS.md`. */
16
8
  export const triage = (base: string): Promise<void> =>
@@ -22,22 +14,6 @@ export const triage = (base: string): Promise<void> =>
22
14
  system: t.designSystem(),
23
15
  })
24
16
 
25
- export const author = (): Promise<void> =>
26
- t.agentWithSkills("author", t.architectureAuthorPrompt(), {
27
- label: "Refining the technical plan",
28
- file: ARCHITECTURE,
29
- mode: "qa",
30
- model: planner(),
31
- system: t.architectSystem(),
32
- })
33
-
34
- export const decompose = (): Promise<void> =>
35
- t.agentWithSkills("decompose.decomposing", t.architectureDecomposePrompt(), {
36
- label: "Decomposing into packages",
37
- model: planner(),
38
- system: t.architectSystem(),
39
- })
40
-
41
17
  export const answerProductQuestions = (): Promise<void> =>
42
18
  human("gate.answer", {
43
19
  message: t.designGateAnswerMessage(riskTierOn()),
@@ -47,30 +23,6 @@ export const answerProductQuestions = (): Promise<void> =>
47
23
  acceptClean: true,
48
24
  })
49
25
 
50
- export const answerTechnicalQuestions = (): Promise<void> =>
51
- human("gate.answer", {
52
- message: t.architectureGateAnswerMessage(),
53
- label: "Awaiting your technical answers",
54
- file: ARCHITECTURE,
55
- mode: "qa",
56
- acceptClean: true,
57
- })
58
-
59
- export const build = (pkg: string): Promise<void> =>
60
- t.agentWithSkills("building", t.packagesItemBuildingPrompt(pkg), {
61
- label: "Building",
62
- model: coder(),
63
- system: t.builderSystem(),
64
- })
65
-
66
- export const fixSuite = (): Promise<void> =>
67
- t.agentWithSkills("fix.suite.fixing", t.packagesItemFixSuitePrompt(), {
68
- label: "Fixing the check",
69
- file: FEEDBACK,
70
- model: coder(),
71
- system: t.builderSystem(),
72
- })
73
-
74
26
  /** Answer every `question` note inline in `.gtd/REVIEW.md`. */
75
27
  export const answerReviewQuestions = (notes: readonly t.NoteInput[]): Promise<void> =>
76
28
  t.agentWithSkills("review.answer-review-questions", t.buildReviewAnswerQuestionsPrompt(notes), {
@@ -1,8 +1,8 @@
1
1
  @inmem
2
- Feature: a process keeps the path it started on when GTD_FLAG_NAIVE_PASS changes
2
+ Feature: a process keeps the risk tier setting it started with when GTD_FLAG_RISK_TIER changes
3
3
 
4
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.
5
+ changes whether the process asks for and records a risk tier.
6
6
 
7
7
  Background:
8
8
  Given the shipped workflows, as gtd install scaffolds them
@@ -29,24 +29,30 @@ Feature: a process keeps the path it started on when GTD_FLAG_NAIVE_PASS changes
29
29
  ### Subtract
30
30
 
31
31
  - `subtract(a, b)` returns `a - b`.
32
+
33
+ ## Risk Tier
34
+
35
+ low — a new pure function
32
36
  """
33
37
 
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"
38
+ Scenario: a process started with the flag off records no tier after the flag turns on
39
+ Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "0"
36
40
  When the process is driven
37
41
  Then the process rests at "design.gate.answer"
38
- Given the ambient environment variable "GTD_FLAG_NAIVE_PASS" is "1"
42
+ Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "1"
39
43
  And step "design.gate.answer" changes nothing
40
44
  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"
45
+ Then the process rests at "seam.naive"
46
+ And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=0"
47
+ And no commit body contains "Gtd-Mark:"
43
48
 
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"
49
+ Scenario: a process started with the flag on records its tier after the flag turns off
50
+ Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "1"
46
51
  When the process is driven
47
52
  Then the process rests at "design.gate.answer"
48
- Given the ambient environment variable "GTD_FLAG_NAIVE_PASS" is "0"
53
+ Given the ambient environment variable "GTD_FLAG_RISK_TIER" is "0"
49
54
  And step "design.gate.answer" changes nothing
50
55
  When the process is driven
51
56
  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"
57
+ And the commit "gtd(human): idle → unwind" has a body containing "Gtd-Var: flag_risk_tier=1"
58
+ And the last commit body contains "Gtd-Mark: risk-tier=low"
@@ -9,11 +9,9 @@ const withVars = (vars: Record<string, string>) => installContext(fixtureContext
9
9
 
10
10
  describe("riskTierOn", () => {
11
11
  it.each([
12
- [{ flag_naive_pass: "1", flag_risk_tier: "1" }, true],
13
- [{ flag_naive_pass: "1", flag_risk_tier: "0" }, false],
14
- [{ flag_naive_pass: "0", flag_risk_tier: "1" }, false],
15
- [{ flag_naive_pass: "0", flag_risk_tier: "0" }, false],
16
- [{ flag_naive_pass: "1" }, false],
12
+ [{ flag_risk_tier: "1" }, true],
13
+ [{ flag_risk_tier: "0" }, false],
14
+ [{}, false],
17
15
  ])("%j is %s", (vars, expected) => {
18
16
  withVars(vars)
19
17
  expect(riskTierOn()).toBe(expected)
@@ -4,8 +4,8 @@ import { REQUIREMENTS } from "../shared/steps.js"
4
4
 
5
5
  export type RiskTier = "low" | "high"
6
6
 
7
- /** GTD_FLAG_NAIVE_PASS, GTD_FLAG_RISK_TIER: both pinned at process start, so a mid-process flip never moves a process. */
8
- export const riskTierOn = (): boolean => vars.flag_naive_pass === "1" && vars.flag_risk_tier === "1"
7
+ /** GTD_FLAG_RISK_TIER: pinned at process start, so a mid-process flip never moves a process. */
8
+ export const riskTierOn = (): boolean => vars.flag_risk_tier === "1"
9
9
 
10
10
  const sectionLines = (
11
11
  text: string | undefined,
@@ -22,7 +22,6 @@ export {
22
22
  export { lensesOf } from "../workflow-kit/index.js"
23
23
  export * from "./feature/steps.js"
24
24
  export * from "./feature/planning.js"
25
- export * from "./feature/packages.js"
26
25
  export * from "./feature/refactor.js"
27
26
  export * from "./feature/seam.js"
28
27
  export {
@@ -10,8 +10,6 @@ describe("the bundled workflow's access export", () => {
10
10
  it("restricts writes on planning, review and lens scopes only", () => {
11
11
  expect(bundled).toEqual({
12
12
  design: { write: [] },
13
- architecture: { write: [".gtd/REQUIREMENTS.md"] },
14
- "architecture.decompose": { write: [".gtd/packages/**", ".gtd/ARCHITECTURE.md"] },
15
13
  "build.review": { write: [".gtd/REVIEW.md"] },
16
14
  "build.review.defer": { write: [".gtd/TODO.md"] },
17
15
  "build.review.fix.nits": {},
@@ -12,8 +12,6 @@ export const access = (
12
12
  vars: Readonly<Record<string, string>>,
13
13
  ): Readonly<Record<string, ScopeAccess>> => ({
14
14
  design: { write: [] },
15
- architecture: { write: [".gtd/REQUIREMENTS.md"] },
16
- "architecture.decompose": { write: [".gtd/packages/**", ".gtd/ARCHITECTURE.md"] },
17
15
  "build.review": { write: [".gtd/REVIEW.md"] },
18
16
  "build.review.defer": { write: [".gtd/TODO.md"] },
19
17
  // `{}` reopens what `build.review` restricted: the fixes edit code.
@@ -23,11 +23,22 @@ describe("the shipped workflow factories", () => {
23
23
  expect(defaults).toHaveProperty(`flag_${name}`, defaultOn ? "1" : "0")
24
24
  })
25
25
 
26
- it("declare seamAllow and flag_naive_pass defaults; flag_naive_pass is no option", () => {
27
- expect(Object.keys(ShippedOptions.fields)).not.toContain("flag_naive_pass")
26
+ it("declare a seamAllow default a factory option overrides", () => {
28
27
  expect(configure(feature({ seamAllow: "docs/**" }))).toMatchObject({
29
28
  ok: true,
30
- build: { defaults: { seamAllow: "docs/**", flag_naive_pass: "0" } },
29
+ build: { defaults: { seamAllow: "docs/**" } },
30
+ })
31
+ })
32
+
33
+ it("default flagMode on and lay a boolean factory option over it as a string", () => {
34
+ expect(defaults.flagMode).toBe("true")
35
+ expect(configure(feature({ flagMode: false }))).toMatchObject({
36
+ ok: true,
37
+ build: { defaults: { flagMode: "false" } },
38
+ })
39
+ expect(configure(review({ flagMode: true }))).toMatchObject({
40
+ ok: true,
41
+ build: { defaults: { flagMode: "true" } },
31
42
  })
32
43
  })
33
44