vigiles 14.6.7 → 14.7.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.
@@ -91,7 +91,7 @@ export interface AuditReport {
91
91
  /**
92
92
  * The one-line verdict + per-recommendation `pointsIfFixed`, both derived by
93
93
  * RE-SCORING (never a hardcoded number). Drives the report's verdict-led header
94
- * ("Two one-line fixes away from a B.") and the `+N pts` badges on fix cards.
94
+ * ("Two fixes away from a B.") and the `+N pts` badges on fix cards.
95
95
  * Pure/deterministic — always present.
96
96
  */
97
97
  readonly verdict: Verdict;
@@ -100,7 +100,7 @@ function structure(r) {
100
100
  {
101
101
  n: deadTools,
102
102
  weight: leaderboard_js_1.W_DANGLING_REF,
103
- label: "agent tool(s) that don't exist (typo / never-available)",
103
+ label: "unavailable agent tool(s) (typo / never-available)",
104
104
  },
105
105
  {
106
106
  n: deadMcpTools,
@@ -11,7 +11,7 @@
11
11
  * 1. `pointsIfFixed` per recommendation — the exact number of overall points the
12
12
  * grade gains if THAT one fix is applied (so a fix card can show `+N pts` and
13
13
  * sort by it). Computed as `overall(report − thisFinding) − overall(report)`.
14
- * 2. A verdict `sentence` for the report header — e.g. "Two one-line fixes away
14
+ * 2. A verdict `sentence` for the report header — e.g. "Two fixes away
15
15
  * from an A." — where the COUNT is the minimal number of fixes whose COMBINED
16
16
  * removal actually crosses the next grade threshold (a real cumulative
17
17
  * re-score), and `pointsToNextGrade` is the real threshold gap.
@@ -12,7 +12,7 @@
12
12
  * 1. `pointsIfFixed` per recommendation — the exact number of overall points the
13
13
  * grade gains if THAT one fix is applied (so a fix card can show `+N pts` and
14
14
  * sort by it). Computed as `overall(report − thisFinding) − overall(report)`.
15
- * 2. A verdict `sentence` for the report header — e.g. "Two one-line fixes away
15
+ * 2. A verdict `sentence` for the report header — e.g. "Two fixes away
16
16
  * from an A." — where the COUNT is the minimal number of fixes whose COMBINED
17
17
  * removal actually crosses the next grade threshold (a real cumulative
18
18
  * re-score), and `pointsToNextGrade` is the real threshold gap.
@@ -241,7 +241,7 @@ function buildSentence(input, pointsToNextGrade, fixesToNextGrade) {
241
241
  const nextGrade = (0, leaderboard_js_1.gradeFor)(score.overall + pointsToNextGrade);
242
242
  // Reachable by the deterministic fix list: fix-count-forward (the actionable framing).
243
243
  if (fixesToNextGrade !== null) {
244
- return `${capitalize(numberWord(fixesToNextGrade))} one-line ${fixNoun(fixesToNextGrade)} away from ${article(nextGrade)} ${nextGrade}.`;
244
+ return `${capitalize(numberWord(fixesToNextGrade))} ${fixNoun(fixesToNextGrade)} away from ${article(nextGrade)} ${nextGrade}.`;
245
245
  }
246
246
  // Not reachable by recommendations alone — lead with the dominant blocking finding.
247
247
  const dom = dominantDeduction(report);
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Levenshtein distance for short-string typo detection. Rule names, tool names,
3
+ * and hook events are short, so edit distance is more appropriate than NCD
4
+ * (which is tuned for longer texts).
5
+ *
6
+ * Extracted to its own zero-dependency leaf module so the typo detectors
7
+ * (tool-contract, hook-events) can import it WITHOUT pulling in `core/linters.ts`,
8
+ * which runs a `node:fs`/`process`/`glob` side effect at import time — the
9
+ * blocker to running those detectors in a browser (the in-browser audit demo).
10
+ */
11
+ export declare function editDistance(a: string, b: string): number;
12
+ //# sourceMappingURL=edit-distance.d.ts.map
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.editDistance = editDistance;
4
+ /**
5
+ * Levenshtein distance for short-string typo detection. Rule names, tool names,
6
+ * and hook events are short, so edit distance is more appropriate than NCD
7
+ * (which is tuned for longer texts).
8
+ *
9
+ * Extracted to its own zero-dependency leaf module so the typo detectors
10
+ * (tool-contract, hook-events) can import it WITHOUT pulling in `core/linters.ts`,
11
+ * which runs a `node:fs`/`process`/`glob` side effect at import time — the
12
+ * blocker to running those detectors in a browser (the in-browser audit demo).
13
+ */
14
+ function editDistance(a, b) {
15
+ if (a === b)
16
+ return 0;
17
+ const m = a.length;
18
+ const n = b.length;
19
+ if (m === 0)
20
+ return n;
21
+ if (n === 0)
22
+ return m;
23
+ const dp = Array.from({ length: n + 1 }, (_, i) => i);
24
+ for (let i = 1; i <= m; i++) {
25
+ let prev = dp[0];
26
+ dp[0] = i;
27
+ for (let j = 1; j <= n; j++) {
28
+ const tmp = dp[j];
29
+ dp[j] =
30
+ a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
31
+ prev = tmp;
32
+ }
33
+ }
34
+ return dp[n];
35
+ }
36
+ //# sourceMappingURL=edit-distance.js.map
@@ -2,13 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.confidentHookEventIssues = confidentHookEventIssues;
4
4
  exports.verifyHookEvents = verifyHookEvents;
5
- const linters_js_1 = require("./linters.js");
5
+ const edit_distance_js_1 = require("./edit-distance.js");
6
6
  /** Closest known hook event by edit distance (≤ 2) — a confidence signal. */
7
7
  function closestEvent(event, dialect) {
8
8
  let best = null;
9
9
  let bestDistance = Infinity;
10
10
  for (const known of dialect.hookEvents) {
11
- const d = (0, linters_js_1.editDistance)(event.toLowerCase(), known.toLowerCase());
11
+ const d = (0, edit_distance_js_1.editDistance)(event.toLowerCase(), known.toLowerCase());
12
12
  if (d < bestDistance) {
13
13
  bestDistance = d;
14
14
  best = known;
@@ -9,6 +9,7 @@
9
9
  * This is the core moat — no other tool resolves rules across 7 catalog APIs
10
10
  * (6 linters + Cedar policy language) and checks config-enabled status.
11
11
  */
12
+ import { editDistance } from "./edit-distance.js";
12
13
  export type ConfigEnabledStatus = "enabled" | "disabled" | "unknown";
13
14
  export interface LinterCheckResult {
14
15
  exists: boolean;
@@ -24,12 +25,7 @@ export interface DetectedLinter {
24
25
  }
25
26
  /** @internal */ export declare function extractLinterName(enforcedBy: string): string;
26
27
  /** @internal */ export declare function extractRuleName(enforcedBy: string): string | null;
27
- /**
28
- * Levenshtein distance for short-string typo detection. Rule names are
29
- * short so edit distance is more appropriate than NCD (which is tuned
30
- * for longer texts).
31
- */
32
- export declare function editDistance(a: string, b: string): number;
28
+ export { editDistance };
33
29
  /** @internal */ export declare function clearCedarCache(): void;
34
30
  /**
35
31
  * Check a single linter rule reference (e.g., "eslint/no-console").
@@ -11,13 +11,15 @@
11
11
  * (6 linters + Cedar policy language) and checks config-enabled status.
12
12
  */
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.editDistance = void 0;
14
15
  exports.extractLinterName = extractLinterName;
15
16
  exports.extractRuleName = extractRuleName;
16
- exports.editDistance = editDistance;
17
17
  exports.clearCedarCache = clearCedarCache;
18
18
  exports.checkLinterRule = checkLinterRule;
19
19
  const node_fs_1 = require("node:fs");
20
20
  const node_path_1 = require("node:path");
21
+ const edit_distance_js_1 = require("./edit-distance.js");
22
+ Object.defineProperty(exports, "editDistance", { enumerable: true, get: function () { return edit_distance_js_1.editDistance; } });
21
23
  const node_child_process_1 = require("node:child_process");
22
24
  const node_module_1 = require("node:module");
23
25
  const glob_1 = require("glob");
@@ -378,38 +380,11 @@ function ruleFileExists(ruleName, rulesDir, basePath) {
378
380
  function makeResult(ctx, exists, enabled = "unknown", error) {
379
381
  return { exists, enabled, linter: ctx.linterName, rule: ctx.ruleName, error };
380
382
  }
381
- /**
382
- * Levenshtein distance for short-string typo detection. Rule names are
383
- * short so edit distance is more appropriate than NCD (which is tuned
384
- * for longer texts).
385
- */
386
- function editDistance(a, b) {
387
- if (a === b)
388
- return 0;
389
- const m = a.length;
390
- const n = b.length;
391
- if (m === 0)
392
- return n;
393
- if (n === 0)
394
- return m;
395
- const dp = Array.from({ length: n + 1 }, (_, i) => i);
396
- for (let i = 1; i <= m; i++) {
397
- let prev = dp[0];
398
- dp[0] = i;
399
- for (let j = 1; j <= n; j++) {
400
- const tmp = dp[j];
401
- dp[j] =
402
- a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
403
- prev = tmp;
404
- }
405
- }
406
- return dp[n];
407
- }
408
383
  /** Top-N closest rule names by edit distance, filtered by a max distance. */
409
384
  function closestRuleNames(target, candidates, limit = 3, maxDistance = 4) {
410
385
  const scored = [];
411
386
  for (const c of candidates) {
412
- const d = editDistance(target, c);
387
+ const d = (0, edit_distance_js_1.editDistance)(target, c);
413
388
  if (d <= maxDistance)
414
389
  scored.push({ name: c, dist: d });
415
390
  }
@@ -4,7 +4,7 @@ exports.closestTool = closestTool;
4
4
  exports.confidentToolIssues = confidentToolIssues;
5
5
  exports.disallowedToolIssues = disallowedToolIssues;
6
6
  exports.verifyToolContract = verifyToolContract;
7
- const linters_js_1 = require("./linters.js");
7
+ const edit_distance_js_1 = require("./edit-distance.js");
8
8
  /**
9
9
  * Closest known built-in tool by edit distance (≤ 2), for a "did you mean" hint.
10
10
  * The ≤ 2 bound is deliberately tight: a suggestion is a CONFIDENCE signal (this
@@ -15,7 +15,7 @@ function closestTool(tool, dialect) {
15
15
  let best = null;
16
16
  let bestDistance = Infinity;
17
17
  for (const known of dialect.builtinAgentTools) {
18
- const d = (0, linters_js_1.editDistance)(tool.toLowerCase(), known.toLowerCase());
18
+ const d = (0, edit_distance_js_1.editDistance)(tool.toLowerCase(), known.toLowerCase());
19
19
  if (d < bestDistance) {
20
20
  bestDistance = d;
21
21
  best = known;
@@ -121,7 +121,7 @@ function reportDeductions(r) {
121
121
  {
122
122
  n: deadTools,
123
123
  weight: exports.W_DANGLING_REF,
124
- label: "agent tool(s) that don't exist (typo / never-available)",
124
+ label: "unavailable agent tool(s) (typo / never-available)",
125
125
  },
126
126
  {
127
127
  n: deadMcpTools,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigiles",
3
- "version": "14.6.7",
3
+ "version": "14.7.0",
4
4
  "description": "Lint & test the harness your AI agent runs on — verify the references in your CLAUDE.md / AGENTS.md and test that your hooks and skills actually work.",
5
5
  "keywords": [
6
6
  "claude-code",