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
package/bin/install.js CHANGED
@@ -369,13 +369,11 @@ function getCommitAttribution(runtime) {
369
369
  const settings = readSettings(path.join(getGlobalDir('claude', explicitConfigDir), 'settings.json')) || {}; // unusable file = no info (read-only probe)
370
370
  result = lib.commitAttributionFromSettings(settings);
371
371
  } else if (runtime === 'copilot') {
372
- // Copilot CLI: user-editable settings live in settings.json; config.json is
373
- // legacy (auto-migrated by the CLI, now internal state) — fall back for old installs
372
+ // Copilot CLI: user settings live in settings.json only. config.json is the CLI's
373
+ // internal state, and Copilot 1.0.93 ignores user settings there (R48), so a
374
+ // stale `attribution` left in it must not decide PAN's attribution.
374
375
  const copilotDir = getGlobalDir('copilot', explicitConfigDir);
375
- let config = readSettings(path.join(copilotDir, 'settings.json')) || {}; // unusable file = no info (read-only probe)
376
- if (!config.attribution) {
377
- config = readSettings(path.join(copilotDir, 'config.json')) || {}; // unusable file = no info (read-only probe)
378
- }
376
+ const config = readSettings(path.join(copilotDir, 'settings.json')) || {}; // unusable file = no info (read-only probe)
379
377
  if (!config.attribution || config.attribution.commit === undefined) {
380
378
  result = undefined;
381
379
  } else if (config.attribution.commit === '') {
@@ -445,6 +443,8 @@ function copyFlattenedCommands(srcDir, destDir, prefix, pathPrefix, runtime) {
445
443
  content = content.replace(globalClaudeRegex, pathPrefix);
446
444
  content = content.replace(localClaudeRegex, `./${getDirName(runtime)}/`);
447
445
  content = content.replace(opencodeDirRegex, pathPrefix);
446
+ // As in copyWithPathReplacement: no `pan-tools` bin is on PATH.
447
+ content = content.replace(/\bpan-tools\b(?=\s+[a-z])/g, `node ${pathPrefix}pan-wizard-core/bin/pan-tools.cjs`);
448
448
  content = processAttribution(content, getCommitAttribution(runtime));
449
449
  content = convertClaudeToOpencodeFrontmatter(content);
450
450
 
@@ -504,6 +504,7 @@ function copyCommandsAsCodexSkills(srcDir, skillsDir, prefix, pathPrefix, runtim
504
504
  content = content.replace(globalClaudeRegex, pathPrefix);
505
505
  content = content.replace(localClaudeRegex, `./${getDirName(runtime)}/`);
506
506
  content = content.replace(codexDirRegex, pathPrefix);
507
+ content = lib.rewriteAgentFileRefs(content, runtime, pathPrefix);
507
508
  // Codex executes commands literally; no `pan-tools` bin on PATH.
508
509
  const panToolsPath = `${pathPrefix}pan-wizard-core/bin/pan-tools.cjs`;
509
510
  content = content.replace(/\bpan-tools\b(?=\s+[a-z])/g, `node ${panToolsPath}`);
@@ -821,6 +822,7 @@ function copyCommandsAsCopilotSkills(srcDir, skillsDir, prefix, pathPrefix, runt
821
822
  const localClaudeRegex = /\.\/\.claude\//g;
822
823
  content = content.replace(globalClaudeRegex, pathPrefix);
823
824
  content = content.replace(localClaudeRegex, `./${getDirName(runtime)}/`);
825
+ content = lib.rewriteAgentFileRefs(content, runtime, pathPrefix);
824
826
  // Copilot CLI executes commands literally; there's no `pan-tools` bin on PATH.
825
827
  // Replace bare `pan-tools` invocations with the explicit node + .cjs path.
826
828
  const panToolsPath = `${pathPrefix}pan-wizard-core/bin/pan-tools.cjs`;
@@ -876,6 +878,11 @@ function copyWithPathReplacement(srcDir, destDir, pathPrefix, runtime, isCommand
876
878
  const localClaudeRegex = /\.\/\.claude\//g;
877
879
  content = content.replace(globalClaudeRegex, pathPrefix);
878
880
  content = content.replace(localClaudeRegex, `./${dirName}/`);
881
+ // No runtime puts a `pan-tools` bin on PATH: invoke it via node, as the Codex
882
+ // and Copilot converters already did. A bare `pan-tools <verb>` in an installed
883
+ // Claude, Gemini or OpenCode command or workflow was a call that could not run.
884
+ content = content.replace(/\bpan-tools\b(?=\s+[a-z])/g, `node ${pathPrefix}pan-wizard-core/bin/pan-tools.cjs`);
885
+ content = lib.rewriteAgentFileRefs(content, runtime, pathPrefix);
879
886
  content = processAttribution(content, getCommitAttribution(runtime));
880
887
 
881
888
  // Convert frontmatter for opencode compatibility
@@ -1213,7 +1220,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1213
1220
  // 4. Remove PAN hooks (scripts + Copilot CLI hooks config file)
1214
1221
  const hooksDir = path.join(targetDir, 'hooks');
1215
1222
  if (fs.existsSync(hooksDir)) {
1216
- const panHooks = ['pan-statusline.js', 'pan-check-update.js', 'pan-check-update.sh', 'pan-context-monitor.js', 'pan-cost-logger.js', 'pan-trace-logger.js', 'pan-stop-guard.js', 'pan-state-reinject.js', 'pan.json'];
1223
+ const panHooks = ['pan-statusline.js', 'pan-check-update.js', 'pan-check-update.sh', 'pan-guard.js', 'pan-context-monitor.js', 'pan-cost-logger.js', 'pan-trace-logger.js', 'pan-stop-guard.js', 'pan-state-reinject.js', 'pan.json'];
1217
1224
  let hookCount = 0;
1218
1225
  for (const hook of panHooks) {
1219
1226
  const hookPath = path.join(hooksDir, hook);
@@ -1244,6 +1251,16 @@ function uninstall(isGlobal, runtime = 'claude') {
1244
1251
  }
1245
1252
  }
1246
1253
 
1254
+ // 4a'. Remove the OpenCode plugin (O12); the plugins directory goes too when
1255
+ // nothing else is in it.
1256
+ const opencodePlugin = path.join(targetDir, 'plugins', OPENCODE_PLUGIN_FILE);
1257
+ if (fs.existsSync(opencodePlugin)) {
1258
+ try { fs.unlinkSync(opencodePlugin); } catch {}
1259
+ try { fs.rmdirSync(path.dirname(opencodePlugin)); } catch { /* not empty: the user's own plugins stay */ }
1260
+ removedCount++;
1261
+ console.log(` ${green}✓${reset} Removed the PAN plugin`);
1262
+ }
1263
+
1247
1264
  // 4b. Codex: strip PAN entries from the shared .codex/hooks.json (foreign
1248
1265
  // hook registrations are preserved; the file is deleted only when nothing
1249
1266
  // but PAN content remained).
@@ -1557,35 +1574,12 @@ function uninstall(isGlobal, runtime = 'claude') {
1557
1574
  // CodeQL js/file-system-race. Same idiom as the hooks' metrics read.
1558
1575
  try {
1559
1576
  const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
1560
- let modified = false;
1561
-
1562
- // Remove PAN permission entries
1563
- if (config.permission) {
1564
- for (const permType of ['read', 'external_directory']) {
1565
- if (config.permission[permType]) {
1566
- const keys = Object.keys(config.permission[permType]);
1567
- for (const key of keys) {
1568
- // Match `pan-wizard` rather than `pan-wizard-core` so the malformed
1569
- // key earlier versions wrote (`~/.config/opencode/pan-wizard/*`) is
1570
- // cleaned too. Without this, machines that ran any global OpenCode
1571
- // install before the glob was fixed keep that entry forever — the
1572
- // uninstaller could never match it, which is what made it residue
1573
- // rather than a cosmetic typo.
1574
- if (key.includes('pan-wizard')) {
1575
- delete config.permission[permType][key];
1576
- modified = true;
1577
- }
1578
- }
1579
- // Clean up empty objects
1580
- if (Object.keys(config.permission[permType]).length === 0) {
1581
- delete config.permission[permType];
1582
- }
1583
- }
1584
- }
1585
- if (Object.keys(config.permission).length === 0) {
1586
- delete config.permission;
1587
- }
1588
- }
1577
+ let modified;
1578
+
1579
+ // Remove PAN permission entries, v1 `permission` keys and OpenCode 2
1580
+ // `permissions[]` rules alike (R47). Keys matching `pan-wizard` rather than
1581
+ // `pan-wizard-core` also clean the malformed key earlier versions wrote.
1582
+ ({ modified } = lib.stripOpencodePermissions(config));
1589
1583
 
1590
1584
  if (modified) {
1591
1585
  // If stripping PAN permissions emptied the config, remove the file
@@ -1699,6 +1693,18 @@ function uninstall(isGlobal, runtime = 'claude') {
1699
1693
  console.log(` ${yellow}⚠${reset} No PAN files found to remove.`);
1700
1694
  }
1701
1695
 
1696
+ // A local install's runtime directory that the removal left empty goes too (X1).
1697
+ // Never a global one (~/.claude and the like are the host's own homes), and never a
1698
+ // directory that still holds anything: `.github` usually holds the project's files.
1699
+ if (!isGlobal) {
1700
+ try {
1701
+ if (fs.readdirSync(targetDir).length === 0) {
1702
+ fs.rmdirSync(targetDir);
1703
+ console.log(` ${green}✓${reset} Removed empty ${locationLabel}`);
1704
+ }
1705
+ } catch { /* already gone or unreadable: leave it */ }
1706
+ }
1707
+
1702
1708
  console.log(`
1703
1709
  ${green}Done!${reset} PAN has been uninstalled from ${runtimeLabel}.
1704
1710
  Your other files and settings have been preserved.
@@ -1741,10 +1747,6 @@ function configureOpencodePermissions(isGlobal = true) {
1741
1747
  }
1742
1748
  }
1743
1749
 
1744
- // Ensure permission structure exists
1745
- if (!config.permission) {
1746
- config.permission = {};
1747
- }
1748
1750
 
1749
1751
  // Build the PAN path using the actual config directory
1750
1752
  // Use ~ shorthand if it's in the default location, otherwise use full path
@@ -1761,25 +1763,9 @@ function configureOpencodePermissions(isGlobal = true) {
1761
1763
  ? '~/.config/opencode/pan-wizard-core/*'
1762
1764
  : `${opencodeConfigDir.replace(/\\/g, '/')}/pan-wizard-core/*`;
1763
1765
 
1764
- let modified = false;
1765
-
1766
- // Configure read permission
1767
- if (!config.permission.read || typeof config.permission.read !== 'object') {
1768
- config.permission.read = {};
1769
- }
1770
- if (config.permission.read[panPath] !== 'allow') {
1771
- config.permission.read[panPath] = 'allow';
1772
- modified = true;
1773
- }
1774
-
1775
- // Configure external_directory permission (the safety guard for paths outside project)
1776
- if (!config.permission.external_directory || typeof config.permission.external_directory !== 'object') {
1777
- config.permission.external_directory = {};
1778
- }
1779
- if (config.permission.external_directory[panPath] !== 'allow') {
1780
- config.permission.external_directory[panPath] = 'allow';
1781
- modified = true;
1782
- }
1766
+ // v1 `permission` object in a new or v1 file; the native `permissions[]` array
1767
+ // in a file the user already converted to OpenCode 2, never both (R47).
1768
+ const { modified } = lib.addOpencodePermissions(config, panPath);
1783
1769
 
1784
1770
  if (!modified) {
1785
1771
  return; // Already configured
@@ -1842,6 +1828,8 @@ const PATCHES_DIR_NAME = 'pan-local-patches';
1842
1828
  // the patches tree stays self-contained.
1843
1829
  const EXTERNAL_PATCHES_SUBDIR = '_external';
1844
1830
  const MANIFEST_NAME = 'pan-file-manifest.json';
1831
+ // PAN's OpenCode plugin, installed as <opencode dir>/plugins/pan-wizard.js (O12).
1832
+ const OPENCODE_PLUGIN_FILE = 'pan-wizard.js';
1845
1833
 
1846
1834
  /**
1847
1835
  * Compute SHA256 hash of file contents
@@ -1963,6 +1951,11 @@ function writeManifest(configDir, runtime = 'claude', isGlobal = false) {
1963
1951
  }
1964
1952
  }
1965
1953
  }
1954
+ // The OpenCode plugin (O12)
1955
+ const opencodePlugin = path.join(configDir, 'plugins', OPENCODE_PLUGIN_FILE);
1956
+ if (isOpencode && fs.existsSync(opencodePlugin)) {
1957
+ manifest.files[`plugins/${OPENCODE_PLUGIN_FILE}`] = fileHash(opencodePlugin);
1958
+ }
1966
1959
 
1967
1960
  try {
1968
1961
  fs.writeFileSync(path.join(configDir, MANIFEST_NAME), JSON.stringify(manifest, null, 2));
@@ -2248,7 +2241,9 @@ function install(isGlobal, runtime = 'claude') {
2248
2241
  // last; the per-runtime core remains for agents/hooks.
2249
2242
  const sharedCoreDest = path.join(agentsRoot, 'pan-wizard-core');
2250
2243
  copySharedCore(path.join(src, 'pan-wizard-core'), sharedCoreDest, corePrefix, pathPrefix, runtime);
2251
- try { fs.writeFileSync(path.join(sharedCoreDest, 'VERSION'), pkg.version); } catch { /* non-fatal */ }
2244
+ // With its newline, as the per-runtime core writes it: `/pan:update` cats the file
2245
+ // and prints the runtime flag next, which glued onto a bare version.
2246
+ try { fs.writeFileSync(path.join(sharedCoreDest, 'VERSION'), pkg.version + '\n'); } catch { /* non-fatal */ }
2252
2247
 
2253
2248
  // Canonical agent-definition reference copies (ADR-0028 agent-ref
2254
2249
  // canonicalization): shared content references these instead of the
@@ -2451,6 +2446,9 @@ function install(isGlobal, runtime = 'claude') {
2451
2446
  // Always replace ~/.claude/ as it is the source of truth in the repo
2452
2447
  const dirRegex = /~\/\.claude\//g;
2453
2448
  content = content.replace(dirRegex, pathPrefix);
2449
+ // As in copyWithPathReplacement: no `pan-tools` bin is on PATH.
2450
+ content = content.replace(/\bpan-tools\b(?=\s+[a-z])/g, `node ${pathPrefix}pan-wizard-core/bin/pan-tools.cjs`);
2451
+ content = lib.rewriteAgentFileRefs(content, runtime, pathPrefix);
2454
2452
  content = processAttribution(content, getCommitAttribution(runtime));
2455
2453
  // Codex custom agents are standalone TOML files (2026-06 format);
2456
2454
  // markdown in .codex/agents/ is not recognized. Handle before
@@ -2639,6 +2637,21 @@ function install(isGlobal, runtime = 'claude') {
2639
2637
  }
2640
2638
  }
2641
2639
 
2640
+ // OpenCode plugin (memory optimisation O12). OpenCode runs no command hooks, but a
2641
+ // plugin can add to the prompt it compacts a session with; PAN's keeps the phase
2642
+ // in flight through a compaction, as hooks/pan-state-reinject.js does on the other
2643
+ // hosts. CommonJS, beside the package.json written above.
2644
+ if (isOpencode) {
2645
+ try {
2646
+ const pluginsDir = path.join(targetDir, 'plugins');
2647
+ fs.mkdirSync(pluginsDir, { recursive: true });
2648
+ fs.copyFileSync(path.join(src, 'pan-wizard-core', 'opencode', OPENCODE_PLUGIN_FILE), path.join(pluginsDir, OPENCODE_PLUGIN_FILE));
2649
+ console.log(` ${green}✓${reset} Installed the PAN plugin to plugins/ (keeps PAN's position through compaction)`);
2650
+ } catch (e) {
2651
+ pushInstallWarning('opencodePlugin', `plugins/${OPENCODE_PLUGIN_FILE}`, e);
2652
+ }
2653
+ }
2654
+
2642
2655
  if (failures.length > 0) {
2643
2656
  console.error(`\n ${yellow}Installation incomplete!${reset} Failed: ${failures.join(', ')}`);
2644
2657
  process.exit(1);
@@ -2739,6 +2752,10 @@ function install(isGlobal, runtime = 'claude') {
2739
2752
  const stateReinjectCommand = isGlobal
2740
2753
  ? buildHookCommand(targetDir, 'pan-state-reinject.js')
2741
2754
  : 'node ' + dirName + '/hooks/pan-state-reinject.js';
2755
+ // The guard names its host: payloads and the way to deny differ per runtime (A7).
2756
+ const guardCommand = (isGlobal
2757
+ ? buildHookCommand(targetDir, 'pan-guard.js')
2758
+ : 'node ' + dirName + '/hooks/pan-guard.js') + ` --host ${runtime}`;
2742
2759
  // Gemini and Copilot (M33): a marker before the compaction, the block on the next
2743
2760
  // tool result. The inject mode names the host, whose output shapes differ.
2744
2761
  const stateReinjectMarkCommand = `${stateReinjectCommand} --mark`;
@@ -2752,7 +2769,7 @@ function install(isGlobal, runtime = 'claude') {
2752
2769
  if (!isOpencode) {
2753
2770
  const entrypoints = lib.verifyHookEntrypoints([
2754
2771
  updateCheckCommand, contextMonitorCommand, statuslineCommand, costLoggerCommand,
2755
- traceLoggerCommand, stopGuardCommand, stateReinjectCommand, stateReinjectMarkCommand, stateReinjectInjectCommand,
2772
+ traceLoggerCommand, stopGuardCommand, stateReinjectCommand, stateReinjectMarkCommand, stateReinjectInjectCommand, guardCommand,
2756
2773
  ], process.cwd());
2757
2774
  if (!entrypoints.ok) {
2758
2775
  console.error(`\n ${red}✖ Hook verification FAILED — these hook commands would run a script that is not there:${reset}`);
@@ -2772,7 +2789,7 @@ function install(isGlobal, runtime = 'claude') {
2772
2789
  let existing = null;
2773
2790
  try { existing = JSON.parse(fs.readFileSync(hooksJsonPath, 'utf8')); } catch { /* absent or invalid — start fresh */ }
2774
2791
  const merged = lib.mergeCodexHooksConfig(existing, {
2775
- updateCheckCommand, contextMonitorCommand, costLoggerCommand, traceLoggerCommand, stopGuardCommand, stateReinjectCommand,
2792
+ updateCheckCommand, contextMonitorCommand, costLoggerCommand, traceLoggerCommand, stopGuardCommand, stateReinjectCommand, guardCommand,
2776
2793
  });
2777
2794
  fs.writeFileSync(hooksJsonPath, JSON.stringify(merged, null, 2) + '\n');
2778
2795
  // Print the path we actually wrote. The hardcoded '.codex/hooks.json' was
@@ -2790,7 +2807,7 @@ function install(isGlobal, runtime = 'claude') {
2790
2807
  // from any legacy config.json registration.
2791
2808
  if (isCopilot) {
2792
2809
  const hooksConfigPath = path.join(targetDir, 'hooks', 'pan.json');
2793
- const hooksConfig = buildCopilotHooksConfig({ updateCheckCommand, contextMonitorCommand, costLoggerCommand, traceLoggerCommand, stopGuardCommand, stateReinjectMarkCommand, stateReinjectInjectCommand });
2810
+ const hooksConfig = buildCopilotHooksConfig({ updateCheckCommand, contextMonitorCommand, costLoggerCommand, traceLoggerCommand, stopGuardCommand, stateReinjectMarkCommand, stateReinjectInjectCommand, guardCommand });
2794
2811
  try {
2795
2812
  fs.mkdirSync(path.dirname(hooksConfigPath), { recursive: true });
2796
2813
  fs.writeFileSync(hooksConfigPath, JSON.stringify(hooksConfig, null, 2) + '\n');
@@ -2884,6 +2901,7 @@ function install(isGlobal, runtime = 'claude') {
2884
2901
  // unbuilt phases — fail-open and inert outside PAN projects.
2885
2902
  const registrations = [
2886
2903
  { slot: 'sessionStart', hook: 'pan-check-update', command: updateCheckCommand, label: 'update check hook' },
2904
+ { slot: 'preToolUse', hook: 'pan-guard', command: guardCommand, label: 'pre-tool guard hook' },
2887
2905
  { slot: 'postToolUse', hook: 'pan-context-monitor', command: contextMonitorCommand, label: 'context window monitor hook' },
2888
2906
  { slot: 'subagentStop', hook: 'pan-cost-logger', command: costLoggerCommand, label: 'cost logger hook' },
2889
2907
  { slot: 'subagentStop', hook: 'pan-trace-logger', command: traceLoggerCommand, label: 'trace logger hook' },
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: army
3
3
  group: Army
4
+ argument-hint: "<goal> [--source scan|backlog] [--max-cycles N] [--total-budget N] [--enforce-budget] [--verify-reserve F] [--squads a,b,c] [--no-build-worktrees] [--push] [--clean-seal] [--schedule <cadence>] [--daily-budget N] [--dry-run] [--continue] [--stop] [--status]"
4
5
  description: Bot-army campaign — Mission Control (the reasoning-tier conductor) delegates a whole-project goal to squads (architecture / build / quality / release), each squad working branch-per-agent worktrees under a hard safety harness, gated by CI + a human merge, looping plan→delegate→execute→review→integrate→learn until the goal ships or a stop condition fires.
5
6
  allowed-tools:
6
7
  - Read
@@ -25,7 +26,7 @@ The army is the campaign-scale sibling of `/pan:exec-phase --hierarchical` (one
25
26
 
26
27
  | Tier | Who | Model tier | Access |
27
28
  |------|-----|-----------|--------|
28
- | 0 · Mission Control | `pan-conductor` | `reasoning` (`mid` under `budget`) | delegation-first (Agent toolset) — instructed to route work, not write it |
29
+ | 0 · Mission Control | `pan-conductor` | the session model (spawned with no `model`, so under every profile) | delegation-first (Agent toolset) — instructed to route work, not write it |
29
30
  | 1 · Architecture | design + planning agents — `squad show architecture` lists them | `reasoning` | `read-only` |
30
31
  | 1 · Build | `pan-executor` | `reasoning` | `read-write-bash` — one branch+worktree per agent |
31
32
  | 1 · Quality | adversarial review + debug agents — `squad show quality` lists them | `mid` | `read-only`, adversarial |
@@ -34,11 +35,11 @@ The army is the campaign-scale sibling of `/pan:exec-phase --hierarchical` (one
34
35
 
35
36
  **Where each row comes from.** The tier-1 rows mirror the `squads[]` records `pan-tools squad list` prints — label, `tier`, `access` (their member names come from `squad show <name>`, since `squad list` reports only a count). The Tier 0 and Tier 2 rows are PAN's hierarchy positions: the same command names them under its `coordinator` and `workers` keys, but reports nothing else about them, so the Model-tier and Access values on those two rows are written here rather than returned by the command. Resolve the roster at runtime — never hardcode it: `pan-tools squad list` and `pan-tools squad show <name>`.
36
37
 
37
- **Reading the Model-tier column.** These are PAN *tiers*, not model names. `reasoning` resolves to `inherit` — the model you launched with — while `mid` and `fast` map to the provider's mid/fast models (Sonnet and Haiku on Anthropic).
38
+ **Reading the Model-tier column.** These are PAN *tiers*, not model names. `reasoning` resolves to `inherit` — the model you launched with — while `mid` and `fast` map to the provider's mid/fast models (Sonnet and Haiku on Anthropic). They are what `squad list` and `resolve-model` report: the army's spawns pass no model, so an agent spawned under its own type runs on its file's `model:` (the reviewer-class agents pin `opus` on Claude Code) or, without one, the session model.
38
39
 
39
40
  **Reading the Access column.** The backticked values on the tier-1 rows are the `access` labels `squad list` reports; tier 0 and tier 2 carry PAN's own. They are role contracts the conductor's prompt assigns when it delegates, not a sandbox: `squads.cjs` says of itself that it "modifies no agent and changes no execution path", so a label can differ from what an agent may actually do — expect that, since several `read-only` squad members hold `Write` to emit planning or verification artifacts. The binding grant is each agent's own `tools:` frontmatter (`grep '^tools:' ~/.claude/agents/*.md`), and Mission Control's includes `Write` and `Bash`: routing rather than coding is how it is instructed to behave, not something the runtime prevents. The rail those grants do enforce is delegation depth — `grep -l '^tools:.*Task' ~/.claude/agents/*.md` names every agent able to spawn another (today, `pan-conductor`), so a squad agent cannot fan out further.
40
41
 
41
- **Squad tier is not profile tier.** The tier column above is a `squads.cjs` grouping attribute — what `pan-tools squad list` reports — and it is not what resolves an agent's model; that comes from the active `model_profile` (`quality` and `balanced` are `reasoning` for every agent, and `budget` is the only profile that down-tiers), plus any `model:` pin in an agent's own frontmatter. So the `mid` on the Quality and Release rows does not describe what those agents run under the default profile — under `quality` and `balanced` they resolve `reasoning` like everything else. The tier-1 values above are the squad groupings; the tier-0 and tier-2 values are per-agent profile tiers. **`budget` resolves per agent, not per row:** it sends some workers to `fast` and others to `mid`, so no single value is true of the Tier 2 row — `MODEL_PROFILES` in `~/.claude/pan-wizard-core/bin/lib/core.cjs` is the table, and it is the one to read rather than a tier written into a doc. For the agents that pin a model outright, `grep -l '^model: opus' ~/.claude/agents/*.md` lists them — the pin applies on Claude Code only, since the installer strips it for the other runtimes.
42
+ **Squad tier is not profile tier.** The tier column above is a `squads.cjs` grouping attribute — what `pan-tools squad list` reports — and it is not an agent's profile tier, which is what `resolve-model` reports from the active `model_profile` (`quality` and `balanced` are `reasoning` for every agent, and `budget` is the only profile that down-tiers). The army applies neither: its spawns pass no model, so an agent runs on its own `model:` pin, else the session model, under every profile. So the `mid` on the Quality and Release rows does not describe what those agents run. The tier-1 values above are the squad groupings; the tier-2 value is the per-agent profile tier `resolve-model` reports. **`budget` resolves per agent, not per row:** `resolve-model` reports `fast` for some workers and `mid` for others, so no single value is true of the Tier 2 row — `MODEL_PROFILES` in `~/.claude/pan-wizard-core/bin/lib/core.cjs` is the table, and it is the one to read rather than a tier written into a doc. For the agents that pin a model outright, `grep -l '^model: opus' ~/.claude/agents/*.md` lists them — the pin applies on Claude Code only, since the installer strips it for the other runtimes.
42
43
 
43
44
  ---
44
45
 
@@ -75,6 +76,7 @@ Every cap the conductor enforces applies to the campaign, scaled up:
75
76
 
76
77
  ```
77
78
  /pan:army "<goal>" [--source scan|backlog] [--max-cycles N] [--total-budget N]
79
+ [--enforce-budget] [--verify-reserve F]
78
80
  [--squads a,b,c] [--no-build-worktrees] [--push] [--clean-seal]
79
81
  [--schedule <cadence>] [--daily-budget N]
80
82
  [--dry-run] [--continue] [--stop] [--status]
@@ -102,20 +104,20 @@ Every cap the conductor enforces applies to the campaign, scaled up:
102
104
 
103
105
  ```
104
106
  /pan:army
105
- Phase 0 MUSTER — squad list + roster validate · cache prime · baseline · loop-state · abort-file clear
107
+ Phase 0 MUSTER — squad list + roster validate · baseline · loop-state · abort-file clear
106
108
  Phase 1 PLAN — Mission Control (session model, xhigh effort) decomposes the goal into dependency-ordered missions
107
109
  Phase 2 DELEGATE — pick the next item (focus-auto --source) · route to the owning squad over the Agent toolset
108
110
  Phase 3 EXECUTE — Build squad: one army/<task> worktree per agent (parallel); Architecture/Quality research in parallel (read-only)
109
111
  Phase 4 REVIEW — Quality squad on the built tree: reviewer + hardener + meta → verdict ladder; a block is a hard gate
110
112
  Phase 5 INTEGRATE— Release squad: prepare squash-merge → CI/verification → ALWAYS-ASK human approval → tag → deploy hand-off
111
- Phase 6 LEARN — summaries return to Mission Control; retro/learn writes patterns to memory (this is "Dreaming")
113
+ Phase 6 LEARN — summaries return to Mission Control; retro/learn patterns go into the next mission's plan (this is "Dreaming")
112
114
  → loop to Phase 2 until a stop condition; --clean-seal once at the end
113
115
  ```
114
116
 
115
117
  ### Phase 0 — Muster (once)
116
- 1. **Onboarding gate (existing projects).** Run `pan-tools init new-project` to detect state. If `is_brownfield` (existing code) and `needs_codebase_map` (no `.planning/codebase/`), the army cannot plan blind — STOP and route through onboarding first: `/pan:map-codebase` (Architecture squad's `pan-document_code` maps the existing system into `.planning/codebase/`), then `/pan:new-project` to build `roadmap.md` + `requirements.md` *against the existing system*. Re-run `/pan:army` once a backlog exists. If a codebase map + roadmap already exist, continue.
118
+ 1. **Onboarding gate (existing projects).** Run `pan-tools init new-project` to detect state. If `is_brownfield` (existing code) and `needs_codebase_map` (no `.planning/codebase/`), the army cannot plan blind — STOP and route through onboarding first: `/pan:map-codebase` (its `pan-document_code` mappers — workers in `pan-tools squad list`, not Architecture squad members — map the existing system into `.planning/codebase/`), then `/pan:new-project` to build `roadmap.md` + `requirements.md` *against the existing system* — only when `project_exists` is false: it refuses an initialized project, which needs just the map. Re-run `/pan:army` once a backlog exists. If a codebase map + roadmap already exist, continue.
117
119
  2. `pan-tools squad list` and validate the roster is healthy.
118
- 3. Prime the cache; capture baseline (`git status` clean of project source; tests green or STOP). On a brownfield repo, the baseline is the current `main` — every `army/<task>` branch forks from it, so the existing code is never edited in place.
120
+ 3. Capture the baseline (`git status` clean of project source; tests green or STOP). On a brownfield repo, the baseline is the commit you have checked out — every `army/<task>` branch forks from it (`worktree create` bases it on `HEAD`), so the existing code is never edited in place.
119
121
  4. Ensure `.planning/orchestration/` exists; clear any stale `abort` file; init loop-state.
120
122
  5. `--dry-run` → print the plan + per-squad delegation and STOP.
121
123
 
@@ -138,7 +140,7 @@ Spawn `pan-release`. It prepares the squash-merge, runs the configured `verifica
138
140
  **Phase report (opt-in build deliverable):** when `workflow.phase_reports.enabled` is `true`, generate the mission's self-contained per-phase HTML report **in the built tree, before staging the squash-merge** — `pan-tools report phase <N>` — so the report rides along in the merge as a phase deliverable. **Never run `report index` inside a squad worktree:** the timeline index is a single shared file that aggregates *all* phases, so a worktree would see only its own phase and concurrent squads would race on it. The index is a single-writer, post-merge concern (Phase 6). Never opens a browser.
139
141
 
140
142
  ### Phase 6 — Learn (Dreaming)
141
- Squad summaries return to Mission Control. Run `/pan:retro --write-memory` (and `/pan:learn` if traces exist) so recurring patterns persist into agent memory for the next mission. Strike the landed item; update loop-state. For a scheduled campaign, also `pan-tools campaign record-run --items <n> --points <p>` so the next-due time and the day's spend advance.
143
+ Squad summaries return to Mission Control. Run `/pan:retro` (and `/pan:learn` if traces exist) and carry the recurring patterns into the next mission yourself: name them in the plan you hand the Architecture squad. Agent memory does not do this, because PAN does not load it into agents. A pattern that should outlast the campaign goes to the human at the merge gate as a proposed line for the project's instructions. Strike the landed item; update loop-state. For a scheduled campaign, also `pan-tools campaign record-run --items <n> --points <p>` so the next-due time and the day's spend advance.
142
144
 
143
145
  **Rebuild the timeline index (single writer).** When `workflow.phase_reports.enabled` and `workflow.phase_reports.index` are `true`, Mission Control — and *only* Mission Control, on the integration branch after the merge has landed — rebuilds the project index once against the now-merged set of phases: `pan-tools report index`, then commit it (the commit honors `commit_docs`). Doing this post-merge from the single conductor is what keeps `report-index.html` consistent while builds run in parallel worktrees.
144
146
 
@@ -161,7 +163,7 @@ Nothing under `pan-army-*` or on an `army/*` branch is a deliverable: the squash
161
163
  PAN is not a daemon — it cannot wake itself while the session is closed. `--schedule` arms a campaign and lets an external trigger drive it; the human merge gate is never relaxed.
162
164
 
163
165
  - **Arm:** `/pan:army "<goal>" --schedule daily --daily-budget 200` writes `.planning/orchestration/schedule.json` (cadence, daily budget, next-due) instead of running once.
164
- - **The trigger (you wire one):** a host scheduler (Claude Code routines / cron / scheduled-tasks) or a `/loop` runs `pan-tools campaign due` and, when it reports due, invokes `/pan:army --continue`. On next session open, a due campaign is surfaced as a nudge.
166
+ - **The trigger (you wire one):** a host scheduler (Claude Code routines / cron / scheduled-tasks) or a `/loop` runs `pan-tools campaign due` and, when it reports due, invokes `/pan:army --continue`. Nothing surfaces a due campaign on its own: PAN does not wake itself, so without a trigger the campaign waits until you run `/pan:army --continue` (`pan-tools campaign due` says whether one is due).
165
167
  - **Resume (`--continue`):** read the schedule + `.planning/orchestration/` + focus-auto state. If `campaign due` is true and the day's `--daily-budget` isn't spent, run the next mission(s), then `campaign record-run` (advances next-due, accrues the day's spend). If not due or budget-spent, report next-due and STOP.
166
168
  - **Bounded spend:** point budgets (`--total-budget`, `--daily-budget`) are **advisory indicators by default** — they're tracked and surfaced, not hard stops. `--enforce-budget` (or config `budget.enforce`) makes `--total-budget` a hard stop; a scheduled campaign's `--daily-budget` pauses the day's run only when the schedule was armed with `--enforce-budget` (`campaign schedule --enforce-budget`; `--advisory-budget` turns it back off). The real bounds are `--max-cycles`, the conductor caps, the abort file, and the human merge gate at every integrate. A scheduled campaign runs the backlog down to staged, reviewed, green PRs over days.
167
169
  - **Verify reserve:** a fraction of `--total-budget` (`--verify-reserve`, default 0.15) is held back so the closing Quality re-review isn't starved. Surfaced always via `campaign status` / `focus auto --status` (`into_verify_reserve`, `new_work_budget_remaining`); under `--enforce-budget` the run stops taking on new missions early (`budget_reserve_reached`) and spends the reserve on the final `--clean-seal` verification before the last INTEGRATE.
@@ -171,7 +173,9 @@ Manage it: `pan-tools campaign status` (active/paused, spent today, next-due), `
171
173
  ---
172
174
 
173
175
  ## Completion contract
174
- The campaign is complete when ANY holds: `--max-cycles` reached · backlog empty · abort file present · context < 25% · a mission cannot pass Quality and can't be cleanly reverted (HARD STOP — preserve state, report). (Budget exhaustion is advisory by default — a stop condition only when `budget.enforce`/`--enforce-budget` is set; under enforcement, crossing into the verify reserve (`budget_reserve_reached`) stops new missions but the reserved points still fund the closing re-verification.) Always run `--clean-seal` (unless omitted) after the last item.
176
+ The campaign is complete when ANY holds: `--max-cycles` reached · backlog empty · abort file present · a mission cannot pass Quality and can't be cleanly reverted (HARD STOP — preserve state, report). (Budget exhaustion is advisory by default — a stop condition only when `budget.enforce`/`--enforce-budget` is set; under enforcement, crossing into the verify reserve (`budget_reserve_reached`) stops new missions but the reserved points still fund the closing re-verification.) Before each new mission, run `pan-tools cost limits --raw`: `weekly_limit_reached` (Claude Code's 7-day usage window at `cost.weekly_limit_stop_pct`, default 90%) is a stop condition too, so the rest of the window stays the user's. Always run `--clean-seal` (unless omitted) after the last item.
177
+
178
+ The context monitor's notes are not a stop condition: they give no figure and ask for a checkpoint. On the critical note, bring the mission's state in `.planning/orchestration/` up to date and carry on. After the host compacts, re-read the campaign with `pan-tools focus auto --status` and `.planning/orchestration/`: PAN's state re-injection carries state.md's position, not the campaign's.
175
179
 
176
180
  ## NEVER DO
177
181
  - Let Mission Control write code, or let a squad agent spawn further agents (depth cap).
@@ -184,7 +188,7 @@ The campaign is complete when ANY holds: `--max-cycles` reached · backlog empty
184
188
  - Plan on the session model Mission Control inherits, delegate over the Agent toolset, keep each squad's return a tight summary.
185
189
  - One worktree per Build agent; parallel research/verify; serial human-gated integrate.
186
190
  - Check the abort file + spawn/budget caps before every spawn.
187
- - Finish with the clean-build seal; write learnings back to memory.
191
+ - Finish with the clean-build seal; carry the learnings into the next mission's plan.
188
192
 
189
193
  ## Examples
190
194
  ```
@@ -2,7 +2,7 @@
2
2
  name: pan:assumptions
3
3
  group: Phase Management
4
4
  description: Surface Claude's assumptions about a phase approach before planning
5
- argument-hint: "[phase]"
5
+ argument-hint: "<phase>"
6
6
  allowed-tools:
7
7
  - Read
8
8
  - Bash
@@ -70,7 +70,7 @@ GOOD: "Assumption: The project uses Express for routing — Evidence: require('e
70
70
  - Surface assumptions about: technical approach, implementation order, scope, risks, dependencies
71
71
  - Present assumptions clearly with file:line references where applicable
72
72
  - Prompt "What do you think?"
73
- 5. Gather feedback and offer next steps
73
+ 6. Gather feedback and offer next steps
74
74
  </process>
75
75
 
76
76
  <success_criteria>
@@ -54,8 +54,7 @@ Claude: <target>/.claude/
54
54
  Gemini: <target>/.gemini/
55
55
  OpenCode: <target>/.opencode/
56
56
  Codex: <target>/.codex/
57
- Copilot: <target>/.copilot/ (or ~/.copilot/)
58
- GitHub: <target>/.github/
57
+ Copilot: <target>/.github/ (local install) or ~/.copilot/ (global)
59
58
  ```
60
59
 
61
60
  For the detected runtime config directory (CONFIG_DIR), audit ALL of the following:
@@ -88,14 +87,14 @@ For the detected runtime config directory (CONFIG_DIR), audit ALL of the followi
88
87
  - [ ] `CONFIG_DIR/agents/` — every manifest-listed agent file present
89
88
  - Verify key agents exist: pan-planner, pan-executor, pan-verifier, pan-debugger
90
89
 
91
- **1.6 Hooks**
90
+ **1.6 Hooks** (not OpenCode: its install copies no hooks — check `CONFIG_DIR/plugins/pan-wizard.js` instead)
92
91
  - [ ] `CONFIG_DIR/hooks/pan-statusline.js` exists
93
92
  - [ ] `CONFIG_DIR/hooks/pan-check-update.js` exists
94
93
  - [ ] `CONFIG_DIR/hooks/pan-context-monitor.js` exists
95
94
 
96
95
  **1.7 Settings/Config**
97
96
  - [ ] Settings file exists (settings.json / opencode.json / config.json)
98
- - [ ] Hooks are registered — Claude `settings.json`: SessionStart, PostToolUse, SubagentStop, Stop, statusLine; Gemini `settings.json`: SessionStart and AfterAgent only (no statusLine); Codex: `.codex/hooks.json`; Copilot: `.github/hooks/pan.json`
97
+ - [ ] Hooks are registered — Claude `settings.json`: SessionStart, PostToolUse, SubagentStop, Stop, statusLine; Gemini `settings.json`: SessionStart, AfterAgent, PreCompress and AfterTool (the last two for state re-injection; no statusLine); Codex: `.codex/hooks.json`; Copilot: `.github/hooks/pan.json`
99
98
  - [ ] Hook commands point to existing files
100
99
 
101
100
  **1.8 Manifest Integrity**
@@ -137,13 +136,13 @@ Check `.planning/` directory in the target:
137
136
  - Parse state.md "Current Position" — extract phase number
138
137
  - Count actual phase directories — do they match?
139
138
  - Check roadmap.md phase count vs actual directories
140
- - Verify no orphaned .continue-here-*.md files (paused but not resumed)
139
+ - Check `.planning/phases/*/.continue-here*.md` (pause writes `.continue-here.md`): resuming does not delete it (only the transition workflow removes a completed phase's handoffs), so its presence alone does not mean the session was never resumed
141
140
 
142
141
  **2.5 Config Sanity**
143
142
  - Validate config.json values are within expected ranges
144
143
  - `model_profile`: "quality" | "balanced" | "budget"
145
144
  - `commit_docs`: boolean
146
- - `workflow.*` toggles (research, plan_check, verifier, ...): all boolean
145
+ - `workflow.*` toggles (research, plan_check, verifier, ...): boolean — except `workflow.phase_reports`, an object (`enabled`, `open`, `theme`, `index`)
147
146
  - `budget`: `default_points` numeric, `enforce` boolean
148
147
  </step>
149
148
 
@@ -170,7 +169,7 @@ For each phase with plan files (`*-plan.md`, e.g. `01-01-plan.md`):
170
169
  - Check for PAN-style commit messages
171
170
 
172
171
  **3.4 Session Continuity**
173
- - Check for .continue-here-*.md files (indicates paused sessions)
172
+ - Check for `.planning/phases/*/.continue-here*.md` files (a pause happened at some point; nothing removes them on resume)
174
173
  - Check state.md session logs for gaps
175
174
  - Look for evidence of context loss (repeated work, contradictory decisions)
176
175
 
@@ -250,7 +249,7 @@ Verification Coverage: <N>%
250
249
  If `--repair` flag was provided, attempt auto-fixes for repairable issues:
251
250
  - Regenerate missing settings.json with default hook config
252
251
  - Create missing .planning/config.json with defaults
253
- - Remove orphaned .continue-here-*.md files
252
+ - Remove `.planning/phases/*/.continue-here*.md` files the user confirms are stale
254
253
 
255
254
  Report repairs performed.
256
255
  </step>
@@ -285,10 +284,10 @@ The spec MUST follow this exact format to be consumable by superplan.md:
285
284
 
286
285
  ## Success Criteria
287
286
 
288
- ```
287
+ ~~~
289
288
  SC-1: <measurable criterion>
290
289
  SC-2: <measurable criterion>
291
- ```
290
+ ~~~
292
291
 
293
292
  ## Design
294
293
 
@@ -313,9 +312,9 @@ SC-2: <measurable criterion>
313
312
 
314
313
  ### Dependency Graph
315
314
 
316
- ```
315
+ ~~~
317
316
  A.1 ──> A.2 ──> A.3
318
- ```
317
+ ~~~
319
318
 
320
319
  ## Test Plan
321
320
 
@@ -2,7 +2,7 @@
2
2
  name: pan:cost
3
3
  group: Observability
4
4
  description: Show token usage and estimated cost across PAN commands and agents
5
- argument-hint: "[report|append|clear|rebuild] [--format json|table|chart] [--since YYYY-MM-DD] [--until YYYY-MM-DD] [--apply] [--no-main-thread]"
5
+ argument-hint: "[report|append|clear|rebuild|limits] [--format json|table|chart] [--since YYYY-MM-DD] [--until YYYY-MM-DD] [--apply] [--no-main-thread]"
6
6
  allowed-tools:
7
7
  - Read
8
8
  - Bash
@@ -13,13 +13,9 @@ Report token usage and estimated cost across all PAN invocations in this project
13
13
 
14
14
  Reads `.planning/metrics/tokens.jsonl` — an append-only log where each line is one call (agent or command) with token counts and model. Cost is computed from a built-in rate table (overridable via `.planning/config.json` → `cost.rates`).
15
15
 
16
- Default output is JSON for piping. Use `--format table` for human-readable tables or `--format chart` for an ASCII bar chart of daily spend.
16
+ Default output is JSON for piping. Use `--format table` for human-readable tables or `--format chart` for an ASCII bar chart of daily spend; both print text, with or without `--raw`.
17
17
  </objective>
18
18
 
19
- <execution_context>
20
- @~/.claude/pan-wizard-core/bin/lib/cost.cjs
21
- </execution_context>
22
-
23
19
  <subcommands>
24
20
 
25
21
  ### `report` (default)
@@ -33,7 +29,7 @@ pan-tools cost report [--format json|table|chart] [--since YYYY-MM-DD] [--until
33
29
  **Flags:**
34
30
  - `--format` — `json` (default, for tools) | `table` (aligned text columns) | `chart` (per-day ASCII bars).
35
31
  - `--since` — ISO date lower bound (inclusive). Records without `ts` always pass.
36
- - `--until` — ISO date upper bound (inclusive).
32
+ - `--until` — ISO upper bound (inclusive): a bare date covers that whole day.
37
33
 
38
34
  **JSON output shape:**
39
35
  ```json
@@ -81,6 +77,10 @@ Delete the cost log. Useful at the start of a billing cycle.
81
77
  pan-tools cost clear
82
78
  ```
83
79
 
80
+ ### `limits`
81
+
82
+ `pan-tools cost limits` shows Claude Code's 5-hour and 7-day usage windows as the status line last saw them, and whether the 7-day one has reached `cost.weekly_limit_stop_pct` (default 90%), where `/pan:focus-auto` and `/pan:army` stop. Interactive Claude Code sessions on a subscription only: headless runs and other runtimes have no reading.
83
+
84
84
  ### `rebuild`
85
85
 
86
86
  Rebuild the ledger from Claude Code's own transcripts (session file plus the per-agent files under `<session>/subagents/`, Workflow-tool subagents one level down). Rows written by hooks before v3.29 booked a slice of the parent session to whichever subagent stopped and counted turns once per content block; the rebuild replaces them with one exact row per agent transcript, typed from the main thread's `Agent` calls, plus one row per session for the main thread's own usage (`--no-main-thread` omits it). Rows whose session transcript is gone, and caller-appended rows, are kept. Dry-run by default — show the user the per-session before → after (and any `warnings`), then apply only on their say-so; the previous ledger is kept beside the new one as `tokens.jsonl.rebuilt-<date>` (a later copy never overwrites an earlier one). Run it **before** `/pan:hygiene --apply` on a poisoned ledger: quarantine moves the whole file aside, and a rebuild afterwards has no rows left to keep. The main-thread row is dated to the session's last record, so `--since`/`--until` windows and the per-day view see a session's own usage on its final day.
@@ -134,7 +134,7 @@ If `.planning/metrics/tokens.jsonl` is empty, `/pan:cost` returns zero totals
134
134
  | Runtime | Support |
135
135
  |---------|---------|
136
136
  | Claude Code | Full — data format + aggregation + all output formats |
137
- | OpenCode | Full aggregator; PAN registers no hooks on OpenCode, so records come from `pan-tools cost append` or an external script |
137
+ | OpenCode | Full aggregator; PAN's only OpenCode hook is its plugin's compaction hook (`plugins/pan-wizard.js`), so cost records come from `pan-tools cost append` or an external script |
138
138
  | Gemini | Full aggregator; PAN registers no cost hook on Gemini CLI (no subagent-completion event), so records come from `pan-tools cost append` or an external script |
139
139
  | Codex | Full — `pan-cost-logger` registered on `SubagentStop` in `.codex/hooks.json` |
140
140
  | Copilot CLI | Full aggregator; `pan-cost-logger` registered on `subagentStop` in `.github/hooks/pan.json` (token counts depend on what the payload carries) |
@@ -20,6 +20,3 @@ pan-tools hud [--out <file>] [--open] [--stdout]
20
20
  See **`/pan:hud`** for the full panel list, flags, JSON result shape, and runtime compatibility. The two commands are interchangeable.
21
21
  </objective>
22
22
 
23
- <execution_context>
24
- @~/.claude/pan-wizard-core/bin/lib/hud.cjs
25
- </execution_context>
@@ -35,7 +35,7 @@ ls .planning/debug/*.md 2>/dev/null | grep -v resolved | head -5
35
35
  INIT=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state load)
36
36
  ```
37
37
 
38
- Extract `commit_docs` from init JSON. Resolve debugger model:
38
+ Extract `config.commit_docs` from the JSON (`state load` nests it under `config`). Resolve debugger model:
39
39
  ```bash
40
40
  DEBUGGER_MODEL=$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs resolve-model pan-debugger --raw)
41
41
  ```
@@ -125,7 +125,10 @@ Task(
125
125
 
126
126
  ## 4. Handle Agent Return
127
127
 
128
- **If `## ROOT CAUSE FOUND`:**
128
+ **If `## DEBUG COMPLETE`** (the success return for `goal: find_and_fix`, after the user confirmed the fix at the `human-verify` checkpoint):
129
+ - Display the root cause, the fix, its verification and the commit; the session file is now `.planning/debug/resolved/{slug}.md`
130
+
131
+ **If `## ROOT CAUSE FOUND`** (returned only for `goal: find_root_cause_only`, which this command does not pass):
129
132
  - Display root cause and evidence summary
130
133
  - Offer options:
131
134
  - "Fix now" - spawn fix subagent
@@ -148,7 +151,7 @@ Task(
148
151
  - "Add more context" - gather more symptoms, spawn again
149
152
 
150
153
  <debug_handoff_schema>
151
- Debug session files (`.planning/debug/{slug}.md`) MUST contain structured state for cross-agent handoff:
154
+ Debug session files (`.planning/debug/{slug}.md`) follow pan-debugger's own structure (agents/pan-debugger.md, "File Structure"): frontmatter `status: gathering | investigating | diagnosed | fixing | verifying | awaiting_human_verify | resolved`, then Current Focus, Symptoms, Reproduction, Eliminated, Evidence and Resolution. The YAML below names the facts a handoff needs; its field names and status values are not the file's:
152
155
 
153
156
  ```yaml
154
157
  # Required sections in debug session file
@@ -182,7 +185,7 @@ fix: # Populated when applied
182
185
  tests_added: ["{test paths}"]
183
186
  ```
184
187
 
185
- **Why structured:** Each continuation agent starts with 0 context. Without structured state, it re-reads the entire investigation log and may re-test eliminated hypotheses. With structured state, it reads `hypotheses_tested` (skip these), checks `hypotheses_remaining` (do these next), and picks up exactly where the previous agent stopped.
188
+ **Why structured:** Each continuation agent starts with 0 context. Without structured state, it re-reads the entire investigation log and may re-test eliminated hypotheses. With structured state, it skips the hypotheses under Eliminated, starts from Current Focus `next_action`, and picks up exactly where the previous agent stopped.
186
189
  </debug_handoff_schema>
187
190
 
188
191
  ## 5. Spawn Continuation Agent (After Checkpoint)
@@ -210,9 +213,9 @@ goal: find_and_fix
210
213
  </mode>
211
214
 
212
215
  <handoff_instructions>
213
- 1. Parse the debug file's structured sections (symptoms, investigation, root_cause, fix)
214
- 2. Do NOT re-test hypotheses marked "eliminated" — they are dead ends
215
- 3. Start from hypotheses_remaining or the checkpoint's next action
216
+ 1. Parse the debug file's sections (frontmatter status, Current Focus, Symptoms, Reproduction, Eliminated, Evidence, Resolution — the format in templates/debug.md)
217
+ 2. Do NOT re-test hypotheses listed under Eliminated — they are dead ends
218
+ 3. Start from Current Focus `next_action` or the checkpoint's next action
216
219
  4. Update the debug file's structured sections as you progress
217
220
  </handoff_instructions>
218
221
  ```