feat: render workflow receipt evidence rows

This commit is contained in:
732642856
2026-07-21 16:56:20 +08:00
parent d6726e849d
commit 9db00c6d33
5 changed files with 54 additions and 4 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ export function ChatMessageRow({ message }: { readonly message: ChatMessageView
{message.role === "assistant" ? (
message.state === "thinking"
? <div className="thinking"><i /><i /><i /></div>
: <><ClaimBoundaryBadge status={message.techniqueTruth} /><EvidenceAuditPanel claimStatus={message.techniqueTruth} /><ChatMessageContent text={message.text} /></>
: <><ClaimBoundaryBadge status={message.techniqueTruth} /><EvidenceAuditPanel claimStatus={message.techniqueTruth} workflowReceipt={message.workflowReceipt} /><ChatMessageContent text={message.text} /></>
) : <p>{message.text}</p>}
</div>
</div>
@@ -4,6 +4,13 @@ type AuditRow = {
boundary: string;
};
type WorkflowReceipt = {
route: string;
status: string;
preciseTiming: string;
missingLayers: readonly string[];
};
const defaultAuditRows: AuditRow[] = [
{ label: "D1 / Natal", status: "required", boundary: "基础命盘层" },
{ label: "Varga: D9 / D10 / D2 / D11", status: "required", boundary: "按问题域调用,不混用" },
@@ -15,12 +22,27 @@ const defaultAuditRows: AuditRow[] = [
{ label: "MEVG / Real Case Calibration", status: "blocked", boundary: "外部校准不足时降级" },
];
export function EvidenceAuditPanel({ claimStatus }: { readonly claimStatus?: string }) {
function workflowRows(receipt?: WorkflowReceipt): AuditRow[] {
if (!receipt) return defaultAuditRows;
return [
{ label: `Workflow route: ${receipt.route}`, status: receipt.status === "blocked" ? "blocked" : "required", boundary: "后端实际路由" },
{ label: `Precise timing: ${receipt.preciseTiming}`, status: receipt.preciseTiming === "allowed" ? "partial" : "blocked", boundary: "精确应期 claim gate" },
{
label: "Missing route layers",
status: receipt.missingLayers.length ? "blocked" : "required",
boundary: receipt.missingLayers.length ? receipt.missingLayers.join(" / ") : "none",
},
...defaultAuditRows,
];
}
export function EvidenceAuditPanel({ claimStatus, workflowReceipt }: { readonly claimStatus?: string; readonly workflowReceipt?: WorkflowReceipt }) {
const rows = workflowRows(workflowReceipt);
return (
<details className="evidence-audit-panel">
<summary> · {claimStatus || "unknown"}</summary>
<div className="evidence-audit-table" role="table" aria-label="Technique Audit Table">
{defaultAuditRows.map((row) => (
{rows.map((row) => (
<div className="evidence-audit-row" role="row" key={row.label}>
<span role="cell">{row.label}</span>
<b role="cell" data-status={row.status}>{row.status}</b>