@netlify/axis 0.3.1 → 1.1.1

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 (56) hide show
  1. package/README.md +3 -5
  2. package/dist/baselines/{diff.d.ts → compare.d.ts} +3 -3
  3. package/dist/baselines/compare.d.ts.map +1 -0
  4. package/dist/baselines/{diff.js → compare.js} +2 -2
  5. package/dist/baselines/compare.js.map +1 -0
  6. package/dist/baselines/index.d.ts +1 -1
  7. package/dist/baselines/index.d.ts.map +1 -1
  8. package/dist/baselines/index.js +1 -1
  9. package/dist/baselines/index.js.map +1 -1
  10. package/dist/cli.js +16 -12
  11. package/dist/cli.js.map +1 -1
  12. package/dist/config/validator.js +4 -4
  13. package/dist/index.d.ts +4 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/report-ui/index.html +49 -46
  18. package/dist/reports/writer.d.ts +28 -7
  19. package/dist/reports/writer.d.ts.map +1 -1
  20. package/dist/reports/writer.js +69 -30
  21. package/dist/reports/writer.js.map +1 -1
  22. package/dist/scoring/deep-eval.d.ts +27 -7
  23. package/dist/scoring/deep-eval.d.ts.map +1 -1
  24. package/dist/scoring/deep-eval.js +242 -147
  25. package/dist/scoring/deep-eval.js.map +1 -1
  26. package/dist/scoring/goal-achievement.d.ts.map +1 -1
  27. package/dist/scoring/goal-achievement.js +26 -102
  28. package/dist/scoring/goal-achievement.js.map +1 -1
  29. package/dist/scoring/index.d.ts +1 -1
  30. package/dist/scoring/index.d.ts.map +1 -1
  31. package/dist/scoring/index.js +12 -7
  32. package/dist/scoring/index.js.map +1 -1
  33. package/dist/scoring/judge.d.ts +14 -0
  34. package/dist/scoring/judge.d.ts.map +1 -0
  35. package/dist/scoring/judge.js +36 -0
  36. package/dist/scoring/judge.js.map +1 -0
  37. package/dist/scoring/prompt-templates.d.ts +50 -0
  38. package/dist/scoring/prompt-templates.d.ts.map +1 -0
  39. package/dist/scoring/prompt-templates.js +252 -0
  40. package/dist/scoring/prompt-templates.js.map +1 -0
  41. package/dist/types/baseline.d.ts +4 -4
  42. package/dist/types/baseline.d.ts.map +1 -1
  43. package/dist/types/config.d.ts +2 -2
  44. package/dist/types/scoring.d.ts +25 -26
  45. package/dist/types/scoring.d.ts.map +1 -1
  46. package/dist/ui/format.d.ts +2 -2
  47. package/dist/ui/format.d.ts.map +1 -1
  48. package/dist/ui/format.js +1 -1
  49. package/dist/ui/format.js.map +1 -1
  50. package/package.json +1 -1
  51. package/dist/baselines/diff.d.ts.map +0 -1
  52. package/dist/baselines/diff.js.map +0 -1
  53. package/dist/scoring/triage.d.ts +0 -15
  54. package/dist/scoring/triage.d.ts.map +0 -1
  55. package/dist/scoring/triage.js +0 -204
  56. package/dist/scoring/triage.js.map +0 -1
