pan-wizard 3.33.0 → 3.35.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 (214) hide show
  1. package/README.md +29 -26
  2. package/agents/pan-conductor.md +18 -17
  3. package/agents/pan-counterfactual.md +2 -2
  4. package/agents/pan-debugger.md +30 -9
  5. package/agents/pan-design-checker.md +2 -1
  6. package/agents/pan-designer.md +2 -2
  7. package/agents/pan-distiller.md +3 -3
  8. package/agents/pan-document_code.md +14 -14
  9. package/agents/pan-executor.md +30 -9
  10. package/agents/pan-experiment-runner.md +9 -8
  11. package/agents/pan-hardener.md +1 -1
  12. package/agents/pan-integration-checker.md +2 -2
  13. package/agents/pan-knowledge.md +1 -1
  14. package/agents/pan-meta-reviewer.md +4 -4
  15. package/agents/pan-optimizer.md +39 -43
  16. package/agents/pan-phase-researcher.md +10 -10
  17. package/agents/pan-plan-checker.md +37 -34
  18. package/agents/pan-planner.md +57 -44
  19. package/agents/pan-previewer.md +1 -1
  20. package/agents/pan-project-researcher.md +12 -12
  21. package/agents/pan-release.md +1 -1
  22. package/agents/pan-research-synthesizer.md +3 -3
  23. package/agents/pan-reviewer.md +26 -3
  24. package/agents/pan-roadmapper.md +15 -14
  25. package/agents/pan-verifier.md +33 -25
  26. package/bin/install-lib.cjs +176 -38
  27. package/bin/install.js +81 -63
  28. package/commands/pan/army.md +15 -11
  29. package/commands/pan/assumptions.md +2 -2
  30. package/commands/pan/audit-deployment.md +11 -12
  31. package/commands/pan/cost.md +8 -8
  32. package/commands/pan/dashboard.md +0 -3
  33. package/commands/pan/debug.md +10 -7
  34. package/commands/pan/design-phase.md +5 -5
  35. package/commands/pan/discuss-phase.md +2 -0
  36. package/commands/pan/exec-phase.md +21 -37
  37. package/commands/pan/experiment.md +9 -8
  38. package/commands/pan/focus-auto.md +22 -20
  39. package/commands/pan/focus-design.md +7 -6
  40. package/commands/pan/focus-doc-audit.md +4 -3
  41. package/commands/pan/focus-drift-walking.md +4 -3
  42. package/commands/pan/focus-exec.md +6 -6
  43. package/commands/pan/focus-plan.md +12 -11
  44. package/commands/pan/focus-scan.md +5 -3
  45. package/commands/pan/focus-sync.md +3 -2
  46. package/commands/pan/git.md +8 -8
  47. package/commands/pan/health.md +2 -2
  48. package/commands/pan/hud.md +4 -7
  49. package/commands/pan/hygiene.md +14 -7
  50. package/commands/pan/knowledge.md +9 -10
  51. package/commands/pan/learn.md +10 -7
  52. package/commands/pan/links.md +4 -1
  53. package/commands/pan/map-codebase.md +1 -1
  54. package/commands/pan/mcp-bridge.md +19 -21
  55. package/commands/pan/milestone-done.md +6 -3
  56. package/commands/pan/milestone-new.md +1 -1
  57. package/commands/pan/new-project.md +10 -10
  58. package/commands/pan/optimize.md +18 -14
  59. package/commands/pan/patches.md +2 -6
  60. package/commands/pan/pause.md +1 -1
  61. package/commands/pan/phase-tests.md +3 -2
  62. package/commands/pan/plan-phase.md +9 -19
  63. package/commands/pan/preview.md +2 -3
  64. package/commands/pan/profile.md +2 -2
  65. package/commands/pan/quick.md +1 -1
  66. package/commands/pan/remove-phase.md +1 -1
  67. package/commands/pan/report.md +3 -7
  68. package/commands/pan/research-phase.md +16 -15
  69. package/commands/pan/resume.md +9 -11
  70. package/commands/pan/retro.md +5 -3
  71. package/commands/pan/review-deep.md +7 -9
  72. package/commands/pan/settings.md +1 -1
  73. package/commands/pan/verify-phase.md +0 -11
  74. package/commands/pan/what-if.md +3 -4
  75. package/hooks/dist/pan-context-monitor.js +352 -44
  76. package/hooks/dist/pan-cost-logger.js +30 -0
  77. package/hooks/dist/pan-guard.js +244 -0
  78. package/hooks/dist/pan-statusline.js +73 -24
  79. package/hooks/dist/pan-stop-guard.js +7 -2
  80. package/package.json +1 -1
  81. package/pan-wizard-core/bin/lib/agents-md.cjs +44 -6
  82. package/pan-wizard-core/bin/lib/bridge.cjs +6 -5
  83. package/pan-wizard-core/bin/lib/campaign.cjs +4 -2
  84. package/pan-wizard-core/bin/lib/commands-learnings.cjs +19 -2
  85. package/pan-wizard-core/bin/lib/commands.cjs +57 -6
  86. package/pan-wizard-core/bin/lib/config.cjs +7 -1
  87. package/pan-wizard-core/bin/lib/constants.cjs +18 -6
  88. package/pan-wizard-core/bin/lib/context-budget.cjs +12 -9
  89. package/pan-wizard-core/bin/lib/core.cjs +53 -19
  90. package/pan-wizard-core/bin/lib/cost-rebuild.cjs +13 -1
  91. package/pan-wizard-core/bin/lib/cost.cjs +142 -13
  92. package/pan-wizard-core/bin/lib/distill.cjs +6 -3
  93. package/pan-wizard-core/bin/lib/doc-lint.cjs +30 -11
  94. package/pan-wizard-core/bin/lib/findings.cjs +135 -21
  95. package/pan-wizard-core/bin/lib/focus.cjs +13 -4
  96. package/pan-wizard-core/bin/lib/frontmatter.cjs +105 -26
  97. package/pan-wizard-core/bin/lib/hygiene.cjs +184 -17
  98. package/pan-wizard-core/bin/lib/init.cjs +13 -4
  99. package/pan-wizard-core/bin/lib/knowledge.cjs +17 -1
  100. package/pan-wizard-core/bin/lib/learn-index.cjs +111 -10
  101. package/pan-wizard-core/bin/lib/learn-lint.cjs +30 -3
  102. package/pan-wizard-core/bin/lib/memory-optimize.cjs +8 -4
  103. package/pan-wizard-core/bin/lib/memory.cjs +508 -54
  104. package/pan-wizard-core/bin/lib/milestone.cjs +8 -3
  105. package/pan-wizard-core/bin/lib/optimize.cjs +97 -17
  106. package/pan-wizard-core/bin/lib/phase-gate.cjs +174 -0
  107. package/pan-wizard-core/bin/lib/phase-remove.cjs +85 -21
  108. package/pan-wizard-core/bin/lib/phase-report.cjs +8 -2
  109. package/pan-wizard-core/bin/lib/phase.cjs +39 -13
  110. package/pan-wizard-core/bin/lib/preview.cjs +34 -31
  111. package/pan-wizard-core/bin/lib/roadmap-compact.cjs +267 -0
  112. package/pan-wizard-core/bin/lib/roadmap.cjs +243 -9
  113. package/pan-wizard-core/bin/lib/runner.cjs +2 -1
  114. package/pan-wizard-core/bin/lib/state-compact.cjs +11 -6
  115. package/pan-wizard-core/bin/lib/state.cjs +43 -28
  116. package/pan-wizard-core/bin/lib/template.cjs +11 -4
  117. package/pan-wizard-core/bin/lib/verdict.cjs +140 -10
  118. package/pan-wizard-core/bin/lib/verify-integrity.cjs +181 -0
  119. package/pan-wizard-core/bin/lib/verify-plan-set.cjs +230 -0
  120. package/pan-wizard-core/bin/lib/verify-preflight.cjs +4 -13
  121. package/pan-wizard-core/bin/lib/verify-retro.cjs +5 -3
  122. package/pan-wizard-core/bin/lib/verify-scope.cjs +11 -7
  123. package/pan-wizard-core/bin/lib/verify.cjs +30 -28
  124. package/pan-wizard-core/bin/lib/whatif.cjs +53 -9
  125. package/pan-wizard-core/bin/pan-tools.cjs +114 -19
  126. package/pan-wizard-core/learnings/index.json +5 -5
  127. package/pan-wizard-core/mcp/merge-gate.cjs +14 -3
  128. package/pan-wizard-core/mcp/native-tools.cjs +3 -3
  129. package/pan-wizard-core/opencode/pan-wizard.js +139 -0
  130. package/pan-wizard-core/references/checkpoints.md +3 -3
  131. package/pan-wizard-core/references/continuation-format.md +3 -3
  132. package/pan-wizard-core/references/decimal-phase-calculation.md +2 -3
  133. package/pan-wizard-core/references/design-methodology.md +1 -1
  134. package/pan-wizard-core/references/git-integration.md +4 -6
  135. package/pan-wizard-core/references/git-planning-commit.md +2 -2
  136. package/pan-wizard-core/references/guardrails.md +2 -2
  137. package/pan-wizard-core/references/handoff-decisions.md +3 -3
  138. package/pan-wizard-core/references/model-profile-resolution.md +5 -5
  139. package/pan-wizard-core/references/model-profiles.md +15 -10
  140. package/pan-wizard-core/references/phase-argument-parsing.md +7 -7
  141. package/pan-wizard-core/references/planning-config.md +7 -7
  142. package/pan-wizard-core/references/tdd.md +10 -1
  143. package/pan-wizard-core/references/verdict-contract.md +6 -1
  144. package/pan-wizard-core/references/verification-patterns.md +5 -5
  145. package/pan-wizard-core/templates/codebase/architecture.md +2 -2
  146. package/pan-wizard-core/templates/codebase/best-practices.md +2 -2
  147. package/pan-wizard-core/templates/codebase/concerns.md +3 -3
  148. package/pan-wizard-core/templates/codebase/integrations.md +6 -6
  149. package/pan-wizard-core/templates/codebase/relationships.md +2 -2
  150. package/pan-wizard-core/templates/codebase/stack.md +2 -2
  151. package/pan-wizard-core/templates/codebase/structure.md +4 -4
  152. package/pan-wizard-core/templates/codebase/testing.md +4 -4
  153. package/pan-wizard-core/templates/config.json +2 -6
  154. package/pan-wizard-core/templates/continue-here.md +1 -1
  155. package/pan-wizard-core/templates/debug-subagent-prompt.md +5 -3
  156. package/pan-wizard-core/templates/debug.md +15 -1
  157. package/pan-wizard-core/templates/milestone-archive.md +6 -6
  158. package/pan-wizard-core/templates/milestone.md +1 -1
  159. package/pan-wizard-core/templates/phase-prompt.md +31 -17
  160. package/pan-wizard-core/templates/planner-subagent-prompt.md +5 -5
  161. package/pan-wizard-core/templates/preview-report.md +1 -1
  162. package/pan-wizard-core/templates/research-project/architecture.md +3 -3
  163. package/pan-wizard-core/templates/research-project/features.md +1 -1
  164. package/pan-wizard-core/templates/research-project/pitfalls.md +1 -1
  165. package/pan-wizard-core/templates/research-project/stack.md +3 -3
  166. package/pan-wizard-core/templates/research.md +5 -5
  167. package/pan-wizard-core/templates/retrospective.md +1 -1
  168. package/pan-wizard-core/templates/roadmap.md +15 -15
  169. package/pan-wizard-core/templates/state.md +4 -4
  170. package/pan-wizard-core/templates/summary-complex.md +1 -0
  171. package/pan-wizard-core/templates/summary-minimal.md +1 -0
  172. package/pan-wizard-core/templates/summary-standard.md +2 -1
  173. package/pan-wizard-core/templates/summary.md +18 -2
  174. package/pan-wizard-core/templates/uat.md +3 -3
  175. package/pan-wizard-core/templates/user-setup.md +8 -8
  176. package/pan-wizard-core/templates/verification-report.md +53 -8
  177. package/pan-wizard-core/workflows/add-phase.md +1 -1
  178. package/pan-wizard-core/workflows/assumptions.md +1 -1
  179. package/pan-wizard-core/workflows/diagnose-issues.md +4 -4
  180. package/pan-wizard-core/workflows/discuss-phase.md +10 -8
  181. package/pan-wizard-core/workflows/exec-phase.md +75 -95
  182. package/pan-wizard-core/workflows/execute-plan.md +8 -7
  183. package/pan-wizard-core/workflows/health.md +13 -12
  184. package/pan-wizard-core/workflows/help.md +8 -9
  185. package/pan-wizard-core/workflows/learn.md +13 -11
  186. package/pan-wizard-core/workflows/map-codebase.md +10 -10
  187. package/pan-wizard-core/workflows/milestone-audit.md +10 -10
  188. package/pan-wizard-core/workflows/milestone-gaps.md +18 -25
  189. package/pan-wizard-core/workflows/milestone-new.md +7 -6
  190. package/pan-wizard-core/workflows/new-project.md +17 -25
  191. package/pan-wizard-core/workflows/optimize.md +11 -9
  192. package/pan-wizard-core/workflows/pause.md +6 -1
  193. package/pan-wizard-core/workflows/phase-tests.md +4 -4
  194. package/pan-wizard-core/workflows/plan-phase.md +53 -42
  195. package/pan-wizard-core/workflows/profile.md +2 -2
  196. package/pan-wizard-core/workflows/progress.md +6 -8
  197. package/pan-wizard-core/workflows/quick.md +7 -5
  198. package/pan-wizard-core/workflows/remove-phase.md +1 -1
  199. package/pan-wizard-core/workflows/research-phase.md +9 -5
  200. package/pan-wizard-core/workflows/resume-project.md +4 -6
  201. package/pan-wizard-core/workflows/retro.md +3 -1
  202. package/pan-wizard-core/workflows/settings.md +16 -24
  203. package/pan-wizard-core/workflows/todo-check.md +4 -3
  204. package/pan-wizard-core/workflows/transition.md +16 -12
  205. package/pan-wizard-core/workflows/update.md +25 -17
  206. package/pan-wizard-core/workflows/verify-phase.md +22 -20
  207. package/pan-zcode/KNOWN-BETA-RISKS.md +2 -2
  208. package/pan-zcode/README.md +7 -7
  209. package/pan-zcode/bin/install-zcode.js +1 -1
  210. package/scripts/build-hooks.js +1 -0
  211. package/scripts/build-plugin.js +3 -1
  212. package/scripts/generate-skills-docs.py +15 -6
  213. package/scripts/prompt-lint.cjs +167 -0
  214. package/scripts/test-surface.cjs +1 -0
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+ // PAN Wizard plugin for OpenCode (memory optimisation O12)
3
+ //
4
+ // OpenCode was the last host without PAN's state re-injection. It runs no command
5
+ // hooks, but its plugins can add to the prompt it compacts a session with:
6
+ // `experimental.session.compacting` fires before the model writes the continuation
7
+ // summary, and strings pushed onto `output.context` go into that prompt
8
+ // (opencode.ai/docs/plugins, read 2026-10-04). This plugin pushes PAN's position —
9
+ // the phase in flight, the plan, where it stopped — read from the planning tree on
10
+ // disk, so the summary carries it. The other hosts get the same block from
11
+ // hooks/pan-state-reinject.js after compaction.
12
+ //
13
+ // Installed by the PAN installer as <opencode config dir>/plugins/pan-wizard.js,
14
+ // below the `{"type":"commonjs"}` package.json PAN writes in the config dir, so this file is
15
+ // CommonJS and exports one object both loaders accept: `{ id, server, setup }`
16
+ // (OpenCode 1 calls server(), OpenCode 2 calls setup()).
17
+ //
18
+ // Inert unless the project is a PAN project with work in flight (a state.md naming
19
+ // a current phase and a roadmap.md with an unticked phase). Never writes anything.
20
+ // Fail-open: an error adds nothing and never breaks a compaction.
21
+ //
22
+ // planningDirName(), field() and positionLines() are copies of the same logic in
23
+ // hooks/pan-state-reinject.js; tests/opencode-plugin.test.cjs pins the two to the
24
+ // same output.
25
+
26
+ const fs = require('fs');
27
+ const path = require('path');
28
+
29
+ function planningDirName() {
30
+ const raw = process.env.PAN_PLANNING_DIR || '';
31
+ if (raw.trim()) {
32
+ const rel = raw.trim().replace(/\\/g, '/');
33
+ const bad = rel.startsWith('/') || rel.startsWith('\\') || /^[A-Za-z]:/.test(rel)
34
+ || rel.split('/').includes('..');
35
+ if (!bad) return rel;
36
+ }
37
+ const track = (process.env.PAN_TRACK || '').trim();
38
+ if (track && /^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(track)) {
39
+ return `.planning/tracks/${track}`;
40
+ }
41
+ return '.planning';
42
+ }
43
+
44
+ const UNTICKED_PHASE_RE = /^- \[ \] \*\*Phase (\d+(?:\.\d+)?):/m;
45
+ const FIELD_MAX = 240;
46
+ const BLOCK_MAX = 2000;
47
+
48
+ function field(content, name) {
49
+ const m = content.match(new RegExp(`\\*\\*${name}:\\*\\*[ \\t]*(.+)`, 'i'));
50
+ if (!m) return null;
51
+ const v = m[1].trim();
52
+ if (!v || /^\[.*\]$/.test(v) || /^none$/i.test(v)) return null;
53
+ return v.length > FIELD_MAX ? v.slice(0, FIELD_MAX - 1) + '…' : v;
54
+ }
55
+
56
+ /** The position lines for a planning tree, or null when nothing is in flight. */
57
+ function positionLines(stateContent, roadmapContent) {
58
+ if (typeof stateContent !== 'string' || typeof roadmapContent !== 'string') return null;
59
+ const phase = field(stateContent, 'Current Phase');
60
+ if (!phase) return null;
61
+ const unticked = roadmapContent.match(UNTICKED_PHASE_RE);
62
+ if (!unticked) return null;
63
+ const name = field(stateContent, 'Current Phase Name');
64
+ const plan = field(stateContent, 'Current Plan');
65
+ const plans = field(stateContent, 'Total Plans in Phase');
66
+ const status = field(stateContent, 'Status');
67
+ const stoppedAt = field(stateContent, 'Stopped At');
68
+ const lastDesc = field(stateContent, 'Last Activity Description');
69
+ const resume = field(stateContent, 'Resume File');
70
+ const lines = [];
71
+ let position = `- Current phase: ${phase}${name ? ` (${name})` : ''}`;
72
+ if (plan) position += `, plan ${plan}${plans ? ` of ${plans}` : ''}`;
73
+ lines.push(position);
74
+ if (status) lines.push(`- Status: ${status}`);
75
+ if (stoppedAt) lines.push(`- Stopped at: ${stoppedAt}`);
76
+ else if (lastDesc) lines.push(`- Last activity: ${lastDesc}`);
77
+ if (resume) lines.push(`- Resume file: ${resume}`);
78
+ lines.push(`- First unbuilt roadmap phase: Phase ${unticked[1]}`);
79
+ return lines;
80
+ }
81
+
82
+ function readIfExists(p) {
83
+ try { return fs.readFileSync(p, 'utf8'); } catch { return null; }
84
+ }
85
+
86
+ /** The block to add to the compaction prompt for a project, or null. */
87
+ function compactionContext(directory) {
88
+ const rel = planningDirName();
89
+ const dir = path.join(directory, ...rel.split('/'));
90
+ const lines = positionLines(readIfExists(path.join(dir, 'state.md')), readIfExists(path.join(dir, 'roadmap.md')));
91
+ if (!lines) return null;
92
+ const block = [
93
+ 'PAN project state at this compaction — keep it in the summary so the work resumes where it stopped:',
94
+ ...lines,
95
+ `After compaction, re-read ${rel}/state.md and the current phase's plan before the next step: continue the work in flight rather than re-planning finished work.`,
96
+ ].join('\n');
97
+ return block.length > BLOCK_MAX ? block.slice(0, BLOCK_MAX - 1) + '…' : block;
98
+ }
99
+
100
+ function directoryOf(ctx) {
101
+ return (ctx && (ctx.directory || ctx.worktree)) || process.cwd();
102
+ }
103
+
104
+ /** Push PAN's block onto the first array target; fail-open, inert outside work in flight. */
105
+ function pushBlock(directory, target) {
106
+ try {
107
+ if (!Array.isArray(target)) return;
108
+ const block = compactionContext(directory);
109
+ if (block) target.push(block);
110
+ } catch { /* fail open: a compaction without PAN's block beats a broken one */ }
111
+ }
112
+
113
+ // OpenCode 1: the loader calls server() and reads its hook map.
114
+ async function server(ctx) {
115
+ const directory = directoryOf(ctx);
116
+ return {
117
+ 'experimental.session.compacting': async (input, output) => {
118
+ pushBlock(directory, output && output.context);
119
+ },
120
+ };
121
+ }
122
+
123
+ // OpenCode 2: the loader requires `setup` (or `effect`) and hooks register through
124
+ // `ctx.session.hook(name, fn)` (opencode.ai/v2/docs/build/plugins, migrate-v1). The
125
+ // compaction event's prompt parts are `system` (read from the 2.0 binary); `context`
126
+ // is the documented v1 name and the fallback.
127
+ function setup(ctx) {
128
+ try {
129
+ const directory = directoryOf(ctx);
130
+ const session = ctx && ctx.session;
131
+ if (!session || typeof session.hook !== 'function') return;
132
+ session.hook('compaction', async (event) => {
133
+ if (!event) return;
134
+ pushBlock(directory, Array.isArray(event.system) ? event.system : event.context);
135
+ });
136
+ } catch { /* fail open: a plugin that cannot register leaves the session as it was */ }
137
+ }
138
+
139
+ module.exports = { id: 'pan-wizard', server, setup };
@@ -299,7 +299,7 @@ How to verify:
299
299
  4. Mobile (375px): Sidebar hidden, hamburger menu appears
