@nerviq/cli 1.9.0 → 1.10.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/README.md CHANGED
@@ -64,18 +64,26 @@ Nerviq scores your AI coding agent setup from 0 to 100, finds what's missing, an
64
64
  Next: nerviq setup
65
65
  ```
66
66
 
67
- ## Quick Start
68
-
69
- ```bash
70
- npx @nerviq/cli audit # Quick scan: score + top 3 actions
71
- npx @nerviq/cli audit --full # Full audit with all checks + badge
72
- npx @nerviq/cli setup # Generate starter-safe baseline
73
- npx @nerviq/cli augment # Improvement plan, no writes
74
- npx @nerviq/cli governance # Permission profiles + policy packs
75
- npx @nerviq/cli benchmark # Before/after in isolated copy
76
- ```
77
-
78
- No install required. Zero dependencies.
67
+ ## Quick Start
68
+
69
+ ```bash
70
+ npx @nerviq/cli --beginner # Show only the 5 starter commands
71
+ npx @nerviq/cli audit # Quick scan: score + top 3 actions
72
+ npx @nerviq/cli audit --full # Full audit with all checks + badge
73
+ npx @nerviq/cli audit --workspace packages/* # Monorepo: root governance + workspace average/package scores
74
+ npx @nerviq/cli setup # Generate starter-safe baseline
75
+ npx @nerviq/cli augment # Improvement plan, no writes
76
+ npx @nerviq/cli governance # Permission profiles + policy packs
77
+ npx @nerviq/cli benchmark # Baseline vs projected score in isolated copy
78
+ ```
79
+
80
+ No install required. Zero dependencies.
81
+
82
+ If you want the shortest possible command list inside the terminal, start with:
83
+
84
+ ```bash
85
+ npx @nerviq/cli --beginner
86
+ ```
79
87
 
80
88
  ## Get Started by Role
81
89
 
@@ -236,14 +244,14 @@ Levels:
236
244
  | `nerviq plan` | Export proposal bundles with previews |
237
245
  | `nerviq apply` | Apply proposals with rollback |
238
246
  | `nerviq governance` | Permission profiles, hooks, policy packs |
239
- | `nerviq benchmark` | Before/after in isolated temp copy |
247
+ | `nerviq benchmark` | Baseline vs projected score in isolated temp copy |
240
248
  | `nerviq check-health` | Detect regressions between audit snapshots |
241
249
  | `nerviq deep-review` | AI-powered config review (opt-in) |
242
250
  | `nerviq interactive` | Step-by-step guided wizard |
243
251
  | `nerviq watch` | Live monitoring with score delta |
244
- | `nerviq history` | Score history from snapshots |
245
- | `nerviq compare` | Compare latest vs previous |
246
- | `nerviq trend` | Export trend report |
252
+ | `nerviq history` | Audit snapshot history from saved snapshots |
253
+ | `nerviq compare` | Compare latest vs previous audit snapshot |
254
+ | `nerviq trend` | Export audit snapshot trend report |
247
255
  | `nerviq feedback` | Record recommendation outcomes |
248
256
  | `nerviq anti-patterns` | Detect anti-patterns in current project |
249
257
  | `nerviq freshness` | Show verification freshness for all checks |
@@ -281,7 +289,7 @@ Levels:
281
289
  | `--only A,B` | Limit apply to selected proposal IDs |
282
290
  | `--format sarif` | SARIF output for code scanning |
283
291
  | `--platform NAME` | Target platform (claude, codex, gemini, copilot, cursor, windsurf, aider, opencode) |
284
- | `--workspace GLOB` | Audit workspaces separately (e.g. packages/*) |
292
+ | `--workspace GLOB` | Audit workspaces separately as package-level live audits (e.g. packages/*) |
285
293
  | `--external PATH` | Benchmark an external repo |
286
294
 
287
295
  ## Backed by Research
@@ -333,9 +341,9 @@ If Nerviq helped you, consider giving it a ⭐ on [GitHub](https://github.com/ne
333
341
 
334
342
  **Not designed for:** Deeply customized setups with 20+ skills, agent teams, and bespoke MCP integrations. If you've already built advanced agent workflows, you may not need this.
335
343
 
336
- **Strongest at:** Agent configuration, workflow governance, repo policy hygiene, cross-platform alignment, and setup standardization.
337
-
338
- **Not a replacement for:** Deep architectural review of business logic, runtime performance profiling, or security penetration testing. Nerviq focuses on how your AI coding agents are configured and governed — not on what your application code does.
344
+ **Strongest at:** AI agent governance, configuration intelligence, workflow policy hygiene, cross-platform alignment, and setup standardization.
345
+
346
+ **Not a replacement for:** Deep architectural review of business logic, runtime performance profiling, full SAST coverage, secret scanning, or security penetration testing. Nerviq focuses on how your AI coding agents are configured and governed — not on what your application code does.
339
347
 
340
348
  **Confidence levels:** Every check includes a `confidence` score (0.0–1.0) and a `sourceUrl` linking to primary documentation. Checks marked `heuristic` are pattern-based and may produce false positives on non-standard project structures.
341
349
 
@@ -347,16 +355,3 @@ If Nerviq helped you, consider giving it a ⭐ on [GitHub](https://github.com/ne
347
355
  | `BETA` | Works but has limited real-world testing. API may change |
348
356
  | `EXPERIMENTAL` | Early stage, static rules, results may vary |
349
357
 
350
- ## Previously nerviq-cli
351
-
352
- Nerviq was previously published as `nerviq-cli`. If you were using it:
353
-
354
- ```bash
355
- # Old
356
- npx nerviq-cli
357
-
358
- # New
359
- npx @nerviq/cli audit
360
- ```
361
-
362
- All features are preserved and expanded.
package/bin/cli.js CHANGED
@@ -61,9 +61,9 @@ function suggestCommand(input) {
61
61
  return bestDistance <= 3 ? best : null;
62
62
  }
63
63
 
64
- function parseArgs(rawArgs) {
65
- const flags = [];
66
- let command = 'audit';
64
+ function parseArgs(rawArgs) {
65
+ const flags = [];
66
+ let command = 'audit';
67
67
  let threshold = null;
68
68
  let out = null;
69
69
  let planFile = null;
@@ -89,10 +89,11 @@ function parseArgs(rawArgs) {
89
89
  let migrateFrom = null;
90
90
  let migrateTo = null;
91
91
  let checkVersion = null;
92
- let external = null;
93
- let repos = [];
94
- let teamProfile = null;
95
- let lang = null;
92
+ let external = null;
93
+ let repos = [];
94
+ let teamProfile = null;
95
+ let lang = null;
96
+ let commandExplicit = false;
96
97
 
97
98
  for (let i = 0; i < rawArgs.length; i++) {
98
99
  const arg = rawArgs[i];
@@ -256,37 +257,47 @@ function parseArgs(rawArgs) {
256
257
  continue;
257
258
  }
258
259
 
259
- if (!commandSet) {
260
- command = arg;
261
- commandSet = true;
262
- } else {
263
- extraArgs.push(arg);
264
- }
265
- }
260
+ if (!commandSet) {
261
+ command = arg;
262
+ commandSet = true;
263
+ commandExplicit = true;
264
+ } else {
265
+ extraArgs.push(arg);
266
+ }
267
+ }
266
268
 
267
269
  const normalizedCommand = COMMAND_ALIASES[command] || command;
268
270
 
269
- return { flags, command, normalizedCommand, threshold, out, planFile, only, profile, mcpPacks, requireChecks, feedbackKey, feedbackStatus, feedbackEffect, feedbackNotes, feedbackSource, feedbackScoreDelta, platform, format, port, workspace, extraArgs, convertFrom, convertTo, migrateFrom, migrateTo, checkVersion, webhookUrl, external, repos, teamProfile, lang };
270
- }
271
-
272
- function printWorkspaceSummary(summary, options) {
273
- if (options.json) {
274
- console.log(JSON.stringify(summary, null, 2));
275
- return;
276
- }
277
-
278
- console.log('');
279
- console.log('\x1b[1m nerviq workspace audit\x1b[0m');
280
- console.log('\x1b[2m ═══════════════════════════════════════\x1b[0m');
281
- console.log(` Root: ${summary.rootDir}`);
282
- console.log(` Platform: ${summary.platform}`);
283
- console.log(` Workspaces: ${summary.workspaceCount}`);
284
- console.log(` Average score: \x1b[1m${summary.averageScore}/100\x1b[0m`);
285
- console.log('');
286
- console.log('\x1b[1m Workspace Score Pass Total Top action\x1b[0m');
287
- console.log(' ' + '─'.repeat(72));
288
- for (const item of summary.workspaces) {
289
- const score = item.score === null ? 'ERR' : String(item.score);
271
+ return { flags, command, commandExplicit, normalizedCommand, threshold, out, planFile, only, profile, mcpPacks, requireChecks, feedbackKey, feedbackStatus, feedbackEffect, feedbackNotes, feedbackSource, feedbackScoreDelta, platform, format, port, workspace, extraArgs, convertFrom, convertTo, migrateFrom, migrateTo, checkVersion, webhookUrl, external, repos, teamProfile, lang };
272
+ }
273
+
274
+ function printWorkspaceSummary(summary, options) {
275
+ if (options.json) {
276
+ console.log(JSON.stringify(summary, null, 2));
277
+ return;
278
+ }
279
+
280
+ const rootScore = summary.rootGovernance?.score === null ? 'ERR' : `${summary.rootGovernance?.score ?? 0}/100`;
281
+ const workspaceAverage = summary.workspaceAggregate?.score ?? summary.averageScore;
282
+
283
+ console.log('');
284
+ console.log('\x1b[1m nerviq workspace audit\x1b[0m');
285
+ console.log('\x1b[2m ═══════════════════════════════════════\x1b[0m');
286
+ console.log(` Root: ${summary.rootDir}`);
287
+ console.log(` Platform: ${summary.platform}`);
288
+ console.log(` Workspaces: ${summary.workspaceCount}`);
289
+ if (summary.patterns?.length > 0) {
290
+ console.log(` Selection: ${summary.patterns.join(', ')}`);
291
+ }
292
+ console.log(` Root governance audit: \x1b[1m${rootScore}\x1b[0m`);
293
+ console.log(` Workspace audit average: \x1b[1m${workspaceAverage}/100\x1b[0m`);
294
+ console.log(' Score semantics: root governance shows shared repo policy health; workspace average shows package-level coverage across the selected workspaces.');
295
+ console.log(' Aggregate vs package: per-workspace scores can legitimately trail the root repo score in a monorepo.');
296
+ console.log('');
297
+ console.log('\x1b[1m Workspace Audit Pass Total Top action\x1b[0m');
298
+ console.log(' ' + '─'.repeat(72));
299
+ for (const item of summary.workspaces) {
300
+ const score = item.score === null ? 'ERR' : String(item.score);
290
301
  const topAction = item.error || item.topAction || '-';
291
302
  console.log(` ${item.workspace.padEnd(26)} ${score.padStart(5)} ${String(item.passed).padStart(5)} ${String(item.total).padStart(6)} ${topAction}`);
292
303
  }
@@ -366,17 +377,18 @@ function printOrgSummary(summary, options) {
366
377
  console.log('');
367
378
  }
368
379
 
369
- const HELP = `
370
- nerviq v${version}
371
- The intelligent nervous system for AI coding agents.
372
- Audit, align, and amplify every platform on every project.
373
-
374
- DISCOVER
375
- nerviq audit Quick scan: score + top 3 gaps (default)
376
- nerviq audit --full Full audit with all checks, weakest areas, badge
377
- nerviq audit --platform X Audit specific platform (claude|codex|cursor|copilot|gemini|windsurf|aider|opencode)
378
- nerviq audit --json Machine-readable JSON output (for CI)
379
- nerviq audit --workspace packages/* Audit each workspace in a monorepo
380
+ const HELP = `
381
+ nerviq v${version}
382
+ The intelligent nervous system for AI coding agents.
383
+ Audit, align, and amplify every platform on every project.
384
+ New here? Run: nerviq --beginner
385
+
386
+ DISCOVER
387
+ nerviq audit Quick scan: score + top 3 gaps (default)
388
+ nerviq audit --full Full audit with all checks, weakest areas, badge
389
+ nerviq audit --platform X Audit specific platform (claude|codex|cursor|copilot|gemini|windsurf|aider|opencode)
390
+ nerviq audit --json Machine-readable JSON output (for CI)
391
+ nerviq audit --workspace packages/* Audit monorepo workspaces with root-vs-package score semantics
380
392
  nerviq scan dir1 dir2 Compare multiple repos side-by-side
381
393
  nerviq org scan dir1 dir2 Aggregate multiple repos into one score table
382
394
  nerviq catalog Full check catalog (all 8 platforms)
@@ -413,30 +425,30 @@ const HELP = `
413
425
  GOVERN
414
426
  nerviq governance Permission profiles + hooks + policy packs
415
427
  nerviq governance --json Machine-readable governance summary
416
- nerviq benchmark Before/after score in isolated temp copy
428
+ nerviq benchmark Baseline vs projected score in isolated temp copy
417
429
  nerviq benchmark --external /path Benchmark an external repo
418
430
  nerviq freshness Show verification freshness for all checks
419
431
  nerviq certify Generate certification badge for your project
420
432
 
421
433
  CROSS-PLATFORM
422
- nerviq harmony-audit Drift detection across all active platforms
423
- nerviq harmony-sync Preview cross-platform sync (dry run)
424
- nerviq harmony-sync --fix Apply cross-platform sync (write files)
425
- nerviq harmony-sync --json JSON output for CI/automation
426
- nerviq harmony-add <platform> Add a new platform to the project
427
- nerviq synergy-report Multi-agent amplification opportunities
434
+ nerviq harmony-audit Drift detection across all active platforms (GA)
435
+ nerviq harmony-sync Preview cross-platform sync (dry run, GA)
436
+ nerviq harmony-sync --fix Apply cross-platform sync (write files, GA)
437
+ nerviq harmony-sync --json JSON output for CI/automation
438
+ nerviq harmony-add <platform> Add a new platform to the project
439
+ nerviq synergy-report [EXPERIMENTAL] Static-rule multi-agent amplification report
428
440
  nerviq convert --from X --to Y Convert configs between platforms
429
441
  nerviq migrate --platform X Platform version migration helper
430
442
  nerviq migrate --platform cursor --from v2 --to v3
431
443
 
432
444
  MONITOR
433
- nerviq dashboard Generate static HTML dashboard report
445
+ nerviq dashboard Generate static dashboard from latest audit snapshot (or live audit if none)
434
446
  nerviq dashboard --out F Save dashboard to custom file
435
447
  nerviq dashboard --open Open dashboard in browser after generating
436
448
  nerviq watch Live config monitoring (re-audits on file change)
437
- nerviq history Score history from saved snapshots
438
- nerviq compare Latest vs previous snapshot diff
439
- nerviq trend Score trend over time
449
+ nerviq history Audit snapshot history from saved snapshots
450
+ nerviq compare Latest vs previous audit snapshot diff
451
+ nerviq trend Audit snapshot trend over time
440
452
  nerviq trend --out report.md Export trend report as markdown
441
453
  nerviq feedback Record recommendation outcomes
442
454
 
@@ -469,26 +481,28 @@ const HELP = `
469
481
  --webhook URL Send audit results to a webhook (Slack/Discord/generic JSON)
470
482
  --external PATH Benchmark an external repo instead of cwd
471
483
  --port N Port for \`serve\` (default: 3000)
472
- --workspace GLOBS Audit workspaces separately (e.g. packages/* or apps/web,apps/api)
484
+ --workspace GLOBS Audit workspaces separately and label root governance vs package scores
473
485
  --snapshot Save snapshot artifact under .claude/nerviq/snapshots/
474
486
  --full Show full audit output (all checks, weakest areas, badge)
475
487
  --lite Short top-3 scan (default behavior since v1.5.2)
476
488
  --dry-run Preview changes without writing files
477
489
  --config-only Only write config files (.claude/, rules, hooks) — never source code
478
490
  --verbose Full audit + medium-priority recommendations
479
- --show-deprecated Show deprecated checks (excluded from scoring)
480
- --json Output as JSON
481
- --auto Apply all generated files without prompting
482
- --key NAME Feedback: recommendation key (e.g. permissionDeny)
491
+ --show-deprecated Show deprecated checks (excluded from scoring)
492
+ --json Output as JSON
493
+ --auto Apply all generated files without prompting
494
+ --beginner Show only the 5 starter commands for first-time users
495
+ --key NAME Feedback: recommendation key (e.g. permissionDeny)
483
496
  --status VALUE Feedback: accepted | rejected | deferred
484
497
  --effect VALUE Feedback: positive | neutral | negative
485
498
  --score-delta N Feedback: observed score delta
486
499
  --help Show this help
487
500
  --version Show version
488
501
 
489
- EXAMPLES
490
- npx nerviq
491
- npx nerviq --lite
502
+ EXAMPLES
503
+ npx nerviq --beginner
504
+ npx nerviq
505
+ npx nerviq --lite
492
506
  npx nerviq --platform cursor
493
507
  npx nerviq audit --workspace packages/*
494
508
  npx nerviq --platform codex augment
@@ -505,9 +519,34 @@ const HELP = `
505
519
  npx nerviq feedback --key permissionDeny --status accepted --effect positive
506
520
 
507
521
  EXIT CODES
508
- 0 Success
509
- 1 Error, unknown command, or score below --threshold
510
- `;
522
+ 0 Success
523
+ 1 Error, unknown command, or score below --threshold
524
+ `;
525
+
526
+ const BEGINNER_HELP = `
527
+ nerviq v${version}
528
+ Start here.
529
+
530
+ If this is your first time, learn just these 5 commands:
531
+
532
+ STARTER COMMANDS
533
+ nerviq audit Score the repo and show the top gaps
534
+ nerviq setup Generate a starter-safe baseline
535
+ nerviq fix Fix what can be fixed or show manual fix guidance
536
+ nerviq augment Show an improvement plan without writing
537
+ nerviq doctor Check install health, freshness, and platform detection
538
+
539
+ SIMPLE PATH
540
+ 1. nerviq audit
541
+ 2. nerviq setup --auto
542
+ 3. nerviq fix --all-critical --auto
543
+ 4. nerviq augment
544
+ 5. nerviq doctor
545
+
546
+ WHEN YOU ARE READY
547
+ nerviq --help Show the full command set
548
+ Docs: https://nerviq.net/docs/getting-started
549
+ `;
511
550
 
512
551
  async function main() {
513
552
  let parsed;
@@ -518,22 +557,27 @@ async function main() {
518
557
  process.exit(1);
519
558
  }
520
559
 
521
- const { flags, command, normalizedCommand } = parsed;
560
+ const { flags, command, commandExplicit, normalizedCommand } = parsed;
522
561
 
523
562
  // Initialize i18n with --lang flag or NERVIQ_LANG env var
524
563
  if (parsed.lang) {
525
564
  initI18n(parsed.lang);
526
565
  }
527
566
 
528
- if (flags.includes('--help') || command === 'help') {
529
- console.log(HELP);
530
- process.exit(0);
531
- }
532
-
533
- if (flags.includes('--version') || command === 'version') {
534
- console.log(version);
535
- process.exit(0);
536
- }
567
+ if (flags.includes('--version') || command === 'version') {
568
+ console.log(version);
569
+ process.exit(0);
570
+ }
571
+
572
+ if (flags.includes('--beginner') && (!commandExplicit || flags.includes('--help') || command === 'help')) {
573
+ console.log(BEGINNER_HELP);
574
+ process.exit(0);
575
+ }
576
+
577
+ if (flags.includes('--help') || command === 'help') {
578
+ console.log(HELP);
579
+ process.exit(0);
580
+ }
537
581
 
538
582
  const options = {
539
583
  verbose: flags.includes('--verbose'),
@@ -746,9 +790,9 @@ async function main() {
746
790
  process.exit(1);
747
791
  }
748
792
  process.exit(0);
749
- } else if (normalizedCommand === 'history') {
750
- const { formatHistory, readSnapshotIndex } = require('../src/activity');
751
- // Handle --prune N
793
+ } else if (normalizedCommand === 'history') {
794
+ const { formatHistory, readSnapshotIndex } = require('../src/activity');
795
+ // Handle --prune N
752
796
  const pruneIdx = flags.indexOf('--prune');
753
797
  if (pruneIdx >= 0) {
754
798
  const keepCount = parseInt(flags[pruneIdx + 1] || parsed.extraArgs[0], 10) || 10;
@@ -756,7 +800,7 @@ async function main() {
756
800
  const pathMod = require('path');
757
801
  const entries = readSnapshotIndex(options.dir);
758
802
  if (entries.length <= keepCount) {
759
- console.log(`\n Nothing to prune (${entries.length} snapshots, keeping ${keepCount}).\n`);
803
+ console.log(`\n Nothing to prune (${entries.length} audit snapshots, keeping ${keepCount}).\n`);
760
804
  } else {
761
805
  const toRemove = entries.slice(0, entries.length - keepCount);
762
806
  let removed = 0;
@@ -767,42 +811,53 @@ async function main() {
767
811
  const kept = entries.slice(entries.length - keepCount);
768
812
  const indexPath = pathMod.join(options.dir, '.nerviq', 'snapshots', 'index.json');
769
813
  try { fsMod.writeFileSync(indexPath, JSON.stringify(kept, null, 2), 'utf8'); } catch {}
770
- console.log(`\n Pruned ${removed} snapshots, kept ${kept.length}.\n`);
814
+ console.log(`\n Pruned ${removed} audit snapshots, kept ${kept.length}.\n`);
771
815
  }
772
816
  process.exit(0);
773
817
  }
774
818
  console.log('');
775
- console.log(formatHistory(options.dir));
776
- console.log('');
777
- process.exit(0);
778
- } else if (normalizedCommand === 'compare') {
779
- const { compareLatest } = require('../src/activity');
780
- const result = compareLatest(options.dir);
781
- if (!result) {
782
- console.log('\n Need at least 2 snapshots to compare. Run `npx nerviq --snapshot` twice.\n');
783
- process.exit(0);
784
- }
819
+ console.log(formatHistory(options.dir));
820
+ console.log('');
821
+ process.exit(0);
822
+ } else if (normalizedCommand === 'compare') {
823
+ const { compareLatest, formatSnapshotBootstrap } = require('../src/activity');
824
+ const result = compareLatest(options.dir);
825
+ if (!result) {
826
+ console.log('');
827
+ console.log(formatSnapshotBootstrap(options.dir, 'compare'));
828
+ console.log('');
829
+ process.exit(0);
830
+ }
785
831
  if (options.json) {
786
832
  console.log(JSON.stringify(result, null, 2));
787
833
  } else {
788
834
  const sign = result.delta.score >= 0 ? '+' : '';
789
835
  console.log('');
790
- console.log(` Previous: ${result.previous.score}/100 (${result.previous.date?.split('T')[0]})`);
791
- console.log(` Current: ${result.current.score}/100 (${result.current.date?.split('T')[0]})`);
792
- console.log(` Delta: ${sign}${result.delta.score} points`);
793
- console.log(` Trend: ${result.trend}`);
836
+ console.log(` Previous snapshot: ${result.previous.score}/100 (${result.previous.date?.split('T')[0]})`);
837
+ console.log(` Current snapshot: ${result.current.score}/100 (${result.current.date?.split('T')[0]})`);
838
+ console.log(` Snapshot delta: ${sign}${result.delta.score} points`);
839
+ console.log(` Trend: ${result.trend}`);
794
840
  if (result.improvements.length > 0) console.log(` Fixed: ${result.improvements.join(', ')}`);
795
841
  if (result.regressions.length > 0) console.log(` New gaps: ${result.regressions.join(', ')}`);
796
842
  console.log('');
797
- }
798
- process.exit(0);
799
- } else if (normalizedCommand === 'trend') {
800
- const { exportTrendReport } = require('../src/activity');
801
- const report = exportTrendReport(options.dir);
802
- if (!report) {
803
- console.log('\n No snapshots found. Run `npx nerviq --snapshot` to start tracking.\n');
804
- process.exit(0);
805
- }
843
+ }
844
+ process.exit(0);
845
+ } else if (normalizedCommand === 'trend') {
846
+ const { exportTrendReport, getHistory, formatSnapshotBootstrap } = require('../src/activity');
847
+ const auditHistory = getHistory(options.dir, 2);
848
+ if (auditHistory.length < 2) {
849
+ console.log('');
850
+ console.log(formatSnapshotBootstrap(options.dir, 'trend'));
851
+ console.log('');
852
+ process.exit(0);
853
+ }
854
+ const report = exportTrendReport(options.dir);
855
+ if (!report) {
856
+ console.log('');
857
+ console.log(formatSnapshotBootstrap(options.dir, 'trend'));
858
+ console.log('');
859
+ process.exit(0);
860
+ }
806
861
  if (options.out) {
807
862
  require('fs').writeFileSync(options.out, report, 'utf8');
808
863
  console.log(`\n Trend report exported to ${options.out}\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nerviq/cli",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "description": "The intelligent nervous system for AI coding agents — 2,438 checks (8 platforms × ~300 governance rules), 10 languages, 62 domain packs. Audit, align, and amplify.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/activity.js CHANGED
@@ -268,8 +268,9 @@ function compareLatest(dir) {
268
268
  }
269
269
 
270
270
  return {
271
- current: { date: current.createdAt, score: current.summary?.score, passed: current.summary?.passed },
272
- previous: { date: previous.createdAt, score: previous.summary?.score, passed: previous.summary?.passed },
271
+ scoreType: 'audit-snapshot-score',
272
+ current: { date: current.createdAt, score: current.summary?.score, passed: current.summary?.passed, scoreType: 'audit-snapshot-score' },
273
+ previous: { date: previous.createdAt, score: previous.summary?.score, passed: previous.summary?.passed, scoreType: 'audit-snapshot-score' },
273
274
  delta,
274
275
  regressions,
275
276
  improvements,
@@ -277,11 +278,60 @@ function compareLatest(dir) {
277
278
  };
278
279
  }
279
280
 
281
+ function formatSnapshotBootstrap(dir, goal = 'history') {
282
+ const snapshotCount = getHistory(dir, 50).length;
283
+ const lines = [];
284
+ const snapshotLabel = snapshotCount === 1
285
+ ? '1 saved audit snapshot'
286
+ : `${snapshotCount} saved audit snapshots`;
287
+
288
+ if (goal === 'compare') {
289
+ lines.push(snapshotCount === 0
290
+ ? 'Compare needs 2 audit snapshots.'
291
+ : 'Compare needs one more audit snapshot.');
292
+ } else if (goal === 'trend') {
293
+ lines.push(snapshotCount === 0
294
+ ? 'Trend needs 2 audit snapshots to start.'
295
+ : 'Trend needs one more audit snapshot to become meaningful.');
296
+ } else {
297
+ lines.push(snapshotCount === 0
298
+ ? 'No audit snapshots found yet.'
299
+ : 'History is initialized, but compare/trend still need one more snapshot.');
300
+ }
301
+
302
+ lines.push(` Current state: ${snapshotLabel}.`);
303
+
304
+ if (snapshotCount === 0) {
305
+ lines.push(' Bootstrap it with:');
306
+ lines.push(' 1. Run `nerviq audit --snapshot` to save the baseline.');
307
+ lines.push(' 2. Make a meaningful repo change (`nerviq setup --auto` or `nerviq fix --all-critical --auto`).');
308
+ lines.push(' 3. Run `nerviq audit --snapshot` again to capture the next state.');
309
+ } else {
310
+ lines.push(' Next:');
311
+ lines.push(' 1. Make a meaningful repo change (`nerviq setup --auto` or `nerviq fix --all-critical --auto`).');
312
+ lines.push(' 2. Run `nerviq audit --snapshot` again.');
313
+ }
314
+
315
+ if (goal === 'compare') {
316
+ lines.push(' Then rerun `nerviq compare`.');
317
+ } else if (goal === 'trend') {
318
+ lines.push(' Then rerun `nerviq trend`.');
319
+ } else {
320
+ lines.push(' Then rerun `nerviq history`, `nerviq compare`, or `nerviq trend`.');
321
+ }
322
+
323
+ return lines.join('\n');
324
+ }
325
+
280
326
  function formatHistory(dir) {
281
327
  const history = getHistory(dir, 10);
282
- if (history.length === 0) return 'No snapshots found. Run `npx nerviq --snapshot` to save one.';
328
+ if (history.length === 0) return formatSnapshotBootstrap(dir, 'history');
283
329
 
284
- const lines = ['Score history (most recent first):', ''];
330
+ const lines = [
331
+ 'Audit snapshot history (most recent first):',
332
+ ' Score type: saved audit snapshot scores only (not live audits or benchmark projections).',
333
+ '',
334
+ ];
285
335
  for (const entry of history) {
286
336
  const dateStr = entry.createdAt || 'unknown';
287
337
  const date = dateStr.split('T')[0] || 'unknown';
@@ -290,14 +340,14 @@ function formatHistory(dir) {
290
340
  const score = entry.summary?.score ?? '?';
291
341
  const passed = entry.summary?.passed ?? '?';
292
342
  const total = entry.summary?.checkCount ?? '?';
293
- lines.push(` ${dateDisplay} ${score}/100 (${passed}/${total} passing)`);
343
+ lines.push(` ${dateDisplay} snapshot ${score}/100 (${passed}/${total} checks passing)`);
294
344
  }
295
345
 
296
346
  const comparison = compareLatest(dir);
297
347
  if (comparison) {
298
348
  lines.push('');
299
349
  const sign = comparison.delta.score >= 0 ? '+' : '';
300
- lines.push(` Trend: ${comparison.trend} (${sign}${comparison.delta.score} since previous)`);
350
+ lines.push(` Latest snapshot trend: ${comparison.trend} (${sign}${comparison.delta.score} since previous snapshot)`);
301
351
  if (comparison.improvements.length > 0) {
302
352
  lines.push(` Fixed: ${comparison.improvements.join(', ')}`);
303
353
  }
@@ -306,6 +356,11 @@ function formatHistory(dir) {
306
356
  }
307
357
  }
308
358
 
359
+ if (history.length === 1) {
360
+ lines.push('');
361
+ lines.push(formatSnapshotBootstrap(dir, 'history'));
362
+ }
363
+
309
364
  return lines.join('\n');
310
365
  }
311
366
 
@@ -315,13 +370,13 @@ function exportTrendReport(dir) {
315
370
 
316
371
  const comparison = compareLatest(dir);
317
372
  const lines = [
318
- '# Claude Code Setup Trend Report',
373
+ '# Nerviq Audit Snapshot Trend Report',
319
374
  '',
320
375
  `**Project:** ${path.basename(dir)}`,
321
376
  `**Generated:** ${new Date().toISOString().split('T')[0]}`,
322
- `**Snapshots:** ${history.length}`,
377
+ `**Audit snapshots:** ${history.length}`,
323
378
  '',
324
- '## Score History',
379
+ '## Audit Snapshot History',
325
380
  '',
326
381
  '| Date | Score | Passed | Checks |',
327
382
  '|------|-------|--------|--------|',
@@ -336,9 +391,9 @@ function exportTrendReport(dir) {
336
391
  lines.push('');
337
392
  lines.push('## Latest Comparison');
338
393
  lines.push('');
339
- lines.push(`- **Previous:** ${comparison.previous.score}/100 (${comparison.previous.date?.split('T')[0]})`);
340
- lines.push(`- **Current:** ${comparison.current.score}/100 (${comparison.current.date?.split('T')[0]})`);
341
- lines.push(`- **Delta:** ${comparison.delta.score >= 0 ? '+' : ''}${comparison.delta.score} points`);
394
+ lines.push(`- **Previous snapshot score:** ${comparison.previous.score}/100 (${comparison.previous.date?.split('T')[0]})`);
395
+ lines.push(`- **Current snapshot score:** ${comparison.current.score}/100 (${comparison.current.date?.split('T')[0]})`);
396
+ lines.push(`- **Snapshot delta:** ${comparison.delta.score >= 0 ? '+' : ''}${comparison.delta.score} points`);
342
397
  lines.push(`- **Trend:** ${comparison.trend}`);
343
398
  if (comparison.improvements.length > 0) lines.push(`- **Fixed:** ${comparison.improvements.join(', ')}`);
344
399
  if (comparison.regressions.length > 0) lines.push(`- **New gaps:** ${comparison.regressions.join(', ')}`);
@@ -803,6 +858,7 @@ module.exports = {
803
858
  readSnapshotIndex,
804
859
  getHistory,
805
860
  compareLatest,
861
+ formatSnapshotBootstrap,
806
862
  formatHistory,
807
863
  exportTrendReport,
808
864
  readOutcomeIndex,