import type { Context } from '@deepseek-ai/cordis'; import type { HarnessResolver } from './_shared.ts'; import type { WorkflowAskCache } from './workflow-policy.ts'; /** Logger label for the workflow-ledger consumer (dsh logger naming: `/`). */ export declare const WORKFLOW_LEDGER_LOGGER = "mstar/workflow-ledger"; /** Consumer log levels the module sink understands. */ export type WorkflowLedgerLogLevel = 'debug' | 'warn'; /** Module-level consumer log sink — bound by `apply` to `ctx.logger(WORKFLOW_LEDGER_LOGGER)` (agent-flow ledger precedent). */ export type WorkflowLedgerLogSink = (level: WorkflowLedgerLogLevel, message: string) => void; /** * Bind the consumer log sink (the entry `apply` binds it to * `ctx.logger(WORKFLOW_LEDGER_LOGGER)`). Returns the PRIOR sink so a caller * can restore it (test pattern: agent-flow `setAgentFlowLogger`). */ export declare function setWorkflowLedgerLogger(sink: WorkflowLedgerLogSink): WorkflowLedgerLogSink; /** * One execution target selected by the native workflow/session resolver. The * store identity and epoch are a single selection and travel unchanged to * every event write. `harnessDir` is the control root the target was resolved * in — the session's SELECTED harness (the bind adoption's root), which may * differ from the carrying session's workspace harness: the scan bound and * the event append must act on the store the binding lives in, never on the * workspace root the row was observed from. */ export type WorkflowLedgerTarget = Readonly<{ workflowId: string; workflowDir: string; sessionId: string; storeId: string; epoch: number; harnessDir: string; }>; /** The resolver returns null when this session has no authorized writer. */ export type ResolveWorkflowLedgerTarget = (sessionId: string, cwd: string) => Promise; /** * Test-only drain for the asynchronous resolver route. No production consumer * calls this; tests opt into waiting explicitly rather than selecting it via * process environment. */ export declare function awaitWorkflowLedgerIdle(): Promise; /** * Register the workflow-ledger consumer: (1) a `session/created` backfill * listener (registered FIRST — — so no apply-time window exists * between the snapshot and the attach); (2) a bounded cold scan over * `ctx.sessions.list()` walking each session's `seq` + `eventAt(seq)` log for * `tool-workflow/*` rows (covers pre-restart runs — constructor-seeded * events never hit the firehose, `firstLiveSeq`); (3) a live * `ctx.events.on('session/event', …)` listener filtering the four types. * The native store keeps one per-workflow/session bound keyed by the verified * stream incarnation. `recordWorkflowEvent` atomically accepts identity, * appends its display row, and advances that bound; the consumer reads it to * skip already-covered positions of the same stream. No cursor or identity * sidecar is read or written. Every source operation is contained: failures * leave the row eligible and never alter a workflow run. Missing sessions * service disables this observe-only consumer. * * @param ctx - the plugin's registrant context (the app composition root). * @param resolver - the shared per-workspace `{HARNESS_DIR}` resolver * (harnessDir attribution from the carrying session's `header.cwd`). * @param workflowAskCache - the apply-scoped P-c ask cache (plan * Task 4 fold-in — the host adapter's * instance; see the module doc "P-c answer observation"). Absent → the * observation hook is disabled (W-B2 tests / compositions without the * workflow gate). * @param resolveTarget - the required native execution-target resolver. Every * event uses only the returned selected workflow and original store generation. */ export declare function registerWorkflowLedger(ctx: Context, resolver: HarnessResolver, workflowAskCache: WorkflowAskCache | undefined, resolveTarget: ResolveWorkflowLedgerTarget): void;