@nerviq/cli 1.29.0 → 1.30.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.
Files changed (93) hide show
  1. package/CHANGELOG.md +1764 -1493
  2. package/README.md +568 -538
  3. package/SECURITY.md +78 -82
  4. package/bin/cli.js +2838 -2558
  5. package/docs/api-reference.md +356 -356
  6. package/docs/audit-fix.md +109 -0
  7. package/docs/autofix.md +3 -62
  8. package/docs/getting-started.md +1 -1
  9. package/docs/index.html +592 -592
  10. package/docs/integration-contracts.md +287 -287
  11. package/docs/maintenance.md +128 -128
  12. package/docs/new-platform-guide.md +202 -202
  13. package/docs/release-process.md +63 -0
  14. package/docs/shallow-risk.md +244 -244
  15. package/docs/why-nerviq.md +82 -82
  16. package/package.json +75 -67
  17. package/sdk/README.md +12 -3
  18. package/sdk/examples/langchain-integration.md +128 -0
  19. package/sdk/examples/self-governing-agent.js +135 -0
  20. package/sdk/index.d.ts +115 -0
  21. package/sdk/index.js +94 -0
  22. package/sdk/package.json +11 -0
  23. package/src/activity.js +13 -0
  24. package/src/aider/activity.js +226 -226
  25. package/src/aider/context.js +162 -162
  26. package/src/aider/freshness.js +123 -123
  27. package/src/aider/techniques.js +3465 -3465
  28. package/src/audit/layers.js +180 -180
  29. package/src/audit.js +1133 -1032
  30. package/src/auto-suggest.js +9 -2
  31. package/src/behavioral-drift.js +37 -2
  32. package/src/benchmark.js +299 -299
  33. package/src/codex/activity.js +324 -324
  34. package/src/codex/freshness.js +149 -142
  35. package/src/codex/techniques.js +4895 -4895
  36. package/src/context.js +326 -326
  37. package/src/continuous-ops.js +11 -1
  38. package/src/convert.js +340 -340
  39. package/src/copilot/config-parser.js +280 -280
  40. package/src/copilot/context.js +218 -218
  41. package/src/copilot/freshness.js +184 -177
  42. package/src/copilot/patch.js +238 -238
  43. package/src/copilot/techniques.js +3578 -3578
  44. package/src/cursor/freshness.js +194 -194
  45. package/src/cursor/patch.js +243 -243
  46. package/src/cursor/techniques.js +3735 -3735
  47. package/src/doctor.js +201 -201
  48. package/src/fix-engine.js +511 -8
  49. package/src/formatters/csv.js +86 -86
  50. package/src/formatters/junit.js +123 -123
  51. package/src/formatters/markdown.js +164 -164
  52. package/src/formatters/otel.js +151 -151
  53. package/src/freshness.js +163 -156
  54. package/src/gemini/activity.js +402 -402
  55. package/src/gemini/context.js +290 -290
  56. package/src/gemini/freshness.js +188 -188
  57. package/src/gemini/patch.js +229 -229
  58. package/src/gemini/techniques.js +3811 -3811
  59. package/src/governance.js +533 -533
  60. package/src/harmony/audit.js +306 -306
  61. package/src/i18n.js +63 -63
  62. package/src/insights.js +119 -119
  63. package/src/integrations.js +134 -134
  64. package/src/locales/en.json +33 -33
  65. package/src/locales/es.json +33 -33
  66. package/src/migrate.js +354 -354
  67. package/src/opencode/activity.js +286 -286
  68. package/src/opencode/freshness.js +137 -137
  69. package/src/opencode/techniques.js +3450 -3450
  70. package/src/safe-glyph.js +97 -0
  71. package/src/setup/analysis.js +12 -12
  72. package/src/setup.js +13 -6
  73. package/src/shallow-risk/index.js +113 -56
  74. package/src/shallow-risk/patterns/agent-config-cross-platform-drift.js +51 -50
  75. package/src/shallow-risk/patterns/agent-config-dangerous-autoapprove.js +47 -46
  76. package/src/shallow-risk/patterns/agent-config-deprecated-keys.js +47 -46
  77. package/src/shallow-risk/patterns/agent-config-framework-version-mismatch.js +138 -0
  78. package/src/shallow-risk/patterns/agent-config-missing-file.js +318 -317
  79. package/src/shallow-risk/patterns/agent-config-script-not-in-package-json.js +108 -0
  80. package/src/shallow-risk/patterns/agent-config-secret-literal.js +52 -49
  81. package/src/shallow-risk/patterns/agent-config-stack-contradiction.js +35 -34
  82. package/src/shallow-risk/patterns/hook-script-missing.js +71 -70
  83. package/src/shallow-risk/patterns/mcp-server-no-allowlist.js +53 -52
  84. package/src/shallow-risk/shared.js +653 -648
  85. package/src/source-urls.js +295 -295
  86. package/src/state-paths.js +85 -85
  87. package/src/supplemental-checks.js +805 -805
  88. package/src/telemetry.js +160 -160
  89. package/src/watch.js +46 -0
  90. package/src/windsurf/context.js +359 -359
  91. package/src/windsurf/freshness.js +194 -194
  92. package/src/windsurf/patch.js +231 -231
  93. package/src/windsurf/techniques.js +3779 -3779
