vdelta 0.1.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/LICENSE +21 -0
- package/README.md +171 -0
- package/dist/adapters/vitest/capture.d.ts +50 -0
- package/dist/adapters/vitest/capture.js +7 -0
- package/dist/adapters/vitest/capture.js.map +1 -0
- package/dist/adapters/vitest/recorder.d.ts +31 -0
- package/dist/adapters/vitest/recorder.js +214 -0
- package/dist/adapters/vitest/recorder.js.map +1 -0
- package/dist/adapters/vitest/reporter.d.ts +15 -0
- package/dist/adapters/vitest/reporter.js +97 -0
- package/dist/adapters/vitest/reporter.js.map +1 -0
- package/dist/canonical.d.ts +9 -0
- package/dist/canonical.js +45 -0
- package/dist/canonical.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +264 -0
- package/dist/cli.js.map +1 -0
- package/dist/compare.d.ts +37 -0
- package/dist/compare.js +476 -0
- package/dist/compare.js.map +1 -0
- package/dist/digest.d.ts +5 -0
- package/dist/digest.js +14 -0
- package/dist/digest.js.map +1 -0
- package/dist/gate.d.ts +11 -0
- package/dist/gate.js +135 -0
- package/dist/gate.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/redact.d.ts +10 -0
- package/dist/redact.js +49 -0
- package/dist/redact.js.map +1 -0
- package/dist/render.d.ts +6 -0
- package/dist/render.js +53 -0
- package/dist/render.js.map +1 -0
- package/dist/run.d.ts +19 -0
- package/dist/run.js +158 -0
- package/dist/run.js.map +1 -0
- package/dist/schema.d.ts +236 -0
- package/dist/schema.js +395 -0
- package/dist/schema.js.map +1 -0
- package/dist/store.d.ts +38 -0
- package/dist/store.js +161 -0
- package/dist/store.js.map +1 -0
- package/dist/tree-digest.d.ts +11 -0
- package/dist/tree-digest.js +103 -0
- package/dist/tree-digest.js.map +1 -0
- package/package.json +53 -0
- package/spec/veridelta-1.md +1093 -0
package/dist/gate.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate (spec §11), MVP scope: report-only policy. Record integrity (INV-10)
|
|
3
|
+
* via content-address recomputation; staleness (INV-11) via exact
|
|
4
|
+
* tree_digest equality with the judged workspace — binary equality, no
|
|
5
|
+
* proximity rescue. Local-store verdicts are always advisory (§11.2).
|
|
6
|
+
*/
|
|
7
|
+
import { buildComparisonReport } from './compare.js';
|
|
8
|
+
import { gitHead, resolveRef, treeDigest } from './tree-digest.js';
|
|
9
|
+
import { StoreCorruptError } from './store.js';
|
|
10
|
+
import { SCHEMA_VERSION, } from './schema.js';
|
|
11
|
+
import { COMPOSITION_ID, DEGRADED_CAPABILITIES } from './adapters/vitest/recorder.js';
|
|
12
|
+
export class GateOperationError extends Error {
|
|
13
|
+
constructor(message) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'GateOperationError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function buildGateReport(store, opts) {
|
|
19
|
+
const resolved = await resolveRef(opts.worktree, opts.ref);
|
|
20
|
+
if (resolved === null) {
|
|
21
|
+
throw new GateOperationError(`cannot resolve ref: ${opts.ref}`);
|
|
22
|
+
}
|
|
23
|
+
const currentId = opts.runId !== undefined ? store.resolveRunId(opts.runId) : store.lastRunId();
|
|
24
|
+
if (currentId === null) {
|
|
25
|
+
throw new GateOperationError(opts.runId !== undefined ? `unknown run id: ${opts.runId}` : 'no recorded run to gate');
|
|
26
|
+
}
|
|
27
|
+
const headSha = (await gitHead(opts.worktree)) ?? '';
|
|
28
|
+
const targetTree = await treeDigest(opts.worktree);
|
|
29
|
+
// INV-10: verify the consulted record's content address before judging.
|
|
30
|
+
let integrityOk;
|
|
31
|
+
let runTree = '';
|
|
32
|
+
try {
|
|
33
|
+
integrityOk = store.verifyIntegrity(currentId);
|
|
34
|
+
runTree = store.readRun(currentId).provenance.tree_digest;
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
if (err instanceof StoreCorruptError) {
|
|
38
|
+
integrityOk = false;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!integrityOk) {
|
|
45
|
+
return integrityFailedReport(currentId, {
|
|
46
|
+
headSha,
|
|
47
|
+
baseSha: resolved.commit,
|
|
48
|
+
runTree,
|
|
49
|
+
targetTree,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const spec = {
|
|
53
|
+
mode: 'git-ref',
|
|
54
|
+
ref: opts.ref,
|
|
55
|
+
commit: resolved.commit,
|
|
56
|
+
tree: resolved.tree,
|
|
57
|
+
};
|
|
58
|
+
const report = buildComparisonReport(store, currentId, spec);
|
|
59
|
+
// INV-11: the judged target is the workspace tree, compared byte-exactly.
|
|
60
|
+
const stalenessMatch = runTree === targetTree;
|
|
61
|
+
const triggered = [];
|
|
62
|
+
if (report.transitions !== undefined) {
|
|
63
|
+
if (report.transitions.new_fail.length > 0)
|
|
64
|
+
triggered.push('new_fail');
|
|
65
|
+
if (report.transitions.updated_fail.length > 0)
|
|
66
|
+
triggered.push('updated_fail');
|
|
67
|
+
}
|
|
68
|
+
if (report.verification_surface?.status === 'reduced') {
|
|
69
|
+
triggered.push('verification_surface_reduced');
|
|
70
|
+
}
|
|
71
|
+
let verdict;
|
|
72
|
+
if (!stalenessMatch) {
|
|
73
|
+
verdict = 'inconclusive';
|
|
74
|
+
}
|
|
75
|
+
else if (report.comparability === 'none' || report.comparability === 'partial') {
|
|
76
|
+
verdict = 'inconclusive';
|
|
77
|
+
}
|
|
78
|
+
else if (triggered.length > 0) {
|
|
79
|
+
verdict = 'fail';
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
verdict = 'pass';
|
|
83
|
+
}
|
|
84
|
+
const gate = {
|
|
85
|
+
policy: 'report-only',
|
|
86
|
+
verdict,
|
|
87
|
+
triggered,
|
|
88
|
+
target: { kind: 'head', head_sha: headSha, base_sha: resolved.commit },
|
|
89
|
+
staleness: {
|
|
90
|
+
run_tree_digest: runTree,
|
|
91
|
+
target_tree_digest: targetTree,
|
|
92
|
+
match: stalenessMatch,
|
|
93
|
+
unverified_submodules: [],
|
|
94
|
+
},
|
|
95
|
+
record_integrity: 'advisory',
|
|
96
|
+
};
|
|
97
|
+
return { ...report, gate };
|
|
98
|
+
}
|
|
99
|
+
function integrityFailedReport(currentId, ctx) {
|
|
100
|
+
// The record cannot be trusted: no red list, no transitions — only the
|
|
101
|
+
// structural failure (§11.2). Reporting floor still discloses the anchor.
|
|
102
|
+
return {
|
|
103
|
+
schema_version: SCHEMA_VERSION,
|
|
104
|
+
outcome_verdict: 'inconclusive',
|
|
105
|
+
comparability: 'none',
|
|
106
|
+
comparability_detail: { reason: 'record-integrity-failed', kind: 'failed' },
|
|
107
|
+
baseline: null,
|
|
108
|
+
current: {
|
|
109
|
+
run_id: currentId,
|
|
110
|
+
complete: false,
|
|
111
|
+
child_exit_code: -1,
|
|
112
|
+
},
|
|
113
|
+
observation_coverage: { current: '0/0' },
|
|
114
|
+
failure_evidence: {
|
|
115
|
+
composition_id: COMPOSITION_ID,
|
|
116
|
+
degraded_capabilities: [...DEGRADED_CAPABILITIES],
|
|
117
|
+
},
|
|
118
|
+
trust: { record_integrity: 'advisory' },
|
|
119
|
+
anchors: { raw: `vdelta show ${currentId.slice(0, 12)} --raw` },
|
|
120
|
+
gate: {
|
|
121
|
+
policy: 'report-only',
|
|
122
|
+
verdict: 'inconclusive',
|
|
123
|
+
triggered: [],
|
|
124
|
+
target: { kind: 'head', head_sha: ctx.headSha, base_sha: ctx.baseSha },
|
|
125
|
+
staleness: {
|
|
126
|
+
run_tree_digest: ctx.runTree,
|
|
127
|
+
target_tree_digest: ctx.targetTree,
|
|
128
|
+
match: ctx.runTree === ctx.targetTree,
|
|
129
|
+
unverified_submodules: [],
|
|
130
|
+
},
|
|
131
|
+
record_integrity: 'advisory',
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=gate.js.map
|
package/dist/gate.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vdelta — reference implementation of veridelta/1.
|
|
3
|
+
* Public API surface: consumer parsers (§9.4), the comparator, the store,
|
|
4
|
+
* and the vitest adapter pieces.
|
|
5
|
+
*/
|
|
6
|
+
export { parseReport, parseRunRecord, SchemaViolationError, SCHEMA_VERSION, VERDICTS, COMPARABILITIES, NONE_REASONS, OUTCOME_VERDICTS, SURFACE_STATUSES, SURFACE_EVENT_KINDS, type ComparisonReport, type RunRecord, type TestObservation, type FailureFinding, type Verdict, type Comparability, } from './schema.js';
|
|
7
|
+
export { RunStore, StoreCorruptError, LockHeldError, computeRunId } from './store.js';
|
|
8
|
+
export { buildComparisonReport, resolveBaseline, streamKey, type BaselineSpec } from './compare.js';
|
|
9
|
+
export { buildGateReport, type GateOptions } from './gate.js';
|
|
10
|
+
export { treeDigest } from './tree-digest.js';
|
|
11
|
+
export { canonicalJson } from './canonical.js';
|
|
12
|
+
export { redactText, redactValue } from './redact.js';
|
|
13
|
+
export { renderReport } from './render.js';
|
|
14
|
+
export { buildRunRecord, COMPOSITION_ID, DEGRADED_CAPABILITIES, ADAPTER_NAME, } from './adapters/vitest/recorder.js';
|
|
15
|
+
export { VDELTA_VERSION } from './run.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vdelta — reference implementation of veridelta/1.
|
|
3
|
+
* Public API surface: consumer parsers (§9.4), the comparator, the store,
|
|
4
|
+
* and the vitest adapter pieces.
|
|
5
|
+
*/
|
|
6
|
+
export { parseReport, parseRunRecord, SchemaViolationError, SCHEMA_VERSION, VERDICTS, COMPARABILITIES, NONE_REASONS, OUTCOME_VERDICTS, SURFACE_STATUSES, SURFACE_EVENT_KINDS, } from './schema.js';
|
|
7
|
+
export { RunStore, StoreCorruptError, LockHeldError, computeRunId } from './store.js';
|
|
8
|
+
export { buildComparisonReport, resolveBaseline, streamKey } from './compare.js';
|
|
9
|
+
export { buildGateReport } from './gate.js';
|
|
10
|
+
export { treeDigest } from './tree-digest.js';
|
|
11
|
+
export { canonicalJson } from './canonical.js';
|
|
12
|
+
export { redactText, redactValue } from './redact.js';
|
|
13
|
+
export { renderReport } from './render.js';
|
|
14
|
+
export { buildRunRecord, COMPOSITION_ID, DEGRADED_CAPABILITIES, ADAPTER_NAME, } from './adapters/vitest/recorder.js';
|
|
15
|
+
export { VDELTA_VERSION } from './run.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,WAAW,EACX,cAAc,EACd,oBAAoB,EACpB,cAAc,EACd,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,GAOpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,SAAS,EAAqB,MAAM,cAAc,CAAA;AACnG,OAAO,EAAE,eAAe,EAAoB,MAAM,WAAW,CAAA;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EACL,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,YAAY,GACb,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA"}
|
package/dist/redact.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic secret redaction (spec §15, §3.5; shapes fixed by
|
|
3
|
+
* docs/conformance-harness.md §5.6). Runs before persistence and before
|
|
4
|
+
* digesting; replacement is `[REDACTED:<kind>]`. Redaction is the sole
|
|
5
|
+
* permitted value-level rewriting of evidence (CE-5) and MUST NOT be used
|
|
6
|
+
* to normalize non-secret volatile values.
|
|
7
|
+
*/
|
|
8
|
+
export declare function redactText(text: string): string;
|
|
9
|
+
/** Recursively redact every string in a JSON-like structure. */
|
|
10
|
+
export declare function redactValue<T>(value: T): T;
|
package/dist/redact.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic secret redaction (spec §15, §3.5; shapes fixed by
|
|
3
|
+
* docs/conformance-harness.md §5.6). Runs before persistence and before
|
|
4
|
+
* digesting; replacement is `[REDACTED:<kind>]`. Redaction is the sole
|
|
5
|
+
* permitted value-level rewriting of evidence (CE-5) and MUST NOT be used
|
|
6
|
+
* to normalize non-secret volatile values.
|
|
7
|
+
*/
|
|
8
|
+
const RULES = [
|
|
9
|
+
{
|
|
10
|
+
kind: 'private-key',
|
|
11
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
12
|
+
},
|
|
13
|
+
{ kind: 'aws-access-key-id', pattern: /AKIA[0-9A-Z]{16}/g },
|
|
14
|
+
{ kind: 'github-token', pattern: /gh[pousr]_[A-Za-z0-9]{36,255}/g },
|
|
15
|
+
{ kind: 'github-token', pattern: /github_pat_[A-Za-z0-9_]{22,255}/g },
|
|
16
|
+
{ kind: 'slack-token', pattern: /xox[baprs]-[A-Za-z0-9-]{10,}/g },
|
|
17
|
+
{ kind: 'jwt', pattern: /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{10,}/g },
|
|
18
|
+
{
|
|
19
|
+
kind: 'bearer-token',
|
|
20
|
+
pattern: /([Bb]earer\s+)[A-Za-z0-9._~+/=-]{16,}/g,
|
|
21
|
+
keepPrefixGroup: 1,
|
|
22
|
+
},
|
|
23
|
+
{ kind: 'api-key', pattern: /sk-[A-Za-z0-9_-]{20,}/g },
|
|
24
|
+
];
|
|
25
|
+
export function redactText(text) {
|
|
26
|
+
let out = text;
|
|
27
|
+
for (const rule of RULES) {
|
|
28
|
+
out = out.replace(rule.pattern, (...args) => rule.keepPrefixGroup !== undefined
|
|
29
|
+
? `${args[rule.keepPrefixGroup]}[REDACTED:${rule.kind}]`
|
|
30
|
+
: `[REDACTED:${rule.kind}]`);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
/** Recursively redact every string in a JSON-like structure. */
|
|
35
|
+
export function redactValue(value) {
|
|
36
|
+
if (typeof value === 'string')
|
|
37
|
+
return redactText(value);
|
|
38
|
+
if (Array.isArray(value))
|
|
39
|
+
return value.map((v) => redactValue(v));
|
|
40
|
+
if (value !== null && typeof value === 'object') {
|
|
41
|
+
const out = {};
|
|
42
|
+
for (const [k, v] of Object.entries(value)) {
|
|
43
|
+
out[k] = redactValue(v);
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=redact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redact.js","sourceRoot":"","sources":["../src/redact.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,MAAM,KAAK,GAA6B;IACtC;QACE,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,6EAA6E;KACvF;IACD,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,mBAAmB,EAAE;IAC3D,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,gCAAgC,EAAE;IACnE,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,kCAAkC,EAAE;IACrE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,+BAA+B,EAAE;IACjE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,+DAA+D,EAAE;IACzF;QACE,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,wCAAwC;QACjD,eAAe,EAAE,CAAC;KACnB;IACD,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,wBAAwB,EAAE;CACvD,CAAA;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,GAAG,GAAG,IAAI,CAAA;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,CAC1C,IAAI,CAAC,eAAe,KAAK,SAAS;YAChC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,CAAW,aAAa,IAAI,CAAC,IAAI,GAAG;YAClE,CAAC,CAAC,aAAa,IAAI,CAAC,IAAI,GAAG,CAC9B,CAAA;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,WAAW,CAAI,KAAQ;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,KAAK,CAAiB,CAAA;IACvE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAiB,CAAA;IACjF,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,GAAG,GAA4B,EAAE,CAAA;QACvC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,EAAE,CAAC;YACtE,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,GAAmB,CAAA;IAC5B,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable rendering (§9.1): a secondary view of the report schema
|
|
3
|
+
* with no independent logic. Deterministic, timestamp-free.
|
|
4
|
+
*/
|
|
5
|
+
import type { ComparisonReport } from './schema.js';
|
|
6
|
+
export declare function renderReport(report: ComparisonReport): string;
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function renderReport(report) {
|
|
2
|
+
const lines = [];
|
|
3
|
+
lines.push(`veridelta/1 ${report.outcome_verdict} (comparability: ${report.comparability})`);
|
|
4
|
+
if (report.comparability_detail) {
|
|
5
|
+
lines.push(` reason: ${report.comparability_detail.reason} (${report.comparability_detail.kind})`);
|
|
6
|
+
}
|
|
7
|
+
if (report.baseline) {
|
|
8
|
+
lines.push(` baseline: ${report.baseline.run_id.slice(0, 12)} [${report.baseline.mode}]`);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
lines.push(' baseline: none');
|
|
12
|
+
}
|
|
13
|
+
lines.push(` current: ${report.current.run_id.slice(0, 12)} exit=${report.current.child_exit_code} coverage=${report.observation_coverage.current}`);
|
|
14
|
+
if (report.current.red && report.current.red.length > 0) {
|
|
15
|
+
lines.push(` red now (${report.current.red.length}):`);
|
|
16
|
+
for (const id of report.current.red)
|
|
17
|
+
lines.push(` ✗ ${id}`);
|
|
18
|
+
}
|
|
19
|
+
const t = report.transitions;
|
|
20
|
+
if (t) {
|
|
21
|
+
const bucket = (label, items) => {
|
|
22
|
+
if (items.length === 0)
|
|
23
|
+
return;
|
|
24
|
+
lines.push(` ${label} (${items.length}):`);
|
|
25
|
+
for (const item of items) {
|
|
26
|
+
const id = typeof item === 'string' ? item : item.test_id;
|
|
27
|
+
lines.push(` ${label === 'repaired' ? '✓' : '✗'} ${id}`);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
bucket('new_fail', t.new_fail);
|
|
31
|
+
bucket('updated_fail', t.updated_fail);
|
|
32
|
+
bucket('still_fail_unchanged', t.still_fail_unchanged);
|
|
33
|
+
if (t.repaired_same_surface.length + t.repaired_with_test_change.length > 0) {
|
|
34
|
+
lines.push(` repaired: ${t.repaired_same_surface.length} same-surface, ${t.repaired_with_test_change.length} with-test-change`);
|
|
35
|
+
}
|
|
36
|
+
bucket('fail_to_skip', t.fail_to_skip);
|
|
37
|
+
bucket('fail_to_xfail', t.fail_to_xfail);
|
|
38
|
+
bucket('removed', t.removed);
|
|
39
|
+
bucket('not_observed', t.not_observed);
|
|
40
|
+
}
|
|
41
|
+
if (report.verification_surface) {
|
|
42
|
+
lines.push(` surface: ${report.verification_surface.status} (${report.verification_surface.events.length} events)`);
|
|
43
|
+
}
|
|
44
|
+
if (report.gate) {
|
|
45
|
+
lines.push(` gate: ${report.gate.verdict} [${report.gate.policy}] triggered=${report.gate.triggered.join(',') || 'none'} staleness=${report.gate.staleness.match ? 'ok' : 'MISMATCH'}`);
|
|
46
|
+
}
|
|
47
|
+
if (report.failure_evidence.degraded_capabilities.length > 0) {
|
|
48
|
+
lines.push(` degraded capabilities: ${report.failure_evidence.degraded_capabilities.join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
lines.push(` drill-down: ${report.anchors.raw ?? 'n/a'}`);
|
|
51
|
+
return `${lines.join('\n')}\n`;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAMA,MAAM,UAAU,YAAY,CAAC,MAAwB;IACnD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,eAAe,oBAAoB,MAAM,CAAC,aAAa,GAAG,CAAC,CAAA;IAC5F,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CACR,aAAa,MAAM,CAAC,oBAAoB,CAAC,MAAM,KAAK,MAAM,CAAC,oBAAoB,CAAC,IAAI,GAAG,CACxF,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAA;IAC5F,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAChC,CAAC;IACD,KAAK,CAAC,IAAI,CACR,eAAe,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,MAAM,CAAC,OAAO,CAAC,eAAe,aAAa,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,CAC3I,CAAA;IACD,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;QACvD,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;IAChE,CAAC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAA;IAC5B,IAAI,CAAC,EAAE,CAAC;QACN,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,KAAyB,EAAQ,EAAE;YAChE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAM;YAC9B,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,MAAM,IAAI,CAAC,CAAA;YAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,EAAE,GACN,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAE,IAA4B,CAAC,OAAO,CAAA;gBACzE,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAA;YAC7D,CAAC;QACH,CAAC,CAAA;QACD,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC9B,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QACtC,MAAM,CAAC,sBAAsB,EAAE,CAAC,CAAC,oBAAoB,CAAC,CAAA;QACtD,IAAI,CAAC,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,CAAC,yBAAyB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5E,KAAK,CAAC,IAAI,CACR,eAAe,CAAC,CAAC,qBAAqB,CAAC,MAAM,kBAAkB,CAAC,CAAC,yBAAyB,CAAC,MAAM,mBAAmB,CACrH,CAAA;QACH,CAAC;QACD,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;QACtC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,aAAa,CAAC,CAAA;QACxC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;QAC5B,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,YAAY,CAAC,CAAA;IACxC,CAAC;IACD,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CACR,cAAc,MAAM,CAAC,oBAAoB,CAAC,MAAM,KAAK,MAAM,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,UAAU,CACzG,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CACR,WAAW,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,eAAe,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,cAAc,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE,CAC7K,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7D,KAAK,CAAC,IAAI,CACR,4BAA4B,MAAM,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACvF,CAAA;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,KAAK,EAAE,CAAC,CAAA;IAC1D,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;AAChC,CAAC"}
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ComparisonReport } from './schema.js';
|
|
2
|
+
export declare const VDELTA_VERSION = "0.1.0";
|
|
3
|
+
export interface RunResult {
|
|
4
|
+
exitCode: number;
|
|
5
|
+
report: ComparisonReport | null;
|
|
6
|
+
degraded: boolean;
|
|
7
|
+
diagnostics: string[];
|
|
8
|
+
rawStdout: Buffer;
|
|
9
|
+
rawStderr: Buffer;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The invocation's selector is its inclusion intent (§6.4): the vitest CLI
|
|
13
|
+
* positional filters. The canonical command excludes them (§5.1).
|
|
14
|
+
*/
|
|
15
|
+
export declare function splitCommandSelector(cmd: string[]): {
|
|
16
|
+
command: string[];
|
|
17
|
+
selector: string[];
|
|
18
|
+
};
|
|
19
|
+
export declare function runAndRecord(cmd: string[], cwd: string): Promise<RunResult>;
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vdelta run -- <cmd>` (spec §10): execute, record, report. The child's
|
|
3
|
+
* exit code passes through unchanged (signal death → 128+N). Internal
|
|
4
|
+
* errors — held lock, capture failure, store trouble — degrade to
|
|
5
|
+
* transparent raw passthrough (INV-5): veridelta is never worse than its
|
|
6
|
+
* absence. Diagnostics go to stderr and never interleave with the report.
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { readFileSync, rmSync } from 'node:fs';
|
|
11
|
+
import { tmpdir } from 'node:os';
|
|
12
|
+
import { dirname, join } from 'node:path';
|
|
13
|
+
import { fileURLToPath } from 'node:url';
|
|
14
|
+
import { buildRunRecord } from './adapters/vitest/recorder.js';
|
|
15
|
+
import { buildComparisonReport } from './compare.js';
|
|
16
|
+
import { canonicalDigest } from './digest.js';
|
|
17
|
+
import { LockHeldError, RunStore } from './store.js';
|
|
18
|
+
import { dirtyDiffMaterial, gitBranch, gitHead, gitRepoRoot, treeDigest } from './tree-digest.js';
|
|
19
|
+
export const VDELTA_VERSION = '0.1.0';
|
|
20
|
+
function reporterModulePath() {
|
|
21
|
+
return join(dirname(fileURLToPath(import.meta.url)), 'adapters', 'vitest', 'reporter.js');
|
|
22
|
+
}
|
|
23
|
+
/** Locate the vitest invocation inside the child argv; null when absent. */
|
|
24
|
+
function findVitestToken(cmd) {
|
|
25
|
+
for (let i = 0; i < cmd.length; i++) {
|
|
26
|
+
const token = cmd[i];
|
|
27
|
+
if (/(^|[\\/])vitest(\.mjs|\.js)?$/.test(token) || token === 'vitest')
|
|
28
|
+
return i;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The invocation's selector is its inclusion intent (§6.4): the vitest CLI
|
|
34
|
+
* positional filters. The canonical command excludes them (§5.1).
|
|
35
|
+
*/
|
|
36
|
+
export function splitCommandSelector(cmd) {
|
|
37
|
+
const idx = findVitestToken(cmd);
|
|
38
|
+
if (idx === null)
|
|
39
|
+
return { command: cmd, selector: [] };
|
|
40
|
+
const command = cmd.slice(0, idx + 1);
|
|
41
|
+
const selector = [];
|
|
42
|
+
for (let i = idx + 1; i < cmd.length; i++) {
|
|
43
|
+
const token = cmd[i];
|
|
44
|
+
if (token === 'run' && i === idx + 1) {
|
|
45
|
+
command.push(token);
|
|
46
|
+
}
|
|
47
|
+
else if (token.startsWith('-')) {
|
|
48
|
+
command.push(token);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
selector.push(token);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { command, selector };
|
|
55
|
+
}
|
|
56
|
+
function runChild(cmd, captureFile) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const child = spawn(cmd[0], cmd.slice(1), {
|
|
59
|
+
env: { ...process.env, VDELTA_CAPTURE_FILE: captureFile },
|
|
60
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
61
|
+
});
|
|
62
|
+
const out = [];
|
|
63
|
+
const err = [];
|
|
64
|
+
child.stdout.on('data', (d) => out.push(d));
|
|
65
|
+
child.stderr.on('data', (d) => err.push(d));
|
|
66
|
+
child.on('error', reject);
|
|
67
|
+
child.on('close', (code, signal) => {
|
|
68
|
+
const exitCode = code !== null ? code : 128 + (signal !== null ? signalNumber(signal) : 0);
|
|
69
|
+
resolve({ exitCode, stdout: Buffer.concat(out), stderr: Buffer.concat(err) });
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function signalNumber(signal) {
|
|
74
|
+
const table = {
|
|
75
|
+
SIGHUP: 1, SIGINT: 2, SIGQUIT: 3, SIGABRT: 6, SIGKILL: 9,
|
|
76
|
+
SIGSEGV: 11, SIGPIPE: 13, SIGTERM: 15,
|
|
77
|
+
};
|
|
78
|
+
return table[signal] ?? 15;
|
|
79
|
+
}
|
|
80
|
+
export async function runAndRecord(cmd, cwd) {
|
|
81
|
+
const diagnostics = [];
|
|
82
|
+
const captureFile = join(tmpdir(), `vdelta-capture-${randomUUID()}.json`);
|
|
83
|
+
const vitestIdx = findVitestToken(cmd);
|
|
84
|
+
const childCmd = vitestIdx !== null
|
|
85
|
+
? [...cmd, '--reporter=default', `--reporter=${reporterModulePath()}`, '--includeTaskLocation']
|
|
86
|
+
: cmd;
|
|
87
|
+
const child = await runChild(childCmd, captureFile);
|
|
88
|
+
const degraded = (why) => {
|
|
89
|
+
diagnostics.push(`vdelta: degraded to raw passthrough (${why})`);
|
|
90
|
+
return {
|
|
91
|
+
exitCode: child.exitCode,
|
|
92
|
+
report: null,
|
|
93
|
+
degraded: true,
|
|
94
|
+
diagnostics,
|
|
95
|
+
rawStdout: child.stdout,
|
|
96
|
+
rawStderr: child.stderr,
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
let capture;
|
|
100
|
+
try {
|
|
101
|
+
capture = JSON.parse(readFileSync(captureFile, 'utf8'));
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return degraded('no capture from the vitest reporter — is the child a vitest invocation?');
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
rmSync(captureFile, { force: true });
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const worktree = await gitRepoRoot(cwd);
|
|
111
|
+
if (worktree === null)
|
|
112
|
+
return degraded('not inside a git worktree');
|
|
113
|
+
const { command, selector } = splitCommandSelector(cmd);
|
|
114
|
+
const ctx = {
|
|
115
|
+
worktree,
|
|
116
|
+
repoIdentity: worktree,
|
|
117
|
+
branch: await gitBranch(worktree),
|
|
118
|
+
cwdRel: cwd === worktree ? '' : cwd.slice(worktree.length + 1),
|
|
119
|
+
command,
|
|
120
|
+
selector,
|
|
121
|
+
head: await gitHead(worktree),
|
|
122
|
+
treeDigest: await treeDigest(worktree),
|
|
123
|
+
dirtyDiffDigest: canonicalDigest(await dirtyDiffMaterial(worktree)),
|
|
124
|
+
childExitCode: child.exitCode,
|
|
125
|
+
rawStdout: child.stdout.toString('utf8'),
|
|
126
|
+
rawStderr: child.stderr.toString('utf8'),
|
|
127
|
+
adapterVersion: VDELTA_VERSION,
|
|
128
|
+
recordedAtMs: Date.now(),
|
|
129
|
+
};
|
|
130
|
+
const record = buildRunRecord(capture, ctx);
|
|
131
|
+
const store = new RunStore(worktree);
|
|
132
|
+
store.ensure();
|
|
133
|
+
store.acquireLock();
|
|
134
|
+
let runId;
|
|
135
|
+
try {
|
|
136
|
+
runId = store.writeRun(record).runId;
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
store.releaseLock();
|
|
140
|
+
}
|
|
141
|
+
const report = buildComparisonReport(store, runId, { mode: 'previous-comparable' });
|
|
142
|
+
return {
|
|
143
|
+
exitCode: child.exitCode,
|
|
144
|
+
report,
|
|
145
|
+
degraded: false,
|
|
146
|
+
diagnostics,
|
|
147
|
+
rawStdout: child.stdout,
|
|
148
|
+
rawStderr: child.stderr,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
if (err instanceof LockHeldError) {
|
|
153
|
+
return degraded('advisory lock is held');
|
|
154
|
+
}
|
|
155
|
+
return degraded(err instanceof Error ? err.message : String(err));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
|