300
300
 
301
301
  ────────────────────────────────────────────────────────
302
- → YOUR ACTION: Type "approved" or describe issues
302
+ → Type "approved" or describe issues
303
303
  ────────────────────────────────────────────────────────
304
304
  ```
305
305
 
@@ -330,7 +330,7 @@ Options:
330
330
  Cons: More setup work, DIY security updates
331
331
 
332
332
  ────────────────────────────────────────────────────────
333
- → YOUR ACTION: Select supabase, clerk, or nextauth
333
+ → Select: supabase / clerk / nextauth
334
334
  ────────────────────────────────────────────────────────
335
335
  ```
336
336
 
@@ -354,7 +354,7 @@ What you need to do:
354
354
  I'll verify: vercel whoami returns your account
355
355
 
356
356
  ────────────────────────────────────────────────────────
357
- → YOUR ACTION: Type "done" when authenticated
357
+ → Type "done" when authenticated
358
358
  ────────────────────────────────────────────────────────
359
359
  ```
360
360
  </execution_protocol>
@@ -191,7 +191,7 @@ Extract: `**Phase 2: Authentication** — JWT login flow with refresh tokens`
191
191
 
192
192
  ```markdown
193
193
  Plans:
194
- - [ ] 02-03: Add refresh token rotation
194
+ - [ ] 02-03-plan.md — Add refresh token rotation
195
195
  ```
196
196
 
197
197
  Or from plan.md `<objective>`:
@@ -240,10 +240,10 @@ Sounds like an afterthought. Use "Also available:" instead.
240
240
 
241
241
  ### Don't: Fenced code blocks for commands
242
242
 
243
- ```
243
+ ~~~
244
244
  ```
245
245
  /pan:plan-phase 3
246
246
  ```
