@mmnto/totem 1.69.0 → 1.70.1

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.
@@ -0,0 +1,445 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { makeRuleEngineCtx } from '../test-utils.js';
3
+ import { ArchivedRuleInScopeError, assertNoArchivedRules, assertUniqueFiringLabels, buildFirings, computePerRuleControlResults, FiringLabelCollisionError, } from './windtunnel-firing.js';
4
+ import { firingLabelId } from './windtunnel-lock.js';
5
+ import { scoreWindtunnel } from './windtunnel-scorer.js';
6
+ // ─── Fixtures ────────────────────────────────────────
7
+ const FILE = 'src/app.ts';
8
+ /** A regex rule firing on the literal `debugger` token (code context). */
9
+ function debuggerRule(overrides = {}) {
10
+ return {
11
+ lessonHash: 'rule-debugger',
12
+ lessonHeading: 'No debugger',
13
+ pattern: 'debugger',
14
+ message: 'debugger statement',
15
+ engine: 'regex',
16
+ compiledAt: '2026-06-20T00:00:00.000Z',
17
+ ...overrides,
18
+ };
19
+ }
20
+ /** A regex rule firing on `eval(` (a second, distinct rule). */
21
+ function evalRule(overrides = {}) {
22
+ return {
23
+ lessonHash: 'rule-eval',
24
+ lessonHeading: 'No eval',
25
+ pattern: 'eval\\(',
26
+ message: 'eval call',
27
+ engine: 'regex',
28
+ compiledAt: '2026-06-20T00:00:00.000Z',
29
+ ...overrides,
30
+ };
31
+ }
32
+ /** Build a unified diff that ADDS the given lines to FILE starting at line 1. */
33
+ function diffAdding(lines, file = FILE) {
34
+ const body = lines.map((l) => `+${l}`).join('\n');
35
+ return [
36
+ `diff --git a/${file} b/${file}`,
37
+ `--- a/${file}`,
38
+ `+++ b/${file}`,
39
+ `@@ -0,0 +1,${lines.length} @@`,
40
+ body,
41
+ ].join('\n');
42
+ }
43
+ /** readStrategy returning a fixed post-image for any file (zero-LLM, no disk). */
44
+ function fixedReadStrategy(content) {
45
+ return async () => content;
46
+ }
47
+ // ─── Real-engine path (replaces runMockEngine) ───────
48
+ describe('buildFirings — real engine path', () => {
49
+ it('fires the regex rule on a real code line and maps it to a RuleFiring with a content-based labelId', async () => {
50
+ const post = ['function run() {', ' debugger;', '}'].join('\n'); // totem-ignore
51
+ const prDiffs = [
52
+ { pr: 100, diff: diffAdding([' debugger;']), controlKind: 'corpus' }, // totem-ignore
53
+ ];
54
+ const result = await buildFirings({
55
+ rules: [debuggerRule()],
56
+ prDiffs,
57
+ cwd: '/repo',
58
+ readStrategy: fixedReadStrategy(post),
59
+ ruleEngineCtx: makeRuleEngineCtx(),
60
+ });
61
+ expect(result.firings).toHaveLength(1);
62
+ const firing = result.firings[0];
63
+ expect(firing.ruleId).toBe('rule-debugger');
64
+ expect(firing.pr).toBe(100);
65
+ expect(firing.controlKind).toBe('corpus');
66
+ expect(firing.labelId).toBe(firingLabelId('rule-debugger', 100, FILE, firing.matchedLine));
67
+ });
68
+ it('suppresses an over-fire: a regex match inside a comment is NOT a firing (astContext parity, C1)', async () => {
69
+ // Line 2 is real code; line 3 is a comment. Both are added. The engine must
70
+ // fire only on the code line (the comment match is telemetry-only).
71
+ const post = [
72
+ 'function run() {',
73
+ ' debugger;', // 2 — code // totem-ignore
74
+ ' // debugger; left here — comment // totem-ignore', // 3 — comment
75
+ '}',
76
+ ].join('\n');
77
+ const prDiffs = [
78
+ {
79
+ pr: 101,
80
+ diff: diffAdding([
81
+ ' debugger;', // totem-ignore
82
+ ' // debugger; left here — comment // totem-ignore',
83
+ ]),
84
+ controlKind: 'corpus',
85
+ },
86
+ ];
87
+ const result = await buildFirings({
88
+ rules: [debuggerRule()],
89
+ prDiffs,
90
+ cwd: '/repo',
91
+ readStrategy: fixedReadStrategy(post),
92
+ ruleEngineCtx: makeRuleEngineCtx(),
93
+ });
94
+ // Only the code line fires.
95
+ expect(result.firings).toHaveLength(1);
96
+ expect(result.firings[0].matchedLine).toContain('debugger');
97
+ });
98
+ it('counts distinct touched files across all diffs (C2 real exposure)', async () => {
99
+ const post = 'const x = 1;\n';
100
+ const prDiffs = [
101
+ { pr: 1, diff: diffAdding(['const x = 1;'], 'src/a.ts'), controlKind: 'corpus' },
102
+ { pr: 2, diff: diffAdding(['const y = 2;'], 'src/b.ts'), controlKind: 'corpus' },
103
+ { pr: 3, diff: diffAdding(['const z = 3;'], 'src/a.ts'), controlKind: 'corpus' }, // dup file
104
+ ];
105
+ const result = await buildFirings({
106
+ rules: [debuggerRule()],
107
+ prDiffs,
108
+ cwd: '/repo',
109
+ readStrategy: fixedReadStrategy(post),
110
+ ruleEngineCtx: makeRuleEngineCtx(),
111
+ });
112
+ expect(result.filesTouchedInWindow).toBe(2); // a.ts + b.ts, not 3
113
+ });
114
+ it('derives positiveControlTargets from positive-control diffs', async () => {
115
+ const post = [' debugger;'].join('\n'); // totem-ignore
116
+ const prDiffs = [
117
+ {
118
+ pr: 50,
119
+ diff: diffAdding([' debugger;']), // totem-ignore
120
+ controlKind: 'positive',
121
+ targetRuleId: 'rule-debugger',
122
+ },
123
+ ];
124
+ const result = await buildFirings({
125
+ rules: [debuggerRule()],
126
+ prDiffs,
127
+ cwd: '/repo',
128
+ readStrategy: fixedReadStrategy(post),
129
+ ruleEngineCtx: makeRuleEngineCtx(),
130
+ });
131
+ expect(result.positiveControlTargets).toEqual([{ pr: 50, targetRuleId: 'rule-debugger' }]);
132
+ expect(result.firings[0].controlKind).toBe('positive');
133
+ expect(result.firings[0].targetRuleId).toBe('rule-debugger');
134
+ });
135
+ it('fold-H: a firing on a NEGATIVE control passes through as controlKind:negative (not dropped)', async () => {
136
+ const post = [' debugger;'].join('\n'); // totem-ignore
137
+ const prDiffs = [
138
+ { pr: 99, diff: diffAdding([' debugger;']), controlKind: 'negative' }, // totem-ignore
139
+ ];
140
+ const result = await buildFirings({
141
+ rules: [debuggerRule()],
142
+ prDiffs,
143
+ cwd: '/repo',
144
+ readStrategy: fixedReadStrategy(post),
145
+ ruleEngineCtx: makeRuleEngineCtx(),
146
+ });
147
+ expect(result.firings).toHaveLength(1);
148
+ expect(result.firings[0].controlKind).toBe('negative');
149
+ });
150
+ it('emits no firings when no rule matches the diff', async () => {
151
+ const post = 'const safe = 1;\n';
152
+ const prDiffs = [
153
+ { pr: 1, diff: diffAdding(['const safe = 1;']), controlKind: 'corpus' },
154
+ ];
155
+ const result = await buildFirings({
156
+ rules: [debuggerRule()],
157
+ prDiffs,
158
+ cwd: '/repo',
159
+ readStrategy: fixedReadStrategy(post),
160
+ ruleEngineCtx: makeRuleEngineCtx(),
161
+ });
162
+ expect(result.firings).toHaveLength(0);
163
+ });
164
+ });
165
+ // ─── fold-F: archived-excluded loud assert ───────────
166
+ describe('fold-F — archived rule in scored set throws (Tenet 4)', () => {
167
+ it('assertNoArchivedRules throws naming the archived rule', () => {
168
+ const rules = [debuggerRule(), evalRule({ status: 'archived' })];
169
+ expect(() => assertNoArchivedRules(rules)).toThrow(ArchivedRuleInScopeError);
170
+ expect(() => assertNoArchivedRules(rules)).toThrow(/rule-eval/);
171
+ });
172
+ it('assertNoArchivedRules passes on active-only rules', () => {
173
+ expect(() => assertNoArchivedRules([debuggerRule({ status: 'active' }), evalRule()])).not.toThrow();
174
+ });
175
+ it('buildFirings throws (and never invokes the engine) when an archived rule is present', async () => {
176
+ const post = [' debugger;'].join('\n'); // totem-ignore
177
+ const prDiffs = [
178
+ { pr: 1, diff: diffAdding([' debugger;']), controlKind: 'corpus' }, // totem-ignore
179
+ ];
180
+ await expect(buildFirings({
181
+ rules: [debuggerRule(), evalRule({ status: 'archived' })],
182
+ prDiffs,
183
+ cwd: '/repo',
184
+ readStrategy: fixedReadStrategy(post),
185
+ ruleEngineCtx: makeRuleEngineCtx(),
186
+ })).rejects.toThrow(ArchivedRuleInScopeError);
187
+ });
188
+ it('zero archived refs reach the firings (the engine ran only on active rules)', async () => {
189
+ const post = [' debugger;', ' eval(x);'].join('\n'); // totem-ignore
190
+ const prDiffs = [
191
+ {
192
+ pr: 1,
193
+ diff: diffAdding([' debugger;', ' eval(x);']), // totem-ignore
194
+ controlKind: 'corpus',
195
+ },
196
+ ];
197
+ const result = await buildFirings({
198
+ rules: [debuggerRule(), evalRule()], // both active
199
+ prDiffs,
200
+ cwd: '/repo',
201
+ readStrategy: fixedReadStrategy(post),
202
+ ruleEngineCtx: makeRuleEngineCtx(),
203
+ });
204
+ const firedRuleIds = new Set(result.firings.map((f) => f.ruleId));
205
+ expect(firedRuleIds.has('rule-debugger')).toBe(true);
206
+ expect(firedRuleIds.has('rule-eval')).toBe(true);
207
+ });
208
+ });
209
+ // ─── A1 (fold-D): hard-gate-unique FLOOR ─────────────
210
+ describe('A1 (fold-D) — assertUniqueFiringLabels hard-gate', () => {
211
+ function firing(labelId, ruleId = 'r', pr = 1) {
212
+ return { ruleId, pr, filePath: FILE, matchedLine: 'x', controlKind: 'corpus', labelId };
213
+ }
214
+ it('passes when all labelIds are unique', () => {
215
+ expect(() => assertUniqueFiringLabels([firing('a'), firing('b'), firing('c')])).not.toThrow();
216
+ });
217
+ it('throws a FiringLabelCollisionError when two firings share a labelId', () => {
218
+ expect(() => assertUniqueFiringLabels([firing('dup'), firing('dup')])).toThrow(FiringLabelCollisionError);
219
+ });
220
+ it('surfaces the colliding labelId + every evidence ref', () => {
221
+ const dup = firingLabelId('r', 1, FILE, 'line');
222
+ const a = {
223
+ ruleId: 'r',
224
+ pr: 1,
225
+ filePath: FILE,
226
+ matchedLine: 'line',
227
+ controlKind: 'corpus',
228
+ labelId: dup,
229
+ };
230
+ const b = { ...a };
231
+ let caught;
232
+ try {
233
+ assertUniqueFiringLabels([a, b]);
234
+ }
235
+ catch (err) {
236
+ caught = err;
237
+ }
238
+ expect(caught).toBeInstanceOf(FiringLabelCollisionError);
239
+ expect(caught.collisions).toHaveLength(1);
240
+ expect(caught.collisions[0].labelId).toBe(dup);
241
+ expect(caught.collisions[0].evidenceRefs).toHaveLength(2);
242
+ expect(caught.collisions[0].evidenceRefs[0].ruleId).toBe('r');
243
+ });
244
+ });
245
+ // ─── C1: per-rule control results (NOT global nonVacuity) ─
246
+ describe('C1 — computePerRuleControlResults (per-rule, survivor-only)', () => {
247
+ function f(ruleId, controlKind, pr, matched = 'x') {
248
+ return {
249
+ ruleId,
250
+ pr,
251
+ filePath: FILE,
252
+ matchedLine: matched,
253
+ controlKind,
254
+ labelId: firingLabelId(ruleId, pr, FILE, matched),
255
+ };
256
+ }
257
+ it('positiveControl is true ONLY for the rule that fired its declared target (never global)', () => {
258
+ // rule-a fired its positive target on pr 10; rule-b is a survivor that never
259
+ // exercised a positive control. The global nonVacuity (all targets fired)
260
+ // would be true — but rule-b's positiveControl must NOT inherit that.
261
+ const firings = [f('rule-a', 'positive', 10), f('rule-b', 'corpus', 1)];
262
+ const result = computePerRuleControlResults({
263
+ firings,
264
+ mintedRuleIds: ['rule-a', 'rule-b'],
265
+ positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
266
+ });
267
+ expect(result.get('rule-a').positiveControl).toBe(true);
268
+ expect(result.get('rule-b').positiveControl).toBe(false);
269
+ });
270
+ it('negativeControl is false (and the rule is excluded as culled) when it fires on a negative control', () => {
271
+ const firings = [f('rule-a', 'negative', 99)];
272
+ const result = computePerRuleControlResults({
273
+ firings,
274
+ mintedRuleIds: ['rule-a', 'rule-b'],
275
+ positiveControlTargets: [],
276
+ });
277
+ // rule-a fired on a negative control → culled → not a survivor → absent.
278
+ expect(result.has('rule-a')).toBe(false);
279
+ // rule-b never fired on a negative control → clean (negativeControl true).
280
+ expect(result.get('rule-b').negativeControl).toBe(true);
281
+ });
282
+ it('a clean survivor carries negativeControl:true with no positive evidence', () => {
283
+ const result = computePerRuleControlResults({
284
+ firings: [],
285
+ mintedRuleIds: ['rule-a'],
286
+ positiveControlTargets: [],
287
+ });
288
+ expect(result.get('rule-a')).toEqual({
289
+ positiveControl: false,
290
+ negativeControl: true,
291
+ evidenceRefs: [],
292
+ });
293
+ });
294
+ it('records evidenceRefs (the firingLabelIds) for both control legs', () => {
295
+ const posFiring = f('rule-a', 'positive', 10);
296
+ const result = computePerRuleControlResults({
297
+ firings: [posFiring],
298
+ mintedRuleIds: ['rule-a'],
299
+ positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
300
+ });
301
+ expect(result.get('rule-a').evidenceRefs).toContain(posFiring.labelId);
302
+ });
303
+ });
304
+ // ─── fold-H: OQ4 real-firing integration matrix ──────
305
+ //
306
+ // End-to-end through the REAL engine (buildFirings) → scoreWindtunnel. Zero-LLM,
307
+ // deterministic: fixture rules + fixture diffs + injected post-image readStrategy.
308
+ describe('fold-H — OQ4 real-firing matrix (buildFirings → scoreWindtunnel)', () => {
309
+ /** Run the deterministic engine, gate uniqueness (A1), then score. */
310
+ async function fireAndScore(opts) {
311
+ const built = await buildFirings({
312
+ rules: opts.rules,
313
+ prDiffs: opts.prDiffs,
314
+ cwd: '/repo',
315
+ readStrategy: fixedReadStrategy(opts.post),
316
+ ruleEngineCtx: makeRuleEngineCtx(),
317
+ });
318
+ assertUniqueFiringLabels(built.firings); // A1 pre-score gate
319
+ const mintedRuleIds = opts.mintedRuleIds ?? opts.rules.map((r) => r.lessonHash);
320
+ return scoreWindtunnel({
321
+ firings: built.firings,
322
+ groundTruth: opts.groundTruth ?? new Map(),
323
+ positiveControlTargets: built.positiveControlTargets,
324
+ mintedRuleIds,
325
+ cullRateThreshold: 0.9,
326
+ exposureFloors: opts.exposureFloors ?? {
327
+ activeRulesEvaluated: 0,
328
+ filesTouchedInWindow: 0,
329
+ positiveControlsExercised: 0,
330
+ },
331
+ actualExposure: {
332
+ activeRulesEvaluated: mintedRuleIds.length,
333
+ filesTouchedInWindow: built.filesTouchedInWindow,
334
+ positiveControlsExercised: built.positiveControlTargets.length,
335
+ },
336
+ });
337
+ }
338
+ it('confirmed-FP firing (sub-floor precision) ⟹ FAIL', async () => {
339
+ const post = [' debugger;'].join('\n'); // totem-ignore
340
+ const prDiffs = [
341
+ { pr: 1, diff: diffAdding([' debugger;']), controlKind: 'corpus' }, // totem-ignore
342
+ ];
343
+ const built = await buildFirings({
344
+ rules: [debuggerRule()],
345
+ prDiffs,
346
+ cwd: '/repo',
347
+ readStrategy: fixedReadStrategy(post),
348
+ ruleEngineCtx: makeRuleEngineCtx(),
349
+ });
350
+ const fpLabel = built.firings[0].labelId;
351
+ const verdict = await fireAndScore({
352
+ rules: [debuggerRule()],
353
+ prDiffs,
354
+ post,
355
+ groundTruth: new Map([[fpLabel, 'FP']]),
356
+ });
357
+ expect(verdict.verdict).toBe('FAIL');
358
+ expect(verdict.precision).toBeLessThan(1);
359
+ });
360
+ it('vacuous positive control (target never fires) ⟹ FAIL / null precision', async () => {
361
+ // The positive control declares rule-eval must fire, but the post-image has
362
+ // no eval( — so the target never fires (vacuous).
363
+ const post = ['const safe = 1;'].join('\n');
364
+ const prDiffs = [
365
+ {
366
+ pr: 10,
367
+ diff: diffAdding(['const safe = 1;']),
368
+ controlKind: 'positive',
369
+ targetRuleId: 'rule-eval',
370
+ },
371
+ ];
372
+ const verdict = await fireAndScore({ rules: [evalRule()], prDiffs, post });
373
+ expect(verdict.verdict).toBe('FAIL');
374
+ expect(verdict.nonVacuity).toBe(false);
375
+ expect(verdict.precision).toBeNull();
376
+ });
377
+ it('unlabeled firing ⟹ HONEST-NEGATIVE (needsAdjudication)', async () => {
378
+ const post = [' debugger;'].join('\n'); // totem-ignore
379
+ const prDiffs = [
380
+ { pr: 1, diff: diffAdding([' debugger;']), controlKind: 'corpus' }, // totem-ignore
381
+ ];
382
+ const verdict = await fireAndScore({
383
+ rules: [debuggerRule()],
384
+ prDiffs,
385
+ post,
386
+ groundTruth: new Map(), // unlabeled
387
+ });
388
+ expect(verdict.verdict).toBe('HONEST-NEGATIVE');
389
+ expect(verdict.needsAdjudication).toHaveLength(1);
390
+ });
391
+ it('all-TP firings with exposure met ⟹ PASS', async () => {
392
+ const post = [' debugger;'].join('\n'); // totem-ignore
393
+ const prDiffs = [
394
+ { pr: 1, diff: diffAdding([' debugger;']), controlKind: 'corpus' }, // totem-ignore
395
+ ];
396
+ const built = await buildFirings({
397
+ rules: [debuggerRule()],
398
+ prDiffs,
399
+ cwd: '/repo',
400
+ readStrategy: fixedReadStrategy(post),
401
+ ruleEngineCtx: makeRuleEngineCtx(),
402
+ });
403
+ const tpLabel = built.firings[0].labelId;
404
+ const verdict = await fireAndScore({
405
+ rules: [debuggerRule()],
406
+ prDiffs,
407
+ post,
408
+ groundTruth: new Map([[tpLabel, 'TP']]),
409
+ });
410
+ expect(verdict.verdict).toBe('PASS');
411
+ expect(verdict.precision).toBe(1.0);
412
+ });
413
+ it('C2: real filesTouched below the floor ⟹ HONEST-NEGATIVE even when the other legs pass', async () => {
414
+ // One TP firing on a single file. The other two legs pass (activeRules ok,
415
+ // no positive controls required) but the filesTouchedInWindow floor is 5 and
416
+ // only 1 file is touched → the third leg demotes to HONEST-NEGATIVE.
417
+ const post = [' debugger;'].join('\n'); // totem-ignore
418
+ const prDiffs = [
419
+ { pr: 1, diff: diffAdding([' debugger;']), controlKind: 'corpus' }, // totem-ignore
420
+ ];
421
+ const built = await buildFirings({
422
+ rules: [debuggerRule()],
423
+ prDiffs,
424
+ cwd: '/repo',
425
+ readStrategy: fixedReadStrategy(post),
426
+ ruleEngineCtx: makeRuleEngineCtx(),
427
+ });
428
+ const tpLabel = built.firings[0].labelId;
429
+ const verdict = await fireAndScore({
430
+ rules: [debuggerRule()],
431
+ prDiffs,
432
+ post,
433
+ groundTruth: new Map([[tpLabel, 'TP']]),
434
+ exposureFloors: {
435
+ activeRulesEvaluated: 0,
436
+ filesTouchedInWindow: 5, // floor exceeds the 1 file actually touched
437
+ positiveControlsExercised: 0,
438
+ },
439
+ });
440
+ expect(built.filesTouchedInWindow).toBe(1);
441
+ expect(verdict.verdict).toBe('HONEST-NEGATIVE');
442
+ expect(verdict.precision).toBeNull();
443
+ });
444
+ });
445
+ //# sourceMappingURL=windtunnel-firing.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windtunnel-firing.test.js","sourceRoot":"","sources":["../../src/spine/windtunnel-firing.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"windtunnel-scorer.d.ts","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,iBAAiB,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,wBAAwB,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,qBAAqB,CAAC;IAC/B;;;;;;;OAOG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sHAAsH;IACtH,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;IACpB,wFAAwF;IACxF,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,uFAAuF;IACvF,WAAW,EAAE,qBAAqB,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;IAChD,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,+EAA+E;IAC/E,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,sBAAsB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE;QACd,oBAAoB,EAAE,MAAM,CAAC;QAC7B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IACF,cAAc,EAAE;QACd,oBAAoB,EAAE,MAAM,CAAC;QAC7B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;CACH;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,iBAAiB,CAoMrE"}
1
+ {"version":3,"file":"windtunnel-scorer.d.ts","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,iBAAiB,GAAG,MAAM,CAAC;AACxE,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,wBAAwB,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,qBAAqB,CAAC;IAC/B;;;;;;;OAOG;IACH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sHAAsH;IACtH,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,UAAU,EAAE,OAAO,CAAC;IACpB,wFAAwF;IACxF,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,uFAAuF;IACvF,WAAW,EAAE,qBAAqB,CAAC;CACpC;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,QAAQ,GAAG,UAAU,GAAG,UAAU,CAAC;IAChD,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,+EAA+E;IAC/E,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC3C,sBAAsB,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE;QACd,oBAAoB,EAAE,MAAM,CAAC;QAC7B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;IACF,cAAc,EAAE;QACd,oBAAoB,EAAE,MAAM,CAAC;QAC7B,oBAAoB,EAAE,MAAM,CAAC;QAC7B,yBAAyB,EAAE,MAAM,CAAC;KACnC,CAAC;CACH;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,WAAW,GAAG,iBAAiB,CA6MrE"}
@@ -121,10 +121,19 @@ export function scoreWindtunnel(input) {
121
121
  };
