pan-wizard 3.14.0 → 3.15.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/LICENSE +21 -21
- package/README.md +1 -1
- package/commands/pan/audit-deployment.md +384 -384
- package/commands/pan/focus-auto.md +683 -683
- package/commands/pan/focus-doc-audit.md +530 -530
- package/commands/pan/focus-drift-walking.md +525 -525
- package/commands/pan/git.md +1 -1
- package/commands/pan/hud.md +3 -2
- package/commands/pan/report.md +70 -0
- package/hooks/dist/pan-check-update.js +62 -62
- package/hooks/dist/pan-context-monitor.js +134 -134
- package/package.json +1 -1
- package/pan-wizard-core/bin/lib/frontmatter.cjs +442 -442
- package/pan-wizard-core/bin/lib/hud.cjs +183 -14
- package/pan-wizard-core/bin/lib/phase-report.cjs +723 -0
- package/pan-wizard-core/bin/lib/utils.cjs +171 -171
- package/pan-wizard-core/bin/pan-tools.cjs +1499 -1473
- package/pan-wizard-core/references/checkpoints.md +776 -776
- package/pan-wizard-core/references/continuation-format.md +249 -249
- package/pan-wizard-core/references/questioning.md +145 -145
- package/pan-wizard-core/references/tdd.md +263 -263
- package/pan-wizard-core/references/ui-brand.md +160 -160
- package/pan-wizard-core/templates/config.json +38 -38
- package/scripts/build-hooks.js +51 -51
- package/scripts/git-hooks/pre-commit +0 -0
- package/scripts/release-check.js +27 -36
|
@@ -1,160 +1,160 @@
|
|
|
1
|
-
<ui_patterns>
|
|
2
|
-
|
|
3
|
-
Visual patterns for user-facing PAN output. Orchestrators @-reference this file.
|
|
4
|
-
|
|
5
|
-
## Stage Banners
|
|
6
|
-
|
|
7
|
-
Use for major workflow transitions.
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
11
|
-
PAN ► {STAGE NAME}
|
|
12
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
**Stage names (uppercase):**
|
|
16
|
-
- `QUESTIONING`
|
|
17
|
-
- `RESEARCHING`
|
|
18
|
-
- `DEFINING REQUIREMENTS`
|
|
19
|
-
- `CREATING ROADMAP`
|
|
20
|
-
- `PLANNING PHASE {N}`
|
|
21
|
-
- `EXECUTING WAVE {N}`
|
|
22
|
-
- `VERIFYING`
|
|
23
|
-
- `PHASE {N} COMPLETE ✓`
|
|
24
|
-
- `MILESTONE COMPLETE 🎉`
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Checkpoint Boxes
|
|
29
|
-
|
|
30
|
-
User action required. 62-character width.
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
╔══════════════════════════════════════════════════════════════╗
|
|
34
|
-
║ CHECKPOINT: {Type} ║
|
|
35
|
-
╚══════════════════════════════════════════════════════════════╝
|
|
36
|
-
|
|
37
|
-
{Content}
|
|
38
|
-
|
|
39
|
-
──────────────────────────────────────────────────────────────
|
|
40
|
-
→ {ACTION PROMPT}
|
|
41
|
-
──────────────────────────────────────────────────────────────
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Types:**
|
|
45
|
-
- `CHECKPOINT: Verification Required` → `→ Type "approved" or describe issues`
|
|
46
|
-
- `CHECKPOINT: Decision Required` → `→ Select: option-a / option-b`
|
|
47
|
-
- `CHECKPOINT: Action Required` → `→ Type "done" when complete`
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## Status Symbols
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
✓ Complete / Passed / Verified
|
|
55
|
-
✗ Failed / Missing / Blocked
|
|
56
|
-
◆ In Progress
|
|
57
|
-
○ Pending
|
|
58
|
-
⚡ Auto-approved
|
|
59
|
-
⚠ Warning
|
|
60
|
-
🎉 Milestone complete (only in banner)
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Progress Display
|
|
66
|
-
|
|
67
|
-
**Phase/milestone level:**
|
|
68
|
-
```
|
|
69
|
-
Progress: ████████░░ 80%
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
**Task level:**
|
|
73
|
-
```
|
|
74
|
-
Tasks: 2/4 complete
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
**Plan level:**
|
|
78
|
-
```
|
|
79
|
-
Plans: 3/5 complete
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
## Spawning Indicators
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
◆ Spawning researcher...
|
|
88
|
-
|
|
89
|
-
◆ Spawning 4 researchers in parallel...
|
|
90
|
-
→ Stack research
|
|
91
|
-
→ Features research
|
|
92
|
-
→ Architecture research
|
|
93
|
-
→ Pitfalls research
|
|
94
|
-
|
|
95
|
-
✓ Researcher complete: STACK.md written
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## Next Up Block
|
|
101
|
-
|
|
102
|
-
Always at end of major completions.
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
───────────────────────────────────────────────────────────────
|
|
106
|
-
|
|
107
|
-
## ▶ Next Up
|
|
108
|
-
|
|
109
|
-
**{Identifier}: {Name}** — {one-line description}
|
|
110
|
-
|
|
111
|
-
`{copy-paste command}`
|
|
112
|
-
|
|
113
|
-
<sub>`/clear` first → fresh context window</sub>
|
|
114
|
-
|
|
115
|
-
───────────────────────────────────────────────────────────────
|
|
116
|
-
|
|
117
|
-
**Also available:**
|
|
118
|
-
- `/pan:alternative-1` — description
|
|
119
|
-
- `/pan:alternative-2` — description
|
|
120
|
-
|
|
121
|
-
───────────────────────────────────────────────────────────────
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## Error Box
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
╔══════════════════════════════════════════════════════════════╗
|
|
130
|
-
║ ERROR ║
|
|
131
|
-
╚══════════════════════════════════════════════════════════════╝
|
|
132
|
-
|
|
133
|
-
{Error description}
|
|
134
|
-
|
|
135
|
-
**To fix:** {Resolution steps}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## Tables
|
|
141
|
-
|
|
142
|
-
```
|
|
143
|
-
| Phase | Status | Plans | Progress |
|
|
144
|
-
|-------|--------|-------|----------|
|
|
145
|
-
| 1 | ✓ | 3/3 | 100% |
|
|
146
|
-
| 2 | ◆ | 1/4 | 25% |
|
|
147
|
-
| 3 | ○ | 0/2 | 0% |
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
## Anti-Patterns
|
|
153
|
-
|
|
154
|
-
- Varying box/banner widths
|
|
155
|
-
- Mixing banner styles (`===`, `---`, `***`)
|
|
156
|
-
- Skipping `PAN ►` prefix in banners
|
|
157
|
-
- Random emoji (`🚀`, `✨`, `💫`)
|
|
158
|
-
- Missing Next Up block after completions
|
|
159
|
-
|
|
160
|
-
</ui_patterns>
|
|
1
|
+
<ui_patterns>
|
|
2
|
+
|
|
3
|
+
Visual patterns for user-facing PAN output. Orchestrators @-reference this file.
|
|
4
|
+
|
|
5
|
+
## Stage Banners
|
|
6
|
+
|
|
7
|
+
Use for major workflow transitions.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
11
|
+
PAN ► {STAGE NAME}
|
|
12
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Stage names (uppercase):**
|
|
16
|
+
- `QUESTIONING`
|
|
17
|
+
- `RESEARCHING`
|
|
18
|
+
- `DEFINING REQUIREMENTS`
|
|
19
|
+
- `CREATING ROADMAP`
|
|
20
|
+
- `PLANNING PHASE {N}`
|
|
21
|
+
- `EXECUTING WAVE {N}`
|
|
22
|
+
- `VERIFYING`
|
|
23
|
+
- `PHASE {N} COMPLETE ✓`
|
|
24
|
+
- `MILESTONE COMPLETE 🎉`
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Checkpoint Boxes
|
|
29
|
+
|
|
30
|
+
User action required. 62-character width.
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
34
|
+
║ CHECKPOINT: {Type} ║
|
|
35
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
36
|
+
|
|
37
|
+
{Content}
|
|
38
|
+
|
|
39
|
+
──────────────────────────────────────────────────────────────
|
|
40
|
+
→ {ACTION PROMPT}
|
|
41
|
+
──────────────────────────────────────────────────────────────
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Types:**
|
|
45
|
+
- `CHECKPOINT: Verification Required` → `→ Type "approved" or describe issues`
|
|
46
|
+
- `CHECKPOINT: Decision Required` → `→ Select: option-a / option-b`
|
|
47
|
+
- `CHECKPOINT: Action Required` → `→ Type "done" when complete`
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Status Symbols
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
✓ Complete / Passed / Verified
|
|
55
|
+
✗ Failed / Missing / Blocked
|
|
56
|
+
◆ In Progress
|
|
57
|
+
○ Pending
|
|
58
|
+
⚡ Auto-approved
|
|
59
|
+
⚠ Warning
|
|
60
|
+
🎉 Milestone complete (only in banner)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Progress Display
|
|
66
|
+
|
|
67
|
+
**Phase/milestone level:**
|
|
68
|
+
```
|
|
69
|
+
Progress: ████████░░ 80%
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Task level:**
|
|
73
|
+
```
|
|
74
|
+
Tasks: 2/4 complete
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**Plan level:**
|
|
78
|
+
```
|
|
79
|
+
Plans: 3/5 complete
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Spawning Indicators
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
◆ Spawning researcher...
|
|
88
|
+
|
|
89
|
+
◆ Spawning 4 researchers in parallel...
|
|
90
|
+
→ Stack research
|
|
91
|
+
→ Features research
|
|
92
|
+
→ Architecture research
|
|
93
|
+
→ Pitfalls research
|
|
94
|
+
|
|
95
|
+
✓ Researcher complete: STACK.md written
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Next Up Block
|
|
101
|
+
|
|
102
|
+
Always at end of major completions.
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
───────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
## ▶ Next Up
|
|
108
|
+
|
|
109
|
+
**{Identifier}: {Name}** — {one-line description}
|
|
110
|
+
|
|
111
|
+
`{copy-paste command}`
|
|
112
|
+
|
|
113
|
+
<sub>`/clear` first → fresh context window</sub>
|
|
114
|
+
|
|
115
|
+
───────────────────────────────────────────────────────────────
|
|
116
|
+
|
|
117
|
+
**Also available:**
|
|
118
|
+
- `/pan:alternative-1` — description
|
|
119
|
+
- `/pan:alternative-2` — description
|
|
120
|
+
|
|
121
|
+
───────────────────────────────────────────────────────────────
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Error Box
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
130
|
+
║ ERROR ║
|
|
131
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
132
|
+
|
|
133
|
+
{Error description}
|
|
134
|
+
|
|
135
|
+
**To fix:** {Resolution steps}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Tables
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
| Phase | Status | Plans | Progress |
|
|
144
|
+
|-------|--------|-------|----------|
|
|
145
|
+
| 1 | ✓ | 3/3 | 100% |
|
|
146
|
+
| 2 | ◆ | 1/4 | 25% |
|
|
147
|
+
| 3 | ○ | 0/2 | 0% |
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Anti-Patterns
|
|
153
|
+
|
|
154
|
+
- Varying box/banner widths
|
|
155
|
+
- Mixing banner styles (`===`, `---`, `***`)
|
|
156
|
+
- Skipping `PAN ►` prefix in banners
|
|
157
|
+
- Random emoji (`🚀`, `✨`, `💫`)
|
|
158
|
+
- Missing Next Up block after completions
|
|
159
|
+
|
|
160
|
+
</ui_patterns>
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mode": "interactive",
|
|
3
|
-
"depth": "standard",
|
|
4
|
-
"workflow": {
|
|
5
|
-
"research": true,
|
|
6
|
-
"plan_check": true,
|
|
7
|
-
"verifier": true,
|
|
8
|
-
"auto_advance": false,
|
|
9
|
-
"nyquist_validation": false,
|
|
10
|
-
"phase_record_compact": false
|
|
11
|
-
},
|
|
12
|
-
"planning": {
|
|
13
|
-
"commit_docs": true,
|
|
14
|
-
"search_gitignored": false
|
|
15
|
-
},
|
|
16
|
-
"parallelization": {
|
|
17
|
-
"enabled": true,
|
|
18
|
-
"plan_level": true,
|
|
19
|
-
"task_level": false,
|
|
20
|
-
"skip_checkpoints": true,
|
|
21
|
-
"max_concurrent_agents": 3,
|
|
22
|
-
"min_plans_for_parallel": 2
|
|
23
|
-
},
|
|
24
|
-
"gates": {
|
|
25
|
-
"confirm_project": true,
|
|
26
|
-
"confirm_phases": true,
|
|
27
|
-
"confirm_roadmap": true,
|
|
28
|
-
"confirm_breakdown": true,
|
|
29
|
-
"confirm_plan": true,
|
|
30
|
-
"execute_next_plan": true,
|
|
31
|
-
"issues_review": true,
|
|
32
|
-
"confirm_transition": true
|
|
33
|
-
},
|
|
34
|
-
"safety": {
|
|
35
|
-
"always_confirm_destructive": true,
|
|
36
|
-
"always_confirm_external_services": true
|
|
37
|
-
}
|
|
38
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"mode": "interactive",
|
|
3
|
+
"depth": "standard",
|
|
4
|
+
"workflow": {
|
|
5
|
+
"research": true,
|
|
6
|
+
"plan_check": true,
|
|
7
|
+
"verifier": true,
|
|
8
|
+
"auto_advance": false,
|
|
9
|
+
"nyquist_validation": false,
|
|
10
|
+
"phase_record_compact": false
|
|
11
|
+
},
|
|
12
|
+
"planning": {
|
|
13
|
+
"commit_docs": true,
|
|
14
|
+
"search_gitignored": false
|
|
15
|
+
},
|
|
16
|
+
"parallelization": {
|
|
17
|
+
"enabled": true,
|
|
18
|
+
"plan_level": true,
|
|
19
|
+
"task_level": false,
|
|
20
|
+
"skip_checkpoints": true,
|
|
21
|
+
"max_concurrent_agents": 3,
|
|
22
|
+
"min_plans_for_parallel": 2
|
|
23
|
+
},
|
|
24
|
+
"gates": {
|
|
25
|
+
"confirm_project": true,
|
|
26
|
+
"confirm_phases": true,
|
|
27
|
+
"confirm_roadmap": true,
|
|
28
|
+
"confirm_breakdown": true,
|
|
29
|
+
"confirm_plan": true,
|
|
30
|
+
"execute_next_plan": true,
|
|
31
|
+
"issues_review": true,
|
|
32
|
+
"confirm_transition": true
|
|
33
|
+
},
|
|
34
|
+
"safety": {
|
|
35
|
+
"always_confirm_destructive": true,
|
|
36
|
+
"always_confirm_external_services": true
|
|
37
|
+
}
|
|
38
|
+
}
|
package/scripts/build-hooks.js
CHANGED
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Copy PAN hooks from hooks/ to hooks/dist/ for installation.
|
|
4
|
-
*
|
|
5
|
-
* This is COPY-ONLY. PAN's hooks are pure Node.js with zero runtime
|
|
6
|
-
* dependencies, so no bundling step is needed. The script is named
|
|
7
|
-
* "build-hooks" for npm-script convention, but the work is `cp`.
|
|
8
|
-
*
|
|
9
|
-
* (See docs/IMPROVEMENT-TODO.md P2 for the rationale.)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const path = require('path');
|
|
14
|
-
|
|
15
|
-
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
|
|
16
|
-
const DIST_DIR = path.join(HOOKS_DIR, 'dist');
|
|
17
|
-
|
|
18
|
-
// Hooks to copy (pure Node.js, no bundling needed)
|
|
19
|
-
const HOOKS_TO_COPY = [
|
|
20
|
-
'pan-check-update.js',
|
|
21
|
-
'pan-context-monitor.js',
|
|
22
|
-
'pan-statusline.js',
|
|
23
|
-
'pan-cost-logger.js',
|
|
24
|
-
'pan-trace-logger.js'
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
function build() {
|
|
28
|
-
// Ensure dist directory exists
|
|
29
|
-
if (!fs.existsSync(DIST_DIR)) {
|
|
30
|
-
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Copy hooks to dist
|
|
34
|
-
for (const hook of HOOKS_TO_COPY) {
|
|
35
|
-
const src = path.join(HOOKS_DIR, hook);
|
|
36
|
-
const dest = path.join(DIST_DIR, hook);
|
|
37
|
-
|
|
38
|
-
if (!fs.existsSync(src)) {
|
|
39
|
-
console.warn(`Warning: ${hook} not found, skipping`);
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.log(`Copying ${hook}...`);
|
|
44
|
-
fs.copyFileSync(src, dest);
|
|
45
|
-
console.log(` → ${dest}`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
console.log('\nBuild complete.');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
build();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copy PAN hooks from hooks/ to hooks/dist/ for installation.
|
|
4
|
+
*
|
|
5
|
+
* This is COPY-ONLY. PAN's hooks are pure Node.js with zero runtime
|
|
6
|
+
* dependencies, so no bundling step is needed. The script is named
|
|
7
|
+
* "build-hooks" for npm-script convention, but the work is `cp`.
|
|
8
|
+
*
|
|
9
|
+
* (See docs/IMPROVEMENT-TODO.md P2 for the rationale.)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
const HOOKS_DIR = path.join(__dirname, '..', 'hooks');
|
|
16
|
+
const DIST_DIR = path.join(HOOKS_DIR, 'dist');
|
|
17
|
+
|
|
18
|
+
// Hooks to copy (pure Node.js, no bundling needed)
|
|
19
|
+
const HOOKS_TO_COPY = [
|
|
20
|
+
'pan-check-update.js',
|
|
21
|
+
'pan-context-monitor.js',
|
|
22
|
+
'pan-statusline.js',
|
|
23
|
+
'pan-cost-logger.js',
|
|
24
|
+
'pan-trace-logger.js'
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
function build() {
|
|
28
|
+
// Ensure dist directory exists
|
|
29
|
+
if (!fs.existsSync(DIST_DIR)) {
|
|
30
|
+
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Copy hooks to dist
|
|
34
|
+
for (const hook of HOOKS_TO_COPY) {
|
|
35
|
+
const src = path.join(HOOKS_DIR, hook);
|
|
36
|
+
const dest = path.join(DIST_DIR, hook);
|
|
37
|
+
|
|
38
|
+
if (!fs.existsSync(src)) {
|
|
39
|
+
console.warn(`Warning: ${hook} not found, skipping`);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log(`Copying ${hook}...`);
|
|
44
|
+
fs.copyFileSync(src, dest);
|
|
45
|
+
console.log(` → ${dest}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log('\nBuild complete.');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
build();
|
|
File without changes
|
package/scripts/release-check.js
CHANGED
|
@@ -116,40 +116,30 @@ process.stderr.write('\n[release-check] Gate 5/7: links validate\n');
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// Gate 6: npm pack dry-run
|
|
130
|
-
process.stderr.write('\n[release-check] Gate 6/7: npm pack --dry-run\n');
|
|
119
|
+
// NOTE: we deliberately do NOT parse `npm pack --json` stdout. Under
|
|
120
|
+
// `npm publish` the runner routes the child pack's lifecycle-script output onto
|
|
121
|
+
// stdout (foreground-scripts), and that noise can include a decoy JSON object —
|
|
122
|
+
// any string heuristic then picks the wrong payload (Gate 7 crashed on
|
|
123
|
+
// packJson[0].filename with "0 files"). Instead, pack into a temp dir and read
|
|
124
|
+
// the .tgz npm actually wrote: a filesystem op that stdout noise cannot corrupt.
|
|
125
|
+
|
|
126
|
+
// Gate 6: npm pack — produces a non-empty, sanely-sized tarball (read the file,
|
|
127
|
+
// never parse stdout)
|
|
128
|
+
process.stderr.write('\n[release-check] Gate 6/7: npm pack (size sanity)\n');
|
|
131
129
|
{
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
const tmp6 = fs.mkdtempSync(path.join(os.tmpdir(), 'pan-release-pack-'));
|
|
131
|
+
const r = run('npm', ['pack', '--pack-destination', tmp6], { capture: true });
|
|
132
|
+
const tgz = r.status === 0 ? fs.readdirSync(tmp6).find(f => f.endsWith('.tgz')) : null;
|
|
133
|
+
const size = tgz ? fs.statSync(path.join(tmp6, tgz)).size : 0;
|
|
134
|
+
const sizeMB = (size / 1024 / 1024).toFixed(2);
|
|
135
|
+
// Sane = a non-empty tarball under 50MB (large for a zero-runtime-dep tool)
|
|
136
|
+
const ok = r.status === 0 && !!tgz && size > 0 && size < 50 * 1024 * 1024;
|
|
137
|
+
logGate('npm pack', ok, tgz ? `${sizeMB}MB tarball` : `no tarball (exit ${r.status})`);
|
|
138
|
+
fs.rmSync(tmp6, { recursive: true, force: true });
|
|
139
|
+
if (!ok) {
|
|
135
140
|
process.stderr.write((r.stderr || '') + '\n');
|
|
136
141
|
process.exit(1);
|
|
137
142
|
}
|
|
138
|
-
// Parse the JSON output to check size
|
|
139
|
-
try {
|
|
140
|
-
const parsed = parseNpmJson(r.stdout);
|
|
141
|
-
const entry = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
142
|
-
const size = entry.size || 0;
|
|
143
|
-
const fileCount = entry.files ? entry.files.length : 0;
|
|
144
|
-
const sizeMB = (size / 1024 / 1024).toFixed(2);
|
|
145
|
-
// Flag if pack size exceeds 50MB — large for a zero-runtime-dep tool
|
|
146
|
-
const ok = size < 50 * 1024 * 1024;
|
|
147
|
-
logGate('npm pack dry-run', ok, `${sizeMB}MB, ${fileCount} files`);
|
|
148
|
-
if (!ok) process.exit(1);
|
|
149
|
-
} catch (err) {
|
|
150
|
-
logGate('npm pack dry-run', false, 'JSON parse failed: ' + err.message);
|
|
151
|
-
process.exit(1);
|
|
152
|
-
}
|
|
153
143
|
}
|
|
154
144
|
|
|
155
145
|
// Gate 7: smoke install — pack and install into temp dir, run pan-tools
|
|
@@ -159,18 +149,19 @@ if (SKIP_SMOKE) {
|
|
|
159
149
|
process.stderr.write('\n[release-check] Gate 7/7: smoke install (npm pack + install + sanity)\n');
|
|
160
150
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pan-release-smoke-'));
|
|
161
151
|
try {
|
|
162
|
-
// Pack
|
|
163
|
-
const pack = run('npm', ['pack', '--pack-destination', tmpDir
|
|
152
|
+
// Pack — read the .tgz npm writes to tmpDir; never parse its stdout (see note).
|
|
153
|
+
const pack = run('npm', ['pack', '--pack-destination', tmpDir], { capture: true });
|
|
164
154
|
if (pack.status !== 0) {
|
|
165
155
|
logGate('smoke install (pack)', false, `exit ${pack.status}`);
|
|
156
|
+
process.stderr.write((pack.stderr || '') + '\n');
|
|
166
157
|
process.exit(1);
|
|
167
158
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
logGate('smoke install (pack)', false, `tarball not found at ${tarball}`);
|
|
159
|
+
const tgz = fs.readdirSync(tmpDir).find(f => f.endsWith('.tgz'));
|
|
160
|
+
if (!tgz) {
|
|
161
|
+
logGate('smoke install (pack)', false, `no .tgz produced in ${tmpDir}`);
|
|
172
162
|
process.exit(1);
|
|
173
163
|
}
|
|
164
|
+
const tarball = path.join(tmpDir, tgz);
|
|
174
165
|
// Install into a separate fake project dir
|
|
175
166
|
const installDir = path.join(tmpDir, 'install-target');
|
|
176
167
|
fs.mkdirSync(installDir, { recursive: true });
|