import type { Action, ActionConfig, ActionFactory, ActionManifest, ActionResult, HookEvent } from '../types.js'; import { RuntimeContext } from 'src/types/runtime.js'; /** * Wall-clock bound on the clearing-house reads this action makes. * * These reads run inside the runtime's `reconcile` key-lock, which the DSL monitor's own * reconcile waits on. The client's retry ladder bounds attempt COUNT, not time — three 45s * attempts plus backoff is ~2.5 min of held lock, and it holds exactly when the MCP is * degraded, which is when the exit engine can least afford to wait. 20s sits under the DSL * tick's 30s default (a recipe on a faster tick loses at most one tick) while leaving a * healthy read, which lands in 1–5s, several attempts of headroom. */ export declare const CLEARINGHOUSE_READ_TIMEOUT_MS = 20000; export declare class OpenPositionAction implements Action { private config; private context; readonly name: string; readonly actionType: "OPEN_POSITION"; private decisionEngine; /** * Ledger of last resort for a context that carries none (standalone scripts, older call * sites). Private to this action, so it still counts this action's own in-flight opens. */ private readonly ownPendingOpens; /** * Edge-trigger state for the full-book log: `full` is the level, the rest bound the repeat * rate while it stays full. Instance state on purpose — a full book is a property of this * strategy, and the action is one per recipe. */ private noSlotsLog; constructor(config: ActionConfig, context: RuntimeContext); private eventCtx; handle(event: HookEvent): Promise; /** The pending-opens ledger this action counts against — the context's when it has one. */ private pendingOpens; /** * One clearinghouse read, fail-closed on both an unreadable response and a throw. A throw is * the same situation as an unreadable response — an unknown book — so it resolves undefined * and reaches the skip below rather than escaping the action with no per-signal outcome * recorded. Shared by the gate at the top of `handle` and the stale-view refetch in the * signal loop. */ /** * The bounded book read, failing closed. A read that throws — including one the deadline * aborts — leaves the exchange view unknown, which the callers treat as a skip rather than * trading against numbers nobody read. */ private readClearinghouseView; /** * Edge-triggered full-book log: once on the transition into full, then at most once per * {@link NO_SLOTS_LOG_INTERVAL_MS} with the count it suppressed in between. * * The early `no_slots` skip used to return silently, so a strategy that had stopped * entering looked identical in the logs to one with no signals — the single hardest state * to diagnose from a box. Logging every signal instead would bury the log, which is how it * came to be silent in the first place. */ private logBookFull; /** * Never open against an unknown exchange view. If the view is undefined after retries we * cannot tell what is already open or how much free margin exists — skip every signal * rather than risk a duplicate or an over-margined open. * * Shared by both read sites (the gate at the top of `handle`, and the stale-view refetch in * the signal loop). The rows come from the caller because the two sites attribute to * different inputs: the scan's own signals before a decision exists, the decision's * candidates after. `riskSnapshot` is undefined at the early site, where no gate snapshot * has been taken yet. */ private skipClearinghouseUnknown; private normalizeSignals; private handleSignals; } export declare const openPositionFactory: ActionFactory; export declare const openPositionManifest: ActionManifest; //# sourceMappingURL=open-position.action.d.ts.map