@@ -1,4 +1,4 @@
1
- <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AXIS Report</title><style>:root{--bg: #fafbf9;--bg-card: #ffffff;--bg-alt: #f3f4f6;--text: #1a1a2e;--text-secondary: #4a5568;--text-muted: #637083;--mid-gray: #6b7280;--light-gray: #e5e7eb;--border: #e5e7eb;--accent: #016867;--accent-hover: #015554;--accent-bright: #2dd4bf;--accent-light: rgba(1, 104, 103, .07);--success: #059669;--success-light: #ecfdf5;--yellow: #d97706;--yellow-light: #fffbeb;--warning: #d97706;--warning-light: #fffbeb;--danger: #dc2626;--danger-light: #fef2f2;--cat-env: #059669;--cat-svc: #2563eb;--cat-agent: #6b7280;--radius: 8px;--radius-lg: 12px;--shadow: 0 1px 3px rgba(0, 0, 0, .04), 0 2px 8px rgba(0, 0, 0, .03);--shadow-lg: 0 4px 16px rgba(0, 0, 0, .06), 0 0 40px rgba(1, 104, 103, .04);--font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, sans-serif;--font-mono: "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;--transition: .15s ease}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{font-size:15px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:var(--font);color:var(--text);background:var(--bg);line-height:1.6;min-height:100vh}.container{max-width:1120px;margin:0 auto;padding:32px 24px 64px}h1{font-size:2rem;font-weight:800;letter-spacing:-.02em;background:linear-gradient(135deg,var(--text) 0%,var(--accent) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}h2{font-size:1.375rem;font-weight:700;letter-spacing:-.01em;color:var(--text)}h3{font-size:1.0625rem;font-weight:600;color:var(--text)}.report-header{margin-bottom:32px}.report-branding{display:flex;align-items:baseline;gap:12px;margin-bottom:16px}.site-logo-mark{font-size:2.0625rem;font-weight:800;letter-spacing:.12em;color:var(--accent)}.logo-ax{letter-spacing:-.06em}.logo-i{display:inline-block;font-style:italic;transform:skew(-20deg);margin-left:2px;margin-right:-2px}.report-badge{font-size:.8125rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted)}.report-meta{margin-bottom:24px}.report-meta-row{font-size:.875rem;line-height:1.8;color:var(--text-secondary)}.report-meta-label{font-weight:600;color:var(--text)}.report-meta-value{color:var(--text-secondary)}.report-meta-id{font-family:var(--font-mono);font-size:.8125rem}.summary-cards{display:flex;gap:12px;flex-wrap:wrap}.summary-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:16px 20px;min-width:120px;flex:1;box-shadow:var(--shadow);transition:box-shadow var(--transition)}.summary-card:hover{box-shadow:var(--shadow-lg)}.summary-card .card-value{font-size:1.5rem;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:2px}.summary-card .card-label{font-size:.75rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);font-weight:500}.summary-card.card-failed .card-value{color:var(--danger)}.score-badge{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:28px;padding:0 8px;border-radius:14px;font-size:.8125rem;font-weight:700;color:#fff;line-height:1}.score-badge.score-green{background:var(--success)}.score-badge.score-yellow{background:var(--yellow)}.score-badge.score-orange{background:#ea580c}.score-badge.score-red{background:var(--danger)}.score-badge.score-na{background:var(--mid-gray);font-weight:500}.score-badge-lg{min-width:64px;height:64px;border-radius:32px;font-size:1.5rem;padding:0 16px}.results-section{margin-top:32px}.results-table{width:100%;border-collapse:collapse;font-size:.875rem}.results-table thead th{text-align:left;padding:10px 12px;font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;border-bottom:2px solid var(--light-gray);white-space:nowrap}.results-table thead th.col-score{text-align:center;width:60px}.results-table thead th.col-right{text-align:right}.result-row{cursor:pointer;transition:background var(--transition)}.result-row:hover,.result-row.expanded{background:var(--accent-light)}.result-row td{padding:12px;border-bottom:1px solid var(--light-gray);vertical-align:middle}.result-row td.col-score{text-align:center}.result-row td.col-right{text-align:right;font-family:var(--font-mono);font-size:.8125rem;color:var(--text-secondary)}.result-row td.col-scenario{font-weight:500;max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.result-row td.col-agent{color:var(--text-secondary);font-family:var(--font-mono);font-size:.8125rem}.result-row .expand-icon{display:inline-block;width:16px;color:var(--text-muted);transition:transform var(--transition);font-size:.75rem}.result-row.expanded .expand-icon{transform:rotate(90deg)}.result-row .error-hint{display:block;font-size:.75rem;color:var(--danger);margin-top:2px}.detail-row{display:none}.detail-row.visible{display:table-row}.detail-row td{padding:0;border-bottom:2px solid var(--light-gray)}.detail-panel{padding:24px;background:var(--bg)}.score-overview{display:flex;align-items:flex-start;gap:32px;margin-bottom:32px;padding-bottom:24px;border-bottom:1px solid var(--light-gray)}.score-overview .big-score{flex-shrink:0}.category-bars{flex:1;display:flex;flex-direction:column;gap:8px;padding-top:4px}.category-bar-row{display:flex;align-items:center;gap:12px}.category-bar-label{width:120px;font-size:.8125rem;font-weight:500;color:var(--text-secondary);flex-shrink:0}.category-bar-value{font-size:.8125rem;font-weight:600;width:32px;text-align:right;flex-shrink:0}.progress-bar{flex:1;height:8px;background:var(--light-gray);border-radius:4px;overflow:hidden;min-width:80px}.progress-bar .fill{height:100%;border-radius:4px;transition:width .4s ease}.progress-bar .fill.fill-green{background:var(--success)}.progress-bar .fill.fill-yellow{background:var(--yellow)}.progress-bar .fill.fill-orange{background:#ea580c}.progress-bar .fill.fill-red{background:var(--danger)}.detail-sections{display:flex;flex-direction:column;gap:20px}.detail-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px;box-shadow:var(--shadow)}.section-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.section-header h3{display:flex;align-items:center;gap:8px}.section-score{font-size:.875rem;font-weight:600;color:var(--text-secondary)}.criteria-list{display:flex;flex-direction:column;gap:12px}.criterion-item{padding:12px;background:var(--bg);border-radius:var(--radius);border:1px solid var(--light-gray)}.criterion-top{display:flex;align-items:center;gap:8px;margin-bottom:6px}.criterion-icon{font-size:.875rem;width:20px;text-align:center;flex-shrink:0}.criterion-icon.high{color:var(--success)}.criterion-icon.good{color:var(--yellow)}.criterion-icon.medium{color:#ea580c}.criterion-icon.low{color:var(--danger)}.criterion-name{flex:1;font-size:.8125rem;font-weight:500}.criterion-score{font-size:.8125rem;font-weight:600;color:var(--text-secondary);flex-shrink:0}.criterion-weight{font-size:.6875rem;color:var(--text-muted);background:var(--light-gray);padding:1px 6px;border-radius:3px;flex-shrink:0}.criterion-bar{margin-bottom:8px}.criterion-rationale{font-size:.8125rem;color:var(--text-secondary);line-height:1.5;font-style:italic}.criterion-perfect{padding:8px 12px;background:var(--success-light);border-left:3px solid var(--success)}.criterion-perfect .criterion-bar{display:none}.criterion-imperfect{border-left:3px solid var(--warning)}.deductions-summary{background:var(--warning-light);border:1px solid var(--warning);border-radius:var(--radius);padding:14px 16px;margin-bottom:16px}.deductions-header{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--warning);margin-bottom:10px}.deduction-item{display:grid;grid-template-columns:1fr auto;gap:4px 12px;padding:6px 0;border-bottom:1px solid rgba(217,119,6,.15)}.deduction-item:last-child{border-bottom:none;padding-bottom:0}.deduction-criterion{font-size:.8125rem;font-weight:500;color:var(--text)}.deduction-lost{font-size:.75rem;font-weight:600;font-family:var(--font-mono);color:var(--warning);white-space:nowrap}.deduction-rationale{grid-column:1 / -1;font-size:.75rem;color:var(--text-secondary);line-height:1.5;font-style:italic}.dim-tags{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}.dim-tag{font-size:.6875rem;font-weight:600;font-family:var(--font-mono);padding:2px 8px;border-radius:10px;color:#fff}.dim-tag.fill-green{background:var(--success)}.dim-tag.fill-yellow{background:var(--yellow)}.dim-tag.fill-orange{background:#ea580c}.dim-tag.fill-red{background:var(--danger)}.cat-deduction-item{padding:8px 0;border-bottom:1px solid rgba(217,119,6,.15)}.cat-deduction-item:last-child{border-bottom:none;padding-bottom:0}.cat-deduction-id{font-family:var(--font-mono);font-size:.75rem;font-weight:600;color:var(--text);margin-right:8px}.cat-deduction-scores{display:inline-flex;gap:4px}.dim-score-tag{font-size:.625rem;font-family:var(--font-mono);background:var(--light-gray);padding:1px 5px;border-radius:3px;color:var(--text-secondary)}.cat-deduction-rationale{display:block;font-size:.75rem;color:var(--text-secondary);line-height:1.5;font-style:italic;margin-top:4px}.cat-deduction-note{font-size:.75rem;color:var(--text-muted);font-style:italic}.deductions-baseline{background:var(--bg);border-color:var(--light-gray)}.deductions-baseline .deductions-header{color:var(--text-muted)}.dimensions-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px;margin-bottom:16px}.dimension-item{display:flex;align-items:center;gap:8px}.dimension-label{width:72px;font-size:.75rem;font-weight:500;color:var(--text-secondary);flex-shrink:0}.dimension-value{font-size:.75rem;font-weight:600;width:28px;text-align:right;flex-shrink:0}.interaction-meta{font-size:.75rem;color:var(--text-muted);margin-bottom:12px}.audits-section{margin-top:12px}.audits-toggle{font-size:.75rem;color:var(--accent);background:none;border:none;cursor:pointer;font-family:var(--font);padding:4px 0;font-weight:500}.audits-toggle:hover{color:var(--accent-hover)}.audits-list{display:none;margin-top:8px}.audits-list.visible{display:block}.audit-item{padding:10px 12px;background:var(--bg);border-radius:var(--radius);margin-bottom:6px;border-left:3px solid var(--mid-gray)}.audit-header{display:flex;align-items:center;gap:8px;margin-bottom:4px;flex-wrap:wrap}.audit-id{font-family:var(--font-mono);font-size:.75rem;font-weight:600;color:var(--text)}.audit-scores{font-family:var(--font-mono);font-size:.6875rem;color:var(--text-muted)}.audit-rationale{font-size:.8125rem;color:var(--text-secondary);line-height:1.5}.necessity-section{margin-top:12px;padding-top:12px;border-top:1px solid var(--light-gray)}.necessity-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.necessity-label{font-size:.75rem;font-weight:600;color:var(--text-secondary)}.necessity-score{font-size:.75rem;font-weight:600}.necessity-rationale{font-size:.8125rem;color:var(--text-secondary);font-style:italic}.waterfall{font-size:.8125rem}.waterfall-header{display:flex;align-items:flex-end;border-bottom:1px solid var(--light-gray);padding-bottom:6px;margin-bottom:2px}.wf-label-col{width:200px;flex-shrink:0;display:flex;align-items:center;gap:6px;overflow:hidden}.waterfall-header .wf-label-col,.waterfall-header .wf-dur-col{font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600}.wf-timeline-col{flex:1;min-width:0;position:relative}.wf-dur-col{width:64px;flex-shrink:0;text-align:right;font-family:var(--font-mono);font-size:.75rem;color:var(--text-secondary)}.wf-ticks{position:relative;height:18px}.wf-tick{position:absolute;transform:translate(-50%);font-family:var(--font-mono);font-size:.625rem;color:var(--text-muted);white-space:nowrap;top:0}.wf-tick:after{content:"";position:absolute;left:50%;top:100%;width:1px;height:4px;background:var(--light-gray)}.waterfall-body{position:relative}.wf-row{display:flex;align-items:center;height:26px;border-bottom:1px solid rgba(0,0,0,.03)}.wf-row:hover{background:var(--accent-light)}.wf-id{font-family:var(--font-mono);font-size:.6875rem;color:var(--text-muted);width:28px;flex-shrink:0}.wf-cat{font-size:.625rem;text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);width:36px;flex-shrink:0}.wf-tool{font-size:.75rem;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wf-track{position:relative;height:14px;background:#00000004;border-radius:2px}.wf-bar{position:absolute;top:2px;height:10px;border-radius:2px;min-width:3px;cursor:default;transition:opacity var(--transition)}.wf-row:hover .wf-bar{opacity:.8}.wf-env .wf-bar{background:var(--cat-env)}.wf-svc .wf-bar{background:var(--cat-svc)}.wf-agent .wf-bar{background:var(--cat-agent)}.wf-bar-error{background:var(--danger)!important}.wf-show-all{display:block;width:100%;margin-top:4px;padding:6px;font-size:.75rem;color:var(--accent);background:none;border:1px dashed var(--light-gray);border-radius:var(--radius);cursor:pointer;font-family:var(--font);font-weight:500}.wf-show-all:hover{background:var(--accent-light);border-color:var(--accent)}.wf-legend{display:flex;gap:16px;margin-top:10px;padding-top:8px;border-top:1px solid var(--light-gray)}.wf-legend-item{display:flex;align-items:center;gap:5px;font-size:.6875rem;color:var(--text-muted)}.wf-legend-dot{width:10px;height:10px;border-radius:2px}.wf-legend-dot.wf-env{background:var(--cat-env)}.wf-legend-dot.wf-svc{background:var(--cat-svc)}.wf-legend-dot.wf-agent{background:var(--cat-agent)}.sparse-index-section{margin-top:16px}.sparse-index-toggle{font-size:.75rem;color:var(--accent);background:none;border:none;cursor:pointer;font-family:var(--font);padding:4px 0;font-weight:500}.sparse-index-content{display:none;margin-top:8px}.sparse-index-content.visible{display:block}.sparse-line{font-family:var(--font-mono);font-size:.75rem;line-height:1.8;padding:3px 10px;border-left:3px solid var(--cat-agent);white-space:pre;overflow-x:auto}.sparse-line.cat-env{border-left-color:var(--cat-env);background:#0596690a}.sparse-line.cat-svc{border-left-color:var(--cat-svc);background:#2563eb0a}.sparse-line.cat-agent{border-left-color:var(--cat-agent)}.sparse-line-expandable{cursor:pointer;position:relative}.sparse-line-expandable:after{content:"▶";position:absolute;right:8px;top:4px;font-size:.6rem;color:var(--text-secondary);transition:transform .15s ease}.sparse-line-expandable.expanded:after{transform:rotate(90deg)}.sparse-line-expandable:hover{background:var(--accent-light)}.sparse-line-content{display:none;margin:4px 0 8px 12px;padding:8px 12px;background:var(--bg-alt);border-radius:4px;border:1px solid var(--border)}.sparse-line-expandable.expanded .sparse-line-content{display:block}.sparse-line-content pre{margin:0;font-family:var(--font-mono);font-size:.7rem;line-height:1.5;white-space:pre-wrap;word-break:break-word;color:var(--text)}.sparse-expand-all{font-size:.75rem;color:var(--accent);background:none;border:none;cursor:pointer;font-family:var(--font);padding:4px 0;font-weight:500;margin-left:12px}.info-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;margin-left:6px;border:1px solid var(--light-gray);border-radius:50%;background:var(--bg-card);color:var(--accent);font-size:.75rem;font-weight:600;cursor:pointer;vertical-align:middle;line-height:1;transition:background var(--transition),border-color var(--transition)}.info-btn:hover{background:var(--accent-light);border-color:var(--accent)}.modal-backdrop{display:none;position:fixed;inset:0;z-index:100;background:#1a1a2e73;align-items:center;justify-content:center;padding:24px}.modal-backdrop.visible{display:flex}.modal{background:var(--bg-card);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg),0 8px 32px #0000001f;max-width:640px;width:100%;max-height:80vh;overflow-y:auto;animation:modal-in .15s ease}@keyframes modal-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:20px 24px 16px;border-bottom:1px solid var(--light-gray)}.modal-header h3{font-size:1.0625rem;font-weight:600;margin-bottom:2px}.modal-subtitle{font-size:.75rem;font-family:var(--font-mono);color:var(--text-muted)}.modal-close{background:none;border:none;font-size:1.5rem;line-height:1;color:var(--text-muted);cursor:pointer;padding:0 4px;flex-shrink:0;transition:color var(--transition)}.modal-close:hover{color:var(--text)}.modal-body{padding:20px 24px 24px}.modal-section{margin-bottom:20px}.modal-section:last-child{margin-bottom:0}.modal-section h4{font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;margin-bottom:8px}.modal-prompt{font-family:var(--font-mono);font-size:.8125rem;line-height:1.6;background:var(--bg);border:1px solid var(--light-gray);border-radius:var(--radius);padding:12px 16px;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow-y:auto}.modal-rubric-table{width:100%;border-collapse:collapse;font-size:.8125rem}.modal-rubric-table thead th{text-align:left;padding:6px 10px;font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;border-bottom:1px solid var(--light-gray)}.modal-rubric-table tbody td{padding:8px 10px;border-bottom:1px solid var(--light-gray);color:var(--text-secondary)}.modal-rubric-weight{width:60px;text-align:right;font-family:var(--font-mono);font-weight:600;color:var(--text)!important}.modal-config{display:flex;flex-direction:column;gap:6px}.modal-config-item{display:flex;align-items:baseline;gap:12px;font-size:.8125rem;padding:6px 10px;background:var(--bg);border-radius:var(--radius)}.modal-config-key{font-family:var(--font-mono);font-weight:600;color:var(--text);flex-shrink:0}.modal-config-val{font-family:var(--font-mono);color:var(--text-secondary);word-break:break-all}.error-banner{background:var(--danger-light);border:1px solid var(--danger);border-radius:var(--radius);padding:12px 16px;color:var(--danger);font-size:.875rem;font-weight:500;margin-bottom:16px}.loading{text-align:center;padding:80px 24px;color:var(--text-muted);font-size:1.125rem}.empty-state{text-align:center;padding:60px 24px;color:var(--text-muted)}@media(max-width:768px){.container{padding:16px 12px 48px}.summary-cards{flex-direction:column}.summary-card{min-width:0}.score-overview{flex-direction:column;align-items:center;gap:16px}.dimensions-grid{grid-template-columns:1fr}.wf-label-col{width:120px}.wf-dur-col{width:48px}.wf-tool{font-size:.6875rem}.results-table{font-size:.8125rem}.results-table thead th.hide-mobile,.results-table tbody td.hide-mobile{display:none}.detail-panel{padding:16px 12px}}@media print{.detail-row{display:table-row!important}.audits-list,.sparse-index-content{display:block!important}.result-row{cursor:default}.wf-overflow{display:block!important}.wf-show-all,.expand-icon,.audits-toggle,.sparse-index-toggle,.info-btn,.modal-backdrop{display:none!important}}
1
+ <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>AXIS Report</title><style>:root{--bg: #fafbf9;--bg-card: #ffffff;--bg-alt: #f3f4f6;--text: #1a1a2e;--text-secondary: #4a5568;--text-muted: #637083;--mid-gray: #6b7280;--light-gray: #e5e7eb;--border: #e5e7eb;--accent: #016867;--accent-hover: #015554;--accent-bright: #2dd4bf;--accent-light: rgba(1, 104, 103, .07);--success: #059669;--success-light: #ecfdf5;--yellow: #d97706;--yellow-light: #fffbeb;--warning: #d97706;--warning-light: #fffbeb;--danger: #dc2626;--danger-light: #fef2f2;--cat-env: #059669;--cat-svc: #2563eb;--cat-agent: #6b7280;--radius: 8px;--radius-lg: 12px;--shadow: 0 1px 3px rgba(0, 0, 0, .04), 0 2px 8px rgba(0, 0, 0, .03);--shadow-lg: 0 4px 16px rgba(0, 0, 0, .06), 0 0 40px rgba(1, 104, 103, .04);--font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, Roboto, sans-serif;--font-mono: "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;--transition: .15s ease}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{font-size:15px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:var(--font);color:var(--text);background:var(--bg);line-height:1.6;min-height:100vh}.container{max-width:1120px;margin:0 auto;padding:32px 24px 64px}h1{font-size:2rem;font-weight:800;letter-spacing:-.02em;background:linear-gradient(135deg,var(--text) 0%,var(--accent) 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}h2{font-size:1.375rem;font-weight:700;letter-spacing:-.01em;color:var(--text)}h3{font-size:1.0625rem;font-weight:600;color:var(--text)}.report-header{display:flex;align-items:flex-start;justify-content:space-between;gap:32px;margin-bottom:32px}.header-left{flex:1;min-width:0}.report-branding{display:flex;align-items:baseline;gap:12px;margin-bottom:16px}.site-logo-mark{font-size:2.0625rem;font-weight:800;letter-spacing:.12em;color:var(--accent)}.logo-ax{letter-spacing:-.06em}.logo-i{display:inline-block;font-style:italic;transform:skew(-20deg);margin-left:2px;margin-right:-2px}.report-badge{font-size:2.0625rem;font-weight:800;letter-spacing:.02em;color:var(--accent)}.report-meta{margin:0}.report-meta-row{font-size:.875rem;line-height:1.8;color:var(--text-secondary)}.report-meta-label{font-weight:600;color:var(--text)}.report-meta-value{color:var(--text-secondary)}.report-meta-id{font-family:var(--font-mono);font-size:.8125rem}.summary-card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:24px 28px;box-shadow:var(--shadow);flex-shrink:0;display:flex;align-items:center;gap:24px}.summary-hero{text-align:center;padding:0 8px}.summary-hero .hero-score{font-size:2.5rem;font-weight:800;line-height:1;color:var(--accent)}.summary-hero .hero-label{font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;margin-top:4px;white-space:nowrap}.summary-divider{width:1px;align-self:stretch;background:var(--border)}.summary-stats{display:flex;gap:20px;align-items:flex-start}.summary-stat{text-align:center;min-width:48px}.summary-stat .stat-value{font-size:1.25rem;font-weight:700;color:var(--text);line-height:1.2;margin-bottom:2px}.summary-stat .stat-label{font-size:.625rem;text-transform:uppercase;letter-spacing:.05em;color:var(--text-muted);font-weight:500;white-space:nowrap}.summary-stat.stat-passed .stat-value{color:var(--success)}.summary-stat.stat-failed .stat-value{color:var(--danger)}.score-badge{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:28px;padding:0 8px;border-radius:14px;font-size:.8125rem;font-weight:700;color:#fff;line-height:1}.score-badge.score-green{background:var(--success)}.score-badge.score-yellow{background:var(--yellow)}.score-badge.score-orange{background:#ea580c}.score-badge.score-red{background:var(--danger)}.score-badge.score-na{background:var(--mid-gray);font-weight:500}.score-badge-lg{min-width:64px;height:64px;border-radius:32px;font-size:1.5rem;padding:0 16px}.results-section{margin-top:32px}.results-table{width:100%;border-collapse:collapse;font-size:.875rem}.results-table thead th{text-align:left;padding:10px 12px;font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;border-bottom:2px solid var(--light-gray);white-space:nowrap}.results-table thead th.col-score{text-align:center;width:60px}.results-table thead th.col-right{text-align:right}.result-row{cursor:pointer;transition:background var(--transition)}.result-row:hover,.result-row.expanded{background:var(--accent-light)}.result-row td{padding:12px;border-bottom:1px solid var(--light-gray);vertical-align:middle}.result-row td.col-score{text-align:center}.result-row td.col-right{text-align:right;font-family:var(--font-mono);font-size:.8125rem;color:var(--text-secondary)}.result-row td.col-scenario{font-weight:500;max-width:240px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.result-row td.col-agent{color:var(--text-secondary);font-family:var(--font-mono);font-size:.8125rem}.result-row .expand-icon{display:inline-block;width:16px;color:var(--text-muted);transition:transform var(--transition);font-size:.75rem}.result-row.expanded .expand-icon{transform:rotate(90deg)}.result-row .error-hint{display:block;font-size:.75rem;color:var(--danger);margin-top:2px}.detail-row{display:none}.detail-row.visible{display:table-row}.detail-row td{padding:0;border-bottom:2px solid var(--light-gray)}.detail-panel{padding:24px;background:var(--bg)}.score-overview{display:flex;align-items:flex-start;gap:32px;margin-bottom:32px;padding-bottom:24px;border-bottom:1px solid var(--light-gray)}.score-overview .big-score{flex-shrink:0}.category-bars{flex:1;display:flex;flex-direction:column;gap:8px;padding-top:4px}.category-bar-row{display:flex;align-items:center;gap:12px}.category-bar-label{width:120px;font-size:.8125rem;font-weight:500;color:var(--text-secondary);flex-shrink:0}.category-bar-value{font-size:.8125rem;font-weight:600;width:32px;text-align:right;flex-shrink:0}.progress-bar{flex:1;height:8px;background:var(--light-gray);border-radius:4px;overflow:hidden;min-width:80px}.progress-bar .fill{height:100%;border-radius:4px;transition:width .4s ease}.progress-bar .fill.fill-green{background:var(--success)}.progress-bar .fill.fill-yellow{background:var(--yellow)}.progress-bar .fill.fill-orange{background:#ea580c}.progress-bar .fill.fill-red{background:var(--danger)}.detail-sections{display:flex;flex-direction:column;gap:20px}.detail-section{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px;box-shadow:var(--shadow)}.section-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px}.section-header h3{display:flex;align-items:center;gap:8px}.section-score{font-size:.875rem;font-weight:600;color:var(--text-secondary)}.criteria-list{display:flex;flex-direction:column;gap:12px}.criterion-item{padding:12px;background:var(--bg);border-radius:var(--radius);border:1px solid var(--light-gray)}.criterion-top{display:flex;align-items:center;gap:8px;margin-bottom:6px}.criterion-icon{font-size:.875rem;width:20px;text-align:center;flex-shrink:0}.criterion-icon.high{color:var(--success)}.criterion-icon.good{color:var(--yellow)}.criterion-icon.medium{color:#ea580c}.criterion-icon.low{color:var(--danger)}.criterion-name{flex:1;font-size:.8125rem;font-weight:500}.criterion-score{font-size:.8125rem;font-weight:600;color:var(--text-secondary);flex-shrink:0}.criterion-weight{font-size:.6875rem;color:var(--text-muted);background:var(--light-gray);padding:1px 6px;border-radius:3px;flex-shrink:0}.criterion-bar{margin-bottom:8px}.criterion-rationale{font-size:.8125rem;color:var(--text-secondary);line-height:1.5;font-style:italic}.criterion-perfect{padding:8px 12px;background:var(--success-light);border-left:3px solid var(--success)}.criterion-perfect .criterion-bar{display:none}.criterion-imperfect{border-left:3px solid var(--warning)}.deductions-summary{background:var(--warning-light);border:1px solid var(--warning);border-radius:var(--radius);padding:14px 16px;margin-bottom:16px}.deductions-header{font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.06em;color:var(--warning);margin-bottom:10px}.deduction-item{display:grid;grid-template-columns:1fr auto;gap:4px 12px;padding:6px 0;border-bottom:1px solid rgba(217,119,6,.15)}.deduction-item:last-child{border-bottom:none;padding-bottom:0}.deduction-criterion{font-size:.8125rem;font-weight:500;color:var(--text)}.deduction-lost{font-size:.75rem;font-weight:600;font-family:var(--font-mono);color:var(--warning);white-space:nowrap}.deduction-rationale{grid-column:1 / -1;font-size:.75rem;color:var(--text-secondary);line-height:1.5;font-style:italic}.dim-tags{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:10px}.dim-tag{font-size:.6875rem;font-weight:600;font-family:var(--font-mono);padding:2px 8px;border-radius:10px;color:#fff}.dim-tag.fill-green{background:var(--success)}.dim-tag.fill-yellow{background:var(--yellow)}.dim-tag.fill-orange{background:#ea580c}.dim-tag.fill-red{background:var(--danger)}.cat-deduction-item{padding:8px 0;border-bottom:1px solid rgba(217,119,6,.15)}.cat-deduction-item:last-child{border-bottom:none;padding-bottom:0}.cat-deduction-id{font-family:var(--font-mono);font-size:.75rem;font-weight:600;color:var(--text);margin-right:8px}.cat-deduction-scores{display:inline-flex;gap:4px}.dim-score-tag{font-size:.625rem;font-family:var(--font-mono);background:var(--light-gray);padding:1px 5px;border-radius:3px;color:var(--text-secondary)}.cat-deduction-rationale{display:block;font-size:.75rem;color:var(--text-secondary);line-height:1.5;font-style:italic;margin-top:4px}.cat-deduction-note{font-size:.75rem;color:var(--text-muted);font-style:italic}.deductions-baseline{background:var(--bg);border-color:var(--light-gray)}.deductions-baseline .deductions-header{color:var(--text-muted)}.dimensions-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:10px;margin-bottom:16px}.dimension-item{display:flex;align-items:center;gap:8px}.dimension-label{width:72px;font-size:.75rem;font-weight:500;color:var(--text-secondary);flex-shrink:0}.dimension-value{font-size:.75rem;font-weight:600;width:28px;text-align:right;flex-shrink:0}.interaction-meta{font-size:.75rem;color:var(--text-muted);margin-bottom:12px}.audits-section{margin-top:12px}.audits-toggle{font-size:.75rem;color:var(--accent);background:none;border:none;cursor:pointer;font-family:var(--font);padding:4px 0;font-weight:500}.audits-toggle:hover{color:var(--accent-hover)}.audits-list{display:none;margin-top:8px}.audits-list.visible{display:block}.audit-item{padding:10px 12px;background:var(--bg);border-radius:var(--radius);margin-bottom:6px;border-left:3px solid var(--mid-gray)}.audit-header{display:flex;align-items:center;gap:8px;margin-bottom:4px;flex-wrap:wrap}.audit-id{font-family:var(--font-mono);font-size:.75rem;font-weight:600;color:var(--text)}.audit-scores{font-family:var(--font-mono);font-size:.6875rem;color:var(--text-muted)}.audit-rationale{font-size:.8125rem;color:var(--text-secondary);line-height:1.5}.necessity-section{margin-top:12px;padding-top:12px;border-top:1px solid var(--light-gray)}.necessity-header{display:flex;align-items:center;gap:8px;margin-bottom:4px}.necessity-label{font-size:.75rem;font-weight:600;color:var(--text-secondary)}.necessity-score{font-size:.75rem;font-weight:600}.necessity-rationale{font-size:.8125rem;color:var(--text-secondary);font-style:italic}.waterfall{font-size:.8125rem}.waterfall-header{display:flex;align-items:flex-end;border-bottom:1px solid var(--light-gray);padding-bottom:6px;margin-bottom:2px}.wf-label-col{width:200px;flex-shrink:0;display:flex;align-items:center;gap:6px;overflow:hidden}.waterfall-header .wf-label-col,.waterfall-header .wf-dur-col{font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600}.wf-timeline-col{flex:1;min-width:0;position:relative}.wf-dur-col{width:64px;flex-shrink:0;text-align:right;font-family:var(--font-mono);font-size:.75rem;color:var(--text-secondary)}.wf-ticks{position:relative;height:18px}.wf-tick{position:absolute;transform:translate(-50%);font-family:var(--font-mono);font-size:.625rem;color:var(--text-muted);white-space:nowrap;top:0}.wf-tick:after{content:"";position:absolute;left:50%;top:100%;width:1px;height:4px;background:var(--light-gray)}.waterfall-body{position:relative}.wf-row{display:flex;align-items:center;height:26px;border-bottom:1px solid rgba(0,0,0,.03)}.wf-row:hover{background:var(--accent-light)}.wf-id{font-family:var(--font-mono);font-size:.6875rem;color:var(--text-muted);width:28px;flex-shrink:0}.wf-cat{font-size:.625rem;text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);width:36px;flex-shrink:0}.wf-tool{font-size:.75rem;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wf-track{position:relative;height:14px;background:#00000004;border-radius:2px}.wf-bar{position:absolute;top:2px;height:10px;border-radius:2px;min-width:3px;cursor:default;transition:opacity var(--transition)}.wf-row:hover .wf-bar{opacity:.8}.wf-env .wf-bar{background:var(--cat-env)}.wf-svc .wf-bar{background:var(--cat-svc)}.wf-agent .wf-bar{background:var(--cat-agent)}.wf-bar-error{background:var(--danger)!important}.wf-show-all{display:block;width:100%;margin-top:4px;padding:6px;font-size:.75rem;color:var(--accent);background:none;border:1px dashed var(--light-gray);border-radius:var(--radius);cursor:pointer;font-family:var(--font);font-weight:500}.wf-show-all:hover{background:var(--accent-light);border-color:var(--accent)}.wf-legend{display:flex;gap:16px;margin-top:10px;padding-top:8px;border-top:1px solid var(--light-gray)}.wf-legend-item{display:flex;align-items:center;gap:5px;font-size:.6875rem;color:var(--text-muted)}.wf-legend-dot{width:10px;height:10px;border-radius:2px}.wf-legend-dot.wf-env{background:var(--cat-env)}.wf-legend-dot.wf-svc{background:var(--cat-svc)}.wf-legend-dot.wf-agent{background:var(--cat-agent)}.sparse-index-section{margin-top:16px}.sparse-index-toggle{font-size:.75rem;color:var(--accent);background:none;border:none;cursor:pointer;font-family:var(--font);padding:4px 0;font-weight:500}.sparse-index-content{display:none;margin-top:8px}.sparse-index-content.visible{display:block}.sparse-line{font-family:var(--font-mono);font-size:.75rem;line-height:1.8;padding:3px 10px;border-left:3px solid var(--cat-agent);white-space:pre;overflow-x:auto}.sparse-line.cat-env{border-left-color:var(--cat-env);background:#0596690a}.sparse-line.cat-svc{border-left-color:var(--cat-svc);background:#2563eb0a}.sparse-line.cat-agent{border-left-color:var(--cat-agent)}.sparse-line-expandable{cursor:pointer;position:relative}.sparse-line-expandable:after{content:"▶";position:absolute;right:8px;top:4px;font-size:.6rem;color:var(--text-secondary);transition:transform .15s ease}.sparse-line-expandable.expanded:after{transform:rotate(90deg)}.sparse-line-expandable:hover{background:var(--accent-light)}.sparse-line-content{display:none;margin:4px 0 8px 12px;padding:8px 12px;background:var(--bg-alt);border-radius:4px;border:1px solid var(--border)}.sparse-line-expandable.expanded .sparse-line-content{display:block}.sparse-line-content pre{margin:0;font-family:var(--font-mono);font-size:.7rem;line-height:1.5;white-space:pre-wrap;word-break:break-word;color:var(--text)}.sparse-expand-all{font-size:.75rem;color:var(--accent);background:none;border:none;cursor:pointer;font-family:var(--font);padding:4px 0;font-weight:500;margin-left:12px}.info-btn{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;margin-left:6px;border:1px solid var(--light-gray);border-radius:50%;background:var(--bg-card);color:var(--accent);font-size:.75rem;font-weight:600;cursor:pointer;vertical-align:middle;line-height:1;transition:background var(--transition),border-color var(--transition)}.info-btn:hover{background:var(--accent-light);border-color:var(--accent)}.modal-backdrop{display:none;position:fixed;inset:0;z-index:100;background:#1a1a2e73;align-items:center;justify-content:center;padding:24px}.modal-backdrop.visible{display:flex}.modal{background:var(--bg-card);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg),0 8px 32px #0000001f;max-width:640px;width:100%;max-height:80vh;overflow-y:auto;animation:modal-in .15s ease}@keyframes modal-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.modal-header{display:flex;align-items:flex-start;justify-content:space-between;padding:20px 24px 16px;border-bottom:1px solid var(--light-gray)}.modal-header h3{font-size:1.0625rem;font-weight:600;margin-bottom:2px}.modal-subtitle{font-size:.75rem;font-family:var(--font-mono);color:var(--text-muted)}.modal-close{background:none;border:none;font-size:1.5rem;line-height:1;color:var(--text-muted);cursor:pointer;padding:0 4px;flex-shrink:0;transition:color var(--transition)}.modal-close:hover{color:var(--text)}.modal-body{padding:20px 24px 24px}.modal-section{margin-bottom:20px}.modal-section:last-child{margin-bottom:0}.modal-section h4{font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;margin-bottom:8px}.modal-prompt{font-family:var(--font-mono);font-size:.8125rem;line-height:1.6;background:var(--bg);border:1px solid var(--light-gray);border-radius:var(--radius);padding:12px 16px;white-space:pre-wrap;word-break:break-word;max-height:240px;overflow-y:auto}.modal-rubric-table{width:100%;border-collapse:collapse;font-size:.8125rem}.modal-rubric-table thead th{text-align:left;padding:6px 10px;font-size:.6875rem;text-transform:uppercase;letter-spacing:.06em;color:var(--text-muted);font-weight:600;border-bottom:1px solid var(--light-gray)}.modal-rubric-table tbody td{padding:8px 10px;border-bottom:1px solid var(--light-gray);color:var(--text-secondary)}.modal-rubric-weight{width:60px;text-align:right;font-family:var(--font-mono);font-weight:600;color:var(--text)!important}.modal-config{display:flex;flex-direction:column;gap:6px}.modal-config-item{display:flex;align-items:baseline;gap:12px;font-size:.8125rem;padding:6px 10px;background:var(--bg);border-radius:var(--radius)}.modal-config-key{font-family:var(--font-mono);font-weight:600;color:var(--text);flex-shrink:0}.modal-config-val{font-family:var(--font-mono);color:var(--text-secondary);word-break:break-all}.error-banner{background:var(--danger-light);border:1px solid var(--danger);border-radius:var(--radius);padding:12px 16px;color:var(--danger);font-size:.875rem;font-weight:500;margin-bottom:16px}.loading{text-align:center;padding:80px 24px;color:var(--text-muted);font-size:1.125rem}.empty-state{text-align:center;padding:60px 24px;color:var(--text-muted)}@media(max-width:768px){.container{padding:16px 12px 48px}.report-header{flex-direction:column;gap:16px}.report-branding{gap:8px;margin-bottom:8px}.site-logo-mark,.report-badge{font-size:1.5rem}.report-meta-row{font-size:.8125rem;line-height:1.7}.summary-card{padding:16px;flex-direction:column;gap:16px;width:100%}.summary-hero .hero-score{font-size:2rem}.summary-divider{width:100%;height:1px;align-self:auto}.summary-stats{flex-wrap:wrap;gap:16px;justify-content:center}.results-table{font-size:.8125rem}.results-table thead th{padding:8px 6px}.results-table thead th.hide-mobile,.results-table tbody td.hide-mobile{display:none}.result-row td{padding:10px 6px}.result-row td:first-child{padding-left:4px;padding-right:0;width:20px}.result-row .expand-icon{width:12px;font-size:.625rem}.result-row td.col-scenario{max-width:120px;font-size:.75rem}.result-row td.col-agent{max-width:70px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.6875rem}.detail-panel{padding:16px 12px}.score-overview{flex-direction:column;align-items:center;gap:16px}.category-bars{width:100%}.category-bar-label{width:80px;font-size:.75rem}.dimensions-grid{grid-template-columns:1fr}.criterion-top{flex-wrap:wrap}.criterion-name{min-width:0;word-break:break-word}.deductions-summary{padding:10px 12px}.deduction-item,.cat-deduction-item{flex-direction:column;gap:4px;align-items:flex-start}.waterfall{overflow-x:auto;-webkit-overflow-scrolling:touch}.wf-label-col{width:100px}.wf-dur-col{width:48px;font-size:.6875rem}.wf-tool{font-size:.625rem;max-width:50px;overflow:hidden;text-overflow:ellipsis}.wf-id,.wf-cat{font-size:.5625rem}.wf-legend{flex-wrap:wrap;gap:8px}.sparse-line{font-size:.6875rem;word-break:break-all}.modal-backdrop{padding:12px}.modal{max-height:90vh;border-radius:var(--radius)}.modal-header{padding:16px}.modal-header h3{font-size:1rem}.modal-body{padding:16px}.modal-prompt{font-size:.75rem}.audit-header{flex-direction:column;gap:4px}.necessity-header{flex-wrap:wrap;gap:4px}}@media print{.detail-row{display:table-row!important}.audits-list,.sparse-index-content{display:block!important}.result-row{cursor:default}.wf-overflow{display:block!important}.wf-show-all,.expand-icon,.audits-toggle,.sparse-index-toggle,.info-btn,.modal-backdrop{display:none!important}}
2
2
  </style></head> <body> <div id="app"> <div class="loading">Loading report&hellip;</div> </div> <script id="axis-data" type="application/json">__AXIS_REPORT_DATA__</script> <script type="module">function C(e){return"averageAxisScore"in e}function o(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function u(e){return!Number.isFinite(e)||e<0?"—":e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}function f(e){return e===void 0||e<=0?"—":`$${e.toFixed(4)}`}function w(e){if(!e)return"—";const s=e.input+e.output+(e.cacheReadInput??0);return s===0?"—":s>=1e6?`${(s/1e6).toFixed(1)}M`:s>=1e3?`${(s/1e3).toFixed(1)}k`:s.toLocaleString()}function A(e){try{return new Date(e).toLocaleString("en-US",{year:"numeric",month:"short",day:"numeric",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}catch{return e}}function E(e){return e>=90?"score-green":e>=80?"score-yellow":e>=70?"score-orange":"score-red"}function x(e){return e>=90?"fill-green":e>=80?"fill-yellow":e>=70?"fill-orange":"fill-red"}function v(e,s=!1){return e===void 0?`<span class="score-badge score-na${s?" score-badge-lg":""}">—</span>`:`<span class="score-badge ${E(e)}${s?" score-badge-lg":""}">${e}</span>`}function b(e,s=100){const t=Math.max(0,Math.min(100,e/s*100));return`<div class="progress-bar"><div class="fill ${x(t)}" style="width: ${t}%"></div></div>`}function L(e,s){return`
3
3
  <div class="dimension-item">
4
4
  <span class="dimension-label">${o(e)}</span>
@@ -11,43 +11,46 @@
11
11
  </div>
12
12
  ${K(e.results)}`}function M(e){const s=C(e.summary),t=e.results.reduce((a,n)=>a+(n.totalCostUsd??0),0);return`
13
13
  <header class="report-header">
14
- <div class="report-branding">
15
- <span class="site-logo-mark"><span class="logo-ax">AX</span><span class="logo-i">I</span>S</span>
16
- <span class="report-badge">Report</span>
17
- </div>
18
- <div class="report-meta">
19
- ${e.name?`<div class="report-meta-row"><span class="report-meta-label">Report name:</span> <span class="report-meta-value">${o(e.name)}</span></div>`:""}
20
- <div class="report-meta-row"><span class="report-meta-label">Generated on:</span> <span class="report-meta-value">${A(e.timestamp)}</span></div>
21
- <div class="report-meta-row"><span class="report-meta-label">ID:</span> <span class="report-meta-value report-meta-id">${o(e.reportId)}</span></div>
22
- </div>
23
- <div class="summary-cards">
24
- <div class="summary-card">
25
- <div class="card-value">${e.summary.total}</div>
26
- <div class="card-label">Scenarios</div>
27
- </div>
28
- <div class="summary-card">
29
- <div class="card-value">${e.summary.completed}</div>
30
- <div class="card-label">Passed</div>
14
+ <div class="header-left">
15
+ <div class="report-branding">
16
+ <span class="site-logo-mark"><span class="logo-ax">AX</span><span class="logo-i">I</span>S</span>
17
+ <span class="report-badge">Report</span>
31
18
  </div>
32
- <div class="summary-card${e.summary.failed>0?" card-failed":""}">
33
- <div class="card-value">${e.summary.failed}</div>
34
- <div class="card-label">Failed</div>
19
+ <div class="report-meta">
20
+ ${e.name?`<div class="report-meta-row"><span class="report-meta-label">Report name:</span> <span class="report-meta-value">${o(e.name)}</span></div>`:""}
21
+ <div class="report-meta-row"><span class="report-meta-label">Generated on:</span> <span class="report-meta-value">${A(e.timestamp)}</span></div>
22
+ <div class="report-meta-row"><span class="report-meta-label">Total duration:</span> <span class="report-meta-value">${u(e.durationMs)}</span></div>
23
+ <div class="report-meta-row"><span class="report-meta-label">Report ID:</span> <span class="report-meta-value report-meta-id">${o(e.reportId)}</span></div>
35
24
  </div>
25
+ </div>
26
+ <div class="summary-card">
36
27
  ${s?`
37
- <div class="summary-card">
38
- <div class="card-value">${v(e.summary.averageAxisScore)}</div>
39
- <div class="card-label">Avg AXIS Result</div>
40
- </div>`:""}
41
- <div class="summary-card">
42
- <div class="card-value">${u(e.durationMs)}</div>
43
- <div class="card-label">Duration</div>
28
+ <div class="summary-hero">
29
+ <div class="hero-score">${e.summary.averageAxisScore}</div>
30
+ <div class="hero-label">AXIS Result</div>
44
31
  </div>
45
- <div class="summary-card">
46
- <div class="card-value">${f(t>0?t:void 0)}</div>
47
- <div class="card-label">Total Cost</div>
32
+ <div class="summary-divider"></div>`:""}
33
+ <div class="summary-stats">
34
+ <div class="summary-stat">
35
+ <div class="stat-value">${e.summary.total}</div>
36
+ <div class="stat-label">Scenarios</div>
37
+ </div>
38
+ <div class="summary-stat stat-passed">
39
+ <div class="stat-value">${e.summary.completed}</div>
40
+ <div class="stat-label">Passed</div>
41
+ </div>
42
+ <div class="summary-stat${e.summary.failed>0?" stat-failed":""}">
43
+ <div class="stat-value">${e.summary.failed}</div>
44
+ <div class="stat-label">Failed</div>
45
+ </div>
46
+ ${t>0?`
47
+ <div class="summary-stat">
48
+ <div class="stat-value">${f(t)}</div>
49
+ <div class="stat-label">Cost</div>
50
+ </div>`:""}
48
51
  </div>
49
52
  </div>
50
- </header>`}function I(e){if(e.results.length===0)return'<div class="empty-state">No results in this report.</div>';const s=e.results.some(a=>a.score!==void 0),t=e.results.map((a,n)=>D(a,n,s)+T(a,n)).join("");return`
53
+ </header>`}function I(e){if(e.results.length===0)return'<div class="empty-state">No results in this report.</div>';const s=e.results.some(a=>a.score!==void 0),t=e.results.map((a,n)=>T(a,n,s)+D(a,n)).join("");return`
51
54
  <section class="results-section">
52
55
  <table class="results-table">
53
56
  <thead>
@@ -69,7 +72,7 @@
69
72
  </thead>
70
73
  <tbody>${t}</tbody>
71
74
  </table>
72
- </section>`}function D(e,s,t){const a=e.score,n=e.exitCode!==0||!!e.error,i=e.error?`<span class="error-hint">${o(te(e.error))}</span>`:"",c=e.prompt?`<button class="info-btn" data-modal-index="${s}" title="View scenario settings">ℹ</button>`:"";if(t)return`
75
+ </section>`}function T(e,s,t){const a=e.score,n=e.exitCode!==0||!!e.error,i=e.error?`<span class="error-hint">${o(te(e.error))}</span>`:"",c=e.prompt?`<button class="info-btn" data-modal-index="${s}" title="View scenario settings">ℹ</button>`:"";if(t)return`
73
76
  <tr class="result-row" data-index="${s}">
74
77
  <td><span class="expand-icon">▶</span></td>
75
78
  <td class="col-scenario">${o(e.scenarioName)}${c}${i}</td>
@@ -82,16 +85,16 @@
82
85
  <td class="col-right hide-mobile">${w(e.tokenUsage)}</td>
83
86
  <td class="col-right hide-mobile">${u(e.durationMs)}</td>
84
87
  <td class="col-right hide-mobile">${f(e.totalCostUsd)}</td>
85
- </tr>`;const l=n?'<span class="score-badge score-red">Fail</span>':'<span class="score-badge score-green">Pass</span>';return`
88
+ </tr>`;const r=n?'<span class="score-badge score-red">Fail</span>':'<span class="score-badge score-green">Pass</span>';return`
86
89
  <tr class="result-row" data-index="${s}">
87
90
  <td><span class="expand-icon">▶</span></td>
88
91
  <td class="col-scenario">${o(e.scenarioName)}${c}${i}</td>
89
92
  <td class="col-agent">${o(e.agentName)}</td>
90
- <td class="col-score">${l}</td>
93
+ <td class="col-score">${r}</td>
91
94
  <td class="col-right hide-mobile">${w(e.tokenUsage)}</td>
92
95
  <td class="col-right hide-mobile">${u(e.durationMs)}</td>
93
96
  <td class="col-right hide-mobile">${f(e.totalCostUsd)}</td>
94
- </tr>`}function T(e,s){const t=e.score?11:8;return`
97
+ </tr>`}function D(e,s){const t=e.score?11:8;return`
95
98
  <tr class="detail-row" id="detail-${s}">
96
99
  <td colspan="${t}">
97
100
  <div class="detail-panel">
@@ -158,7 +161,7 @@
158
161
  </div>
159
162
  <div class="criterion-bar">${b(e.score,10)}</div>
160
163
  ${s?"":`<div class="criterion-rationale">${o(e.rationale)}</div>`}
161
- </div>`}function h(e,s){const t=s.dimensions,a=s.audits.filter(d=>d.rationale!=="default"),n=a.length>0,i=[{label:"Success",value:t.success},{label:"Speed",value:t.speed},{label:"Relevance",value:t.relevance},{label:"Necessity",value:t.necessity}],c=i.filter(d=>d.value<100),l=n?`<div class="dimensions-grid">${i.map(d=>L(d.label,d.value)).join("")}</div>`:"",r=c.length>0?U(c,a):"";return`
164
+ </div>`}function h(e,s){const t=s.dimensions,a=s.audits.filter(d=>d.rationale!=="default"),n=a.length>0,i=[{label:"Success",value:t.success},{label:"Speed",value:t.speed},{label:"Relevance",value:t.relevance},{label:"Necessity",value:t.necessity}],c=i.filter(d=>d.value<100),r=n?`<div class="dimensions-grid">${i.map(d=>L(d.label,d.value)).join("")}</div>`:"",l=c.length>0?U(c,a):"";return`
162
165
  <div class="detail-section">
163
166
  <div class="section-header">
164
167
  <h3>${o(e)}</h3>
@@ -168,8 +171,8 @@
168
171
  ${s.interactionCount} interaction${s.interactionCount!==1?"s":""}
169
172
  ${n?`&middot; ${s.auditedCount} audited`:""}
170
173
  </div>
171
- ${l}
172
174
  ${r}
175
+ ${l}
173
176
  ${n?O(a):""}
174
177
  ${_(s.necessity)}
175
178
  </div>`}function U(e,s,t){const a=e.map(i=>`<span class="dim-tag ${x(i.value)}">${i.label}: ${i.value}</span>`).join(""),n=s.map(i=>`
@@ -203,7 +206,7 @@
203
206
  ${t}
204
207
  </div>
205
208
  <div class="necessity-rationale">${o(e.rationale)}</div>
206
- </div>`}const $=30;function G(e){const{interactions:s}=e;if(!s.some(r=>r.startMs!==null)||s.length===0)return"";const a=e.stats.wallClockMs||z(s);if(a<=0)return"";const n=V(a),i=s.length>$,c=i?s.slice(0,$):s,l=i?s.slice($):[];return`
209
+ </div>`}const $=30;function G(e){const{interactions:s}=e;if(!s.some(l=>l.startMs!==null)||s.length===0)return"";const a=e.stats.wallClockMs||z(s);if(a<=0)return"";const n=V(a),i=s.length>$,c=i?s.slice(0,$):s,r=i?s.slice($):[];return`
207
210
  <div class="detail-section">
208
211
  <div class="section-header">
209
212
  <h3>Timeline</h3>
@@ -214,14 +217,14 @@
214
217
  <div class="wf-label-col"></div>
215
218
  <div class="wf-timeline-col">
216
219
  <div class="wf-ticks">
217
- ${n.map(r=>`<span class="wf-tick" style="left: ${r.pct.toFixed(2)}%">${r.label}</span>`).join("")}
220
+ ${n.map(l=>`<span class="wf-tick" style="left: ${l.pct.toFixed(2)}%">${l.label}</span>`).join("")}
218
221
  </div>
219
222
  </div>
220
223
  <div class="wf-dur-col">Duration</div>
221
224
  </div>
222
225
  <div class="waterfall-body">
223
- ${c.map(r=>S(r,a)).join("")}
224
- ${i?`<div class="wf-overflow" style="display:none">${l.map(r=>S(r,a)).join("")}</div>`:""}
226
+ ${c.map(l=>S(l,a)).join("")}
227
+ ${i?`<div class="wf-overflow" style="display:none">${r.map(l=>S(l,a)).join("")}</div>`:""}
225
228
  </div>
226
229
  ${i?`<button class="wf-show-all">Show all ${s.length} interactions</button>`:""}
227
230
  <div class="wf-legend">
@@ -230,21 +233,21 @@
230
233
  <span class="wf-legend-item"><span class="wf-legend-dot wf-agent"></span>Agent</span>
231
234
  </div>
232
235
  </div>
233
- </div>`}function S(e,s){const t=e.startMs??0,a=e.durationMs??0,n=t/s*100,i=Math.max(.4,a/s*100),c=W(e),l=e.hasError?" wf-bar-error":"",r=e.toolName??"thinking",d=e.categories.includes("environment")?"env":e.categories.includes("service")?"svc":"agent",k=[`#${e.id} ${r} (${d})`,e.durationMs!==null?`Duration: ${u(e.durationMs)}`:null,`Context: ${X(e.contextBytes)}`,e.hasError?"ERROR":null].filter(Boolean).join(`
236
+ </div>`}function S(e,s){const t=e.startMs??0,a=e.durationMs??0,n=t/s*100,i=Math.max(.4,a/s*100),c=W(e),r=e.hasError?" wf-bar-error":"",l=e.toolName??"thinking",d=e.categories.includes("environment")?"env":e.categories.includes("service")?"svc":"agent",k=[`#${e.id} ${l} (${d})`,e.durationMs!==null?`Duration: ${u(e.durationMs)}`:null,`Context: ${X(e.contextBytes)}`,e.hasError?"ERROR":null].filter(Boolean).join(`
234
237
  `);return`
235
238
  <div class="wf-row ${c}">
236
239
  <div class="wf-label-col">
237
240
  <span class="wf-id">#${e.id}</span>
238
241
  <span class="wf-cat">${d}</span>
239
- <span class="wf-tool">${o(r)}</span>
242
+ <span class="wf-tool">${o(l)}</span>
240
243
  </div>
241
244
  <div class="wf-timeline-col">
242
245
  <div class="wf-track">
243
- <div class="wf-bar${l}" style="left:${n.toFixed(2)}%;width:${i.toFixed(2)}%" title="${o(k)}"></div>
246
+ <div class="wf-bar${r}" style="left:${n.toFixed(2)}%;width:${i.toFixed(2)}%" title="${o(k)}"></div>
244
247
  </div>
245
248
  </div>
246
249
  <div class="wf-dur-col">${e.durationMs!==null?u(e.durationMs):"—"}</div>
247
- </div>`}function W(e){return e.categories.includes("environment")?"wf-env":e.categories.includes("service")?"wf-svc":"wf-agent"}function X(e){return e<1024?`${e}B`:`${(e/1024).toFixed(1)}KB`}function z(e){let s=0;for(const t of e)if(t.startMs!==null){const a=t.startMs+(t.durationMs??0);a>s&&(s=a)}return s}function V(e){const s=[50,100,200,250,500,1e3,2e3,2500,5e3,1e4,15e3,3e4,6e4,12e4,3e5];let t=s[s.length-1];for(const n of s){const i=Math.floor(e/n);if(i>=3&&i<=8){t=n;break}}const a=[];for(let n=0;n<=e;n+=t)a.push({pct:n/e*100,label:u(n)});return a.length===0&&a.push({pct:0,label:"0s"}),a}function J(e){const s=e.interactions.some(a=>a.content),t=e.lines.map((a,n)=>{const i=e.interactions[n];let c="cat-agent";i?i.categories.includes("environment")?c="cat-env":i.categories.includes("service")&&(c="cat-svc"):a.includes(" env ")?c="cat-env":(a.includes(" service ")||a.includes(" svc "))&&(c="cat-svc");const l=i?.content?" sparse-line-expandable":"",r=i?.content?`<div class="sparse-line-content"><pre>${o(i.content)}</pre></div>`:"";return`<div class="sparse-line ${c}${l}">${o(a)}${r}</div>`}).join("");return`
250
+ </div>`}function W(e){return e.categories.includes("environment")?"wf-env":e.categories.includes("service")?"wf-svc":"wf-agent"}function X(e){return e<1024?`${e}B`:`${(e/1024).toFixed(1)}KB`}function z(e){let s=0;for(const t of e)if(t.startMs!==null){const a=t.startMs+(t.durationMs??0);a>s&&(s=a)}return s}function V(e){const s=[50,100,200,250,500,1e3,2e3,2500,5e3,1e4,15e3,3e4,6e4,12e4,3e5];let t=s[s.length-1];for(const n of s){const i=Math.floor(e/n);if(i>=3&&i<=8){t=n;break}}const a=[];for(let n=0;n<=e;n+=t)a.push({pct:n/e*100,label:u(n)});return a.length===0&&a.push({pct:0,label:"0s"}),a}function J(e){const s=e.interactions.some(a=>a.content),t=e.lines.map((a,n)=>{const i=e.interactions[n];let c="cat-agent";i?i.categories.includes("environment")?c="cat-env":i.categories.includes("service")&&(c="cat-svc"):a.includes(" env ")?c="cat-env":(a.includes(" service ")||a.includes(" svc "))&&(c="cat-svc");const r=i?.content?" sparse-line-expandable":"",l=i?.content?`<div class="sparse-line-content"><pre>${o(i.content)}</pre></div>`:"";return`<div class="sparse-line ${c}${r}">${o(a)}${l}</div>`}).join("");return`
248
251
  <div class="detail-section">
249
252
  <div class="section-header">
250
253
  <h3>Transcript</h3>
@@ -1,12 +1,33 @@
1
- import type { RunOutput } from "../types/output.js";
2
- import type { ScoredOutput } from "../types/scoring.js";
1
+ import type { RunOutput, RunResult } from "../types/output.js";
2
+ import type { ScoredOutput, ScoredRunResult, SparseIndex } from "../types/scoring.js";
3
3
  /**
4
- * Write a run's output to the persistent report store.
5
- * Returns the reportId (used to recall the report later).
4
+ * Create the report directory for a run.
5
+ * Call this early before scoring — so the report dir is available
6
+ * for writing raw data that judges can read.
7
+ */
8
+ export declare function initReport(timestamp: string, configDir: string): {
9
+ reportId: string;
10
+ reportDir: string;
11
+ };
12
+ /**
13
+ * Write raw run data for a single scenario×agent to the report directory.
14
+ * Call this after building the sparse index but before running LLM judges,
15
+ * so judges can read these files for context.
6
16
  *
7
- * Structure:
8
- * .axis/reports/{reportId}/report.json
9
- * .axis/reports/{reportId}/scenarios/{scenarioKey}/{agentName}.json
17
+ * Writes:
18
+ * - `{agent}.raw.ndjson` — raw agent stdout lines (if available)
19
+ * - `{agent}.sparse-index.txt` — human-readable sparse index (always)
20
+ */
21
+ export declare function writeScenarioRawData(reportDir: string, result: RunResult | ScoredRunResult, sparseIndex?: SparseIndex): void;
22
+ /**
23
+ * Finalize a report: write scored scenario JSON, manifest, and HTML.
24
+ * Call this after all scoring is complete.
25
+ */
26
+ export declare function finalizeReport(reportDir: string, output: ScoredOutput | RunOutput, name?: string): void;
27
+ /**
28
+ * Write a run's output to the persistent report store in a single call.
29
+ * Combines initReport + writeScenarioRawData + finalizeReport.
30
+ * Returns the reportId.
10
31
  */
11
32
  export declare function writeReportToStore(output: ScoredOutput | RunOutput, configDir: string, name?: string): string;
12
33
  /** Resolve the reports directory for a given config directory. */
@@ -1 +1 @@
1
- {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/reports/writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,qBAAqB,CAAC;AAMzE;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAqE7G;AAyCD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD"}
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/reports/writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAQtF;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAKzC;AAID;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,SAAS,GAAG,eAAe,EACnC,WAAW,CAAC,EAAE,WAAW,GACxB,IAAI,CA2BN;AAID;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAyCvG;AAID;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAa7G;AAyCD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD"}
@@ -3,51 +3,74 @@ import * as path from "node:path";
3
3
  import { isScoredResult } from "../types/output.js";
4
4
  import { generateReportHtml } from "./html.js";
5
5
  const REPORTS_DIR = ".axis/reports";
6
+ // --- Phase 1: Create report directory ---
6
7
  /**
7
- * Write a run's output to the persistent report store.
8
- * Returns the reportId (used to recall the report later).
9
- *
10
- * Structure:
11
- * .axis/reports/{reportId}/report.json
12
- * .axis/reports/{reportId}/scenarios/{scenarioKey}/{agentName}.json
8
+ * Create the report directory for a run.
9
+ * Call this early before scoring — so the report dir is available
10
+ * for writing raw data that judges can read.
13
11
  */
14
- export function writeReportToStore(output, configDir, name) {
15
- const reportId = generateReportId(output.timestamp);
12
+ export function initReport(timestamp, configDir) {
13
+ const reportId = generateReportId(timestamp);
16
14
  const reportDir = path.join(configDir, REPORTS_DIR, reportId);
17
15
  fs.mkdirSync(reportDir, { recursive: true });
16
+ return { reportId, reportDir };
17
+ }
18
+ // --- Phase 2: Write raw data (before scoring judges run) ---
19
+ /**
20
+ * Write raw run data for a single scenario×agent to the report directory.
21
+ * Call this after building the sparse index but before running LLM judges,
22
+ * so judges can read these files for context.
23
+ *
24
+ * Writes:
25
+ * - `{agent}.raw.ndjson` — raw agent stdout lines (if available)
26
+ * - `{agent}.sparse-index.txt` — human-readable sparse index (always)
27
+ */
28
+ export function writeScenarioRawData(reportDir, result, sparseIndex) {
29
+ const scenarioDir = path.join(reportDir, "scenarios", result.scenarioKey);
30
+ fs.mkdirSync(scenarioDir, { recursive: true });
31
+ const baseName = result.agentName;
32
+ // Write raw NDJSON (if available)
33
+ const rawOutput = result.output.rawOutput;
34
+ if (rawOutput?.length) {
35
+ const rawPath = path.join(scenarioDir, `${baseName}.raw.ndjson`);
36
+ fs.writeFileSync(rawPath, rawOutput.join("\n") + "\n");
37
+ }
38
+ // Write sparse index (always, when available)
39
+ if (sparseIndex) {
40
+ const indexPath = path.join(scenarioDir, `${baseName}.sparse-index.txt`);
41
+ const header = [
42
+ `# Sparse Index: ${result.scenarioKey} / ${result.agentName}`,
43
+ `# ${sparseIndex.stats.totalInteractions} interactions | ` +
44
+ `env: ${sparseIndex.stats.byCategory.environment} | ` +
45
+ `svc: ${sparseIndex.stats.byCategory.service} | ` +
46
+ `agent: ${sparseIndex.stats.byCategory.agent} | ` +
47
+ `errors: ${sparseIndex.stats.totalErrors}`,
48
+ "",
49
+ ];
50
+ fs.writeFileSync(indexPath, header.join("\n") + sparseIndex.lines.join("\n") + "\n");
51
+ }
52
+ }
53
+ // --- Phase 3: Finalize report (after scoring completes) ---
54
+ /**
55
+ * Finalize a report: write scored scenario JSON, manifest, and HTML.
56
+ * Call this after all scoring is complete.
57
+ */
58
+ export function finalizeReport(reportDir, output, name) {
59
+ const reportId = path.basename(reportDir);
18
60
  const entries = [];
19
61
  for (const result of output.results) {
20
62
  const relPath = `scenarios/${result.scenarioKey}/${result.agentName}.json`;
21
63
  const absPath = path.join(reportDir, relPath);
22
64
  fs.mkdirSync(path.dirname(absPath), { recursive: true });
23
- // Strip rawOutput from scenario JSON — written as a separate file
24
- const { rawOutput, ...outputWithoutRaw } = result.output;
25
- // Strip sparseIndex from score — written as a separate file in debug mode
65
+ // Strip rawOutput from scenario JSON — written separately in phase 2
66
+ const { rawOutput: _rawOutput, ...outputWithoutRaw } = result.output;
67
+ // Strip sparseIndex from score — written separately in phase 2
26
68
  let resultToWrite = { ...result, output: outputWithoutRaw };
27
69
  if (isScoredResult(result) && result.score.sparseIndex) {
28
70
  const { sparseIndex: _sparseIndex, ...scoreWithoutIndex } = result.score;
29
71
  resultToWrite = { ...resultToWrite, score: scoreWithoutIndex };
30
72
  }
31
73
  fs.writeFileSync(absPath, JSON.stringify(resultToWrite, null, 2));
32
- if (rawOutput?.length) {
33
- const rawPath = absPath.replace(/\.json$/, ".raw.ndjson");
34
- fs.writeFileSync(rawPath, rawOutput.join("\n") + "\n");
35
- }
36
- // Write sparse index as a human-readable file in debug mode
37
- if (rawOutput && isScoredResult(result) && result.score.sparseIndex) {
38
- const indexPath = absPath.replace(/\.json$/, ".sparse-index.txt");
39
- const { sparseIndex } = result.score;
40
- const header = [
41
- `# Sparse Index: ${result.scenarioKey} / ${result.agentName}`,
42
- `# ${sparseIndex.stats.totalInteractions} interactions | ` +
43
- `env: ${sparseIndex.stats.byCategory.environment} | ` +
44
- `svc: ${sparseIndex.stats.byCategory.service} | ` +
45
- `agent: ${sparseIndex.stats.byCategory.agent} | ` +
46
- `errors: ${sparseIndex.stats.totalErrors}`,
47
- "",
48
- ];
49
- fs.writeFileSync(indexPath, header.join("\n") + sparseIndex.lines.join("\n") + "\n");
50
- }
51
74
  entries.push(buildResultEntry(result, relPath));
52
75
  }
53
76
  const manifest = {
@@ -66,6 +89,22 @@ export function writeReportToStore(output, configDir, name) {
66
89
  catch {
67
90
  /* HTML generation is optional — template may not be built yet */
68
91
  }
92
+ }
93
+ // --- Convenience wrapper (backward compat) ---
94
+ /**
95
+ * Write a run's output to the persistent report store in a single call.
96
+ * Combines initReport + writeScenarioRawData + finalizeReport.
97
+ * Returns the reportId.
98
+ */
99
+ export function writeReportToStore(output, configDir, name) {
100
+ const { reportId, reportDir } = initReport(output.timestamp, configDir);
101
+ // Write raw data for each result
102
+ for (const result of output.results) {
103
+ const sparseIndex = isScoredResult(result) ? result.score.sparseIndex : undefined;
104
+ writeScenarioRawData(reportDir, result, sparseIndex);
105
+ }
106
+ // Finalize with scored results, manifest, and HTML
107
+ finalizeReport(reportDir, output, name);
69
108
  return reportId;
70
109
  }
71
110
  function buildResultEntry(result, relPath) {
@@ -1 +1 @@
1
- {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/reports/writer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/reports/writer.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,22 @@
1
1
  import type { NormalizedTranscript } from "../transcript/types.js";
2
2
  import type { RunResult } from "../types/output.js";
3
- import type { DeepEvalResult, Interaction, SparseIndex, TriageResult } from "../types/scoring.js";
3
+ import type { ScoringWeights } from "../types/config.js";
4
+ import type { CategoryEvalResult, DeepEvalResult, Interaction, InteractionCategory, SparseIndex } from "../types/scoring.js";
5
+ /** Options for the deep evaluation pass. */
6
+ export interface DeepEvalOptions {
7
+ /** Scoring weights — categories with weight 0 are skipped. */
8
+ weights?: ScoringWeights;
9
+ /** Report directory containing raw data files for judges. */
10
+ reportDir?: string;
11
+ }
4
12
  /**
5
- * Run the deep evaluation LLM pass.
13
+ * Run the deep evaluation as parallel per-category judge calls.
6
14
  *
15
+ * Each category (environment, service, agent) gets its own focused LLM judge.
16
+ * Categories with no interactions or zero weight are skipped (default scores used).
7
17
  * Speed is always computed heuristically from interaction timing data (no LLM needed).
8
- * The LLM evaluates ALL interactions for success, weight, contextRelevance,
9
- * and necessity per category.
10
18
  */
11
- export declare function runDeepEval(result: RunResult, sparseIndex: SparseIndex, triage: TriageResult, normalized: NormalizedTranscript): Promise<DeepEvalResult>;
19
+ export declare function runDeepEval(result: RunResult, sparseIndex: SparseIndex, normalized: NormalizedTranscript, options?: DeepEvalOptions): Promise<DeepEvalResult>;
12
20
  /**
13
21
  * Compute a heuristic speed score (0-1) for an interaction based on
14
22
  * duration and category. Deterministic — no LLM needed.
@@ -18,8 +26,20 @@ export declare function runDeepEval(result: RunResult, sparseIndex: SparseIndex,
18
26
  */
19
27
  export declare function computeHeuristicSpeed(interaction: Interaction): number;
20
28
  /**
21
- * Parse the deep eval LLM response.
22
- * Fills in default audits for interactions the LLM missed and default necessity for missing categories.
29
+ * Parse a per-category judge response into a CategoryEvalResult.
30
+ * Fills in default audits for interactions the LLM missed.
31
+ */
32
+ export declare function parseCategoryEvalResponse(responseText: string, category: InteractionCategory, sparseIndex: SparseIndex): CategoryEvalResult;
33
+ /**
34
+ * Parse the legacy deep eval LLM response (all categories in one call).
35
+ * Kept for backward compatibility with existing tests and any code that uses it.
23
36
  */
24
37
  export declare function parseDeepEvalResponse(responseText: string, sparseIndex: SparseIndex): DeepEvalResult;
38
+ /**
39
+ * Merge per-category results into a single DeepEvalResult.
40
+ * Interactions that appear in multiple categories get the audit from the first
41
+ * category that evaluated them (multi-category interactions are rare).
42
+ */
43
+ export declare function mergeCategoryResults(categoryResults: CategoryEvalResult[], sparseIndex: SparseIndex): DeepEvalResult;
44
+ export declare function buildDefaultCategoryResult(category: InteractionCategory, interactions?: Interaction[]): CategoryEvalResult;
25
45
  //# sourceMappingURL=deep-eval.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deep-eval.d.ts","sourceRoot":"","sources":["../../src/scoring/deep-eval.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAmB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EAIX,WAAW,EACX,YAAY,EACb,MAAM,qBAAqB,CAAC;AAa7B;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,oBAAoB,GAC/B,OAAO,CAAC,cAAc,CAAC,CAoBzB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAgCtE;AAqMD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,cAAc,CA+CpG"}
1
+ {"version":3,"file":"deep-eval.d.ts","sourceRoot":"","sources":["../../src/scoring/deep-eval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EAEd,WAAW,EAEX,mBAAmB,EAEnB,WAAW,EACZ,MAAM,qBAAqB,CAAC;AAe7B,4CAA4C;AAC5C,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,oBAAoB,EAChC,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,cAAc,CAAC,CAqCzB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,CAgCtE;AAgID;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,WAAW,GACvB,kBAAkB,CAkCpB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,GAAG,cAAc,CAiDpG;AAID;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,kBAAkB,EAAE,EACrC,WAAW,EAAE,WAAW,GACvB,cAAc,CAgChB;AA0BD,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,mBAAmB,EAC7B,YAAY,CAAC,EAAE,WAAW,EAAE,GAC3B,kBAAkB,CAsBpB"}