122
122
  }
123
123
  // ── Masquerade guards (may only DEMOTE a would-be PASS) ──
124
- // Step 5: Exposure floor (P2). activeRules/positiveControls below floor
124
+ // Step 5: Exposure floor (P2 + C2). All THREE exposure legs are enforced:
125
+ // activeRules / filesTouchedInWindow / positiveControls below their floor →
125
126
  // HONEST-NEGATIVE (no claim → precision null). Ranked above needs-adjudication
126
127
  // (Step 7): labeling won't rescue a sub-floor run (strategy-claude tie-break).
128
+ //
129
+ // C2 (5c-i): `filesTouchedInWindow` was previously omitted (the CLI passed a
130
+ // hard-coded 0, so the leg was inert). The certifying run computes real
131
+ // touched-file exposure from the corpus/diffs; this guard makes the third leg
132
+ // load-bearing — a sub-floor file exposure is a masquerade (the run scanned too
133
+ // little of the window to make a precision claim) and must demote to
134
+ // HONEST-NEGATIVE even when the other two legs pass.
127
135
  if (actualExposure.activeRulesEvaluated < exposureFloors.activeRulesEvaluated ||
136
+ actualExposure.filesTouchedInWindow < exposureFloors.filesTouchedInWindow ||
128
137
  actualExposure.positiveControlsExercised < exposureFloors.positiveControlsExercised) {
129
138
  return {
130
139
  verdict: 'HONEST-NEGATIVE',
@@ -1 +1 @@
1
- {"version":3,"file":"windtunnel-scorer.js","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"windtunnel-scorer.js","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.ts"],"names":[],"mappings":"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"}
@@ -165,6 +165,38 @@ describe('exposure floor check (P2)', () => {
165
165
  }));
166
166
  expect(result.verdict).toBe('PASS');
167
167
  });
