pincer-workflow 0.5.0 → 0.7.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.
Files changed (59) hide show
  1. package/README.md +106 -19
  2. package/bin/pincer.js +17 -1
  3. package/package.json +3 -3
  4. package/template/.agents/skills/pincer-code/SKILL.md +88 -14
  5. package/template/.agents/skills/pincer-evaluate/SKILL.md +42 -13
  6. package/template/.agents/skills/pincer-narrow/SKILL.md +53 -12
  7. package/template/.agents/skills/pincer-plan/SKILL.md +12 -4
  8. package/template/.agents/skills/pincer-release/SKILL.md +18 -0
  9. package/template/.agents/skills/pincer-status/SKILL.md +29 -5
  10. package/template/.claude/commands/pincer-code.md +88 -14
  11. package/template/.claude/commands/pincer-evaluate.md +42 -13
  12. package/template/.claude/commands/pincer-narrow.md +53 -12
  13. package/template/.claude/commands/pincer-plan.md +12 -4
  14. package/template/.claude/commands/pincer-release.md +18 -0
  15. package/template/.claude/commands/pincer-status.md +29 -5
  16. package/template/.claude/hooks/hook-policy.cjs +13 -6
  17. package/template/.claude/references/prd-template.md +11 -4
  18. package/template/.codex/README.md +1 -1
  19. package/template/.github/prompts/pincer-code.prompt.md +88 -14
  20. package/template/.github/prompts/pincer-evaluate.prompt.md +42 -13
  21. package/template/.github/prompts/pincer-narrow.prompt.md +53 -12
  22. package/template/.github/prompts/pincer-plan.prompt.md +12 -4
  23. package/template/.github/prompts/pincer-release.prompt.md +18 -0
  24. package/template/.github/prompts/pincer-status.prompt.md +29 -5
  25. package/template/AGENTS.md +17 -1
  26. package/template/docs/dry-run-checklist.md +30 -3
  27. package/template/docs/release-checklist.md +3 -1
  28. package/template/docs/runtime-contracts.md +1428 -96
  29. package/template/scripts/pincer-evidence.cjs +9 -7
  30. package/template/scripts/pincer-runtime/adopt.cjs +132 -0
  31. package/template/scripts/pincer-runtime/agreement.cjs +240 -0
  32. package/template/scripts/pincer-runtime/authorization.cjs +167 -0
  33. package/template/scripts/pincer-runtime/changes.cjs +517 -0
  34. package/template/scripts/pincer-runtime/checks.cjs +48 -0
  35. package/template/scripts/pincer-runtime/coverage.cjs +361 -0
  36. package/template/scripts/pincer-runtime/dispositions.cjs +95 -0
  37. package/template/scripts/pincer-runtime/evidence.cjs +303 -18
  38. package/template/scripts/pincer-runtime/gates.cjs +73 -0
  39. package/template/scripts/pincer-runtime/identity.cjs +21 -4
  40. package/template/scripts/pincer-runtime/impact.cjs +177 -0
  41. package/template/scripts/pincer-runtime/io.cjs +41 -0
  42. package/template/scripts/pincer-runtime/lifecycle.cjs +34 -12
  43. package/template/scripts/pincer-runtime/locator.cjs +158 -0
  44. package/template/scripts/pincer-runtime/migrate.cjs +140 -63
  45. package/template/scripts/pincer-runtime/parse.cjs +20 -1
  46. package/template/scripts/pincer-runtime/phases.cjs +245 -0
  47. package/template/scripts/pincer-runtime/readiness.cjs +15 -2
  48. package/template/scripts/pincer-runtime/requirements.cjs +255 -0
  49. package/template/scripts/pincer-runtime/resume.cjs +273 -0
  50. package/template/scripts/pincer-runtime/routing.cjs +54 -0
  51. package/template/scripts/pincer-runtime/runner.cjs +24 -6
  52. package/template/scripts/pincer-runtime/scaffold.cjs +254 -0
  53. package/template/scripts/pincer-runtime/state.cjs +29 -7
  54. package/template/scripts/pincer-runtime/status.cjs +178 -22
  55. package/template/scripts/pincer-runtime/transaction.cjs +200 -0
  56. package/template/scripts/pincer-runtime/transitions.cjs +134 -0
  57. package/template/scripts/pincer-runtime.cjs +412 -76
  58. package/template/scripts/pincer-status.sh +1 -1
  59. package/template/scripts/pincer-ticket.sh +1 -1
package/README.md CHANGED
@@ -31,15 +31,80 @@ On Codex CLI the commands are skills, invoked by mention rather than slash:
31
31
  `$pincer-plan <brief>` → `$pincer-narrow` → `$pincer-code` → `$pincer-evaluate`
32
32
  → `$pincer-release`, and `$pincer-status`.
33
33
 
34
+ ## Your first change, end to end
35
+
36
+ The five commands above are the shape of the work. This is the whole journey for one
37
+ change on a project that wants strict requirement coverage — the path most of the
38
+ runtime exists to support. Every step is a real command; none of them is optional
39
+ ceremony, and the two read-only reports (`coverage scaffold`, `resume --brief`) write
40
+ nothing.
41
+
42
+ ```bash
43
+ # 1. Install, then plan and break down the work.
44
+ npx pincer-workflow init
45
+ # /pincer-plan <brief> → .prd/prd-v1.md with R-NN requirements and S-NN scenarios
46
+ # /pincer-narrow → tickets/T-*.md, one per unit of work
47
+
48
+ # 2. Register the change and select it in this worktree.
49
+ node scripts/pincer-runtime.cjs register --prd .prd/prd-v1.md
50
+ node scripts/pincer-runtime.cjs change select prd-v1
51
+
52
+ # 3. Choose your coverage. Default is fine: tickets, checks and evidence work without
53
+ # this step. Strict coverage additionally binds every S-NN to a ticket and a check.
54
+ # Start the map from the draft — it lists every scenario and ticket for you:
55
+ node scripts/pincer-runtime.cjs coverage scaffold --change prd-v1
56
+
57
+ # 4. Author .prd/coverage/prd-v1.json yourself from that draft, then review the links.
58
+ # The draft never invents a link, a check command or a scope disposition, and it is
59
+ # not a map: `coverage adopt` refuses it. Working through its Unresolved list is the
60
+ # authoring step.
61
+
62
+ # 5. Adopt strict coverage explicitly, then record the user's actual approval.
63
+ node scripts/pincer-runtime.cjs coverage adopt --preview --change prd-v1
64
+ node scripts/pincer-runtime.cjs coverage adopt --apply --change prd-v1
65
+ node scripts/pincer-runtime.cjs change authorize prd-v1 --agreement <digest> \
66
+ --reference "<where the user said it>" --excerpt "<the user's approval, quoted>"
67
+ node scripts/pincer-runtime.cjs change activate prd-v1
68
+
69
+ # 6. Implement. One commit per ticket; `done` refuses without a current passing check.
70
+ # /pincer-code
71
+
72
+ # 7. Come back tomorrow, or in a fresh session with no memory of any of this:
73
+ node scripts/pincer-runtime.cjs resume --brief
74
+ # → one screen: the change, the authorization verdict, the coverage label, the
75
+ # blocker categories with counts, and the exact next command. `resume` (no
76
+ # --brief) prints every row; the brief names the command that shows them.
77
+
78
+ # 8. Evaluate and audit.
79
+ # /pincer-evaluate → validated evidence under .prd/evidence/
80
+ # /pincer-release → read-only pass/fail audit
81
+ ```
82
+
83
+ Adoption grants no approval, and approval is never inferred: `coverage adopt` records
84
+ the agreement, `change authorize` records what the user actually said about it, and a
85
+ generic "continue" authorizes no revised scope. Edit the PRD, the tickets or the map
86
+ afterwards and the agreement changes — the runtime reports `AGREEMENT_CHANGED` and
87
+ waits for a fresh decision rather than carrying the old approval forward.
88
+
89
+ ### Pinning a management kit
90
+
91
+ The kit under `scripts/` is code that the workflow also runs *on* the project. When you
92
+ are changing that code, manage the work with a pinned released copy from outside the
93
+ tree rather than with the version you are editing — extract the scripts from a release
94
+ tag into a directory outside the repository, record its digest, and run the lifecycle
95
+ commands from there. A project that only uses PINCER never needs this; a project that
96
+ develops it does.
97
+
34
98
  ### Claude Code
