@mmnto/totem 1.64.2 → 1.66.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/ast-gate.d.ts +9 -0
- package/dist/ast-gate.d.ts.map +1 -1
- package/dist/ast-gate.js +64 -25
- package/dist/ast-gate.js.map +1 -1
- package/dist/ast-gate.test.js +47 -0
- package/dist/ast-gate.test.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/spine/windtunnel-lock.d.ts +440 -0
- package/dist/spine/windtunnel-lock.d.ts.map +1 -0
- package/dist/spine/windtunnel-lock.js +115 -0
- package/dist/spine/windtunnel-lock.js.map +1 -0
- package/dist/spine/windtunnel-lock.test.d.ts +2 -0
- package/dist/spine/windtunnel-lock.test.d.ts.map +1 -0
- package/dist/spine/windtunnel-lock.test.js +214 -0
- package/dist/spine/windtunnel-lock.test.js.map +1 -0
- package/dist/spine/windtunnel-parity.test.d.ts +2 -0
- package/dist/spine/windtunnel-parity.test.d.ts.map +1 -0
- package/dist/spine/windtunnel-parity.test.js +192 -0
- package/dist/spine/windtunnel-parity.test.js.map +1 -0
- package/dist/spine/windtunnel-scorer.d.ts +93 -0
- package/dist/spine/windtunnel-scorer.d.ts.map +1 -0
- package/dist/spine/windtunnel-scorer.js +191 -0
- package/dist/spine/windtunnel-scorer.js.map +1 -0
- package/dist/spine/windtunnel-scorer.test.d.ts +2 -0
- package/dist/spine/windtunnel-scorer.test.d.ts.map +1 -0
- package/dist/spine/windtunnel-scorer.test.js +533 -0
- package/dist/spine/windtunnel-scorer.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { firingLabelId } from './windtunnel-lock.js';
|
|
3
|
+
import { scoreWindtunnel } from './windtunnel-scorer.js';
|
|
4
|
+
// ─── Helpers ─────────────────────────────────────────
|
|
5
|
+
function makeFiring(ruleId, pr, controlKind, matchedLine = 'const x = 1;', filePath = 'src/foo.ts') {
|
|
6
|
+
return {
|
|
7
|
+
ruleId,
|
|
8
|
+
pr,
|
|
9
|
+
filePath,
|
|
10
|
+
matchedLine,
|
|
11
|
+
controlKind,
|
|
12
|
+
labelId: firingLabelId(ruleId, pr, filePath, matchedLine),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function baseInput(overrides) {
|
|
16
|
+
return {
|
|
17
|
+
firings: [],
|
|
18
|
+
groundTruth: new Map(),
|
|
19
|
+
positiveControlTargets: [],
|
|
20
|
+
mintedRuleIds: ['rule-a', 'rule-b'],
|
|
21
|
+
cullRateThreshold: 0.5,
|
|
22
|
+
exposureFloors: {
|
|
23
|
+
activeRulesEvaluated: 2,
|
|
24
|
+
filesTouchedInWindow: 0,
|
|
25
|
+
positiveControlsExercised: 0,
|
|
26
|
+
},
|
|
27
|
+
actualExposure: {
|
|
28
|
+
activeRulesEvaluated: 2,
|
|
29
|
+
filesTouchedInWindow: 5,
|
|
30
|
+
positiveControlsExercised: 1,
|
|
31
|
+
},
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// ─── FP label → FAIL ─────────────────────────────────
|
|
36
|
+
describe('FP label → FAIL', () => {
|
|
37
|
+
it('returns FAIL when any firing is labeled FP', () => {
|
|
38
|
+
const firing = makeFiring('rule-a', 1, 'corpus');
|
|
39
|
+
const gt = new Map([[firing.labelId, 'FP']]);
|
|
40
|
+
const result = scoreWindtunnel(baseInput({ firings: [firing], groundTruth: gt }));
|
|
41
|
+
expect(result.verdict).toBe('FAIL');
|
|
42
|
+
expect(result.precision).toBeLessThan(1);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
// ─── Non-vacuity → FAIL ──────────────────────────────
|
|
46
|
+
describe('positive control does not fire its target rule → FAIL', () => {
|
|
47
|
+
it('returns FAIL when positive control target rule never fires', () => {
|
|
48
|
+
const result = scoreWindtunnel(baseInput({
|
|
49
|
+
positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
|
|
50
|
+
firings: [],
|
|
51
|
+
}));
|
|
52
|
+
expect(result.verdict).toBe('FAIL');
|
|
53
|
+
expect(result.nonVacuity).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
it('returns PASS when positive control target rule fires', () => {
|
|
56
|
+
const firing = makeFiring('rule-a', 10, 'positive');
|
|
57
|
+
const gt = new Map([[firing.labelId, 'TP']]);
|
|
58
|
+
const result = scoreWindtunnel(baseInput({
|
|
59
|
+
positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
|
|
60
|
+
firings: [firing],
|
|
61
|
+
groundTruth: gt,
|
|
62
|
+
}));
|
|
63
|
+
expect(result.verdict).toBe('PASS');
|
|
64
|
+
expect(result.nonVacuity).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
// ─── Negative control → culled + recorded ────────────
|
|
68
|
+
describe('negative control fires → culled and recorded in cullLedger', () => {
|
|
69
|
+
it('culls the rule and records in cullLedger (not silently dropped)', () => {
|
|
70
|
+
const firing = makeFiring('rule-a', 99, 'negative', 'near-miss line');
|
|
71
|
+
const result = scoreWindtunnel(baseInput({ firings: [firing] }));
|
|
72
|
+
expect(result.culledCount).toBe(1);
|
|
73
|
+
expect(result.cullLedger).toHaveLength(1);
|
|
74
|
+
expect(result.cullLedger[0].ruleId).toBe('rule-a');
|
|
75
|
+
expect(result.cullLedger[0].reason).toBe('negative-control-fired');
|
|
76
|
+
});
|
|
77
|
+
it('does not count a culled rule as a surviving rule', () => {
|
|
78
|
+
const firing = makeFiring('rule-a', 99, 'negative');
|
|
79
|
+
const result = scoreWindtunnel(baseInput({ firings: [firing], mintedRuleIds: ['rule-a', 'rule-b'] }));
|
|
80
|
+
expect(result.mintedRuleCount).toBe(2);
|
|
81
|
+
expect(result.culledCount).toBe(1);
|
|
82
|
+
expect(result.survivingRuleCount).toBe(1);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
// ─── Unlabeled firing → needsAdjudication (not PASS) ─
|
|
86
|
+
describe('unlabeled firing → needsAdjudication, not PASS', () => {
|
|
87
|
+
it('returns HONEST-NEGATIVE with firing in needsAdjudication when label is missing', () => {
|
|
88
|
+
const firing = makeFiring('rule-a', 1, 'corpus');
|
|
89
|
+
// No groundTruth entry for this firing
|
|
90
|
+
const result = scoreWindtunnel(baseInput({ firings: [firing], groundTruth: new Map() }));
|
|
91
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
92
|
+
expect(result.needsAdjudication).toContain(firing.labelId);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
// ─── Exposure floor trip → HONEST-NEGATIVE (P2) ──────
|
|
96
|
+
describe('exposure floor check (P2)', () => {
|
|
97
|
+
it('returns HONEST-NEGATIVE when activeRules < floor', () => {
|
|
98
|
+
const result = scoreWindtunnel(baseInput({
|
|
99
|
+
actualExposure: {
|
|
100
|
+
activeRulesEvaluated: 1,
|
|
101
|
+
filesTouchedInWindow: 5,
|
|
102
|
+
positiveControlsExercised: 0,
|
|
103
|
+
},
|
|
104
|
+
exposureFloors: {
|
|
105
|
+
activeRulesEvaluated: 2,
|
|
106
|
+
filesTouchedInWindow: 0,
|
|
107
|
+
positiveControlsExercised: 0,
|
|
108
|
+
},
|
|
109
|
+
}));
|
|
110
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
111
|
+
});
|
|
112
|
+
it('returns PASS when activeRules exactly equals floor = 2 (P2 equality boundary)', () => {
|
|
113
|
+
const result = scoreWindtunnel(baseInput({
|
|
114
|
+
actualExposure: {
|
|
115
|
+
activeRulesEvaluated: 2,
|
|
116
|
+
filesTouchedInWindow: 5,
|
|
117
|
+
positiveControlsExercised: 0,
|
|
118
|
+
},
|
|
119
|
+
exposureFloors: {
|
|
120
|
+
activeRulesEvaluated: 2,
|
|
121
|
+
filesTouchedInWindow: 0,
|
|
122
|
+
positiveControlsExercised: 0,
|
|
123
|
+
},
|
|
124
|
+
}));
|
|
125
|
+
// All firings empty + labeled TP by default → PASS
|
|
126
|
+
expect(result.verdict).toBe('PASS');
|
|
127
|
+
});
|
|
128
|
+
it('returns HONEST-NEGATIVE when activeRules = 1 (below floor 2, P2)', () => {
|
|
129
|
+
const result = scoreWindtunnel(baseInput({
|
|
130
|
+
actualExposure: {
|
|
131
|
+
activeRulesEvaluated: 1,
|
|
132
|
+
filesTouchedInWindow: 0,
|
|
133
|
+
positiveControlsExercised: 0,
|
|
134
|
+
},
|
|
135
|
+
}));
|
|
136
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
137
|
+
});
|
|
138
|
+
it('returns HONEST-NEGATIVE when positiveControls < positiveControlsExercised floor', () => {
|
|
139
|
+
const result = scoreWindtunnel(baseInput({
|
|
140
|
+
actualExposure: {
|
|
141
|
+
activeRulesEvaluated: 3,
|
|
142
|
+
filesTouchedInWindow: 5,
|
|
143
|
+
positiveControlsExercised: 0,
|
|
144
|
+
},
|
|
145
|
+
exposureFloors: {
|
|
146
|
+
activeRulesEvaluated: 2,
|
|
147
|
+
filesTouchedInWindow: 0,
|
|
148
|
+
positiveControlsExercised: 2,
|
|
149
|
+
},
|
|
150
|
+
}));
|
|
151
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
152
|
+
});
|
|
153
|
+
it('passes when positiveControls exactly equals floor (P2 equality boundary)', () => {
|
|
154
|
+
const result = scoreWindtunnel(baseInput({
|
|
155
|
+
actualExposure: {
|
|
156
|
+
activeRulesEvaluated: 3,
|
|
157
|
+
filesTouchedInWindow: 5,
|
|
158
|
+
positiveControlsExercised: 2,
|
|
159
|
+
},
|
|
160
|
+
exposureFloors: {
|
|
161
|
+
activeRulesEvaluated: 2,
|
|
162
|
+
filesTouchedInWindow: 0,
|
|
163
|
+
positiveControlsExercised: 2,
|
|
164
|
+
},
|
|
165
|
+
}));
|
|
166
|
+
expect(result.verdict).toBe('PASS');
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
// ─── Cull-rate guard → HONEST-NEGATIVE (C5/S2) ───────
|
|
170
|
+
describe('cull-rate guard (C5/S2)', () => {
|
|
171
|
+
it('returns HONEST-NEGATIVE when cull rate exceeds threshold', () => {
|
|
172
|
+
// 2 minted, 2 culled → rate = 1.0 > threshold 0.5
|
|
173
|
+
const firingA = makeFiring('rule-a', 99, 'negative');
|
|
174
|
+
const firingB = makeFiring('rule-b', 99, 'negative', 'other line');
|
|
175
|
+
const result = scoreWindtunnel(baseInput({
|
|
176
|
+
firings: [firingA, firingB],
|
|
177
|
+
mintedRuleIds: ['rule-a', 'rule-b'],
|
|
178
|
+
cullRateThreshold: 0.5,
|
|
179
|
+
}));
|
|
180
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
181
|
+
expect(result.culledCount).toBe(2);
|
|
182
|
+
// precision is the NULL not-computed sentinel on a no-claim verdict (#2189
|
|
183
|
+
// ruling) — NEVER 0 (a real all-FP value) and NEVER a survival ratio. Locks
|
|
184
|
+
// the greptile-P1 / CR fix + the strategy-claude 2026-06-17 sentinel ruling.
|
|
185
|
+
expect(result.precision).toBeNull();
|
|
186
|
+
});
|
|
187
|
+
it('does not apply cull-rate guard when mintedRuleCount = 0 (harness phase)', () => {
|
|
188
|
+
const result = scoreWindtunnel(baseInput({
|
|
189
|
+
mintedRuleIds: [],
|
|
190
|
+
firings: [],
|
|
191
|
+
cullRateThreshold: 0.0,
|
|
192
|
+
// Need actualExposure to pass floor check even with 0 minted
|
|
193
|
+
exposureFloors: {
|
|
194
|
+
activeRulesEvaluated: 0,
|
|
195
|
+
filesTouchedInWindow: 0,
|
|
196
|
+
positiveControlsExercised: 0,
|
|
197
|
+
},
|
|
198
|
+
actualExposure: {
|
|
199
|
+
activeRulesEvaluated: 0,
|
|
200
|
+
filesTouchedInWindow: 0,
|
|
201
|
+
positiveControlsExercised: 0,
|
|
202
|
+
},
|
|
203
|
+
}));
|
|
204
|
+
// No minted rules, no firings → PASS (vacuous but valid for harness)
|
|
205
|
+
expect(result.verdict).toBe('PASS');
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
// ─── #2189 ruling: FAIL outranks the masquerade guards ──
|
|
209
|
+
//
|
|
210
|
+
// strategy-claude verdict-semantics RULING (2026-06-17): a confirmed FP — or a
|
|
211
|
+
// vacuous positive control — is a *claim*, not a no-claim. It must FAIL even
|
|
212
|
+
// when an exposure-floor / cull-rate masquerade guard would otherwise return
|
|
213
|
+
// HONEST-NEGATIVE. The guards may only DEMOTE a would-be PASS; they may never
|
|
214
|
+
// UPGRADE a FAIL. Under the pre-#2189 order these returned HONEST-NEGATIVE.
|
|
215
|
+
describe('#2189: FAIL precedence outranks the masquerade guards', () => {
|
|
216
|
+
it('unconditionally evaluates to FAIL when a firing is labeled FP, ignoring a sub-floor exposure', () => {
|
|
217
|
+
const fp = makeFiring('rule-a', 1, 'corpus', '// const secret = "x"');
|
|
218
|
+
const gt = new Map([[fp.labelId, 'FP']]);
|
|
219
|
+
const result = scoreWindtunnel(baseInput({
|
|
220
|
+
firings: [fp],
|
|
221
|
+
groundTruth: gt,
|
|
222
|
+
// sub-floor exposure that WOULD trip HONEST-NEGATIVE first under the old order
|
|
223
|
+
actualExposure: {
|
|
224
|
+
activeRulesEvaluated: 1,
|
|
225
|
+
filesTouchedInWindow: 0,
|
|
226
|
+
positiveControlsExercised: 0,
|
|
227
|
+
},
|
|
228
|
+
exposureFloors: {
|
|
229
|
+
activeRulesEvaluated: 2,
|
|
230
|
+
filesTouchedInWindow: 0,
|
|
231
|
+
positiveControlsExercised: 0,
|
|
232
|
+
},
|
|
233
|
+
}));
|
|
234
|
+
expect(result.verdict).toBe('FAIL');
|
|
235
|
+
});
|
|
236
|
+
it('evaluates to FAIL when a firing is labeled FP, ignoring an over-threshold cull rate', () => {
|
|
237
|
+
// rule-a culled on a negative control (1/2 = 0.5 > threshold 0.4 → cull-rate HN
|
|
238
|
+
// under the old order); rule-b (surviving) fires a confirmed FP → must FAIL.
|
|
239
|
+
const culled = makeFiring('rule-a', 99, 'negative');
|
|
240
|
+
const fp = makeFiring('rule-b', 1, 'corpus', 'fp line');
|
|
241
|
+
const gt = new Map([[fp.labelId, 'FP']]);
|
|
242
|
+
const result = scoreWindtunnel(baseInput({
|
|
243
|
+
firings: [culled, fp],
|
|
244
|
+
mintedRuleIds: ['rule-a', 'rule-b'],
|
|
245
|
+
groundTruth: gt,
|
|
246
|
+
cullRateThreshold: 0.4,
|
|
247
|
+
}));
|
|
248
|
+
expect(result.verdict).toBe('FAIL');
|
|
249
|
+
});
|
|
250
|
+
it('evaluates to FAIL on a vacuous positive control even under a sub-floor exposure', () => {
|
|
251
|
+
const result = scoreWindtunnel(baseInput({
|
|
252
|
+
positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
|
|
253
|
+
firings: [], // target never fires → vacuous
|
|
254
|
+
actualExposure: {
|
|
255
|
+
activeRulesEvaluated: 1,
|
|
256
|
+
filesTouchedInWindow: 0,
|
|
257
|
+
positiveControlsExercised: 0,
|
|
258
|
+
},
|
|
259
|
+
exposureFloors: {
|
|
260
|
+
activeRulesEvaluated: 2,
|
|
261
|
+
filesTouchedInWindow: 0,
|
|
262
|
+
positiveControlsExercised: 0,
|
|
263
|
+
},
|
|
264
|
+
}));
|
|
265
|
+
expect(result.verdict).toBe('FAIL');
|
|
266
|
+
expect(result.nonVacuity).toBe(false);
|
|
267
|
+
});
|
|
268
|
+
it('FP takes precedence over a vacuous positive control when both occur', () => {
|
|
269
|
+
// A confirmed FP on a corpus firing AND a positive control whose target
|
|
270
|
+
// never fires (vacuous). Step 4a (FP) precedes Step 4b (vacuous): the
|
|
271
|
+
// verdict is FAIL with the breaching precision 0.5 — NOT null (which the
|
|
272
|
+
// vacuous-control FAIL would have returned).
|
|
273
|
+
const fp = makeFiring('rule-b', 1, 'corpus', 'fp');
|
|
274
|
+
const tp = makeFiring('rule-c', 2, 'corpus', 'tp');
|
|
275
|
+
const result = scoreWindtunnel(baseInput({
|
|
276
|
+
firings: [fp, tp],
|
|
277
|
+
mintedRuleIds: ['rule-a', 'rule-b', 'rule-c'],
|
|
278
|
+
groundTruth: new Map([
|
|
279
|
+
[fp.labelId, 'FP'],
|
|
280
|
+
[tp.labelId, 'TP'],
|
|
281
|
+
]),
|
|
282
|
+
positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
|
|
283
|
+
}));
|
|
284
|
+
expect(result.verdict).toBe('FAIL');
|
|
285
|
+
expect(result.nonVacuity).toBe(false);
|
|
286
|
+
expect(result.precision).toBe(0.5);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
// ─── #2189 ruling: precision is a null no-claim sentinel ─
|
|
290
|
+
//
|
|
291
|
+
// precision carries a real value ONLY on verdicts that make a precision claim —
|
|
292
|
+
// PASS (1.0) and confirmed-FP FAIL (the breaching value, which IS the evidence).
|
|
293
|
+
// On every no-claim verdict it is null — NEVER 0 (a real all-FP value).
|
|
294
|
+
describe('#2189: precision null-sentinel on no-claim verdicts', () => {
|
|
295
|
+
it('precision is null on an exposure-floor HONEST-NEGATIVE', () => {
|
|
296
|
+
const result = scoreWindtunnel(baseInput({
|
|
297
|
+
actualExposure: {
|
|
298
|
+
activeRulesEvaluated: 1,
|
|
299
|
+
filesTouchedInWindow: 0,
|
|
300
|
+
positiveControlsExercised: 0,
|
|
301
|
+
},
|
|
302
|
+
exposureFloors: {
|
|
303
|
+
activeRulesEvaluated: 2,
|
|
304
|
+
filesTouchedInWindow: 0,
|
|
305
|
+
positiveControlsExercised: 0,
|
|
306
|
+
},
|
|
307
|
+
}));
|
|
308
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
309
|
+
expect(result.precision).toBeNull();
|
|
310
|
+
});
|
|
311
|
+
it('precision is null on a needs-adjudication HONEST-NEGATIVE', () => {
|
|
312
|
+
const firing = makeFiring('rule-a', 1, 'corpus');
|
|
313
|
+
const result = scoreWindtunnel(baseInput({ firings: [firing], groundTruth: new Map() }));
|
|
314
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
315
|
+
expect(result.needsAdjudication).toContain(firing.labelId);
|
|
316
|
+
expect(result.precision).toBeNull();
|
|
317
|
+
});
|
|
318
|
+
it('precision is null on a vacuous-control FAIL (structural failure, no precision claim — Q-A)', () => {
|
|
319
|
+
const result = scoreWindtunnel(baseInput({ positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }], firings: [] }));
|
|
320
|
+
expect(result.verdict).toBe('FAIL');
|
|
321
|
+
expect(result.precision).toBeNull();
|
|
322
|
+
});
|
|
323
|
+
it('precision is a real value on PASS (1.0) and on FP-FAIL (the breaching value, never null)', () => {
|
|
324
|
+
const tp = makeFiring('rule-a', 1, 'corpus');
|
|
325
|
+
const pass = scoreWindtunnel(baseInput({ firings: [tp], groundTruth: new Map([[tp.labelId, 'TP']]) }));
|
|
326
|
+
expect(pass.verdict).toBe('PASS');
|
|
327
|
+
expect(pass.precision).toBe(1.0);
|
|
328
|
+
// 1 FP + 1 TP → breaching precision 0.5, a real number (the evidence)
|
|
329
|
+
const fp = makeFiring('rule-a', 2, 'corpus', 'fp');
|
|
330
|
+
const tp2 = makeFiring('rule-b', 3, 'corpus', 'tp');
|
|
331
|
+
const fail = scoreWindtunnel(baseInput({
|
|
332
|
+
firings: [fp, tp2],
|
|
333
|
+
groundTruth: new Map([
|
|
334
|
+
[fp.labelId, 'FP'],
|
|
335
|
+
[tp2.labelId, 'TP'],
|
|
336
|
+
]),
|
|
337
|
+
}));
|
|
338
|
+
expect(fail.verdict).toBe('FAIL');
|
|
339
|
+
expect(fail.precision).toBe(0.5);
|
|
340
|
+
});
|
|
341
|
+
it('precision is 0 (a real all-FP measurement, never the not-computed sentinel) when every labeled firing is FP', () => {
|
|
342
|
+
// The ruling reserves 0 for a REAL all-FP value (precision = 0/N). A pure
|
|
343
|
+
// all-FP run must report precision === 0, distinct from the null sentinel
|
|
344
|
+
// — a regression that re-introduced 0-as-"not-computed" would break here.
|
|
345
|
+
const fpA = makeFiring('rule-a', 1, 'corpus', 'fp a');
|
|
346
|
+
const fpB = makeFiring('rule-b', 2, 'corpus', 'fp b');
|
|
347
|
+
const result = scoreWindtunnel(baseInput({
|
|
348
|
+
firings: [fpA, fpB],
|
|
349
|
+
mintedRuleIds: ['rule-a', 'rule-b'],
|
|
350
|
+
groundTruth: new Map([
|
|
351
|
+
[fpA.labelId, 'FP'],
|
|
352
|
+
[fpB.labelId, 'FP'],
|
|
353
|
+
]),
|
|
354
|
+
}));
|
|
355
|
+
expect(result.verdict).toBe('FAIL');
|
|
356
|
+
expect(result.precision).toBe(0);
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
// ─── #2189 ruling: diagnostics.survivorPrecision is separate ─
|
|
360
|
+
//
|
|
361
|
+
// CR's survivor-precision is informative ("culled 8/10, the 2 survivors were
|
|
362
|
+
// clean") but must NOT live on the certifying field. It is descriptive and
|
|
363
|
+
// distinct from `precision`.
|
|
364
|
+
describe('#2189: diagnostics.survivorPrecision is a separate descriptive field', () => {
|
|
365
|
+
it('carries the survivor ratio on a HONEST-NEGATIVE while certifying precision stays null', () => {
|
|
366
|
+
// Cull rule-a (over-threshold cull rate), survivor rule-b fires clean TP →
|
|
367
|
+
// survivor ratio 1.0, but the verdict is a no-claim HONEST-NEGATIVE so the
|
|
368
|
+
// certifying precision is null.
|
|
369
|
+
const culled = makeFiring('rule-a', 99, 'negative');
|
|
370
|
+
const survivorTp = makeFiring('rule-b', 1, 'corpus', 'clean');
|
|
371
|
+
const result = scoreWindtunnel(baseInput({
|
|
372
|
+
firings: [culled, survivorTp],
|
|
373
|
+
mintedRuleIds: ['rule-a', 'rule-b'],
|
|
374
|
+
groundTruth: new Map([[survivorTp.labelId, 'TP']]),
|
|
375
|
+
cullRateThreshold: 0.4, // 1/2 = 0.5 > 0.4 → cull-rate HONEST-NEGATIVE
|
|
376
|
+
}));
|
|
377
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
378
|
+
expect(result.precision).toBeNull();
|
|
379
|
+
expect(result.diagnostics.survivorPrecision).toBe(1.0);
|
|
380
|
+
});
|
|
381
|
+
it('survivorPrecision is null when no surviving firing is labeled', () => {
|
|
382
|
+
const result = scoreWindtunnel(baseInput({ firings: [] }));
|
|
383
|
+
expect(result.diagnostics.survivorPrecision).toBeNull();
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
// ─── exposureTuple is always a 3-tuple (never collapsed) ─
|
|
387
|
+
describe('exposureTuple invariant', () => {
|
|
388
|
+
it('emits a 3-tuple, never collapsed to a product', () => {
|
|
389
|
+
const result = scoreWindtunnel(baseInput());
|
|
390
|
+
expect(Array.isArray(result.exposureTuple)).toBe(true);
|
|
391
|
+
expect(result.exposureTuple).toHaveLength(3);
|
|
392
|
+
expect(typeof result.exposureTuple[0]).toBe('number');
|
|
393
|
+
expect(typeof result.exposureTuple[1]).toBe('number');
|
|
394
|
+
expect(typeof result.exposureTuple[2]).toBe('number');
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
// ─── Precision over surviving rules (S2) ─────────────
|
|
398
|
+
describe('precision is over surviving rules (S2)', () => {
|
|
399
|
+
it('labels precision as over surviving rules after culling', () => {
|
|
400
|
+
const culled = makeFiring('rule-a', 99, 'negative');
|
|
401
|
+
const tp = makeFiring('rule-b', 1, 'corpus');
|
|
402
|
+
const gt = new Map([[tp.labelId, 'TP']]);
|
|
403
|
+
const result = scoreWindtunnel(baseInput({
|
|
404
|
+
firings: [culled, tp],
|
|
405
|
+
mintedRuleIds: ['rule-a', 'rule-b'],
|
|
406
|
+
groundTruth: gt,
|
|
407
|
+
cullRateThreshold: 0.9,
|
|
408
|
+
}));
|
|
409
|
+
expect(result.verdict).toBe('PASS');
|
|
410
|
+
expect(result.precision).toBe(1.0);
|
|
411
|
+
expect(result.culledCount).toBe(1);
|
|
412
|
+
expect(result.survivingRuleCount).toBe(1);
|
|
413
|
+
});
|
|
414
|
+
});
|
|
415
|
+
// ─── Mock engine: always-0 fires → FAIL vacuity ──────
|
|
416
|
+
describe('OQ2: mock engine coverage', () => {
|
|
417
|
+
it('mock always-0 engine: positive control target never fires → FAIL', () => {
|
|
418
|
+
// Always-0 engine: no firings. Positive control target expects rule-a.
|
|
419
|
+
const result = scoreWindtunnel(baseInput({
|
|
420
|
+
firings: [], // always-0: never fires
|
|
421
|
+
positiveControlTargets: [{ pr: 1, targetRuleId: 'rule-a' }],
|
|
422
|
+
}));
|
|
423
|
+
expect(result.verdict).toBe('FAIL');
|
|
424
|
+
});
|
|
425
|
+
it('mock always-1 engine: fires on negative control → culled, possibly HONEST-NEGATIVE', () => {
|
|
426
|
+
// Always-1 engine fires on the negative control
|
|
427
|
+
const negFiring = makeFiring('rule-a', 99, 'negative', 'near-miss');
|
|
428
|
+
const result = scoreWindtunnel(baseInput({
|
|
429
|
+
firings: [negFiring],
|
|
430
|
+
mintedRuleIds: ['rule-a'],
|
|
431
|
+
cullRateThreshold: 0.5,
|
|
432
|
+
}));
|
|
433
|
+
// 1 minted, 1 culled → rate = 1.0 > 0.5 → HONEST-NEGATIVE
|
|
434
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
435
|
+
expect(result.cullLedger).toHaveLength(1);
|
|
436
|
+
});
|
|
437
|
+
it('mock exposure-floor-trip engine → HONEST-NEGATIVE', () => {
|
|
438
|
+
const result = scoreWindtunnel(baseInput({
|
|
439
|
+
actualExposure: {
|
|
440
|
+
activeRulesEvaluated: 1,
|
|
441
|
+
filesTouchedInWindow: 0,
|
|
442
|
+
positiveControlsExercised: 0,
|
|
443
|
+
},
|
|
444
|
+
exposureFloors: {
|
|
445
|
+
activeRulesEvaluated: 2,
|
|
446
|
+
filesTouchedInWindow: 0,
|
|
447
|
+
positiveControlsExercised: 0,
|
|
448
|
+
},
|
|
449
|
+
}));
|
|
450
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
451
|
+
});
|
|
452
|
+
it('mock unlabeled-firing engine → needs-adjudication HONEST-NEGATIVE', () => {
|
|
453
|
+
const firing = makeFiring('rule-a', 5, 'corpus', 'some matched line');
|
|
454
|
+
// No groundTruth labels → unlabeled
|
|
455
|
+
const result = scoreWindtunnel(baseInput({
|
|
456
|
+
firings: [firing],
|
|
457
|
+
groundTruth: new Map(),
|
|
458
|
+
}));
|
|
459
|
+
expect(result.verdict).toBe('HONEST-NEGATIVE');
|
|
460
|
+
expect(result.needsAdjudication).toHaveLength(1);
|
|
461
|
+
expect(result.needsAdjudication[0]).toBe(firing.labelId);
|
|
462
|
+
});
|
|
463
|
+
it('mock perfect engine: all TPs, positive control fires, exposure met → PASS', () => {
|
|
464
|
+
const corpusFiring = makeFiring('rule-a', 1, 'corpus', 'pattern match');
|
|
465
|
+
const positiveFiring = makeFiring('rule-a', 10, 'positive', 'target match');
|
|
466
|
+
const gt = new Map([
|
|
467
|
+
[corpusFiring.labelId, 'TP'],
|
|
468
|
+
[positiveFiring.labelId, 'TP'],
|
|
469
|
+
]);
|
|
470
|
+
const result = scoreWindtunnel(baseInput({
|
|
471
|
+
firings: [corpusFiring, positiveFiring],
|
|
472
|
+
groundTruth: gt,
|
|
473
|
+
positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
|
|
474
|
+
}));
|
|
475
|
+
expect(result.verdict).toBe('PASS');
|
|
476
|
+
expect(result.precision).toBe(1.0);
|
|
477
|
+
expect(result.nonVacuity).toBe(true);
|
|
478
|
+
});
|
|
479
|
+
});
|
|
480
|
+
// ─── Scorer-level FP handling (NOT the parity test) ──
|
|
481
|
+
//
|
|
482
|
+
// The real bidirectional firing-parity test (S1+C1) — replay firings ==
|
|
483
|
+
// production firings through enrichWithAstContext + the rule engine, covering
|
|
484
|
+
// both the regex/astContext over-fire suppression and the AST whole-file
|
|
485
|
+
// under-fire cases — lives in `windtunnel-parity.test.ts`. That test exercises
|
|
486
|
+
// the production classification path end-to-end; the case below only confirms
|
|
487
|
+
// the scorer turns a labeled FP into a FAIL verdict.
|
|
488
|
+
describe('scorer FP handling (see windtunnel-parity.test.ts for the real S1+C1 parity test)', () => {
|
|
489
|
+
it('a firing labeled FP (e.g. a comment-context match) yields FAIL with precision < 1', () => {
|
|
490
|
+
const firing = makeFiring('rule-a', 1, 'corpus', '// const secret = "abc"');
|
|
491
|
+
const gt = new Map([[firing.labelId, 'FP']]);
|
|
492
|
+
const result = scoreWindtunnel(baseInput({ firings: [firing], groundTruth: gt }));
|
|
493
|
+
expect(result.verdict).toBe('FAIL');
|
|
494
|
+
expect(result.precision).toBeLessThan(1.0);
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
// ─── Label identity (A2) ─────────────────────────────
|
|
498
|
+
describe('content-based firing label id (A2)', () => {
|
|
499
|
+
it('same content → same label id (deterministic)', () => {
|
|
500
|
+
const id1 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const x = 1;');
|
|
501
|
+
const id2 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const x = 1;');
|
|
502
|
+
expect(id1).toBe(id2);
|
|
503
|
+
});
|
|
504
|
+
it('different matched line → different label id (survives line-drift)', () => {
|
|
505
|
+
const id1 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const x = 1;');
|
|
506
|
+
const id2 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const y = 2;');
|
|
507
|
+
expect(id1).not.toBe(id2);
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
// ─── Phase (P1) ──────────────────────────────────────
|
|
511
|
+
describe('phase discrimination (P1)', () => {
|
|
512
|
+
it('harness lock emits PASS at harness phase with zero minted rules', () => {
|
|
513
|
+
// Harness phase: mintedRuleCount ≈ 0, exposureFloors allow it
|
|
514
|
+
const result = scoreWindtunnel(baseInput({
|
|
515
|
+
mintedRuleIds: [],
|
|
516
|
+
firings: [],
|
|
517
|
+
exposureFloors: {
|
|
518
|
+
activeRulesEvaluated: 0,
|
|
519
|
+
filesTouchedInWindow: 0,
|
|
520
|
+
positiveControlsExercised: 0,
|
|
521
|
+
},
|
|
522
|
+
actualExposure: {
|
|
523
|
+
activeRulesEvaluated: 0,
|
|
524
|
+
filesTouchedInWindow: 0,
|
|
525
|
+
positiveControlsExercised: 0,
|
|
526
|
+
},
|
|
527
|
+
}));
|
|
528
|
+
// Zero rules, zero firings → vacuous PASS (valid for harness)
|
|
529
|
+
expect(result.verdict).toBe('PASS');
|
|
530
|
+
expect(result.mintedRuleCount).toBe(0);
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
//# sourceMappingURL=windtunnel-scorer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windtunnel-scorer.test.js","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.test.ts"],"names":[],"mappings":"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"}
|