plumbbob 0.6.5 → 0.6.6

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "plumbbob",
3
3
  "displayName": "PlumbBob",
4
- "version": "0.6.5",
4
+ "version": "0.6.6",
5
5
  "description": "Attention-first build process — driver skills + a CLI that keep you the decider; guidance, not enforcement.",
6
6
  "author": { "name": "Rob McLarty", "email": "hello@robmclarty.com", "url": "https://robmclarty.com" },
7
7
  "homepage": "https://github.com/robmclarty/plumbbob#readme",
@@ -51,12 +51,13 @@ export function parseStepSeam(content, step) {
51
51
  // The seam declaration is the seam line plus any wrapped continuation lines.
52
52
  // Truncate each at an HTML-comment opener so a trailing `<!-- ... -->` note
53
53
  // (which may carry its own backticks) is never read as a seam token; a
54
- // continuation ends at the first line whose pre-comment text has no backtick.
54
+ // continuation ends at the first line whose pre-comment text has no backtick
55
+ // or that opens a new sub-bullet (a `- model:` note may carry backticks too, D62).
55
56
  const seamStart = seamLines[0] ?? 0;
56
57
  const decl = [];
57
58
  for (let i = seamStart; i < itemLines.length; i++) {
58
59
  const beforeComment = (itemLines[i] ?? '').split('<!--')[0] ?? '';
59
- if (i > seamStart && !beforeComment.includes('`')) {
60
+ if (i > seamStart && (!beforeComment.includes('`') || /^\s*-\s/.test(beforeComment))) {
60
61
  break;
61
62
  }
62
63
  decl.push(beforeComment);
@@ -49,7 +49,9 @@ export function parseSteps(intent) {
49
49
  const block = lines.slice(s.idx, blockEnd).join('\n');
50
50
  const dw = /\*\*done when:\*\*\s*(.+)/i.exec(block);
51
51
  const doneWhen = dw ? (dw[1] ?? '').trim() : null;
52
- return { n: s.n, done: s.done, title: s.title, planned: /done when/i.test(block), doneWhen };
52
+ const md = /^\s*-\s*model:\s*(.+)$/im.exec(block);
53
+ const model = md ? (md[1] ?? '').trim() : null;
54
+ return { n: s.n, done: s.done, title: s.title, planned: /done when/i.test(block), doneWhen, model };
53
55
  });
54
56
  }
55
57
  // Flip step N's `[ ]` checkbox to `[x]` within the `## Steps` section — mechanical
@@ -134,6 +136,7 @@ export function orient(input) {
134
136
  next: nextMove(input.spiking, steps, input.inFlight, parked),
135
137
  nextDoneWhen: nextUndone?.doneWhen ?? null,
136
138
  nextSeam: seamParse !== null && seamParse.ok ? seamParse.seam : [],
139
+ nextModel: nextUndone?.model ?? null,
137
140
  };
138
141
  }
139
142
  export function formatOrientation(o) {
@@ -155,6 +158,9 @@ export function formatOrientation(o) {
155
158
  if (o.nextSeam.length > 0) {
156
159
  detail.push(` seam: ${o.nextSeam.join(', ')}`);
157
160
  }
161
+ if (o.nextModel !== null) {
162
+ detail.push(` model: ${o.nextModel}`);
163
+ }
158
164
  return detail.length > 0 ? [head, ...detail].join('\n') : head;
159
165
  });
160
166
  const stepsBlock = o.steps.length === 0 ? ' (no steps planned yet)' : ` steps ${doneCount}/${o.steps.length} done\n${stepLines.join('\n')}`;
@@ -81,9 +81,10 @@ function planSubject(root) {
81
81
  return title ? `plumbbob: plan — ${title}` : 'plumbbob: plan';
82
82
  }
83
83
  // Step resolution (D3): explicit arg > in-flight STEP file > first undone step in
