@nerviq/cli 1.6.4 → 1.6.5
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/cli.js +41 -10
- package/package.json +1 -1
- package/src/governance.js +19 -6
- package/src/setup.js +1 -1
package/bin/cli.js
CHANGED
|
@@ -609,7 +609,30 @@ async function main() {
|
|
|
609
609
|
}
|
|
610
610
|
process.exit(0);
|
|
611
611
|
} else if (normalizedCommand === 'history') {
|
|
612
|
-
const { formatHistory } = require('../src/activity');
|
|
612
|
+
const { formatHistory, readSnapshotIndex } = require('../src/activity');
|
|
613
|
+
// Handle --prune N
|
|
614
|
+
const pruneIdx = flags.indexOf('--prune');
|
|
615
|
+
if (pruneIdx >= 0) {
|
|
616
|
+
const keepCount = parseInt(flags[pruneIdx + 1] || parsed.extraArgs[0], 10) || 10;
|
|
617
|
+
const fsMod = require('fs');
|
|
618
|
+
const pathMod = require('path');
|
|
619
|
+
const entries = readSnapshotIndex(options.dir);
|
|
620
|
+
if (entries.length <= keepCount) {
|
|
621
|
+
console.log(`\n Nothing to prune (${entries.length} snapshots, keeping ${keepCount}).\n`);
|
|
622
|
+
} else {
|
|
623
|
+
const toRemove = entries.slice(0, entries.length - keepCount);
|
|
624
|
+
let removed = 0;
|
|
625
|
+
for (const entry of toRemove) {
|
|
626
|
+
const fp = pathMod.join(options.dir, entry.relativePath);
|
|
627
|
+
try { fsMod.unlinkSync(fp); removed++; } catch {}
|
|
628
|
+
}
|
|
629
|
+
const kept = entries.slice(entries.length - keepCount);
|
|
630
|
+
const indexPath = pathMod.join(options.dir, '.nerviq', 'snapshots', 'index.json');
|
|
631
|
+
try { fsMod.writeFileSync(indexPath, JSON.stringify(kept, null, 2), 'utf8'); } catch {}
|
|
632
|
+
console.log(`\n Pruned ${removed} snapshots, kept ${kept.length}.\n`);
|
|
633
|
+
}
|
|
634
|
+
process.exit(0);
|
|
635
|
+
}
|
|
613
636
|
console.log('');
|
|
614
637
|
console.log(formatHistory(options.dir));
|
|
615
638
|
console.log('');
|
|
@@ -1037,16 +1060,24 @@ async function main() {
|
|
|
1037
1060
|
} else if (normalizedCommand === 'rules-export') {
|
|
1038
1061
|
const { generateRecommendationRules } = require('../src/recommendation-rules');
|
|
1039
1062
|
const rules = generateRecommendationRules();
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
} else {
|
|
1046
|
-
console.log(output);
|
|
1047
|
-
}
|
|
1063
|
+
if (options.json) {
|
|
1064
|
+
console.log(JSON.stringify(rules, null, 2));
|
|
1065
|
+
} else if (options.out) {
|
|
1066
|
+
require('fs').writeFileSync(options.out, JSON.stringify(rules, null, 2), 'utf8');
|
|
1067
|
+
console.log(`\n Rules exported to ${options.out} (${rules.totalRules} rules)\n`);
|
|
1048
1068
|
} else {
|
|
1049
|
-
|
|
1069
|
+
// Human-readable summary
|
|
1070
|
+
console.log(`\n Nerviq Recommendation Rules (${rules.totalRules} rules)\n`);
|
|
1071
|
+
const byCategory = {};
|
|
1072
|
+
for (const rule of (rules.rules || [])) {
|
|
1073
|
+
const cat = rule.category || 'other';
|
|
1074
|
+
if (!byCategory[cat]) byCategory[cat] = 0;
|
|
1075
|
+
byCategory[cat]++;
|
|
1076
|
+
}
|
|
1077
|
+
for (const [cat, count] of Object.entries(byCategory).sort((a, b) => b[1] - a[1])) {
|
|
1078
|
+
console.log(` ${cat.padEnd(20)} ${count} rules`);
|
|
1079
|
+
}
|
|
1080
|
+
console.log(`\n Use --json for full output or --out <file> to save.\n`);
|
|
1050
1081
|
}
|
|
1051
1082
|
process.exit(0);
|
|
1052
1083
|
} else if (normalizedCommand === 'check-health') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nerviq/cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"description": "The intelligent nervous system for AI coding agents — 2,431 checks across 8 platforms, 10 languages, and 62 domain packs. Audit, align, and amplify.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/governance.js
CHANGED
|
@@ -433,22 +433,35 @@ function printGovernanceSummary(summary, options = {}) {
|
|
|
433
433
|
}
|
|
434
434
|
console.log('');
|
|
435
435
|
|
|
436
|
-
|
|
437
|
-
|
|
436
|
+
const domainPacks = summary.domainPacks || [];
|
|
437
|
+
const mcpPacks = summary.mcpPacks || [];
|
|
438
|
+
const compact = !options.verbose;
|
|
439
|
+
const COMPACT_LIMIT = 5;
|
|
440
|
+
|
|
441
|
+
console.log(` Domain Packs (${domainPacks.length})`);
|
|
442
|
+
if (domainPacks.length === 0) {
|
|
438
443
|
console.log(' - none shipped yet for this platform');
|
|
439
444
|
}
|
|
440
|
-
|
|
445
|
+
const domainShow = compact ? domainPacks.slice(0, COMPACT_LIMIT) : domainPacks;
|
|
446
|
+
for (const pack of domainShow) {
|
|
441
447
|
console.log(` - ${pack.label}: ${pack.useWhen}`);
|
|
442
448
|
}
|
|
449
|
+
if (compact && domainPacks.length > COMPACT_LIMIT) {
|
|
450
|
+
console.log(` ... and ${domainPacks.length - COMPACT_LIMIT} more (use --verbose to see all)`);
|
|
451
|
+
}
|
|
443
452
|
console.log('');
|
|
444
453
|
|
|
445
|
-
console.log(
|
|
446
|
-
if (
|
|
454
|
+
console.log(` MCP Packs (${mcpPacks.length})`);
|
|
455
|
+
if (mcpPacks.length === 0) {
|
|
447
456
|
console.log(' - none shipped yet for this platform');
|
|
448
457
|
}
|
|
449
|
-
|
|
458
|
+
const mcpShow = compact ? mcpPacks.slice(0, COMPACT_LIMIT) : mcpPacks;
|
|
459
|
+
for (const pack of mcpShow) {
|
|
450
460
|
console.log(` - ${pack.label}: ${Object.keys(pack.servers).join(', ')}`);
|
|
451
461
|
}
|
|
462
|
+
if (compact && mcpPacks.length > COMPACT_LIMIT) {
|
|
463
|
+
console.log(` ... and ${mcpPacks.length - COMPACT_LIMIT} more (use --verbose to see all)`);
|
|
464
|
+
}
|
|
452
465
|
console.log('');
|
|
453
466
|
|
|
454
467
|
if (Array.isArray(summary.platformCaveats) && summary.platformCaveats.length > 0) {
|
package/src/setup.js
CHANGED
|
@@ -1022,7 +1022,7 @@ Prepare a release candidate for: $ARGUMENTS
|
|
|
1022
1022
|
const hasTS = stacks.some(s => s.key === 'typescript');
|
|
1023
1023
|
const hasPython = stacks.some(s => s.key === 'python');
|
|
1024
1024
|
const hasFrontend = stacks.some(s => ['react', 'vue', 'angular', 'svelte', 'nextjs'].includes(s.key));
|
|
1025
|
-
const hasBackend = stacks.some(s => ['go', 'python', 'django', 'fastapi', 'rust', 'java'].includes(s.key));
|
|
1025
|
+
const hasBackend = stacks.some(s => ['go', 'python', 'django', 'fastapi', 'rust', 'java', 'node', 'nestjs'].includes(s.key));
|
|
1026
1026
|
|
|
1027
1027
|
if (hasFrontend || (hasTS && !hasBackend)) {
|
|
1028
1028
|
rules['frontend.md'] = `When editing JavaScript/TypeScript files (*.ts, *.tsx, *.js, *.jsx, *.vue):
|