pan-wizard 3.8.0 → 3.10.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 +4 -1
- package/agents/pan-conductor.md +1 -2
- package/agents/pan-counterfactual.md +1 -2
- package/agents/pan-debugger.md +1 -2
- package/agents/pan-distiller.md +1 -2
- package/agents/pan-document_code.md +1 -0
- package/agents/pan-executor.md +1 -0
- package/agents/pan-experiment-runner.md +1 -2
- package/agents/pan-hardener.md +1 -2
- package/agents/pan-integration-checker.md +1 -2
- package/agents/pan-knowledge.md +1 -2
- package/agents/pan-meta-reviewer.md +1 -2
- package/agents/pan-optimizer.md +1 -0
- package/agents/pan-phase-researcher.md +1 -0
- package/agents/pan-plan-checker.md +1 -2
- package/agents/pan-planner.md +1 -0
- package/agents/pan-previewer.md +1 -2
- package/agents/pan-project-researcher.md +6 -0
- package/agents/pan-research-synthesizer.md +7 -0
- package/agents/pan-reviewer.md +2 -3
- package/agents/pan-roadmapper.md +1 -0
- package/agents/pan-verifier.md +1 -2
- package/bin/install-lib.cjs +661 -46
- package/bin/install.js +722 -116
- package/commands/pan/experiment.md +2 -0
- package/commands/pan/profile.md +2 -0
- package/hooks/dist/pan-cost-logger.js +22 -7
- package/package.json +5 -4
- package/pan-wizard-core/bin/lib/commands-learnings.cjs +544 -0
- package/pan-wizard-core/bin/lib/commands.cjs +12 -523
- package/pan-wizard-core/bin/lib/core.cjs +69 -0
- package/pan-wizard-core/bin/lib/cost.cjs +62 -8
- package/pan-wizard-core/bin/lib/git.cjs +6 -1
- package/pan-wizard-core/bin/lib/lock.cjs +108 -0
- package/pan-wizard-core/bin/lib/milestone.cjs +3 -2
- package/pan-wizard-core/bin/lib/phase-remove.cjs +392 -0
- package/pan-wizard-core/bin/lib/phase.cjs +4 -369
- package/pan-wizard-core/bin/lib/runner.cjs +5 -0
- package/pan-wizard-core/bin/lib/state.cjs +10 -1
- package/pan-wizard-core/bin/lib/verify-deploy.cjs +181 -0
- package/pan-wizard-core/bin/lib/verify-drift.cjs +255 -0
- package/pan-wizard-core/bin/lib/verify-preflight.cjs +261 -0
- package/pan-wizard-core/bin/lib/verify-retro.cjs +177 -0
- package/pan-wizard-core/bin/lib/verify.cjs +10 -797
- package/pan-wizard-core/bin/pan-tools.cjs +10 -0
- package/pan-wizard-core/workflows/plan-phase.md +11 -0
- package/scripts/build-plugin.js +105 -0
- package/scripts/install-git-hooks.js +64 -0
- package/scripts/release-check.js +13 -2
|
@@ -1039,6 +1039,16 @@ async function main() {
|
|
|
1039
1039
|
break;
|
|
1040
1040
|
}
|
|
1041
1041
|
|
|
1042
|
+
case 'models': {
|
|
1043
|
+
const subcommand = args[1];
|
|
1044
|
+
if (subcommand === 'check' || !subcommand) {
|
|
1045
|
+
cost.cmdModelsCheck(raw);
|
|
1046
|
+
} else {
|
|
1047
|
+
error('Unknown models subcommand. Available: check');
|
|
1048
|
+
}
|
|
1049
|
+
break;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1042
1052
|
case 'bus': {
|
|
1043
1053
|
const subcommand = args[1];
|
|
1044
1054
|
if (subcommand === 'publish') {
|
|
@@ -511,6 +511,17 @@ Offer: 1) Force proceed, 2) Provide guidance and retry, 3) Abandon
|
|
|
511
511
|
|
|
512
512
|
## 13. Present Final Status
|
|
513
513
|
|
|
514
|
+
**Sync state.md first** — without this, state.md says "Ready to plan" until the
|
|
515
|
+
first plan's summary lands, and `/pan:progress`/`preflight` read a stale picture:
|
|
516
|
+
|
|
517
|
+
```bash
|
|
518
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state update "Status" "Ready to execute"
|
|
519
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state update "Current Plan" "1"
|
|
520
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state update "Total Plans in Phase" "${PLAN_COUNT}"
|
|
521
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state update "Last Activity" "$(node ~/.claude/pan-wizard-core/bin/pan-tools.cjs current-timestamp date --raw)"
|
|
522
|
+
node ~/.claude/pan-wizard-core/bin/pan-tools.cjs state update "Last Activity Description" "Phase ${PHASE_NUMBER} planned — ${PLAN_COUNT} plans created"
|
|
523
|
+
```
|
|
524
|
+
|
|
514
525
|
Route to `<offer_next>` OR `auto_advance` depending on flags/config.
|
|
515
526
|
|
|
516
527
|
**Circular optimization — log plan creation:**
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the PAN Wizard Claude Code plugin (ecosystem review item: plugin
|
|
3
|
+
* distribution, first slice). Emits a self-contained plugin directory at
|
|
4
|
+
* dist/pan-wizard-plugin/ following the verified plugin layout:
|
|
5
|
+
*
|
|
6
|
+
* .claude-plugin/plugin.json manifest (metadata; components auto-discover)
|
|
7
|
+
* commands/pan/*.md command markdown (Claude flavor)
|
|
8
|
+
* agents/pan-*.md agent definitions
|
|
9
|
+
* hooks/hooks.json PAN hooks with ${CLAUDE_PLUGIN_ROOT} paths
|
|
10
|
+
* hooks/pan-*.js hook scripts
|
|
11
|
+
* pan-wizard-core/ dispatcher + modules + workflows + templates
|
|
12
|
+
*
|
|
13
|
+
* Distribution status: built ALONGSIDE the loose-file installer. Marketplace
|
|
14
|
+
* publishing is gated on one live verification — whether ${CLAUDE_PLUGIN_ROOT}
|
|
15
|
+
* expands inside command markdown content (documented for hook/MCP configs
|
|
16
|
+
* only). Until then, content references core paths relative to the plugin
|
|
17
|
+
* root, which matches the documented plugin working layout.
|
|
18
|
+
*
|
|
19
|
+
* Usage: node scripts/build-plugin.js (or npm run build:plugin)
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
const fs = require('fs');
|
|
25
|
+
const path = require('path');
|
|
26
|
+
|
|
27
|
+
const ROOT = path.join(__dirname, '..');
|
|
28
|
+
const OUT = path.join(ROOT, 'dist', 'pan-wizard-plugin');
|
|
29
|
+
const pkg = require(path.join(ROOT, 'package.json'));
|
|
30
|
+
const lib = require(path.join(ROOT, 'bin', 'install-lib.cjs'));
|
|
31
|
+
|
|
32
|
+
// Plugin-relative prefix used inside markdown content. Hook/MCP configs get
|
|
33
|
+
// the documented ${CLAUDE_PLUGIN_ROOT} form via buildPluginHooksConfig().
|
|
34
|
+
const CONTENT_PREFIX = '${CLAUDE_PLUGIN_ROOT}/';
|
|
35
|
+
|
|
36
|
+
function rewriteContent(content) {
|
|
37
|
+
return content
|
|
38
|
+
.replace(/~\/\.claude\/pan-wizard-core\//g, `${CONTENT_PREFIX}pan-wizard-core/`)
|
|
39
|
+
.replace(/\.\/\.claude\/pan-wizard-core\//g, `${CONTENT_PREFIX}pan-wizard-core/`)
|
|
40
|
+
.replace(/~\/\.claude\/agents\//g, `${CONTENT_PREFIX}agents/`)
|
|
41
|
+
.replace(/\.\/\.claude\/agents\//g, `${CONTENT_PREFIX}agents/`)
|
|
42
|
+
.replace(/~\/\.claude\//g, CONTENT_PREFIX)
|
|
43
|
+
.replace(/\.\/\.claude\//g, CONTENT_PREFIX);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function copyTree(srcDir, destDir, transformMd) {
|
|
47
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
48
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
49
|
+
const srcPath = path.join(srcDir, entry.name);
|
|
50
|
+
const destPath = path.join(destDir, entry.name);
|
|
51
|
+
if (entry.isDirectory()) {
|
|
52
|
+
copyTree(srcPath, destPath, transformMd);
|
|
53
|
+
} else if (transformMd && entry.name.endsWith('.md')) {
|
|
54
|
+
fs.writeFileSync(destPath, transformMd(fs.readFileSync(srcPath, 'utf8')));
|
|
55
|
+
} else {
|
|
56
|
+
fs.copyFileSync(srcPath, destPath);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function main() {
|
|
62
|
+
// Clean output
|
|
63
|
+
fs.rmSync(OUT, { recursive: true, force: true });
|
|
64
|
+
fs.mkdirSync(path.join(OUT, '.claude-plugin'), { recursive: true });
|
|
65
|
+
|
|
66
|
+
// 1. Manifest
|
|
67
|
+
fs.writeFileSync(
|
|
68
|
+
path.join(OUT, '.claude-plugin', 'plugin.json'),
|
|
69
|
+
JSON.stringify(lib.buildPluginManifest(pkg), null, 2) + '\n'
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// 2. Commands (Claude flavor, plugin-root-relative paths)
|
|
73
|
+
copyTree(path.join(ROOT, 'commands', 'pan'), path.join(OUT, 'commands', 'pan'), rewriteContent);
|
|
74
|
+
|
|
75
|
+
// 3. Agents
|
|
76
|
+
copyTree(path.join(ROOT, 'agents'), path.join(OUT, 'agents'), rewriteContent);
|
|
77
|
+
|
|
78
|
+
// 4. Hooks: config + scripts
|
|
79
|
+
fs.mkdirSync(path.join(OUT, 'hooks'), { recursive: true });
|
|
80
|
+
fs.writeFileSync(
|
|
81
|
+
path.join(OUT, 'hooks', 'hooks.json'),
|
|
82
|
+
JSON.stringify(lib.buildPluginHooksConfig(), null, 2) + '\n'
|
|
83
|
+
);
|
|
84
|
+
const hooksDist = path.join(ROOT, 'hooks', 'dist');
|
|
85
|
+
if (fs.existsSync(hooksDist)) {
|
|
86
|
+
for (const f of fs.readdirSync(hooksDist).filter(n => n.endsWith('.js'))) {
|
|
87
|
+
fs.copyFileSync(path.join(hooksDist, f), path.join(OUT, 'hooks', f));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 5. Core (strip source-only internal learnings, same policy as the installer)
|
|
92
|
+
copyTree(path.join(ROOT, 'pan-wizard-core'), path.join(OUT, 'pan-wizard-core'), rewriteContent);
|
|
93
|
+
fs.rmSync(path.join(OUT, 'pan-wizard-core', 'learnings', 'internal'), { recursive: true, force: true });
|
|
94
|
+
fs.writeFileSync(path.join(OUT, 'pan-wizard-core', 'VERSION'), pkg.version);
|
|
95
|
+
|
|
96
|
+
// Sanity report
|
|
97
|
+
const count = (p) => { try { return fs.readdirSync(p).length; } catch { return 0; } };
|
|
98
|
+
console.log('PAN plugin built at', path.relative(ROOT, OUT));
|
|
99
|
+
console.log(' commands/pan:', count(path.join(OUT, 'commands', 'pan')));
|
|
100
|
+
console.log(' agents:', count(path.join(OUT, 'agents')));
|
|
101
|
+
console.log(' hooks:', count(path.join(OUT, 'hooks')));
|
|
102
|
+
console.log(' version:', pkg.version);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
main();
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* install-git-hooks.js
|
|
4
|
+
*
|
|
5
|
+
* Points this repo's git at `scripts/git-hooks/` instead of the per-clone
|
|
6
|
+
* `.git/hooks/` directory. Run automatically by the `prepare` npm script,
|
|
7
|
+
* which fires on `npm install` inside the source repo.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists:
|
|
10
|
+
* `.git/hooks/` is per-clone (never committed). Without this, every fresh
|
|
11
|
+
* clone of PAN Wizard would have to manually `cp scripts/git-hooks/pre-commit
|
|
12
|
+
* .git/hooks/` to get the gitleaks pre-commit scan. With `core.hooksPath`
|
|
13
|
+
* set to the tracked `scripts/git-hooks/` directory, the hook is active
|
|
14
|
+
* the moment you finish `npm install`.
|
|
15
|
+
*
|
|
16
|
+
* No-op when not in a git working tree (e.g., the package is being installed
|
|
17
|
+
* as a dependency in someone else's `node_modules/`, where there's no `.git`).
|
|
18
|
+
*
|
|
19
|
+
* Safe to re-run.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
const { execFileSync } = require('child_process');
|
|
25
|
+
const fs = require('fs');
|
|
26
|
+
const path = require('path');
|
|
27
|
+
|
|
28
|
+
const REPO_ROOT = path.resolve(__dirname, '..');
|
|
29
|
+
const HOOKS_DIR = 'scripts/git-hooks';
|
|
30
|
+
|
|
31
|
+
// 1. Are we in a git working tree? If not, this is a downstream install —
|
|
32
|
+
// do nothing.
|
|
33
|
+
const gitDir = path.join(REPO_ROOT, '.git');
|
|
34
|
+
if (!fs.existsSync(gitDir)) {
|
|
35
|
+
// Silent no-op for downstream consumers. Their `node_modules/pan-wizard/`
|
|
36
|
+
// doesn't have its own .git directory.
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. Set core.hooksPath. Idempotent — overwrites any previous value.
|
|
41
|
+
try {
|
|
42
|
+
execFileSync('git', ['config', '--local', 'core.hooksPath', HOOKS_DIR], {
|
|
43
|
+
cwd: REPO_ROOT,
|
|
44
|
+
stdio: 'inherit',
|
|
45
|
+
});
|
|
46
|
+
} catch (err) {
|
|
47
|
+
// If `git` isn't on PATH or the config write fails, warn but don't fail
|
|
48
|
+
// the install. The user can run this manually later.
|
|
49
|
+
console.warn(`[install-git-hooks] could not set core.hooksPath: ${err.message}`);
|
|
50
|
+
process.exit(0);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 3. Confirm the hook file is executable on Unix. On Windows the bit doesn't
|
|
54
|
+
// matter — Git Bash treats `.sh` and shebanged scripts as executable.
|
|
55
|
+
const hookFile = path.join(REPO_ROOT, HOOKS_DIR, 'pre-commit');
|
|
56
|
+
if (process.platform !== 'win32') {
|
|
57
|
+
try {
|
|
58
|
+
fs.chmodSync(hookFile, 0o755);
|
|
59
|
+
} catch {
|
|
60
|
+
// Best effort.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.error(`[install-git-hooks] core.hooksPath → ${HOOKS_DIR} (gitleaks pre-commit active)`);
|
package/scripts/release-check.js
CHANGED
|
@@ -100,6 +100,17 @@ process.stderr.write('\n[release-check] Gate 4/6: doc-lint counts docs/\n');
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
|
|
104
|
+
// npm runs lifecycle scripts (prepare) before pack; any of their stdout noise
|
|
105
|
+
// lands ahead of the --json payload. npm pretty-prints the JSON array starting
|
|
106
|
+
// on its own line — parse from there.
|
|
107
|
+
function parseNpmJson(stdout) {
|
|
108
|
+
try { return JSON.parse(stdout); } catch { /* fall through to extraction */ }
|
|
109
|
+
const m = stdout.search(/^[[{]s*$/m);
|
|
110
|
+
if (m === -1) throw new Error('no JSON payload found in npm output');
|
|
111
|
+
return JSON.parse(stdout.slice(m));
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
// Gate 5: npm pack dry-run
|
|
104
115
|
process.stderr.write('\n[release-check] Gate 5/6: npm pack --dry-run\n');
|
|
105
116
|
{
|
|
@@ -111,7 +122,7 @@ process.stderr.write('\n[release-check] Gate 5/6: npm pack --dry-run\n');
|
|
|
111
122
|
}
|
|
112
123
|
// Parse the JSON output to check size
|
|
113
124
|
try {
|
|
114
|
-
const parsed =
|
|
125
|
+
const parsed = parseNpmJson(r.stdout);
|
|
115
126
|
const entry = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
116
127
|
const size = entry.size || 0;
|
|
117
128
|
const fileCount = entry.files ? entry.files.length : 0;
|
|
@@ -139,7 +150,7 @@ if (SKIP_SMOKE) {
|
|
|
139
150
|
logGate('smoke install (pack)', false, `exit ${pack.status}`);
|
|
140
151
|
process.exit(1);
|
|
141
152
|
}
|
|
142
|
-
const packJson =
|
|
153
|
+
const packJson = parseNpmJson(pack.stdout);
|
|
143
154
|
const tarball = path.join(tmpDir, packJson[0].filename);
|
|
144
155
|
if (!fs.existsSync(tarball)) {
|
|
145
156
|
logGate('smoke install (pack)', false, `tarball not found at ${tarball}`);
|