plumbbob 0.9.5 → 0.10.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 (142) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +87 -86
  3. package/dist/cli-core.js +8 -8
  4. package/dist/cli.js +1 -1
  5. package/dist/lib/agents.js +26 -26
  6. package/dist/lib/buildlog.js +11 -11
  7. package/dist/lib/buildlogsync.js +8 -8
  8. package/dist/lib/check.js +14 -14
  9. package/dist/lib/commitbody.js +72 -0
  10. package/dist/lib/commitmsg.js +7 -7
  11. package/dist/lib/git.js +44 -15
  12. package/dist/lib/intent.js +20 -19
  13. package/dist/lib/latch.js +16 -16
  14. package/dist/lib/orient.js +36 -17
  15. package/dist/lib/reentry.js +3 -3
  16. package/dist/lib/settings.js +16 -16
  17. package/dist/lib/sidecar.js +54 -54
  18. package/dist/lib/templates.js +1 -1
  19. package/dist/verbs/agent.js +25 -25
  20. package/dist/verbs/build.js +9 -9
  21. package/dist/verbs/check.js +6 -6
  22. package/dist/verbs/checkpoint.js +48 -47
  23. package/dist/verbs/doctor.js +27 -26
  24. package/dist/verbs/finish.js +27 -40
  25. package/dist/verbs/handoff.js +9 -8
  26. package/dist/verbs/init.js +9 -9
  27. package/dist/verbs/park.js +3 -3
  28. package/dist/verbs/recover.js +11 -11
  29. package/dist/verbs/revert.js +12 -12
  30. package/dist/verbs/spike.js +17 -17
  31. package/dist/verbs/start.js +49 -19
  32. package/dist/verbs/status.js +8 -8
  33. package/dist/verbs/turn.js +16 -16
  34. package/dist/verbs/use.js +4 -4
  35. package/node_modules/checkride/.claude-plugin/plugin.json +1 -1
  36. package/node_modules/checkride/CHANGELOG.md +401 -0
  37. package/node_modules/checkride/README.md +27 -9
  38. package/node_modules/checkride/dist/adapters.d.ts +12 -4
  39. package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
  40. package/node_modules/checkride/dist/adapters.js +21 -1
  41. package/node_modules/checkride/dist/adapters.js.map +1 -1
  42. package/node_modules/checkride/dist/agent-setup/cursor.d.ts +9 -1
  43. package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -1
  44. package/node_modules/checkride/dist/agent-setup/cursor.js +59 -1
  45. package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -1
  46. package/node_modules/checkride/dist/agent-setup/harness.d.ts +1 -1
  47. package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -1
  48. package/node_modules/checkride/dist/agent-setup/harness.js +10 -1
  49. package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -1
  50. package/node_modules/checkride/dist/agent-setup/scripts.d.ts +23 -0
  51. package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -1
  52. package/node_modules/checkride/dist/agent-setup/scripts.js +387 -82
  53. package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -1
  54. package/node_modules/checkride/dist/baseline/fallow.js +2 -2
  55. package/node_modules/checkride/dist/baseline/fingerprint.d.ts +14 -5
  56. package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
  57. package/node_modules/checkride/dist/baseline/fingerprint.js +58 -5
  58. package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
  59. package/node_modules/checkride/dist/baseline/history.d.ts +98 -0
  60. package/node_modules/checkride/dist/baseline/history.d.ts.map +1 -0
  61. package/node_modules/checkride/dist/baseline/history.js +232 -0
  62. package/node_modules/checkride/dist/baseline/history.js.map +1 -0
  63. package/node_modules/checkride/dist/baseline/index.d.ts +4 -2
  64. package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
  65. package/node_modules/checkride/dist/baseline/index.js +2 -1
  66. package/node_modules/checkride/dist/baseline/index.js.map +1 -1
  67. package/node_modules/checkride/dist/baseline/store.d.ts +30 -7
  68. package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
  69. package/node_modules/checkride/dist/baseline/store.js +50 -16
  70. package/node_modules/checkride/dist/baseline/store.js.map +1 -1
  71. package/node_modules/checkride/dist/cli.d.ts +5 -1
  72. package/node_modules/checkride/dist/cli.d.ts.map +1 -1
  73. package/node_modules/checkride/dist/cli.js +98 -25
  74. package/node_modules/checkride/dist/cli.js.map +1 -1
  75. package/node_modules/checkride/dist/config.d.ts +33 -4
  76. package/node_modules/checkride/dist/config.d.ts.map +1 -1
  77. package/node_modules/checkride/dist/config.js +21 -6
  78. package/node_modules/checkride/dist/config.js.map +1 -1
  79. package/node_modules/checkride/dist/digest/digest.js +1 -1
  80. package/node_modules/checkride/dist/doctor.d.ts +2 -0
  81. package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
  82. package/node_modules/checkride/dist/doctor.js +39 -1
  83. package/node_modules/checkride/dist/doctor.js.map +1 -1
  84. package/node_modules/checkride/dist/gate.d.ts +49 -4
  85. package/node_modules/checkride/dist/gate.d.ts.map +1 -1
  86. package/node_modules/checkride/dist/gate.js +143 -16
  87. package/node_modules/checkride/dist/gate.js.map +1 -1
  88. package/node_modules/checkride/dist/init.d.ts +8 -1
  89. package/node_modules/checkride/dist/init.d.ts.map +1 -1
  90. package/node_modules/checkride/dist/init.js +68 -7
  91. package/node_modules/checkride/dist/init.js.map +1 -1
  92. package/node_modules/checkride/dist/node-pin.d.ts +1 -1
  93. package/node_modules/checkride/dist/node-pin.js +1 -1
  94. package/node_modules/checkride/dist/orchestrator.d.ts +13 -0
  95. package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
  96. package/node_modules/checkride/dist/orchestrator.js +118 -13
  97. package/node_modules/checkride/dist/orchestrator.js.map +1 -1
  98. package/node_modules/checkride/dist/pm/index.d.ts +1 -0
  99. package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
  100. package/node_modules/checkride/dist/pm/index.js.map +1 -1
  101. package/node_modules/checkride/dist/pm/launch.d.ts +23 -2
  102. package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -1
  103. package/node_modules/checkride/dist/pm/launch.js +16 -0
  104. package/node_modules/checkride/dist/pm/launch.js.map +1 -1
  105. package/node_modules/checkride/dist/pm/translate.js +1 -1
  106. package/node_modules/checkride/dist/pm/translate.js.map +1 -1
  107. package/node_modules/checkride/dist/qa/mutation.d.ts +4 -4
  108. package/node_modules/checkride/dist/qa/mutation.js +4 -4
  109. package/node_modules/checkride/dist/recover.d.ts +48 -0
  110. package/node_modules/checkride/dist/recover.d.ts.map +1 -0
  111. package/node_modules/checkride/dist/recover.js +220 -0
  112. package/node_modules/checkride/dist/recover.js.map +1 -0
  113. package/node_modules/checkride/dist/smoke.d.ts +1 -1
  114. package/node_modules/checkride/dist/smoke.js +1 -1
  115. package/node_modules/checkride/dist/snippets.d.ts +1 -1
  116. package/node_modules/checkride/package.json +3 -2
  117. package/node_modules/checkride/schema/checkride.config.schema.json +9 -1
  118. package/node_modules/checkride/skills/check/SKILL.md +9 -1
  119. package/node_modules/checkride/templates/shared/styles/Repo/Drift.yml +41 -0
  120. package/node_modules/checkride/templates/shared/styles/Repo/Latin.yml +14 -0
  121. package/node_modules/checkride/templates/shared/styles/Repo/LyHyphen.yml +28 -0
  122. package/node_modules/checkride/templates/shared/styles/Repo/Minted.yml +33 -0
  123. package/node_modules/checkride/templates/shared/styles/Repo/ThereIs.yml +16 -0
  124. package/node_modules/checkride/templates/shared/styles/Repo/Weasel.yml +26 -0
  125. package/node_modules/checkride/templates/shared/vale.ini +34 -0
  126. package/package.json +10 -9
  127. package/skills/build/SKILL.md +69 -64
  128. package/skills/doctor/SKILL.md +11 -11
  129. package/skills/finish/SKILL.md +20 -19
  130. package/skills/harvest/SKILL.md +13 -12
  131. package/skills/park/SKILL.md +10 -10
  132. package/skills/plan/SKILL.md +63 -54
  133. package/skills/recover/SKILL.md +6 -6
  134. package/skills/refine/SKILL.md +18 -16
  135. package/skills/revert/SKILL.md +6 -6
  136. package/skills/spike/SKILL.md +9 -9
  137. package/skills/status/SKILL.md +5 -5
  138. package/skills/step/SKILL.md +17 -12
  139. package/skills/verify/SKILL.md +45 -40
  140. package/templates/build-log.md +7 -7
  141. package/templates/intent.md +49 -39
  142. package/templates/spike-report.md +10 -10
