@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 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
- const output = JSON.stringify(rules, null, 2);
1041
- if (options.out) {
1042
- require('fs').writeFileSync(options.out, output, 'utf8');
1043
- if (!options.json) {
1044
- console.log(`\n Rules exported to ${options.out} (${rules.totalRules} rules)\n`);
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
- console.log(output);
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.4",
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
- console.log(' Domain Packs');
437
- if ((summary.domainPacks || []).length === 0) {
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
- for (const pack of summary.domainPacks || []) {
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(' MCP Packs');
446
- if ((summary.mcpPacks || []).length === 0) {
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
- for (const pack of summary.mcpPacks || []) {
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):