@mmnto/totem 1.70.0 → 1.71.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 (46) hide show
  1. package/dist/ast-grep-query.d.ts +12 -0
  2. package/dist/ast-grep-query.d.ts.map +1 -1
  3. package/dist/ast-grep-query.js +4 -0
  4. package/dist/ast-grep-query.js.map +1 -1
  5. package/dist/ast-query.d.ts +12 -0
  6. package/dist/ast-query.d.ts.map +1 -1
  7. package/dist/ast-query.js +4 -0
  8. package/dist/ast-query.js.map +1 -1
  9. package/dist/index.d.ts +7 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +3 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/rule-engine.d.ts.map +1 -1
  14. package/dist/rule-engine.js +37 -6
  15. package/dist/rule-engine.js.map +1 -1
  16. package/dist/rule-engine.test.js +96 -0
  17. package/dist/rule-engine.test.js.map +1 -1
  18. package/dist/spine/legitimacy-projection.d.ts +61 -0
  19. package/dist/spine/legitimacy-projection.d.ts.map +1 -0
  20. package/dist/spine/legitimacy-projection.js +67 -0
  21. package/dist/spine/legitimacy-projection.js.map +1 -0
  22. package/dist/spine/legitimacy-projection.test.d.ts +2 -0
  23. package/dist/spine/legitimacy-projection.test.d.ts.map +1 -0
  24. package/dist/spine/legitimacy-projection.test.js +153 -0
  25. package/dist/spine/legitimacy-projection.test.js.map +1 -0
  26. package/dist/spine/windtunnel-firing.d.ts +154 -0
  27. package/dist/spine/windtunnel-firing.d.ts.map +1 -0
  28. package/dist/spine/windtunnel-firing.js +273 -0
  29. package/dist/spine/windtunnel-firing.js.map +1 -0
  30. package/dist/spine/windtunnel-firing.test.d.ts +2 -0
  31. package/dist/spine/windtunnel-firing.test.d.ts.map +1 -0
  32. package/dist/spine/windtunnel-firing.test.js +469 -0
  33. package/dist/spine/windtunnel-firing.test.js.map +1 -0
  34. package/dist/spine/windtunnel-lock.d.ts +9 -0
  35. package/dist/spine/windtunnel-lock.d.ts.map +1 -1
  36. package/dist/spine/windtunnel-lock.js +17 -0
  37. package/dist/spine/windtunnel-lock.js.map +1 -1
  38. package/dist/spine/windtunnel-lock.test.js +24 -0
  39. package/dist/spine/windtunnel-lock.test.js.map +1 -1
  40. package/dist/spine/windtunnel-scorer.d.ts +22 -0
  41. package/dist/spine/windtunnel-scorer.d.ts.map +1 -1
  42. package/dist/spine/windtunnel-scorer.js +10 -1
  43. package/dist/spine/windtunnel-scorer.js.map +1 -1
  44. package/dist/spine/windtunnel-scorer.test.js +32 -0
  45. package/dist/spine/windtunnel-scorer.test.js.map +1 -1
  46. package/package.json +1 -1
