pincer-workflow 0.2.3 → 0.4.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 (35) hide show
  1. package/README.md +19 -14
  2. package/bin/pincer.js +47 -11
  3. package/package.json +2 -2
  4. package/template/.agents/skills/pincer-code/SKILL.md +62 -17
  5. package/template/.agents/skills/pincer-evaluate/SKILL.md +85 -15
  6. package/template/.agents/skills/pincer-narrow/SKILL.md +67 -22
  7. package/template/.agents/skills/pincer-plan/SKILL.md +62 -25
  8. package/template/.agents/skills/pincer-release/SKILL.md +31 -12
  9. package/template/.agents/skills/pincer-status/SKILL.md +5 -3
  10. package/template/.claude/commands/pincer-code.md +61 -16
  11. package/template/.claude/commands/pincer-evaluate.md +85 -15
  12. package/template/.claude/commands/pincer-narrow.md +65 -20
  13. package/template/.claude/commands/pincer-plan.md +57 -20
  14. package/template/.claude/commands/pincer-release.md +30 -11
  15. package/template/.claude/commands/pincer-status.md +5 -3
  16. package/template/.claude/hooks/block-dangerous.sh +7 -18
  17. package/template/.claude/hooks/hook-policy.cjs +351 -0
  18. package/template/.claude/hooks/ticket-guard.sh +6 -63
  19. package/template/.claude/references/prd-template.md +41 -9
  20. package/template/.claude/references/ticket-template.md +37 -4
  21. package/template/.codex/README.md +4 -4
  22. package/template/.github/prompts/pincer-code.prompt.md +61 -16
  23. package/template/.github/prompts/pincer-evaluate.prompt.md +85 -15
  24. package/template/.github/prompts/pincer-narrow.prompt.md +65 -20
  25. package/template/.github/prompts/pincer-plan.prompt.md +57 -20
  26. package/template/.github/prompts/pincer-release.prompt.md +30 -11
  27. package/template/.github/prompts/pincer-status.prompt.md +5 -3
  28. package/template/AGENTS.md +11 -5
  29. package/template/docs/dry-run-checklist.md +143 -27
  30. package/template/docs/release-checklist.md +35 -0
  31. package/template/scripts/pincer-evidence.cjs +292 -0
  32. package/template/scripts/pincer-status.sh +83 -26
  33. package/template/scripts/pincer-ticket-lib.sh +321 -0
  34. package/template/scripts/pincer-ticket.sh +58 -47
  35. package/template/scripts/sync-prompts.sh +6 -1
@@ -1,66 +1,9 @@
1
1
  #!/bin/bash
2
- # PreToolUse guard for ticket state. A ticket's state fields — status
3
- # (in_progress / done), started, verified, finished are written only by
4
- # scripts/pincer-ticket.sh, whose `done` needs a passing verification receipt.
5
- # This hook makes that script the only door on Claude Code: editing tools may
6
- # not write those fields into tickets/T-*.md, and Bash may not sed/echo them in.
7
- # Creating a ticket with `status: open` and ticking acceptance boxes stay allowed.
8
- # Exit 2 blocks the tool call; stderr goes back to the agent.
9
- #
10
- # A guard against carelessness, not an adversary: the agent could still route
11
- # around it, but it can no longer do so by accident or habit.
12
-
13
- input=$(cat)
14
-
15
- field() { # dotted path into the hook JSON, e.g. tool_input.file_path
16
- if command -v jq >/dev/null 2>&1; then
17
- printf '%s' "$input" | jq -r ".$1 // empty" 2>/dev/null
18
- elif command -v python3 >/dev/null 2>&1; then
19
- printf '%s' "$input" | python3 -c '
20
- import json, sys
21
- d = json.load(sys.stdin)
22
- for k in sys.argv[1].split("."):
23
- d = d.get(k, "") if isinstance(d, dict) else ""
24
- print(d if isinstance(d, str) else json.dumps(d))' "$1" 2>/dev/null
25
- else # crude fallback: last path segment, first match, no unescaping
26
- printf '%s' "$input" | grep -oE "\"${1##*.}\"[[:space:]]*:[[:space:]]*\"([^\"\\\\]|\\\\.)*\"" | head -1 | sed -E 's/^"[^"]*"[[:space:]]*:[[:space:]]*"//; s/"$//'
27
- fi
28
- }
29
-
30
- tool=$(field tool_name)
31
- # `status: open` is fine; these are the fields only the script may write.
32
- PROTECTED='(^|\\n|[[:space:]])(status:[[:space:]]*(in_progress|done)|started:|verified:|finished:)'
33
- TICKET='(^|/)tickets/T-[0-9]+[^/]*\.md$'
34
-
35
- block() {
36
- echo "Blocked by PINCER ticket guard: $1 Use pincer-ticket.sh (path in the /pincer-code playbook): 'verify T-NN' writes the receipt when the check passes, 'done T-NN' flips the status. Ticking acceptance boxes and editing the body are fine." >&2
2
+ # PreToolUse guard for ticket lifecycle fields. The Node helper parses JSON,
3
+ # compares existing and proposed frontmatter for editing tools, and permits only
4
+ # exact pincer-ticket.sh lifecycle calls as shell writers.
5
+ command -v node >/dev/null 2>&1 || {
6
+ echo 'Blocked by PINCER ticket guard: Node.js is required to parse hook input safely.' >&2
37
7
  exit 2
38
8
  }
39
-
40
- case "$tool" in
41
- Edit|Write|MultiEdit)
42
- file=$(field tool_input.file_path)
43
- printf '%s' "$file" | grep -qE "$TICKET" || exit 0
44
- case "$tool" in
45
- Edit) new=$(field tool_input.new_string) ;;
46
- Write) new=$(field tool_input.content) ;;
47
- *) new=$(field tool_input.edits) ;;
48
- esac
49
- [ -n "$new" ] || new=$input
50
- if printf '%s' "$new" | grep -qE "$PROTECTED"; then
51
- block "ticket state fields (status in_progress/done, started, verified, finished) are never written by hand."
52
- fi
53
- ;;
54
- Bash)
55
- cmd=$(field tool_input.command)
56
- [ -n "$cmd" ] || cmd=$input
57
- printf '%s' "$cmd" | grep -q 'pincer-ticket.sh' && exit 0
58
- if printf '%s' "$cmd" | grep -qE 'tickets/|T-[0-9][0-9]' &&
59
- printf '%s' "$cmd" | grep -qE 'status:[[:space:]]*(in_progress|done)|started:|verified:|finished:' &&
60
- printf '%s' "$cmd" | grep -qE '(sed|perl)[[:space:]]+(-[a-zA-Z]*i|-i)|>|tee[[:space:]]|python|node|ruby'; then
61
- block "that command writes ticket state fields from the shell."
62
- fi
63
- ;;
64
- esac
65
-
66
- exit 0
9
+ exec node "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/hook-policy.cjs" ticket
@@ -1,17 +1,33 @@
1
1
  # PRD Template
