pan-wizard 3.29.0 → 3.31.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 (50) hide show
  1. package/README.md +40 -40
  2. package/bin/install-lib.cjs +186 -83
  3. package/bin/install.js +213 -195
  4. package/commands/pan/army.md +4 -4
  5. package/commands/pan/audit-deployment.md +2 -2
  6. package/commands/pan/cost.md +5 -5
  7. package/commands/pan/exec-phase.md +2 -0
  8. package/commands/pan/focus-auto.md +5 -5
  9. package/commands/pan/verify-phase.md +8 -9
  10. package/hooks/dist/pan-check-update.js +53 -2
  11. package/hooks/dist/pan-context-monitor.js +41 -0
  12. package/hooks/dist/pan-cost-logger.js +71 -2
  13. package/hooks/dist/pan-state-reinject.js +158 -0
  14. package/hooks/dist/pan-stop-guard.js +127 -2
  15. package/hooks/dist/pan-trace-logger.js +42 -1
  16. package/package.json +1 -1
  17. package/pan-wizard-core/bin/lib/agents-md.cjs +3 -2
  18. package/pan-wizard-core/bin/lib/commands.cjs +20 -4
  19. package/pan-wizard-core/bin/lib/config.cjs +2 -0
  20. package/pan-wizard-core/bin/lib/constants.cjs +3 -1
  21. package/pan-wizard-core/bin/lib/context-budget.cjs +27 -2
  22. package/pan-wizard-core/bin/lib/core.cjs +249 -27
  23. package/pan-wizard-core/bin/lib/cost-rebuild.cjs +11 -0
  24. package/pan-wizard-core/bin/lib/cost.cjs +234 -88
  25. package/pan-wizard-core/bin/lib/frontmatter.cjs +5 -2
  26. package/pan-wizard-core/bin/lib/memory-optimize.cjs +12 -6
  27. package/pan-wizard-core/bin/lib/memory-rebuild.cjs +12 -5
  28. package/pan-wizard-core/bin/lib/phase-report.cjs +4 -1
  29. package/pan-wizard-core/bin/lib/roadmap.cjs +87 -18
  30. package/pan-wizard-core/bin/lib/state.cjs +86 -22
  31. package/pan-wizard-core/bin/lib/suggest.cjs +21 -9
  32. package/pan-wizard-core/bin/lib/template.cjs +6 -3
  33. package/pan-wizard-core/bin/lib/verify-deploy.cjs +20 -3
  34. package/pan-wizard-core/bin/pan-tools.cjs +10 -1
  35. package/pan-wizard-core/mcp/tool-registry.cjs +14 -4
  36. package/pan-wizard-core/references/model-profiles.md +4 -4
  37. package/pan-wizard-core/references/planning-config.md +19 -23
  38. package/pan-wizard-core/workflows/exec-phase.md +8 -0
  39. package/pan-wizard-core/workflows/help.md +2 -2
  40. package/pan-wizard-core/workflows/phase-tests.md +1 -1
  41. package/pan-wizard-core/workflows/progress.md +1 -1
  42. package/pan-wizard-core/workflows/settings.md +2 -4
  43. package/pan-wizard-core/workflows/todo-add.md +1 -1
  44. package/pan-wizard-core/workflows/todo-check.md +7 -6
  45. package/scripts/build-agent-plugin.js +4 -0
  46. package/scripts/build-hooks.js +2 -1
  47. package/scripts/build-plugin.js +10 -0
  48. package/scripts/npm-dist-tag.js +47 -0
  49. package/scripts/plugin-path.js +6 -1
  50. package/scripts/test-surface.cjs +11 -9
@@ -31,7 +31,7 @@ Parse current values (default to `true` if not present):
31
31
  - `workflow.nyquist_validation` — validation architecture research during plan-phase
32
32
  - `model_profile` — which model each agent uses (default: `balanced`)
33
33
  - `routing.strategy` — how model tiers are adjusted at runtime (default: `static`)
34
- - `git.branching_strategy` — branching approach (default: `"none"`)
34
+ - `branching_strategy` — branching approach (default: `"none"`; a top-level key — a nested `git.branching_strategy` is ignored when the top-level key exists, as it does in every config `config-ensure-section` creates — write the top-level key)
35
35
  </step>
