@nerviq/cli 1.27.1 → 1.29.1

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 (80) hide show
  1. package/CHANGELOG.md +1527 -1407
  2. package/README.md +550 -538
  3. package/SECURITY.md +82 -82
  4. package/bin/cli.js +2562 -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 +67 -67
  17. package/src/aider/activity.js +226 -226
  18. package/src/aider/context.js +162 -162
  19. package/src/aider/freshness.js +123 -123
  20. package/src/aider/techniques.js +3465 -3465
  21. package/src/audit/layers.js +180 -180
  22. package/src/audit.js +1032 -1032
  23. package/src/benchmark.js +299 -299
  24. package/src/codex/activity.js +324 -324
  25. package/src/codex/freshness.js +142 -142
  26. package/src/codex/techniques.js +4895 -4895
  27. package/src/context.js +326 -326
  28. package/src/continuous-ops.js +11 -1
  29. package/src/convert.js +340 -340
  30. package/src/copilot/config-parser.js +280 -280
  31. package/src/copilot/context.js +218 -218
  32. package/src/copilot/freshness.js +177 -177
  33. package/src/copilot/patch.js +238 -238
  34. package/src/copilot/techniques.js +3578 -3578
  35. package/src/cursor/freshness.js +194 -194
  36. package/src/cursor/patch.js +243 -243
  37. package/src/cursor/techniques.js +3735 -3735
  38. package/src/doctor.js +201 -201
  39. package/src/fix-engine.js +511 -8
  40. package/src/formatters/csv.js +86 -86
  41. package/src/formatters/junit.js +123 -123
  42. package/src/formatters/markdown.js +164 -164
  43. package/src/formatters/otel.js +151 -151
  44. package/src/freshness.js +156 -156
  45. package/src/gemini/activity.js +402 -402
  46. package/src/gemini/context.js +290 -290
  47. package/src/gemini/freshness.js +183 -183
  48. package/src/gemini/patch.js +229 -229
  49. package/src/gemini/techniques.js +3811 -3811
  50. package/src/governance.js +533 -533
  51. package/src/harmony/audit.js +306 -306
  52. package/src/i18n.js +63 -63
  53. package/src/insights.js +119 -119
  54. package/src/integrations.js +134 -134
  55. package/src/locales/en.json +33 -33
  56. package/src/locales/es.json +33 -33
  57. package/src/migrate.js +354 -354
  58. package/src/opencode/activity.js +286 -286
  59. package/src/opencode/freshness.js +137 -137
  60. package/src/opencode/techniques.js +3450 -3450
  61. package/src/setup/analysis.js +12 -12
  62. package/src/setup.js +7 -6
  63. package/src/shallow-risk/index.js +56 -56
  64. package/src/shallow-risk/patterns/agent-config-cross-platform-drift.js +50 -50
  65. package/src/shallow-risk/patterns/agent-config-dangerous-autoapprove.js +46 -46
  66. package/src/shallow-risk/patterns/agent-config-deprecated-keys.js +46 -46
  67. package/src/shallow-risk/patterns/agent-config-missing-file.js +317 -72
  68. package/src/shallow-risk/patterns/agent-config-secret-literal.js +49 -49
  69. package/src/shallow-risk/patterns/agent-config-stack-contradiction.js +34 -34
  70. package/src/shallow-risk/patterns/hook-script-missing.js +70 -70
  71. package/src/shallow-risk/patterns/mcp-server-no-allowlist.js +52 -52
  72. package/src/shallow-risk/shared.js +648 -520
  73. package/src/source-urls.js +295 -295
  74. package/src/state-paths.js +85 -85
  75. package/src/supplemental-checks.js +805 -805
  76. package/src/telemetry.js +160 -160
  77. package/src/windsurf/context.js +359 -359
  78. package/src/windsurf/freshness.js +194 -194
  79. package/src/windsurf/patch.js +231 -231
  80. package/src/windsurf/techniques.js +3779 -3779
