@pmelab/gtd 29.3.1 → 30.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.
Files changed (50) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +55 -63
  3. package/dist/chunks/{reserved-Dmpg6dAp.mjs → reserved-iG86IR3I.mjs} +19 -233
  4. package/dist/chunks/{tail-CLyE5VFR.mjs → tail-DA2UuJNP.mjs} +1 -1
  5. package/dist/gtd.bundle.mjs +0 -5
  6. package/dist/testkit.mjs +0 -5
  7. package/dist/workflows/cleanup.mjs +2 -2
  8. package/dist/workflows/feature.mjs +14 -180
  9. package/dist/workflows/fix.mjs +2 -2
  10. package/dist/workflows/review.mjs +2 -2
  11. package/dist/workflows/rollout.mjs +1 -1
  12. package/dist/workflows.mjs +29 -409
  13. package/package.json +1 -1
  14. package/skills/authoring/SKILL.md +15 -27
  15. package/src/cli/Cli.test.ts +6 -6
  16. package/src/edge/Edge.test.ts +7 -7
  17. package/src/flags/index.test.ts +0 -4
  18. package/src/flags/index.ts +0 -1
  19. package/src/workflow/load.test.ts +1 -1
  20. package/src/workflows/feature/fast-path.feature +1 -2
  21. package/src/workflows/feature/feature.test.ts +74 -63
  22. package/src/workflows/feature/feature.ts +13 -35
  23. package/src/workflows/feature/index.ts +0 -1
  24. package/src/workflows/feature/one-step-land.feature +4 -6
  25. package/src/workflows/feature/planning.ts +2 -27
  26. package/src/workflows/feature/refactor-absorbs.feature +1 -2
  27. package/src/workflows/feature/refactor-first.feature +1 -3
  28. package/src/workflows/feature/refactor-review.feature +0 -1
  29. package/src/workflows/feature/risk-tier.feature +2 -3
  30. package/src/workflows/feature/seam-rejection.feature +1 -3
  31. package/src/workflows/feature/seam.feature +4 -6
  32. package/src/workflows/feature/steps.test.ts +0 -20
  33. package/src/workflows/feature/steps.ts +1 -49
  34. package/src/workflows/feature/{seam-pin.feature → tier-pin.feature} +17 -11
  35. package/src/workflows/feature/tier.test.ts +3 -5
  36. package/src/workflows/feature/tier.ts +2 -2
  37. package/src/workflows/index.ts +0 -1
  38. package/src/workflows/shared/access.test.ts +0 -2
  39. package/src/workflows/shared/access.ts +0 -2
  40. package/src/workflows/shared/options.test.ts +2 -3
  41. package/src/workflows/shared/prose.ts +4 -11
  42. package/src/workflows/shared/reserved.ts +2 -2
  43. package/src/workflows/shared/skills.test.ts +0 -11
  44. package/src/workflows/shared/skills.ts +2 -9
  45. package/src/workflows/shared/steps.ts +0 -1
  46. package/src/workflows/shared/text.test.ts +4 -104
  47. package/src/workflows/shared/text.ts +15 -223
  48. package/src/workflows/shared/vars.ts +1 -3
  49. package/src/workflows/feature/packages.test.ts +0 -368
  50. package/src/workflows/feature/packages.ts +0 -173
