@mmnto/totem 1.64.1 → 1.65.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 (41) hide show
  1. package/dist/ast-gate.d.ts +9 -0
  2. package/dist/ast-gate.d.ts.map +1 -1
  3. package/dist/ast-gate.js +64 -25
  4. package/dist/ast-gate.js.map +1 -1
  5. package/dist/ast-gate.test.js +47 -0
  6. package/dist/ast-gate.test.js.map +1 -1
  7. package/dist/compiler-schema.d.ts +329 -0
  8. package/dist/compiler-schema.d.ts.map +1 -1
  9. package/dist/compiler-schema.js +136 -1
  10. package/dist/compiler-schema.js.map +1 -1
  11. package/dist/compiler-schema.test.js +136 -1
  12. package/dist/compiler-schema.test.js.map +1 -1
  13. package/dist/compiler.d.ts +2 -2
  14. package/dist/compiler.d.ts.map +1 -1
  15. package/dist/compiler.js +1 -1
  16. package/dist/compiler.js.map +1 -1
  17. package/dist/index.d.ts +6 -2
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/spine/windtunnel-lock.d.ts +440 -0
  22. package/dist/spine/windtunnel-lock.d.ts.map +1 -0
  23. package/dist/spine/windtunnel-lock.js +115 -0
  24. package/dist/spine/windtunnel-lock.js.map +1 -0
  25. package/dist/spine/windtunnel-lock.test.d.ts +2 -0
  26. package/dist/spine/windtunnel-lock.test.d.ts.map +1 -0
  27. package/dist/spine/windtunnel-lock.test.js +214 -0
  28. package/dist/spine/windtunnel-lock.test.js.map +1 -0
  29. package/dist/spine/windtunnel-parity.test.d.ts +2 -0
  30. package/dist/spine/windtunnel-parity.test.d.ts.map +1 -0
  31. package/dist/spine/windtunnel-parity.test.js +192 -0
  32. package/dist/spine/windtunnel-parity.test.js.map +1 -0
  33. package/dist/spine/windtunnel-scorer.d.ts +70 -0
  34. package/dist/spine/windtunnel-scorer.d.ts.map +1 -0
  35. package/dist/spine/windtunnel-scorer.js +176 -0
  36. package/dist/spine/windtunnel-scorer.js.map +1 -0
  37. package/dist/spine/windtunnel-scorer.test.d.ts +2 -0
  38. package/dist/spine/windtunnel-scorer.test.d.ts.map +1 -0
  39. package/dist/spine/windtunnel-scorer.test.js +354 -0
  40. package/dist/spine/windtunnel-scorer.test.js.map +1 -0
  41. package/package.json +1 -1
