import { useMutation } from "@tanstack/react-query"; import { ENVIRONMENT_LEASE_POLICIES, WORKSPACE_SOURCE_VERIFICATION_REASONS } from "@paperclipai/shared"; import { issuesApi } from "../api/issues"; import { Button } from "./ui/button"; import { formatDateTime } from "../lib/utils"; function recordedFailure(evidence: Record): string { const recovery = evidence.systemRecovery; if (!recovery || typeof recovery !== "object" || !("failure" in recovery)) return "No recorded system recovery failure."; const failure = recovery.failure; if (!failure || typeof failure !== "object" || !("code" in failure) || typeof failure.code !== "string") return "No recorded system recovery failure."; const detail = "sourceVerification" in failure ? failure.sourceVerification : null; if (!detail || typeof detail !== "object" || !("reason" in detail) || typeof detail.reason !== "string" || !(WORKSPACE_SOURCE_VERIFICATION_REASONS as readonly string[]).includes(detail.reason)) return failure.code; const policy = "observedLeasePolicy" in detail ? detail.observedLeasePolicy : null; const allowedPolicy = typeof policy === "string" && (policy === "unrecognized" || (ENVIRONMENT_LEASE_POLICIES as readonly string[]).includes(policy)); return [failure.code, detail.reason, ...(allowedPolicy ? [`lease policy ${policy}`] : [])].join(" · "); } export function RunWorkspaceSourceInspection({ issueId, runId }: { issueId: string; runId: string }) { const listing = useMutation({ mutationFn: () => issuesApi.recoveryActions(issueId, { runId }) }); const inspection = useMutation({ mutationFn: (actionId: string) => issuesApi.recoveryActions(issueId, { runId, actionId }) }); const pending = listing.isPending || inspection.isPending; const error = listing.error ?? inspection.error; const current = inspection.data?.sourceInspection; return (
{error ?

{error instanceof Error ? error.message : "Recovery inspection failed. Try inspecting again."}

: null} {listing.data?.actions.length === 0 ?

No recorded recovery action for this run.

: null} {listing.data?.actions.map(action => (

Recorded failure: {recordedFailure(action.evidence)}

{action.id} · {action.status}

))} {current ?

Current recorded-source identity

Action {current.actionId}

This read-only observation checks recorded identity. It does not confirm provider termination, local files, or successful preservation.

{current.status === "verified" ?

Recorded-source identity verified.

: current.status === "not_inspected" ?

Source not inspected: this record exceeds the inspection limit. Service attention is required.

:

Blocked: {current.sourceVerification?.reason ?? current.failureCode} {current.sourceVerification?.observedLeasePolicy ? <> · lease policy {current.sourceVerification.observedLeasePolicy} : null}

}

Observed {formatDateTime(current.observedAt)}

: null}
); }