@mmnto/totem 1.18.2 → 1.19.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/compile-lesson.d.ts +42 -0
- package/dist/compile-lesson.d.ts.map +1 -1
- package/dist/compile-lesson.js +189 -0
- package/dist/compile-lesson.js.map +1 -1
- package/dist/compile-lesson.test.js +539 -0
- package/dist/compile-lesson.test.js.map +1 -1
- package/dist/compiler-schema.d.ts +110 -30
- package/dist/compiler-schema.d.ts.map +1 -1
- package/dist/compiler-schema.js +48 -2
- package/dist/compiler-schema.js.map +1 -1
- package/dist/compiler-schema.test.js +80 -0
- package/dist/compiler-schema.test.js.map +1 -1
- package/dist/compiler.d.ts +13 -6
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +14 -7
- package/dist/compiler.js.map +1 -1
- package/dist/compiler.test.js +33 -0
- package/dist/compiler.test.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/recurrence-stats.d.ts +10 -10
- package/dist/retrospect.d.ts +42 -42
- package/dist/stage4-verifier.d.ts +133 -0
- package/dist/stage4-verifier.d.ts.map +1 -0
- package/dist/stage4-verifier.js +355 -0
- package/dist/stage4-verifier.js.map +1 -0
- package/dist/stage4-verifier.test.d.ts +2 -0
- package/dist/stage4-verifier.test.d.ts.map +1 -0
- package/dist/stage4-verifier.test.js +372 -0
- package/dist/stage4-verifier.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-091 Stage 4 Verify-Against-Codebase verifier (mmnto-ai/totem#1682).
|
|
3
|
+
*
|
|
4
|
+
* Runs a compiled rule deterministically (zero LLM) against the consumer's
|
|
5
|
+
* existing codebase before promoting it to Active status. Catches the class
|
|
6
|
+
* of false positive that Layer 3 (ADR-088) cannot — Layer 3 verifies the
|
|
7
|
+
* pattern matches the lesson's authored `badExample` (internal consistency);
|
|
8
|
+
* Stage 4 verifies the pattern doesn't accidentally fire on legitimate code
|
|
9
|
+
* (global false-positive safety).
|
|
10
|
+
*
|
|
11
|
+
* Four outcomes per ADR-091 §"Stage 4: Verify-Against-Codebase":
|
|
12
|
+
*
|
|
13
|
+
* - **No matches** (`outcome: 'no-matches'`) — the verifier ran, found zero
|
|
14
|
+
* hits in the codebase. Caller sets `status: 'untested-against-codebase'`;
|
|
15
|
+
* subsequent compile cycles in a populated repo can re-run Stage 4 and
|
|
16
|
+
* promote.
|
|
17
|
+
* - **Out-of-scope baseline match** (`outcome: 'out-of-scope'`) — the rule
|
|
18
|
+
* fired on at least one file in the verification baseline (test files,
|
|
19
|
+
* fixture directories, or files outside the rule's `fileGlobs` scope).
|
|
20
|
+
* The pattern is over-broad. Caller archives the rule with
|
|
21
|
+
* `reasonCode: 'stage4-out-of-scope-match'` and the offending paths.
|
|
22
|
+
* - **In-scope `badExample`-shape match** (`outcome: 'in-scope-bad-example'`)
|
|
23
|
+
* — the rule fired only on in-scope files AND every in-scope match line is
|
|
24
|
+
* structurally equivalent to the rule's `badExample`. The rule fires on
|
|
25
|
+
* real code in the exact authored shape. Caller sets `status: 'active'`
|
|
26
|
+
* with `confidence: 'high'`.
|
|
27
|
+
* - **Candidate Debt** (`outcome: 'candidate-debt'`) — the rule fired only
|
|
28
|
+
* on in-scope files but at least one match line differs from the
|
|
29
|
+
* `badExample` shape. The rule may be catching real debt, or producing
|
|
30
|
+
* false positives the LLM-generated pattern overshoots into. Caller
|
|
31
|
+
* accepts as `status: 'active'` and forces `severity: 'warning'` so it
|
|
32
|
+
* never breaks CI on first run; `totem doctor` (mmnto-ai/totem#1685)
|
|
33
|
+
* surfaces the candidate-debt sites for human confirmation.
|
|
34
|
+
*
|
|
35
|
+
* Bootstrap modes: T1 ships local-compile fully (the verifier runs against
|
|
36
|
+
* the consumer's working tree before `totem lesson compile` serializes the
|
|
37
|
+
* rule). Pack install→lint promotion lands in T3 (mmnto-ai/totem#1684).
|
|
38
|
+
* Consumer baseline overrides land in T2 (mmnto-ai/totem#1683). Perf
|
|
39
|
+
* optimizations (single-pass, file-tree caching, streaming short-circuit)
|
|
40
|
+
* land in T5 (mmnto-ai/totem#1686). T1 walks per-rule, no caching.
|
|
41
|
+
*
|
|
42
|
+
* Architecture: callback-based filesystem. The verifier accepts `listFiles`
|
|
43
|
+
* + `readFile` callbacks instead of touching `fs` directly so core stays
|
|
44
|
+
* orchestration-only. CLI implementations back the callbacks with `git
|
|
45
|
+
* ls-files` and `fs.readFile`; tests stub them with synthetic file maps.
|
|
46
|
+
*/
|
|
47
|
+
import { applyAstRulesToAdditions, applyRulesToAdditions } from './rule-engine.js';
|
|
48
|
+
// ─── Default baseline ───────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Glob shapes the test-contract scope classifier (mmnto-ai/totem#1626 /
|
|
51
|
+
* mmnto-ai/totem#1652) promotes-to-test-inclusive when emitting LLM scope.
|
|
52
|
+
* Stage 4 mirrors them as the default baseline so any rule that fires on a
|
|
53
|
+
* test or fixture file is treated as out-of-scope by default. T2
|
|
54
|
+
* (mmnto-ai/totem#1683) lets consumers `exclude` from this list when their
|
|
55
|
+
* project legitimately treats `tests/` as production.
|
|
56
|
+
*/
|
|
57
|
+
export const DEFAULT_BASELINE_GLOBS = [
|
|
58
|
+
'**/*.test.*',
|
|
59
|
+
'**/*.spec.*',
|
|
60
|
+
'**/__tests__/**',
|
|
61
|
+
'**/tests/**',
|
|
62
|
+
'**/__fixtures__/**',
|
|
63
|
+
'**/fixtures/**',
|
|
64
|
+
];
|
|
65
|
+
export function getDefaultBaseline() {
|
|
66
|
+
// T1: the default baseline is rule-independent (every rule gets the same
|
|
67
|
+
// test/fixture exclusion). T2 (mmnto-ai/totem#1683) introduces per-config
|
|
68
|
+
// `extend`/`exclude` overrides; the function signature accepts a rule
|
|
69
|
+
// parameter then so per-rule baseline derivation can layer on top.
|
|
70
|
+
return { excludeFileGlobs: DEFAULT_BASELINE_GLOBS };
|
|
71
|
+
}
|
|
72
|
+
// ─── Glob matching (matches rule-engine semantics) ─
|
|
73
|
+
function matchesGlob(filePath, glob) {
|
|
74
|
+
// Normalize Windows backslashes to forward slashes — globs use forward
|
|
75
|
+
// slashes universally, repo paths come back from git-ls-files in either
|
|
76
|
+
// shape on Windows depending on core.autocrlf.
|
|
77
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
78
|
+
// Exact glob match — escape regex metacharacters except `*`, `?`, and
|
|
79
|
+
// brace groups, then expand `**` to `.*`, `*` to `[^/]*`, `?` to `.`.
|
|
80
|
+
if (glob.includes('*') || glob.includes('?') || glob.includes('{')) {
|
|
81
|
+
const regexPattern = globToRegex(glob);
|
|
82
|
+
return new RegExp(`^${regexPattern}$`).test(normalized);
|
|
83
|
+
}
|
|
84
|
+
// Literal filename match (e.g., "Dockerfile")
|
|
85
|
+
return normalized === glob || normalized.endsWith('/' + glob);
|
|
86
|
+
}
|
|
87
|
+
function globToRegex(glob) {
|
|
88
|
+
let result = '';
|
|
89
|
+
let i = 0;
|
|
90
|
+
while (i < glob.length) {
|
|
91
|
+
const ch = glob[i];
|
|
92
|
+
if (ch === '*') {
|
|
93
|
+
if (glob[i + 1] === '*') {
|
|
94
|
+
result += '.*';
|
|
95
|
+
i += 2;
|
|
96
|
+
// Consume trailing `/` if present so `**/foo` becomes `.*foo`
|
|
97
|
+
if (glob[i] === '/')
|
|
98
|
+
i++;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
result += '[^/]*';
|
|
102
|
+
}
|
|
103
|
+
else if (ch === '?') {
|
|
104
|
+
result += '[^/]';
|
|
105
|
+
}
|
|
106
|
+
else if (ch === '{') {
|
|
107
|
+
const end = glob.indexOf('}', i);
|
|
108
|
+
if (end === -1) {
|
|
109
|
+
result += '\\{';
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const alts = glob.slice(i + 1, end).split(',');
|
|
113
|
+
result += '(?:' + alts.map(escapeRegex).join('|') + ')';
|
|
114
|
+
i = end + 1;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if ('.+()[]^$|\\'.includes(ch)) {
|
|
119
|
+
result += '\\' + ch;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
result += ch;
|
|
123
|
+
}
|
|
124
|
+
i++;
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
function escapeRegex(s) {
|
|
129
|
+
return s.replace(/[.+()[\]^$|\\*?{}]/g, '\\$&');
|
|
130
|
+
}
|
|
131
|
+
function fileMatchesAnyGlob(filePath, globs) {
|
|
132
|
+
return globs.some((g) => matchesGlob(filePath, g));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* A file is "in scope" for Stage 4 verification when it matches the rule's
|
|
136
|
+
* declared `fileGlobs` (or has none, meaning the rule applies everywhere)
|
|
137
|
+
* AND is not in the baseline-excluded set. A baseline-excluded test file
|
|
138
|
+
* inside `**\/*.ts` scope counts as baseline, not in-scope, because the
|
|
139
|
+
* verifier's job is to detect over-broad firing — including on tests the
|
|
140
|
+
* rule is supposed to skip.
|
|
141
|
+
*/
|
|
142
|
+
function classifyFile(filePath, ruleFileGlobs, baseline) {
|
|
143
|
+
// Rule has explicit fileGlobs and this file doesn't match → baseline (out-of-scope).
|
|
144
|
+
if (ruleFileGlobs && ruleFileGlobs.length > 0) {
|
|
145
|
+
const positive = ruleFileGlobs.filter((g) => !g.startsWith('!'));
|
|
146
|
+
const negative = ruleFileGlobs.filter((g) => g.startsWith('!')).map((g) => g.slice(1));
|
|
147
|
+
const matchesPositive = positive.length === 0 || fileMatchesAnyGlob(filePath, positive);
|
|
148
|
+
const matchesNegative = fileMatchesAnyGlob(filePath, negative);
|
|
149
|
+
if (!matchesPositive || matchesNegative)
|
|
150
|
+
return 'baseline';
|
|
151
|
+
}
|
|
152
|
+
// File matches rule scope (or rule has no scope). Now check baseline overrides.
|
|
153
|
+
if (fileMatchesAnyGlob(filePath, baseline.excludeFileGlobs))
|
|
154
|
+
return 'baseline';
|
|
155
|
+
return 'in-scope';
|
|
156
|
+
}
|
|
157
|
+
// ─── Synthetic DiffAddition production ─────────────
|
|
158
|
+
/**
|
|
159
|
+
* Convert raw file content into the `DiffAddition[]` shape the rule engine
|
|
160
|
+
* expects. One addition per line. `precedingLine` carries the prior line
|
|
161
|
+
* verbatim so suppression directives (`// totem-ignore-next-line`) work
|
|
162
|
+
* inside the verifier the same way they do in lint. `astContext` is left
|
|
163
|
+
* undefined — the engine treats undefined as "code", which is exactly the
|
|
164
|
+
* Stage 4 contract: detect over-broad firing on any source line, not just
|
|
165
|
+
* lines a Tree-sitter classifier labels as code.
|
|
166
|
+
*/
|
|
167
|
+
function fileToAdditions(file, content) {
|
|
168
|
+
// CR mmnto-ai/totem#1757 R3: don't synthesize a trailing blank line.
|
|
169
|
+
// `''.split(/\r?\n/)` returns `['']` and `'foo\n'.split(/\r?\n/)`
|
|
170
|
+
// returns `['foo', '']`, both of which would inject a non-existent
|
|
171
|
+
// blank addition. A pattern like `^$` (blank-line detector) would
|
|
172
|
+
// then falsely fire on every newline-terminated file in the
|
|
173
|
+
// codebase, flipping rules into out-of-scope or candidate-debt for
|
|
174
|
+
// the wrong reason.
|
|
175
|
+
if (content.length === 0)
|
|
176
|
+
return [];
|
|
177
|
+
const lines = content.split(/\r?\n/);
|
|
178
|
+
if (/\r?\n$/.test(content)) {
|
|
179
|
+
lines.pop();
|
|
180
|
+
}
|
|
181
|
+
const additions = [];
|
|
182
|
+
for (let i = 0; i < lines.length; i++) {
|
|
183
|
+
const line = lines[i] ?? '';
|
|
184
|
+
additions.push({
|
|
185
|
+
file,
|
|
186
|
+
line,
|
|
187
|
+
lineNumber: i + 1,
|
|
188
|
+
precedingLine: i > 0 ? (lines[i - 1] ?? null) : null,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
return additions;
|
|
192
|
+
}
|
|
193
|
+
// ─── Rule execution ────────────────────────────────
|
|
194
|
+
const NOOP_LOGGER = { warn: () => undefined };
|
|
195
|
+
function defaultRuleCtx() {
|
|
196
|
+
return {
|
|
197
|
+
logger: NOOP_LOGGER,
|
|
198
|
+
state: { hasWarnedShieldContext: false },
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Run the rule against the entire codebase, with `fileGlobs` stripped so
|
|
203
|
+
* the rule fires on every file (in-scope AND baseline). Stage 4 partitions
|
|
204
|
+
* the resulting violations by file classification afterward. Without the
|
|
205
|
+
* strip, `applyRulesToAdditions` would skip baseline files internally and
|
|
206
|
+
* the verifier would see zero out-of-scope hits even when the pattern is
|
|
207
|
+
* obviously over-broad.
|
|
208
|
+
*/
|
|
209
|
+
async function runRuleAgainstAllFiles(rule, additions, ctx, workingDirectory) {
|
|
210
|
+
const ruleNoScope = { ...rule, fileGlobs: undefined };
|
|
211
|
+
if (rule.engine === 'regex' || !rule.engine) {
|
|
212
|
+
return applyRulesToAdditions(ctx, [ruleNoScope], [...additions]);
|
|
213
|
+
}
|
|
214
|
+
// ast / ast-grep — requires a working directory for file resolution.
|
|
215
|
+
// Fail loud when absent so Stage 4 cannot silently misclassify the run
|
|
216
|
+
// as `'no-matches'`. T1's CLI integration always passes a
|
|
217
|
+
// workingDirectory; tests that hit this path must pass one too.
|
|
218
|
+
// (CR mmnto-ai/totem#1757 R1 — earlier `return []` short-circuit
|
|
219
|
+
// hid the missing-input case as a clean result.)
|
|
220
|
+
if (!workingDirectory) {
|
|
221
|
+
const msg = `[Totem Error] Stage 4 verifier requires deps.workingDirectory for ${rule.engine} rules.`;
|
|
222
|
+
throw new Error(msg);
|
|
223
|
+
}
|
|
224
|
+
return applyAstRulesToAdditions(ctx, [ruleNoScope], [...additions], workingDirectory);
|
|
225
|
+
}
|
|
226
|
+
// ─── Structural equivalence ────────────────────────
|
|
227
|
+
/**
|
|
228
|
+
* T1 uses byte-equal trimmed comparison: a violation line is `badExample`-
|
|
229
|
+
* shape iff `line.trim()` equals `badExample.trim()`. Stricter equivalence
|
|
230
|
+
* (full subtree match for ast-grep, normalized whitespace for regex) is
|
|
231
|
+
* deferred to T5 (mmnto-ai/totem#1686) when the perf-pass adds AST-aware
|
|
232
|
+
* comparison.
|
|
233
|
+
*
|
|
234
|
+
* `badExample` may carry multiple lines (Pipeline 3 reuses Bad snippets
|
|
235
|
+
* verbatim). The function compares against ANY trimmed line of the
|
|
236
|
+
* `badExample` block — a violation matches if the line equals any one of
|
|
237
|
+
* the badExample's component lines.
|
|
238
|
+
*/
|
|
239
|
+
function lineMatchesBadExample(line, badExample) {
|
|
240
|
+
if (badExample === undefined)
|
|
241
|
+
return false;
|
|
242
|
+
const trimmedLine = line.trim();
|
|
243
|
+
if (trimmedLine.length === 0)
|
|
244
|
+
return false;
|
|
245
|
+
for (const candidate of badExample.split(/\r?\n/)) {
|
|
246
|
+
if (candidate.trim() === trimmedLine)
|
|
247
|
+
return true;
|
|
248
|
+
}
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
// ─── Public API ────────────────────────────────────
|
|
252
|
+
/**
|
|
253
|
+
* Run Stage 4 verification for a single compiled rule against the consumer's
|
|
254
|
+
* codebase. Caller decides what to do with the returned outcome:
|
|
255
|
+
*
|
|
256
|
+
* - `'no-matches'` → set rule.status = 'untested-against-codebase'
|
|
257
|
+
* - `'out-of-scope'` → archive rule with reasonCode 'stage4-out-of-scope-match'
|
|
258
|
+
* - `'in-scope-bad-example'` → set rule.status = 'active', confidence = 'high'
|
|
259
|
+
* - `'candidate-debt'` → set rule.status = 'active', force severity = 'warning'
|
|
260
|
+
*
|
|
261
|
+
* The verifier itself does NOT mutate the rule. Mutation happens at the
|
|
262
|
+
* compileLesson integration site so the trace event and lifecycle field
|
|
263
|
+
* preservation remain centralized.
|
|
264
|
+
*
|
|
265
|
+
* For Pipeline 1 manual rules, the integration site bypasses Stage 4
|
|
266
|
+
* entirely — those rules are human-authored and Stage 4 is a safety net
|
|
267
|
+
* for LLM-generated patterns. The verifier itself is engine-agnostic and
|
|
268
|
+
* will run on any rule it's handed.
|
|
269
|
+
*/
|
|
270
|
+
export async function verifyAgainstCodebase(rule, baseline, deps) {
|
|
271
|
+
const files = await deps.listFiles();
|
|
272
|
+
const ctx = deps.ruleCtx ?? defaultRuleCtx();
|
|
273
|
+
// Build all additions across all files. T5 (mmnto-ai/totem#1686) will
|
|
274
|
+
// batch this across rules per compile cycle; T1 walks per-rule.
|
|
275
|
+
const additions = [];
|
|
276
|
+
for (const file of files) {
|
|
277
|
+
let content;
|
|
278
|
+
try {
|
|
279
|
+
content = await deps.readFile(file);
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
// Fail loud per Tenet 4. The file showed up in listFiles() so its
|
|
283
|
+
// absence here is a real environment problem (race with deletion,
|
|
284
|
+
// permission change, broken symlink). The operator needs to see
|
|
285
|
+
// exactly which file failed; preserving `cause` keeps the original
|
|
286
|
+
// stack/context intact (CR mmnto-ai/totem#1757 R2 — the prior
|
|
287
|
+
// `${err.message}` concat flattened the original exception).
|
|
288
|
+
throw new Error(`Stage 4 verifier could not read ${file}.`, { cause: err });
|
|
289
|
+
}
|
|
290
|
+
additions.push(...fileToAdditions(file, content));
|
|
291
|
+
}
|
|
292
|
+
if (additions.length === 0) {
|
|
293
|
+
return {
|
|
294
|
+
outcome: 'no-matches',
|
|
295
|
+
baselineMatches: [],
|
|
296
|
+
inScopeMatches: [],
|
|
297
|
+
candidateDebtLines: [],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
const violations = await runRuleAgainstAllFiles(rule, additions, ctx, deps.workingDirectory);
|
|
301
|
+
if (violations.length === 0) {
|
|
302
|
+
return {
|
|
303
|
+
outcome: 'no-matches',
|
|
304
|
+
baselineMatches: [],
|
|
305
|
+
inScopeMatches: [],
|
|
306
|
+
candidateDebtLines: [],
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
// Partition violations by file classification.
|
|
310
|
+
const baselineMatchSet = new Set();
|
|
311
|
+
const inScopeMatchSet = new Set();
|
|
312
|
+
const candidateDebtLines = [];
|
|
313
|
+
for (const violation of violations) {
|
|
314
|
+
const classification = classifyFile(violation.file, rule.fileGlobs, baseline);
|
|
315
|
+
if (classification === 'baseline') {
|
|
316
|
+
baselineMatchSet.add(violation.file);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
inScopeMatchSet.add(violation.file);
|
|
320
|
+
if (!lineMatchesBadExample(violation.line, rule.badExample)) {
|
|
321
|
+
candidateDebtLines.push(violation.line);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// Out-of-scope wins precedence over in-scope outcomes — even one baseline
|
|
326
|
+
// match means the pattern is over-broad and gets archived. ADR-091
|
|
327
|
+
// §"Stage 4: Verify-Against-Codebase" is explicit on this ordering.
|
|
328
|
+
if (baselineMatchSet.size > 0) {
|
|
329
|
+
return {
|
|
330
|
+
outcome: 'out-of-scope',
|
|
331
|
+
baselineMatches: [...baselineMatchSet].sort(),
|
|
332
|
+
inScopeMatches: [...inScopeMatchSet].sort(),
|
|
333
|
+
candidateDebtLines: [],
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
// All violations are in-scope. Distinguish bad-example shape from
|
|
337
|
+
// candidate debt by whether ANY violation line failed to match the
|
|
338
|
+
// badExample. A single mismatch flips the outcome to candidate-debt;
|
|
339
|
+
// the rule ships at warning severity until a human confirms the hits.
|
|
340
|
+
if (candidateDebtLines.length === 0) {
|
|
341
|
+
return {
|
|
342
|
+
outcome: 'in-scope-bad-example',
|
|
343
|
+
baselineMatches: [],
|
|
344
|
+
inScopeMatches: [...inScopeMatchSet].sort(),
|
|
345
|
+
candidateDebtLines: [],
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
outcome: 'candidate-debt',
|
|
350
|
+
baselineMatches: [],
|
|
351
|
+
inScopeMatches: [...inScopeMatchSet].sort(),
|
|
352
|
+
candidateDebtLines,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=stage4-verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage4-verifier.js","sourceRoot":"","sources":["../src/stage4-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage4-verifier.test.d.ts","sourceRoot":"","sources":["../src/stage4-verifier.test.ts"],"names":[],"mappings":""}
|