@mmnto/totem 1.67.1 → 1.69.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.
Files changed (90) hide show
  1. package/dist/capability/falsification.d.ts +18 -0
  2. package/dist/capability/falsification.d.ts.map +1 -0
  3. package/dist/capability/falsification.js +56 -0
  4. package/dist/capability/falsification.js.map +1 -0
  5. package/dist/capability/falsification.test.d.ts +2 -0
  6. package/dist/capability/falsification.test.d.ts.map +1 -0
  7. package/dist/capability/falsification.test.js +112 -0
  8. package/dist/capability/falsification.test.js.map +1 -0
  9. package/dist/capability/regenerate.d.ts +20 -0
  10. package/dist/capability/regenerate.d.ts.map +1 -0
  11. package/dist/capability/regenerate.js +0 -0
  12. package/dist/capability/regenerate.js.map +1 -0
  13. package/dist/capability/regenerate.test.d.ts +2 -0
  14. package/dist/capability/regenerate.test.d.ts.map +1 -0
  15. package/dist/capability/regenerate.test.js +136 -0
  16. package/dist/capability/regenerate.test.js.map +1 -0
  17. package/dist/capability/review-catch.d.ts +53 -0
  18. package/dist/capability/review-catch.d.ts.map +1 -0
  19. package/dist/capability/review-catch.js +92 -0
  20. package/dist/capability/review-catch.js.map +1 -0
  21. package/dist/capability/review-catch.test.d.ts +2 -0
  22. package/dist/capability/review-catch.test.d.ts.map +1 -0
  23. package/dist/capability/review-catch.test.js +90 -0
  24. package/dist/capability/review-catch.test.js.map +1 -0
  25. package/dist/capability/schema.d.ts +244 -0
  26. package/dist/capability/schema.d.ts.map +1 -0
  27. package/dist/capability/schema.js +141 -0
  28. package/dist/capability/schema.js.map +1 -0
  29. package/dist/capability/schema.test.d.ts +2 -0
  30. package/dist/capability/schema.test.d.ts.map +1 -0
  31. package/dist/capability/schema.test.js +93 -0
  32. package/dist/capability/schema.test.js.map +1 -0
  33. package/dist/index.d.ts +20 -0
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +10 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/spine/candidate-rule.d.ts +84 -0
  38. package/dist/spine/candidate-rule.d.ts.map +1 -0
  39. package/dist/spine/candidate-rule.js +68 -0
  40. package/dist/spine/candidate-rule.js.map +1 -0
  41. package/dist/spine/candidate-rule.test.d.ts +2 -0
  42. package/dist/spine/candidate-rule.test.d.ts.map +1 -0
  43. package/dist/spine/candidate-rule.test.js +40 -0
  44. package/dist/spine/candidate-rule.test.js.map +1 -0
  45. package/dist/spine/classify.d.ts +93 -0
  46. package/dist/spine/classify.d.ts.map +1 -0
  47. package/dist/spine/classify.js +190 -0
  48. package/dist/spine/classify.js.map +1 -0
  49. package/dist/spine/classify.test.d.ts +2 -0
  50. package/dist/spine/classify.test.d.ts.map +1 -0
  51. package/dist/spine/classify.test.js +302 -0
  52. package/dist/spine/classify.test.js.map +1 -0
  53. package/dist/spine/compile.d.ts +62 -0
  54. package/dist/spine/compile.d.ts.map +1 -0
  55. package/dist/spine/compile.js +204 -0
  56. package/dist/spine/compile.js.map +1 -0
  57. package/dist/spine/compile.test.d.ts +2 -0
  58. package/dist/spine/compile.test.d.ts.map +1 -0
  59. package/dist/spine/compile.test.js +327 -0
  60. package/dist/spine/compile.test.js.map +1 -0
  61. package/dist/spine/extract.d.ts +146 -0
  62. package/dist/spine/extract.d.ts.map +1 -0
  63. package/dist/spine/extract.js +227 -0
  64. package/dist/spine/extract.js.map +1 -0
  65. package/dist/spine/extract.test.d.ts +2 -0
  66. package/dist/spine/extract.test.d.ts.map +1 -0
  67. package/dist/spine/extract.test.js +382 -0
  68. package/dist/spine/extract.test.js.map +1 -0
  69. package/dist/spine/ledgers.d.ts +1102 -0
  70. package/dist/spine/ledgers.d.ts.map +1 -0
  71. package/dist/spine/ledgers.js +209 -0
  72. package/dist/spine/ledgers.js.map +1 -0
  73. package/dist/spine/miner-harness.d.ts +30 -0
  74. package/dist/spine/miner-harness.d.ts.map +1 -0
  75. package/dist/spine/miner-harness.js +214 -0
  76. package/dist/spine/miner-harness.js.map +1 -0
  77. package/dist/spine/miner-harness.test.d.ts +2 -0
  78. package/dist/spine/miner-harness.test.d.ts.map +1 -0
  79. package/dist/spine/miner-harness.test.js +231 -0
  80. package/dist/spine/miner-harness.test.js.map +1 -0
  81. package/dist/spine/split.d.ts +149 -0
  82. package/dist/spine/split.d.ts.map +1 -0
  83. package/dist/spine/split.js +235 -0
  84. package/dist/spine/split.js.map +1 -0
  85. package/dist/spine/split.test.d.ts +2 -0
  86. package/dist/spine/split.test.d.ts.map +1 -0
  87. package/dist/spine/split.test.js +142 -0
  88. package/dist/spine/split.test.js.map +1 -0
  89. package/dist/spine/windtunnel-lock.d.ts +8 -8
  90. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledgers.d.ts","sourceRoot":"","sources":["../../src/spine/ledgers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,209 @@
