pincer-workflow 0.4.1 → 0.6.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/README.md +9 -7
- package/bin/pincer.js +58 -5
- package/package.json +3 -3
- package/template/.agents/skills/pincer-code/SKILL.md +117 -12
- package/template/.agents/skills/pincer-evaluate/SKILL.md +57 -10
- package/template/.agents/skills/pincer-narrow/SKILL.md +48 -8
- package/template/.agents/skills/pincer-plan/SKILL.md +12 -4
- package/template/.agents/skills/pincer-release/SKILL.md +32 -3
- package/template/.agents/skills/pincer-status/SKILL.md +25 -2
- package/template/.claude/commands/pincer-code.md +117 -12
- package/template/.claude/commands/pincer-evaluate.md +57 -10
- package/template/.claude/commands/pincer-narrow.md +48 -8
- package/template/.claude/commands/pincer-plan.md +12 -4
- package/template/.claude/commands/pincer-release.md +32 -3
- package/template/.claude/commands/pincer-status.md +25 -2
- package/template/.claude/hooks/hook-policy.cjs +24 -3
- package/template/.claude/references/prd-template.md +11 -4
- package/template/.claude/references/ticket-template.md +4 -0
- package/template/.codex/README.md +3 -2
- package/template/.github/prompts/pincer-code.prompt.md +117 -12
- package/template/.github/prompts/pincer-evaluate.prompt.md +57 -10
- package/template/.github/prompts/pincer-narrow.prompt.md +48 -8
- package/template/.github/prompts/pincer-plan.prompt.md +12 -4
- package/template/.github/prompts/pincer-release.prompt.md +32 -3
- package/template/.github/prompts/pincer-status.prompt.md +25 -2
- package/template/AGENTS.md +22 -0
- package/template/docs/dry-run-checklist.md +70 -6
- package/template/docs/release-checklist.md +5 -2
- package/template/docs/runtime-contracts.md +1683 -0
- package/template/scripts/pincer-evidence.cjs +13 -229
- package/template/scripts/pincer-runtime/adopt.cjs +132 -0
- package/template/scripts/pincer-runtime/agreement.cjs +240 -0
- package/template/scripts/pincer-runtime/authorization.cjs +167 -0
- package/template/scripts/pincer-runtime/changes.cjs +517 -0
- package/template/scripts/pincer-runtime/checks.cjs +48 -0
- package/template/scripts/pincer-runtime/coverage.cjs +361 -0
- package/template/scripts/pincer-runtime/dispositions.cjs +95 -0
- package/template/scripts/pincer-runtime/evidence.cjs +676 -0
- package/template/scripts/pincer-runtime/fsutil.cjs +37 -0
- package/template/scripts/pincer-runtime/gates.cjs +73 -0
- package/template/scripts/pincer-runtime/identity.cjs +163 -0
- package/template/scripts/pincer-runtime/impact.cjs +177 -0
- package/template/scripts/pincer-runtime/io.cjs +41 -0
- package/template/scripts/pincer-runtime/lifecycle.cjs +311 -0
- package/template/scripts/pincer-runtime/locator.cjs +158 -0
- package/template/scripts/pincer-runtime/migrate.cjs +204 -0
- package/template/scripts/pincer-runtime/parse.cjs +316 -0
- package/template/scripts/pincer-runtime/phases.cjs +245 -0
- package/template/scripts/pincer-runtime/readiness.cjs +97 -0
- package/template/scripts/pincer-runtime/requirements.cjs +255 -0
- package/template/scripts/pincer-runtime/resume.cjs +205 -0
- package/template/scripts/pincer-runtime/routing.cjs +54 -0
- package/template/scripts/pincer-runtime/runner.cjs +242 -0
- package/template/scripts/pincer-runtime/sanitize.cjs +63 -0
- package/template/scripts/pincer-runtime/source.cjs +129 -0
- package/template/scripts/pincer-runtime/state.cjs +314 -0
- package/template/scripts/pincer-runtime/status.cjs +514 -0
- package/template/scripts/pincer-runtime/transaction.cjs +200 -0
- package/template/scripts/pincer-runtime/transitions.cjs +134 -0
- package/template/scripts/pincer-runtime.cjs +661 -0
- package/template/scripts/pincer-status.sh +11 -162
- package/template/scripts/pincer-ticket.sh +19 -139
- package/template/scripts/pincer-ticket-lib.sh +0 -321
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ in chat. `.github/copilot-instructions.md` is wired to `AGENTS.md`.
|
|
|
65
65
|
|
|
66
66
|
Claude users can install PINCER as a plugin instead — commands arrive
|
|
67
67
|
namespaced (`/pincer:plan` … `/pincer:release`) and update automatically
|
|
68
|
-
through the marketplace. The plugin's structured hook parser requires Node.js
|
|
68
|
+
through the marketplace. The plugin's structured hook parser requires Node.js 22+:
|
|
69
69
|
|
|
70
70
|
```
|
|
71
71
|
/plugin marketplace add orchestratedbyalex/pincer-workflow
|
|
@@ -86,7 +86,7 @@ want the repo-side rules too can copy `AGENTS.md` from the
|
|
|
86
86
|
npx pincer-workflow@latest update
|
|
87
87
|
```
|
|
88
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.) Files you edited are left
|
|
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. The next version 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. The next version 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
|
|
90
90
|
alone — the new version lands next to them as `<file>.new` for a manual merge.
|
|
91
91
|
`npx pincer-workflow doctor` checks the health of an install (hook executable,
|
|
92
92
|
`.gitignore` covering `.env*`, no unmerged `*.new` files, version current).
|
|
@@ -98,13 +98,15 @@ alone — the new version lands next to them as `<file>.new` for a manual merge.
|
|
|
98
98
|
| `AGENTS.md` | Project rules, single cross-platform source (workflow order, security defaults, secrets, untrusted-content and dependency rules) |
|
|
99
99
|
| `.claude/commands/` | The five playbooks plus `/pincer-status` (canonical — adapters are generated from them; ships on every platform together with `agents/` and `references/`) |
|
|
100
100
|
| `.claude/agents/` | `codebase-explorer` and `code-quality-reviewer` subagents, with inline fallbacks for platforms without subagents |
|
|
101
|
-
| `scripts/pincer-
|
|
102
|
-
| `scripts/pincer-
|
|
103
|
-
| `scripts/pincer-
|
|
104
|
-
|
|
|
101
|
+
| `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
|
+
| `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
|
+
| `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
|
+
| `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 (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 |
|
|
106
|
+
| `.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 |
|
|
105
107
|
| `.agents/skills/` · `.codex/` · `.github/` | Generated Codex skills and Copilot prompt files + platform wiring (`.codex/README.md` covers the Codex posture) |
|
|
106
108
|
| `scripts/sync-prompts.sh` | Regenerates the adapters after you edit a playbook |
|
|
107
|
-
| `scripts/build-plugin.sh` | Regenerates the Claude Code plugin (`plugin/`) from the template |
|
|
109
|
+
| `scripts/build-plugin.sh` (maintainers of this repository only — not installed into your project) | Regenerates the Claude Code plugin (`plugin/`) from the template |
|
|
108
110
|
| `docs/release-checklist.md` | General, read-only candidate audit used by `/pincer-release` |
|
|
109
111
|
| `docs/dry-run-checklist.md` | Separate manual platform trial for the Pincer kit |
|
|
110
112
|
|
package/bin/pincer.js
CHANGED
|
@@ -26,13 +26,15 @@ const MANIFEST_SCHEMA = 2;
|
|
|
26
26
|
// and Copilot prompts point at them), so they ship everywhere; only Claude
|
|
27
27
|
// Code's own wiring (CLAUDE.md, settings.json, hooks) is platform-specific.
|
|
28
28
|
const PLATFORM_ROOTS = {
|
|
29
|
-
common: ['AGENTS.md', 'docs/release-checklist.md', 'docs/dry-run-checklist.md', 'scripts/sync-prompts.sh', 'scripts/pincer-ticket.sh', 'scripts/pincer-
|
|
29
|
+
common: ['AGENTS.md', 'docs/release-checklist.md', 'docs/dry-run-checklist.md', 'docs/runtime-contracts.md', 'scripts/sync-prompts.sh', 'scripts/pincer-ticket.sh', 'scripts/pincer-status.sh', 'scripts/pincer-evidence.cjs', 'scripts/pincer-runtime.cjs', 'scripts/pincer-runtime', '.claude/commands', '.claude/agents', '.claude/references'],
|
|
30
30
|
claude: ['CLAUDE.md', '.claude/settings.json', '.claude/hooks'],
|
|
31
31
|
codex: ['.codex', '.agents'],
|
|
32
32
|
copilot: ['.github'],
|
|
33
33
|
};
|
|
34
34
|
const EXECUTABLES = ['scripts/sync-prompts.sh', 'scripts/pincer-ticket.sh', 'scripts/pincer-status.sh', '.claude/hooks/block-dangerous.sh', '.claude/hooks/ticket-guard.sh'];
|
|
35
35
|
const GITIGNORE_LINES = ['.env', '.env.*', '!.env.example'];
|
|
36
|
+
// The runtime's local state (attempts, locks, backups) is never tracked.
|
|
37
|
+
const RUNTIME_IGNORE = '.pincer/';
|
|
36
38
|
|
|
37
39
|
const sha = (buf) => crypto.createHash('sha256').update(buf).digest('hex');
|
|
38
40
|
|
|
@@ -134,12 +136,18 @@ function install(dir, platforms, baseline) {
|
|
|
134
136
|
|
|
135
137
|
function ensureGitignore(dir) {
|
|
136
138
|
const p = path.join(dir, '.gitignore');
|
|
137
|
-
|
|
139
|
+
let existing = fs.existsSync(p) ? fs.readFileSync(p, 'utf8') : '';
|
|
138
140
|
const have = new Set(existing.split('\n').map((l) => l.trim()));
|
|
139
141
|
const missing = GITIGNORE_LINES.filter((l) => !have.has(l));
|
|
140
|
-
if (missing.length
|
|
141
|
-
|
|
142
|
-
|
|
142
|
+
if (missing.length) {
|
|
143
|
+
const lead = existing && !existing.endsWith('\n') ? '\n' : '';
|
|
144
|
+
fs.appendFileSync(p, `${lead}${existing ? '\n' : ''}# secrets (added by pincer init)\n${missing.join('\n')}\n`);
|
|
145
|
+
existing = fs.readFileSync(p, 'utf8');
|
|
146
|
+
}
|
|
147
|
+
if (![RUNTIME_IGNORE, '/.pincer/', '.pincer'].some((l) => have.has(l))) {
|
|
148
|
+
const lead = existing && !existing.endsWith('\n') ? '\n' : '';
|
|
149
|
+
fs.appendFileSync(p, `${lead}${existing ? '\n' : ''}# pincer runtime state (added by pincer init)\n${RUNTIME_IGNORE}\n`);
|
|
150
|
+
}
|
|
143
151
|
}
|
|
144
152
|
|
|
145
153
|
function report({ written, skipped, conflicted }) {
|
|
@@ -240,10 +248,55 @@ function cmdDoctor() {
|
|
|
240
248
|
const gi = fs.existsSync(path.join(dir, '.gitignore')) ? fs.readFileSync(path.join(dir, '.gitignore'), 'utf8') : '';
|
|
241
249
|
check(GITIGNORE_LINES.every((l) => gi.split('\n').map((s) => s.trim()).includes(l)),
|
|
242
250
|
'.gitignore covers .env files', 'add: .env / .env.* / !.env.example');
|
|
251
|
+
if (![RUNTIME_IGNORE, '/.pincer/', '.pincer'].some((l) => gi.split('\n').map((s) => s.trim()).includes(l))) {
|
|
252
|
+
console.log(` note .gitignore does not list ${RUNTIME_IGNORE} (runtime state); \`pincer update\`, \`register\` or \`migrate --apply\` adds it`);
|
|
253
|
+
}
|
|
243
254
|
|
|
244
255
|
const stale = fs.existsSync(TEMPLATE) && manifest.version !== VERSION;
|
|
245
256
|
check(!stale, `install is current (v${manifest.version})`, 'run: pincer update');
|
|
246
257
|
|
|
258
|
+
// The runtime ships with every layout; a project with legacy receipts and no
|
|
259
|
+
// change binding can migrate explicitly (never silently here).
|
|
260
|
+
const runtimeFiles = Object.keys(manifest.files).filter((rel) => rel === 'scripts/pincer-runtime.cjs' || rel.startsWith('scripts/pincer-runtime/'));
|
|
261
|
+
if (runtimeFiles.length) {
|
|
262
|
+
const missingRuntime = runtimeFiles.filter((rel) => !fs.existsSync(path.join(dir, rel)));
|
|
263
|
+
check(missingRuntime.length === 0, 'runtime files present', `missing: ${missingRuntime.join(', ')} — run: pincer update`);
|
|
264
|
+
}
|
|
265
|
+
// Files an earlier kit installed that this version no longer ships stay on disk
|
|
266
|
+
// (the installer never deletes); name them so they can be removed by hand.
|
|
267
|
+
const OBSOLETE = ['scripts/pincer-ticket-lib.sh'];
|
|
268
|
+
const obsolete = OBSOLETE.filter((rel) => fs.existsSync(path.join(dir, rel)) && !(rel in manifest.files));
|
|
269
|
+
if (obsolete.length) console.log(` note obsolete kit file(s) from an earlier version, safe to delete: ${obsolete.join(', ')}`);
|
|
270
|
+
|
|
271
|
+
const ticketsDir = path.join(dir, 'tickets');
|
|
272
|
+
const legacyReceipts = fs.existsSync(ticketsDir)
|
|
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
|
+
: [];
|
|
275
|
+
const bindingsDir = path.join(dir, '.prd', 'changes');
|
|
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
|
+
}
|
|
293
|
+
if (legacyReceipts.length && !hasBinding) {
|
|
294
|
+
const prdDir = path.join(dir, '.prd');
|
|
295
|
+
const prds = fs.existsSync(prdDir) ? fs.readdirSync(prdDir).map((n) => n.match(/^prd-v(\d+)\.md$/)).filter(Boolean).map((m) => Number(m[1])) : [];
|
|
296
|
+
const latest = prds.length ? `.prd/prd-v${Math.max(...prds)}.md` : '.prd/prd-vN.md';
|
|
297
|
+
console.log(` note migration available: ${legacyReceipts.length} ticket(s) carry legacy receipts and no change binding exists — preview with: node scripts/pincer-runtime.cjs migrate --preview --prd ${latest}`);
|
|
298
|
+
}
|
|
299
|
+
|
|
247
300
|
const edited = Object.entries(manifest.files)
|
|
248
301
|
.filter(([rel, h]) => fs.existsSync(path.join(dir, rel)) && sha(fs.readFileSync(path.join(dir, rel))) !== h)
|
|
249
302
|
.map(([rel]) => rel);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pincer-workflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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": ">=
|
|
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/workflow.test.js && node test/distribution.test.js"
|
|
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/coverage-inventory.test.js && node test/coverage-map.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/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/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/delivery-benchmark.test.js && node test/coverage-trial-record.test.js && node test/coverage-review-packet.test.js"
|
|
18
18
|
},
|
|
19
19
|
"keywords": [
|
|
20
20
|
"claude-code",
|
|
@@ -18,6 +18,17 @@ Ticket state lives in the ticket file's frontmatter and is written **only** by
|
|
|
18
18
|
Verification block and stamps a receipt only on a green exit; `done` refuses without a
|
|
19
19
|
receipt that matches the current check, or with unticked acceptance criteria. Never edit
|
|
20
20
|
`status`, `started`, `last_check`, `verified`, or `finished` by hand — on Claude Code a hook blocks it.
|
|
21
|
+
On a migrated project (a change binding under `.prd/changes/`; the `Runtime` line of
|
|
22
|
+
`scripts/pincer-status.sh` names it) `verify` records an attempt under `.pincer/runtime/`
|
|
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/`, `.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.
|
|
21
32
|
|
|
22
33
|
## Before the loop
|
|
23
34
|
|
|
@@ -25,7 +36,34 @@ Run `scripts/pincer-status.sh`. It lists every ticket's state, what is blocked,
|
|
|
25
36
|
build time from the clock, and the next action. If a ticket is `in_progress`, you are
|
|
26
37
|
resuming: read it, check `git status` / `git diff` for uncommitted work, and continue
|
|
27
38
|
from wherever the receipt says you are. Do not ask the user to reconfirm unchanged,
|
|
28
|
-
previously authorized work.
|
|
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. Select the change to work on (`node scripts/pincer-runtime.cjs change
|
|
44
|
+
select <id>`; selection is local metadata and touches no source), activate it
|
|
45
|
+
(`change activate <id>`; refused until the user's authorization is recorded with
|
|
46
|
+
`change authorize` and no consequential decision is open) and resume a paused change
|
|
47
|
+
with `change resume <id>`. On a change with strict coverage (`Coverage strict …` in status) also read
|
|
48
|
+
`node scripts/pincer-runtime.cjs coverage` — it names the scenario, ticket, check or
|
|
49
|
+
decision that is next and every structural gap (`COVERAGE_INCOMPLETE`,
|
|
50
|
+
`SCOPE_UNAUTHORIZED`, `OBLIGATION_MISSING`) — and, after any PRD, ticket or map edit,
|
|
51
|
+
`node scripts/pincer-runtime.cjs impact` (`--from G-NN` for another baseline): it
|
|
52
|
+
lists the affected scenarios, tickets and checks with reasons and the dependency
|
|
53
|
+
dependents separately, and reports an unscoped PRD change or unavailable history
|
|
54
|
+
rather than "no impact". `legacy` and no ticket of this PRD carries legacy
|
|
55
|
+
receipts → register now (`node scripts/pincer-runtime.cjs register --prd .prd/prd-vN.md`,
|
|
56
|
+
commit `.prd/changes/` and `.gitignore` as `Register PRD vN`), then record the user's
|
|
57
|
+
approval (`change authorize …`, as `$pincer-narrow` describes), select and activate.
|
|
58
|
+
`legacy` with legacy receipts, or a v0.5.0 binding (`Runtime change <id> · revision …`)
|
|
59
|
+
→ run `node scripts/pincer-runtime.cjs migrate --preview --prd .prd/prd-vN.md`, show
|
|
60
|
+
the plan (backups, receipts imported as history, the converted binding, the
|
|
61
|
+
`.gitignore` line, the local selection) and ask once whether to apply. Apply only on
|
|
62
|
+
a yes, then commit the rewritten tickets, `.gitignore` and the record as `Migrate PRD
|
|
63
|
+
vN to the runtime`. The migrated change is planned with no authorization: record the
|
|
64
|
+
user's actual earlier instruction with `change authorize` (the v0.5.0 free text is
|
|
65
|
+
history only) and activate it. Never migrate silently, and never apply when the
|
|
66
|
+
preview reports a conflict.
|
|
29
67
|
|
|
30
68
|
## Loop (per ticket, in dependency order)
|
|
31
69
|
|
|
@@ -40,7 +78,9 @@ previously authorized work.
|
|
|
40
78
|
dispatch a subagent with a clean prompt: paste the full ticket body, the relevant
|
|
41
79
|
conventions, and nothing else.
|
|
42
80
|
3. **Verify:** `scripts/pincer-ticket.sh verify T-{NN}` — runs the Verification block and
|
|
43
|
-
writes the receipt only if it exits 0
|
|
81
|
+
writes the receipt only if it exits 0 (after migration it records an attempt with the
|
|
82
|
+
captured log under `.pincer/runtime/` and writes no receipt into the ticket; readiness
|
|
83
|
+
derives from the latest attempt and the current source). Red → fix and re-run; report the actual output,
|
|
44
84
|
not assumptions. Green output is the definition of done, not your confidence. If the
|
|
45
85
|
check only validated syntax or a build, say so — that is not behavioral proof. A
|
|
46
86
|
visual judgment is recorded separately in evaluation, not as the receipt, and a tool
|
|
@@ -58,7 +98,10 @@ previously authorized work.
|
|
|
58
98
|
- No error path leaks internals (stack traces, key names with values) to the client.
|
|
59
99
|
If the review changed code, run `verify` again — the receipt must match the code you commit.
|
|
60
100
|
5. **Close the ticket:** tick every verified acceptance-criteria checkbox (`- [ ]` → `- [x]`;
|
|
61
|
-
editing the checkboxes is allowed), then `scripts/pincer-ticket.sh done T-{NN}`.
|
|
101
|
+
editing the checkboxes is allowed), then `scripts/pincer-ticket.sh done T-{NN}`. After
|
|
102
|
+
migration `done` consumes the current passing attempt and does not re-run the check; it
|
|
103
|
+
refuses with a reason code (`SOURCE_CHANGED`, `CHECK_CHANGED`, `CHECK_FAILED`,
|
|
104
|
+
`CRITERIA_UNTICKED`, …) and the next step when the latest attempt is not current. A
|
|
62
105
|
criterion that was cut is a scope change to record in the PRD, not a box to skip.
|
|
63
106
|
Inspect `git status --short`, preserve pre-existing staged work, and stage only the
|
|
64
107
|
explicit paths changed for this ticket plus its ticket file. Review `git diff --cached`
|
|
@@ -89,20 +132,78 @@ the script or `scripts/pincer-status.sh` printed, and hand the repair to the use
|
|
|
89
132
|
performs it in their own terminal. Then return through the lifecycle — `start`,
|
|
90
133
|
`verify`, `done` — so the ticket carries fresh verification; a restored receipt is
|
|
91
134
|
never evidence. Do not recommend restoring source files or unrelated edits as routine
|
|
92
|
-
ticket repair. One exception: when the PRD is built with valid candidate evidence
|
|
135
|
+
ticket repair. One exception: when the PRD is built with valid candidate evidence;
|
|
93
136
|
tracked files other than the ticket file being restored match the evaluated candidate
|
|
94
|
-
(or the candidate plus its evidence-only commit) with nothing untracked
|
|
95
|
-
|
|
96
|
-
|
|
137
|
+
(or the candidate plus its evidence-only commit) with nothing untracked; the recorded
|
|
138
|
+
failure is explained by a working-tree change that has since been reverted (the failed
|
|
139
|
+
`last_check` was stamped while source differed from the candidate, and that difference
|
|
140
|
+
is gone); and the ticket's Verification block passes when run
|
|
141
|
+
directly rather than through `verify` (which would write a receipt), in the
|
|
142
|
+
same execution context as `verify` — the same shell, working directory, `PATH`
|
|
143
|
+
and environment, with no substituted binary and no repair made first — then
|
|
97
144
|
the committed evaluation still describes the tree. Say so, name the exact command
|
|
98
145
|
for the user to restore the ticket file in their own terminal, and
|
|
99
146
|
do not run `verify`, refresh the receipt or commit anything — the restored file is
|
|
100
147
|
what is already committed, not new evidence. If the block fails on that clean tree,
|
|
101
148
|
the failure is real: keep the failed `last_check` and repair through the lifecycle.
|
|
149
|
+
A changed executable, runner, working directory or environment repair requires a
|
|
150
|
+
new recorded verification through `verify`; the exception does not apply to it.
|
|
151
|
+
An unexplained failure cannot be cleared by restoring a receipt: when no
|
|
152
|
+
since-reverted source change explains it (a service down, a missing dependency, a
|
|
153
|
+
check that reads external data), keep the failure, name the cause you observed, and
|
|
154
|
+
ask for the environment to be repaired before `verify` runs again.
|
|
102
155
|
If source still differs from the candidate, name the differing paths and let the
|
|
103
156
|
user decide rather than asking which way to fix them; permission to restore a ticket
|
|
104
|
-
does not authorize discarding source changes.
|
|
105
|
-
|
|
157
|
+
does not authorize discarding source changes.
|
|
158
|
+
After migration (a change binding exists) recovery is the lifecycle itself: retain the
|
|
159
|
+
failure, repair the cause, run `verify` again; readiness derives from the latest attempt,
|
|
160
|
+
both attempts stay in `.pincer/runtime/` and no tracked file changes. Never restore a
|
|
161
|
+
ticket file or delete `.pincer/runtime` to obtain a green status; the legacy exception
|
|
162
|
+
above applies only before migration. A session that died mid-`verify` leaves a `running`
|
|
163
|
+
attempt: run `node scripts/pincer-runtime.cjs recover`, which finalizes it as
|
|
164
|
+
`interrupted` once the owner process is gone, then `verify` again.
|
|
165
|
+
|
|
166
|
+
## Changes: pausing, decisions and completion
|
|
167
|
+
|
|
168
|
+
- Stopping before the change is complete (end of session, switching to another
|
|
169
|
+
change): `node scripts/pincer-runtime.cjs change pause <id> --reason "<why>" --note "<handoff for the next session>"`
|
|
170
|
+
and commit the record. Pausing keeps every ticket state, attempt and authorization;
|
|
171
|
+
it refuses while a check is running (`recover` first if its owner died). A fresh
|
|
172
|
+
session runs `resume`, then `change resume <id>` under the existing authorization —
|
|
173
|
+
do not ask the user to re-approve unchanged scope. Another change's work in the
|
|
174
|
+
meantime makes this change's passing attempts `SOURCE_CHANGED`; verify again, do
|
|
175
|
+
not ask for approval again.
|
|
176
|
+
- A newly discovered consequential choice: `node scripts/pincer-runtime.cjs change decide <id> --summary "<the question>"`
|
|
177
|
+
blocks execution (`DECISION_REQUIRED`) until the user answers; record the answer with
|
|
178
|
+
`change decide <id> --resolve D-NN --reference "<where>" --excerpt "<the user's words>"`,
|
|
179
|
+
then `change authorize <id> --agreement <digest> --reference … --excerpt … --decision D-NN`.
|
|
180
|
+
A revision within the user's delegation (for example an added regression check for
|
|
181
|
+
approved behavior) records `change authorize <id> --agreement <digest> --delegated --basis A-NN --explanation "<why it stays within the delegation>"`
|
|
182
|
+
without asking again, and the changed check still needs fresh verification.
|
|
183
|
+
- Editing the PRD under its filename, or a ticket's acceptance text, dependencies,
|
|
184
|
+
size, timeout, association or check — and, with strict coverage, a scenario's text,
|
|
185
|
+
a map link, a declared command or timeout, or a scope entry — changes the agreement:
|
|
186
|
+
execution refuses with `AGREEMENT_CHANGED` (status shows the structural difference;
|
|
187
|
+
`impact` explains it) until its disposition is recorded as above. Ticking criteria, starting or closing tickets and recording
|
|
188
|
+
attempts never change it. An `AGREEMENT_CHANGED` caused by an edit this session
|
|
189
|
+
did not make — a revised PRD, an added or changed ticket found on resume — is a
|
|
190
|
+
consequential decision: raise it with `change decide <id> --summary "<what changed>"`,
|
|
191
|
+
report the structural difference (and the `impact` report) and stop. A general instruction to continue,
|
|
192
|
+
resume or not re-ask never authorizes new scope; record a `user` authorization for
|
|
193
|
+
the revised agreement only for an instruction that names the revised content. With strict coverage a scenario that will not be delivered is
|
|
194
|
+
never dropped from the map or the PRD: it is deferred or removed through a decision
|
|
195
|
+
the user resolves naming it, a `scope` entry (a removal keeps a tombstone naming the
|
|
196
|
+
prior agreement) and an authorization naming that decision; `coverage` reports
|
|
197
|
+
`OBLIGATION_MISSING` or `SCOPE_UNAUTHORIZED` until then, and `change complete`
|
|
198
|
+
refuses. A revised check declaration (a stricter command, an added check) within the
|
|
199
|
+
user's delegation is a `--delegated` authorization and needs fresh verification.
|
|
200
|
+
- When every ticket is done and ready: `node scripts/pincer-runtime.cjs change complete <id>`
|
|
201
|
+
(it refuses unfinished tickets, unticked criteria, stale or failed verification and
|
|
202
|
+
open decisions; with strict coverage also an incomplete map, an unauthorized
|
|
203
|
+
disposition or a missing obligation, before the ticket gate) and commit the record
|
|
204
|
+
as `Complete PRD vN`. Completion never asks for candidate evidence. Completed means ready
|
|
205
|
+
for evaluation, not evaluated or released; a later finding is `change reopen <id> --reason …`
|
|
206
|
+
plus a fix ticket.
|
|
106
207
|
|
|
107
208
|
## Budget rules
|
|
108
209
|
|
|
@@ -115,7 +216,8 @@ attempt history is later work (M1).
|
|
|
115
216
|
|
|
116
217
|
## When all tickets are done
|
|
117
218
|
|
|
118
|
-
|
|
219
|
+
On a project with change records, complete the change first (`change complete <id>`,
|
|
220
|
+
committed as `Complete PRD vN`). Then update the PRD to `status: built` and commit that change on its own (`PRD vN: built`).
|
|
119
221
|
The built transition is part of the candidate that `$pincer-evaluate` reviews; it is
|
|
120
222
|
never moved into a later evidence-only commit. Then finish with:
|
|
121
223
|
"All tickets built. Run `$pincer-evaluate` for a final quality pass."
|
|
@@ -127,6 +229,9 @@ material choice not already authorized, and prepare the concrete proposal before
|
|
|
127
229
|
asking. A decision the user delegated (for example "pick the architecture") does not
|
|
128
230
|
need another approval when you exercise it, but a newly discovered consequential
|
|
129
231
|
choice is surfaced before implementation. Record the authorization basis and the
|
|
130
|
-
scope it covers in the PRD or the handover
|
|
232
|
+
scope it covers in the PRD or the handover, and on a project with change records as
|
|
233
|
+
a `change authorize` record (the user's words as the excerpt, or a `--delegated`
|
|
234
|
+
disposition with its basis). An agent-written record or a status
|
|
131
235
|
field is not authenticated human approval. When resuming without the context that
|
|
132
|
-
granted authorization, do not invent it —
|
|
236
|
+
granted authorization, do not invent it — read the `resume` report; an authorization
|
|
237
|
+
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
|
|
25
|
-
|
|
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.
|
|
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;
|
|
@@ -64,7 +72,41 @@ run the pipeline, then present results.
|
|
|
64
72
|
material decision; never make an ad-hoc `review: fixes` commit. Every fix commit
|
|
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
|
-
9. Persist evidence for the candidate under `.prd/evidence/prd-vN/<candidate
|
|
75
|
+
9. Persist evidence for the candidate under `.prd/evidence/prd-vN/<candidate>/`.
|
|
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 —
|
|
90
|
+
`node scripts/pincer-runtime.cjs check C-NN --candidate <sha> -- <command>` (one
|
|
91
|
+
command per check, the command line as run; `npm test` stays one aggregate check) —
|
|
92
|
+
then write the authored fields to a draft outside the evidence directory, for
|
|
93
|
+
example `.pincer/drafts/<sha>.json`: `environment.tools` and `environment.limitations`,
|
|
94
|
+
`coverage_review`, `requirements`, review and visual checks with their saved
|
|
95
|
+
artifacts, `visual_review`, and a stub `{"id": "C-NN", "kind": "command",
|
|
96
|
+
"required": true|false}` for each executable check. Then run
|
|
97
|
+
`node scripts/pincer-runtime.cjs evidence export --candidate <sha> --base <base> --prd .prd/prd-vN.md --draft <file>`.
|
|
98
|
+
The export writes `checks/C-NN.log` from the captured logs, fills `command`,
|
|
99
|
+
`result`, `provenance: runtime` and `attempt` from the attempts, labels review and
|
|
100
|
+
visual checks `provenance: authored`, computes the digests and writes an evidence
|
|
101
|
+
schema 2 manifest; it refuses a dirty tree, a HEAD that is not the candidate, a stub
|
|
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
|
|
108
|
+
`result: unverified` and a note, as before. Legacy project (no change binding):
|
|
109
|
+
author the schema 1 manifest as follows.
|
|
68
110
|
- `checks/C-NN.log` — the command and a redacted summary or safe log of each
|
|
69
111
|
executable check. Never secrets, never an environment dump. Record
|
|
70
112
|
one check per command: `command` holds the command line as run, never prose
|
|
@@ -104,11 +146,13 @@ run the pipeline, then present results.
|
|
|
104
146
|
evidence: .prd/evidence/prd-vN/<candidate>/manifest.json
|
|
105
147
|
---
|
|
106
148
|
```
|
|
107
|
-
Then commit NOTES.md, the manifest
|
|
149
|
+
Then commit NOTES.md, the manifest, its listed artifacts and (change records) the
|
|
150
|
+
evaluation locator — and nothing else —
|
|
108
151
|
as `evaluate: PRD vN candidate <short sha>`. Status accepts this later commit only
|
|
109
|
-
when its diff from the candidate is limited to `NOTES.md
|
|
110
|
-
|
|
111
|
-
|
|
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
|
|
112
156
|
do not establish readiness. Then describe what was built, what was cut
|
|
113
157
|
and why, known issues, and what you'd do next with more time. Then a **Handover**
|
|
114
158
|
section, written for the stranger who inherits this repo in six months: how to get
|
|
@@ -126,6 +170,9 @@ material choice not already authorized, and prepare the concrete proposal before
|
|
|
126
170
|
asking. A decision the user delegated (for example "pick the architecture") does not
|
|
127
171
|
need another approval when you exercise it, but a newly discovered consequential
|
|
128
172
|
choice is surfaced before implementation. Record the authorization basis and the
|
|
129
|
-
scope it covers in the PRD or the handover
|
|
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
|
|
130
176
|
field is not authenticated human approval. When resuming without the context that
|
|
131
|
-
granted authorization, do not invent it —
|
|
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,14 +34,25 @@ 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
|
|
39
|
-
Objective. Resolve missing coverage and conflicting criteria with
|
|
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`): one `scenarios` row per `S-NN` naming its
|
|
43
|
+
implementing tickets and declared checks, every ticket of the change in
|
|
44
|
+
`tickets` as `implements` or `enables` (with a rationale), each check declared
|
|
45
|
+
once in `checks` with its kind, `required` flag and, for a command, the exact
|
|
46
|
+
command line and timeout, and a `scope` entry (`deferred` or `removed`) for a
|
|
47
|
+
scenario this change will not deliver, naming the decision that records the
|
|
48
|
+
user's choice. The map is authored work you edit by hand; the runtime never
|
|
49
|
+
rewrites it, and it validates it against the PRD's definitions.
|
|
41
50
|
- Every ticket gets a runnable command in its Verification block — a fenced `bash`
|
|
42
51
|
block that exits 0 only when the ticket is done. `scripts/pincer-ticket.sh verify`
|
|
43
52
|
runs it verbatim and stamps the receipt that `done` requires, so it must be
|
|
44
|
-
non-interactive and self-contained (no "check by hand").
|
|
53
|
+
non-interactive and self-contained (no "check by hand"). An optional
|
|
54
|
+
`timeout: <seconds>` frontmatter field (default 600) bounds the run; it is part of
|
|
55
|
+
the check identity, so changing it invalidates earlier passes.
|
|
45
56
|
- Each Verification section opens with `Proves:` — what the check establishes and
|
|
46
57
|
which regression it detects. A check for an executable change must exercise
|
|
47
58
|
observable behavior (including relevant rejection paths and, in brownfield work,
|
|
@@ -83,7 +94,33 @@ existing authorization for the same scope and order.
|
|
|
83
94
|
inspect existing staged changes, stage that PRD and the explicit new ticket paths,
|
|
84
95
|
review `git diff --cached`, and commit only those paths. Ask first — and finalize
|
|
85
96
|
once it is resolved — only when step 4 surfaced a newly discovered consequential
|
|
86
|
-
choice or a scope change the PRD does not cover.
|
|
97
|
+
choice or a scope change the PRD does not cover. Then register the change when the
|
|
98
|
+
`Runtime` status line says `legacy` and no ticket of this PRD carries legacy
|
|
99
|
+
receipts, or `changes` (the project already keeps change records):
|
|
100
|
+
`node scripts/pincer-runtime.cjs register --prd .prd/prd-vN.md` writes the change
|
|
101
|
+
record `.prd/changes/prd-vN.json` (retaining every earlier change); stage
|
|
102
|
+
`.prd/changes/` and `.gitignore` (registration adds `.pincer/` to it) and commit them
|
|
103
|
+
as `Register PRD vN`. Then record the user's actual approval against the agreement
|
|
104
|
+
the record binds — `node scripts/pincer-runtime.cjs change show prd-vN --json`
|
|
105
|
+
prints the agreement digest — with
|
|
106
|
+
`node scripts/pincer-runtime.cjs change authorize prd-vN --agreement <digest> --reference "<where the user said it>" --excerpt "<the user's approval, quoted>"`,
|
|
107
|
+
select it for this worktree (`node scripts/pincer-runtime.cjs change select prd-vN`)
|
|
108
|
+
and commit `.prd/changes/` as `Authorize PRD vN`. When the map was authored, adopt
|
|
109
|
+
strict coverage explicitly: `node scripts/pincer-runtime.cjs coverage adopt --preview --change prd-vN`
|
|
110
|
+
shows the inventory, the map digest and the agreement it records (it refuses an
|
|
111
|
+
incomplete map, naming the scenario or ticket); `--apply` writes the schema 3
|
|
112
|
+
record with a backup and grants nothing — record the user's approval of that
|
|
113
|
+
agreement with `change authorize` (the same instruction, if it named this
|
|
114
|
+
breakdown; a delegated disposition needs its basis) and commit `.prd/coverage/`
|
|
115
|
+
and `.prd/changes/` as `Adopt strict coverage for PRD vN`. A scenario the user
|
|
116
|
+
deferred or removed is a decision: `change decide --summary "<the choice>"`,
|
|
117
|
+
`--resolve D-NN` with the user's words naming the scenario, the `scope` entry in
|
|
118
|
+
the map, then `change authorize … --decision D-NN`. Never record a disposition
|
|
119
|
+
the user did not state; `coverage` reports `SCOPE_UNAUTHORIZED` until it is. The excerpt records the user's own
|
|
120
|
+
words; running the command proves nothing by itself, and a registration, a PRD
|
|
121
|
+
status or a passing check never becomes an authorization. A project whose tickets
|
|
122
|
+
carry legacy receipts, or that still holds a v0.5.0 binding (`Runtime change <id> ·
|
|
123
|
+
revision …`), is migrated from `$pincer-code` after a preview, never here. Finish with:
|
|
87
124
|
"Tickets ready in `tickets/`. Run `$pincer-code` to start implementing."
|
|
88
125
|
|
|
89
126
|
## Authorization rule (shared by plan, narrow, code and evaluate)
|
|
@@ -93,6 +130,9 @@ material choice not already authorized, and prepare the concrete proposal before
|
|
|
93
130
|
asking. A decision the user delegated (for example "pick the architecture") does not
|
|
94
131
|
need another approval when you exercise it, but a newly discovered consequential
|
|
95
132
|
choice is surfaced before implementation. Record the authorization basis and the
|
|
96
|
-
scope it covers in the PRD or the handover
|
|
133
|
+
scope it covers in the PRD or the handover, and on a project with change records as
|
|
134
|
+
a `change authorize` record (the user's words as the excerpt, or a `--delegated`
|
|
135
|
+
disposition with its basis). An agent-written record or a status
|
|
97
136
|
field is not authenticated human approval. When resuming without the context that
|
|
98
|
-
granted authorization, do not invent it —
|
|
137
|
+
granted authorization, do not invent it — read the `resume` report; an authorization
|
|
138
|
+
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
|
|
97
|
-
|
|
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
|
|
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 —
|
|
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.
|