pan-wizard 3.36.0 → 3.37.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 (314) hide show
  1. package/CHANGELOG.md +3645 -0
  2. package/README.md +36 -48
  3. package/agents/pan-conductor.md +2 -3
  4. package/agents/pan-counterfactual.md +1 -2
  5. package/agents/pan-debugger.md +14 -3
  6. package/agents/pan-design-checker.md +1 -2
  7. package/agents/pan-designer.md +1 -2
  8. package/agents/pan-document_code.md +1 -2
  9. package/agents/pan-hardener.md +2 -3
  10. package/agents/pan-integration-checker.md +1 -2
  11. package/agents/pan-knowledge.md +1 -2
  12. package/agents/pan-meta-reviewer.md +3 -3
  13. package/agents/pan-optimizer.md +4 -4
  14. package/agents/pan-phase-researcher.md +79 -488
  15. package/agents/pan-plan-checker.md +12 -2
  16. package/agents/pan-planner.md +10 -6
  17. package/agents/pan-previewer.md +1 -2
  18. package/agents/pan-project-researcher.md +70 -499
  19. package/agents/pan-release.md +1 -1
  20. package/agents/pan-reviewer.md +9 -3
  21. package/agents/pan-roadmapper.md +12 -7
  22. package/agents/pan-verifier.md +7 -2
  23. package/bin/install-lib.cjs +134 -14
  24. package/bin/install.js +59 -12
  25. package/commands/pan/army.md +1 -1
  26. package/commands/pan/autodev.md +76 -0
  27. package/commands/pan/exec-phase.md +3 -4
  28. package/commands/pan/focus-auto.md +14 -7
  29. package/commands/pan/focus-design.md +4 -5
  30. package/commands/pan/focus-docs.md +24 -0
  31. package/commands/pan/learn.md +13 -6
  32. package/commands/pan/milestone-audit.md +8 -1
  33. package/commands/pan/milestone-done.md +10 -5
  34. package/commands/pan/milestone-new.md +2 -2
  35. package/commands/pan/new-project.md +15 -12
  36. package/commands/pan/plan-phase.md +15 -9
  37. package/commands/pan/quick.md +1 -1
  38. package/commands/pan/review-deep.md +11 -5
  39. package/commands/pan/settings.md +6 -0
  40. package/commands/pan/verify-phase.md +6 -2
  41. package/docs/AGENTS.md +917 -0
  42. package/docs/ARCHITECTURE.md +1054 -0
  43. package/docs/CLI-REFERENCE.md +4582 -0
  44. package/docs/COMPARISON.md +116 -0
  45. package/docs/DEVELOPMENT.md +490 -0
  46. package/docs/ECOSYSTEM-REVIEW-2026-06.md +107 -0
  47. package/docs/ECOSYSTEM-REVIEW-2026-08.md +349 -0
  48. package/docs/EXAMPLES.md +584 -0
  49. package/docs/FAQ.md +254 -0
  50. package/docs/FIELD-HARVEST-2026-07.md +88 -0
  51. package/docs/FIELD-REPORT-army-2026-06.md +121 -0
  52. package/docs/HOOKS.md +638 -0
  53. package/docs/IMPROVEMENT-TODO.md +246 -0
  54. package/docs/INTERNALS.md +485 -0
  55. package/docs/MIGRATION-v2-to-v3.md +258 -0
  56. package/docs/SECURITY-HARDENING.md +230 -0
  57. package/docs/SKILLS-ENHANCEMENT-PLAN-V2.md +122 -0
  58. package/docs/SKILLS-FULL-TEXT.md +9685 -0
  59. package/docs/SKILLS-REFERENCE.md +1037 -0
  60. package/docs/TROUBLESHOOTING.md +1084 -0
  61. package/docs/USER-GUIDE.md +1437 -0
  62. package/docs/archive/SKILLS-ENHANCEMENT-PLAN.md +230 -0
  63. package/docs/audits/AUDIT-2026-08-e2e-ROADMAP.md +117 -0
  64. package/docs/audits/AUDIT-2026-08-e2e-VERIFICATION.md +693 -0
  65. package/docs/audits/AUDIT-2026-08-e2e.md +1546 -0
  66. package/docs/audits/OUTSTANDING-2026-08.md +275 -0
  67. package/docs/audits/STABILITY-TEST-2026-08.md +640 -0
  68. package/docs/branding/README-brand-draft.md +119 -0
  69. package/docs/branding/handoff/IMPLEMENTATION.md +205 -0
  70. package/docs/branding/handoff/README-brand-draft.md +119 -0
  71. package/docs/branding/handoff/image-prompts.md +46 -0
  72. package/docs/branding/image-prompts.md +46 -0
  73. package/docs/branding/nano-banana-prompts.txt +60 -0
  74. package/docs/context-monitor.md +13 -0
  75. package/docs/decisions/ADR-0001-strategic-feature-prioritization.md +83 -0
  76. package/docs/decisions/ADR-0002-copilot-cli-runtime.md +71 -0
  77. package/docs/decisions/ADR-0003-smart-execution.md +84 -0
  78. package/docs/decisions/ADR-0004-copilot-cli-interaction.md +89 -0
  79. package/docs/decisions/ADR-0005-command-naming.md +80 -0
  80. package/docs/decisions/ADR-0006-focus-commands.md +101 -0
  81. package/docs/decisions/ADR-0007-ship-v1.md +73 -0
  82. package/docs/decisions/ADR-0008-map-codebase-mermaid-togaf.md +80 -0
  83. package/docs/decisions/ADR-0009-production-deployment-checklist.md +68 -0
  84. package/docs/decisions/ADR-0010-standards-integration.md +79 -0
  85. package/docs/decisions/ADR-0011-help-commands-rewrite.md +64 -0
  86. package/docs/decisions/ADR-0012-contributors-attribution-index.md +42 -0
  87. package/docs/decisions/ADR-0013-strategic-feature-additions.md +53 -0
  88. package/docs/decisions/ADR-0014-internal-cleanup-code-quality.md +53 -0
  89. package/docs/decisions/ADR-0015-focus-auto-runner.md +296 -0
  90. package/docs/decisions/ADR-0016-enhanced-doc-sync.md +54 -0
  91. package/docs/decisions/ADR-0017-enhanced-focus-design.md +69 -0
  92. package/docs/decisions/ADR-0018-user-reality-testing.md +84 -0
  93. package/docs/decisions/ADR-0019-end-to-end-user-acceptance-testing.md +113 -0
  94. package/docs/decisions/ADR-0020-ai-drift-prevention.md +55 -0
  95. package/docs/decisions/ADR-0021-codebase-mapper-v2.md +76 -0
  96. package/docs/decisions/ADR-0022-lifecycle-completeness.md +63 -0
  97. package/docs/decisions/ADR-0023-opus-4-7-adoption.md +89 -0
  98. package/docs/decisions/ADR-0024-spec-b-v2-completion.md +137 -0
  99. package/docs/decisions/ADR-0025-behavioral-guardrails-layer.md +129 -0
  100. package/docs/decisions/ADR-0026-self-improvement-loop.md +171 -0
  101. package/docs/decisions/ADR-0027-doc-code-link-graph.md +164 -0
  102. package/docs/decisions/ADR-0028-unified-agents-skills-target.md +46 -0
  103. package/docs/decisions/ADR-0029-experiment-evaluator.md +76 -0
  104. package/docs/decisions/ADR-0030-planning-concurrency.md +37 -0
  105. package/docs/decisions/ADR-0031-focus-auto-backlog-source.md +47 -0
  106. package/docs/decisions/ADR-0032-squad-model.md +64 -0
  107. package/docs/decisions/ADR-0033-army-campaign.md +40 -0
  108. package/docs/decisions/ADR-0034-scheduled-campaigns.md +57 -0
  109. package/docs/decisions/ADR-0035-army-hud-dashboard.md +40 -0
  110. package/docs/decisions/ADR-0036-agentic-memory-architecture.md +106 -0
  111. package/docs/decisions/ADR-0037-pin-security-agents-to-opus.md +51 -0
  112. package/docs/decisions/ADR-0038-skill-aligned-decomposition.md +41 -0
  113. package/docs/decisions/ADR-0039-worktree-as-project-variant.md +37 -0
  114. package/docs/decisions/ADR-0040-memory-injection-defense.md +55 -0
  115. package/docs/decisions/ADR-0041-mcp-dual-era-bridge.md +47 -0
  116. package/docs/decisions/ADR-0042-design-parity-both-flows.md +45 -0
  117. package/docs/decisions/ADR-0043-addressable-planning-roots.md +56 -0
  118. package/docs/decisions/ADR-0044-bound-the-cached-context.md +104 -0
  119. package/docs/decisions/ADR-0045-agent-plugins-bundle.md +76 -0
  120. package/docs/decisions/ADR-0046-subagent-frontmatter-decisions.md +39 -0
  121. package/docs/decisions/ADR-0047-pan-harness.md +76 -0
  122. package/docs/decisions/ADR-0048-one-core-per-project.md +43 -0
  123. package/docs/decisions/ADR-0049-machine-verdicts-and-findings-ledger.md +116 -0
  124. package/docs/specs/ai_drift_prevention_featureai.md +286 -0
  125. package/docs/specs/codebase_mapper_v2_featureai.md +930 -0
  126. package/docs/specs/command_naming_optimization_featureai.md +930 -0
  127. package/docs/specs/comp_analysis_markdown_v1.md +149 -0
  128. package/docs/specs/continuous_autonomous_execution_featureai.md +304 -0
  129. package/docs/specs/contributors_attribution_index_featureai.md +476 -0
  130. package/docs/specs/copilot_cli_interaction_featureai.md +868 -0
  131. package/docs/specs/copilot_cli_runtime_featureai.md +647 -0
  132. package/docs/specs/custom-skills-assessment.md +461 -0
  133. package/docs/specs/deployment_audit_findings_featureai.md +243 -0
  134. package/docs/specs/doc_code_link_graph_featureai.md +253 -0
  135. package/docs/specs/documentation_alignment_cleanup_featureai.md +69 -0
  136. package/docs/specs/e2e_visual_testing_featureai.md +615 -0
  137. package/docs/specs/end_to_end_user_acceptance_testing_featureai.md +810 -0
  138. package/docs/specs/evidence-loop-plan.md +76 -0
  139. package/docs/specs/evidence_loop_featureai.md +497 -0
  140. package/docs/specs/focus-auto-optimize-category.md +449 -0
  141. package/docs/specs/focus-auto-optimize-superplan.md +188 -0
  142. package/docs/specs/focus_auto_runner_featureai.md +1102 -0
  143. package/docs/specs/focus_design_v2_featureai.md +197 -0
  144. package/docs/specs/focus_sync_v2_featureai.md +202 -0
  145. package/docs/specs/git_integration_overhaul_featureai.md +326 -0
  146. package/docs/specs/glm_zai_provider_featureai.md +200 -0
  147. package/docs/specs/googlecli_adoption_featureai.md +661 -0
  148. package/docs/specs/help_commands_rewrite_featureai.md +860 -0
  149. package/docs/specs/industry_analysis_strategic_additions_featureai.md +231 -0
  150. package/docs/specs/industry_comparison_and_feature_gaps_featureai.md +674 -0
  151. package/docs/specs/internal_cleanup_code_quality_featureai.md +486 -0
  152. package/docs/specs/investigations/README.md +31 -0
  153. package/docs/specs/investigations/digests/2026-09-28.md +47 -0
  154. package/docs/specs/investigations/digests/2026-10-08.md +62 -0
  155. package/docs/specs/investigations/digests/2026-10-10.md +61 -0
  156. package/docs/specs/investigations/features/debugger-red-loop-first.md +55 -0
  157. package/docs/specs/investigations/features/harness-cross-host-behaviour.md +93 -0
  158. package/docs/specs/investigations/features/optimize-apply-regression-gate.md +66 -0
  159. package/docs/specs/investigations/features/reviewer-smell-baseline.md +57 -0
  160. package/docs/specs/investigations/features/trace-failure-capture.md +69 -0
  161. package/docs/specs/lifecycle_completeness_featureai.md +754 -0
  162. package/docs/specs/local-first-ci.md +42 -0
  163. package/docs/specs/map_codebase_mermaid_togaf_featureai.md +805 -0
  164. package/docs/specs/market-delta-2026-09-superplan.md +310 -0
  165. package/docs/specs/market-ideas-2026-09.md +131 -0
  166. package/docs/specs/market-ideas-2026-10.md +428 -0
  167. package/docs/specs/market-ideas-ledger.md +177 -0
  168. package/docs/specs/memory-optimization-2026-10.md +285 -0
  169. package/docs/specs/multi-track-planning-roots.md +143 -0
  170. package/docs/specs/multi_model_routing_featureai.md +687 -0
  171. package/docs/specs/multi_model_routing_superplan.md +197 -0
  172. package/docs/specs/opus_47_existing_enhancements_featureai.md +247 -0
  173. package/docs/specs/opus_47_extended_features_featureai.md +363 -0
  174. package/docs/specs/opus_47_extended_features_v2_featureai.md +397 -0
  175. package/docs/specs/pan_focus_commands_featureai.md +2336 -0
  176. package/docs/specs/pan_zcode_mcp_bridge_featureai.md +120 -0
  177. package/docs/specs/product-excellence-superplan.md +315 -0
  178. package/docs/specs/product_excellence_program_2026_q4_featureai.md +365 -0
  179. package/docs/specs/production_deployment_readiness_featureai.md +433 -0
  180. package/docs/specs/production_readiness_ship_v1_featureai.md +698 -0
  181. package/docs/specs/real_test_enforcement_featureai.md +213 -0
  182. package/docs/specs/reality-check-2026-09-superplan.md +362 -0
  183. package/docs/specs/right-sized-ceremony.md +74 -0
  184. package/docs/specs/roadmap_and_competition_2026_q4_featureai.md +390 -0
  185. package/docs/specs/self_improvement_loop_featureai.md +875 -0
  186. package/docs/specs/skill-aligned-decomposition.md +155 -0
  187. package/docs/specs/standards_integration_featureai.md +833 -0
  188. package/docs/specs/testing-system-redesign-2026-09.md +267 -0
  189. package/docs/specs/user_reality_testing_system_featureai.md +788 -0
  190. package/docs/specs/watch-triggers.json +22 -0
  191. package/docs/specs/workflow-integration-redesign.md +742 -0
  192. package/docs/specs/workflow_state_consistency_featureai.md +183 -0
  193. package/hooks/dist/pan-context-monitor.js +9 -2
  194. package/hooks/dist/pan-cost-logger.js +5 -0
  195. package/hooks/dist/pan-guard.js +28 -5
  196. package/hooks/dist/pan-stop-guard.js +9 -9
  197. package/hooks/dist/pan-trace-logger.js +5 -0
  198. package/package.json +10 -2
  199. package/pan-wizard-core/bin/lib/agents-md.cjs +57 -8
  200. package/pan-wizard-core/bin/lib/autodev-report.cjs +180 -0
  201. package/pan-wizard-core/bin/lib/autodev.cjs +642 -0
  202. package/pan-wizard-core/bin/lib/ci.cjs +143 -0
  203. package/pan-wizard-core/bin/lib/commands.cjs +1 -1
  204. package/pan-wizard-core/bin/lib/config.cjs +31 -2
  205. package/pan-wizard-core/bin/lib/constants.cjs +27 -1
  206. package/pan-wizard-core/bin/lib/core.cjs +22 -10
  207. package/pan-wizard-core/bin/lib/cost.cjs +14 -4
  208. package/pan-wizard-core/bin/lib/cross-family.cjs +164 -0
  209. package/pan-wizard-core/bin/lib/debug-cases.cjs +104 -0
  210. package/pan-wizard-core/bin/lib/failure-class.cjs +81 -0
  211. package/pan-wizard-core/bin/lib/findings.cjs +34 -4
  212. package/pan-wizard-core/bin/lib/focus.cjs +1 -1
  213. package/pan-wizard-core/bin/lib/hosts.cjs +88 -0
  214. package/pan-wizard-core/bin/lib/init.cjs +7 -2
  215. package/pan-wizard-core/bin/lib/knowledge.cjs +2 -0
  216. package/pan-wizard-core/bin/lib/merge.cjs +50 -0
  217. package/pan-wizard-core/bin/lib/mutate.cjs +16 -5
  218. package/pan-wizard-core/bin/lib/next-action.cjs +112 -0
  219. package/pan-wizard-core/bin/lib/optimize.cjs +2 -2
  220. package/pan-wizard-core/bin/lib/phase.cjs +48 -4
  221. package/pan-wizard-core/bin/lib/plan-lint.cjs +150 -1
  222. package/pan-wizard-core/bin/lib/preview.cjs +23 -4
  223. package/pan-wizard-core/bin/lib/requirements-lint.cjs +130 -0
  224. package/pan-wizard-core/bin/lib/research-lint.cjs +150 -3
  225. package/pan-wizard-core/bin/lib/review-deep.cjs +14 -22
  226. package/pan-wizard-core/bin/lib/review-vote.cjs +105 -0
  227. package/pan-wizard-core/bin/lib/runner.cjs +2 -16
  228. package/pan-wizard-core/bin/lib/sizing.cjs +356 -0
  229. package/pan-wizard-core/bin/lib/squads.cjs +1 -1
  230. package/pan-wizard-core/bin/lib/state-write.cjs +247 -0
  231. package/pan-wizard-core/bin/lib/uat.cjs +149 -0
  232. package/pan-wizard-core/bin/lib/verdict.cjs +26 -3
  233. package/pan-wizard-core/bin/lib/verify-plan-set.cjs +30 -1
  234. package/pan-wizard-core/bin/lib/verify-preflight.cjs +2 -2
  235. package/pan-wizard-core/bin/lib/verify-red.cjs +37 -1
  236. package/pan-wizard-core/bin/lib/verify-retro.cjs +3 -2
  237. package/pan-wizard-core/bin/lib/verify.cjs +59 -4
  238. package/pan-wizard-core/bin/lib/worktree.cjs +70 -0
  239. package/pan-wizard-core/bin/pan-tools.cjs +168 -27
  240. package/pan-wizard-core/learnings/universal/autonomous-loop.md +2 -2
  241. package/pan-wizard-core/references/continuation-format.md +3 -3
  242. package/pan-wizard-core/references/guardrails.md +1 -1
  243. package/pan-wizard-core/references/model-profiles.md +2 -3
  244. package/pan-wizard-core/references/questioning.md +24 -0
  245. package/pan-wizard-core/references/ui-brand.md +4 -6
  246. package/pan-wizard-core/references/verdict-contract.md +2 -1
  247. package/pan-wizard-core/templates/config.json +5 -1
  248. package/pan-wizard-core/templates/debug.md +1 -0
  249. package/pan-wizard-core/templates/discovery.md +2 -2
  250. package/pan-wizard-core/templates/requirements.md +9 -0
  251. package/pan-wizard-core/workflows/add-phase.md +4 -6
  252. package/pan-wizard-core/workflows/assumptions.md +19 -1
  253. package/pan-wizard-core/workflows/diagnose-issues.md +2 -0
  254. package/pan-wizard-core/workflows/discuss-phase.md +4 -2
  255. package/pan-wizard-core/workflows/exec-lean.md +69 -0
  256. package/pan-wizard-core/workflows/exec-phase.md +36 -8
  257. package/{commands/pan → pan-wizard-core/workflows}/focus-doc-audit.md +13 -29
  258. package/{commands/pan → pan-wizard-core/workflows}/focus-drift-walking.md +3 -18
  259. package/{commands/pan → pan-wizard-core/workflows}/focus-exec.md +8 -23
  260. package/{commands/pan → pan-wizard-core/workflows}/focus-plan.md +6 -20
  261. package/{commands/pan → pan-wizard-core/workflows}/focus-scan.md +3 -16
  262. package/{commands/pan → pan-wizard-core/workflows}/focus-sync.md +7 -21
  263. package/pan-wizard-core/workflows/health.md +6 -0
  264. package/pan-wizard-core/workflows/help.md +31 -53
  265. package/pan-wizard-core/workflows/insert-phase.md +4 -6
  266. package/pan-wizard-core/workflows/learn.md +3 -3
  267. package/pan-wizard-core/workflows/milestone-audit.md +2 -2
  268. package/pan-wizard-core/workflows/milestone-new.md +38 -95
  269. package/pan-wizard-core/workflows/new-project.md +96 -258
  270. package/pan-wizard-core/workflows/optimize.md +107 -5
  271. package/pan-wizard-core/workflows/phase-tests.md +10 -0
  272. package/pan-wizard-core/workflows/plan-phase.md +86 -43
  273. package/pan-wizard-core/workflows/profile.md +50 -0
  274. package/pan-wizard-core/workflows/progress.md +10 -0
  275. package/pan-wizard-core/workflows/quick.md +34 -43
  276. package/pan-wizard-core/workflows/research-phase.md +118 -40
  277. package/pan-wizard-core/workflows/resume-project.md +18 -2
  278. package/pan-wizard-core/workflows/settings.md +21 -24
  279. package/pan-wizard-core/workflows/todo-check.md +6 -2
  280. package/pan-wizard-core/workflows/transition.md +22 -4
  281. package/pan-wizard-core/workflows/uat-walkthrough.md +90 -0
  282. package/pan-wizard-core/workflows/update.md +1 -1
  283. package/pan-wizard-core/workflows/verify-phase.md +2 -2
  284. package/scripts/build-agent-plugin.js +35 -15
  285. package/scripts/build-plugin.js +10 -1
  286. package/scripts/deprecate-old-versions.js +70 -3
  287. package/scripts/generate-skills-docs.py +1 -1
  288. package/scripts/git-hooks/pre-push +27 -0
  289. package/scripts/install-git-hooks.js +7 -5
  290. package/scripts/install-pre-push.cjs +38 -0
  291. package/scripts/land.cjs +151 -0
  292. package/scripts/local-ci.cjs +501 -0
  293. package/scripts/local-schedule.cjs +277 -0
  294. package/scripts/prompt-lint.cjs +32 -0
  295. package/scripts/prompt-rules.cjs +156 -0
  296. package/scripts/run-tests.cjs +7 -1
  297. package/scripts/test-quality-lint.cjs +3 -3
  298. package/scripts/test-surface.cjs +9 -2
  299. package/agents/pan-research-synthesizer.md +0 -246
  300. package/commands/pan/audit-deployment.md +0 -386
  301. package/commands/pan/dashboard.md +0 -22
  302. package/commands/pan/discord.md +0 -19
  303. package/commands/pan/mcp-bridge.md +0 -143
  304. package/commands/pan/milestone-cleanup.md +0 -19
  305. package/commands/pan/milestone-gaps.md +0 -35
  306. package/commands/pan/optimize.md +0 -115
  307. package/commands/pan/profile.md +0 -76
  308. package/commands/pan/research-phase.md +0 -189
  309. package/pan-wizard-core/bin/lib/bridge.cjs +0 -269
  310. package/pan-wizard-core/templates/research-project/architecture.md +0 -210
  311. package/pan-wizard-core/templates/research-project/features.md +0 -153
  312. package/pan-wizard-core/templates/research-project/pitfalls.md +0 -206
  313. package/pan-wizard-core/templates/research-project/stack.md +0 -126
  314. package/pan-wizard-core/templates/research-project/summary.md +0 -170
