{"version":3,"file":"process-terminal.d.ts","sourceRoot":"","sources":["../../../../src/runs/background/process-terminal.ts"],"names":[],"mappings":"AAGA,OAAO,EAGN,KAAK,qBAAqB,EAE1B,KAAK,iBAAiB,EAEtB,MAAM,uBAAuB,CAAC;AAG/B,MAAM,WAAW,wBAAwB;IACxC,OAAO,EAAE,CAAC,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;IACjD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,+BAA+B,CAAC,EAAE,OAAO,CAAC;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACtC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAsBD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAErE;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE5D;AAMD,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,wBAAwB,GAAG,SAAS,CAoDnG;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,wBAAwB,GAAG,IAAI,CAEzG;AAED,wBAAgB,wCAAwC,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,IAAI,CAIrH;AAwFD,wBAAgB,uBAAuB,CACtC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;CAAE,EAC9D,KAAK,SAAW,GACd,iBAAiB,GAAG,SAAS,CAa/B;AAED,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,uBAAuB,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D,iBAAiB,GAAG,SAAS,CAc/B;AA8DD,wBAAgB,uBAAuB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,sBAAsB,GACjC,iBAAiB,CAyFnB","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { writeAtomicJson, writePrivateAtomicJson } from \"../../shared/atomic-json.ts\";\nimport {\n\ttype AsyncStatus,\n\ttype CanonicalSessionTerminalV1,\n\ttype ProcessInstanceExitV1,\n\ttype ProcessTerminalReason,\n\ttype ProcessTerminalV1,\n\tSUBAGENT_LIFECYCLE_ARTIFACT_VERSION,\n} from \"../../shared/types.ts\";\nimport { canonicalSessionId, inspectSessionLease } from \"../shared/session-lease.ts\";\n\nexport interface ProcessTerminalCandidate {\n\tversion: 1;\n\trunId: string;\n\trunnerProcessInstanceId: string;\n\twriters: Record<string, ProcessInstanceExitV1[]>;\n\texpectedWriters?: Record<string, number>;\n\tsessionFile?: string;\n\trevivalLeaseToken?: string;\n\trevivalLeaseReleaseAcknowledged?: boolean;\n}\n\nexport interface RunnerCloseObservation {\n\tprocessInstanceId: string;\n\tcloseObservedAt: number;\n\texitCode: number | null;\n\tsignal: string | null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction validProcessInstance(value: unknown, kind?: \"runner\" | \"pi-writer\"): value is ProcessInstanceExitV1 {\n\tif (!isRecord(value)) return false;\n\tif (typeof value.processInstanceId !== \"string\" || value.processInstanceId.length === 0) return false;\n\tif (kind ? value.kind !== kind : value.kind !== \"runner\" && value.kind !== \"pi-writer\") return false;\n\tif (typeof value.closeObservedAt !== \"number\" || !Number.isFinite(value.closeObservedAt)) return false;\n\tif (typeof value.exitCode !== \"number\" && value.exitCode !== null) return false;\n\tif (typeof value.signal !== \"string\" && value.signal !== null) return false;\n\treturn value.kind === \"runner\"\n\t\t? value.attempt === undefined\n\t\t: typeof value.attempt === \"number\" && Number.isInteger(value.attempt) && value.attempt >= 0;\n}\n\nfunction validInstance(value: unknown): value is ProcessInstanceExitV1 {\n\treturn validProcessInstance(value, \"pi-writer\");\n}\n\nexport function processTerminalCandidatePath(asyncDir: string): string {\n\treturn path.join(asyncDir, \"process-terminal-candidate.json\");\n}\n\nexport function processTerminalPath(asyncDir: string): string {\n\treturn path.join(asyncDir, \"process-terminal.json\");\n}\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nexport function readProcessTerminalCandidate(asyncDir: string): ProcessTerminalCandidate | undefined {\n\ttry {\n\t\tconst raw = JSON.parse(fs.readFileSync(processTerminalCandidatePath(asyncDir), \"utf-8\")) as unknown;\n\t\tif (\n\t\t\t!isRecord(raw) ||\n\t\t\traw.version !== 1 ||\n\t\t\ttypeof raw.runId !== \"string\" ||\n\t\t\ttypeof raw.runnerProcessInstanceId !== \"string\" ||\n\t\t\t!isRecord(raw.writers)\n\t\t) {\n\t\t\tthrow new Error(`Invalid process-terminal candidate in '${asyncDir}'.`);\n\t\t}\n\t\tconst writers: Record<string, ProcessInstanceExitV1[]> = {};\n\t\tfor (const [index, entries] of Object.entries(raw.writers)) {\n\t\t\tif (!Array.isArray(entries) || !entries.every(validInstance))\n\t\t\t\tthrow new Error(`Invalid writer process records for child '${index}'.`);\n\t\t\twriters[index] = entries;\n\t\t}\n\t\tlet expectedWriters: Record<string, number> | undefined;\n\t\tif (raw.expectedWriters !== undefined) {\n\t\t\tif (!isRecord(raw.expectedWriters)) throw new Error(\"Invalid expected writer process records.\");\n\t\t\texpectedWriters = {};\n\t\t\tfor (const [index, count] of Object.entries(raw.expectedWriters)) {\n\t\t\t\tif (typeof count !== \"number\" || !Number.isInteger(count) || count < 0)\n\t\t\t\t\tthrow new Error(`Invalid expected writer count for child '${index}'.`);\n\t\t\t\texpectedWriters[index] = count;\n\t\t\t}\n\t\t}\n\t\tif (raw.sessionFile !== undefined && typeof raw.sessionFile !== \"string\")\n\t\t\tthrow new Error(\"Invalid process-terminal candidate sessionFile.\");\n\t\tif (raw.revivalLeaseToken !== undefined && typeof raw.revivalLeaseToken !== \"string\")\n\t\t\tthrow new Error(\"Invalid process-terminal candidate lease token.\");\n\t\tif (raw.revivalLeaseReleaseAcknowledged !== undefined && typeof raw.revivalLeaseReleaseAcknowledged !== \"boolean\")\n\t\t\tthrow new Error(\"Invalid process-terminal lease release acknowledgement.\");\n\t\treturn {\n\t\t\tversion: 1,\n\t\t\trunId: raw.runId,\n\t\t\trunnerProcessInstanceId: raw.runnerProcessInstanceId,\n\t\t\twriters,\n\t\t\t...(expectedWriters ? { expectedWriters } : {}),\n\t\t\t...(typeof raw.sessionFile === \"string\" && raw.sessionFile ? { sessionFile: raw.sessionFile } : {}),\n\t\t\t...(typeof raw.revivalLeaseToken === \"string\" && raw.revivalLeaseToken\n\t\t\t\t? { revivalLeaseToken: raw.revivalLeaseToken }\n\t\t\t\t: {}),\n\t\t\t...(typeof raw.revivalLeaseReleaseAcknowledged === \"boolean\"\n\t\t\t\t? { revivalLeaseReleaseAcknowledged: raw.revivalLeaseReleaseAcknowledged }\n\t\t\t\t: {}),\n\t\t};\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\tthrow error;\n\t}\n}\n\nexport function writeProcessTerminalCandidate(asyncDir: string, candidate: ProcessTerminalCandidate): void {\n\twritePrivateAtomicJson(processTerminalCandidatePath(asyncDir), candidate);\n}\n\nexport function markProcessTerminalCandidateLeaseRelease(asyncDir: string, token: string, acknowledged: boolean): void {\n\tconst candidate = readProcessTerminalCandidate(asyncDir);\n\tif (!candidate || candidate.revivalLeaseToken !== token) return;\n\twriteProcessTerminalCandidate(asyncDir, { ...candidate, revivalLeaseReleaseAcknowledged: acknowledged });\n}\n\nfunction unknownProof(\n\trunId: string,\n\trunnerProcessInstanceId: string,\n\treason: ProcessTerminalReason,\n\tdiagnostic?: string,\n): ProcessTerminalV1 {\n\treturn {\n\t\tversion: 1,\n\t\tstate: \"unknown\",\n\t\trunId,\n\t\trunnerProcessInstanceId,\n\t\treason,\n\t\t...(diagnostic ? { diagnostic } : {}),\n\t};\n}\n\nfunction resumeDisposition(\n\tstate: string | undefined,\n\tsessionFile: string | undefined,\n): \"resumable\" | \"non-resumable\" | \"unavailable\" {\n\tif (state === \"stopped\") return \"non-resumable\";\n\tif (state !== \"complete\" && state !== \"completed\" && state !== \"failed\" && state !== \"paused\") return \"unavailable\";\n\treturn sessionFile && fs.existsSync(sessionFile) ? \"resumable\" : \"unavailable\";\n}\n\nfunction sessionProjection(\n\tcandidate: ProcessTerminalCandidate,\n\tlease: ReturnType<typeof inspectSessionLease>,\n): CanonicalSessionTerminalV1 | undefined {\n\tif (!candidate.sessionFile || lease.state !== \"free\") return undefined;\n\tif (candidate.revivalLeaseToken && candidate.revivalLeaseReleaseAcknowledged !== true) return undefined;\n\treturn {\n\t\tcanonicalSessionId: canonicalSessionId(candidate.sessionFile),\n\t\tleaseDisposition: candidate.revivalLeaseToken ? \"released\" : \"not-held\",\n\t\tfreeAtObservation: true,\n\t\t...(candidate.revivalLeaseToken ? { canonicalSessionLeaseReleased: true } : {}),\n\t};\n}\n\nfunction validateProof(\n\traw: unknown,\n\tasyncDir: string,\n\tfallback?: { runId?: string; runnerProcessInstanceId?: string },\n): raw is ProcessTerminalV1 {\n\tif (\n\t\t!isRecord(raw) ||\n\t\traw.version !== 1 ||\n\t\t![\"pending\", \"observed\", \"unknown\", \"not-started\"].includes(String(raw.state)) ||\n\t\ttypeof raw.runId !== \"string\" ||\n\t\t!raw.runId ||\n\t\ttypeof raw.runnerProcessInstanceId !== \"string\" ||\n\t\t!raw.runnerProcessInstanceId\n\t) {\n\t\tthrow new Error(`Invalid process-terminal proof in '${asyncDir}'.`);\n\t}\n\tif (fallback?.runId && raw.runId !== fallback.runId)\n\t\tthrow new Error(\n\t\t\t`Process-terminal proof in '${asyncDir}' belongs to run '${raw.runId}', expected '${fallback.runId}'.`,\n\t\t);\n\tif (fallback?.runnerProcessInstanceId && raw.runnerProcessInstanceId !== fallback.runnerProcessInstanceId)\n\t\tthrow new Error(\n\t\t\t`Process-terminal proof in '${asyncDir}' belongs to runner '${raw.runnerProcessInstanceId}', expected '${fallback.runnerProcessInstanceId}'.`,\n\t\t);\n\tif (\n\t\traw.instances !== undefined &&\n\t\t(!Array.isArray(raw.instances) || !raw.instances.every((entry) => validProcessInstance(entry)))\n\t) {\n\t\tthrow new Error(`Invalid process-terminal instances in '${asyncDir}'.`);\n\t}\n\tif (raw.state === \"observed\") {\n\t\tif (typeof raw.observedAt !== \"number\" || !Number.isFinite(raw.observedAt))\n\t\t\tthrow new Error(`Observed process-terminal proof in '${asyncDir}' is missing observedAt.`);\n\t\tif (!Array.isArray(raw.instances))\n\t\t\tthrow new Error(`Observed process-terminal proof in '${asyncDir}' is missing instances.`);\n\t\tconst runner = raw.instances.find((entry) => isRecord(entry) && entry.kind === \"runner\");\n\t\tif (!validProcessInstance(runner, \"runner\") || runner.processInstanceId !== raw.runnerProcessInstanceId)\n\t\t\tthrow new Error(`Observed process-terminal proof in '${asyncDir}' has no matching runner instance.`);\n\t}\n\tif (\n\t\traw.resumeDisposition !== undefined &&\n\t\t![\"resumable\", \"non-resumable\", \"unavailable\"].includes(String(raw.resumeDisposition))\n\t)\n\t\tthrow new Error(`Invalid process-terminal resume disposition in '${asyncDir}'.`);\n\treturn true;\n}\n\nexport function sanitizeProcessTerminal(\n\tvalue: unknown,\n\tfallback: { runId?: string; runnerProcessInstanceId?: string },\n\tlabel = \"status\",\n): ProcessTerminalV1 | undefined {\n\tif (value === undefined) return undefined;\n\ttry {\n\t\tvalidateProof(value, label, fallback);\n\t\treturn value as ProcessTerminalV1;\n\t} catch (error) {\n\t\treturn unknownProof(\n\t\t\tfallback.runId ?? label,\n\t\t\tfallback.runnerProcessInstanceId ?? \"unknown\",\n\t\t\t\"proof-write-failed\",\n\t\t\terrorMessage(error),\n\t\t);\n\t}\n}\n\nexport function readProcessTerminal(\n\tasyncDir: string,\n\tfallback?: { runId?: string; runnerProcessInstanceId?: string },\n): ProcessTerminalV1 | undefined {\n\ttry {\n\t\tconst raw = JSON.parse(fs.readFileSync(processTerminalPath(asyncDir), \"utf-8\")) as unknown;\n\t\tvalidateProof(raw, asyncDir, fallback);\n\t\treturn raw as ProcessTerminalV1;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\treturn unknownProof(\n\t\t\tfallback?.runId ?? path.basename(asyncDir),\n\t\t\tfallback?.runnerProcessInstanceId ?? \"unknown\",\n\t\t\t\"proof-write-failed\",\n\t\t\terrorMessage(error),\n\t\t);\n\t}\n}\n\nfunction stepProcessTerminalProof(\n\tproof: ProcessTerminalV1,\n\tchildIndex: number,\n\tstate: ProcessTerminalV1[\"state\"],\n\trecords: ProcessInstanceExitV1[],\n\tresumeDispositionValue: ProcessTerminalV1[\"resumeDisposition\"],\n): ProcessTerminalV1 {\n\tconst base = {\n\t\tversion: 1 as const,\n\t\trunId: proof.runId,\n\t\tchildIndex,\n\t\trunnerProcessInstanceId: proof.runnerProcessInstanceId,\n\t\t...(resumeDispositionValue ? { resumeDisposition: resumeDispositionValue } : {}),\n\t};\n\tif (state === \"observed\") {\n\t\treturn {\n\t\t\t...base,\n\t\t\tstate,\n\t\t\tobservedAt: proof.state === \"observed\" ? proof.observedAt : Date.now(),\n\t\t\tinstances: records,\n\t\t};\n\t}\n\tif (state === \"unknown\") {\n\t\treturn { ...base, state, reason: proof.state === \"unknown\" ? proof.reason : \"writer-close-unverified\" };\n\t}\n\treturn { ...base, state };\n}\n\nfunction overlayStatus(asyncDir: string, proof: ProcessTerminalV1, candidate?: ProcessTerminalCandidate): void {\n\tconst statusPath = path.join(asyncDir, \"status.json\");\n\ttry {\n\t\tconst status = JSON.parse(fs.readFileSync(statusPath, \"utf-8\")) as AsyncStatus;\n\t\tstatus.processTerminal = proof;\n\t\tif (status.steps) {\n\t\t\tfor (const [index, step] of status.steps.entries()) {\n\t\t\t\tconst records = candidate?.writers[String(index)] ?? [];\n\t\t\t\tconst expected = candidate?.expectedWriters?.[String(index)] ?? (records.length > 0 ? records.length : 0);\n\t\t\t\tconst stepState =\n\t\t\t\t\texpected === 0\n\t\t\t\t\t\t? \"not-started\"\n\t\t\t\t\t\t: proof.state === \"observed\" && records.length === expected\n\t\t\t\t\t\t\t? \"observed\"\n\t\t\t\t\t\t\t: proof.state === \"pending\"\n\t\t\t\t\t\t\t\t? \"pending\"\n\t\t\t\t\t\t\t\t: \"unknown\";\n\t\t\t\tstep.processTerminal = stepProcessTerminalProof(\n\t\t\t\t\tproof,\n\t\t\t\t\tindex,\n\t\t\t\t\tstepState,\n\t\t\t\t\trecords,\n\t\t\t\t\tresumeDisposition(step.status, step.sessionFile ?? candidate?.sessionFile),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\twriteAtomicJson(statusPath, status);\n\t} catch {\n\t\t// The proof sidecar remains authoritative when terminal status is unavailable.\n\t}\n}\n\nexport function finalizeProcessTerminal(\n\tasyncDir: string,\n\trunId: string,\n\trunnerClose: RunnerCloseObservation,\n): ProcessTerminalV1 {\n\tconst existing = readProcessTerminal(asyncDir, { runId, runnerProcessInstanceId: runnerClose.processInstanceId });\n\tif (existing && fs.existsSync(processTerminalPath(asyncDir))) {\n\t\tif (\n\t\t\texisting.state === \"observed\" &&\n\t\t\texisting.runId === runId &&\n\t\t\texisting.runnerProcessInstanceId === runnerClose.processInstanceId\n\t\t)\n\t\t\treturn existing;\n\t\tif (existing.state === \"unknown\") return existing;\n\t}\n\tlet proof: ProcessTerminalV1;\n\tlet candidateForOverlay: ProcessTerminalCandidate | undefined;\n\ttry {\n\t\tconst candidate = readProcessTerminalCandidate(asyncDir);\n\t\tcandidateForOverlay = candidate;\n\t\tif (!candidate) proof = unknownProof(runId, runnerClose.processInstanceId, \"runner-candidate-missing\");\n\t\telse if (candidate.runId !== runId || candidate.runnerProcessInstanceId !== runnerClose.processInstanceId)\n\t\t\tproof = unknownProof(runId, runnerClose.processInstanceId, \"runner-instance-mismatch\");\n\t\telse {\n\t\t\tconst allWriters = Object.values(candidate.writers).flat();\n\t\t\tconst status = (() => {\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.parse(fs.readFileSync(path.join(asyncDir, \"status.json\"), \"utf-8\")) as AsyncStatus;\n\t\t\t\t} catch {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t})();\n\t\t\tconst session = candidate.sessionFile ? inspectSessionLease(candidate.sessionFile) : undefined;\n\t\t\tconst writerEntries = Object.entries(candidate.writers);\n\t\t\tconst expectedWriters =\n\t\t\t\tcandidate.expectedWriters ??\n\t\t\t\tObject.fromEntries(writerEntries.map(([index, records]) => [index, records.length]));\n\t\t\tconst expectedEntries = Object.entries(expectedWriters);\n\t\t\tconst expectedIndexes = new Set(expectedEntries.map(([index]) => index));\n\t\t\tconst writerIndexes = new Set(writerEntries.map(([index]) => index));\n\t\t\tconst inconsistentWriters =\n\t\t\t\twriterEntries.some(\n\t\t\t\t\t([index, records]) => !expectedIndexes.has(index) || records.length !== expectedWriters[index],\n\t\t\t\t) || expectedEntries.some(([index, expected]) => !writerIndexes.has(index) && expected !== 0);\n\t\t\tif (session && session.state !== \"free\") {\n\t\t\t\tproof = unknownProof(\n\t\t\t\t\trunId,\n\t\t\t\t\trunnerClose.processInstanceId,\n\t\t\t\t\tsession.state === \"owned\" ? \"canonical-session-lease-active\" : \"canonical-session-unavailable\",\n\t\t\t\t);\n\t\t\t} else if (candidate.revivalLeaseToken && candidate.revivalLeaseReleaseAcknowledged !== true) {\n\t\t\t\tproof = unknownProof(runId, runnerClose.processInstanceId, \"canonical-session-release-unverified\");\n\t\t\t} else if (inconsistentWriters || (allWriters.length === 0 && expectedEntries.length === 0)) {\n\t\t\t\tproof = unknownProof(runId, runnerClose.processInstanceId, \"writer-close-unverified\");\n\t\t\t} else {\n\t\t\t\tconst runner: ProcessInstanceExitV1 = { kind: \"runner\", ...runnerClose };\n\t\t\t\tconst canonicalSession = session && sessionProjection(candidate, session);\n\t\t\t\tproof = {\n\t\t\t\t\tversion: 1,\n\t\t\t\t\tstate: \"observed\",\n\t\t\t\t\trunId,\n\t\t\t\t\trunnerProcessInstanceId: runnerClose.processInstanceId,\n\t\t\t\t\tobservedAt: runnerClose.closeObservedAt,\n\t\t\t\t\tinstances: [runner, ...allWriters],\n\t\t\t\t\tresumeDisposition: resumeDisposition(status?.state, candidate.sessionFile ?? status?.sessionFile),\n\t\t\t\t\t...(canonicalSession ? { canonicalSession } : {}),\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tproof = unknownProof(runId, runnerClose.processInstanceId, \"proof-write-failed\", errorMessage(error));\n\t}\n\tlet durable = false;\n\ttry {\n\t\twriteAtomicJson(processTerminalPath(asyncDir), proof);\n\t\tdurable = true;\n\t\toverlayStatus(asyncDir, proof, candidateForOverlay);\n\t\tfs.appendFileSync(\n\t\t\tpath.join(asyncDir, \"events.jsonl\"),\n\t\t\t`${JSON.stringify({ type: \"subagent.run.process_terminal\", lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION, ts: Date.now(), runId, processTerminal: proof })}\\n`,\n\t\t\t\"utf-8\",\n\t\t);\n\t} catch {\n\t\t// Do not emit a process-terminal event when the proof sidecar was not durable.\n\t}\n\treturn durable\n\t\t? proof\n\t\t: unknownProof(\n\t\t\t\trunId,\n\t\t\t\trunnerClose.processInstanceId,\n\t\t\t\t\"proof-write-failed\",\n\t\t\t\t\"Failed to persist process-terminal proof.\",\n\t\t\t);\n}\n"]}