pan-wizard 3.27.0 → 3.29.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 (40) hide show
  1. package/README.md +48 -48
  2. package/agents/pan-previewer.md +1 -1
  3. package/bin/install-lib.cjs +580 -18
  4. package/bin/install.js +25 -44
  5. package/commands/pan/army.md +1 -1
  6. package/commands/pan/cost.md +14 -2
  7. package/commands/pan/preview.md +2 -2
  8. package/hooks/dist/pan-check-update.js +4 -0
  9. package/hooks/dist/pan-cost-logger.js +322 -43
  10. package/hooks/dist/pan-trace-logger.js +275 -32
  11. package/package.json +8 -2
  12. package/pan-wizard-core/bin/lib/commands.cjs +3 -1
  13. package/pan-wizard-core/bin/lib/constants.cjs +39 -0
  14. package/pan-wizard-core/bin/lib/context-budget.cjs +80 -0
  15. package/pan-wizard-core/bin/lib/cost-rebuild.cjs +511 -0
  16. package/pan-wizard-core/bin/lib/cost.cjs +174 -18
  17. package/pan-wizard-core/bin/lib/foreign-planning.cjs +56 -0
  18. package/pan-wizard-core/bin/lib/git.cjs +5 -1
  19. package/pan-wizard-core/bin/lib/hud.cjs +5 -3
  20. package/pan-wizard-core/bin/lib/hygiene.cjs +52 -24
  21. package/pan-wizard-core/bin/lib/init.cjs +8 -0
  22. package/pan-wizard-core/bin/lib/memory.cjs +14 -8
  23. package/pan-wizard-core/bin/lib/optimize.cjs +78 -2
  24. package/pan-wizard-core/bin/lib/utils.cjs +22 -0
  25. package/pan-wizard-core/bin/lib/verify.cjs +46 -12
  26. package/pan-wizard-core/bin/pan-tools.cjs +8 -1
  27. package/pan-wizard-core/mcp/server.cjs +92 -8
  28. package/pan-wizard-core/mcp/tool-registry.cjs +50 -3
  29. package/pan-wizard-core/references/model-profiles.md +2 -2
  30. package/pan-wizard-core/workflows/health.md +2 -0
  31. package/pan-zcode/README.md +1 -1
  32. package/scripts/build-agent-plugin.js +220 -0
  33. package/scripts/build-plugin.js +48 -3
  34. package/scripts/coverage-gate.cjs +257 -0
  35. package/scripts/generate-skills-docs.py +1 -1
  36. package/scripts/install-git-hooks.js +5 -0
  37. package/scripts/mutation-probe.cjs +272 -0
  38. package/scripts/release-check.js +80 -13
  39. package/scripts/test-quality-lint.cjs +240 -0
  40. package/scripts/test-surface.cjs +335 -0
package/bin/install.js CHANGED
@@ -46,7 +46,7 @@ const pkg = require('../package.json');
46
46
  // phrased by capability, not by name; these are the "switch to this" examples
47
47
  // that keep the advice actionable. Nothing in PAN gates on these values.
48
48
  const RECOMMENDED_MODELS = {
49
- flagship: 'claude-fable-5',
49
+ flagship: 'claude-fable-5-1',
50
50
  reasoningTier: 'claude-opus-5 / claude-opus-4-8',
51
51
  };
52
52
 
