plumbbob 0.6.5 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +2 -2
- package/README.md +24 -7
- package/dist/cli-core.js +7 -2
- package/dist/lib/buildlog.js +5 -2
- package/dist/lib/check.js +33 -1
- package/dist/lib/git.js +17 -0
- package/dist/lib/intent.js +3 -2
- package/dist/lib/latch.js +97 -0
- package/dist/lib/orient.js +31 -1
- package/dist/lib/sidecar.js +116 -0
- package/dist/verbs/build.js +5 -1
- package/dist/verbs/checkpoint.js +61 -7
- package/dist/verbs/doctor.js +33 -2
- package/dist/verbs/finish.js +57 -1
- package/dist/verbs/revert.js +19 -1
- package/dist/verbs/start.js +22 -2
- package/dist/verbs/status.js +10 -3
- package/dist/verbs/turn.js +106 -0
- package/hooks/hooks.json +15 -0
- package/hooks/pre-bash-commit.sh +69 -0
- package/node_modules/checkride/CHANGELOG.md +111 -0
- package/node_modules/checkride/README.md +185 -20
- package/node_modules/checkride/dist/adapters.d.ts +9 -4
- package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
- package/node_modules/checkride/dist/adapters.js +62 -2
- package/node_modules/checkride/dist/adapters.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/hook.d.ts +63 -0
- package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/hook.js +92 -0
- package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -0
- package/node_modules/checkride/dist/agent-setup/index.d.ts +8 -0
- package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/agent-setup/index.js +7 -0
- package/node_modules/checkride/dist/agent-setup/index.js.map +1 -0
- package/node_modules/checkride/dist/atomic.d.ts +13 -0
- package/node_modules/checkride/dist/atomic.d.ts.map +1 -0
- package/node_modules/checkride/dist/atomic.js +24 -0
- package/node_modules/checkride/dist/atomic.js.map +1 -0
- package/node_modules/checkride/dist/baseline/command.d.ts +42 -0
- package/node_modules/checkride/dist/baseline/command.d.ts.map +1 -0
- package/node_modules/checkride/dist/baseline/command.js +58 -0
- package/node_modules/checkride/dist/baseline/command.js.map +1 -0
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts +41 -0
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -0
- package/node_modules/checkride/dist/baseline/fingerprint.js +119 -0
- package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -0
- package/node_modules/checkride/dist/baseline/index.d.ts +13 -0
- package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/baseline/index.js +10 -0
- package/node_modules/checkride/dist/baseline/index.js.map +1 -0
- package/node_modules/checkride/dist/baseline/store.d.ts +67 -0
- package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -0
- package/node_modules/checkride/dist/baseline/store.js +110 -0
- package/node_modules/checkride/dist/baseline/store.js.map +1 -0
- package/node_modules/checkride/dist/cli.d.ts.map +1 -1
- package/node_modules/checkride/dist/cli.js +37 -3
- package/node_modules/checkride/dist/cli.js.map +1 -1
- package/node_modules/checkride/dist/config.d.ts +43 -3
- package/node_modules/checkride/dist/config.d.ts.map +1 -1
- package/node_modules/checkride/dist/config.js +95 -22
- package/node_modules/checkride/dist/config.js.map +1 -1
- package/node_modules/checkride/dist/digest/digest.d.ts +52 -0
- package/node_modules/checkride/dist/digest/digest.d.ts.map +1 -0
- package/node_modules/checkride/dist/digest/digest.js +147 -0
- package/node_modules/checkride/dist/digest/digest.js.map +1 -0
- package/node_modules/checkride/dist/digest/index.d.ts +8 -0
- package/node_modules/checkride/dist/digest/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/digest/index.js +7 -0
- package/node_modules/checkride/dist/digest/index.js.map +1 -0
- package/node_modules/checkride/dist/doctor.d.ts +4 -0
- package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
- package/node_modules/checkride/dist/doctor.js +33 -10
- package/node_modules/checkride/dist/doctor.js.map +1 -1
- package/node_modules/checkride/dist/index.d.ts +1 -1
- package/node_modules/checkride/dist/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/index.js +1 -1
- package/node_modules/checkride/dist/index.js.map +1 -1
- package/node_modules/checkride/dist/init.d.ts +38 -0
- package/node_modules/checkride/dist/init.d.ts.map +1 -1
- package/node_modules/checkride/dist/init.js +97 -8
- package/node_modules/checkride/dist/init.js.map +1 -1
- package/node_modules/checkride/dist/orchestrator.d.ts +58 -1
- package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
- package/node_modules/checkride/dist/orchestrator.js +155 -27
- package/node_modules/checkride/dist/orchestrator.js.map +1 -1
- package/node_modules/checkride/dist/pm/detect.d.ts +21 -0
- package/node_modules/checkride/dist/pm/detect.d.ts.map +1 -0
- package/node_modules/checkride/dist/pm/detect.js +60 -0
- package/node_modules/checkride/dist/pm/detect.js.map +1 -0
- package/node_modules/checkride/dist/pm/index.d.ts +10 -0
- package/node_modules/checkride/dist/pm/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/pm/index.js +9 -0
- package/node_modules/checkride/dist/pm/index.js.map +1 -0
- package/node_modules/checkride/dist/pm/translate.d.ts +28 -0
- package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -0
- package/node_modules/checkride/dist/pm/translate.js +40 -0
- package/node_modules/checkride/dist/pm/translate.js.map +1 -0
- package/node_modules/checkride/package.json +20 -17
- package/node_modules/checkride/schema/checkride.config.schema.json +97 -0
- package/node_modules/checkride/schema/checkride.summary.schema.json +57 -0
- package/node_modules/checkride/templates/shared/cspell.json +1 -0
- package/node_modules/checkride/templates/shared/prettierrc.json +6 -0
- package/package.json +8 -4
- package/skills/pb-build/SKILL.md +32 -14
- package/skills/pb-finish/SKILL.md +5 -6
- package/skills/pb-harvest/SKILL.md +1 -2
- package/skills/pb-park/SKILL.md +1 -1
- package/skills/pb-plan/SKILL.md +37 -5
- package/skills/pb-refine/SKILL.md +0 -1
- package/skills/pb-status/SKILL.md +5 -1
- package/skills/pb-step/SKILL.md +5 -4
- package/skills/pb-verify/SKILL.md +26 -9
- package/templates/intent.md +4 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/robmclarty/checkride/main/schema/checkride.config.schema.json",
|
|
4
|
+
"title": "checkride configuration",
|
|
5
|
+
"description": "Schema for checkride.config.json — add it only to deviate from the zero-config defaults.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "URL of this JSON Schema, for editor validation and autocompletion."
|
|
12
|
+
},
|
|
13
|
+
"extends": {
|
|
14
|
+
"description": "Preset(s) to inherit — a file path (./base.json) or package specifier (@acme/preset), or an array of them. Bases merge left-to-right and the local config wins over all; objects deep-merge, arrays and scalars replace (arrays are not concatenated).",
|
|
15
|
+
"oneOf": [
|
|
16
|
+
{ "type": "string" },
|
|
17
|
+
{ "type": "array", "items": { "type": "string" } }
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"timeout": {
|
|
21
|
+
"type": "number",
|
|
22
|
+
"minimum": 0,
|
|
23
|
+
"description": "Default per-check timeout in seconds. Unset, checks fall back to the built-in 600s cap; 0 here or on a check disables the cap."
|
|
24
|
+
},
|
|
25
|
+
"checks": {
|
|
26
|
+
"type": "object",
|
|
27
|
+
"description": "Per-slot configuration. A key that matches a catalogue slot (types, format, lint, struct, dead, test, docs, links, spell, mutation, security, publint, attw) configures that slot; any other key is a custom check that runs alongside the catalogue. Naming an opt-in slot (format, mutation, security, publint, attw) here also opts it into the default run.",
|
|
28
|
+
"additionalProperties": {
|
|
29
|
+
"$ref": "#/definitions/slotConfig"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"definitions": {
|
|
34
|
+
"slotConfig": {
|
|
35
|
+
"description": "How to fill a slot: an adapter name, false to disable it, an adapter with overrides, or a custom check.",
|
|
36
|
+
"oneOf": [
|
|
37
|
+
{
|
|
38
|
+
"type": "string",
|
|
39
|
+
"description": "Adapter name that fills this slot, beating detection."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"const": false,
|
|
43
|
+
"description": "Disable this slot (skipped, not failed)."
|
|
44
|
+
},
|
|
45
|
+
{ "$ref": "#/definitions/useConfig" },
|
|
46
|
+
{ "$ref": "#/definitions/customCheck" }
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
"useConfig": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"description": "Pick an adapter by name and override individual fields.",
|
|
52
|
+
"required": ["use"],
|
|
53
|
+
"additionalProperties": false,
|
|
54
|
+
"properties": {
|
|
55
|
+
"use": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"description": "Adapter name to select from the registry."
|
|
58
|
+
},
|
|
59
|
+
"command": { "type": "string" },
|
|
60
|
+
"args": { "type": "array", "items": { "type": "string" } },
|
|
61
|
+
"description": { "type": "string" },
|
|
62
|
+
"outputFile": { "type": ["string", "null"] },
|
|
63
|
+
"changedArgs": { "type": "array", "items": { "type": "string" } },
|
|
64
|
+
"fixArgs": { "type": "array", "items": { "type": "string" } },
|
|
65
|
+
"timeout": { "type": "number", "minimum": 0 }
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"customCheck": {
|
|
69
|
+
"type": "object",
|
|
70
|
+
"description": "A bare command that needs no adapter.",
|
|
71
|
+
"required": ["command"],
|
|
72
|
+
"additionalProperties": false,
|
|
73
|
+
"properties": {
|
|
74
|
+
"command": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"description": "Executable to spawn."
|
|
77
|
+
},
|
|
78
|
+
"args": { "type": "array", "items": { "type": "string" } },
|
|
79
|
+
"description": { "type": "string" },
|
|
80
|
+
"outputFile": { "type": ["string", "null"] },
|
|
81
|
+
"changedArgs": { "type": "array", "items": { "type": "string" } },
|
|
82
|
+
"fixArgs": { "type": "array", "items": { "type": "string" } },
|
|
83
|
+
"timeout": { "type": "number", "minimum": 0 },
|
|
84
|
+
"name": { "type": "string" },
|
|
85
|
+
"detect": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"items": { "type": "string" },
|
|
88
|
+
"description": "Marker files that gate a non-catalogue custom check: it runs only when at least one listed file exists, and is skipped otherwise. Ignored on an entry that fills a catalogue slot."
|
|
89
|
+
},
|
|
90
|
+
"order": {
|
|
91
|
+
"enum": ["first", "last"],
|
|
92
|
+
"description": "Where a non-catalogue custom check runs relative to the catalogue. Default 'last'."
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/robmclarty/checkride/main/schema/checkride.summary.schema.json",
|
|
4
|
+
"title": "checkride run summary",
|
|
5
|
+
"description": "Schema for .check/summary.json — the aggregate report every run writes. A public API for agents and gate consumers. Fields are additive under schema_version 1: they are added (in lockstep with this schema), never renamed, removed, or retyped without a version bump. See docs/contract.md.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["schema_version", "timestamp", "ok", "checks_run", "total_duration_ms", "checks"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"schema_version": {
|
|
11
|
+
"const": 1,
|
|
12
|
+
"description": "Version of this report shape. Bumped only for a breaking (non-additive) change."
|
|
13
|
+
},
|
|
14
|
+
"timestamp": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "ISO 8601 time the report was written."
|
|
17
|
+
},
|
|
18
|
+
"ok": {
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"description": "True when every check passed (skipped checks count as ok). Can be vacuous — see checks_run."
|
|
21
|
+
},
|
|
22
|
+
"checks_run": {
|
|
23
|
+
"type": "integer",
|
|
24
|
+
"minimum": 0,
|
|
25
|
+
"description": "Count of checks that actually executed (skipped entries excluded). ok=true with checks_run=0 is a vacuous green: nothing was verified. Gate consumers should treat it as a failure (or run with --strict, which exits 2)."
|
|
26
|
+
},
|
|
27
|
+
"total_duration_ms": {
|
|
28
|
+
"type": "number",
|
|
29
|
+
"minimum": 0,
|
|
30
|
+
"description": "Sum of all check durations in milliseconds."
|
|
31
|
+
},
|
|
32
|
+
"checks": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"items": { "$ref": "#/definitions/check" },
|
|
35
|
+
"description": "One entry per selected slot, in pipeline order."
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"definitions": {
|
|
39
|
+
"check": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": false,
|
|
42
|
+
"required": ["name", "adapter", "description", "ok", "exit_code", "duration_ms", "output_file"],
|
|
43
|
+
"properties": {
|
|
44
|
+
"name": { "type": "string", "description": "Slot name (e.g. lint), or a custom check's key." },
|
|
45
|
+
"adapter": { "type": ["string", "null"], "description": "Adapter that ran (e.g. oxlint), or null when the slot resolved to nothing." },
|
|
46
|
+
"description": { "type": "string", "description": "Human description of the check." },
|
|
47
|
+
"ok": { "type": "boolean", "description": "Pass/fail after any baseline masking; skipped checks are ok." },
|
|
48
|
+
"skipped": { "type": "boolean", "description": "Present (true) when the check did not execute; see reason." },
|
|
49
|
+
"reason": { "type": "string", "description": "Why a skipped check sat out (no tool detected, disabled in config, unavailable under this package manager, ...)." },
|
|
50
|
+
"exit_code": { "type": ["integer", "null"], "description": "The tool's exit code; -1 for spawn failure or timeout; null when skipped." },
|
|
51
|
+
"duration_ms": { "type": "number", "description": "Wall-clock duration in milliseconds (0 when skipped)." },
|
|
52
|
+
"output_file": { "type": ["string", "null"], "description": "The .check/ file holding the tool's raw JSON output, when it emits JSON on stdout." },
|
|
53
|
+
"baselined": { "type": "integer", "minimum": 1, "description": "Present only when a committed baseline masked diagnostics: how many current findings are grandfathered." }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Attention-first build process: 12 skills + a CLI that keep you the decider — guidance,
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Attention-first build process: 12 skills + a CLI that keep you the decider — guidance on the work, a latch on the record.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
7
7
|
"claude",
|
|
@@ -48,13 +48,14 @@
|
|
|
48
48
|
"@types/node": "^24.0.0",
|
|
49
49
|
"@vitest/coverage-v8": "^4.1.9",
|
|
50
50
|
"fallow": "^2.103.0",
|
|
51
|
+
"fascicle": "0.8.16",
|
|
51
52
|
"markdownlint-cli2": "^0.22.1",
|
|
52
53
|
"oxlint": "^1.69.0",
|
|
53
54
|
"typescript": "^6.0.3",
|
|
54
55
|
"vitest": "^4.1.8"
|
|
55
56
|
},
|
|
56
57
|
"dependencies": {
|
|
57
|
-
"checkride": "0.
|
|
58
|
+
"checkride": "0.3.0"
|
|
58
59
|
},
|
|
59
60
|
"bundleDependencies": [
|
|
60
61
|
"checkride"
|
|
@@ -63,6 +64,9 @@
|
|
|
63
64
|
"clean": "rm -rf dist",
|
|
64
65
|
"build": "tsc -p tsconfig.build.json",
|
|
65
66
|
"check": "checkride",
|
|
66
|
-
"test": "vitest run"
|
|
67
|
+
"test": "vitest run",
|
|
68
|
+
"eval:baseline": "pnpm build && node test/evals/run.ts --sweep baseline",
|
|
69
|
+
"eval:latched": "pnpm build && node test/evals/run.ts --sweep latched",
|
|
70
|
+
"eval:report": "node test/evals/run.ts --report"
|
|
67
71
|
}
|
|
68
72
|
}
|
package/skills/pb-build/SKILL.md
CHANGED
|
@@ -3,7 +3,6 @@ name: pb-build
|
|
|
3
3
|
description: The default engine — read the next planned step from intent, implement it (its done-when, seam, Decisions, Constraints), then verify it through to the approval pause. Swappable — build by hand/vibed/another harness and run /pb-verify instead. `--auto` self-approves and chains to done; a step range like `1-3` self-approves through step 3, then pauses.
|
|
4
4
|
argument-hint: "[step-number | step-range] [--auto]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
|
-
model: opus
|
|
7
6
|
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*)
|
|
8
7
|
---
|
|
9
8
|
|
|
@@ -12,7 +11,7 @@ allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob build:*
|
|
|
12
11
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
13
12
|
|
|
14
13
|
This is the **bundled executor** — the default engine, not the only one. It is
|
|
15
|
-
**swappable
|
|
14
|
+
**swappable**: you can implement any step by hand, in a vibe session, or with
|
|
16
15
|
another harness and go straight to `/pb-verify` instead — plumbbob does not care how
|
|
17
16
|
the diff appeared. When you do run it, it reads the plan, writes the step, and
|
|
18
17
|
carries straight through to the verify pause.
|
|
@@ -21,6 +20,11 @@ Since `/pb-plan` lays down the whole step list up front, the happy path is to fi
|
|
|
21
20
|
`/pb-build` once per step until done — each run builds the next undone step and stops
|
|
22
21
|
at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick.**
|
|
23
22
|
|
|
23
|
+
A model note: this skill **inherits the session model** — nothing pins or switches
|
|
24
|
+
it. If the step you're about to build carries a `- model:` recommendation that
|
|
25
|
+
differs from the model you're running as, say so before implementing — the human can
|
|
26
|
+
`/model` and re-fire to honor it, or wave you on. Advisory, never a gate.
|
|
27
|
+
|
|
24
28
|
## What this skill does, in order
|
|
25
29
|
|
|
26
30
|
1. **Pick the step.** Use the number you were invoked with (e.g. `/pb-build 4`) — or,
|
|
@@ -34,7 +38,7 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
34
38
|
3. **Read the plan.** Read the step's **done-when**, its **seam**, and the
|
|
35
39
|
**Decisions** and **Constraints** in `intent.md`. Build to *that* — the deciding
|
|
36
40
|
already happened, off the chat.
|
|
37
|
-
- **Run any bound `before`-agents
|
|
41
|
+
- **Run any bound `before`-agents**. If the build's `harness.json` binds
|
|
38
42
|
agents to this step's `before` slot, run `plumbbob agent run --step <n> --mode
|
|
39
43
|
before` first: each returns a validated envelope on stdout that plumbbob also
|
|
40
44
|
appends to the step's `handoff.json`, and its `summary`/`body` become **context you
|
|
@@ -45,17 +49,17 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
45
49
|
edit — capture it and stay on the step. If you genuinely cannot finish without
|
|
46
50
|
touching more than the seam, that is scope drift: surface it to the human rather
|
|
47
51
|
than sprawling.
|
|
48
|
-
- **If a `build`-slot agent is bound, delegate the diff to it
|
|
52
|
+
- **If a `build`-slot agent is bound, delegate the diff to it**. Run
|
|
49
53
|
`plumbbob agent run --step <n> --mode build` and let that agent author the step's
|
|
50
54
|
code instead of writing it yourself; its envelope reports what it did. You still
|
|
51
|
-
own the verify tick below — the diff is reviewed the same way whoever wrote it
|
|
52
|
-
- **A manifest's `when` prose is your cue to fire an agent mid-build
|
|
55
|
+
own the verify tick below — the diff is reviewed the same way whoever wrote it.
|
|
56
|
+
- **A manifest's `when` prose is your cue to fire an agent mid-build**.
|
|
53
57
|
The three slots are the only *declarative* lifecycle points; there is no config for
|
|
54
58
|
"a salient moment in the middle." That is judgment, and you are the frontier model
|
|
55
59
|
in the room: when the work reaches the situation a bound agent's `when` (or a step
|
|
56
60
|
`note`) describes, fire `plumbbob agent run <name> --step <n>` yourself. Prose is
|
|
57
61
|
the orchestration language; you are the workflow engine.
|
|
58
|
-
- **Route a non-`done` envelope by its status
|
|
62
|
+
- **Route a non-`done` envelope by its status**. An agent that returns
|
|
59
63
|
`blocked` couldn't finish (missing input, failed precondition): surface its `notes`,
|
|
60
64
|
let the human unblock, and re-run it — don't work around it. One that returns
|
|
61
65
|
`drift` finished but found the plan no longer matches reality: **stop and send the
|
|
@@ -68,9 +72,9 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
68
72
|
still runs everything) → run any bound `after`-agents (`plumbbob agent run --step
|
|
69
73
|
<n> --mode after`) and fold their envelopes into the self-review as **advisory
|
|
70
74
|
input** — they inform, they never gate (checkride gates, the human is the clock; an
|
|
71
|
-
`after`-agent that could fail a step is the lock in autonomy's costume
|
|
75
|
+
`after`-agent that could fail a step is the lock in autonomy's costume) →
|
|
72
76
|
self-review the diff against the done-when, the Decisions, and the Constraints (a
|
|
73
|
-
single structured read
|
|
77
|
+
single structured read) → validate → **PAUSE
|
|
74
78
|
for the human's approval** → only on approval, checkpoint with
|
|
75
79
|
`plumbbob checkpoint <n> --body <<'BODY' … BODY` — a commit body **proportional to the
|
|
76
80
|
step** (a line for a trivial change, a short paragraph for a meatier one; no TIL scan,
|
|
@@ -79,14 +83,23 @@ at the pause for your approval. **Re-firing `/pb-build` is itself the clock tick
|
|
|
79
83
|
`--body` for the deterministic done-when + seam + diffstat fallback). Do **not** bump
|
|
80
84
|
the version or changelog — that is the human's `/version` call.
|
|
81
85
|
|
|
86
|
+
**The latch makes this pause real (D64).** On the default (non-`--auto`) path you
|
|
87
|
+
build the step and reach the pause *in one turn* — so under plumbbob's turn hook the
|
|
88
|
+
checkpoint at the end of that turn is **refused** ("no human turn since this step
|
|
89
|
+
began"), and that refusal **is** the pause working as designed. Do exactly what the
|
|
90
|
+
pause already asks: present the diff and the self-review, **end the turn**, and the
|
|
91
|
+
human's next message is the tick that lands the checkpoint when you re-fire. **Never
|
|
92
|
+
route around a refusal with a raw `git commit`** — the work plane stays free (D10/D13),
|
|
93
|
+
but the *record* is latched on purpose.
|
|
94
|
+
|
|
82
95
|
## `--auto` — let the agent be the clock (opt-in)
|
|
83
96
|
|
|
84
97
|
`/pb-build --auto` is the explicit escape hatch when the human wants unattended
|
|
85
98
|
progress instead of approving each step. It does the same work, but **the agent reviews
|
|
86
99
|
and approves in the human's place**, and it **chains**:
|
|
87
100
|
|
|
88
|
-
- Build the next step, running its slots in the same order as the default
|
|
89
|
-
|
|
101
|
+
- Build the next step, running its slots in the same order as the default
|
|
102
|
+
path: bound `before`-agents → implement (or the bound `build`-agent) → bound
|
|
90
103
|
`after`-agents → `check` → self-review → **if the check is green AND the
|
|
91
104
|
self-review finds no done-when / Decision / Constraint mismatch, checkpoint** and move
|
|
92
105
|
straight on to the next planned step. Repeat. `--auto` adds no new machinery — the
|
|
@@ -94,7 +107,7 @@ and approves in the human's place**, and it **chains**:
|
|
|
94
107
|
- **Stop and hand back to the human** the moment any of these is true: the check is red,
|
|
95
108
|
the self-review finds a mismatch (surface exactly what, and do not checkpoint it), a
|
|
96
109
|
bound agent returns `blocked` or `drift` (unblock-and-re-run, or `/pb-refine` — an
|
|
97
|
-
agent cannot advance the loop
|
|
110
|
+
agent cannot advance the loop), a new decision is needed, no planned steps
|
|
98
111
|
remain, or the top of a requested range is reached.
|
|
99
112
|
|
|
100
113
|
`--auto` and a step range are the only paths that checkpoint without a human pause, and
|
|
@@ -126,14 +139,19 @@ just the one more entry already in the halt list above.
|
|
|
126
139
|
## The hard contracts
|
|
127
140
|
|
|
128
141
|
- **Swappable, never required.** The loop works without this skill; `/pb-verify`
|
|
129
|
-
checkpoints a hand-built or vibed diff just the same
|
|
142
|
+
checkpoints a hand-built or vibed diff just the same.
|
|
130
143
|
- **Build the decided step, not a new one.** Implement what `intent.md` settled. A
|
|
131
144
|
new idea mid-build is a `/pb-park`, not an edit.
|
|
132
145
|
- **Default ends at the pause.** Implement → verify → wait for approval; never
|
|
133
146
|
checkpoint without it. Only an explicit `--auto` or a step range lets the agent approve
|
|
134
147
|
in your place, and it still halts on a red check or any mismatch — a range also stops
|
|
135
148
|
at its top.
|
|
136
|
-
- **Agents feed the beat; they never advance it
|
|
149
|
+
- **Agents feed the beat; they never advance it**. `before` loads context,
|
|
137
150
|
`build` writes the diff, `after` is advisory — none can checkpoint, flip a step, or
|
|
138
151
|
chain. `blocked` → unblock and re-run; `drift` → `/pb-refine`. You are still the one
|
|
139
152
|
who verifies and (bar `--auto`) the human is still the clock.
|
|
153
|
+
- **A refused checkpoint is the pause, not an error (D64).** Under plumbbob's turn
|
|
154
|
+
hook a same-turn `checkpoint` is refused by design — present the diff, **end the
|
|
155
|
+
turn**, and the human's next message is the tick that lands it on re-fire. Never route
|
|
156
|
+
around it with a raw `git commit`; `--auto`, a typed range, or `auto: true` are the
|
|
157
|
+
only self-approvals.
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: pb-finish
|
|
3
3
|
description: Finish the build — write the report (what shipped, decisions, parked/harvested items, deferred tangents), then make the final commit that closes the session. The build folder rides the branch into the PR — no separate archive. Report by default, no gate.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
model: opus
|
|
6
5
|
allowed-tools: Read, Write, Bash(plumbbob status:*), Bash(plumbbob finish:*)
|
|
7
6
|
---
|
|
8
7
|
|
|
@@ -11,8 +10,8 @@ allowed-tools: Read, Write, Bash(plumbbob status:*), Bash(plumbbob finish:*)
|
|
|
11
10
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
12
11
|
|
|
13
12
|
`/pb-finish` ends the build: it captures what happened, then makes the final commit
|
|
14
|
-
that closes the session. **Report by default**
|
|
15
|
-
and no separate docs phase. The build folder is tracked
|
|
13
|
+
that closes the session. **Report by default** — no refuse-without-report gate,
|
|
14
|
+
and no separate docs phase. The build folder is tracked: it merges with the
|
|
16
15
|
branch and shows up in the PR, so there is nothing to archive — the folder *is* the
|
|
17
16
|
record.
|
|
18
17
|
|
|
@@ -30,8 +29,8 @@ record.
|
|
|
30
29
|
- **Deferred tangents** — the harvested items that become future work.
|
|
31
30
|
This is the "yeah, I did that" artifact. Write it by default; the human may edit it.
|
|
32
31
|
2. **Finish.** Run `plumbbob finish`, which appends the checkpoint SHAs to the
|
|
33
|
-
report and makes the final commit — subject `plumbbob: finish — <title
|
|
34
|
-
with an optional proportional body via `--body` (the
|
|
32
|
+
report and makes the final commit — subject `plumbbob: finish — <title>`,
|
|
33
|
+
with an optional proportional body via `--body` (the stdin heredoc) — then
|
|
35
34
|
clears the control state (markers, the `activeBuild` cursor, STATE last). The
|
|
36
35
|
build folder stays in place, committed, and rides the branch into the PR.
|
|
37
36
|
3. **Point at the next goal** — `/pb-plan` to frame the next one.
|
|
@@ -43,7 +42,7 @@ record.
|
|
|
43
42
|
- **The log is the history; the report is the synthesis.** `checkpoint` already recorded
|
|
44
43
|
what shipped, step by step — finish applies the *unique additions* (the why, the deferred
|
|
45
44
|
tangents, the final status), it does not rewrite the timeline.
|
|
46
|
-
- **The folder is the archive, never destroy
|
|
45
|
+
- **The folder is the archive, never destroy**. `finish` keeps intent +
|
|
47
46
|
build-log + report in `builds/<slug>/` and commits them; nothing is copied out and
|
|
48
47
|
nothing is deleted but the untracked control markers.
|
|
49
48
|
- **No version bump, no docs phase.** Updating real docs is a separate, explicit ask;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: pb-harvest
|
|
3
3
|
description: Triage the park list at a step boundary — propose one class (blocker/tangent/pivot) per parked item, write only after the human confirms each, record under ## Harvest, and fold a confirmed blocker into intent.
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
model: opus
|
|
6
5
|
allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
7
6
|
---
|
|
8
7
|
|
|
@@ -10,7 +9,7 @@ allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
|
10
9
|
|
|
11
10
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
12
11
|
|
|
13
|
-
`/pb-harvest` is the complement of `/pb-park
|
|
12
|
+
`/pb-harvest` is the complement of `/pb-park`: you parked ideas as seeds during a
|
|
14
13
|
build; now, at a boundary, you harvest them — decide what each one is.
|
|
15
14
|
|
|
16
15
|
## When to run it — boundary only
|
package/skills/pb-park/SKILL.md
CHANGED
|
@@ -12,7 +12,7 @@ allowed-tools: Bash(plumbbob status:*), Bash(plumbbob park:*)
|
|
|
12
12
|
Current session state (injected when this skill runs): !`plumbbob status 2>/dev/null || echo "plumbbob CLI not on PATH in this session. Marketplace install: confirm the plugin is enabled in /plugin, then /reload-plugins. Skills-dir/global install: npm i -g plumbbob && plumbbob init."`
|
|
13
13
|
|
|
14
14
|
`/pb-park` is the **capture** half of the loop; `/pb-harvest` is where parked items
|
|
15
|
-
get triaged later
|
|
15
|
+
get triaged later. Capturing the instant an idea arrives — instead of acting on
|
|
16
16
|
it — is the whole point: it protects the step in flight.
|
|
17
17
|
|
|
18
18
|
## Wrong-state refusal
|
package/skills/pb-plan/SKILL.md
CHANGED
|
@@ -3,7 +3,6 @@ name: pb-plan
|
|
|
3
3
|
description: "Frame a fresh goal and author the whole plan — Frame, Decisions, Constraints, and all Steps — before any code. Three input modes: no arg interviews you; a file path absorbs a spec; any other text expands your inline intent."
|
|
4
4
|
argument-hint: "[spec-path | intent]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
|
-
model: opus
|
|
7
6
|
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob start:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent list:*)
|
|
8
7
|
---
|
|
9
8
|
|
|
@@ -17,6 +16,11 @@ of your head and onto `intent.md` *before* any code. By default it authors the
|
|
|
17
16
|
`/pb-build` until done. (Revising a single increment later is the separate `/pb-step`
|
|
18
17
|
move; do not confuse the two.)
|
|
19
18
|
|
|
19
|
+
A model note: this skill **inherits the session model** — nothing pins or switches
|
|
20
|
+
it. Planning is where frontier-class judgment pays for itself, so if the session is
|
|
21
|
+
running a small model, suggest `/model opus` (or better) before framing — the
|
|
22
|
+
human's call, never a gate.
|
|
23
|
+
|
|
20
24
|
## Three input modes (disambiguated for you — no quotes needed)
|
|
21
25
|
|
|
22
26
|
Look at the argument the human gave and pick the mode yourself:
|
|
@@ -41,6 +45,10 @@ an agent can follow with `/pb-build`. The argument only seeds how you get there.
|
|
|
41
45
|
1. **Scaffold.** If there is no active session, run `plumbbob start "<title>"`
|
|
42
46
|
to create `.plumbbob/` (baseline recorded, session opened). If a session already
|
|
43
47
|
exists, say so and edit the existing `intent.md` rather than starting over.
|
|
48
|
+
- **If `start` warns that the gate sees no code checks**, surface that to the
|
|
49
|
+
human now — while they're still deciding, not at the first refused
|
|
50
|
+
checkpoint — and offer to set the `check` key in `.plumbbob/settings.json`
|
|
51
|
+
(e.g. `"check": "npm test"`) before any step is built.
|
|
44
52
|
2. **Frame** (`.plumbbob/intent.md`), with the human: the **Problem** in plain words,
|
|
45
53
|
the **smallest thing** that solves it, what **done looks like**, and what you are
|
|
46
54
|
**explicitly NOT doing**. This is the human's convergence — propose wording, but
|
|
@@ -54,13 +62,24 @@ an agent can follow with `/pb-build`. The argument only seeds how you get there.
|
|
|
54
62
|
```markdown
|
|
55
63
|
1. [ ] <title> — **done when:** <criterion, ideally a test or check result>
|
|
56
64
|
- seam: `<file>`, `<file>`
|
|
65
|
+
- model: <optional — smallest that can carry it, with the one-phrase why>
|
|
57
66
|
```
|
|
58
67
|
|
|
59
68
|
Every step needs a **done-when** `/pb-verify` can check and a **seam** (the exact
|
|
60
69
|
paths it touches). Later steps may be fuzzier than the first — that's fine; they get
|
|
61
70
|
sharpened just-in-time when you reach them with `/pb-step`. Keep each small enough to
|
|
62
71
|
verify in one review pass.
|
|
63
|
-
|
|
72
|
+
|
|
73
|
+
**Recommend a model per step where the signal is clear** *(optional)*: the
|
|
74
|
+
`- model:` sub-line names the **smallest model that can carry the step**, with the
|
|
75
|
+
one-phrase why — the human buys capability only where the step needs it. E.g.
|
|
76
|
+
`model: sonnet — mechanical, fully specified by the done-when` for rote edits;
|
|
77
|
+
`model: opus — strong-assertion test authoring` where the tests do the thinking;
|
|
78
|
+
`model: fable — subtle cross-cutting design` for judgment-heavy or creative work.
|
|
79
|
+
It is advisory metadata for the human — `/pb-status` surfaces it before each build —
|
|
80
|
+
never a gate, and nothing switches models automatically. Write it plain (no
|
|
81
|
+
backticks) and omit it when any model would do.
|
|
82
|
+
5. **Offer harness bindings** *(optional)*. If the build will lean on
|
|
64
83
|
user-authored agents, author `harness.json` in the build folder (beside `intent.md`)
|
|
65
84
|
and review it at the **same plan pause**, alongside the steps — bindings are
|
|
66
85
|
plan-adjacent configuration, so they converge with the plan. It binds agents to a
|
|
@@ -76,18 +95,31 @@ an agent can follow with `/pb-build`. The argument only seeds how you get there.
|
|
|
76
95
|
}
|
|
77
96
|
```
|
|
78
97
|
|
|
79
|
-
Keep it **bindings + prose only, never a conditional
|
|
98
|
+
Keep it **bindings + prose only, never a conditional**: the file says *which*
|
|
80
99
|
agent, not *when* — the host model reads each manifest's `when` prose and a step's
|
|
81
100
|
`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
|
|
101
|
+
uses an agent — the loop runs identically without it. The plan commit picks it
|
|
83
102
|
up automatically (it lives in the build folder).
|
|
84
103
|
6. **Commit the plan.** Once the human approves the frame and steps, run
|
|
85
104
|
`plumbbob checkpoint --plan` to commit the scaffold on its own — subject
|
|
86
105
|
`plumbbob: plan — <title>`, only `.plumbbob/builds/<slug>/`, a `plan <sha>` line in
|
|
87
|
-
`checkpoints
|
|
106
|
+
`checkpoints`. This keeps the first step's diff clean, so history reads
|
|
88
107
|
baseline → plan → steps. Pass a proportional `--body` (the single-quoted stdin
|
|
89
108
|
heredoc) when the rationale is worth carrying; skip it for a small plan. Do this
|
|
90
109
|
only on the human's approval — the plan is their convergence.
|
|
110
|
+
- **The plan commit is latched too (D64).** Once the turn ledger exists, `checkpoint
|
|
111
|
+
--plan` refuses to land in the same turn `start` stamped it: present the plan,
|
|
112
|
+
**end the turn**, and the human's approving message is the tick that lets it
|
|
113
|
+
commit on re-fire — the refusal *is* the plan pause. Never route around it with a
|
|
114
|
+
raw `git commit`. (One documented seam: the very first plan of a brand-new
|
|
115
|
+
session runs `start` *before* the turn hook has ever ticked, so that single
|
|
116
|
+
commit predates the ledger and stays guidance-governed — it lands without a
|
|
117
|
+
refusal.)
|
|
118
|
+
- **Say what the commit publishes.** The close-out line names the tracked folder:
|
|
119
|
+
`.plumbbob/builds/<slug>/` now rides this branch into the PR, so teammates will
|
|
120
|
+
see the plan and build record in review. In the same breath, offer the way out:
|
|
121
|
+
a repo that won't track a tool folder can restart with `plumbbob start --local`
|
|
122
|
+
(a fully untracked sidecar) before any steps are built.
|
|
91
123
|
7. **Offer to stress-test it.** Suggest `/pb-refine` to attack the frame for holes (or
|
|
92
124
|
to repair the plan as it drifts). Optional, the human's call.
|
|
93
125
|
|
|
@@ -3,7 +3,6 @@ name: pb-refine
|
|
|
3
3
|
description: Keep intent.md true — attack the plan for holes (append as Open questions) and refine or repair the Frame, Decisions, Constraints, and Steps to match reality. Usable at any point; you propose, the human approves.
|
|
4
4
|
argument-hint: "[focus]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
|
-
model: opus
|
|
7
6
|
allowed-tools: Read, Edit, Bash(plumbbob status:*)
|
|
8
7
|
---
|
|
9
8
|
|
|
@@ -19,4 +19,8 @@ skill carries **no Edit and no Write tool**: the CLI is the source of truth, so
|
|
|
19
19
|
## What it does
|
|
20
20
|
|
|
21
21
|
1. Surface the injected `status` output — the dashboard and its suggested next move.
|
|
22
|
-
2. If
|
|
22
|
+
2. If the next step's detail carries a `model:` line, point it out: it is the
|
|
23
|
+
plan's recommendation of the smallest model that can carry that step, so the human
|
|
24
|
+
can switch (e.g. `/model sonnet`) before firing `/pb-build` — or ignore it. Guidance,
|
|
25
|
+
never a gate.
|
|
26
|
+
3. If it reads `NO ACTIVE SESSION`, tell the human to `/pb-plan` to frame a goal.
|
package/skills/pb-step/SKILL.md
CHANGED
|
@@ -3,7 +3,6 @@ name: pb-step
|
|
|
3
3
|
description: Revise the next increment just-in-time — sharpen the next undone step against what's now true, or (with input) re-cut, split, or add a step. Empty input runs an automatic sharpen. One at a time; the human approves.
|
|
4
4
|
argument-hint: "[what-changed]"
|
|
5
5
|
disable-model-invocation: true
|
|
6
|
-
model: opus
|
|
7
6
|
allowed-tools: Read, Edit, Write, Bash(plumbbob status:*), Bash(plumbbob agent list:*)
|
|
8
7
|
---
|
|
9
8
|
|
|
@@ -36,17 +35,19 @@ grew — but its everyday job is to sharpen, not to invent.
|
|
|
36
35
|
2. **Propose the revision** (or the new/split step): a one-line **title**, a **done-when**
|
|
37
36
|
`/pb-verify` can validate, and a **seam** (exact paths, or a `dir/` grant). Keep it
|
|
38
37
|
small enough to verify in one review pass. Show the before/after so the human can see
|
|
39
|
-
what you changed and why.
|
|
38
|
+
what you changed and why. Re-check the optional `- model:` recommendation too:
|
|
39
|
+
a step that sharpened into rote work can drop to a smaller model; one that grew subtle
|
|
40
|
+
earns a frontier one. Advisory, plain text (no backticks), never a gate.
|
|
40
41
|
3. **Get the human's OK**, then write it into `## Steps` in the standard format —
|
|
41
42
|
`N. [ ] <title> — **done when:** <criterion>` with a `- seam:` sub-line. Revise the
|
|
42
43
|
existing step in place; only append when you are genuinely adding an increment.
|
|
43
|
-
4. **Revise the step's harness bindings if they drifted too** *(optional
|
|
44
|
+
4. **Revise the step's harness bindings if they drifted too** *(optional)*. If the
|
|
44
45
|
build carries a `harness.json` (beside `intent.md`) and the reality that moved the
|
|
45
46
|
step also changed which agents it wants, sharpen that step's slot bindings
|
|
46
47
|
(`before`/`build`/`after`) and `note` at the same time — this is the just-in-time
|
|
47
48
|
counterpart to `/pb-plan`'s plan-time binding. `plumbbob agent list` shows what's
|
|
48
49
|
resolvable. Same rule as the plan move: bindings + prose only, never a conditional
|
|
49
|
-
|
|
50
|
+
. Leave it untouched when the step's agents are still right, or when the build
|
|
50
51
|
uses none.
|
|
51
52
|
|
|
52
53
|
## The hard contracts
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
name: pb-verify
|
|
3
3
|
description: "The verify tick — run the check, self-review the diff against intent, validate the step's done-when, pause for your approval, then checkpoint. Executor-agnostic: it reads the diff, not who wrote it."
|
|
4
4
|
disable-model-invocation: true
|
|
5
|
-
model: opus
|
|
6
5
|
allowed-tools: Read, Bash(plumbbob status:*), Bash(plumbbob check:*), Bash(plumbbob checkpoint:*), Bash(plumbbob agent:*), Bash(git diff:*), Bash(git status:*)
|
|
7
6
|
---
|
|
8
7
|
|
|
@@ -12,29 +11,29 @@ Current session state (injected when this skill runs): !`plumbbob status 2>/dev/
|
|
|
12
11
|
|
|
13
12
|
This is the **tick** — the one beat where the human is the clock. Whatever produced
|
|
14
13
|
the current diff — `/pb-build`, your own hands, a vibe session, another harness —
|
|
15
|
-
this skill verifies it the same way: **it reads the diff, not the author
|
|
14
|
+
this skill verifies it the same way: **it reads the diff, not the author**.
|
|
16
15
|
|
|
17
16
|
## What this skill does, in order
|
|
18
17
|
|
|
19
18
|
1. **Check.** Run `plumbbob check` (the heavy gate — checkride unless the repo
|
|
20
|
-
configures a `check` override
|
|
19
|
+
configures a `check` override). If it comes back **red**, stop here: the gate
|
|
21
20
|
names the failing slots and where each tool's raw output landed — read
|
|
22
21
|
`.check/summary.json`, then the failing slot's own file (`.check/<slot>.json` or
|
|
23
22
|
`.check/<slot>.stdout.txt`) for the actual diagnostics instead of scraping
|
|
24
23
|
scrollback. Report what failed and do **not** pause for approval — there is
|
|
25
24
|
nothing to approve yet. The human fixes it and re-invokes. (Exit 2 means the gate
|
|
26
25
|
itself broke — a harness problem to surface, not a code failure.)
|
|
27
|
-
2. **Run any bound `after`-agents** *(optional
|
|
26
|
+
2. **Run any bound `after`-agents** *(optional)*. If the build's `harness.json`
|
|
28
27
|
binds agents to this step's `after` slot, run `plumbbob agent run --step <n> --mode
|
|
29
28
|
after`. Their envelopes are **advisory input to the self-review, never a gate** —
|
|
30
29
|
`plumbbob check` already gated in step 1, and an `after`-agent that could fail a step
|
|
31
|
-
is the lock returning in autonomy's costume
|
|
32
|
-
`summary`/`body` into the review below; route a non-`done` one by its status
|
|
30
|
+
is the lock returning in autonomy's costume. Fold a `done` envelope's
|
|
31
|
+
`summary`/`body` into the review below; route a non-`done` one by its status: a
|
|
33
32
|
`blocked` agent couldn't finish — surface its `notes`, let the human unblock, re-run;
|
|
34
33
|
a `drift` agent found the plan no longer matches reality — stop and send the human to
|
|
35
34
|
`/pb-refine` to repair the plan before checkpointing. No binding, or no harness, is a
|
|
36
35
|
clean no-op.
|
|
37
|
-
3. **Self-review** *(a single structured read
|
|
36
|
+
3. **Self-review** *(a single structured read)*. Read `git diff` and
|
|
38
37
|
`.plumbbob/intent.md`, then in one pass check the diff against:
|
|
39
38
|
- the current step's **done-when** criterion — is it actually met?
|
|
40
39
|
- the **Decisions** — does anything contradict a settled call?
|
|
@@ -64,16 +63,34 @@ this skill verifies it the same way: **it reads the diff, not the author** (D3).
|
|
|
64
63
|
(done-when + seam + diffstat) on its own. Either way, do **not** bump the version or
|
|
65
64
|
touch the changelog — that is the human's `/version` call.
|
|
66
65
|
|
|
66
|
+
## The latch makes the pause real (D64)
|
|
67
|
+
|
|
68
|
+
When this session runs under plumbbob's turn hook, `plumbbob checkpoint` **refuses to
|
|
69
|
+
land a step in the same turn it was entered** — and that refusal **is** this pause, not
|
|
70
|
+
an error to route around. If the checkpoint prints *"checkpoint refused — no human turn
|
|
71
|
+
since this step began,"* you have reached the pause the hard way: present the diff and
|
|
72
|
+
the self-review, **end the turn**, and the human's next message is the tick that lets
|
|
73
|
+
the checkpoint land when you re-fire. **Never reach for a raw `git commit` to force the
|
|
74
|
+
land** — that forges the very record the latch exists to keep honest, and the
|
|
75
|
+
commit-ask hook asks the human about it anyway. The refusal is a healthy latch doing its
|
|
76
|
+
job on the *record* while the *work* plane stays free (D10/D13); a `/pb-build --auto` or
|
|
77
|
+
a typed step range in the human's own prompt is the only self-approval, and `auto: true`
|
|
78
|
+
in settings is the standing one.
|
|
79
|
+
|
|
67
80
|
## The hard contracts
|
|
68
81
|
|
|
69
82
|
- **Never skip the pause.** Check → self-review → validate, then wait. Approval is
|
|
70
83
|
the only thing that triggers the checkpoint.
|
|
71
|
-
- **Read the diff, not the author
|
|
84
|
+
- **Read the diff, not the author**. Verify identically whether the code was
|
|
72
85
|
built by `/pb-build`, by hand, vibed, or by another harness.
|
|
73
86
|
- **Red means stop, not pause.** A failing check is not an approval decision; report
|
|
74
87
|
it and end your turn.
|
|
75
88
|
- **You review; you do not build.** If the self-review finds a problem, surface it
|
|
76
89
|
and stop — fixing is a new build beat, not part of verify.
|
|
77
|
-
- **`after`-agents advise; they never gate
|
|
90
|
+
- **`after`-agents advise; they never gate**. Their output feeds the
|
|
78
91
|
self-review — checkride gates, the human approves. `blocked` → unblock and re-run;
|
|
79
92
|
`drift` → `/pb-refine` before checkpointing. No code path makes them blocking.
|
|
93
|
+
- **A refused checkpoint is the pause, never a workaround (D64).** Under the turn
|
|
94
|
+
hook a same-turn checkpoint is refused *by design* — present the diff, **end the
|
|
95
|
+
turn**, and let the human's next message re-tick it. Never route around it with a raw
|
|
96
|
+
`git commit`; the latch guards the record, not the work.
|