import { type StepError } from './step-error.js'; import type { MetaTouch } from './step-meta.js'; /** A `trace_step` row staged in memory, ready to be flushed. */ export interface PendingStep { readonly id: string; readonly traceDay: string; readonly traceId: string; readonly seq: number; readonly parentStepId: string | null; readonly flowStepRef: string; readonly status: 'ok' | 'error'; readonly startedAt: Date; readonly completedAt: Date; readonly durationMicros: bigint; /** * Tier-2 input capture (Q5): one bounded-serialized payload per parameter, * in declaration order. `null` when the transformer emitted no capture * metadata for this step or the `captureInputs` kill-switch is off. */ readonly capturedInputs: readonly unknown[] | null; readonly error: StepError | null; } /** A step that has started but not yet completed — the handle `complete` settles. */ export interface BegunStep { readonly seq: number; readonly stepId: string; readonly parentStepId: string | null; readonly flowStepRef: string; readonly startedAt: Date; readonly startHrTime: bigint; /** Captured at begin time so a mutating impl can't change what the row records. */ readonly capturedInputs: readonly unknown[] | null; /** * `@touches Entity:verb` targets baked into this step's meta. Empty means * no audit projection — the executor takes the vanilla-DML branch and * `__flowStep`'s completion path emits no read-touches audit row. */ readonly touches: readonly MetaTouch[]; /** * Set to true by the executor when it commits a `pipe.*` write under this * step. `__flowStep` reads this at completion to decide whether to emit the * read-touches `audit_record` row (only when `touches.length > 0` and no * write happened). The CTE branch handled the audit itself. */ wroteForAudit: boolean; } /** * The active-step handle the write executor reads to compile its CTE. Captures * everything the `audit_inserts` SELECT needs from the step's runtime context: * the step id and trace id that link the audit row back to the source step, * the partition day, the bounded-serialized captured inputs, and the active * touches. Returned by `StepBuffer.currentStep()` only while a step is open * for audit (touches present); otherwise `null` so the executor falls through * to vanilla DML. */ export interface ActiveAuditStep { readonly traceId: string; readonly traceDay: string; readonly stepId: string; readonly touches: readonly MetaTouch[]; readonly capturedInputs: readonly unknown[] | null; /** Called by the executor right before it returns — flips `wroteForAudit` on the underlying BegunStep. */ markWrote(): void; } export interface StepBufferParams { readonly traceId: string; /** The parent trace's `openedDay` — the partition every step row lands in. */ readonly traceDay: string; /** * The Q7 step cap. The `seq` that first exceeds it trips truncation; * `Infinity` disables the cap (no `structuralMax` resolved yet). */ readonly cap: number; /** * The Q5 input-capture kill-switch, resolved at trace open from * `instance.config.trace.captureInputs`. When `false`, every step in this * trace stages `capturedInputs: null` regardless of what the transformer * emitted — Tier-1 capture is unaffected. */ readonly captureInputs: boolean; } export declare class StepBuffer { private readonly traceId; private readonly traceDay; private readonly cap; readonly captureInputs: boolean; private seq; private currentStepId; /** * The active begun-step at the deepest open nesting level. `__flowStep` * pushes on `begin` and pops on `complete`; the write executor reads the * top of the stack through `currentStep()` to compile its audit CTE. * * The stack pairs with `currentStepId` — both describe step nesting — but * keeps the full `BegunStep` reference so the executor and the read-touches * emitter can reach `touches` and `capturedInputs` without a second lookup. */ private readonly active; private pending; private truncatedAtSeqValue; private truncationDoneValue; constructor(params: StepBufferParams); /** True once the step cap has been blown — the trace records no further steps. */ get truncated(): boolean; /** The `seq` that tripped truncation, for `trace.truncated_at_seq`. */ get truncatedAtSeq(): number | null; /** * Settles when `truncateTrace`'s side effects have landed (flush + status * `UPDATE`). `closeTrace` awaits this before its copy-on-error so the cold * row reflects `truncated_at_seq`. `null` when the trace was never truncated. */ get truncationDone(): Promise | null; /** Records the truncation's settle handle. `truncateTrace` calls this once. */ markTruncationDone(promise: Promise): void; /** * Opens a step: assigns its `seq`, mints its id, and nests it under the step * currently executing. Returns `null` when this step is the one that blows * the cap — the caller runs the implementation untraced from here on. * * `capturedInputs` is the bounded-serialized projection of the step's args * (built by `__flowStep` from `meta.capture`), or `null` for Tier-1-only. * `touches` is the `@touches Entity:verb` set baked into the step's meta, * or empty when the step has no audit projection. */ begin(flowStepRef: string, capturedInputs: readonly unknown[] | null, touches?: readonly MetaTouch[]): BegunStep | null; /** * The active step's audit handle, or `null` when there is no open step or * the open step has no `@touches`. The write executor uses this to decide: * `null` → vanilla DML; non-null → compile the `audit_inserts` CTE. The * returned handle's `markWrote()` flips `wroteForAudit` so `__flowStep` * suppresses the read-touches emission at step completion. */ currentStep(): ActiveAuditStep | null; /** Settles a begun step: stamps its outcome and timing, stages the row, unnests. */ complete(begun: BegunStep, status: 'ok' | 'error', thrown: unknown): void; /** Removes and returns every staged row — the buffer is empty afterwards. */ drain(): PendingStep[]; } //# sourceMappingURL=step-buffer.d.ts.map