@mmnto/totem 1.67.0 → 1.68.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/dist/capability/falsification.d.ts +18 -0
- package/dist/capability/falsification.d.ts.map +1 -0
- package/dist/capability/falsification.js +56 -0
- package/dist/capability/falsification.js.map +1 -0
- package/dist/capability/falsification.test.d.ts +2 -0
- package/dist/capability/falsification.test.d.ts.map +1 -0
- package/dist/capability/falsification.test.js +112 -0
- package/dist/capability/falsification.test.js.map +1 -0
- package/dist/capability/regenerate.d.ts +20 -0
- package/dist/capability/regenerate.d.ts.map +1 -0
- package/dist/capability/regenerate.js +0 -0
- package/dist/capability/regenerate.js.map +1 -0
- package/dist/capability/regenerate.test.d.ts +2 -0
- package/dist/capability/regenerate.test.d.ts.map +1 -0
- package/dist/capability/regenerate.test.js +136 -0
- package/dist/capability/regenerate.test.js.map +1 -0
- package/dist/capability/review-catch.d.ts +53 -0
- package/dist/capability/review-catch.d.ts.map +1 -0
- package/dist/capability/review-catch.js +92 -0
- package/dist/capability/review-catch.js.map +1 -0
- package/dist/capability/review-catch.test.d.ts +2 -0
- package/dist/capability/review-catch.test.d.ts.map +1 -0
- package/dist/capability/review-catch.test.js +90 -0
- package/dist/capability/review-catch.test.js.map +1 -0
- package/dist/capability/schema.d.ts +244 -0
- package/dist/capability/schema.d.ts.map +1 -0
- package/dist/capability/schema.js +141 -0
- package/dist/capability/schema.js.map +1 -0
- package/dist/capability/schema.test.d.ts +2 -0
- package/dist/capability/schema.test.d.ts.map +1 -0
- package/dist/capability/schema.test.js +93 -0
- package/dist/capability/schema.test.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/spine/candidate-rule.d.ts +84 -0
- package/dist/spine/candidate-rule.d.ts.map +1 -0
- package/dist/spine/candidate-rule.js +68 -0
- package/dist/spine/candidate-rule.js.map +1 -0
- package/dist/spine/candidate-rule.test.d.ts +2 -0
- package/dist/spine/candidate-rule.test.d.ts.map +1 -0
- package/dist/spine/candidate-rule.test.js +40 -0
- package/dist/spine/candidate-rule.test.js.map +1 -0
- package/dist/spine/classify.d.ts +93 -0
- package/dist/spine/classify.d.ts.map +1 -0
- package/dist/spine/classify.js +190 -0
- package/dist/spine/classify.js.map +1 -0
- package/dist/spine/classify.test.d.ts +2 -0
- package/dist/spine/classify.test.d.ts.map +1 -0
- package/dist/spine/classify.test.js +302 -0
- package/dist/spine/classify.test.js.map +1 -0
- package/dist/spine/compile.d.ts +62 -0
- package/dist/spine/compile.d.ts.map +1 -0
- package/dist/spine/compile.js +204 -0
- package/dist/spine/compile.js.map +1 -0
- package/dist/spine/compile.test.d.ts +2 -0
- package/dist/spine/compile.test.d.ts.map +1 -0
- package/dist/spine/compile.test.js +327 -0
- package/dist/spine/compile.test.js.map +1 -0
- package/dist/spine/extract.d.ts +146 -0
- package/dist/spine/extract.d.ts.map +1 -0
- package/dist/spine/extract.js +227 -0
- package/dist/spine/extract.js.map +1 -0
- package/dist/spine/extract.test.d.ts +2 -0
- package/dist/spine/extract.test.d.ts.map +1 -0
- package/dist/spine/extract.test.js +382 -0
- package/dist/spine/extract.test.js.map +1 -0
- package/dist/spine/ledgers.d.ts +1102 -0
- package/dist/spine/ledgers.d.ts.map +1 -0
- package/dist/spine/ledgers.js +209 -0
- package/dist/spine/ledgers.js.map +1 -0
- package/dist/spine/miner-harness.d.ts +30 -0
- package/dist/spine/miner-harness.d.ts.map +1 -0
- package/dist/spine/miner-harness.js +214 -0
- package/dist/spine/miner-harness.js.map +1 -0
- package/dist/spine/miner-harness.test.d.ts +2 -0
- package/dist/spine/miner-harness.test.d.ts.map +1 -0
- package/dist/spine/miner-harness.test.js +231 -0
- package/dist/spine/miner-harness.test.js.map +1 -0
- package/dist/spine/selection-rule.d.ts +4 -1
- package/dist/spine/selection-rule.d.ts.map +1 -1
- package/dist/spine/selection-rule.js +3 -2
- package/dist/spine/selection-rule.js.map +1 -1
- package/dist/spine/split.d.ts +149 -0
- package/dist/spine/split.d.ts.map +1 -0
- package/dist/spine/split.js +235 -0
- package/dist/spine/split.js.map +1 -0
- package/dist/spine/split.test.d.ts +2 -0
- package/dist/spine/split.test.d.ts.map +1 -0
- package/dist/spine/split.test.js +142 -0
- package/dist/spine/split.test.js.map +1 -0
- package/dist/spine/windtunnel-lock.d.ts +8 -8
- package/package.json +1 -1
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// ─── ADR-111 §5 Gate-1 train/test split — frozen, ancestry-ordered ──────────
|
|
2
|
+
//
|
|
3
|
+
// The mining/control split over the frozen corpus `selectionRule(asOfCommit)`
|
|
4
|
+
// (ADR-110 §6). Committed as a lock BEFORE extraction; `trainPrs` = the OLDER
|
|
5
|
+
// ancestry segment (mining), `heldOutPrs` = the NEWER held-out segment
|
|
6
|
+
// (control) — forward-chronological, never a random shuffle (reverse-causality
|
|
7
|
+
// leakage) and never commit-date (rebase-rewritable; the same `--topo-order`
|
|
8
|
+
// invariant as #2197). The split is a THREE-WAY DISJOINT COVER of the corpus:
|
|
9
|
+
// `trainPrs ⊎ heldOutPrs ⊎ excludedPrs == selectionRule(asOfCommit)`, with the
|
|
10
|
+
// positive/negative controls as designated tags WITHIN `heldOutPrs` (never a
|
|
11
|
+
// separate cover bucket). Total accounting (FM (d)/(g)): a corpus PR in no slice
|
|
12
|
+
// is a silent drop; a slice PR outside the corpus is an out-of-corpus member.
|
|
13
|
+
//
|
|
14
|
+
// This module is the pure schema + the deterministic cover validator (the §8
|
|
15
|
+
// split-ledger check) + the forward-ancestry-cut producer. IO (git enumeration
|
|
16
|
+
// → PrMeta) lives in the cli layer, as with `selection-rule.ts`.
|
|
17
|
+
import { z } from 'zod';
|
|
18
|
+
import { diffPrSets } from './selection-rule.js';
|
|
19
|
+
/** Lowercase 40-hex git commit SHA — canonical git form (cf. compiler-schema `COMMIT_SHA_RE`). */
|
|
20
|
+
const COMMIT_SHA_RE = /^[0-9a-f]{40}$/;
|
|
21
|
+
const PrNumber = z.number().int().positive();
|
|
22
|
+
/**
|
|
23
|
+
* ADR-111 §5 — the frozen split artifact, committed before extraction. The
|
|
24
|
+
* concrete `cutIndex` is the deferred window-open scalar (Deferred Decisions);
|
|
25
|
+
* the field is required in the committed artifact, only its value is deferred.
|
|
26
|
+
*/
|
|
27
|
+
export const SplitArtifactSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
asOfCommit: z.string().regex(COMMIT_SHA_RE),
|
|
30
|
+
/** The OLDER ancestry segment — the mining slice. */
|
|
31
|
+
trainPrs: z.array(PrNumber),
|
|
32
|
+
/** The NEWER held-out segment — control evaluation. Controls are tags within this. */
|
|
33
|
+
heldOutPrs: z.array(PrNumber),
|
|
34
|
+
/** Explicitly enumerated drops (the atomic revert pairs). */
|
|
35
|
+
excludedPrs: z.array(PrNumber),
|
|
36
|
+
/** Positive controls — a designated subset (tag) of `heldOutPrs`, never a separate cover bucket. */
|
|
37
|
+
positiveControlPrs: z.array(PrNumber),
|
|
38
|
+
/** Negative controls — a designated subset (tag) of `heldOutPrs`. */
|
|
39
|
+
negativeControlPrs: z.array(PrNumber),
|
|
40
|
+
splitRule: z.object({
|
|
41
|
+
/** Human-readable predicate expression that generated the corpus (mirrors the windtunnel lock's `selectionRule.predicate`). */
|
|
42
|
+
predicate: z.string().refine((s) => s.trim().length > 0, {
|
|
43
|
+
message: 'splitRule.predicate must be a non-empty expression',
|
|
44
|
+
}),
|
|
45
|
+
/**
|
|
46
|
+
* Forward-chronological ancestry cut: `trainPrs` = the `cutIndex` OLDEST
|
|
47
|
+
* corpus PRs (ancestry order), `heldOutPrs` = the newer remainder. Concrete
|
|
48
|
+
* value deferred to window-open (ADR-111 Deferred Decisions).
|
|
49
|
+
*/
|
|
50
|
+
cutIndex: z.number().int().nonnegative(),
|
|
51
|
+
}),
|
|
52
|
+
})
|
|
53
|
+
.superRefine((s, ctx) => {
|
|
54
|
+
// Disjoint cover is a BAG/ROW property, but the cover/overlap checks dedupe via
|
|
55
|
+
// Set semantics — so a duplicate row (e.g. trainPrs [1,1,2]) would slip through.
|
|
56
|
+
// Reject duplicates within each slice/control list at the schema boundary.
|
|
57
|
+
const lists = [
|
|
58
|
+
['trainPrs', s.trainPrs],
|
|
59
|
+
['heldOutPrs', s.heldOutPrs],
|
|
60
|
+
['excludedPrs', s.excludedPrs],
|
|
61
|
+
['positiveControlPrs', s.positiveControlPrs],
|
|
62
|
+
['negativeControlPrs', s.negativeControlPrs],
|
|
63
|
+
];
|
|
64
|
+
for (const [field, arr] of lists) {
|
|
65
|
+
if (new Set(arr).size !== arr.length) {
|
|
66
|
+
ctx.addIssue({
|
|
67
|
+
code: z.ZodIssueCode.custom,
|
|
68
|
+
message: `${field} contains duplicate PRs`,
|
|
69
|
+
path: [field],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
/** Thrown when `resolveSplit` cannot produce a clean three-way disjoint cover (Tenet 4, fail-loud). */
|
|
75
|
+
export class SplitCoverError extends Error {
|
|
76
|
+
result;
|
|
77
|
+
constructor(result) {
|
|
78
|
+
super(`[Totem Error] split is not a valid disjoint cover of selectionRule(asOfCommit): ${summarizeCover(result)}`);
|
|
79
|
+
this.result = result;
|
|
80
|
+
this.name = 'SplitCoverError';
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function uniqueSorted(xs) {
|
|
84
|
+
return [...new Set(xs)].sort((a, b) => a - b);
|
|
85
|
+
}
|
|
86
|
+
function intersect(a, b) {
|
|
87
|
+
const bs = new Set(b);
|
|
88
|
+
return uniqueSorted(a.filter((x) => bs.has(x)));
|
|
89
|
+
}
|
|
90
|
+
function summarizeCover(r) {
|
|
91
|
+
const parts = [];
|
|
92
|
+
if (r.cover.missing.length)
|
|
93
|
+
parts.push(`missing(FM-g)=[${r.cover.missing}]`);
|
|
94
|
+
if (r.cover.extra.length)
|
|
95
|
+
parts.push(`extra(FM-d)=[${r.cover.extra}]`);
|
|
96
|
+
if (r.overlaps.trainHeldOut.length)
|
|
97
|
+
parts.push(`train∩heldOut=[${r.overlaps.trainHeldOut}]`);
|
|
98
|
+
if (r.overlaps.trainExcluded.length)
|
|
99
|
+
parts.push(`train∩excluded=[${r.overlaps.trainExcluded}]`);
|
|
100
|
+
if (r.overlaps.heldOutExcluded.length)
|
|
101
|
+
parts.push(`heldOut∩excluded=[${r.overlaps.heldOutExcluded}]`);
|
|
102
|
+
if (r.controlsOutsideHeldOut.length)
|
|
103
|
+
parts.push(`controls⊄heldOut=[${r.controlsOutsideHeldOut}]`);
|
|
104
|
+
if (r.controlOverlap.length)
|
|
105
|
+
parts.push(`pos∩neg=[${r.controlOverlap}]`);
|
|
106
|
+
if (r.mergeCommitCollisions.length)
|
|
107
|
+
parts.push(`mergeCommitCollisions=[${r.mergeCommitCollisions}]`);
|
|
108
|
+
return parts.join(' ');
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* The §8 split-ledger check: verifies the split is a three-way disjoint cover of
|
|
112
|
+
* `corpus` (= `selectionRule(asOfCommit)`), that the controls are tags within
|
|
113
|
+
* `heldOutPrs`, and that the slices are disjoint by merge-commit (not only PR#).
|
|
114
|
+
* Pure; the harness asserts `ok` and reads the per-field diffs to pin the exact
|
|
115
|
+
* Falsifying-Metric clause (FM(d) extra / FM(g) missing).
|
|
116
|
+
*/
|
|
117
|
+
export function validateSplitCover(split, corpus, mergeCommitByPr) {
|
|
118
|
+
const union = [...split.trainPrs, ...split.heldOutPrs, ...split.excludedPrs];
|
|
119
|
+
const cover = diffPrSets(corpus, union); // missing ⇒ FM(g), extra ⇒ FM(d)
|
|
120
|
+
const overlaps = {
|
|
121
|
+
trainHeldOut: intersect(split.trainPrs, split.heldOutPrs),
|
|
122
|
+
trainExcluded: intersect(split.trainPrs, split.excludedPrs),
|
|
123
|
+
heldOutExcluded: intersect(split.heldOutPrs, split.excludedPrs),
|
|
124
|
+
};
|
|
125
|
+
const heldOutSet = new Set(split.heldOutPrs);
|
|
126
|
+
const controlsOutsideHeldOut = uniqueSorted([...split.positiveControlPrs, ...split.negativeControlPrs].filter((pr) => !heldOutSet.has(pr)));
|
|
127
|
+
const controlOverlap = intersect(split.positiveControlPrs, split.negativeControlPrs);
|
|
128
|
+
const mergeCommitCollisions = mergeCommitCollisionsAcrossSlices(split, mergeCommitByPr);
|
|
129
|
+
const ok = cover.missing.length === 0 &&
|
|
130
|
+
cover.extra.length === 0 &&
|
|
131
|
+
overlaps.trainHeldOut.length === 0 &&
|
|
132
|
+
overlaps.trainExcluded.length === 0 &&
|
|
133
|
+
overlaps.heldOutExcluded.length === 0 &&
|
|
134
|
+
controlsOutsideHeldOut.length === 0 &&
|
|
135
|
+
controlOverlap.length === 0 &&
|
|
136
|
+
mergeCommitCollisions.length === 0;
|
|
137
|
+
return { ok, cover, overlaps, controlsOutsideHeldOut, controlOverlap, mergeCommitCollisions };
|
|
138
|
+
}
|
|
139
|
+
/** SHAs whose owning PRs land in >1 slice. With 1:1 PR→SHA this also catches a malformed straddle. */
|
|
140
|
+
function mergeCommitCollisionsAcrossSlices(split, mergeCommitByPr) {
|
|
141
|
+
const slices = [split.trainPrs, split.heldOutPrs, split.excludedPrs];
|
|
142
|
+
const shaSliceCount = new Map();
|
|
143
|
+
for (const slice of slices) {
|
|
144
|
+
const shasInSlice = new Set();
|
|
145
|
+
for (const pr of slice) {
|
|
146
|
+
const sha = mergeCommitByPr.get(pr);
|
|
147
|
+
if (sha !== undefined)
|
|
148
|
+
shasInSlice.add(sha);
|
|
149
|
+
}
|
|
150
|
+
for (const sha of shasInSlice)
|
|
151
|
+
shaSliceCount.set(sha, (shaSliceCount.get(sha) ?? 0) + 1);
|
|
152
|
+
}
|
|
153
|
+
return [...shaSliceCount.entries()]
|
|
154
|
+
.filter(([, n]) => n > 1)
|
|
155
|
+
.map(([sha]) => sha)
|
|
156
|
+
.sort();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Produce a frozen split from the resolved corpus by the forward-chronological
|
|
160
|
+
* ancestry cut. `corpus` is `selectionRule(asOfCommit)` (the cover base);
|
|
161
|
+
* `orderedNewestFirst` is the same ancestry enumeration `resolveSelectionRule`
|
|
162
|
+
* consumes (`git log --topo-order`, newest-first) and MUST cover the corpus.
|
|
163
|
+
* `excludedPrs` (the atomic revert pairs) are removed from train/heldOut but
|
|
164
|
+
* remain in the cover. Validates the result and throws `SplitCoverError` on any
|
|
165
|
+
* cover/disjointness violation (Tenet 4) — a malformed split never freezes.
|
|
166
|
+
*
|
|
167
|
+
* CONTRACT (corpus-scope model A, confirmed by totem-codex's #2200 review; pending
|
|
168
|
+
* strategy-claude's final §5 word): `corpus` is the cover BASE that INCLUDES the
|
|
169
|
+
* PRs later assigned to `excludedPrs` — i.e. `selectionRule` is resolved here with
|
|
170
|
+
* reverts retained, and `excludedPrs` enumerates them explicitly, so
|
|
171
|
+
* `train ⊎ heldOut ⊎ excluded == corpus` holds and every `excludedPr` is a corpus
|
|
172
|
+
* member. (The alternative — `selectionRule(asOfCommit)` pre-excludes reverts yet
|
|
173
|
+
* the split still records them in `excludedPrs` — is NOT supported by the current
|
|
174
|
+
* schema, which rejects excluded PRs outside the corpus; revisit only if strategy
|
|
175
|
+
* pins that model.) The fail-loud `excludedPrs ⊆ corpus` guard below enforces this.
|
|
176
|
+
*/
|
|
177
|
+
export function resolveSplit(params) {
|
|
178
|
+
const corpusSet = new Set(params.corpus);
|
|
179
|
+
const excludedSet = new Set(params.excludedPrs);
|
|
180
|
+
// Corpus PRs in ancestry order, newest-first, deduped — then reversed to oldest-first.
|
|
181
|
+
const seen = new Set();
|
|
182
|
+
const newestFirstCorpus = [];
|
|
183
|
+
for (const pr of params.orderedNewestFirst) {
|
|
184
|
+
if (!corpusSet.has(pr) || seen.has(pr))
|
|
185
|
+
continue;
|
|
186
|
+
seen.add(pr);
|
|
187
|
+
newestFirstCorpus.push(pr);
|
|
188
|
+
}
|
|
189
|
+
const ordering = diffPrSets(params.corpus, newestFirstCorpus);
|
|
190
|
+
if (ordering.missing.length > 0) {
|
|
191
|
+
throw new Error(`[Totem Error] resolveSplit: orderedNewestFirst does not cover the corpus (missing ancestry order for [${ordering.missing}])`);
|
|
192
|
+
}
|
|
193
|
+
// The merge-commit collision check silently skips PRs absent from the map, so a
|
|
194
|
+
// partial map would weaken the disjoint-by-merge-commit guard — require coverage.
|
|
195
|
+
const missingMergeCommits = params.corpus.filter((pr) => !params.mergeCommitByPr.has(pr));
|
|
196
|
+
if (missingMergeCommits.length > 0) {
|
|
197
|
+
throw new Error(`[Totem Error] resolveSplit: mergeCommitByPr does not cover the corpus (missing merge commits for [${missingMergeCommits}])`);
|
|
198
|
+
}
|
|
199
|
+
// excludedPrs MUST be corpus-scoped revert pairs (ADR-111 §5: every listed PR is
|
|
200
|
+
// a corpus member). A non-corpus entry is a caller contract violation — fail loud
|
|
201
|
+
// (NOT silently filtered, which would hide the error and break total accounting).
|
|
202
|
+
const nonCorpusExcluded = params.excludedPrs.filter((pr) => !corpusSet.has(pr));
|
|
203
|
+
if (nonCorpusExcluded.length > 0) {
|
|
204
|
+
throw new Error(`[Totem Error] resolveSplit: excludedPrs contains PRs outside the corpus [${nonCorpusExcluded}] — excludedPrs must be corpus-scoped (ADR-111 §5)`);
|
|
205
|
+
}
|
|
206
|
+
const oldestFirstNonExcluded = [...newestFirstCorpus]
|
|
207
|
+
.reverse()
|
|
208
|
+
.filter((pr) => !excludedSet.has(pr));
|
|
209
|
+
// A certifying split needs BOTH a non-empty train slice and a non-empty held-out
|
|
210
|
+
// slice — cutIndex 0 (empty train) or == size (empty held-out, which `slice`
|
|
211
|
+
// reaches by silent clamp) makes the train/test contract vacuous. Fail loud.
|
|
212
|
+
if (params.cutIndex <= 0 || params.cutIndex >= oldestFirstNonExcluded.length) {
|
|
213
|
+
throw new Error(`[Totem Error] resolveSplit: cutIndex ${params.cutIndex} must be strictly between 0 and the non-excluded corpus size ${oldestFirstNonExcluded.length} (non-empty train + held-out)`);
|
|
214
|
+
}
|
|
215
|
+
const trainPrs = uniqueSorted(oldestFirstNonExcluded.slice(0, params.cutIndex));
|
|
216
|
+
const heldOutPrs = uniqueSorted(oldestFirstNonExcluded.slice(params.cutIndex));
|
|
217
|
+
const split = SplitArtifactSchema.parse({
|
|
218
|
+
asOfCommit: params.asOfCommit,
|
|
219
|
+
trainPrs,
|
|
220
|
+
heldOutPrs,
|
|
221
|
+
excludedPrs: uniqueSorted(params.excludedPrs),
|
|
222
|
+
positiveControlPrs: uniqueSorted(params.positiveControlPrs ?? []),
|
|
223
|
+
negativeControlPrs: uniqueSorted(params.negativeControlPrs ?? []),
|
|
224
|
+
splitRule: { predicate: params.predicate, cutIndex: params.cutIndex },
|
|
225
|
+
});
|
|
226
|
+
const validation = validateSplitCover(split, params.corpus, params.mergeCommitByPr);
|
|
227
|
+
if (!validation.ok)
|
|
228
|
+
throw new SplitCoverError(validation);
|
|
229
|
+
return split;
|
|
230
|
+
}
|
|
231
|
+
/** Re-export for callers building the `mergeCommitByPr` map from enumerated metas. */
|
|
232
|
+
export function mergeCommitMap(metas) {
|
|
233
|
+
return new Map(metas.map((m) => [m.pr, m.mergeCommit]));
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=split.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.js","sourceRoot":"","sources":["../../src/spine/split.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.test.d.ts","sourceRoot":"","sources":["../../src/spine/split.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { resolveSplit, SplitArtifactSchema, SplitCoverError, validateSplitCover, } from './split.js';
|
|
3
|
+
const sha = (n) => String(n).padStart(40, '0');
|
|
4
|
+
const mcMap = (prs) => new Map(prs.map((pr) => [pr, sha(pr)]));
|
|
5
|
+
function split(overrides) {
|
|
6
|
+
return SplitArtifactSchema.parse({
|
|
7
|
+
asOfCommit: sha(100),
|
|
8
|
+
trainPrs: [1, 2],
|
|
9
|
+
heldOutPrs: [3, 4],
|
|
10
|
+
excludedPrs: [],
|
|
11
|
+
positiveControlPrs: [3],
|
|
12
|
+
negativeControlPrs: [4],
|
|
13
|
+
splitRule: { predicate: 'code-touching non-bot', cutIndex: 2 },
|
|
14
|
+
...overrides,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
describe('validateSplitCover', () => {
|
|
18
|
+
const corpus = [1, 2, 3, 4];
|
|
19
|
+
const mc = mcMap(corpus);
|
|
20
|
+
it('accepts a clean three-way disjoint cover', () => {
|
|
21
|
+
expect(validateSplitCover(split(), corpus, mc).ok).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
it('rejects duplicate PRs within a slice at the schema boundary', () => {
|
|
24
|
+
expect(() => split({ trainPrs: [1, 1, 2] })).toThrow(/duplicate/);
|
|
25
|
+
});
|
|
26
|
+
it('flags an out-of-corpus member as FM(d) (cover.extra)', () => {
|
|
27
|
+
const r = validateSplitCover(split({ heldOutPrs: [3, 4, 99] }), corpus, mcMap([...corpus, 99]));
|
|
28
|
+
expect(r.cover.extra).toEqual([99]);
|
|
29
|
+
expect(r.cover.missing).toEqual([]);
|
|
30
|
+
expect(r.ok).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it('flags a silent corpus drop as FM(g) (cover.missing)', () => {
|
|
33
|
+
const r = validateSplitCover(split({ heldOutPrs: [3], negativeControlPrs: [] }), corpus, mc);
|
|
34
|
+
expect(r.cover.missing).toEqual([4]);
|
|
35
|
+
expect(r.cover.extra).toEqual([]);
|
|
36
|
+
expect(r.ok).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
it('flags a train/heldOut overlap (e-split disjointness)', () => {
|
|
39
|
+
const r = validateSplitCover(split({ trainPrs: [1, 2, 3], heldOutPrs: [3, 4] }), corpus, mc);
|
|
40
|
+
expect(r.overlaps.trainHeldOut).toEqual([3]);
|
|
41
|
+
expect(r.ok).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
it('flags a control outside heldOut', () => {
|
|
44
|
+
const r = validateSplitCover(split({ positiveControlPrs: [1] }), corpus, mc);
|
|
45
|
+
expect(r.controlsOutsideHeldOut).toEqual([1]);
|
|
46
|
+
expect(r.ok).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
it('flags a PR tagged as both a positive and negative control', () => {
|
|
49
|
+
const r = validateSplitCover(split({ negativeControlPrs: [3, 4] }), corpus, mc);
|
|
50
|
+
expect(r.controlOverlap).toEqual([3]);
|
|
51
|
+
expect(r.ok).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
it('flags a merge-commit collision across slices', () => {
|
|
54
|
+
const collide = new Map(mc);
|
|
55
|
+
collide.set(3, sha(2)); // PR 3 (heldOut) collides with PR 2 (train)
|
|
56
|
+
const r = validateSplitCover(split(), corpus, collide);
|
|
57
|
+
expect(r.mergeCommitCollisions).toEqual([sha(2)]);
|
|
58
|
+
expect(r.ok).toBe(false);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe('resolveSplit — forward-ancestry cut', () => {
|
|
62
|
+
const corpus = [1, 2, 3, 4];
|
|
63
|
+
it('puts the OLDER ancestry segment in train', () => {
|
|
64
|
+
const s = resolveSplit({
|
|
65
|
+
asOfCommit: sha(100),
|
|
66
|
+
corpus,
|
|
67
|
+
orderedNewestFirst: [4, 3, 2, 1], // newest-first; oldest-first = [1,2,3,4]
|
|
68
|
+
excludedPrs: [],
|
|
69
|
+
cutIndex: 2,
|
|
70
|
+
positiveControlPrs: [3],
|
|
71
|
+
negativeControlPrs: [4],
|
|
72
|
+
predicate: 'p',
|
|
73
|
+
mergeCommitByPr: mcMap(corpus),
|
|
74
|
+
});
|
|
75
|
+
expect(s.trainPrs).toEqual([1, 2]);
|
|
76
|
+
expect(s.heldOutPrs).toEqual([3, 4]);
|
|
77
|
+
});
|
|
78
|
+
it('throws on excludedPrs outside the corpus (fail-loud, not silently filtered)', () => {
|
|
79
|
+
expect(() => resolveSplit({
|
|
80
|
+
asOfCommit: sha(100),
|
|
81
|
+
corpus,
|
|
82
|
+
orderedNewestFirst: [4, 3, 2, 1],
|
|
83
|
+
excludedPrs: [99], // not a corpus member
|
|
84
|
+
cutIndex: 2,
|
|
85
|
+
predicate: 'p',
|
|
86
|
+
mergeCommitByPr: mcMap(corpus),
|
|
87
|
+
})).toThrow(/excludedPrs contains PRs outside the corpus/);
|
|
88
|
+
});
|
|
89
|
+
it('throws when mergeCommitByPr does not cover the corpus', () => {
|
|
90
|
+
expect(() => resolveSplit({
|
|
91
|
+
asOfCommit: sha(100),
|
|
92
|
+
corpus,
|
|
93
|
+
orderedNewestFirst: [4, 3, 2, 1],
|
|
94
|
+
excludedPrs: [],
|
|
95
|
+
cutIndex: 2,
|
|
96
|
+
predicate: 'p',
|
|
97
|
+
mergeCommitByPr: mcMap([1, 2, 3]), // missing PR 4
|
|
98
|
+
})).toThrow(/mergeCommitByPr does not cover the corpus/);
|
|
99
|
+
});
|
|
100
|
+
it('throws SplitCoverError when a designated control falls outside heldOut', () => {
|
|
101
|
+
expect(() => resolveSplit({
|
|
102
|
+
asOfCommit: sha(100),
|
|
103
|
+
corpus,
|
|
104
|
+
orderedNewestFirst: [4, 3, 2, 1],
|
|
105
|
+
excludedPrs: [],
|
|
106
|
+
cutIndex: 2,
|
|
107
|
+
positiveControlPrs: [1], // a train PR, not in heldOut
|
|
108
|
+
predicate: 'p',
|
|
109
|
+
mergeCommitByPr: mcMap(corpus),
|
|
110
|
+
})).toThrow(SplitCoverError);
|
|
111
|
+
});
|
|
112
|
+
it('throws when the ancestry ordering does not cover the corpus', () => {
|
|
113
|
+
expect(() => resolveSplit({
|
|
114
|
+
asOfCommit: sha(100),
|
|
115
|
+
corpus,
|
|
116
|
+
orderedNewestFirst: [4, 3, 2], // missing PR 1
|
|
117
|
+
excludedPrs: [],
|
|
118
|
+
cutIndex: 2,
|
|
119
|
+
predicate: 'p',
|
|
120
|
+
mergeCommitByPr: mcMap(corpus),
|
|
121
|
+
})).toThrow(/does not cover the corpus/);
|
|
122
|
+
});
|
|
123
|
+
const cutParams = (cutIndex) => ({
|
|
124
|
+
asOfCommit: sha(100),
|
|
125
|
+
corpus,
|
|
126
|
+
orderedNewestFirst: [4, 3, 2, 1],
|
|
127
|
+
excludedPrs: [],
|
|
128
|
+
cutIndex,
|
|
129
|
+
predicate: 'p',
|
|
130
|
+
mergeCommitByPr: mcMap(corpus),
|
|
131
|
+
});
|
|
132
|
+
it('throws when cutIndex exceeds the non-excluded corpus size', () => {
|
|
133
|
+
expect(() => resolveSplit(cutParams(5))).toThrow(/cutIndex 5 must be strictly between/);
|
|
134
|
+
});
|
|
135
|
+
it('throws when cutIndex is 0 (empty train slice)', () => {
|
|
136
|
+
expect(() => resolveSplit(cutParams(0))).toThrow(/cutIndex 0 must be strictly between/);
|
|
137
|
+
});
|
|
138
|
+
it('throws when cutIndex == size (empty held-out slice)', () => {
|
|
139
|
+
expect(() => resolveSplit(cutParams(4))).toThrow(/cutIndex 4 must be strictly between/);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
//# sourceMappingURL=split.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.test.js","sourceRoot":"","sources":["../../src/spine/split.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,6 +50,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
50
50
|
excludeBotPrs: z.ZodDefault<z.ZodBoolean>;
|
|
51
51
|
}, "strip", z.ZodTypeAny, {
|
|
52
52
|
state: string;
|
|
53
|
+
asOfCommit: string;
|
|
53
54
|
predicate: string;
|
|
54
55
|
window: {
|
|
55
56
|
type: "all";
|
|
@@ -57,7 +58,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
57
58
|
type: "bounded";
|
|
58
59
|
n: number;
|
|
59
60
|
};
|
|
60
|
-
asOfCommit: string;
|
|
61
61
|
excludeRevertPairs: boolean;
|
|
62
62
|
excludeBotPrs: boolean;
|
|
63
63
|
codePathClassifier?: {
|
|
@@ -66,6 +66,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
66
66
|
} | undefined;
|
|
67
67
|
}, {
|
|
68
68
|
state: string;
|
|
69
|
+
asOfCommit: string;
|
|
69
70
|
predicate: string;
|
|
70
71
|
window: {
|
|
71
72
|
type: "all";
|
|
@@ -73,7 +74,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
73
74
|
type: "bounded";
|
|
74
75
|
n: number;
|
|
75
76
|
};
|
|
76
|
-
asOfCommit: string;
|
|
77
77
|
codePathClassifier?: {
|
|
78
78
|
includeGlobs: string[];
|
|
79
79
|
excludeGlobs: string[];
|
|
@@ -104,6 +104,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
104
104
|
repo: string;
|
|
105
105
|
selectionRule: {
|
|
106
106
|
state: string;
|
|
107
|
+
asOfCommit: string;
|
|
107
108
|
predicate: string;
|
|
108
109
|
window: {
|
|
109
110
|
type: "all";
|
|
@@ -111,7 +112,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
111
112
|
type: "bounded";
|
|
112
113
|
n: number;
|
|
113
114
|
};
|
|
114
|
-
asOfCommit: string;
|
|
115
115
|
excludeRevertPairs: boolean;
|
|
116
116
|
excludeBotPrs: boolean;
|
|
117
117
|
codePathClassifier?: {
|
|
@@ -130,6 +130,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
130
130
|
repo: string;
|
|
131
131
|
selectionRule: {
|
|
132
132
|
state: string;
|
|
133
|
+
asOfCommit: string;
|
|
133
134
|
predicate: string;
|
|
134
135
|
window: {
|
|
135
136
|
type: "all";
|
|
@@ -137,7 +138,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
137
138
|
type: "bounded";
|
|
138
139
|
n: number;
|
|
139
140
|
};
|
|
140
|
-
asOfCommit: string;
|
|
141
141
|
codePathClassifier?: {
|
|
142
142
|
includeGlobs: string[];
|
|
143
143
|
excludeGlobs: string[];
|
|
@@ -247,6 +247,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
247
247
|
repo: string;
|
|
248
248
|
selectionRule: {
|
|
249
249
|
state: string;
|
|
250
|
+
asOfCommit: string;
|
|
250
251
|
predicate: string;
|
|
251
252
|
window: {
|
|
252
253
|
type: "all";
|
|
@@ -254,7 +255,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
254
255
|
type: "bounded";
|
|
255
256
|
n: number;
|
|
256
257
|
};
|
|
257
|
-
asOfCommit: string;
|
|
258
258
|
excludeRevertPairs: boolean;
|
|
259
259
|
excludeBotPrs: boolean;
|
|
260
260
|
codePathClassifier?: {
|
|
@@ -309,6 +309,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
309
309
|
repo: string;
|
|
310
310
|
selectionRule: {
|
|
311
311
|
state: string;
|
|
312
|
+
asOfCommit: string;
|
|
312
313
|
predicate: string;
|
|
313
314
|
window: {
|
|
314
315
|
type: "all";
|
|
@@ -316,7 +317,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
316
317
|
type: "bounded";
|
|
317
318
|
n: number;
|
|
318
319
|
};
|
|
319
|
-
asOfCommit: string;
|
|
320
320
|
codePathClassifier?: {
|
|
321
321
|
includeGlobs: string[];
|
|
322
322
|
excludeGlobs: string[];
|
|
@@ -371,6 +371,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
371
371
|
repo: string;
|
|
372
372
|
selectionRule: {
|
|
373
373
|
state: string;
|
|
374
|
+
asOfCommit: string;
|
|
374
375
|
predicate: string;
|
|
375
376
|
window: {
|
|
376
377
|
type: "all";
|
|
@@ -378,7 +379,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
378
379
|
type: "bounded";
|
|
379
380
|
n: number;
|
|
380
381
|
};
|
|
381
|
-
asOfCommit: string;
|
|
382
382
|
excludeRevertPairs: boolean;
|
|
383
383
|
excludeBotPrs: boolean;
|
|
384
384
|
codePathClassifier?: {
|
|
@@ -433,6 +433,7 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
433
433
|
repo: string;
|
|
434
434
|
selectionRule: {
|
|
435
435
|
state: string;
|
|
436
|
+
asOfCommit: string;
|
|
436
437
|
predicate: string;
|
|
437
438
|
window: {
|
|
438
439
|
type: "all";
|
|
@@ -440,7 +441,6 @@ export declare const WindtunnelLockSchema: z.ZodEffects<z.ZodObject<{
|
|
|
440
441
|
type: "bounded";
|
|
441
442
|
n: number;
|
|
442
443
|
};
|
|
443
|
-
asOfCommit: string;
|
|
444
444
|
codePathClassifier?: {
|
|
445
445
|
includeGlobs: string[];
|
|
446
446
|
excludeGlobs: string[];
|