import type { Pattern, PredicateContext, PredicateFn, PredicateHandler, ReservedPredicateKey, TopLevelWhenClause } from "../schema.ts"; /** * Runtime list of predicate keys that plugins are NOT allowed to * register. Mirrors the type-level {@link ReservedPredicateKey} from * `schema.ts`. Adding a new modifier to {@link PredicateModifiers} OR a * new operator field requires updating both this list and the matching * type union; the {@link reservedPredicateKeysCoverReservedTypes} * sync-pinning test in `evaluator.test.ts` fails when the two drift. * * The engine (in the plugin merger) throws at plugin-registration time * if a plugin attempts a reserved key, with a concrete error message * pointing the plugin author at the collision and suggesting an * alternative name. */ export declare const RESERVED_PREDICATE_KEYS: readonly ["not", "onUnknown"]; /** * Whether a string key is reserved (cannot be used as a plugin * predicate name). Used by the plugin merger and by * {@link validateWhenClauseShape} when computing the leaf-key set of * a `not:` block. */ export declare function isReservedPredicateKey(key: string): key is ReservedPredicateKey; /** * Throws if a `when:` or `not:` block contains no predicate-leaf keys * after stripping modifier keys. * * Catches three foot-guns at config-resolve time so the engine never * has to silently skip a malformed clause: * - `when: {}` — zero keys. * - `not: { onUnknown: "block" }` — one key, but it's a modifier; no * leaves means the block has nothing to evaluate. * - `when: { not: { not: ... } }` — nested `not:` inside a not-block, * authored via JSON load or `as any` escape hatch (the type-level * ban via {@link TopLevelWhenClauseNoRecurse} catches authoring- * time mistakes; the same recursion catches the JSON / `as any` * escape hatch). * * The `not:` operator field itself counts as a leaf at the outer * `when:` level (it produces a verdict via Kleene composition of the * inner not-block); only modifier keys are stripped. Built-in * non-registry keys (`condition`, `happened`, `cwd`) count as leaves; * plugin-registered predicates count as leaves regardless of whether * the plugin is currently loaded — the unknown-predicate check fires * later via {@link UnknownPredicateError}. * * Recurses into the `not:` block to enforce the same shape there. * * `path` describes the call site for error messages, e.g. * `'rule "no-main-commit".when'` or `'rule "no-git-worktree".when.not'`. */ export declare function validateWhenClauseShape(block: TopLevelWhenClause | undefined, path: string): void; /** * Modifier-only subset of {@link RESERVED_PREDICATE_KEYS} — used by * {@link validateWhenClauseShape} to strip modifiers when counting * leaves. Operator fields (currently `"not"`) are NOT modifiers; they * produce verdicts and count as leaves. * * Type-level coverage assertion (mirrors the * {@link _RESERVED_PREDICATE_KEYS_COVERS_TYPE} pattern): the * `satisfies readonly (keyof PredicateModifiers)[]` clause pins each * entry to a real modifier key, AND the * {@link _MODIFIER_KEYS_COVERS_TYPE} constant fails compilation if a * future modifier (e.g. a hypothetical v0.2 `priority?: number`) is * added to {@link PredicateModifiers} without updating this list. * Without the lockstep check, the new modifier would be counted as a * leaf by {@link validateWhenClauseShape}, masking empty-clause * configs that are now "only modifiers, no real leaves." */ export declare const MODIFIER_KEYS: readonly ["onUnknown"]; /** * Match a string against a {@link Pattern} (string source or RegExp). * Patterns are compiled once and cached; RegExps pass through. */ export declare function matchesPattern(pattern: Pattern, target: string): boolean; /** * Evaluate a rule-level predicate (`pattern`, `requires`, `unless`). * * Accepts the same union v1's `Rule` supported plus {@link PredicateFn}: * - `string` / `RegExp` → pattern match against `target`. * - `function` → call with `ctx`, coerce result to boolean. */ export declare function matchesPatternOrFn(value: Pattern | PredicateFn, target: string, ctx: PredicateContext): Promise; /** * Thrown when a {@link TopLevelWhenClause} references a predicate name that no * plugin has registered. The error message includes the offending key * so the source of the typo / missing plugin is clear at the site of * the rule. * * Schema-level typo detection doesn't cover this because the * `TopLevelWhenClause` mapped-type's index signature is deliberately * loose (`unknown`) — per * the ADR, plugin predicates can accept arbitrary arg shapes. The * trade-off is that we surface the error at evaluation time instead of * load time; the key-scoped message keeps that tolerable. */ export declare class UnknownPredicateError extends Error { readonly key: string; constructor(key: string); } /** * Walker state consumed by `when` evaluation. Today just the per-ref * cwd; the shape is open for future built-ins (e.g. branch) to pull * their own fields from the same snapshot. * * @internal — not a plugin-author surface. Plugin predicates consume * `ctx.walkerState` (the public `Readonly>` * on {@link PredicateContext}) instead. */ interface WhenWalkerState { readonly cwd: string; } /** * Evaluate a {@link TopLevelWhenClause}: returns true if every predicate in the * clause "matches" for the given context. An empty / undefined clause * trivially matches (rule fires regardless of `when`). * * Dispatch table: * - `cwd` — built-in (walker-tied), consumes `state.cwd`. Returns * trinary; outer leaf-level `onUnknown:` modifier on * the spread form projects to a definite boolean via * {@link projectVerdict} (default `"block"` = * fail-CLOSED). * - `happened` — built-in (session-entry-scoped), consumes * `ctx.findEntries` + `ctx.agentLoopIndex`. Boolean. * - `not` — nested `not:` block; dispatched to * {@link evaluateNotBlock} which composes leaves with * Kleene 3-valued AND and applies the block-level * `onUnknown:` policy without the not-flip on unknown * leaves. * - `condition` — {@link PredicateFn}; call with ctx. Throws caught * and treated as `"unknown"`. Outer-level * `condition:` is bare-`PredicateFn`-typed (no * spread shape), so the projection always uses the * default `"block"` policy and a throwing condition * fires the rule fail-CLOSED. Mirrors the inner * not-block exception treatment + the * plugin-handler contract in * {@link evaluateLeafTrinary}. * - anything else — `predicates[key]`; trinary handler with * leaf-level `onUnknown:` modifier projection. Throws * treated as `"unknown"` per spec. * * Reserved keys (`onUnknown`, future modifiers) are skipped here too — * they're meaningful as siblings to leaves at the outer level (per * spread form `{ pattern, onUnknown }` placement) but the engine * doesn't iterate them as standalone keys; the leaf adapter consumes * them inline. A bare `onUnknown:` at the outer level (without a * containing leaf) is type-banned but skipped here defensively. */ export declare function evaluateWhen(when: TopLevelWhenClause | undefined, state: WhenWalkerState, ctx: PredicateContext, predicates: Record, ruleName: string, source: string): Promise; export {}; //# sourceMappingURL=predicates.d.ts.map