@@ -565,21 +565,15 @@ function copyCommandsAsUnifiedSkills(srcDir, skillsDir, prefix, pathPrefix, core
565
565
  fs.mkdirSync(skillDir, { recursive: true });
566
566
 
567
567
  let content = fs.readFileSync(srcPath, 'utf8');
568
- // Core + agent-definition references → shared .agents/ copies (specific,
569
- // before the generic rewrites); everything else .claude-scoped → the
570
- // installing runtime. Agent refs point at the canonical reference copies
571
- // shipped with the shared core — the runtime's own agents dir may carry
572
- // a different format (Codex TOML, Copilot .agent.md).
573
- content = content.replace(/~\/\.claude\/pan-wizard-core\//g, `${corePrefix}pan-wizard-core/`);
574
- content = content.replace(/\.\/\.claude\/pan-wizard-core\//g, `${corePrefix}pan-wizard-core/`);
575
- content = content.replace(/~\/\.claude\/agents\//g, `${corePrefix}pan-wizard-core/agents/`);
576
- content = content.replace(/\.\/\.claude\/agents\//g, `${corePrefix}pan-wizard-core/agents/`);
577
- content = content.replace(/~\/\.claude\//g, pathPrefix);
578
- content = content.replace(/\.\/\.claude\//g, `./${getDirName(runtime)}/`);
579
- // Not every runtime puts a `pan-tools` bin on PATH — invoke via node.
580
- const panToolsPath = `${corePrefix}pan-wizard-core/bin/pan-tools.cjs`;
581
- content = content.replace(/\bpan-tools\b(?=\s+[a-z])/g, `node ${panToolsPath}`);
582
- content = processAttribution(content, getCommitAttribution(runtime));
568
+ // The path rewrite lives in install-lib (rewriteUnifiedSkillCommandContent)
569
+ // because the Agent Plugins bundle builder runs the SAME function — one
570
+ // converter, several call sites, never a second copy (ADR-0028, ADR-0045).
571
+ content = lib.rewriteUnifiedSkillCommandContent(content, {
572
+ corePrefix,
573
+ pathPrefix,
574
+ projectDirPrefix: `./${getDirName(runtime)}/`,
575
+ attribution: getCommitAttribution(runtime),
576
+ });
583
577
  content = convertClaudeCommandToUnifiedSkill(content, skillName);
584
578
 
585
579
  fs.writeFileSync(path.join(skillDir, 'SKILL.md'), content);
@@ -670,17 +664,14 @@ function copySharedCore(srcDir, destDir, corePrefix, runtimePathPrefix, runtime)
670
664
  recurse(srcPath, destPath);
671
665
  } else if (entry.name.endsWith('.md')) {
672
666
  try {
673
- let content = fs.readFileSync(srcPath, 'utf8');
674
- content = content.replace(/~\/\.claude\/pan-wizard-core\//g, `${corePrefix}pan-wizard-core/`);
675
- content = content.replace(/\.\/\.claude\/pan-wizard-core\//g, `${corePrefix}pan-wizard-core/`);
676
- // Agent-definition refs → the canonical reference copies in the
677
- // shared core (runtime agents dirs carry runtime-specific formats).
678
- content = content.replace(/~\/\.claude\/agents\//g, `${corePrefix}pan-wizard-core/agents/`);
679
- content = content.replace(/\.\/\.claude\/agents\//g, `${corePrefix}pan-wizard-core/agents/`);
680
- content = content.replace(/~\/\.claude\//g, runtimePathPrefix);
681
- content = content.replace(/\.\/\.claude\//g, `./${dirName}/`);
682
- content = processAttribution(content, getCommitAttribution(runtime));
683
- content = convertSlashCommandsToCopilotSkillMentions(content);
667
+ // Shared with the Agent Plugins bundle builder (install-lib) — see
668
+ // rewriteSharedCoreMarkdown for the rewrite order and rationale.
669
+ const content = lib.rewriteSharedCoreMarkdown(fs.readFileSync(srcPath, 'utf8'), {
670
+ corePrefix,
671
+ pathPrefix: runtimePathPrefix,
672
+ projectDirPrefix: `./${dirName}/`,
673
+ attribution: getCommitAttribution(runtime),
674
+ });
684
675
  fs.writeFileSync(destPath, content);
685
676
  } catch (err) {
686
677
  pushInstallWarning('copySharedCore(md)', destPath, err);
@@ -728,21 +719,13 @@ function stripInternalFromLearningsIndex(indexPath) {
728
719
  if (err.code !== 'ENOENT') pushInstallWarning('stripInternalLearnings', 'learnings/index.json', err);
729
720
  return;
730
721
  }
731
- if (!parsed || !Array.isArray(parsed.topics)) return;
732
-
733
- const kept = parsed.topics.filter(t => t && t.scope !== 'internal');
734
- if (kept.length === parsed.topics.length) return; // nothing internal to drop
735
-
736
- parsed.topics = kept;
737
- if (parsed.totals && typeof parsed.totals === 'object') {
738
- parsed.totals.topics = kept.length;
739
- parsed.totals.patterns = kept.reduce((n, t) => n + (Array.isArray(t.patterns) ? t.patterns.length : 0), 0);
740
- parsed.totals.size_bytes = kept.reduce((n, t) => n + (t.size_bytes || 0), 0);
741
- parsed.totals.size_tokens_est = kept.reduce((n, t) => n + (t.size_tokens_est || 0), 0);
742
- }
722
+ // The transform is pure and shared with the bundle builders (install-lib):
723
+ // null means "not an index" or "nothing internal to drop" — both no-ops here.
724
+ const stripped = lib.stripInternalLearningsTopics(parsed);
725
+ if (!stripped) return;
743
726
 
744
727
  try {
745
- fs.writeFileSync(indexPath, JSON.stringify(parsed, null, 2) + '\n');
728
+ fs.writeFileSync(indexPath, JSON.stringify(stripped, null, 2) + '\n');
746
729
  } catch (err) {
747
730
  pushInstallWarning('stripInternalLearnings', 'learnings/index.json', err);
748
731
  }
@@ -2230,10 +2213,8 @@ function install(isGlobal, runtime = 'claude') {
2230
2213
  fs.mkdirSync(agentsRefDir, { recursive: true });
2231
2214
  const agentsSrc = path.join(src, 'agents');
2232
2215
  for (const f of fs.readdirSync(agentsSrc).filter(n => n.endsWith('.md'))) {
2233
- let content = fs.readFileSync(path.join(agentsSrc, f), 'utf8');
2234
- content = content.replace(/~\/\.claude\/pan-wizard-core\//g, `${corePrefix}pan-wizard-core/`);
2235
- content = content.replace(/\.\/\.claude\/pan-wizard-core\//g, `${corePrefix}pan-wizard-core/`);
2236
- content = convertSlashCommandsToCopilotSkillMentions(content);
2216
+ // Shared with the Agent Plugins bundle builder (install-lib).
2217
+ const content = lib.rewriteAgentReferenceCopy(fs.readFileSync(path.join(agentsSrc, f), 'utf8'), corePrefix);
2237
2218
  fs.writeFileSync(path.join(agentsRefDir, f), content);
2238
2219
  }
2239
2220
  } catch (e) {
@@ -92,7 +92,7 @@ Every cap the conductor enforces applies to the campaign, scaled up:
92
92
  | `--push` | off | Push approved merges to origin (still human-gated). |
93
93
  | `--clean-seal` | off | One clean build + full verification after the last item (commands from config). |
94
94
  | `--schedule` | off | Arm a self-resuming campaign at this cadence (`hourly`/`daily`/`weekly`/`Nh`/`Nd`) instead of running once — writes the schedule descriptor (ADR-0034). Pair with `--daily-budget`. |
95
- | `--daily-budget` | 300 | Per-day point budget for a scheduled campaign. Advisory by default (an indicator of the day's spend); it only pauses the day's run when `budget.enforce`/`enforce_budget` is set. |
95
+ | `--daily-budget` | 300 | Per-day point budget for a scheduled campaign. Advisory by default (an indicator of the day's spend); it only pauses the day's run when `enforce_budget: true` is set by hand in the schedule descriptor (`schedule.json`); no flag or config key sets it. |
96
96
  | `--dry-run` | off | Plan + squad delegation preview only; STOP. |
97
97
  | `--continue` / `--stop` / `--status` | — | Resume / halt / report from `.planning/orchestration/` + focus-auto state. |
98
98
 
@@ -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] [--format json|table|chart] [--since YYYY-MM-DD] [--until YYYY-MM-DD]"
5
+ argument-hint: "[report|append|clear|rebuild] [--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
@@ -45,7 +45,10 @@ pan-tools cost report [--format json|table|chart] [--since YYYY-MM-DD] [--until
45
45
  "cache_read_tokens": 50000,
46
46
  "cache_write_tokens": 5000,
47
47
  "cost_usd": 2.1234,
48
- "cost_unknown": 0
48
+ "cost_unknown": 0,
49
+ "suspect_excluded": 0,
50
+ "empty_excluded": 0,
51
+ "malformed_skipped": 0
49
52
  },
50
53
  "cache_hit_rate_pct": 40.5,
51
54
  "by_agent": { "pan-planner": { "calls": 8, "input": 50000, ... } },
@@ -78,6 +81,15 @@ Delete the cost log. Useful at the start of a billing cycle.
78
81
  pan-tools cost clear
79
82
  ```
80
83
 
84
+ ### `rebuild`
85
+
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.
87
+
88
+ ```
89
+ pan-tools cost rebuild # dry run
90
+ pan-tools cost rebuild --apply # write the rebuilt ledger
91
+ ```
92
+
81
93
  </subcommands>
82
94
 
83
95
  <rate_table>
@@ -34,9 +34,9 @@ Consolidates Spec B v1's architect + simulate + predict-milestone into one entry
34
34
  **What it does:**
35
35
  1. `pan-tools preview phase <N>` returns `{files_mentioned, test_files_mentioned, risk_signals, risk_score, plans[], status}`.
36
36
  2. Spawn `pan-previewer` with the payload as `<preview_input>`.
37
- 3. Agent writes `.planning/phases/<N>/preview.md` with files touched / tests at risk / migration steps / risk assessment / bottom line.
37
+ 3. Agent writes `.planning/phases/<NN-slug>/preview.md` with files touched / tests at risk / migration steps / risk assessment / bottom line.
38
38
 
39
- **Output:** `.planning/phases/<N>/preview.md`
39
+ **Output:** `.planning/phases/<NN-slug>/preview.md`
40
40
 
41
41
  ### `phases` — Cross-phase dependency graph
42
42
 
@@ -113,6 +113,10 @@ function defaultFetchLatest() {
113
113
  encoding: 'utf8',
114
114
  timeout: 10000,
115
115
  windowsHide: true,
116
+ // Own the silence here rather than relying on the caller's stdio: 'ignore'. npm
117
+ // writes registry and PATH failures to stderr, and a hook that lets them through
118
+ // puts its own diagnostics in front of the user mid-session.
119
+ stdio: ['ignore', 'pipe', 'ignore'],
116
120
  }).trim();
117
121
  }
118
122