fix: her evidence comes from the trace, not from a form field
Case 58325 died submitting findings: the submit_decision call arrived with no `data` at all. The final model reply was exactly 4,096 output tokens — the service's cap — so the JSON was cut off mid-call. Asking Ava to paste 16 full SQL statements into sql_log, on top of a summary, root cause, five recommendations and a scanned-summary, is what pushed one tool call past the limit and lost the whole investigation. The platform already records every statement the agentic tool sends, verbatim, with Databricks' own SUCCEEDED/FAILED and the row count. So SqlEvidence now renders from the trace and treats sql_log as a one-line index per step. Her charter gained hard per-field character limits to match (sm2/custom-apps/denials-investigator/05_ai_employee.sql). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
e294df6eba
commit
92ea27d27e
@ -1,7 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { AlertTriangle, CheckCircle2, ChevronDown, FileSearch } from 'lucide-react';
|
||||
import { Badge, Card, Facts } from './core';
|
||||
import type { Row } from '../api/types';
|
||||
import type { AvaTraceStep, Row } from '../api/types';
|
||||
import {
|
||||
firstDeadline,
|
||||
headline,
|
||||
@ -148,11 +148,22 @@ export function FullStory({ row }: { row: Row }) {
|
||||
);
|
||||
}
|
||||
|
||||
/** Every SQL statement she ran. For the sceptic in the room. Collapsed. */
|
||||
export function SqlEvidence({ row }: { row: Row }) {
|
||||
/**
|
||||
* Every SQL statement she ran. For the sceptic in the room. Collapsed.
|
||||
*
|
||||
* SOURCE OF TRUTH IS THE TRACE, not her sql_log field. The platform records
|
||||
* every statement the agentic tool sent, verbatim, with Databricks' own
|
||||
* SUCCEEDED/FAILED and the row count — so that is what is shown. Her sql_log
|
||||
* is now a one-line-per-step index ("3c: department cut -> Cardiology +13
|
||||
* pts") and is used only as the note beside each statement. Asking her to
|
||||
* paste 16 full queries into a form field was what blew the tool call past
|
||||
* the output cap and lost a whole investigation.
|
||||
*/
|
||||
export function SqlEvidence({ row, steps }: { row: Row; steps: AvaTraceStep[] }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const steps = sqlSteps(row.sql_log);
|
||||
if (steps.length === 0) return null;
|
||||
const queries = steps.filter((s) => s.type === 'api' && s.detail);
|
||||
const notes = sqlSteps(row.sql_log);
|
||||
if (queries.length === 0 && notes.length === 0) return null;
|
||||
|
||||
return (
|
||||
<Disclosure
|
||||
@ -160,19 +171,40 @@ export function SqlEvidence({ row }: { row: Row }) {
|
||||
onToggle={() => setOpen(!open)}
|
||||
icon={<CheckCircle2 className="h-4 w-4 text-good" />}
|
||||
title="Her evidence"
|
||||
hint={`${steps.length} database queries, exactly as she ran them — anyone can re-run these`}
|
||||
hint={
|
||||
queries.length
|
||||
? `${queries.length} database queries, exactly as she ran them — anyone can re-run these`
|
||||
: `${notes.length} steps, in her own words`
|
||||
}
|
||||
>
|
||||
<ol className="divide-y divide-line">
|
||||
{steps.map((s, i) => (
|
||||
<li key={i} className="px-5 py-3">
|
||||
{s.label && (
|
||||
<p className="text-[11px] font-semibold tracking-wide text-faint uppercase">{s.label}</p>
|
||||
)}
|
||||
<pre className="sql mt-1 text-muted">{s.sql}</pre>
|
||||
{s.note && <p className="mt-1.5 text-xs text-ink">{s.note}</p>}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
{queries.length > 0 ? (
|
||||
<ol className="divide-y divide-line">
|
||||
{queries.map((q, i) => (
|
||||
<li key={`${q.seq}-${i}`} className="px-5 py-3">
|
||||
<p className="flex items-center gap-2 text-[11px] font-semibold tracking-wide text-faint uppercase">
|
||||
Query {i + 1}
|
||||
{q.query_state === 'FAILED' ? (
|
||||
<Badge tone="amber">error — corrected next</Badge>
|
||||
) : q.rows_returned != null ? (
|
||||
<span className="tnum font-normal normal-case">{q.rows_returned} row{q.rows_returned === 1 ? '' : 's'}</span>
|
||||
) : null}
|
||||
</p>
|
||||
<pre className="sql mt-1 text-muted">{q.detail}</pre>
|
||||
{notes[i]?.note && <p className="mt-1.5 text-xs text-ink">{notes[i].note}</p>}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
) : (
|
||||
<ol className="divide-y divide-line">
|
||||
{notes.map((s, i) => (
|
||||
<li key={i} className="px-5 py-3">
|
||||
{s.label && <p className="text-[11px] font-semibold tracking-wide text-faint uppercase">{s.label}</p>}
|
||||
<p className="mt-1 text-sm text-ink">{s.sql}</p>
|
||||
{s.note && <p className="mt-1 text-xs text-muted">{s.note}</p>}
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
)}
|
||||
</Disclosure>
|
||||
);
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ export function CaseScreen() {
|
||||
{hasFindings && (
|
||||
<>
|
||||
<FullStory row={row} />
|
||||
<SqlEvidence row={row} />
|
||||
<SqlEvidence row={row} steps={trace.data ?? []} />
|
||||
{!aiOwned && (
|
||||
<Disclosure
|
||||
open={showWork}
|
||||
@ -185,7 +185,7 @@ export function CaseScreen() {
|
||||
)}
|
||||
{quiet && (
|
||||
<>
|
||||
<SqlEvidence row={row} />
|
||||
<SqlEvidence row={row} steps={trace.data ?? []} />
|
||||
<Disclosure
|
||||
open={showWork}
|
||||
onToggle={() => setShowWork(!showWork)}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user