247
- ```
247
+ ~~~
248
248
 
249
249
  Fenced blocks inside templates create nesting ambiguity. Use inline backticks instead.
@@ -32,9 +32,8 @@ With existing decimals:
32
32
  ## Extract Values
33
33
 
34
34
  ```bash
35
- DECIMAL_INFO=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs phase next-decimal "${AFTER_PHASE}")
36
- DECIMAL_PHASE=$(echo "$DECIMAL_INFO" | jq -r '.next')
37
- BASE_PHASE=$(echo "$DECIMAL_INFO" | jq -r '.base_phase')
35
+ DECIMAL_PHASE=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs phase next-decimal "${AFTER_PHASE}" --raw)
36
+ BASE_PHASE="${DECIMAL_PHASE%.*}"
38
37
  ```
39
38
 
40
39
  Or with --raw flag:
@@ -2,7 +2,7 @@
2
2
 
3
3
  Single source of truth for how PAN designs a change **before** it is planned or
4
4
  executed. Cited by `pan-designer` (main flow, via `/pan:design-phase`) and by
5
- `focus-design` (the `/featureAI` feature pipeline). Both flows use the *same*
5
+ `/pan:focus-design` (the feature investigation and design pipeline). Both flows use the *same*
6
6
  method at different **depth tiers** so design quality can't drift between them.
7
7
 
8
8
  This reference defines: the depth tiers, what each tier must produce, and the
@@ -13,9 +13,9 @@ The git log should read like a changelog of what shipped, not a diary of plannin
13
13
 
14
14
  | Event | Commit? | Why |
15
15
  | ----------------------- | ------- | ------------------------------------------------ |
16
- | BRIEF + ROADMAP created | YES | Project initialization |
17
- | plan.md created | NO | Intermediate - commit with plan completion |
18
- | research.md created | NO | Intermediate |
16
+ | project.md + roadmap.md created | YES | Project initialization |
17
+ | plan.md created | YES | pan-planner: `docs({phase}): create phase plan` |
18
+ | research.md created | OPTIONAL | phase researcher: `docs({phase}): research phase domain` |
19
19
  | discovery.md created | NO | Intermediate |
20
20
  | **Task completed** | YES | Atomic unit of work (1 commit per task) |
21
21
  | **Plan completed** | YES | Metadata commit (SUMMARY + STATE + ROADMAP) |
@@ -40,7 +40,7 @@ If NO_GIT: Run `git init` silently. PAN projects always get their own repo.
40
40
  ```
