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.
- package/README.md +40 -40
- package/bin/install-lib.cjs +186 -83
- package/bin/install.js +213 -195
- package/commands/pan/army.md +4 -4
- package/commands/pan/audit-deployment.md +2 -2
- package/commands/pan/cost.md +5 -5
- package/commands/pan/exec-phase.md +2 -0
- package/commands/pan/focus-auto.md +5 -5
- package/commands/pan/verify-phase.md +8 -9
- package/hooks/dist/pan-check-update.js +53 -2
- package/hooks/dist/pan-context-monitor.js +41 -0
- package/hooks/dist/pan-cost-logger.js +71 -2
- package/hooks/dist/pan-state-reinject.js +158 -0
- package/hooks/dist/pan-stop-guard.js +127 -2
- package/hooks/dist/pan-trace-logger.js +42 -1
- package/package.json +1 -1
- package/pan-wizard-core/bin/lib/agents-md.cjs +3 -2
- package/pan-wizard-core/bin/lib/commands.cjs +20 -4
- package/pan-wizard-core/bin/lib/config.cjs +2 -0
- package/pan-wizard-core/bin/lib/constants.cjs +3 -1
- package/pan-wizard-core/bin/lib/context-budget.cjs +27 -2
- package/pan-wizard-core/bin/lib/core.cjs +249 -27
- package/pan-wizard-core/bin/lib/cost-rebuild.cjs +11 -0
- package/pan-wizard-core/bin/lib/cost.cjs +234 -88
- package/pan-wizard-core/bin/lib/frontmatter.cjs +5 -2
- package/pan-wizard-core/bin/lib/memory-optimize.cjs +12 -6
- package/pan-wizard-core/bin/lib/memory-rebuild.cjs +12 -5
- package/pan-wizard-core/bin/lib/phase-report.cjs +4 -1
- package/pan-wizard-core/bin/lib/roadmap.cjs +87 -18
- package/pan-wizard-core/bin/lib/state.cjs +86 -22
- package/pan-wizard-core/bin/lib/suggest.cjs +21 -9
- package/pan-wizard-core/bin/lib/template.cjs +6 -3
- package/pan-wizard-core/bin/lib/verify-deploy.cjs +20 -3
- package/pan-wizard-core/bin/pan-tools.cjs +10 -1
- package/pan-wizard-core/mcp/tool-registry.cjs +14 -4
- package/pan-wizard-core/references/model-profiles.md +4 -4
- package/pan-wizard-core/references/planning-config.md +19 -23
- package/pan-wizard-core/workflows/exec-phase.md +8 -0
- package/pan-wizard-core/workflows/help.md +2 -2
- package/pan-wizard-core/workflows/phase-tests.md +1 -1
- package/pan-wizard-core/workflows/progress.md +1 -1
- package/pan-wizard-core/workflows/settings.md +2 -4
- package/pan-wizard-core/workflows/todo-add.md +1 -1
- package/pan-wizard-core/workflows/todo-check.md +7 -6
- package/scripts/build-agent-plugin.js +4 -0
- package/scripts/build-hooks.js +2 -1
- package/scripts/build-plugin.js +10 -0
- package/scripts/npm-dist-tag.js +47 -0
- package/scripts/plugin-path.js +6 -1
- 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
|
-
- `
|
|
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
|
-
"
|
|
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/
|
|
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" —
|
|
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" —
|
|
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
|
-
|
|
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
|
|
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/
|
|
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
|
|
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
|
}
|
package/scripts/build-hooks.js
CHANGED
package/scripts/build-plugin.js
CHANGED
|
@@ -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();
|
package/scripts/plugin-path.js
CHANGED
|
@@ -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) {
|
package/scripts/test-surface.cjs
CHANGED
|
@@ -49,24 +49,26 @@ const CONTENT_DIRS = Object.freeze({
|
|
|
49
49
|
'pan-wizard-core/workflows': /\.(md|js)$/,
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
//
|
|
53
|
-
//
|
|
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
|
-
//
|
|
59
|
-
//
|
|
60
|
-
// registration cannot sit outside it, so a hand-maintained list is the weak point
|
|
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) ─────────────────────────────────────────────────────────
|