@@ -56,13 +56,20 @@ function analyzeSuggestions(dir) {
56
56
  let bootstrap = { ready: true, state: 'ready', message: null, steps: [] };
57
57
 
58
58
  if (totalEvents === 0 && auditSnapshots.length === 0) {
59
+ // BUG-07 fix: when feedback was just recorded but pattern events are 0,
60
+ // the user already ran `nerviq feedback` and got "No local usage..."
61
+ // back. After the activity.js fix, feedback now bumps usage-patterns,
62
+ // so this state means feedback never ran AT ALL. Be explicit about
63
+ // what's missing so the user doesn't think the loop is broken.
59
64
  bootstrap = {
60
65
  ready: false,
61
66
  state: 'empty',
62
- message: 'No local usage or snapshot history exists yet.',
67
+ message: 'No local usage or snapshot history exists yet. Need at least 2 snapshots and/or 2 recorded outcomes per check before suggestions surface.',
68
+ missingSignals: ['snapshots', 'recorded-outcomes'],
69
+ threshold: { minEventsPerCheck: MIN_EVENTS, minSnapshotsForPriority: 2 },
63
70
  steps: [
64
71
  'Run `nerviq audit --snapshot` to save the baseline.',
65
- 'Use `nerviq fix`, `nerviq fix --all-critical`, or `nerviq feedback` to record recommendation outcomes.',
72
+ 'Use `nerviq fix`, `nerviq fix --all-critical`, or `nerviq feedback --key <K> --status accepted` to record recommendation outcomes.',
66
73
  'Run `nerviq audit --snapshot` again after a meaningful repo change.',
67
74
  'Re-run `nerviq suggest-rules`.',
68
75
  ],
@@ -685,12 +685,29 @@ function analyzeBehavioralDrift(dir, options = {}) {
685
685
  const structuralSignals = buildStructuralSignals(dir, options);
686
686
  const intentSignals = collectIntentSignals(dir);
687
687
  const { findings, labels } = deriveBehavioralFindings(structuralSignals, intentSignals);
688
- const score = buildBehavioralScore(structuralSignals, findings);
688
+
689
+ // BUG-05 fix: a perfect 100 alignment score on a repo with no source files
690
+ // is misleading — the buildBehavioralScore math starts at 100 and subtracts
691
+ // penalties; with zero structural signal there's nothing to subtract, so
692
+ // empty repos look "perfectly aligned." Surface insufficient-signal status
693
+ // explicitly instead of returning the bogus 100. Threshold: <5 source files
694
+ // is treated as insufficient signal (calibrated from the user-lab fixture
695
+ // where 0 source files returned 100).
696
+ const SUFFICIENT_SIGNAL_FLOOR = 5;
697
+ const insufficientSignal = structuralSignals.sourceFiles < SUFFICIENT_SIGNAL_FLOOR;
698
+
699
+ const score = insufficientSignal
700
+ ? null
701
+ : buildBehavioralScore(structuralSignals, findings);
689
702
 
690
703
  return {
691
704
  mode: 'behavioral-drift',
692
705
  scoreType: 'behavioral-alignment-score',
693
706
  score,
707
+ status: insufficientSignal ? 'insufficient-signal' : 'ok',
708
+ insufficientSignalReason: insufficientSignal
709
+ ? `Need ≥${SUFFICIENT_SIGNAL_FLOOR} source files to compute a meaningful alignment score; found ${structuralSignals.sourceFiles}.`
710
+ : null,
694
711
  scope: SCOPE_CONTRACT,
695
712
  repoSummary: {
696
713
  project: path.basename(dir),
@@ -703,7 +720,13 @@ function analyzeBehavioralDrift(dir, options = {}) {
703
720
  intentSignals,
704
721
  driftLabels: labels,
705
722
  findings,
706
- nextSteps: buildBehavioralNextSteps(findings),
723
+ nextSteps: insufficientSignal
724
+ ? [{
725
+ key: 'add-source-code',
726
+ title: `Add at least ${SUFFICIENT_SIGNAL_FLOOR} source files before re-running behavioral review.`,
727
+ severity: 'low',
728
+ }]
729
+ : buildBehavioralNextSteps(findings),
707
730
  };
708
731
  }
709
732
 
@@ -713,6 +736,18 @@ function writeBehavioralSnapshot(dir, report, meta = {}) {
713
736
 
714
737
  function formatBehavioralReport(report, options = {}) {
715
738
  const lines = [];
739
+ // BUG-05 fix: handle insufficient-signal status — the score is null and a
740
+ // human-friendly explanation replaces the colored gauge.
741
+ if (report.status === 'insufficient-signal') {
742
+ lines.push('');
743
+ lines.push(c(' nerviq behavioral drift review', 'bold'));
744
+ lines.push(c(' ═══════════════════════════════════════', 'dim'));
745
+ lines.push(c(' Alignment score: insufficient signal', 'yellow'));
746
+ lines.push(c(` ${report.insufficientSignalReason || 'Not enough source files to compute a meaningful score.'}`, 'dim'));
747
+ lines.push(c(' No score returned to avoid a misleading 100 on empty repos.', 'dim'));
748
+ lines.push('');
749
+ return lines.join('\n');
750
+ }
716
751
  const scoreColor = report.score >= 75 ? 'green' : report.score >= 55 ? 'yellow' : 'red';
717
752
 
718
753
  lines.push('');