@nerviq/cli 1.25.0 → 1.26.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 +2 -2
- package/package.json +1 -1
- package/src/instruction-surfaces.js +61 -5
- package/src/techniques/shared.js +110 -0
package/README.md
CHANGED
|
@@ -234,8 +234,8 @@ All successful operational responses are wrapped in a JSON envelope:
|
|
|
234
234
|
{
|
|
235
235
|
"data": {},
|
|
236
236
|
"meta": {
|
|
237
|
-
"version": "1.
|
|
238
|
-
"timestamp": "2026-04-
|
|
237
|
+
"version": "1.26.0",
|
|
238
|
+
"timestamp": "2026-04-15T14:00:00.000Z"
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nerviq/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.26.0",
|
|
4
4
|
"description": "The intelligent nervous system for AI coding agents — 2,441 checks (8 platforms × ~300 governance rules), 10 languages, 62 domain packs. Audit, align, and amplify.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -6,21 +6,37 @@ const TEST_COMMAND_PATTERNS = [
|
|
|
6
6
|
/\bpython\s+manage\.py\s+test\b/i,
|
|
7
7
|
/\bdjango-admin\s+test\b/i,
|
|
8
8
|
/\bpython\s+-m\s+unittest\b/i,
|
|
9
|
+
/\bpoetry\s+run\s+(?:pytest|test)\b/i,
|
|
10
|
+
/\buv\s+run\s+(?:pytest|test)\b/i,
|
|
11
|
+
/\bpdm\s+run\s+(?:pytest|test)\b/i,
|
|
12
|
+
/\bhatch\s+run\s+(?:test|pytest)\b/i,
|
|
13
|
+
/\brye\s+run\s+(?:test|pytest)\b/i,
|
|
14
|
+
/\btox(?:\s|$)/i,
|
|
15
|
+
/\bnox(?:\s|$)/i,
|
|
9
16
|
/\bgo\s+test(?:\s|$)/i,
|
|
10
17
|
/\bcargo\s+test\b/i,
|
|
11
|
-
/\bmake\s+test\b/i,
|
|
18
|
+
/\bmake\s+(?:test|check|ci)\b/i,
|
|
19
|
+
/\bjust\s+test\b/i,
|
|
12
20
|
/\bmix\s+test\b/i,
|
|
13
21
|
/\bbundle\s+exec\s+rspec\b/i,
|
|
14
22
|
/\brspec\b/i,
|
|
15
23
|
/\bphpunit\b/i,
|
|
16
24
|
/\bdotnet\s+test(?:\s|$)/i,
|
|
17
25
|
/\bflutter\s+test\b/i,
|
|
26
|
+
/\bfvm\s+flutter\s+test\b/i,
|
|
18
27
|
/\bswift\s+test\b/i,
|
|
19
28
|
/\bxcodebuild\b[^\n\r`]{0,200}\btest\b/i,
|
|
20
|
-
/\
|
|
29
|
+
/\bfastlane\s+(?:test|scan)\b/i,
|
|
30
|
+
/\bxctest\b/i,
|
|
31
|
+
/\bgradlew?\s+(?:test|check|connectedAndroidTest)\b/i,
|
|
21
32
|
/\bmvn(?:w)?\s+test\b/i,
|
|
22
33
|
/\bplaywright\s+test\b/i,
|
|
23
34
|
/\bcypress\s+run\b/i,
|
|
35
|
+
// pyproject.toml / setup.cfg tool configuration signals
|
|
36
|
+
/\[tool\.pytest\.ini_options\]/i,
|
|
37
|
+
/\[tool:pytest\]/i,
|
|
38
|
+
// Manifest / config signals that testing is wired up
|
|
39
|
+
/\bpytest\s*[=:]/i,
|
|
24
40
|
];
|
|
25
41
|
|
|
26
42
|
const LINT_COMMAND_PATTERNS = [
|
|
@@ -33,6 +49,7 @@ const LINT_COMMAND_PATTERNS = [
|
|
|
33
49
|
/\bpylint\b/i,
|
|
34
50
|
/\bmypy\b/i,
|
|
35
51
|
/\bpyright\b/i,
|
|
52
|
+
/\bpre-commit\s+run\b/i,
|
|
36
53
|
/\bgo\s+vet\b/i,
|
|
37
54
|
/\bgofmt\b/i,
|
|
38
55
|
/\bgofumpt\b/i,
|
|
@@ -41,11 +58,19 @@ const LINT_COMMAND_PATTERNS = [
|
|
|
41
58
|
/\bcargo\s+clippy\b/i,
|
|
42
59
|
/\bflutter\s+analyze\b/i,
|
|
43
60
|
/\bdart\s+analyze\b/i,
|
|
61
|
+
/\bdart\s+format\b/i,
|
|
44
62
|
/\bswiftlint\b/i,
|
|
45
63
|
/\bswift(?:-|\s+)format\b/i,
|
|
46
64
|
/\bdotnet\s+format(?:\s|$)/i,
|
|
47
|
-
/\bgradlew?\s+lint\b/i,
|
|
65
|
+
/\bgradlew?\s+(?:lint|ktlintCheck|detekt|spotless(?:Check|Apply)?)\b/i,
|
|
48
66
|
/\bmvn(?:w)?\s+(?:checkstyle:check|spotbugs:check|verify)\b/i,
|
|
67
|
+
// pyproject.toml / config signals
|
|
68
|
+
/\[tool\.ruff\]/i,
|
|
69
|
+
/\[tool\.black\]/i,
|
|
70
|
+
/\[tool\.mypy\]/i,
|
|
71
|
+
/\[tool\.pyright\]/i,
|
|
72
|
+
/\[tool\.flake8\]/i,
|
|
73
|
+
/\[tool\.pylint\b/i,
|
|
49
74
|
];
|
|
50
75
|
|
|
51
76
|
const BUILD_COMMAND_PATTERNS = [
|
|
@@ -53,16 +78,20 @@ const BUILD_COMMAND_PATTERNS = [
|
|
|
53
78
|
/\btsc(?:\s|$)/i,
|
|
54
79
|
/\bgo\s+build(?:\s|$)/i,
|
|
55
80
|
/\bcargo\s+(?:build|check)\b/i,
|
|
56
|
-
/\bmake\s+build\b/i,
|
|
81
|
+
/\bmake\s+(?:build|all)\b/i,
|
|
82
|
+
/\bjust\s+build\b/i,
|
|
57
83
|
/\bdotnet\s+(?:build|publish)(?:\s|$)/i,
|
|
58
84
|
/\bmsbuild\b/i,
|
|
59
85
|
/\bflutter\s+build(?:\s|$)/i,
|
|
60
86
|
/\bswift\s+build\b/i,
|
|
61
87
|
/\bxcodebuild\b/i,
|
|
62
|
-
/\bgradlew?\s+(?:build|assemble)\b/i,
|
|
88
|
+
/\bgradlew?\s+(?:build|assemble|assembleDebug|assembleRelease)\b/i,
|
|
63
89
|
/\bmvn(?:w)?\s+(?:compile|package|verify|install)\b/i,
|
|
64
90
|
/\bpython\s+-m\s+build\b/i,
|
|
65
91
|
/\bpoetry\s+build\b/i,
|
|
92
|
+
/\buv\s+build\b/i,
|
|
93
|
+
/\bhatch\s+build\b/i,
|
|
94
|
+
/\bpdm\s+build\b/i,
|
|
66
95
|
];
|
|
67
96
|
|
|
68
97
|
function normalizePath(filePath) {
|
|
@@ -118,6 +147,33 @@ function buildSurfaceList(ctx, scope) {
|
|
|
118
147
|
if (includeReadme) {
|
|
119
148
|
addSurface(ctx, surfaces, seen, 'README.md');
|
|
120
149
|
addSurface(ctx, surfaces, seen, 'CONTRIBUTING.md');
|
|
150
|
+
// CTO-07: framework-native verification surfaces. When a repo has
|
|
151
|
+
// `flutter test` in CONTRIBUTING.md, pytest configured in
|
|
152
|
+
// pyproject.toml, xcodebuild wired in a workflow, or gradle test in
|
|
153
|
+
// build.gradle, that is legitimate evidence of verification — an
|
|
154
|
+
// agent working in this repo can observe these files directly.
|
|
155
|
+
addSurface(ctx, surfaces, seen, 'pyproject.toml');
|
|
156
|
+
addSurface(ctx, surfaces, seen, 'setup.cfg');
|
|
157
|
+
addSurface(ctx, surfaces, seen, 'tox.ini');
|
|
158
|
+
addSurface(ctx, surfaces, seen, 'noxfile.py');
|
|
159
|
+
addSurface(ctx, surfaces, seen, 'Pipfile');
|
|
160
|
+
addSurface(ctx, surfaces, seen, 'Makefile');
|
|
161
|
+
addSurface(ctx, surfaces, seen, 'justfile');
|
|
162
|
+
addSurface(ctx, surfaces, seen, 'Justfile');
|
|
163
|
+
addSurface(ctx, surfaces, seen, 'Rakefile');
|
|
164
|
+
addSurface(ctx, surfaces, seen, 'pubspec.yaml');
|
|
165
|
+
addSurface(ctx, surfaces, seen, 'analysis_options.yaml');
|
|
166
|
+
addSurface(ctx, surfaces, seen, 'Package.swift');
|
|
167
|
+
addSurface(ctx, surfaces, seen, 'Podfile');
|
|
168
|
+
addSurface(ctx, surfaces, seen, 'Cartfile');
|
|
169
|
+
addSurface(ctx, surfaces, seen, 'fastlane/Fastfile');
|
|
170
|
+
addSurface(ctx, surfaces, seen, 'build.gradle');
|
|
171
|
+
addSurface(ctx, surfaces, seen, 'build.gradle.kts');
|
|
172
|
+
addSurface(ctx, surfaces, seen, 'settings.gradle');
|
|
173
|
+
addSurface(ctx, surfaces, seen, 'settings.gradle.kts');
|
|
174
|
+
addSurface(ctx, surfaces, seen, '.pre-commit-config.yaml');
|
|
175
|
+
addSurface(ctx, surfaces, seen, '.pre-commit-config.yml');
|
|
176
|
+
addDirSurfaces(ctx, surfaces, seen, '.github/workflows', /\.ya?ml$/i);
|
|
121
177
|
}
|
|
122
178
|
|
|
123
179
|
return surfaces;
|
package/src/techniques/shared.js
CHANGED
|
@@ -202,6 +202,106 @@ function isDotnetProject(ctx) {
|
|
|
202
202
|
return ctx.__nerviqIsDotnet;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
// ─── CTO-07 Framework-native verification signals ───────────────────────
|
|
206
|
+
// Memoized on ctx. These are "this stack has verification wired up"
|
|
207
|
+
// signals that augment documentation-surface detection.
|
|
208
|
+
|
|
209
|
+
function hasIosXcodeProject(ctx) {
|
|
210
|
+
if (ctx.__nerviqHasIosXcode !== undefined) return ctx.__nerviqHasIosXcode;
|
|
211
|
+
ctx.__nerviqHasIosXcode =
|
|
212
|
+
hasCoreProjectFile(ctx, /\.xcodeproj\//i) ||
|
|
213
|
+
hasCoreProjectFile(ctx, /\.xcworkspace\//i) ||
|
|
214
|
+
hasCoreRootFile(ctx, /(^|\/)Package\.swift$/i);
|
|
215
|
+
return ctx.__nerviqHasIosXcode;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function hasAndroidGradle(ctx) {
|
|
219
|
+
if (ctx.__nerviqHasAndroidGradle !== undefined) return ctx.__nerviqHasAndroidGradle;
|
|
220
|
+
ctx.__nerviqHasAndroidGradle =
|
|
221
|
+
hasCoreRootFile(ctx, /(^|\/)build\.gradle(\.kts)?$/i) ||
|
|
222
|
+
hasCoreRootFile(ctx, /(^|\/)settings\.gradle(\.kts)?$/i);
|
|
223
|
+
return ctx.__nerviqHasAndroidGradle;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function hasFlutterProject(ctx) {
|
|
227
|
+
if (ctx.__nerviqHasFlutter !== undefined) return ctx.__nerviqHasFlutter;
|
|
228
|
+
const pubspec = ctx.fileContent('pubspec.yaml') || '';
|
|
229
|
+
ctx.__nerviqHasFlutter = /\bflutter:\s*\n/i.test(pubspec) || /\bsdk:\s*flutter\b/i.test(pubspec);
|
|
230
|
+
return ctx.__nerviqHasFlutter;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function _pyProjectText(ctx) {
|
|
234
|
+
return getPythonProjectText(ctx);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function hasPythonPoetry(ctx) {
|
|
238
|
+
if (ctx.__nerviqHasPoetry !== undefined) return ctx.__nerviqHasPoetry;
|
|
239
|
+
const text = _pyProjectText(ctx);
|
|
240
|
+
ctx.__nerviqHasPoetry = /\[tool\.poetry\]/i.test(text) || !!ctx.fileContent('poetry.lock');
|
|
241
|
+
return ctx.__nerviqHasPoetry;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function hasPythonUv(ctx) {
|
|
245
|
+
if (ctx.__nerviqHasUv !== undefined) return ctx.__nerviqHasUv;
|
|
246
|
+
const text = _pyProjectText(ctx);
|
|
247
|
+
ctx.__nerviqHasUv = /\[tool\.uv\]/i.test(text) || !!ctx.fileContent('uv.lock');
|
|
248
|
+
return ctx.__nerviqHasUv;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function hasPythonPdm(ctx) {
|
|
252
|
+
if (ctx.__nerviqHasPdm !== undefined) return ctx.__nerviqHasPdm;
|
|
253
|
+
const text = _pyProjectText(ctx);
|
|
254
|
+
ctx.__nerviqHasPdm = /\[tool\.pdm\b/i.test(text) || !!ctx.fileContent('pdm.lock');
|
|
255
|
+
return ctx.__nerviqHasPdm;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function hasPythonHatch(ctx) {
|
|
259
|
+
if (ctx.__nerviqHasHatch !== undefined) return ctx.__nerviqHasHatch;
|
|
260
|
+
const text = _pyProjectText(ctx);
|
|
261
|
+
ctx.__nerviqHasHatch = /\[tool\.hatch\b/i.test(text);
|
|
262
|
+
return ctx.__nerviqHasHatch;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function hasFastApiProject(ctx) {
|
|
266
|
+
if (ctx.__nerviqHasFastApi !== undefined) return ctx.__nerviqHasFastApi;
|
|
267
|
+
const text = _pyProjectText(ctx);
|
|
268
|
+
ctx.__nerviqHasFastApi = /\bfastapi\b/i.test(text);
|
|
269
|
+
return ctx.__nerviqHasFastApi;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const ML_DEP_PATTERN = /\b(pytorch|torch|tensorflow|keras|scikit-learn|sklearn|jax|transformers|datasets|huggingface|accelerate|xgboost|lightgbm)\b/i;
|
|
273
|
+
|
|
274
|
+
function hasMlScaffolding(ctx) {
|
|
275
|
+
if (ctx.__nerviqHasMl !== undefined) return ctx.__nerviqHasMl;
|
|
276
|
+
const text = _pyProjectText(ctx);
|
|
277
|
+
if (ML_DEP_PATTERN.test(text)) {
|
|
278
|
+
ctx.__nerviqHasMl = true;
|
|
279
|
+
return true;
|
|
280
|
+
}
|
|
281
|
+
// Heuristic: notebooks/ or experiments/ dir with actual .ipynb files
|
|
282
|
+
const hasNotebooks = findProjectFiles(ctx, /\.ipynb$/i).length > 0;
|
|
283
|
+
ctx.__nerviqHasMl = hasNotebooks;
|
|
284
|
+
return ctx.__nerviqHasMl;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Checks whether a Python tool is actively configured in pyproject.toml /
|
|
289
|
+
* setup.cfg (e.g., `[tool.ruff]`, `[tool.pytest.ini_options]`,
|
|
290
|
+
* `[tool.mypy]`). When configured, any verification-surface check for that
|
|
291
|
+
* tool should pass: an agent working in this repo can run the tool.
|
|
292
|
+
*/
|
|
293
|
+
function hasConfiguredTooling(ctx, toolName) {
|
|
294
|
+
const text = _pyProjectText(ctx);
|
|
295
|
+
if (!text) return false;
|
|
296
|
+
const name = String(toolName || '').toLowerCase();
|
|
297
|
+
const sectionRe = new RegExp(`\\[tool\\.${name.replace(/[-_.]/g, '[-_.]')}(?:[.\\]]|\\s|$)`, 'i');
|
|
298
|
+
if (sectionRe.test(text)) return true;
|
|
299
|
+
if (name === 'pytest') {
|
|
300
|
+
return /\[tool\.pytest\.ini_options\]/i.test(text) || /\[tool:pytest\]/i.test(text);
|
|
301
|
+
}
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
|
|
205
305
|
/**
|
|
206
306
|
* Map category names to their project detection function.
|
|
207
307
|
* Used by the audit to skip entire categories when the stack isn't detected.
|
|
@@ -418,6 +518,16 @@ module.exports = {
|
|
|
418
518
|
isPhpProject,
|
|
419
519
|
isDotnetProject,
|
|
420
520
|
STACK_CATEGORY_DETECTORS,
|
|
521
|
+
hasIosXcodeProject,
|
|
522
|
+
hasAndroidGradle,
|
|
523
|
+
hasFlutterProject,
|
|
524
|
+
hasPythonPoetry,
|
|
525
|
+
hasPythonUv,
|
|
526
|
+
hasPythonPdm,
|
|
527
|
+
hasPythonHatch,
|
|
528
|
+
hasFastApiProject,
|
|
529
|
+
hasMlScaffolding,
|
|
530
|
+
hasConfiguredTooling,
|
|
421
531
|
getPythonFiles,
|
|
422
532
|
getMainPythonFiles,
|
|
423
533
|
getPythonProjectText,
|