grimoire-framework 1.0.15 → 1.0.17
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.
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
# - SHA256 hashes for change detection
|
|
8
8
|
# - File types for categorization
|
|
9
9
|
#
|
|
10
|
-
version: 1.0.
|
|
11
|
-
generated_at: "2026-02-
|
|
10
|
+
version: 1.0.17
|
|
11
|
+
generated_at: "2026-02-22T13:53:52.136Z"
|
|
12
12
|
generator: scripts/generate-install-manifest.js
|
|
13
13
|
file_count: 1011
|
|
14
14
|
files:
|
package/bin/commands/update.js
CHANGED
|
@@ -29,6 +29,7 @@ const FRAMEWORK_SYNC_DIRS = [
|
|
|
29
29
|
// Single files to sync (framework root → project root)
|
|
30
30
|
const FRAMEWORK_SYNC_FILES = [
|
|
31
31
|
{ src: 'GEMINI.md', dest: 'GEMINI.md' },
|
|
32
|
+
{ src: '.grimoire/product/templates/ide-rules/gemini-rules.md', dest: path.join('.gemini', 'rules.md') },
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
/**
|
package/bin/grimoire-cli.js
CHANGED
|
@@ -132,12 +132,22 @@ function handleStatus() {
|
|
|
132
132
|
const check = (p) => fs.existsSync(p);
|
|
133
133
|
const icon = (v) => v ? '✅' : '❌';
|
|
134
134
|
|
|
135
|
-
// Detect project root (has .codex or .grimoire)
|
|
136
135
|
const hasCodex = check(path.join(cwd, '.codex'));
|
|
137
136
|
const hasGrimoire = check(path.join(cwd, '.grimoire'));
|
|
138
137
|
const hasGemini = check(path.join(cwd, '.gemini'));
|
|
139
138
|
const hasCursor = check(path.join(cwd, '.cursor'));
|
|
140
139
|
const hasClaude = check(path.join(cwd, '.claude'));
|
|
140
|
+
const hasGeminiMd = check(path.join(cwd, 'GEMINI.md'));
|
|
141
|
+
const hasGeminiRules = check(path.join(cwd, '.gemini', 'rules.md'));
|
|
142
|
+
|
|
143
|
+
// Check GEMINI.md has correct persona
|
|
144
|
+
let geminiPersonaOk = false;
|
|
145
|
+
if (hasGeminiMd) {
|
|
146
|
+
try {
|
|
147
|
+
const content = fs.readFileSync(path.join(cwd, 'GEMINI.md'), 'utf8');
|
|
148
|
+
geminiPersonaOk = content.includes('Michelangelo');
|
|
149
|
+
} catch (e) { /* ignore */ }
|
|
150
|
+
}
|
|
141
151
|
|
|
142
152
|
// Hooks check
|
|
143
153
|
const settingsPath = path.join(cwd, '.gemini', 'settings.json');
|
|
@@ -162,44 +172,41 @@ function handleStatus() {
|
|
|
162
172
|
const memDir = path.join(cwd, '.grimoire', 'memory');
|
|
163
173
|
const hasMemory = check(memDir);
|
|
164
174
|
|
|
165
|
-
//
|
|
166
|
-
const
|
|
167
|
-
let
|
|
168
|
-
if (check(
|
|
169
|
-
try {
|
|
170
|
-
const lines = fs.readFileSync(sessionLog, 'utf8').trim().split('\n');
|
|
171
|
-
const last = lines.filter(l => l.includes('agent:')).pop();
|
|
172
|
-
if (last) lastAgent = last.split('agent:')[1]?.trim();
|
|
173
|
-
} catch (e) { /* ignore */ }
|
|
175
|
+
// Installed version vs package.json
|
|
176
|
+
const installedPkgPath = path.join(cwd, 'node_modules', 'grimoire-framework', 'package.json');
|
|
177
|
+
let installedVersion = null;
|
|
178
|
+
if (check(installedPkgPath)) {
|
|
179
|
+
try { installedVersion = JSON.parse(fs.readFileSync(installedPkgPath, 'utf8')).version; } catch (e) { }
|
|
174
180
|
}
|
|
181
|
+
const versionMatch = installedVersion === packageJson.version;
|
|
175
182
|
|
|
176
183
|
console.log(`
|
|
177
184
|
🔮 Grimoire Framework Status
|
|
178
185
|
${'='.repeat(40)}
|
|
179
|
-
📎 Version: v${packageJson.version}
|
|
180
|
-
📁 Project: ${cwd}
|
|
186
|
+
📎 Version: v${packageJson.version}${installedVersion && !versionMatch ? ` (project has v${installedVersion})` : ''}
|
|
187
|
+
📁 Project: ${path.basename(cwd)}
|
|
181
188
|
|
|
182
189
|
🔧 Core
|
|
183
190
|
${icon(hasCodex)} .codex (agents & config)
|
|
184
191
|
${icon(hasGrimoire)} .grimoire (memory & metrics)
|
|
185
192
|
${icon(agentCount > 0)} Agents: ${agentCount} loaded
|
|
186
193
|
|
|
187
|
-
🪝 Hooks (Gemini CLI)
|
|
188
|
-
${icon(check(settingsPath))} settings.json
|
|
189
|
-
${icon(hooksActive)} Hooks active: ${hooksActive ? hooks.length + ' configured' : 'none found'}
|
|
190
|
-
|
|
191
194
|
💻 IDE Integration
|
|
192
|
-
${icon(
|
|
195
|
+
${icon(hasGeminiMd)} GEMINI.md (Gemini CLI — primary config)
|
|
196
|
+
${icon(geminiPersonaOk)} Michelangelo persona active
|
|
197
|
+
${icon(hasGeminiRules)} .gemini/rules.md (compatibility fallback)
|
|
193
198
|
${icon(hasCursor)} .cursor (Cursor rules)
|
|
194
199
|
${icon(hasClaude)} .claude (Claude commands)
|
|
195
200
|
|
|
201
|
+
🪝 Hooks (Gemini CLI)
|
|
202
|
+
${icon(check(settingsPath))} settings.json
|
|
203
|
+
${icon(hooksActive)} Hooks: ${hooksActive ? hooks.length + ' configured' : 'none'}
|
|
204
|
+
|
|
196
205
|
💾 Memory Layer
|
|
197
206
|
${icon(hasMemory)} Memory store ${hasMemory ? '(active)' : '(not initialized)'}
|
|
198
|
-
${lastAgent ? `
|
|
199
|
-
🧙 Last Agent: @${lastAgent}` : ''}
|
|
200
207
|
|
|
201
|
-
Run 'grimoire agents list' to see all agents.
|
|
202
|
-
Run 'grimoire
|
|
208
|
+
${!hasGeminiMd || !geminiPersonaOk ? '⚠️ Run: npx grimoire-framework update --force to fix missing files\n' : ''} Run 'grimoire agents list' to see all agents.
|
|
209
|
+
Run 'grimoire doctor' for diagnostics with tips.
|
|
203
210
|
`);
|
|
204
211
|
}
|
|
205
212
|
|
|
@@ -276,29 +283,95 @@ ${config.squad ? `👥 Squad: ${config.squad}` : ''}
|
|
|
276
283
|
function handleDoctor() {
|
|
277
284
|
const cwd = process.cwd();
|
|
278
285
|
const check = (p) => fs.existsSync(p);
|
|
279
|
-
const ok = (v, msg) =>
|
|
286
|
+
const ok = (v, msg, hint) => {
|
|
287
|
+
console.log(` ${v ? '✅' : '❌'} ${msg}`);
|
|
288
|
+
if (!v && hint) console.log(` 💡 ${hint}`);
|
|
289
|
+
};
|
|
290
|
+
const warn = (v, msg, hint) => {
|
|
291
|
+
console.log(` ${v ? '✅' : '⚠️ '} ${msg}`);
|
|
292
|
+
if (!v && hint) console.log(` 💡 ${hint}`);
|
|
293
|
+
};
|
|
280
294
|
|
|
281
295
|
console.log('\n🏥 Grimoire Doctor\n' + '='.repeat(40));
|
|
282
296
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
297
|
+
// ── Gemini CLI Integration ──────────────────────────────────────
|
|
298
|
+
console.log('\n💻 Gemini CLI Integration:');
|
|
299
|
+
const geminiMdPath = path.join(cwd, 'GEMINI.md');
|
|
300
|
+
const rulesPath = path.join(cwd, '.gemini', 'rules.md');
|
|
301
|
+
const hasGeminiMd = check(geminiMdPath);
|
|
302
|
+
const hasRulesMd = check(rulesPath);
|
|
303
|
+
|
|
304
|
+
ok(hasGeminiMd, 'GEMINI.md (primary config for modern Gemini CLI)',
|
|
305
|
+
'Run: npx grimoire-framework update --force');
|
|
306
|
+
warn(hasRulesMd, '.gemini/rules.md (compatibility fallback)',
|
|
307
|
+
'Run: npx grimoire-framework update --force');
|
|
288
308
|
|
|
289
|
-
|
|
309
|
+
if (hasGeminiMd) {
|
|
310
|
+
try {
|
|
311
|
+
const content = fs.readFileSync(geminiMdPath, 'utf8');
|
|
312
|
+
ok(content.includes('Michelangelo'), 'Michelangelo persona in GEMINI.md',
|
|
313
|
+
'GEMINI.md may be outdated — run: npx grimoire-framework update --force');
|
|
314
|
+
ok(content.includes('@dev'), 'Agent roster in GEMINI.md',
|
|
315
|
+
'GEMINI.md is missing the agent roster');
|
|
316
|
+
} catch (e) { ok(false, 'GEMINI.md readable'); }
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ── Agents ─────────────────────────────────────────────────────
|
|
320
|
+
console.log('\n🤖 Agents:');
|
|
321
|
+
const agentsDir = path.join(cwd, '.codex', 'agents');
|
|
322
|
+
ok(check(agentsDir), '.codex/agents directory', 'Run: npx grimoire-framework update --force');
|
|
323
|
+
if (check(agentsDir)) {
|
|
324
|
+
const agents = fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'));
|
|
325
|
+
ok(agents.length >= 10, `Core agents installed (${agents.length} found, need ≥10)`,
|
|
326
|
+
'Run: npx grimoire-framework update --force');
|
|
327
|
+
|
|
328
|
+
const requiredAgents = ['grimoire-master.md', 'dev.md', 'qa.md', 'architect.md', 'pm.md'];
|
|
329
|
+
for (const a of requiredAgents) {
|
|
330
|
+
warn(agents.includes(a), `Agent: ${a.replace('.md', '')}`);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Check grimoire-master has Michelangelo
|
|
334
|
+
const masterPath = path.join(agentsDir, 'grimoire-master.md');
|
|
335
|
+
if (check(masterPath)) {
|
|
336
|
+
try {
|
|
337
|
+
const content = fs.readFileSync(masterPath, 'utf8');
|
|
338
|
+
ok(content.includes('Michelangelo'), 'grimoire-master has Michelangelo persona',
|
|
339
|
+
'Outdated agent — run: npx grimoire-framework update --force');
|
|
340
|
+
} catch (e) { }
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ── Framework Package ──────────────────────────────────────────
|
|
345
|
+
console.log('\n📦 Package:');
|
|
290
346
|
const pkgPath = path.join(cwd, 'package.json');
|
|
291
347
|
if (check(pkgPath)) {
|
|
292
348
|
try {
|
|
293
349
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
294
350
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
295
|
-
ok(!!deps['grimoire-framework'], 'grimoire-framework in package.json'
|
|
351
|
+
ok(!!deps['grimoire-framework'], 'grimoire-framework in package.json',
|
|
352
|
+
'Run: npm install grimoire-framework');
|
|
353
|
+
|
|
354
|
+
// Check installed version vs latest
|
|
355
|
+
const installedPkgPath = path.join(cwd, 'node_modules', 'grimoire-framework', 'package.json');
|
|
356
|
+
if (check(installedPkgPath)) {
|
|
357
|
+
try {
|
|
358
|
+
const installedVer = JSON.parse(fs.readFileSync(installedPkgPath, 'utf8')).version;
|
|
359
|
+
const declaredVer = (deps['grimoire-framework'] || '').replace(/[^0-9.]/g, '');
|
|
360
|
+
ok(true, `Installed version: v${installedVer}`);
|
|
361
|
+
} catch (e) { }
|
|
362
|
+
}
|
|
296
363
|
} catch (e) { ok(false, 'package.json readable'); }
|
|
297
364
|
} else {
|
|
298
365
|
ok(false, 'package.json found');
|
|
299
366
|
}
|
|
300
367
|
|
|
301
|
-
|
|
368
|
+
// ── Other IDEs ────────────────────────────────────────────────
|
|
369
|
+
console.log('\n🔗 Other IDE Integration:');
|
|
370
|
+
warn(check(path.join(cwd, '.cursor', 'rules')), '.cursor/rules (Cursor)');
|
|
371
|
+
warn(check(path.join(cwd, '.claude')), '.claude/ (Claude Code)');
|
|
372
|
+
|
|
373
|
+
console.log('\n Run \'grimoire status\' for full framework state.');
|
|
374
|
+
console.log(' Run \'npx grimoire-framework update --force\' to resync all files.\n');
|
|
302
375
|
}
|
|
303
376
|
|
|
304
377
|
function showHelp() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grimoire-framework",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.17",
|
|
4
4
|
"description": "Grimoire: AI-Orchestrated System for Full Stack Development - Core Framework",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
"validate:semantic-lint": "node scripts/semantic-lint.js",
|
|
78
78
|
"manifest:ensure": "node scripts/ensure-manifest.js",
|
|
79
79
|
"sync:ide:cursor": "node .grimoire/infrastructure/scripts/ide-sync/index.js sync --ide cursor",
|
|
80
|
-
"prepublishOnly": "npm run generate:manifest && npm run validate:manifest",
|
|
80
|
+
"prepublishOnly": "node scripts/pre-publish-check.js && npm run generate:manifest && npm run validate:manifest",
|
|
81
81
|
"prepare": "husky"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
* @module packages/installer/src/updater
|
|
6
6
|
* @story Epic 7 - CLI Update Command
|
|
7
7
|
* @version 1.0.0
|
|
8
|
+
* @deprecated Use bin/commands/update.js instead.
|
|
9
|
+
* The new smart update command (grimoire-framework@1.0.10+) replaces this class.
|
|
10
|
+
* This file is kept for backwards compatibility of the installer wizard only.
|
|
11
|
+
* DO NOT add new update logic here — use bin/commands/update.js.
|
|
8
12
|
*
|
|
9
13
|
* Features:
|
|
10
14
|
* - Detects installed version vs latest available
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* pre-publish-check.js
|
|
6
|
+
* Validates that all critical files are included in the npm package before publish.
|
|
7
|
+
* Run: node scripts/pre-publish-check.js
|
|
8
|
+
*
|
|
9
|
+
* Bloqueia o publish se arquivos críticos estiverem faltando.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const { execSync } = require('child_process');
|
|
15
|
+
|
|
16
|
+
const ROOT = path.resolve(__dirname, '..');
|
|
17
|
+
const PASS = '✅';
|
|
18
|
+
const FAIL = '❌';
|
|
19
|
+
const WARN = '⚠️ ';
|
|
20
|
+
|
|
21
|
+
let hasErrors = false;
|
|
22
|
+
|
|
23
|
+
function check(label, condition, errorMsg) {
|
|
24
|
+
if (condition) {
|
|
25
|
+
console.log(` ${PASS} ${label}`);
|
|
26
|
+
} else {
|
|
27
|
+
console.log(` ${FAIL} ${label}`);
|
|
28
|
+
console.log(` → ${errorMsg}`);
|
|
29
|
+
hasErrors = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function warn(label, condition, warnMsg) {
|
|
34
|
+
if (condition) {
|
|
35
|
+
console.log(` ${PASS} ${label}`);
|
|
36
|
+
} else {
|
|
37
|
+
console.log(` ${WARN} ${label}`);
|
|
38
|
+
console.log(` → ${warnMsg}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
console.log('\n🔍 Grimoire Framework — Pre-Publish Quality Gate\n' + '='.repeat(50));
|
|
43
|
+
|
|
44
|
+
// ── 1. Critical root files ─────────────────────────────────────────────────
|
|
45
|
+
console.log('\n📄 Critical root files:');
|
|
46
|
+
check('GEMINI.md exists', fs.existsSync(path.join(ROOT, 'GEMINI.md')), 'GEMINI.md is required for Gemini CLI integration');
|
|
47
|
+
check('README.md exists', fs.existsSync(path.join(ROOT, 'README.md')), 'README.md missing');
|
|
48
|
+
check('LICENSE exists', fs.existsSync(path.join(ROOT, 'LICENSE')), 'LICENSE file missing');
|
|
49
|
+
|
|
50
|
+
// ── 2. package.json files[] validation ────────────────────────────────────
|
|
51
|
+
console.log('\n📦 package.json files[] field:');
|
|
52
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
|
|
53
|
+
const files = pkg.files || [];
|
|
54
|
+
|
|
55
|
+
const requiredInFiles = [
|
|
56
|
+
'GEMINI.md',
|
|
57
|
+
'.codex/',
|
|
58
|
+
'.gemini/',
|
|
59
|
+
'.cursor/',
|
|
60
|
+
'.grimoire/',
|
|
61
|
+
'bin/',
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
for (const required of requiredInFiles) {
|
|
65
|
+
check(
|
|
66
|
+
`files[] includes "${required}"`,
|
|
67
|
+
files.some(f => f === required || f.startsWith(required.replace('/', ''))),
|
|
68
|
+
`Add "${required}" to the "files" array in package.json`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ── 3. Binary entry points ─────────────────────────────────────────────────
|
|
73
|
+
console.log('\n⚙️ Binary entry points (bin/):');
|
|
74
|
+
const binEntries = pkg.bin || {};
|
|
75
|
+
const CORRECT_CLI = 'bin/grimoire-cli.js';
|
|
76
|
+
|
|
77
|
+
for (const [name, script] of Object.entries(binEntries)) {
|
|
78
|
+
if (name === 'grimoire-minimal') continue; // known exception
|
|
79
|
+
check(
|
|
80
|
+
`"${name}" → ${script}`,
|
|
81
|
+
script === CORRECT_CLI,
|
|
82
|
+
`Binary "${name}" points to "${script}" but should point to "${CORRECT_CLI}"`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── 4. .codex/agents presence ─────────────────────────────────────────────
|
|
87
|
+
console.log('\n🤖 Agents (.codex/agents):');
|
|
88
|
+
const agentsDir = path.join(ROOT, '.codex', 'agents');
|
|
89
|
+
const requiredAgents = [
|
|
90
|
+
'grimoire-master.md', 'dev.md', 'qa.md', 'architect.md',
|
|
91
|
+
'pm.md', 'po.md', 'sm.md', 'devops.md',
|
|
92
|
+
'data-engineer.md', 'analyst.md', 'ux-design-expert.md', 'squad-creator.md',
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
if (fs.existsSync(agentsDir)) {
|
|
96
|
+
const existingAgents = fs.readdirSync(agentsDir);
|
|
97
|
+
check(
|
|
98
|
+
`At least ${requiredAgents.length} core agents exist (found ${existingAgents.length})`,
|
|
99
|
+
existingAgents.length >= requiredAgents.length,
|
|
100
|
+
`Expected ${requiredAgents.length} agents, found ${existingAgents.length}`
|
|
101
|
+
);
|
|
102
|
+
for (const agent of requiredAgents) {
|
|
103
|
+
check(
|
|
104
|
+
`Agent: ${agent}`,
|
|
105
|
+
existingAgents.includes(agent),
|
|
106
|
+
`Missing required agent file: .codex/agents/${agent}`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
check('.codex/agents/ directory exists', false, '.codex/agents/ directory is missing');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── 5. GEMINI.md content validation ───────────────────────────────────────
|
|
114
|
+
console.log('\n📝 GEMINI.md content:');
|
|
115
|
+
const geminiMd = path.join(ROOT, 'GEMINI.md');
|
|
116
|
+
if (fs.existsSync(geminiMd)) {
|
|
117
|
+
const content = fs.readFileSync(geminiMd, 'utf8');
|
|
118
|
+
check('Contains Michelangelo persona', content.includes('Michelangelo'), 'GEMINI.md must define Michelangelo as default agent');
|
|
119
|
+
check('Contains agent roster', content.includes('@dev'), 'GEMINI.md should include agent roster');
|
|
120
|
+
check('Non-empty (>500 chars)', content.length > 500, 'GEMINI.md seems too short, may be incomplete');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ── 6. bin/grimoire-cli.js entry point ────────────────────────────────────
|
|
124
|
+
console.log('\n🚀 CLI entry point:');
|
|
125
|
+
const cliPath = path.join(ROOT, 'bin', 'grimoire-cli.js');
|
|
126
|
+
if (fs.existsSync(cliPath)) {
|
|
127
|
+
const cliContent = fs.readFileSync(cliPath, 'utf8');
|
|
128
|
+
check('commands/update.js is used (not grimoireUpdater)',
|
|
129
|
+
cliContent.includes("require('./commands/update')"),
|
|
130
|
+
'grimoire-cli.js should delegate update to commands/update.js'
|
|
131
|
+
);
|
|
132
|
+
check('No direct reference to old updater',
|
|
133
|
+
!cliContent.includes('grimoireUpdater'),
|
|
134
|
+
'grimoire-cli.js still references old grimoireUpdater'
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── 7. npm pack dry-run to count files ────────────────────────────────────
|
|
139
|
+
console.log('\n📦 npm pack dry-run:');
|
|
140
|
+
try {
|
|
141
|
+
const packOutput = execSync('npm pack --dry-run 2>&1', { cwd: ROOT, encoding: 'utf8' });
|
|
142
|
+
const fileCount = (packOutput.match(/npm notice \d+\.\d+[kBMG]B/g) || []).length;
|
|
143
|
+
warn(
|
|
144
|
+
`Package contains files (detected ~${fileCount} size entries)`,
|
|
145
|
+
fileCount > 10,
|
|
146
|
+
'Very few files detected in package — check the files[] field'
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const hasGeminiMd = packOutput.includes('GEMINI.md');
|
|
150
|
+
check('GEMINI.md is in the published package', hasGeminiMd, 'GEMINI.md not found in npm pack output — add to files[]');
|
|
151
|
+
|
|
152
|
+
const hasCodex = packOutput.includes('.codex/');
|
|
153
|
+
check('.codex/ agents are in the published package', hasCodex, '.codex/ not found in npm pack output — add to files[]');
|
|
154
|
+
} catch (err) {
|
|
155
|
+
warn('npm pack dry-run', false, `Could not run npm pack: ${err.message}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ── Summary ────────────────────────────────────────────────────────────────
|
|
159
|
+
console.log('\n' + '='.repeat(50));
|
|
160
|
+
if (hasErrors) {
|
|
161
|
+
console.log('❌ Pre-publish check FAILED — fix the errors above before publishing.\n');
|
|
162
|
+
process.exit(1);
|
|
163
|
+
} else {
|
|
164
|
+
console.log('✅ All checks passed — safe to publish!\n');
|
|
165
|
+
process.exit(0);
|
|
166
|
+
}
|