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.
- package/README.md +29 -26
- package/agents/pan-conductor.md +18 -17
- package/agents/pan-counterfactual.md +2 -2
- package/agents/pan-debugger.md +30 -9
- package/agents/pan-design-checker.md +2 -1
- package/agents/pan-designer.md +2 -2
- package/agents/pan-distiller.md +3 -3
- package/agents/pan-document_code.md +14 -14
- package/agents/pan-executor.md +30 -9
- package/agents/pan-experiment-runner.md +9 -8
- package/agents/pan-hardener.md +1 -1
- package/agents/pan-integration-checker.md +2 -2
- package/agents/pan-knowledge.md +1 -1
- package/agents/pan-meta-reviewer.md +4 -4
- package/agents/pan-optimizer.md +39 -43
- package/agents/pan-phase-researcher.md +10 -10
- package/agents/pan-plan-checker.md +37 -34
- package/agents/pan-planner.md +57 -44
- package/agents/pan-previewer.md +1 -1
- package/agents/pan-project-researcher.md +12 -12
- package/agents/pan-release.md +1 -1
- package/agents/pan-research-synthesizer.md +3 -3
- package/agents/pan-reviewer.md +26 -3
- package/agents/pan-roadmapper.md +15 -14
- package/agents/pan-verifier.md +33 -25
- package/bin/install-lib.cjs +176 -38
- package/bin/install.js +81 -63
- package/commands/pan/army.md +15 -11
- package/commands/pan/assumptions.md +2 -2
- package/commands/pan/audit-deployment.md +11 -12
- package/commands/pan/cost.md +8 -8
- package/commands/pan/dashboard.md +0 -3
- package/commands/pan/debug.md +10 -7
- package/commands/pan/design-phase.md +5 -5
- package/commands/pan/discuss-phase.md +2 -0
- package/commands/pan/exec-phase.md +21 -37
- package/commands/pan/experiment.md +9 -8
- package/commands/pan/focus-auto.md +22 -20
- package/commands/pan/focus-design.md +7 -6
- package/commands/pan/focus-doc-audit.md +4 -3
- package/commands/pan/focus-drift-walking.md +4 -3
- package/commands/pan/focus-exec.md +6 -6
- package/commands/pan/focus-plan.md +12 -11
- package/commands/pan/focus-scan.md +5 -3
- package/commands/pan/focus-sync.md +3 -2
- package/commands/pan/git.md +8 -8
- package/commands/pan/health.md +2 -2
- package/commands/pan/hud.md +4 -7
- package/commands/pan/hygiene.md +14 -7
- package/commands/pan/knowledge.md +9 -10
- package/commands/pan/learn.md +10 -7
- package/commands/pan/links.md +4 -1
- package/commands/pan/map-codebase.md +1 -1
- package/commands/pan/mcp-bridge.md +19 -21
- package/commands/pan/milestone-done.md +6 -3
- package/commands/pan/milestone-new.md +1 -1
- package/commands/pan/new-project.md +10 -10
- package/commands/pan/optimize.md +18 -14
- package/commands/pan/patches.md +2 -6
- package/commands/pan/pause.md +1 -1
- package/commands/pan/phase-tests.md +3 -2
- package/commands/pan/plan-phase.md +9 -19
- package/commands/pan/preview.md +2 -3
- package/commands/pan/profile.md +2 -2
- package/commands/pan/quick.md +1 -1
- package/commands/pan/remove-phase.md +1 -1
- package/commands/pan/report.md +3 -7
- package/commands/pan/research-phase.md +16 -15
- package/commands/pan/resume.md +9 -11
- package/commands/pan/retro.md +5 -3
- package/commands/pan/review-deep.md +7 -9
- package/commands/pan/settings.md +1 -1
- package/commands/pan/verify-phase.md +0 -11
- package/commands/pan/what-if.md +3 -4
- package/hooks/dist/pan-context-monitor.js +352 -44
- package/hooks/dist/pan-cost-logger.js +30 -0
- package/hooks/dist/pan-guard.js +244 -0
- package/hooks/dist/pan-statusline.js +73 -24
- package/hooks/dist/pan-stop-guard.js +7 -2
- package/package.json +1 -1
- package/pan-wizard-core/bin/lib/agents-md.cjs +44 -6
- package/pan-wizard-core/bin/lib/bridge.cjs +6 -5
- package/pan-wizard-core/bin/lib/campaign.cjs +4 -2
- package/pan-wizard-core/bin/lib/commands-learnings.cjs +19 -2
- package/pan-wizard-core/bin/lib/commands.cjs +57 -6
- package/pan-wizard-core/bin/lib/config.cjs +7 -1
- package/pan-wizard-core/bin/lib/constants.cjs +18 -6
- package/pan-wizard-core/bin/lib/context-budget.cjs +12 -9
- package/pan-wizard-core/bin/lib/core.cjs +53 -19
- package/pan-wizard-core/bin/lib/cost-rebuild.cjs +13 -1
- package/pan-wizard-core/bin/lib/cost.cjs +142 -13
- package/pan-wizard-core/bin/lib/distill.cjs +6 -3
- package/pan-wizard-core/bin/lib/doc-lint.cjs +30 -11
- package/pan-wizard-core/bin/lib/findings.cjs +135 -21
- package/pan-wizard-core/bin/lib/focus.cjs +13 -4
- package/pan-wizard-core/bin/lib/frontmatter.cjs +105 -26
- package/pan-wizard-core/bin/lib/hygiene.cjs +184 -17
- package/pan-wizard-core/bin/lib/init.cjs +13 -4
- package/pan-wizard-core/bin/lib/knowledge.cjs +17 -1
- package/pan-wizard-core/bin/lib/learn-index.cjs +111 -10
- package/pan-wizard-core/bin/lib/learn-lint.cjs +30 -3
- package/pan-wizard-core/bin/lib/memory-optimize.cjs +8 -4
- package/pan-wizard-core/bin/lib/memory.cjs +508 -54
- package/pan-wizard-core/bin/lib/milestone.cjs +8 -3
- package/pan-wizard-core/bin/lib/optimize.cjs +97 -17
- package/pan-wizard-core/bin/lib/phase-gate.cjs +174 -0
- package/pan-wizard-core/bin/lib/phase-remove.cjs +85 -21
- package/pan-wizard-core/bin/lib/phase-report.cjs +8 -2
- package/pan-wizard-core/bin/lib/phase.cjs +39 -13
- package/pan-wizard-core/bin/lib/preview.cjs +34 -31
- package/pan-wizard-core/bin/lib/roadmap-compact.cjs +267 -0
- package/pan-wizard-core/bin/lib/roadmap.cjs +243 -9
- package/pan-wizard-core/bin/lib/runner.cjs +2 -1
- package/pan-wizard-core/bin/lib/state-compact.cjs +11 -6
- package/pan-wizard-core/bin/lib/state.cjs +43 -28
- package/pan-wizard-core/bin/lib/template.cjs +11 -4
- package/pan-wizard-core/bin/lib/verdict.cjs +140 -10
- package/pan-wizard-core/bin/lib/verify-integrity.cjs +181 -0
- package/pan-wizard-core/bin/lib/verify-plan-set.cjs +230 -0
- package/pan-wizard-core/bin/lib/verify-preflight.cjs +4 -13
- package/pan-wizard-core/bin/lib/verify-retro.cjs +5 -3
- package/pan-wizard-core/bin/lib/verify-scope.cjs +11 -7
- package/pan-wizard-core/bin/lib/verify.cjs +30 -28
- package/pan-wizard-core/bin/lib/whatif.cjs +53 -9
- package/pan-wizard-core/bin/pan-tools.cjs +114 -19
- package/pan-wizard-core/learnings/index.json +5 -5
- package/pan-wizard-core/mcp/merge-gate.cjs +14 -3
- package/pan-wizard-core/mcp/native-tools.cjs +3 -3
- package/pan-wizard-core/opencode/pan-wizard.js +139 -0
- package/pan-wizard-core/references/checkpoints.md +3 -3
- package/pan-wizard-core/references/continuation-format.md +3 -3
- package/pan-wizard-core/references/decimal-phase-calculation.md +2 -3
- package/pan-wizard-core/references/design-methodology.md +1 -1
- package/pan-wizard-core/references/git-integration.md +4 -6
- package/pan-wizard-core/references/git-planning-commit.md +2 -2
- package/pan-wizard-core/references/guardrails.md +2 -2
- package/pan-wizard-core/references/handoff-decisions.md +3 -3
- package/pan-wizard-core/references/model-profile-resolution.md +5 -5
- package/pan-wizard-core/references/model-profiles.md +15 -10
- package/pan-wizard-core/references/phase-argument-parsing.md +7 -7
- package/pan-wizard-core/references/planning-config.md +7 -7
- package/pan-wizard-core/references/tdd.md +10 -1
- package/pan-wizard-core/references/verdict-contract.md +6 -1
- package/pan-wizard-core/references/verification-patterns.md +5 -5
- package/pan-wizard-core/templates/codebase/architecture.md +2 -2
- package/pan-wizard-core/templates/codebase/best-practices.md +2 -2
- package/pan-wizard-core/templates/codebase/concerns.md +3 -3
- package/pan-wizard-core/templates/codebase/integrations.md +6 -6
- package/pan-wizard-core/templates/codebase/relationships.md +2 -2
- package/pan-wizard-core/templates/codebase/stack.md +2 -2
- package/pan-wizard-core/templates/codebase/structure.md +4 -4
- package/pan-wizard-core/templates/codebase/testing.md +4 -4
- package/pan-wizard-core/templates/config.json +2 -6
- package/pan-wizard-core/templates/continue-here.md +1 -1
- package/pan-wizard-core/templates/debug-subagent-prompt.md +5 -3
- package/pan-wizard-core/templates/debug.md +15 -1
- package/pan-wizard-core/templates/milestone-archive.md +6 -6
- package/pan-wizard-core/templates/milestone.md +1 -1
- package/pan-wizard-core/templates/phase-prompt.md +31 -17
- package/pan-wizard-core/templates/planner-subagent-prompt.md +5 -5
- package/pan-wizard-core/templates/preview-report.md +1 -1
- package/pan-wizard-core/templates/research-project/architecture.md +3 -3
- package/pan-wizard-core/templates/research-project/features.md +1 -1
- package/pan-wizard-core/templates/research-project/pitfalls.md +1 -1
- package/pan-wizard-core/templates/research-project/stack.md +3 -3
- package/pan-wizard-core/templates/research.md +5 -5
- package/pan-wizard-core/templates/retrospective.md +1 -1
- package/pan-wizard-core/templates/roadmap.md +15 -15
- package/pan-wizard-core/templates/state.md +4 -4
- package/pan-wizard-core/templates/summary-complex.md +1 -0
- package/pan-wizard-core/templates/summary-minimal.md +1 -0
- package/pan-wizard-core/templates/summary-standard.md +2 -1
- package/pan-wizard-core/templates/summary.md +18 -2
- package/pan-wizard-core/templates/uat.md +3 -3
- package/pan-wizard-core/templates/user-setup.md +8 -8
- package/pan-wizard-core/templates/verification-report.md +53 -8
- package/pan-wizard-core/workflows/add-phase.md +1 -1
- package/pan-wizard-core/workflows/assumptions.md +1 -1
- package/pan-wizard-core/workflows/diagnose-issues.md +4 -4
- package/pan-wizard-core/workflows/discuss-phase.md +10 -8
- package/pan-wizard-core/workflows/exec-phase.md +75 -95
- package/pan-wizard-core/workflows/execute-plan.md +8 -7
- package/pan-wizard-core/workflows/health.md +13 -12
- package/pan-wizard-core/workflows/help.md +8 -9
- package/pan-wizard-core/workflows/learn.md +13 -11
- package/pan-wizard-core/workflows/map-codebase.md +10 -10
- package/pan-wizard-core/workflows/milestone-audit.md +10 -10
- package/pan-wizard-core/workflows/milestone-gaps.md +18 -25
- package/pan-wizard-core/workflows/milestone-new.md +7 -6
- package/pan-wizard-core/workflows/new-project.md +17 -25
- package/pan-wizard-core/workflows/optimize.md +11 -9
- package/pan-wizard-core/workflows/pause.md +6 -1
- package/pan-wizard-core/workflows/phase-tests.md +4 -4
- package/pan-wizard-core/workflows/plan-phase.md +53 -42
- package/pan-wizard-core/workflows/profile.md +2 -2
- package/pan-wizard-core/workflows/progress.md +6 -8
- package/pan-wizard-core/workflows/quick.md +7 -5
- package/pan-wizard-core/workflows/remove-phase.md +1 -1
- package/pan-wizard-core/workflows/research-phase.md +9 -5
- package/pan-wizard-core/workflows/resume-project.md +4 -6
- package/pan-wizard-core/workflows/retro.md +3 -1
- package/pan-wizard-core/workflows/settings.md +16 -24
- package/pan-wizard-core/workflows/todo-check.md +4 -3
- package/pan-wizard-core/workflows/transition.md +16 -12
- package/pan-wizard-core/workflows/update.md +25 -17
- package/pan-wizard-core/workflows/verify-phase.md +22 -20
- package/pan-zcode/KNOWN-BETA-RISKS.md +2 -2
- package/pan-zcode/README.md +7 -7
- package/pan-zcode/bin/install-zcode.js +1 -1
- package/scripts/build-hooks.js +1 -0
- package/scripts/build-plugin.js +3 -1
- package/scripts/generate-skills-docs.py +15 -6
- package/scripts/prompt-lint.cjs +167 -0
- 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
|
|
373
|
-
//
|
|
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
|
-
|
|
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
|
|
1561
|
-
|
|
1562
|
-
// Remove PAN permission entries
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
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
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
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
|
-
|
|
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' },
|
package/commands/pan/army.md
CHANGED
|
@@ -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` |
|
|
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
|
|
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 ·
|
|
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
|
|
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` (
|
|
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.
|
|
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
|
|
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`.
|
|
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 ·
|
|
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;
|
|
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: "
|
|
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
|
-
|
|
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>/.
|
|
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
|
|
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
|
-
-
|
|
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, ...):
|
|
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
|
|
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
|
|
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
|
|
package/commands/pan/cost.md
CHANGED
|
@@ -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
|
|
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
|
|
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>
|
package/commands/pan/debug.md
CHANGED
|
@@ -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
|
|
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 `##
|
|
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`)
|
|
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
|
|
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
|
|
214
|
-
2. Do NOT re-test hypotheses
|
|
215
|
-
3. Start from
|
|
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
|
```
|