pan-wizard 3.31.0 → 3.33.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 (87) hide show
  1. package/README.md +28 -24
  2. package/agents/pan-conductor.md +2 -2
  3. package/agents/pan-design-checker.md +18 -0
  4. package/agents/pan-document_code.md +2 -2
  5. package/agents/pan-executor.md +3 -3
  6. package/agents/pan-experiment-runner.md +7 -10
  7. package/agents/pan-hardener.md +15 -15
  8. package/agents/pan-knowledge.md +1 -1
  9. package/agents/pan-meta-reviewer.md +2 -2
  10. package/agents/pan-optimizer.md +7 -3
  11. package/agents/pan-phase-researcher.md +2 -2
  12. package/agents/pan-plan-checker.md +29 -2
  13. package/agents/pan-planner.md +23 -10
  14. package/agents/pan-project-researcher.md +10 -67
  15. package/agents/pan-reviewer.md +19 -0
  16. package/agents/pan-roadmapper.md +5 -48
  17. package/agents/pan-verifier.md +49 -11
  18. package/bin/install-lib.cjs +170 -15
  19. package/bin/install.js +39 -14
  20. package/commands/pan/army.md +2 -2
  21. package/commands/pan/design-phase.md +8 -0
  22. package/commands/pan/exec-phase.md +1 -1
  23. package/commands/pan/experiment.md +2 -2
  24. package/commands/pan/focus-auto.md +12 -8
  25. package/commands/pan/focus-design.md +2 -0
  26. package/commands/pan/focus-exec.md +1 -1
  27. package/commands/pan/focus-scan.md +2 -7
  28. package/commands/pan/git.md +2 -2
  29. package/commands/pan/learn.md +2 -0
  30. package/commands/pan/map-codebase.md +4 -4
  31. package/commands/pan/mcp-bridge.md +1 -1
  32. package/commands/pan/milestone-done.md +1 -2
  33. package/commands/pan/optimize.md +14 -2
  34. package/commands/pan/phase-tests.md +2 -2
  35. package/commands/pan/profile.md +2 -2
  36. package/commands/pan/research-phase.md +2 -4
  37. package/commands/pan/review-deep.md +8 -8
  38. package/commands/pan/todo-add.md +2 -2
  39. package/commands/pan/todo-check.md +2 -2
  40. package/hooks/dist/pan-context-monitor.js +1 -1
  41. package/hooks/dist/pan-cost-logger.js +63 -11
  42. package/hooks/dist/pan-state-reinject.js +142 -17
  43. package/hooks/dist/pan-stop-guard.js +2 -2
  44. package/hooks/dist/pan-trace-logger.js +283 -18
  45. package/package.json +1 -1
  46. package/pan-wizard-core/bin/lib/agents-md.cjs +4 -1
  47. package/pan-wizard-core/bin/lib/commands.cjs +95 -2
  48. package/pan-wizard-core/bin/lib/config.cjs +110 -0
  49. package/pan-wizard-core/bin/lib/constants.cjs +39 -9
  50. package/pan-wizard-core/bin/lib/core.cjs +27 -7
  51. package/pan-wizard-core/bin/lib/cost.cjs +16 -6
  52. package/pan-wizard-core/bin/lib/findings.cjs +385 -0
  53. package/pan-wizard-core/bin/lib/focus.cjs +72 -19
  54. package/pan-wizard-core/bin/lib/foreign-planning.cjs +24 -6
  55. package/pan-wizard-core/bin/lib/hygiene.cjs +12 -2
  56. package/pan-wizard-core/bin/lib/init.cjs +9 -2
  57. package/pan-wizard-core/bin/lib/optimize.cjs +349 -21
  58. package/pan-wizard-core/bin/lib/phase.cjs +52 -2
  59. package/pan-wizard-core/bin/lib/review-deep.cjs +38 -2
  60. package/pan-wizard-core/bin/lib/state.cjs +10 -4
  61. package/pan-wizard-core/bin/lib/verdict.cjs +481 -0
  62. package/pan-wizard-core/bin/lib/verify-drift.cjs +14 -5
  63. package/pan-wizard-core/bin/lib/verify-preflight.cjs +4 -2
  64. package/pan-wizard-core/bin/lib/verify-scope.cjs +223 -0
  65. package/pan-wizard-core/bin/lib/verify.cjs +111 -8
  66. package/pan-wizard-core/bin/pan-tools.cjs +68 -6
  67. package/pan-wizard-core/learnings/README.md +10 -7
  68. package/pan-wizard-core/mcp/server.cjs +18 -9
  69. package/pan-wizard-core/mcp/tool-registry.cjs +2 -0
  70. package/pan-wizard-core/references/checkpoints.md +4 -2
  71. package/pan-wizard-core/references/verdict-contract.md +102 -0
  72. package/pan-wizard-core/templates/discovery.md +1 -1
  73. package/pan-wizard-core/templates/phase-prompt.md +2 -1
  74. package/pan-wizard-core/templates/verification-report.md +21 -0
  75. package/pan-wizard-core/workflows/exec-phase.md +73 -50
  76. package/pan-wizard-core/workflows/health.md +3 -0
  77. package/pan-wizard-core/workflows/learn.md +4 -2
  78. package/pan-wizard-core/workflows/milestone-audit.md +15 -3
  79. package/pan-wizard-core/workflows/new-project.md +1 -1
  80. package/pan-wizard-core/workflows/optimize.md +14 -1
  81. package/pan-wizard-core/workflows/plan-phase.md +20 -15
  82. package/pan-wizard-core/workflows/quick.md +6 -6
  83. package/pan-wizard-core/workflows/verify-phase.md +10 -15
  84. package/pan-zcode/README.md +3 -3
  85. package/scripts/build-agent-plugin.js +19 -5
  86. package/scripts/git-hooks/pre-commit +2 -1
  87. package/scripts/test-surface.cjs +4 -0