@@ -1,29 +1,29 @@
1
1
  ---
2
2
  name: spike
3
- description: Human-triggered driver for `plumbbob spike` — open a throwaway worktree experiment for a genuine fork, scaffold a spike report for a spike-as-step, or tear it down with `spike done`.
3
+ description: "Human-triggered driver for `plumbbob spike`: open a throwaway worktree experiment for a genuine fork, scaffold a spike report for a spike-as-step, or tear it down with `spike done`."
4
4
  argument-hint: "<slug> | report <slug> | done"
5
5
  disable-model-invocation: true
6
6
  model: haiku
7
7
  allowed-tools: Bash(plumbbob status:*), Bash(plumbbob spike:*)
8
8
  ---
9
9
 
10
- # PlumbBob — spike an experiment (driver)
10
+ # PlumbBob: spike an experiment (driver)
11
11
 
12
12
  Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
13
13
 
14
- This is a **driver skill** — a chat-side trigger for the mechanical `plumbbob spike` verb, so the whole workflow runs from the agent window instead of a terminal. It is `disable-model-invocation: true`: only the human fires it. It carries **no Edit and no Write tool** — its only action is to shell the verb and report the verb's output verbatim, including any refusal. The CLI is the source of truth: never retry a refused transition, and never edit a file to work around one.
14
+ This is a **driver skill**: a chat-side trigger for the mechanical `plumbbob spike` verb, so the whole workflow runs from the agent window instead of a terminal. It is `disable-model-invocation: true`: only the human fires it. It carries **no Edit and no Write tool**; its only action is to shell the verb and report the verb's output verbatim, including any refusal. The CLI is the source of truth: never retry a refused transition, and never edit a file to work around one.
15
15
 
16
16
  ## What it does
17
17
 
18
- 1. Read the spike target from the way you were invoked: a slug to open one (e.g. `/plumbbob:spike redis-cache`), `report <slug>` to scaffold a report without worktrees (`/plumbbob:spike report auth-store`), or the literal `done` to tear the current spike down (`/plumbbob:spike done`). If none is present, ask which and run nothing.
18
+ 1. Read the spike target from the way you were invoked: a slug to open one (for example `/plumbbob:spike redis-cache`), `report <slug>` to scaffold a report without worktrees (`/plumbbob:spike report auth-store`), or the literal `done` to tear the current spike down (`/plumbbob:spike done`). If none is present, ask which and run nothing.
19
19
  2. Run `plumbbob spike "<slug>"`, `plumbbob spike report "<slug>"`, or `plumbbob spike done` via Bash.
20
- 3. Report the verb's output verbatim — the worktree it created or removed, the spike report it scaffolded, or any refusal. When the verb names a `spike-NN-<slug>.md` report, point the human at it; when `spike done` nudges that a verdict is unrecorded, relay that nudge verbatim.
20
+ 3. Report the verb's output verbatim: the worktree it created or removed, the spike report it scaffolded, or any refusal. When the verb names a `spike-NN-<slug>.md` report, point the human at it; when `spike done` nudges that a verdict is unrecorded, relay that nudge verbatim.
21
21
 
22
- ## The spike report — D70 (spike-reports)
22
+ ## The spike report ([D70 (spike-reports)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d70))
23
23
 