@@ -0,0 +1,45 @@
1
+ # ADR-0042: Design-quality parity across the main and focus flows — shared design tiers + independent design verification
2
+
3
+ ## Status
4
+
5
+ Accepted — 2026-08-05. Implemented incrementally (see `references/design-methodology.md`, `agents/pan-design-checker.md`, `agents/pan-designer.md`, `commands/pan/design-phase.md`, and the `focus-design`/`plan-phase` wiring).
6
+
7
+ ## Context
8
+
9
+ PAN has two ways to reach implementation, and they were asymmetric on design quality:
10
+
11
+ - **Main flow** (phase lifecycle: `discuss-phase → research-phase → plan-phase → exec-phase → verify-phase`) produces an *executable plan* and verifies it with an **independent** adversarial agent (`pan-plan-checker`, `effort: xhigh`, goal-backward, max-2 reflexion loop). But it has **no design step**: `discuss-phase` explicitly defers architecture ("Do NOT ask about architecture choices — Claude handles these"), so architecture, ADRs, and threat modeling are left implicit.
12
+ - **Focus flow** (`focus-design`, the `/featureAI` pipeline) produces a **deep** design: a 10-phase strategic pipeline with architecture assessment, design synthesis, ADR, STRIDE-lite threat model, and a machine-checkable test plan. But its verification is **self-review only** — there is no independent checker for the spec/ADR the way `plan-phase` has `pan-plan-checker`.
13
+
14
+ So each flow was strong on the axis the other was weak on: the main flow had independent verification but shallow design; the focus flow had deep design but only self-verification. The goal is parity — **both flows get deep design AND independent design verification** — without duplicating the ~1100-line focus-design methodology into the per-phase path, and without making the frequently-run main flow slow.
15
+
16
+ ## Decision
17
+
18
+ Adopt four coupled decisions:
19
+
20
+ 1. **One methodology, four depth tiers.** Extract the design method into a single reference, `pan-wizard-core/references/design-methodology.md`, with tiers `spike` / `phase` / `feature` / `full`. Both entry points cite it — `focus-design` at `feature`/`full`, the main flow at `phase` — so the method can't drift between flows (consistent with the "single source of truth" rule in CLAUDE.md). The design artifact schema lives in `pan-wizard-core/templates/design.md`, with tier-gated mandatory sections.
21
+
22
+ 2. **A shared, independent design-checker.** Add `agents/pan-design-checker.md`, modeled exactly on `pan-plan-checker` (`effort: xhigh`; `tools: Read, Bash, Glob, Grep`; goal-backward; adversarial; max-2 reflexion loop). It verifies design artifacts against seven dimensions: requirement coverage, ≥2 machine-checkable success criteria, architecture conformance to *discovered* project conventions, ADR honesty (real alternatives, mitigated consequences), threat coverage, testability, and scope discipline. Both flows spawn it.
23
+
24
+ 3. **Ramp the main flow up with a dedicated `/pan:design-phase` command** (not folded into `plan-phase`). It runs `pan-designer` at the `phase` tier → `pan-design-checker` reflexion loop → writes `{phase}-design.md`. The lifecycle becomes `discuss → research → design → plan → verify`. `design.md` is an *optional upstream input* consumed by `pan-planner` exactly as `context.md` is, so existing projects without a design step still plan. Trivial phases auto-skip; `--skip-design` forces it. A dedicated command (vs a gate inside `plan-phase`) keeps the step optional, cacheable like `research.md`, and independently invocable.
25
+
26
+ 4. **Altitude split.** Product/strategic design (demand validation, competitive intelligence, market analysis) runs **once** at feature/milestone creation (`focus-design`, and a product-design pass wired into `milestone-new`), not per phase. Per-phase design (`design-phase`) covers only architecture, ADR, threat model, design synthesis, and machine-checkable criteria — the `phase` tier — so the per-phase path stays fast.
27
+
28
+ `plan-phase` gains a `## Design` upstream input and passes it to `pan-planner`; `pan-plan-checker` gains a **Design Conformance** dimension (does the plan implement the approved design?). `focus-design` spawns `pan-design-checker` after its ADR phase and its final-artifact phase.
29
+
30
+ ## Consequences
31
+
32
+ - **Parity achieved:** both flows produce deep design *and* pass it through an independent adversarial checker.
33
+ - **No duplication:** the methodology is defined once and cited twice; the checker is one agent used by both flows.
34
+ - **Bounded overhead:** the depth dial + altitude split + auto-skip + `design.md` caching keep the per-phase path cheap; the reflexion loop is capped at 2 iterations (same as `pan-plan-checker`) so verification can't stall.
35
+ - **Backward compatible:** `design.md` is optional upstream input; projects and phases without it still plan and execute unchanged.
36
+ - **Runtime-agnostic:** new agents/commands use no host-specific tools; any Workflow fan-out keeps its no-op fallback (ADR-0031), so all five runtimes are unaffected.
37
+ - **Cost:** two new agents, one new command, one reference, one template, and wiring/tests. The main-flow lifecycle gains a step (optional), which is a real behavior change teams will see.
38
+
39
+ ## References
40
+
41
+ - `pan-wizard-core/references/design-methodology.md`, `pan-wizard-core/templates/design.md`
42
+ - `agents/pan-designer.md`, `agents/pan-design-checker.md`, `commands/pan/design-phase.md`
43
+ - Existing pattern this mirrors: `agents/pan-plan-checker.md`, `agents/pan-planner.md`, `commands/pan/plan-phase.md`
44
+ - Deep design source being tiered: `commands/pan/focus-design.md` (the `/featureAI` pipeline)
45
+ - Related: ADR-0031 (Workflow fan-out with no-op fallback), ADR-0038 (skill-aligned decomposition).
@@ -0,0 +1,56 @@
1
+ # ADR-0043: Addressable planning roots — a command must be able to name the tree it acted on
2
+
3
+ ## Status
4
+
5
+ Accepted — 2026-08-21. Implemented in `pan-wizard-core/bin/lib/planning-root.cjs`, with `utils.planningPath()` / `utils.planningRel()` as the only path constructors. `hygiene` and `init milestone-op` (which backs `/pan:milestone-audit`) are the multi-root consumers.
6
+
7
+ ## Context
8
+
9
+ Every planning path in PAN was built as `path.join(cwd, PLANNING_DIR, …)`, where `PLANNING_DIR` was the hard-coded constant `'.planning'`. That made exactly one planning tree per project addressable, and it was the only tree any command could see.
10
+
11
+ The `--cwd` flag looked like an escape hatch but is not one: it moves the *project* root, and the planning tree is always `<project>/.planning`. A repo whose planning trees live at `.planning/tracks/{core,defense,verify}/` — several independently-planned products merged into one repository — had three of its four trees permanently unreachable.
12
+
13
+ The damage was not that the other trees were awkward to reach. It was that **the commands did not fail.** They succeeded against the wrong tree:
14
+
15
+ - `hygiene scan` reported `summary.total: 0` — "clean" — while `tracks/verify/optimization/traces` held 18 trace sessions against a retention of 5. Thirteen were prunable. The command exists to prune them and reported nothing to do.
16
+ - `milestone-audit` resolved a different track than the one requested.
17
+ - `milestone-done` would have archived the wrong milestone.
18
+
19
+ A tool that errors is safe: the reader retries. A tool that reports "clean" teaches the reader to trust a result it never computed. That is the failure mode this ADR addresses, and it generalises past `hygiene` — any command that silently resolves an implicit target has it.
20
+
21
+ ## Decision
22
+
23
+ **1. One resolver owns the question "which tree?".** `planning-root.cjs` is a leaf module (it requires only `fs` and `path`) that resolves a project-relative, POSIX-separated planning root, with precedence:
24
+
25
+ | Rank | Source | Form |
26
+ |---|---|---|
27
+ | 1 | `--planning-dir <path>` / `--track <name>` | explicit flag |
28
+ | 2 | `PAN_PLANNING_DIR` | project-relative path |
29
+ | 3 | `PAN_TRACK` | track name |
30
+ | 4 | default | `.planning` |
31
+
32
+ **2. Every resolution carries its provenance.** The resolver returns `{rel, source, track}`, never a bare string, and `describePlanningRoot()` adds `planning_root_exists`. Commands surface all four fields. This is the half of the fix that matters most: it is what makes a wrong target *visible* rather than indistinguishable from a right one. A mistyped `--track ghost` now reports `planning_root_exists: false` next to its zero findings, instead of passing for a healthy project.
33
+
34
+ **3. Two path constructors, no direct joins.** `utils.planningPath(cwd, …segments)` builds absolute paths; `utils.planningRel(…segments)` builds the project-relative display form used in output, findings, and `git add` arguments. They read the same root, so what a command *reports* is always the tree it *touched*. Roughly ninety direct `path.join(cwd, PLANNING_DIR, …)` sites were routed through them, and `PLANNING_DIR` is no longer imported for path building anywhere.
35
+
36
+ **4. Tracks are discovered, not declared.** `discoverTracks()` walks `.planning/tracks/*/` and returns only directories carrying a planning spine (`state.md`, `roadmap.md`, `phases/`, `focus/`, …). An empty or incidental folder under `tracks/` is not a track — inventing one would reintroduce exactly the "acted on the wrong thing" failure being removed. No registry file, so a track cannot drift out of sync with the filesystem.
37
+
38
+ **5. Sweeping several trees is scoped, not threaded.** `withPlanningRoot(rel, fn)` pins the root for a synchronous callback and restores it in a `finally`. `hygiene --all-tracks` uses it per tree. Threading a root parameter through each check would have stopped at the module boundary — the checks call into `memory.cjs` and `cost.cjs`, which resolve the root themselves — so the ambient scope is what makes downstream readers follow the sweep instead of all reporting on `.planning/`.
39
+
40
+ **6. Project-level checks run once.** Version alignment is a property of the project (which runtimes are installed, at what version), not of any planning tree. Sweeping four trees must not report the same drift four times.
41
+
42
+ ## Consequences
43
+
44
+ - **The reported defect is closed.** `--track verify` surfaces the 13 prunable sessions; `--all-tracks` sweeps the root tree and every track, attributing each finding to its track; `clean --apply` prunes the offending tree and leaves the others intact.
45
+ - **Clean verdicts now name their scope.** Every `hygiene` scan prints the tree it read, and a single-tree scan on a project with tracks says so and points at `--all-tracks`.
46
+ - **Traversal is bounded at the seam.** `--planning-dir` rejects absolute, drive-relative, and `..`-containing paths; `--track` is restricted to a slug alphabet. Both checks are inline literals rather than helper calls, because static analysis does not follow guards across function boundaries.
47
+ - **Behaviour is unchanged when nothing is passed.** The default root stays `.planning`; the full suite passed before the new tests were added, which is the evidence that the ~90-site reroute is faithful.
48
+ - **`withPlanningRoot` is synchronous-only.** Overlapping scopes would interleave and restore onto the wrong value. This is documented at the function and is the one sharp edge the design accepts in exchange for downstream readers following the sweep.
49
+ - **Two commands sweep today.** `--track` / `--planning-dir` work for every command because they resolve at the seam. `--all-tracks` aggregation is implemented for `hygiene` and `init milestone-op`; extending it to the phase/state commands is follow-on work, not a gap in the seam.
50
+ - **The audit gained a refusal.** `init milestone-op` now reports `milestone_basis` and `milestone_ambiguous`, and `/pan:milestone-audit` stops when the roadmap marks more than one milestone current. This is the same principle applied one level up: an audit that cannot resolve its subject must say so rather than produce a confident report about a silently-chosen one.
51
+
52
+ ## Alternatives considered
53
+
54
+ - **A `--planning-dir` flag with no provenance reporting.** Cheaper, and it would have made the tracks reachable — but it fixes only the "unreachable" half. The costly half of the defect was that a wrong target looked like a right one, which no amount of reachability addresses.
55
+ - **Resolving `PLANNING_DIR` from the environment at module load.** Nearly zero churn: every existing call site would have become track-aware for free. Rejected because the value freezes at first `require`, so any in-process caller that sets the root afterwards (every test, and the `--all-tracks` sweep) silently gets the stale tree — the same class of silent-wrong-target bug, relocated.
56
+ - **A `tracks.json` registry.** Explicit, but a declared list drifts from the filesystem, and a track missing from the registry would be invisible in precisely the way this ADR exists to prevent.
@@ -0,0 +1,104 @@
1
+ # ADR-0044: Bound the cached context — PAN's dominant cost is what it re-reads, not what it generates
2
+
3
+ ## Status
4
+
5
+ Accepted — 2026-08-21. Implemented across `state-compact.cjs` (new), `hygiene.cjs`, `context-budget.cjs`, `core.cjs::buildCachedContext`, and the three planning-aware hooks.
6
+
7
+ > **Amended 2026-10-04 (memory optimisation O1–O3).** The memory review measured the field installs and found three gaps in this decision's reach.
8
+ >
9
+ > 1. **The bound never ran on Windows.** `memory optimize` and the automatic reconcile matched `\n` only. Every Windows field project's planning files are CRLF, so state.md's append-only lists were never reconciled there. One client's Decisions list held 145 entries, and the file was 35 KB where it should have been 10 KB. Every planning-file parser now reads on LF and writes back in the file's own ending (O1).
10
+ > 2. **The largest re-read was not state.md.** The planner and plan checker were handed the whole roadmap.md and requirements.md, and every plan's `<context>` named the whole roadmap for its executors. Phase agents now read `roadmap slice <phase>`, which is 75–98% smaller on the field projects (O2). So "the cached block is re-read on every agent call" now holds for state.md only.
11
+ > 3. **The roadmap had no compaction path.** It is what grows in a long project: 476 KB at 54 phases. `roadmap compact` (`roadmap-compact.cjs`) moves shipped phases' sections to `roadmap-history.md` under the same rules as Decision 1 below: history first, a stub left behind, dry-run by default, declined when it would not shrink. hygiene offers it as the `compact-roadmap` fix (O3).
12
+
13
+ ## Context
14
+
15
+ A field project reported that PAN had got slow. Its cost ledger explains why.
16
+
17
+ Excluding the 24% of rows that PAN's own `isSuspectRecord` flags as pre-v3.12.4 oversum poison, 92 clean records show:
18
+
19
+ | axis | tokens |
20
+ |---|---:|
21
+ | cache_read | 550.2M |
22
+ | output | 8.7M |
23
+ | input | 1.9M |
24
+
25
+ **Cache reads are 98.1% of all token traffic** — roughly sixty times the generated output. `pan-executor` averaged 7.0M cache-read tokens per call across 47 calls.
26
+
27
+ The block being re-read on every agent call was 109 KB ≈ 28k tokens:
28
+
29
+ ```
30
+ project.md 14.1 KB
31
+ requirements.md 21.5 KB
32
+ roadmap.md 18.3 KB
33
+ state.md 53.8 KB ← half the block
34
+ ```
35
+
36
+ And 56% of `state.md` was settled history: a 25.6 KB session log from ten weeks earlier, a resolved milestone audit, and three phase closures. Roughly 7k tokens of finished work re-read into every agent call for months.
37
+
38
+ Two structural facts made this inevitable rather than accidental:
39
+
40
+ 1. **`state.md` can only grow.** Its section writers are append-only — `sectionBody.trimEnd() + '\n' + entry` in both `cmdStateAddDecision` and `cmdStateAddBlocker`. PAN bounds its other append-only store (`memory compact`, `DEFAULT_MAX_ENTRIES`) but never applied the same idea to the file that dominates every prompt.
41
+
42
+ 2. **Nothing watched the block.** `context-budget.cjs` computed `cache.total_tokens` and `eligible_pct` and reported them with no threshold attached. A measurement with no classification is not a signal — a 28k-token block looked exactly like a 3k-token one.
43
+
44
+ Two adjacent failures shared the shape:
45
+
46
+ - **The ledger poison gate counted rows, not tokens.** `checkCostLedger` fired at `suspect/records.length ≥ 0.5`. The field ledger sat at 24% by count — passing — while those rows carried 89% of the token mass. A ledger that is arithmetically useless reported clean.
47
+ - **Phase attribution only worked under tracing.** The cost hook read the phase from `.planning/optimization/current-session`, which exists only while the optimizer runs. With tracing off — the default — 100% of rows carried `phase: null`, so "which phase got expensive" was unanswerable from PAN's own telemetry.
48
+
49
+ ## Decision
50
+
51
+ **1. `state.md` gets a compaction path.** New `pan-tools state compact [--apply] [--keep-days N]` moves settled sections into `state-history.md`. Safety is ordered:
52
+
53
+ - Nothing is deleted. History is appended to the archive **first**, then `state.md` is rewritten, so an interruption can only duplicate, never lose.
54
+ - Only unambiguous history moves: a heading dated past the retention window, or one saying "closure"/"closed". Anything unrecognised stays.
55
+ - A protected list guards the headings PAN reads and writes (`state get <section>` can read *any* heading by name).
56
+ - A section carrying a field the frontmatter is rebuilt from (`**Status:**`, `**Current Phase:**`, …) is never moved: `syncStateFrontmatter` regenerates frontmatter from the **first** such match in the body, so relocating one could silently rewrite `state.md` metadata.
57
+ - Compaction that would not shrink the file is declined. On a small file the pointers cost more than the sections they replace, and churning `state.md` to make it bigger helps nobody.
58
+ - Dry-run by default, and the dry-run's byte count is produced by the same rebuild `--apply` uses — a dry-run that disagrees with the apply is not a dry-run.
59
+
60
+ **2. The cached block is classified, not merely measured.** `CACHE_BLOCK_WARN_TOKENS` (15k) / `CACHE_BLOCK_CRIT_TOKENS` (25k) / `CACHE_FILE_WARN_TOKENS` (6k), mirroring the existing `MEMORY_LOAD_*` pattern. `context-budget` gains `cache.status` plus advice naming the largest file, and hygiene gains a `cache-context` check whose `state.md` finding carries the `compact-state` remedy.
61
+
62
+ **3. Hygiene covers the rest of the growth surface.** `optimization/reports/` is now pruned on the same retention and keep-newest floor as `optimization/traces/` — previously traces aged out while the analysis JSON beside them (92 KB in the field) never did.
63
+
64
+ **4. The ledger poison gate watches token mass.** `HYGIENE_LEDGER_SUSPECT_MASS_RATIO` fires when suspect rows carry ≥50% of the token mass, whatever their count. The finding names which gate tripped so a healthy-looking row count is not mistaken for a false positive. Mass is what `aggregate` sums, so mass is what the gate has to watch.
65
+
66
+ **5. Phase attribution works without tracing.** The cost hook falls back to `state.md` — frontmatter `current_phase`, then the `**Current Phase:**` body field — when no trace session is active.
67
+
68
+ **6. The cached list is extensible.** `config.json → cache.extra_files` lets a project add its own stable documents. The built-in list is the *phase-model* spine, so a focus-model project had an empty block and therefore no prompt caching at all. Entries are appended after the built-ins so the cache prefix stays byte-stable for projects that configure nothing.
69
+
70
+ **7. All three planning-aware hooks resolve the same root.** `pan-cost-logger`, `pan-trace-logger`, and `pan-stop-guard` now honour `PAN_PLANNING_DIR` / `PAN_TRACK`. Without this the CLI could be pointed at a track (ADR-0043) while the hooks kept writing to `.planning/`, stranding that track's telemetry in the wrong tree.
71
+
72
+ ## Consequences
73
+
74
+ - **The reported slowdown has a measured remedy.** On the field project, `state compact` archives four sections and cuts the per-call re-read by ~6,995 tokens — roughly halving `state.md` and taking the block from `critical` to below it.
75
+ - **`cost_usd` stays null in the ledger, deliberately.** It is computed at read time from current rates (`appendRecord`, `aggregate`). Freezing a value at write time would bake in stale pricing. This was considered and rejected, not overlooked.
76
+ - **A conservative compactor leaves things behind.** On the field file it correctly declined to archive a milestone audit marked "GAPS FOUND" — an open item that merely looked historical. Under-archiving is the right failure direction for a tool that edits the project's source of truth.
77
+ - **`walkPlanning` no longer descends into `tracks/`.** Fixing this was forced by the new check: the root scan had been absorbing every track's files, which also meant `--all-tracks` double-counted `.tmp` orphans. A latent ADR-0043 defect, surfaced by giving the walker a second consumer.
78
+ - **One existing test changed meaning.** `small or mostly-clean ledgers are not flagged` asserted that 5 poisoned rows among 25 were fine. Under the mass gate they are not — those rows held 99.99% of the tokens. The test was rewritten to be clean on both axes, and a new test pins the count-passes/mass-fails case.
79
+
80
+ ## Convergence — a clean must actually finish
81
+
82
+ Applying the above surfaced a fourth failure, reported from the field as "hygiene doesn't properly fix a project". Running `hygiene clean --apply` twice on a real tree showed why:
83
+
84
+ ```
85
+ PASS 2: ✗ compact-state .planning/state.md nothing past the retention window
86
+ fixable: 1, executed: 0, failed: 1, manual: 1
87
+ ```
88
+
89
+ Three defects, all of the same kind — the tool claiming more than it delivers:
90
+
91
+ 1. **A finding advertised a fix that could no longer do anything.** `fixable` was derived from the mere presence of a `fix` object, so once state.md's settled history was archived the `compact-state` remedy stayed attached to a file whose remaining bulk is LIVE content. Every subsequent `clean --apply` reported `failed: 1`, forever. `checkCachedContext` now consults `planStateCompaction` and offers the fix only when something is genuinely archivable; otherwise the finding is honestly manual and says so.
92
+
93
+ 2. **Quarantines accumulated without limit.** Each poisoned-ledger quarantine left a dated copy and nothing ever removed one — the field tree already held a July file alongside the new one. Quarantine now prunes superseded copies, keeping the newest so the evidence survives. The cure had become the disease it treats.
94
+
95
+ 3. **The cost cursor outlived the ledger it indexed.** `.cost-cursor.json` holds per-transcript high-water marks into `tokens.jsonl`; leaving it after a quarantine meant the "fresh" ledger inherited the old read position and undercounted its next slice. It is now cleared with the rename.
96
+
97
+ After these, the same tree converges: `fixable: 0, executed: 0, failed: 0, manual: 2`, with the two remaining findings carrying honest manual advice. **`auto-fixable` now means "running clean will change this"** — which is the only reading that makes a repeat run meaningful.
98
+
99
+ ## Alternatives considered
100
+
101
+ - **Cap `state.md` at a byte limit and truncate.** Simple, and unacceptable: the file is the project's source of truth, and a size-triggered truncation would drop live content as readily as settled content.
102
+ - **Stop caching `state.md`.** Removes the growth cost but also the benefit — it is genuinely stable within a phase, which is exactly what prompt caching rewards. The problem was never that it was cached; it was that it was unbounded.
103
+ - **Classify sections with an agent.** More flexible than pattern rules, and wrong for this job: compaction rewrites the project's source of truth and must be deterministic, reviewable in a dry-run, and identical on every run.
104
+ - **Infer the phase from the transcript path or session id.** Cheaper than reading `state.md`, but it guesses. `state.md` is where the current phase actually lives.
@@ -0,0 +1,76 @@
1
+ # ADR-0045: Ship PAN as an Agent Plugins bundle — one portable package for the non-Claude runtimes
2
+
3
+ ## Status
4
+
5
+ Accepted — 2026-09-10. Spike complete (this document, plus the two normative schemas pinned under `tests/fixtures/agent-plugins/`). Implementation tracked as items 4b–4g of `docs/specs/market-delta-2026-09-superplan.md`.
6
+
7
+ ## Context
8
+
9
+ PAN reaches five runtimes with a loose-file installer and reaches Claude Code additionally as a plugin (`scripts/build-plugin.js`, ADR-0028 Phase 3). The June review planned bespoke packaging for the others — "Codex plugin + Gemini extension remain" — and the August review ranked plugin distribution as the unit that matters. Neither review saw the thing that changed the picture.
10
+
11
+ **Agent Plugins 1.0** was published on 2026-08-06 by Vercel with Amazon, Cursor, GitHub, Microsoft and OpenAI; Google joined the same day. It is a vendor-neutral package format for exactly two component types: Agent Skills and MCP servers. It is loaded natively by Copilot CLI, VS Code and the Copilot app (GA 2026-08-12), by Codex (0.146–0.147, remote marketplaces from 0.153), by Cursor and Kiro, and Antigravity declares its plugin format a superset that discovers from the workspace `.agents/plugins/` tree. Anthropic is not a maintainer; Claude Code keeps its own format.
12
+
13
+ PAN already has both component types the standard packages: a spec-conformant skills compiler (`convertClaudeCommandToUnifiedSkill`, ADR-0028) and a zero-dependency MCP server (`pan-wizard-core/mcp/`, ADR-0041). What it lacks is the wrapper.
14
+
15
+ ### What was verified, and from where (read 2026-09-10)
16
+
17
+ | Fact | Source | Status |
18
+ |---|---|---|
19
+ | `plugin.json` is a **closed** schema: required `$schema` (const `https://agent-plugins.org/schemas/1.0.0/plugin.schema.json`) and `name` (1–64 chars, `^(?!.*(?:--|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$`); optional `version`, `description`, `author{name,email,url}`, `homepage`, `repository`, `license`, `keywords[]`, `extensions{reverse-domain: object}`; `additionalProperties: false` | `agent-plugins.org/schemas/1.0.0/plugin.schema.json`, pinned as a fixture | Verified |
20
+ | Optional metadata fields are "validated only by their JSON types" — a client must not reject on semver/URL/SPDX format | `spec/1.0.0.md` §5 | Verified |
21
+ | Unknown top-level manifest field or non-object `extensions` is **non-fatal**; any other schema violation is **fatal** to the whole plugin | `spec/1.0.0.md` conformance section | Verified |
22
+ | Skills: fixed `skills/` directory; each immediate child holding a regular file named exactly `SKILL.md` is one skill; no recursion; a non-conforming skill is skipped, not fatal | `spec/1.0.0.md` | Verified |
23
+ | MCP: fixed `mcp.json` at plugin root, never inline in the manifest; `$schema` const `…/1.0.0/mcp.schema.json` + `mcpServers`; stdio servers carry `type: "stdio"`, `command` (single executable token, bare name or `./`-prefixed, **no placeholder**), optional `args[]`, `env{}`, `cwd` | `mcp.schema.json`, pinned as a fixture; `spec/1.0.0.md` | Verified |
24
+ | `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` are expanded by the client in `args` elements, `env` values and `cwd` — not in `command`, not in keys, not anywhere else. Single non-recursive textual replacement; unknown placeholder-like text stays literal | `spec/1.0.0.md` | Verified |
25
+ | **When `cwd` is omitted, the client MUST use the plugin root as the subprocess working directory** | `spec/1.0.0.md` | Verified — and consequential, see D6 |
26
+ | Client-specific files live in a top-level directory named for a reverse-domain namespace; matching manifest data goes under `extensions[namespace]`; a client ignores namespaces it does not implement without validating them. No registry of namespaces exists | `spec/1.0.0.md` | Verified |
27
+ | Copilot: namespace `com.github.copilot/` with `agents/*.agent.md`, `hooks/hooks.json`, `commands/`, `rules/`; the older root-level layout (`agents/`, `hooks.json`, `.mcp.json`) is still read; plugin hooks accept the Claude matcher format and expand `${CLAUDE_PLUGIN_ROOT}` (also exported to the hook process) | `code.visualstudio.com/docs/agent-customization/agent-plugins`; `github.blog` changelog 2026-08-12 | Verified for VS Code; **Copilot CLI's own how-to shows only the root layout** — treat the namespace layout as VS Code-verified, CLI-unverified |
28
+ | Codex: consumes the root `plugin.json` directly; OpenAI-specific data lives inline under `extensions["com.openai"]` (`hooks` path or inline, `apps`, `interface`), hooks at `hooks/hooks.json`; `.codex-plugin/plugin.json` remains a compatibility fallback; marketplaces at `.agents/plugins/marketplace.json` (repo) or `~/.agents/plugins/marketplace.json`; install via `codex plugin marketplace add` / `/plugin`; enable in `config.toml` as `[plugins."name@marketplace"] enabled = true` | `developers.openai.com/plugins/build/plugins` | Verified |
29
+ | Antigravity: discovers `<workspace>/.agents/plugins/<name>/` and `~/.gemini/antigravity-cli/plugins/<name>/`; layout `plugin.json` (**own closed schema: `name`, `description`, `$schema` only**), `mcp_config.json`, `hooks.json`, `skills/`, `agents/`, `rules/`; install `agy plugin install <path>` | `antigravity.google/docs/cli/plugins/` | Verified layout; **mcp_config.json shape, hooks.json shape, agent/rule formats, and whether an Agent Plugins `$schema` is accepted are all UNSPECIFIED on the page** |
30
+ | Spec 1.1.0 is a working draft that still scopes v1 to skills + MCP: "Other component types are outside the v1 format" | `spec/1.1.0.md` | Verified |
31
+
32
+ Three facts that a changelog-level reading would have gotten wrong, recorded so they are not re-derived: the Antigravity manifest schema is **closed and different** from the Agent Plugins one, so a single `plugin.json` cannot satisfy both; `command` in `mcp.json` may **not** carry a placeholder, so the bundled server must be launched as `node` + `${PLUGIN_ROOT}/…` in `args`; and the stdio default working directory is the **plugin root**, which is the opposite of what PAN's server assumes.
33
+
34
+ ## Decision
35
+
36
+ **D1 — One bundle, a separate builder.** Emit an Agent Plugins 1.0 package to `dist/pan-agent-plugin/` from a new `scripts/build-agent-plugin.js`. The Claude plugin builder is not extended with a format flag: the two layouts share almost no file paths, and the Claude plugin's output must stay byte-identical (a test pins that). Shared logic goes into pure functions in `bin/install-lib.cjs`, never into a second copy.
37
+
38
+ **D2 — Skills come from the one compiler.** The bundle's `skills/pan-*/SKILL.md` is produced by `convertClaudeCommandToUnifiedSkill` with the same content rewrite the installer applies — extracted from `bin/install.js` into install-lib so the installer and the builder call one function. ADR-0028's rule stands: no second skills compiler, ever. The emitted skills already satisfy every hard rule the spec's skills discovery applies (name equals directory, closed key set, no angle brackets, single-line description).
39
+
40
+ **D3 — A PAN placeholder, not a client one, for paths inside skill bodies.** Agent Plugins expands `${PLUGIN_ROOT}` only in `mcp.json`; Claude's `${CLAUDE_PLUGIN_ROOT}` textual substitution in content is Claude-specific (VS Code expands it in hooks and MCP config, not in skill bodies). Skill bodies in the bundle therefore reference the bundled core through PAN's own token, `{{PAN_PLUGIN_ROOT}}`, in the same style as the existing `{{PAN_ARGS}}`, and the skill adapter header defines it: the directory containing this plugin's `plugin.json`, two levels above the `SKILL.md`, which the runtime reports when it loads the skill. The header also says to prefer the `pan` MCP server's tools where the runtime has connected them. Whether models resolve the token reliably on each runtime is the live gate in 4c/4d; a conformance test can only assert that no `.claude/` or install-directory path survives in the bundle.
41
+
42
+ **D4 — `mcp.json` declares the bundled bridge.** `{"$schema": …, "mcpServers": {"pan": {"type": "stdio", "command": "node", "args": ["${PLUGIN_ROOT}/pan-wizard-core/mcp/server.cjs"]}}}`. `node` is a bare executable token, which the spec permits; the placeholder sits in `args`, where expansion is defined. No `env` block: a plugin serves whatever project the session is in, the same rule the Claude plugin follows.
43
+
44
+ **D5 — Vendor directories per runtime, each behind its own verification.** Copilot: `com.github.copilot/agents/*.agent.md` via the existing `convertClaudeToCopilotAgent`, and `com.github.copilot/hooks/hooks.json` in the Claude matcher format with `${CLAUDE_PLUGIN_ROOT}` paths, since that is the form VS Code documents as expanded. Codex: agents via `convertClaudeAgentToCodexToml`, location and hook variable **unverified** — emit only after reading the Codex plugin reference for agents, and register hooks under `extensions["com.openai"].hooks` only once its path form is known. Antigravity: **a separate variant, not this bundle**, because its manifest schema is closed with a different `$schema`; it is deferred until `mcp_config.json` and `hooks.json` shapes are read from a primary source. Emitting an unverified shape would repeat the dead-config-path class the June review caught twice.
45
+
46
+ **D6 — The server must learn the project root from the call, not the process.** `pan-wizard-core/mcp/server.cjs` resolves its project as `opts.cwd || PAN_PROJECT_ROOT || process.cwd()`. Under Claude Code the process cwd is the project, so it works. Under Agent Plugins the client launches the server **in the plugin root**, so every tool would read `.planning/` from inside the plugin cache and report an empty project — cleanly, which is the worst kind of failure. The fix is additive and shared with the Claude plugin: every registry tool gains an optional `cwd` input (absolute project path), the server uses it per call when present and falls back to today's resolution otherwise, and the resource rule from ADR-0041 (`args` static, never a function of client input) is preserved by scoping the parameter to tools only. Tracked as new item 4g; it is a prerequisite for the live gates, not a follow-up to them.
47
+
48
+ **D7 — Distribution.** A Codex marketplace file at `.agents/plugins/marketplace.json` in this repository (local `./dist/pan-agent-plugin` source for the test bed; a git source once published) and a Copilot marketplace file where its docs place it. Both gated on the same policy as the Claude plugin: ship the versioned bundle before listing anywhere that indexes without certifying.
49
+
50
+ **D8 — Conformance suite before any live gate.** A zero-dependency structural validator, driven by the pinned schemas, asserts: the manifest validates against `plugin.schema.json` (required keys, `$schema` const, name pattern, closed key set, field types); `mcp.json` validates against `mcp.schema.json`; every skill directory name equals its `name`; skill frontmatter uses only the closed key set with no angle brackets; every `{{PAN_PLUGIN_ROOT}}` reference resolves to a file inside the bundle; no `.claude/` or `.agents/pan-wizard-core/` path survives; a non-vacuity guard runs first. The Claude plugin build is asserted byte-identical before and after the compiler extraction.
51
+
52
+ **D9 — A skill longer than Codex loads ships as a pointer page (added 2026-10-03, market-ideas S8).** Codex injects at most the first 8,000 bytes of a skill that came from an Agent Plugin (`codex-rs/ext/skills/src/render.rs`, `MAX_SKILL_PROMPT_BYTES`). Measured on Codex CLI 0.157.1 with a capture-only mock provider, so no model was involved: a 56,540-byte PAN skill reached the model cut mid-sentence, with a "was truncated" warning. The same skill from an install's `.agents/skills/` arrived whole, so the cut applies to plugins only. The builder now keeps every bundle `SKILL.md` within the limit. A skill over it keeps its frontmatter and adapter block, says where the full instructions are, and carries a short summary. The body moves to `skills/<name>/references/instructions.md`, the Agent Skills directory for files a skill loads on demand. The split is `splitOversizedSkill()` in install-lib, applied after the one compiler (D2 stands). A test rebuilds every skill and asserts each one is either the compiler's output unchanged or exactly its split. Re-probed live the same day: the 3,116-byte pointer page arrived whole and the reference file was installed beside it. Untested without a model: that a model follows the pointer.
53
+
54
+ ## Consequences
55
+
56
+ - One emitted bundle serves Copilot and Codex today and Cursor/Kiro incidentally; Antigravity needs a thin variant later. This replaces the June plan's two bespoke packagings and closes ADR-0028 Phase 3's remaining half for those runtimes.
57
+ - The skills compiler extraction touches the installer's unified-skills path. Its output is pinned by `tests/unified-skills-install.test.cjs`; the extraction must leave that suite untouched and green.
58
+ - D6 changes the MCP bridge's tool schemas (additive optional field). Every runtime that registers the bridge sees the new parameter; the tool descriptions must make clear it is optional.
59
+ - The `{{PAN_PLUGIN_ROOT}}` convention is a bet on runtimes exposing the skill's file location at activation. If a runtime does not, its skills cannot reach `pan-tools` by path and must rely on the `pan` MCP tools — which is why D4 and D6 are not optional.
60
+ - PAN takes on a second `dist/` artefact and a second manifest that mirrors `package.json`; the manifest-mirror test pattern from the Claude plugin applies.
61
+
62
+ ## Alternatives considered
63
+
64
+ - **Extend `build-plugin.js` with `--format agent-plugins`.** Rejected: different manifest location and schema, different MCP file name and schema, different placeholder, different vendor layout — a flag would be two builders in one function, and the Claude plugin's byte-identity guarantee would be harder to hold.
65
+ - **Fork the skills compiler for the bundle.** Rejected outright; it recreates the drift class ADR-0028 removed.
66
+ - **Use `${PLUGIN_ROOT}` inside skill bodies.** Rejected: the spec defines expansion only for `mcp.json` fields; the token would reach the model literally and unexplained.
67
+ - **Set `PAN_PROJECT_ROOT` in `mcp.json` `env`.** Rejected: the project path is unknown at build time, and `env` cannot name `PLUGIN_ROOT` or `PLUGIN_DATA`.
68
+ - **Wait for Agent Plugins 1.1 to add agents and hooks natively.** Rejected: the draft explicitly keeps them out of v1 scope; vendor namespaces are the standard's answer and are stable.
69
+
70
+ ## Verification caveats
71
+
72
+ Copilot CLI's namespace layout is verified through VS Code's documentation and GitHub's changelog, not through the CLI's own how-to; Codex agent placement and hook path variables, and every Antigravity file shape, are unverified. Each is gated in the plan. Re-read the spec repository before implementing 4c/4d — the 1.1.0 draft is live.
73
+
74
+ ## Amendment — `2026-10-19`: Codex loads no hooks from the bundle
75
+
76
+ Codex decides a plugin's format from its manifest. A root `plugin.json` carrying the agent-plugins.org schema is an Agent Plugin, and for an Agent Plugin the loader returns no hook sources at all (`codex-rs/core-plugins/src/loader.rs`; introduced by "Enforce Agent Plugin runtime boundaries", openai/codex#37027, `2026-08-05`; identical at `rust-v0.163.0`). A `.codex-plugin/plugin.json` beside it is read only as an overlay and does not change the format. The `hooks/hooks.json` this bundle emits for Codex (D5), and the stop guard added to it (MI-037), therefore never fire on Codex. The `plugin_hooks` feature flag Codex now lists as removed is a compatibility flag for the other manifest format. Nothing changes in the build: the file is harmless and other consumers may read it. Codex users get PAN's hooks from a `--codex` install, which writes `.codex/hooks.json`. Found by the reality check (R55).
@@ -0,0 +1,39 @@
1
+ # ADR-0046: Newer Claude Code subagent frontmatter — what PAN adopts, and what it declines
2
+
3
+ ## Status
4
+
5
+ Accepted — 2026-09-10. A decision record, not a feature: four fields are declined with reasons, and the one capability PAN does want (a longer prompt-cache lifetime for subagents) is delivered as a **recommendation from measured data** rather than as emitted frontmatter. Plan items 7a/7b of `docs/specs/market-delta-2026-09-superplan.md`.
6
+
7
+ ## Context
8
+
9
+ Claude Code's subagent frontmatter grew a set of fields PAN's agents do not use: `maxTurns` (now yielding partial, resumable output — 2.1.246/2.1.259), `memory` (`user` / `project` / `local` scopes), `isolation: worktree`, `skills:` preload, `experimental.cacheTtl` (2.1.248), and the `fork` spawn mode that inherits the parent's context and cache. The August review listed them as "unadopted"; this record decides each on its merits. Two constraints frame every decision:
10
+
11
+ - **PAN's quality guarantee is that every agent starts from zero context and reads its inputs from disk.** Anything that trades that for convenience changes the thing PAN sells.
12
+ - **ADR-0028's frontmatter rule:** a field is emitted only where a runtime has been seen to read it, and PAN ships the same agents to five runtimes. A Claude-only field must be stripped for the other four and must earn its place on Claude.
13
+
14
+ ## Decisions
15
+
16
+ **D1 — `maxTurns`: declined as a shipped default.** PAN agents run whole protocols — a planner writes a complete plan set, a verifier walks every success criterion. A turn cap mid-protocol leaves a half-written artifact on disk that the next hop will read as finished; the "partial + resume" contract only helps when the *orchestrator* notices the partial flag and resumes, and PAN's orchestrators are markdown prose — exactly the layer PanLoop finding 0 showed drops steps at its lowest-context moment. Revisit when a native workflow owns the orchestration, where honouring a partial result and re-issuing the agent is a mechanical step the script cannot skim past. Budgeting remains the `budget` profile's job (cheaper tiers, not fewer turns).
17
+
18
+ **D2 — `memory`: declined.** PAN already has two memory surfaces with explicit curation rules: `.planning/memory/*.md` (project rules injected into executor prompts, verified by the reviewer) and the learnings store with its `learn promote` gate. A third, agent-private memory that Claude Code curates by its own rules — and that only exists on one runtime — would diverge from those two and be invisible to PAN's hygiene and drift checks. If per-agent recall is wanted, it belongs in `.planning/memory/` where every runtime and every check can see it.
19
+
20
+ **D3 — `isolation: worktree`: declined for the shipped agents.** The execution protocol requires the executor to commit to the project's branch and to update `state.md`, `roadmap.md` and `summary.md` where the orchestrator and the verifier will read them; an executor in a private worktree would leave those on a branch the main checkout cannot see. Where PAN wants isolation it already has it, with explicit naming and teardown: `worktree.cjs` and the `army/<task>` branches (ADR-0033, P-1815). Two isolation mechanisms with different cleanup rules is the class of defect P-1815 closed.
21
+
22
+ **D4 — `skills:` preload: declined.** The field injects each listed skill's *full body* into the agent at startup. PAN's agents already instruct the model to read project skills from `.agents/skills/` when they exist, which loads only what a task needs. Preloading would put every listed body into every agent call — the opposite of the cached-context discipline ADR-0044 imposed.
23
+
24
+ **D5 — `experimental.cacheTtl` and `subagentPromptCacheTtl`: recommend, do not emit.** The one-hour lifetime is worth having for a phase whose agents are spaced more than five minutes apart, and worthless for a burst that never idles; one-hour writes bill at 2× base input against 1.25×. PAN cannot know which pattern a project has — but its cost ledger can. `context-budget` now reports `cache.ttl` (cache writes that followed an idle gap of five to sixty minutes, the misses a one-hour lifetime would have avoided) and hygiene raises an `info` finding naming the setting when the pattern recurs. The user makes the trade with the numbers in front of them. Emitting `experimental.cacheTtl: 1h` on selected agents was considered and rejected: it is marked experimental, it would need stripping on four runtimes, and it hard-codes a cost decision that varies per project.
25
+
26
+ **D6 — `fork` spawn mode: declined for the planning chain, allowed nowhere by default.** Forking inherits the parent's full conversation and cache. That is the inverse of PAN's fresh-context guarantee for the planner, executor, verifier and reviewer. It suits a cheap same-context follow-up and nothing in PAN's chain is that.
27
+
28
+ ## Consequences
29
+
30
+ - Nothing is emitted; ADR-0028's rule is untouched. The plan's item 7b ("adopt whatever 7a accepts") closes with no adoption, by decision rather than omission.
31
+ - The cache-lifetime capability arrives as data (`cache.ttl`) plus a documented setting, so the recommendation improves as the ledger grows and is wrong for nobody.
32
+ - D1 names its own revisit trigger: native workflows owning orchestration. When `pan-exec-waves` or a successor runs executors, a `maxTurns` on those spawns with a scripted re-issue is the right shape, and this record should be superseded for that path.
33
+ - **`2026-09-26` — the trigger fired, and D1 still stands.** `pan-exec-waves` (3.28.0) owns the executor spawns, so market-ideas queue item M9 took the revisit up. The Workflow tool's `agent()` takes `label`, `phase`, `schema`, `model`, `effort`, `isolation` and `agentType` — no turn cap per spawn (the workflow-authoring reference, read that day). The only other place for `maxTurns` is `pan-executor`'s frontmatter, and a cap there binds every executor spawn, the markdown `exec-phase` path included — exactly what D1 declined. So nothing ships; revisit when the engine offers a per-spawn cap, or if PAN ever emits a wave-only executor agent for the native path.
34
+
35
+ ## Alternatives considered
36
+
37
+ - Emit `maxTurns` only on read-only agents (researcher, verifier). Rejected: a verifier cut off mid-criteria writes a verification file that reads as complete.
38
+ - Emit `memory: project` on `pan-reviewer` to accumulate recurring findings. Rejected in favour of `.planning/memory/` — same benefit, visible to hygiene and to all five runtimes.
39
+ - Emit `experimental.cacheTtl: 1h` on `pan-executor` and `pan-verifier`. Rejected per D5.
@@ -0,0 +1,76 @@
1
+ # ADR-0047: PAN Harness — a behavioural test harness that lives with the code it tests
2
+
3
+ ## Status
4
+
5
+ **Amended `2026-10-12` (D2):** a step backed by the harness's local model double — capture, scripted or replayed answers, with no request reaching a real model — spends nothing and counts as tier 0, so it needs no `--max-usd` and may run in CI. Record mode (which proxies to a real model) stays tier ≥1, needs `--max-usd`, and uses API-key auth only (decided by the maintainer, `docs/specs/product_excellence_program_2026_q4_featureai.md` §3.4).
6
+
7
+ **Amended `2026-10-10` (D4, MI-104):** a `model` step may name a `runtime` — `claude` (the default and the only host with an output parser) or `codex`, `copilot`, `gemini`, `opencode`, whose argv follows each CLI's own help. A host without a parser is refused before anything runs, because D2's cap needs the step's cost; each host gets its parser from one captured run.
8
+
9
+ Accepted — 2026-09-10. Replaces the PanLoop harness (`D:\panwiz_recursiontest`), which no longer exists on disk; only its Claude transcript folder survives, and this record was written from what that transcript and its recovered files show worked. Implementation under `harness/`; the model-free tier ran green against a packed artifact the day this was accepted.
10
+
11
+ ## Context
12
+
13
+ PAN had one thing almost nothing in its category has: a behavioural eval harness that drove *deployed* installs and measured what the model actually did. PanLoop found the auto-advance chain drop (0/3 → 16/16 across the fix chain), two dead MCP resources, a dead reconcile gate, and its own over-claiming checks. Then it disappeared with the directory it lived in. The market-delta plan (`docs/specs/market-delta-2026-09-superplan.md`) closed every item except the ones that needed it: the behavioural gate for the new native workflows (5c), the agent-scope probe (3b), and the live installs for the Agent Plugins vendor directories.
14
+
15
+ What the recovered material establishes about the old harness, and what this design keeps or changes:
16
+
17
+ | PanLoop practice | Verdict | Why |
18
+ |---|---|---|
19
+ | Scenario = JSON with `tier`, `description`, a `why` per step, `expect` assertions, a `budget` | **Keep** | The `why` is what made findings legible months later |
20
+ | Steps of three kinds: `panSteps` (pan-tools argv), `mcpSteps` (JSON-RPC to the installed bridge), `steps` (a prompt to `claude -p`) | **Keep, unify** | One `steps` array with a `kind` field; the old split hid that a scenario could mix them |
21
+ | Install from a **packed artifact**, never the source tree; identify the build by content | **Keep** | The released and branch builds shared a version string once; `npx <tgz>` silently no-ops on Windows |
22
+ | Model steps run under `--mcp-config <ws>/.mcp.json --strict-mcp-config` | **Keep** | Measured: without it an agent saw two `pan` servers (workspace + plugin cache) with near-identical tool names |
23
+ | Findings ledger with signatures, promotion rule (deterministic, or seen in ≥2 runs), recheck sweep | **Keep** | It stopped single flaky runs from becoming filed defects |
24
+ | Every check must be proven able to **fail** (mutation fixture) — PanLoop withdrew four of its own claims for lacking this | **Keep, enforce in tests** | A check that cannot fail is a false pass waiting to be believed |
25
+ | Lived in its own directory with its own git history | **Change** | It vanished. Scenarios assert PAN's contracts; they version with PAN |
26
+ | Run scenarios five times | **Keep for model tiers** | One green run proves nothing at a 4/5 failure rate |
27
+
28
+ ## Decision
29
+
30
+ **D1 — Location: source in the repo, state outside it.** `harness/` in this repository holds the runner, the scenario definitions and the seeds; it is absent from `package.json` `files`, so nothing ships. Run state — workspaces, extracted artifacts, per-run reports — goes under `d:\pantesting\harness-runs\<run-id>\` by default (`--state-dir`, or `PAN_HARNESS_STATE`), honouring the rule that installs never touch the source checkout. The findings ledger, `harness/ledger.jsonl`, is tracked: it is the finding history the promotion rule depends on.
31
+
32
+ **D2 — Three tiers, model spend is opt-in and capped.** Tier 0 is model-free (pan-tools, filesystem, the bridge over stdio) and is the default run. Tier 1 is one model turn per step; tier 2 is a chain run. A tier ≥1 step is refused unless the run carries `--max-usd`; the runner stops when the cap is reached and records the stop as a finding of the run, not of PAN. Costs come from `claude -p --output-format json` (`total_cost_usd`), so the cap is enforced from measured spend, not estimates.
33
+
34
+ **D3 — Artifact-first.** A run begins with `npm pack` of the repository into the run directory, extraction with `tar` (never `npx`), and an install from the extracted package into each workspace. The run records the package version, the repository HEAD, and the tarball's SHA-256; a report that names only a version is not a report.
35
+
36
+ **D4 — Scenario schema.** One JSON file per scenario:
37
+
38
+ ```
39
+ { id, tier, description, why,
40
+ seed: "<name under harness/seeds>" | "empty",
41
+ install: ["--claude", "--codex", …] | null, // installer flags; null = no install
42
+ requires: { cli: "copilot" } | null, // absent CLI → the scenario is SKIPPED with the reason, never green
43
+ budget: { maxUsd, maxMinutes, maxStepMinutes },
44
+ steps: [ { kind: "pan" | "sh" | "mcp" | "model" | "fs", …, expect: [ … ], why } ] }
45
+ ```
46
+
47
+ Step kinds: `pan` runs the **installed** `pan-tools` with an argv; `sh` runs a whitelisted node script (never a shell string); `mcp` sends a JSON-RPC batch to the **installed** bridge over stdio; `model` runs `claude -p` in the workspace; `fs` asserts without running anything. Assertion kinds: `exit:<n>`, `file:<rel>`, `absent:<rel>`, `glob:<pattern>`, `count:<glob>=<n>`, `json:<path>` (key present) and `json:<path>=<value>` (on stdout JSON), `stdout~<regex>`, `stderr~<regex>`, and for `mcp` steps `rpc:<id>.<path>=<value>`. Every kind has a unit test that shows it failing on a mutated input.
48
+
49
+ **D5 — Findings.** A failed assertion is a finding with a signature (`sha1(scenario, step, kind, normalised detail)`). The ledger records first/last seen, the runs and builds it appeared in, and `resolved_at` when a later run passes the same step. Promotion rule as before: a tier-0 finding is promotable at once; a model-tier finding after two runs. A skipped scenario is recorded as `skipped` with its reason in the report and is never counted as passed.
50
+
51
+ **D6 — What it covers first.** The coverage matrix the plan left open:
52
+
53
+ | Plan item | Scenario | Tier |
54
+ |---|---|---|
55
+ | Deployed install of every runtime; Codex hooks async; native workflows shipped; MCP registrations written | `install-matrix` | 0 |
56
+ | 4g — the installed bridge answers for another project when `cwd` says so | `mcp-bridge-cwd` | 0 |
57
+ | Native workflow scripts as deployed: parse, meta first, phases agree | `native-workflows-deployed` | 0 |
58
+ | Agent Plugins bundle builds from the artifact's sibling repo and validates; Copilot/Codex/Antigravity live installs | `agent-plugin-bundle`, `live-gate-copilot`, `live-gate-codex`, `live-gate-antigravity` | 0 (skips with reason when the CLI is absent) |
59
+ | 5c — `/pan-exec-waves` chain completion vs the markdown path on a seeded two-plan phase | `native-exec-waves-chain` | 2 |
60
+ | 3b — agent scope inside the Claude plugin (`AGENT_SCOPE: scoped\|bare`) | `plugin-agent-scope` | 1 |
61
+
62
+ **D7 — Seeds are PAN-shaped.** A seed is a `.planning/` tree written the way PAN's own templates write it (roadmap, state, plan files with the frontmatter `phase-plan-index` parses), because the reconcile-gate lesson stands: a fixture hand-written in a format PAN never emits verifies nothing.
63
+
64
+ ## Consequences
65
+
66
+ - The harness can no longer be lost separately from the code; a change to a PAN contract and the scenario that asserts it land in the same commit.
67
+ - Tier 0 runs in CI-like conditions with no spend and no credentials; it is the release gate's natural ninth step once it has run green for a while.
68
+ - Model tiers spend the maintainer's Claude usage. They never run by accident: no `--max-usd`, no model step.
69
+ - The live gates for Copilot, Codex and Antigravity are encoded now and will report `skipped: <cli> not installed` on this machine until the CLIs exist; on a machine that has them, the same run turns them into real results.
70
+ - Every assertion kind carries a both-direction test, so the harness cannot accumulate checks that pass vacuously — the failure mode PanLoop found in itself.
71
+
72
+ ## Alternatives considered
73
+
74
+ - **Rebuild PanLoop as a sibling repository.** Rejected: it is how the last one was lost, and its scenarios asserted contracts that live here.
75
+ - **Reuse `tests/scenarios/` for behavioural runs.** Rejected: those are unit-shaped, model-free and run from the source tree; the harness's value is the deployed artifact and the model.
76
+ - **Drive Claude Code through the Agent SDK instead of `claude -p`.** Deferred: `claude -p --output-format json` already yields cost and result; the SDK adds a dependency to a zero-dependency project for no measured gain.
@@ -0,0 +1,43 @@
1
+ # ADR-0048: One core per project — collapse the per-runtime `pan-wizard-core` copies for local installs
2
+
3
+ ## Status
4
+
5
+ Accepted — option A (status quo) — 2026-09-10, by the maintainer, after the reality check framed the choice (plan item R16a). The per-runtime duplication is recorded here as an accepted cost; R16b is closed without implementation. Revisit trigger: a second runtime-neutral consumer that needs the shared core, or a measured version-drift incident that `hygiene scan` did not catch.
6
+
7
+ ## Context
8
+
9
+ A local install selects one or more of the five runtimes, and each selected runtime directory receives its own complete copy of `pan-wizard-core/` — the engine, the workflows, the templates, the references, the MCP bridge. Measured on a packed `3.27.0` install into all five runtimes on 2026-09-10 (reality check RC18, reproduce with Phase 4.2 of `.claude/commands/reality-check.md`): five identical core trees, one per runtime directory, and a sixth under `.agents/pan-wizard-core/` when `--unified-skills` is on. Each copy is a few megabytes and a few hundred files. The duplication is a design consequence, not an accident:
10
+
11
+ - **Per-runtime self-containment.** Every runtime's commands embed a path into *its own* core (`~/.claude/pan-wizard-core/…`, `.opencode/pan-wizard-core/…`), so a runtime keeps working when another is uninstalled, and a global install of one runtime never depends on another's home.
12
+ - **Manifest ownership.** Each runtime's `pan-file-manifest.json` tracks the files it installed; uninstall removes exactly those.
13
+ - **The shared tree already exists for one case.** ADR-0028 Phase 2 introduced `.agents/pan-wizard-core/` as the runtime-neutral home for unified skills, with path rewriting (`rewriteSharedCoreMarkdown`) and a ref-counted uninstall (the last tracker removes and prunes). The per-runtime copies remained for the proprietary command trees.
14
+
15
+ What the duplication costs: disk and file count per project; five drift surfaces where one would do (a partial upgrade leaves two runtimes on two engine versions, which `hygiene scan`'s version-alignment check exists to catch); and five MCP server locations registered per project when one would serve every client.
16
+
17
+ ## Options
18
+
19
+ **A — Status quo.** Keep one core per runtime directory. Cost: the duplication above. Benefit: no migration, no cross-runtime coupling, global installs and local installs share one code path.
20
+
21
+ **B — One core per project for local installs.** Local installs place the core once at `.agents/pan-wizard-core/` (the ADR-0028 location) and every runtime's commands, agents, hooks and MCP registration point there. Global installs are unchanged: their homes differ per runtime (`~/.claude`, `~/.config/opencode`, `~/.gemini`, `~/.codex`, `~/.copilot`) and cannot share a tree.
22
+
23
+ - Converters: the path rewriting exists (`rewriteSharedCoreMarkdown`, `rewriteUnifiedSkillCommandContent`); the proprietary command converters would take the same target.
24
+ - Manifests and uninstall: the shared tree's ref-counted uninstall exists; every runtime's manifest would record the shared core with a shared-owner marker, as unified skills do today.
25
+ - Hooks: the hook scripts resolve the engine relative to their runtime directory today; they would resolve the shared path instead, with a fallback to the per-runtime copy for older installs.
26
+ - MCP registration: one server path in every runtime's registration file.
27
+ - `--config-dir`: a custom runtime directory still points at the project's shared core.
28
+ - Migration: an upgrade over an existing five-copy install must either migrate (remove the per-runtime cores after re-pointing) or keep serving the old layout; `hygiene` would report the leftover copies.
29
+ - Failure domain: the shared tree is a single point of failure for every runtime in the project — the same trade ADR-0028 accepted for unified skills, mitigated by the same scenario matrix.
30
+
31
+ **C — Links.** Symlink or hardlink the per-runtime paths to one tree. Rejected: Windows symlinks need a privilege or Developer Mode, hardlinks do not cross volumes, and a link is invisible to the manifest.
32
+
33
+ ## Decision
34
+
35
+ **A — status quo — accepted 2026-09-10.** The reality check recommended B scoped to local installs; the maintainer chose A: `hygiene scan`'s version-alignment check already catches the drift class, the footprint cost is disk only, and B would carry two install layouts indefinitely because global installs cannot share. If the revisit trigger in Status fires, B re-opens under the gates below.
36
+
37
+ Gates for accepting B: the `install-matrix` and `runtime-roundtrip` scenarios green on the new layout; the packed-install footprint measured before and after with the Phase 4.2 command; an upgrade from a five-copy install verified in `d:\pantesting`; `hygiene scan` recognising and offering to remove the orphaned per-runtime copies.
38
+
39
+ ## Consequences
40
+
41
+ If A: nothing changes; RC18 stays an accepted cost and is recorded here so the next review does not rediscover it.
42
+
43
+ If B: one engine version per project, one MCP server per project, a smaller footprint, and a migration path that every existing local install will walk once. Global installs keep the per-runtime layout, so the installer carries both layouts indefinitely — the documentation must say which layout a given install has and why.