delimit-cli 4.1.1 → 4.1.2
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/bin/delimit-cli.js +91 -0
- package/package.json +1 -1
package/bin/delimit-cli.js
CHANGED
|
@@ -2328,6 +2328,97 @@ program
|
|
|
2328
2328
|
console.log('');
|
|
2329
2329
|
});
|
|
2330
2330
|
|
|
2331
|
+
// Scan command — instant governance analysis of any project or spec
|
|
2332
|
+
program
|
|
2333
|
+
.command('scan [path]')
|
|
2334
|
+
.description('Scan a project or OpenAPI spec for governance insights')
|
|
2335
|
+
.action(async (specPath) => {
|
|
2336
|
+
const target = specPath || '.';
|
|
2337
|
+
console.log(chalk.bold('\n Delimit Scan\n'));
|
|
2338
|
+
|
|
2339
|
+
// Detect if target is a spec file or a project directory
|
|
2340
|
+
const isFile = fs.existsSync(target) && fs.statSync(target).isFile();
|
|
2341
|
+
|
|
2342
|
+
if (isFile) {
|
|
2343
|
+
// Spec file — run spec health + show results
|
|
2344
|
+
console.log(chalk.gray(` Analyzing ${target}...\n`));
|
|
2345
|
+
try {
|
|
2346
|
+
const result = execSync(
|
|
2347
|
+
`python3 -c "import sys,json; sys.path.insert(0,'${continuityContext.serverDir}'); from core.spec_health import score_spec; import yaml; spec=yaml.safe_load(open('${target}')); r=score_spec(spec); print(json.dumps(r))"`,
|
|
2348
|
+
{ encoding: 'utf-8', timeout: 15000, cwd: continuityContext.serverDir }
|
|
2349
|
+
);
|
|
2350
|
+
const health = JSON.parse(result);
|
|
2351
|
+
const gradeColors = { A: 'green', B: 'blue', C: 'yellow', D: 'red', F: 'red' };
|
|
2352
|
+
const gradeColor = gradeColors[health.grade] || 'white';
|
|
2353
|
+
console.log(` ${chalk[gradeColor].bold(health.grade)} ${chalk.white.bold(health.overall_score + '/100')} ${chalk.gray('Spec Health Score')}\n`);
|
|
2354
|
+
for (const [dim, data] of Object.entries(health.dimensions || {})) {
|
|
2355
|
+
const score = data.score || 0;
|
|
2356
|
+
const bar = '█'.repeat(Math.round(score / 5)) + '░'.repeat(20 - Math.round(score / 5));
|
|
2357
|
+
const color = score >= 70 ? 'green' : score >= 40 ? 'yellow' : 'red';
|
|
2358
|
+
console.log(` ${chalk.gray(dim.padEnd(16))} ${chalk[color](bar)} ${score}`);
|
|
2359
|
+
}
|
|
2360
|
+
if (health.recommendations && health.recommendations.length > 0) {
|
|
2361
|
+
console.log(chalk.bold('\n Recommendations:\n'));
|
|
2362
|
+
health.recommendations.slice(0, 5).forEach(r => {
|
|
2363
|
+
const text = typeof r === 'object' ? (r.recommendation || r.text || JSON.stringify(r)) : r;
|
|
2364
|
+
console.log(` ${chalk.yellow('→')} ${text}`);
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
console.log(chalk.bold('\n Next steps:\n'));
|
|
2368
|
+
console.log(` ${chalk.green('npx delimit-cli lint')} ${target} ${chalk.gray('— check for breaking changes')}`);
|
|
2369
|
+
console.log(` ${chalk.green('npx delimit-cli init')} ${chalk.gray('— set up governance for this project')}\n`);
|
|
2370
|
+
} catch (e) {
|
|
2371
|
+
console.log(chalk.red(` Error: ${e.message}`));
|
|
2372
|
+
}
|
|
2373
|
+
} else {
|
|
2374
|
+
// Project directory — find specs and scan
|
|
2375
|
+
console.log(chalk.gray(` Scanning ${path.resolve(target)}...\n`));
|
|
2376
|
+
try {
|
|
2377
|
+
const result = execSync(
|
|
2378
|
+
`python3 -c "import sys,json; sys.path.insert(0,'${continuityContext.serverDir}'); from ai.server import delimit_scan; r=delimit_scan.fn('${target}') if hasattr(delimit_scan,'fn') else delimit_scan('${target}'); print(json.dumps(r))"`,
|
|
2379
|
+
{ encoding: 'utf-8', timeout: 30000, cwd: continuityContext.serverDir }
|
|
2380
|
+
);
|
|
2381
|
+
const scan = JSON.parse(result);
|
|
2382
|
+
const findings = scan.findings || [];
|
|
2383
|
+
const specs = findings.find(f => f.type === 'openapi_specs');
|
|
2384
|
+
if (specs) {
|
|
2385
|
+
console.log(` ${chalk.green('✓')} Found ${specs.count} OpenAPI spec(s): ${specs.files.slice(0, 3).join(', ')}`);
|
|
2386
|
+
} else {
|
|
2387
|
+
console.log(` ${chalk.yellow('—')} No OpenAPI specs found`);
|
|
2388
|
+
}
|
|
2389
|
+
const frameworks = findings.filter(f => f.type === 'framework');
|
|
2390
|
+
frameworks.forEach(f => console.log(` ${chalk.green('✓')} Framework: ${f.name}`));
|
|
2391
|
+
const suggestions = scan.suggestions || [];
|
|
2392
|
+
if (suggestions.length > 0) {
|
|
2393
|
+
console.log(chalk.bold('\n Suggestions:\n'));
|
|
2394
|
+
suggestions.slice(0, 3).forEach(s => {
|
|
2395
|
+
console.log(` ${chalk.blue('→')} ${s.detail}`);
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
// If spec found, run health on it
|
|
2399
|
+
if (specs && specs.files.length > 0) {
|
|
2400
|
+
const specFile = path.join(target, specs.files[0]);
|
|
2401
|
+
console.log(chalk.gray(`\n Running spec health on ${specs.files[0]}...`));
|
|
2402
|
+
try {
|
|
2403
|
+
const healthResult = execSync(
|
|
2404
|
+
`python3 -c "import sys,json; sys.path.insert(0,'${continuityContext.serverDir}'); from core.spec_health import score_spec; import yaml; spec=yaml.safe_load(open('${specFile}')); r=score_spec(spec); print(json.dumps(r))"`,
|
|
2405
|
+
{ encoding: 'utf-8', timeout: 15000, cwd: continuityContext.serverDir }
|
|
2406
|
+
);
|
|
2407
|
+
const health = JSON.parse(healthResult);
|
|
2408
|
+
const gradeColors = { A: 'green', B: 'blue', C: 'yellow', D: 'red', F: 'red' };
|
|
2409
|
+
const gradeColor = gradeColors[health.grade] || 'white';
|
|
2410
|
+
console.log(`\n ${chalk[gradeColor].bold(health.grade)} ${chalk.white.bold(health.overall_score + '/100')} ${chalk.gray('Spec Health Score')}`);
|
|
2411
|
+
} catch {}
|
|
2412
|
+
}
|
|
2413
|
+
console.log(chalk.bold('\n Next:\n'));
|
|
2414
|
+
console.log(` ${chalk.green('npx delimit-cli init')} ${chalk.gray('— set up governance')}`);
|
|
2415
|
+
console.log(` ${chalk.green('npx delimit-cli setup')} ${chalk.gray('— configure AI assistants')}\n`);
|
|
2416
|
+
} catch (e) {
|
|
2417
|
+
console.log(chalk.red(` Error: ${e.message}`));
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
});
|
|
2421
|
+
|
|
2331
2422
|
// Try command — zero-risk demo with Markdown report artifact (LED-264)
|
|
2332
2423
|
program
|
|
2333
2424
|
.command('try')
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "delimit-cli",
|
|
3
3
|
"mcpName": "io.github.delimit-ai/delimit-mcp-server",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.2",
|
|
5
5
|
"description": "Unify Claude Code, Codex, Cursor, and Gemini CLI with persistent context, governance, and multi-model debate.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"files": [
|