35
99
 
36
- Works immediately: the commands, the two subagents, the `.env` deny rules and
100
+ Installs complete: the commands, the two subagents, the `.env` deny rules and
37
101
  the destructive-command and ticket-guard hooks install to `.claude/`. Start
38
- `claude` in the repo and run `/pincer-plan <brief>`.
102
+ `claude` in the repo and run `/pincer-plan <brief>`. See
103
+ [platform support](#platform-support) for what that install has been observed to do.
39
104
 
40
105
  ### Codex CLI
41
106
 
42
- Works immediately as well: `AGENTS.md` loads natively, and the six commands
107
+ Installs complete as well: `AGENTS.md` loads natively, and the six commands
43
108
  install as skills under `.agents/skills/`, which Codex discovers from the repo
44
109
  (no copying into your home directory — Codex removed custom prompts and
45
110
  `~/.codex/prompts/` in early 2026). Start `codex` in the repo, then type
@@ -61,11 +126,33 @@ Full notes in `.codex/README.md`.
61
126
  Enable `"chat.promptFiles": true` in VS Code settings, then run `/pincer-plan`
62
127
  in chat. `.github/copilot-instructions.md` is wired to `AGENTS.md`.
63
128
 
129
+ ## Platform support
130
+
131
+ Two different claims, kept apart on purpose. **Installation-tested** means the packed
132
+ artifact installs and its files land where they should, proven by the suites in this
133
+ repository on every push. **Live-observed** means a real agent session carried a real
134
+ change through the workflow on that surface and the artifacts were reviewed. An
135
+ installation check is not a platform trial, and packaged parity is not live success.
136
+
137
+ | Surface | Installation-tested | Live-observed |
138
+ | --- | --- | --- |
139
+ | Claude Code (`npx pincer-workflow init`) | yes — packed install, layout and generated parity | not for this release |
140
+ | Codex CLI (`.agents/skills/`) | yes — packed install and skill layout | not for this release |
141
+ | GitHub Copilot (VS Code prompts) | yes — packed install and prompt layout | no |
142
+ | Claude Code plugin (marketplace) | yes — plugin build parity | no |
143
+ | Windows (native, no POSIX shell) | no | no |
144
+
145
+ No live platform trial has been observed for the current release. The work that would
146
+ produce one — a full strict journey on Claude Code and on Codex, plus a real cross-agent
147
+ handoff resumed from files — is open, and until it reports, every "live-observed" cell
148
+ above stays as it reads. Earlier releases have their own recorded trials under `docs/`;
149
+ those describe the versions they were run against, not this one.
150
+
64
151
  ## Claude Code plugin (alternative)
65
152
 
66
153
  Claude users can install PINCER as a plugin instead — commands arrive
67
154
  namespaced (`/pincer:plan` … `/pincer:release`) and update automatically
68
- through the marketplace. The plugin's structured hook parser requires Node.js 18+:
155
+ through the marketplace. The plugin's structured hook parser requires Node.js 22+:
69
156
 
70
157
  ```
71
158
  /plugin marketplace add orchestratedbyalex/pincer-workflow
@@ -80,17 +167,6 @@ and Copilot). Installing both gives you duplicate commands. Plugin users who
80
167
  want the repo-side rules too can copy `AGENTS.md` from the
81
168
  [template](template/AGENTS.md).
82
169
 
83
- ## Update
84
-
85
- ```bash
86
- npx pincer-workflow@latest update
87
- ```
88
-
89
- Files you never touched are refreshed in place. (Installs older than v0.2.0 gain the ticket state machine, the status report and the ticket-guard hook on update; `.claude/settings.json` conflicts if you edited it — merge the new hook entry from the `.new` file. v0.2.2 replaces the Codex adapter: the commands are now skills in `.agents/skills/` invoked as `$pincer-*`, since Codex no longer loads `~/.codex/prompts/` — you can delete the copies there. v0.2.3 ships the playbooks, rubrics and templates under `.claude/` on every platform, which Codex- and Copilot-only installs were missing. v0.3.0 makes trust revocable: every verification attempt is recorded, `done` re-runs the check, tickets carry `prd:`, the release audit is read-only, and `.pincer.json` moves to schema 2 — an install from 0.2.x is treated as an untrusted baseline, so on the first update every changed file arrives as a `.new` proposal once; hooks now need Node 18+. v0.4.0 carries requirement IDs and `Proves:` checks from the PRD to evaluation, adds `profile: small|standard`, and saves candidate evidence under `.prd/evidence/`; the update is additive, but an existing `NOTES.md` without an `evidence:` manifest reads as stale until `/pincer-evaluate` is re-run. v0.4.1 is playbook wording only: the code playbook gains one recovery exception (a tree back at the evaluated candidate is restored by the user and nothing is committed), evaluate records one check per command, and plan asks only the open part of a partly answered question. v0.5.0 adds the runtime: `scripts/pincer-runtime.cjs` with its modules under `scripts/pincer-runtime/` now implements the ticket lifecycle, status, migration and evidence export, and `pincer-ticket.sh` / `pincer-status.sh` delegate to it, so every command needs Node.js 18+; unmigrated projects keep their receipts and behavior. Run `node scripts/pincer-runtime.cjs migrate --preview --prd .prd/prd-vN.md` to see what migration would change; after `--apply`, `verify` records attempts with captured logs under the ignored `.pincer/runtime/` and writes no receipt into the ticket, `done` consumes the current passing attempt against the current source, and `/pincer-evaluate` exports evidence schema 2 from runtime attempts. `docs/runtime-contracts.md` is the contract; `pincer doctor` tells you when a migration is available and never migrates on its own. Updating the kit inside a migrated project changes tracked runtime files, so every done ticket's attempt reads `SOURCE_CHANGED` until it is verified again; update between changes, not mid-ticket. An update from 0.4.x leaves the retired `scripts/pincer-ticket-lib.sh` on disk; `pincer doctor` names it and it is safe to delete.) Files you edited are left
90
- alone — the new version lands next to them as `<file>.new` for a manual merge.
91
- `npx pincer-workflow doctor` checks the health of an install (hook executable,
92
- `.gitignore` covering `.env*`, no unmerged `*.new` files, version current).
93
-
94
170
  ## What you get
95
171
 
96
172
  | Piece | Purpose |
@@ -98,18 +174,29 @@ alone — the new version lands next to them as `<file>.new` for a manual merge.
98
174
  | `AGENTS.md` | Project rules, single cross-platform source (workflow order, security defaults, secrets, untrusted-content and dependency rules) |
99
175
  | `.claude/commands/` | The five playbooks plus `/pincer-status` (canonical — adapters are generated from them; ships on every platform together with `agents/` and `references/`) |
100
176
  | `.claude/agents/` | `codebase-explorer` and `code-quality-reviewer` subagents, with inline fallbacks for platforms without subagents |
101
- | `scripts/pincer-runtime.cjs` + `scripts/pincer-runtime/` | The runtime (Node.js 18+, no dependencies): one implementation of the ticket lifecycle, readiness, status (`--json` too), change registration, source identity, verification attempts with sanitized captured logs, migration with backups, candidate checks and evidence export; `docs/runtime-contracts.md` is its contract. Local attempts live in the ignored `.pincer/runtime/`, change bindings in `.prd/changes/`; both are written only by the runtime |
177
+ | `scripts/pincer-runtime.cjs` + `scripts/pincer-runtime/` | The runtime (Node.js 22+, no dependencies): one implementation of the ticket lifecycle, readiness, status (`--json` too), change records with lifecycle, agreements, authorization and decisions (`change list|show|select|activate|pause|resume|complete|reopen|cancel|supersede|revise|authorize|decide`), the read-only `resume` report, source identity, verification attempts with sanitized captured logs, migration with backups, candidate checks and evidence export; `docs/runtime-contracts.md` is its contract. Local attempts and the worktree's selection live in the ignored `.pincer/runtime/`, change records in `.prd/changes/`, evaluation locators in `.prd/evidence/changes/`; all are written only by the runtime |
102
178
  | `scripts/pincer-ticket.sh` | Wrapper for the lifecycle: `start` (enforces dependency order) → `verify` (runs the ticket's check; before migration it stamps a receipt only on green, after migration it records an attempt bound to the current source) → `done` (refuses without a current pass or with unticked criteria; after migration it consumes the attempt without re-running the check) |
103
179
  | `scripts/pincer-status.sh` | Wrapper for the read-only state report: current PRD and profile, `Runtime` mode, associated tickets, wall-clock elapsed time while work is active or against an explicit budget, evidence verdict and `Provenance`, warnings with reason codes, and next command |
104
180
  | `scripts/pincer-evidence.cjs` | Read-only validator for candidate evidence (schema 1 authored, schema 2 exported from runtime attempts): `/pincer-evaluate` writes `.prd/evidence/prd-vN/<candidate>/manifest.json` plus logs and screenshots; status and release validate schema, references, candidate association, required results, provenance, file containment and SHA-256 digests. Legacy `NOTES.md` without a manifest is readable but never release-ready; an older runtime does not enforce this contract |
105
- | `docs/runtime-contracts.md` | The runtime contract: modes, commands and exit codes, supported grammar, identities, source manifest, attempts, capture limits, reason codes, evidence schema 2, migration and rollback |
106
- | `.claude/hooks/` + `settings.json` | Claude guardrails for documented destructive command forms and for writes to ticket state, `.pincer/` and `.prd/changes/`; Node.js 18+ parses hook payloads structurally |
181
+ | `docs/runtime-contracts.md` | The runtime contract: modes (legacy, migrated, changes), commands and exit codes, supported grammar, change records, selection, lifecycle, agreements and authorization, command gates, identities, source manifest, attempts, transactions, capture limits, reason codes, evidence schema 2, the evaluation locator, the resume report, migration and rollback, worktrees |
182
+ | `.claude/hooks/` + `settings.json` | Claude guardrails for documented destructive command forms and for writes to ticket state, `.pincer/`, `.prd/changes/` and `.prd/evidence/changes/`; Node.js 22+ parses hook payloads structurally |
107
183
  | `.agents/skills/` · `.codex/` · `.github/` | Generated Codex skills and Copilot prompt files + platform wiring (`.codex/README.md` covers the Codex posture) |
108
184
  | `scripts/sync-prompts.sh` | Regenerates the adapters after you edit a playbook |
109
- | `scripts/build-plugin.sh` | Regenerates the Claude Code plugin (`plugin/`) from the template |
185
+ | `scripts/build-plugin.sh` (maintainers of this repository only — not installed into your project) | Regenerates the Claude Code plugin (`plugin/`) from the template |
110
186
  | `docs/release-checklist.md` | General, read-only candidate audit used by `/pincer-release` |
111
187
  | `docs/dry-run-checklist.md` | Separate manual platform trial for the Pincer kit |
112
188
 
189
+ ## Update
190
+
191
+ ```bash
192
+ npx pincer-workflow@latest update
193
+ ```
194
+
195
+ Files you never touched are refreshed in place. (Installs older than v0.2.0 gain the ticket state machine, the status report and the ticket-guard hook on update; `.claude/settings.json` conflicts if you edited it — merge the new hook entry from the `.new` file. v0.2.2 replaces the Codex adapter: the commands are now skills in `.agents/skills/` invoked as `$pincer-*`, since Codex no longer loads `~/.codex/prompts/` — you can delete the copies there. v0.2.3 ships the playbooks, rubrics and templates under `.claude/` on every platform, which Codex- and Copilot-only installs were missing. v0.3.0 makes trust revocable: every verification attempt is recorded, `done` re-runs the check, tickets carry `prd:`, the release audit is read-only, and `.pincer.json` moves to schema 2 — an install from 0.2.x is treated as an untrusted baseline, so on the first update every changed file arrives as a `.new` proposal once; hooks now need Node 18+. v0.4.0 carries requirement IDs and `Proves:` checks from the PRD to evaluation, adds `profile: small|standard`, and saves candidate evidence under `.prd/evidence/`; the update is additive, but an existing `NOTES.md` without an `evidence:` manifest reads as stale until `/pincer-evaluate` is re-run. v0.4.1 is playbook wording only: the code playbook gains one recovery exception (a tree back at the evaluated candidate is restored by the user and nothing is committed), evaluate records one check per command, and plan asks only the open part of a partly answered question. v0.5.0 adds the runtime: `scripts/pincer-runtime.cjs` with its modules under `scripts/pincer-runtime/` now implements the ticket lifecycle, status, migration and evidence export, and `pincer-ticket.sh` / `pincer-status.sh` delegate to it, so every command needs Node.js 18+; unmigrated projects keep their receipts and behavior. Run `node scripts/pincer-runtime.cjs migrate --preview --prd .prd/prd-vN.md` to see what migration would change; after `--apply`, `verify` records attempts with captured logs under the ignored `.pincer/runtime/` and writes no receipt into the ticket, `done` consumes the current passing attempt against the current source, and `/pincer-evaluate` exports evidence schema 2 from runtime attempts. `docs/runtime-contracts.md` is the contract; `pincer doctor` tells you when a migration is available and never migrates on its own. v0.6.0 keeps several changes side by side: `register` writes a change record (schema 2) that retains every earlier change, the worktree selects the change it works on (`change select`), the user's approval is recorded against the reviewed agreement (`change authorize`), the lifecycle is explicit (`change activate|pause|resume|complete|reopen|cancel|supersede`), and `resume` prints where to continue from files alone. A v0.5.0 binding converts with the same `migrate --preview` / `--apply`; the converted change is planned with no authorization, its old attempts and evaluation are history until verified again, and the old free-text authorization never authorizes execution. Selection and local attempts are per worktree; records are tracked and shared through git; completed means ready for evaluation, not released. v0.6.0 also raises the floor to Node.js 22+, because 18 and 20 are past end of life. It separately fixes a defect that was never version-specific: a command whose output exceeded one pipe buffer (65,536 bytes) lost the tail when the process exited and still exited 0, on every version including 22 and 24. Every write is now synchronous, so piped `--json` is complete. Updating the kit inside a migrated project changes tracked runtime files, so every done ticket's attempt reads `SOURCE_CHANGED` until it is verified again; update between changes, not mid-ticket. An update from 0.4.x leaves the retired `scripts/pincer-ticket-lib.sh` on disk; `pincer doctor` names it and it is safe to delete.) Files you edited are left
196
+ alone — the new version lands next to them as `<file>.new` for a manual merge.
197
+ `npx pincer-workflow doctor` checks the health of an install (hook executable,
198
+ `.gitignore` covering `.env*`, no unmerged `*.new` files, version current).
199
+
113
200
  ## Design principles
114
201
 
115
202
  - **Approval gates scale with decision cost** — a human owns architecture, scope,
package/bin/pincer.js CHANGED
@@ -273,7 +273,23 @@ function cmdDoctor() {
273
273
  ? fs.readdirSync(ticketsDir).filter((n) => /^T-\d+.*\.md$/.test(n)).filter((n) => /^(verified|last_check):/m.test(fs.readFileSync(path.join(ticketsDir, n), 'utf8')))
274
274
  : [];
275
275
  const bindingsDir = path.join(dir, '.prd', 'changes');
276
- const hasBinding = fs.existsSync(bindingsDir) && fs.readdirSync(bindingsDir).some((n) => n.endsWith('.json'));
276
+ const bindingFiles = fs.existsSync(bindingsDir) ? fs.readdirSync(bindingsDir).filter((n) => n.endsWith('.json')) : [];
277
+ const hasBinding = bindingFiles.length > 0;
278
+ // A v0.5.0 binding (schema 1) converts explicitly into a schema 2 change record; doctor only reports it.
279
+ const oldBindings = bindingFiles.filter((n) => { try { return JSON.parse(fs.readFileSync(path.join(bindingsDir, n), 'utf8')).schema === 1; } catch { return false; } });
280
+ for (const n of oldBindings) {
281
+ let prd = '.prd/prd-vN.md';
282
+ try { prd = JSON.parse(fs.readFileSync(path.join(bindingsDir, n), 'utf8')).prd || prd; } catch { /* reported above by the runtime */ }
283
+ console.log(` note migration to change records available: .prd/changes/${n} is a v0.5.0 binding (schema 1) — preview with: node scripts/pincer-runtime.cjs migrate --preview --prd ${prd}`);
284
+ }
285
+ // A schema 2 change record beside an authored coverage map can adopt strict coverage explicitly; doctor only reports it.
286
+ for (const n of bindingFiles) {
287
+ let doc = null;
288
+ try { doc = JSON.parse(fs.readFileSync(path.join(bindingsDir, n), 'utf8')); } catch { doc = null; }
289
+ if (!doc || doc.schema !== 2) continue;
290
+ const id = n.replace(/\.json$/, '');
291
+ if (fs.existsSync(path.join(dir, '.prd', 'coverage', `${id}.json`))) console.log(` note strict coverage adoption available: .prd/coverage/${id}.json exists and .prd/changes/${n} is a schema 2 record — preview with: node scripts/pincer-runtime.cjs coverage adopt --preview --change ${id}`);
292
+ }
277
293
  if (legacyReceipts.length && !hasBinding) {
278
294
  const prdDir = path.join(dir, '.prd');
279
295
  const prds = fs.existsSync(prdDir) ? fs.readdirSync(prdDir).map((n) => n.match(/^prd-v(\d+)\.md$/)).filter(Boolean).map((m) => Number(m[1])) : [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pincer-workflow",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "PINCER — a PRD-driven agentic delivery workflow for Claude Code, Codex CLI, and GitHub Copilot. Plan · Investigate · Narrow · Code · Evaluate · Release.",
5
5
  "bin": {
6
6
  "pincer": "bin/pincer.js"
@@ -11,10 +11,10 @@
11
11
  "template"
12
12
  ],
13
13
  "engines": {
14
- "node": ">=18"
14
+ "node": ">=22"
15
15
  },
16
16
  "scripts": {
17
- "test": "node test/smoke.test.js && node test/installer.test.js && node test/ticket.test.js && node test/validation.test.js && node test/verification.test.js && node test/behavioral-verification.test.js && node test/evidence.test.js && node test/candidate.test.js && node test/recovery.test.js && node test/hooks.test.js && node test/runtime-parse.test.js && node test/runtime-identity.test.js && node test/runtime-state.test.js && node test/runtime-status.test.js && node test/runtime-runner.test.js && node test/runtime-lifecycle.test.js && node test/runtime-migrate.test.js && node test/runtime-evidence.test.js && node test/workflow.test.js && node test/contracts.test.js && node test/distribution.test.js"
17
+ "test": "node test/smoke.test.js && node test/installer.test.js && node test/strict-onboarding.test.js && node test/ticket.test.js && node test/validation.test.js && node test/verification.test.js && node test/behavioral-verification.test.js && node test/evidence.test.js && node test/candidate.test.js && node test/recovery.test.js && node test/hooks.test.js && node test/runtime-parse.test.js && node test/coverage-inventory.test.js && node test/coverage-map.test.js && node test/coverage-scaffold.test.js && node test/coverage-agreement.test.js && node test/coverage-adoption.test.js && node test/coverage-readiness.test.js && node test/coverage-impact.test.js && node test/coverage-checks.test.js && node test/coverage-evidence.test.js && node test/coverage-reports.test.js && node test/runtime-identity.test.js && node test/change-registry.test.js && node test/change-selection.test.js && node test/change-agreement.test.js && node test/change-authorization.test.js && node test/change-lifecycle.test.js && node test/change-command-gates.test.js && node test/change-evidence-context.test.js && node test/change-evaluations.test.js && node test/change-resume.test.js && node test/resume-brief.test.js && node test/change-trial-record.test.js && node test/change-review-packet.test.js && node test/runtime-state.test.js && node test/change-transactions.test.js && node test/runtime-status.test.js && node test/runtime-output.test.js && node test/runtime-runner.test.js && node test/runtime-lifecycle.test.js && node test/runtime-migrate.test.js && node test/change-migration.test.js && node test/runtime-evidence.test.js && node test/workflow.test.js && node test/improvement-contracts.test.js && node test/contracts.test.js && node test/change-contracts.test.js && node test/coverage-contracts.test.js && node test/distribution.test.js && node test/change-distribution.test.js && node test/coverage-distribution.test.js && node test/effort-records.test.js && node test/execution-freeze.test.js && node test/delivery-benchmark.test.js && node test/delivery-benchmark-v7.test.js && node test/benchmark-orchestrator.test.js && node test/strict-pilot-records.test.js && node test/platform-trial-records.test.js && node test/improvement-trial-records.test.js && node test/coverage-trial-record.test.js && node test/coverage-review-packet.test.js && node test/improvement-review-packet.test.js && node test/readiness-contracts.test.js && node test/benchmark-effective-inputs.test.js && node test/release-preparation.test.js && node test/benchmark-run-claims.test.js && node test/benchmark-environment.test.js && node test/benchmark-browser.test.js && node test/benchmark-restart.test.js && node test/benchmark-usage-completeness.test.js && node test/benchmark-terminal-records.test.js && node test/study-readiness.test.js && node test/benchmark-allocation.test.js && node test/benchmark-prepared-bases.test.js && node test/benchmark-study-launch.test.js"
18
18
  },
19
19
  "keywords": [
20
20
  "claude-code",
@@ -21,8 +21,14 @@ receipt that matches the current check, or with unticked acceptance criteria. Ne
21
21
  On a migrated project (a change binding under `.prd/changes/`; the `Runtime` line of
22
22
  `scripts/pincer-status.sh` names it) `verify` records an attempt under `.pincer/runtime/`
23
23
  and writes no receipt into the ticket, and `done` consumes the current passing attempt
24
- against the current source without re-running the check. `.pincer/` and `.prd/changes/`
25
- are written only by the runtime; never edit or delete them by hand.
24
+ against the current source without re-running the check. `.pincer/`, `.prd/changes/` and `.prd/evidence/changes/`
25
+ are written only by the runtime; never edit or delete them by hand. On a project with
26
+ change records (`Runtime changes …`) every `start`, `verify` and `done` first passes
27
+ the change gate: the ticket's change must be selected in this worktree, `active`
28
+ (`verify` also runs on a `completed` change), on a compatible branch, and authorized
29
+ for the current agreement — otherwise the command refuses with `SELECTION_REQUIRED`,
30
+ `WRONG_CHANGE`, `LIFECYCLE_BLOCKED`, `BASE_MISMATCH`, `DECISION_REQUIRED`,
31
+ `AUTHORIZATION_REQUIRED` or `AGREEMENT_CHANGED` before anything runs or is written.
26
32
 
27
33
  ## Before the loop
28
34
 
@@ -30,15 +36,37 @@ Run `scripts/pincer-status.sh`. It lists every ticket's state, what is blocked,
30
36
  build time from the clock, and the next action. If a ticket is `in_progress`, you are
31
37
  resuming: read it, check `git status` / `git diff` for uncommitted work, and continue
32
38
  from wherever the receipt says you are. Do not ask the user to reconfirm unchanged,
33
- previously authorized work. Read the `Runtime` line before the first ticket: a change
34
- binding present → continue; `legacy` and no ticket of this PRD carries legacy
35
- receipts → register now (`node scripts/pincer-runtime.cjs register --prd .prd/prd-vN.md --authorization "<the user's approval, quoted>"`,
36
- commit `.prd/changes/` and `.gitignore` as `Register PRD vN`); `legacy` with legacy receipts → run
37
- `node scripts/pincer-runtime.cjs migrate --preview --prd .prd/prd-vN.md`, show the plan
38
- (backups, receipts imported as history, `.gitignore` line) and ask once whether to
39
- apply. Apply only on a yes, then commit the rewritten tickets, `.gitignore` and the
40
- binding as `Migrate PRD vN to the runtime`. Never migrate silently, and never apply
41
- when the preview reports a conflict.
39
+ previously authorized work. Read the `Runtime` line before the first ticket. `changes` (change records under
40
+ `.prd/changes/`) → run `node scripts/pincer-runtime.cjs resume` and follow its `Next`
41
+ line: it names the selected change, its lifecycle state, the agreement and the
42
+ authorization verdict, the blockers in order and the exact next command, all from the
43
+ files on disk. `resume --brief` is the same report projected to counts and one next
44
+ action — the same verdict and the same `Next` line, with every blocker category kept
45
+ and its `Detail` line naming the command that prints the rows it grouped. Prefer it
46
+ when you are orienting, and read the full report when a blocker needs its detail. Select the change to work on (`node scripts/pincer-runtime.cjs change
47
+ select <id>`; selection is local metadata and touches no source), activate it
48
+ (`change activate <id>`; refused until the user's authorization is recorded with
49
+ `change authorize` and no consequential decision is open) and resume a paused change
50
+ with `change resume <id>`. On a change with strict coverage (`Coverage strict …` in status) also read
51
+ `node scripts/pincer-runtime.cjs coverage` — it names the scenario, ticket, check or
52
+ decision that is next and every structural gap (`COVERAGE_INCOMPLETE`,
53
+ `SCOPE_UNAUTHORIZED`, `OBLIGATION_MISSING`) — and, after any PRD, ticket or map edit,
54
+ `node scripts/pincer-runtime.cjs impact` (`--from G-NN` for another baseline): it
55
+ lists the affected scenarios, tickets and checks with reasons and the dependency
56
+ dependents separately, and reports an unscoped PRD change or unavailable history
57
+ rather than "no impact". `legacy` and no ticket of this PRD carries legacy
58
+ receipts → register now (`node scripts/pincer-runtime.cjs register --prd .prd/prd-vN.md`,
59
+ commit `.prd/changes/` and `.gitignore` as `Register PRD vN`), then record the user's
60
+ approval (`change authorize …`, as `$pincer-narrow` describes), select and activate.
61
+ `legacy` with legacy receipts, or a v0.5.0 binding (`Runtime change <id> · revision …`)
62
+ → run `node scripts/pincer-runtime.cjs migrate --preview --prd .prd/prd-vN.md`, show
63
+ the plan (backups, receipts imported as history, the converted binding, the
64
+ `.gitignore` line, the local selection) and ask once whether to apply. Apply only on
65
+ a yes, then commit the rewritten tickets, `.gitignore` and the record as `Migrate PRD
66
+ vN to the runtime`. The migrated change is planned with no authorization: record the
67
+ user's actual earlier instruction with `change authorize` (the v0.5.0 free text is
68
+ history only) and activate it. Never migrate silently, and never apply when the
69
+ preview reports a conflict.
42
70
 
43
71
  ## Loop (per ticket, in dependency order)
44
72
 
@@ -138,6 +166,48 @@ above applies only before migration. A session that died mid-`verify` leaves a `
138
166
  attempt: run `node scripts/pincer-runtime.cjs recover`, which finalizes it as
139
167
  `interrupted` once the owner process is gone, then `verify` again.
140
168
 
169
+ ## Changes: pausing, decisions and completion
170
+
171
+ - Stopping before the change is complete (end of session, switching to another
172
+ change): `node scripts/pincer-runtime.cjs change pause <id> --reason "<why>" --note "<handoff for the next session>"`
173
+ and commit the record. Pausing keeps every ticket state, attempt and authorization;
174
+ it refuses while a check is running (`recover` first if its owner died). A fresh
175
+ session runs `resume`, then `change resume <id>` under the existing authorization —
176
+ do not ask the user to re-approve unchanged scope. Another change's work in the
177
+ meantime makes this change's passing attempts `SOURCE_CHANGED`; verify again, do
178
+ not ask for approval again.
179
+ - A newly discovered consequential choice: `node scripts/pincer-runtime.cjs change decide <id> --summary "<the question>"`
180
+ blocks execution (`DECISION_REQUIRED`) until the user answers; record the answer with
181
+ `change decide <id> --resolve D-NN --reference "<where>" --excerpt "<the user's words>"`,
182
+ then `change authorize <id> --agreement <digest> --reference … --excerpt … --decision D-NN`.
183
+ A revision within the user's delegation (for example an added regression check for
184
+ approved behavior) records `change authorize <id> --agreement <digest> --delegated --basis A-NN --explanation "<why it stays within the delegation>"`
185
+ without asking again, and the changed check still needs fresh verification.
186
+ - Editing the PRD under its filename, or a ticket's acceptance text, dependencies,
187
+ size, timeout, association or check — and, with strict coverage, a scenario's text,
188
+ a map link, a declared command or timeout, or a scope entry — changes the agreement:
189
+ execution refuses with `AGREEMENT_CHANGED` (status shows the structural difference;
190
+ `impact` explains it) until its disposition is recorded as above. Ticking criteria, starting or closing tickets and recording
191
+ attempts never change it. An `AGREEMENT_CHANGED` caused by an edit this session
192
+ did not make — a revised PRD, an added or changed ticket found on resume — is a
193
+ consequential decision: raise it with `change decide <id> --summary "<what changed>"`,
194
+ report the structural difference (and the `impact` report) and stop. A general instruction to continue,
195
+ resume or not re-ask never authorizes new scope; record a `user` authorization for
196
+ the revised agreement only for an instruction that names the revised content. With strict coverage a scenario that will not be delivered is
197
+ never dropped from the map or the PRD: it is deferred or removed through a decision
198
+ the user resolves naming it, a `scope` entry (a removal keeps a tombstone naming the
199
+ prior agreement) and an authorization naming that decision; `coverage` reports
200
+ `OBLIGATION_MISSING` or `SCOPE_UNAUTHORIZED` until then, and `change complete`
201
+ refuses. A revised check declaration (a stricter command, an added check) within the
202
+ user's delegation is a `--delegated` authorization and needs fresh verification.
203
+ - When every ticket is done and ready: `node scripts/pincer-runtime.cjs change complete <id>`
204
+ (it refuses unfinished tickets, unticked criteria, stale or failed verification and
205
+ open decisions; with strict coverage also an incomplete map, an unauthorized
206
+ disposition or a missing obligation, before the ticket gate) and commit the record
207
+ as `Complete PRD vN`. Completion never asks for candidate evidence. Completed means ready
208
+ for evaluation, not evaluated or released; a later finding is `change reopen <id> --reason …`
209
+ plus a fix ticket.
210
+
141
211
  ## Budget rules
