/** * Semantic checks on a parsed recipe — the things a schema cannot express. * * Each is a pure function over the parsed config, exported individually so the same check can run * from `senpi validate` and, later, from the install and boot paths. One implementation, several * callers, rather than a validation copy that drifts from the enforcement copy. * * ## Every check here was measured against the fleet before it was written * * A check that refuses a working strategy is worse than no check: it trains people to bypass the * gate. Each of these was run against all 125 production instances first, and each fires on **none** * of them. Two were narrowed as a direct result — see `findUnsizedStrategy` and * `findMarginPctFraction`, where the obvious version of the check would have been wrong. */ import type { RuntimeConfig } from "../runtime/runtime-schema.js"; import type { Finding } from "./types.js"; /** * An entry action for which **no margin source can ever resolve**. * * The runtime resolves margin in priority order: a per-signal `marginPct`, then config * `margin_pct`, then `margin_per_slot`, then budget ÷ slots. If none produces a value the signal is * skipped as `no_margin_configured` — the failure class behind thousands of declined signals. * * ## Why this is narrower than "no configured margin" * * **49% of production instances (61 of 125) declare no config margin at all.** They size from a * per-signal `marginPct` their scanner emits, with config margin as an optional fallback — that is * the fleet norm, not an oversight. Refusing them would have made this command reject half of a * working fleet on its first day. * * So this fires only when *nothing could supply a margin*: no config source, no external scanner * that could emit one, and no model-mode decision that could override. That condition is provable * from the recipe alone, and it matches none of the 125. * * The weaker case — config margin absent and the scanner simply never emits one — is not knowable * statically. It is caught at the live stage, where the signals a tick actually emits can be read. */ export declare function findUnsizedStrategy(config: RuntimeConfig): Finding[]; /** * An entry action with no risk guardrails. * * With no guardrail block the risk gate evaluates fully open: no daily loss limit, no drawdown * ceiling, no trade cap. Every one of the 125 production instances declares one, so requiring it * matches practice rather than imposing a new rule. */ export declare function findUngatedStrategy(config: RuntimeConfig): Finding[]; /** * `strategy.margin_pct` given as a fraction where a percent is required. * * `margin_pct: 0.20` is accepted by the schema — it is positive and under 100 — and sizes **0.2%** * of withdrawable rather than 20%. A hundred times too small, with no error at any point. * * ## Scope: only what the runtime reads as a percent * * Deliberately not a walk of the whole document. Scanner `inputs` are private tunables in whatever * units their scanner defines, and at least one production strategy carries fractional tier values * there on purpose, converting them before emitting. Flagging those would accuse a correct strategy * of a bug — so this reads only the field the runtime itself interprets as a percent. * * An emitted per-signal value is checked separately at the live stage, where the real value is * visible rather than inferred. */ export declare function findMarginPctFraction(config: RuntimeConfig): Finding[]; /** A model-mode decision action with no model configured — the decision step cannot run. */ export declare function findLlmActionsWithoutModel(config: RuntimeConfig): Finding[]; /** * A declared entrypoint that is not on disk. * * Needs the resolved scanner root, so it takes what the target resolver worked out rather than * re-deriving it. Without this the failure surfaces only when the scanner process starts and dies. */ export declare function findMissingEntrypoints(config: RuntimeConfig, resolveScannerRoot: (scannerPath: string) => { ok: true; root: string; } | { ok: false; reason: string; }, exists: (path: string) => boolean, join: (...parts: string[]) => string): Finding[]; //# sourceMappingURL=recipe-checks.d.ts.map