2
2
 
3
- Used by `/pincer-plan` Phase 4. Core sections always included; optional sections only when they
4
- earn their space in the timebox. Keep the whole PRD under ~2 pages.
3
+ Used by `/pincer-plan` Phase 4. Core sections are always included. Add optional detail
4
+ when uncertainty, product context, or risk warrants it; a small fix may remain compact.
5
+
6
+ ## Profile
7
+
8
+ The frontmatter field `profile: small | standard` sets the planning weight; a PRD
9
+ without it is `standard`. `small` means bounded scope, low risk, known behavior and
10
+ straightforward verification. Few changed lines alone do not qualify: migrations,
11
+ authorization boundaries, uncertain requirements and broad effects stay `standard`
12
+ even for a tiny patch. The PRD records in one or two sentences why the profile fits.
13
+
14
+ A small PRD keeps Problem (with the outcome), Scope, Requirements with scenarios,
15
+ Success Criteria (its verification), risks and exclusions, and omits empty sections
16
+ and repetition. Interface examples may clarify a contract; implementation code must
17
+ not substitute for requirements in any profile.
5
18
 
6
19
  ---
7
20
 
8
21
  ## Core Sections (always include)
9
22
 
10
23
  ### 1. Problem
11
- What problem does this solve? Who has it? (2–4 sentences.)
24
+ What problem does this solve? Who has it? (2–4 sentences.) Preserve or link the
25
+ original brief (quote it in an appendix or name where it lives) so the source of
26
+ every requirement stays reviewable.
12
27
 
13
28
  ### 2. Solution
14
- One-paragraph summary of what we're building.
29
+ One-paragraph summary of what we're building: the desired outcome, the assumptions
30
+ it rests on, and what it deliberately excludes.
15
31
 
16
32
  ### 3. Scope
17
33
 
@@ -19,7 +35,22 @@ One-paragraph summary of what we're building.
19
35
  | --- | --- |
20
36
  | ... | ... |
21
37
 
22
- ### 4. Architecture
38
+ ### 4. Requirements
39
+ One entry per requirement with a stable ID. IDs are assigned once within this PRD
40
+ and never renumbered: a revision keeps existing IDs and adds new ones. Tickets
41
+ name the IDs they implement and evaluation dispositions every ID.
42
+
43
+ #### R-01 — short title
44
+ - Scenario: an observable acceptance scenario (given / when / then, or a command
45
+ and its expected output). Add one line per scenario.
46
+ - Failure path: what invalid input or the relevant failure produces.
47
+ - Preserve: existing behavior this must not change (brownfield).
48
+
49
+ When the user supplied a PRD, keep its meaning and its existing requirement IDs.
50
+ If its structure needs adapting to this template, add a `Requirement mapping`
51
+ table under this section (`their section or ID → R-NN`) instead of rewriting it.
52
+
53
+ ### 5. Architecture
23
54
 
24
55
  #### Structure