84
- // intent.md. Returns null when none can be determined.
84
+ // intent.md. Returns null when none can be determined. A `-m` value is a message,
85
+ // never a step — `checkpoint -m "2"` must not read as step 2.
85
86
  function resolveStep(root, args) {
86
- const explicit = args.find((a) => /^\d+$/.test(a));
87
+ const explicit = args.filter((_, i) => args[i - 1] !== '-m').find((a) => /^\d+$/.test(a));
87
88
  if (explicit !== undefined) {
88
89
  return Number(explicit);
89
90
  }
@@ -135,7 +136,10 @@ function flipIntent(root, step) {
135
136
  writeFileSync(intentPath(root), markStepDone(readFileSync(intentPath(root), 'utf8'), step));
136
137
  }
137
138
  catch {
138
- // best-effort bookkeeping; the checkpoint SHA is the source of truth.
139
+ // Best-effort bookkeeping the checkpoint SHA is the source of truth — but the
140
+ // dashboard reads intent.md, so a swallowed failure here makes orientation lie.
141
+ process.stderr.write(`plumbbob: heads-up — could not flip step ${step} to [x] in intent.md; ` +
142
+ `the checkpoint is recorded, but the dashboard will still show step ${step} as next. Flip it by hand.\n`);
139
143
  }
140
144
  }
141
145
  // Append a dated line to the build-log's `## Log` so the build's history accrues at
