vigiles 7.0.0 → 9.0.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 +207 -88
- package/dist/adoptability.d.ts +55 -0
- package/dist/adoptability.js +196 -0
- package/dist/audit-html.d.ts +20 -0
- package/dist/audit-html.js +61 -0
- package/dist/audit-prompts.d.ts +46 -0
- package/dist/audit-prompts.js +90 -0
- package/dist/audit-report.d.ts +70 -0
- package/dist/audit-report.js +51 -0
- package/dist/audit-report.template.html +110 -0
- package/dist/audit-score.d.ts +44 -0
- package/dist/audit-score.js +221 -0
- package/dist/cli-commands.d.ts +1 -1
- package/dist/cli-commands.js +3 -7
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +749 -180
- package/dist/core/adopt.d.ts +65 -0
- package/dist/core/adopt.js +199 -0
- package/dist/core/compose.d.ts +1 -1
- package/dist/core/compose.js +1 -1
- package/dist/core/evolve.d.ts +4 -0
- package/dist/core/evolve.js +4 -0
- package/dist/core/frontmatter.d.ts +8 -7
- package/dist/core/frontmatter.js +8 -7
- package/dist/core/generate-harness.d.ts +1 -1
- package/dist/core/generate-harness.js +3 -3
- package/dist/core/generate-schema.js +1 -1
- package/dist/core/inline.d.ts +6 -6
- package/dist/core/inline.js +17 -7
- package/dist/core/integrity.d.ts +31 -0
- package/dist/core/integrity.js +45 -0
- package/dist/core/orphans.js +1 -1
- package/dist/core/spec.d.ts +40 -2
- package/dist/core/spec.js +16 -1
- package/dist/core/types.d.ts +42 -6
- package/dist/core/validate.js +26 -26
- package/dist/dialect-drift.js +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/guardrail-check.d.ts +1 -1
- package/dist/guardrail-check.js +1 -1
- package/dist/optimize.d.ts +12 -5
- package/dist/optimize.js +27 -5
- package/dist/scan-behavioral.d.ts +8 -2
- package/dist/scan-behavioral.js +6 -4
- package/dist/scan-trigger-suggest.d.ts +91 -0
- package/dist/scan-trigger-suggest.js +103 -0
- package/dist/scan.d.ts +53 -12
- package/dist/scan.js +92 -16
- package/dist/score-explainer.d.ts +1 -1
- package/dist/setup-plan.d.ts +59 -1
- package/dist/setup-plan.js +103 -5
- package/hooks/post-edit.sh +1 -1
- package/package.json +4 -2
- package/skills/adopt-spec/SKILL.md +7 -7
- package/skills/linter-docs/eslint.md +1 -1
- package/skills/strengthen/SKILL.md +1 -1
- package/skills/test-harness/SKILL.md +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AuditReport } from "./audit-report.js";
|
|
2
|
+
/**
|
|
3
|
+
* Candidate locations for the built template, relative to this module (`__dirname`
|
|
4
|
+
* is the compiled `dist/` at runtime, or `src/` under vitest). CommonJS output, so
|
|
5
|
+
* we use `__dirname`, not `import.meta`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function templatePath(): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Inject the report JSON into a template by replacing the quoted placeholder
|
|
10
|
+
* string with the JSON object literal. Pure — the testable core. Throws if the
|
|
11
|
+
* template is missing the placeholder.
|
|
12
|
+
*/
|
|
13
|
+
export declare function injectReportData(template: string, report: AuditReport): string;
|
|
14
|
+
/**
|
|
15
|
+
* Render the self-contained HTML report (React template + injected data). Throws
|
|
16
|
+
* if the template hasn't been built — the caller (writeAuditHtml) catches that and
|
|
17
|
+
* skips the HTML, since the JSON + terminal report don't depend on it.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderAuditHtml(report: AuditReport): string;
|
|
20
|
+
//# sourceMappingURL=audit-html.d.ts.map
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.templatePath = templatePath;
|
|
4
|
+
exports.injectReportData = injectReportData;
|
|
5
|
+
exports.renderAuditHtml = renderAuditHtml;
|
|
6
|
+
/**
|
|
7
|
+
* The shareable HTML audit report — the prebuilt **Vite + React + shadcn** template
|
|
8
|
+
* (`report/`, built to one self-contained file at `dist/audit-report.template.html`)
|
|
9
|
+
* with the {@link AuditReport} JSON injected. The React app runs in the reader's
|
|
10
|
+
* browser, so the CLI stays runtime-dependency-light and the output is still a
|
|
11
|
+
* single offline file. There is ONE renderer (pure shadcn/Tailwind) — no inline-CSS
|
|
12
|
+
* fallback; the build guarantees the template exists, and if it somehow doesn't the
|
|
13
|
+
* caller skips the HTML (the JSON + terminal report still work).
|
|
14
|
+
*
|
|
15
|
+
* `<`/`>`/`&` are escaped on injection so report text can never break out of the
|
|
16
|
+
* `<script>`. `injectReportData` is the pure, testable core.
|
|
17
|
+
*/
|
|
18
|
+
const node_fs_1 = require("node:fs");
|
|
19
|
+
const node_path_1 = require("node:path");
|
|
20
|
+
const PLACEHOLDER = "__VIGILES_DATA_PLACEHOLDER__";
|
|
21
|
+
/**
|
|
22
|
+
* Candidate locations for the built template, relative to this module (`__dirname`
|
|
23
|
+
* is the compiled `dist/` at runtime, or `src/` under vitest). CommonJS output, so
|
|
24
|
+
* we use `__dirname`, not `import.meta`.
|
|
25
|
+
*/
|
|
26
|
+
function templatePath() {
|
|
27
|
+
const candidates = [
|
|
28
|
+
(0, node_path_1.resolve)(__dirname, "audit-report.template.html"), // dist/ (shipped)
|
|
29
|
+
(0, node_path_1.resolve)(__dirname, "..", "dist", "audit-report.template.html"), // src/ under vitest
|
|
30
|
+
];
|
|
31
|
+
return candidates.find((p) => (0, node_fs_1.existsSync)(p)) ?? null;
|
|
32
|
+
}
|
|
33
|
+
/** Escape `<`, `>`, `&` so report text can never break out of the `<script>`. */
|
|
34
|
+
function escapeForScript(json) {
|
|
35
|
+
return json.replace(/[<>&]/g, (ch) => "\\u00" + ch.charCodeAt(0).toString(16).padStart(2, "0"));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Inject the report JSON into a template by replacing the quoted placeholder
|
|
39
|
+
* string with the JSON object literal. Pure — the testable core. Throws if the
|
|
40
|
+
* template is missing the placeholder.
|
|
41
|
+
*/
|
|
42
|
+
function injectReportData(template, report) {
|
|
43
|
+
const re = new RegExp(`(["'])${PLACEHOLDER}\\1`);
|
|
44
|
+
if (!re.test(template)) {
|
|
45
|
+
throw new Error("audit report template is missing the data placeholder");
|
|
46
|
+
}
|
|
47
|
+
return template.replace(re, escapeForScript(JSON.stringify(report)));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Render the self-contained HTML report (React template + injected data). Throws
|
|
51
|
+
* if the template hasn't been built — the caller (writeAuditHtml) catches that and
|
|
52
|
+
* skips the HTML, since the JSON + terminal report don't depend on it.
|
|
53
|
+
*/
|
|
54
|
+
function renderAuditHtml(report) {
|
|
55
|
+
const p = templatePath();
|
|
56
|
+
if (!p) {
|
|
57
|
+
throw new Error("audit report template not built — run `npm run build` (builds report/), or use --json / --no-html");
|
|
58
|
+
}
|
|
59
|
+
return injectReportData((0, node_fs_1.readFileSync)(p, "utf-8"), report);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=audit-html.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generated trigger probes for `vigiles audit`'s model trigger tier.
|
|
3
|
+
*
|
|
4
|
+
* The trigger-rate eval needs a per-skill prompt set (does the description FIRE?
|
|
5
|
+
* — recall + precision). Authoring that set by hand was the friction that made
|
|
6
|
+
* the eval un-wowable. The trigger tier removes it: derive a small, DIVERSE probe
|
|
7
|
+
* set from each skill's own description — zero setup. `--prompts=<file>` still
|
|
8
|
+
* overrides for a rigorous, curated benchmark.
|
|
9
|
+
*
|
|
10
|
+
* Deterministic by design (no model needed to AUTHOR the probes — the model is
|
|
11
|
+
* spent RUNNING them). The trick that clears the diversity gate: extract a SHORT
|
|
12
|
+
* topic from the description (so the shared text stays small relative to the
|
|
13
|
+
* frame) and wrap it in lexically-distant frames. Measured min pairwise NCD
|
|
14
|
+
* ~0.27 across short/long descriptions — comfortably above {@link AUTO_MIN_DISTANCE}.
|
|
15
|
+
*/
|
|
16
|
+
import type { TriggerPromptSet } from "./scan-behavioral.js";
|
|
17
|
+
export interface PromptSkill {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly description: string;
|
|
20
|
+
}
|
|
21
|
+
/** How many recall probes we generate per skill (each a distinct frame). */
|
|
22
|
+
export declare const AUTO_RECALL_COUNT = 6;
|
|
23
|
+
/**
|
|
24
|
+
* The diversity floor for AUTO probes — relaxed from the default 0.3 because a
|
|
25
|
+
* templated-but-varied machine probe legitimately shares a topic phrase (the
|
|
26
|
+
* generator's measured min is ~0.27). Still well above 0 → genuine copy-paste
|
|
27
|
+
* is caught; the gate's "vary the phrasing" advice is for hand-authored sets.
|
|
28
|
+
*/
|
|
29
|
+
export declare const AUTO_MIN_DISTANCE = 0.2;
|
|
30
|
+
/**
|
|
31
|
+
* Extract a short, action-shaped topic from a description: drop boilerplate
|
|
32
|
+
* lead-ins ("A skill that…", "Use this skill to…"), take the first clause, cap
|
|
33
|
+
* at 8 words. Capping is load-bearing — a long verbatim topic makes the frames
|
|
34
|
+
* too similar (NCD collapses below the gate).
|
|
35
|
+
*/
|
|
36
|
+
export declare function topicOf(description: string): string;
|
|
37
|
+
/** Recall probes for one skill: distinct frames around its extracted topic. */
|
|
38
|
+
export declare function recallPrompts(description: string, count?: number): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Build a {@link TriggerPromptSet} from skill descriptions — zero-setup trigger
|
|
41
|
+
* probes. Each skill gets `recallPrompts` derived from its description plus the
|
|
42
|
+
* shared irrelevant bank for precision. Skills with an empty description are
|
|
43
|
+
* skipped (nothing to derive a topic from).
|
|
44
|
+
*/
|
|
45
|
+
export declare function autoTriggerPrompts(skills: readonly PromptSkill[], count?: number): TriggerPromptSet;
|
|
46
|
+
//# sourceMappingURL=audit-prompts.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUTO_MIN_DISTANCE = exports.AUTO_RECALL_COUNT = void 0;
|
|
4
|
+
exports.topicOf = topicOf;
|
|
5
|
+
exports.recallPrompts = recallPrompts;
|
|
6
|
+
exports.autoTriggerPrompts = autoTriggerPrompts;
|
|
7
|
+
/** How many recall probes we generate per skill (each a distinct frame). */
|
|
8
|
+
exports.AUTO_RECALL_COUNT = 6;
|
|
9
|
+
/**
|
|
10
|
+
* The diversity floor for AUTO probes — relaxed from the default 0.3 because a
|
|
11
|
+
* templated-but-varied machine probe legitimately shares a topic phrase (the
|
|
12
|
+
* generator's measured min is ~0.27). Still well above 0 → genuine copy-paste
|
|
13
|
+
* is caught; the gate's "vary the phrasing" advice is for hand-authored sets.
|
|
14
|
+
*/
|
|
15
|
+
exports.AUTO_MIN_DISTANCE = 0.2;
|
|
16
|
+
// Lexically-distant frames around a short topic. Order matters: the first N are
|
|
17
|
+
// used, and they're arranged so any prefix stays diverse (verified in the test).
|
|
18
|
+
const RECALL_FRAMES = [
|
|
19
|
+
(t) => `I need help to ${t} in my project right now.`,
|
|
20
|
+
(t) => `How do I ${t}? Walk me through the steps.`,
|
|
21
|
+
(t) => `Please ${t} before I open this pull request.`,
|
|
22
|
+
(t) => `What's the recommended way to ${t} on a large team?`,
|
|
23
|
+
(t) => `Can you take a look and ${t} for me?`,
|
|
24
|
+
(t) => `My task today: ${t} across the whole repo.`,
|
|
25
|
+
(t) => `Is there a tool that will ${t} automatically?`,
|
|
26
|
+
(t) => `Give me a checklist to ${t} thoroughly.`,
|
|
27
|
+
];
|
|
28
|
+
// Unrelated requests for the precision arm — varied, clearly off-topic, so a
|
|
29
|
+
// well-scoped skill should NOT fire on them (a too-broad description that hijacks
|
|
30
|
+
// these fails precision). Generic on purpose, distant from any one skill's topic.
|
|
31
|
+
// Count is load-bearing: the auto trigger tier applies the diversity gate's
|
|
32
|
+
// `minPrompts` floor (= AUTO_RECALL_COUNT) to BOTH arms, so the bank must hold at
|
|
33
|
+
// least AUTO_RECALL_COUNT entries or the precision arm fails preflight and every
|
|
34
|
+
// skill reports "unmeasured" instead of running.
|
|
35
|
+
const IRRELEVANT_BANK = [
|
|
36
|
+
"What's the weather forecast for Tokyo this weekend?",
|
|
37
|
+
"Summarize the plot of Hamlet in two sentences.",
|
|
38
|
+
"Convert 100 US dollars to euros at today's rate.",
|
|
39
|
+
"Recommend a good pasta recipe for dinner tonight.",
|
|
40
|
+
"Who won the most Olympic gold medals in swimming?",
|
|
41
|
+
"Explain how photosynthesis works in plants.",
|
|
42
|
+
"Suggest a weekend hiking trail near Seattle.",
|
|
43
|
+
];
|
|
44
|
+
// Boilerplate lead-in words that carry no topical signal (skill descriptions
|
|
45
|
+
// open with a verb — "Reviews…", "Generate…" — so stripping these from the front
|
|
46
|
+
// never eats the real action). Applied iteratively until a content word remains.
|
|
47
|
+
const LEAD_WORD = /^(a|an|the|this|use|skill|agent|tool|command|helper|that|which|to|for|when|invoked?|invoke|used?|helps?|you|with)\b[\s,:-]*/i;
|
|
48
|
+
/**
|
|
49
|
+
* Extract a short, action-shaped topic from a description: drop boilerplate
|
|
50
|
+
* lead-ins ("A skill that…", "Use this skill to…"), take the first clause, cap
|
|
51
|
+
* at 8 words. Capping is load-bearing — a long verbatim topic makes the frames
|
|
52
|
+
* too similar (NCD collapses below the gate).
|
|
53
|
+
*/
|
|
54
|
+
function topicOf(description) {
|
|
55
|
+
let t = description.trim().toLowerCase();
|
|
56
|
+
let prev = "";
|
|
57
|
+
while (t !== prev) {
|
|
58
|
+
prev = t;
|
|
59
|
+
t = t.replace(LEAD_WORD, "");
|
|
60
|
+
}
|
|
61
|
+
const firstClause = t.split(/[.,;:!?]/)[0].trim();
|
|
62
|
+
const words = firstClause.split(/\s+/).filter(Boolean).slice(0, 8);
|
|
63
|
+
const topic = words.join(" ");
|
|
64
|
+
// Fall back to the raw (capped, lowercased) description if stripping left nothing.
|
|
65
|
+
return (topic || description.trim().toLowerCase().split(/\s+/).slice(0, 8).join(" "));
|
|
66
|
+
}
|
|
67
|
+
/** Recall probes for one skill: distinct frames around its extracted topic. */
|
|
68
|
+
function recallPrompts(description, count = exports.AUTO_RECALL_COUNT) {
|
|
69
|
+
const topic = topicOf(description);
|
|
70
|
+
return RECALL_FRAMES.slice(0, count).map((frame) => frame(topic));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a {@link TriggerPromptSet} from skill descriptions — zero-setup trigger
|
|
74
|
+
* probes. Each skill gets `recallPrompts` derived from its description plus the
|
|
75
|
+
* shared irrelevant bank for precision. Skills with an empty description are
|
|
76
|
+
* skipped (nothing to derive a topic from).
|
|
77
|
+
*/
|
|
78
|
+
function autoTriggerPrompts(skills, count = exports.AUTO_RECALL_COUNT) {
|
|
79
|
+
const set = {};
|
|
80
|
+
for (const s of skills) {
|
|
81
|
+
if (!s.description.trim())
|
|
82
|
+
continue;
|
|
83
|
+
set[s.name] = {
|
|
84
|
+
prompts: recallPrompts(s.description, count),
|
|
85
|
+
irrelevant: [...IRRELEVANT_BANK],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return set;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=audit-prompts.js.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `AuditReport` — the versioned JSON contract that IS the audit's product
|
|
3
|
+
* boundary. Everything renders FROM it: the local self-contained HTML report,
|
|
4
|
+
* `audit --json` for CI, and (later) an upload to a hosted dashboard. Because it's
|
|
5
|
+
* the wire format between the CLI and anything downstream, it is VERSIONED
|
|
6
|
+
* (`meta.schemaVersion`) and stable — additive changes only within a version.
|
|
7
|
+
*
|
|
8
|
+
* Pure: `buildAuditReport` assembles the report from the same deterministic pieces
|
|
9
|
+
* the terminal output uses (`auditScore` + `optimize` + the scan inventory) — no
|
|
10
|
+
* re-detection (one-detector-no-drift), no model, no clock (a `generatedAt`
|
|
11
|
+
* timestamp is attached by the CLI at write time, never by this pure builder, so
|
|
12
|
+
* the embedded-in-HTML form stays deterministic).
|
|
13
|
+
*/
|
|
14
|
+
import { type AuditScore } from "./audit-score.js";
|
|
15
|
+
import { type Recommendation } from "./optimize.js";
|
|
16
|
+
import type { AdoptabilityResult } from "./adoptability.js";
|
|
17
|
+
import type { ScanReport } from "./scan.js";
|
|
18
|
+
/** The current schema version. Bump only on a BREAKING change to the shape. */
|
|
19
|
+
export declare const AUDIT_SCHEMA_VERSION = 1;
|
|
20
|
+
export interface AuditReportMeta {
|
|
21
|
+
/** Wire-format version — consumers gate on this. */
|
|
22
|
+
readonly schemaVersion: typeof AUDIT_SCHEMA_VERSION;
|
|
23
|
+
readonly tool: "vigiles";
|
|
24
|
+
/** The vigiles version that produced the report. */
|
|
25
|
+
readonly vigilesVersion: string;
|
|
26
|
+
/** The detected/selected harness (`claude-code`, `codex`, …). */
|
|
27
|
+
readonly harness: string;
|
|
28
|
+
/** The audited directory. */
|
|
29
|
+
readonly dir: string;
|
|
30
|
+
/** ISO-8601 produced-at stamp — set by the CLI at write time (NOT the pure builder). */
|
|
31
|
+
readonly generatedAt?: string;
|
|
32
|
+
}
|
|
33
|
+
/** What the harness ships — the "inventory" surface counts. */
|
|
34
|
+
export interface AuditInventory {
|
|
35
|
+
readonly skills: number;
|
|
36
|
+
readonly agents: number;
|
|
37
|
+
readonly hooks: number;
|
|
38
|
+
readonly commands: number;
|
|
39
|
+
readonly mcp: boolean;
|
|
40
|
+
readonly untested: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The full audit, as the dashboard / CI / HTML all consume it. Self-describing
|
|
44
|
+
* and versioned; additive-only within a `schemaVersion`.
|
|
45
|
+
*/
|
|
46
|
+
export interface AuditReport {
|
|
47
|
+
readonly meta: AuditReportMeta;
|
|
48
|
+
/** The four deterministic category rings + the weighted overall + grade. */
|
|
49
|
+
readonly score: AuditScore;
|
|
50
|
+
/** The deterministic, ranked fixes (the inline recommendations). */
|
|
51
|
+
readonly recommendations: readonly Recommendation[];
|
|
52
|
+
readonly inventory: AuditInventory;
|
|
53
|
+
/**
|
|
54
|
+
* The adoption preview — "what would vigiles catch in your repo?" Present only
|
|
55
|
+
* when the model-gated tier ran (behind consent); a deterministic read omits it.
|
|
56
|
+
* Additive/optional, so the schema version is unchanged.
|
|
57
|
+
*/
|
|
58
|
+
readonly adoptability?: AdoptabilityResult;
|
|
59
|
+
}
|
|
60
|
+
export interface BuildAuditReportOptions {
|
|
61
|
+
readonly harness: string;
|
|
62
|
+
readonly vigilesVersion: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Assemble the versioned {@link AuditReport} from a scan report — pure, no clock.
|
|
66
|
+
* The CLI attaches `meta.generatedAt` when it writes the JSON artifact; the
|
|
67
|
+
* HTML-embedded form omits it so the rendered file stays deterministic.
|
|
68
|
+
*/
|
|
69
|
+
export declare function buildAuditReport(report: ScanReport, opts: BuildAuditReportOptions): AuditReport;
|
|
70
|
+
//# sourceMappingURL=audit-report.d.ts.map
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AUDIT_SCHEMA_VERSION = void 0;
|
|
4
|
+
exports.buildAuditReport = buildAuditReport;
|
|
5
|
+
/**
|
|
6
|
+
* The `AuditReport` — the versioned JSON contract that IS the audit's product
|
|
7
|
+
* boundary. Everything renders FROM it: the local self-contained HTML report,
|
|
8
|
+
* `audit --json` for CI, and (later) an upload to a hosted dashboard. Because it's
|
|
9
|
+
* the wire format between the CLI and anything downstream, it is VERSIONED
|
|
10
|
+
* (`meta.schemaVersion`) and stable — additive changes only within a version.
|
|
11
|
+
*
|
|
12
|
+
* Pure: `buildAuditReport` assembles the report from the same deterministic pieces
|
|
13
|
+
* the terminal output uses (`auditScore` + `optimize` + the scan inventory) — no
|
|
14
|
+
* re-detection (one-detector-no-drift), no model, no clock (a `generatedAt`
|
|
15
|
+
* timestamp is attached by the CLI at write time, never by this pure builder, so
|
|
16
|
+
* the embedded-in-HTML form stays deterministic).
|
|
17
|
+
*/
|
|
18
|
+
const audit_score_js_1 = require("./audit-score.js");
|
|
19
|
+
const optimize_js_1 = require("./optimize.js");
|
|
20
|
+
/** The current schema version. Bump only on a BREAKING change to the shape. */
|
|
21
|
+
exports.AUDIT_SCHEMA_VERSION = 1;
|
|
22
|
+
/**
|
|
23
|
+
* Assemble the versioned {@link AuditReport} from a scan report — pure, no clock.
|
|
24
|
+
* The CLI attaches `meta.generatedAt` when it writes the JSON artifact; the
|
|
25
|
+
* HTML-embedded form omits it so the rendered file stays deterministic.
|
|
26
|
+
*/
|
|
27
|
+
function buildAuditReport(report, opts) {
|
|
28
|
+
return {
|
|
29
|
+
meta: {
|
|
30
|
+
schemaVersion: exports.AUDIT_SCHEMA_VERSION,
|
|
31
|
+
tool: "vigiles",
|
|
32
|
+
vigilesVersion: opts.vigilesVersion,
|
|
33
|
+
harness: opts.harness,
|
|
34
|
+
dir: report.dir,
|
|
35
|
+
},
|
|
36
|
+
score: (0, audit_score_js_1.auditScore)(report),
|
|
37
|
+
recommendations: (0, optimize_js_1.optimize)(report).recommendations,
|
|
38
|
+
inventory: {
|
|
39
|
+
skills: report.skills.length,
|
|
40
|
+
agents: report.agents.length,
|
|
41
|
+
// All hooks, file-backed + inline — matches formatScanReport and the
|
|
42
|
+
// emptiness/scoring count, so a JSON/HTML "What it ships" never reports 0
|
|
43
|
+
// hooks for an inline-hook-only harness.
|
|
44
|
+
hooks: report.hooks.length + report.inlineHooks,
|
|
45
|
+
commands: report.commands,
|
|
46
|
+
mcp: report.mcp,
|
|
47
|
+
untested: report.untested,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=audit-report.js.map
|