25
56
  ```
@@ -32,13 +63,13 @@ What each component does, owns, and depends on.
32
63
  #### Data flow
33
64
  Input → processing → output.
34
65
 
35
- ### 5. Success Criteria
66
+ ### 6. Success Criteria
36
67
 
37
68
  | Criterion | How to verify |
38
69
  | --- | --- |
39
70
  | ... | a command to run or a thing to observe |
40
71
 
41
- ### 6. Out of Scope
72
+ ### 7. Out of Scope
42
73
  Explicit list. Anything cut for time during `/pincer-code` gets appended here with a reason.
43
74
 
44
75
  ---
@@ -56,13 +87,14 @@ and where they live (server-side only, named in `.env.example`), and what the cl
56
87
  sees on failure (generic message — details stay in server logs).
57
88
 
58
89
  ### Dependencies & Risks
59
- Only if something outside our control could sink the timebox.
90
+ Include when something outside our control or a migration/rollback concern could sink delivery.
60
91
 
61
92
  ---
62
93
 
63
94
  ## Formatting Rules
64
95
 
65
- - Save as `.prd/prd-v{N}.md` with YAML frontmatter (`version`, `status`, `date`).
96
+ - Save as `.prd/prd-v{N}.md` with YAML frontmatter (`version`, `status`, `date`,
97
+ and `profile` when small).
66
98
  - Status lifecycle: `draft → ticketed → built`.
67
99
  - Diagrams as ASCII or markdown tables only.
68
100
  - No implementation code and no exact line numbers — those belong in tickets.
@@ -6,7 +6,8 @@ Used by `/pincer-narrow` for every file in `tickets/`. Filename: `T-{NN}-{slug}.
6
6
  ---
7
7
  ticket: T-{NN}
8
8
  status: open # open | in_progress | done
9
- size: S # S (≤15 min) | M (≤30 min)
9
+ size: S # S | M | L, relative scope; split when it improves verification
10
+ prd: .prd/prd-v{N}.md # the selected PRD, never inferred from ticket numbering
10
11
  depends_on: [] # e.g. [T-01]
11
12
  ---
12
13
 
@@ -16,6 +17,8 @@ One sentence: what to build and why.
16
17
  ## Context
