@gate-forge/core 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 +202 -0
- package/dist/baselines/adoption.d.ts +76 -0
- package/dist/baselines/adoption.d.ts.map +1 -0
- package/dist/baselines/adoption.js +163 -0
- package/dist/baselines/adoption.js.map +1 -0
- package/dist/baselines/index.d.ts +102 -0
- package/dist/baselines/index.d.ts.map +1 -0
- package/dist/baselines/index.js +186 -0
- package/dist/baselines/index.js.map +1 -0
- package/dist/canonical-json.d.ts +51 -0
- package/dist/canonical-json.d.ts.map +1 -0
- package/dist/canonical-json.js +112 -0
- package/dist/canonical-json.js.map +1 -0
- package/dist/classifier/bind.d.ts +64 -0
- package/dist/classifier/bind.d.ts.map +1 -0
- package/dist/classifier/bind.js +188 -0
- package/dist/classifier/bind.js.map +1 -0
- package/dist/classifier/classify.d.ts +154 -0
- package/dist/classifier/classify.d.ts.map +1 -0
- package/dist/classifier/classify.js +1207 -0
- package/dist/classifier/classify.js.map +1 -0
- package/dist/classifier/glob.d.ts +48 -0
- package/dist/classifier/glob.d.ts.map +1 -0
- package/dist/classifier/glob.js +104 -0
- package/dist/classifier/glob.js.map +1 -0
- package/dist/classifier/index.d.ts +10 -0
- package/dist/classifier/index.d.ts.map +1 -0
- package/dist/classifier/index.js +21 -0
- package/dist/classifier/index.js.map +1 -0
- package/dist/classifier/schema.d.ts +150 -0
- package/dist/classifier/schema.d.ts.map +1 -0
- package/dist/classifier/schema.js +139 -0
- package/dist/classifier/schema.js.map +1 -0
- package/dist/config/index.d.ts +259 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +523 -0
- package/dist/config/index.js.map +1 -0
- package/dist/fingerprints.d.ts +56 -0
- package/dist/fingerprints.d.ts.map +1 -0
- package/dist/fingerprints.js +59 -0
- package/dist/fingerprints.js.map +1 -0
- package/dist/graph/build.d.ts +16 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +423 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/index.d.ts +12 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +10 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/schema.d.ts +448 -0
- package/dist/graph/schema.d.ts.map +1 -0
- package/dist/graph/schema.js +237 -0
- package/dist/graph/schema.js.map +1 -0
- package/dist/graph/symbols.d.ts +129 -0
- package/dist/graph/symbols.d.ts.map +1 -0
- package/dist/graph/symbols.js +177 -0
- package/dist/graph/symbols.js.map +1 -0
- package/dist/graph/util.d.ts +40 -0
- package/dist/graph/util.d.ts.map +1 -0
- package/dist/graph/util.js +41 -0
- package/dist/graph/util.js.map +1 -0
- package/dist/index.d.ts +683 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +563 -0
- package/dist/index.js.map +1 -0
- package/dist/mapping/resolve.d.ts +177 -0
- package/dist/mapping/resolve.d.ts.map +1 -0
- package/dist/mapping/resolve.js +523 -0
- package/dist/mapping/resolve.js.map +1 -0
- package/dist/policy/coverage.d.ts +79 -0
- package/dist/policy/coverage.d.ts.map +1 -0
- package/dist/policy/coverage.js +119 -0
- package/dist/policy/coverage.js.map +1 -0
- package/dist/policy/evaluate.d.ts +275 -0
- package/dist/policy/evaluate.d.ts.map +1 -0
- package/dist/policy/evaluate.js +382 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +14 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/trusted.d.ts +59 -0
- package/dist/policy/trusted.d.ts.map +1 -0
- package/dist/policy/trusted.js +96 -0
- package/dist/policy/trusted.js.map +1 -0
- package/dist/provenance.d.ts +170 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +306 -0
- package/dist/provenance.js.map +1 -0
- package/dist/receipt/index.d.ts +74 -0
- package/dist/receipt/index.d.ts.map +1 -0
- package/dist/receipt/index.js +154 -0
- package/dist/receipt/index.js.map +1 -0
- package/dist/report/index.d.ts +100 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +355 -0
- package/dist/report/index.js.map +1 -0
- package/dist/schemas/adoption.d.ts +40 -0
- package/dist/schemas/adoption.d.ts.map +1 -0
- package/dist/schemas/adoption.js +87 -0
- package/dist/schemas/adoption.js.map +1 -0
- package/dist/schemas/baseline.d.ts +19 -0
- package/dist/schemas/baseline.d.ts.map +1 -0
- package/dist/schemas/baseline.js +45 -0
- package/dist/schemas/baseline.js.map +1 -0
- package/dist/schemas/claim.d.ts +32 -0
- package/dist/schemas/claim.d.ts.map +1 -0
- package/dist/schemas/claim.js +34 -0
- package/dist/schemas/claim.js.map +1 -0
- package/dist/schemas/classification-policy.d.ts +84 -0
- package/dist/schemas/classification-policy.d.ts.map +1 -0
- package/dist/schemas/classification-policy.js +130 -0
- package/dist/schemas/classification-policy.js.map +1 -0
- package/dist/schemas/classification-signal.d.ts +125 -0
- package/dist/schemas/classification-signal.d.ts.map +1 -0
- package/dist/schemas/classification-signal.js +126 -0
- package/dist/schemas/classification-signal.js.map +1 -0
- package/dist/schemas/classification.d.ts +120 -0
- package/dist/schemas/classification.d.ts.map +1 -0
- package/dist/schemas/classification.js +154 -0
- package/dist/schemas/classification.js.map +1 -0
- package/dist/schemas/common.d.ts +73 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +60 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/coverage-policy.d.ts +89 -0
- package/dist/schemas/coverage-policy.d.ts.map +1 -0
- package/dist/schemas/coverage-policy.js +81 -0
- package/dist/schemas/coverage-policy.js.map +1 -0
- package/dist/schemas/evidence.d.ts +65 -0
- package/dist/schemas/evidence.d.ts.map +1 -0
- package/dist/schemas/evidence.js +64 -0
- package/dist/schemas/evidence.js.map +1 -0
- package/dist/schemas/execution-result.d.ts +214 -0
- package/dist/schemas/execution-result.d.ts.map +1 -0
- package/dist/schemas/execution-result.js +240 -0
- package/dist/schemas/execution-result.js.map +1 -0
- package/dist/schemas/gate-receipt.d.ts +86 -0
- package/dist/schemas/gate-receipt.d.ts.map +1 -0
- package/dist/schemas/gate-receipt.js +193 -0
- package/dist/schemas/gate-receipt.js.map +1 -0
- package/dist/schemas/index.d.ts +22 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +22 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/obligation.d.ts +37 -0
- package/dist/schemas/obligation.d.ts.map +1 -0
- package/dist/schemas/obligation.js +46 -0
- package/dist/schemas/obligation.js.map +1 -0
- package/dist/schemas/plugin.d.ts +19 -0
- package/dist/schemas/plugin.d.ts.map +1 -0
- package/dist/schemas/plugin.js +20 -0
- package/dist/schemas/plugin.js.map +1 -0
- package/dist/schemas/policy.d.ts +73 -0
- package/dist/schemas/policy.d.ts.map +1 -0
- package/dist/schemas/policy.js +46 -0
- package/dist/schemas/policy.js.map +1 -0
- package/dist/schemas/resource.d.ts +26 -0
- package/dist/schemas/resource.d.ts.map +1 -0
- package/dist/schemas/resource.js +29 -0
- package/dist/schemas/resource.js.map +1 -0
- package/dist/schemas/run-manifest.d.ts +72 -0
- package/dist/schemas/run-manifest.d.ts.map +1 -0
- package/dist/schemas/run-manifest.js +125 -0
- package/dist/schemas/run-manifest.js.map +1 -0
- package/dist/schemas/runner-adapter.d.ts +169 -0
- package/dist/schemas/runner-adapter.d.ts.map +1 -0
- package/dist/schemas/runner-adapter.js +2 -0
- package/dist/schemas/runner-adapter.js.map +1 -0
- package/dist/schemas/test-catalog.d.ts +472 -0
- package/dist/schemas/test-catalog.d.ts.map +1 -0
- package/dist/schemas/test-catalog.js +311 -0
- package/dist/schemas/test-catalog.js.map +1 -0
- package/dist/schemas/test-map.d.ts +99 -0
- package/dist/schemas/test-map.d.ts.map +1 -0
- package/dist/schemas/test-map.js +103 -0
- package/dist/schemas/test-map.js.map +1 -0
- package/dist/schemas/verdict.d.ts +73 -0
- package/dist/schemas/verdict.d.ts.map +1 -0
- package/dist/schemas/verdict.js +92 -0
- package/dist/schemas/verdict.js.map +1 -0
- package/dist/schemas/waiver.d.ts +36 -0
- package/dist/schemas/waiver.d.ts.map +1 -0
- package/dist/schemas/waiver.js +42 -0
- package/dist/schemas/waiver.js.map +1 -0
- package/dist/supervision/index.d.ts +170 -0
- package/dist/supervision/index.d.ts.map +1 -0
- package/dist/supervision/index.js +354 -0
- package/dist/supervision/index.js.map +1 -0
- package/dist/testing/clock.d.ts +50 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +75 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/env.d.ts +66 -0
- package/dist/testing/env.d.ts.map +1 -0
- package/dist/testing/env.js +106 -0
- package/dist/testing/env.js.map +1 -0
- package/dist/testing/gate-runner.d.ts +141 -0
- package/dist/testing/gate-runner.d.ts.map +1 -0
- package/dist/testing/gate-runner.js +173 -0
- package/dist/testing/gate-runner.js.map +1 -0
- package/dist/testing/gf19.d.ts +106 -0
- package/dist/testing/gf19.d.ts.map +1 -0
- package/dist/testing/gf19.js +282 -0
- package/dist/testing/gf19.js.map +1 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/red-probe.d.ts +138 -0
- package/dist/testing/red-probe.d.ts.map +1 -0
- package/dist/testing/red-probe.js +251 -0
- package/dist/testing/red-probe.js.map +1 -0
- package/dist/testing/temp-repo.d.ts +126 -0
- package/dist/testing/temp-repo.d.ts.map +1 -0
- package/dist/testing/temp-repo.js +214 -0
- package/dist/testing/temp-repo.js.map +1 -0
- package/dist/verdict/cause.d.ts +99 -0
- package/dist/verdict/cause.d.ts.map +1 -0
- package/dist/verdict/cause.js +206 -0
- package/dist/verdict/cause.js.map +1 -0
- package/dist/verdict/evaluate.d.ts +135 -0
- package/dist/verdict/evaluate.d.ts.map +1 -0
- package/dist/verdict/evaluate.js +1513 -0
- package/dist/verdict/evaluate.js.map +1 -0
- package/dist/verdict/index.d.ts +21 -0
- package/dist/verdict/index.d.ts.map +1 -0
- package/dist/verdict/index.js +20 -0
- package/dist/verdict/index.js.map +1 -0
- package/dist/verdict/pack-verifiers.d.ts +97 -0
- package/dist/verdict/pack-verifiers.d.ts.map +1 -0
- package/dist/verdict/pack-verifiers.js +763 -0
- package/dist/verdict/pack-verifiers.js.map +1 -0
- package/dist/verdict/registry.d.ts +180 -0
- package/dist/verdict/registry.d.ts.map +1 -0
- package/dist/verdict/registry.js +67 -0
- package/dist/verdict/registry.js.map +1 -0
- package/dist/waivers/index.d.ts +103 -0
- package/dist/waivers/index.d.ts.map +1 -0
- package/dist/waivers/index.js +192 -0
- package/dist/waivers/index.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trusted runner supervision — expected-set enforcement (plan
|
|
3
|
+
* 2026-09-13 Phase 4 work item 4, ADR 0005 D2). The supervisor fixes the
|
|
4
|
+
* expected test set BEFORE the run (from resolved mappings/catalog
|
|
5
|
+
* selection) and compares planned versus executed instances after it.
|
|
6
|
+
* Suite reporter data is INPUT here, never signature authority: a suite
|
|
7
|
+
* that writes its own report cannot shrink its expected set, hide a
|
|
8
|
+
* skip, or turn an incomplete shard into success.
|
|
9
|
+
*
|
|
10
|
+
* Every problem becomes a typed finding with a plan §5.4 run cause —
|
|
11
|
+
* `TEST_NOT_EXECUTED` / `TEST_FAILED` / `RUN_INCOMPLETE` — and any
|
|
12
|
+
* finding fails the whole run (§3.3 rule 5): there is no selective
|
|
13
|
+
* pass out of a failed required suite.
|
|
14
|
+
*
|
|
15
|
+
* Execution authority (enforcement-review fix 2): the runner-reported
|
|
16
|
+
* outcomes document is suite-writable and is therefore DEMOTED to detail
|
|
17
|
+
* input. When the supervisor supplies a witness-side `sessionTrace` (the
|
|
18
|
+
* signing authority's own record of which expected tests opened exactly
|
|
19
|
+
* one or more sealed sessions, and with which outcomes), supervision
|
|
20
|
+
* grades completeness from it: every expected test must have at least one
|
|
21
|
+
* SEALED session whose outcome is 'passed' (parameterized instances of one
|
|
22
|
+
* expected test produce one session per executed instance; every one of
|
|
23
|
+
* them must seal passed), no session may remain unsealed, and every traced
|
|
24
|
+
* test must belong to the expected set. A trace that could not be fetched
|
|
25
|
+
* (`sessionTrace: null`) blocks the run outright — a missing authority is
|
|
26
|
+
* never graded as success.
|
|
27
|
+
*
|
|
28
|
+
* Pure and deterministic: identical inputs produce identical findings in
|
|
29
|
+
* identical order.
|
|
30
|
+
*/
|
|
31
|
+
import { compareStrings } from '../graph/util.js';
|
|
32
|
+
import { sha256Canonical } from '../canonical-json.js';
|
|
33
|
+
/** Identity key for planned/executed matching: project + file + titlePath. */
|
|
34
|
+
function instanceKey(project, file, titlePath) {
|
|
35
|
+
return `${project ?? '-'}\u0000${file}\u0000${titlePath.join('>')}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Enforces the expected test set (ADR 0005 D2). Findings cover, in
|
|
39
|
+
* deterministic order: zero selected tests, `.only`/`.skip`/`.fixme` in
|
|
40
|
+
* the required selection, cases the runner never enumerated, retry-
|
|
41
|
+
* assisted execution, planned instances that never executed, unexpected
|
|
42
|
+
* executed instances outside the expected set, failed instances,
|
|
43
|
+
* expected failures, skipped/fixme outcomes, teardown/fixture failures,
|
|
44
|
+
* shard incompleteness, adapter-judged incompleteness, and a nonzero
|
|
45
|
+
* runner exit. All are blocking; `complete` is true only when none fired.
|
|
46
|
+
*
|
|
47
|
+
* Args:
|
|
48
|
+
* planned: the expected set fixed BEFORE the run.
|
|
49
|
+
* envelope: the structured execution envelope (input only).
|
|
50
|
+
*
|
|
51
|
+
* Returns:
|
|
52
|
+
* SupervisionResult: complete flag plus typed findings.
|
|
53
|
+
*/
|
|
54
|
+
export function superviseExecution(planned, envelope) {
|
|
55
|
+
const findings = [];
|
|
56
|
+
// Zero selected tests is never a clean run (plan Phase 4 acceptance:
|
|
57
|
+
// "no-tests case"). Nothing executed means nothing is proven.
|
|
58
|
+
if (planned.length === 0) {
|
|
59
|
+
findings.push({
|
|
60
|
+
cause: 'TEST_NOT_EXECUTED',
|
|
61
|
+
detail: 'the required selection contains zero tests — an empty run never proves coverage (run or repair the selected suite)',
|
|
62
|
+
logicalKey: null,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
// Pre-run annotations: `.only`/`.skip`/`.fixme` inside the required
|
|
66
|
+
// selection block outright — required retries are zero and required
|
|
67
|
+
// skips do not exist (plan §3.3 rule 5, E08).
|
|
68
|
+
for (const instance of planned) {
|
|
69
|
+
for (const annotation of instance.blockingAnnotations) {
|
|
70
|
+
findings.push({
|
|
71
|
+
cause: 'TEST_NOT_EXECUTED',
|
|
72
|
+
detail: `required selection carries a '${annotation}' annotation on '${instance.logicalKey}' ` +
|
|
73
|
+
'(`.${annotation}` in a required run is blocking — remove it or drop the case from the required suite)',
|
|
74
|
+
logicalKey: instance.logicalKey,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
if (instance.unenumeratedReason !== undefined) {
|
|
78
|
+
findings.push({
|
|
79
|
+
cause: 'RUN_INCOMPLETE',
|
|
80
|
+
detail: `the runner did not enumerate required case '${instance.logicalKey}' ` +
|
|
81
|
+
`(${instance.unenumeratedReason}) — the expected set cannot be sealed over an unenumerable case`,
|
|
82
|
+
logicalKey: instance.logicalKey,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Retry-assisted execution: required retries are zero. Any attempt
|
|
87
|
+
// above the first invalidates the run regardless of outcome (E08).
|
|
88
|
+
if (envelope.retriesDetected) {
|
|
89
|
+
findings.push({
|
|
90
|
+
cause: 'RUN_INCOMPLETE',
|
|
91
|
+
detail: `retry-assisted execution detected${envelope.retriesDetail !== undefined ? ` (${envelope.retriesDetail})` : ''} — ` +
|
|
92
|
+
'required retries are zero; only first-attempt outcomes prove behavior (plan §3.3 rule 3)',
|
|
93
|
+
logicalKey: null,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
// Planned versus executed: multiset comparison by instance identity
|
|
97
|
+
// (project + file + titlePath). Reporter rows cannot shrink the set:
|
|
98
|
+
// every planned instance must appear, and nothing outside it may run.
|
|
99
|
+
const plannedByKey = new Map();
|
|
100
|
+
for (const instance of planned) {
|
|
101
|
+
const key = instanceKey(instance.project, instance.file, instance.titlePath);
|
|
102
|
+
plannedByKey.set(key, instance);
|
|
103
|
+
}
|
|
104
|
+
const executedByLogicalKey = new Map();
|
|
105
|
+
for (const outcome of envelope.outcomes) {
|
|
106
|
+
const list = executedByLogicalKey.get(outcome.logicalKey) ?? [];
|
|
107
|
+
list.push(outcome);
|
|
108
|
+
executedByLogicalKey.set(outcome.logicalKey, list);
|
|
109
|
+
}
|
|
110
|
+
const executedKeys = new Set();
|
|
111
|
+
for (const outcome of envelope.outcomes) {
|
|
112
|
+
executedKeys.add(instanceKey(outcome.project, outcome.file, outcome.titlePath));
|
|
113
|
+
}
|
|
114
|
+
for (const instance of planned) {
|
|
115
|
+
const key = instanceKey(instance.project, instance.file, instance.titlePath);
|
|
116
|
+
if (!executedKeys.has(key)) {
|
|
117
|
+
findings.push({
|
|
118
|
+
cause: 'RUN_INCOMPLETE',
|
|
119
|
+
detail: `planned instance '${instance.logicalKey}' never executed — a missing selected case blocks the run (plan §3.3 rule 5)`,
|
|
120
|
+
logicalKey: instance.logicalKey,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const outcome of envelope.outcomes) {
|
|
125
|
+
const key = instanceKey(outcome.project, outcome.file, outcome.titlePath);
|
|
126
|
+
if (!plannedByKey.has(key)) {
|
|
127
|
+
findings.push({
|
|
128
|
+
cause: 'RUN_INCOMPLETE',
|
|
129
|
+
detail: `executed instance '${outcome.logicalKey}' is outside the planned expected set — ` +
|
|
130
|
+
'selective narrowing of the required suite is prohibited (no selective pass out of a failed suite)',
|
|
131
|
+
logicalKey: outcome.logicalKey,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Per-instance outcomes: every non-pass, every expected failure, and
|
|
136
|
+
// every skip is a typed block (E07/E08). Attempts are supervision
|
|
137
|
+
// property too — any attempt above the first is retry-assisted even if
|
|
138
|
+
// the adapter failed to raise its own flag (fail closed, D2).
|
|
139
|
+
for (const outcome of envelope.outcomes) {
|
|
140
|
+
if (outcome.attempt > 1) {
|
|
141
|
+
findings.push({
|
|
142
|
+
cause: 'RUN_INCOMPLETE',
|
|
143
|
+
detail: `instance '${outcome.logicalKey}' executed on attempt ${String(outcome.attempt)} — ` +
|
|
144
|
+
'retry-assisted execution is prohibited (required retries are zero; plan §3.3 rule 3)',
|
|
145
|
+
logicalKey: outcome.logicalKey,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (outcome.status === 'failed' && !outcome.expectedFailure) {
|
|
149
|
+
findings.push({
|
|
150
|
+
cause: 'TEST_FAILED',
|
|
151
|
+
detail: `instance '${outcome.logicalKey}' failed on attempt ${String(outcome.attempt)} — the whole run fails (plan §3.3 rule 5)`,
|
|
152
|
+
logicalKey: outcome.logicalKey,
|
|
153
|
+
});
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (outcome.expectedFailure) {
|
|
157
|
+
findings.push({
|
|
158
|
+
cause: 'TEST_NOT_EXECUTED',
|
|
159
|
+
detail: `instance '${outcome.logicalKey}' is an expected failure — an expected-failure exemption never proves behavior (plan §3.3 rule 3)`,
|
|
160
|
+
logicalKey: outcome.logicalKey,
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (outcome.status === 'skipped' || outcome.status === 'fixme' || outcome.status === 'not-run') {
|
|
165
|
+
findings.push({
|
|
166
|
+
cause: 'TEST_NOT_EXECUTED',
|
|
167
|
+
detail: `instance '${outcome.logicalKey}' did not execute (status '${outcome.status}') — a skip is never coverage`,
|
|
168
|
+
logicalKey: outcome.logicalKey,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Setup/teardown/runner-body failures (E07 teardown leg).
|
|
173
|
+
if (envelope.fixtureOutcome !== 'passed') {
|
|
174
|
+
findings.push({
|
|
175
|
+
cause: 'RUN_INCOMPLETE',
|
|
176
|
+
detail: envelope.fixtureOutcome === 'failed'
|
|
177
|
+
? 'the run did not end successfully: a setup, teardown, or runner-level error was observed — fixtures and teardown must pass too (plan §3.3 rule 5)'
|
|
178
|
+
: 'the run did not report a final fixture/teardown outcome (crash or lost reporter contact) — fail closed',
|
|
179
|
+
logicalKey: null,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// Shard completeness (E12 incomplete-shard leg).
|
|
183
|
+
if (envelope.shards !== null && !envelope.shards.complete) {
|
|
184
|
+
findings.push({
|
|
185
|
+
cause: 'RUN_INCOMPLETE',
|
|
186
|
+
detail: `incomplete shards: ${envelope.shards.detail} — a partial shard run cannot certify the expected set`,
|
|
187
|
+
logicalKey: null,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// The adapter's own completeness judgment (timeouts, crashes, lost
|
|
191
|
+
// reporter data).
|
|
192
|
+
if (!envelope.complete) {
|
|
193
|
+
findings.push({
|
|
194
|
+
cause: 'RUN_INCOMPLETE',
|
|
195
|
+
detail: envelope.incompleteDetail !== undefined && envelope.incompleteDetail.length > 0
|
|
196
|
+
? envelope.incompleteDetail
|
|
197
|
+
: 'the supervised run did not complete (no detail reported) — fail closed',
|
|
198
|
+
logicalKey: null,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
// Runner process exit: supplementary, but nonzero is never clean.
|
|
202
|
+
if (envelope.processExit !== null && envelope.processExit !== 0) {
|
|
203
|
+
findings.push({
|
|
204
|
+
cause: 'RUN_INCOMPLETE',
|
|
205
|
+
detail: `runner process exited with status ${String(envelope.processExit)} — a failed runner never reports a green gate`,
|
|
206
|
+
logicalKey: null,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
// Execution authority (enforcement-review fix 2b): when a witness-side
|
|
210
|
+
// session trace was supplied, the runner-reported outcomes are detail
|
|
211
|
+
// input only — completeness is graded from the trace. A fabricated or
|
|
212
|
+
// absent outcomes document cannot manufacture execution that the
|
|
213
|
+
// witness never recorded, and a trace the supervisor could not fetch
|
|
214
|
+
// blocks outright (fail closed).
|
|
215
|
+
if (envelope.sessionTrace !== undefined) {
|
|
216
|
+
findings.push(...gradeSessionTrace(planned, envelope.sessionTrace));
|
|
217
|
+
}
|
|
218
|
+
findings.sort((a, b) => compareStrings(a.cause, b.cause) ||
|
|
219
|
+
compareStrings(a.logicalKey ?? '', b.logicalKey ?? '') ||
|
|
220
|
+
compareStrings(a.detail, b.detail));
|
|
221
|
+
return { complete: findings.length === 0, findings };
|
|
222
|
+
}
|
|
223
|
+
/** Identity key shared by planned instances and traced tests. */
|
|
224
|
+
function traceKey(project, file, titlePath) {
|
|
225
|
+
return `${project ?? '-'}\u0000${file}\u0000${titlePath.join('>')}`;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Grades the witness-side session trace against the expected set (the
|
|
229
|
+
* typed core of enforcement-review fix 2). Deterministic findings, in a
|
|
230
|
+
* stable order:
|
|
231
|
+
* - a `null` trace (witness wired, trace unfetchable) blocks the run;
|
|
232
|
+
* - every expected test must have at least one SEALED session whose
|
|
233
|
+
* outcome is 'passed' — zero sessions yields the review's exact
|
|
234
|
+
* 'has no sealed session' cause, an unsealed session or a non-passed
|
|
235
|
+
* outcome blocks with its own precise detail;
|
|
236
|
+
* - every traced test must belong to the expected set (a session for an
|
|
237
|
+
* unregistered test cannot hide outside supervision).
|
|
238
|
+
*
|
|
239
|
+
* Args:
|
|
240
|
+
* planned: the expected set fixed BEFORE the run.
|
|
241
|
+
* trace: the witness-side trace (array), or null when unavailable.
|
|
242
|
+
*
|
|
243
|
+
* Returns:
|
|
244
|
+
* SupervisionFinding[]: the trace-derived findings (possibly empty).
|
|
245
|
+
*/
|
|
246
|
+
function gradeSessionTrace(planned, trace) {
|
|
247
|
+
if (trace === null) {
|
|
248
|
+
return [
|
|
249
|
+
{
|
|
250
|
+
cause: 'RUN_INCOMPLETE',
|
|
251
|
+
detail: 'the witness-side execution trace is unavailable — the session record is the execution ' +
|
|
252
|
+
'authority and a run without it is never graded complete (fail closed)',
|
|
253
|
+
logicalKey: null,
|
|
254
|
+
},
|
|
255
|
+
];
|
|
256
|
+
}
|
|
257
|
+
const findings = [];
|
|
258
|
+
const tracedByKey = new Map();
|
|
259
|
+
for (const traced of trace) {
|
|
260
|
+
tracedByKey.set(traceKey(traced.project, traced.file, traced.titlePath), traced);
|
|
261
|
+
}
|
|
262
|
+
const plannedKeys = new Set();
|
|
263
|
+
for (const instance of planned) {
|
|
264
|
+
const key = traceKey(instance.project, instance.file, instance.titlePath);
|
|
265
|
+
plannedKeys.add(key);
|
|
266
|
+
const traced = tracedByKey.get(key);
|
|
267
|
+
if (traced === undefined) {
|
|
268
|
+
findings.push({
|
|
269
|
+
cause: 'RUN_INCOMPLETE',
|
|
270
|
+
detail: `expected test '${instance.logicalKey}' has no sealed session in the witness trace — ` +
|
|
271
|
+
'the witness-side session record is the execution authority; a passing runner-reported ' +
|
|
272
|
+
'outcome without a supervisor-sealed session never proves execution',
|
|
273
|
+
logicalKey: instance.logicalKey,
|
|
274
|
+
});
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (traced.sessions.length === 0) {
|
|
278
|
+
findings.push({
|
|
279
|
+
cause: 'RUN_INCOMPLETE',
|
|
280
|
+
detail: `expected test '${instance.logicalKey}' has no sealed session — the witness recorded ` +
|
|
281
|
+
'no supervisor-opened session for it, so no execution of it is proven',
|
|
282
|
+
logicalKey: instance.logicalKey,
|
|
283
|
+
});
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
for (const session of traced.sessions) {
|
|
287
|
+
if (session.sealedTick === null) {
|
|
288
|
+
findings.push({
|
|
289
|
+
cause: 'RUN_INCOMPLETE',
|
|
290
|
+
detail: `expected test '${instance.logicalKey}' has an unsealed session (${session.sessionId}) — ` +
|
|
291
|
+
'a session the supervisor never closed proves no completed execution',
|
|
292
|
+
logicalKey: instance.logicalKey,
|
|
293
|
+
});
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (session.outcome !== 'passed') {
|
|
297
|
+
findings.push({
|
|
298
|
+
cause: 'RUN_INCOMPLETE',
|
|
299
|
+
detail: `expected test '${instance.logicalKey}' sealed session (${session.sessionId}) with ` +
|
|
300
|
+
`outcome '${String(session.outcome ?? 'unknown')}' — only sealed passed sessions prove execution`,
|
|
301
|
+
logicalKey: instance.logicalKey,
|
|
302
|
+
});
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
// No activity requirement here (execution-authority fix): a
|
|
306
|
+
// genuine passing test that never touches the witness still
|
|
307
|
+
// executed — the supervisor observed its begin/end through the
|
|
308
|
+
// trusted reporter channel. Session fabrication is defeated at
|
|
309
|
+
// the channel (trusted-config synthesis + unknown run-state
|
|
310
|
+
// paths + lifecycle-conflict detection), not by counting.
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
for (const [key, traced] of tracedByKey) {
|
|
314
|
+
if (!plannedKeys.has(key)) {
|
|
315
|
+
findings.push({
|
|
316
|
+
cause: 'RUN_INCOMPLETE',
|
|
317
|
+
detail: `the witness recorded session(s) for a test outside the expected set ` +
|
|
318
|
+
`(${traced.file}#${traced.titlePath.join('>')}) — sessions are minted only for the ` +
|
|
319
|
+
'registered expected tests; an unregistered trace entry blocks the run',
|
|
320
|
+
logicalKey: null,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
findings.sort((a, b) => compareStrings(a.logicalKey ?? '', b.logicalKey ?? '') ||
|
|
325
|
+
compareStrings(a.detail, b.detail));
|
|
326
|
+
return findings;
|
|
327
|
+
}
|
|
328
|
+
/** Domain tag separating expected-set (enumeration) digests from every other hash. */
|
|
329
|
+
export const ENUMERATION_DOMAIN = 'gateforge.enumeration.v1';
|
|
330
|
+
/**
|
|
331
|
+
* Computes the domain-separated enumeration digest over the expected set
|
|
332
|
+
* registered with the witness BEFORE the run (enforcement-review fix 2d):
|
|
333
|
+
* the execution result binds this digest so a receipt names the exact
|
|
334
|
+
* expected set the witness enforced.
|
|
335
|
+
*
|
|
336
|
+
* Args:
|
|
337
|
+
* tests: the expected tests (sorted/deduplicated by this function).
|
|
338
|
+
*
|
|
339
|
+
* Returns:
|
|
340
|
+
* string: 64-char lowercase hex digest.
|
|
341
|
+
*/
|
|
342
|
+
export function enumerationDigestOf(tests) {
|
|
343
|
+
const normalized = [...tests]
|
|
344
|
+
.map((test) => ({
|
|
345
|
+
project: test.project,
|
|
346
|
+
file: test.file,
|
|
347
|
+
titlePath: [...test.titlePath],
|
|
348
|
+
}))
|
|
349
|
+
.sort((a, b) => compareStrings(a.project ?? '', b.project ?? '') ||
|
|
350
|
+
compareStrings(a.file, b.file) ||
|
|
351
|
+
compareStrings(a.titlePath.join('>'), b.titlePath.join('>')));
|
|
352
|
+
return sha256Canonical({ domain: ENUMERATION_DOMAIN, tests: normalized });
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/supervision/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected clock for fixture runs (fixture harness, G7).
|
|
3
|
+
*
|
|
4
|
+
* Gateforge never reads the wall clock at test time: run manifests are
|
|
5
|
+
* stamped from the injected clock (pin #4) and verdict evaluation
|
|
6
|
+
* receives `now` (pin #9). `makeClock` produces deterministic `now`
|
|
7
|
+
* values from a fixed instant, an explicit sequence (e.g. waiver expiry
|
|
8
|
+
* crossings, GF-16), or a stepping start instant.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Minimal clock surface consumed by the gate runner and evaluators.
|
|
12
|
+
* `now()` always returns canonical ISO-8601 (`YYYY-MM-DDTHH:mm:ss.sssZ`).
|
|
13
|
+
*/
|
|
14
|
+
export interface TestClock {
|
|
15
|
+
now(): string;
|
|
16
|
+
}
|
|
17
|
+
/** Clock specification: exactly one shape. */
|
|
18
|
+
export type ClockSpec = {
|
|
19
|
+
fixedAt: string | Date;
|
|
20
|
+
} | {
|
|
21
|
+
sequence: Array<string | Date>;
|
|
22
|
+
} | {
|
|
23
|
+
startAt: string | Date;
|
|
24
|
+
stepMs?: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Normalizes an instant to canonical ISO-8601.
|
|
28
|
+
*
|
|
29
|
+
* Args:
|
|
30
|
+
* value: ISO-8601 string or Date.
|
|
31
|
+
*
|
|
32
|
+
* Returns:
|
|
33
|
+
* string: canonical `toISOString()` form.
|
|
34
|
+
* @throws TypeError on unparseable input (fail loud, never NaN dates).
|
|
35
|
+
*/
|
|
36
|
+
export declare function toIso(value: string | Date): string;
|
|
37
|
+
/**
|
|
38
|
+
* Builds a deterministic {@link TestClock} from a spec.
|
|
39
|
+
*
|
|
40
|
+
* Args:
|
|
41
|
+
* spec: `{fixedAt}` (constant), `{sequence}` (ordered instants,
|
|
42
|
+
* exhausted = thrown RangeError, never silent repetition), or
|
|
43
|
+
* `{startAt, stepMs}` (monotonic stepping).
|
|
44
|
+
*
|
|
45
|
+
* Returns:
|
|
46
|
+
* TestClock: `now()` yields canonical ISO-8601 instants.
|
|
47
|
+
* @throws TypeError on an empty sequence or unparseable instants.
|
|
48
|
+
*/
|
|
49
|
+
export declare function makeClock(spec: ClockSpec): TestClock;
|
|
50
|
+
//# sourceMappingURL=clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,GAAG,IAAI,MAAM,CAAC;CACf;AAED,8CAA8C;AAC9C,MAAM,MAAM,SAAS,GACjB;IACE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1B;IACE,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CAAE,GAClC;IACE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAExB;;;;;;;;;GASG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMlD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAqCpD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Injected clock for fixture runs (fixture harness, G7).
|
|
3
|
+
*
|
|
4
|
+
* Gateforge never reads the wall clock at test time: run manifests are
|
|
5
|
+
* stamped from the injected clock (pin #4) and verdict evaluation
|
|
6
|
+
* receives `now` (pin #9). `makeClock` produces deterministic `now`
|
|
7
|
+
* values from a fixed instant, an explicit sequence (e.g. waiver expiry
|
|
8
|
+
* crossings, GF-16), or a stepping start instant.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Normalizes an instant to canonical ISO-8601.
|
|
12
|
+
*
|
|
13
|
+
* Args:
|
|
14
|
+
* value: ISO-8601 string or Date.
|
|
15
|
+
*
|
|
16
|
+
* Returns:
|
|
17
|
+
* string: canonical `toISOString()` form.
|
|
18
|
+
* @throws TypeError on unparseable input (fail loud, never NaN dates).
|
|
19
|
+
*/
|
|
20
|
+
export function toIso(value) {
|
|
21
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
22
|
+
if (Number.isNaN(date.getTime())) {
|
|
23
|
+
throw new TypeError(`not a valid instant: ${String(value)}`);
|
|
24
|
+
}
|
|
25
|
+
return date.toISOString();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Builds a deterministic {@link TestClock} from a spec.
|
|
29
|
+
*
|
|
30
|
+
* Args:
|
|
31
|
+
* spec: `{fixedAt}` (constant), `{sequence}` (ordered instants,
|
|
32
|
+
* exhausted = thrown RangeError, never silent repetition), or
|
|
33
|
+
* `{startAt, stepMs}` (monotonic stepping).
|
|
34
|
+
*
|
|
35
|
+
* Returns:
|
|
36
|
+
* TestClock: `now()` yields canonical ISO-8601 instants.
|
|
37
|
+
* @throws TypeError on an empty sequence or unparseable instants.
|
|
38
|
+
*/
|
|
39
|
+
export function makeClock(spec) {
|
|
40
|
+
if ('fixedAt' in spec) {
|
|
41
|
+
const fixed = toIso(spec.fixedAt);
|
|
42
|
+
return { now: () => fixed };
|
|
43
|
+
}
|
|
44
|
+
if ('sequence' in spec) {
|
|
45
|
+
if (spec.sequence.length === 0) {
|
|
46
|
+
throw new TypeError('sequence clock requires at least one instant');
|
|
47
|
+
}
|
|
48
|
+
const instants = spec.sequence.map(toIso);
|
|
49
|
+
let index = 0;
|
|
50
|
+
return {
|
|
51
|
+
now: () => {
|
|
52
|
+
if (index >= instants.length) {
|
|
53
|
+
throw new RangeError('clock sequence exhausted (fail loud: give the fixture enough instants, never silently repeat)');
|
|
54
|
+
}
|
|
55
|
+
const next = instants[index];
|
|
56
|
+
if (next === undefined) {
|
|
57
|
+
throw new RangeError(`clock sequence index ${index} out of range (internal corruption)`);
|
|
58
|
+
}
|
|
59
|
+
index += 1;
|
|
60
|
+
return next;
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const startMs = Date.parse(toIso(spec.startAt));
|
|
65
|
+
const stepMs = spec.stepMs ?? 1000;
|
|
66
|
+
let ticks = 0;
|
|
67
|
+
return {
|
|
68
|
+
now: () => {
|
|
69
|
+
const value = new Date(startMs + stepMs * ticks).toISOString();
|
|
70
|
+
ticks += 1;
|
|
71
|
+
return value;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=clock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoBH;;;;;;;;;GASG;AACH,MAAM,UAAU,KAAK,CAAC,KAAoB;IACxC,MAAM,IAAI,GAAG,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,SAAS,CAAC,wBAAwB,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAC,IAAe;IACvC,IAAI,SAAS,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,UAAU,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,OAAO;YACL,GAAG,EAAE,GAAG,EAAE;gBACR,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;oBAC7B,MAAM,IAAI,UAAU,CAClB,+FAA+F,CAChG,CAAC;gBACJ,CAAC;gBACD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACvB,MAAM,IAAI,UAAU,CAAC,wBAAwB,KAAK,qCAAqC,CAAC,CAAC;gBAC3F,CAAC;gBACD,KAAK,IAAI,CAAC,CAAC;gBACX,OAAO,IAAI,CAAC;YACd,CAAC;SACF,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;IACnC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO;QACL,GAAG,EAAE,GAAG,EAAE;YACR,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAC/D,KAAK,IAAI,CAAC,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ChangedProvider } from '../schemas/run-manifest.js';
|
|
2
|
+
import type { TempRepo } from './temp-repo.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runs `body` with a patched `process.env`, restoring the previous
|
|
5
|
+
* environment on every path (sync throw, async rejection, success).
|
|
6
|
+
* A `undefined` value deletes the variable for the body's duration.
|
|
7
|
+
*
|
|
8
|
+
* Args:
|
|
9
|
+
* vars: variable name to value (or undefined to unset).
|
|
10
|
+
* body: closure to run under the patched environment; may be async.
|
|
11
|
+
*
|
|
12
|
+
* Returns:
|
|
13
|
+
* The body's return value (awaited when async).
|
|
14
|
+
*/
|
|
15
|
+
export declare function withEnv<V>(vars: Record<string, string | undefined>, body: () => V): V;
|
|
16
|
+
/**
|
|
17
|
+
* Minimal changed-file provider surface (pin #5 of architecture
|
|
18
|
+
* contracts). The real providers live with the CLI; fixtures consume
|
|
19
|
+
* this shape so parity tests run against both halves.
|
|
20
|
+
*/
|
|
21
|
+
export interface ChangedFileProvider {
|
|
22
|
+
/** Provider identity stamped into the run manifest (pin #4). */
|
|
23
|
+
provider: ChangedProvider;
|
|
24
|
+
/**
|
|
25
|
+
* Repo-root-relative posix paths, deduplicated and codepoint-sorted.
|
|
26
|
+
*/
|
|
27
|
+
changedFiles(): string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Normalizes a changed-file list: posix separators, deduplicated,
|
|
31
|
+
* codepoint-sorted. Provider outputs are compared as sets by GF-09.
|
|
32
|
+
*
|
|
33
|
+
* Args:
|
|
34
|
+
* files: raw provider output.
|
|
35
|
+
*
|
|
36
|
+
* Returns:
|
|
37
|
+
* string[]: canonical form.
|
|
38
|
+
*/
|
|
39
|
+
export declare function normalizeChangedFiles(files: string[]): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Builds a fake changed-file provider from an explicit list — the CI
|
|
42
|
+
* stand-in (`github-pr` / `gitlab-mr` merge-base diff) and the
|
|
43
|
+
* `all-files` full-scan provider for fixtures. The list is snapshotted
|
|
44
|
+
* (defensive copy + normalization) at construction.
|
|
45
|
+
*
|
|
46
|
+
* Args:
|
|
47
|
+
* provider: provider identity this fake impersonates.
|
|
48
|
+
* files: raw changed-file list.
|
|
49
|
+
*
|
|
50
|
+
* Returns:
|
|
51
|
+
* ChangedFileProvider: deterministic, offline, network-free.
|
|
52
|
+
*/
|
|
53
|
+
export declare function fakeProvider(provider: ChangedProvider, files: string[]): ChangedFileProvider;
|
|
54
|
+
/**
|
|
55
|
+
* Real `local-staged` provider over a {@link TempRepo}: reads the
|
|
56
|
+
* repository's actual index (`git diff --cached --name-only`) at call
|
|
57
|
+
* time, so fixtures exercise the genuine local half of GF-09 parity.
|
|
58
|
+
*
|
|
59
|
+
* Args:
|
|
60
|
+
* repo: the fixture repository.
|
|
61
|
+
*
|
|
62
|
+
* Returns:
|
|
63
|
+
* ChangedFileProvider: staged files, freshly read on every call.
|
|
64
|
+
*/
|
|
65
|
+
export declare function localStagedProvider(repo: TempRepo): ChangedFileProvider;
|
|
66
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/testing/env.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CA+BrF;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,gEAAgE;IAChE,QAAQ,EAAE,eAAe,CAAC;IAC1B;;OAEG;IACH,YAAY,IAAI,MAAM,EAAE,CAAC;CAC1B;AAED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAM/D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAG5F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,mBAAmB,CAEvE"}
|