@mmnto/cli 1.16.0 → 1.17.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 (35) hide show
  1. package/dist/adapters/github-cli-pr.d.ts +13 -1
  2. package/dist/adapters/github-cli-pr.d.ts.map +1 -1
  3. package/dist/adapters/github-cli-pr.js +60 -2
  4. package/dist/adapters/github-cli-pr.js.map +1 -1
  5. package/dist/adapters/github-cli-pr.test.js +67 -0
  6. package/dist/adapters/github-cli-pr.test.js.map +1 -1
  7. package/dist/adapters/pr-adapter.d.ts +25 -0
  8. package/dist/adapters/pr-adapter.d.ts.map +1 -1
  9. package/dist/commands/retrospect.d.ts +37 -0
  10. package/dist/commands/retrospect.d.ts.map +1 -0
  11. package/dist/commands/retrospect.js +472 -0
  12. package/dist/commands/retrospect.js.map +1 -0
  13. package/dist/commands/retrospect.test.d.ts +2 -0
  14. package/dist/commands/retrospect.test.d.ts.map +1 -0
  15. package/dist/commands/retrospect.test.js +696 -0
  16. package/dist/commands/retrospect.test.js.map +1 -0
  17. package/dist/commands/shield-estimate.d.ts +24 -0
  18. package/dist/commands/shield-estimate.d.ts.map +1 -0
  19. package/dist/commands/shield-estimate.js +55 -0
  20. package/dist/commands/shield-estimate.js.map +1 -0
  21. package/dist/commands/shield-estimate.test.d.ts +2 -0
  22. package/dist/commands/shield-estimate.test.d.ts.map +1 -0
  23. package/dist/commands/shield-estimate.test.js +309 -0
  24. package/dist/commands/shield-estimate.test.js.map +1 -0
  25. package/dist/commands/shield-templates.d.ts +9 -0
  26. package/dist/commands/shield-templates.d.ts.map +1 -1
  27. package/dist/commands/shield-templates.js +9 -0
  28. package/dist/commands/shield-templates.js.map +1 -1
  29. package/dist/commands/shield.d.ts +13 -0
  30. package/dist/commands/shield.d.ts.map +1 -1
  31. package/dist/commands/shield.js +33 -0
  32. package/dist/commands/shield.js.map +1 -1
  33. package/dist/index.js +65 -0
  34. package/dist/index.js.map +1 -1
  35. package/package.json +2 -2