17
18
  - Relevant files: `src/path/to/file.ts` (what's there / what to follow)
18
19
  - PRD section: which part of the PRD this implements
20
+ - Implements: R-01, R-03 (requirement IDs from the PRD; enabling work that
21
+ implements no requirement states its purpose in the Objective instead)
19
22
 
20
23
  ## Requirements
21
24
  - Concrete, checkable requirements. No vague "handle errors properly" —
@@ -26,6 +29,7 @@ One sentence: what to build and why.
26
29
  - [ ] Observable behavior 2
27
30
 
28
31
  ## Verification
32
+ Proves: one line — what this check establishes and which regression it detects.
29
33
  ```bash
30
34
  # command(s) the builder runs to prove the criteria — tests, build, curl, etc.
31
35
  ```
@@ -35,15 +39,44 @@ One sentence: what to build and why.
35
39
  ```
36
40
 
37
41
  Rules:
38
- - `status` and the stamps `started`, `verified`, `finished` are written only by
42
+ - New tickets always name their PRD with `prd: .prd/prd-vN.md`. The file must
43
+ have matching version metadata and status `ticketed` or `built` before work
44
+ starts. This status is a workflow precondition, not proof of user approval.
45
+ Legacy tickets with one PRD are associated on start; with multiple PRDs, use
46
+ `scripts/pincer-ticket.sh bind T-NN .prd/prd-vN.md` to resolve explicitly.
47
+ - Supported syntax is deliberately limited: closed `---` frontmatter with unique,
48
+ unindented `key: value` fields; required `ticket`, `status`, `size`, and
49
+ `depends_on`. IDs use `T-01` through `T-999999` and match the filename; dependencies
50
+ use an inline list such as `[T-01, T-02]`, without duplicates or self references.
51
+ - Use exactly one `## Acceptance Criteria` section with nonempty checkboxes.
52
+ Indentation and `-`, `+`, `*`, or numbered list markers are supported, with
53
+ `[ ]`, `[x]`, or `[X]`. Every unchecked criterion blocks completion.
54
+ - Use exactly one `## Verification` section containing one closed fenced `bash`
55
+ block with runnable commands. Missing sections, malformed metadata, duplicate
56
+ ticket IDs, unsupported checkbox syntax, and invalid Bash fail before a transition.
57
+ - `status` and the attempt/stamp fields `started`, `last_check`, `verified`, `finished` are written only by
39
58
  `scripts/pincer-ticket.sh` (`start` / `verify` / `done`). `verify` runs the
40
59
  Verification block verbatim and writes a receipt only on exit 0; `done`
41
60
  requires that receipt to match the current block. Never write these by hand.
42
61
  - The Verification block is a fenced `bash` block that exits 0 only when the
43
62
  ticket is done — non-interactive, no "check by hand".
63
+ - The Verification section opens with a one-line `Proves:` statement: what the
64
+ check establishes and which regression it detects. Executable changes need
65
+ checks that exercise observable behavior — including relevant rejection paths
66
+ and, in brownfield work, preservation of existing behavior. Reuse adequate
67
+ focused tests rather than inventing ad-hoc commands. A build, a syntax check, or
68
+ an identifier grep alone does not prove a feature works: the check must fail
69
+ when the behavior is wrong, not only when a name is renamed. Static assertions
70
+ may be primary evidence for static contracts (generated files, adapter wording)
71
+ when `Proves:` explains that fit.
72
+ - Manual visual judgment is recorded separately during evaluation, never as the
73
+ Verification command. When a tool the check needs is unavailable, the result is
74
+ an explicit `unverified`, never fabricated output or a silent waiver.
44
75
  - Every ticket must be verifiable without human judgment where possible.
45
76
  - If the ticket's surface accepts external input (HTTP, form, file, LLM output),
46
77
  Requirements must state the validation and the rejection behavior, and
47
78
  Acceptance Criteria must include the reject path as an observable behavior.
48
- - Ticket T-01 is the walking skeleton: scaffold + thin end-to-end slice that runs.
49
- - If a ticket needs more than ~30 minutes, split it before writing it.
79
+ - Use a walking skeleton for greenfield work when it reduces integration risk. In
80
+ brownfield work, protect the smallest useful vertical change and characterize
81
+ uncovered load-bearing behavior before modifying it.
82
+ - Split a ticket when it contains separate dependencies, owners, or verification paths.
@@ -28,8 +28,8 @@ commit the result.
28
28
 
29
29
  ## Recommended posture (`~/.codex/config.toml`)
30
30
 
31
- Codex has no PreToolUse hooks, so PINCER's guardrail posture is expressed
32
- through the sandbox and approval policy instead:
31
+ This kit does not currently install a Codex hook adapter. Use Codex's sandbox,
32
+ approval policy, and project instructions as the guardrail posture:
33
33
 
34
34
  ```toml
35
35
  approval_policy = "on-request" # agent asks before escalating
@@ -38,8 +38,8 @@ sandbox_mode = "workspace-write" # writes confined to the repo; no network by
38
38
 
39
39
  The ticket scripts are plain bash and work here unchanged:
40
40
  `scripts/pincer-ticket.sh start|verify|done T-NN` and `scripts/pincer-status.sh`.
41
- What Codex lacks is the hook that stops an agent hand-editing ticket state, so the
42
- rule in `AGENTS.md` carries that weight; `$pincer-status` warns about any ticket
41
+ Without a Pincer Codex hook adapter, the rule in `AGENTS.md` carries the weight
42
+ of stopping hand-edited ticket state; `$pincer-status` warns about any ticket
43
43
  marked done without a receipt.
44
44
 
45
45
  Never run with approvals disabled. The destructive-command rule in `AGENTS.md`
@@ -7,8 +7,9 @@ description: "Implement tickets sequentially with verification and one commit pe
7
7
 
8
8
  # /pincer-code — Ticket Implementation
9
9
 
10
- You are implementing the tickets in `tickets/` sequentially. Mostly autonomous: after the
11
- user confirms the starting point, run continuously and report progress between tickets.
10
+ You are implementing the tickets in `tickets/` sequentially. The approved PRD, ticket
11
+ breakdown, and existing session authorization define the work; run continuously and report
12
+ progress between tickets unless a material scope or design decision appears.
12
13
 
13
14
  **Initial request:** ${input:request:Task brief or arguments (optional)}
14
15
 
@@ -16,14 +17,15 @@ Ticket state lives in the ticket file's frontmatter and is written **only** by
16
17
  `scripts/pincer-ticket.sh` (`start` → `verify` → `done`). `verify` runs the ticket's
17
18
  Verification block and stamps a receipt only on a green exit; `done` refuses without a
18
19
  receipt that matches the current check, or with unticked acceptance criteria. Never edit
19
- `status`, `started`, `verified`, or `finished` by hand — on Claude Code a hook blocks it.
20
+ `status`, `started`, `last_check`, `verified`, or `finished` by hand — on Claude Code a hook blocks it.
20
21
 
21
22
  ## Before the loop
22
23
 
23
24
  Run `scripts/pincer-status.sh`. It lists every ticket's state, what is blocked, elapsed
24
25
  build time from the clock, and the next action. If a ticket is `in_progress`, you are
25
26
  resuming: read it, check `git status` / `git diff` for uncommitted work, and continue
26
- from wherever the receipt says you are. Confirm the starting point with the user, then go.
27
+ from wherever the receipt says you are. Do not ask the user to reconfirm unchanged,
28
+ previously authorized work.
27
29
 
28
30
  ## Loop (per ticket, in dependency order)
29
31
 
@@ -39,14 +41,17 @@ from wherever the receipt says you are. Confirm the starting point with the user
39
41
  conventions, and nothing else.
40
42
  3. **Verify:** `scripts/pincer-ticket.sh verify T-{NN}` — runs the Verification block and
41
43
  writes the receipt only if it exits 0. Red → fix and re-run; report the actual output,
42
- not assumptions. Green output is the definition of done, not your confidence.
44
+ not assumptions. Green output is the definition of done, not your confidence. If the
45
+ check only validated syntax or a build, say so — that is not behavioral proof. A
46
+ visual judgment is recorded separately in evaluation, not as the receipt, and a tool
47
+ the check needs but cannot run yields an explicit `unverified` result, never
48
+ fabricated output.
43
49
  4. **Self-review the diff** before committing: silent failures (empty catches,
44
50
  un-awaited promises), leftover debug code, drift from the ticket's acceptance criteria.
45
51
  Then a security sweep of the same diff:
46
- - No secret values: run
47
- `git diff | grep -iE '(api[_-]?key|secret|token|password)[[:space:]]*[:=]'`
48
- and treat any hit that isn't a `process.env` reference or a name in
49
- `.env.example` as a blocker.
52
+ - Check for secret-like assignments without printing values. If a scanner reports a
53
+ possible secret, report only its file and line until the value is safely redacted;
54
+ environment references and names in `.env.example` are allowed.
50
55
  - External input touched by this diff is validated server-side, and untrusted
51
56
  content (user input, LLM output) is escaped where rendered — per the
52
57
  Security defaults in `AGENTS.md`.
@@ -55,14 +60,41 @@ from wherever the receipt says you are. Confirm the starting point with the user
55
60
  5. **Close the ticket:** tick every verified acceptance-criteria checkbox (`- [ ]` → `- [x]`;
56
61
  editing the checkboxes is allowed), then `scripts/pincer-ticket.sh done T-{NN}`. A
57
62
  criterion that was cut is a scope change to record in the PRD, not a box to skip.
58
- Commit code and ticket file together: `git add -A && git commit -m "T-{NN}: {title}"`.
59
- 6. Give a one-line progress update using the elapsed figure from
60
- `scripts/pincer-status.sh` ("T-02 done, 3 remaining, 38m elapsed of 75m") and continue.
63
+ Inspect `git status --short`, preserve pre-existing staged work, and stage only the
64
+ explicit paths changed for this ticket plus its ticket file. Review `git diff --cached`
65
+ before committing as `T-{NN}: {title}`.
66
+ 6. Give a one-line progress update ("T-02 done, 3 remaining") and continue. Quote the
67
+ wall-clock elapsed figure from `scripts/pincer-status.sh` when it shows one — it
68
+ appears while a ticket is in progress or a budget is set, and it is not a measure
69
+ of active execution time.
61
70
 
62
- ## Timebox rules
71
+ ## Recovering a ticket file
63
72
 
64
- - The budget is ~75 minutes of build time, measured by `scripts/pincer-status.sh` from
65
- the first ticket's start stamp never estimated. If the remaining tickets won't fit,
73
+ Ticket lifecycle fields are written only by `scripts/pincer-ticket.sh`, and the guard
74
+ also blocks shell restores that would touch ticket files from the assistant's shell:
75
+ `git checkout`/`git restore`/`git switch` naming a ticket path or a normalized
76
+ pathspec that cannot be shown to stay outside `tickets/` (the whole tree, `.`, `:/`,
77
+ `:(top)`, globs, absolute or unexpanded paths, `tickets/…` in any spelling, a
78
+ `-C tickets` prefix), force flags (`-f`, `--force`, `--discard-changes`,
79
+ `--pathspec-from-file`), `git reset --hard|--merge|--keep`, `git stash` (except
80
+ `list`, `show`, `create`, `store`), `git clean -f` without a narrow pathspec,
81
+ `git checkout-index -a` and `git read-tree -u|--reset`, including when wrapped in
82
+ `bash -c`, `eval`, `nice`, `time`, `nohup`, `timeout` or `xargs`. Restoring HEAD
83
+ would erase a newer failed attempt and revive an old passing receipt. Branch
84
+ switches and file-specific restores outside `tickets/` stay allowed. The guard is a
85
+ pattern-based safety net for documented mistake forms, not a complete shell
86
+ boundary; the receipt and status checks remain the source of trust. When a ticket file is malformed or its state was hand
87
+ edited, preserve the malformed contents as they are, report the validation error that
88
+ the script or `scripts/pincer-status.sh` printed, and hand the repair to the user, who
89
+ performs it in their own terminal. Then return through the lifecycle — `start`,
90
+ `verify`, `done` — so the ticket carries fresh verification; a restored receipt is
91
+ never evidence. Do not recommend restoring source files or unrelated edits as routine
92
+ ticket repair. Automated recovery that preserves attempt history is later work (M1).
93
+
94
+ ## Budget rules
95
+
96
+ - If the user set `PINCER_BUILD_BUDGET_MIN` or stated another budget, use the elapsed
97
+ figure from `scripts/pincer-status.sh` rather than estimating. If the remaining tickets won't fit,
66
98
  stop and propose a scope cut: which remaining tickets to drop or shrink. Cutting scope
67
99
  deliberately beats an unfinished mess — record the cut in the PRD's Out of Scope.
68
100
  - If a ticket reveals the plan was wrong, stop and say so rather than silently diverging.
@@ -70,5 +102,18 @@ from wherever the receipt says you are. Confirm the starting point with the user
70
102
 
71
103
  ## When all tickets are done
72
104
 
73
- Update the PRD to `status: built`, then finish with:
105
+ Update the PRD to `status: built` and commit that change on its own (`PRD vN: built`).
106
+ The built transition is part of the candidate that `/pincer-evaluate` reviews; it is
107
+ never moved into a later evidence-only commit. Then finish with:
74
108
  "All tickets built. Run `/pincer-evaluate` for a final quality pass."
109
+
110
+ ## Authorization rule (shared by plan, narrow, code and evaluate)
111
+
112
+ Reuse explicit authorization for the same scope and decisions; ask only about a
113
+ material choice not already authorized, and prepare the concrete proposal before
114
+ asking. A decision the user delegated (for example "pick the architecture") does not
115
+ need another approval when you exercise it, but a newly discovered consequential
116
+ choice is surfaced before implementation. Record the authorization basis and the
117
+ scope it covers in the PRD or the handover. An agent-written record or a status
118
+ field is not authenticated human approval. When resuming without the context that
119
+ granted authorization, do not invent it — ask.
@@ -12,23 +12,42 @@ run the pipeline, then present results.
12
12
 
13
13
  ## Steps
14
14
 
15
- 1. Run `scripts/pincer-status.sh`. Every ticket should be `done` with a receipt; if one
15
+ 1. Run `scripts/pincer-status.sh`. Review only tickets associated with the selected
16
+ PRD. Every such ticket should be `done` with a current receipt; if one
16
17
  is still open or in progress, stop and ask whether it was cut (then it goes in the
17
18
  PRD's Out of Scope) or should be finished first via `/pincer-code`. Then get the full
18
- diff of the session: `git log --oneline` and `git diff <first-commit>..HEAD`.
19
+ diff of the change: identify the actual base commit before this change from
20
+ its ticket commits and recorded context. If it cannot be established, resolve
21
+ that uncertainty before claiming a complete review. Record full commit IDs for
22
+ `base` and `candidate` (`git rev-parse HEAD`), then review `git diff <base>..<candidate>`.
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
26
+ to `/pincer-code`; do not review a dirty tree.
19
27
  2. Dispatch a `code-quality-reviewer` agent with: the diff, the PRD's Success Criteria and
20
28
  Scope sections, and the list of tickets. If the diff is large, split by area and
21
29
  dispatch two in parallel. (No subagents on this platform? Review the diff yourself
22
30
  in a separate pass, applying `.claude/agents/code-quality-reviewer.md` as the rubric.)
23
- 3. Yourself, in parallel, check spec compliance: does what was built match every ticket's
24
- acceptance criteria and the PRD scope? List any gaps.
31
+ Keep the reviewer's report or its explicit no-findings statement for step 9,
32
+ 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
34
+ PRD record one disposition: `delivered` (evidence on this candidate), `blocked`
35
+ (required behavior failed or was left unverified — this blocks PASS; do not relabel
36
+ it a known limitation to pass), or `deferred` (only with explicit user authorization;
37
+ record the scope decision in the PRD's Out of Scope and evaluate the revised
38
+ candidate). Compare what was built against every ticket's acceptance criteria and
39
+ the PRD scope, and list any gaps. Whether the requirement map is complete and each
40
+ check is semantically adequate is your judgment as reviewer — record that judgment
41
+ in the evaluation; the kit is not a mechanical traceability engine and does not
42
+ validate requirement-revision impact.
25
43
  4. If the project has a UI, look at it — don't only read the code. Start it, open it in
26
44
  the browser (screenshot via Chrome DevTools MCP if available), and check it against
27
45
  the PRD's Visual Direction and Success Criteria. Note anything visibly broken or off.
28
- 5. Run a mechanical security audit (cheap, ~2 min — do all of these):
29
- - Whole history, not just the tree:
30
- `git log -p | grep -iE '(api[_-]?key|secret|token|password)[[:space:]]*[:=]'`
31
- a secret committed then deleted is still leaked.
46
+ 5. Run a mechanical security audit:
47
+ - Inspect the relevant history with a secret scanner that redacts values, when one is
48
+ available. Otherwise review likely locations without copying candidate values into
49
+ output. Report file, line, and remediation only; a secret committed then deleted is
50
+ still leaked.
32
51
  - `.gitignore` covers `.env*` (except `.env.example`), and `git ls-files | grep -i env`
33
52
  shows only `.env.example`.
34
53
  - `npm audit --omit=dev` (or the ecosystem's equivalent) — report high/critical only.
@@ -38,15 +57,66 @@ run the pipeline, then present results.
38
57
  concrete bugs, silent failures, misleading code. Drop nitpicks and style opinions.
39
58
  7. Present findings as a short list with `file:line` references, ordered by severity.
40
59
  Security findings always rank above style-adjacent ones. For each, say whether you
41
- recommend fixing now (within the timebox) or noting as known-issue.
42
- 8. Fix what the user approves (or everything clearly broken, if time allows), verify,
43
- and commit as `review: fixes`.
44
- 9. Close out: write a brief `NOTES.md` at the repo root what was built, what was cut
60
+ recommend fixing now through a ticket or recording it as a known issue.
61
+ 8. Fix findings clearly within the authorized PRD through a new ticket associated with
62
+ that PRD. Use `pincer-ticket.sh` to start, verify, and close it, then make a scoped
63
+ `T-{NN}: {title}` commit. Ask only when a fix changes scope, architecture, or another
64
+ material decision; never make an ad-hoc `review: fixes` commit. Every fix commit
65
+ produces a new candidate: re-record `candidate`, re-run the checks against it, and
66
+ 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>/`:
68
+ - `checks/C-NN.log` — the command and a redacted summary or safe log of each
69
+ executable check. Never secrets, never an environment dump.
70
+ - `visual/<scenario>.png` — each visual capture from step 4, with its scenario,
71
+ viewport and observed result recorded in the manifest. When nothing renders,
72
+ record `visual_review: {applicable: false, reason}` and say why.
73
+ - `review/code-quality.md` — the reviewer's findings from step 2 with their
74
+ dispositions, or its explicit no-findings statement, recorded as a check of
75
+ kind `review` and referenced by the requirements it covers.
76
+ - `manifest.json` — evidence schema 1 (field list in the header of
77
+ `scripts/pincer-evidence.cjs`): selected PRD, full `base` and `candidate` IDs,
78
+ `created`, `environment` with tool limitations, `coverage_review` (your judgment
79
+ from step 3), one `requirements` entry per `R-NN` with its disposition, tickets
80
+ and check IDs, one `checks` entry per check with `kind`, `required`, `result`,
81
+ `command`, timestamp and artifact paths, and `artifacts` with digests from
82
+ `node scripts/pincer-evidence.cjs digest <file>...`.
83
+ A tool you cannot run yields a check with `result: unverified` and a note — never a
84
+ fabricated artifact. A deferred requirement carries `authorized_by` naming the
85
+ user's explicit authorization. Then run
86
+ `node scripts/pincer-evidence.cjs validate .prd/evidence/prd-vN/<candidate>/manifest.json --candidate <candidate> --prd .prd/prd-vN.md`
87
+ and correct the manifest until it prints `ok`; the same validator runs in status
88
+ and release. It checks the record's consistency, not that the commands ran.
89
+ 10. Close out: write a brief `NOTES.md` at the repo root with frontmatter:
90
+ ```yaml
91
+ ---
92
+ prd: .prd/prd-vN.md
93
+ base: <full reviewed base commit ID>
94
+ candidate: <full reviewed candidate commit ID>
95
+ evidence: .prd/evidence/prd-vN/<candidate>/manifest.json
96
+ ---
97
+ ```
98
+ Then commit NOTES.md, the manifest and its listed artifacts — and nothing else —
99
+ as `evaluate: PRD vN candidate <short sha>`. Status accepts this later commit only
100
+ when its diff from the candidate is limited to `NOTES.md` and the evidence files
101
+ the manifest lists; changes to source, tests, configuration, tickets, the PRD or
102
+ other evaluations require reevaluation. Legacy notes without these references
103
+ do not establish readiness. Then describe what was built, what was cut
45
104
  and why, known issues, and what you'd do next with more time. Then a **Handover**
46
105
  section, written for the stranger who inherits this repo in six months: how to get
47
106
  oriented (which file to read first), what each dependency is for and why it earned
48
107
  its place, and what breaks first as the code ages (the riskiest assumption, the
49
- least-tested path). Commit it. This is the first document a reviewer of this repo
50
- should read.
51
- 10. Suggest `/pincer-release` as the final step: "Run `/pincer-release` for a pass/fail audit of the
108
+ least-tested path). This is the first document a reviewer of this repo should read;
109
+ summarize the requirement dispositions from the manifest in it.
110
+ 11. Suggest `/pincer-release` as the final step: "Run `/pincer-release` for a pass/fail audit of the
52
111
  whole workflow's artifacts."