@@ -50,6 +50,15 @@ const META_SERVER_INFO_KEY = 'io.modelcontextprotocol/serverInfo';
50
50
  // claim to speak a version we don't. Newest first (the `server/discover` order).
51
51
  const SUPPORTED_VERSIONS_LIST = [MODERN_PROTOCOL_VERSION, '2025-06-18', '2025-03-26', '2024-11-05'];
52
52
  const SUPPORTED_PROTOCOL_VERSIONS = new Set(SUPPORTED_VERSIONS_LIST);
53
+ // The `CacheableResult` fields a modern result MUST carry where its type extends
54
+ // that interface: DiscoverResult, ListToolsResult, ListResourcesResult and
55
+ // ReadResourceResult (schema/2026-07-28/schema.ts). Claude Code 2.1.288 drops a
56
+ // list without them, so the server showed as connected with no tools and no
57
+ // resources (live check H2, 2026-10-03). The registry is fixed for the life of the
58
+ // process, so its lists are public and long-lived; a resource is the project's
59
+ // state at the moment it is read, so a read is private and stale at once.
60
+ const REGISTRY_CACHE = Object.freeze({ ttlMs: 3600000, cacheScope: 'public' });
61
+ const READ_CACHE = Object.freeze({ ttlMs: 0, cacheScope: 'private' });
53
62
  /**
54
63
  * The version the server reports in `initialize` / `server/discover`. Read from the
55
64
  * package.json two levels up: the repository root in the source tree, the runtime
@@ -320,12 +329,13 @@ function createServer(opts = {}) {
320
329
  { supported: SUPPORTED_VERSIONS_LIST, requested: requestedVersion });
321
330
  }
322
331
 
323
- // Modern results MUST carry a `resultType`; legacy results MUST NOT change
324
- // shape (clients treat an absent resultType as "complete"). Stamp it only on
332
+ // Modern results MUST carry a `resultType`, a cacheable one its caching fields,
333
+ // and each SHOULD name the server in `_meta`; legacy results MUST NOT change
334
+ // shape (clients treat an absent resultType as "complete"). Stamp them only on
325
335
  // the modern path.
326
- const reply = (result) => rpcResult(id,
336
+ const reply = (result, cache) => rpcResult(id,
327
337
  isModern && result && typeof result === 'object' && result.resultType === undefined
328
- ? { resultType: 'complete', ...result }
338
+ ? { resultType: 'complete', ...cache, ...result, _meta: { ...result._meta, [META_SERVER_INFO_KEY]: SERVER_INFO } }
329
339
  : result);
330
340
 
331
341
  switch (method) {
@@ -339,8 +349,7 @@ function createServer(opts = {}) {
339
349
  supportedVersions: SUPPORTED_VERSIONS_LIST,
340
350
  capabilities: { tools: {}, resources: {} },
341
351
  instructions: 'PAN Wizard engine bridge: planning, verification, and orchestration tools backed by the pan-tools CLI. All tools are read-only except the gated pan_confirm_merge.',
342
- ttlMs: 3600000,
343
- cacheScope: 'public',
352
+ ...REGISTRY_CACHE,
344
353
  _meta: { [META_SERVER_INFO_KEY]: SERVER_INFO },
345
354
  });
346
355
  case 'initialize': {
@@ -354,9 +363,9 @@ function createServer(opts = {}) {
354
363
  case 'ping':
355
364
  return reply({});
356
365
  case 'tools/list':
357
- return reply({ tools: reg.TOOLS.map(toMcpTool) });
366
+ return reply({ tools: reg.TOOLS.map(toMcpTool) }, REGISTRY_CACHE);
358
367
  case 'resources/list':
359
- return reply({ resources: reg.RESOURCES.map(toMcpResource) });
368
+ return reply({ resources: reg.RESOURCES.map(toMcpResource) }, REGISTRY_CACHE);
360
369
  case 'tools/call': {
361
370
  const out = callTool(params && params.name, params && params.arguments);
362
371
  return out.error ? rpcError(id, out.error.code, out.error.message) : reply(out.result);
@@ -364,7 +373,7 @@ function createServer(opts = {}) {
364
373
  case 'resources/read': {
365
374
  const out = readResource(params && params.uri);
366
375
  if (out.unknown) return rpcError(id, -32602, `Unknown resource: ${params && params.uri}`);
367
- return out.error ? rpcError(id, out.error.code, out.error.message) : reply(out.result);
376
+ return out.error ? rpcError(id, out.error.code, out.error.message) : reply(out.result, READ_CACHE);
368
377
  }
369
378
  default:
370
379
  return rpcError(id, -32601, `Method not found: ${method}`);
@@ -69,6 +69,8 @@ const RESOURCES = [
69
69
  description: 'Doc↔code link graph verdict: forward links, backlink contracts, and anchor targets, with finding codes.' },
70
70
  { uri: 'pan://cost', name: 'Token cost', verb: 'cost', args: ['report'],
71
71
  description: 'Aggregated token spend from the .planning/metrics ledger. Reads as zeros on a project with no recorded calls.' },
72
+ { uri: 'pan://findings', name: 'Findings', verb: 'findings', args: ['list'],
73
+ description: 'Every finding PAN\'s judges recorded (verifier, plan checker, reviewer, design checker), with its folded status — open, fixed, deferred, dismissed or decision — and the reason given. Reads as an empty list on a project with no recorded verdicts.' },
72
74
  ];
73
75
 
74
76
  /** Actionable pan-tools verbs → MCP tools (each spawns `node pan-tools.cjs <verb>`). */
