@@ -56,7 +56,7 @@ <h4 class="text-xs font-semibold text-gray-400 uppercase tracking-wide">Determin
5656 < div class ="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-2.5 ">
5757 {% for f in rep.agentic_findings %}
5858 < details class ="agentic-finding-card min-w-0 rounded-lg border px-3 py-2.5 {% if f.status == 'FAIL' or f.status == 'ERROR' %}border-red-900/50 bg-red-950/20{% elif f.status == 'INCONCLUSIVE' %}border-amber-900/50 bg-amber-950/10{% else %}border-gray-800 bg-surface-overlay/30{% endif %} " data-severity ="{{ f.severity }} " data-status ="{{ f.status }} ">
59- < summary class ="cursor-pointer select-none list-none ">
59+ < summary class ="cursor-pointer select-none list-none [&::-webkit-details-marker]:hidden ">
6060 < div class ="flex items-center gap-2 min-w-0 ">
6161 < span class ="shrink-0 px-1.5 py-0.5 rounded text-[10px] font-semibold {% if f.status == 'PASS' %}bg-emerald-900/40 text-emerald-300{% elif f.status == 'INCONCLUSIVE' %}bg-amber-900/40 text-amber-300{% else %}bg-red-900/40 text-red-300{% endif %} "> {{ f.status }}</ span >
6262 {% if f.severity %}< span class ="shrink-0 px-1.5 py-0.5 rounded text-[10px] uppercase tracking-wide {% if f.severity == 'critical' %}bg-red-950 text-red-300{% elif f.severity == 'high' %}bg-orange-950 text-orange-300{% elif f.severity == 'medium' %}bg-amber-950 text-amber-300{% else %}bg-gray-800 text-gray-400{% endif %} "> {{ f.severity }}</ span > {% endif %}
@@ -91,13 +91,17 @@ <h4 class="text-xs font-semibold text-gray-400 uppercase tracking-wide">Determin
9191 {% endif %}
9292 < div class ="space-y-1.5 ">
9393 {% for check in rep.agentic.checks %}
94+ {% if check.expected or check.observed or check.evidence_span_ids %}
9495 < details class ="rounded bg-surface-overlay/50 px-3 py-2 ">
95- < summary class ="cursor-pointer text-xs text-gray-300 "> < span class ="mr-2 {% if check.status == 'PASS' %}text-emerald-400{% elif check.status == 'INCONCLUSIVE' %}text-amber-400{% else %}text-red-400{% endif %} "> {{ check.status }}</ span > {{ check.id }} — {{ check.summary }}</ summary >
96+ < summary class ="cursor-pointer text-xs text-gray-300 "> < span class ="mr-2 {% if check.status == 'PASS' %}text-emerald-400{% elif check.status == 'INCONCLUSIVE' %}text-amber-400{% else %}text-red-400{% endif %} "> {{ check.status }}</ span > {{ check.id }} — {{ check.summary }}</ summary >
9697 {% if check.expected or check.observed %}< div class ="mt-2 text-[11px] text-gray-500 "> Expected: {{ check.expected|default:'—' }} · Observed: {{ check.observed|default:'—' }}</ div > {% endif %}
9798 {% if check.evidence_span_ids %}< div class ="mt-1 text-[11px] text-gray-500 "> Evidence spans:
98- {% for span_id in check.evidence_span_ids %}< a class ="text-violet-300 hover:text-violet-200 underline " href ="#trace-span-{{ rep.index }}-{{ span_id }} "> {{ span_id }}</ a > {% if not forloop.last %}, {% endif %}{% endfor %}
99+ {% for sp in check.evidence_spans %}< a class ="text-violet-300 hover:text-violet-200 underline " href ="#trace-span-{{ rep.index }}-{{ sp.id }} "> {{ sp.label }}</ a > {% if not forloop.last %}, {% endif %}{% endfor %}
99100 </ div > {% endif %}
100101 </ details >
102+ {% else %}
103+ < div class ="rounded bg-surface-overlay/50 px-3 py-2 text-xs text-gray-300 "> < span class ="mr-2 {% if check.status == 'PASS' %}text-emerald-400{% elif check.status == 'INCONCLUSIVE' %}text-amber-400{% else %}text-red-400{% endif %} "> {{ check.status }}</ span > {{ check.id }} — {{ check.summary }}</ div >
104+ {% endif %}
101105 {% endfor %}
102106
103107 {% if rep.agentic_judge %}
@@ -211,78 +215,6 @@ <h3 class="text-sm font-semibold text-gray-300 mb-2">Judge rationale</h3>
211215 </ div >
212216 {% endif %}
213217
214- {% if rep.trace %}
215- < details class ="bg-surface-raised rounded-xl border border-violet-900/40 p-4 group ">
216- < summary class ="flex cursor-pointer select-none flex-wrap items-center gap-3 ">
217- < h3 class ="text-sm font-semibold text-violet-300 "> Target trace</ h3 >
218- < span class ="text-xs text-gray-500 "> {{ rep.trace.spans|length }} span{{ rep.trace.spans|length|pluralize }} exported under {{ rep.trace.trace_ids|length }} trace{{ rep.trace.trace_ids|length|pluralize }}</ span >
219- < span class ="text-[10px] text-gray-600 group-open:hidden "> click to expand</ span >
220- </ summary >
221- < div class ="mt-3 ">
222- {% if rep.trace.spans %}
223- {% if rep.trace.trace_ids %}
224- < div class ="flex flex-wrap gap-1.5 mb-3 ">
225- {% for tid in rep.trace.trace_ids %}
226- < code class ="px-1.5 py-0.5 rounded bg-surface-overlay/70 border border-gray-800 text-[11px] text-gray-300 " title ="{{ tid }} "> {{ tid|slice:":12" }}…</ code >
227- {% endfor %}
228- </ div >
229- {% endif %}
230- < ul class ="space-y-1.5 ">
231- {% for s in rep.trace.spans %}
232- < li class ="scroll-mt-4 ">
233- < details class ="rounded border border-gray-800/70 bg-surface-overlay/40 ">
234- < summary id ="trace-span-{{ rep.index }}-{{ s.span_id }} " class ="flex cursor-pointer select-none items-center gap-2 px-2 py-1.5 text-sm ">
235- < span class ="shrink-0 px-1.5 py-0.5 rounded bg-surface-overlay/60 border border-gray-800 text-[10px] uppercase tracking-wide {% if s.kind == 'LLM' %}text-sky-300{% elif s.kind == 'RETRIEVER' %}text-emerald-300{% elif s.kind == 'TOOL' %}text-amber-300{% elif s.kind == 'AGENT' %}text-fuchsia-300{% elif s.kind == 'GUARDRAIL' %}text-fuchsia-300{% elif s.kind == 'EVALUATOR' %}text-fuchsia-300{% elif s.kind == 'SPAN_KIND_SERVER' %}text-violet-300{% elif s.kind == 'SPAN_KIND_CLIENT' %}text-cyan-300{% elif s.kind == 'SPAN_KIND_INTERNAL' %}text-gray-400{% elif s.kind == 'CHAIN' %}text-gray-400{% else %}text-gray-300{% endif %} " title ="{{ s.kind }} "> {{ s.kind }}</ span >
236- < span class ="text-gray-200 truncate " title ="{{ s.name }} "> {{ s.name }}</ span >
237- {% if s.attributes.tool_name %}< span class ="text-gray-500 text-xs truncate " title ="{{ s.attributes.tool_name }} "> · {{ s.attributes.tool_name }}</ span > {% endif %}
238- < span class ="shrink-0 ml-auto flex items-center gap-2 text-[11px] text-gray-500 tabular-nums ">
239- {% if s.offset_ms is not None %}< span title ="ms after the first span in this trace "> +{{ s.offset_ms }} ms</ span > {% endif %}
240- {% if s.dur_ms > 0 %}< span > {{ s.dur_ms }} ms</ span > {% endif %}
241- </ span >
242- </ summary >
243- {% if s.content_blocks or s.attributes %}
244- < div class ="space-y-2 border-t border-gray-800/70 px-3 py-2 ">
245- {% for label, value in s.content_blocks %}
246- < div >
247- < p class ="mb-1 text-[10px] uppercase tracking-wide text-gray-500 "> {{ label }}</ p >
248- < pre class ="max-h-56 overflow-auto whitespace-pre-wrap break-words rounded bg-surface p-2 text-[11px] text-gray-300 "> {{ value }}</ pre >
249- </ div >
250- {% endfor %}
251- < details >
252- < summary class ="cursor-pointer select-none text-[10px] uppercase tracking-wide text-gray-500 hover:text-gray-300 "> All attributes ({{ s.attributes|length }})</ summary >
253- < pre class ="mt-1 max-h-64 overflow-auto rounded bg-surface p-2 text-[11px] text-gray-400 "> {{ s.attributes|jsonify }}</ pre >
254- </ details >
255- </ div >
256- {% endif %}
257- </ details >
258- </ li >
259- {% endfor %}
260- </ ul >
261- {% if rep.trace.hidden_spans %}
262- < p class ="mt-2 text-xs text-gray-500 "> + {{ rep.trace.hidden_spans }} more span{{ rep.trace.hidden_spans|pluralize }} (shorter / beyond preview).</ p >
263- {% endif %}
264- < p class ="mt-2 text-[11px] text-gray-600 "> Click a span for its tool arguments / results and raw attributes. Evidence links from the checks above jump to their spans.</ p >
265- < script >
266- // Evidence-link clicks expand the target span's detail (idempotent: the
267- // panel is included once per repetition on the same page).
268- ( function ( ) {
269- if ( window . __traceSpanExpandBound ) return ;
270- window . __traceSpanExpandBound = true ;
271- document . addEventListener ( 'click' , function ( e ) {
272- var a = e . target . closest ? e . target . closest ( 'a[href^="#trace-span-"]' ) : null ;
273- if ( ! a ) return ;
274- var el = document . getElementById ( a . getAttribute ( 'href' ) . slice ( 1 ) ) ;
275- var d = el && el . closest ? el . closest ( 'details' ) : null ;
276- if ( d ) d . open = true ;
277- } ) ;
278- } ) ( ) ;
279- </ script >
280- {% else %}
281- < p class ="text-xs text-gray-500 "> The target exported no spans under this rep's trace{{ rep.trace.trace_ids|length|default:0|pluralize }} (tracing was on; the target's OTel may not be wired for this deployment).</ p >
282- {% endif %}
283- </ div >
284- </ details >
285- {% endif %}
286218
287219 {% include "partials/agentic_timeline.html" %}
288220
0 commit comments