112
+
113
+ ## Authorization rule (shared by plan, narrow, code and evaluate)
114
+
115
+ Reuse explicit authorization for the same scope and decisions; ask only about a
116
+ material choice not already authorized, and prepare the concrete proposal before
117
+ asking. A decision the user delegated (for example "pick the architecture") does not
118
+ need another approval when you exercise it, but a newly discovered consequential
119
+ choice is surfaced before implementation. Record the authorization basis and the
120
+ scope it covers in the PRD or the handover. An agent-written record or a status
121
+ field is not authenticated human approval. When resuming without the context that
122
+ granted authorization, do not invent it — ask.
@@ -7,47 +7,92 @@ description: "Turn the approved PRD into local, AI-ready ticket files"
7
7
 
8
8
  # /pincer-narrow — PRD to Local Tickets
9
9
 
10
- You are decomposing the PRD into small, independently verifiable tickets stored as local
11
- markdown files (no external tracker needed). Target: 4–7 tickets that fit a ~75-minute
12
- build window.
10
+ You are decomposing the PRD into coherent, independently verifiable tickets stored as
11
+ local markdown files (no external tracker needed). Ticket count and size follow the
12
+ change's dependencies and risk, plus any budget the user supplied. There is no hard
13
+ one-to-two-ticket cap for small PRDs and no default timebox: cohesion and dependencies
14
+ decide the count. A breakdown that follows the PRD needs no second approval; a newly
15
+ discovered consequential choice is surfaced before implementation.
13
16
 
