/** Launch decision panel: policy outcome banner, the deterministic matrix row * that fired, option cards with expected loss + hard-constraint feasibility, * the human-review form, and the audit trail viewer. */ import { useState } from 'react'; import Alert from '@mui/material/Alert'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Chip from '@mui/material/Chip'; import MenuItem from '@mui/material/MenuItem'; import Paper from '@mui/material/Paper'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; import type { AuditRecord, HumanReviewDecision, PolicyEvaluation, } from '../../types/agentic'; import { submitHumanReview } from '../../services/agentic'; import { fmtRate, KV, OUTCOME_STYLE, PanelTitle, SeverityChip } from './common'; const OPTION_TITLES: Record = { STOP_SHIP: 'Stop Ship', OPTION_A_DELAY: 'Option A — Delay Launch', OPTION_B_MITIGATION: 'Option B — Ship w/ Mitigation', OPTION_C_REDUCED_ODD: 'Option C — Reduced ODD', EXPAND_EVALUATION: 'Expand Evaluation', HUMAN_SAFETY_REVIEW: 'Human Safety Review', PROCEED: 'Proceed', }; const DECISIONS = [ 'confirm_failure', 'reject_failure', 'approve_option', 'approve_launch', 'block_launch', 'request_more_evidence', ]; export default function DecisionPanel({ failureId, evaluation, decisions, audit, auditValid, onReviewed, }: { failureId: string; evaluation: PolicyEvaluation; decisions: HumanReviewDecision[]; audit: AuditRecord[]; auditValid: boolean | null; onReviewed: () => void; }) { const [reviewer, setReviewer] = useState(''); const [decision, setDecision] = useState('confirm_failure'); const [rationale, setRationale] = useState(''); const [overrideReason, setOverrideReason] = useState(''); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); const [showAudit, setShowAudit] = useState(false); const style = OUTCOME_STYLE[evaluation.outcome]; const row = evaluation.matrix_row_fired; const submit = async () => { setSubmitting(true); setError(null); try { await submitHumanReview(failureId, { reviewer, decision, rationale, approved_option: decision === 'approve_option' ? evaluation.recommended_option : null, evidence_reviewed: ['evidence_graph', 'statistical_assessment', 'policy_evaluation'], override_reason: overrideReason || null, }); setRationale(''); onReviewed(); } catch (e) { setError((e as Error).message); } finally { setSubmitting(false); } }; return ( {/* outcome banner */} {style.label} {(evaluation.severity_assignment?.taxonomy_description ?? '') + (evaluation.automatic_stop_ship_condition ? ` · pre-authorized stop-ship condition ${evaluation.automatic_stop_ship_condition.condition_id} fired` : '')} {evaluation.indeterminate_reasons?.length ? ( Fail-safe reasons: {evaluation.indeterminate_reasons.join('; ')} ) : null} {/* matrix row */} {row ? ( ) : null} {/* option cards */} Expected loss is reported for every option, but SAFETY IS A HARD CONSTRAINT: options whose residual failure rate violates the policy limit are excluded from selection no matter how cheap they are. {evaluation.expected_loss_table.map((o) => { const recommended = o.option === evaluation.recommended_option; return ( {OPTION_TITLES[o.option] ?? o.option} {recommended ? ( ) : null} {!o.feasible ? ( ) : null} expected loss {o.expected_loss.toLocaleString()} residual rate {fmtRate(o.residual_failure_rate)} business cost {o.business_cost.toLocaleString()} {o.infeasible_reason ? ( {o.infeasible_reason} ) : null} ); })} {evaluation.option_c_evaluation && !evaluation.option_c_evaluation.feasible ? ( Option C (reduced ODD) rejected checks: {evaluation.option_c_evaluation.checks .filter((c) => !c.passed) .map((c) => ( ✗ {c.check} — {c.detail} ))} ) : null} {/* mandatory triggers */} {evaluation.mandatory_review_triggers?.some((t) => t.fired) ? ( Mandatory human review triggers fired:{' '} {evaluation.mandatory_review_triggers .filter((t) => t.fired) .map((t) => t.trigger) .join(', ')} ) : null} {/* human review form */} No agent output authorizes a launch. Authorization = deterministic policy outcome above + this recorded human decision (against policy {evaluation.policy_version}). setReviewer(e.target.value)} sx={{ width: 180 }} /> setDecision(e.target.value)} sx={{ width: 210 }}> {DECISIONS.map((d) => ( {d.replace(/_/g, ' ')} ))} setRationale(e.target.value)} sx={{ flex: 1, minWidth: 260 }} multiline /> setOverrideReason(e.target.value)} sx={{ minWidth: 260 }} /> {error ? ( {error} ) : null} {decisions.length > 0 ? ( {decisions.map((d) => ( {d.reviewer} — {d.decision.replace(/_/g, ' ')} {d.approved_option ? ` (${d.approved_option})` : ''} · {d.timestamp} · policy{' '} {d.policy_version || '—'} {d.override_reason ? ` · OVERRIDE: ${d.override_reason}` : ''} — “{d.rationale}” ))} ) : null} {/* audit trail */} {auditValid !== null ? ( ) : null} } /> {showAudit ? ( {audit.map((r) => ( #{r.seq} [{r.timestamp}] {r.event_type} · {r.actor} · {r.detail}{' '} ({r.prev_hash} → {r.hash}) ))} ) : null} ); }