/**
 * Process evaluator — interpreter loop for `ProcessStep[]`.
 *
 * A rule is a process: a flat sequence of primitive calls (Task 1.1 types,
 * Task 1.2 registry). This module walks the array, dispatches each step
 * through the registry, manages variable bindings (`as:` writes), evaluates
 * `if:` conditions, applies `on_empty:` early-exit policy, and recognises the
 * `verdict` primitive as the terminal step. The output is a `RuleResult`.
 *
 * What the evaluator deliberately is NOT:
 *
 *   - A string-eval engine. `if:` parsing is delegated to the chevrotain
 *     grammar in `runtime/evaluator/expression/index.ts` (H.1.6 cutover);
 *     this module never sees raw expression strings beyond the one-line
 *     delegate at the bottom of the file. No `eval()` / `new Function()`
 *     anywhere — audit-grepped on both this file and the expression dir.
 *     The grammar supports logical ops (`||`, `&&`, `!`), parens, dotted
 *     and bracket paths, function calls (5 allow-listed: `len`, `contains`,
 *     `match`, `startsWith`, `endsWith`), and strict equality.
 *
 *   - A template engine. `{{name}}` interpolation runs against string
 *     `args` values only; nested objects with template strings are NOT
 *     walked in Phase 1. Unbound variables substitute the empty string.
 *
 *   - A scheduler. Steps run strictly in order. Concurrency would need a
 *     primitive that fans out internally; the interpreter itself is serial.
 *
 * Purity: no module-level state. All variable scope lives in `ctx.bindings`,
 * which the caller owns. A second `evaluateProcess` call against the same
 * steps with a fresh ctx must produce the same result — tests rely on this.
 *
 * Durable execution (DURABLE.2):
 *
 *   When the caller passes a `checkpoint` option containing a CheckpointStore
 *   + runId, every step whose primitive declares `durable: true` is wrapped:
 *
 *     1. Resolve `(call, interpolatedArgs)` → `inputsHash` via canonical JSON
 *     2. Look up `checkpoints[runId][stepIdx]` (prefetched at entry)
 *     3. If the row exists, has `status: 'completed'`, and `inputsHash`
 *        matches → restore the row's `outputs` into `ctx.bindings[step.as]`,
 *        skip the primitive call entirely
 *     4. Else → execute the primitive, then `store.append(...)` the row
 *
 *   Non-durable primitives bypass the wrap entirely (no hash, no lookup, no
 *   write) — the audit guarantee is that the only durable-execution overhead
 *   on cheap primitives is one `if (def.durable)` branch per step.
 *
 *   Errored primitive results write a row with `status: 'errored'` so the
 *   resumer can re-run that step on the next pass. The evaluator still
 *   returns the error to the caller — the checkpoint write is best-effort
 *   accounting, not a swallowed failure.
 *
 * Memoization (DURABLE.3):
 *
 *   When the caller passes a `memo` option containing a MemoCache, primitives
 *   that declare `memoizable: true` (DURABLE.2 metadata) get an extra layer
 *   AFTER the checkpoint-hit branch but BEFORE the primitive invoke:
 *
 *     1. Run the same `inputsHash` derivation.
 *     2. If checkpoint hit → use it (covers same-run resume, exact-input).
 *     3. Else look up `memoCache.get(fn, inputsHash)` — cross-run cache.
 *     4. On memo hit → return value, write a checkpoint row (so a resume
 *        of THIS run remembers the step) but DON'T re-invoke the primitive.
 *     5. On memo miss → singleflight the invocation so 100 concurrent
 *        misses on the same key → 1 primitive call. Set the cache + write
 *        the checkpoint inside the singleflight body.
 *
 *   Memoization fires ONLY for `memoizable: true` primitives. Cheap
 *   non-memoizable primitives (state_lookup, verdict, match_regex) flow
 *   straight through — same as in DURABLE.2.
 *
 *   TTLs are caller-provided (per-primitive class defaults live in the
 *   caller's `memo.ttlForFn(fn)` callback). The evaluator never invents a
 *   TTL of its own — keeping the TTL policy with the caller lets pack
 *   authors override per-fn defaults.
 *
 * Imports from: runtime/types.ts, runtime/result.ts, functions/registry.ts,
 *   runtime/durable/checkpoint_store.ts, runtime/durable/canonical_json.ts,
 *   runtime/durable/run_id.ts, runtime/durable/memo_cache.ts.
 * Imported by: runtime/ (rule dispatcher in later phases).
 */
import type { FunctionRegistry, EvalCtx } from '../functions/registry.js';
import type { CheckpointStore } from './durable/checkpoint_store.js';
import type { MemoCache } from './durable/memo_cache.js';
import type { ProcessStep, RuleResult } from './types.js';
export interface CheckpointOptions {
    store: CheckpointStore;
    runId: string;
}
/**
 * Memoization wiring (DURABLE.3). `cache` is the shared two-tier MemoCache;
 * `ttlForFn` is an optional per-primitive TTL resolver — when omitted, all
 * memoizable primitives use the cache's no-TTL behavior (entry lives until
 * evicted by LRU or explicit `clear()`).
 *
 * Default TTLs (when callers wire a resolver):
 *   - llm_classify         → 1h
 *   - recall, embed        → 5m
 *   - http_request         → 30s
 *   - check_destination    → 1h
 */
export interface MemoOptions {
    cache: MemoCache;
    ttlForFn?: (fn: string) => number | undefined;
}
interface EvaluateOptions {
    checkpoint?: CheckpointOptions;
    memo?: MemoOptions;
}
export declare function evaluateProcess(steps: ProcessStep[], ctx: EvalCtx, registry: FunctionRegistry, options?: EvaluateOptions): Promise<RuleResult>;
export {};
//# sourceMappingURL=evaluator.d.ts.map