14
17
  **Initial request:** ${input:request:Task brief or arguments (optional)}
15
18
 
16
19
  ## Steps
17
20
 
18
- 1. Run `scripts/pincer-status.sh`. If tickets already exist, ask before adding to them
19
- new tickets continue the numbering, existing ones are never renumbered. Then read the
21
+ 1. Run `scripts/pincer-status.sh`. If tickets already exist for another PRD, leave them
22
+ as history. New tickets continue the numbering and existing ones are never renumbered.
23
+ If tickets already exist for this PRD, extend them only when the current request already
24
+ authorizes that work; otherwise present the concrete addition before asking. Then read the
20
25
  PRD (`${input:request:Task brief or arguments (optional)}` or the latest `.prd/prd-v*.md`). If its status isn't `draft`, ask
21
26
  which PRD to use.
22
27
  2. Decompose into tickets. Rules:
23
- - Each ticket is one coherent unit: sized S or M, never L. Split anything larger.
24
- - Ticket 1 is always the walking skeleton: project scaffold + a thin end-to-end slice
25
- that runs. Everything after builds on a working base.
28
+ - Each ticket is one coherent unit. Use S, M, or L as relative scope indicators and
29
+ split work when that improves dependency order, verification, or ownership.
30
+ - For greenfield work, use a walking skeleton when it reduces integration risk. For
31
+ brownfield work, begin with the smallest protected vertical change; add a
32
+ characterization ticket before changing load-bearing code that lacks coverage.
26
33
  - Order by dependency; note blockers explicitly ("depends on T-01").