24
- Every spike leaves a durable `spike-NN-<slug>.md` in the build folder, beside `intent.md`/`report.md`, so the fork's verdict rides the branch into the PR instead of evaporating. The CLI scaffolds it from a template and numbers it — you never create or number the file:
24
+ Every spike leaves a durable `spike-NN-<slug>.md` in the build folder, beside `intent.md`/`report.md`, so the fork's verdict rides the branch into the PR instead of evaporating. The CLI scaffolds it from a template and numbers it; you never create or number the file:
25
25
 
26
26
  - **`/plumbbob:spike <slug>`** scaffolds the report *at open*, so findings accrue while the throwaway worktrees are still live. Fill its **Findings** and **Verdict** before `/plumbbob:spike done`.
27
- - **`/plumbbob:spike report <slug>`** is for a *spike-as-step* — a planned step titled `spike: …`, where the increment itself is the experiment and there are no worktrees. It stamps the report's provenance as `step <n>` when a step is in flight.
27
+ - **`/plumbbob:spike report <slug>`** is for a *spike-as-step*: a planned step titled `spike: …`, where the increment itself is the experiment and there are no worktrees. It stamps the report's provenance as `step <n>` when a step is in flight.
28
28
 
29
- This skill stays Write-less: the CLI owns the file. Your job is to run the verb and, between runs, help the human fill the report's prose — but the edits land through the normal build flow, not this driver.
29
+ This skill stays Write-less: the CLI owns the file. Your job is to run the verb and, between runs, help the human fill the report's prose, but the edits land through the normal build flow, not this driver.
@@ -1,26 +1,26 @@
1
1
  ---
2
2
  name: status
3
- description: Show the orientation dashboard — where you are, what's done, what's parked, and the next move. A thin trigger for `plumbbob status`.
3
+ description: "Show the orientation dashboard: where you are, what's done, what's parked, and the next move. A thin trigger for `plumbbob status`."
4
4
  disable-model-invocation: true
5
5
  model: haiku
6
6
  allowed-tools: Bash(plumbbob status:*)
7
7
  ---
8
8
 
9
- # PlumbBob — orient (the where-am-I move)
9
+ # PlumbBob: orient (the where-am-I move)
10
10
 
11
11
  Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
12
12
 
13
13
  This is a **thin driver** for `plumbbob status`. The dashboard above is your
14
- orientation — the intent, the step list, the parked/open-question counts, and the
14
+ orientation: the intent, the step list, the parked/open-question counts, and the
15
15
  inferred next move. Report it verbatim and point the human at that next move. This
16
16
  skill carries **no Edit and no Write tool**: the CLI is the source of truth, so
17
17
  **never retry**, and never edit a file to change what the orientation says.
18
18
 
19
19
  ## What it does
20
20
 
21
- 1. Surface the injected `status` output — the dashboard and its suggested next move.
21
+ 1. Surface the injected `status` output: the dashboard and its suggested next move.
22
22
  2. If the next step's detail carries a `model:` line, point it out: it is the
23
23
  plan's recommendation of the smallest model that can carry that step, so the human
24
- can switch (e.g. `/model sonnet`) before firing `/plumbbob:build` — or ignore it. Guidance,
24
+ can switch (for example `/model sonnet`) before firing `/plumbbob:build`, or ignore it. Guidance,
25
25
  never a gate.
26
26
  3. If it reads `NO ACTIVE SESSION`, tell the human to `/plumbbob:plan` to frame a goal.
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: step
3
- description: Revise the next increment just-in-time — sharpen the next undone step against what's now true, or (with input) re-cut, split, or add a step. Empty input runs an automatic sharpen. One at a time; the human approves.
3
+ description: "Revise the next increment just-in-time: sharpen the next undone step against what's now true, or (with input) re-cut, split, or add a step. Empty input runs an automatic sharpen. One at a time; the human approves."
4
4
  argument-hint: "[what-changed]"
5
5
  disable-model-invocation: true
6
6
  allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob agent list:*)
7
7
  ---
8
8
 
9
- # PlumbBob — revise the next step (the single-increment move)
9
+ # PlumbBob: revise the next step (the single-increment move)
10
10
 
11
11
  Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
12
12
 
@@ -14,14 +14,14 @@ Current session state (injected when this skill runs): !`plumbbob status 2>/dev/
14
14
  **just-in-time revision** move: it keeps the *next* undone step honest against what the
15
15
  build has actually taught you, right before you `/plumbbob:build` it. (Framing the whole goal
16
16
  is the separate `/plumbbob:plan` move.) It can also add or re-cut a step when scope genuinely
17
- grew — but its everyday job is to sharpen, not to invent.
17
+ grew, but its everyday job is to sharpen, not to invent.
18
18
 
19
19
  ## Two ways to run it
20
20
 
21
21
  - **`/plumbbob:step` (no input) → automatic sharpen.** Re-examine the next undone step
22
22
  against the completed code, the Decisions, the Constraints, and the build-log, then
23
- make the obvious revisions to its **done-when** and **seam** so it matches reality —
24
- e.g. a file moved, a decision narrowed the scope, an earlier step already did part of
23
+ make the obvious revisions to its **done-when** and **seam** so it matches reality:
24
+ for example a file moved, a decision narrowed the scope, an earlier step already did part of
25
25
  it. This is the zero-effort "keep my next step in sync" move: if the human does
26
26
  nothing else, the next step stays current.
27
27
  - **`/plumbbob:step <what changed>` → directed revision.** Take the human's input and propose
@@ -38,21 +38,21 @@ grew — but its everyday job is to sharpen, not to invent.
38
38
  what you changed and why. Re-check the optional `- model:` recommendation too:
39
39
  a step that sharpened into rote work can drop to a smaller model; one that grew subtle
40
40
  earns a frontier one. Advisory, plain text (no backticks), never a gate.
41
- 3. **Get the human's OK**, then write it into `## Steps` in the standard format —
42
- `N. [ ] <title> — **done when:** <criterion>` with a `- seam:` sub-line. Keep the
41
+ 3. **Get the human's OK**, then write it into `## Steps` in the standard format:
42
+ `N. [ ] <title>, **done when:** <criterion>` with a `- seam:` sub-line. Keep the
43
43
  sharpened `<title>` a plain, single-line Conventional-Commit subject,