41
41
  docs: initialize [project-name] ([N] phases)
42
42
 
43
- [One-liner from PROJECT.md]
43
+ [One-liner from project.md]
44
44
 
45
45
  Phases:
46
46
  1. [phase-name]: [goal]
@@ -205,8 +205,6 @@ Each plan produces 2-4 commits (tasks + metadata). Clear, granular, bisectable.
205
205
  <anti_patterns>
206
206
 
207
207
  **Still don't commit (intermediate artifacts):**
208
- - plan.md creation (commit with plan completion)
209
- - research.md (intermediate)
210
208
  - discovery.md (intermediate)
211
209
  - Minor planning tweaks
212
210
  - "Fixed typo in roadmap"
@@ -28,8 +28,8 @@ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs commit "" --files .planning/cod
28
28
  | execute-phase | phase | `docs(phase-03): complete authentication phase` |
29
29
  | new-milestone | milestone | `docs: start milestone v1.1` |
30
30
  | remove-phase | chore | `chore: remove phase 17 (dashboard)` |
31
- | insert-phase | phase | `docs: insert phase 16.1 (critical fix)` |
32
- | add-phase | phase | `docs: add phase 07 (settings page)` |
31
+ | insert-phase | — | no commit (the user decides when to commit) |
32
+ | add-phase | — | no commit |
33
33
 