34
+ - Build the requirement map: for every `R-NN` in the PRD and each of its
35
+ scenarios, name the ticket that owns the implementation and the executable
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.
27
41
  - Every ticket gets a runnable command in its Verification block — a fenced `bash`
28
42
  block that exits 0 only when the ticket is done. `scripts/pincer-ticket.sh verify`
29
43
  runs it verbatim and stamps the receipt that `done` requires, so it must be
30
44
  non-interactive and self-contained (no "check by hand").
45
+ - Each Verification section opens with `Proves:` — what the check establishes and
46
+ which regression it detects. A check for an executable change must exercise
47
+ observable behavior (including relevant rejection paths and, in brownfield work,
48
+ preservation of existing behavior) and fail when the behavior is wrong, not only
49
+ when an identifier is renamed. Reuse adequate focused tests. A build, a syntax
50
+ check, or an identifier grep alone is not proof; static assertions are primary
51
+ evidence only for static contracts such as generated files, and `Proves:` says so.
52
+ - Adequacy is a judgment about what the command observes, never a word match: do
53
+ not call a command sufficient because it contains `grep`, `test`, or a runner
54
+ name, nor insufficient for lacking them. Manual visual judgment is recorded
55
+ separately in evaluation; a tool the check needs but cannot run yields an
56
+ explicit `unverified` result, never fabricated evidence or a silent waiver.
31
57
  - If the brief or stack implies automated tests, at least one ticket's verification
