arkgate 4.8.21 → 4.8.22
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/CHANGELOG.md +48 -0
- package/README.md +2 -2
- package/bin/lib/analysis-engine.mjs +8 -8
- package/bin/lib/invariant-coverage.mjs +27 -3
- package/dist/{diagnosticCatalog-B7BXlet6.d.ts → diagnosticCatalog-WD2TPSwZ.d.ts} +8 -3
- package/dist/index.cjs +29 -29
- package/dist/index.d.ts +2 -2
- package/dist/index.js +30 -30
- package/dist/nestjs/index.cjs +1 -1
- package/dist/nestjs/index.js +1 -1
- package/dist/runtime/index.cjs +19 -19
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +19 -19
- package/docs/README.md +2 -1
- package/docs/product-voice.md +1 -1
- package/package.json +2 -1
- package/server.json +2 -2
- package/templates/agent-skills/README.md +1 -1
|
@@ -133,7 +133,7 @@ function matchTestTitle(content, id) {
|
|
|
133
133
|
if (!id)
|
|
134
134
|
return undefined;
|
|
135
135
|
const escaped = escapeRegExp(id);
|
|
136
|
-
const re = new RegExp(`(?:describe|it|test|context)\\s*\\(\\s*(['"\`])([
|
|
136
|
+
const re = new RegExp(`(?:describe|it|test|context)\\s*\\(\\s*(['"\`])((?:(?!\\1)[^\\\\]|\\\\.)*?${escaped}(?:(?!\\1)[^\\\\]|\\\\.)*?)\\1`, 'i');
|
|
137
137
|
const match = re.exec(maskNonCode(content, false));
|
|
138
138
|
const title = match?.[2];
|
|
139
139
|
return title === undefined ? undefined : title;
|
|
@@ -160,7 +160,7 @@ function declarationShape(content, name) {
|
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
shape: 'const',
|
|
163
|
-
source: `(?:^|[\\s;{}])export\\s+(?:const|let|var)\\s+${n}
|
|
163
|
+
source: `(?:^|[\\s;{}])export\\s+(?:const|let|var)\\s+${n}(?:\\s*:(?:[^=]|=>)+?)?\\s*=(?!>)`,
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
166
|
shape: 'type',
|
|
@@ -382,15 +382,36 @@ function rankCoverage(invariant, files, scanTests = true) {
|
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
|
-
|
|
385
|
+
let best = testTitle
|
|
386
386
|
? { kind: 'test-title', file: testTitle.file, title: testTitle.title }
|
|
387
387
|
: declaration
|
|
388
388
|
? { kind: 'declaration', file: declaration.file, shape: declaration.shape }
|
|
389
389
|
: mention
|
|
390
390
|
? { kind: 'mention-only', file: mention.file, context: mention.context }
|
|
391
391
|
: { kind: 'none' };
|
|
392
|
+
if (best.kind === 'mention-only' &&
|
|
393
|
+
best.context === 'comment' &&
|
|
394
|
+
needle &&
|
|
395
|
+
symbolInCodeElsewhere(files.fileContents, tests, needle.name, best.file)) {
|
|
396
|
+
best = { kind: 'declaration-miss', symbol: needle.name };
|
|
397
|
+
}
|
|
392
398
|
return { best, ...(testTitle ? { testTitle } : {}), ...(declaration ? { declaration } : {}) };
|
|
393
399
|
}
|
|
400
|
+
/** True when `name` survives comment/string masking in some non-test file other than `mentionFile`. */
|
|
401
|
+
function symbolInCodeElsewhere(fileContents, tests, name, mentionFile) {
|
|
402
|
+
const needle = new RegExp(`(?:^|[^A-Za-z0-9_$])${escapeRegExp(name)}(?=$|[^A-Za-z0-9_$])`);
|
|
403
|
+
const mention = normalizePath(mentionFile);
|
|
404
|
+
for (const file of Object.keys(fileContents)) {
|
|
405
|
+
if (tests.has(normalizePath(file)) || normalizePath(file) === mention)
|
|
406
|
+
continue;
|
|
407
|
+
const content = fileContents[file];
|
|
408
|
+
if (!content)
|
|
409
|
+
continue;
|
|
410
|
+
if (needle.test(maskNonCode(content, true)))
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
394
415
|
/**
|
|
395
416
|
* Best coverage evidence for `invariant` in `files`.
|
|
396
417
|
* test-title beats a declaration; a declaration beats a bare mention; a bare
|
|
@@ -409,6 +430,7 @@ export function countsAsCoverage(ev) {
|
|
|
409
430
|
case 'declaration':
|
|
410
431
|
return true;
|
|
411
432
|
case 'mention-only':
|
|
433
|
+
case 'declaration-miss':
|
|
412
434
|
case 'none':
|
|
413
435
|
return false;
|
|
414
436
|
}
|
|
@@ -434,6 +456,8 @@ export function describeCoverage(invariant, ev) {
|
|
|
434
456
|
return `found \`${ev.shape} ${declaredLabel(invariant)}\` in ${ev.file}`;
|
|
435
457
|
case 'mention-only':
|
|
436
458
|
return `${invariant.id} appears only in ${mentionWhere(ev.context)} in ${ev.file}; put it in a describe/it title`;
|
|
459
|
+
case 'declaration-miss':
|
|
460
|
+
return `no declaration matched \`${ev.symbol}\``;
|
|
437
461
|
case 'none':
|
|
438
462
|
return 'no scanned test names it in a describe/it title and no declared symbol was found';
|
|
439
463
|
}
|
|
@@ -392,7 +392,7 @@ declare function createAdapterResult(input: {
|
|
|
392
392
|
}): CurrentAdapterResult;
|
|
393
393
|
|
|
394
394
|
/** ArkGate library version — single source of truth. */
|
|
395
|
-
declare const version = "4.8.
|
|
395
|
+
declare const version = "4.8.22";
|
|
396
396
|
|
|
397
397
|
/**
|
|
398
398
|
* AI Code Gate (basic).
|
|
@@ -1738,8 +1738,10 @@ type DeclarationShape = 'function' | 'class' | 'const' | 'method' | 'type' | 'in
|
|
|
1738
1738
|
type MentionContext = 'test-body' | 'comment' | 'string' | 'import';
|
|
1739
1739
|
/**
|
|
1740
1740
|
* One coverage verdict. Best evidence wins: test-title, then declaration,
|
|
1741
|
-
* then mention-only, then none.
|
|
1742
|
-
* `
|
|
1741
|
+
* then mention-only, then none. A comment in another file, when the symbol
|
|
1742
|
+
* still occurs in code, is `declaration-miss` and does not count.
|
|
1743
|
+
* Regexes, the test-file vs source split, and `Aggregate.method` lookup stay
|
|
1744
|
+
* behind this value.
|
|
1743
1745
|
*/
|
|
1744
1746
|
type CoverageEvidence = {
|
|
1745
1747
|
kind: 'test-title';
|
|
@@ -1753,6 +1755,9 @@ type CoverageEvidence = {
|
|
|
1753
1755
|
kind: 'mention-only';
|
|
1754
1756
|
file: string;
|
|
1755
1757
|
context: MentionContext;
|
|
1758
|
+
} | {
|
|
1759
|
+
kind: 'declaration-miss';
|
|
1760
|
+
symbol: string;
|
|
1756
1761
|
} | {
|
|
1757
1762
|
kind: 'none';
|
|
1758
1763
|
};
|