import { type CodeCheck, type Rule } from "oh-my-plumb-schema";
import { type McpLaunch } from "./mcp.js";
import type { Verdict } from "oh-my-plumb-schema";
export type McpRoute = {
server: string;
tool: string;
};
/** One guard check resolved for routing: where it triggers, what runs, which rule owns it. */
export type GuardRoute = {
/** The owning rubric rule: the id a guard hit reports. */
ruleId: string;
trigger: string;
command?: string[];
server?: string;
tool?: string;
/** Resolved skill guard entry: the absolute path of `
//guard.*`. */
skill?: string;
/** Inline code check, run in-process under a sandbox. */
code?: CodeCheck;
};
export type GuardHit = {
ruleId: string;
source: string;
reason: string;
};
export declare const routesForFile: (routes: readonly GuardRoute[], file: string) => GuardRoute[];
/** Narrow one `{ isError, content }` result, shared by the line and MCP paths. */
export declare const guardOutputOf: (value: unknown) => {
isError: boolean;
content: string;
} | undefined;
/** Parse one JSON line of `{ isError, content }` from a guard process. */
export declare const parseGuardOutput: (text: string) => {
isError: boolean;
content: string;
} | undefined;
/** Resolve a skill guard entry under known skills dirs. Returns absolute path or undefined. */
export declare const resolveSkillGuard: (root: string, skillDirs: readonly string[], name: string) => string | undefined;
export declare const SKILL_DIRS: string[];
/** Guard routes from the rubric: one per guard or code check, keyed to the rule that owns it. */
export declare const guardRoutes: (rules: readonly Rule[], root: string) => GuardRoute[];
/**
* Read-only: why a configured guard cannot run here; empty means it resolves.
* A skill route only parses when its guard file already resolved, so only a
* guard whose server or script is gone, and one with nothing to run, are missing.
*/
export declare const routeGaps: (root: string, route: Pick, mcpServers: readonly string[]) => string[];
/** Guard deadline: a guard that hangs is a skip, never a hold. */
export declare const GUARD_TIMEOUT_MS = 2000;
/**
* The code rules in scope of one file, run against the file's content on disk,
* as act-band verdicts. The `check` command uses this to agree with the hooks:
* a code rule fires the same way in both. Missing or unreadable file: no hits.
*/
export declare const codeCheckVerdicts: (rules: readonly Rule[], root: string, file: string) => Promise;
/**
* Run one guard command with FILE_PATH in env and the file text on stdin.
* Resolves a block hit, or undefined on pass/timeout/bad-output/missing-binary.
*/
export declare const runGuard: (ruleId: string, source: string, command: string[], file: string, text: string, timeoutMs?: number, cwd?: string) => Promise;
/**
* MCP guard: call the tool on a server started from the host's own MCP config.
* `launch` is undefined when no config names that server; that, like every
* protocol failure, is a silent pass with a logged skip.
*/
export declare const runMcpGuard: (ruleId: string, launch: McpLaunch | undefined, route: McpRoute, cwd: string, file: string, text: string, timeoutMs?: number) => Promise;
/** CPU wall for one code check: counting ops take microseconds, so past this the script is stuck. */
export declare const CODE_CHECK_TIMEOUT_MS = 500;
/**
* Inline code check: run the rubric's own predicate over the edited file.
*
* The script is the body of a `(path, contents) => …` function. It runs once,
* in a fresh vm realm, strictly, over a null-prototype sandbox: the script
* sees only its two string arguments and its realm's own JS builtins — no
* require, process or filesystem, and no host object whose prototype chain
* reaches back into ours (`globalThis.constructor.constructor` over a plain
* `{}` sandbox is the known way out of node:vm).
*
* A throw, a timeout, or anything but a `{ isError: true, content }` answer
* is a silent pass, like every guard. A rejection the script left dangling
* (a dynamic `import()`, an orphaned promise) lands after the vm call, so the
* drain below catches it while the guard listener is on: without it, an
* unhandled rejection would crash the whole hook. node:vm is a fence, not a
* wall; the rubric is still code the repo author trusts.
*/
export declare const runCodeCheck: (ruleId: string, check: CodeCheck, file: string, text: string) => Promise;
//# sourceMappingURL=guards.d.ts.map