32
58
  command must be the test runner (e.g. `npm test`) — manual checks alone don't count.
33
59
  - Any ticket whose surface accepts external input (HTTP endpoint, form, file,
34
60
  LLM output) gets an acceptance criterion for the reject path — what invalid
35
61
  input produces (e.g. "empty goal → 400 with a clear message"), not only the
36
62
  happy path.
37
- - The walking skeleton (T-01) includes `.gitignore` covering `.env*` (except
38
- `.env.example`) and an `.env.example` naming any required secrets before
39
- any secret can exist in the repo.
40
- - Brownfield: a ticket that modifies load-bearing code with no test coverage
41
- is preceded by a characterization ticket — a test that pins the current
42
- behavior before any ticket is allowed to change it.
63
+ - A greenfield setup ticket includes `.gitignore` covering `.env*` (except
64
+ `.env.example`) and an `.env.example` naming any required secrets before any
65
+ secret can exist in the repo. In brownfield repositories, preserve and verify
66
+ the existing ignore and environment conventions.
43
67
  3. Write each ticket to `tickets/T-{NN}-{slug}.md` using
44
- `.claude/references/ticket-template.md`, with `status: open`. The other state fields
45
- (`started`, `verified`, `finished`) are added later by `scripts/pincer-ticket.sh`
68
+ `.claude/references/ticket-template.md`, with `status: open` and an explicit
69
+ `prd: .prd/prd-vN.md` naming the selected PRD. Never infer this association from
70
+ numbering or old notes. The other state fields
71
+ (`started`, `last_check`, `verified`, `finished`) are added later by `scripts/pincer-ticket.sh` —
46
72
  never write them yourself.
47
- 4. Present the ticket list (number, title, size, dependencies) as a table.
73
+ 4. Present the ticket list (number, title, size, dependencies) as a table, followed
74
+ by the requirement map as a second table (requirement · scenario · ticket · check
75
+ or review method). Whether the map is complete and each check is adequate is your
76
+ judgment as the author; say so rather than presenting the table as mechanical proof.
48
77
 
49
- **Gate (medium):** Ask for approval of the breakdown and build order. Adjust if pushed back.
78
+ Present the concrete breakdown and build order as a report, not a question. Reuse
79
+ existing authorization for the same scope and order.
50
80
 
51
- 5. After approval, update the PRD frontmatter to `status: ticketed`, commit the tickets
52
- (`git add .prd tickets && git commit`), and finish with:
81
+ 5. Finalize. A breakdown that follows the PRD is already authorized by the PRD: do not
82
+ ask whether to proceed. Update the selected PRD frontmatter to `status: ticketed`,
83
+ inspect existing staged changes, stage that PRD and the explicit new ticket paths,
84
+ review `git diff --cached`, and commit only those paths. Ask first — and finalize
85
+ once it is resolved — only when step 4 surfaced a newly discovered consequential
86
+ choice or a scope change the PRD does not cover. Finish with:
53
87
  "Tickets ready in `tickets/`. Run `/pincer-code` to start implementing."
88
+
89
+ ## Authorization rule (shared by plan, narrow, code and evaluate)
90
+
91
+ Reuse explicit authorization for the same scope and decisions; ask only about a
92
+ material choice not already authorized, and prepare the concrete proposal before
93
+ asking. A decision the user delegated (for example "pick the architecture") does not
94
+ need another approval when you exercise it, but a newly discovered consequential
95
+ choice is surfaced before implementation. Record the authorization basis and the
96
+ scope it covers in the PRD or the handover. An agent-written record or a status
97
+ field is not authenticated human approval. When resuming without the context that
98
+ granted authorization, do not invent it — ask.