@@ -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
@@ -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,10 @@ 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/**" } },
31
30
  })
32
31
  })
33
32
 
@@ -73,12 +73,6 @@ classified list of concerns, and hold the running product conversation
73
73
  with the human it depends on. You are read by that human — write
74
74
  plainly — not by a parser, except where a state says otherwise.`
75
75
 
76
- export const architectPersona = `You are the technical planning voice in gtd's build pipeline: take over
77
- once product concerns are settled, reading them cold, no carried
78
- conversation. Work out the *how* per concern — structure, data models,
79
- tech-stack choices, error handling — raise the technical open
80
- questions, then pin interfaces and tests in the architecture document.`
81
-
82
76
  export const reviewerPersona = `You are the independent reviewing mind in gtd's build pipeline —
83
77
  deliberately separate from whoever wrote the code, with no attachment
84
78
  to it. Write a structured review document grouping a diff into
@@ -88,11 +82,10 @@ and, when asked, fix the small nits the human flagged and the risks
88
82
  you marked yourself, each in one batch.
89
83
  Beyond that you never fix or build anything yourself.`
90
84
 
91
- export const builderPersona = `You are the TDD implementer in gtd's build pipeline: build one
92
- package's declared scope end to end, tests first, and come back to fix
85
+ export const builderPersona = `You are the TDD implementer in gtd's build pipeline: build the
86
+ task in front of you end to end, tests first, and come back to fix
93
87
  things when redirected — a failing check, or reviewer feedback. Stay
94
- strictly inside the package in front of you; never touch another
95
- package's files or code outside the task. Treat feedback as the
88
+ strictly inside that task; never touch code outside it. Treat feedback as the
96
89
  diagnosis to act on; discard it, with reason, only when simply wrong.`
97
90
 
98
91
  export const finisherPersona = `You are the closing identity in gtd's build pipeline — the last coder
@@ -136,7 +129,7 @@ export const questionBar = `- The goal is shared understanding, not a quota or a
136
129
  settle it (treat an explicit \`.gtd/TODO.md\` directive, a committed
137
130
  hand-edit, or — on a loop-back lap — the human's own review-round
138
131
  edit/note as settled); or it would be expensive to undo once
139
- packages are written
132
+ code is written
140
133
  - Where no gap in shared understanding exists, decide it yourself:
141
134
  record it under \`## Answered Questions\` as
142
135
  \`### <the point phrased as a question>\`
@@ -1,6 +1,6 @@
1
1
  import type { Summary } from "../../flows/index.js"
2
2
  import * as t from "./text.js"
3
- import { ARCHITECTURE, REQUIREMENTS, REVIEW } from "./steps.js"
3
+ import { REQUIREMENTS, REVIEW } from "./steps.js"
4
4
 
5
5
  export { defaults, envDefaults } from "./vars.js"
6
6
  export { skills } from "./skills.js"
@@ -8,4 +8,4 @@ export { access } from "./access.js"
8
8
 
9
9
  export const summary: Summary = t.summaryPrompt
10
10
 
11
- export const steering = { [REQUIREMENTS]: "qa", [ARCHITECTURE]: "qa", [REVIEW]: "review" }
11
+ export const steering = { [REQUIREMENTS]: "qa", [REVIEW]: "review" }
@@ -14,11 +14,6 @@ describe("the bundled workflow's skills export", () => {
14
14
  expect(Object.keys(bundled).sort()).toEqual(
15
15
  [
16
16
  "design",
17
- "architecture",
18
- "architecture.decompose",
19
- "packages.item",
20
- "packages.item.fix.suite",
21
- "packages.item.health",
22
17
  "build",
23
18
  "build.health",
24
19
  "build.fix.quality",
@@ -54,7 +49,6 @@ describe("the bundled workflow's skills export", () => {
54
49
 
55
50
  it("keys no group scope or non-agent step", () => {
56
51
  for (const group of [
57
- "packages.item.fix",
58
52
  "build.fix",
59
53
  "build.review.fix",
60
54
  "build.quality",
@@ -70,11 +64,6 @@ describe("the bundled workflow's skills export", () => {
70
64
  it("pins each scope's list", () => {
71
65
  expect(bundled).toMatchObject({
72
66
  design: ["spec-driven-development", "planning-and-task-breakdown"],
73
- architecture: ["api-and-interface-design", "documentation-and-adrs", "ponytail"],
74
- "architecture.decompose": ["incremental-implementation", "planning-and-task-breakdown"],
75
- "packages.item": ["test-driven-development", "incremental-implementation"],
76
- "packages.item.fix.suite": ["debugging-and-error-recovery"],
77
- "packages.item.health": ["debugging-and-error-recovery"],
78
67
  build: ["debugging-and-error-recovery"],
79
68
  "build.health": ["debugging-and-error-recovery"],
80
69
  "build.fix.quality": ["incremental-implementation", "code-simplification"],
@@ -4,7 +4,7 @@ import { lensesOf, lensScopes } from "../../workflow-kit/index.js"
4
4
  // The bundled workflow's default skills, one list per SCOPE, keyed by the
5
5
  // scope's full name — the same name a `config.skills` entry addresses. A
6
6
  // nested scope with no entry inherits its parent's; group scopes
7
- // (`packages.item.fix`, `build.fix`, `build.review.fix`, `build.quality`, `refactor.fix`) run
7
+ // (`implement.fix`, `build.fix`, `build.review.fix`, `build.quality`, `refactor.fix`) run
8
8
  // no turn and carry no key. `build.quality.<lens>` is one key per
9
9
  // `qualityReviews` entry, so the export is a function of the vars.
10
10
  export const skills = (
@@ -20,12 +20,6 @@ export const skills = (
20
20
  }
21
21
  return {
22
22
  design: ["spec-driven-development", "planning-and-task-breakdown"],
23
- architecture: ["api-and-interface-design", "documentation-and-adrs", "ponytail"],
24
- "architecture.decompose": ["incremental-implementation", "planning-and-task-breakdown"],
25
- "packages.item": ["test-driven-development", "incremental-implementation"],
26
- "packages.item.fix.suite": ["debugging-and-error-recovery"],
27
- // `health` is shared code reached from both `packages.item` and `build`.
28
- "packages.item.health": ["debugging-and-error-recovery"],
29
23
  // `fix`'s turn over the notes a review handed on.
30
24
  notes: ["incremental-implementation", "code-simplification"],
31
25
  // The refactor's own turns load `ponytail`; `refactor.build.*` carry the `build.*` lists.
@@ -34,11 +28,10 @@ export const skills = (
34
28
  refactor: ["ponytail"],
35
29
  "refactor.fix.suite": ["ponytail", "debugging-and-error-recovery"],
36
30
  "refactor.health": ["ponytail", "debugging-and-error-recovery"],
37
- // Declared whether or not `naive_pass` is on, so a config keyed on them keeps
38
- // loading when the flag flips off.
39
31
  seam: ["incremental-implementation"],
40
32
  implement: ["test-driven-development", "incremental-implementation"],
41
33
  "implement.fix.suite": ["debugging-and-error-recovery"],
34
+ // `health` is shared code reached from both `implement` and `build`.
42
35
  "implement.health": ["debugging-and-error-recovery"],
43
36
  ...lensScopes(
44
37
  "build.quality",
@@ -10,7 +10,6 @@ import * as t from "./text.js"
10
10
  export const FEEDBACK = ".gtd/FEEDBACK.md"
11
11
  export const ESCALATION = ".gtd/ESCALATION.md"
12
12
  export const REQUIREMENTS = ".gtd/REQUIREMENTS.md"
13
- export const ARCHITECTURE = ".gtd/ARCHITECTURE.md"
14
13
  export const REVIEW = ".gtd/REVIEW.md"
15
14
  export const REFACTOR = ".gtd/REFACTOR.md"
16
15
  export const QUALITY = ".gtd/QUALITY.md"
@@ -8,10 +8,6 @@ import {
8
8
  deferNotesScript,
9
9
  buildReviewReviewingPrompt,
10
10
  agentWithSkills,
11
- architectureAuthorPrompt,
12
- architectureDecomposePrompt,
13
- packagesItemBuildingPrompt,
14
- architectureGateAnswerMessage,
15
11
  buildFixPrompt,
16
12
  buildFixQualityPrompt,
17
13
  buildReviewFixNitsPrompt,
@@ -167,23 +163,6 @@ describe("the shared open-question instruction", () => {
167
163
  expect(prompt).toContain("one to four bullets, free-form")
168
164
  expect(prompt).toContain("labels, no fixed bullet count")
169
165
  })
170
-
171
- it("is the identical block, full text, in both the design gate and the architecture gate", () => {
172
- // Anchored at questionBar's own first and last lines (not a bullet
173
- // partway in) so the whole ~3.4k-char block is compared — a divergence
174
- // anywhere inside, including its opening bullets, fails this test the
175
- // moment either gate's copy drifts from the shared source.
176
- const start = "The goal is shared understanding, not a quota or an empty section"
177
- const end = "Never tick a box yourself — the human ticks exactly one per question"
178
- const sharedBlock = (prompt: string): string =>
179
- prompt.slice(prompt.indexOf(start), prompt.indexOf(end) + end.length)
180
-
181
- const designBlock = sharedBlock(renderText(() => designTriagePrompt("base")))
182
- const architectureBlock = sharedBlock(renderText(() => architectureAuthorPrompt()))
183
-
184
- expect(designBlock.length).toBeGreaterThan(3000)
185
- expect(designBlock).toBe(architectureBlock)
186
- })
187
166
  })
188
167
 
189
168
  describe("answered-entry footnote exception", () => {
@@ -196,32 +175,6 @@ describe("answered-entry footnote exception", () => {
196
175
  expect(prompt).not.toContain("never re-open a settled")
197
176
  expect(prompt).not.toContain("never re-open one")
198
177
  })
199
-
200
- it("is in the architecture return lap and keeps the first-lap settled line", () => {
201
- const prompt = renderText(() => architectureAuthorPrompt())
202
- expect(prompt).toContain(`entry stays settled, except one ${exception}`)
203
- expect(prompt).not.toContain("never re-open a settled")
204
- expect(prompt).toMatch(/treat every decision[\s\S]*as settled — never re-open it/)
205
- })
206
- })
207
-
208
- describe("architectureAuthorPrompt", () => {
209
- it("qualifies the PERMISSIVE default with a settled-requirements exception", () => {
210
- const prompt = renderText(() => architectureAuthorPrompt())
211
- expect(prompt).toContain("is an open question, not a")
212
- })
213
- it("names the four content sections in order and the entry forms", () => {
214
- const prompt = renderText(() => architectureAuthorPrompt())
215
- const at = ["## Interfaces", "## Call Stacks", "## E2E Scenarios", "## Unit Tests"].map((h) =>
216
- prompt.indexOf(h),
217
- )
218
- expect(at.every((i) => i >= 0)).toBe(true)
219
- expect([...at].sort((a, b) => a - b)).toEqual(at)
220
- expect(prompt).toContain("- unit: <path>")
221
- expect(prompt).toContain("- e2e: <path>")
222
- expect(prompt).toContain("- chore: <path>")
223
- expect(prompt).toContain("No e2e change.")
224
- })
225
178
  })
226
179
 
227
180
  describe("buildFixPrompt", () => {
@@ -688,16 +641,11 @@ Print the closing message and stop — this writes nothing itself.
688
641
  it("treats a flag-on process with no tier mark as high", () => {
689
642
  const prompt = summaryPrompt({
690
643
  ...base,
691
- vars: { flag_risk_tier: "1", flag_naive_pass: "1" },
644
+ vars: { flag_risk_tier: "1" },
692
645
  })
693
646
  expect(prompt).toContain("Risk tier: high")
694
647
  })
695
648
 
696
- it("marks no tier when the risk-tier flag is on without naive-pass", () => {
697
- const prompt = summaryPrompt({ ...base, vars: { flag_risk_tier: "1", flag_naive_pass: "0" } })
698
- expect(prompt).not.toContain("Risk tier")
699
- })
700
-
701
649
  it("says the human left no comment or edit this process when humanCommits is empty", () => {
702
650
  expect(summaryPrompt(base)).toContain(
703
651
  "The human left no comment or edit this process —\nevery commit is machine-authored.",
@@ -812,10 +760,9 @@ describe("buildReviewCollectingPrompt without a refactor", () => {
812
760
  })
813
761
 
814
762
  describe("the thread rules", () => {
815
- it("are in all three answering prompts and no longer say a footnote is human input only", () => {
763
+ it("are in both answering prompts and no longer say a footnote is human input only", () => {
816
764
  const prompts = renderText(() => [
817
765
  designTriagePrompt("base"),
818
- architectureAuthorPrompt(),
819
766
  buildReviewCollectingPrompt("capture"),
820
767
  ])
821
768
  for (const prompt of prompts) {
@@ -837,13 +784,9 @@ describe("code threads in prompts", () => {
837
784
  { path: "src/b.ts", line: 9, waitingOn: "human", first: "done", faults: [] },
838
785
  ] as const
839
786
 
840
- it("lists the code threads waiting on the agent in the three gates", () => {
787
+ it("lists the code threads waiting on the agent in both gates", () => {
841
788
  const prompts = renderText(
842
- () => [
843
- designTriagePrompt("base"),
844
- architectureAuthorPrompt(),
845
- buildReviewCollectingPrompt("capture"),
846
- ],
789
+ () => [designTriagePrompt("base"), buildReviewCollectingPrompt("capture")],
847
790
  { codeThreads: waiting },
848
791
  )
849
792
  for (const prompt of prompts) {
@@ -866,7 +809,6 @@ describe("code threads in prompts", () => {
866
809
  it("teaches the syntax once in the footnote rules", () => {
867
810
  for (const message of renderText(() => [
868
811
  designGateAnswerMessage(),
869
- architectureGateAnswerMessage(),
870
812
  buildReviewAwaitReviewMessage("base"),
871
813
  ])) {
872
814
  expect(message).toContain("gtd check --open-threads")
@@ -1306,45 +1248,3 @@ it("asks the refactor review, and only it, to flag a test-file hunk that is more
1306
1248
  expect(refactor).toContain("give any test-file hunk its own chunk")
1307
1249
  expect(first).not.toContain("give any test-file hunk its own chunk")
1308
1250
  })
1309
-
1310
- describe("architectureDecomposePrompt tests rule", () => {
1311
- it("states one rule: write-or-change, relied-on marked (unchanged), no other untouched", () => {
1312
- const prompt = renderText(() => architectureDecomposePrompt()).replace(/\s+/g, " ")
1313
- expect(prompt).toContain("List every test the package writes or changes")
1314
- expect(prompt).toContain("also list an existing test a criterion relies on")
1315
- expect(prompt).toContain("list no other untouched test")
1316
- expect(prompt).toContain("- unit: \\`<path>\\` (unchanged)")
1317
- expect(prompt).toContain("- e2e: \\`<path>\\` (unchanged)")
1318
- expect(prompt).toContain("only decompose places the marker")
1319
- })
1320
- })
1321
-
1322
- describe("packagesItemBuildingPrompt", () => {
1323
- const prompt = renderText(() => packagesItemBuildingPrompt(".gtd/packages/01-a.md")).replace(
1324
- /\s+/g,
1325
- " ",
1326
- )
1327
- it("carries the evidence kinds and the already-done check", () => {
1328
- for (const w of [
1329
- "evidence per criterion",
1330
- "commit, file, symbol, issue URL, or command output — and change nothing else",
1331
- "it was not already done",
1332
- "via `gh`",
1333
- ])
1334
- expect(prompt).toContain(w)
1335
- })
1336
- it("states the already-met, no-tests out-of-tree and implement-normally rules flat", () => {
1337
- expect(prompt).toContain("Every criterion already met in the tree")
1338
- expect(prompt).toContain("No `## Tests` and work outside the tree")
1339
- expect(prompt).toContain(
1340
- "Any other package**: implement normally, write no `.gtd/SATISFIED.md`",
1341
- )
1342
- })
1343
- it("says an (unchanged) line must exist and stay untouched", () => {
1344
- expect(prompt).toContain("(unchanged)")
1345
- expect(prompt).toContain("stay untouched")
1346
- expect(prompt).toContain("creating, editing or deleting it refuses the turn")
1347
- expect(prompt).toContain("must exist before the turn")
1348
- expect(prompt).toContain("stop without creating it")
1349
- })
1350
- })