@@ -0,0 +1,176 @@
1
+ // ─── Types ──────────────────────────────────────────
2
+ // ─── Pure scorer ─────────────────────────────────────
3
+ /**
4
+ * Score a wind-tunnel run. Pure function: no IO, no clock, no randomness.
5
+ * Implements ADR-110 §4/§5 done-criterion exactly per spec invariants.
6
+ *
7
+ * Verdict ordering (highest precedence first):
8
+ * 1. Exposure floor below minimum → HONEST-NEGATIVE (masquerade guard)
9
+ * 2. Cull rate exceeds threshold → HONEST-NEGATIVE (cull-laundering guard)
10
+ * 3. Positive control does not fire its target → FAIL (vacuous pass)
11
+ * 4. Any firing labeled FP → FAIL (precision < 1.0)
12
+ * 5. Any unlabeled firing → HONEST-NEGATIVE (needs adjudication, not PASS)
13
+ * 6. All labeled TP → PASS
14
+ */
15
+ export function scoreWindtunnel(input) {
16
+ const { firings, groundTruth, positiveControlTargets, mintedRuleIds, cullRateThreshold, exposureFloors, actualExposure, } = input;
17
+ const mintedRuleCount = mintedRuleIds.length;
18
+ const cullLedger = [];
19
+ const needsAdjudication = [];
20
+ // Step 1: Cull rules that fire on negative controls (S2/C5).
21
+ // A rule firing on ANY negative-control item is culled + recorded in
22
+ // cullLedger. Never silently dropped.
23
+ const culledRuleIds = new Set();
24
+ for (const firing of firings) {
25
+ if (firing.controlKind === 'negative') {
26
+ culledRuleIds.add(firing.ruleId);
27
+ cullLedger.push({
28
+ ruleId: firing.ruleId,
29
+ pr: firing.pr,
30
+ filePath: firing.filePath.replace(/\\/g, '/'),
31
+ matchedLine: firing.matchedLine,
32
+ reason: 'negative-control-fired',
33
+ });
34
+ }
35
+ }
36
+ const culledCount = culledRuleIds.size;
37
+ const survivingRuleCount = mintedRuleCount - culledCount;
38
+ // Exposure tuple: always a 3-tuple, never collapsed (spec invariant).
39
+ const exposureTuple = [
40
+ actualExposure.activeRulesEvaluated,
41
+ actualExposure.filesTouchedInWindow,
42
+ actualExposure.positiveControlsExercised,
43
+ ];
44
+ // Step 2: Exposure floor check (P2).
45
+ // activeRules < floor or positiveControls < floor → HONEST-NEGATIVE.
46
+ if (actualExposure.activeRulesEvaluated < exposureFloors.activeRulesEvaluated ||
47
+ actualExposure.positiveControlsExercised < exposureFloors.positiveControlsExercised) {
48
+ return {
49
+ verdict: 'HONEST-NEGATIVE',
50
+ precision: 0,
51
+ mintedRuleCount,
52
+ culledCount,
53
+ survivingRuleCount,
54
+ exposureTuple,
55
+ cullLedger,
56
+ nonVacuity: false,
57
+ needsAdjudication,
58
+ };
59
+ }
60
+ // Step 3: Cull-rate guard (C5/S2).
61
+ // culledCount / mintedRuleCount > threshold → HONEST-NEGATIVE.
62
+ // Guard applies only when mintedRuleCount > 0 (avoids division by zero at
63
+ // harness phase where mintedRuleCount ≈ 0).
64
+ if (mintedRuleCount > 0 && culledCount / mintedRuleCount > cullRateThreshold) {
65
+ return {
66
+ verdict: 'HONEST-NEGATIVE',
67
+ // precision is NOT computed here (this returns before FP/TP adjudication
68
+ // at Step 5), so report the same "not-computed" sentinel the exposure-floor
69
+ // HONEST-NEGATIVE path uses (0) — never a survival ratio mislabeled as
70
+ // precision. Whether a HONEST-NEGATIVE should instead carry the real
71
+ // precision-over-survivors is a §4/§5 contract question deferred to #2189.
72
+ precision: 0,
73
+ mintedRuleCount,
74
+ culledCount,
75
+ survivingRuleCount,
76
+ exposureTuple,
77
+ cullLedger,
78
+ nonVacuity: false,
79
+ needsAdjudication,
80
+ };
81
+ }
82
+ // Step 4: Positive control non-vacuity check.
83
+ // Every positive control target must have its targetRuleId fire on an
84
+ // uncalled rule (not culled). A vacuous pass (rule never fires) → FAIL.
85
+ let nonVacuity = true;
86
+ for (const target of positiveControlTargets) {
87
+ const fired = firings.some((f) => f.controlKind === 'positive' &&
88
+ f.pr === target.pr &&
89
+ f.ruleId === target.targetRuleId &&
90
+ !culledRuleIds.has(f.ruleId));
91
+ if (!fired) {
92
+ nonVacuity = false;
93
+ break;
94
+ }
95
+ }
96
+ if (!nonVacuity) {
97
+ return {
98
+ verdict: 'FAIL',
99
+ precision: 0,
100
+ mintedRuleCount,
101
+ culledCount,
102
+ survivingRuleCount,
103
+ exposureTuple,
104
+ cullLedger,
105
+ nonVacuity: false,
106
+ needsAdjudication,
107
+ };
108
+ }
109
+ // Step 5: Check FP labels and collect unlabeled firings.
110
+ // Scope: non-negative-control, non-culled firings only.
111
+ let hasFp = false;
112
+ let tpCount = 0;
113
+ let labeledCount = 0;
114
+ for (const firing of firings) {
115
+ if (firing.controlKind === 'negative')
116
+ continue;
117
+ if (culledRuleIds.has(firing.ruleId))
118
+ continue;
119
+ const label = groundTruth.get(firing.labelId);
120
+ if (label === undefined) {
121
+ needsAdjudication.push(firing.labelId);
122
+ }
123
+ else if (label === 'FP') {
124
+ hasFp = true;
125
+ labeledCount++;
126
+ }
127
+ else {
128
+ tpCount++;
129
+ labeledCount++;
130
+ }
131
+ }
132
+ // FP → FAIL (precision < 1.0; zero-confirmed-FP floor violated)
133
+ if (hasFp) {
134
+ const precision = labeledCount > 0 ? tpCount / labeledCount : 0;
135
+ return {
136
+ verdict: 'FAIL',
137
+ precision,
138
+ mintedRuleCount,
139
+ culledCount,
140
+ survivingRuleCount,
141
+ exposureTuple,
142
+ cullLedger,
143
+ nonVacuity: true,
144
+ needsAdjudication,
145
+ };
146
+ }
147
+ // Unlabeled firings → not PASS (operator must adjudicate first)
148
+ if (needsAdjudication.length > 0) {
149
+ const precision = labeledCount > 0 ? tpCount / labeledCount : 1.0;
150
+ return {
151
+ verdict: 'HONEST-NEGATIVE',
152
+ precision,
153
+ mintedRuleCount,
154
+ culledCount,
155
+ survivingRuleCount,
156
+ exposureTuple,
157
+ cullLedger,
158
+ nonVacuity: true,
159
+ needsAdjudication,
160
+ };
161
+ }
162
+ // All firings labeled TP, exposure floors met, positive controls verified → PASS
163
+ const precision = labeledCount > 0 ? tpCount / labeledCount : 1.0;
164
+ return {
165
+ verdict: 'PASS',
166
+ precision,
167
+ mintedRuleCount,
168
+ culledCount,
169
+ survivingRuleCount,
170
+ exposureTuple,
171
+ cullLedger,
172
+ nonVacuity: true,
173
+ needsAdjudication: [],
174
+ };
175
+ }
176
+ //# sourceMappingURL=windtunnel-scorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windtunnel-scorer.js","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=windtunnel-scorer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windtunnel-scorer.test.d.ts","sourceRoot":"","sources":["../../src/spine/windtunnel-scorer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,354 @@
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 not-computed sentinel (0), NOT a survival ratio
183
+ // (survivingRuleCount / mintedRuleCount) — locks the greptile-P1 / CR fix.
184
+ expect(result.precision).toBe(0);
185
+ });
186
+ it('does not apply cull-rate guard when mintedRuleCount = 0 (harness phase)', () => {
187
+ const result = scoreWindtunnel(baseInput({
188
+ mintedRuleIds: [],
189
+ firings: [],
190
+ cullRateThreshold: 0.0,
191
+ // Need actualExposure to pass floor check even with 0 minted
192
+ exposureFloors: {
193
+ activeRulesEvaluated: 0,
194
+ filesTouchedInWindow: 0,
195
+ positiveControlsExercised: 0,
196
+ },
197
+ actualExposure: {
198
+ activeRulesEvaluated: 0,
199
+ filesTouchedInWindow: 0,
200
+ positiveControlsExercised: 0,
201
+ },
202
+ }));
203
+ // No minted rules, no firings → PASS (vacuous but valid for harness)
204
+ expect(result.verdict).toBe('PASS');
205
+ });
206
+ });
207
+ // ─── exposureTuple is always a 3-tuple (never collapsed) ─
208
+ describe('exposureTuple invariant', () => {
209
+ it('emits a 3-tuple, never collapsed to a product', () => {
210
+ const result = scoreWindtunnel(baseInput());
211
+ expect(Array.isArray(result.exposureTuple)).toBe(true);
212
+ expect(result.exposureTuple).toHaveLength(3);
213
+ expect(typeof result.exposureTuple[0]).toBe('number');
214
+ expect(typeof result.exposureTuple[1]).toBe('number');
215
+ expect(typeof result.exposureTuple[2]).toBe('number');
216
+ });
217
+ });
218
+ // ─── Precision over surviving rules (S2) ─────────────
219
+ describe('precision is over surviving rules (S2)', () => {
220
+ it('labels precision as over surviving rules after culling', () => {
221
+ const culled = makeFiring('rule-a', 99, 'negative');
222
+ const tp = makeFiring('rule-b', 1, 'corpus');
223
+ const gt = new Map([[tp.labelId, 'TP']]);
224
+ const result = scoreWindtunnel(baseInput({
225
+ firings: [culled, tp],
226
+ mintedRuleIds: ['rule-a', 'rule-b'],
227
+ groundTruth: gt,
228
+ cullRateThreshold: 0.9,
229
+ }));
230
+ expect(result.verdict).toBe('PASS');
231
+ expect(result.precision).toBe(1.0);
232
+ expect(result.culledCount).toBe(1);
233
+ expect(result.survivingRuleCount).toBe(1);
234
+ });
235
+ });
236
+ // ─── Mock engine: always-0 fires → FAIL vacuity ──────
237
+ describe('OQ2: mock engine coverage', () => {
238
+ it('mock always-0 engine: positive control target never fires → FAIL', () => {
239
+ // Always-0 engine: no firings. Positive control target expects rule-a.
240
+ const result = scoreWindtunnel(baseInput({
241
+ firings: [], // always-0: never fires
242
+ positiveControlTargets: [{ pr: 1, targetRuleId: 'rule-a' }],
243
+ }));
244
+ expect(result.verdict).toBe('FAIL');
245
+ });
246
+ it('mock always-1 engine: fires on negative control → culled, possibly HONEST-NEGATIVE', () => {
247
+ // Always-1 engine fires on the negative control
248
+ const negFiring = makeFiring('rule-a', 99, 'negative', 'near-miss');
249
+ const result = scoreWindtunnel(baseInput({
250
+ firings: [negFiring],
251
+ mintedRuleIds: ['rule-a'],
252
+ cullRateThreshold: 0.5,
253
+ }));
254
+ // 1 minted, 1 culled → rate = 1.0 > 0.5 → HONEST-NEGATIVE
255
+ expect(result.verdict).toBe('HONEST-NEGATIVE');
256
+ expect(result.cullLedger).toHaveLength(1);
257
+ });
258
+ it('mock exposure-floor-trip engine → HONEST-NEGATIVE', () => {
259
+ const result = scoreWindtunnel(baseInput({
260
+ actualExposure: {
261
+ activeRulesEvaluated: 1,
262
+ filesTouchedInWindow: 0,
263
+ positiveControlsExercised: 0,
264
+ },
265
+ exposureFloors: {
266
+ activeRulesEvaluated: 2,
267
+ filesTouchedInWindow: 0,
268
+ positiveControlsExercised: 0,
269
+ },
270
+ }));
271
+ expect(result.verdict).toBe('HONEST-NEGATIVE');
272
+ });
273
+ it('mock unlabeled-firing engine → needs-adjudication HONEST-NEGATIVE', () => {
274
+ const firing = makeFiring('rule-a', 5, 'corpus', 'some matched line');
275
+ // No groundTruth labels → unlabeled
276
+ const result = scoreWindtunnel(baseInput({
277
+ firings: [firing],
278
+ groundTruth: new Map(),
279
+ }));
280
+ expect(result.verdict).toBe('HONEST-NEGATIVE');
281
+ expect(result.needsAdjudication).toHaveLength(1);
282
+ expect(result.needsAdjudication[0]).toBe(firing.labelId);
283
+ });
284
+ it('mock perfect engine: all TPs, positive control fires, exposure met → PASS', () => {
285
+ const corpusFiring = makeFiring('rule-a', 1, 'corpus', 'pattern match');
286
+ const positiveFiring = makeFiring('rule-a', 10, 'positive', 'target match');
287
+ const gt = new Map([
288
+ [corpusFiring.labelId, 'TP'],
289
+ [positiveFiring.labelId, 'TP'],
290
+ ]);
291
+ const result = scoreWindtunnel(baseInput({
292
+ firings: [corpusFiring, positiveFiring],
293
+ groundTruth: gt,
294
+ positiveControlTargets: [{ pr: 10, targetRuleId: 'rule-a' }],
295
+ }));
296
+ expect(result.verdict).toBe('PASS');
297
+ expect(result.precision).toBe(1.0);
298
+ expect(result.nonVacuity).toBe(true);
299
+ });
300
+ });
301
+ // ─── Scorer-level FP handling (NOT the parity test) ──
302
+ //
303
+ // The real bidirectional firing-parity test (S1+C1) — replay firings ==
304
+ // production firings through enrichWithAstContext + the rule engine, covering
305
+ // both the regex/astContext over-fire suppression and the AST whole-file
306
+ // under-fire cases — lives in `windtunnel-parity.test.ts`. That test exercises
307
+ // the production classification path end-to-end; the case below only confirms
308
+ // the scorer turns a labeled FP into a FAIL verdict.
309
+ describe('scorer FP handling (see windtunnel-parity.test.ts for the real S1+C1 parity test)', () => {
310
+ it('a firing labeled FP (e.g. a comment-context match) yields FAIL with precision < 1', () => {
311
+ const firing = makeFiring('rule-a', 1, 'corpus', '// const secret = "abc"');
312
+ const gt = new Map([[firing.labelId, 'FP']]);
313
+ const result = scoreWindtunnel(baseInput({ firings: [firing], groundTruth: gt }));
314
+ expect(result.verdict).toBe('FAIL');
315
+ expect(result.precision).toBeLessThan(1.0);
316
+ });
317
+ });
318
+ // ─── Label identity (A2) ─────────────────────────────
319
+ describe('content-based firing label id (A2)', () => {
320
+ it('same content → same label id (deterministic)', () => {
321
+ const id1 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const x = 1;');
322
+ const id2 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const x = 1;');
323
+ expect(id1).toBe(id2);
324
+ });
325
+ it('different matched line → different label id (survives line-drift)', () => {
326
+ const id1 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const x = 1;');
327
+ const id2 = firingLabelId('rule-a', 1, 'src/foo.ts', 'const y = 2;');
328
+ expect(id1).not.toBe(id2);
329
+ });
330
+ });
331
+ // ─── Phase (P1) ──────────────────────────────────────
332
+ describe('phase discrimination (P1)', () => {
333
+ it('harness lock emits PASS at harness phase with zero minted rules', () => {
334
+ // Harness phase: mintedRuleCount ≈ 0, exposureFloors allow it
335
+ const result = scoreWindtunnel(baseInput({
336
+ mintedRuleIds: [],
337
+ firings: [],
338
+ exposureFloors: {
339
+ activeRulesEvaluated: 0,
340
+ filesTouchedInWindow: 0,
341
+ positiveControlsExercised: 0,
342
+ },
343
+ actualExposure: {
344
+ activeRulesEvaluated: 0,
345
+ filesTouchedInWindow: 0,
346
+ positiveControlsExercised: 0,
347
+ },
348
+ }));
349
+ // Zero rules, zero firings → vacuous PASS (valid for harness)
350
+ expect(result.verdict).toBe('PASS');
351
+ expect(result.mintedRuleCount).toBe(0);
352
+ });
353
+ });
354
+ //# 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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmnto/totem",
3
- "version": "1.64.1",
3
+ "version": "1.65.0",
4
4
  "description": "Persistent memory and context layer for AI agents",
5
5
  "type": "module",
6
6
  "engines": {