168
+ // ── C2 (5c-i): the third exposure leg is now load-bearing ──
169
+ it('returns HONEST-NEGATIVE when filesTouchedInWindow < floor (C2 — third leg enforced)', () => {
170
+ const result = scoreWindtunnel(baseInput({
171
+ actualExposure: {
172
+ activeRulesEvaluated: 3, // passes
173
+ filesTouchedInWindow: 1, // BELOW floor
174
+ positiveControlsExercised: 2, // passes
175
+ },
176
+ exposureFloors: {
177
+ activeRulesEvaluated: 2,
178
+ filesTouchedInWindow: 5,
179
+ positiveControlsExercised: 2,
180
+ },
181
+ }));
182
+ expect(result.verdict).toBe('HONEST-NEGATIVE');
183
+ expect(result.precision).toBeNull();
184
+ });
185
+ it('passes when filesTouchedInWindow exactly equals floor (C2 equality boundary)', () => {
186
+ const result = scoreWindtunnel(baseInput({
187
+ actualExposure: {
188
+ activeRulesEvaluated: 3,
189
+ filesTouchedInWindow: 5,
190
+ positiveControlsExercised: 2,
191
+ },
192
+ exposureFloors: {
193
+ activeRulesEvaluated: 2,
194
+ filesTouchedInWindow: 5,
195
+ positiveControlsExercised: 2,
196
+ },
197
+ }));
198
+ expect(result.verdict).toBe('PASS');
199
+ });
168
200
  });
169
201
  // ─── Cull-rate guard → HONEST-NEGATIVE (C5/S2) ───────
170
202
  describe('cull-rate guard (C5/S2)', () => {