@@ -8,7 +8,7 @@ Plans execute autonomously. Checkpoints formalize interaction points where human
8
8
  2. **Claude sets up the verification environment** - Start dev servers, seed databases, configure env vars
9
9
  3. **User only does what requires human judgment** - Visual checks, UX evaluation, "does this feel right?"
10
10
  4. **Secrets come from user, automation comes from Claude** - Ask for API keys, then Claude uses them via CLI
11
- 5. **Auto-mode bypasses verification/decision checkpoints** — When `workflow.auto_advance` is true in config: human-verify auto-approves, decision auto-selects first option, human-action still stops (auth gates cannot be automated)
11
+ 5. **Auto-mode bypasses verification checkpoints, and decisions only where the planner named a default** — When `workflow.auto_advance` is true in config: human-verify auto-approves; a decision with `auto_select="<option id>"` takes that option, and a decision without it stops for a human (auto mode never takes an option because it is listed first); human-action still stops (auth gates cannot be automated)
12
12
  </overview>
13
13
 
14
14
  <checkpoint_types>
@@ -105,7 +105,7 @@ Plans execute autonomously. Checkpoints formalize interaction points where human
105
105
 
106
106
  **Structure:**
107
107
  ```xml
108
- <task type="checkpoint:decision" gate="blocking">
108
+ <task type="checkpoint:decision" gate="blocking" auto_select="option-a">
109
109
  <decision>[What's being decided]</decision>
110
110
  <context>[Why this decision matters]</context>
111
111
  <options>
@@ -124,6 +124,8 @@ Plans execute autonomously. Checkpoints formalize interaction points where human
124
124
  </task>
125
125
  ```
126
126
 
127
+ **`auto_select` (optional)** names the option auto mode takes. Set it only when the choice is safe to make without the user: reversible, no new paid service, no credential, no data-model lock-in. It must name an `id` from this checkpoint's options; `verify plan-structure` fails one that names no option. Leave it out when a human must choose, and auto mode stops at this checkpoint. The examples below omit it: picking a vendor or a database is the user's call.
128
+
127
129
  **Example: Auth Provider Selection**