@@ -179,9 +183,10 @@ function messageArg(args) {
179
183
  // so the skill can compose proportional prose the CLI never could. Returns null
180
184
  // when the flag is absent or stdin is empty — either way the deterministic
181
185
  // fallback body takes over. Reading fd 0 blocks until EOF, which the heredoc
182
- // supplies; a read error (no stdin attached) degrades to the fallback.
186
+ // supplies; a read error (no stdin attached) degrades to the fallback, and an
187
+ // interactive TTY — which would never send EOF — skips the read instead of hanging.
183
188
  function bodyArg(args) {
184
- if (!args.includes('--body')) {
189
+ if (!args.includes('--body') || process.stdin.isTTY === true) {
185
190
  return null;
186
191
  }
187
192
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plumbbob",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Attention-first build process: 12 skills + a CLI that keep you the decider — guidance, not enforcement.",
5
5
  "keywords": [
6
6
  "claude-code",
@@ -3,7 +3,6 @@ name: pb-build
3
3
  description: The default engine — read the next planned step from intent, implement it (its done-when, seam, Decisions, Constraints), then verify it through to the approval pause. Swappable — build by hand/vibed/another harness and run /pb-verify instead. `--auto` self-approves and chains to done; a step range like `1-3` self-approves through step 3, then pauses.
4
4
  argument-hint: "[step-number | step-range] [--auto]"
5
5
  disable-model-invocation: true
6
- model: opus
7
6
  allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*)
8
7
  ---
9
8
 
@@ -12,7 +11,7 @@ allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*
12
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."`
13
12
 
14
13
  This is the **bundled executor** — the default engine, not the only one. It is
15
- **swappable** (D3): you can implement any step by hand, in a vibe session, or with
14
+ **swappable**: you can implement any step by hand, in a vibe session, or with
16
15
  another harness and go straight to `/pb-verify` instead — plumbbob does not care how
17
16
  the diff appeared. When you do run it, it reads the plan, writes the step, and
18
17
  carries straight through to the verify pause.
@@ -21,6 +20,11 @@ Since `/pb-plan` lays down the whole step list up front, the happy path is to fi
21
20
  `/pb-build` once per step until done — each run builds the next undone step and stops
22
21
  at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick.**
23
22
 
23
+ A model note: this skill **inherits the session model** — nothing pins or switches
24
+ it. If the step you're about to build carries a `- model:` recommendation that
25
+ differs from the model you're running as, say so before implementing — the human can
26
+ `/model` and re-fire to honor it, or wave you on. Advisory, never a gate.
27
+
24
28
  ## What this skill does, in order
25
29
 
26
30
  1. **Pick the step.** Use the number you were invoked with (e.g. `/pb-build 4`) — or,
@@ -34,7 +38,7 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
34
38
  3. **Read the plan.** Read the step's **done-when**, its **seam**, and the
35
39
  **Decisions** and **Constraints** in `intent.md`. Build to *that* — the deciding
36
40
  already happened, off the chat.
37
- - **Run any bound `before`-agents** *(D43/D59)*. If the build's `harness.json` binds
41
+ - **Run any bound `before`-agents**. If the build's `harness.json` binds
38
42
  agents to this step's `before` slot, run `plumbbob agent run --step <n> --mode
39
43
  before` first: each returns a validated envelope on stdout that plumbbob also
40
44
  appends to the step's `handoff.json`, and its `summary`/`body` become **context you
@@ -45,17 +49,17 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
45
49
  edit — capture it and stay on the step. If you genuinely cannot finish without
46
50
  touching more than the seam, that is scope drift: surface it to the human rather
47
51
  than sprawling.
48
- - **If a `build`-slot agent is bound, delegate the diff to it** *(D43)*. Run
52
+ - **If a `build`-slot agent is bound, delegate the diff to it**. Run
49
53
  `plumbbob agent run --step <n> --mode build` and let that agent author the step's
50
54
  code instead of writing it yourself; its envelope reports what it did. You still
51
- own the verify tick below — the diff is reviewed the same way whoever wrote it (D3).
52
- - **A manifest's `when` prose is your cue to fire an agent mid-build** *(D43/D55)*.
55
+ own the verify tick below — the diff is reviewed the same way whoever wrote it.
56
+ - **A manifest's `when` prose is your cue to fire an agent mid-build**.
53
57
  The three slots are the only *declarative* lifecycle points; there is no config for
54
58
  "a salient moment in the middle." That is judgment, and you are the frontier model
55
59
  in the room: when the work reaches the situation a bound agent's `when` (or a step
56
60
  `note`) describes, fire `plumbbob agent run <name> --step <n>` yourself. Prose is
57
61
  the orchestration language; you are the workflow engine.
58
- - **Route a non-`done` envelope by its status** *(D52)*. An agent that returns
62
+ - **Route a non-`done` envelope by its status**. An agent that returns
59
63
  `blocked` couldn't finish (missing input, failed precondition): surface its `notes`,
60
64
  let the human unblock, and re-run it — don't work around it. One that returns
61
65
  `drift` finished but found the plan no longer matches reality: **stop and send the
@@ -68,9 +72,9 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
68
72
  still runs everything) → run any bound `after`-agents (`plumbbob agent run --step
69
73
  <n> --mode after`) and fold their envelopes into the self-review as **advisory
70
74
  input** — they inform, they never gate (checkride gates, the human is the clock; an
71
- `after`-agent that could fail a step is the lock in autonomy's costume, D45) →
75
+ `after`-agent that could fail a step is the lock in autonomy's costume) →
72
76
  self-review the diff against the done-when, the Decisions, and the Constraints (a
73
- single structured read, D16) → validate → **PAUSE
77
+ single structured read) → validate → **PAUSE
74
78
  for the human's approval** → only on approval, checkpoint with
75
79
  `plumbbob checkpoint <n> --body <<'BODY' … BODY` — a commit body **proportional to the
76
80
  step** (a line for a trivial change, a short paragraph for a meatier one; no TIL scan,
@@ -85,8 +89,8 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
85
89
  progress instead of approving each step. It does the same work, but **the agent reviews
86
90
  and approves in the human's place**, and it **chains**:
87
91
 
88
- - Build the next step, running its slots in the same order as the default path
89
- (D56): bound `before`-agents → implement (or the bound `build`-agent) → bound
92
+ - Build the next step, running its slots in the same order as the default
93
+ path: bound `before`-agents → implement (or the bound `build`-agent) → bound
90
94
  `after`-agents → `check` → self-review → **if the check is green AND the
91
95
  self-review finds no done-when / Decision / Constraint mismatch, checkpoint** and move
92
96
  straight on to the next planned step. Repeat. `--auto` adds no new machinery — the
@@ -94,7 +98,7 @@ and approves in the human's place**, and it **chains**:
94
98
  - **Stop and hand back to the human** the moment any of these is true: the check is red,
95
99
  the self-review finds a mismatch (surface exactly what, and do not checkpoint it), a
96
100
  bound agent returns `blocked` or `drift` (unblock-and-re-run, or `/pb-refine` — an
97
- agent cannot advance the loop, C6), a new decision is needed, no planned steps
101
+ agent cannot advance the loop), a new decision is needed, no planned steps
98
102
  remain, or the top of a requested range is reached.
99
103
 
100
104
  `--auto` and a step range are the only paths that checkpoint without a human pause, and
@@ -126,14 +130,14 @@ just the one more entry already in the halt list above.
126
130
  ## The hard contracts
127
131
 
128
132
  - **Swappable, never required.** The loop works without this skill; `/pb-verify`
129
- checkpoints a hand-built or vibed diff just the same (D3).
133
+ checkpoints a hand-built or vibed diff just the same.
130
134
  - **Build the decided step, not a new one.** Implement what `intent.md` settled. A
131
135
  new idea mid-build is a `/pb-park`, not an edit.
132
136
  - **Default ends at the pause.** Implement → verify → wait for approval; never
133
137
  checkpoint without it. Only an explicit `--auto` or a step range lets the agent approve
134
138
  in your place, and it still halts on a red check or any mismatch — a range also stops
135
139
  at its top.
136
- - **Agents feed the beat; they never advance it** (C6/D45). `before` loads context,
140
+ - **Agents feed the beat; they never advance it**. `before` loads context,
137
141
  `build` writes the diff, `after` is advisory — none can checkpoint, flip a step, or
138
142
  chain. `blocked` → unblock and re-run; `drift` → `/pb-refine`. You are still the one
139
143
  who verifies and (bar `--auto`) the human is still the clock.
@@ -2,7 +2,6 @@
2
2
  name: pb-finish
3
3
  description: Finish the build — write the report (what shipped, decisions, parked/harvested items, deferred tangents), then make the final commit that closes the session. The build folder rides the branch into the PR — no separate archive. Report by default, no gate.
4
4
  disable-model-invocation: true
5
- model: opus
6
5
  allowed-tools: Read, Write, Bash(plumbbob status:*), Bash(plumbbob finish:*)
7
6
  ---
8
7
 
@@ -11,8 +10,8 @@ allowed-tools: Read, Write, Bash(plumbbob status:*), Bash(plumbbob finish:*)
11
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."`
12
11
 
13
12
  `/pb-finish` ends the build: it captures what happened, then makes the final commit
14
- that closes the session. **Report by default** (D9) — no refuse-without-report gate,
15
- and no separate docs phase. The build folder is tracked (D26/D29): it merges with the
13
+ that closes the session. **Report by default** — no refuse-without-report gate,
14
+ and no separate docs phase. The build folder is tracked: it merges with the
16
15
  branch and shows up in the PR, so there is nothing to archive — the folder *is* the
17
16
  record.
18
17
 
@@ -30,8 +29,8 @@ record.
30
29
  - **Deferred tangents** — the harvested items that become future work.
31
30
  This is the "yeah, I did that" artifact. Write it by default; the human may edit it.
32
31
  2. **Finish.** Run `plumbbob finish`, which appends the checkpoint SHAs to the
33
- report and makes the final commit — subject `plumbbob: finish — <title>` (D34),
34
- with an optional proportional body via `--body` (the D34 stdin heredoc) — then
32
+ report and makes the final commit — subject `plumbbob: finish — <title>`,
33
+ with an optional proportional body via `--body` (the stdin heredoc) — then
35
34
  clears the control state (markers, the `activeBuild` cursor, STATE last). The
36
35
  build folder stays in place, committed, and rides the branch into the PR.
37
36
  3. **Point at the next goal** — `/pb-plan` to frame the next one.
@@ -43,7 +42,7 @@ record.
43
42
  - **The log is the history; the report is the synthesis.** `checkpoint` already recorded
44
43
  what shipped, step by step — finish applies the *unique additions* (the why, the deferred
45
44
  tangents, the final status), it does not rewrite the timeline.
46
- - **The folder is the archive, never destroy** (C4/D29). `finish` keeps intent +
45
+ - **The folder is the archive, never destroy**. `finish` keeps intent +
47
46
  build-log + report in `builds/<slug>/` and commits them; nothing is copied out and
48
47
  nothing is deleted but the untracked control markers.
49
48
  - **No version bump, no docs phase.** Updating real docs is a separate, explicit ask;
@@ -2,7 +2,6 @@
2
2
  name: pb-harvest
3
3
  description: Triage the park list at a step boundary — propose one class (blocker/tangent/pivot) per parked item, write only after the human confirms each, record under ## Harvest, and fold a confirmed blocker into intent.
4
4
  disable-model-invocation: true
5
- model: opus
6
5
  allowed-tools: Read, Edit, Bash(plumbbob status:*)
7
6
  ---
8
7
 
@@ -10,7 +9,7 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
10
9
 
11
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."`
12
11
 
13
- `/pb-harvest` is the complement of `/pb-park` (D7): you parked ideas as seeds during a
12
+ `/pb-harvest` is the complement of `/pb-park`: you parked ideas as seeds during a
14
13
  build; now, at a boundary, you harvest them — decide what each one is.
15
14
 
16
15
  ## When to run it — boundary only
@@ -12,7 +12,7 @@ allowed-tools: Bash(plumbbob status:*), Bash(plumbbob park:*)
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
14
  `/pb-park` is the **capture** half of the loop; `/pb-harvest` is where parked items
15
- get triaged later (D7). Capturing the instant an idea arrives — instead of acting on
15
+ get triaged later. Capturing the instant an idea arrives — instead of acting on
16
16
  it — is the whole point: it protects the step in flight.
17
17
 
18
18
  ## Wrong-state refusal
@@ -3,7 +3,6 @@ name: pb-plan
3
3
  description: "Frame a fresh goal and author the whole plan — Frame, Decisions, Constraints, and all Steps — before any code. Three input modes: no arg interviews you; a file path absorbs a spec; any other text expands your inline intent."
4
4
  argument-hint: "[spec-path | intent]"
5
5
  disable-model-invocation: true
6
- model: opus
7
6
  allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob start:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent list:*)
8
7
  ---
9
8
 
@@ -17,6 +16,11 @@ of your head and onto `intent.md` *before* any code. By default it authors the
17
16
  `/pb-build` until done. (Revising a single increment later is the separate `/pb-step`
18
17
  move; do not confuse the two.)
19
18
 
19
+ A model note: this skill **inherits the session model** — nothing pins or switches
20
+ it. Planning is where frontier-class judgment pays for itself, so if the session is
21
+ running a small model, suggest `/model opus` (or better) before framing — the
22
+ human's call, never a gate.
23
+
20
24
  ## Three input modes (disambiguated for you — no quotes needed)
21
25
 
22
26
  Look at the argument the human gave and pick the mode yourself:
@@ -54,13 +58,24 @@ an agent can follow with `/pb-build`. The argument only seeds how you get there.
54
58
  ```markdown
55
59
  1. [ ] <title> — **done when:** <criterion, ideally a test or check result>
56
60
  - seam: `<file>`, `<file>`
61
+ - model: <optional — smallest that can carry it, with the one-phrase why>
57
62
  ```
58
63
 
59
64
  Every step needs a **done-when** `/pb-verify` can check and a **seam** (the exact
60
65
  paths it touches). Later steps may be fuzzier than the first — that's fine; they get
61
66
  sharpened just-in-time when you reach them with `/pb-step`. Keep each small enough to
62
67
  verify in one review pass.
63
- 5. **Offer harness bindings** *(optional — D42/D43)*. If the build will lean on
68
+
69
+ **Recommend a model per step where the signal is clear** *(optional)*: the
70
+ `- model:` sub-line names the **smallest model that can carry the step**, with the
71
+ one-phrase why — the human buys capability only where the step needs it. E.g.
72
+ `model: sonnet — mechanical, fully specified by the done-when` for rote edits;
73
+ `model: opus — strong-assertion test authoring` where the tests do the thinking;
74
+ `model: fable — subtle cross-cutting design` for judgment-heavy or creative work.
75
+ It is advisory metadata for the human — `/pb-status` surfaces it before each build —
76
+ never a gate, and nothing switches models automatically. Write it plain (no
77
+ backticks) and omit it when any model would do.
78
+ 5. **Offer harness bindings** *(optional)*. If the build will lean on
64
79
  user-authored agents, author `harness.json` in the build folder (beside `intent.md`)
65
80
  and review it at the **same plan pause**, alongside the steps — bindings are
66
81
  plan-adjacent configuration, so they converge with the plan. It binds agents to a
@@ -76,15 +91,15 @@ an agent can follow with `/pb-build`. The argument only seeds how you get there.
76
91
  }
77
92
  ```
78
93
 
79
- Keep it **bindings + prose only, never a conditional** (C3): the file says *which*
94
+ Keep it **bindings + prose only, never a conditional**: the file says *which*
80
95
  agent, not *when* — the host model reads each manifest's `when` prose and a step's
81
96
  `note` and decides when to fire one mid-build. Skip the file entirely when no step
82
- uses an agent — the loop runs identically without it (D54). The plan commit picks it
97
+ uses an agent — the loop runs identically without it. The plan commit picks it
83
98
  up automatically (it lives in the build folder).
84
99
  6. **Commit the plan.** Once the human approves the frame and steps, run
85
100
  `plumbbob checkpoint --plan` to commit the scaffold on its own — subject
86
101
  `plumbbob: plan — <title>`, only `.plumbbob/builds/<slug>/`, a `plan <sha>` line in
87
- `checkpoints` (D36). This keeps the first step's diff clean, so history reads
102
+ `checkpoints`. This keeps the first step's diff clean, so history reads
88
103
  baseline → plan → steps. Pass a proportional `--body` (the single-quoted stdin
89
104
  heredoc) when the rationale is worth carrying; skip it for a small plan. Do this
90
105
  only on the human's approval — the plan is their convergence.
@@ -3,7 +3,6 @@ name: pb-refine
3
3
  description: Keep intent.md true — attack the plan for holes (append as Open questions) and refine or repair the Frame, Decisions, Constraints, and Steps to match reality. Usable at any point; you propose, the human approves.
4
4
  argument-hint: "[focus]"
5
5
  disable-model-invocation: true
6
- model: opus
7
6
  allowed-tools: Read, Edit, Bash(plumbbob status:*)
8
7
  ---
9
8
 
@@ -19,4 +19,8 @@ skill carries **no Edit and no Write tool**: the CLI is the source of truth, so
19
19
  ## What it does
20
20
 
21
21
  1. Surface the injected `status` output — the dashboard and its suggested next move.
22
- 2. If it reads `NO ACTIVE SESSION`, tell the human to `/pb-plan` to frame a goal.
22
+ 2. If the next step's detail carries a `model:` line, point it out: it is the
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 `/pb-build` — or ignore it. Guidance,
25
+ never a gate.
26
+ 3. If it reads `NO ACTIVE SESSION`, tell the human to `/pb-plan` to frame a goal.
@@ -3,7 +3,6 @@ name: pb-step
3
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
- model: opus
7
6
  allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob agent list:*)
8
7
  ---
9
8
 
@@ -36,17 +35,19 @@ grew — but its everyday job is to sharpen, not to invent.
36
35
  2. **Propose the revision** (or the new/split step): a one-line **title**, a **done-when**
37
36
  `/pb-verify` can validate, and a **seam** (exact paths, or a `dir/` grant). Keep it
38
37
  small enough to verify in one review pass. Show the before/after so the human can see
39
- what you changed and why.
38
+ what you changed and why. Re-check the optional `- model:` recommendation too:
39
+ a step that sharpened into rote work can drop to a smaller model; one that grew subtle
40
+ earns a frontier one. Advisory, plain text (no backticks), never a gate.
40
41
  3. **Get the human's OK**, then write it into `## Steps` in the standard format —
41
42
  `N. [ ] <title> — **done when:** <criterion>` with a `- seam:` sub-line. Revise the
42
43
  existing step in place; only append when you are genuinely adding an increment.
43
- 4. **Revise the step's harness bindings if they drifted too** *(optional — D42)*. If the
44
+ 4. **Revise the step's harness bindings if they drifted too** *(optional)*. If the
44
45
  build carries a `harness.json` (beside `intent.md`) and the reality that moved the
45
46
  step also changed which agents it wants, sharpen that step's slot bindings
46
47
  (`before`/`build`/`after`) and `note` at the same time — this is the just-in-time
47
48
  counterpart to `/pb-plan`'s plan-time binding. `plumbbob agent list` shows what's
48
49
  resolvable. Same rule as the plan move: bindings + prose only, never a conditional
49
- (C3). Leave it untouched when the step's agents are still right, or when the build
50
+ . Leave it untouched when the step's agents are still right, or when the build
50
51
  uses none.
51
52
 
52
53
  ## The hard contracts
@@ -2,7 +2,6 @@
2
2
  name: pb-verify
3
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
- model: opus
6
5
  allowed-tools: Read, Bash(plumbbob status:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*), Bash(git status:*)
7
6
  ---
8
7
 
@@ -12,29 +11,29 @@ Current session state (injected when this skill runs): !`plumbbob status 2>/dev/
12
11
 
13
12
  This is the **tick** — the one beat where the human is the clock. Whatever produced
14
13
  the current diff — `/pb-build`, your own hands, a vibe session, another harness —
15
- this skill verifies it the same way: **it reads the diff, not the author** (D3).
14
+ this skill verifies it the same way: **it reads the diff, not the author**.
16
15
 
17
16
  ## What this skill does, in order
18
17
 
19
18
  1. **Check.** Run `plumbbob check` (the heavy gate — checkride unless the repo
20
- configures a `check` override, D32). If it comes back **red**, stop here: the gate
19
+ configures a `check` override). If it comes back **red**, stop here: the gate
21
20
  names the failing slots and where each tool's raw output landed — read
22
21
  `.check/summary.json`, then the failing slot's own file (`.check/<slot>.json` or
23
22
  `.check/<slot>.stdout.txt`) for the actual diagnostics instead of scraping
24
23
  scrollback. Report what failed and do **not** pause for approval — there is
25
24
  nothing to approve yet. The human fixes it and re-invokes. (Exit 2 means the gate
26
25
  itself broke — a harness problem to surface, not a code failure.)
27
- 2. **Run any bound `after`-agents** *(optional — D45)*. If the build's `harness.json`
26
+ 2. **Run any bound `after`-agents** *(optional)*. If the build's `harness.json`
28
27
  binds agents to this step's `after` slot, run `plumbbob agent run --step <n> --mode
29
28
  after`. Their envelopes are **advisory input to the self-review, never a gate** —
30
29
  `plumbbob check` already gated in step 1, and an `after`-agent that could fail a step
31
- is the lock returning in autonomy's costume (D45). Fold a `done` envelope's
32
- `summary`/`body` into the review below; route a non-`done` one by its status (D52): a
30
+ is the lock returning in autonomy's costume. Fold a `done` envelope's
31
+ `summary`/`body` into the review below; route a non-`done` one by its status: a
33
32
  `blocked` agent couldn't finish — surface its `notes`, let the human unblock, re-run;
34
33
  a `drift` agent found the plan no longer matches reality — stop and send the human to
35
34
  `/pb-refine` to repair the plan before checkpointing. No binding, or no harness, is a
36
35
  clean no-op.
37
- 3. **Self-review** *(a single structured read, D16)*. Read `git diff` and
36
+ 3. **Self-review** *(a single structured read)*. Read `git diff` and
38
37
  `.plumbbob/intent.md`, then in one pass check the diff against:
39
38
  - the current step's **done-when** criterion — is it actually met?
40
39
  - the **Decisions** — does anything contradict a settled call?
@@ -68,12 +67,12 @@ this skill verifies it the same way: **it reads the diff, not the author** (D3).
68
67
 
69
68
  - **Never skip the pause.** Check → self-review → validate, then wait. Approval is
70
69
  the only thing that triggers the checkpoint.
71
- - **Read the diff, not the author** (D3). Verify identically whether the code was
70
+ - **Read the diff, not the author**. Verify identically whether the code was
72
71
  built by `/pb-build`, by hand, vibed, or by another harness.
73
72
  - **Red means stop, not pause.** A failing check is not an approval decision; report
74
73
  it and end your turn.
75
74
  - **You review; you do not build.** If the self-review finds a problem, surface it
76
75
  and stop — fixing is a new build beat, not part of verify.
77
- - **`after`-agents advise; they never gate** (D45). Their output feeds the
76
+ - **`after`-agents advise; they never gate**. Their output feeds the
78
77
  self-review — checkride gates, the human approves. `blocked` → unblock and re-run;
79
78
  `drift` → `/pb-refine` before checkpointing. No code path makes them blocking.
@@ -47,12 +47,16 @@ holes `/pb-refine` surfaces, and as blockers fold in during BUILD.)*
47
47
  *(The build plan. `/pb-plan` authors the **whole list up front** — each step a small,
48
48
  verifiable increment with its own **done-when** and **seam** (the paths it will touch,
49
49
  which `/pb-build` records in the build folder's `SEAM` for orientation — awareness, not a lock).
50
+ An optional **model** line recommends the smallest model that can carry the step —
51
+ mechanical work runs fine on a small model; subtle or creative work earns a frontier
52
+ one. Advisory for the human, never a gate; write it plain, no backticks (D62).
50
53
  Then drive `/pb-build` until done. Later steps may be fuzzier than the first;
51
54
  sharpen the next one just-in-time with `/pb-step` (empty input auto-syncs it), and use
52
55
  `/pb-refine` to repair the whole plan when a blocker rewrites it.)*
53
56
 
54
57
  1. [ ] <step> — **done when:** <criterion, ideally a test or check result>
55
58
  - seam: `<file>`, `<file>`
59
+ - model: <smallest that can carry it, e.g. sonnet — mechanical, fully specified>
56
60
  2. [ ] <step> — **done when:** <criterion>
57
61
  - seam: `<file>`
58
62