142
212
 
143
213
  - If the user set `PINCER_BUILD_BUDGET_MIN` or stated another budget, use the elapsed
@@ -149,7 +219,8 @@ attempt: run `node scripts/pincer-runtime.cjs recover`, which finalizes it as
149
219
 
150
220
  ## When all tickets are done
151
221
 
152
- Update the PRD to `status: built` and commit that change on its own (`PRD vN: built`).
222
+ On a project with change records, complete the change first (`change complete <id>`,
223
+ committed as `Complete PRD vN`). Then update the PRD to `status: built` and commit that change on its own (`PRD vN: built`).
153
224
  The built transition is part of the candidate that `$pincer-evaluate` reviews; it is
154
225
  never moved into a later evidence-only commit. Then finish with:
155
226
  "All tickets built. Run `$pincer-evaluate` for a final quality pass."
@@ -161,6 +232,9 @@ material choice not already authorized, and prepare the concrete proposal before
161
232
  asking. A decision the user delegated (for example "pick the architecture") does not
162
233
  need another approval when you exercise it, but a newly discovered consequential
163
234
  choice is surfaced before implementation. Record the authorization basis and the
164
- scope it covers in the PRD or the handover. An agent-written record or a status
235
+ scope it covers in the PRD or the handover, and on a project with change records as
236
+ a `change authorize` record (the user's words as the excerpt, or a `--delegated`
237
+ disposition with its basis). An agent-written record or a status
165
238
  field is not authenticated human approval. When resuming without the context that
