/** * Durable docflow observation record (ADR 0016 rule 2). * * An observation is one authored-node invocation recorded on the same durable * wire receipts use (the runtime receipt gateway) into the scheduler schema's * `observations` table. It is keyed like a receipt — org/run scope proven by the * executor token, fenced by the per-attempt authority — plus the node id and the * wrapper's per-attempt invocation sequence. * * Observations are a projection of the live `docflow.node.*` execution events * onto durable storage; the wrapper still emits those events for live streaming. * They carry only BOUNDED input/output previews (per `docflow-node-io`), never * per-row map truth — maps observe at the node level while per-row outcomes live * in the sheets. */ import type { PlayDocflowNodeIoPreviewMap } from './docflow-node-io'; export type DocflowObservationStatus = 'started' | 'completed' | 'failed'; /** * A single upsert of one node invocation's state. The gateway upserts on * (run_id, attempt, node_id, invocation_seq); a later `completed`/`failed` * write for the same key supersedes an earlier `started` (status precedence * started < completed/failed, never regressing to `started`). */ export type DocflowObservationUpsert = { runId: string; attempt: number; nodeId: string; invocationSeq: number; invocationId?: string | null; status: DocflowObservationStatus; inputs?: PlayDocflowNodeIoPreviewMap | null; outputs?: PlayDocflowNodeIoPreviewMap | null; inputsTruncated?: boolean; outputsTruncated?: boolean; error?: string | null; /** Epoch ms; started writes carry it, terminal writes carry a settled ts. */ at: number; }; /** A durable observation row read back for terminal ledger reconciliation. */ export type DocflowObservationRecord = { runId: string; attempt: number; nodeId: string; invocationSeq: number; invocationId: string | null; status: DocflowObservationStatus; inputs: PlayDocflowNodeIoPreviewMap | null; outputs: PlayDocflowNodeIoPreviewMap | null; inputsTruncated: boolean; outputsTruncated: boolean; error: string | null; startedAt: number | null; settledAt: number | null; }; /** Numeric precedence so a late `started` never clobbers a settled write. */ export function docflowObservationStatusRank( status: DocflowObservationStatus, ): number { return status === 'started' ? 0 : 1; }