1
+ // ─── ADR-111 §8 Gate-1 miner execution ledgers ──────────────────────────────
2
+ //
3
+ // The five CI-observable ledgers a deterministic zero-LLM harness asserts the
4
+ // Falsifying Metric against (run in `totem lint` / the test suite). The schemas
5
+ // here are the on-disk contract; the harness (separate module) reads them +
6
+ // the split's cover validator to pin each of the 9 FM clauses:
7
+ // emission → FM(a) provenance / FM(b) unverified / FM(f) seed-blindness
8
+ // drop → §6 sole disposition for content failure
9
+ // classifier → FM(c) behavioral never compiled
10
+ // split → FM(d)/(g) cover + FM(e) split-disjointness
11
+ // apiUsage → FM(h) held-out-fetch count MUST be 0
12
+ import { z } from 'zod';
13
+ import { ProvenanceRecordSchema } from '../compiler-schema.js';
14
+ import { ClassifierDispositionSchema } from './candidate-rule.js';
15
+ import { SplitArtifactSchema } from './split.js';
16
+ function nonEmpty(label) {
17
+ return z.string().refine((s) => s.trim().length > 0, {
18
+ message: `${label} must be a non-empty reference`,
19
+ });
20
+ }
21
+ const PrNumber = z.number().int().positive();
22
+ /** Routing off the classifier gate: structural → `compile`, behavioral → `rag-only` (never compiled). */
23
+ export const RoutingSchema = z.enum(['compile', 'rag-only']);
24
+ /**
25
+ * Provenance of a classifier-ledger disposition: a genuine classifier judgment
26
+ * (`classified`) vs a safe-default forced by classifier failure (`error-default`,
27
+ * always `behavioral`/RAG-only). Reported in the §8 done-criterion so a flaky
28
+ * classifier's error rate is a NAMED third cause of behavioral-heavy output —
29
+ * never conflated with "lc structural signal is sparse" (a valid HONEST-NEGATIVE)
30
+ * or "the classifier mis-routed everything" (Tenet 19). It is NOT a falsifying
31
+ * condition (no FM clause) — a done-criterion diagnostic, like `stage4Confirmed`.
32
+ */
33
+ export const DispositionSourceSchema = z.enum(['classified', 'error-default']);
34
+ /**
35
+ * Compile + Stage-4 disposition of a compile-routed (structural) candidate (slice 4).
36
+ * Recorded additively on the classifier ledger so the §8 done-criterion (which reads
37
+ * the LEDGER, not the compiled `rule.status`) can distinguish the verify-stage outcomes
38
+ * rather than collapse them onto the `stage4Confirmed` boolean:
39
+ * - `confirmed` — Stage-4 found positive in-scope evidence (active rule).
40
+ * - `untested-no-matches` — Stage-4 ran, zero hits (neutral/inconclusive).
41
+ * - `archived-out-of-scope` — the §4 backstop ACTIVELY rejected a mis-structural
42
+ * candidate (fired on the baseline) — a classifier-over-eager
43
+ * signal, NOT the same as `no-matches` (Tenet 19, the
44
+ * compile-stage twin of `dispositionSource`).
45
+ * - `compile-rejected` — the pattern parsed but failed per-engine safety
46
+ * validation (e.g. ReDoS); never produced as a rule.
47
+ * Absent on entries the compile stage never touched (behavioral/rag-only, or a
48
+ * classify-only run). NOT a falsifying condition (no FM clause) — a done-criterion
49
+ * diagnostic; the harness only locks its consistency with `stage4Confirmed`.
50
+ */
51
+ export const Stage4LedgerOutcomeSchema = z.enum([
52
+ 'confirmed',
53
+ 'untested-no-matches',
54
+ 'archived-out-of-scope',
55
+ 'compile-rejected',
56
+ ]);
57
+ // ── 1. Emission ledger ──────────────────────────────────────────────────────
58
+ export const EmissionLedgerEntrySchema = z.object({
59
+ candidateRef: nonEmpty('candidateRef'),
60
+ provenance: ProvenanceRecordSchema,
61
+ classifierDisposition: ClassifierDispositionSchema,
62
+ routing: RoutingSchema,
63
+ classifierLedgerRef: nonEmpty('classifierLedgerRef'),
64
+ unverified: z.literal(true),
65
+ });
66
+ export const EmissionLedgerSchema = z.object({
67
+ entries: z.array(EmissionLedgerEntrySchema),
68
+ /**
69
+ * Run-level seed-blindness attestation (§7). `false` = no seed class was
70
+ * supplied to any extraction/classification stage; `true` falsifies FM(f).
71
+ */
72
+ extractionInputsAttestation: z.object({ seedClassesProvided: z.boolean() }),
73
+ });
74
+ // ── 2. Drop ledger — the SOLE disposition for any content/provenance failure ──
75
+ export const DropReasonCodeSchema = z.enum([
76
+ 'unreachable',
77
+ 'truncated',
78
+ 'unparseable',
79
+ 'incomplete-provenance',
80
+ // 'resolved-rejected' (slice 5a, mmnto-ai/totem#2201) — an ELIGIBILITY
81
+ // rejection, semantically distinct from the four above. The content WAS
82
+ // fetched (not `unreachable`), CAN be complete (not `truncated`), and PARSES
83
+ // (not `unparseable`); its provenance is intact (not `incomplete-provenance`).
84
+ // It is dropped because every human comment lived on review threads whose
85
+ // resolution status (`isResolved || isOutdated`) marks them contamination: a
86
+ // resolved/outdated thread reflects a discussion the author already closed, so
87
+ // mining it would launder superseded review noise into a candidate rule. The
88
+ // §6 resolution gate (in `runExtractStage`) emptied the eligible-human-comment
89
+ // set — every such rejection is ledgered here (never silently pre-filtered by
90
+ // the adapter), satisfying §8 "every rejection ledgered" + the FM.
91
+ 'resolved-rejected',
92
+ ]);
93
+ export const DropLedgerEntrySchema = z.object({
94
+ /**
95
+ * Source PR of the dropped candidate. REQUIRED — the funnel always knows which
96
+ * train PR it is processing (it iterates the train slice), even for an
97
+ * `incomplete-provenance` drop where the review-thread/SHA is missing. An
98
+ * unrecorded source would make the drop uncreditable and open an undetectable
99
+ * FM(i) train-skip gap.
100
+ */
101
+ sourcePr: PrNumber,
102
+ reasonCode: DropReasonCodeSchema,
103
+ detail: z.string().optional(),
104
+ });
105
+ export const DropLedgerSchema = z.object({ entries: z.array(DropLedgerEntrySchema) });
106
+ // ── 3. Classifier ledger (reported in the done-criterion, §8) ────────────────
107
+ export const ClassifierLedgerEntrySchema = z.object({
108
+ /**
109
+ * This classifier-ledger entry's own ref — the JOIN KEY that an emission entry's
110
+ * `classifierLedgerRef` points to (not necessarily the candidate's own
111
+ * `candidateRef`). Slice 1 joins on this ref + checks disposition consistency; a
112
+ * stricter same-candidate identity assertion is deferred to slice 2.
113
+ */
114
+ candidateRef: nonEmpty('candidateRef'),
115
+ disposition: ClassifierDispositionSchema,
116
+ /**
117
+ * Stage-4 Verify-Against-Codebase confirmation — the deterministic backstop.
118
+ * NON-CERTIFYING IN SLICE 1: Stage-4 is wired in slice 4, so the harness does NOT
119
+ * yet require `stage4Confirmed === true` for compile-routed candidates (it checks
120
+ * disposition consistency only). The field is carried now so slice 4 can enforce
121
+ * it without a schema change.
122
+ */
123
+ stage4Confirmed: z.boolean(),
124
+ /**
125
+ * Whether `disposition` is a genuine classifier judgment or a safe-default on
126
+ * classifier failure (always `behavioral`). Present-and-`'classified'` in normal
127
+ * runs; set `'error-default'` on the safe-default path (slice 3). Read by the §8
128
+ * terminal report (slice 5) to keep a flaky-classifier error rate from
129
+ * masquerading as structural-signal sparsity (Tenet 19, panel flag-5). Not an FM
130
+ * condition — a diagnostic, like `stage4Confirmed`.
131
+ */
132
+ dispositionSource: DispositionSourceSchema,
133
+ /**
134
+ * Compile + Stage-4 outcome (slice 4), set by `runCompileStage` on the matched
135
+ * compile-routed entry. OPTIONAL — absent until the compile stage runs (and
136
+ * never set on behavioral/rag-only entries, which are never compiled). When
137
+ * present it MUST be consistent with `stage4Confirmed`: `confirmed` ⟺
138
+ * `stage4Confirmed === true`; the other three outcomes ⟺ `false`. The §8 harness
139
+ * locks that consistency (no new FM clause) — see `Stage4LedgerOutcomeSchema`.
140
+ */
141
+ stage4Outcome: Stage4LedgerOutcomeSchema.optional(),
142
+ });
143
+ export const ClassifierLedgerSchema = z.object({ entries: z.array(ClassifierLedgerEntrySchema) });
144
+ // ── 4. Split ledger — self-contained for the cover check ─────────────────────
145
+ export const SplitLedgerSchema = z
146
+ .object({
147
+ split: SplitArtifactSchema,
148
+ /** The frozen corpus = `selectionRule(asOfCommit)` the cover is checked against. */
149
+ corpus: z.array(PrNumber),
150
+ /** PR → merge-commit, for the disjoint-by-merge-commit check (rebuilds the map). */
151
+ corpusMergeCommits: z.array(z.object({
152
+ pr: PrNumber,
153
+ // Lowercase 40-hex SHA (same canonical form as asOfCommit / provenance.commitSha)
154
+ // — a generic string would admit case/format bypasses of the collision check.
155
+ mergeCommit: z.string().regex(/^[0-9a-f]{40}$/, {
156
+ message: 'mergeCommit must be a lowercase 40-hex SHA',
157
+ }),
158
+ })),
159
+ })
160
+ .refine((d) => {
161
+ const covered = new Set(d.corpusMergeCommits.map((e) => e.pr));
162
+ return d.corpus.every((pr) => covered.has(pr));
163
+ }, {
164
+ // An incomplete map would silently skip merge-commit collision detection for
165
+ // the absent PRs — a straddling revert pair could escape the disjoint-by-
166
+ // merge-commit guard. Require full coverage of the corpus.
167
+ message: 'corpusMergeCommits must cover every corpus PR',
168
+ path: ['corpusMergeCommits'],
169
+ })
170
+ .superRefine((d, ctx) => {
171
+ // Duplicate rows would inflate the cover-base bag while the Set-based checks
172
+ // dedupe them away — reject duplicates in corpus and corpusMergeCommits.pr.
173
+ if (new Set(d.corpus).size !== d.corpus.length) {
174
+ ctx.addIssue({
175
+ code: z.ZodIssueCode.custom,
176
+ message: 'corpus contains duplicate PRs',
177
+ path: ['corpus'],
178
+ });
179
+ }
180
+ const prs = d.corpusMergeCommits.map((e) => e.pr);
181
+ if (new Set(prs).size !== prs.length) {
182
+ ctx.addIssue({
183
+ code: z.ZodIssueCode.custom,
184
+ message: 'corpusMergeCommits contains duplicate PRs',
185
+ path: ['corpusMergeCommits'],
186
+ });
187
+ }
188
+ });
189
+ // ── 5. API-usage ledger ──────────────────────────────────────────────────────
190
+ export const ApiFetchSliceSchema = z.enum(['train', 'heldOut']);
191
+ export const ApiUsageLedgerEntrySchema = z.object({
192
+ targetPr: PrNumber,
193
+ slice: ApiFetchSliceSchema,
194
+ fetchKind: nonEmpty('fetchKind'),
195
+ });
196
+ export const ApiUsageLedgerSchema = z.object({
197
+ entries: z.array(ApiUsageLedgerEntrySchema),
198
+ /** MUST be 0 — any held-out/control content fetch during mining falsifies FM(h). */
199
+ heldOutFetchCount: z.number().int().nonnegative(),
200
+ });
201
+ // ── Aggregate ────────────────────────────────────────────────────────────────
202
+ export const MinerLedgersSchema = z.object({
203
+ emission: EmissionLedgerSchema,
204
+ drop: DropLedgerSchema,
205
+ classifier: ClassifierLedgerSchema,
206
+ split: SplitLedgerSchema,
207
+ apiUsage: ApiUsageLedgerSchema,
208
+ });
209
+ //# sourceMappingURL=ledgers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ledgers.js","sourceRoot":"","sources":["../../src/spine/ledgers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { type MinerLedgers } from './ledgers.js';
2
+ export type FmClause = 'a' | 'b' | 'c' | 'd' | 'e-split' | 'e-emission' | 'f' | 'g' | 'h' | 'i' | 'stage4-consistency' | 'schema';
3
+ export interface FmViolation {
4
+ clause: FmClause;
5
+ detail: string;
6
+ }
7
+ export interface FalsificationResult {
8
+ /** true iff NO Falsifying-Metric clause holds (the miner run is contract-clean). */
9
+ ok: boolean;
10
+ violations: FmViolation[];
11
+ }
12
+ /**
13
+ * Run the §8 falsification harness over raw (untrusted) ledger JSON. The schema
14
+ * parse is the first gate — an incomplete provenance tuple (FM(a)) or a
15
+ * non-`unverified` mint (FM(b)) cannot construct a valid `MinerLedgers`, so a
16
+ * parse failure is mapped to its clause. Surviving ledgers then run the
17
+ * cross-cutting checks (c, d, e-split, e-emission, f, g, h, i).
18
+ */
19
+ export declare function runFalsificationHarness(rawLedgers: unknown): FalsificationResult;
20
+ /**
21
+ * Cross-cutting checks over an ALREADY-VALIDATED `MinerLedgers`.
22
+ *
23
+ * ⚠ FM(a) (incomplete provenance) and FM(b) (non-`unverified` mint) are
24
+ * SCHEMA-ENFORCED and are NOT re-asserted here — a caller that hands in an
25
+ * in-process `MinerLedgers` gets no FM(a)/(b) coverage from this function. For
26
+ * untrusted/raw ledger JSON use {@link runFalsificationHarness}, which parses
27
+ * (catching FM(a)/(b)) before delegating here.
28
+ */
29
+ export declare function checkParsedLedgers(ledgers: MinerLedgers): FmViolation[];
30
+ //# sourceMappingURL=miner-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"miner-harness.d.ts","sourceRoot":"","sources":["../../src/spine/miner-harness.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,KAAK,YAAY,EAAsB,MAAM,cAAc,CAAC;AAGrE,MAAM,MAAM,QAAQ,GAChB,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GACH,SAAS,GACT,YAAY,GACZ,GAAG,GACH,GAAG,GACH,GAAG,GACH,GAAG,GAIH,oBAAoB,GACpB,QAAQ,CAAC;AAEb,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,oFAAoF;IACpF,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,WAAW,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,OAAO,GAAG,mBAAmB,CAOhF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW,EAAE,CAUvE"}
@@ -0,0 +1,214 @@
1
+ // ─── ADR-111 §8 Gate-1 falsification harness — zero-LLM, CI-observable ───────
2
+ //
3
+ // Asserts the nine Falsifying-Metric clauses (a)–(i) against the five execution
4
+ // ledgers (§8) + the split cover validator. Pure + deterministic; runs in
5
+ // `totem lint` / the test suite. The miner run is contract-clean iff `ok` (no
6
+ // clause holds). Clause (e) has two halves: `e-split` (slice disjointness, from
7
+ // the cover validator) and `e-emission` (∀ emitted: `provenance.mergedPr ∈
8
+ // trainPrs`) — split-disjointness is necessary-not-sufficient (a candidate can
9
+ // be sourced from a held-out PR even with perfectly disjoint slices).
10
+ import { MinerLedgersSchema } from './ledgers.js';
11
+ import { validateSplitCover } from './split.js';
12
+ /**
13
+ * Run the §8 falsification harness over raw (untrusted) ledger JSON. The schema
14
+ * parse is the first gate — an incomplete provenance tuple (FM(a)) or a
15
+ * non-`unverified` mint (FM(b)) cannot construct a valid `MinerLedgers`, so a
16
+ * parse failure is mapped to its clause. Surviving ledgers then run the
17
+ * cross-cutting checks (c, d, e-split, e-emission, f, g, h, i).
18
+ */
19
+ export function runFalsificationHarness(rawLedgers) {
20
+ const parsed = MinerLedgersSchema.safeParse(rawLedgers);
21
+ if (!parsed.success) {
22
+ return { ok: false, violations: parsed.error.issues.map(mapZodIssueToClause) };
23
+ }
24
+ const violations = checkParsedLedgers(parsed.data);
25
+ return { ok: violations.length === 0, violations };
26
+ }
27
+ /**
28
+ * Cross-cutting checks over an ALREADY-VALIDATED `MinerLedgers`.
29
+ *
30
+ * ⚠ FM(a) (incomplete provenance) and FM(b) (non-`unverified` mint) are
31
+ * SCHEMA-ENFORCED and are NOT re-asserted here — a caller that hands in an
32
+ * in-process `MinerLedgers` gets no FM(a)/(b) coverage from this function. For
33
+ * untrusted/raw ledger JSON use {@link runFalsificationHarness}, which parses
34
+ * (catching FM(a)/(b)) before delegating here.
35
+ */
36
+ export function checkParsedLedgers(ledgers) {
37
+ const violations = [];
38
+ checkClassifierRouting(ledgers, violations); // (c)
39
+ checkStage4Consistency(ledgers, violations); // (consistency, not an FM letter)
40
+ checkSplitCover(ledgers, violations); // (d) / (g) / (e-split)
41
+ checkEmissionMembership(ledgers, violations); // (e-emission)
42
+ checkSeedBlindness(ledgers, violations); // (f)
43
+ checkApiUsage(ledgers, violations); // (h)
44
+ checkTrainCoverage(ledgers, violations); // (i)
45
+ return violations;
46
+ }
47
+ // Map a Zod parse failure to its FM clause by a SEGMENT match on the issue path:
48
+ // a `provenance` segment ⇒ FM(a) (incomplete tuple), an `unverified` segment ⇒
49
+ // FM(b) (non-Yellow mint). Segment-level (not a substring on the joined path) so
50
+ // a future field like `classifierProvenanceRef` can't masquerade as `provenance`.
51
+ function mapZodIssueToClause(issue) {
52
+ const segments = issue.path.map(String);
53
+ const clause = segments.includes('unverified')
54
+ ? 'b'
55
+ : segments.includes('provenance')
56
+ ? 'a'
57
+ : 'schema';
58
+ return { clause, detail: `${segments.join('.') || '<root>'}: ${issue.message}` };
59
+ }
60
+ // (c) — a behavioral candidate must never reach compile, and every emitted
61
+ // candidate must carry an attesting classifier-ledger entry.
62
+ function checkClassifierRouting(ledgers, out) {
63
+ const classifierByRef = new Map(ledgers.classifier.entries.map((c) => [c.candidateRef, c]));
64
+ for (const e of ledgers.emission.entries) {
65
+ if (e.classifierDisposition === 'behavioral' && e.routing === 'compile') {
66
+ out.push({
67
+ clause: 'c',
68
+ detail: `candidate ${e.candidateRef}: behavioral candidate routed to compile`,
69
+ });
70
+ }
71
+ const attesting = classifierByRef.get(e.classifierLedgerRef);
72
+ if (attesting === undefined) {
73
+ out.push({
74
+ clause: 'c',
75
+ detail: `candidate ${e.candidateRef}: no classifier-ledger entry for ref '${e.classifierLedgerRef}'`,
76
+ });
77
+ }
78
+ else if (e.classifierDisposition !== attesting.disposition) {
79
+ // The two ledgers disagree on this candidate's class — a producer integrity bug.
80
+ out.push({
81
+ clause: 'c',
82
+ detail: `candidate ${e.candidateRef}: emission disposition '${e.classifierDisposition}' does not match classifier-ledger disposition '${attesting.disposition}'`,
83
+ });
84
+ }
85
+ else if (e.routing === 'compile' && attesting.disposition === 'behavioral') {
86
+ out.push({
87
+ clause: 'c',
88
+ detail: `candidate ${e.candidateRef}: compile-routed but classifier ledger attests behavioral`,
89
+ });
90
+ }
91
+ }
92
+ }
93
+ // (consistency, NOT an FM letter) — the compile/Stage-4 outcome recorded on a
94
+ // classifier entry must agree with its `stage4Confirmed` boolean. By construction
95
+ // `runCompileStage`'s atomic outcome→{status, stage4Confirmed, stage4Outcome} map
96
+ // makes desync unreachable; this locks it anyway (symmetric to FM(c)'s by-
97
+ // construction check). `confirmed` ⟺ `stage4Confirmed:true`; the three inert
98
+ // outcomes ⟺ `false`; an entry with NO recorded outcome can never be confirmed
99
+ // (nothing produced the evidence — e.g. a behavioral/rag-only or pre-compile entry).
100
+ // Per the panel (strategy/codex/gemini flag-5 shape) this is a done-criterion guard,
101
+ // NOT a new lettered Falsifying-Metric clause — a–i are unchanged.
102
+ function checkStage4Consistency(ledgers, out) {
103
+ for (const c of ledgers.classifier.entries) {
104
+ if (c.stage4Outcome === undefined) {
105
+ if (c.stage4Confirmed) {
106
+ out.push({
107
+ clause: 'stage4-consistency',
108
+ detail: `classifier entry ${c.candidateRef}: stage4Confirmed is true but no stage4Outcome was recorded`,
109
+ });
110
+ }
111
+ continue;
112
+ }
113
+ const confirmedByOutcome = c.stage4Outcome === 'confirmed';
114
+ if (c.stage4Confirmed !== confirmedByOutcome) {
115
+ out.push({
116
+ clause: 'stage4-consistency',
117
+ detail: `classifier entry ${c.candidateRef}: stage4Confirmed=${c.stage4Confirmed} is inconsistent with stage4Outcome='${c.stage4Outcome}'`,
118
+ });
119
+ }
120
+ }
121
+ }
122
+ // (d) extra / (g) missing / (e-split) disjointness — via the cover validator.
123
+ function checkSplitCover(ledgers, out) {
124
+ const { split, corpus, corpusMergeCommits } = ledgers.split;
125
+ const mergeCommitByPr = new Map(corpusMergeCommits.map(({ pr, mergeCommit }) => [pr, mergeCommit]));
126
+ const r = validateSplitCover(split, corpus, mergeCommitByPr);
127
+ if (r.cover.extra.length > 0) {
128
+ out.push({ clause: 'd', detail: `out-of-corpus split members: [${r.cover.extra}]` });
129
+ }
130
+ if (r.cover.missing.length > 0) {
131
+ out.push({ clause: 'g', detail: `corpus PRs in no slice (silent drop): [${r.cover.missing}]` });
132
+ }
133
+ const splitDisjointness = r.overlaps.trainHeldOut.length +
134
+ r.overlaps.trainExcluded.length +
135
+ r.overlaps.heldOutExcluded.length +
136
+ r.controlsOutsideHeldOut.length +
137
+ r.controlOverlap.length +
138
+ r.mergeCommitCollisions.length;
139
+ if (splitDisjointness > 0) {
140
+ out.push({
141
+ clause: 'e-split',
142
+ detail: `slice disjointness violated — train∩heldOut=[${r.overlaps.trainHeldOut}] ` +
143
+ `train∩excluded=[${r.overlaps.trainExcluded}] heldOut∩excluded=[${r.overlaps.heldOutExcluded}] ` +
144
+ `controls⊄heldOut=[${r.controlsOutsideHeldOut}] pos∩neg=[${r.controlOverlap}] ` +
145
+ `mergeCommitCollisions=[${r.mergeCommitCollisions}]`,
146
+ });
147
+ }
148
+ }
149
+ // (e-emission) — every emitted candidate's provenance PR must be in the train slice.
150
+ function checkEmissionMembership(ledgers, out) {
151
+ const trainSet = new Set(ledgers.split.split.trainPrs);
152
+ const mergeCommitByPr = new Map(ledgers.split.corpusMergeCommits.map(({ pr, mergeCommit }) => [pr, mergeCommit]));
153
+ for (const e of ledgers.emission.entries) {
154
+ if (!trainSet.has(e.provenance.mergedPr)) {
155
+ out.push({
156
+ clause: 'e-emission',
157
+ detail: `candidate ${e.candidateRef}: provenance PR ${e.provenance.mergedPr} is not in the train slice`,
158
+ });
159
+ continue;
160
+ }
161
+ // The provenance commit SHA must be the PR's frozen merge commit — a tuple
162
+ // carrying an arbitrary (or another PR's) SHA is provenance in name only.
163
+ const expectedSha = mergeCommitByPr.get(e.provenance.mergedPr);
164
+ if (expectedSha !== undefined && e.provenance.commitSha !== expectedSha) {
165
+ out.push({
166
+ clause: 'e-emission',
167
+ detail: `candidate ${e.candidateRef}: provenance commitSha does not match PR ${e.provenance.mergedPr}'s frozen merge commit`,
168
+ });
169
+ }
170
+ }
171
+ }
172
+ // (f) — seed-blindness attestation.
173
+ function checkSeedBlindness(ledgers, out) {
174
+ if (ledgers.emission.extractionInputsAttestation.seedClassesProvided) {
175
+ out.push({
176
+ clause: 'f',
177
+ detail: 'a seed class was supplied to an extraction/classification stage',
178
+ });
179
+ }
180
+ }
181
+ // (h) — no content fetch against a held-out/control PR. The actual partition is
182
+ // DERIVED from the frozen split (heldOut membership), NOT trusted from the
183
+ // ledger's self-declared `slice` label — a buggy/adversarial producer could read
184
+ // held-out material and label it `slice: "train"`. The declared heldOutFetchCount
185
+ // is likewise recomputed from the entries, never trusted as an independent claim.
186
+ function checkApiUsage(ledgers, out) {
187
+ const heldOutSet = new Set(ledgers.split.split.heldOutPrs);
188
+ const heldOutFetches = ledgers.apiUsage.entries.filter((f) => heldOutSet.has(f.targetPr) || f.slice === 'heldOut');
189
+ if (heldOutFetches.length > 0 || ledgers.apiUsage.heldOutFetchCount !== heldOutFetches.length) {
190
+ out.push({
191
+ clause: 'h',
192
+ detail: `held-out fetch(es) present or miscounted (derived=${heldOutFetches.length}, declared=${ledgers.apiUsage.heldOutFetchCount}, targets=[${heldOutFetches.map((f) => f.targetPr)}])`,
193
+ });
194
+ }
195
+ }
196
+ // (i) — every train PR must be processed by the emission OR the drop ledger.
197
+ // This is AT-LEAST-ONE (the ADR-111 FM(i) violation is "processed by NEITHER the
198
+ // emission ledger NOR the drop ledger"), NOT exactly-one: a single PR's review
199
+ // thread can yield multiple candidates, so the same train PR legitimately appears
200
+ // in BOTH ledgers (one candidate emitted, another dropped). `sourcePr` is
201
+ // required on every drop, so each drop is creditable here (no uncreditable gap).
202
+ function checkTrainCoverage(ledgers, out) {
203
+ const emitted = new Set(ledgers.emission.entries.map((e) => e.provenance.mergedPr));
204
+ const dropped = new Set(ledgers.drop.entries.map((d) => d.sourcePr));
205
+ for (const pr of ledgers.split.split.trainPrs) {
206
+ if (!emitted.has(pr) && !dropped.has(pr)) {
207
+ out.push({
208
+ clause: 'i',
209
+ detail: `train PR ${pr} processed by neither the emission nor the drop ledger`,
210
+ });
211
+ }
212
+ }
213
+ }
214
+ //# sourceMappingURL=miner-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"miner-harness.js","sourceRoot":"","sources":["../../src/spine/miner-harness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=miner-harness.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"miner-harness.test.d.ts","sourceRoot":"","sources":["../../src/spine/miner-harness.test.ts"],"names":[],"mappings":""}