166
- granted authorization, do not invent it — ask.
239
+ granted authorization, do not invent it — read the `resume` report; an authorization
240
+ it reports as `current` needs no repeat approval, and any other verdict is asked.
@@ -21,8 +21,10 @@ run the pipeline, then present results.
21
21
  that uncertainty before claiming a complete review. Record full commit IDs for
22
22
  `base` and `candidate` (`git rev-parse HEAD`), then review `git diff <base>..<candidate>`.
23
23
  The candidate is the clean, committed tree that already includes the implementation,
24
- the ticket closures and the PRD `status: built` commit: `git status --short` must be
25
- empty before review. If anything is uncommitted or the PRD is not yet built, return
24
+ the ticket closures, on a project with change records the `change complete` commit
25
+ (the `Runtime` line reads `… · completed ·`; `check` and `evidence export` refuse an
26
+ active, paused or unauthorized change), and the PRD `status: built` commit:
27
+ `git status --short` must be empty before review. If anything is uncommitted or the PRD is not yet built, return
26
28
  to `$pincer-code`; do not review a dirty tree.
27
29
  2. Dispatch a `code-quality-reviewer` agent with: the diff, the PRD's Success Criteria and
28
30
  Scope sections, and the list of tickets. If the diff is large, split by area and
@@ -30,7 +32,13 @@ run the pipeline, then present results.
30
32
  in a separate pass, applying `.claude/agents/code-quality-reviewer.md` as the rubric.)
