plumbbob 0.4.2 → 0.4.8
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 +2 -2
- package/README.md +60 -44
- package/bin/pb +6 -0
- package/bin/plumbbob +9 -0
- package/dist/cli-core.js +19 -0
- package/dist/lib/orient.js +12 -12
- package/dist/lib/plugins.js +24 -0
- package/dist/verbs/check.js +1 -1
- package/dist/verbs/checkpoint.js +1 -1
- package/dist/verbs/doctor.js +22 -4
- package/dist/verbs/init.js +25 -9
- package/dist/verbs/park.js +1 -1
- package/dist/verbs/wrap.js +3 -3
- package/package.json +2 -1
- package/skills/{build → pb-build}/SKILL.md +13 -13
- package/skills/{harvest → pb-harvest}/SKILL.md +4 -4
- package/skills/{park → pb-park}/SKILL.md +2 -2
- package/skills/{plan → pb-plan}/SKILL.md +9 -9
- package/skills/{refine → pb-refine}/SKILL.md +7 -7
- package/skills/{revert → pb-revert}/SKILL.md +2 -2
- package/skills/{spike → pb-spike}/SKILL.md +2 -2
- package/skills/{status → pb-status}/SKILL.md +2 -2
- package/skills/{step → pb-step}/SKILL.md +8 -8
- package/skills/{verify → pb-verify}/SKILL.md +3 -3
- package/skills/{wrap → pb-wrap}/SKILL.md +3 -3
- package/templates/build-log.md +7 -7
- package/templates/intent.md +7 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
|
-
"displayName": "
|
|
4
|
-
"version": "0.4.
|
|
3
|
+
"displayName": "PlumbBob",
|
|
4
|
+
"version": "0.4.8",
|
|
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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PlumbBob
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<img src="hero.jpg" alt="A row of plumb bobs of varying shapes hanging from strings" width="600">
|
|
@@ -66,55 +66,55 @@ and it cannot be skipped.
|
|
|
66
66
|
|
|
67
67
|
You drive the whole loop from your IDE with eight `/plumbbob:*` skills — no step numbers to
|
|
68
68
|
remember, no raw CLI to type. Each is `disable-model-invocation`, so *you* fire
|
|
69
|
-
every move, and `/plumbbob:status` always names your next one.
|
|
69
|
+
every move, and `/plumbbob:pb-status` always names your next one.
|
|
70
70
|
|
|
71
71
|
| Skill | Does |
|
|
72
72
|
|-------|------|
|
|
73
|
-
| `/plumbbob:plan` | plan the whole goal — scaffold the session + author intent's Frame, Decisions, Constraints, **and all Steps** |
|
|
74
|
-
| `/plumbbob:step` | revise/sharpen the next step (empty input auto-syncs it to reality) |
|
|
75
|
-
| `/plumbbob:build` | *(optional)* implement the next planned step, then verify it to the pause — `--auto` self-approves and chains to done |
|
|
76
|
-
| `/plumbbob:verify` | the tick — check → self-review → validate → **PAUSE** → checkpoint |
|
|
77
|
-
| `/plumbbob:park` | capture an idea without chasing it |
|
|
78
|
-
| `/plumbbob:status` | orient — where you are, the next step's done-when + seam, and the next move |
|
|
79
|
-
| `/plumbbob:harvest` | triage parked ideas at a boundary (blocker / tangent / pivot) |
|
|
80
|
-
| `/plumbbob:wrap` | wrap up — write the report, archive safely, clear for a fresh goal |
|
|
81
|
-
|
|
82
|
-
Three optional power moves survive for when you need them: `/plumbbob:revert` (recover to
|
|
83
|
-
a checkpoint), `/plumbbob:spike` (throwaway worktree experiment), and `/plumbbob:refine` (attack
|
|
73
|
+
| `/plumbbob:pb-plan` | plan the whole goal — scaffold the session + author intent's Frame, Decisions, Constraints, **and all Steps** |
|
|
74
|
+
| `/plumbbob:pb-step` | revise/sharpen the next step (empty input auto-syncs it to reality) |
|
|
75
|
+
| `/plumbbob:pb-build` | *(optional)* implement the next planned step, then verify it to the pause — `--auto` self-approves and chains to done |
|
|
76
|
+
| `/plumbbob:pb-verify` | the tick — check → self-review → validate → **PAUSE** → checkpoint |
|
|
77
|
+
| `/plumbbob:pb-park` | capture an idea without chasing it |
|
|
78
|
+
| `/plumbbob:pb-status` | orient — where you are, the next step's done-when + seam, and the next move |
|
|
79
|
+
| `/plumbbob:pb-harvest` | triage parked ideas at a boundary (blocker / tangent / pivot) |
|
|
80
|
+
| `/plumbbob:pb-wrap` | wrap up — write the report, archive safely, clear for a fresh goal |
|
|
81
|
+
|
|
82
|
+
Three optional power moves survive for when you need them: `/plumbbob:pb-revert` (recover to
|
|
83
|
+
a checkpoint), `/plumbbob:pb-spike` (throwaway worktree experiment), and `/plumbbob:pb-refine` (attack
|
|
84
84
|
the frame for holes, or repair the plan when it drifts — usable at any point).
|
|
85
85
|
|
|
86
86
|
## The loop
|
|
87
87
|
|
|
88
|
-
The happy path is **plan the whole thing up front, then drive `/plumbbob:build` until
|
|
88
|
+
The happy path is **plan the whole thing up front, then drive `/plumbbob:pb-build` until
|
|
89
89
|
done** — approving each step at its verify pause:
|
|
90
90
|
|
|
91
91
|
```text
|
|
92
|
-
/plumbbob:plan author the whole plan (incl. all steps) (once)
|
|
92
|
+
/plumbbob:pb-plan author the whole plan (incl. all steps) (once)
|
|
93
93
|
└ per step:
|
|
94
|
-
/plumbbob:status review the next step (done-when + seam)
|
|
95
|
-
/plumbbob:step (optional) sharpen/revise it first if needed
|
|
96
|
-
/plumbbob:build (or DIY) implement it → verify → PAUSE → checkpoint
|
|
97
|
-
/plumbbob:park capture strays mid-build
|
|
98
|
-
/plumbbob:harvest triage them at a boundary
|
|
99
|
-
/plumbbob:wrap report + archive + clear (once)
|
|
94
|
+
/plumbbob:pb-status review the next step (done-when + seam)
|
|
95
|
+
/plumbbob:pb-step (optional) sharpen/revise it first if needed
|
|
96
|
+
/plumbbob:pb-build (or DIY) implement it → verify → PAUSE → checkpoint
|
|
97
|
+
/plumbbob:pb-park capture strays mid-build
|
|
98
|
+
/plumbbob:pb-harvest triage them at a boundary
|
|
99
|
+
/plumbbob:pb-wrap report + archive + clear (once)
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
Each `/plumbbob:build` builds the next undone step and stops at the pause for your
|
|
103
|
-
approval — re-firing it is itself the clock tick. (`/plumbbob:build --auto` is the opt-in
|
|
102
|
+
Each `/plumbbob:pb-build` builds the next undone step and stops at the pause for your
|
|
103
|
+
approval — re-firing it is itself the clock tick. (`/plumbbob:pb-build --auto` is the opt-in
|
|
104
104
|
that lets the agent self-approve and chain to done, halting on a red check or any
|
|
105
105
|
mismatch.) For a worked example that walks one goal end to end — planning, building
|
|
106
106
|
each step, wrapping up, archiving, and starting the next task — see
|
|
107
107
|
[`docs/happy-path.md`](docs/happy-path.md).
|
|
108
108
|
|
|
109
|
-
**Three ways to plan.** `/plumbbob:plan` produces the same artifact — a complete, standalone
|
|
109
|
+
**Three ways to plan.** `/plumbbob:pb-plan` produces the same artifact — a complete, standalone
|
|
110
110
|
`intent.md` — from whichever seed you give it: **no argument** runs a short interview;
|
|
111
111
|
**a file path** absorbs an out-of-band spec (retaining its detail so the plan stands on
|
|
112
112
|
its own); **any other text** expands your inline intent. No quotes required — it
|
|
113
113
|
disambiguates the mode itself.
|
|
114
114
|
|
|
115
|
-
**The pluggable executor.** `/plumbbob:build` is one way to turn a planned step into code
|
|
115
|
+
**The pluggable executor.** `/plumbbob:pb-build` is one way to turn a planned step into code
|
|
116
116
|
— it is *optional*. Implement by hand, in a vibe session, or with another harness,
|
|
117
|
-
and run `/plumbbob:verify` instead: it reads the *diff, not the author*. Plumbbob is the
|
|
117
|
+
and run `/plumbbob:pb-verify` instead: it reads the *diff, not the author*. Plumbbob is the
|
|
118
118
|
harness-agnostic spine; how the diff appears is a slot you fill however you like.
|
|
119
119
|
|
|
120
120
|
## Calibration: size everything to the work
|
|
@@ -123,7 +123,7 @@ The fastest way to abandon this is ceremony on a one-liner. The discipline is
|
|
|
123
123
|
*decisions before code*, not *always produce three files*.
|
|
124
124
|
|
|
125
125
|
- **Tiny** (typo, one-liner): no session. Just fix it.
|
|
126
|
-
- **Small** (a contained bug/change): `/plumbbob:plan` a frame + 2–3 decisions; one or two
|
|
126
|
+
- **Small** (a contained bug/change): `/plumbbob:pb-plan` a frame + 2–3 decisions; one or two
|
|
127
127
|
steps; build → verify → checkpoint.
|
|
128
128
|
- **Medium** (a feature touching a few modules): the full loop above.
|
|
129
129
|
- **Large / architectural**: that's Ridgeline's job, not Plumbbob's.
|
|
@@ -134,7 +134,8 @@ Calibration is the skill. When in doubt, smaller.
|
|
|
134
134
|
|
|
135
135
|
- A `plumbbob` CLI (TypeScript, run natively by Node ≥ 22.18, zero runtime
|
|
136
136
|
dependencies) — the dumb mechanical verbs the skills shell out to. You never type
|
|
137
|
-
it by hand.
|
|
137
|
+
it by hand (beyond `plumbbob --help` and `plumbbob --version`). The marketplace
|
|
138
|
+
plugin carries it on PATH via `bin/` shims; `npm i -g` installs it globally.
|
|
138
139
|
- The eight `/plumbbob:*` skills plus the optional power moves, each
|
|
139
140
|
`disable-model-invocation` so *you* fire every move.
|
|
140
141
|
- One session-gated Claude Code hook — `post-edit.sh`, a non-blocking light-feedback
|
|
@@ -150,14 +151,14 @@ Calibration is the skill. When in doubt, smaller.
|
|
|
150
151
|
blocks an edit. It exists only because Claude can't see your editor's LSP, so the
|
|
151
152
|
light tier *serves the model*.
|
|
152
153
|
- **Heavy** — the full `pnpm check` (tsc, oxlint, ast-grep, vitest, knip,
|
|
153
|
-
markdownlint). Not a hook: it runs *inside* `/plumbbob:verify`, which refuses to
|
|
154
|
+
markdownlint). Not a hook: it runs *inside* `/plumbbob:pb-verify`, which refuses to
|
|
154
155
|
checkpoint while red. The hard gate lives on the deliberate boundary, not the
|
|
155
156
|
keystroke.
|
|
156
157
|
|
|
157
158
|
## STATE is orientation, not a gate
|
|
158
159
|
|
|
159
160
|
The current position lives in one word in `.plumbbob/STATE` — `DESIGN`, `BUILD`, or
|
|
160
|
-
`SPIKE`. It no longer gates anything. It is read by `/plumbbob:status` to tell you where
|
|
161
|
+
`SPIKE`. It no longer gates anything. It is read by `/plumbbob:pb-status` to tell you where
|
|
161
162
|
you are and what to do next; a wrong state is a mislabeled position on a map, not a
|
|
162
163
|
locked door. The post-edit hook is session-gated: a repo with no `.plumbbob/STATE`
|
|
163
164
|
behaves exactly like plain Claude Code.
|
|
@@ -177,7 +178,8 @@ archives plain markdown under `.plumbbob/archive/` and never touches git.
|
|
|
177
178
|
STATE # one word: DESIGN | BUILD | SPIKE — orientation, not a gate
|
|
178
179
|
SEAM # the in-flight step's declared paths (awareness, not a lock)
|
|
179
180
|
STEP # the in-flight step number
|
|
180
|
-
|
|
181
|
+
config # key=value; check=<heavy-check command> (defaults to pnpm run check)
|
|
182
|
+
checkpoints # "baseline <sha>" then "step N <sha>", one per verified step
|
|
181
183
|
intent.md # canonical intent
|
|
182
184
|
build-log.md # live ledger
|
|
183
185
|
archive/
|
|
@@ -189,21 +191,34 @@ archives plain markdown under `.plumbbob/archive/` and never touches git.
|
|
|
189
191
|
|
|
190
192
|
## Install
|
|
191
193
|
|
|
192
|
-
Plumbbob
|
|
193
|
-
|
|
194
|
-
|
|
194
|
+
Plumbbob installs **once, globally** — like `gh` or your dotfiles. There are two co-equal,
|
|
195
|
+
mutually-exclusive ways to do it (both register a Claude Code plugin named `plumbbob`;
|
|
196
|
+
running both collides over the `/plumbbob:*` namespace).
|
|
197
|
+
|
|
198
|
+
**npm global + `init`** — the npm package ships the CLI, the skills, and the hook; `plumbbob
|
|
199
|
+
init` links them into Claude Code as an in-place plugin:
|
|
195
200
|
|
|
196
201
|
```sh
|
|
197
202
|
npm i -g plumbbob # the CLI (also a `pb` shorthand)
|
|
198
203
|
plumbbob init # link it into Claude Code; --uninstall to undo
|
|
199
204
|
```
|
|
200
205
|
|
|
201
|
-
`init` symlinks the package into `~/.claude/skills/plumbbob`, where Claude Code
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
206
|
+
`init` symlinks the package into `~/.claude/skills/plumbbob`, where Claude Code loads it as a
|
|
207
|
+
plugin; the post-edit hook auto-registers from `hooks.json`. Because it's a symlink, a later
|
|
208
|
+
`npm i -g plumbbob@latest` stays live with no re-link.
|
|
209
|
+
|
|
210
|
+
**The marketplace plugin** — self-contained: it ships the skills *and* the `plumbbob`/`pb`
|
|
211
|
+
CLI on PATH (via its `bin/` shims), so it needs neither `npm i -g` nor `plumbbob init`:
|
|
212
|
+
|
|
213
|
+
```text
|
|
214
|
+
/plugin install plumbbob@<marketplace>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Either way, Claude Code namespaces the skills as `/plumbbob:<skill>`, so they appear as
|
|
218
|
+
`/plumbbob:pb-plan`, `/plumbbob:pb-status`, and the rest. Nothing else under `~` is touched
|
|
219
|
+
and `settings.json` is left alone — restart Claude Code (or `/reload-plugins`) to activate.
|
|
220
|
+
If a marketplace plumbbob is already installed, `plumbbob init` refuses rather than create
|
|
221
|
+
the collision (`--force` overrides), and `plumbbob doctor` flags a double-install.
|
|
207
222
|
|
|
208
223
|
**Sessions are per-project.** Install scope is not session scope: you install the
|
|
209
224
|
tool once, but each goal lives in its own repo — `plumbbob start "<goal>"` writes a
|
|
@@ -219,10 +234,11 @@ look. Claude Code is the first, first-class target.
|
|
|
219
234
|
plumbbob doctor
|
|
220
235
|
```
|
|
221
236
|
|
|
222
|
-
`doctor`
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
237
|
+
`doctor` works for either install path: it confirms a marketplace plugin, or checks that the
|
|
238
|
+
skills-dir link resolves to the plugin manifest, the skills, and the hook — flagging a
|
|
239
|
+
double-install collision — and prints the exact fix for anything broken. Run it first if a
|
|
240
|
+
`/plumbbob:*` skill ever opens with an empty dashboard;
|
|
241
|
+
[`docs/troubleshooting.md`](docs/troubleshooting.md) covers the rest.
|
|
226
242
|
|
|
227
243
|
## Development
|
|
228
244
|
|
package/bin/pb
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# pb — short alias for `plumbbob` (see bin/plumbbob for the full note). Same PATH
|
|
3
|
+
# shim: resolves the bundled CLI relative to this file so the plugin works on PATH
|
|
4
|
+
# without a global install.
|
|
5
|
+
here=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
|
|
6
|
+
exec node "$here/../dist/cli.js" "$@"
|
package/bin/plumbbob
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# plumbbob — PATH shim for the marketplace / plugin install. Claude Code adds this
|
|
3
|
+
# bin/ dir to the Bash tool's PATH while the plugin is enabled (the plugins `bin/`
|
|
4
|
+
# convention), so the driver skills can shell a bare `plumbbob` without a global
|
|
5
|
+
# `npm i -g`. The CLI is resolved relative to this file, so it works from the
|
|
6
|
+
# plugin's install/cache dir wherever that lands. Requires node >=22 on PATH (the
|
|
7
|
+
# same requirement as the published `bin`/`dist/cli.js` shebang).
|
|
8
|
+
here=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)
|
|
9
|
+
exec node "$here/../dist/cli.js" "$@"
|
package/dist/cli-core.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// entry (cli.ts) so the routing/help logic is unit-testable in-process without
|
|
3
3
|
// the top-level process.exit. Zero runtime deps, node: builtins only (D1/C2).
|
|
4
4
|
// Functional/procedural: no classes, no `this`, no default export (C1).
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
5
7
|
import { start } from "./verbs/start.js";
|
|
6
8
|
import { status } from "./verbs/status.js";
|
|
7
9
|
import { park } from "./verbs/park.js";
|
|
@@ -36,6 +38,19 @@ export function formatHelp() {
|
|
|
36
38
|
const rows = VERBS.map((v) => ` ${v.name.padEnd(width)} ${v.summary}`);
|
|
37
39
|
return ['plumbbob — attention-first build process', '', 'Usage: plumbbob <verb> [args]', '', 'Verbs:', ...rows, ''].join('\n');
|
|
38
40
|
}
|
|
41
|
+
// The package version, read from the package.json that ships one level above the
|
|
42
|
+
// compiled CLI (dist/cli-core.js → ../package.json; in tests src/cli-core.ts →
|
|
43
|
+
// ../package.json, the repo root). Builtins only (C2); an absent or malformed
|
|
44
|
+
// manifest degrades to 'unknown' rather than throwing, so `--version` never errors.
|
|
45
|
+
export function readVersion() {
|
|
46
|
+
try {
|
|
47
|
+
const raw = readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8');
|
|
48
|
+
return JSON.parse(raw).version ?? 'unknown';
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return 'unknown';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
39
54
|
function dispatch(verb, cwd, rest) {
|
|
40
55
|
switch (verb) {
|
|
41
56
|
case 'start':
|
|
@@ -72,6 +87,10 @@ export function run(argv) {
|
|
|
72
87
|
process.stdout.write(`${formatHelp()}\n`);
|
|
73
88
|
return 0;
|
|
74
89
|
}
|
|
90
|
+
if (verb === 'version' || verb === '--version' || verb === '-v') {
|
|
91
|
+
process.stdout.write(`plumbbob ${readVersion()}\n`);
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
75
94
|
try {
|
|
76
95
|
return dispatch(verb, process.cwd(), rest);
|
|
77
96
|
}
|
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 `/plumbbob:harvest` and no longer counts; the
|
|
80
|
+
// A harvested item is flipped to `- [x]` by `/plumbbob: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;
|
|
@@ -99,30 +99,30 @@ function nextMove(state, steps, inFlight, parked) {
|
|
|
99
99
|
case 'SPIKE':
|
|
100
100
|
return 'close the spike — `plumbbob spike done`';
|
|
101
101
|
case 'FINISH':
|
|
102
|
-
return 'wrap up — `/plumbbob:wrap`';
|
|
102
|
+
return 'wrap up — `/plumbbob:pb-wrap`';
|
|
103
103
|
case 'REVIEW':
|
|
104
|
-
return 'read the diff cold against intent, then `/plumbbob:verify`';
|
|
104
|
+
return 'read the diff cold against intent, then `/plumbbob:pb-verify`';
|
|
105
105
|
case 'BUILD': {
|
|
106
106
|
const n = inFlight ?? steps.find((s) => !s.done)?.n;
|
|
107
107
|
return n === undefined
|
|
108
|
-
? 'finish the step in flight — `/plumbbob:verify`'
|
|
109
|
-
: `finish step ${n} — \`/plumbbob:verify\` (or keep editing, then \`/plumbbob:verify\`)`;
|
|
108
|
+
? 'finish the step in flight — `/plumbbob:pb-verify`'
|
|
109
|
+
: `finish step ${n} — \`/plumbbob:pb-verify\` (or keep editing, then \`/plumbbob:pb-verify\`)`;
|
|
110
110
|
}
|
|
111
111
|
default: {
|
|
112
112
|
// DESIGN (and any unknown state): you are at the boundary.
|
|
113
113
|
const nextUndone = steps.find((s) => !s.done);
|
|
114
114
|
if (nextUndone === undefined) {
|
|
115
115
|
if (steps.length === 0) {
|
|
116
|
-
return 'plan the first step — `/plumbbob:step`';
|
|
116
|
+
return 'plan the first step — `/plumbbob:pb-step`';
|
|
117
117
|
}
|
|
118
118
|
// Batch-default: the steps were planned up front, so finishing them usually
|
|
119
|
-
// means "wrap up" — but `/plumbbob:step` can still add an increment if reality grew.
|
|
120
|
-
const harvest = parked > 0 ? `harvest ${parked} parked idea${parked === 1 ? '' : 's'} — \`/plumbbob:harvest\`; then ` : '';
|
|
121
|
-
return `${harvest}wrap up — \`/plumbbob:wrap\` (or \`/plumbbob:step\` to add another increment)`;
|
|
119
|
+
// means "wrap up" — but `/plumbbob:pb-step` can still add an increment if reality grew.
|
|
120
|
+
const harvest = parked > 0 ? `harvest ${parked} parked idea${parked === 1 ? '' : 's'} — \`/plumbbob:pb-harvest\`; then ` : '';
|
|
121
|
+
return `${harvest}wrap up — \`/plumbbob:pb-wrap\` (or \`/plumbbob:pb-step\` to add another increment)`;
|
|
122
122
|
}
|
|
123
123
|
return nextUndone.planned
|
|
124
|
-
? `build step ${nextUndone.n} — \`/plumbbob:build\` (or \`/plumbbob:step\` to revise it first)`
|
|
125
|
-
: `plan step ${nextUndone.n} — \`/plumbbob:step\``;
|
|
124
|
+
? `build step ${nextUndone.n} — \`/plumbbob:pb-build\` (or \`/plumbbob:pb-step\` to revise it first)`
|
|
125
|
+
: `plan step ${nextUndone.n} — \`/plumbbob:pb-step\``;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
}
|
|
@@ -153,7 +153,7 @@ export function formatOrientation(o) {
|
|
|
153
153
|
if (s !== nextUndone) {
|
|
154
154
|
return head;
|
|
155
155
|
}
|
|
156
|
-
// Surface the next step's detail so the human can review it (and `/plumbbob:step`-
|
|
156
|
+
// Surface the next step's detail so the human can review it (and `/plumbbob:pb-step`-
|
|
157
157
|
// revise) before building. Only what's present — a rough step shows neither.
|
|
158
158
|
const detail = [];
|
|
159
159
|
if (o.nextDoneWhen !== null) {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Detect a marketplace-installed plumbbob plugin from Claude Code's plugin state.
|
|
2
|
+
// Used to keep the skills-dir install (`plumbbob init`) from colliding with a
|
|
3
|
+
// marketplace install: two plugins both named `plumbbob` fight over the
|
|
4
|
+
// `/plumbbob:*` namespace and the skills can drop to flat names (`/pb-status`).
|
|
5
|
+
// Read-only, node builtins only (C1/C2): a missing / unreadable / malformed file
|
|
6
|
+
// means "none installed".
|
|
7
|
+
import { readFileSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
// Marketplace plugin ids for plumbbob recorded in installed_plugins.json
|
|
10
|
+
// (e.g. "plumbbob@robmclarty"). Empty when none, or the file is absent/unreadable.
|
|
11
|
+
// `plumbbob@<marketplace>` matches; `plumbbob-spike@x` and the like do not.
|
|
12
|
+
export function marketplacePlumbbob(home) {
|
|
13
|
+
try {
|
|
14
|
+
const raw = readFileSync(join(home, '.claude', 'plugins', 'installed_plugins.json'), 'utf8');
|
|
15
|
+
const plugins = JSON.parse(raw).plugins;
|
|
16
|
+
if (plugins === undefined || plugins === null) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
return Object.keys(plugins).filter((id) => id === 'plumbbob' || id.startsWith('plumbbob@'));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
}
|
package/dist/verbs/check.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// `plumbbob check` — run the heavy gate (D16/D24) and report, with NO state
|
|
2
|
-
// change. The read-only half of the verify tick: `/plumbbob:verify` runs this before the
|
|
2
|
+
// change. The read-only half of the verify tick: `/plumbbob: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).
|
|
5
5
|
import { findRepoRoot } from "../lib/git.js";
|
package/dist/verbs/checkpoint.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// It gates on a green check, then commits any pending work (or records the existing
|
|
5
5
|
// HEAD when the tree is already clean — the human's commit skill may have committed
|
|
6
6
|
// first), records the SHA, flips the intent checkbox to `[x]`, clears any STEP/SEAM,
|
|
7
|
-
// and returns to DESIGN. The diff's author is irrelevant: `/plumbbob:build`, your hands,
|
|
7
|
+
// and returns to DESIGN. The diff's author is irrelevant: `/plumbbob:pb-build`, your hands,
|
|
8
8
|
// a vibe session, or another harness all checkpoint the same way.
|
|
9
9
|
import { appendFileSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
10
|
import { commit, findRepoRoot, headSha, isDirty, stageAll } from "../lib/git.js";
|
package/dist/verbs/doctor.js
CHANGED
|
@@ -4,12 +4,13 @@
|
|
|
4
4
|
// in place as a plugin (skills `/plumbbob:*`, the post-edit hook from hooks.json).
|
|
5
5
|
// doctor verifies the link resolves to a package carrying the manifest, the skills,
|
|
6
6
|
// and the hook — and names the fix for anything missing. The failure class it
|
|
7
|
-
// exists for is SILENT (a `/plumbbob:status` that opens an empty dashboard because the
|
|
7
|
+
// exists for is SILENT (a `/plumbbob:pb-status` that opens an empty dashboard because the
|
|
8
8
|
// plugin never linked). Functional, node builtins only (C1/C2).
|
|
9
9
|
import { existsSync, lstatSync, readdirSync, readlinkSync } from 'node:fs';
|
|
10
10
|
import { homedir } from 'node:os';
|
|
11
11
|
import { join } from 'node:path';
|
|
12
12
|
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { marketplacePlumbbob } from "../lib/plugins.js";
|
|
13
14
|
// The plumbbob package's own skills/ dir (the canonical set), off this module's
|
|
14
15
|
// URL so it resolves the same from src/ (dev) and dist/ (published).
|
|
15
16
|
function packageDir(name) {
|
|
@@ -58,8 +59,25 @@ export function doctor() {
|
|
|
58
59
|
const link = join(home, '.claude', 'skills', 'plumbbob');
|
|
59
60
|
const shipped = listSkills(packageDir('skills'));
|
|
60
61
|
const pkg = linkedPackage(link);
|
|
61
|
-
const
|
|
62
|
-
|
|
62
|
+
const market = marketplacePlumbbob(home);
|
|
63
|
+
let checks;
|
|
64
|
+
if (pkg === null) {
|
|
65
|
+
checks =
|
|
66
|
+
market.length > 0
|
|
67
|
+
? [{ ok: true, label: `installed via marketplace (${market.join(', ')}) — skills load as /plumbbob:*, the CLI is on PATH from the plugin bin/. No init needed.` }]
|
|
68
|
+
: [{ ok: false, label: `not linked — no plugin at ${link}`, fix: 'install the marketplace plugin (/plugin install plumbbob@<marketplace>) or run: plumbbob init' }];
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
checks = buildChecks(link, pkg, shipped);
|
|
72
|
+
if (market.length > 0) {
|
|
73
|
+
checks.unshift({
|
|
74
|
+
ok: false,
|
|
75
|
+
label: `collision — also installed via marketplace (${market.join(', ')}); two plugins named plumbbob fight over /plumbbob:* and skills can drop to flat names`,
|
|
76
|
+
fix: 'keep one — `plumbbob init --uninstall` to use the marketplace plugin, or `/plugin uninstall` the marketplace one to keep this link',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const out = ['plumbbob doctor — plugin install'];
|
|
63
81
|
for (const c of checks) {
|
|
64
82
|
out.push(c.ok ? ` ✓ ${c.label}` : ` ✗ ${c.label}\n → ${c.fix}`);
|
|
65
83
|
}
|
|
@@ -68,7 +86,7 @@ export function doctor() {
|
|
|
68
86
|
out.push(failed === 0
|
|
69
87
|
? 'plumbbob: all checks passed. If a skill still misbehaves, restart Claude Code (or /reload-plugins).'
|
|
70
88
|
: `plumbbob: ${failed} problem(s) — apply the → fixes, then restart Claude Code.`);
|
|
71
|
-
out.push('plumbbob: skills shell a bare `plumbbob
|
|
89
|
+
out.push('plumbbob: skills shell a bare `plumbbob`. The marketplace plugin puts it on PATH via bin/; for the skills-dir/global install run `npm i -g plumbbob`. Sessions are per-project via `plumbbob start`.');
|
|
72
90
|
process.stdout.write(`${out.join('\n')}\n`);
|
|
73
91
|
return failed === 0 ? 0 : 1;
|
|
74
92
|
}
|
package/dist/verbs/init.js
CHANGED
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
// `plumbbob init [--uninstall]` — link plumbbob into Claude Code as an
|
|
2
|
-
// skills-directory plugin.
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
1
|
+
// `plumbbob init [--uninstall] [--force]` — link plumbbob into Claude Code as an
|
|
2
|
+
// in-place skills-directory plugin. It symlinks the installed package into
|
|
3
|
+
// ~/.claude/skills/plumbbob, where Claude Code discovers it as `plumbbob@skills-dir`
|
|
4
|
+
// — the skills load namespaced (`/plumbbob:*`) and the post-edit hook auto-registers
|
|
5
|
+
// from hooks/hooks.json. This is the deliberate non-marketplace install path — kept
|
|
6
|
+
// first-class, not deprecated: it serves an `npm i -g` global, local dev, and clients
|
|
7
|
+
// predating plugins, and keeps plumbbob usable as a standalone CLI (and, later, under
|
|
8
|
+
// other agents) rather than Claude-marketplace-only. The marketplace plugin is the
|
|
9
|
+
// co-equal self-contained alternative (it ships skills AND the `plumbbob` CLI on PATH
|
|
10
|
+
// via bin/, so it needs neither `npm i -g` nor `init`). The two are mutually
|
|
11
|
+
// exclusive: both register a plugin named `plumbbob`, and a double-install collides
|
|
12
|
+
// over the /plumbbob:* namespace (skills can drop to flat `/pb-status` names). So init
|
|
13
|
+
// REFUSES when a marketplace plumbbob is already installed — `--force` overrides
|
|
14
|
+
// (the dev-install path uses it). Global-only by design: install scope is NOT session
|
|
15
|
+
// scope — sessions stay per-project via `plumbbob start`. Idempotent + reversible
|
|
16
|
+
// (`--uninstall` drops the link); it NEVER writes settings.json. Node builtins only.
|
|
10
17
|
import { lstatSync, mkdirSync, readlinkSync, rmSync, symlinkSync } from 'node:fs';
|
|
11
18
|
import { homedir } from 'node:os';
|
|
12
19
|
import { join } from 'node:path';
|
|
13
20
|
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import { marketplacePlumbbob } from "../lib/plugins.js";
|
|
14
22
|
// The installed package root (parent of .claude-plugin/, skills/, hooks/, dist/),
|
|
15
23
|
// off this module's URL — the global install when run as the published bin, the
|
|
16
24
|
// checkout in dev. No trailing slash, so it compares clean against a readlink.
|
|
@@ -47,6 +55,14 @@ export function init(args) {
|
|
|
47
55
|
if (args.includes('--uninstall')) {
|
|
48
56
|
return uninstall(link);
|
|
49
57
|
}
|
|
58
|
+
const market = marketplacePlumbbob(home);
|
|
59
|
+
if (market.length > 0 && !args.includes('--force')) {
|
|
60
|
+
process.stderr.write(`plumbbob: a marketplace plumbbob plugin is already installed (${market.join(', ')}).\n` +
|
|
61
|
+
'plumbbob: it already provides the skills (`/plumbbob:*`) and the `plumbbob` CLI on PATH (the plugin bin/) — no `plumbbob init` needed.\n' +
|
|
62
|
+
`plumbbob: linking ${link} would register a SECOND plugin named \`plumbbob\`; the two collide over the /plumbbob:* namespace and skills can drop to flat names (\`/pb-status\`).\n` +
|
|
63
|
+
'plumbbob: to use the skills-dir link instead, first remove the marketplace one (`/plugin uninstall plumbbob@<marketplace>`), or re-run with `--force` if you know what you are doing.\n');
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
50
66
|
mkdirSync(join(home, '.claude', 'skills'), { recursive: true });
|
|
51
67
|
if (present(link)) {
|
|
52
68
|
const current = symlinkTarget(link);
|
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 /park's job).
|
|
2
|
+
// the build-log's Park list. No model turn, no composition (that is /plumbbob: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/dist/verbs/wrap.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// `plumbbob wrap` (D9) — the v2 close-out, replacing the v1 four-verb
|
|
2
2
|
// finish ceremony. It archives intent + build-log + report
|
|
3
|
-
// (the `/plumbbob:wrap` skill writes the report by default) under .plumbbob/archive/,
|
|
3
|
+
// (the `/plumbbob:pb-wrap` skill writes the report by default) under .plumbbob/archive/,
|
|
4
4
|
// clears the active files, and deletes the control state (STATE last). Unlike v1
|
|
5
5
|
// `finish` there is NO refuse-without-report gate — guidance offers the artifact, it
|
|
6
6
|
// does not wall the exit. Archive-then-clear, never destroy (C4); git untouched (C5).
|
|
@@ -20,7 +20,7 @@ export function wrap(cwd) {
|
|
|
20
20
|
}
|
|
21
21
|
else {
|
|
22
22
|
process.stderr.write('plumbbob: note — no report.md found; archiving intent + build-log without one ' +
|
|
23
|
-
'(/plumbbob:wrap normally writes the report first). No gate (D9).\n');
|
|
23
|
+
'(/plumbbob:pb-wrap normally writes the report first). No gate (D9).\n');
|
|
24
24
|
}
|
|
25
25
|
const archived = archiveSession(root);
|
|
26
26
|
// Clear the active files — now safely archived — then the control state, STATE
|
|
@@ -32,7 +32,7 @@ export function wrap(cwd) {
|
|
|
32
32
|
rmSync(stepPath(root), { force: true });
|
|
33
33
|
rmSync(join(sidecarDir(root), 'STATE'), { force: true });
|
|
34
34
|
process.stdout.write(`plumbbob: wrap — archived to ${relative(root, archived)}. Sidecar cleared. ` +
|
|
35
|
-
'Run `/plumbbob:plan` (or `plumbbob start "<title>"`) to frame the next goal.\n');
|
|
35
|
+
'Run `/plumbbob:pb-plan` (or `plumbbob start "<title>"`) to frame the next goal.\n');
|
|
36
36
|
return 0;
|
|
37
37
|
}
|
|
38
38
|
// Append the recorded checkpoints (baseline + each `step n <sha>`) to the report so
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"description": "Attention-first build process: 11 skills + a CLI that keep you the decider — guidance, not enforcement.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
".claude-plugin",
|
|
28
|
+
"bin",
|
|
28
29
|
"dist",
|
|
29
30
|
"hooks",
|
|
30
31
|
"skills",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: build
|
|
2
|
+
name: pb-build
|
|
3
3
|
description: The optional engine — read the next planned step from intent, implement it (its done-when, seam, Decisions, Constraints), then verify it through to the approval pause. Skip it to build by hand/vibed/another harness. `--auto` self-approves and chains to done.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
model: opus
|
|
@@ -12,31 +12,31 @@ Current session state (injected when this skill runs): !`plumbbob status 2>/dev/
|
|
|
12
12
|
|
|
13
13
|
This is the **bundled executor** — one way to turn a planned step into code. It is
|
|
14
14
|
**optional** (D3): you can implement any step by hand, in a vibe session, or with
|
|
15
|
-
another harness and go straight to `/plumbbob:verify` instead — plumbbob does not care how
|
|
15
|
+
another harness and go straight to `/plumbbob:pb-verify` instead — plumbbob does not care how
|
|
16
16
|
the diff appeared. When you do run it, it reads the plan, writes the step, and
|
|
17
17
|
carries straight through to the verify pause.
|
|
18
18
|
|
|
19
|
-
Since `/plumbbob:plan` lays down the whole step list up front, the happy path is to fire
|
|
20
|
-
`/plumbbob:build` once per step until done — each run builds the next undone step and stops
|
|
21
|
-
at the pause for your approval. **Re-firing `/plumbbob:build` is itself the clock tick.**
|
|
19
|
+
Since `/plumbbob:pb-plan` lays down the whole step list up front, the happy path is to fire
|
|
20
|
+
`/plumbbob:pb-build` once per step until done — each run builds the next undone step and stops
|
|
21
|
+
at the pause for your approval. **Re-firing `/plumbbob:pb-build` is itself the clock tick.**
|
|
22
22
|
|
|
23
23
|
## What this skill does, in order
|
|
24
24
|
|
|
25
|
-
1. **Pick the step.** Use the number you were invoked with (e.g. `/plumbbob:build 4`), else
|
|
25
|
+
1. **Pick the step.** Use the number you were invoked with (e.g. `/plumbbob:pb-build 4`), else
|
|
26
26
|
the next undone, planned step in `.plumbbob/intent.md`. If there is no planned step
|
|
27
|
-
to build, stop and tell the human to `/plumbbob:step` first.
|
|
27
|
+
to build, stop and tell the human to `/plumbbob:pb-step` first.
|
|
28
28
|
2. **Enter the step.** Run `plumbbob build <n>` (records the in-flight STEP +
|
|
29
|
-
SEAM so `/plumbbob:status` shows the step in flight; in v2 the seam is awareness, not a
|
|
29
|
+
SEAM so `/plumbbob:pb-status` shows the step in flight; in v2 the seam is awareness, not a
|
|
30
30
|
lock).
|
|
31
31
|
3. **Read the plan.** Read the step's **done-when**, its **seam**, and the
|
|
32
32
|
**Decisions** and **Constraints** in `intent.md`. Build to *that* — the deciding
|
|
33
33
|
already happened, off the chat.
|
|
34
34
|
4. **Implement** the step, and only that step, staying within the declared seam. A
|
|
35
|
-
new problem or "ooh what if" that surfaces mid-build is a `/plumbbob:park`, **not** an
|
|
35
|
+
new problem or "ooh what if" that surfaces mid-build is a `/plumbbob:pb-park`, **not** an
|
|
36
36
|
edit — capture it and stay on the step. If you genuinely cannot finish without
|
|
37
37
|
touching more than the seam, that is scope drift: surface it to the human rather
|
|
38
38
|
than sprawling.
|
|
39
|
-
5. **Verify, through to the pause.** Run the verify tick exactly as `/plumbbob:verify`
|
|
39
|
+
5. **Verify, through to the pause.** Run the verify tick exactly as `/plumbbob:pb-verify`
|
|
40
40
|
does: `plumbbob check` → self-review the diff against the done-when, the
|
|
41
41
|
Decisions, and the Constraints (a single structured read, D16) → validate → **PAUSE
|
|
42
42
|
for the human's approval** → only on approval, checkpoint with
|
|
@@ -45,7 +45,7 @@ at the pause for your approval. **Re-firing `/plumbbob:build` is itself the cloc
|
|
|
45
45
|
|
|
46
46
|
## `--auto` — let the agent be the clock (opt-in)
|
|
47
47
|
|
|
48
|
-
`/plumbbob:build --auto` is the explicit escape hatch when the human wants unattended
|
|
48
|
+
`/plumbbob:pb-build --auto` is the explicit escape hatch when the human wants unattended
|
|
49
49
|
progress instead of approving each step. It does the same work, but **the agent reviews
|
|
50
50
|
and approves in the human's place**, and it **chains**:
|
|
51
51
|
|
|
@@ -61,10 +61,10 @@ human asked for it by name. The default — no flag — always ends at the pause
|
|
|
61
61
|
|
|
62
62
|
## The hard contracts
|
|
63
63
|
|
|
64
|
-
- **Optional, never required.** The loop works without this skill; `/plumbbob:verify`
|
|
64
|
+
- **Optional, never required.** The loop works without this skill; `/plumbbob:pb-verify`
|
|
65
65
|
checkpoints a hand-built or vibed diff just the same (D3).
|
|
66
66
|
- **Build the decided step, not a new one.** Implement what `intent.md` settled. A
|
|
67
|
-
new idea mid-build is a `/plumbbob:park`, not an edit.
|
|
67
|
+
new idea mid-build is a `/plumbbob:pb-park`, not an edit.
|
|
68
68
|
- **Default ends at the pause.** Implement → verify → wait for approval; never
|
|
69
69
|
checkpoint without it. Only an explicit `--auto` lets the agent approve in your place,
|
|
70
70
|
and it still halts on a red check or any mismatch.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: harvest
|
|
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
5
|
model: opus
|
|
@@ -10,7 +10,7 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
|
10
10
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
|
-
`/plumbbob:harvest` is the complement of `/plumbbob:park` (D7): you parked ideas as seeds during a
|
|
13
|
+
`/plumbbob:pb-harvest` is the complement of `/plumbbob:pb-park` (D7): you parked ideas as seeds during a
|
|
14
14
|
build; now, at a boundary, you harvest them — decide what each one is.
|
|
15
15
|
|
|
16
16
|
## When to run it — wrong-state refusal
|
|
@@ -19,7 +19,7 @@ Harvest at a **step boundary**: after a step is checkpointed and you are back in
|
|
|
19
19
|
DESIGN, not mid-step. Read the state injected above:
|
|
20
20
|
|
|
21
21
|
- `NO ACTIVE SESSION` — **refuse**; tell the human to `plumbbob start "<title>"` first.
|
|
22
|
-
- `BUILD` — a step is in flight; **refuse** and suggest finishing it with `/plumbbob:verify`
|
|
22
|
+
- `BUILD` — a step is in flight; **refuse** and suggest finishing it with `/plumbbob:pb-verify`
|
|
23
23
|
before harvesting. Chasing parked items mid-step is the disease parking prevents.
|
|
24
24
|
- `DESIGN` (and other settled states) — go ahead.
|
|
25
25
|
|
|
@@ -40,7 +40,7 @@ one line of reasoning, then **wait for the human to confirm or override**. Write
|
|
|
40
40
|
**only after** per-item confirmation:
|
|
41
41
|
|
|
42
42
|
- Record each confirmed class in `build-log.md`'s `## Harvest` section.
|
|
43
|
-
- **Flip the harvested item** from `- [ ]` to `- [x]` in the Park list, so `/plumbbob:status`
|
|
43
|
+
- **Flip the harvested item** from `- [ ]` to `- [x]` in the Park list, so `/plumbbob:pb-status`
|
|
44
44
|
stops counting it as open.
|
|
45
45
|
- A confirmed **blocker** also folds its decision into `intent.md`.
|
|
46
46
|
- Never reclassify or resolve an item the human hasn't confirmed, and default every
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: park
|
|
2
|
+
name: pb-park
|
|
3
3
|
description: Compose one tidy tagged park line, get the human's OK in-turn, then capture it by shelling `plumbbob park` — never by editing a file. The capture half of the park/harvest loop.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
model: haiku
|
|
@@ -10,7 +10,7 @@ allowed-tools: Bash(plumbbob status:*), Bash(plumbbob park:*)
|
|
|
10
10
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
|
-
`/plumbbob:park` is the **capture** half of the loop; `/plumbbob:harvest` is where parked items
|
|
13
|
+
`/plumbbob:pb-park` is the **capture** half of the loop; `/plumbbob:pb-harvest` is where parked items
|
|
14
14
|
get triaged later (D7). Capturing the instant an idea arrives — instead of acting on
|
|
15
15
|
it — is the whole point: it protects the step in flight.
|
|
16
16
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: plan
|
|
2
|
+
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
|
disable-model-invocation: true
|
|
5
5
|
model: opus
|
|
@@ -10,10 +10,10 @@ allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob start:*
|
|
|
10
10
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
|
-
`/plumbbob:plan` is the **whole-goal** move — it opens a session and gets the deciding out
|
|
13
|
+
`/plumbbob:pb-plan` is the **whole-goal** move — it opens a session and gets the deciding out
|
|
14
14
|
of your head and onto `intent.md` *before* any code. By default it authors the
|
|
15
15
|
**complete plan, including all the Steps**, so the happy path afterward is just
|
|
16
|
-
`/plumbbob:build` until done. (Revising a single increment later is the separate `/plumbbob:step`
|
|
16
|
+
`/plumbbob:pb-build` until done. (Revising a single increment later is the separate `/plumbbob:pb-step`
|
|
17
17
|
move; do not confuse the two.)
|
|
18
18
|
|
|
19
19
|
## Three input modes (disambiguated for you — no quotes needed)
|
|
@@ -33,7 +33,7 @@ Look at the argument the human gave and pick the mode yourself:
|
|
|
33
33
|
genuinely ambiguous.
|
|
34
34
|
|
|
35
35
|
All three modes converge on the **same artifact**: a complete, standalone `intent.md`
|
|
36
|
-
an agent can follow with `/plumbbob:build`. The argument only seeds how you get there.
|
|
36
|
+
an agent can follow with `/plumbbob:pb-build`. The argument only seeds how you get there.
|
|
37
37
|
|
|
38
38
|
## What this skill does
|
|
39
39
|
|
|
@@ -55,11 +55,11 @@ an agent can follow with `/plumbbob:build`. The argument only seeds how you get
|
|
|
55
55
|
- seam: `<file>`, `<file>`
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
Every step needs a **done-when** `/plumbbob:verify` can check and a **seam** (the exact
|
|
58
|
+
Every step needs a **done-when** `/plumbbob:pb-verify` can check and a **seam** (the exact
|
|
59
59
|
paths it touches). Later steps may be fuzzier than the first — that's fine; they get
|
|
60
|
-
sharpened just-in-time when you reach them with `/plumbbob:step`. Keep each small enough to
|
|
60
|
+
sharpened just-in-time when you reach them with `/plumbbob:pb-step`. Keep each small enough to
|
|
61
61
|
verify in one review pass.
|
|
62
|
-
5. **Offer to stress-test it.** Suggest `/plumbbob:refine` to attack the frame for holes (or
|
|
62
|
+
5. **Offer to stress-test it.** Suggest `/plumbbob:pb-refine` to attack the frame for holes (or
|
|
63
63
|
to repair the plan as it drifts). Optional, the human's call.
|
|
64
64
|
|
|
65
65
|
## The interview (mode 1)
|
|
@@ -72,11 +72,11 @@ Make it easy and non-intrusive:
|
|
|
72
72
|
without typing** ("done-when: the 6th request in 60s returns 429 — good?"), while
|
|
73
73
|
taking arbitrary detail when they want to give it, including pointers to other files.
|
|
74
74
|
- **Let them double back.** They will revise as the picture sharpens; that's expected.
|
|
75
|
-
They can also edit `intent.md` by hand at any time, or call `/plumbbob:refine` to repair it.
|
|
75
|
+
They can also edit `intent.md` by hand at any time, or call `/plumbbob:pb-refine` to repair it.
|
|
76
76
|
|
|
77
77
|
## The hard contracts
|
|
78
78
|
|
|
79
|
-
- **Deciding before code.** `/plumbbob:plan` writes `intent.md` only — never source.
|
|
79
|
+
- **Deciding before code.** `/plumbbob:pb-plan` writes `intent.md` only — never source.
|
|
80
80
|
- **The human converges.** You surface options and draft wording; the human picks.
|
|
81
81
|
An unresolved hole is an Open question, not a guessed Decision.
|
|
82
82
|
- **Stands on its own.** Whatever the input mode, the finished `intent.md` carries
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: refine
|
|
2
|
+
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
|
disable-model-invocation: true
|
|
5
5
|
model: opus
|
|
@@ -10,16 +10,16 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
|
10
10
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
|
-
`/plumbbob:refine` keeps `intent.md` honest. Use it at **any point** — right after `/plumbbob:plan`
|
|
13
|
+
`/plumbbob:pb-refine` keeps `intent.md` honest. Use it at **any point** — right after `/plumbbob:pb-plan`
|
|
14
14
|
to stress-test a fresh frame, or mid-build to repair a plan that drifted from what the
|
|
15
|
-
code is actually doing. It is the document-level complement to `/plumbbob:step` (which only
|
|
16
|
-
sharpens the *next* step): `/plumbbob:refine` works the *whole* plan.
|
|
15
|
+
code is actually doing. It is the document-level complement to `/plumbbob:pb-step` (which only
|
|
16
|
+
sharpens the *next* step): `/plumbbob:pb-refine` works the *whole* plan.
|
|
17
17
|
|
|
18
18
|
## No-session refusal
|
|
19
19
|
|
|
20
20
|
This skill refines an existing plan, so it needs one. Read the state injected above: if
|
|
21
21
|
it is `NO ACTIVE SESSION`, **refuse** in one line and tell the human to run
|
|
22
|
-
`plumbbob start "<title>"` (or `/plumbbob:plan`) first, and edit nothing. Every active state
|
|
22
|
+
`plumbbob start "<title>"` (or `/plumbbob:pb-plan`) first, and edit nothing. Every active state
|
|
23
23
|
is fine — refining is always available.
|
|
24
24
|
|
|
25
25
|
## Two modes
|
|
@@ -41,5 +41,5 @@ is fine — refining is always available.
|
|
|
41
41
|
approves every change to `intent.md`. Never guess a hole into a Decision.
|
|
42
42
|
- **Open questions for holes, edits for drift.** New uncertainty goes to
|
|
43
43
|
`## Open questions`; settled drift gets repaired in place once the human OKs it.
|
|
44
|
-
- **Refine the plan, not the code.** `/plumbbob:refine` touches `intent.md` only — turning a
|
|
45
|
-
decision into a diff is `/plumbbob:build` or your own hands, never this skill.
|
|
44
|
+
- **Refine the plan, not the code.** `/plumbbob:pb-refine` touches `intent.md` only — turning a
|
|
45
|
+
decision into a diff is `/plumbbob:pb-build` or your own hands, never this skill.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: revert
|
|
2
|
+
name: pb-revert
|
|
3
3
|
description: Human-triggered driver for `plumbbob revert` — git reset --hard to a checkpoint SHA (discarding the half-done step) and return to DESIGN.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
model: haiku
|
|
@@ -14,6 +14,6 @@ This is a **driver skill** — a chat-side trigger for the mechanical `plumbbob
|
|
|
14
14
|
|
|
15
15
|
## What it does
|
|
16
16
|
|
|
17
|
-
1. Read an optional target step from the way you were invoked (e.g. `/plumbbob:revert --to 2` → step `2`). With no target, revert goes to the last done-checkpoint.
|
|
17
|
+
1. Read an optional target step from the way you were invoked (e.g. `/plumbbob:pb-revert --to 2` → step `2`). With no target, revert goes to the last done-checkpoint.
|
|
18
18
|
2. Run `plumbbob revert` (or `plumbbob revert --to <n>`) via Bash. This is a `git reset --hard` — it discards the current in-progress step. Run it exactly as the human asked; do not add or drop the `--to` on your own.
|
|
19
19
|
3. Report the verb's output verbatim — which checkpoint it reset to, or any refusal.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: spike
|
|
2
|
+
name: pb-spike
|
|
3
3
|
description: Human-triggered driver for `plumbbob spike` — open a throwaway worktree experiment for a genuine fork, or tear it down with `spike done`.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
model: haiku
|
|
@@ -14,6 +14,6 @@ This is a **driver skill** — a chat-side trigger for the mechanical `plumbbob
|
|
|
14
14
|
|
|
15
15
|
## What it does
|
|
16
16
|
|
|
17
|
-
1. Read the spike target from the way you were invoked: a slug to open one (e.g. `/plumbbob:spike redis-cache`), or the literal `done` to tear the current spike down (`/plumbbob:spike done`). If neither is present, ask which and run nothing.
|
|
17
|
+
1. Read the spike target from the way you were invoked: a slug to open one (e.g. `/plumbbob:pb-spike redis-cache`), or the literal `done` to tear the current spike down (`/plumbbob:pb-spike done`). If neither is present, ask which and run nothing.
|
|
18
18
|
2. Run `plumbbob spike "<slug>"` or `plumbbob spike done` via Bash.
|
|
19
19
|
3. Report the verb's output verbatim — the worktree it created or removed, or any refusal.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: status
|
|
2
|
+
name: pb-status
|
|
3
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
|
|
@@ -19,4 +19,4 @@ 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 `/plumbbob:plan` to frame a goal.
|
|
22
|
+
2. If it reads `NO ACTIVE SESSION`, tell the human to `/plumbbob:pb-plan` to frame a goal.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: step
|
|
2
|
+
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
|
disable-model-invocation: true
|
|
5
5
|
model: opus
|
|
@@ -10,21 +10,21 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
|
10
10
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
|
-
`/plumbbob:plan` authors the **whole** step list up front, so `/plumbbob:step` is the
|
|
13
|
+
`/plumbbob:pb-plan` authors the **whole** step list up front, so `/plumbbob:pb-step` is the
|
|
14
14
|
**just-in-time revision** move: it keeps the *next* undone step honest against what the
|
|
15
|
-
build has actually taught you, right before you `/plumbbob:build` it. (Framing the whole goal
|
|
16
|
-
is the separate `/plumbbob:plan` move.) It can also add or re-cut a step when scope genuinely
|
|
15
|
+
build has actually taught you, right before you `/plumbbob:pb-build` it. (Framing the whole goal
|
|
16
|
+
is the separate `/plumbbob:pb-plan` move.) It can also add or re-cut a step when scope genuinely
|
|
17
17
|
grew — but its everyday job is to sharpen, not to invent.
|
|
18
18
|
|
|
19
19
|
## Two ways to fire it
|
|
20
20
|
|
|
21
|
-
- **`/plumbbob:step` (no input) → automatic sharpen.** Re-examine the next undone step
|
|
21
|
+
- **`/plumbbob:pb-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
23
|
make the obvious revisions to its **done-when** and **seam** so it matches reality —
|
|
24
24
|
e.g. 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
|
-
- **`/plumbbob:step <what changed>` → directed revision.** Take the human's input and propose
|
|
27
|
+
- **`/plumbbob:pb-step <what changed>` → directed revision.** Take the human's input and propose
|
|
28
28
|
the matching change: tighten the done-when, adjust the seam, split the step in two, or
|
|
29
29
|
add a new increment the plan was missing.
|
|
30
30
|
|
|
@@ -33,7 +33,7 @@ grew — but its everyday job is to sharpen, not to invent.
|
|
|
33
33
|
1. **Read the plan and the reality.** Read `intent.md`'s Frame, Decisions, Constraints,
|
|
34
34
|
and the steps already done, plus the next undone step, to see what it *should* now be.
|
|
35
35
|
2. **Propose the revision** (or the new/split step): a one-line **title**, a **done-when**
|
|
36
|
-
`/plumbbob:verify` can validate, and a **seam** (exact paths, or a `dir/` grant). Keep it
|
|
36
|
+
`/plumbbob:pb-verify` can validate, and a **seam** (exact paths, or a `dir/` grant). Keep it
|
|
37
37
|
small enough to verify in one review pass. Show the before/after so the human can see
|
|
38
38
|
what you changed and why.
|
|
39
39
|
3. **Get the human's OK**, then write it into `## Steps` in the standard format —
|
|
@@ -42,7 +42,7 @@ grew — but its everyday job is to sharpen, not to invent.
|
|
|
42
42
|
|
|
43
43
|
## The hard contracts
|
|
44
44
|
|
|
45
|
-
- **One verifiable increment.** Each step carries a done-when `/plumbbob:verify` can check
|
|
45
|
+
- **One verifiable increment.** Each step carries a done-when `/plumbbob:pb-verify` can check
|
|
46
46
|
and a seam small enough to review in one pass.
|
|
47
47
|
- **Edit `## Steps` only**, in the standard format `status` and `build` parse — never
|
|
48
48
|
the Roadmap, never loose prose. A done step (`[x]`) is history; do not rewrite it.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: verify
|
|
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
5
|
model: opus
|
|
@@ -11,7 +11,7 @@ allowed-tools: Read, Bash(plumbbob status:*), Bash(plumbbob check:*), Bash(plumb
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
13
|
This is the **tick** — the one beat where the human is the clock. Whatever produced
|
|
14
|
-
the current diff — `/plumbbob:build`, your own hands, a vibe session, another harness —
|
|
14
|
+
the current diff — `/plumbbob:pb-build`, your own hands, a vibe session, another harness —
|
|
15
15
|
this skill verifies it the same way: **it reads the diff, not the author** (D3).
|
|
16
16
|
|
|
17
17
|
## What this skill does, in order
|
|
@@ -40,7 +40,7 @@ this skill verifies it the same way: **it reads the diff, not the author** (D3).
|
|
|
40
40
|
- **Never skip the pause.** Check → self-review → validate, then wait. Approval is
|
|
41
41
|
the only thing that triggers the checkpoint.
|
|
42
42
|
- **Read the diff, not the author** (D3). Verify identically whether the code was
|
|
43
|
-
built by `/plumbbob:build`, by hand, vibed, or by another harness.
|
|
43
|
+
built by `/plumbbob:pb-build`, by hand, vibed, or by another harness.
|
|
44
44
|
- **Red means stop, not pause.** A failing check is not an approval decision; report
|
|
45
45
|
it and end your turn.
|
|
46
46
|
- **You review; you do not build.** If the self-review finds a problem, surface it
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: wrap
|
|
2
|
+
name: pb-wrap
|
|
3
3
|
description: Wrap up the build — write the report (what shipped, decisions, parked/harvested items, deferred tangents), then safely archive intent + build-log + report before clearing for a fresh goal. Archive-then-clear, never destroy. Report by default, no gate.
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
model: opus
|
|
@@ -10,7 +10,7 @@ allowed-tools: Read, Write, Bash(plumbbob status:*), Bash(plumbbob wrap:*)
|
|
|
10
10
|
|
|
11
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not found - install the dep and re-run: npm i -g plumbbob && plumbbob init"`
|
|
12
12
|
|
|
13
|
-
`/plumbbob:wrap` ends the build: it captures what happened, archives it, and clears the
|
|
13
|
+
`/plumbbob:pb-wrap` ends the build: it captures what happened, archives it, and clears the
|
|
14
14
|
sidecar for the next goal. **Report by default** (D9) — no refuse-without-report gate,
|
|
15
15
|
and no separate docs phase.
|
|
16
16
|
|
|
@@ -27,7 +27,7 @@ and no separate docs phase.
|
|
|
27
27
|
to the report, archives intent + build-log + report to
|
|
28
28
|
`.plumbbob/archive/<date>-<slug>/`, and clears the sidecar (STATE last). Git is not
|
|
29
29
|
touched.
|
|
30
|
-
3. **Point at the next goal** — `/plumbbob:plan` to frame the next one.
|
|
30
|
+
3. **Point at the next goal** — `/plumbbob:pb-plan` to frame the next one.
|
|
31
31
|
|
|
32
32
|
## The hard contracts
|
|
33
33
|
|
package/templates/build-log.md
CHANGED
|
@@ -5,7 +5,7 @@ step boundaries. The antidote to "my plan got lost in the noise."
|
|
|
5
5
|
Steps : where you are. One step in flight at a time.
|
|
6
6
|
Park list : where ideas go so you do not chase them. CAPTURE, never act inline.
|
|
7
7
|
Harvest : the boundary ritual that keeps you on one branch.
|
|
8
|
-
Log : the audit trail. Feeds the /plumbbob:wrap report, then gets archived.
|
|
8
|
+
Log : the audit trail. Feeds the /plumbbob:pb-wrap report, then gets archived.
|
|
9
9
|
-->
|
|
10
10
|
|
|
11
11
|
# Build log — {{TITLE}}
|
|
@@ -16,8 +16,8 @@ step boundaries. The antidote to "my plan got lost in the noise."
|
|
|
16
16
|
## Steps
|
|
17
17
|
|
|
18
18
|
*(Mirror of intent.md's Steps, with live status. Only ONE step is in flight. A step
|
|
19
|
-
is done only after a checkpoint — check green + checkpoint taken, via `/plumbbob:verify` or
|
|
20
|
-
`/plumbbob:build`.)*
|
|
19
|
+
is done only after a checkpoint — check green + checkpoint taken, via `/plumbbob:pb-verify` or
|
|
20
|
+
`/plumbbob:pb-build`.)*
|
|
21
21
|
|
|
22
22
|
- ☐ 1. <step>
|
|
23
23
|
|
|
@@ -25,16 +25,16 @@ is done only after a checkpoint — check green + checkpoint taken, via `/plumbb
|
|
|
25
25
|
|
|
26
26
|
> Mid-step, every new problem / idea / "ooh what if" lands HERE, untouched, and you
|
|
27
27
|
> go straight back to the step. Acting the instant an idea arrives is the disease.
|
|
28
|
-
> Capture is one line (`/plumbbob:park` composes it). Harvest happens only at the boundary.
|
|
28
|
+
> Capture is one line (`/plumbbob:pb-park` composes it). Harvest happens only at the boundary.
|
|
29
29
|
|
|
30
|
-
## Harvest *(run `/plumbbob:harvest` at each step boundary, after green)*
|
|
30
|
+
## Harvest *(run `/plumbbob:pb-harvest` at each step boundary, after green)*
|
|
31
31
|
|
|
32
32
|
Classify each parked item as exactly ONE. Naming it before acting is what keeps you
|
|
33
33
|
from sprawling across branches.
|
|
34
34
|
|
|
35
35
|
| Class | Meaning | Action |
|
|
36
36
|
|------------------|-------------------------------------------|---------------------------------|
|
|
37
|
-
| **blocker** | Plan was wrong/incomplete; can't proceed | `/plumbbob:revert`, fold into intent |
|
|
37
|
+
| **blocker** | Plan was wrong/incomplete; can't proceed | `/plumbbob:pb-revert`, fold into intent |
|
|
38
38
|
| **tangent** | A different path, not clearly better | Defer or kill. Default here. |
|
|
39
39
|
| **pivot signal** | Evidence the whole approach is wrong | Stop. Replan deliberately. |
|
|
40
40
|
|
|
@@ -48,7 +48,7 @@ Harvest results this boundary:
|
|
|
48
48
|
## Log
|
|
49
49
|
|
|
50
50
|
*(Append-only. One decision or event per line, dated. What you point at to say "I
|
|
51
|
-
did that — the LLM helped, but those were my calls." `/plumbbob:wrap` reads this for the
|
|
51
|
+
did that — the LLM helped, but those were my calls." `/plumbbob:pb-wrap` reads this for the
|
|
52
52
|
report; `plumbbob wrap` archives it under `.plumbbob/archive/`.)*
|
|
53
53
|
|
|
54
54
|
- <date> — <decision / event / what shipped this step>
|
package/templates/intent.md
CHANGED
|
@@ -33,24 +33,24 @@ open. If the implementor (you-later, or the LLM) has to guess, the doc failed.
|
|
|
33
33
|
## Decisions
|
|
34
34
|
|
|
35
35
|
*(One line each. Settled, not re-litigated in the chat. Grows as you resolve the
|
|
36
|
-
holes `/plumbbob:refine` surfaces, and as blockers fold in during BUILD.)*
|
|
36
|
+
holes `/plumbbob:pb-refine` surfaces, and as blockers fold in during BUILD.)*
|
|
37
37
|
|
|
38
38
|
- D1: <decision> — *because* <the one reason that mattered>
|
|
39
39
|
|
|
40
40
|
## Constraints
|
|
41
41
|
|
|
42
|
-
*(Hard rules the build must honor. `/plumbbob:verify` and `/plumbbob:refine` read against these.)*
|
|
42
|
+
*(Hard rules the build must honor. `/plumbbob:pb-verify` and `/plumbbob:pb-refine` read against these.)*
|
|
43
43
|
|
|
44
44
|
- C1: <e.g. functional/procedural only; no new dependencies>
|
|
45
45
|
|
|
46
46
|
## Steps
|
|
47
47
|
|
|
48
|
-
*(The build plan. `/plumbbob:plan` authors the **whole list up front** — each step a small,
|
|
48
|
+
*(The build plan. `/plumbbob:pb-plan` authors the **whole list up front** — each step a small,
|
|
49
49
|
verifiable increment with its own **done-when** and **seam** (the paths it will touch,
|
|
50
|
-
which `/plumbbob:build` records in `.plumbbob/SEAM` for orientation — awareness, not a lock
|
|
51
|
-
in v2). Then drive `/plumbbob:build` until done. Later steps may be fuzzier than the first;
|
|
52
|
-
sharpen the next one just-in-time with `/plumbbob:step` (empty input auto-syncs it), and use
|
|
53
|
-
`/plumbbob:refine` to repair the whole plan when a blocker rewrites it.)*
|
|
50
|
+
which `/plumbbob:pb-build` records in `.plumbbob/SEAM` for orientation — awareness, not a lock
|
|
51
|
+
in v2). Then drive `/plumbbob:pb-build` until done. Later steps may be fuzzier than the first;
|
|
52
|
+
sharpen the next one just-in-time with `/plumbbob:pb-step` (empty input auto-syncs it), and use
|
|
53
|
+
`/plumbbob:pb-refine` to repair the whole plan when a blocker rewrites it.)*
|
|
54
54
|
|
|
55
55
|
1. [ ] <step> — **done when:** <criterion, ideally a test or check result>
|
|
56
56
|
- seam: `<file>`, `<file>`
|