/** * Running a validation and deciding what it means. * * Deliberately free of any command-line concern: it takes resolved options and returns a result * object. The command layer is a thin translation on either side, so the parts worth testing — * ordering, verdict, exit code, the basis — are testable without spawning anything. */ import { type ValidateDeps } from "./universe-stage.js"; import { type Depth, type Finding } from "./types.js"; export type Verdict = "PASS" | "FAIL" | "UNPROVEN"; /** 0 pass · 1 something is wrong · 2 ran but proved nothing · 3 the request itself was malformed. */ export type ExitCode = 0 | 1 | 2 | 3; /** Re-exported so a caller configures the run from one module. Defined with the check that uses it. */ export type { ValidateDeps }; export interface ValidateOptions { /** Positional target. Omitted means the working directory. */ target?: string; /** Recipe text supplied instead of a path. */ content?: string; /** Directory relative scanner paths resolve against, when content is supplied. */ dir?: string; cwd: string; depth: Depth; /** Restrict execution and reporting to one scanner. Never produces a proof. */ scanner?: string; /** Account identity for the live depth. */ wallet?: string; /** Per-scanner tick budget, seconds. */ timeoutSeconds?: number; /** Treat warnings as failures. */ strict?: boolean; /** Suppress proof recording even on a complete passing run. */ noAttest?: boolean; /** Sources for the checks that need one. Omitted means those checks do not run. */ deps?: ValidateDeps; } export interface VerdictBasis { /** The rule that decided it, rendered from the table rather than written per outcome. */ rule: string; observed: Record; /** What a passing run at this depth does and does not establish. */ proves?: string; does_not_prove?: string[]; why_not_pass?: string; what_would_change_it?: string; } export interface ValidateResult { verdict: Verdict; exit_code: ExitCode; target: { kind?: string; recipe?: string; scanner_roots?: string[]; }; stages_run: Depth[]; verdict_basis: VerdictBasis; findings: Finding[]; /** True only when this run was complete enough to be worth recording as a proof. */ proof_eligible: boolean; /** Present only on eligible runs: whether the record actually landed on disk. */ proof_recorded?: boolean; } export declare function isImplemented(depth: Depth): boolean; /** * Static findings that do NOT stop the depths below them. * * The depth loop halts on error-severity findings because *"the next reads a shape this one could * not establish"* — true of a recipe that will not parse or will not satisfy the schema, since * every deeper stage starts from a parsed config. It is not true of every error: a package-level * fault like a mixed-case id, or a recipe that ships no exit block, leaves the code just as * importable and just as tickable as it was. * * That distinction is load-bearing for the authoring loop rather than cosmetic. `--stage import` is * the taught write-time tool (`senpi-strategy-author/SKILL.md`: "Use it while you write, not only * at the end"), and the interview it drives settles the exit block LAST — so a static error that * halts on a half-written recipe takes the fast-feedback path away exactly when it is being used. * * A closed list rather than a severity sweep or a stage test, for the reason `install-gate.ts` * keeps one: a rule that widens silently as checks are added is one that will one day let * something through that nobody decided to let through. Adding a code here is a claim that the * import and live stages can still say something true while this fault stands. */ export declare const NON_HALTING_CODES: ReadonlySet; /** True when at least one finding invalidates the depths after this one. */ export declare function haltsDeeperStages(findings: readonly Finding[]): boolean; /** * Validate, and report what it means. * * Stages short-circuit: a depth that produced an error stops the ones after it, because they would * be reading a shape that was never established — for the errors where that is actually so. See * {@link NON_HALTING_CODES}. */ export declare function runValidation(options: ValidateOptions): Promise; /** * The verdict, from the findings alone. * * Three outcomes rather than two. A run that executed cleanly and established nothing is neither a * pass nor a failure: called a failure it sends someone hunting a defect that may not exist, called * a pass it is precisely the hole this command exists to close. It gets its own verdict and its own * exit code so a caller can tell the difference without parsing anything. * * Pure, and exported, because this is the rule the whole command reduces to. */ export declare function decideVerdict(findings: Finding[], options?: { strict?: boolean; }): { verdict: Verdict; exit_code: ExitCode; errors: number; warnings: number; }; /** * How long one tick may take. * * Never derived from the cadence. A strategy that ticks every six hours is not a strategy whose * tick may take six hours — the cadence is how long the runtime waits between ticks, and inheriting * it would make `senpi validate` hang for a working scanner while looking like it was doing * something. What the recipe declares wins; failing that, a bound that keeps the command * answerable. */ export declare function tickBudgetSeconds(declared: Record | undefined, override?: number): number; /** * What the environment is missing before a tick could run at all. * * Named rather than counted: "credentials are missing" leaves someone guessing which, and this is * the one finding whose fix belongs to whoever set the environment up rather than to the author. */ export declare function missingCredentials(env?: NodeJS.ProcessEnv): string[]; //# sourceMappingURL=run.d.ts.map