@@ -0,0 +1,273 @@
1
+ import { enrichWithAstContext } from '../ast-gate.js';
2
+ import { extractAddedLines } from '../diff-parser.js';
3
+ import { applyAstRulesToAdditions, applyRulesToAdditions } from '../rule-engine.js';
4
+ import { firingLabelId } from './windtunnel-lock.js';
5
+ /** Thrown by `assertUniqueFiringLabels` (A1 hard-gate floor, Tenet 4). */
6
+ export class FiringLabelCollisionError extends Error {
7
+ collisions;
8
+ constructor(collisions) {
9
+ const detail = collisions
10
+ .map((c) => ` • labelId ${c.labelId.slice(0, 12)}… collides across ${c.evidenceRefs.length} firings: ` +
11
+ c.evidenceRefs
12
+ .map((e) => `[rule ${e.ruleId} pr#${e.pr} ${e.filePath} "${e.matchedLine}"]`)
13
+ .join(', '))
14
+ .join('\n');
15
+ super(`Wind-tunnel firing-label collision (A1, fold-D): ${collisions.length} labelId(s) map to ` +
16
+ `multiple firings — the labelId→evidenceRef contract is violated and ground-truth ` +
17
+ `joins would silently overwrite.\n${detail}`);
18
+ this.name = 'FiringLabelCollisionError';
19
+ this.collisions = collisions;
20
+ }
21
+ }
22
+ /** Thrown when an archived rule reaches the scored set (fold-F, Tenet 4). */
23
+ export class ArchivedRuleInScopeError extends Error {
24
+ archivedRuleIds;
25
+ constructor(archivedRuleIds) {
26
+ super(`Wind-tunnel scorer-input (fold-F): ${archivedRuleIds.length} archived rule(s) reached the ` +
27
+ `scored set — archived rules must never enter the wind-tunnel (archived ≠ wind-tunnel FP). ` +
28
+ `Filter to active rules before building firings. Offending: [${archivedRuleIds.join(', ')}]`);
29
+ this.name = 'ArchivedRuleInScopeError';
30
+ this.archivedRuleIds = archivedRuleIds;
31
+ }
32
+ }
33
+ // ─── Helpers ─────────────────────────────────────────
34
+ /**
35
+ * Normalize a matched line for the content-based labelId (A2/A3). Trailing
36
+ * whitespace is dropped so cosmetic EOL drift between the post-image and the
37
+ * diff does not split a firing into a new labelId; interior content is
38
+ * preserved (the label must still distinguish genuinely different lines).
39
+ */
40
+ function normalizeMatchedLine(line) {
41
+ return line.replace(/\s+$/, '');
42
+ }
43
+ /** The rule id used for firings + ground-truth joins (the lessonHash). */
44
+ function ruleIdOf(rule) {
45
+ return rule.lessonHash;
46
+ }
47
+ // ─── fold-F: archived-excluded loud assert ───────────
48
+ /**
49
+ * fold-F — assert no `status:'archived'` rule is in the scored set (Tenet 4).
50
+ * Called at the scorer input boundary BEFORE the engine runs, so
51
+ * `applyAstRulesToAdditions` is never invoked on an archived rule and zero
52
+ * archived refs can reach `RuleFiring[]`. Archived ≠ wind-tunnel FP: an
53
+ * archived rule that "fires" is not evidence of imprecision, it is a corpus
54
+ * contamination that must fail loud.
55
+ */
56
+ export function assertNoArchivedRules(rules) {
57
+ const archived = rules.filter((r) => r.status === 'archived').map(ruleIdOf);
58
+ if (archived.length > 0) {
59
+ throw new ArchivedRuleInScopeError(archived);
60
+ }
61
+ }
62
+ // ─── A1 (fold-D): post-dedup uniqueness INVARIANT ────
63
+ /**
64
+ * A1 (fold-D) — assert `firings.length === unique(labelIds).size` BEFORE
65
+ * `scoreWindtunnel` (Tenet 4). Originally specced as a hard-gate FLOOR that
66
+ * threw on any collision; the strategy ruling (2026-06-20) DEMOTED it to a
67
+ * post-dedup invariant once `buildFirings` learned to collapse same-labelId
68
+ * matches (`dedupeFirings`). It still THROWS on a collision — but a collision
69
+ * here now means a dedup BUG (or a caller that bypassed `buildFirings`), not an
70
+ * honest multi-match line, so failing loud is correct. We deliberately do NOT
71
+ * add an occurrence discriminator / ordinal (it would regress `firingLabelId`'s
72
+ * line-drift resistance); a diff-hunk-span discriminator stays reserved. The
73
+ * invariant guards the `labelId→evidenceRef` contract the ground-truth join
74
+ * depends on: a 1:1 labelId→firing map.
75
+ */
76
+ export function assertUniqueFiringLabels(firings) {
77
+ const byLabel = new Map();
78
+ for (const f of firings) {
79
+ const existing = byLabel.get(f.labelId);
80
+ if (existing)
81
+ existing.push(f);
82
+ else
83
+ byLabel.set(f.labelId, [f]);
84
+ }
85
+ const collisions = [];
86
+ for (const [labelId, group] of byLabel) {
87
+ if (group.length > 1) {
88
+ collisions.push({
89
+ labelId,
90
+ evidenceRefs: group.map((f) => ({
91
+ ruleId: f.ruleId,
92
+ pr: f.pr,
93
+ filePath: f.filePath,
94
+ matchedLine: f.matchedLine,
95
+ })),
96
+ });
97
+ }
98
+ }
99
+ if (collisions.length > 0) {
100
+ throw new FiringLabelCollisionError(collisions);
101
+ }
102
+ }
103
+ /**
104
+ * The real-engine firing path (replaces `runMockEngine` for the certifying
105
+ * phase). For each resolved-PR diff: extract additions → `enrichWithAstContext`
106
+ * (regex astContext via the shared post-image readStrategy) → regex engine +
107
+ * `applyAstRulesToAdditions` (AST/ast-grep, same readStrategy) → map every
108
+ * `Violation` to a `RuleFiring` with `labelId = firingLabelId(...)`.
109
+ *
110
+ * Invariants honored here:
111
+ * - **fold-F**: throws if any archived rule is present (assertNoArchivedRules),
112
+ * so the engine is never invoked on an archived rule.
113
+ * - **fold-H**: a firing on a `negative` PR is emitted as `controlKind:'negative'`
114
+ * (the scorer culls + ledgers it — never dropped pre-score). Unlabeled firings
115
+ * stay in `firings` (no ground-truth) so the scorer routes them to
116
+ * needsAdjudication.
117
+ * - **C2**: `filesTouchedInWindow` is the count of distinct post-image files
118
+ * across all diffs — the real third exposure leg.
119
+ *
120
+ * fold-D: before returning, same-`labelId` matches are collapsed to ONE logical
121
+ * firing (`dedupeFirings`), retaining every raw match as `evidence`. The caller's
122
+ * `assertUniqueFiringLabels` is therefore a post-dedup INVARIANT (it can no
123
+ * longer fire on an honest multi-match line), not a pre-score floor.
124
+ */
125
+ export async function buildFirings(input) {
126
+ const { rules, prDiffs, cwd, readStrategy, ruleEngineCtx, onWarn } = input;
127
+ // fold-F: hard-gate the scored set BEFORE touching the engine.
128
+ assertNoArchivedRules(rules);
129
+ // Pre-dedup firings (one per raw engine match); collapsed by labelId at return.
130
+ const rawFirings = [];
131
+ const touchedFiles = new Set();
132
+ const positiveControlTargets = [];
133
+ for (const prDiff of prDiffs) {
134
+ if (prDiff.controlKind === 'positive' && prDiff.targetRuleId) {
135
+ positiveControlTargets.push({ pr: prDiff.pr, targetRuleId: prDiff.targetRuleId });
136
+ }
137
+ const additions = extractAddedLines(prDiff.diff);
138
+ for (const a of additions) {
139
+ touchedFiles.add(a.file.replace(/\\/g, '/'));
140
+ }
141
+ if (additions.length === 0 || rules.length === 0)
142
+ continue;
143
+ // Enrich with AST context (regex over-fire suppression parity, C1) using the
144
+ // SAME post-image content the AST engine will parse (S1).
145
+ await enrichWithAstContext(additions, { cwd, readStrategy, onWarn });
146
+ // Both engines receive the FULL rule set and self-filter by `rule.engine`
147
+ // into DISJOINT partitions — applyRulesToAdditions takes `engine === 'regex'
148
+ // || !engine`; applyAstRulesToAdditions takes `engine === 'ast' | 'ast-grep'`
149
+ // (rule-engine.ts). No rule is processed by both, so double-processing can
150
+ // never manufacture a same-rule labelId self-collision at the A1 gate. (CR #2215.)
151
+ const regexViolations = applyRulesToAdditions(ruleEngineCtx, rules, additions);
152
+ // AST / ast-grep violations (whole post-image via the shared readStrategy).
153
+ const astViolations = await applyAstRulesToAdditions(ruleEngineCtx, rules, additions, cwd, undefined, onWarn, readStrategy);
154
+ for (const v of [...regexViolations, ...astViolations]) {
155
+ rawFirings.push(violationToFiring(v, prDiff));
156
+ }
157
+ }
158
+ return {
159
+ // fold-D: collapse same-labelId matches to ONE logical firing before scoring.
160
+ firings: dedupeFirings(rawFirings),
161
+ filesTouchedInWindow: touchedFiles.size,
162
+ positiveControlTargets,
163
+ };
164
+ }
165
+ /**
166
+ * fold-D — collapse raw firings that share a `labelId` into ONE logical firing,
167
+ * retaining every raw match as `evidence`. Same-labelId matches arise when a
168
+ * rule matches more than once under the identical (ruleId, pr, filePath,
169
+ * normalizedLine) key — multiple matches on one line, or distinct physical lines
170
+ * whose trailing-whitespace difference normalizes away. Per the strategy ruling
171
+ * (2026-06-20) we DEDUP rather than throw or add an occurrence discriminator: an
172
+ * ordinal would regress `firingLabelId`'s deliberate line-drift resistance, and
173
+ * the collapse is verdict-safe under ADR-110's 1.0 precision floor (it only
174
+ * affects the precision denominator, never the binary verdict). A diff-hunk-span
175
+ * discriminator stays RESERVED (measure-first) if the frozen corpus ever needs
176
+ * it. The retained firing keeps the FIRST match's fields (identical across the
177
+ * group by construction of the key) and accumulates all matches' evidence; the
178
+ * caller's `assertUniqueFiringLabels` is then a post-dedup invariant, not a gate.
179
+ */
180
+ function dedupeFirings(rawFirings) {
181
+ const byLabel = new Map();
182
+ for (const f of rawFirings) {
183
+ const existing = byLabel.get(f.labelId);
184
+ if (!existing) {
185
+ byLabel.set(f.labelId, f);
186
+ continue;
187
+ }
188
+ // Collapse: append this raw match's evidence to the retained firing.
189
+ existing.evidence = [...(existing.evidence ?? []), ...(f.evidence ?? [])];
190
+ }
191
+ return [...byLabel.values()];
192
+ }
193
+ /** Map one engine `Violation` to a scored `RuleFiring` (content-based labelId). */
194
+ function violationToFiring(violation, prDiff) {
195
+ const ruleId = ruleIdOf(violation.rule);
196
+ const filePath = violation.file.replace(/\\/g, '/');
197
+ const matchedLine = normalizeMatchedLine(violation.line);
198
+ const firing = {
199
+ ruleId,
200
+ pr: prDiff.pr,
201
+ filePath,
202
+ matchedLine,
203
+ controlKind: prDiff.controlKind,
204
+ labelId: firingLabelId(ruleId, prDiff.pr, filePath, matchedLine),
205
+ // fold-D: the raw match backing this firing (≥1 after dedup collapse).
206
+ evidence: [{ lineNumber: violation.lineNumber, rawLine: violation.line }],
207
+ };
208
+ // Carry the positive control's target so the scorer's non-vacuity check can
209
+ // match on (pr, ruleId) — only meaningful for positive-control firings.
210
+ if (prDiff.controlKind === 'positive' && prDiff.targetRuleId) {
211
+ firing.targetRuleId = prDiff.targetRuleId;
212
+ }
213
+ return firing;
214
+ }
215
+ // ─── C1: per-rule control results ────────────────────
216
+ /**
217
+ * C1 (fold-B's data prerequisite) — build a `Map<ruleId, PerRuleControlResult>`
218
+ * over the SURVIVING rules (active rules that were NOT culled by a negative
219
+ * control). `positiveControl` is true ONLY when THIS rule fired its declared
220
+ * positive-control target — derived from the rule's own firings, never from the
221
+ * global `nonVacuity`. `negativeControl` is true when the rule fired on NO
222
+ * negative control. 5c-ii reads this to stamp legitimacy survivor-only.
223
+ *
224
+ * Survivors = mintedRuleIds minus rules that fired on any negative control
225
+ * (those are culled; the scorer records them in the cullLedger and we do not
226
+ * stamp them).
227
+ */
228
+ export function computePerRuleControlResults(input) {
229
+ const { firings, mintedRuleIds, positiveControlTargets } = input;
230
+ // Rules culled by a negative-control firing (not survivors).
231
+ const culled = new Set();
232
+ for (const f of firings) {
233
+ if (f.controlKind === 'negative')
234
+ culled.add(f.ruleId);
235
+ }
236
+ // Per-rule positive-control evidence: a firing whose (pr, ruleId) matches a
237
+ // declared positive-control target on a positive-control item.
238
+ const targetByRule = new Map();
239
+ for (const t of positiveControlTargets) {
240
+ const prs = targetByRule.get(t.targetRuleId) ?? new Set();
241
+ prs.add(t.pr);
242
+ targetByRule.set(t.targetRuleId, prs);
243
+ }
244
+ const posFiringsByRule = new Map();
245
+ for (const f of firings) {
246
+ if (f.controlKind !== 'positive')
247
+ continue;
248
+ const prs = targetByRule.get(f.ruleId);
249
+ if (prs && prs.has(f.pr)) {
250
+ const arr = posFiringsByRule.get(f.ruleId) ?? [];
251
+ arr.push(f.labelId);
252
+ posFiringsByRule.set(f.ruleId, arr);
253
+ }
254
+ }
255
+ const result = new Map();
256
+ for (const ruleId of mintedRuleIds) {
257
+ if (culled.has(ruleId))
258
+ continue; // not a survivor — never stamped
259
+ const posEvidence = posFiringsByRule.get(ruleId) ?? [];
260
+ result.set(ruleId, {
261
+ // Per-rule, NOT global nonVacuity: true only if THIS rule fired its target.
262
+ positiveControl: posEvidence.length > 0,
263
+ // Survivors are non-culled by construction (a negative-control firing culls
264
+ // the rule and we `continue` above), so a rule reaching here fired on NO
265
+ // negative control → negativeControl is invariantly true; the negative leg
266
+ // carries no evidence refs (it is an absence, not a firing). (greptile #2215 P2.)
267
+ negativeControl: true,
268
+ evidenceRefs: posEvidence,
269
+ });
270
+ }
271
+ return result;
272
+ }
273
+ //# sourceMappingURL=windtunnel-firing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windtunnel-firing.js","sourceRoot":"","sources":["../../src/spine/windtunnel-firing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=windtunnel-firing.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"windtunnel-firing.test.d.ts","sourceRoot":"","sources":["../../src/spine/windtunnel-firing.test.ts"],"names":[],"mappings":""}