36
36
 
37
37
  <step name="present_settings">
@@ -131,9 +131,7 @@ Merge new settings into existing config.json:
131
131
  "auto_advance": true/false,
132
132
  "nyquist_validation": true/false
133
133
  },
134
- "git": {
135
- "branching_strategy": "none" | "phase" | "milestone"
136
- },
134
+ "branching_strategy": "none" | "phase" | "milestone",
137
135
  "routing": {
138
136
  "strategy": "static" | "complexity"
139
137
  }
@@ -19,7 +19,7 @@ Extract from init JSON: `commit_docs`, `date`, `timestamp`, `todo_count`, `todos
19
19
 
20
20
  Ensure directories exist:
21
21
  ```bash
22
- mkdir -p .planning/todos/pending .planning/todos/done
22
+ mkdir -p .planning/todos/pending .planning/todos/completed
23
23
  ```
24
24
 
25
25
  Note existing areas from the todos array for consistency in infer_area step.
@@ -105,7 +105,7 @@ Use AskUserQuestion:
105
105
  - header: "Action"
106
106
  - question: "This todo relates to Phase [N]: [name]. What would you like to do?"
107
107
  - options:
108
- - "Work on it now" — move to done, start working
108
+ - "Work on it now" — mark it completed, start working
109
109
  - "Add to phase plan" — include when planning Phase [N]
110
110
  - "Brainstorm approach" — think through before deciding
111
111
  - "Put it back" — return to list
@@ -116,7 +116,7 @@ Use AskUserQuestion:
116
116
  - header: "Action"
117
117
  - question: "What would you like to do with this todo?"
118
118
  - options:
119
- - "Work on it now" — move to done, start working
119
+ - "Work on it now" — mark it completed, start working
120
120
  - "Create a phase" — /pan:add-phase with this scope
121
121
  - "Brainstorm approach" — think through before deciding
122
122
  - "Put it back" — return to list
@@ -125,8 +125,9 @@ Use AskUserQuestion:
125
125
  <step name="execute_action">
126
126
  **Work on it now:**
127
127
  ```bash
128
- mv ".planning/todos/pending/[filename]" ".planning/todos/done/"
128
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs todo complete "[filename]"
129
129
  ```
130
+ This moves it to `.planning/todos/completed/` with a `completed:` date — the directory `init todos` and `/pan:progress` count.
130
131
  Update state.md todo count. Present problem/solution context. Begin work or ask how to proceed.
131
132
 
132
133
  **Add to phase plan:**
@@ -150,11 +151,11 @@ Re-run `init todos` to get updated count, then update state.md "### Pending Todo
150
151
  </step>
151
152
 
152
153
  <step name="git_commit">
153
- If todo was moved to done/, commit the change:
154
+ If the todo was completed, commit the change:
154
155
 
155
156
  ```bash
156
157
  git rm --cached .planning/todos/pending/[filename] 2>/dev/null || true