34
34
  ## When to Skip
35
35
 
@@ -9,8 +9,8 @@ phase — context compaction may have dropped earlier sections.
9
9
 
10
10
  | Shortcut | Why it fails | Correct action |
11
11
  |----------|--------------|----------------|
12
- | "User's request is clear, no need to clarify" | You're guessing at intent. Phase 0 catches misunderstandings before scaffolding. | Run the Phase 0 4-question check (see `new-project.md` / `plan-phase.md`). |
13
- | "Phase tests passed locally, /pan:verify-phase isn't needed" | One run isn't validation. verify-phase checks state consistency, doc sync, blockers, and the full suite — not just the phase's own tests. | Always run `/pan:verify-phase` before marking a phase complete. |
12
+ | "User's request is clear, no need to clarify" | You're guessing at intent. Phase 0 catches misunderstandings before scaffolding. | Run the Phase 0 clarification check (see `new-project.md` / `plan-phase.md`). |
13
+ | "Phase tests passed locally, /pan:verify-phase isn't needed" | One run isn't validation. verify-phase checks the phase goal against the code (must-haves, artifacts, wiring, requirements, anti-patterns) and runs the full test suite — not just the phase's own tests. | Always run `/pan:verify-phase` before marking a phase complete. |
14
14
  | "I'll skip /pan:focus-scan and pick the next item myself" | Manual selection ignores priority/budget logic in `focus.cjs`. You'll bias toward easy items and miss higher-priority work. | Use `/pan:focus-scan` → `/pan:focus-plan` → `/pan:focus-exec`. |
15
15
  | "I'll bump the model / add a flag / refactor while I'm here" | Scope creep. The user asked for one change; surrounding cleanup belongs in a separate item. | Do only the requested change. Note unrelated cleanup as a TODO for a future focus-scan. |
16
16
  | "I'll mark this phase complete; the docs can lag behind" | Doc/state drift compounds. By the next session, the agent reads stale docs and proceeds on false assumptions. | Run the doc-sync step (update CHANGELOG/state and commit via `pan-tools commit`) before phase completion. CHANGELOG and version bumps are part of the phase, not after it. |
@@ -55,7 +55,7 @@ No decisions worth documenting — plan is mechanical implementation of must_hav
55
55
  - **Open** — Choices left to the executor's judgment, but bounded.
56
56
  The planner names the decision space and the constraints; the
57
57
  executor picks within them. The executor should log which option
58
- they took in the summary's `Decisions Taken`.
58
+ they took in the summary's `Implementation Decisions` → `Taken` bucket (DT-N).
59
59
  Example: "Hashing algorithm: bcrypt | argon2 | scrypt. Constraint:
60
60
  zero-deps Node builtin. Reason left open: equivalent for this use case."
61
61
 
@@ -74,7 +74,7 @@ No decisions worth documenting — plan is mechanical implementation of must_hav
74
74
 
75
75
  ## Schema — `## Implementation Decisions` (executor → verifier handoff)
76
76
 
77
- Lives in `summary.md`, after `## Files Changed`:
77
+ Lives in `summary.md`, after `## Files Created/Modified`:
78
78
 
79
79
  ```markdown
80
80
  ## Implementation Decisions
@@ -152,5 +152,5 @@ that field default to v1.
152
152
 
153
153
  - Cognition, "Don't Build Multi-Agents" (Jun 2025): https://cognition.ai/blog/dont-build-multi-agents
154
154
  - Anthropic, "How we built our multi-agent research system": https://www.anthropic.com/engineering/multi-agent-research-system
155
- - Internal: `pan-wizard-core/learnings/internal/external-research.md` P-RES-003
155
+ - Internal: P-RES-003 (PAN's source-only internal learnings)
156
156
  - Spec: this reference doc IS the spec; no separate doc.
@@ -5,7 +5,7 @@ Resolve model profile once at the start of orchestration, then use it for all Ta
5
5
  ## Resolution Pattern
6
6
 
7
7
  ```bash
8
- MODEL_PROFILE=$(cat .planning/config.json 2>/dev/null | grep -o '"model_profile"[[:space:]]*:[[:space:]]*"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"' || echo "balanced")
8
+ MODEL_PROFILE=$(cat .planning/config.json 2>/dev/null | grep -o '"model_profile"[[:space:]]*:[[:space:]]*"[^"]*"' | grep -o '"[^"]*"$' | tr -d '"'); MODEL_PROFILE=${MODEL_PROFILE:-balanced}
9
9
  ```
10
10
 
11
11
  Default: `balanced` if not set or config missing.
@@ -14,13 +14,13 @@ Default: `balanced` if not set or config missing.
14
14
 
15
15
  @~/.claude/pan-wizard-core/references/model-profiles.md
16
16
 
17
- Look up the agent in the table for the resolved profile. Pass the model parameter to Task calls:
17
+ Prefer the `*_model` fields your workflow's `init` call returns, or `pan-tools resolve-model <agent> --raw`: both apply `model_overrides` and the provider mapping, which a table lookup skips. A phase's `<!-- model_tier: … -->` pin applies only when the phase is passed: `resolve-model <agent> --metadata '{"phaseNum":"N"}' --raw`. `routing.strategy: complexity` applies to any `--metadata`, and scores only its `fileCount`, `waveCount`, `requirementCount` and `isArchitectural`: metadata without them, a bare `phaseNum` included, scores as a simple task and drops the agent one tier (an agent already on the fast tier stays there). Otherwise look up the agent in the table for the resolved profile. Pass the model parameter to Task calls:
18
18
 
19
19
  ```
20
20
  Task(
21
21
  prompt="...",
22
22
  subagent_type="pan-planner",
23
- model="{resolved_model}" # "inherit", "sonnet", or "haiku"
23
+ model="{resolved_model}" # "inherit" for the reasoning tier, otherwise the provider's model name ("sonnet"/"haiku" on Anthropic)
24
24
  )
25
25
  ```
26
26
 
@@ -30,5 +30,5 @@ Task(
30
30
 
31
31
  1. Resolve once at orchestration start
32
32
  2. Store the profile value
33
- 3. Look up each agent's model from the table when spawning
34
- 4. Pass model parameter to each Task call (values: `"inherit"`, `"sonnet"`, `"haiku"`)
33
+ 3. Take each agent's model from the init `*_model` field or `resolve-model` (the table only when neither is available)
34
+ 4. Pass that value to each Task call as is
@@ -34,7 +34,7 @@ PAN never selects your host model — it recommends a *class*. Because the `reas
34
34
 
