@mutagent/evaluator 0.1.0-alpha.6 → 0.2.0-alpha.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 (28) hide show
  1. package/.claude/skills/mutagent-evaluator/SKILL.md +23 -25
  2. package/.claude/skills/mutagent-evaluator/assets/agents/dataset-builder.md +6 -5
  3. package/.claude/skills/mutagent-evaluator/assets/agents/evaluator.md +77 -14
  4. package/.claude/skills/mutagent-evaluator/assets/templates/discover-report.template.html +397 -0
  5. package/.claude/skills/mutagent-evaluator/assets/templates/eval-report.template.html +594 -0
  6. package/.claude/skills/mutagent-evaluator/assets/templates/review-report.template.html +560 -0
  7. package/.claude/skills/mutagent-evaluator/golden/judge-trajectory.prose.md +69 -0
  8. package/.claude/skills/mutagent-evaluator/references/data-registry.md +43 -0
  9. package/.claude/skills/mutagent-evaluator/references/eval-layers.md +52 -0
  10. package/.claude/skills/mutagent-evaluator/references/eval-stage.md +1 -1
  11. package/.claude/skills/mutagent-evaluator/scripts/aggregate-discover.ts +254 -9
  12. package/.claude/skills/mutagent-evaluator/scripts/audience.ts +84 -0
  13. package/.claude/skills/mutagent-evaluator/scripts/code-eval-library.ts +201 -0
  14. package/.claude/skills/mutagent-evaluator/scripts/contracts/agentspec-evals.ts +101 -39
  15. package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-matrix.ts +287 -3
  16. package/.claude/skills/mutagent-evaluator/scripts/contracts/eval-types.ts +30 -4
  17. package/.claude/skills/mutagent-evaluator/scripts/materialize-dataset.ts +130 -68
  18. package/.claude/skills/mutagent-evaluator/scripts/matrix-judge.ts +219 -1
  19. package/.claude/skills/mutagent-evaluator/scripts/merge-criteria.ts +849 -0
  20. package/.claude/skills/mutagent-evaluator/scripts/render-discover-report-v3.ts +1155 -0
  21. package/.claude/skills/mutagent-evaluator/scripts/render-eval-report-v3.ts +610 -0
  22. package/.claude/skills/mutagent-evaluator/scripts/render-eval-report.ts +2 -1
  23. package/.claude/skills/mutagent-evaluator/scripts/render-review-report-v3.ts +691 -0
  24. package/.claude/skills/mutagent-evaluator/scripts/route-failures.ts +10 -7
  25. package/.claude/skills/mutagent-evaluator/scripts/run-evaluate.ts +46 -1
  26. package/.claude/skills/mutagent-evaluator/scripts/run-review.ts +266 -0
  27. package/.claude/skills/mutagent-evaluator/scripts/verify-render.ts +728 -0
  28. package/package.json +2 -2
