homingo 0.1.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 (112) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +68 -0
  3. package/README.md +249 -0
  4. package/dist/commands/audit.d.ts +14 -0
  5. package/dist/commands/audit.d.ts.map +1 -0
  6. package/dist/commands/audit.js +178 -0
  7. package/dist/commands/audit.js.map +1 -0
  8. package/dist/commands/init.d.ts +2 -0
  9. package/dist/commands/init.d.ts.map +1 -0
  10. package/dist/commands/init.js +240 -0
  11. package/dist/commands/init.js.map +1 -0
  12. package/dist/commands/lint.d.ts +20 -0
  13. package/dist/commands/lint.d.ts.map +1 -0
  14. package/dist/commands/lint.js +490 -0
  15. package/dist/commands/lint.js.map +1 -0
  16. package/dist/commands/logs.d.ts +8 -0
  17. package/dist/commands/logs.d.ts.map +1 -0
  18. package/dist/commands/logs.js +67 -0
  19. package/dist/commands/logs.js.map +1 -0
  20. package/dist/config.d.ts +8 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +67 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +54 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/providers/anthropic.d.ts +7 -0
  29. package/dist/providers/anthropic.d.ts.map +1 -0
  30. package/dist/providers/anthropic.js +29 -0
  31. package/dist/providers/anthropic.js.map +1 -0
  32. package/dist/providers/index.d.ts +20 -0
  33. package/dist/providers/index.d.ts.map +1 -0
  34. package/dist/providers/index.js +43 -0
  35. package/dist/providers/index.js.map +1 -0
  36. package/dist/providers/openai.d.ts +7 -0
  37. package/dist/providers/openai.d.ts.map +1 -0
  38. package/dist/providers/openai.js +32 -0
  39. package/dist/providers/openai.js.map +1 -0
  40. package/dist/providers/tracked-provider.d.ts +15 -0
  41. package/dist/providers/tracked-provider.d.ts.map +1 -0
  42. package/dist/providers/tracked-provider.js +26 -0
  43. package/dist/providers/tracked-provider.js.map +1 -0
  44. package/dist/providers/types.d.ts +23 -0
  45. package/dist/providers/types.d.ts.map +1 -0
  46. package/dist/providers/types.js +2 -0
  47. package/dist/providers/types.js.map +1 -0
  48. package/dist/reporting/html-renderer.d.ts +26 -0
  49. package/dist/reporting/html-renderer.d.ts.map +1 -0
  50. package/dist/reporting/html-renderer.js +549 -0
  51. package/dist/reporting/html-renderer.js.map +1 -0
  52. package/dist/reporting/logs-viewer.d.ts +12 -0
  53. package/dist/reporting/logs-viewer.d.ts.map +1 -0
  54. package/dist/reporting/logs-viewer.js +221 -0
  55. package/dist/reporting/logs-viewer.js.map +1 -0
  56. package/dist/reporting/opener.d.ts +9 -0
  57. package/dist/reporting/opener.d.ts.map +1 -0
  58. package/dist/reporting/opener.js +49 -0
  59. package/dist/reporting/opener.js.map +1 -0
  60. package/dist/reporting/run-metadata.d.ts +55 -0
  61. package/dist/reporting/run-metadata.d.ts.map +1 -0
  62. package/dist/reporting/run-metadata.js +61 -0
  63. package/dist/reporting/run-metadata.js.map +1 -0
  64. package/dist/reporting/storage.d.ts +27 -0
  65. package/dist/reporting/storage.d.ts.map +1 -0
  66. package/dist/reporting/storage.js +126 -0
  67. package/dist/reporting/storage.js.map +1 -0
  68. package/dist/rewriter/rewriter.d.ts +21 -0
  69. package/dist/rewriter/rewriter.d.ts.map +1 -0
  70. package/dist/rewriter/rewriter.js +63 -0
  71. package/dist/rewriter/rewriter.js.map +1 -0
  72. package/dist/shadow-router/generator.d.ts +14 -0
  73. package/dist/shadow-router/generator.d.ts.map +1 -0
  74. package/dist/shadow-router/generator.js +58 -0
  75. package/dist/shadow-router/generator.js.map +1 -0
  76. package/dist/shadow-router/pair-selector.d.ts +17 -0
  77. package/dist/shadow-router/pair-selector.d.ts.map +1 -0
  78. package/dist/shadow-router/pair-selector.js +146 -0
  79. package/dist/shadow-router/pair-selector.js.map +1 -0
  80. package/dist/shadow-router/scorer.d.ts +4 -0
  81. package/dist/shadow-router/scorer.d.ts.map +1 -0
  82. package/dist/shadow-router/scorer.js +169 -0
  83. package/dist/shadow-router/scorer.js.map +1 -0
  84. package/dist/shadow-router/simulator.d.ts +17 -0
  85. package/dist/shadow-router/simulator.d.ts.map +1 -0
  86. package/dist/shadow-router/simulator.js +64 -0
  87. package/dist/shadow-router/simulator.js.map +1 -0
  88. package/dist/shard/analyzer.d.ts +28 -0
  89. package/dist/shard/analyzer.d.ts.map +1 -0
  90. package/dist/shard/analyzer.js +146 -0
  91. package/dist/shard/analyzer.js.map +1 -0
  92. package/dist/shard/writer.d.ts +11 -0
  93. package/dist/shard/writer.d.ts.map +1 -0
  94. package/dist/shard/writer.js +53 -0
  95. package/dist/shard/writer.js.map +1 -0
  96. package/dist/skills/parser.d.ts +3 -0
  97. package/dist/skills/parser.d.ts.map +1 -0
  98. package/dist/skills/parser.js +48 -0
  99. package/dist/skills/parser.js.map +1 -0
  100. package/dist/types.d.ts +83 -0
  101. package/dist/types.d.ts.map +1 -0
  102. package/dist/types.js +2 -0
  103. package/dist/types.js.map +1 -0
  104. package/dist/utils/concurrency.d.ts +2 -0
  105. package/dist/utils/concurrency.d.ts.map +1 -0
  106. package/dist/utils/concurrency.js +14 -0
  107. package/dist/utils/concurrency.js.map +1 -0
  108. package/dist/utils/retry.d.ts +7 -0
  109. package/dist/utils/retry.d.ts.map +1 -0
  110. package/dist/utils/retry.js +44 -0
  111. package/dist/utils/retry.js.map +1 -0
  112. package/package.json +88 -0