35
35
  The IDs below are *examples* of what you can configure in each class — not an exhaustive or only-valid list. A newer release in the same class behaves the same way here.
36
36
 
37
- At install time PAN also runs a **best-effort, advisory** capability check on the model ID you have configured (`detectModelCapabilities` in `bin/install-lib.cjs`). It recognizes the current Claude generations by name, and its forward threshold per family is the last reduced-capability release it records rather than the newest release it lists: any Claude ID newer than that boundary — a new major, or a later point release inside a major it already lists — inherits that family's modern profile instead of reporting no capabilities at all. "That family's profile" is the point: a newer Haiku inherits Haiku's, which is not a 1M-context/thinking profile. An ID resolves either by matching an explicit branch in the table or — for Claude names — by carrying a family plus a readable release number strictly newer than that family's last reduced-capability release; anything that resolves neither way reads as `tier: 'unknown'` with every capability flag false. It is a name-matching heuristic, not a live probe of the model, so it can still be imprecise about something released after this table — read it as a hint, not a contract. Either way it decides one thing only: whether the installer prints a capability *warning*. No routing, mode-selection, or feature gate in PAN reads it, so a wrong guess costs you a misleading install-time line and nothing else.
37
+ At install time PAN also runs a **best-effort, advisory** capability check on the model ID you have configured (`detectModelCapabilities` in `bin/install-lib.cjs`). It recognizes the current Claude generations by name, and its forward threshold per family is the last reduced-capability release it records rather than the newest release it lists: any Claude ID newer than that boundary — a new major, or a later point release inside a major it already lists — inherits that family's modern profile instead of reporting no capabilities at all. "That family's profile" is the point: a newer Haiku inherits the newest Haiku profile the table records (1M context and thinking, at the fast tier), not Opus's. An ID resolves either by matching an explicit branch in the table or — for Claude names — by carrying a family plus a readable release number strictly newer than that family's last reduced-capability release; anything that resolves neither way reads as `tier: 'unknown'` with every capability flag false. It is a name-matching heuristic, not a live probe of the model, so it can still be imprecise about something released after this table — read it as a hint, not a contract. Either way it decides one thing only: whether the installer prints a capability *warning*. No routing, mode-selection, or feature gate in PAN reads it, so a wrong guess costs you a misleading install-time line and nothing else.
38
38
 
39
39
  | Class | Example model IDs | Role in PAN | Context | Relative cost | Notes |
40
40
  |-------|-------------------|-------------|---------|---------------|-------|
@@ -105,10 +105,13 @@ Use `/pan:profile <profile>` to see estimated cost differences before switching.
105
105
  Model resolution follows this priority chain:
106
106
 
107
107
  ```
108
- 1. Per-agent override (model_overrides in config.json) ← highest priority
109
- 2. Per-phase override (<!-- model_tier: X --> in roadmap)
110
- 3. Complexity routing (if strategy = "complexity")
111
- 4. Profile lookup (MODEL_PROFILES[agent][profile]) ← lowest priority
108
+ 1. Per-agent override (model_overrides in config.json) ← highest priority; used as-is
109
+ 2. Per-phase override (<!-- model_tier: X --> in roadmap) ← used as-is
110
+ 3. Profile lookup (MODEL_PROFILES[agent][profile]) ← the base tier
111
+ 4. Complexity routing (if strategy = "complexity") ← moves that tier ±1
112
+ 5. Capability hints (context_estimate / needs_thinking / cache_warm)
113
+ 6. Failure escalation (attempt > 1, capped by routing.max_escalations)
114
+ 7. Provider resolution (tier → model id)
112
115
  ```
113
116
 
114
117
  ### Provider Detection
@@ -117,8 +120,9 @@ PAN auto-detects the LLM provider to map tiers to the right model names:
117
120
 
118
121
  1. **Explicit config** — `routing.provider` in config.json (if not `"auto"`)
119
122
  2. **Environment variable** — `PAN_PROVIDER` env var
120
- 3. **Runtime directory** — `.claude/` → Anthropic, `.codex/` → OpenAI, `.gemini/` → Google, `.opencode/` → OpenAI, `.github/` → default (first match wins)
121
- 4. **Fallback** — Default provider map (Anthropic-style names)
123
+ 3. **OpenCode's configured model** — on an OpenCode install, the provider prefix (anthropic, openai or google) of `model` in `opencode.json` or `.opencode/opencode.json`
124
+ 4. **Runtime directory** — `.claude/` → Anthropic, `.codex/` → OpenAI, `.gemini/` → Google, `.opencode/` → OpenAI, `.github/` → default (first match wins)
125
+ 5. **Fallback** — Default provider map (Anthropic-style names)
122
126
 
123
127
  ---
124
128
 
@@ -136,7 +140,7 @@ Set in `.planning/config.json` under the `routing` section:
136
140
  }
137
141
  ```
138
142
 
139
- Every agent always gets the tier assigned by its profile. Predictable and simple.
143
+ Every agent gets the tier its profile assigns, with no complexity scoring; only capability hints and failure escalation (steps 5–6 above) can still move it, when the caller passes them. Predictable and simple.
140
144
 
141
145
  ### Complexity
142
146
 
@@ -232,6 +236,7 @@ Full routing config in `.planning/config.json`:
232
236
  | `routing.cascade_quality_gate` | `true`, `false` | `true` | Reserved for future cascade routing |
233
237
  | `routing.complexity_thresholds.downgrade_max` | number | `2` | Max complexity score to downgrade tier |
234
238
  | `routing.complexity_thresholds.upgrade_min` | number | `6` | Min complexity score to upgrade tier |
239
+ | `routing.max_escalations` | integer | `1` | How many tiers a retry may climb (failure escalation) |
235
240
 
236
241
  ---
237
242
 
@@ -243,12 +248,12 @@ Runtime: `/pan:profile <profile>`
243
248
 
244
249
  | Direction | Example | Behavior |
245
250
  |-----------|---------|----------|
246
- | Downgrade | quality → balanced | Confirmation required |
251
+ | Same tier | quality → balanced | Proceeds silently (both resolve every agent to the reasoning tier) |
247
252
  | Downgrade | balanced → budget | Confirmation required |
248
253
  | Upgrade | budget → balanced | Proceeds silently |
249
254
  | Same | balanced → balanced | Proceeds silently |
250
255
 
251
- **Tier Order:** `quality` (3) > `balanced` (2) > `budget` (1)
256
+ **Tier Order:** `quality` = `balanced` (2) > `budget` (1)
252
257
 
253
258
  ---
254
259
 
@@ -19,11 +19,11 @@ PHASE_INFO=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs find-phase "${PHAS
19
19
 
20
20
  Returns JSON with:
21
21
  - `found`: true/false
22
- - `directory`: Full path to phase directory
22
+ - `directory`: Phase directory, relative to the project root (e.g., ".planning/phases/06-foundation")
23
23
  - `phase_number`: Normalized number (e.g., "06", "06.1")
24
24
  - `phase_name`: Name portion (e.g., "foundation")
25
- - `plans`: Array of PLAN.md files
26
- - `summaries`: Array of SUMMARY.md files
25
+ - `plans`: Array of plan file names (e.g., "06-01-plan.md")
26
+ - `summaries`: Array of summary file names (e.g., "06-01-summary.md")
27
27
 
28
28
  ## Manual Normalization (Legacy)
29
29
 
@@ -33,10 +33,10 @@ Zero-pad integer phases to 2 digits. Preserve decimal suffixes.
33
33
  # Normalize phase number
34
34
  if [[ "$PHASE" =~ ^[0-9]+$ ]]; then
35
35
  # Integer: 8 → 08
36
- PHASE=$(printf "%02d" "$PHASE")
36
+ PHASE=$(printf "%02d" "$((10#$PHASE))")
37
37
  elif [[ "$PHASE" =~ ^([0-9]+)\.([0-9]+)$ ]]; then
38
38
  # Decimal: 2.1 → 02.1
39
- PHASE=$(printf "%02d.%s" "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}")
39
+ PHASE=$(printf "%02d.%s" "$((10#${BASH_REMATCH[1]}))" "${BASH_REMATCH[2]}")
40
40
  fi
41
41
  ```