157
- node ~/.claude/pan-wizard-core/bin/pan-tools.cjs commit "docs: start work on todo - [title]" --files .planning/todos/done/[filename] .planning/state.md
158
+ node ~/.claude/pan-wizard-core/bin/pan-tools.cjs commit "docs: start work on todo - [title]" --files .planning/todos/completed/[filename] .planning/state.md
158
159
  ```
159
160
 
160
161
  Tool respects `commit_docs` config and gitignore automatically.
@@ -172,5 +173,5 @@ Confirm: "Committed: docs: start work on todo - [title]"
172
173
  - [ ] Appropriate actions offered
173
174
  - [ ] Selected action executed
174
175
  - [ ] state.md updated if todo count changed
175
- - [ ] Changes committed to git (if todo moved to done/)
176
+ - [ ] Changes committed to git (if the todo was completed)
176
177
  </success_criteria>
@@ -150,6 +150,8 @@ function hookCommands(rootVar) {
150
150
  contextMonitorCommand: cmd('pan-context-monitor.js'),
151
151
  costLoggerCommand: cmd('pan-cost-logger.js'),
152
152
  traceLoggerCommand: cmd('pan-trace-logger.js'),
153
+ stopGuardCommand: cmd('pan-stop-guard.js'),
154
+ stateReinjectCommand: cmd('pan-state-reinject.js'),
153
155
  };
154
156
  }
155
157
 
@@ -166,6 +168,8 @@ function emitCopilotNamespace(agentsSrc, nsDir) {
166
168
  content = lib.rewriteAgentReferenceCopy(content, TOKEN_PREFIX);
167
169
  content = lib.stripThinkingFrontmatter(content, 'copilot');
168
170
  content = lib.convertClaudeToCopilotAgent(content);
171
+ // The agent carries the root token, so it carries what the token means.
172
+ if (content.includes(TOKEN_PREFIX)) content = content.replace(/\s*$/, '\n\n' + lib.agentPluginSkillAdapterNote('agent') + '\n');
169
173
  fs.writeFileSync(path.join(agentsDest, f.replace(/\.md$/, '.agent.md')), content);
170
174
  agents++;
171
175
  }
@@ -22,7 +22,8 @@ const HOOKS_TO_COPY = [
22
22
  'pan-statusline.js',
23
23
  'pan-cost-logger.js',
24
24
  'pan-trace-logger.js',
25
- 'pan-stop-guard.js'
25
+ 'pan-stop-guard.js',
26
+ 'pan-state-reinject.js'
26
27
  ];
27
28
 
28
29
  function build() {
@@ -169,6 +169,15 @@ function main() {
169
169
  );
170
170
  }
171
171
 
172
+ // 7. Eval suite (market-ideas M4). `claude plugin eval` reads `evals/` at the
173
+ // plugin root; the cases live in harness/plugin-evals/ beside the harness
174
+ // scenarios they come from. harness/ is not in the npm package, so a build from
175
+ // an installed copy has no suite to copy and the plugin ships without one.
176
+ const evalsSrc = path.join(ROOT, 'harness', 'plugin-evals');
177
+ if (fs.existsSync(evalsSrc)) {
178
+ fs.cpSync(evalsSrc, path.join(OUT, 'evals'), { recursive: true });
179
+ }
180
+
172
181
  // Sanity report
173
182
  const count = (p) => { try { return fs.readdirSync(p).length; } catch { return 0; } };
174
183
  console.log('PAN plugin built at', path.relative(ROOT, OUT));
@@ -176,6 +185,7 @@ function main() {
176
185
  console.log(' agents:', count(path.join(OUT, 'agents')));
177
186
  console.log(' hooks:', count(path.join(OUT, 'hooks')));
178
187
  console.log(' workflows:', workflowScripts.length);
188
+ console.log(' eval cases:', count(path.join(OUT, 'evals')) ? fs.readdirSync(path.join(OUT, 'evals'), { withFileTypes: true }).filter(e => e.isDirectory()).length : 0);
179
189
  console.log(' version:', pkg.version);
180
190
  }
181
191
 
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Print the npm dist-tag a version publishes under: `next` for a prerelease
4
+ * (`3.31.0-rc.1`), `latest` otherwise.
5
+ *
6
+ * WHY. The release workflow ran `npm publish` with no `--tag`, and npm's default
7
+ * tag is `latest` — so a release candidate would have become what
8
+ * `npm install pan-wizard` resolves to for every user (market-ideas queue M1,
9
+ * 2026-09-21). Publishing a candidate under `next` keeps it installable by name
10
+ * (`pan-wizard@next`, `pan-wizard@3.31.0-rc.1`) without moving anyone onto it.
11
+ *
12
+ * A version that is not `major.minor.patch[-prerelease]` exits 1 rather than
13
+ * guessing a tag: publishing junk under `latest` is the failure this prevents.
14
+ *
15
+ * Usage:
16
+ * node scripts/npm-dist-tag.js # the tag for package.json's version
17
+ * node scripts/npm-dist-tag.js 3.31.0-rc.1
18
+ */
19
+
20
+ 'use strict';
21
+
22
+ const path = require('path');
23
+ const { parse } = require('./deprecate-old-versions.js');
24
+
25
+ /**
26
+ * @param {string} version
27
+ * @returns {'latest'|'next'|null} null when the version does not parse
28
+ */
29
+ function distTagFor(version) {
30
+ const v = parse(version);
31
+ if (!v) return null;
32
+ return v.pre === null ? 'latest' : 'next';
33
+ }
34
+
35
+ function main() {
36
+ const version = process.argv[2] || require(path.join(__dirname, '..', 'package.json')).version;
37
+ const tag = distTagFor(version);
38
+ if (!tag) {
39
+ process.stderr.write(`npm-dist-tag: '${version}' is not a semver version — refusing to pick a tag\n`);
40
+ process.exit(1);
41
+ }
42
+ process.stdout.write(tag + '\n');
43
+ }
44
+
45
+ module.exports = { distTagFor };
46
+
47
+ if (require.main === module) main();
@@ -49,8 +49,13 @@ function fail(message) {
49
49
  function build() {
50
50
  try {
51
51
  // Relay the builder's stdout to stderr so stdout stays single-line.
52
+ // PAN_PLUGIN_OUT redirects the builder; this script prints PLUGIN_DIR, so a value
53
+ // inherited from the caller's environment would build one place and point the
54
+ // marketplace at another (3.28.0 review, LOW). Build where the path says.
55
+ const env = { ...process.env };
56
+ delete env.PAN_PLUGIN_OUT;
52
57
  const out = execFileSync(process.execPath, [path.join(ROOT, 'scripts', 'build-plugin.js')], {
53
- cwd: ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
58
+ cwd: ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], env,
54
59
  });
55
60
  if (out) process.stderr.write(out);
56
61
  } catch (err) {
@@ -49,24 +49,26 @@ const CONTENT_DIRS = Object.freeze({
49
49
  'pan-wizard-core/workflows': /\.(md|js)$/,
50
50
  });
51
51
 
52
- // Hooks the installer wires outside HOOK_EVENT_MAP (bin/install.js: the Stop guard
53
- // on the two runtimes with a Stop event, the statusline on Claude Code only).
52
+ // Registrations the installer wires outside HOOK_EVENT_MAP: the statuslines. (The
53
+ // stop guard moved INTO the table on 2026-09-23 as its `stop` slot, so its Gemini
54
+ // row follows Gemini's vocabulary — AfterAgent — instead of a hand-written `Stop`
55
+ // that Gemini never read.)
54
56
  const EXTRA_HOOK_ROWS = Object.freeze([
55
- { runtime: 'claude', hook: 'pan-stop-guard.js', event: 'Stop', surface: 'settings.json' },
56
- { runtime: 'gemini', hook: 'pan-stop-guard.js', event: 'Stop', surface: 'settings.json' },
57
57
  { runtime: 'claude', hook: 'pan-statusline.js', event: 'statusLine', surface: 'settings.json' },
58
- // Gemini and Copilot register a statusline too. Both were missing here until a real
59
- // install was read back (2026-09-17) — the registry's whole purpose is that a shipped
60
- // registration cannot sit outside it, so a hand-maintained list is the weak point and
61
- // these rows are the evidence for why it must be checked against an install.
62
- { runtime: 'gemini', hook: 'pan-statusline.js', event: 'statusLine', surface: 'settings.json' },
58
+ // Copilot registers a statusline too; it was missing here until a real install was
59
+ // read back (2026-09-17) — the registry's whole purpose is that a shipped
60
+ // registration cannot sit outside it, so a hand-maintained list is the weak point.
63
61
  // Copilot keeps its hooks in hooks/pan.json but its statusline in copilot/settings.json.
62
+ // Gemini's row is gone: Gemini CLI has no statusline command, so PAN stopped
63
+ // writing one there (R29).
64
64
  { runtime: 'copilot', hook: 'pan-statusline.js', event: 'statusLine', surface: 'copilot/settings.json' },
65
65
  ]);
66
66
  const EVENT_HOOKS = Object.freeze({
67
67
  sessionStart: ['pan-check-update.js'],
68
68
  postToolUse: ['pan-context-monitor.js'],
69
69
  subagentStop: ['pan-cost-logger.js', 'pan-trace-logger.js'],
70
+ stop: ['pan-stop-guard.js'],
71
+ compact: ['pan-state-reinject.js'],
70
72
  });
71
73
 
72
74
  // ─── Parsers (pure) ─────────────────────────────────────────────────────────