128
130
  ```xml
129
131
  <task type="checkpoint:decision" gate="blocking">
@@ -0,0 +1,102 @@
1
+ # The `pan-verdict` block
2
+
3
+ A judging agent ends its report with one fenced `pan-verdict` block. The block is the machine-readable form of the verdict the report already gives in prose. The orchestrator records it with `pan-tools findings record`, and that record is what the workflow branches on. It also feeds the findings ledger that milestone audits read for tech debt. The prose stays for people, and the block states the same verdict for code.
4
+
5
+ ## Rules
6
+
7
+ 1. **Place it last.** The block is the final element of your return. When a report holds more than one block, the recorder reads the last one.
8
+ 2. **Valid JSON only.** No comments and no trailing commas. One line or pretty-printed are both fine.
9
+ 3. **Same verdict as the prose.** `verdict` is the word your report already uses, and `outcome` is what that word means (see the table below). The block never disagrees with the report.
10
+ 4. **One finding per issue.** List the findings the report lists, each as its own entry, most severe first. A clean pass has `"findings": []`.
11
+ 5. **Plain summaries.** State each finding in one sentence of 300 characters or fewer. Put the location in `where`, not in `summary`.
12
+
13
+ ````markdown
14
+ ```pan-verdict
15
+ {"contract":"1.0","agent":"pan-reviewer","phase":"03","verdict":"NEEDS_FIXES","outcome":"fail","findings":[{"class":"defect","severity":"high","where":"src/utils/parser.ts:42","summary":"parse() drops the final token of every line"}]}
16
+ ```
17
+ ````
18
+
19
+ ## Fields
20
+
21
+ | Field | Required | Value |
22
+ |---|---|---|
23
+ | `contract` | yes | `"1.0"` |
24
+ | `agent` | yes | your agent name, e.g. `pan-reviewer` |
25
+ | `phase` | when you know it | the phase number you were asked about, e.g. `"03"` |
26
+ | `verdict` | yes | your own verdict word (table below) |
27
+ | `outcome` | yes | `pass`, `fail` or `needs_human` |
28
+ | `findings` | yes (may be empty) | a list of `{class, severity, where, summary}` |
29
+ | `not_checked` | when a check could not run | a list of `{check, reason}`: a check you were asked to make and could not run, and why (no test script, no browser, a file you could not read). Never fold it into `pass`: a verdict with entries here says what it did not see |
30
+
31
+ | Agent | `verdict` → `outcome` |
32
+ |---|---|
33
+ | pan-plan-checker | `passed` → `pass` · `issues_found` → `fail` |
34
+ | pan-reviewer | `PASS` → `pass` · `PASS_WITH_WARNINGS` → `pass` · `NEEDS_FIXES` → `fail` |
35
+ | pan-design-checker | `PASS` → `pass` · `GAPS` → `fail` |
36
+
37
+ The verifier does not emit this block. Its verification.md frontmatter (`status`, `gaps`, `human_verification`, `unrequested`, `test_gate`, `not_checked`) is its machine contract, and the recorder reads that directly. `test_gate` is `passed`, `failed` or `skipped`. A skipped gate is recorded as a `tests` entry in `not_checked` even when the list leaves it out, and a verification that does not record `test_gate` at all is recorded with a `test_gate_unrecorded` warning.
38
+
39
+ ## `class`: what kind of finding
40
+
41
+ | Class | Use when |
42
+ |---|---|
43
+ | `missing` | Something required is absent: a requirement with no task, a must-have not built, an unplanned key link |
44
+ | `partial` | Present but incomplete: a task missing its verify/done fields, a stub, a half-derived criterion |
45
+ | `contradicts` | It conflicts with a requirement, a locked decision (context.md) or the codebase's established architecture |
46
+ | `unrequested` | Work, a file or a behaviour that no plan or requirement asked for (scope creep) |
47
+ | `defect` | Incorrect behaviour or a code error; a broken dependency order in a plan |
48
+ | `risk` | A security, reliability or scale exposure; a plan whose scope will not fit its budget |
49
+ | `quality` | Convention, naming, style or maintainability, with no correctness impact |
50
+ | `human` | Cannot be settled by a check, so a person must look |
51
+
52
+ ## `severity`: how much it matters
53
+
54
+ `critical` · `high` · `medium` · `low` · `info`. This is the same ladder `/pan:review-deep` uses.
55
+
56
+ ## Mapping for each judge
57
+
58
+ **pan-plan-checker.**
59
+ - Classes by dimension:
60
+ - Requirement coverage, key links, test coverage, Nyquist → `missing`
61
+ - Task completeness, verification derivation, spec sufficiency, decision trace → `partial`
62
+ - Dependency correctness → `defect`
63
+ - Scope sanity → `risk`
64
+ - Context compliance → `contradicts`
65
+ - Standards → `quality`
66
+ - Severity: blocker → `high`, warning → `medium`, info → `info`.
67
+ - `where`: `NN-MM-plan.md` or `NN-MM-plan.md#task-N`.
68
+
69
+ **pan-reviewer.**
70
+ - Classes by category: Convention → `quality`, Security → `risk`, Code Quality → `defect`, work no plan asked for → `unrequested`.
71
+ - Severity: ERROR → `high`, WARNING → `medium`, INFO → `info`.
72
+ - `where`: `path:line`.
73
+
74
+ **pan-design-checker.**
75
+ - Classes by dimension:
76
+ - Requirement coverage → `missing`
77
+ - Architecture conformance → `contradicts`
78
+ - Threat coverage → `risk`
79
+ - Scope discipline → `unrequested`
80
+ - Every other dimension → `partial`
81
+ - Severity: each gap is `high`. A gap you report as a caveat on the final iteration is `medium`.
82
+ - `where`: the design section, e.g. `03-design.md#interfaces`.
83
+
84
+ ## Examples
85
+
86
+ A plan check that passes:
87
+
88
+ ````markdown
89
+ ```pan-verdict
90
+ {"contract":"1.0","agent":"pan-plan-checker","phase":"05","verdict":"passed","outcome":"pass","findings":[]}
91
+ ```
92
+ ````
93
+
94
+ A design check with two gaps:
95
+
96
+ ````markdown
97
+ ```pan-verdict
98
+ {"contract":"1.0","agent":"pan-design-checker","phase":"05","verdict":"GAPS","outcome":"fail","findings":[
99
+ {"class":"missing","severity":"high","where":"05-design.md#requirements","summary":"REQ-12 (export to CSV) maps to no design element"},
100
+ {"class":"risk","severity":"high","where":"05-design.md#threats","summary":"the upload endpoint accepts any file type and no threat entry covers it"}]}
101
+ ```
102
+ ````
@@ -30,7 +30,7 @@ Discover [topic] to inform [phase name] implementation.
30
30
 
31
31
  Purpose: [What decision/implementation this enables]
32
32
  Scope: [Boundaries]
33
- Output: DISCOVERY.md with recommendation
33
+ Output: discovery.md with recommendation
34
34
  </discovery_objective>
35
35
 
36
36
  <discovery_scope>
@@ -79,7 +79,8 @@ Output: [What artifacts will be created]
79
79
  <!-- For checkpoint task examples and patterns, see @~/.claude/pan-wizard-core/references/checkpoints.md -->
80
80
  <!-- Key rule: Claude starts dev server BEFORE human-verify checkpoints. User only visits URLs. -->
81
81
 
82
- <task type="checkpoint:decision" gate="blocking">
82
+ <task type="checkpoint:decision" gate="blocking" auto_select="option-a">
83
+ <!-- auto_select: the option auto mode takes. Omit it when a human must choose. -->
83
84
  <decision>[What needs deciding]</decision>
84
85
  <context>[Why this decision matters]</context>
85
86
  <options>
@@ -10,8 +10,16 @@ Template for `.planning/phases/XX-name/{phase_num}-verification.md` — phase go
10
10
  ---
11
11
  phase: XX-name
12
12
  verified: YYYY-MM-DDTHH:MM:SSZ
13
+ verified_commit: <sha> # git rev-parse HEAD before writing this file; `pan-tools verify stale` compares against it
13
14
  status: passed | gaps_found | human_needed
14
15
  score: N/M must-haves verified
16
+ test_gate: passed | failed | skipped
17
+ not_checked: # Only for checks that could not run, with why — a skipped test gate is one
18
+ - check: "tests"
19
+ reason: "no test script in package.json"
20
+ unrequested: # Only when the scope check (`pan-tools verify scope <phase>`) found work no plan asked for
21
+ - path: "src/admin/panel.tsx"
22
+ what: "An admin panel no plan or requirement asked for"
15
23
  ---
16
24
 
17
25
  # Phase {X}: {Name} Verification Report