42
42
 
@@ -45,8 +45,8 @@ fi
45
45
  Use `roadmap get-phase` to validate phase exists:
46
46
 
47
47
  ```bash
48
- PHASE_CHECK=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs roadmap get-phase "${PHASE}")
49
- if [ "$(echo "$PHASE_CHECK" | jq -r '.found')" = "false" ]; then
48
+ PHASE_SECTION=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs roadmap get-phase "${PHASE}" --raw) # empty when the phase is not in the roadmap
49
+ if [ -z "$PHASE_SECTION" ]; then
50
50
  echo "ERROR: Phase ${PHASE} not found in roadmap"
51
51
  exit 1
52
52
  fi
@@ -14,7 +14,7 @@ Configuration options for `.planning/` directory behavior.
14
14
  | Option | Default | Description |
15
15
  |--------|---------|-------------|
16
16
  | `commit_docs` | `true` | Whether to commit planning artifacts to git |
17
- | `search_gitignored` | `false` | Add `--no-ignore` to broad rg searches |
17
+ | `search_gitignored` | `false` | Reserved — no workflow or agent acts on it; to include `.planning/` in a broad rg search, add `--no-ignore` yourself |
18
18
  | `branching_strategy` | `"none"` | Git branching approach: `"none"`, `"phase"`, or `"milestone"` |
19
19
  | `phase_branch_template` | `"pan/phase-{phase}-{slug}"` | Branch template for phase strategy |
20
20
  | `milestone_branch_template` | `"pan/{milestone}-{slug}"` | Branch template for milestone strategy |
@@ -42,14 +42,14 @@ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs commit "docs: update state" --f
42
42
 
43
43
  # Load config via state load (returns JSON):
44
44
  INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state load)
45
- # commit_docs is available in the JSON output
45
+ # commit_docs is at .config.commit_docs in the JSON output
46
46
 
47
47
  # Or use init commands which include commit_docs:
48
48
  INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs init execute-phase "1")
49
49
  # commit_docs is included in all init command outputs
50
50
  ```
51
51
 
52
- **Auto-detection:** If `.planning/` is gitignored, `commit_docs` is automatically `false` regardless of config.json. This prevents git errors when users have `.planning/` in `.gitignore`.
52
+ **Gitignored planning tree:** if `.planning/` is gitignored, `pan-tools commit` and `phase complete` skip their commit (`commit` reports `reason: skipped_gitignored`, exit 0) whatever `commit_docs` says; `commit_docs` itself still reads as configured, and `/pan:health` reports the mismatch as I005.
53
53
 
54
54
  **Commit via CLI (handles checks automatically):**
55
55
 
@@ -68,8 +68,8 @@ The CLI checks `commit_docs` config and gitignore status internally — no manua
68
68
  - Direct path searches work: `rg "pattern" .planning/` finds files
69
69
  - Broad searches skip gitignored: `rg "pattern"` skips `.planning/`
70
70
 
71
- **When `search_gitignored: true`:**
72
- - Add `--no-ignore` to broad rg searches that should include `.planning/`
71
+ **When `search_gitignored: true`:** nothing changes — no workflow or agent reads the setting.
72
+ - To include `.planning/` in a broad rg search, add `--no-ignore` to that `rg` call yourself
73
73
  - Only needed when searching entire repo and expecting `.planning/` matches
74
74
 
75
75
  **Note:** Most PAN operations use direct file reads or explicit paths, which work regardless of gitignore status.
@@ -147,7 +147,7 @@ INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs init execute-phase "1")
147
147
  Or use `state load` for the config values:
148
148
  ```bash
149
149
  INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state load)
150
- # Parse branching_strategy, phase_branch_template, milestone_branch_template from JSON
150
+ # Parse .config.branching_strategy, .config.phase_branch_template, .config.milestone_branch_template from JSON
151
151
  ```
152
152
 
153
153
  **Branch creation:**
@@ -168,7 +168,7 @@ if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
168
168
  fi
169
169
  ```
170
170
 
171
- **Merge options at milestone-done:**
171
+ **Merge options after milestone-done (it does not merge — run one yourself):**
172
172
 
173
173
  | Option | Git command | Result |
174
174
  |--------|-------------|--------|
@@ -41,6 +41,15 @@ Each TDD plan implements **one feature** through the full RED-GREEN-REFACTOR cyc
41
41
  phase: XX-name
42
42
  plan: NN
43
43
  type: tdd
44
+ wave: N
45
+ depends_on: []
46
+ files_modified: []
47
+ autonomous: true
48
+ requirements: []
49
+ must_haves:
50
+ truths: []
51
+ artifacts: []
52
+ key_links: []
44
53
  ---
45
54
 
46
55
  <objective>
@@ -51,7 +60,7 @@ Output: [Working, tested feature]
51
60
 
52
61
  <context>
53
62
  @.planning/project.md
54
- @.planning/roadmap.md
63
+ @.planning/phases/XX-name/{phase}-roadmap-slice.md
55
64
  @relevant/source/files.ts
56
65
  </context>
57
66
 
@@ -26,6 +26,7 @@ A judging agent ends its report with one fenced `pan-verdict` block. The block i
26
26
  | `verdict` | yes | your own verdict word (table below) |
27
27
  | `outcome` | yes | `pass`, `fail` or `needs_human` |
28
28
  | `findings` | yes (may be empty) | a list of `{class, severity, where, summary}` |
29
+ | `resolutions` | on a re-check | a list of `{id, status, evidence}` answering each earlier open finding you were given in `<open_findings>`: `status` is `resolved` (with `evidence`: what you checked and saw), `still_present` or `cannot_tell`. A finding you leave out stays open, and `resolved` without evidence is recorded as `cannot_tell` |
29
30
  | `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
 
