plumbbob 0.6.3 → 0.6.5
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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/lib/buildlog.js +1 -1
- package/dist/lib/orient.js +9 -9
- package/dist/verbs/build.js +7 -0
- package/dist/verbs/check.js +1 -1
- package/dist/verbs/checkpoint.js +2 -2
- package/dist/verbs/doctor.js +2 -2
- package/dist/verbs/finish.js +2 -2
- package/dist/verbs/park.js +1 -1
- package/package.json +1 -1
- package/skills/pb-build/SKILL.md +37 -11
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
3
|
"displayName": "PlumbBob",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.5",
|
|
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",
|
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ nothing else:
|
|
|
121
121
|
| Skill <img alt="" width="110" height="1"> | Does |
|
|
122
122
|
|------------------------------------|------|
|
|
123
123
|
| `/pb-plan` | plan the whole goal — open the session and author intent's Frame, Decisions, Constraints, **and all Steps** |
|
|
124
|
-
| `/pb-build` | implement the next planned step, then verify it to the pause — `--auto` self-approves and chains to done |
|
|
124
|
+
| `/pb-build` | implement the next planned step, then verify it to the pause — `--auto` self-approves and chains to done; a range like `1-3` self-approves through step 3, then pauses |
|
|
125
125
|
| `/pb-finish` | finish up — write the report, make the final commit, clear for a fresh goal |
|
|
126
126
|
|
|
127
127
|
**Plan-shaping moves** — optional, for when the plan needs work mid-flight:
|
package/dist/lib/buildlog.js
CHANGED
|
@@ -27,7 +27,7 @@ export function appendToSection(content, heading, line) {
|
|
|
27
27
|
}
|
|
28
28
|
// The Log line `checkpoint` writes for a landed step: dated, names the step (its
|
|
29
29
|
// title when intent.md still carries it), and carries the short SHA. One line of the
|
|
30
|
-
// build's history — `/
|
|
30
|
+
// build's history — `/pb-finish` reads these instead of re-narrating the build.
|
|
31
31
|
export function checkpointLogLine(date, step, sha, title) {
|
|
32
32
|
const head = `- ${date} — step ${step} checkpointed · ${sha.slice(0, 9)}`;
|
|
33
33
|
return title !== null && title.length > 0 ? `${head} — ${title}` : head;
|
package/dist/lib/orient.js
CHANGED
|
@@ -77,7 +77,7 @@ export function parseOpenQuestions(intent) {
|
|
|
77
77
|
.length;
|
|
78
78
|
}
|
|
79
79
|
// Open parked items: `- [ ]` lines under `## Park list` (the `park` verb's format).
|
|
80
|
-
// A harvested item is flipped to `- [x]` by `/
|
|
80
|
+
// A harvested item is flipped to `- [x]` by `/pb-harvest` and no longer counts; the
|
|
81
81
|
// `(none yet)` placeholder and the blockquote instructions never match.
|
|
82
82
|
export function parseParked(buildLog) {
|
|
83
83
|
return sectionLines(buildLog, '## Park list').filter((l) => /^-\s+\[ \]\s+\S/.test(l.trim())).length;
|
|
@@ -101,22 +101,22 @@ function nextMove(spiking, steps, inFlight, parked) {
|
|
|
101
101
|
return 'close the spike — `plumbbob spike done`';
|
|
102
102
|
}
|
|
103
103
|
if (inFlight !== null) {
|
|
104
|
-
return `finish step ${inFlight} — \`/
|
|
104
|
+
return `finish step ${inFlight} — \`/pb-verify\` (or keep editing, then \`/pb-verify\`)`;
|
|
105
105
|
}
|
|
106
106
|
// At the boundary (DESIGN): the move follows from the steps.
|
|
107
107
|
const nextUndone = steps.find((s) => !s.done);
|
|
108
108
|
if (nextUndone === undefined) {
|
|
109
109
|
if (steps.length === 0) {
|
|
110
|
-
return 'plan the first step — `/
|
|
110
|
+
return 'plan the first step — `/pb-step`';
|
|
111
111
|
}
|
|
112
112
|
// Batch-default: the steps were planned up front, so finishing them usually
|
|
113
|
-
// means "finish up" — but `/
|
|
114
|
-
const harvest = parked > 0 ? `harvest ${parked} parked idea${parked === 1 ? '' : 's'} — \`/
|
|
115
|
-
return `${harvest}finish up — \`/
|
|
113
|
+
// means "finish up" — but `/pb-step` can still add an increment if reality grew.
|
|
114
|
+
const harvest = parked > 0 ? `harvest ${parked} parked idea${parked === 1 ? '' : 's'} — \`/pb-harvest\`; then ` : '';
|
|
115
|
+
return `${harvest}finish up — \`/pb-finish\` (or \`/pb-step\` to add another increment)`;
|
|
116
116
|
}
|
|
117
117
|
return nextUndone.planned
|
|
118
|
-
? `build step ${nextUndone.n} — \`/
|
|
119
|
-
: `plan step ${nextUndone.n} — \`/
|
|
118
|
+
? `build step ${nextUndone.n} — \`/pb-build\` (or \`/pb-step\` to revise it first)`
|
|
119
|
+
: `plan step ${nextUndone.n} — \`/pb-step\``;
|
|
120
120
|
}
|
|
121
121
|
export function orient(input) {
|
|
122
122
|
const steps = parseSteps(input.intent);
|
|
@@ -146,7 +146,7 @@ export function formatOrientation(o) {
|
|
|
146
146
|
if (s !== nextUndone) {
|
|
147
147
|
return head;
|
|
148
148
|
}
|
|
149
|
-
// Surface the next step's detail so the human can review it (and `/
|
|
149
|
+
// Surface the next step's detail so the human can review it (and `/pb-step`-
|
|
150
150
|
// revise) before building. Only what's present — a rough step shows neither.
|
|
151
151
|
const detail = [];
|
|
152
152
|
if (o.nextDoneWhen !== null) {
|
package/dist/verbs/build.js
CHANGED
|
@@ -13,6 +13,13 @@ export function build(cwd, args) {
|
|
|
13
13
|
}
|
|
14
14
|
const { build: slug, rest } = resolveBuild(root, args);
|
|
15
15
|
const raw = rest.find((a) => !a.startsWith('--'));
|
|
16
|
+
// A step range like `1-3` is a `/pb-build` skill affordance (auto-approve
|
|
17
|
+
// through the range, then pause), not a CLI capability — the CLI records one
|
|
18
|
+
// in-flight step at a time. Name it rather than bounce off the generic usage.
|
|
19
|
+
if (raw !== undefined && /^\d+-\d*$/.test(raw)) {
|
|
20
|
+
process.stderr.write(`plumbbob: build takes one step number; \`${raw}\` step ranges are a \`/pb-build\` feature (auto-approve through the range, then pause). Try \`plumbbob build ${raw.split('-')[0]}\`.\n`);
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
16
23
|
if (raw === undefined || !/^\d+$/.test(raw) || Number(raw) < 1) {
|
|
17
24
|
process.stderr.write('plumbbob: build needs a step number. Try: plumbbob build 2.\n');
|
|
18
25
|
return 1;
|
package/dist/verbs/check.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `plumbbob check` — run the heavy gate (D16/D24/D32) and report, with NO state
|
|
2
|
-
// change. The read-only half of the verify tick: `/
|
|
2
|
+
// change. The read-only half of the verify tick: `/pb-verify` runs this before the
|
|
3
3
|
// pause so the human approves on a known-green check. Exits with the check's own
|
|
4
4
|
// code (0 = green, 1 = red, 2 = the gate itself broke).
|
|
5
5
|
//
|
package/dist/verbs/checkpoint.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// is already clean — the human's commit skill may have committed first), records the
|
|
6
6
|
// SHA, flips the intent checkbox to `[x]`, and clears any STEP/SEAM (which returns
|
|
7
7
|
// the dashboard to the DESIGN boundary). The diff's author is irrelevant:
|
|
8
|
-
// `/
|
|
8
|
+
// `/pb-build`, your hands, a vibe session, or another harness all checkpoint
|
|
9
9
|
// the same way.
|
|
10
10
|
import { appendFileSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
11
11
|
import { commit, findRepoRoot, headSha, isDirty, stageAll, stagePath, stagedPaths, stagedStat } from "../lib/git.js";
|
|
@@ -108,7 +108,7 @@ function warnScopeDrift(root, step) {
|
|
|
108
108
|
const outside = scopeDrift(stagedPaths(root), seam);
|
|
109
109
|
if (outside.length > 0) {
|
|
110
110
|
process.stderr.write(`plumbbob: heads-up — staged paths outside step ${step}'s seam: ${outside.join(', ')}. ` +
|
|
111
|
-
`The checkpoint captures them; if that's real scope drift, the plan may need a \`/
|
|
111
|
+
`The checkpoint captures them; if that's real scope drift, the plan may need a \`/pb-step\` revision.\n`);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
// The seam tokens for the in-flight step: the normalized SEAM file `build` wrote
|
package/dist/verbs/doctor.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// Code loads it in place as a plugin (skills `/plumbbob:*`, the post-edit hook from
|
|
6
6
|
// hooks.json). doctor verifies the link resolves to a package carrying the manifest,
|
|
7
7
|
// the skills, and the hook — and names the fix for anything missing. The failure
|
|
8
|
-
// class it exists for is SILENT (a `/
|
|
8
|
+
// class it exists for is SILENT (a `/pb-status` that opens an empty dashboard
|
|
9
9
|
// because the plugin never linked).
|
|
10
10
|
//
|
|
11
11
|
// 2. The repo sidecar layout. A repo scaffolded by a pre-restructure plumbbob carries a
|
|
@@ -419,7 +419,7 @@ export async function doctor(cwd, args = []) {
|
|
|
419
419
|
out.push(failed === 0
|
|
420
420
|
? 'plumbbob: all checks passed. If a skill still misbehaves, restart Claude Code (or /reload-plugins).'
|
|
421
421
|
: `plumbbob: ${failed} problem(s) — apply the → fixes, then restart Claude Code.`);
|
|
422
|
-
out.push('plumbbob: skills shell a bare `plumbbob`. The marketplace plugin puts it on PATH only inside a Claude Code session (via bin/) — there is no terminal `plumbbob`; for one (or the skills-dir install) run `npm i -g plumbbob`. In-session you can also run this as `/
|
|
422
|
+
out.push('plumbbob: skills shell a bare `plumbbob`. The marketplace plugin puts it on PATH only inside a Claude Code session (via bin/) — there is no terminal `plumbbob`; for one (or the skills-dir install) run `npm i -g plumbbob`. In-session you can also run this as `/pb-doctor`. Sessions are per-project via `plumbbob start`.');
|
|
423
423
|
process.stdout.write(`${out.join('\n')}\n`);
|
|
424
424
|
return failed === 0 ? 0 : 1;
|
|
425
425
|
}
|
package/dist/verbs/finish.js
CHANGED
|
@@ -23,7 +23,7 @@ export function finish(cwd, args = []) {
|
|
|
23
23
|
}
|
|
24
24
|
else {
|
|
25
25
|
process.stderr.write('plumbbob: note — no report.md found; finishing without one ' +
|
|
26
|
-
'(/
|
|
26
|
+
'(/pb-finish normally writes the report first). No gate (D9).\n');
|
|
27
27
|
}
|
|
28
28
|
// The final commit (D34): stage the report just written plus the build folder's
|
|
29
29
|
// tail (the last step's checkpoint line lands one commit late, D37) and commit it
|
|
@@ -49,7 +49,7 @@ export function finish(cwd, args = []) {
|
|
|
49
49
|
rmSync(join(sidecarDir(root), 'STATE'), { force: true });
|
|
50
50
|
const where = slug === null ? '.plumbbob/' : `.plumbbob/builds/${slug}/`;
|
|
51
51
|
process.stdout.write(`plumbbob: finished — ${sha.slice(0, 9)}. ${where} rides your branch into the PR. ` +
|
|
52
|
-
'Run `/
|
|
52
|
+
'Run `/pb-plan` (or `plumbbob start "<title>"`) to frame the next goal.\n');
|
|
53
53
|
return 0;
|
|
54
54
|
}
|
|
55
55
|
// The CLI-owned final-commit subject (D34): `plumbbob: finish — <title>`, mirroring
|
package/dist/verbs/park.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `plumbbob park "<text>"` — the dumb capture path: append one raw line under
|
|
2
|
-
// the build-log's Park list. No model turn, no composition (that is /
|
|
2
|
+
// the build-log's Park list. No model turn, no composition (that is /pb-park's job).
|
|
3
3
|
// Capture is not a transition, so it runs in any context (terminal or in-session).
|
|
4
4
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { findRepoRoot } from "../lib/git.js";
|
package/package.json
CHANGED
package/skills/pb-build/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pb-build
|
|
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.
|
|
4
|
-
argument-hint: "[step-number] [--auto]"
|
|
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
|
+
argument-hint: "[step-number | step-range] [--auto]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
model: opus
|
|
7
7
|
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*)
|
|
@@ -23,9 +23,11 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
23
23
|
|
|
24
24
|
## What this skill does, in order
|
|
25
25
|
|
|
26
|
-
1. **Pick the step.** Use the number you were invoked with (e.g. `/pb-build 4`),
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
1. **Pick the step.** Use the number you were invoked with (e.g. `/pb-build 4`) — or,
|
|
27
|
+
if you were given a range like `/pb-build 1-3`, start at the first number and treat
|
|
28
|
+
the second as the auto-approve ceiling (see the range note under `--auto`). With no
|
|
29
|
+
argument, take the next undone, planned step in `.plumbbob/intent.md`. If there is no
|
|
30
|
+
planned step to build, stop and tell the human to `/pb-step` first.
|
|
29
31
|
2. **Enter the step.** Run `plumbbob build <n>` (records the in-flight STEP +
|
|
30
32
|
SEAM so `/pb-status` shows the step in flight; the seam is awareness, not a
|
|
31
33
|
lock).
|
|
@@ -92,11 +94,34 @@ and approves in the human's place**, and it **chains**:
|
|
|
92
94
|
- **Stop and hand back to the human** the moment any of these is true: the check is red,
|
|
93
95
|
the self-review finds a mismatch (surface exactly what, and do not checkpoint it), a
|
|
94
96
|
bound agent returns `blocked` or `drift` (unblock-and-re-run, or `/pb-refine` — an
|
|
95
|
-
agent cannot advance the loop, C6), a new decision is needed,
|
|
96
|
-
remain.
|
|
97
|
+
agent cannot advance the loop, C6), a new decision is needed, no planned steps
|
|
98
|
+
remain, or the top of a requested range is reached.
|
|
97
99
|
|
|
98
|
-
`--auto`
|
|
99
|
-
human asked for it by name
|
|
100
|
+
`--auto` and a step range are the only paths that checkpoint without a human pause, and
|
|
101
|
+
only because the human asked for it by name; a range re-imposes the pause at its top.
|
|
102
|
+
The default — no flag, no range — always ends at the pause.
|
|
103
|
+
|
|
104
|
+
### A step range (`N-M`) is a bounded `--auto`
|
|
105
|
+
|
|
106
|
+
`/pb-build 1-3` self-approves steps 1 through 3 exactly as `--auto` does, then **pauses
|
|
107
|
+
after step 3** instead of chaining to done. The range *is* the opt-in — you do not also
|
|
108
|
+
pass `--auto`. Run it as the `--auto` loop with one extra halt: **stop before building
|
|
109
|
+
any next step whose plan number is past the top of the range.** It adds no machinery —
|
|
110
|
+
just the one more entry already in the halt list above.
|
|
111
|
+
|
|
112
|
+
- **`N-M` with N ≤ M** — build N…M, self-approving and checkpointing each, then pause at
|
|
113
|
+
M. `N-N` is just the single step `N` (which already ends at the pause).
|
|
114
|
+
- **N > M** (e.g. `3-1`) — that is not a range you can walk; report it and stop rather
|
|
115
|
+
than guess the intent.
|
|
116
|
+
- **M past the last planned step** (e.g. `1-9` with three steps) — build through the
|
|
117
|
+
last planned step and stop; that is the existing "no planned steps remain" halt, not
|
|
118
|
+
an error.
|
|
119
|
+
- **A step inside the range won't build** (missing, or its seam won't parse) — `plumbbob
|
|
120
|
+
build <n>` fails exactly as it always does; surface it and stop, the same as a red
|
|
121
|
+
check. Do not skip past the gap.
|
|
122
|
+
- **N is above the next undone step** — you are jumping over earlier planned work; note
|
|
123
|
+
that you are skipping the steps before N, then proceed (the same latitude as a
|
|
124
|
+
single-number jump like `/pb-build 4`).
|
|
100
125
|
|
|
101
126
|
## The hard contracts
|
|
102
127
|
|
|
@@ -105,8 +130,9 @@ human asked for it by name. The default — no flag — always ends at the pause
|
|
|
105
130
|
- **Build the decided step, not a new one.** Implement what `intent.md` settled. A
|
|
106
131
|
new idea mid-build is a `/pb-park`, not an edit.
|
|
107
132
|
- **Default ends at the pause.** Implement → verify → wait for approval; never
|
|
108
|
-
checkpoint without it. Only an explicit `--auto` lets the agent approve
|
|
109
|
-
and it still halts on a red check or any mismatch
|
|
133
|
+
checkpoint without it. Only an explicit `--auto` or a step range lets the agent approve
|
|
134
|
+
in your place, and it still halts on a red check or any mismatch — a range also stops
|
|
135
|
+
at its top.
|
|
110
136
|
- **Agents feed the beat; they never advance it** (C6/D45). `before` loads context,
|
|
111
137
|
`build` writes the diff, `after` is advisory — none can checkpoint, flip a step, or
|
|
112
138
|
chain. `blocked` → unblock and re-run; `drift` → `/pb-refine`. You are still the one
|