@@ -89,6 +97,19 @@ None — all verifiable items checked programmatically.
89
97
  **Expected:** {What should happen}
90
98
  **Why human:** {Why can't verify programmatically}
91
99
 
100
+ ## Unrequested Work
101
+
102
+ {If the scope check found none:}
103
+ None: every change traces to a plan.
104
+
105
+ {Otherwise, one row per `unrequested:` entry:}
106
+
107
+ | File | What it adds | Why no plan covers it |
108
+ |------|--------------|-----------------------|
109
+ | src/admin/panel.tsx | An admin panel | No requirement mentions admin tooling |
110
+
111
+ Unrequested work is recorded, not blocking: the status does not change because of it.
112
+
92
113
  ## Gaps Summary
93
114
 
94
115
  {If no gaps:}
@@ -256,7 +256,11 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true`
256
256
 
257
257
  **Known Claude Code bug (classifyHandoffIfNeeded):** If an agent reports "failed" with error containing `classifyHandoffIfNeeded is not defined`, this is a Claude Code runtime bug — not a PAN or agent issue. The error fires in the completion handler AFTER all tool calls finish. In this case: run the same spot-checks as step 4 (summary.md exists, git commits present, no Self-Check: FAILED). If spot-checks PASS → treat as **successful**. If spot-checks FAIL → treat as real failure below.
258
258
 
259
- For real failures: report which plan failed → ask "Continue?" or "Stop?" → if continue, dependent plans may also fail. If stop, partial completion report.
259
+ For real failures: report which plan failed → ask "Continue?" or "Stop?". If stop, partial completion report. If continue, never run a plan that depends on a failed one; ask the engine which plans are blocked:
260
+ ```bash
261
+ BLOCKED=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs phase-plan-index "${PHASE_NUMBER}" --failed "${FAILED_PLAN_IDS}")
262
+ ```
263
+ `${FAILED_PLAN_IDS}` is the comma-separated ids of every plan that failed so far. `blocked` lists each unfinished plan whose `depends_on` reaches a failed plan, directly or through another blocked plan, with the failed plans behind it. Do not spawn those plans in this or any later wave. Name them in the wave report and the final summary ("Skipped 03-03 and 03-04: they depend on 03-01, which failed"), and run every other plan as planned. The same applies after "Continue with remaining waves?" in step 4.
260
264
 
261
265
  6. **Execute checkpoint plans between waves** — see `<checkpoint_handling>`.
262
266
 
@@ -275,7 +279,7 @@ AUTO_CFG=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs config-get workflow.
275
279
 
276
280
  When executor returns a checkpoint AND `AUTO_CFG` is `"true"`:
277
281
  - **human-verify** → Auto-spawn continuation agent with `{user_response}` = `"approved"`. Log `⚡ Auto-approved checkpoint`.
278
- - **decision** → Auto-spawn continuation agent with `{user_response}` = first option from checkpoint details. Log `⚡ Auto-selected: [option]`.
282
+ - **decision** → The executor already took the plan's `auto_select` option when the task had one, so a decision that comes back has none: present it to the user (standard flow below). If a returned decision's task does carry `auto_select` in the plan file, auto-spawn the continuation agent with `{user_response}` = that option id and log `⚡ Auto-selected: [option] (auto_select)`. Never answer with an option because it is listed first.
279
283
  - **human-action** → Present to user (existing behavior below). Auth gates cannot be automated.
280
284
 
281
285
  **Standard flow (not auto-mode, or human-action type):**
@@ -425,13 +429,21 @@ Task(
425
429
  )
426
430
  ```
427
431
 
428
- 3. Handle review results:
432
+ 3. **Save the report.** Use the Write tool to write the reviewer's returned text, verbatim and in full (including its closing `pan-verdict` block), to `{phase_dir}/{phase_number}-review.md`. The reviewer is read-only by design, so the orchestrator saves the report. `/pan:review-deep` and the findings ledger read this file.
433
+
434
+ 4. **Record the verdict, then act on it.** The record is what this step branches on. It also adds the findings to the ledger (`.planning/findings.jsonl`) and logs the verdict to the trace, so no separate trace call is needed:
435
+ ```bash
436
+ REVIEW_FILE="{phase_dir}/{phase_number}-review.md"
437
+ REVIEW_VERDICT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${PHASE_NUMBER}" --agent pan-reviewer --file "$REVIEW_FILE" --raw 2>/dev/null) \
438
+ || REVIEW_VERDICT=$(grep -A1 '^### Verdict' "$REVIEW_FILE" | tail -1 | tr -d ' ')
439
+ ```
440
+ The fallback reads the word under `### Verdict` when the report carries no valid `pan-verdict` block.
429
441
 
430
442
  | Verdict | Action |
431
443
  |---------|--------|
432
444
  | `PASS` | Continue to verification |
433
- | `PASS_WITH_WARNINGS` | Report warnings, continue to verification |
434
- | `NEEDS_FIXES` | Present ERROR findings to user: "Fix before verification?" or "Continue anyway?" |
445
+ | `PASS_WITH_WARNINGS` | Report the warnings, then record that the phase continues past them (below), and continue to verification |
446
+ | `NEEDS_FIXES` | Present the ERROR findings to the user: "Fix before verification?" or "Continue anyway?" |
435
447
 
436
448
  ```
437
449
  ## Code Review Results
@@ -442,34 +454,60 @@ Task(
442
454
  {If errors: list top 5 with file:line}
443
455
  ```
444
456
 
