plumbbob 0.5.4 → 0.6.3
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 +46 -17
- package/dist/cli-core.js +4 -0
- package/dist/lib/agents.js +498 -0
- package/dist/lib/intent.js +98 -8
- package/dist/lib/settings.js +17 -0
- package/dist/lib/sidecar.js +36 -0
- package/dist/verbs/agent.js +312 -0
- package/dist/verbs/checkpoint.js +2 -1
- package/dist/verbs/doctor.js +96 -3
- package/dist/verbs/status.js +64 -2
- package/node_modules/checkride/CHANGELOG.md +139 -0
- package/node_modules/checkride/LICENSE +21 -0
- package/node_modules/checkride/README.md +179 -0
- package/node_modules/checkride/dist/adapters.d.ts +56 -0
- package/node_modules/checkride/dist/adapters.d.ts.map +1 -0
- package/node_modules/checkride/dist/adapters.js +219 -0
- package/node_modules/checkride/dist/adapters.js.map +1 -0
- package/node_modules/checkride/dist/cli.d.ts +29 -0
- package/node_modules/checkride/dist/cli.d.ts.map +1 -0
- package/node_modules/checkride/dist/cli.js +227 -0
- package/node_modules/checkride/dist/cli.js.map +1 -0
- package/node_modules/checkride/dist/config.d.ts +74 -0
- package/node_modules/checkride/dist/config.d.ts.map +1 -0
- package/node_modules/checkride/dist/config.js +126 -0
- package/node_modules/checkride/dist/config.js.map +1 -0
- package/node_modules/checkride/dist/doctor.d.ts +76 -0
- package/node_modules/checkride/dist/doctor.d.ts.map +1 -0
- package/node_modules/checkride/dist/doctor.js +299 -0
- package/node_modules/checkride/dist/doctor.js.map +1 -0
- package/node_modules/checkride/dist/index.d.ts +18 -0
- package/node_modules/checkride/dist/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/index.js +13 -0
- package/node_modules/checkride/dist/index.js.map +1 -0
- package/node_modules/checkride/dist/init.d.ts +64 -0
- package/node_modules/checkride/dist/init.d.ts.map +1 -0
- package/node_modules/checkride/dist/init.js +489 -0
- package/node_modules/checkride/dist/init.js.map +1 -0
- package/node_modules/checkride/dist/links.d.ts +23 -0
- package/node_modules/checkride/dist/links.d.ts.map +1 -0
- package/node_modules/checkride/dist/links.js +125 -0
- package/node_modules/checkride/dist/links.js.map +1 -0
- package/node_modules/checkride/dist/orchestrator.d.ts +96 -0
- package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -0
- package/node_modules/checkride/dist/orchestrator.js +234 -0
- package/node_modules/checkride/dist/orchestrator.js.map +1 -0
- package/node_modules/checkride/package.json +76 -0
- package/node_modules/checkride/templates/flat/fallow.toml +26 -0
- package/node_modules/checkride/templates/flat/pnpm-workspace.yaml +6 -0
- package/node_modules/checkride/templates/flat/tsconfig.json +9 -0
- package/node_modules/checkride/templates/hybrid/fallow.toml +42 -0
- package/node_modules/checkride/templates/hybrid/pnpm-workspace.yaml +6 -0
- package/node_modules/checkride/templates/hybrid/tsconfig.json +12 -0
- package/node_modules/checkride/templates/monorepo/fallow.toml +44 -0
- package/node_modules/checkride/templates/monorepo/pnpm-workspace.yaml +7 -0
- package/node_modules/checkride/templates/monorepo/tsconfig.json +7 -0
- package/node_modules/checkride/templates/shared/cspell.json +35 -0
- package/node_modules/checkride/templates/shared/gitignore +10 -0
- package/node_modules/checkride/templates/shared/markdownlint-cli2.jsonc +11 -0
- package/node_modules/checkride/templates/shared/npmrc +1 -0
- package/node_modules/checkride/templates/shared/oxlintrc.json +33 -0
- package/node_modules/checkride/templates/shared/rules/no-class.yml +8 -0
- package/node_modules/checkride/templates/shared/rules/no-deep-sibling-import.yml +15 -0
- package/node_modules/checkride/templates/shared/rules/no-default-export.yml +9 -0
- package/node_modules/checkride/templates/shared/rules/require-js-extension.yml +21 -0
- package/node_modules/checkride/templates/shared/sgconfig.yml +2 -0
- package/node_modules/checkride/templates/shared/tsconfig.base.json +28 -0
- package/node_modules/checkride/templates/shared/vitest.config.ts.template +27 -0
- package/package.json +4 -1
- package/skills/pb-build/SKILL.md +47 -12
- package/skills/pb-finish/SKILL.md +1 -1
- package/skills/pb-harvest/SKILL.md +1 -1
- package/skills/pb-park/SKILL.md +1 -1
- package/skills/pb-plan/SKILL.md +25 -4
- package/skills/pb-refine/SKILL.md +1 -1
- package/skills/pb-revert/SKILL.md +1 -1
- package/skills/pb-spike/SKILL.md +1 -1
- package/skills/pb-status/SKILL.md +1 -1
- package/skills/pb-step/SKILL.md +10 -2
- package/skills/pb-verify/SKILL.md +21 -6
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Fallow: dead code, circular deps, duplication, complexity, architecture boundaries.
|
|
2
|
+
# Docs: https://docs.fallow.tools
|
|
3
|
+
|
|
4
|
+
entry = [
|
|
5
|
+
"apps/*/src/index.ts",
|
|
6
|
+
"libs/*/src/index.ts",
|
|
7
|
+
"apps/*/src/**/*.test.ts",
|
|
8
|
+
"libs/*/src/**/*.test.ts",
|
|
9
|
+
"apps/*/test/**/*.test.ts",
|
|
10
|
+
"libs/*/test/**/*.test.ts",
|
|
11
|
+
"test/**/*.test.ts",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
# CLI/tooling deps used via command line or config files, not imported from source.
|
|
15
|
+
ignoreDependencies = ["@ast-grep/cli"]
|
|
16
|
+
|
|
17
|
+
[rules]
|
|
18
|
+
unused-exports = "error"
|
|
19
|
+
unused-files = "error"
|
|
20
|
+
unused-dependencies = "error"
|
|
21
|
+
circular-dependencies = "error"
|
|
22
|
+
boundary-violation = "error"
|
|
23
|
+
|
|
24
|
+
[duplicates]
|
|
25
|
+
mode = "mild"
|
|
26
|
+
minTokens = 50
|
|
27
|
+
|
|
28
|
+
[health]
|
|
29
|
+
maxCyclomatic = 15
|
|
30
|
+
maxCognitive = 15
|
|
31
|
+
|
|
32
|
+
# Architecture boundaries: libs are reusable internals; apps are deployable
|
|
33
|
+
# leaves. libs may not import from apps.
|
|
34
|
+
[[boundaries.zones]]
|
|
35
|
+
name = "apps"
|
|
36
|
+
patterns = ["apps/*/src/**"]
|
|
37
|
+
|
|
38
|
+
[[boundaries.zones]]
|
|
39
|
+
name = "libs"
|
|
40
|
+
patterns = ["libs/*/src/**"]
|
|
41
|
+
|
|
42
|
+
[[boundaries.rules]]
|
|
43
|
+
from = "libs"
|
|
44
|
+
allow = ["libs"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2",
|
|
3
|
+
"language": "en",
|
|
4
|
+
"files": ["**/src/**/*.ts", "**/test/**/*.ts", "**/*.md"],
|
|
5
|
+
"ignorePaths": [
|
|
6
|
+
"**/node_modules/**",
|
|
7
|
+
"**/dist/**",
|
|
8
|
+
".check/**",
|
|
9
|
+
"pnpm-lock.yaml",
|
|
10
|
+
"package.json",
|
|
11
|
+
"CHANGELOG.md"
|
|
12
|
+
],
|
|
13
|
+
"words": [
|
|
14
|
+
"checkride",
|
|
15
|
+
"biome",
|
|
16
|
+
"cspell",
|
|
17
|
+
"devDeps",
|
|
18
|
+
"esbuild",
|
|
19
|
+
"eslint",
|
|
20
|
+
"fallow",
|
|
21
|
+
"knip",
|
|
22
|
+
"markdownlint",
|
|
23
|
+
"NodeNext",
|
|
24
|
+
"noemit",
|
|
25
|
+
"oxlint",
|
|
26
|
+
"oxlintrc",
|
|
27
|
+
"pnpm",
|
|
28
|
+
"sgconfig",
|
|
29
|
+
"stryker",
|
|
30
|
+
"tsbuildinfo",
|
|
31
|
+
"tsconfig",
|
|
32
|
+
"tsgolint",
|
|
33
|
+
"vitest"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
save-exact=true
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./node_modules/oxlint/configuration_schema.json",
|
|
3
|
+
"plugins": ["typescript", "unicorn", "import"],
|
|
4
|
+
"categories": {
|
|
5
|
+
"correctness": "error",
|
|
6
|
+
"suspicious": "error",
|
|
7
|
+
"perf": "warn",
|
|
8
|
+
"style": "off"
|
|
9
|
+
},
|
|
10
|
+
"options": {
|
|
11
|
+
"typeAware": true
|
|
12
|
+
},
|
|
13
|
+
"rules": {
|
|
14
|
+
"typescript/no-floating-promises": "error",
|
|
15
|
+
"typescript/no-misused-promises": "error",
|
|
16
|
+
"typescript/no-explicit-any": "error",
|
|
17
|
+
"typescript/await-thenable": "error",
|
|
18
|
+
"typescript/no-unnecessary-type-assertion": "error",
|
|
19
|
+
"typescript/prefer-nullish-coalescing": "error",
|
|
20
|
+
"typescript/prefer-optional-chain": "error",
|
|
21
|
+
"no-console": "warn",
|
|
22
|
+
"eqeqeq": "error"
|
|
23
|
+
},
|
|
24
|
+
"overrides": [
|
|
25
|
+
{
|
|
26
|
+
"files": ["**/*.test.ts"],
|
|
27
|
+
"rules": {
|
|
28
|
+
"typescript/no-unsafe-type-assertion": "off"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"ignorePatterns": ["dist/**", ".check/**", ".claude/**", "node_modules/**"]
|
|
33
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
id: no-deep-sibling-import
|
|
2
|
+
message: |
|
|
3
|
+
Deep-module boundary: don't reach past a sibling module's index.
|
|
4
|
+
Use `import { ... } from '../<sibling>/index.js'` instead of
|
|
5
|
+
`'../<sibling>/<internal>.js'`.
|
|
6
|
+
severity: error
|
|
7
|
+
language: typescript
|
|
8
|
+
files:
|
|
9
|
+
- '**/src/**/*.ts'
|
|
10
|
+
rule:
|
|
11
|
+
all:
|
|
12
|
+
- kind: import_statement
|
|
13
|
+
- regex: "from\\s+['\"]\\.\\./[^/]+/[^'\"]+['\"]"
|
|
14
|
+
- not:
|
|
15
|
+
regex: "from\\s+['\"]\\.\\./[^/]+/index\\.js['\"]"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: require-js-extension
|
|
2
|
+
message: |
|
|
3
|
+
NodeNext resolution requires an explicit `.js` (or `.mjs` / `.json`) extension
|
|
4
|
+
on relative imports. Use `'./foo.js'`, not `'./foo'` or `'./foo.ts'`.
|
|
5
|
+
severity: error
|
|
6
|
+
language: typescript
|
|
7
|
+
files:
|
|
8
|
+
- '**/src/**/*.ts'
|
|
9
|
+
- '**/test/**/*.ts'
|
|
10
|
+
rule:
|
|
11
|
+
any:
|
|
12
|
+
- all:
|
|
13
|
+
- kind: import_statement
|
|
14
|
+
- regex: "from\\s+['\"]\\.{1,2}/"
|
|
15
|
+
- not:
|
|
16
|
+
regex: "from\\s+['\"]\\.{1,2}/[^'\"]*\\.(js|mjs|json)['\"]"
|
|
17
|
+
- all:
|
|
18
|
+
- kind: export_statement
|
|
19
|
+
- regex: "from\\s+['\"]\\.{1,2}/"
|
|
20
|
+
- not:
|
|
21
|
+
regex: "from\\s+['\"]\\.{1,2}/[^'\"]*\\.(js|mjs|json)['\"]"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2024",
|
|
4
|
+
"lib": ["ES2024"],
|
|
5
|
+
"module": "NodeNext",
|
|
6
|
+
"moduleResolution": "NodeNext",
|
|
7
|
+
|
|
8
|
+
"strict": true,
|
|
9
|
+
"noUncheckedIndexedAccess": true,
|
|
10
|
+
"exactOptionalPropertyTypes": true,
|
|
11
|
+
"noImplicitOverride": true,
|
|
12
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
13
|
+
"noFallthroughCasesInSwitch": true,
|
|
14
|
+
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"verbatimModuleSyntax": true,
|
|
17
|
+
"esModuleInterop": true,
|
|
18
|
+
"forceConsistentCasingInFileNames": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"resolveJsonModule": true,
|
|
21
|
+
"types": ["node"],
|
|
22
|
+
|
|
23
|
+
"composite": true,
|
|
24
|
+
"declaration": true,
|
|
25
|
+
"declarationMap": true,
|
|
26
|
+
"sourceMap": true
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
include: ['**/src/**/*.{test,spec}.ts', '**/test/**/*.{test,spec}.ts'],
|
|
6
|
+
exclude: ['**/node_modules/**', '**/dist/**'],
|
|
7
|
+
reporters: ['default'],
|
|
8
|
+
coverage: {
|
|
9
|
+
provider: 'v8',
|
|
10
|
+
include: ['**/src/**/*.ts'],
|
|
11
|
+
exclude: [
|
|
12
|
+
'**/src/**/*.{test,spec}.ts',
|
|
13
|
+
'**/src/**/*.d.ts',
|
|
14
|
+
'**/node_modules/**',
|
|
15
|
+
'**/dist/**',
|
|
16
|
+
],
|
|
17
|
+
reporter: ['text', 'json-summary', 'json'],
|
|
18
|
+
reportsDirectory: '.check/coverage',
|
|
19
|
+
thresholds: {
|
|
20
|
+
lines: 70,
|
|
21
|
+
functions: 70,
|
|
22
|
+
branches: 70,
|
|
23
|
+
statements: 70,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.3",
|
|
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",
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"checkride": "0.1.6"
|
|
58
58
|
},
|
|
59
|
+
"bundleDependencies": [
|
|
60
|
+
"checkride"
|
|
61
|
+
],
|
|
59
62
|
"scripts": {
|
|
60
63
|
"clean": "rm -rf dist",
|
|
61
64
|
"build": "tsc -p tsconfig.build.json",
|
package/skills/pb-build/SKILL.md
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pb-build
|
|
3
|
-
description: The
|
|
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
4
|
argument-hint: "[step-number] [--auto]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
model: opus
|
|
7
|
-
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(git diff:*)
|
|
7
|
+
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*)
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
# PlumbBob — build a step (the
|
|
10
|
+
# PlumbBob — build a step (the default engine)
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
12
|
+
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
13
13
|
|
|
14
|
-
This is the **bundled executor** —
|
|
15
|
-
**
|
|
14
|
+
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
|
|
16
16
|
another harness and go straight to `/pb-verify` instead — plumbbob does not care how
|
|
17
17
|
the diff appeared. When you do run it, it reads the plan, writes the step, and
|
|
18
18
|
carries straight through to the verify pause.
|
|
@@ -32,17 +32,43 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
32
32
|
3. **Read the plan.** Read the step's **done-when**, its **seam**, and the
|
|
33
33
|
**Decisions** and **Constraints** in `intent.md`. Build to *that* — the deciding
|
|
34
34
|
already happened, off the chat.
|
|
35
|
+
- **Run any bound `before`-agents** *(D43/D59)*. If the build's `harness.json` binds
|
|
36
|
+
agents to this step's `before` slot, run `plumbbob agent run --step <n> --mode
|
|
37
|
+
before` first: each returns a validated envelope on stdout that plumbbob also
|
|
38
|
+
appends to the step's `handoff.json`, and its `summary`/`body` become **context you
|
|
39
|
+
read into the build** (that is the whole point of the slot — load the context in
|
|
40
|
+
before you write). No binding, or no harness, is a clean no-op — just build.
|
|
35
41
|
4. **Implement** the step, and only that step, staying within the declared seam. A
|
|
36
42
|
new problem or "ooh what if" that surfaces mid-build is a `/pb-park`, **not** an
|
|
37
43
|
edit — capture it and stay on the step. If you genuinely cannot finish without
|
|
38
44
|
touching more than the seam, that is scope drift: surface it to the human rather
|
|
39
45
|
than sprawling.
|
|
46
|
+
- **If a `build`-slot agent is bound, delegate the diff to it** *(D43)*. Run
|
|
47
|
+
`plumbbob agent run --step <n> --mode build` and let that agent author the step's
|
|
48
|
+
code instead of writing it yourself; its envelope reports what it did. You still
|
|
49
|
+
own the verify tick below — the diff is reviewed the same way whoever wrote it (D3).
|
|
50
|
+
- **A manifest's `when` prose is your cue to fire an agent mid-build** *(D43/D55)*.
|
|
51
|
+
The three slots are the only *declarative* lifecycle points; there is no config for
|
|
52
|
+
"a salient moment in the middle." That is judgment, and you are the frontier model
|
|
53
|
+
in the room: when the work reaches the situation a bound agent's `when` (or a step
|
|
54
|
+
`note`) describes, fire `plumbbob agent run <name> --step <n>` yourself. Prose is
|
|
55
|
+
the orchestration language; you are the workflow engine.
|
|
56
|
+
- **Route a non-`done` envelope by its status** *(D52)*. An agent that returns
|
|
57
|
+
`blocked` couldn't finish (missing input, failed precondition): surface its `notes`,
|
|
58
|
+
let the human unblock, and re-run it — don't work around it. One that returns
|
|
59
|
+
`drift` finished but found the plan no longer matches reality: **stop and send the
|
|
60
|
+
human to `/pb-refine`** to repair the plan before continuing, rather than building
|
|
61
|
+
on a plan that's now wrong. A non-zero exit is a failed run: report it and stop.
|
|
40
62
|
5. **Verify, through to the pause.** Run the verify tick exactly as `/pb-verify`
|
|
41
63
|
does: `plumbbob check` (on red, read `.check/summary.json` and the failing slot's
|
|
42
64
|
raw output under `.check/` for the actual diagnostics; while iterating on a fix,
|
|
43
65
|
narrow the loop with `plumbbob check --bail --only <slots>` — the checkpoint gate
|
|
44
|
-
still runs everything) →
|
|
45
|
-
|
|
66
|
+
still runs everything) → run any bound `after`-agents (`plumbbob agent run --step
|
|
67
|
+
<n> --mode after`) and fold their envelopes into the self-review as **advisory
|
|
68
|
+
input** — they inform, they never gate (checkride gates, the human is the clock; an
|
|
69
|
+
`after`-agent that could fail a step is the lock in autonomy's costume, D45) →
|
|
70
|
+
self-review the diff against the done-when, the Decisions, and the Constraints (a
|
|
71
|
+
single structured read, D16) → validate → **PAUSE
|
|
46
72
|
for the human's approval** → only on approval, checkpoint with
|
|
47
73
|
`plumbbob checkpoint <n> --body <<'BODY' … BODY` — a commit body **proportional to the
|
|
48
74
|
step** (a line for a trivial change, a short paragraph for a meatier one; no TIL scan,
|
|
@@ -57,22 +83,31 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
57
83
|
progress instead of approving each step. It does the same work, but **the agent reviews
|
|
58
84
|
and approves in the human's place**, and it **chains**:
|
|
59
85
|
|
|
60
|
-
- Build the next step
|
|
86
|
+
- Build the next step, running its slots in the same order as the default path
|
|
87
|
+
(D56): bound `before`-agents → implement (or the bound `build`-agent) → bound
|
|
88
|
+
`after`-agents → `check` → self-review → **if the check is green AND the
|
|
61
89
|
self-review finds no done-when / Decision / Constraint mismatch, checkpoint** and move
|
|
62
|
-
straight on to the next planned step. Repeat.
|
|
90
|
+
straight on to the next planned step. Repeat. `--auto` adds no new machinery — the
|
|
91
|
+
`after`-agent output simply feeds the *existing* self-review halt condition.
|
|
63
92
|
- **Stop and hand back to the human** the moment any of these is true: the check is red,
|
|
64
93
|
the self-review finds a mismatch (surface exactly what, and do not checkpoint it), a
|
|
65
|
-
|
|
94
|
+
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, or no planned steps
|
|
96
|
+
remain.
|
|
66
97
|
|
|
67
98
|
`--auto` is the only path that checkpoints without a human pause, and only because the
|
|
68
99
|
human asked for it by name. The default — no flag — always ends at the pause.
|
|
69
100
|
|
|
70
101
|
## The hard contracts
|
|
71
102
|
|
|
72
|
-
- **
|
|
103
|
+
- **Swappable, never required.** The loop works without this skill; `/pb-verify`
|
|
73
104
|
checkpoints a hand-built or vibed diff just the same (D3).
|
|
74
105
|
- **Build the decided step, not a new one.** Implement what `intent.md` settled. A
|
|
75
106
|
new idea mid-build is a `/pb-park`, not an edit.
|
|
76
107
|
- **Default ends at the pause.** Implement → verify → wait for approval; never
|
|
77
108
|
checkpoint without it. Only an explicit `--auto` lets the agent approve in your place,
|
|
78
109
|
and it still halts on a red check or any mismatch.
|
|
110
|
+
- **Agents feed the beat; they never advance it** (C6/D45). `before` loads context,
|
|
111
|
+
`build` writes the diff, `after` is advisory — none can checkpoint, flip a step, or
|
|
112
|
+
chain. `blocked` → unblock and re-run; `drift` → `/pb-refine`. You are still the one
|
|
113
|
+
who verifies and (bar `--auto`) the human is still the clock.
|
|
@@ -8,7 +8,7 @@ allowed-tools: Read, Write, Bash(plumbbob status:*), Bash(plumbbob finish:*)
|
|
|
8
8
|
|
|
9
9
|
# PlumbBob — finish the build (the close-out)
|
|
10
10
|
|
|
11
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
11
|
+
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
12
12
|
|
|
13
13
|
`/pb-finish` ends the build: it captures what happened, then makes the final commit
|
|
14
14
|
that closes the session. **Report by default** (D9) — no refuse-without-report gate,
|
|
@@ -8,7 +8,7 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
|
8
8
|
|
|
9
9
|
# PlumbBob — harvest the park list
|
|
10
10
|
|
|
11
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
11
|
+
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
12
12
|
|
|
13
13
|
`/pb-harvest` is the complement of `/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.
|
package/skills/pb-park/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ allowed-tools: Bash(plumbbob status:*), Bash(plumbbob park:*)
|
|
|
9
9
|
|
|
10
10
|
# PlumbBob — park an idea (capture, don't chase)
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
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
15
|
get triaged later (D7). Capturing the instant an idea arrives — instead of acting on
|
package/skills/pb-plan/SKILL.md
CHANGED
|
@@ -4,12 +4,12 @@ description: "Frame a fresh goal and author the whole plan — Frame, Decisions,
|
|
|
4
4
|
argument-hint: "[spec-path | intent]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
model: opus
|
|
7
|
-
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob start:*), Bash(plumbbob checkpoint:*)
|
|
7
|
+
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob start:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent list:*)
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# PlumbBob — plan a goal (the whole-goal move)
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
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-plan` is the **whole-goal** move — it opens a session and gets the deciding out
|
|
15
15
|
of your head and onto `intent.md` *before* any code. By default it authors the
|
|
@@ -60,14 +60,35 @@ an agent can follow with `/pb-build`. The argument only seeds how you get there.
|
|
|
60
60
|
paths it touches). Later steps may be fuzzier than the first — that's fine; they get
|
|
61
61
|
sharpened just-in-time when you reach them with `/pb-step`. Keep each small enough to
|
|
62
62
|
verify in one review pass.
|
|
63
|
-
5. **
|
|
63
|
+
5. **Offer harness bindings** *(optional — D42/D43)*. If the build will lean on
|
|
64
|
+
user-authored agents, author `harness.json` in the build folder (beside `intent.md`)
|
|
65
|
+
and review it at the **same plan pause**, alongside the steps — bindings are
|
|
66
|
+
plan-adjacent configuration, so they converge with the plan. It binds agents to a
|
|
67
|
+
step's three lifecycle slots — `before` (context in), `build` (the diff), `after`
|
|
68
|
+
(advisory review) — with an optional prose `note`; a `defaults` block binds every
|
|
69
|
+
step. Run `plumbbob agent list` to see what's resolvable, per step:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"contract": 1,
|
|
74
|
+
"defaults": { "after": ["reviewer"] },
|
|
75
|
+
"steps": { "3": { "before": ["context-loader"], "note": "watch the auth seam" } }
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Keep it **bindings + prose only, never a conditional** (C3): the file says *which*
|
|
80
|
+
agent, not *when* — the host model reads each manifest's `when` prose and a step's
|
|
81
|
+
`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
|
|
83
|
+
up automatically (it lives in the build folder).
|
|
84
|
+
6. **Commit the plan.** Once the human approves the frame and steps, run
|
|
64
85
|
`plumbbob checkpoint --plan` to commit the scaffold on its own — subject
|
|
65
86
|
`plumbbob: plan — <title>`, only `.plumbbob/builds/<slug>/`, a `plan <sha>` line in
|
|
66
87
|
`checkpoints` (D36). This keeps the first step's diff clean, so history reads
|
|
67
88
|
baseline → plan → steps. Pass a proportional `--body` (the single-quoted stdin
|
|
68
89
|
heredoc) when the rationale is worth carrying; skip it for a small plan. Do this
|
|
69
90
|
only on the human's approval — the plan is their convergence.
|
|
70
|
-
|
|
91
|
+
7. **Offer to stress-test it.** Suggest `/pb-refine` to attack the frame for holes (or
|
|
71
92
|
to repair the plan as it drifts). Optional, the human's call.
|
|
72
93
|
|
|
73
94
|
## The interview (mode 1)
|
|
@@ -9,7 +9,7 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
|
9
9
|
|
|
10
10
|
# PlumbBob — refine the plan
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
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-refine` keeps `intent.md` honest. Use it at **any point** — right after `/pb-plan`
|
|
15
15
|
to stress-test a fresh frame, or mid-build to repair a plan that drifted from what the
|
|
@@ -9,7 +9,7 @@ allowed-tools: Bash(plumbbob status:*), Bash(plumbbob revert:*)
|
|
|
9
9
|
|
|
10
10
|
# PlumbBob — revert to a checkpoint (driver)
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
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
|
This is a **driver skill** — a chat-side trigger for the mechanical `plumbbob revert` verb, so the whole workflow runs from the agent window instead of a terminal. It is `disable-model-invocation: true`: only the human fires it. It carries **no Edit and no Write tool** — its only action is to shell the verb and report the verb's output verbatim, including any refusal. The CLI is the source of truth: never retry a refused transition, and never edit a file to work around one.
|
|
15
15
|
|
package/skills/pb-spike/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ allowed-tools: Bash(plumbbob status:*), Bash(plumbbob spike:*)
|
|
|
9
9
|
|
|
10
10
|
# PlumbBob — spike an experiment (driver)
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
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
|
This is a **driver skill** — a chat-side trigger for the mechanical `plumbbob spike` verb, so the whole workflow runs from the agent window instead of a terminal. It is `disable-model-invocation: true`: only the human fires it. It carries **no Edit and no Write tool** — its only action is to shell the verb and report the verb's output verbatim, including any refusal. The CLI is the source of truth: never retry a refused transition, and never edit a file to work around one.
|
|
15
15
|
|
|
@@ -8,7 +8,7 @@ allowed-tools: Bash(plumbbob status:*)
|
|
|
8
8
|
|
|
9
9
|
# PlumbBob — orient (the where-am-I move)
|
|
10
10
|
|
|
11
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
11
|
+
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
12
12
|
|
|
13
13
|
This is a **thin driver** for `plumbbob status`. The dashboard above is your
|
|
14
14
|
orientation — the intent, the step list, the parked/open-question counts, and the
|
package/skills/pb-step/SKILL.md
CHANGED
|
@@ -4,12 +4,12 @@ description: Revise the next increment just-in-time — sharpen the next undone
|
|
|
4
4
|
argument-hint: "[what-changed]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
6
|
model: opus
|
|
7
|
-
allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
7
|
+
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob agent list:*)
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# PlumbBob — revise the next step (the single-increment move)
|
|
11
11
|
|
|
12
|
-
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not
|
|
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-plan` authors the **whole** step list up front, so `/pb-step` is the
|
|
15
15
|
**just-in-time revision** move: it keeps the *next* undone step honest against what the
|
|
@@ -40,6 +40,14 @@ grew — but its everyday job is to sharpen, not to invent.
|
|
|
40
40
|
3. **Get the human's OK**, then write it into `## Steps` in the standard format —
|
|
41
41
|
`N. [ ] <title> — **done when:** <criterion>` with a `- seam:` sub-line. Revise the
|
|
42
42
|
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
|
+
build carries a `harness.json` (beside `intent.md`) and the reality that moved the
|
|
45
|
+
step also changed which agents it wants, sharpen that step's slot bindings
|
|
46
|
+
(`before`/`build`/`after`) and `note` at the same time — this is the just-in-time
|
|
47
|
+
counterpart to `/pb-plan`'s plan-time binding. `plumbbob agent list` shows what's
|
|
48
|
+
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
|
+
uses none.
|
|
43
51
|
|
|
44
52
|
## The hard contracts
|
|
45
53
|
|