44
- `type(scope): description` — it lands in `git log` verbatim, so as the step tightens
44
+ `type(scope): description`; it lands in `git log` verbatim, so as the step tightens
45
45
  keep load-bearing detail (file paths, module names) in `seam` and `done-when`,
46
46
  **never jammed into the title**. A sharpened step carries its own `(scope)`
47
- when it touches a distinct code area — one that **overrides the build-default**
47
+ when it touches a distinct code area, one that **overrides the build-default**
48
48
  `**Scope:**` header; drop the scope and it falls back to that default → build slug →
49
- bare, and the type to `feat` ([D68 (conventional-subjects)](../../docs/decisions.md#d68)). Aim for a soft
49
+ bare, and the type to `feat` ([D68 (conventional-subjects)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d68)). Aim for a soft
50
50
  ≤72 chars, no gate. Revise the existing step in place; only append when you are
51
51
  genuinely adding an increment.
52
52
  4. **Revise the step's harness bindings if they drifted too** *(optional)*. If the
53
53
  build carries a `harness.json` (beside `intent.md`) and the reality that moved the
54
54
  step also changed which agents it wants, sharpen that step's slot bindings
55
- (`before`/`build`/`after`) and `note` at the same time — this is the just-in-time
55
+ (`before`/`build`/`after`) and `note` at the same time; this is the just-in-time
56
56
  counterpart to `/plumbbob:plan`'s plan-time binding. `plumbbob agent list` shows what's
57
57
  resolvable. Same rule as the plan move: bindings + prose only, never a conditional
58
58
  . Leave it untouched when the step's agents are still right, or when the build
@@ -62,6 +62,11 @@ grew — but its everyday job is to sharpen, not to invent.
62
62
 
63
63
  - **One verifiable increment.** Each step carries a done-when `/plumbbob:verify` can check
64
64
  and a seam small enough to review in one pass.
65
- - **Edit `## Steps` only**, in the standard format `status` and `build` parse — never
65
+ - **Edit `## Steps` only**, in the standard format `status` and `build` parse: never
66
66
  the Roadmap, never loose prose. A done step (`[x]`) is history; do not rewrite it.
67
+ - **Cite the plan's own numbers in the linked form.** A `D`/`C`/`Q` you write into a
68
+ step's done-when, seam, or notes reads `[D4 (default-waves)](#d4)`; the slug travels
69
+ with the number, and the link lands on the `<a id="d4">` anchor minted where the item
70
+ was born. Never a bare `D4`; if the item you want to cite has no anchor yet, that is a
71
+ `/plumbbob:refine` repair, not something to invent here.
67
72
  - **The human approves the revision** before it lands. You propose; they decide.
@@ -1,69 +1,69 @@
1
1
  ---
2
2
  name: verify
3
- description: "The verify tick — run the check, self-review the diff against intent, validate the step's done-when, pause for your approval, then checkpoint. Executor-agnostic: it reads the diff, not who wrote it."
3
+ description: "The verify tick: run the check, self-review the diff against intent, validate the step's done-when, pause for your approval, then checkpoint. Executor-agnostic: it reads the diff, not who wrote it."
4
4
  disable-model-invocation: true
5
5
  allowed-tools: Read, Bash(plumbbob status:*), Bash(plumbbob handoff:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*), Bash(git status:*)
6
6
  ---
7
7
 
8
- # PlumbBob — verify a step (the tick)
8
+ # PlumbBob: verify a step (the tick)
9
9
 
10
10
  Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
11
11
 
12
- This is the **tick** — the one beat where the human is the clock. Whatever produced
13
- the current diff — `/plumbbob:build`, your own hands, a vibe session, another harness —
14
- this skill verifies it the same way: **it reads the diff, not the author** — D3
15
- (author-blind-executor).
12
+ This is the **tick**: the one beat where the human is the clock. Whatever produced
13
+ the current diff (`/plumbbob:build`, your own hands, a vibe session, another harness),
14
+ this skill verifies it the same way: **it reads the diff, not the author**
15
+ ([D3 (author-blind-executor)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d3)).
16
16
 
17
17
  ## What this skill does, in order
18
18
 
19
- 1. **Check.** Run `plumbbob check` (the heavy gate — checkride unless the repo
19
+ 1. **Check.** Run `plumbbob check` (the heavy gate: checkride unless the repo
20
20
  configures a `check` override). If it comes back **red**, stop here: the gate
21
- names the failing slots and where each tool's raw output landed — read
21
+ names the failing slots and where each tool's raw output landed: read
22
22
  `.check/summary.json`, then the failing slot's own file (`.check/<slot>.json` or
23
23
  `.check/<slot>.stdout.txt`) for the actual diagnostics instead of scraping
24
- scrollback. Report what failed and do **not** pause for approval — there is
24
+ scrollback. Report what failed and do **not** pause for approval; there is
25
25
  nothing to approve yet. The human fixes it and re-invokes. (Exit 2 means the gate
26
- itself broke — a harness problem to surface, not a code failure.)
26
+ itself broke: a harness problem to surface, not a code failure.)
27
27
  2. **Run any bound `after`-agents** *(optional)*. If the build's `harness.json`
28
28
  binds agents to this step's `after` slot, run `plumbbob agent run --step <n> --mode
29
- after`. Their envelopes are **advisory input to the self-review, never a gate** —
29
+ after`. Their envelopes are **advisory input to the self-review, never a gate**;
30
30
  `plumbbob check` already gated in step 1, and an `after`-agent that could fail a step
31
31
  would be the old lock back in another form. Fold a `done` envelope's
32
- `summary`/`body` into the review below; route a non-`done` one by its status: a
33
- `blocked` agent couldn't finish — surface its `notes`, let the human unblock, re-run;
34
- a `drift` agent found the plan no longer matches reality — stop and send the human to
32
+ `summary`/`body` into the review below; route a non-`done` one by its status. A
33
+ `blocked` agent couldn't finish: surface its `notes`, let the human unblock, re-run.
34
+ A `drift` agent found the plan no longer matches reality: stop and send the human to
35
35
  `/plumbbob:refine` to repair the plan before checkpointing. No binding, or no harness, is a
36
36
  clean no-op.
37
37
  3. **Self-review** *(a single structured read)*. Read `git diff` and
38
38
  `.plumbbob/intent.md`, then in one pass check the diff against:
39
- - the current step's **done-when** criterion — is it actually met?
40
- - the **Decisions** — does anything contradict a settled call?
41
- - the **Constraints** — are any violated?
42
- - any **`after`-agent findings** from step 2 — advisory, weigh them, don't defer to them.
39
+ - the current step's **done-when** criterion: is it actually met?
40
+ - the **Decisions**: does anything contradict a settled call?
41
+ - the **Constraints**: are any violated?
42
+ - any **`after`-agent findings** from step 2: advisory, weigh them, don't defer to them.
43
43
  Surface every mismatch plainly, and when you cite a Decision or Constraint, carry its
44
- slug from `intent.md` — `C1 (no-new-deps)`, never a bare `C1` — so each finding reads
45
- on its own. You are reviewing, not building — do not fix anything.
44
+ slug from `intent.md` (`C1 (no-new-deps)`, never a bare `C1`) so each finding reads
45
+ on its own. You are reviewing, not building; do not fix anything.
46
46
  4. **Validate.** State, yes or no, whether the step's done-when is met, with the evidence.
47
47
  5. **PAUSE.** Present the check result, the self-review (with any `after`-agent
48
48
  findings), and the validation, then
49
49
  **stop and wait for the human's explicit approval.** This is the convergence beat;
50
50
  the human is the clock. Never checkpoint without it.
51
51
  - **Reconcile a drifted subject here, in the open.** The planned title *is* the
52
- checkpoint subject — D68 (conventional-subjects). If the diff drifted from it — the
53
- step landed something the title no longer describes — the body pass may propose a
52
+ checkpoint subject ([D68 (conventional-subjects)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d68)). If the diff drifted from it (the
53
+ step landed something the title no longer describes), the body pass may propose a
54
54
  corrected subject, but it **presents** it at this pause for explicit approval: show
55
55
  `planned title → proposed subject`, one line, as part of what the human OKs. This is
56
56
  the exception, not the default: with **nothing presented**, the deterministic
57
57
  title-derived subject lands untouched. A silent `-m` swap is exactly the
58
- agent-authored subject D68 (conventional-subjects) refuses — so a reconcile is
58
+ agent-authored subject [D68 (conventional-subjects)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d68) refuses, so a reconcile is
59
59
  *only ever* the visible, approved kind.
60
60
  6. **Checkpoint** *(only after approval)*. Run `plumbbob checkpoint`: it makes the WIP
61
61
  commit, records the SHA, flips the step to done, appends the step to the build-log's
62
- `## Log`, and returns to DESIGN. The CLI owns the commit **subject** — a Conventional
63
- `<type>(<scope>): <description>` composed from the step title and the build slug — and
62
+ `## Log`, and returns to DESIGN. The CLI owns the commit **subject** (a Conventional
63
+ `<type>(<scope>): <description>` composed from the step title and the build slug) and
64
64
  leads the **body** with a `plumbbob step N` marker; you own the rest of the **body**.
65
- Compose a body *proportional to the step* — a one-liner for a trivial change, a short
66
- paragraph on the what/why for a meatier one — and pass it on stdin:
65
+ Compose a body *proportional to the step* (a one-liner for a trivial change, a short
66
+ paragraph on the what/why for a meatier one) and pass it on stdin:
67
67
 
68
68
  ```bash
69
69
  plumbbob checkpoint <n> --body <<'BODY'
@@ -71,11 +71,16 @@ this skill verifies it the same way: **it reads the diff, not the author** — D
71
71
  BODY
72
72
  ```
73
73
 
74
- Do **not** run a TIL scan or reach for a separate commit skill — the body is yours to
74
+ Redirect the heredoc *into* the command (`--body <<'BODY'`). Do **not** pass it as
75
+ an argument value (`--body "$(cat <<'BODY'…)"`): `--body` ignores an argument and
76
+ always reads stdin. Under an agent harness that stdin is a socket, and `--body` now
77
+ refuses rather than blocking on one; the refusal names this exact heredoc form.
78
+
79
+ Do **not** run a TIL scan or reach for a separate commit skill; the body is yours to
75
80
  write in one breath. Omit `--body` entirely and the CLI writes a deterministic body
76
81
  (done-when + seam + diffstat) on its own. Either way, do **not** bump the version or
77
- touch the changelog — that is the human's `/version` call. And if step 5 surfaced a
78
- drifted subject the human approved, land *that* subject by adding `-m "<subject>"` —
82
+ touch the changelog; that is the human's `/version` call. And if step 5 surfaced a
83
+ drifted subject the human approved, land *that* subject by adding `-m "<subject>"`,
79
84
  overriding the title-derived default for this one commit; unpresented, the CLI's
80
85
  deterministic subject stands.
81
86
  7. **Hand off with the next model** *(once the checkpoint lands)*. `plumbbob checkpoint`
@@ -91,17 +96,17 @@ this skill verifies it the same way: **it reads the diff, not the author** — D
91
96
  ## The latch makes the pause real
92
97
 
93
98
  When this session runs under plumbbob's turn hook, `plumbbob checkpoint` **refuses to
94
- land a step in the same turn it was entered** — and that refusal **is** this pause, not
95
- an error to route around. If the checkpoint prints *"checkpoint refused — no human turn
96
- since this step began,"* you have reached the pause the hard way: present the diff and
99
+ land a step in the same turn it was entered**, and that refusal **is** this pause, not
100
+ an error to route around. If the checkpoint prints `checkpoint refused — no human turn
101
+ since this step began`, you have reached the pause the hard way: present the diff and
97
102
  the self-review, **end the turn**, and the human's next message is the tick that lets
98
103
  the checkpoint land when you run it again. **Never reach for a raw `git commit` to force the
99
- land** — that forges the very record the latch exists to keep honest, and the
104
+ land**; that forges the very record the latch exists to keep honest, and the
100
105
  commit-ask hook asks the human about it anyway. The refusal is a healthy latch doing its
101
106
  job on the *record* while the *work* plane stays free; a `/plumbbob:build --auto` or
102
- a typed step range in the human's own prompt is the only self-approval — **never write
107
+ a typed step range in the human's own prompt is the only self-approval; **never write
103
108
  `auto` into a settings file to unlock the land; the latch ignores a model-minted grant
104
- — D67 (auto-not-a-grant) — so ask the human to type `/plumbbob:build --auto` again
109
+ ([D67 (auto-not-a-grant)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d67)), so ask the human to type `/plumbbob:build --auto` again
105
110
  instead.**
106
111
 
107
112
  ## The hard contracts
@@ -113,15 +118,15 @@ instead.**
113
118
  - **Red means stop, not pause.** A failing check is not an approval decision; report
114
119
  it and end your turn.
115
120
  - **You review; you do not build.** If the self-review finds a problem, surface it
116
- and stop — fixing is a new build beat, not part of verify.
121
+ and stop; fixing is a new build beat, not part of verify.
117
122
  - **`after`-agents advise; they never gate**. Their output feeds the
118
- self-review — checkride gates, the human approves. `blocked` → unblock and re-run;
123
+ self-review; checkride gates, the human approves. `blocked` → unblock and re-run;
119
124
  `drift` → `/plumbbob:refine` before checkpointing. No code path makes them blocking.
120
125
  - **A refused checkpoint is the pause, never a workaround.** Under the turn
121
- hook a same-turn checkpoint is refused *by design* — present the diff, **end the
126
+ hook a same-turn checkpoint is refused *by design*: present the diff, **end the
122
127
  turn**, and let the human's next message re-tick it. Never route around it with a raw
123
128
  `git commit`; the latch guards the record, not the work.
124
129
  - **Close with the next model.** After the checkpoint lands, run `plumbbob handoff` and
125
- relay its block — it cites the completed step and the next undone step, and surfaces that
130
+ relay its block; it cites the completed step and the next undone step, and surfaces that
126
131
  next step's `- model:` recommendation when it has one, which is what a fresh context
127
132
  window needs to pick the right `/model`. Guidance, never a gate.
@@ -1,26 +1,26 @@
1
1
  <!--
2
- build-log.md — your live ledger for execution. Append constantly; reorganize at
2
+ build-log.md: your live ledger for execution. Append constantly; reorganize at
3
3
  step boundaries. The antidote to "my plan got lost in the noise."
4
4
 
5
5
  Steps : where you are. One step in flight at a time. CLI-maintained: `build`,
6
6
  `checkpoint`, and `revert` keep this mirror and the Current step line
7
- in sync with intent.md — you never hand-edit them.
7
+ in sync with intent.md; you never hand-edit them.
8
8
  Park list : where ideas go so you do not chase them. CAPTURE, never act inline.
9
9
  Harvest : the boundary ritual that keeps you on one branch.
10
10
  Log : the build's history. `plumbbob checkpoint` appends a line per step as it
11
11
  lands; feeds the /plumbbob:finish report, which rides the branch into the PR.
12
12
  -->
13
13
 
14
- # Build log — {{TITLE}}
14
+ # Build log: {{TITLE}}
15
15
 
16
16
  **Current step:** none (at the boundary)
17
17
  **Heavy check:** {{CHECK}}
18
18
 
19
19
  ## Steps
20
20
 
21
- *(Mirror of intent.md's Steps, with live status — CLI-maintained, not hand-edited.
21
+ *(Mirror of intent.md's Steps, with live status; CLI-maintained, not hand-edited.
22
22
  `build`/`checkpoint`/`revert` re-render this from intent.md, and set the Current step
23
- line above. Only ONE step is in flight; a step is done only after a checkpoint —
23
+ line above. Only ONE step is in flight; a step is done only after a checkpoint:
24
24
  check green + checkpoint taken, via `/plumbbob:verify` or `/plumbbob:build`.)*
25
25
 
26
26
  - ☐ 1. <step>
@@ -52,8 +52,8 @@ Harvest results this boundary:
52
52
  ## Log
53
53
 
54
54
  *(The build's history, oldest first. `plumbbob checkpoint` appends a dated line here
55
- every time a step lands — via `/plumbbob:build` or `/plumbbob:verify` — so this
55
+ every time a step lands (via `/plumbbob:build` or `/plumbbob:verify`), so this
56
56
  fills in as you go, not at the end. Add your own decision/event lines too: this is what
57
- you point at to say "I did that — the LLM helped, but those were my calls."
57
+ you point at to say "I did that: the LLM helped, but those were my calls."
58
58
  `/plumbbob:finish` reads this for the report; `plumbbob finish` commits it with the build
59
59
  folder, so it rides the branch into the PR.)*
@@ -1,5 +1,5 @@
1
1
  <!--
2
- intent.md — your canonical intent, written in DESIGN before any code. This is the
2
+ intent.md: your canonical intent, written in DESIGN before any code. This is the
3
3
  head; the chat is the hand. When the model floods you, read this, not your memory.
4
4
 
5
5
  Size to the work: a small change fills Frame + a couple of Decisions and deletes
@@ -7,8 +7,8 @@ the rest; a medium feature fills it all. Opinionated where decided, explicit whe
7
7
  open. If the implementor (you-later, or the LLM) has to guess, the doc failed.
8
8
 
9
9
  One rule runs through the whole doc: compress what's settled; expand what's pending.
10
- Decisions and Constraints stay one line each — they re-inject into every build step,
11
- so their tokens recur. Open questions expand into plain-then-lean prose — a human
10
+ Decisions and Constraints stay one line each; they re-inject into every build step,
11
+ so their tokens recur. Open questions expand into plain-then-lean prose; a human
12
12
  reads them once, to decide, and that legibility buys back a chat round-trip.
13
13
  -->
14
14
 
@@ -16,11 +16,11 @@ reads them once, to decide, and that legibility buys back a chat round-trip.
16
16
 
17
17
  **Phase** (your own bookkeeping while framing): frame
18
18
  **Size:** tiny | small | medium
19
- **Scope:** <short-scope> <!-- the build's default commit scope — D68 (conventional-subjects): a short feature-level name each step's own `(scope)` overrides. Leave the `<…>` placeholder (or blank) and it parses as absent — commits fall through to the build slug. -->
19
+ **Scope:** <short-scope> <!-- the build's default commit scope (plumbbob [D68 (conventional-subjects)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d68)): a short feature-level name each step's own `(scope)` overrides. Leave the `<…>` placeholder (or blank) and it parses as absent; commits fall through to the build slug. -->
20
20
 
21
21
  ## Frame
22
22
 
23
- *(You, on paper first. The problem in plain words — before any solution.)*
23
+ *(You, on paper first. The problem in plain words, before any solution.)*
24
24
 
25
25
  - **Problem:** <what is wrong or missing, and why it matters>
26
26
  - **Smallest thing that solves it:** <the minimal change, not the ideal system>
@@ -37,32 +37,34 @@ reads them once, to decide, and that legibility buys back a chat round-trip.
37
37
 
38
38
  ## Decisions
39
39
 
40
- *(One line each — settled, not re-litigated in the chat. Grows as you resolve the
41
- holes `/plumbbob:refine` surfaces, and as blockers fold in during BUILD. Mint a two- or
42
- three-word slug where each item is born — `D1 (slug-here)` — and copy that slug at
43
- every reference site, so a later `D4 (default-waves)` never decays into a bare `D4`
44
- a cold reader has to hunt down.)*
40
+ *(One line each: settled, not re-litigated in the chat. Grows as you resolve the
41
+ holes `/plumbbob:refine` surfaces, and as blockers fold in during BUILD. **Anchor and slug
42
+ each item where it is born**: a two- or three-word slug, and an `<a id="…">` for
43
+ references to land on; then cite it from anywhere else in this file as
44
+ `[D1 (slug-here)](#d1)`, carrying that same slug verbatim. One link, one glance: a later
45
+ `D4` never decays into a bare number a cold reader has to hunt down.)*
45
46
 
46
- - D1 (slug-here): <decision> — *because* <the one reason that mattered>
47
+ - <a id="d1"></a>**D1 (slug-here)**: <decision>, *because* <the one reason that mattered>
47
48
 
48
49
  ## Constraints
49
50
 
50
51
  *(Hard rules the build must honor. `/plumbbob:verify` and `/plumbbob:refine` read against these.
51
- Slug and gloss them at birth too — `C1 (no-new-deps)` — same one line, same rule.)*
52
+ Anchor and slug them at birth too (cited as `[C1 (no-new-deps)](#c1)`): same one line,
53
+ same rule.)*
52
54
 
53
- - C1 (no-new-deps): <e.g. functional/procedural only; no new dependencies>
55
+ - <a id="c1"></a>**C1 (no-new-deps)**: <for example functional/procedural only; no new dependencies>
54
56
 
55
57
  ## Steps
56
58
 
57
- *(The build plan. `/plumbbob:plan` authors the **whole list up front** — each step a small,
59
+ *(The build plan. `/plumbbob:plan` authors the **whole list up front**: each step a small,
58
60
  verifiable increment with its own **done-when** and **seam** (the paths it will touch,
59
- which `/plumbbob:build` records in the build folder's `SEAM` for orientation — awareness, not a lock).
60
- An optional **model** line recommends the smallest model that can carry the step —
61
+ which `/plumbbob:build` records in the build folder's `SEAM` for orientation: awareness, not a lock).
62
+ An optional **model** line recommends the smallest model that can carry the step:
61
63
  mechanical work runs fine on a small model; subtle or creative work earns a frontier
62
- one. Advisory for the human, never a gate; write it plain, no backticks — D62
63
- (model-recommendation). The step title *is* the checkpoint's commit subject — D68
64
- (conventional-subjects): write it as one plain line, `type(scope): description` —
65
- load-bearing paths live in `seam`, never jammed into the title — aiming for ≤72
64
+ one. Advisory for the human, never a gate; write it plain, no backticks (plumbbob
65
+ [D62 (model-recommendation)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d62)). The step title *is* the checkpoint's commit subject
66
+ (plumbbob [D68 (conventional-subjects)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d68)): write it as one plain line, `type(scope): description`
67
+ (load-bearing paths live in `seam`, never jammed into the title), aiming for ≤72
66
68
  characters (GitHub's subject convention: soft, no gate).
67
69
  The `(scope)` names the primary code area the step touches (`plan`, `commitmsg`); the
68
70
  build's `**Scope:**` header is the feature-level catch-all a step overrides. Scope
@@ -71,51 +73,59 @@ title-type → `feat`. Then drive `/plumbbob:build` until done. Later steps may
71
73
  fuzzier than the first; sharpen the next one just-in-time with `/plumbbob:step` (empty input
72
74
  auto-syncs it), and use `/plumbbob:refine` to repair the whole plan when a blocker rewrites it.)*
73
75
 
74
- 1. [ ] feat: <step> — **done when:** <criterion, ideally a test or check result>
76
+ 1. [ ] feat: <step>, **done when:** <criterion, ideally a test or check result>
75
77
  - seam: `<file>`, `<file>`
76
- - model: <smallest that can carry it, e.g. sonnet — mechanical, fully specified>
77
- 2. [ ] <step> — **done when:** <criterion>
78
+ - model: <smallest that can carry it, for example sonnet (mechanical, fully specified)>
79
+ 2. [ ] <step>, **done when:** <criterion>
78
80
  - seam: `<file>`
79
81
 
80
82
  ## Open questions
81
83
 
82
- *(Holes you could NOT resolve on paper — the one section that expands rather than
84
+ *(Holes you could NOT resolve on paper: the one section that expands rather than
83
85
  compresses. Do not guess them into Decisions; a genuine fork goes to a SPIKE, with
84
86
  the verdict recorded below and in Decisions.)*
85
87
 
86
88
  <!--
87
89
  Write each open question so a cold reader could answer it without flipping back to
88
- the code or the chat — that cold-reader test is the whole point of expanding it.
90
+ the code or the chat; that cold-reader test is the whole point of expanding it.
89
91
  Three lines:
90
92
 
91
- · the opener — the hole as a question, slugged at birth, tagged
92
- *resolve by:* decide | spike | ask
93
- · *plain:* — what's at stake, in plain words: the context and the cost of getting
93
+ · the opener: the hole as a question, anchored and slugged at birth the same way a
94
+ Decision is (`- <a id="q1"></a>**Q1 (slug-here)**: …`, so a `[Q1 (slug-here)](#q1)`
95
+ reference has somewhere to land), tagged *resolve by:* decide | spike | ask
96
+ · *plain:* what's at stake, in plain words: the context and the cost of getting
94
97
  it wrong, enough to judge it cold
95
- · *lean:* — the model's proposed resolution: one answer to react to, not a menu
98
+ · *lean:* the model's proposed resolution: one answer to react to, not a menu
96
99
 
97
- The human reads *plain* to understand, then *lean* to approve or redirect — one
100
+ The human reads *plain* to understand, then *lean* to approve or redirect: one
98
101
  pass, no round-trip.
99
102
 
100
103
  When a question resolves, swap *resolve by:* for *resolved:* <date, the call> ON THE
101
104
  OPENER LINE, e.g.
102
105
 
103
- - Q3 (default-waves): *resolved:* 2026-07-18, default off
106
+ - <a id="q3"></a>**Q3 (default-waves)**: *resolved:* 2026-07-18, default off
104
107
 
105
108
  The status counter reads opener lines only, so a *resolved:* left on a *plain:* or
106
- *lean:* sub-line leaves the question still counted as open.
107
-
108
- Size to the work: a tiny build's single, obvious question may stay one bare line —
109
+ *lean:* sub-line leaves the question still counted as open
110
+ ([D76 (resolved-on-opener)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d76)).
111
+ It reads "resolved" as a whole word, so an opener that still calls itself
112
+ "unresolved" keeps counting. The scaffolded Q1 below stays uncounted for as long as
113
+ its body is unfilled, still opening on its `<...>` fill-in, which is how a fresh
114
+ build reports zero open questions
115
+ ([D77 (placeholder-uncounted)](https://github.com/robmclarty/plumbbob/blob/main/docs/decisions.md#d77));
116
+ fill it in and it counts.
117
+
118
+ Size to the work: a tiny build's single, obvious question may stay one bare line;
109
119
  the *plain:*/*lean:* pair earns its keep only when a human decision genuinely waits
110
120
  on it.
111
121
  -->
112
122
 
113
- - Q1 (slug-here): <the unresolved hole, framed as a question> — *resolve by:* decide | spike | ask
114
- - *plain:* <what's at stake, in plain words — enough to judge it cold>
115
- - *lean:* <the model's proposed resolution — the answer to react to>
123
+ - <a id="q1"></a>**Q1 (slug-here)**: <the unresolved hole, framed as a question>, *resolve by:* decide | spike | ask
124
+ - *plain:* <what's at stake, in plain words, enough to judge it cold>
125
+ - *lean:* <the model's proposed resolution: the answer to react to>
116
126
 
117
127
  ## Verdicts
118
128
 
119
- *(Filled in as spikes and forks resolve — the audit trail of "these were my calls.")*
129
+ *(Filled in as spikes and forks resolve: the audit trail of "these were my calls.")*
120
130
 
121
- - <date> — <fork> → chose <option> because <reason>; deleted <the rest>
131
+ - <date>: <fork> → chose <option> because <reason>; deleted <the rest>
@@ -1,16 +1,16 @@
1
1
  <!--
2
- spike-report.md — the durable receipt for a spike (a fork the plan couldn't settle
2
+ spike-report.md: the durable receipt for a spike (a fork the plan couldn't settle
3
3
  on paper). One per spike, numbered and named `spike-NN-<slug>.md`, riding the build
4
- folder into the PR beside intent.md / report.md. Fill it while the experiment is live
5
- — the worktrees and their learnings are torn down at `spike done`, but this stays.
4
+ folder into the PR beside intent.md / report.md. Fill it while the experiment is
5
+ live; the worktrees and their learnings are torn down at `spike done`, but this stays.
6
6
 
7
7
  Two ways a spike is born, both landing here:
8
- - `/plumbbob:spike <slug>` — an explicit mid-build fork with throwaway worktrees.
9
- - a planned step titled `spike: …` — the increment IS the experiment.
8
+ - `/plumbbob:spike <slug>`: an explicit mid-build fork with throwaway worktrees.
9
+ - a planned step titled `spike: …`: the increment IS the experiment.
10
10
  Record the Verdict before you close the spike (or check off the step).
11
11
  -->
12
12
 
13
- # Spike — {{TITLE}}
13
+ # Spike: {{TITLE}}
14
14
 
15
15
  **Via:** {{VIA}}
16
16
  **Opened:** {{DATE}}
@@ -22,17 +22,17 @@ would each answer commit us to?)*
22
22
 
23
23
  ## Options tried
24
24
 
25
- *(Each path you actually ran, and what it took — one bullet each.)*
25
+ *(Each path you actually ran, and what it took: one bullet each.)*
26
26
 
27
27
  ## Findings
28
28
 
29
- *(What the experiment showed — evidence, not opinion. Numbers, errors, surprises.)*
29
+ *(What the experiment showed: evidence, not opinion. Numbers, errors, surprises.)*
30
30
 
31
31
  ## Verdict
32
32
 
33
- **Verdict:** *(viable | not viable | partial — replace this line with the call and why)*
33
+ **Verdict:** *(viable | not viable | partial; replace this line with the call and why)*
34
34
 
35
35
  ## What this decides
36
36
 
37
- *(The intent.md Decision this feeds — which option won, what dies, and the one reason
37
+ *(The intent.md Decision this feeds: which option won, what dies, and the one reason
38
38
  that settled it. Copy the call into intent.md's Decisions / Verdicts too.)*