31
32
  | Agent | `verdict` → `outcome` |
@@ -36,6 +37,10 @@ A judging agent ends its report with one fenced `pan-verdict` block. The block i
36
37
 
37
38
  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
 
40
+ **Findings close on evidence, never on silence.** An earlier finding closes only when the judge answers it `resolved` with evidence (a `resolutions` entry, or a truth in the verifier's `re_verification.gaps_closed`), or, for a `code-fact:` finding, when that fact passes. A finding the new report neither repeats nor answers stays open and is listed as `unaddressed`. A reworded report of an earlier finding (same class family, where `missing` and `partial` count as one; same file; same truth or a similar summary) keeps the earlier id.
41
+
42
+ **Code facts only lower a verdict (two-key verdict).** A fact the engine measures can turn a judge's `pass` or `needs_human` into a fail, never the reverse. `test_gate: failed` under `status: passed` records as `gaps_found`: the record keeps the judge's own word as `agent_verdict`, names the fact in `lowered_by`, and adds a high finding at `code-fact:test_gate` for the gap round to close. `findings record --raw` prints the lowered word, so the workflow routes to gap closure.
43
+
39
44
  ## `class`: what kind of finding
40
45
 
41
46
  | Class | Use when |
@@ -67,7 +72,7 @@ The verifier does not emit this block. Its verification.md frontmatter (`status`
67
72
  - `where`: `NN-MM-plan.md` or `NN-MM-plan.md#task-N`.
68
73
 
69
74
  **pan-reviewer.**
70
- - Classes by category: Convention → `quality`, Security → `risk`, Code Quality → `defect`, work no plan asked for → `unrequested`.
75
+ - Classes by category: Convention → `quality`, Security → `risk`, Code Quality → `defect`, Design smell → `quality`, work no plan asked for → `unrequested`.
71
76
  - Severity: ERROR → `high`, WARNING → `medium`, INFO → `info`.
72
77
  - `where`: `path:line`.
73
78
 
@@ -316,7 +316,7 @@ grep -E "^$VAR_NAME=" .env .env.local 2>/dev/null
316
316
  **Substantive check:**
317
317
  ```bash
318
318
  # Variable has actual value (not placeholder)
319
- grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -v "your-.*-here|xxx|placeholder|TODO" -i
319
+ grep -E "^$VAR_NAME=.+" .env .env.local 2>/dev/null | grep -viE "your-.*-here|xxx|placeholder|TODO"
320
320
 
321
321
  # Value looks valid for type:
322
322
  # - URLs should start with http
@@ -336,7 +336,7 @@ NEXT_PUBLIC_API_URL=http://localhost:3000 # Still pointing to localhost in prod
336
336
  **Wiring check:**
337
337
  ```bash
338
338
  # Variable is actually used in code
339
- grep -r "process\.env\.$VAR_NAME|env\.$VAR_NAME" src/ --include="*.ts" --include="*.tsx"
339
+ grep -rE "process\.env\.$VAR_NAME|env\.$VAR_NAME" src/ --include="*.ts" --include="*.tsx"
340
340
 
341
341
  # Variable is in validation schema (if using zod/etc for env)
342
342
  grep -E "$VAR_NAME" src/env.ts src/env.mjs 2>/dev/null
@@ -530,7 +530,7 @@ check_exists() {
530
530
  # 2. Check for stub patterns
531
531
  check_stubs() {
532
532
  local file="$1"
533
- local stubs=$(grep -c -E "TODO|FIXME|placeholder|not implemented" "$file" 2>/dev/null || echo 0)
533
+ local stubs=$(grep -c -E "TODO|FIXME|placeholder|not implemented" "$file" 2>/dev/null); stubs=${stubs:-0}
534
534
  [ "$stubs" -gt 0 ] && echo "STUB_PATTERNS: $stubs in $file"
535
535
  }
536
536
 
@@ -547,7 +547,7 @@ check_substantive() {
547
547
  local min_lines="$2"
548
548
  local pattern="$3"
549
549
  local lines=$(wc -l < "$file" 2>/dev/null || echo 0)
550
- local has_pattern=$(grep -c -E "$pattern" "$file" 2>/dev/null || echo 0)
550
+ local has_pattern=$(grep -c -E "$pattern" "$file" 2>/dev/null); has_pattern=${has_pattern:-0}
551
551
  [ "$lines" -ge "$min_lines" ] && [ "$has_pattern" -gt 0 ] && echo "SUBSTANTIVE: $file" || echo "THIN: $file ($lines lines, $has_pattern matches)"
552
552
  }
553
553
  ```
@@ -652,7 +652,7 @@ Fixture the wrong-shape case explicitly: feed the loader `[]`, `null`, `{}`, and
652
652
 
653
653
  **Implication for the agents:** `pan-plan-checker`, `pan-verifier`, `pan-reviewer`, `pan-meta-reviewer`, `pan-hardener` should each periodically audit their own prose-vs-mechanical check ratio. If a dimension is 100% prose, ask whether the role earns its compute or whether the structural reset (fresh context, forced re-reading of plan/code) is doing the real work.
654
654
 
655
- **Source:** `pan-wizard-core/learnings/internal/external-research.md` P-RES-006 (S2R / RLVR, ACL 2025).
655
+ **Source:** P-RES-006 (S2R / RLVR, ACL 2025), recorded in PAN's source-only internal learnings.
656
656
 
657
657
  ---
658
658
 
@@ -8,7 +8,7 @@ Template for `.planning/codebase/architecture.md` - captures conceptual code org
8
8
 
9
9
  ## File Template
10
10
 
11
- ```markdown
11
+ ~~~markdown
12
12
  # Architecture
13
13
 
14
14
  **Analysis Date:** [YYYY-MM-DD]
@@ -129,7 +129,7 @@ sequenceDiagram
129
129
 
130
130
  *Architecture analysis: [date]*
131
131
  *Update when major patterns change*
132
- ```
132
+ ~~~
133
133
 
134
134
  <good_examples>
135
135
  ```markdown
@@ -8,7 +8,7 @@ Template for `.planning/codebase/best-practices.md` - assesses coding practices
8
8
 
9
9
  ## File Template
10
10
 
11
- ```markdown
11
+ ~~~markdown
12
12
  # Best Practices Assessment
13
13
 
14
14
  **Analysis Date:** [YYYY-MM-DD]
@@ -98,7 +98,7 @@ Top 3 improvements ranked by impact:
98
98
 
99
99
  *Best practices assessment: [date]*
100
100
  *Update after significant codebase changes*
101
- ```
101
+ ~~~
102
102
 
103
103
  <guidelines>
104
104
  **What belongs in best-practices.md:**