/** * ExecutionRuntime — The runtime environment for one flowchart execution. * * Wires up the three memory primitives into a single container: * - SharedMemory (the heap — shared state across all stages) * - StageContext (the call stack — per-stage execution tree) * - EventLog (the transaction log — commit history for replay) * * The engine (FlowchartTraverser) receives this as its runtime parameter. * After execution, consumers query it for the full execution state. */ import { EventLog } from '../memory/EventLog.js'; import { SharedMemory } from '../memory/SharedMemory.js'; import { StageContext } from '../memory/StageContext.js'; import type { CommitBundle, CommitValuesMode, ReadTrackingMode, StageSnapshot, WriteTrackingMode } from '../memory/types.js'; import type { ObserverStats } from './DeferredObserverTier.js'; /** Snapshot of a single recorder's collected data. */ export interface RecorderSnapshot { id: string; name: string; /** ScopeRecorder type and pattern description (e.g., "Translator (KeyedStore) — per-step token usage"). */ description?: string; /** Preferred read-time operation — hints the UI about which view to show prominently. */ preferredOperation?: 'translate' | 'accumulate' | 'aggregate'; data: unknown; } export type RuntimeSnapshot = { sharedState: Record; executionTree: StageSnapshot; commitLog: CommitBundle[]; /** * Encoding discriminant for `commitLog` (#13c-B): `'full'` — every `set` * bundle stores the full final value (historical); `'delta'` — bundles may * carry `append`/`delete` trace verbs with verb-qualified `overwrite` * payloads (tails). Offline tooling keys on this field; a bundle stream * without context remains self-describing via the verbs themselves. */ commitValues: CommitValuesMode; /** * Per-subflow execution results, DUAL-KEYED (design: docs/design/subflow-commit-visibility.md): * - by subflow PATH (`subflowId`, e.g. `'sf-pay'`) → the LAST iteration (back-compat); this * is what `getSubtreeSnapshot(path)` and `listSubflowPaths()` resolve. * - by per-execution mount `runtimeStageId` (e.g. `'sf-pay#5'`) → THAT iteration's result, so * a LOOPING subflow retains EVERY iteration (not just the last). Look up a specific * iteration as `subflowResults[node.runtimeStageId] ?? subflowResults[node.subflowId]`. * Both keys point at the same object for a single mount; iterate with care (count via the * path keys — those without `'#'`). The pause checkpoint carries only the path keys, lean. */ subflowResults?: Record; /** Snapshot data from recorders that implement toSnapshot(). */ recorders?: RecorderSnapshot[]; /** * Deferred-observer accounting (RFC-001 Block 9) — queue depth, drops, * flush/budget counters, per-listener time attribution, and the * terminal-flush stranding count. ABSENT unless a recorder was attached * with `{ delivery: 'deferred' }` on this executor (zero-cost discipline). */ observerStats?: ObserverStats; }; export declare class ExecutionRuntime { globalStore: SharedMemory; /** * Parallel redacted mirror of `globalStore`. Populated during traversal via * `StageContext.commit()` using the already-computed redacted patches. * Only exists when `enableRedactedMirror()` has been called — typically by * `FlowChartExecutor` when a `RedactionPolicy` is configured. Otherwise * undefined and zero cost. * * Read via `getSnapshot({ redact: true })`. */ redactedStore?: SharedMemory; rootStageContext: StageContext; executionHistory: EventLog; /** Original root for getSnapshot() — set before resume changes rootStageContext. */ private _snapshotRoot?; private _initialState; private _defaultValues; /** Active commit-values encoding (#13c-B) — surfaced as the snapshot * discriminant {@link RuntimeSnapshot.commitValues}. */ private commitValues; constructor(rootName: string, rootId: string, defaultValues?: unknown, initialState?: unknown); /** * Opt in to maintaining a parallel redacted mirror of `globalStore`. After * this call, every `StageContext.commit()` in the run writes the redacted * patches (the same ones fed to the event log) into `redactedStore` in * addition to the raw ones written to `globalStore`. * * The mirror is created lazily and propagated into all child / next * contexts, so it correctly reflects subflow-scope writes. When no * `RedactionPolicy` is configured, callers should skip this — unused * allocation, no functional difference in the snapshot. */ enableRedactedMirror(): void; /** * Set the read-tracking policy (#14) on the root stage context. Descendant * contexts inherit via `createNext`/`createChild`; subflow root contexts * inherit from their parent-mount context via `SubflowExecutor`. Called by * `FlowChartExecutor.createTraverser()` when the executor's policy is not * the default `'full'` — including the resume path, where it is applied to * the freshly-created continuation root. */ useReadTracking(mode: ReadTrackingMode): void; /** * Set the write-tracking policy (#13c-A) on the root stage context — the * sibling of {@link useReadTracking}, with identical plumbing: descendant * contexts inherit via `createNext`/`createChild`; subflow root contexts * inherit from their parent-mount context via `SubflowExecutor`. Called by * `FlowChartExecutor.createTraverser()` when the executor's policy is not * the default `'full'` — including the resume path, where it is applied to * the freshly-created continuation root. */ useWriteTracking(mode: WriteTrackingMode): void; /** * Set the commit-values encoding policy (#13c-B) on the root stage context * — the third dial of the {@link useReadTracking}/{@link useWriteTracking} * family, with identical plumbing: descendant contexts inherit via * `createNext`/`createChild`; subflow root contexts inherit from their * parent-mount context via `SubflowExecutor`. Called by * `FlowChartExecutor.createTraverser()` when the executor's policy is not * the default `'full'` — including the resume path, where it is applied to * the freshly-created continuation root. */ useCommitValues(mode: CommitValuesMode): void; /** Preserve the current rootStageContext for snapshots before changing it for resume. */ preserveSnapshotRoot(): void; getPipelines(): string[]; setRootObject(path: string[], key: string, value: unknown): void; /** * Return the runtime snapshot. * * @param options.redact When `true`, returns `sharedState` from the * parallel redacted mirror (if one was enabled). This is the safe view * for sharing traces externally — paste into a viewer, ship to support, * etc. When the mirror was never enabled, falls back to raw `globalStore` * and a dev-mode warning is emitted (silent in production). * * Default `false` preserves the runtime view — necessary for pause / * resume (resumption must replay against the real values, not * '[REDACTED]'). * * Other fields (`executionTree`, `commitLog`) are the same either way — * the commit log is already redacted at write-time, and the execution * tree only carries structural metadata. */ getSnapshot(options?: { redact?: boolean; }): RuntimeSnapshot; }