31
33
  Keep the reviewer's report — or its explicit no-findings statement — for step 9,
32
34
  where it is saved as an artifact; a review that left no record cannot be audited.
33
- 3. Yourself, in parallel, check spec compliance. For every requirement `R-NN` in the
35
+ 3. Yourself, in parallel, check spec compliance. On a change with strict coverage
36
+ (`Coverage strict …` in status) start from `node scripts/pincer-runtime.cjs coverage`:
37
+ its structure must be complete, and its scenario rows are the obligations — the
38
+ export derives every disposition from the map and the outcomes, so you do not
39
+ author `requirements`; your judgment is recorded as `adequacy` (whether the
40
+ declared checks and reviews really establish their scenarios) and in
41
+ `coverage_review`. Otherwise, for every requirement `R-NN` in the
34
42
  PRD record one disposition: `delivered` (evidence on this candidate), `blocked`
35
43
  (required behavior failed or was left unverified — this blocks PASS; do not relabel
36
44
  it a known limitation to pass), or `deferred` (only with explicit user authorization;
@@ -65,8 +73,20 @@ run the pipeline, then present results.
65
73
  produces a new candidate: re-record `candidate`, re-run the checks against it, and
66
74
  write fresh evidence in step 9 — never reuse a manifest from a previous candidate.
67
75
  9. Persist evidence for the candidate under `.prd/evidence/prd-vN/<candidate>/`.
68
- Migrated project (the `Runtime` status line names a change): run each executable
69
- check through the runtime on the clean candidate view —
76
+ Strict coverage: run every declared command check as
77
+ `node scripts/pincer-runtime.cjs check C-NN --candidate <sha>` (no command, no
78
+ timeout: the map's declaration is the only source, and a supplied command is
79
+ `CHECK_UNDECLARED`); record each declared review or visual obligation in the
80
+ draft with its `result` and an artifact saved under the candidate's evidence
81
+ directory (a required one that is not passed with an artifact is
82
+ `REVIEW_MISSING`); write `adequacy: { verdict: "adequate" | "inadequate", note }`;
83
+ list every declared check once and no `requirements` (they are derived). The
84
+ export writes the inventory and map snapshots under `coverage/`, derives the
85
+ scenario and requirement rows and `delivery` (original versus agreed scope) and
86
+ validates them against the committed candidate; an `inadequate` judgment or a
87
+ failed required check is recorded honestly and blocks readiness. Migrated
88
+ project without strict coverage (the `Runtime` status line names a change): run
89
+ each executable check through the runtime on the clean candidate view —
70
90
  `node scripts/pincer-runtime.cjs check C-NN --candidate <sha> -- <command>` (one
71
91
  command per check, the command line as run; `npm test` stays one aggregate check) —
72
92
  then write the authored fields to a draft outside the evidence directory, for
@@ -79,8 +99,12 @@ run the pipeline, then present results.
79
99
  `result`, `provenance: runtime` and `attempt` from the attempts, labels review and
80
100
  visual checks `provenance: authored`, computes the digests and writes an evidence
81
101
  schema 2 manifest; it refuses a dirty tree, a HEAD that is not the candidate, a stub
82
- without an attempt, and a `passed` or `failed` command result written by hand. A
83
- tool that cannot run is recorded as an authored command check with
102
+ without an attempt, and a `passed` or `failed` command result written by hand. On a
103
+ project with change records the export also appends the evaluation to the change's
104
+ locator `.prd/evidence/changes/<id>.json` (the identity of this change's
105
+ evaluation; root `NOTES.md` stays the human summary and may be overwritten by a
106
+ later change's evaluation without losing this one) — commit the locator with the
107
+ evidence. A tool that cannot run is recorded as an authored command check with
84
108
  `result: unverified` and a note, as before. Legacy project (no change binding):
85
109
  author the schema 1 manifest as follows.
86
110
  - `checks/C-NN.log` — the command and a redacted summary or safe log of each
@@ -122,11 +146,13 @@ run the pipeline, then present results.
122
146
  evidence: .prd/evidence/prd-vN/<candidate>/manifest.json
123
147
  ---
124
148
  ```
125
- Then commit NOTES.md, the manifest and its listed artifacts — and nothing else —
149
+ Then commit NOTES.md, the manifest, its listed artifacts and (change records) the
150
+ evaluation locator — and nothing else —
126
151
  as `evaluate: PRD vN candidate <short sha>`. Status accepts this later commit only
127
- when its diff from the candidate is limited to `NOTES.md` and the evidence files
128
- the manifest lists; changes to source, tests, configuration, tickets, the PRD or
129
- other evaluations require reevaluation. Legacy notes without these references
152
+ when its diff from the candidate is limited to `NOTES.md`, the candidate's evidence
153
+ directories and evaluation locators; changes to source, tests, configuration,
154
+ tickets, the PRD or the change record (a lifecycle transition after the
155
+ candidate) require reevaluation. Legacy notes without these references
130
156
  do not establish readiness. Then describe what was built, what was cut
131
157
  and why, known issues, and what you'd do next with more time. Then a **Handover**
132
158
  section, written for the stranger who inherits this repo in six months: how to get
@@ -144,6 +170,9 @@ material choice not already authorized, and prepare the concrete proposal before
144
170
  asking. A decision the user delegated (for example "pick the architecture") does not
145
171
  need another approval when you exercise it, but a newly discovered consequential
146
172
  choice is surfaced before implementation. Record the authorization basis and the
147
- scope it covers in the PRD or the handover. An agent-written record or a status
173
+ scope it covers in the PRD or the handover, and on a project with change records as
174
+ a `change authorize` record (the user's words as the excerpt, or a `--delegated`
175
+ disposition with its basis). An agent-written record or a status
148
176
  field is not authenticated human approval. When resuming without the context that
149
- granted authorization, do not invent it — ask.
177
+ granted authorization, do not invent it — read the `resume` report; an authorization
178
+ it reports as `current` needs no repeat approval, and any other verdict is asked.
@@ -34,10 +34,29 @@ discovered consequential choice is surfaced before implementation.
34
34
  - Build the requirement map: for every `R-NN` in the PRD and each of its
35
35
  scenarios, name the ticket that owns the implementation and the executable
36
36
  check that exercises it, or an explicit review method when no executable check
37
- exists. Record the IDs in each ticket's Context as `Implements: R-NN, R-MM`.
38
- Enabling work that implements no requirement states its purpose in the ticket
39
- Objective. Resolve missing coverage and conflicting criteria with the user
40
- before implementation; do not start with an unmapped required scenario.
37
+ exists. Record the IDs in each ticket's Context as `Implements: R-NN, R-MM`
38
+ (a navigation aid). Enabling work that implements no requirement states its purpose
39
+ in the ticket Objective. Resolve missing coverage and conflicting criteria with
40
+ the user before implementation; do not start with an unmapped required scenario. On a change with change records, author the map once as
41
+ `.prd/coverage/<change id>.json` (coverage map schema 1, "Coverage map" in
42
+ `docs/runtime-contracts.md`). Start from
43
+ `node scripts/pincer-runtime.cjs coverage scaffold --change <change id>`: it prints
44
+ a read-only draft listing every live scenario exactly once with its requirement,
45
+ every ticket with its objective, its own `Implements:` claim and its Verification
46
+ text, and an `Unresolved` list of what is still unauthored. It writes nothing,
47
+ adopts nothing and decides nothing — it removes the transcription, not the
48
+ judgment, so a ticket's claim is material to check rather than a link, and no check
49
+ command, ticket role or scope disposition is ever invented. The draft is not a map:
50
+ it carries no `schema` key and `coverage adopt` refuses it. You author the real map
51
+ yourself, working through the draft's unresolved entries:
52
+ one `scenarios` row per `S-NN` naming its
53
+ implementing tickets and declared checks, every ticket of the change in
54
+ `tickets` as `implements` or `enables` (with a rationale), each check declared
55
+ once in `checks` with its kind, `required` flag and, for a command, the exact
56
+ command line and timeout, and a `scope` entry (`deferred` or `removed`) for a
57
+ scenario this change will not deliver, naming the decision that records the
58
+ user's choice. The map is authored work you edit by hand; the runtime never
59
+ rewrites it, and it validates it against the PRD's definitions.
41
60
  - Every ticket gets a runnable command in its Verification block — a fenced `bash`
42
61
  block that exits 0 only when the ticket is done. `scripts/pincer-ticket.sh verify`
43
62
  runs it verbatim and stamps the receipt that `done` requires, so it must be
@@ -87,12 +106,31 @@ existing authorization for the same scope and order.
87
106
  once it is resolved — only when step 4 surfaced a newly discovered consequential
88
107
  choice or a scope change the PRD does not cover. Then register the change when the
89
108
  `Runtime` status line says `legacy` and no ticket of this PRD carries legacy
90
- receipts: `node scripts/pincer-runtime.cjs register --prd .prd/prd-vN.md --authorization "<the user's approval, quoted>"`,
91
- then stage `.prd/changes/` and `.gitignore` (registration adds `.pincer/` to it) and
92
- commit them as `Register PRD vN`. The authorization
93
- text records the user's own words; running the command proves nothing by itself. A
94
- project whose tickets carry legacy receipts is migrated from `$pincer-code` after a
95
- preview, never here. Finish with:
109
+ receipts, or `changes` (the project already keeps change records):
110
+ `node scripts/pincer-runtime.cjs register --prd .prd/prd-vN.md` writes the change
111
+ record `.prd/changes/prd-vN.json` (retaining every earlier change); stage
112
+ `.prd/changes/` and `.gitignore` (registration adds `.pincer/` to it) and commit them
113
+ as `Register PRD vN`. Then record the user's actual approval against the agreement
114
+ the record binds — `node scripts/pincer-runtime.cjs change show prd-vN --json`
115
+ prints the agreement digest — with
116
+ `node scripts/pincer-runtime.cjs change authorize prd-vN --agreement <digest> --reference "<where the user said it>" --excerpt "<the user's approval, quoted>"`,
117
+ select it for this worktree (`node scripts/pincer-runtime.cjs change select prd-vN`)
118
+ and commit `.prd/changes/` as `Authorize PRD vN`. When the map was authored, adopt
119
+ strict coverage explicitly: `node scripts/pincer-runtime.cjs coverage adopt --preview --change prd-vN`
120
+ shows the inventory, the map digest and the agreement it records (it refuses an
121
+ incomplete map, naming the scenario or ticket); `--apply` writes the schema 3
122
+ record with a backup and grants nothing — record the user's approval of that
123
+ agreement with `change authorize` (the same instruction, if it named this
124
+ breakdown; a delegated disposition needs its basis) and commit `.prd/coverage/`
125
+ and `.prd/changes/` as `Adopt strict coverage for PRD vN`. A scenario the user
126
+ deferred or removed is a decision: `change decide --summary "<the choice>"`,
127
+ `--resolve D-NN` with the user's words naming the scenario, the `scope` entry in
128
+ the map, then `change authorize … --decision D-NN`. Never record a disposition
129
+ the user did not state; `coverage` reports `SCOPE_UNAUTHORIZED` until it is. The excerpt records the user's own
130
+ words; running the command proves nothing by itself, and a registration, a PRD
131
+ status or a passing check never becomes an authorization. A project whose tickets
132
+ carry legacy receipts, or that still holds a v0.5.0 binding (`Runtime change <id> ·
133
+ revision …`), is migrated from `$pincer-code` after a preview, never here. Finish with:
96
134
  "Tickets ready in `tickets/`. Run `$pincer-code` to start implementing."
97
135
 
98
136
  ## Authorization rule (shared by plan, narrow, code and evaluate)
@@ -102,6 +140,9 @@ material choice not already authorized, and prepare the concrete proposal before
102
140
  asking. A decision the user delegated (for example "pick the architecture") does not
103
141
  need another approval when you exercise it, but a newly discovered consequential
104
142
  choice is surfaced before implementation. Record the authorization basis and the
105
- scope it covers in the PRD or the handover. An agent-written record or a status
143
+ scope it covers in the PRD or the handover, and on a project with change records as
144
+ a `change authorize` record (the user's words as the excerpt, or a `--delegated`
145
+ disposition with its basis). An agent-written record or a status
106
146
  field is not authenticated human approval. When resuming without the context that
107
- granted authorization, do not invent it — ask.
147
+ granted authorization, do not invent it — read the `resume` report; an authorization
148
+ it reports as `current` needs no repeat approval, and any other verdict is asked.
@@ -93,8 +93,13 @@ concrete scope and architecture; do not repeat an approval already given for the
93
93
  In Requirements, assign stable `R-NN` IDs within the selected PRD: a revision
94
94
  keeps existing IDs and adds new ones, never renumbers. Every requirement has
95
95
  observable acceptance scenarios, the relevant failure paths, and the existing
96
- behavior it must preserve — `$pincer-narrow` maps each scenario to a ticket and
97
- a check, and `$pincer-evaluate` dispositions every ID.
96
+ behavior it must preserve, each written as a bold `- **S-NN:** …` item under its
97
+ requirement heading (the template's grammar; the runtime parses exactly these
98
+ definitions into the inventory that strict coverage tracks, and a requirement
99
+ without a scenario is invalid there) — `$pincer-narrow` maps each scenario to a
100
+ ticket and a check in the coverage map, and `$pincer-evaluate` dispositions every
101
+ ID. A supplied PRD keeps its own uppercase IDs (`REQ-1`, `AC-3`); only its
102
+ definition syntax is adapted, and the mapping table records what changed.
98
103
  2. Include optional sections when risk or the product context warrants them.
99
104
  3. Save to the next unused `.prd/prd-v{N}.md` (create `.prd/` if needed), with `N`
100
105
  matching the filename and frontmatter:
@@ -121,6 +126,9 @@ material choice not already authorized, and prepare the concrete proposal before
121
126
  asking. A decision the user delegated (for example "pick the architecture") does not
122
127
  need another approval when you exercise it, but a newly discovered consequential
123
128
  choice is surfaced before implementation. Record the authorization basis and the
124
- scope it covers in the PRD or the handover. An agent-written record or a status
129
+ scope it covers in the PRD or the handover, and on a project with change records as
130
+ a `change authorize` record (the user's words as the excerpt, or a `--delegated`
131
+ disposition with its basis). An agent-written record or a status
125
132
  field is not authenticated human approval. When resuming without the context that
126
- granted authorization, do not invent it — ask.
133
+ granted authorization, do not invent it — read the `resume` report; an authorization
134
+ it reports as `current` needs no repeat approval, and any other verdict is asked.