@@ -0,0 +1,472 @@
1
+ /**
2
+ * `totem retrospect <pr>` — bot-tax circuit-breaker (mmnto-ai/totem#1713).
3
+ *
4
+ * Reads a PR's bot-review history live, groups findings into push-based
5
+ * rounds via the per-submission `commit_id` field, enriches each finding
6
+ * with cross-PR-recurrence flags from `.totem/recurrence-stats.json`
7
+ * (read-only) plus rule-coverage flags from `compiled-rules.json`, and
8
+ * emits a console report classifying findings as `route-out`,
9
+ * `in-pr-fix`, or `undetermined` via a deterministic table-driven
10
+ * heuristic.
11
+ *
12
+ * Substrate of the bot-tax cluster (#1715 + #1714 + #1713). Reuses the
13
+ * `recurrence-stats.ts` signature + severity vocabulary so the cluster
14
+ * has a single source of truth.
15
+ *
16
+ * No LLM. No GitHub API writes. Read-only outside the optional
17
+ * `--out <path>` JSON write.
18
+ *
19
+ * NOTE on `--auto-file`: the auto-spec proposed shelling out to
20
+ * `gh issue create` for every route-out candidate. The locked design
21
+ * (see `.totem/specs/1713.md` Q2) defers `--auto-file` to a follow-up
22
+ * ticket because mass-filing issues is irreversible and the v0.1
23
+ * surface emits suggested titles + bodies that the human can copy-paste.
24
+ */
25
+ // totem-context: type-only imports above are erased at compile time and don't
26
+ // violate the lazy-import command policy (mmnto-ai/totem#1729 CR R1). All
27
+ // runtime imports (node:fs, node:path, zod, @mmnto/totem, helpers, adapters)
28
+ // are dynamic — see runRetrospect body.
29
+ // ─── Constants ───────────────────────────────────────
30
+ export const RETROSPECT_DISPLAY_TAG = 'Retrospect';
31
+ const TAG = RETROSPECT_DISPLAY_TAG;
32
+ const DEFAULT_THRESHOLD = 5;
33
+ const BODY_EXCERPT_MAX = 280;
34
+ /** Jaccard similarity above which a finding signature is treated as covered by an existing compiled rule. Mirrors `recurrence-stats.ts` `COVERAGE_JACCARD_THRESHOLD`. */
35
+ const RULE_COVERAGE_JACCARD_THRESHOLD = 0.6;
36
+ /** Max chars rendered for a finding's body excerpt in the console report. */
37
+ const RENDER_SNIPPET_MAX = 80;
38
+ /**
39
+ * Strip ANSI/control bytes from text that originated in untrusted GitHub
40
+ * review content before it lands in `log.dim()`. Per CR mmnto-ai/totem#1734
41
+ * round-2: raw `bodyExcerpt` printed without sanitization is a terminal-
42
+ * injection vector (a hostile reviewer can plant CSI sequences that spoof
43
+ * cursor moves or color resets).
44
+ *
45
+ * Removes:
46
+ * - CSI sequences (ESC `[` … final byte): the standard ANSI escape form.
47
+ * - C0/C1 control bytes other than `\n` and `\t` (which `replace(/\s+/g, ' ')`
48
+ * downstream collapses anyway, but pre-replacing makes the surface stable
49
+ * regardless of caller order).
50
+ */
51
+ function sanitizeForTerminal(value) {
52
+ return value
53
+ .replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, '')
54
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, ' ');
55
+ }
56
+ // ─── Main entrypoint ────────────────────────────────
57
+ export async function runRetrospect(options) {
58
+ // Dynamic imports per `packages/cli/src/commands/**` lazy-import policy
59
+ // (mmnto-ai/totem#1729 CR R1).
60
+ const fs = await import('node:fs');
61
+ const path = await import('node:path');
62
+ const { z } = await import('zod');
63
+ const { GitHubCliPrAdapter } = await import('../adapters/github-cli-pr.js');
64
+ const { log } = await import('../ui.js');
65
+ const { isBotComment, detectBot, parseCRSeverity, parseGCASeverity, stripHtmlWrappers, extractReviewBodyFindings, } = await import('../parsers/bot-review-parser.js');
66
+ const { buildStopConditions, classifyFinding, computeDedupRate, computeSignature, groupFindingsByRound, jaccard, loadCompiledRules, normalizeFindingBody, readLedgerEvents, RetrospectReportSchema, toSeverityBucket, tokenizeForJaccard, } = await import('@mmnto/totem');
67
+ const { loadConfig, resolveConfigPath } = await import('../utils.js');
68
+ // Local schema — the recurrence-stats file shape is defined in core,
69
+ // but reading it here keeps the zod import lazy.
70
+ const RecurrenceStatsFileSchema = z.object({
71
+ version: z.literal(1),
72
+ patterns: z.array(z.object({
73
+ signature: z.string(),
74
+ prs: z.array(z.string()),
75
+ })),
76
+ coveredPatterns: z
77
+ .array(z.object({
78
+ signature: z.string(),
79
+ prs: z.array(z.string()),
80
+ }))
81
+ .optional(),
82
+ });
83
+ const cwd = process.cwd();
84
+ const threshold = clampThreshold(options.threshold);
85
+ const prNumber = options.prNumber;
86
+ // Strict integer parse (reject "5foo", "5.2", " 5 ") — `Number.parseInt`
87
+ // silently accepts trailing non-numerics; per CR/GCA mmnto-ai/totem#1734
88
+ // review-1 we use `Number()` + `Number.isInteger` for CLI inputs.
89
+ const prNumberInt = Number(prNumber);
90
+ if (!Number.isInteger(prNumberInt) || prNumberInt <= 0) {
91
+ const { TotemConfigError } = await import('@mmnto/totem');
92
+ throw new TotemConfigError(`Invalid PR number: ${prNumber}`, "Pass a positive integer (e.g. 'totem retrospect 1734').", 'CONFIG_INVALID');
93
+ }
94
+ log.info(TAG, `Retrospect on PR #${prNumber} (threshold=${threshold}).`);
95
+ // 1. Live-fetch PR + reviews + comments.
96
+ const adapter = new GitHubCliPrAdapter(cwd);
97
+ const prData = adapter.fetchPr(prNumberInt);
98
+ const reviewSubmissions = adapter.fetchReviews(prNumberInt);
99
+ const reviewComments = adapter.fetchReviewComments(prNumberInt);
100
+ // 2. Round-grouping. Build a SHA → finding-count map by joining inline
101
+ // comments back to the closest preceding review submission via
102
+ // timestamp. We only consider BOT submissions because the round
103
+ // count is a measure of bot-driven feedback waves.
104
+ // Null-guard before isBotComment — GitHub API permits null `user`
105
+ // (deleted/ghost accounts). Without the guard, `isBotComment(null)`
106
+ // would silently exclude bot rounds. Per CR mmnto-ai/totem#1734 review-1.
107
+ const botSubmissions = reviewSubmissions
108
+ .filter((r) => r.user_login !== null && isBotComment(r.user_login))
109
+ .map((r) => ({
110
+ id: r.id,
111
+ commit_id: r.commit_id ?? null,
112
+ submitted_at: r.submitted_at ?? null,
113
+ user_login: r.user_login,
114
+ }));
115
+ // Bucket each finding by the parent review submission's commit_id.
116
+ // Per CR mmnto-ai/totem#1734 round-2: `created_at` can predate
117
+ // `submitted_at` for pending/draft reviews, so a timestamp join
118
+ // mis-attributes the head SHA. The GitHub API exposes
119
+ // `pull_request_review_id` on each review comment as the stable
120
+ // foreign key back to its parent submission — we use that.
121
+ const sortedSubs = [...botSubmissions].sort((a, b) => {
122
+ const at = a.submitted_at ?? '';
123
+ const bt = b.submitted_at ?? '';
124
+ if (at < bt)
125
+ return -1;
126
+ if (at > bt)
127
+ return 1;
128
+ return 0;
129
+ });
130
+ /** review_id → commit_id lookup over bot-authored submissions only. */
131
+ const reviewIdToSha = new Map();
132
+ for (const s of botSubmissions) {
133
+ if (typeof s.commit_id === 'string')
134
+ reviewIdToSha.set(s.id, s.commit_id);
135
+ }
136
+ function shaForInlineComment(reviewId) {
137
+ if (typeof reviewId !== 'number')
138
+ return '';
139
+ return reviewIdToSha.get(reviewId) ?? '';
140
+ }
141
+ // 3. Inline + review-body bot finding extraction.
142
+ const inlineBotComments = reviewComments.filter((c) => isBotComment(c.author));
143
+ const inlineFindings = [];
144
+ for (const c of inlineBotComments) {
145
+ const tool = detectBot(c.author);
146
+ const severity = tool === 'coderabbit'
147
+ ? parseCRSeverity(c.body)
148
+ : tool === 'gca'
149
+ ? parseGCASeverity(c.body)
150
+ : 'info';
151
+ const body = stripHtmlWrappers(c.body);
152
+ const hunkMatch = c.diffHunk.match(/@@ .+?\+(\d+)/);
153
+ const line = hunkMatch ? Number.parseInt(hunkMatch[1], 10) : undefined;
154
+ inlineFindings.push({
155
+ finding: {
156
+ tool,
157
+ severity,
158
+ file: c.path,
159
+ line,
160
+ body,
161
+ resolutionSignal: 'none',
162
+ rootCommentId: c.id,
163
+ },
164
+ sha: shaForInlineComment(c.pullRequestReviewId),
165
+ observedAt: c.createdAt ?? '',
166
+ });
167
+ }
168
+ // CR review-body findings (outside-diff + nits) — bucket into the SHA
169
+ // of the review submission that carried them.
170
+ const reviewBodyFindings = [];
171
+ for (const r of reviewSubmissions) {
172
+ // Null-guard: deleted/ghost accounts skip this branch — same rationale as the bot-submissions filter above.
173
+ if (r.user_login === null || !isBotComment(r.user_login))
174
+ continue;
175
+ const synthesized = extractReviewBodyFindings([{ author: r.user_login, body: r.body ?? '' }]);
176
+ const sha = typeof r.commit_id === 'string' ? r.commit_id : '';
177
+ const observedAt = r.submitted_at ?? '';
178
+ for (const f of synthesized) {
179
+ reviewBodyFindings.push({ finding: f, sha, observedAt });
180
+ }
181
+ }
182
+ const allFindings = [...inlineFindings, ...reviewBodyFindings];
183
+ // SHA → finding count.
184
+ const findingsPerSha = new Map();
185
+ for (const f of allFindings) {
186
+ findingsPerSha.set(f.sha, (findingsPerSha.get(f.sha) ?? 0) + 1);
187
+ }
188
+ // Compute rounds via the pure helper.
189
+ const rounds = groupFindingsByRound(sortedSubs, findingsPerSha);
190
+ // SHA → roundNumber lookup so we can stamp each finding.
191
+ const shaToRoundNumber = new Map();
192
+ for (const r of rounds) {
193
+ shaToRoundNumber.set(r.headSha ?? '', r.roundNumber);
194
+ }
195
+ // 4. Substrate read — recurrence-stats (graceful degrade if missing).
196
+ const config = await loadConfig(resolveConfigPath(cwd));
197
+ const totemDir = path.join(cwd, config.totemDir);
198
+ const substratePath = path.join(totemDir, 'recurrence-stats.json');
199
+ let substrateAvailable = false;
200
+ /** signature → list of OTHER PRs sharing this signature (target excluded). */
201
+ const crossPrIndex = new Map();
202
+ if (fs.existsSync(substratePath)) {
203
+ try {
204
+ const raw = fs.readFileSync(substratePath, 'utf-8');
205
+ const parsed = JSON.parse(raw);
206
+ const validated = RecurrenceStatsFileSchema.parse(parsed);
207
+ substrateAvailable = true;
208
+ const allEntries = [...(validated.patterns ?? []), ...(validated.coveredPatterns ?? [])];
209
+ for (const entry of allEntries) {
210
+ const others = entry.prs.filter((p) => p !== prNumber);
211
+ const set = crossPrIndex.get(entry.signature) ?? new Set();
212
+ for (const pr of others)
213
+ set.add(pr);
214
+ crossPrIndex.set(entry.signature, set);
215
+ }
216
+ // totem-context: malformed substrate is a graceful-degrade path per the mmnto-ai/totem#1713 failure-mode table — log + continue with `crossPrRecurrence: 0` for every finding; `substrateAvailable: false` surfaces the degradation in the report so the consumer can see it explicitly. Hard-erroring would block the circuit-breaker the user invoked retrospect to run.
217
+ }
218
+ catch (err) {
219
+ const msg = err instanceof Error ? err.message : String(err);
220
+ log.warn(TAG, `Could not parse ${substratePath}: ${msg} — running without cross-PR recurrence enrichment.`);
221
+ }
222
+ }
223
+ else {
224
+ log.warn(TAG, `${substratePath} not found — run 'totem stats --pattern-recurrence' first to enable cross-PR enrichment.`);
225
+ }
226
+ // 5. Compiled-rules read — graceful degrade if missing.
227
+ // `loadCompiledRules` is intentionally `[]`-returning on ENOENT so a
228
+ // sync-after-fresh-clone doesn't crash; we can't tell "missing" from
229
+ // "empty manifest" by return value alone. Gate on file existence
230
+ // first so the report's `compiledRulesAvailable` flag matches the
231
+ // user's mental model: if the file isn't there, the coverage check
232
+ // is structurally unavailable.
233
+ const rulesPath = path.join(totemDir, 'compiled-rules.json');
234
+ let compiledRulesAvailable = false;
235
+ let ruleTokenSets = [];
236
+ if (fs.existsSync(rulesPath)) {
237
+ try {
238
+ const compiledRules = loadCompiledRules(rulesPath);
239
+ compiledRulesAvailable = true;
240
+ ruleTokenSets = compiledRules.map((r) => tokenizeForJaccard(r.message ?? ''));
241
+ // totem-context: malformed compiled-rules.json is a graceful-degrade path per the mmnto-ai/totem#1713 failure-mode table — log + continue with `coveredByRule: false` for every finding; `compiledRulesAvailable: false` surfaces the degradation. Mirrors the pattern in `runRecurrenceStats` step 6 ("missing/malformed compiled-rules.json disables coverage routing only").
242
+ }
243
+ catch (err) {
244
+ const msg = err instanceof Error ? err.message : String(err);
245
+ log.warn(TAG, `Could not load compiled rules: ${msg} — coverage check disabled.`);
246
+ }
247
+ }
248
+ else {
249
+ log.warn(TAG, `${rulesPath} not found — run 'totem lesson compile' first to enable rule-coverage enrichment.`);
250
+ }
251
+ // 6. Trap-ledger override events (read-only, count only). Today the
252
+ // LedgerEventSchema does NOT carry a `prNumber` field, so we cannot
253
+ // actually scope the count to the target PR — every event passes
254
+ // the predicate. The cast-based predicate below is a forward-compat
255
+ // scaffold: when a future ticket adds `prNumber` to LedgerEvent
256
+ // (filed as the mmnto-ai/totem#1734-CR-7 follow-up), the predicate
257
+ // will start filtering automatically with no command-side change.
258
+ // Per CR mmnto-ai/totem#1734 review-1.
259
+ const ledgerEvents = readLedgerEvents(totemDir, (msg) => log.warn(TAG, msg));
260
+ const overrideEventsObserved = ledgerEvents.filter((e) => {
261
+ if (e.type !== 'override')
262
+ return false;
263
+ const eventPr = e.prNumber;
264
+ return eventPr === undefined || String(eventPr) === prNumber;
265
+ }).length;
266
+ // 7. Annotate every finding: signature, classification, recurrence, coverage.
267
+ const annotated = allFindings.map((f) => ({
268
+ finding: f.finding,
269
+ roundNumber: shaToRoundNumber.get(f.sha) ?? 0,
270
+ observedAt: f.observedAt,
271
+ }));
272
+ // Per discriminated union (CR mmnto-ai/totem#1734 round-2): `routeOutReason`
273
+ // is present iff `classification === 'route-out'`; the schema infers
274
+ // `RetrospectFinding` accordingly.
275
+ const enriched = [];
276
+ for (const a of annotated) {
277
+ const normalized = normalizeFindingBody(a.finding.body);
278
+ if (normalized.length === 0)
279
+ continue;
280
+ const signature = computeSignature(normalized);
281
+ const tool = a.finding.tool === 'coderabbit' ? 'coderabbit' : a.finding.tool === 'gca' ? 'gca' : 'unknown';
282
+ const severityBucket = toSeverityBucket(tool, a.finding.severity);
283
+ // Cross-PR recurrence — count of OTHER PRs (target excluded by construction).
284
+ const crossPrRecurrence = crossPrIndex.get(signature)?.size ?? 0;
285
+ // Coverage check — Jaccard 0.6 against any rule message.
286
+ let coveredByRule = false;
287
+ if (compiledRulesAvailable && ruleTokenSets.length > 0) {
288
+ const findingTokens = tokenizeForJaccard(normalized);
289
+ let maxJ = 0;
290
+ for (const ruleTokens of ruleTokenSets) {
291
+ const v = jaccard(findingTokens, ruleTokens);
292
+ if (v > maxJ)
293
+ maxJ = v;
294
+ }
295
+ coveredByRule = maxJ >= RULE_COVERAGE_JACCARD_THRESHOLD;
296
+ }
297
+ const verdict = classifyFinding({
298
+ severityBucket,
299
+ roundNumber: a.roundNumber > 0 ? a.roundNumber : 1,
300
+ crossPrRecurrence,
301
+ coveredByRule,
302
+ });
303
+ const base = {
304
+ signature,
305
+ tool,
306
+ severityBucket,
307
+ bodyExcerpt: a.finding.body.slice(0, BODY_EXCERPT_MAX),
308
+ file: a.finding.file,
309
+ line: a.finding.line,
310
+ roundNumber: a.roundNumber > 0 ? a.roundNumber : 1,
311
+ crossPrRecurrence,
312
+ coveredByRule,
313
+ };
314
+ if (verdict.classification === 'route-out' && verdict.routeOutReason !== undefined) {
315
+ enriched.push({
316
+ ...base,
317
+ classification: 'route-out',
318
+ routeOutReason: verdict.routeOutReason,
319
+ });
320
+ }
321
+ else if (verdict.classification === 'route-out') {
322
+ // Defensive: classifier returned 'route-out' without a reason — should
323
+ // be unreachable per the table. Fail loud (Tenet 4) so the missing
324
+ // catalog entry surfaces immediately.
325
+ throw new Error(`[Totem Error] classifier returned route-out without routeOutReason for signature ${signature}`);
326
+ }
327
+ else {
328
+ enriched.push({ ...base, classification: verdict.classification });
329
+ }
330
+ }
331
+ // 8. Distribution counts.
332
+ const byTool = {};
333
+ const bySeverity = {};
334
+ const byClassification = {};
335
+ for (const f of enriched) {
336
+ byTool[f.tool] = (byTool[f.tool] ?? 0) + 1;
337
+ bySeverity[f.severityBucket] = (bySeverity[f.severityBucket] ?? 0) + 1;
338
+ byClassification[f.classification] = (byClassification[f.classification] ?? 0) + 1;
339
+ }
340
+ // Sort buckets — primary by roundNumber asc; tie-break: numeric PR
341
+ // sort is on `prs[]` arrays (lesson-26935d32 applies in
342
+ // `recurrence-stats`); here we stay deterministic via signature.
343
+ const sortByRoundThenSig = (a, b) => {
344
+ if (a.roundNumber !== b.roundNumber)
345
+ return a.roundNumber - b.roundNumber;
346
+ return a.signature.localeCompare(b.signature);
347
+ };
348
+ const routeOutCandidates = enriched
349
+ .filter((f) => f.classification === 'route-out')
350
+ .sort(sortByRoundThenSig);
351
+ const inPrFixes = enriched
352
+ .filter((f) => f.classification === 'in-pr-fix')
353
+ .sort(sortByRoundThenSig);
354
+ const undetermined = enriched
355
+ .filter((f) => f.classification === 'undetermined')
356
+ .sort(sortByRoundThenSig);
357
+ const dedupRate = computeDedupRate(enriched);
358
+ // 9. Build report.
359
+ const report = {
360
+ version: 1,
361
+ prNumber,
362
+ prState: prData.state,
363
+ generatedAt: new Date().toISOString(),
364
+ threshold,
365
+ substrateAvailable,
366
+ compiledRulesAvailable,
367
+ rounds,
368
+ totalFindings: enriched.length,
369
+ dedupRate,
370
+ findingDistribution: { byTool, bySeverity, byClassification },
371
+ routeOutCandidates,
372
+ inPrFixes,
373
+ undetermined,
374
+ stopConditions: [],
375
+ overrideEventsObserved,
376
+ };
377
+ report.stopConditions = buildStopConditions(report);
378
+ // Validate the assembled report shape — fail-loud on schema drift.
379
+ RetrospectReportSchema.parse(report);
380
+ // 10. Threshold gate.
381
+ if (rounds.length < threshold && !options.force) {
382
+ log.info(TAG, `PR #${prNumber} has ${rounds.length} bot-review round(s); below threshold ${threshold}. Skipping (pass --force to inspect anyway).`);
383
+ return;
384
+ }
385
+ // 11. Render console report.
386
+ renderReport(report, log);
387
+ // 12. Optional --out write (deterministic two-space JSON).
388
+ if (options.out) {
389
+ const outPath = path.isAbsolute(options.out) ? options.out : path.join(cwd, options.out);
390
+ fs.mkdirSync(path.dirname(outPath), { recursive: true });
391
+ fs.writeFileSync(outPath, JSON.stringify(report, null, 2) + '\n', 'utf-8');
392
+ log.info(TAG, `Wrote report → ${outPath}`);
393
+ }
394
+ }
395
+ function renderReport(report, log) {
396
+ log.info(TAG, `PR #${report.prNumber} (${report.prState}) — ${report.rounds.length} round(s), ${report.totalFindings} bot finding(s).`);
397
+ log.dim(TAG, ` substrate=${report.substrateAvailable ? 'available' : 'absent'}, compiled-rules=${report.compiledRulesAvailable ? 'available' : 'absent'}, dedup-rate=${(report.dedupRate * 100).toFixed(0)}%`);
398
+ // Distribution
399
+ const tools = Object.entries(report.findingDistribution.byTool)
400
+ .sort((a, b) => b[1] - a[1])
401
+ .map(([k, v]) => `${k}:${v}`)
402
+ .join(' ');
403
+ const severities = Object.entries(report.findingDistribution.bySeverity)
404
+ .sort((a, b) => b[1] - a[1])
405
+ .map(([k, v]) => `${k}:${v}`)
406
+ .join(' ');
407
+ const classifications = Object.entries(report.findingDistribution.byClassification)
408
+ .sort((a, b) => b[1] - a[1])
409
+ .map(([k, v]) => `${k}:${v}`)
410
+ .join(' ');
411
+ if (tools)
412
+ log.dim(TAG, ` tool: ${tools}`);
413
+ if (severities)
414
+ log.dim(TAG, ` severity: ${severities}`);
415
+ if (classifications)
416
+ log.dim(TAG, ` classification: ${classifications}`);
417
+ // Route-out candidates.
418
+ if (report.routeOutCandidates.length > 0) {
419
+ log.info(TAG, `Route-out candidates (${report.routeOutCandidates.length}):`);
420
+ for (const f of report.routeOutCandidates) {
421
+ const snippet = sanitizeForTerminal(f.bodyExcerpt)
422
+ .replace(/\s+/g, ' ')
423
+ .slice(0, RENDER_SNIPPET_MAX);
424
+ // Schema discriminates: `f.classification === 'route-out'` guarantees `routeOutReason`.
425
+ const reason = f.routeOutReason;
426
+ log.dim(TAG, ` [r${f.roundNumber}] ${f.severityBucket} ${f.signature} — ${snippet} (${reason})`);
427
+ }
428
+ }
429
+ else {
430
+ log.dim(TAG, 'Route-out candidates: (none)');
431
+ }
432
+ // In-PR fixes.
433
+ if (report.inPrFixes.length > 0) {
434
+ log.info(TAG, `In-PR fixes (${report.inPrFixes.length}):`);
435
+ for (const f of report.inPrFixes) {
436
+ const snippet = sanitizeForTerminal(f.bodyExcerpt)
437
+ .replace(/\s+/g, ' ')
438
+ .slice(0, RENDER_SNIPPET_MAX);
439
+ log.dim(TAG, ` [r${f.roundNumber}] ${f.severityBucket} ${f.signature} — ${snippet}`);
440
+ }
441
+ }
442
+ else {
443
+ log.dim(TAG, 'In-PR fixes: (none)');
444
+ }
445
+ // Undetermined.
446
+ if (report.undetermined.length > 0) {
447
+ log.info(TAG, `Undetermined (${report.undetermined.length}):`);
448
+ for (const f of report.undetermined) {
449
+ const snippet = sanitizeForTerminal(f.bodyExcerpt)
450
+ .replace(/\s+/g, ' ')
451
+ .slice(0, RENDER_SNIPPET_MAX);
452
+ log.dim(TAG, ` [r${f.roundNumber}] ${f.severityBucket} ${f.signature} — ${snippet}`);
453
+ }
454
+ }
455
+ // Stop conditions.
456
+ if (report.stopConditions.length > 0) {
457
+ log.info(TAG, 'Stop conditions:');
458
+ for (const cond of report.stopConditions) {
459
+ log.dim(TAG, ` • ${cond}`);
460
+ }
461
+ }
462
+ if (report.overrideEventsObserved > 0) {
463
+ log.dim(TAG, `Trap ledger: ${report.overrideEventsObserved} override event(s) observed.`);
464
+ }
465
+ }
466
+ // ─── Helpers ────────────────────────────────────────
467
+ function clampThreshold(input) {
468
+ if (input === undefined || !Number.isFinite(input) || input < 1)
469
+ return DEFAULT_THRESHOLD;
470
+ return Math.floor(input);
471
+ }
472
+ //# sourceMappingURL=retrospect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrospect.js","sourceRoot":"","sources":["../../src/commands/retrospect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=retrospect.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrospect.test.d.ts","sourceRoot":"","sources":["../../src/commands/retrospect.test.ts"],"names":[],"mappings":""}