445
- **If user chooses "Continue anyway":** Proceed to verification. Review findings are informational, not blocking.
457
+ **Never continue past findings silently.** Whenever the phase moves on with review findings still open, record why. The reason is what a milestone audit later reports as tech debt:
458
+ - `PASS_WITH_WARNINGS`:
459
+ ```bash
460
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings dispose --phase "${PHASE_NUMBER}" --agent pan-reviewer --open --as deferred --reason "accepted at review: PASS_WITH_WARNINGS"
461
+ ```
462
+ - **The user chooses "Continue anyway"** at `NEEDS_FIXES`: the same command with `--reason "continued past NEEDS_FIXES at the user's choice"`, then proceed to verification.
463
+ - **The user chooses "Fix before verification"**: apply the fixes, then run the review once more (steps 2–4). The new record closes the findings it no longer reports.
446
464
 
447
- 4. **Circular optimization — log reviewer corrections to trace bus (W1 fix):**
465
+ 5. **No separate trace logging.** The record logs `verdict_passed` or `verdict_failed` for the reviewer on every runtime. The `reviewer_correction` and `reviewer_warnings` trace calls that used to sit here read the error count from a shell variable nothing ever set.
448
466
 
449
- When verdict is `NEEDS_FIXES`, write a `reviewer_correction` event so the optimizer can see the primary quality signal:
450
- ```bash
451
- # Extract error count from review output (parse "Errors: N" line)
452
- REVIEW_ERROR_COUNT=$(echo "$REVIEW_OUTPUT" | grep -E "^- Errors: [0-9]+" | grep -oE "[0-9]+" | head -1)
453
- REVIEW_ERROR_COUNT=${REVIEW_ERROR_COUNT:-1}
454
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
455
- --type error --category reviewer_correction \
456
- --description "Phase ${PHASE_NUMBER} reviewer: NEEDS_FIXES — ${REVIEW_ERROR_COUNT} error(s) found" \
457
- --agent pan-reviewer --impact major \
458
- --context "{\"phase\":\"${PHASE_NUMBER}\",\"verdict\":\"NEEDS_FIXES\",\"error_count\":${REVIEW_ERROR_COUNT}}" \
459
- 2>/dev/null || true
467
+ 6. **Deep review — only when `--deep-review` is in $ARGUMENTS.** The security pass and cross-check that `/pan:review-deep` runs, done inline right after the normal review. If the normal review was skipped (`--skip-review` or `--fast`), say that `--deep-review` needs the review it builds on, and continue without it.
468
+
469
+ a. Spawn the hardener. Its output path is `.planning/reviews/${PHASE_NUMBER}/hardener.md`:
470
+ ```
471
+ Task(
472
+ subagent_type="pan-hardener",
473
+ model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-hardener --raw)",
474
+ prompt="
475
+ <files_to_read>
476
+ - {phase_dir}/{phase_number}-review.md (the first-pass review)
477
+ - the phase plans: {phase_dir}/*-plan.md
478
+ Changed files to audit:
479
+ ${CHANGED_FILES_LIST}
480
+ </files_to_read>
481
+ <output_path>.planning/reviews/${PHASE_NUMBER}/hardener.md</output_path>
482
+ <framework_scope>OWASP Top 10 (2025) and STRIDE, across every changed file.</framework_scope>
483
+ "
484
+ )
460
485
  ```
461
486
 
462
- When verdict is `PASS_WITH_WARNINGS`, log a softer signal:
463
- ```bash
464
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
465
- --type decision --category reviewer_warnings \
466
- --description "Phase ${PHASE_NUMBER} reviewer: PASS_WITH_WARNINGS — warnings present" \
467
- --agent pan-reviewer --impact trivial \
468
- --context "{\"phase\":\"${PHASE_NUMBER}\",\"verdict\":\"PASS_WITH_WARNINGS\"}" \
469
- 2>/dev/null || true
487
+ b. Spawn the meta-reviewer on both first-pass reports. Its output path is `.planning/reviews/${PHASE_NUMBER}/meta.md`:
470
488
  ```
489
+ Task(
490
+ subagent_type="pan-meta-reviewer",
491
+ model="$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-meta-reviewer --raw)",
492
+ prompt="
493
+ <files_to_read>
494
+ - {phase_dir}/{phase_number}-review.md
495
+ - .planning/reviews/${PHASE_NUMBER}/hardener.md
496
+ </files_to_read>
497
+ <output_path>.planning/reviews/${PHASE_NUMBER}/meta.md</output_path>
498
+ "
499
+ )
500
+ ```
501
+ If either agent returns its report instead of writing the output path, save the returned text there with the Write tool before the merge.
471
502
 
472
- When verdict is `PASS`, no trace event needed — clean passes are the expected baseline.
503
+ c. Merge the three reports:
504
+ ```bash
505
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs review-deep merge "${PHASE_NUMBER}" \
506
+ --reviewer-file "{phase_dir}/{phase_number}-review.md" \
507
+ --hardener-file ".planning/reviews/${PHASE_NUMBER}/hardener.md" \
508
+ --meta-file ".planning/reviews/${PHASE_NUMBER}/meta.md"
509
+ ```
510
+ This writes `.planning/reviews/${PHASE_NUMBER}/deep-review.md` and prints its verdict (`ok` · `ok_with_minor` · `fix_before_merge` · `review_required` · `block`). Report the verdict and the finding count. On `review_required` or `block`, stop before verification and present the high and critical findings to the user, as with `NEEDS_FIXES`.
473
511
  </step>
474
512
 
475
513
  <step name="close_parent_artifacts">
@@ -533,41 +571,26 @@ Phase goal: {goal from roadmap.md}
533
571
  Phase requirement IDs: {phase_req_ids}
534
572
  Check must_haves against actual codebase.
535
573
  Cross-reference requirement IDs from PLAN frontmatter against requirements.md — every ID MUST be accounted for.
574
+ Run the project's test suite as the test gate (the run_test_suite step of @~/.claude/pan-wizard-core/workflows/verify-phase.md) and record test_gate in the frontmatter.
536
575
  Create verification.md.",
537
576
  subagent_type="pan-verifier",
538
577
  model="{verifier_model}"
539
578
  )
540
579
  ```
541
580
 
542
- Read status:
581
+ Record the verification and read its status:
543
582
  ```bash
544
- VERIF_STATUS=$(grep "^status:" "$PHASE_DIR"/*-verification.md | cut -d: -f2 | tr -d ' ')
583
+ VERIF_FILE=$(ls "$PHASE_DIR"/*-verification.md 2>/dev/null | head -1)
584
+ VERIF_STATUS=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings record --phase "${PHASE_NUMBER}" --file "$VERIF_FILE" --raw 2>/dev/null) \
585
+ || VERIF_STATUS=$(grep "^status:" "$VERIF_FILE" | cut -d: -f2 | tr -d ' ')
545
586
  ```
587
+ `findings record` reads the verdict from the verification frontmatter (`status`, `gaps`, `human_verification`, `unrequested`) and adds its findings to the ledger. A re-verification after a fix round is the next attempt: the gaps it no longer reports are closed, and the retry is logged. Recording the same file twice is a no-op, so verify-phase recording it too is safe. The grep fallback keeps the old reading when the record cannot parse the file.
546
588
 
547
- **P-1806 fix (v3.7.8):** the trace event for verify-phase outcome is logged HERE (in exec-phase.md after the verifier returns) rather than only at the end of verify-phase.md. When verification runs inline (orchestrator-as-verifier in auto mode, no separate Task spawn), the trace.log block at the bottom of verify-phase.md never executes — the orchestrator just writes verification.md and continues. By logging here, the event fires regardless of the verification path taken. Surfaced by the wookie autonomous build (v3.7.5–v3.7.7): all 5 phases used inline verification, no `verification_passed` events appeared in the trace despite v3.7.5 adding the trace block to verify-phase.md.
548
-
549
- ```bash
550
- if [ "$VERIF_STATUS" = "passed" ]; then
551
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
552
- --type decision --category verification_passed \
553
- --description "Phase ${PHASE_NUMBER} verification passed (logged from exec-phase, P-1806)" \
554
- --agent pan-verifier --impact minor 2>/dev/null || true
555
- elif [ "$VERIF_STATUS" = "gaps_found" ]; then
556
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
557
- --type error --category verification_gaps \
558
- --description "Phase ${PHASE_NUMBER} verification found gaps" \
559
- --agent pan-verifier --impact major 2>/dev/null || true
560
- elif [ "$VERIF_STATUS" = "human_needed" ]; then
561
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize trace log \
562
- --type decision --category verification_human_needed \
563
- --description "Phase ${PHASE_NUMBER} verification awaiting human review" \
564
- --agent pan-verifier --impact minor 2>/dev/null || true
565
- fi
566
- ```
589
+ **Trace logging happens in the record.** The record above logs the verification outcome (`verdict_passed`, `verdict_failed` or `verdict_needs_human`) here, after the verifier returns. That covers inline verification too, which is the reason P-1806 moved the trace call here (v3.7.8). No separate `optimize trace log` call is needed.
567
590
 
568
591
  | Status | Action |
569
592
  |--------|--------|
570
- | `passed` | → update_roadmap |
593
+ | `passed` | → update_roadmap. If the verification frontmatter has `test_gate: skipped` or a `not_checked` list, say so when you report the phase: "passed — not checked: tests (no test script)". A pass never hides what it did not check |
571
594
  | `human_needed` | Present items for human testing, get approval or feedback |
572
595
  | `gaps_found` | Present gap summary, offer `/pan:plan-phase {phase} --gaps` |
573
596
 
@@ -163,6 +163,9 @@ Report final status.
163
163
  | I001 | info | Plan without SUMMARY (may be in progress) | No |
164
164
  | I002 | info | Phase in ROADMAP ahead of current phase, not planned yet | No |
165
165
  | I003 | info | Focus-model or campaign tree — the phase-model checks do not apply | No |
166
+ | I004 | info | planning-with-files shares the tree — PAN leaves its files alone | No |
167
+ | I005 | info | The planning tree is gitignored while commit_docs is true — planning commits commit nothing | No |
168
+ | I006 | info | config.json holds keys PAN does not read (usually a typo); the fix names the nearest known key | No |
166
169
  | STATE_REQ_DRIFT | warning | state.md complete but REQUIREMENTS.md has unchecked boxes | Yes |
167
170
  | STATE_ROADMAP_DRIFT | warning | state.md complete but roadmap.md has unchecked plan boxes | Yes |
168
171
  | VERIFICATION_GATE_MISSING | warning | Phase has completed plans but no verification record | No |
@@ -31,10 +31,10 @@ If `--session <id>` was specified, use that session ID.
31
31
 
32
32
  Run:
33
33
  ```
34
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize learn [--session <id>]
34
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize learn [--session <id> | --sessions <n>]
35
35
  ```
36
36
 
37
- This produces `.planning/optimization/reports/{session}-analysis.json`.
37
+ This produces `.planning/optimization/reports/{session}-analysis.json`. With `--sessions <n>` it pools the last n sessions into `pooled-<n>-{session}-analysis.json`: a recommendation should explain failures that recur across runs, not one run's accident.
38
38
 
39
39
  Read the output and note:
40
40
  - `summary.errors` — how many error events
@@ -42,6 +42,8 @@ Read the output and note:
42
42
  - `summary.memory_misses` — how many memory miss events
43
43
  - `summary.wasted_tokens` — tokens wasted on redundancies
44
44
  - `top_error_patterns` — most frequent error categories
45
+ - `top_tool_error_patterns` — failed tool calls captured from the subagents' own transcripts, ranked by how many spawns hit them
46
+ - `verdict_stats` — each judge's pass/fail counts, retries, and the retries that resolved a failure
45
47
  - `top_memory_misses` — most frequent memory miss topics
46
48
 
47
49
  ## Step 3 — Invoke pan-optimizer agent
@@ -82,6 +82,18 @@ From each verification.md, extract:
82
82
 
83
83
  If a phase is missing verification.md, flag it as "unverified phase" — this is a blocker.
84
84
 
85
+ ### 2b. Read the Recorded Findings
86
+
87
+ What the judges found in this milestone, and what was decided about each finding, is on record. Read it rather than reconstructing it from prose:
88
+
89
+ ```bash
90
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs findings debt --milestone "{version}"
91
+ ```
92
+
93
+ - **`deferred`** findings were continued past on purpose, and each carries the reason recorded at the time. They are the milestone's tech debt: put every one in `tech_debt`, with its id and reason.
94
+ - **`open`** findings were never disposed (no fix, deferral, dismissal or decision). List them under "Undisposed findings" in the report. They are not blockers by themselves: the verification gate handles blockers. They do mean the milestone cannot be `passed`, so the status is at least `tech_debt`.
95
+ - A dismissal or decision is settled and not debt. `findings list --milestone "{version}" --status dismissed` shows the dismissals and their reasons when the report needs them.
96
+
85
97
  ## 3. Spawn Integration Checker
86
98
 
87
99
  With phase context collected:
@@ -181,11 +193,11 @@ gaps: # Critical blockers
181
193
  evidence: "{specific evidence or lack thereof}"
182
194
  integration: [...]
183
195
  flows: [...]
184
- tech_debt: # Non-critical, deferred
196
+ tech_debt: # Non-critical, deferred — from `findings debt` (step 2b) plus anything the verifications list
185
197
  - phase: 01-auth
186
198
  items:
199
+ - "[f_81ab3c9d20] no password strength validation — deferred: accepted at review: PASS_WITH_WARNINGS"
187
200
  - "TODO: add rate limiting"
188
- - "Warning: no password strength validation"
189
201
  - phase: 03-dashboard
190
202
  items:
191
203
  - "Deferred: mobile responsive layout"
@@ -197,7 +209,7 @@ Plus full markdown report with tables for requirements, phases, integration, tec
197
209
  **Status values:**
198
210
  - `passed` — all requirements met, no critical gaps, minimal tech debt
199
211
  - `gaps_found` — critical blockers exist
200
- - `tech_debt` — no blockers but accumulated deferred items need review
212
+ - `tech_debt` — no blockers but accumulated deferred items need review, or recorded findings were never disposed
201
213
 
202
214
  ## 7. Present Results
203
215
 
@@ -985,7 +985,7 @@ Use AskUserQuestion:
985
985
  - .planning/roadmap.md (Current roadmap to revise)
986
986
  </files_to_read>
987
987
 
988
- Update the roadmap based on feedback. Edit files in place.
988
+ Update the roadmap based on feedback: rewrite each changed file with one Write.
989
989
  Return ROADMAP REVISED with changes made.
990
990
  </revision>
991
991
  ", subagent_type="pan-roadmapper", model="{roadmapper_model}", description="Revise roadmap")
@@ -8,6 +8,7 @@ Manage the circular optimization loop — apply reports, check stats, control tr
8
8
  |------------|--------|
9
9
  | `apply` | Apply safe recommendations from most recent report |
10
10
  | `apply --report <file>` | Apply from a specific report |
11
+ | `revert <apply_id>` / `revert --last` | Undo one apply exactly |
11
12
  | `list` | List all reports |
12
13
  | `stats` | Show cumulative stats |
13
14
  | `trace init` | Start a new trace session |
@@ -40,8 +41,9 @@ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize apply [--report <path>
40
41
 
41
42
  Show the user:
42
43
  - **Applied** — each item that was written (memory entries, notes)
43
- - **Skipped** — items that already exist or had unknown types
44
+ - **Skipped** — items that already exist, that an earlier apply already wrote, or that had unknown types
44
45
  - **Still needs review** — prompt/workflow suggestions in `suggestions.md`
46
+ - **The `apply_id`**, and how to undo the apply: `/pan:optimize revert <apply_id>`
45
47
 
46
48
  If memory entries were written, tell the user:
47
49
  > Memory entries have been added to `.planning/memory/`. They will be loaded on the next agent run, reducing future memory misses for these topics.
@@ -54,6 +56,17 @@ If `.planning/optimization/suggestions.md` exists, tell the user to review it fo
54
56
 
55
57
  ---
56
58
 
59
+ ## revert
60
+
61
+ ```
62
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize revert <apply_id>
63
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs optimize revert --last
64
+ ```
65
+
66
+ Show the user each reverted action and each refused one, with its reason. A refusal means someone edited the file after the apply, or a later apply also wrote it. Revert that later apply first; never force it. The status is `reverted`, `partial`, `refused` or `nothing_to_revert`.
67
+
68
+ ---
69
+
57
70
  ## trace init
58
71
 
59
72
  ### Step 1 — Extract description