@lsctech/polaris 0.5.7 → 0.5.8

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.
@@ -0,0 +1,282 @@
1
+ "use strict";
2
+ /**
3
+ * SOL SmartDocs Markdown report renderer.
4
+ *
5
+ * Renders human-readable SOL evaluation reports from a run-level
6
+ * evaluation record, the computed scorecard set, and optional QC
7
+ * follow-up recommendations.
8
+ *
9
+ * Reports include:
10
+ * - Source references back to raw evidence
11
+ * - Per-subject confidence and availability
12
+ * - Skipped dimensions with reasons
13
+ * - Window / grouping metadata
14
+ * - Recommendation inputs for downstream routing advice
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.renderSolMarkdown = renderSolMarkdown;
18
+ // ──────────────────────────────────────────────
19
+ // Formatting helpers
20
+ // ──────────────────────────────────────────────
21
+ function fmtScore(v) {
22
+ return v !== null ? v.toFixed(4) : "N/A";
23
+ }
24
+ function fmtBoolean(v) {
25
+ if (v === null)
26
+ return "N/A";
27
+ return v ? "Yes" : "No";
28
+ }
29
+ function fmtList(items) {
30
+ if (!items || items.length === 0)
31
+ return "_None_";
32
+ return items.map((i) => `- ${i}`).join("\n");
33
+ }
34
+ function escapeCell(s) {
35
+ // Normalize line breaks so table cells remain valid Markdown.
36
+ return s.replace(/\r?\n/g, " ").replace(/\|/g, "\\|").trim();
37
+ }
38
+ // ──────────────────────────────────────────────
39
+ // Subscore table
40
+ // ──────────────────────────────────────────────
41
+ function renderSubscoreTable(scorecard) {
42
+ const rows = scorecard.subscores.map((s) => {
43
+ const value = s.score !== null ? fmtScore(s.score) : "_skipped_";
44
+ const reason = s.skipped_reason ? ` (${s.skipped_reason})` : "";
45
+ const detail = s.detail ? ` ${s.detail}` : "";
46
+ return `| ${s.dimension} | ${value} | ${s.confidence} | ${escapeCell(reason + detail) || "—"} |`;
47
+ });
48
+ return [
49
+ "| Dimension | Score | Confidence | Notes |",
50
+ "|---|---|---|---|",
51
+ ...rows,
52
+ ].join("\n");
53
+ }
54
+ // ──────────────────────────────────────────────
55
+ // Source references
56
+ // ──────────────────────────────────────────────
57
+ function renderSourceRefs(refs) {
58
+ const unique = new Map();
59
+ for (const ref of refs) {
60
+ unique.set(`${ref.kind}|${ref.path}`, ref);
61
+ }
62
+ const rows = Array.from(unique.values())
63
+ .sort((a, b) => a.path.localeCompare(b.path))
64
+ .map((r) => {
65
+ const status = r.available ? "available" : `missing${r.unavailable_reason ? `: ${r.unavailable_reason}` : ""}`;
66
+ return `| ${r.kind} | \`${r.path}\` | ${status} |`;
67
+ });
68
+ return [
69
+ "| Kind | Path | Status |",
70
+ "|---|---|---|",
71
+ ...rows,
72
+ ].join("\n");
73
+ }
74
+ // ──────────────────────────────────────────────
75
+ // Recommendation inputs
76
+ // ──────────────────────────────────────────────
77
+ function renderRecommendationInputs(scorecard) {
78
+ const i = scorecard.recommendation_inputs;
79
+ const flags = [];
80
+ if (i.below_threshold)
81
+ flags.push("below threshold");
82
+ if (i.over_token_budget)
83
+ flags.push("over token budget");
84
+ if (i.intervention_detected)
85
+ flags.push("intervention detected");
86
+ if (i.router_issue_detected)
87
+ flags.push("router issue detected");
88
+ if (i.qc_issue_detected)
89
+ flags.push("QC issue detected");
90
+ const cells = [
91
+ scorecard.subject,
92
+ scorecard.subject_key,
93
+ flags.length > 0 ? flags.join(", ") : "—",
94
+ i.low_scoring_dimensions.join(", ") || "—",
95
+ i.skipped_dimensions.join(", ") || "—",
96
+ ];
97
+ return `| ${cells.map(escapeCell).join(" | ")} |`;
98
+ }
99
+ function renderRecommendationInputsHeader() {
100
+ return [
101
+ "| Subject | Key | Flags | Low dimensions | Skipped dimensions |",
102
+ "|---|---|---|---|---|",
103
+ ].join("\n");
104
+ }
105
+ // ──────────────────────────────────────────────
106
+ // Scorecard detail section
107
+ // ──────────────────────────────────────────────
108
+ function renderScorecardDetail(scorecard) {
109
+ const lines = [];
110
+ lines.push(`### ${scorecard.subject}: ${scorecard.subject_key}`);
111
+ lines.push("");
112
+ lines.push(`- **Availability:** ${scorecard.availability}${scorecard.availability_reason ? ` — ${scorecard.availability_reason}` : ""}`);
113
+ lines.push(`- **Aggregate score:** ${fmtScore(scorecard.aggregate_score)} (${scorecard.aggregate_confidence})`);
114
+ lines.push(`- **Aggregate formula:** \`${scorecard.aggregate_formula_version}\``);
115
+ lines.push(`- **Window:** run_id=${scorecard.window.run_id ?? "n/a"}, cluster_id=${scorecard.window.cluster_id ?? "n/a"}, sample_count=${scorecard.window.sample_count ?? "n/a"}`);
116
+ const grouping = Object.entries(scorecard.grouping_keys)
117
+ .filter(([, v]) => v !== undefined)
118
+ .map(([k, v]) => `${k}=${v}`)
119
+ .join(", ");
120
+ lines.push(`- **Grouping keys:** ${grouping || "—"}`);
121
+ lines.push("");
122
+ lines.push(renderSubscoreTable(scorecard));
123
+ lines.push("");
124
+ lines.push("**Source references**");
125
+ lines.push("");
126
+ lines.push(renderSourceRefs(scorecard.source_refs));
127
+ lines.push("");
128
+ return lines.join("\n");
129
+ }
130
+ /**
131
+ * Render a complete SOL evaluation report as Markdown.
132
+ */
133
+ function renderSolMarkdown(record, scorecardSet, qcRecommendations) {
134
+ const allScorecards = [
135
+ scorecardSet.foreman,
136
+ ...scorecardSet.workers,
137
+ ...scorecardSet.providers,
138
+ ...scorecardSet.models,
139
+ ...scorecardSet.routing,
140
+ ];
141
+ const skipped = allScorecards.flatMap((s) => s.subscores
142
+ .filter((sub) => sub.score === null && sub.skipped_reason)
143
+ .map((sub) => ({ subject: s.subject, key: s.subject_key, dimension: sub.dimension, reason: sub.skipped_reason })));
144
+ const lines = [];
145
+ lines.push(`# SOL Evaluation Report: ${record.run_id}`);
146
+ lines.push("");
147
+ lines.push(`**Generated:** ${record.generated_at}`);
148
+ lines.push(`**Scored at:** ${record.scored_at}`);
149
+ lines.push(`**Cluster:** ${record.cluster_id ?? "n/a"}`);
150
+ lines.push("");
151
+ // Run-level summary
152
+ lines.push("## Run summary");
153
+ lines.push("");
154
+ lines.push(`| Metric | Value |`);
155
+ lines.push(`|---|---|`);
156
+ lines.push(`| Run composite score | ${fmtScore(record.report.run_composite_score)} |`);
157
+ lines.push(`| Foreman composite | ${fmtScore(record.report.foreman.composite_score)} (${record.report.foreman.composite_confidence}) |`);
158
+ lines.push(`| Worker count | ${Object.keys(record.report.workers).length} |`);
159
+ lines.push(`| Scorecards produced | ${allScorecards.length} |`);
160
+ lines.push("");
161
+ // Scorecard index
162
+ lines.push("## Scorecard index");
163
+ lines.push("");
164
+ lines.push("| Subject | Key | Aggregate | Confidence | Availability |");
165
+ lines.push("|---|---|---|---|---|");
166
+ for (const s of allScorecards) {
167
+ lines.push(`| ${s.subject} | ${escapeCell(s.subject_key)} | ${fmtScore(s.aggregate_score)} | ${s.aggregate_confidence} | ${s.availability} |`);
168
+ }
169
+ lines.push("");
170
+ // Foreman
171
+ lines.push("## Foreman");
172
+ lines.push("");
173
+ lines.push(renderScorecardDetail(scorecardSet.foreman));
174
+ // Workers
175
+ if (scorecardSet.workers.length > 0) {
176
+ lines.push("## Workers");
177
+ lines.push("");
178
+ for (const s of scorecardSet.workers) {
179
+ lines.push(renderScorecardDetail(s));
180
+ }
181
+ }
182
+ // Providers
183
+ if (scorecardSet.providers.length > 0) {
184
+ lines.push("## Providers");
185
+ lines.push("");
186
+ for (const s of scorecardSet.providers) {
187
+ lines.push(renderScorecardDetail(s));
188
+ }
189
+ }
190
+ // Models
191
+ if (scorecardSet.models.length > 0) {
192
+ lines.push("## Models");
193
+ lines.push("");
194
+ for (const s of scorecardSet.models) {
195
+ lines.push(renderScorecardDetail(s));
196
+ }
197
+ }
198
+ // Routing
199
+ if (scorecardSet.routing.length > 0) {
200
+ lines.push("## Routing decisions");
201
+ lines.push("");
202
+ for (const s of scorecardSet.routing) {
203
+ lines.push(renderScorecardDetail(s));
204
+ }
205
+ }
206
+ // Token efficiency
207
+ lines.push("## Token efficiency");
208
+ lines.push("");
209
+ const qptScorecards = allScorecards.filter((s) => s.subscores.some((sub) => sub.dimension === "quality_per_token"));
210
+ if (qptScorecards.length === 0) {
211
+ lines.push("No quality-per-token subscores were computed (token evidence may be missing).");
212
+ }
213
+ else {
214
+ lines.push("| Subject | Key | Quality / token | Confidence |");
215
+ lines.push("|---|---|---|---|");
216
+ for (const s of qptScorecards) {
217
+ const qpt = s.subscores.find((sub) => sub.dimension === "quality_per_token");
218
+ lines.push(`| ${s.subject} | ${escapeCell(s.subject_key)} | ${fmtScore(qpt?.score ?? null)} | ${qpt?.confidence ?? "none"} |`);
219
+ }
220
+ }
221
+ lines.push("");
222
+ // QC outcome
223
+ lines.push("## QC outcome");
224
+ lines.push("");
225
+ const foremanQc = scorecardSet.foreman.subscores.find((s) => s.dimension === "qc_repair_loop");
226
+ if (!foremanQc) {
227
+ lines.push("No QC repair-loop subscore available.");
228
+ }
229
+ else if (foremanQc.score === null) {
230
+ lines.push(`QC repair-loop dimension skipped: ${foremanQc.skipped_reason ?? "no reason given"}.`);
231
+ }
232
+ else {
233
+ lines.push(`QC repair-loop score: **${fmtScore(foremanQc.score)}** (${foremanQc.confidence})${foremanQc.detail ? ` — ${escapeCell(foremanQc.detail)}` : ""}`);
234
+ }
235
+ lines.push("");
236
+ if (qcRecommendations && qcRecommendations.recommendations.length > 0) {
237
+ lines.push("### QC follow-up recommendations");
238
+ lines.push("");
239
+ for (const r of qcRecommendations.recommendations) {
240
+ lines.push(`- **[${r.action_type}] ${r.id}** — ${escapeCell(r.proposed_action)} (${(r.confidence * 100).toFixed(1)}% confidence)`);
241
+ lines.push(` - Rationale: ${escapeCell(r.rationale)}`);
242
+ }
243
+ lines.push("");
244
+ }
245
+ // Recommendation inputs
246
+ lines.push("## Recommendation inputs");
247
+ lines.push("");
248
+ lines.push(renderRecommendationInputsHeader());
249
+ for (const s of allScorecards) {
250
+ lines.push(renderRecommendationInputs(s));
251
+ }
252
+ lines.push("");
253
+ // Skipped evidence
254
+ lines.push("## Skipped evidence");
255
+ lines.push("");
256
+ if (skipped.length === 0) {
257
+ lines.push("All dimensions were scored; no evidence was skipped.");
258
+ }
259
+ else {
260
+ lines.push("| Subject | Key | Dimension | Reason |");
261
+ lines.push("|---|---|---|---|");
262
+ for (const row of skipped) {
263
+ lines.push(`| ${row.subject} | ${escapeCell(row.key)} | ${row.dimension} | ${escapeCell(row.reason)} |`);
264
+ }
265
+ }
266
+ lines.push("");
267
+ // Source references (aggregated)
268
+ lines.push("## Source references");
269
+ lines.push("");
270
+ lines.push(renderSourceRefs(allScorecards.flatMap((s) => s.source_refs)));
271
+ lines.push("");
272
+ const markdown = lines.join("\n");
273
+ return {
274
+ markdown,
275
+ summary: {
276
+ run_id: record.run_id,
277
+ aggregate_score: record.report.run_composite_score,
278
+ scorecard_count: allScorecards.length,
279
+ skipped_dimensions: skipped.length,
280
+ },
281
+ };
282
+ }