@@ -0,0 +1,594 @@
1
+ <!doctype html>
2
+ <html lang="en"><head><meta charset="utf-8">
3
+ <meta name="viewport" content="width=device-width,initial-scale=1">
4
+ <link rel="icon" href="data:,">
5
+ <title>@@TITLE@@</title>
6
+ <link rel="preconnect" href="https://fonts.googleapis.com">
7
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
8
+ <style>
9
+ :root{--bg:#0a0a12;--surf:#14141d;--surf2:#1a1a25;--surf3:#22222f;--border:rgba(255,255,255,.09);--borderS:rgba(255,255,255,.16);
10
+ --fg:#d6dbe6;--fgS:#eef1f6;--muted:#8a8698;--dim:#5a5667;--primary:#7E47D7;--primarySoft:#b794f4;--cyan:#45b8cc;
11
+ --pass:#43c39a;--fail:#e06666;--warn:#e8a64d;--pass-bg:rgba(67,195,154,.16);--fail-bg:rgba(224,102,102,.16);--warn-bg:rgba(232,166,77,.16);
12
+ --hm-pass:rgba(67,195,154,.38);--hm-fail:rgba(224,102,102,.42);--hm-indet:rgba(232,166,77,.40);--hm-skip:#22222f;
13
+ --font:'Space Grotesk',system-ui,sans-serif;--mono:'IBM Plex Mono',ui-monospace,monospace}
14
+ *{box-sizing:border-box;border-radius:0}
15
+ body{margin:0;background:var(--bg);color:var(--fg);font-family:var(--font);font-size:14px;line-height:1.55;padding-bottom:110px}
16
+ .wrap{max-width:1180px;margin:0 auto;padding:0 22px 40px}
17
+ .hdr{position:sticky;top:0;z-index:30;background:rgba(10,10,18,.92);backdrop-filter:blur(8px);border-bottom:1px solid var(--border);padding:12px 22px;display:flex;align-items:center;gap:12px}
18
+ .wm{font-weight:700;font-size:18px;letter-spacing:.5px}
19
+ .wm b{background:linear-gradient(90deg,var(--primarySoft),var(--cyan));-webkit-background-clip:text;background-clip:text;color:transparent}
20
+ .mockbadge{font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--warn);border:1px solid var(--warn);padding:2px 8px}
21
+ .panel{border:1px solid var(--border);background:var(--surf);margin-top:14px}
22
+ .panel-h{display:flex;align-items:center;gap:8px;padding:9px 15px;border-bottom:1px solid var(--border);font-family:var(--mono);font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--primarySoft);background:var(--surf2)}
23
+ .panel-h .r{margin-left:auto;color:var(--muted);text-transform:none}
24
+ .panel-b{padding:13px 15px}
25
+ .tabs{display:flex;border-bottom:1px solid var(--border);background:var(--bg);flex-wrap:wrap}
26
+ .tabs s{font-family:var(--mono);font-size:11px;padding:8px 13px;border-right:1px solid var(--border);color:var(--muted);cursor:pointer;text-decoration:none}
27
+ .tabs s.on{color:var(--primarySoft);border-bottom:2px solid var(--primary);background:var(--surf)}
28
+ .sec{display:none}.sec.show{display:block}
29
+ .h4s{margin:20px 0 8px;font-size:15px;color:var(--fgS);font-weight:600;border-bottom:1px solid var(--border);padding-bottom:5px;max-width:88ch}
30
+ .intro{margin:0 0 14px}
31
+ .intro h4{margin:0 0 6px;font-size:16px;color:var(--fgS);font-weight:600}
32
+ .intro p{margin:0 0 6px;font-size:14px;color:var(--muted);max-width:86ch;line-height:1.6}
33
+ .intro p b{color:var(--fg)}
34
+ .kpi{display:flex;gap:7px;flex-wrap:wrap}
35
+ .kpi i{font-family:var(--mono);font-size:12px;font-style:normal;padding:4px 10px;border:1px solid var(--border);color:var(--muted)}
36
+ .kpi i b{color:var(--fgS)} .kpi i.pass b{color:var(--pass)} .kpi i.fail b{color:var(--fail)} .kpi i.warn b{color:var(--warn)} .kpi i.p b{color:var(--primarySoft)}
37
+ .verd{font-family:var(--mono);font-size:11px;font-weight:700;padding:3px 9px;border:1px solid}
38
+ .verd.pass{color:var(--pass);border-color:var(--pass)} .verd.fail{color:var(--fail);border-color:var(--fail)} .verd.inc{color:var(--warn);border-color:var(--warn)}
39
+ .sev{font-family:var(--mono);font-size:11px;font-weight:700;padding:2px 7px}
40
+ .sev.CRIT{color:var(--fail);background:var(--fail-bg)} .sev.HIGH{color:var(--warn);background:var(--warn-bg)} .sev.MED{color:var(--cyan);background:rgba(69,184,204,.10)} .sev.LOW{color:var(--muted);background:var(--surf3)}
41
+ .chip{font-family:var(--mono);font-size:11px;color:var(--muted);border:1px solid var(--border);padding:1px 6px}
42
+ .lstrip{display:inline-flex;gap:3px;vertical-align:middle}
43
+ .lstrip u{font-family:var(--mono);font-size:11px;text-decoration:none;padding:1px 5px;border:1px solid var(--border);color:var(--dim)}
44
+ .lstrip u.pass{color:var(--pass);border-color:var(--pass)} .lstrip u.fail{color:var(--fail);border-color:var(--fail)}
45
+ .lstrip u.undecidable{color:var(--warn);border-color:var(--warn)} .lstrip u.skip{color:var(--dim);border-style:dashed}
46
+ .lstrip u.fired{color:var(--cyan);border-color:var(--cyan)} .hm .cell.fired{background:rgba(69,184,204,.30)}
47
+ .lstrip u.no-fires{color:var(--pass);border-color:var(--pass)} .hm .cell.no-fires{background:rgba(67,195,154,.22)}
48
+ /* VQ */
49
+ .vq{border:1px dashed var(--cyan);background:rgba(69,184,204,.05);padding:8px 11px;margin:12px 0}
50
+ .vq .q{font-family:var(--mono);font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--cyan);margin-bottom:5px}
51
+ .vq .opts{display:flex;gap:6px;flex-wrap:wrap}
52
+ .vq .opts button{font-family:var(--mono);font-size:11px;padding:3px 11px;background:var(--surf2);border:1px solid var(--border);color:var(--muted);cursor:pointer}
53
+ .vq .opts button.on{border-color:var(--cyan);color:var(--cyan);background:rgba(69,184,204,.12)}
54
+ /* ledger */
55
+ .ledger{width:100%;border-collapse:collapse;font-size:14px}
56
+ .ledger th{font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);text-align:left;padding:7px 9px;border-bottom:1px solid var(--borderS)}
57
+ .ledger td{padding:10px 10px;border-bottom:1px solid var(--borderS);color:var(--fg);cursor:pointer;font-size:14px}
58
+ .ledger tr:hover td{background:var(--surf2)}
59
+ .ledger td b{color:var(--fgS);font-size:14.5px}
60
+ .confbadge{font-family:var(--mono);font-size:11px;color:var(--fail);border:1px solid var(--fail);padding:1px 6px}
61
+ /* two-lane walk (faithful to render-eval-report §2) */
62
+ .walk{border:1px solid var(--borderS);background:var(--bg);margin:0}
63
+ .walk-h{position:sticky;top:49px;z-index:10;display:flex;gap:9px;align-items:center;flex-wrap:wrap;padding:8px 13px;background:var(--surf2);border-bottom:1px solid var(--borderS)}
64
+ .walk-h .tid{font-family:var(--mono);font-weight:600;color:var(--fgS);font-size:15px}
65
+ .tnav{font-family:var(--mono);font-size:11px;padding:3px 12px;background:rgba(126,71,215,.12);border:1px solid var(--primary);color:var(--primarySoft);cursor:pointer;font-weight:600}
66
+ .tnav:hover{color:var(--fgS);background:rgba(126,71,215,.25)}
67
+ .lanehdr{display:grid;grid-template-columns:1fr 34px 1fr;background:var(--surf2)}
68
+ .lanehdr div{font-family:var(--mono);font-size:11px;text-transform:uppercase;letter-spacing:.05em;padding:6px 10px;border-bottom:1px solid var(--borderS)}
69
+ .lanehdr .a{color:var(--fgS)} .lanehdr .x{text-align:center;color:var(--dim)} .lanehdr .j{color:var(--primarySoft)}
70
+ .band{display:grid;grid-template-columns:1fr 34px 1fr;border-bottom:1px solid var(--border)}
71
+ .band .lane-a{padding:9px 12px}
72
+ .band .lane-x{display:flex;align-items:center;justify-content:center;color:var(--dim);font-family:var(--mono);font-size:11px}
73
+ .band .lane-j{padding:9px 12px;border-left:1px solid var(--border);background:var(--surf)}
74
+ .band.divg .lane-a{border-left:3px solid var(--fail)}
75
+ .tool{font-family:var(--mono);font-size:13px;color:var(--cyan)}
76
+ .tool .args{color:var(--dim)}
77
+ .ltag{font-family:var(--mono);font-size:11px;color:var(--primarySoft);border:1px solid rgba(126,71,215,.5);padding:0 4px;margin-left:6px}
78
+ .divmark{font-family:var(--mono);font-size:11px;color:var(--fail);margin-left:8px}
79
+ .out{font-family:var(--mono);font-size:13px;color:var(--muted);background:var(--surf);border:1px solid var(--border);padding:5px 9px;margin-top:5px;overflow-wrap:anywhere;line-height:1.5}
80
+ .out mark{background:rgba(67,195,154,.25);color:var(--fgS);padding:0 2px}
81
+ /* walk criteria context (VQ-E6 variants) */
82
+ .critband{display:grid;grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:6px;padding:9px 12px;background:var(--surf);border-bottom:1px solid var(--borderS)}
83
+ .critband .cc{border:1px solid var(--border);background:var(--surf2);padding:9px 11px 10px;font-size:13px;line-height:1.45;cursor:pointer;position:relative;min-height:118px;display:flex;flex-direction:column}
84
+ .critband .cc .cc-title{display:flex;gap:8px;align-items:center;margin-bottom:3px}
85
+ .critband .cc .cc-title .sev{margin-left:auto}
86
+ .critband .cc .cc-title b{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
87
+ .critband .cc.open{border-color:var(--primary);box-shadow:0 0 0 1px rgba(126,71,215,.5)}
88
+ .critband .ccdetail{grid-column:1/-1;border:1px solid var(--border);border-left:3px solid var(--primary);background:var(--bg);padding:11px 13px;font-size:13.5px;line-height:1.65;color:var(--fg);max-height:340px;overflow-y:auto;overscroll-behavior:contain}
89
+ .critband .ccdetail b{color:var(--fgS)}
90
+ .critband .cc:hover{border-color:var(--primarySoft);background:var(--surf3);box-shadow:0 0 0 1px rgba(126,71,215,.35)}
91
+ .critband .cc.bound{border-color:rgba(126,71,215,.6)}
92
+ .critband .cc.dim{opacity:.45}
93
+ .critband .cc b{color:var(--fgS);font-family:var(--mono);font-size:13px}
94
+ .critband .cc .st{color:var(--muted);display:block;margin-top:2px}
95
+ .critband .cc .tag{float:right;font-family:var(--mono);font-size:10.5px;color:var(--primarySoft);line-height:20px}
96
+ .critband .cc .pol{display:none;margin-top:7px;padding:8px 10px;background:var(--bg);border:1px solid var(--border);border-left:3px solid var(--primary);color:var(--fg);font-size:13.5px;line-height:1.6}
97
+ .critband .cc .pol b{font-family:var(--font);font-size:13.5px;color:var(--fgS)}
98
+ .critband .cc.open .pol{display:block}
99
+ .critband .cc .hint{font-family:var(--mono);font-size:11px;color:var(--primarySoft);border:1px solid rgba(126,71,215,.5);padding:1px 7px;display:inline-block;margin-top:auto;align-self:flex-start}
100
+ .critband .cc .st{padding-bottom:10px}
101
+ .critband .cc .hint::before{content:'click to expand policy ▸'}
102
+ .critband .cc.open .hint::before{content:'click to collapse ▾ (details below)'}
103
+ /* uniform badge/label heights */
104
+ .sev,.chip,.cchip,.verd,.toolb,.idc{display:inline-flex;align-items:center;height:20px;line-height:1;box-sizing:border-box}
105
+ .idc{font-family:var(--mono);font-size:12px;padding:0 8px;border:1px solid;margin:5px 4px 0 0}
106
+ .idc.k{color:var(--primarySoft);border-color:rgba(126,71,215,.6)}
107
+ .idc.m{color:var(--cyan);border-color:rgba(69,184,204,.6)}
108
+ .idc.f{color:var(--warn);border-color:rgba(232,166,77,.6)}
109
+ .cchip{font-family:var(--mono);font-size:11px;padding:1px 8px;border:1px solid var(--border);color:var(--dim);margin-left:6px;cursor:default}
110
+ .cchip.bound{color:var(--primarySoft);border-color:rgba(126,71,215,.6)}
111
+ /* judge micro-steps */
112
+ .jstep{border:1px solid var(--border);background:var(--surf2);padding:6px 9px;margin:4px 0;font-size:13.5px;color:var(--muted);line-height:1.5}
113
+ .jstep b{color:var(--fg)}
114
+ .kind{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;padding:1px 6px;margin-right:6px}
115
+ .kind.gather{color:var(--cyan);background:rgba(69,184,204,.12)} .kind.expect{color:var(--primarySoft);background:rgba(126,71,215,.14)}
116
+ .kind.examine{color:var(--muted);background:var(--surf3)} .kind.bind{color:#5aa6d6;background:rgba(90,166,214,.12)}
117
+ .kind.ground{color:var(--pass);background:var(--pass-bg)} .kind.critique{color:var(--primarySoft);background:rgba(126,71,215,.14)}
118
+ .kind.decide-pass{color:var(--pass);background:var(--pass-bg)} .kind.decide-fail{color:var(--fail);background:var(--fail-bg)} .kind.decide-uncertain{color:var(--warn);background:var(--warn-bg)}
119
+ .kind.localize{color:var(--fail);background:var(--fail-bg)}
120
+ .jref{font-family:var(--mono);font-size:12px;color:var(--fg);background:var(--bg);border:1px solid var(--border);padding:2px 7px;margin-top:4px;display:inline-block}
121
+ .jref b{color:var(--pass)}
122
+ .locband{border-top:1px solid var(--fail);background:var(--fail-bg);padding:8px 13px;font-size:14px;color:var(--fg)}
123
+ .gband{background:rgba(69,184,204,.04);border-bottom:1px solid var(--border)}
124
+ /* scorecard metrics tiles (UI-5) */
125
+ .sc-metrics{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:8px;margin:10px 0 4px}
126
+ .scm{border:1px solid var(--border);background:var(--surf2);padding:10px 12px}
127
+ .scm-v{font-size:24px;font-weight:700;color:var(--fgS)}
128
+ .scm.ok .scm-v{color:var(--pass)} .scm.bad .scm-v{color:var(--fail)} .scm.mid .scm-v{color:var(--warn)}
129
+ .scm-l{font-family:var(--mono);font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-top:2px}
130
+ .scm-n{font-size:12.5px;color:var(--dim);margin-top:3px}
131
+ /* heatmap */
132
+ .hm{display:grid;gap:3px;font-family:var(--mono);font-size:12px}
133
+ .hm .lab{color:var(--fg);opacity:.88;text-align:right;padding-right:6px;line-height:18px;white-space:nowrap}
134
+ .hm .lab i{font-style:normal;color:var(--muted)}
135
+ .hm .cell{height:18px;border:1px solid rgba(0,0,0,.35)}
136
+ .hm .cell.pass{background:var(--hm-pass)} .hm .cell.fail{background:var(--hm-fail)} .hm .cell.uncertain{background:var(--hm-indet)} .hm .cell.skip{background:var(--hm-skip)}
137
+ .hm .colh{font-size:11px;color:var(--dim);writing-mode:vertical-rl;text-orientation:mixed;height:76px}
138
+ .subc{border:1px solid var(--border);background:var(--surf2);margin-top:10px}
139
+ .subc-h{display:flex;gap:9px;align-items:center;padding:8px 11px;border-bottom:1px solid var(--border);flex-wrap:wrap}
140
+ .nest{border:1px solid var(--border);background:var(--surf);margin:7px 11px;padding:7px 10px;font-family:var(--mono);font-size:13px;color:var(--muted);line-height:1.55}
141
+ .nest b{color:var(--fg)} .nest .ok{color:var(--pass)} .nest .w{color:var(--warn)}
142
+ .nest-h{font-family:var(--mono);font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin:-7px -10px 6px;padding:5px 10px;border-bottom:1px solid var(--border)}
143
+ /* finding + selfeval cards */
144
+ .fcard{border:1px solid var(--border);background:var(--surf2);margin:12px 0}
145
+ .fcard-h{display:flex;gap:9px;align-items:center;flex-wrap:wrap;padding:8px 12px;border-bottom:1px solid var(--border)}
146
+ .fcard-h b{color:var(--fgS);font-size:14.5px}
147
+ .fcard-b{padding:10px 13px;font-size:14px;color:var(--muted);line-height:1.6}
148
+ .fcard-b b{color:var(--fg)}
149
+ .tlink{font-family:var(--mono);font-size:12.5px;color:var(--cyan);border:1px solid var(--cyan);padding:2px 9px;cursor:pointer;margin-right:6px;display:inline-block}
150
+ .tlink:hover{background:rgba(69,184,204,.15)}
151
+ .toolb{font-family:var(--mono);font-size:12px;padding:2px 8px;border:1px solid;margin:2px 4px 2px 0;display:inline-block}
152
+ .toolb.read{color:var(--cyan);border-color:rgba(69,184,204,.6)}
153
+ .toolb.act{color:var(--warn);border-color:rgba(232,166,77,.6)}
154
+ /* judge-block style variants (VQ-E5) */
155
+ .tlwrap{border-left:2px solid rgba(126,71,215,.4);padding-left:14px;margin:2px 0}
156
+ .tl{position:relative;margin:7px 0;font-size:13.5px;color:var(--muted);line-height:1.5}
157
+ .tl .dot{position:absolute;left:-19px;top:5px;width:9px;height:9px;background:var(--dim)}
158
+ .tl .dot.gather{background:var(--cyan)} .tl .dot.expect{background:var(--primarySoft)} .tl .dot.examine{background:var(--dim)}
159
+ .tl .dot.bind{background:#5aa6d6} .tl .dot.ground{background:var(--pass)} .tl .dot.critique{background:var(--primarySoft)}
160
+ .tl .dot.decide-pass{background:var(--pass)} .tl .dot.decide-fail{background:var(--fail)} .tl .dot.decide-uncertain{background:var(--warn)}
161
+ .tl b{color:var(--fg)}
162
+ .gv{border:1px solid var(--border);background:var(--surf2);margin:6px 0}
163
+ .gv-h{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:6px 10px;border-bottom:1px solid var(--border);background:var(--surf3)}
164
+ .gv-h .cid{font-family:var(--mono);font-size:13px;font-weight:700;color:var(--fgS)}
165
+ .gv-h .chain{display:inline-flex;gap:4px}
166
+ .gv-b{padding:7px 10px;font-size:13.5px;color:var(--muted);line-height:1.55}
167
+ .gv-b b{color:var(--fg)}
168
+ .gv-ref{font-family:var(--mono);font-size:12px;color:var(--fg);background:var(--bg);border:1px solid var(--border);padding:2px 7px;margin-top:5px;display:inline-block}
169
+ .gv-ref b{color:var(--pass)}
170
+ .handoffbtn{background:var(--surf2);border:1px solid var(--pass);color:var(--pass);font-family:var(--mono);font-size:11px;letter-spacing:.05em;text-transform:none;padding:4px 12px;cursor:pointer;margin-left:auto}
171
+ .handoffbtn.done{background:var(--pass-bg)}
172
+ .hero{padding:26px 0 10px;border-bottom:1px solid var(--border);margin-bottom:6px}
173
+ .hero .who{font-family:var(--mono);font-size:11.5px;color:var(--cyan);text-transform:uppercase;letter-spacing:.14em;margin-bottom:7px}
174
+ .hero h1{font-size:clamp(24px,3.4vw,32px);margin:0 0 8px;color:var(--fgS);letter-spacing:-.01em;font-weight:700}
175
+ .hero p{font-size:15.5px;color:var(--muted);max-width:88ch;margin:0 0 8px;line-height:1.65}
176
+ .hero p b{color:var(--fg)}
177
+ .foot{margin-top:32px;color:var(--dim);font-size:11px;border-top:1px solid var(--border);padding-top:12px;font-family:var(--mono)}
178
+ #fbpanel{position:fixed;bottom:0;left:0;right:0;background:rgba(10,10,18,.97);border-top:1px solid var(--primary);padding:9px 22px 11px;z-index:50}
179
+ #fbpanel .frow{max-width:1180px;margin:0 auto;display:flex;gap:12px;align-items:flex-end}
180
+ #fbpanel label{font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--primarySoft);display:block;margin-bottom:4px}
181
+ #fbtext{flex:1;background:var(--surf2);border:1px solid var(--border);color:var(--fg);font-family:var(--font);font-size:13px;padding:7px 10px;min-height:40px;max-height:110px;resize:vertical}
182
+ #fbcopy{background:var(--surf2);border:1px solid var(--primary);color:var(--primarySoft);font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;padding:10px 16px;cursor:pointer;white-space:nowrap}
183
+ #fbcopy.done{border-color:var(--pass);color:var(--pass)}
184
+ /* profile variants */
185
+ .profgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:0;border:1px solid var(--border);background:var(--surf2)}
186
+ .profgrid>div{padding:11px 14px;border-right:1px solid var(--border)}
187
+ .profstrip{display:flex;gap:8px;flex-wrap:wrap;align-items:center;border:1px solid var(--border);background:var(--surf2);padding:10px 13px}
188
+ .proftwo{display:grid;grid-template-columns:1fr 1.2fr;gap:0;border:1px solid var(--border);background:var(--surf2)}
189
+ .proftwo>div{padding:11px 14px}
190
+ .proftwo>div:last-child{border-left:1px solid var(--border)}
191
+ .pk{font-family:var(--mono);font-size:11px;color:var(--dim);text-transform:uppercase;letter-spacing:.06em;margin-bottom:4px}
192
+ .pv{font-size:14px;color:var(--muted);line-height:1.55}
193
+ .pv b{color:var(--fg)}
194
+ </style></head><body>
195
+ <div class="hdr"><div class="wm">MUTAGENT<b>/evaluator</b> · Evaluation Report</div>
196
+ @@RUN_BADGE@@</div>
197
+ <div class="wrap">
198
+
199
+ <div class="hero" data-component="mgt-report-hero">
200
+ <div class="who">Automated judgment · layered evidence</div>
201
+ <h1>@@HERO_TITLE@@</h1>
202
+ <p>@@HERO_LEDE@@</p>
203
+ </div>
204
+
205
+ <div class="panel"><div class="panel-b" style="display:flex;align-items:center;gap:10px;flex-wrap:wrap">
206
+ @@IDENTITY_STRIP@@
207
+ </div></div>
208
+
209
+ <div class="panel" id="report">
210
+ <div class="tabs">
211
+ <s class="on" onclick="tab(0)">① Overview</s><s onclick="tab(1)">② Trajectory ‖ Judge</s>
212
+ <s onclick="tab(2)">③ Eval Scorecard</s><s onclick="tab(3)">④ Findings</s><s onclick="tab(4)">⑤ Self-Eval</s>
213
+ </div>
214
+
215
+ <!-- ① OVERVIEW -->
216
+ <div class="sec show" data-page="overview"><div class="panel-h">① Overview</div><div class="panel-b">
217
+ <div class="h4s" style="margin-top:4px">Who was judged</div>
218
+ <div id="profhost" data-component="mgt-subject-profile"></div>
219
+
220
+ <div class="h4s">The scores</div>
221
+ <div class="sc-metrics" data-component="mgt-metrics-tiles">
222
+ @@METRICS_TILES@@
223
+ </div>
224
+
225
+ <div class="h4s">The eval suite — what we checked</div>
226
+ <p style="font-size:14px;color:var(--muted);margin:4px 0 8px;max-width:86ch">@@SUITE_LEDE@@</p>
227
+ <div id="suitehost" data-component="mgt-suite-summary"></div>
228
+
229
+ <div class="h4s">The corpus — every ingested trace</div>
230
+ @@TRACE_LIST@@
231
+
232
+ <div class="h4s">Bottom line — what this run tells you</div>
233
+ <p style="font-size:14px;color:var(--muted);max-width:86ch;line-height:1.65">@@BOTTOM_LINE@@</p>
234
+ </div></div>
235
+
236
+ <!-- ② TRAJECTORY ‖ JUDGE -->
237
+ <div class="sec" data-page="trajectory-judge"><div class="panel-h">② Trajectory ‖ Judge <span class="r">agent lane LEFT · judge's anchored reasoning RIGHT</span></div><div class="panel-b">
238
+ <div class="intro">
239
+ <h4>The Target-Agent trajectory ‖ Judge trajectory, side by side</h4>
240
+ <p>Click a row to drill in. The agent's steps render on the <b>left lane</b>; the judge's reasoning walk — anchored to each
241
+ step — on the <b>right</b>: its gathered understanding, the trajectory it EXPECTED before looking, every examine/bind/
242
+ ground/critique/decide micro-step with quoted evidence, and the root localization when something went wrong.</p>
243
+ </div>
244
+
245
+
246
+ <div class="h4s" style="margin-top:6px">Legend — the judge's micro-steps (right lane)</div>
247
+ <div style="display:flex;gap:14px;flex-wrap:wrap;font-size:13.5px;color:var(--muted);margin:6px 0 12px;line-height:2">
248
+ <span><span class="kind gather">gather</span>understand the agent + classify the scenario</span>
249
+ <span><span class="kind expect">expect</span>predict the correct path BEFORE looking</span>
250
+ <span><span class="kind examine">examine</span>compare a step against the expected path</span>
251
+ <span><span class="kind bind">bind</span>a criterion's terms attach to this step</span>
252
+ <span><span class="kind ground">ground</span>quote the exact evidence string</span>
253
+ <span><span class="kind critique">critique</span>reason it out IN WRITING before deciding</span>
254
+ <span><span class="kind decide-pass">decide</span>the binary verdict + confidence note</span>
255
+ <span><span class="kind localize">localize</span>name the FIRST thing that went wrong</span>
256
+ </div>
257
+ <div style="font-family:var(--mono);font-size:11px;color:var(--cyan);margin:2px 0 6px">▸ click any row — the two-lane walk expands IN PLACE · ⚡ = layer conflict (VQ-E3 locked: badge)</div>
258
+ <table class="ledger" id="ledger" data-component="mgt-trace-ledger"><thead><tr>
259
+ <th>trajectory</th><th>scenario</th><th>layers L0–L4</th><th>outcome</th><th>gate</th><th>conf</th><th>run</th>
260
+ </tr></thead><tbody></tbody></table>
261
+ </div></div>
262
+
263
+ <!-- ③ SCORECARD -->
264
+ <div class="sec" data-page="scorecard"><div class="panel-h">③ Eval Scorecard <span class="r">scores · layer matrix · criteria matrix · calibration</span></div><div class="panel-b">
265
+
266
+ <div class="h4s" style="margin-top:2px">The scores</div>
267
+ <div class="sc-metrics" data-component="mgt-metrics-tiles">
268
+ @@SCORECARD_SCORES@@
269
+ </div>
270
+
271
+ <div class="h4s">How each evidence layer judged each trace</div>
272
+ <p style="font-size:13.5px;color:var(--muted);margin:2px 0 8px;max-width:86ch">One row per layer of the judge's walk, one column per trace. → means the layer was skipped because the outcome check already settled everything.</p>
273
+ <div id="hmlayers" data-component="mgt-layer-matrix"></div>
274
+
275
+ <div class="h4s">How each criterion verdicted — with its score</div>
276
+ <p style="font-size:13.5px;color:var(--muted);margin:2px 0 8px;max-width:86ch">The gating surface: every user-defined check with its pass count over the applicable trajectories.</p>
277
+ <div id="hmcrit" data-component="mgt-criteria-matrix"></div>
278
+
279
+ @@CRITERION_DETAILS@@
280
+
281
+ @@CONFLICTS@@
282
+ </div></div>
283
+
284
+ <!-- ④ FINDINGS -->
285
+ <div class="sec" data-page="findings"><div class="panel-h">④ Findings <span class="r">judge-only → routed to diagnostics (EV-051)</span><button class="handoffbtn" id="fhbtn" onclick="copyFindingsHandoff()">Copy findings handoff (markdown)</button></div><div class="panel-b">
286
+ <div class="intro"><h4>What the judge found — and where each finding went</h4>
287
+ <p>Findings are auditable: verbatim evidence, the judge's reasoning, and a route. The evaluator never fixes — failures go
288
+ to diagnostics; open questions go to your calibration queue.</p></div>
289
+
290
+ @@FINDINGS_CARDS@@
291
+ </div></div>
292
+
293
+ <!-- ⑤ SELF-EVAL -->
294
+ <div class="sec" data-page="self-eval"><div class="panel-h">⑤ Self-Eval · Methodology <span class="r">internal — stripped on publish</span></div><div class="panel-b">
295
+ <div class="intro"><h4>The judge grading its own run</h4>
296
+ <p>Before you trust the verdicts above, these are the checks the pipeline ran on ITSELF — completeness, reproducibility,
297
+ economy, and independent verification. Advisory only: they never change a subject's gate.</p></div>
298
+
299
+ @@SELFEVAL_CARDS@@
300
+ </div></div>
301
+ </div>
302
+
303
+ <div class="foot">@@FOOT@@</div>
304
+ </div>
305
+
306
+ <div id="fbpanel" data-component="mgt-feedback-bar"><div class="frow">
307
+ <div style="flex:1"><label for="fbtext">@@FEEDBACK_LABEL@@</label>
308
+ <textarea id="fbtext" placeholder="e.g. 'profile variant C but move suite table left' …"></textarea></div>
309
+ <button id="fbcopy" type="button">Copy&nbsp;MD</button>
310
+ </div></div>
311
+
312
+ <script>window.ASTER=@@DATA_JSON@@;
313
+ window.__OPEN_TRACE__=window.ASTER.openTrace;
314
+ window.ASTER.cellFor=function(id,tr){return ((tr.cells||{})[id])||'skip';};</script>
315
+ <script>
316
+ function tab(i){var t=document.querySelectorAll('#report>.tabs s'),s=document.querySelectorAll('#report>.sec');
317
+ t.forEach(function(x,k){x.classList.toggle('on',k===i)});s.forEach(function(x,k){x.classList.toggle('show',k===i)});}
318
+ var LAYERS=['L0','L1','L2','L3','L4'];
319
+ var LNAMES={L0:'code checks',L1:'outcome',L2:'trajectory',L3:'tool outputs',L4:'context'};
320
+ var profStyle='grid', openTrace=window.__OPEN_TRACE__||null;
321
+ function esc(s){return String(s).split('&').join('&amp;').split('<').join('&lt;');}
322
+
323
+ /* ── ① subject profile variants ── */
324
+ function renderProf(){
325
+ var host=document.getElementById('profhost'),h='';
326
+ var facts=ASTER.profile;
327
+ if(profStyle==='grid'){
328
+ var genB='',opB='';
329
+ facts.gen.split(' · ').forEach(function(t){genB+='<span class="toolb read">'+t+'</span>';});
330
+ facts.op.split(' · ').forEach(function(t){opB+='<span class="toolb act">'+t+'</span>';});
331
+ h='<div class="profgrid">'
332
+ +'<div><div class="pk">identity</div><div class="pv"><b>'+esc(facts.name)+'</b> — '+esc(facts.desc)+'<br>'+(facts.chips||[]).map(function(c,i){return '<span class="idc '+(['k','m','f'][i%3])+'">'+esc(c)+'</span>';}).join('')+'</div></div>'
333
+ +'<div><div class="pk">'+esc(facts.toolsHeading)+'</div><div class="pv">'
334
+ +'<div style="margin-bottom:5px"><span style="color:var(--cyan);font-size:12.5px">reads data:</span><br>'+genB+'</div>'
335
+ +'<div><span style="color:var(--warn);font-size:12.5px">acts on the world:</span><br>'+opB+'</div>'
336
+ +'<div style="font-size:12.5px;color:var(--dim);margin-top:5px">acting tools are the high-stakes ones — that is what the guards protect</div></div></div>'
337
+ +'<div><div class="pk">what was judged</div><div class="pv"><b>'+facts.corpus+'</b><br>'+facts.split+'<br><span style="font-size:12.5px;color:var(--dim)">judge: host model · pinned · temperature 0</span></div></div></div>';
338
+ }else if(profStyle==='strip'){
339
+ h='<div class="profstrip"><b style="font-size:15px;color:var(--fgS)">'+esc(facts.name)+'</b>'
340
+ +'<span class="idc k">agent</span><span class="idc m">code-based</span><span class="idc f">mastra</span><span class="chip">8 tools (3 read · 5 operational)</span>'
341
+ +'<span class="chip">12 traces · 3 scenarios</span><span class="chip">Jul 20–23</span><span class="chip">judge pinned · temp 0</span>'
342
+ +'<span style="flex-basis:100%;font-size:13.5px;color:var(--muted)">'+facts.desc+'</span></div>';
343
+ }else{
344
+ h='<div class="proftwo">'
345
+ +'<div><div class="pk">the subject</div><div class="pv"><b>'+esc(facts.name)+'</b> — '+facts.desc+'<br><br><b style="color:var(--cyan)">reads:</b> '+facts.gen+'<br><b style="color:var(--warn)">acts:</b> '+facts.op+'</div></div>'
346
+ +'<div><div class="pk">this evaluation</div><div class="pv"><b>'+facts.corpus+'</b> ('+facts.split+')<br>Suite: living-suite v2 — 6 binary criteria mined from Aster\'s own sessions.<br>Judge: host-runtime, pinned model, temperature 0 → byte-identical reruns.<br>Gate: fires on any CRIT/HIGH criterion failing.</div></div></div>';
347
+ }
348
+ host.innerHTML=h;
349
+ }
350
+ /* ── ① suite summary ── */
351
+ function renderSuite(){
352
+ var h='<table class="ledger"><thead><tr><th>id</th><th>the check (plain language)</th><th>layer</th><th>kind</th><th>severity</th><th>score</th></tr></thead><tbody>';
353
+ var scores=ASTER.scores;
354
+ ASTER.criteria.forEach(function(c){
355
+ h+='<tr style="cursor:default"><td><b>'+c.id+'</b> '+c.slug+'</td><td>'+esc(c.statement)+'</td><td>'+c.layer+'</td><td>'+c.cls+'</td>'
356
+ +'<td><span class="sev '+c.sev+'">'+c.sev+'</span></td><td style="font-family:var(--mono)">'+scores[c.id]+' pass</td></tr>';
357
+ });
358
+ document.getElementById('suitehost').innerHTML=h+'</tbody></table>';
359
+ }
360
+
361
+ /* ── ② ledger + two-lane walk ── */
362
+ function stripHtml(tr){
363
+ var h='<span class="lstrip">';
364
+ LAYERS.forEach(function(L){var st=tr.layers[L]||'skip';var sym=st==='pass'?'✓':st==='fail'?'✗':st==='undecidable'?'?':st==='fired'?'⚑':'→';
365
+ h+='<u class="'+st+'">'+L+sym+'</u>';});
366
+ return h+'</span>';
367
+ }
368
+ var PAGE=25, ledgerPage=0;
369
+ function renderLedger(){
370
+ var tb=document.querySelector('#ledger tbody'),h='';
371
+ var T=ASTER.traces, paged=T.length>PAGE;
372
+ var pages=paged?Math.ceil(T.length/PAGE):1;
373
+ if(ledgerPage>=pages)ledgerPage=0;
374
+ var view=paged?T.slice(ledgerPage*PAGE,(ledgerPage+1)*PAGE):T;
375
+ if(paged){
376
+ h+='<tr style="cursor:default"><td colspan="7" data-component="mgt-ledger-pager" style="background:var(--surf2)">'
377
+ +'<span class="tnav" onclick="event.stopPropagation();ledgerPage=Math.max(0,ledgerPage-1);renderLedger();renderWalk()">← page</span> '
378
+ +'<span class="tnav" onclick="event.stopPropagation();ledgerPage=Math.min('+(pages-1)+',ledgerPage+1);renderLedger();renderWalk()">page →</span> '
379
+ +'<span style="font-family:var(--mono);font-size:12.5px;color:var(--muted);margin-left:8px">page '+(ledgerPage+1)+' of '+pages+' · showing '+view[0].id+' … '+view[view.length-1].id+' of '+T.length+' trajectories</span></td></tr>';
380
+ }
381
+ view.forEach(function(tr){
382
+ var gv=tr.gate==='pass'?'<span class="verd pass">pass</span>':tr.gate==='fail'?'<span class="verd fail">fail</span>':'<span class="verd inc">incomplete</span>';
383
+ var extra=tr.earlyExit==='L1'?'<span class="chip">early-exit@outcome</span>':(tr.earlyExit==='fidelity'?'<span class="chip" style="color:var(--warn)">truncated</span>':'');
384
+ var isOpen=openTrace===tr.id;
385
+ h+='<tr onclick="openFeed(\''+tr.id+'\')"'+(isOpen?' style="background:var(--surf2)"':'')+'><td><b>'+tr.id+'</b>'+(tr.conflict?' <span class="confbadge">⚡1</span>':'')+'</td><td>'+tr.scenario+'</td><td>'+stripHtml(tr)+'</td>'
386
+ +'<td>'+tr.outcome.verdict+'</td><td>'+gv+' '+extra+'</td><td style="font-family:var(--mono)">'+tr.judgeConf.toFixed(2)+'</td>'
387
+ +'<td style="white-space:nowrap"><span class="tnav" style="display:inline-block;white-space:nowrap">'+(isOpen?'▾ close':'▸ view')+'</span></td></tr>';
388
+ if(isOpen){h+='<tr><td colspan="7" id="feedcell" style="padding:0;background:var(--bg);cursor:default"></td></tr>';}
389
+ });
390
+ tb.innerHTML=h;
391
+ }
392
+ function openFeed(id){openTrace=(openTrace===id?null:id);renderLedger();renderWalk();}
393
+ function navWalk(d){var i=-1;ASTER.traces.forEach(function(t,k){if(t.id===openTrace)i=k;});
394
+ if(i<0)i=0;var n=(i+d+ASTER.traces.length)%ASTER.traces.length;openTrace=ASTER.traces[n].id;renderLedger();renderWalk();
395
+ var el=document.getElementById('feedcell');if(el)el.scrollIntoView({behavior:'smooth',block:'nearest'});}
396
+ function markOut(s,refs){
397
+ var body=esc(s.output);
398
+ (refs||[]).forEach(function(r){if(r&&r.value){var ev=esc(r.value);body=body.split(ev).join('<mark>'+ev+'</mark>');}});
399
+ return '<div class="out">'+body+'</div>';
400
+ }
401
+ var jstyle='cards', wcStyle='band';
402
+ function setWc(v,btn){wcStyle=v;vqOn(btn);renderWalk();}
403
+ function critsBound(tr){
404
+ var set={};tr.steps.forEach(function(s){(s.verdicts||[]).forEach(function(vd){set[vd.crit]=true;});});
405
+ return set;
406
+ }
407
+ function critBandHtml(tr){
408
+ var bound=critsBound(tr),h='<div class="critband" data-component="mgt-walk-criteria">';
409
+ ASTER.criteria.forEach(function(c,ci){
410
+ var isB=!!bound[c.id];
411
+ h+='<div class="cc '+(isB?'bound':'dim')+'" onclick="ccToggle(this,'+ci+')">'
412
+ +'<div class="cc-title"><b>'+c.id+' · '+c.slug+'</b><span class="sev '+c.sev+'" style="font-size:11px">'+c.sev+'</span></div>'
413
+ +'<span class="st">'+esc(c.statement)+'</span>'
414
+ +'<span class="hint"></span>'
415
+ +'</div>';
416
+ });
417
+ return h+'</div>';
418
+ }
419
+ var openCrit=null;
420
+ function ccToggle(el,ci){
421
+ var band=el.parentElement;
422
+ var old=band.querySelector('.ccdetail');if(old)old.remove();
423
+ band.querySelectorAll('.cc').forEach(function(x){x.classList.remove('open');});
424
+ if(openCrit===ci){openCrit=null;return;}
425
+ openCrit=ci;el.classList.add('open');
426
+ var c=ASTER.criteria[ci];
427
+ var d=document.createElement('div');d.className='ccdetail';
428
+ d.innerHTML='<b>'+esc(c.id)+' · '+esc(c.slug)+' — the full check (the policy being enforced)</b><br>'+esc(c.policy||c.statement)
429
+ +'<br><br><b>Passes:</b> '+esc(c.passDef)+(c.failDef?' · <b>Fails:</b> '+esc(c.failDef):'');
430
+ band.appendChild(d);
431
+ }
432
+ function critChipsHtml(tr){
433
+ var bound=critsBound(tr),h='';
434
+ ASTER.criteria.forEach(function(c){
435
+ h+='<span class="cchip '+(!!bound[c.id]?'bound':'')+'" title="'+esc(c.statement)+' — passes: '+esc(c.passDef)+' · fails: '+esc(c.failDef)+'">'+c.id+'</span>';
436
+ });
437
+ return h;
438
+ }
439
+ function judgeLane(s){
440
+ var vs=s.verdicts||[];
441
+ if(jstyle==='cards'){
442
+ if(vs.length===0)return '<div class="jstep"><span class="kind examine">examine</span>step matches the expected path — nothing binds here.</div>';
443
+ var r='';
444
+ vs.forEach(function(vd){
445
+ var cdef=null;ASTER.criteria.forEach(function(c){if(c.id===vd.crit)cdef=c;});
446
+ r+='<div class="jstep"><span class="kind bind">bind</span><b>'+vd.crit+(cdef?' · '+cdef.slug:'')+'</b> binds to this step'
447
+ +(wcStyle==='inline'&&cdef?' — <i style="font-style:normal;color:var(--fg)">"'+esc(cdef.statement)+'"</i>':' — its terms resolve in this situation.')+'</div>';
448
+ if(vd.ref){r+='<div class="jstep"><span class="kind ground">ground</span>evidence: <span class="jref">'+vd.ref.obs+' · '+vd.ref.path+' = <b>"'+esc(vd.ref.value)+'"</b></span></div>';}
449
+ r+='<div class="jstep"><span class="kind critique">critique</span>'+esc(vd.critique)+'</div>';
450
+ r+='<div class="jstep"><span class="kind decide-'+vd.verdict+'">decide</span><b>'+vd.crit+' → '+vd.verdict.toUpperCase()+'</b> · confidence .'+Math.round(vd.conf*100)
451
+ +(vd.ref?'':' · abstain — no evidence bound')+'</div>';
452
+ });
453
+ return r;
454
+ }
455
+ if(jstyle==='timeline'){
456
+ if(vs.length===0)return '<div class="tlwrap"><div class="tl"><span class="dot examine"></span>examine — matches the expected path.</div></div>';
457
+ var t='<div class="tlwrap">';
458
+ vs.forEach(function(vd){
459
+ t+='<div class="tl"><span class="dot bind"></span><b>'+vd.crit+'</b> binds here</div>';
460
+ if(vd.ref)t+='<div class="tl"><span class="dot ground"></span>"'+esc(vd.ref.value)+'" <span style="color:var(--dim)">('+vd.ref.obs+' · '+vd.ref.path+')</span></div>';
461
+ t+='<div class="tl"><span class="dot critique"></span>'+esc(vd.critique)+'</div>';
462
+ t+='<div class="tl"><span class="dot decide-'+vd.verdict+'"></span><b>'+vd.verdict.toUpperCase()+'</b> · conf .'+Math.round(vd.conf*100)+'</div>';
463
+ });
464
+ return t+'</div>';
465
+ }
466
+ /* grouped — one compact card per verdict, chain shown as chips */
467
+ if(vs.length===0)return '<div style="font-family:var(--mono);font-size:12px;color:var(--dim);padding:4px 0">examine — on expected path, nothing binds</div>';
468
+ var g='';
469
+ vs.forEach(function(vd){
470
+ g+='<div class="gv"><div class="gv-h"><span class="cid">'+vd.crit+'</span>'
471
+ +'<span class="kind decide-'+vd.verdict+'">'+vd.verdict.toUpperCase()+' · .'+Math.round(vd.conf*100)+'</span>'
472
+ +'<span class="chain"><span class="kind bind">bind</span><span class="kind ground">'+(vd.ref?'ground ✓':'no evidence')+'</span></span></div>'
473
+ +'<div class="gv-b">'+esc(vd.critique)
474
+ +(vd.ref?'<br><span class="gv-ref">'+vd.ref.obs+' · '+vd.ref.path+' = <b>"'+esc(vd.ref.value)+'"</b></span>':'')
475
+ +'</div></div>';
476
+ });
477
+ return g;
478
+ }
479
+ function setJs(v,btn){jstyle=v;vqOn(btn);renderWalk();}
480
+ function renderWalk(){
481
+ var tr=null;ASTER.traces.forEach(function(t){if(t.id===openTrace)tr=t;});
482
+ var host=document.getElementById('feedcell');if(!host)return;if(!tr){host.innerHTML='';return;}
483
+ var h='<div class="walk"><div class="walk-h">'
484
+ +'<span class="tnav" onclick="event.stopPropagation();navWalk(-1)">← prev</span><span class="tnav" onclick="event.stopPropagation();navWalk(1)">next →</span>'
485
+ +'<span class="tid">'+tr.id+'</span><span class="chip">'+tr.scenario+'</span>'+stripHtml(tr)
486
+ +'<span class="chip">outcome '+tr.outcome.verdict+'</span>'
487
+ +(tr.gate==='pass'?'<span class="verd pass">GATE ✓</span>':tr.gate==='fail'?'<span class="verd fail">GATE ✗</span>':'<span class="verd inc">INC</span>')
488
+ +'<span class="chip">judge conf '+tr.judgeConf.toFixed(2)+'</span>'+(tr.conflict?'<span class="confbadge">⚡ conflict</span>':'')+'</div>';
489
+ if(wcStyle==='inline'){h+='<div style="padding:6px 13px;background:var(--surf);border-bottom:1px solid var(--border);font-family:var(--mono);font-size:12px;color:var(--muted)">checks in play:'+critChipsHtml(tr)+'</div>';}
490
+ if(wcStyle==='band') h+=critBandHtml(tr);
491
+ h+='<div class="lanehdr"><div class="a">TARGET AGENT — what it did</div><div class="x">‖</div><div class="j">JUDGE — anchored reasoning walk'+(wcStyle==='chips'?critChipsHtml(tr):'')+'</div></div>';
492
+ /* gather + expected band */
493
+ h+='<div class="band gband"><div class="lane-a" style="color:var(--dim);font-size:13px">— session start —</div><div class="lane-x">◦</div><div class="lane-j">'
494
+ +'<div class="jstep"><span class="kind gather">gather</span><b>Understanding:</b> '+esc(tr.understanding||('scenario classified as '+tr.scenario))+'</div>'
495
+ +'<div class="jstep"><span class="kind expect">expect</span><b>Expected trajectory before looking:</b> '+esc(tr.expectedLine||tr.outcome.expected)+'</div>'
496
+ +'</div></div>';
497
+ if(tr.fidelity) h+='<div class="locband" style="border-color:var(--warn);background:var(--warn-bg)">◔ '+esc(tr.fidelity)+'</div>';
498
+ tr.steps.forEach(function(s,ix){
499
+ var refs=(s.verdicts||[]).map(function(vd){return vd.ref;});
500
+ var left='<span class="tool">'+s.tool+' <span class="args">'+esc(s.args)+'</span></span>';
501
+ (s.layers||[]).forEach(function(L){left+='<span class="ltag">'+L+'</span>';});
502
+ if(s.divergence)left+='<span class="divmark">◆ first divergence</span>';
503
+ left+=markOut(s,refs);
504
+ h+='<div class="band'+(s.divergence?' divg':'')+'"><div class="lane-a"><span style="font-family:var(--mono);font-size:11px;color:var(--dim)">'+tr.id+' · obs-'+(ix+1)+'</span><br>'+left+'</div><div class="lane-x">‣</div><div class="lane-j">'+judgeLane(s)+'</div></div>';
505
+ });
506
+ if(tr.divergence) h+='<div class="locband"><span class="kind localize">localize</span><b>Root, not symptom:</b> '+esc(tr.divergence)+'</div>';
507
+ if(tr.conflict) h+='<div class="locband"><span class="kind localize">conflict</span>'+esc(tr.conflictNote)+' — queued for human adjudication.</div>';
508
+ h+='</div>';
509
+ host.innerHTML=h;
510
+ }
511
+
512
+ /* ── ③ heatmaps — per-trace when small; WINDOWED pass-rate cells at scale (production ehm idiom) ── */
513
+ var HM_WINDOW_AT=36;
514
+ function hmWindowSize(){return Math.max(10,Math.ceil(ASTER.traces.length/20));}
515
+ function renderHm(){
516
+ var T=ASTER.traces;
517
+ var scores=ASTER.scores;
518
+ if(T.length<=HM_WINDOW_AT){
519
+ var cellsFor=function(getter){var h='';T.forEach(function(tr){var st=getter(tr);h+='<span class="cell '+(st==='undecidable'?'uncertain':st)+'" title="'+tr.id+'"></span>';});return h;};
520
+ var colh='<span></span>';T.forEach(function(tr){colh+='<span class="colh">'+tr.id+'</span>';});
521
+ var grid='grid-template-columns:230px repeat('+T.length+',1fr)';
522
+ var h='<div class="hm" style="'+grid+'">'+colh;
523
+ LAYERS.forEach(function(L){h+='<span class="lab" style="color:var(--primarySoft)">'+LNAMES[L]+' ('+L+')</span>'+cellsFor(function(tr){return tr.layers[L]||'skip';});});
524
+ document.getElementById('hmlayers').innerHTML=h+'</div>';
525
+ var h2='<div class="hm" style="'+grid+'">'+colh;
526
+ ASTER.criteria.forEach(function(c){h2+='<span class="lab">'+c.id+' '+c.slug+' <i>· '+scores[c.id]+'</i></span>'+cellsFor(function(tr){return ASTER.cellFor(c.id,tr);});});
527
+ document.getElementById('hmcrit').innerHTML=h2+'</div>';
528
+ return;
529
+ }
530
+ /* windowed: one column per window of 25; cell = pass-rate % (colour) — mgt-windowed-matrix */
531
+ var wins=[];var W=hmWindowSize();for(var i=0;i<T.length;i+=W)wins.push(T.slice(i,i+W));
532
+ var note='<div class="explain" style="margin:0 0 8px"><b>Large corpus ('+T.length+' traces):</b> columns are windows of '+hmWindowSize()+' — each cell shows the pass-rate % over that window (green ≥95 · amber ≥80 · red &lt;80). Per-trace drill lives in tab ②.</div>';
533
+ var colh='<span></span>';wins.forEach(function(w){colh+='<span class="colh">'+w[0].id+'–'+w[w.length-1].id+'</span>';});
534
+ var grid='grid-template-columns:230px repeat('+wins.length+',minmax(34px,1fr))';
535
+ function winCells(getter){
536
+ var h='';
537
+ wins.forEach(function(w){
538
+ var pass=0,tot=0;
539
+ w.forEach(function(tr){var st=getter(tr);if(st==='skip')return;tot++;if(st==='pass')pass++;});
540
+ if(tot===0){h+='<span class="cell skip" style="height:20px"></span>';return;}
541
+ var r=Math.round(100*pass/tot);
542
+ var cls=r>=95?'pass':(r>=80?'uncertain':'fail');
543
+ h+='<span class="cell '+cls+'" style="height:20px;display:flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:11px;color:rgba(255,255,255,.85)" title="'+pass+'/'+tot+' pass in this window">'+r+'</span>';
544
+ });
545
+ return h;
546
+ }
547
+ var h='<div class="hm" data-component="mgt-windowed-matrix" style="'+grid+'">'+colh;
548
+ LAYERS.forEach(function(L){h+='<span class="lab" style="color:var(--primarySoft)">'+LNAMES[L]+' ('+L+')</span>'+winCells(function(tr){return tr.layers[L]||'skip';});});
549
+ document.getElementById('hmlayers').innerHTML=note+h+'</div>';
550
+ var h2='<div class="hm" data-component="mgt-windowed-matrix" style="'+grid+'">'+colh;
551
+ ASTER.criteria.forEach(function(c){h2+='<span class="lab">'+c.id+' '+c.slug+'</span>'+winCells(function(tr){return ASTER.cellFor(c.id,tr);});});
552
+ document.getElementById('hmcrit').innerHTML=h2+'</div>';
553
+ }
554
+
555
+ function copyFindingsHandoff(){
556
+ var md=ASTER.handoffMd||'';var btn=document.getElementById('fhbtn');
557
+ function ok(){btn.classList.add('done');btn.textContent='✓ copied';setTimeout(function(){btn.classList.remove('done');btn.textContent='Copy findings handoff (markdown)';},2000);}
558
+ if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(md).then(ok,function(){fbc(md);});}else{fbc(md);}
559
+ function fbc(t){var x=document.createElement('textarea');x.value=t;document.body.appendChild(x);x.select();
560
+ try{document.execCommand('copy');}catch(e){}document.body.removeChild(x);ok();}
561
+ }
562
+ function gotoTrace(id){
563
+ tab(1);openTrace=id;renderLedger();renderWalk();
564
+ var el=document.getElementById('feedcell');
565
+ if(el)el.scrollIntoView({behavior:'smooth',block:'start'});
566
+ }
567
+ renderProf();renderSuite();renderLedger();renderWalk();renderHm();
568
+ /* deep-link: eval-report-mock.html#tr-005 opens that trace's walk (used by discovery peek) */
569
+ if(location.hash&&location.hash.indexOf('#tr-')===0){gotoTrace(location.hash.slice(1));}
570
+ function setProf(v,btn){profStyle=v;vqOn(btn);renderProf();}
571
+ function vqOn(btn){btn.parentElement.querySelectorAll('button').forEach(function(b){b.classList.remove('on');});btn.classList.add('on');}
572
+ (function(){
573
+ var btn=document.getElementById('fbcopy'),ta=document.getElementById('fbtext');
574
+ if(!btn||!ta)return;
575
+ function buildMd(){
576
+ var lines=['## Feedback — '+(ASTER.feedbackTitle||document.title),'','Artifact: `'+(ASTER.artifactPath||'evaluation-report.html')+'`'];
577
+ document.querySelectorAll('.vq').forEach(function(vq){
578
+ var on=vq.querySelector('button.on');
579
+ lines.push('- **'+vq.getAttribute('data-vq')+'**: '+(on?on.getAttribute('data-v'):'(none)'));
580
+ });
581
+ lines.push('','### Notes');
582
+ var note=ta.value.trim();lines.push(note.length?note:'_(no notes entered)_');
583
+ return lines.join('\n');
584
+ }
585
+ function done(){btn.classList.add('done');btn.textContent='Copied ✓';setTimeout(function(){btn.classList.remove('done');btn.textContent='Copy MD';},1800);}
586
+ btn.addEventListener('click',function(){
587
+ var md=buildMd();
588
+ if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(md).then(done,function(){fb(md);});}else{fb(md);}
589
+ function fb(t){var x=document.createElement('textarea');x.value=t;document.body.appendChild(x);x.select();
590
+ try{document.execCommand('copy');}catch(e){}document.body.removeChild(x);done();}
591
+ });
592
+ })();
593
+ </script>
594
+ </body></html>