@@ -0,0 +1,549 @@
1
+ // ── Public API ─────────────────────────────────────────────────
2
+ export function generateHtml(command, metadata, commandData) {
3
+ let body;
4
+ switch (command) {
5
+ case "audit":
6
+ body = renderAuditBody(commandData);
7
+ break;
8
+ case "lint":
9
+ body = renderLintBody(commandData);
10
+ break;
11
+ }
12
+ return wrapPage(command, metadata, body);
13
+ }
14
+ // ── Severity helpers ───────────────────────────────────────────
15
+ const SEVERITY_COLORS = {
16
+ CRITICAL: "#dc2626",
17
+ HIGH: "#f59e0b",
18
+ MEDIUM: "#3b82f6",
19
+ LOW: "#22c55e",
20
+ };
21
+ function severityBadge(level) {
22
+ const color = SEVERITY_COLORS[level] || "#6b7280";
23
+ return `<span style="display:inline-block;padding:2px 8px;border-radius:4px;font-size:12px;font-weight:600;color:#fff;background:${color}">${esc(level)}</span>`;
24
+ }
25
+ // ── Shared page wrapper ────────────────────────────────────────
26
+ function wrapPage(command, meta, body) {
27
+ const title = `Homingo ${capitalize(command)} Report`;
28
+ const date = meta.timestamp.slice(0, 10);
29
+ const duration = (meta.durationMs / 1000).toFixed(1);
30
+ const totalTokens = meta.tokens.total.toLocaleString();
31
+ return `<!DOCTYPE html>
32
+ <html lang="en">
33
+ <head>
34
+ <meta charset="utf-8">
35
+ <meta name="viewport" content="width=device-width, initial-scale=1">
36
+ <title>${esc(title)} — ${date}</title>
37
+ <style>${CSS}</style>
38
+ </head>
39
+ <body>
40
+ <header>
41
+ <div class="header-row">
42
+ <h1>🐦 ${esc(title)}</h1>
43
+ <a href="../logs-viewer.html" class="home-link">← All Runs</a>
44
+ </div>
45
+ <div class="meta-bar">
46
+ <span class="meta-item"><strong>Date:</strong> ${esc(date)}</span>
47
+ <span class="meta-item"><strong>Model:</strong> ${esc(meta.model)}</span>
48
+ <span class="meta-item"><strong>Provider:</strong> ${esc(meta.provider)}</span>
49
+ <span class="meta-item"><strong>Skills:</strong> ${meta.skillCount}</span>
50
+ <span class="meta-item"><strong>Duration:</strong> ${duration}s</span>
51
+ <span class="meta-item"><strong>Tokens:</strong> ${totalTokens} (${meta.tokens.input.toLocaleString()} in / ${meta.tokens.output.toLocaleString()} out)</span>
52
+ ${meta.gitCommitHash ? `<span class="meta-item"><strong>Git:</strong> <code>${esc(meta.gitCommitHash)}</code></span>` : ""}
53
+ </div>
54
+ </header>
55
+ <main>
56
+ ${body}
57
+ </main>
58
+ <footer>
59
+ <p>Generated by <strong>Homingo</strong> · Run ID: <code>${esc(meta.id.slice(0, 8))}</code></p>
60
+ </footer>
61
+ </body>
62
+ </html>`;
63
+ }
64
+ // ── Audit renderer ─────────────────────────────────────────────
65
+ function renderAuditBody(report) {
66
+ const sections = [
67
+ { label: "CRITICAL", pairs: report.criticalPairs },
68
+ { label: "HIGH", pairs: report.highPairs },
69
+ { label: "MEDIUM", pairs: report.mediumPairs },
70
+ { label: "LOW", pairs: report.lowPairs },
71
+ ];
72
+ let html = `
73
+ <div class="summary-cards">
74
+ <div class="card card-stat">
75
+ <div class="card-label">Fleet Error Rate</div>
76
+ <div class="card-value">${report.estimatedFleetErrorRate}%</div>
77
+ </div>
78
+ <div class="card card-stat">
79
+ <div class="card-label">Pairs Tested</div>
80
+ <div class="card-value">${report.totalPairsTested}</div>
81
+ </div>
82
+ <div class="card card-stat">
83
+ <div class="card-label">Total Skills</div>
84
+ <div class="card-value">${report.totalSkills}</div>
85
+ </div>
86
+ <div class="card card-stat">
87
+ <div class="card-label">Critical Pairs</div>
88
+ <div class="card-value" style="color:${SEVERITY_COLORS.CRITICAL}">${report.criticalPairs.length}</div>
89
+ </div>
90
+ </div>`;
91
+ for (const section of sections) {
92
+ if (section.pairs.length === 0)
93
+ continue;
94
+ html += renderPairSection(section.label, section.pairs);
95
+ }
96
+ if (report.topFiveOffenders.length > 0) {
97
+ html += `<section><h2>Top Offenders</h2><ol>`;
98
+ for (const name of report.topFiveOffenders) {
99
+ html += `<li><strong>${esc(name)}</strong></li>`;
100
+ }
101
+ html += `</ol></section>`;
102
+ }
103
+ return html;
104
+ }
105
+ function renderPairSection(label, pairs) {
106
+ const color = SEVERITY_COLORS[label] || "#6b7280";
107
+ let html = `<section>
108
+ <h2 style="color:${color}">${esc(label)} <span class="count">(${pairs.length} pair${pairs.length !== 1 ? "s" : ""})</span></h2>
109
+ <table>
110
+ <thead><tr><th>Skill Pair</th><th>Accuracy</th><th>Action</th></tr></thead>
111
+ <tbody>`;
112
+ for (const pair of pairs) {
113
+ html += `<tr>
114
+ <td><strong>${esc(pair.skillA)}</strong> ↔ <strong>${esc(pair.skillB)}</strong></td>
115
+ <td>${pair.routingAccuracy}%</td>
116
+ <td>${esc(pair.recommendedAction)}</td>
117
+ </tr>`;
118
+ // Expandable misroute details
119
+ if (pair.misroutes.length > 0) {
120
+ html += `<tr><td colspan="3">
121
+ <details>
122
+ <summary>${pair.misroutes.length} misrouted prompt${pair.misroutes.length !== 1 ? "s" : ""}</summary>
123
+ <ul class="misroute-list">`;
124
+ for (const m of pair.misroutes.slice(0, 10)) {
125
+ html += `<li>
126
+ <span class="prompt-text">"${esc(m.promptText)}"</span>
127
+ <br><span class="misroute-detail">Expected: <strong>${esc(m.expectedSkill)}</strong> → Got: <strong>${esc(m.selectedSkill)}</strong></span>
128
+ </li>`;
129
+ }
130
+ if (pair.misroutes.length > 10) {
131
+ html += `<li class="more">…and ${pair.misroutes.length - 10} more</li>`;
132
+ }
133
+ html += `</ul></details></td></tr>`;
134
+ }
135
+ }
136
+ html += `</tbody></table></section>`;
137
+ return html;
138
+ }
139
+ // ── Lint renderer ──────────────────────────────────────────────
140
+ function renderLintBody(data) {
141
+ const totalNeighbors = data.failingReports.length + data.passingCount;
142
+ const allPassed = data.failingReports.length === 0;
143
+ let html = `
144
+ <div class="summary-cards">
145
+ <div class="card card-stat ${allPassed ? "card-pass" : "card-fail"}">
146
+ <div class="card-label">Result</div>
147
+ <div class="card-value">${allPassed ? "✅ PASS" : "❌ FAIL"}</div>
148
+ </div>
149
+ <div class="card card-stat">
150
+ <div class="card-label">Neighbors Tested</div>
151
+ <div class="card-value">${totalNeighbors}</div>
152
+ </div>
153
+ <div class="card card-stat">
154
+ <div class="card-label">Passing</div>
155
+ <div class="card-value" style="color:${SEVERITY_COLORS.LOW}">${data.passingCount}</div>
156
+ </div>
157
+ <div class="card card-stat">
158
+ <div class="card-label">Failing</div>
159
+ <div class="card-value" style="color:${SEVERITY_COLORS.CRITICAL}">${data.failingReports.length}</div>
160
+ </div>
161
+ </div>`;
162
+ if (data.failingReports.length > 0) {
163
+ html += `<section><h2>Failing Pairs</h2>`;
164
+ html += `<table>
165
+ <thead><tr><th>Skill Pair</th><th>Accuracy</th><th>Severity</th><th>Action</th></tr></thead>
166
+ <tbody>`;
167
+ for (const r of data.failingReports) {
168
+ html += `<tr>
169
+ <td>${esc(r.skillA)} ↔ ${esc(r.skillB)}</td>
170
+ <td>${r.routingAccuracy}%</td>
171
+ <td>${severityBadge(r.severityLevel)}</td>
172
+ <td>${esc(r.recommendedAction)}</td>
173
+ </tr>`;
174
+ }
175
+ html += `</tbody></table></section>`;
176
+ }
177
+ if (data.rewriteSuggestions.length > 0) {
178
+ html += `<section><h2>Rewrite Suggestions</h2>`;
179
+ for (const s of data.rewriteSuggestions) {
180
+ html += `<div class="rewrite-card">
181
+ <h3>${esc(s.skillName)}</h3>
182
+ <p class="reasoning">${esc(s.reasoning)}</p>
183
+ <div class="diff-view">
184
+ <div class="diff-old"><strong>Original:</strong><pre>${esc(s.originalDescription)}</pre></div>
185
+ <div class="diff-new"><strong>Suggested:</strong><pre>${esc(s.rewrittenDescription)}</pre></div>
186
+ </div>
187
+ <p class="conflicts-with">Conflicts with: ${s.conflictsWith.map((c) => `<code>${esc(c)}</code>`).join(", ")}</p>
188
+ </div>`;
189
+ }
190
+ html += `</section>`;
191
+ }
192
+ // Scope overload / shard findings
193
+ if (data.shardFindings && data.shardFindings.length > 0) {
194
+ const overloaded = data.shardFindings.filter((f) => f.isOverloaded);
195
+ if (overloaded.length > 0) {
196
+ html += `<section><h2>Scope Overload</h2>
197
+ <p class="section-desc">${overloaded.length} skill${overloaded.length !== 1 ? "s" : ""} detected as overloaded — descriptions cover too many intents.</p>`;
198
+ for (const finding of overloaded) {
199
+ html += `<div class="skill-card">
200
+ <h3>${esc(finding.skillName)} <span class="count">(${finding.descriptionLength} chars)</span></h3>
201
+ <p class="reasoning">${esc(finding.reason)}</p>`;
202
+ if (finding.plan) {
203
+ html += renderShardPlanDetails(finding.plan);
204
+ }
205
+ html += `</div>`;
206
+ }
207
+ html += `</section>`;
208
+ }
209
+ }
210
+ return html;
211
+ }
212
+ // ── Shard plan detail renderer (used within lint reports) ──────
213
+ function renderShardPlanDetails(plan) {
214
+ let html = `
215
+ <div class="shard-details">
216
+ <p><strong>Identified Intents:</strong></p>
217
+ <ol>`;
218
+ for (const intent of plan.identifiedIntents) {
219
+ html += `<li>${esc(intent)}</li>`;
220
+ }
221
+ html += `</ol>
222
+
223
+ <p><strong>Proposed Sub-Skills:</strong></p>`;
224
+ for (const sub of plan.subSkills) {
225
+ html += `<div class="skill-card">
226
+ <h3>${esc(sub.name)}</h3>
227
+ <p>${esc(sub.description)}</p>
228
+ <p><strong>Intents:</strong> ${sub.intents.map((i) => `<code>${esc(i)}</code>`).join(", ")}</p>
229
+ ${sub.negativeTriggers.length > 0 ? `<p class="negative-triggers"><strong>Negative triggers:</strong> ${sub.negativeTriggers.map((t) => `<em>${esc(t)}</em>`).join(" · ")}</p>` : ""}
230
+ </div>`;
231
+ }
232
+ html += `<p><strong>Orchestrator:</strong></p>
233
+ <div class="skill-card orchestrator-card">
234
+ <h3>${esc(plan.orchestrator.name)}</h3>
235
+ <p>${esc(plan.orchestrator.description)}</p>
236
+ ${plan.orchestrator.negativeTriggers.length > 0 ? `<p class="negative-triggers"><strong>Negative triggers:</strong> ${plan.orchestrator.negativeTriggers.map((t) => `<em>${esc(t)}</em>`).join(" · ")}</p>` : ""}
237
+ </div>
238
+ </div>`;
239
+ return html;
240
+ }
241
+ // ── Utilities ──────────────────────────────────────────────────
242
+ function esc(s) {
243
+ return s
244
+ .replace(/&/g, "&amp;")
245
+ .replace(/</g, "&lt;")
246
+ .replace(/>/g, "&gt;")
247
+ .replace(/"/g, "&quot;");
248
+ }
249
+ function capitalize(s) {
250
+ return s.charAt(0).toUpperCase() + s.slice(1);
251
+ }
252
+ // ── CSS ────────────────────────────────────────────────────────
253
+ const CSS = `
254
+ :root {
255
+ --bg: #f8fafc;
256
+ --card-bg: #ffffff;
257
+ --text: #1e293b;
258
+ --text-muted: #64748b;
259
+ --border: #e2e8f0;
260
+ --critical: #dc2626;
261
+ --high: #f59e0b;
262
+ --medium: #3b82f6;
263
+ --low: #22c55e;
264
+ --accent: #6366f1;
265
+ }
266
+
267
+ * { margin: 0; padding: 0; box-sizing: border-box; }
268
+
269
+ body {
270
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
271
+ background: var(--bg);
272
+ color: var(--text);
273
+ line-height: 1.6;
274
+ padding: 2rem;
275
+ max-width: 1200px;
276
+ margin: 0 auto;
277
+ }
278
+
279
+ header {
280
+ margin-bottom: 2rem;
281
+ padding-bottom: 1rem;
282
+ border-bottom: 2px solid var(--border);
283
+ }
284
+
285
+ header h1 {
286
+ font-size: 1.5rem;
287
+ margin-bottom: 0;
288
+ }
289
+
290
+ .header-row {
291
+ display: flex;
292
+ justify-content: space-between;
293
+ align-items: center;
294
+ margin-bottom: 0.75rem;
295
+ }
296
+
297
+ .home-link {
298
+ color: var(--accent);
299
+ text-decoration: none;
300
+ font-size: 0.9rem;
301
+ font-weight: 500;
302
+ padding: 0.4rem 0.75rem;
303
+ border: 1px solid var(--accent);
304
+ border-radius: 6px;
305
+ transition: background 0.15s, color 0.15s;
306
+ }
307
+
308
+ .home-link:hover {
309
+ background: var(--accent);
310
+ color: #fff;
311
+ }
312
+
313
+ .meta-bar {
314
+ display: flex;
315
+ flex-wrap: wrap;
316
+ gap: 1rem;
317
+ font-size: 0.85rem;
318
+ color: var(--text-muted);
319
+ }
320
+
321
+ .meta-item code {
322
+ font-family: "SF Mono", "Fira Code", monospace;
323
+ background: var(--border);
324
+ padding: 1px 4px;
325
+ border-radius: 3px;
326
+ font-size: 0.8rem;
327
+ }
328
+
329
+ .summary-cards {
330
+ display: grid;
331
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
332
+ gap: 1rem;
333
+ margin-bottom: 2rem;
334
+ }
335
+
336
+ .card {
337
+ background: var(--card-bg);
338
+ border: 1px solid var(--border);
339
+ border-radius: 8px;
340
+ padding: 1rem 1.25rem;
341
+ }
342
+
343
+ .card-stat .card-label {
344
+ font-size: 0.8rem;
345
+ color: var(--text-muted);
346
+ text-transform: uppercase;
347
+ letter-spacing: 0.05em;
348
+ }
349
+
350
+ .card-stat .card-value {
351
+ font-size: 1.75rem;
352
+ font-weight: 700;
353
+ margin-top: 0.25rem;
354
+ }
355
+
356
+ .card-pass { border-left: 4px solid var(--low); }
357
+ .card-fail { border-left: 4px solid var(--critical); }
358
+
359
+ section {
360
+ margin-bottom: 2rem;
361
+ }
362
+
363
+ section h2 {
364
+ font-size: 1.25rem;
365
+ margin-bottom: 0.75rem;
366
+ }
367
+
368
+ .count {
369
+ font-weight: 400;
370
+ font-size: 0.9rem;
371
+ color: var(--text-muted);
372
+ }
373
+
374
+ table {
375
+ width: 100%;
376
+ border-collapse: collapse;
377
+ background: var(--card-bg);
378
+ border-radius: 8px;
379
+ overflow: hidden;
380
+ border: 1px solid var(--border);
381
+ }
382
+
383
+ thead th {
384
+ text-align: left;
385
+ padding: 0.75rem 1rem;
386
+ background: #f1f5f9;
387
+ font-size: 0.8rem;
388
+ text-transform: uppercase;
389
+ letter-spacing: 0.05em;
390
+ color: var(--text-muted);
391
+ }
392
+
393
+ tbody td {
394
+ padding: 0.75rem 1rem;
395
+ border-top: 1px solid var(--border);
396
+ font-size: 0.9rem;
397
+ }
398
+
399
+ details {
400
+ margin: 0.5rem 0;
401
+ }
402
+
403
+ summary {
404
+ cursor: pointer;
405
+ font-size: 0.85rem;
406
+ color: var(--accent);
407
+ font-weight: 500;
408
+ }
409
+
410
+ .misroute-list {
411
+ list-style: none;
412
+ padding: 0.5rem 0;
413
+ }
414
+
415
+ .misroute-list li {
416
+ padding: 0.5rem 0;
417
+ border-bottom: 1px solid var(--border);
418
+ font-size: 0.85rem;
419
+ }
420
+
421
+ .misroute-list li:last-child { border-bottom: none; }
422
+
423
+ .prompt-text {
424
+ font-style: italic;
425
+ color: var(--text-muted);
426
+ }
427
+
428
+ .misroute-detail {
429
+ font-size: 0.8rem;
430
+ }
431
+
432
+ .more {
433
+ color: var(--text-muted);
434
+ font-style: italic;
435
+ }
436
+
437
+ .rewrite-card {
438
+ background: var(--card-bg);
439
+ border: 1px solid var(--border);
440
+ border-radius: 8px;
441
+ padding: 1.25rem;
442
+ margin-bottom: 1rem;
443
+ }
444
+
445
+ .rewrite-card h3 { margin-bottom: 0.5rem; }
446
+ .rewrite-card .reasoning { color: var(--text-muted); font-size: 0.9rem; margin-bottom: 0.75rem; }
447
+
448
+ .diff-view {
449
+ display: grid;
450
+ grid-template-columns: 1fr 1fr;
451
+ gap: 1rem;
452
+ margin-bottom: 0.75rem;
453
+ }
454
+
455
+ .diff-old, .diff-new {
456
+ border-radius: 6px;
457
+ padding: 0.75rem;
458
+ font-size: 0.85rem;
459
+ }
460
+
461
+ .diff-old {
462
+ background: #fef2f2;
463
+ border: 1px solid #fecaca;
464
+ }
465
+
466
+ .diff-new {
467
+ background: #f0fdf4;
468
+ border: 1px solid #bbf7d0;
469
+ }
470
+
471
+ .diff-old pre, .diff-new pre {
472
+ white-space: pre-wrap;
473
+ word-break: break-word;
474
+ font-family: "SF Mono", "Fira Code", monospace;
475
+ font-size: 0.8rem;
476
+ margin-top: 0.5rem;
477
+ }
478
+
479
+ .conflicts-with { font-size: 0.85rem; color: var(--text-muted); }
480
+ .conflicts-with code { background: var(--border); padding: 1px 4px; border-radius: 3px; }
481
+
482
+ .skill-card {
483
+ background: var(--card-bg);
484
+ border: 1px solid var(--border);
485
+ border-radius: 8px;
486
+ padding: 1.25rem;
487
+ margin-bottom: 1rem;
488
+ }
489
+
490
+ .skill-card h3 { margin-bottom: 0.5rem; }
491
+ .skill-card code { background: var(--border); padding: 1px 4px; border-radius: 3px; font-size: 0.8rem; }
492
+
493
+ .orchestrator-card {
494
+ border-left: 4px solid var(--accent);
495
+ }
496
+
497
+ .negative-triggers {
498
+ font-size: 0.85rem;
499
+ color: var(--text-muted);
500
+ margin-top: 0.5rem;
501
+ }
502
+
503
+ .negative-triggers em {
504
+ background: #fef3c7;
505
+ padding: 1px 4px;
506
+ border-radius: 3px;
507
+ font-style: normal;
508
+ font-size: 0.8rem;
509
+ }
510
+
511
+ .section-desc {
512
+ color: var(--text-muted);
513
+ font-size: 0.9rem;
514
+ margin-bottom: 1rem;
515
+ }
516
+
517
+ .shard-details {
518
+ margin-top: 1rem;
519
+ padding-top: 0.75rem;
520
+ border-top: 1px solid var(--border);
521
+ }
522
+
523
+ footer {
524
+ margin-top: 3rem;
525
+ padding-top: 1rem;
526
+ border-top: 1px solid var(--border);
527
+ text-align: center;
528
+ font-size: 0.8rem;
529
+ color: var(--text-muted);
530
+ }
531
+
532
+ footer code {
533
+ font-family: "SF Mono", "Fira Code", monospace;
534
+ background: var(--border);
535
+ padding: 1px 4px;
536
+ border-radius: 3px;
537
+ }
538
+
539
+ ol, ul { padding-left: 1.5rem; }
540
+ li { margin-bottom: 0.25rem; }
541
+
542
+ @media (max-width: 768px) {
543
+ body { padding: 1rem; }
544
+ .summary-cards { grid-template-columns: 1fr 1fr; }
545
+ .diff-view { grid-template-columns: 1fr; }
546
+ .meta-bar { flex-direction: column; gap: 0.5rem; }
547
+ }
548
+ `;
549
+ //# sourceMappingURL=html-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-renderer.js","sourceRoot":"","sources":["../../src/reporting/html-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { CommandName, RunMetadata } from "./run-metadata.js";
2
+ export interface LogEntry {
3
+ metadata: RunMetadata;
4
+ htmlPath: string;
5
+ }
6
+ export type LogsByCommand = Record<CommandName, LogEntry[]>;
7
+ /**
8
+ * Generate a self-contained HTML page that lets the user browse
9
+ * the last 10 runs per command with tabs and "View Report" links.
10
+ */
11
+ export declare function generateLogsViewer(allRuns: LogsByCommand): string;
12
+ //# sourceMappingURL=logs-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logs-viewer.d.ts","sourceRoot":"","sources":["../../src/reporting/logs-viewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC;AAE5D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAmFjE"}