@@ -1,180 +1,180 @@
1
- /**
2
- * CTO-08 — 5-layer scope clarity.
3
- *
4
- * Every check in the NERVIQ audit is tagged with exactly one layer so
5
- * customers and evaluators get an explicit map of what NERVIQ covers and
6
- * what it does not. The 4 positive layers below intentionally exclude any
7
- * "deep-review" / general-security-scanning lane: NERVIQ is an
8
- * agent-configuration audit tool, not a code-review tool.
9
- *
10
- * Taxonomy (canonical — mirrored in docs/integration-contracts.md §8):
11
- *
12
- * governance — Agent configuration posture: presence, content, and
13
- * quality of agent-instruction files and platform
14
- * settings. Answers "does my agent know X?".
15
- *
16
- * drift — Cross-platform consistency: do multiple platform
17
- * configs agree? Does the declared state match the
18
- * repo reality? Answers "do two places agree on X?".
19
- *
20
- * hygiene — Repo-level cleanliness and operational basics
21
- * adjacent to agents (gitignore, CHANGELOG, SECURITY.md,
22
- * CI, Dependabot, license, editorconfig, Node version
23
- * pinning, etc.). Answers "does the repo have standard
24
- * engineering hygiene that makes the agent's job
25
- * easier?".
26
- *
27
- * shallow-risk — Parallel, opt-in boundary checks that sit at the
28
- * agent-config <-> codebase edge. Findings are emitted
29
- * through `auditResult.shallowRiskHints[]` and are not
30
- * folded into governance scoring.
31
- *
32
- * Disambiguation rule-of-thumb when a check could plausibly belong to
33
- * more than one layer: prefer the most specific layer (drift > hygiene
34
- * > governance). If in doubt, default to hygiene — a mild
35
- * misclassification is recoverable; a missing tag breaks the coverage
36
- * test.
37
- */
38
-
39
- 'use strict';
40
-
41
- const LAYERS = Object.freeze({
42
- GOVERNANCE: 'governance',
43
- DRIFT: 'drift',
44
- HYGIENE: 'hygiene',
45
- SHALLOW_RISK: 'shallow-risk',
46
- });
47
-
48
- const LAYER_DEFINITIONS = Object.freeze({
49
- [LAYERS.GOVERNANCE]: 'Agent configuration posture: presence, content, and quality of agent-instruction files and platform settings.',
50
- [LAYERS.DRIFT]: 'Cross-platform consistency: do multiple platform configs agree, and does the declared state match repo reality?',
51
- [LAYERS.HYGIENE]: 'Repo-level cleanliness and operational basics adjacent to agents (gitignore, CHANGELOG, SECURITY.md, CI, license, etc.).',
52
- [LAYERS.SHALLOW_RISK]: 'Parallel, opt-in boundary checks emitted via auditResult.shallowRiskHints[]; shown separately and excluded from governance scoring.',
53
- });
54
-
55
- const VALID_LAYER_VALUES = new Set(Object.values(LAYERS));
56
-
57
- function isValidLayer(value) {
58
- return typeof value === 'string' && VALID_LAYER_VALUES.has(value);
59
- }
60
-
61
- /**
62
- * Name/id patterns that strongly indicate a drift check. Applied only as
63
- * a heuristic when tagging existing check bags (see assignLayers).
64
- */
65
- const DRIFT_PATTERNS = [
66
- /drift/i,
67
- /harmony/i,
68
- /\bpropagation\b/i,
69
- /consisten(t|cy)/i,
70
- /cross[- ]?platform/i,
71
- /across (surfaces|platforms|all .* surfaces)/i,
72
- /\bpacks are consistent\b/i,
73
- /propagation (checklist|completeness|delay)/i,
74
- ];
75
-
76
- /**
77
- * Hygiene name patterns — used to upgrade a check from a default
78
- * governance bag into hygiene when the check is clearly about repo
79
- * engineering hygiene rather than agent config.
80
- */
81
- const HYGIENE_PATTERNS = [
82
- /\.gitignore/i,
83
- /\bCHANGELOG\b/i,
84
- /\bCONTRIBUTING\b/i,
85
- /\bLICENSE\b/i,
86
- /\.editorconfig/i,
87
- /\bEditorConfig\b/i,
88
- /\bSECURITY\.md\b/i,
89
- /\bCODE_OF_CONDUCT\b/i,
90
- /\bDependabot\b/i,
91
- /\bNode version pinned\b/i,
92
- /\bREADME\b.*\b(install|usage|contributing|sections|section)\b/i,
93
- /\blockfile\b/i,
94
- /\bcargo-audit\b/i,
95
- /\bDockerfile\b/i,
96
- /\bCI (is configured|configured|pipeline|workflow)/i,
97
- /\bGitHub Actions\b/i,
98
- /\b\.github\/workflows\b/i,
99
- /\bpre-commit\b/i,
100
- /\b(poetry|uv|pipenv|npm|pnpm|yarn|bun)\.lock/i,
101
- /\brenovate\b/i,
102
- /\bsemver\b/i,
103
- /\brelease automation\b/i,
104
- ];
105
-
106
- /**
107
- * Check categories that strongly indicate repo-hygiene rather than
108
- * agent-configuration. These cover the stack-specific engineering
109
- * baselines (Python lockfile, Rust target/ in .gitignore, etc.) that
110
- * ship via the stacks checks.
111
- */
112
- const HYGIENE_CATEGORIES = new Set([
113
- 'dependency-management', 'supply-chain', 'release-freshness',
114
- 'docker', 'ci', 'ci-cd',
115
- 'git', // the cross-platform hygiene.js checks live here
116
- ]);
117
-
118
- function inferLayerForCheck(check, defaultLayer) {
119
- const probe = `${check.name || ''} ${check.id || ''} ${check.key || ''}`;
120
- if (DRIFT_PATTERNS.some((re) => re.test(probe))) return LAYERS.DRIFT;
121
- if (defaultLayer === LAYERS.GOVERNANCE) {
122
- if (HYGIENE_PATTERNS.some((re) => re.test(probe))) return LAYERS.HYGIENE;
123
- if (check.category && HYGIENE_CATEGORIES.has(check.category)) return LAYERS.HYGIENE;
124
- }
125
- return defaultLayer;
126
- }
127
-
128
- /**
129
- * Mutates `bag` (a technique dictionary of { key: { name, id, ... } })
130
- * so every entry has a `layer` field. Existing `layer` values on
131
- * individual checks are respected.
132
- *
133
- * @param {Object} bag technique dictionary
134
- * @param {string} defaultLayer one of LAYERS.*, used when heuristics don't fire
135
- * @returns {Object} the same bag, for chaining
136
- */
137
- function assignLayers(bag, defaultLayer = LAYERS.GOVERNANCE) {
138
- if (!bag || typeof bag !== 'object') return bag;
139
- if (!isValidLayer(defaultLayer)) {
140
- throw new Error(`assignLayers: invalid defaultLayer "${defaultLayer}"`);
141
- }
142
- for (const [key, check] of Object.entries(bag)) {
143
- if (!check || typeof check !== 'object') continue;
144
- if (isValidLayer(check.layer)) continue;
145
- const withKey = { ...check, key };
146
- check.layer = inferLayerForCheck(withKey, defaultLayer);
147
- }
148
- return bag;
149
- }
150
-
151
- /**
152
- * Summary helper — counts checks per layer in a results array. Used by
153
- * the audit text renderer and by the coverage test.
154
- */
155
- function summarizeLayers(results) {
156
- const summary = {
157
- [LAYERS.GOVERNANCE]: { total: 0, passed: 0, failed: 0, skipped: 0 },
158
- [LAYERS.DRIFT]: { total: 0, passed: 0, failed: 0, skipped: 0 },
159
- [LAYERS.HYGIENE]: { total: 0, passed: 0, failed: 0, skipped: 0 },
160
- [LAYERS.SHALLOW_RISK]: { total: 0, passed: 0, failed: 0, skipped: 0 },
161
- };
162
- for (const r of results || []) {
163
- const layer = isValidLayer(r.layer) ? r.layer : LAYERS.HYGIENE;
164
- const bucket = summary[layer];
165
- bucket.total += 1;
166
- if (r.passed === true) bucket.passed += 1;
167
- else if (r.passed === false) bucket.failed += 1;
168
- else bucket.skipped += 1;
169
- }
170
- return summary;
171
- }
172
-
173
- module.exports = {
174
- LAYERS,
175
- LAYER_DEFINITIONS,
176
- isValidLayer,
177
- assignLayers,
178
- summarizeLayers,
179
- inferLayerForCheck,
180
- };
1
+ /**
2
+ * CTO-08 — 5-layer scope clarity.
3
+ *
4
+ * Every check in the NERVIQ audit is tagged with exactly one layer so
5
+ * customers and evaluators get an explicit map of what NERVIQ covers and
6
+ * what it does not. The 4 positive layers below intentionally exclude any
7
+ * "deep-review" / general-security-scanning lane: NERVIQ is an
8
+ * agent-configuration audit tool, not a code-review tool.
9
+ *
10
+ * Taxonomy (canonical — mirrored in docs/integration-contracts.md §8):
11
+ *
12
+ * governance — Agent configuration posture: presence, content, and
13
+ * quality of agent-instruction files and platform
14
+ * settings. Answers "does my agent know X?".
15
+ *
16
+ * drift — Cross-platform consistency: do multiple platform
17
+ * configs agree? Does the declared state match the
18
+ * repo reality? Answers "do two places agree on X?".
19
+ *
20
+ * hygiene — Repo-level cleanliness and operational basics
21
+ * adjacent to agents (gitignore, CHANGELOG, SECURITY.md,
22
+ * CI, Dependabot, license, editorconfig, Node version
23
+ * pinning, etc.). Answers "does the repo have standard
24
+ * engineering hygiene that makes the agent's job
25
+ * easier?".
26
+ *
27
+ * shallow-risk — Parallel, opt-in boundary checks that sit at the
28
+ * agent-config <-> codebase edge. Findings are emitted
29
+ * through `auditResult.shallowRiskHints[]` and are not
30
+ * folded into governance scoring.
31
+ *
32
+ * Disambiguation rule-of-thumb when a check could plausibly belong to
33
+ * more than one layer: prefer the most specific layer (drift > hygiene
34
+ * > governance). If in doubt, default to hygiene — a mild
35
+ * misclassification is recoverable; a missing tag breaks the coverage
36
+ * test.
37
+ */
38
+
39
+ 'use strict';
40
+
41
+ const LAYERS = Object.freeze({
42
+ GOVERNANCE: 'governance',
43
+ DRIFT: 'drift',
44
+ HYGIENE: 'hygiene',
45
+ SHALLOW_RISK: 'shallow-risk',
46
+ });
47
+
48
+ const LAYER_DEFINITIONS = Object.freeze({
49
+ [LAYERS.GOVERNANCE]: 'Agent configuration posture: presence, content, and quality of agent-instruction files and platform settings.',
50
+ [LAYERS.DRIFT]: 'Cross-platform consistency: do multiple platform configs agree, and does the declared state match repo reality?',
51
+ [LAYERS.HYGIENE]: 'Repo-level cleanliness and operational basics adjacent to agents (gitignore, CHANGELOG, SECURITY.md, CI, license, etc.).',
52
+ [LAYERS.SHALLOW_RISK]: 'Parallel, opt-in boundary checks emitted via auditResult.shallowRiskHints[]; shown separately and excluded from governance scoring.',
53
+ });
54
+
55
+ const VALID_LAYER_VALUES = new Set(Object.values(LAYERS));
56
+
57
+ function isValidLayer(value) {
58
+ return typeof value === 'string' && VALID_LAYER_VALUES.has(value);
59
+ }
60
+
61
+ /**
62
+ * Name/id patterns that strongly indicate a drift check. Applied only as
63
+ * a heuristic when tagging existing check bags (see assignLayers).
64
+ */
65
+ const DRIFT_PATTERNS = [
66
+ /drift/i,
67
+ /harmony/i,
68
+ /\bpropagation\b/i,
69
+ /consisten(t|cy)/i,
70
+ /cross[- ]?platform/i,
71
+ /across (surfaces|platforms|all .* surfaces)/i,
72
+ /\bpacks are consistent\b/i,
73
+ /propagation (checklist|completeness|delay)/i,
74
+ ];
75
+
76
+ /**
77
+ * Hygiene name patterns — used to upgrade a check from a default
78
+ * governance bag into hygiene when the check is clearly about repo
79
+ * engineering hygiene rather than agent config.
80
+ */
81
+ const HYGIENE_PATTERNS = [
82
+ /\.gitignore/i,
83
+ /\bCHANGELOG\b/i,
84
+ /\bCONTRIBUTING\b/i,
85
+ /\bLICENSE\b/i,
86
+ /\.editorconfig/i,
87
+ /\bEditorConfig\b/i,
88
+ /\bSECURITY\.md\b/i,
89
+ /\bCODE_OF_CONDUCT\b/i,
90
+ /\bDependabot\b/i,
91
+ /\bNode version pinned\b/i,
92
+ /\bREADME\b.*\b(install|usage|contributing|sections|section)\b/i,
93
+ /\blockfile\b/i,
94
+ /\bcargo-audit\b/i,
95
+ /\bDockerfile\b/i,
96
+ /\bCI (is configured|configured|pipeline|workflow)/i,
97
+ /\bGitHub Actions\b/i,
98
+ /\b\.github\/workflows\b/i,
99
+ /\bpre-commit\b/i,
100
+ /\b(poetry|uv|pipenv|npm|pnpm|yarn|bun)\.lock/i,
101
+ /\brenovate\b/i,
102
+ /\bsemver\b/i,
103
+ /\brelease automation\b/i,
104
+ ];
105
+
106
+ /**
107
+ * Check categories that strongly indicate repo-hygiene rather than
108
+ * agent-configuration. These cover the stack-specific engineering
109
+ * baselines (Python lockfile, Rust target/ in .gitignore, etc.) that
110
+ * ship via the stacks checks.
111
+ */
112
+ const HYGIENE_CATEGORIES = new Set([
113
+ 'dependency-management', 'supply-chain', 'release-freshness',
114
+ 'docker', 'ci', 'ci-cd',
115
+ 'git', // the cross-platform hygiene.js checks live here
116
+ ]);
117
+
118
+ function inferLayerForCheck(check, defaultLayer) {
119
+ const probe = `${check.name || ''} ${check.id || ''} ${check.key || ''}`;
120
+ if (DRIFT_PATTERNS.some((re) => re.test(probe))) return LAYERS.DRIFT;
121
+ if (defaultLayer === LAYERS.GOVERNANCE) {
122
+ if (HYGIENE_PATTERNS.some((re) => re.test(probe))) return LAYERS.HYGIENE;
123
+ if (check.category && HYGIENE_CATEGORIES.has(check.category)) return LAYERS.HYGIENE;
124
+ }
125
+ return defaultLayer;
126
+ }
127
+
128
+ /**
129
+ * Mutates `bag` (a technique dictionary of { key: { name, id, ... } })
130
+ * so every entry has a `layer` field. Existing `layer` values on
131
+ * individual checks are respected.
132
+ *
133
+ * @param {Object} bag technique dictionary
134
+ * @param {string} defaultLayer one of LAYERS.*, used when heuristics don't fire
135
+ * @returns {Object} the same bag, for chaining
136
+ */
137
+ function assignLayers(bag, defaultLayer = LAYERS.GOVERNANCE) {
138
+ if (!bag || typeof bag !== 'object') return bag;
139
+ if (!isValidLayer(defaultLayer)) {
140
+ throw new Error(`assignLayers: invalid defaultLayer "${defaultLayer}"`);
141
+ }
142
+ for (const [key, check] of Object.entries(bag)) {
143
+ if (!check || typeof check !== 'object') continue;
144
+ if (isValidLayer(check.layer)) continue;
145
+ const withKey = { ...check, key };
146
+ check.layer = inferLayerForCheck(withKey, defaultLayer);
147
+ }
148
+ return bag;
149
+ }
150
+
151
+ /**
152
+ * Summary helper — counts checks per layer in a results array. Used by
153
+ * the audit text renderer and by the coverage test.
154
+ */
155
+ function summarizeLayers(results) {
156
+ const summary = {
157
+ [LAYERS.GOVERNANCE]: { total: 0, passed: 0, failed: 0, skipped: 0 },
158
+ [LAYERS.DRIFT]: { total: 0, passed: 0, failed: 0, skipped: 0 },
159
+ [LAYERS.HYGIENE]: { total: 0, passed: 0, failed: 0, skipped: 0 },
160
+ [LAYERS.SHALLOW_RISK]: { total: 0, passed: 0, failed: 0, skipped: 0 },
161
+ };
162
+ for (const r of results || []) {
163
+ const layer = isValidLayer(r.layer) ? r.layer : LAYERS.HYGIENE;
164
+ const bucket = summary[layer];
165
+ bucket.total += 1;
166
+ if (r.passed === true) bucket.passed += 1;
167
+ else if (r.passed === false) bucket.failed += 1;
168
+ else bucket.skipped += 1;
169
+ }
170
+ return summary;
171
+ }
172
+
173
+ module.exports = {
174
+ LAYERS,
175
+ LAYER_DEFINITIONS,
176
+ isValidLayer,
177
+ assignLayers,
178
+ summarizeLayers,
179
+ inferLayerForCheck,
180
+ };