import type { AgencyNode, Assignment, Expression } from "../types.js"; import type { TypeCheckError } from "./types.js"; import type { InterruptEffect } from "../symbolTable.js"; /** * The assignments at module top level, with a `with handler { ... }` * wrapper peeled off. Both `static const x = ...` and `with handler * { static const x = ... }` count, the same way `sectionAssembler` and * `initDepGraph` see them. */ export declare function topLevelAssignments(nodes: AgencyNode[]): Assignment[]; /** * Per-run primitives that need an execution context to run. Calling * any of these from a `static` initializer (which runs once at * process startup, before any agent run has begun) is a logic error * — there is no per-run ctx, no thread, no checkpoint store, no LLM * client wired up yet. * * `interrupt` lives on this list as a *function name* even though * the parser usually emits an `interruptStatement` node — a bare * call like `interrupt("foo")` could parse as either depending on * surrounding shape, so we check both. See `checkInterruptStatement` * below for the statement form. */ export declare const BANNED_BUILTINS_IN_STATIC_INIT: Record; /** * Walk a static initializer expression (or bare statement) and emit * a diagnostic for each direct call to a banned builtin. Does NOT * descend into nested `function` / `graphNode` bodies — those run * later, in per-run ctx, so calls there are fine. Matches the * ancestor-check pattern used by `collectFreeIdentifiers` in * `lib/compiler/initDepGraph.ts`. * * `contextLabel` is the human-readable subject of the diagnostic * (e.g. "static const 'prompt'" or "the `static greet()` bare * statement"). Used as the lead of the error message so the user * sees what part of their code is being rejected. */ export declare function checkBannedBuiltinCalls(expr: Expression | AgencyNode, contextLabel: string, staticName?: string): TypeCheckError[]; /** * Flag a call, inside a static initializer, to a function that can raise an * interrupt (issue #912). `effectsByFunction` is the table of UNANSWERED * effects (`collectUnansweredFacts`), propagated across files, so an interrupt * any number of calls away is found and a helper that answers its own * interrupt with `with approve` is left alone. * * `topLevelNode` is the whole statement, including a `with approve` wrapper, * so a call answered at the site is left alone too. `with propagate` answers * nothing and is still flagged. * * A function handed to a call, as in `helper(read)`, counts as called. * * The table is built by reading syntax. It cannot see through a function held * in a variable or a method call, and this rule says nothing there: the * runtime error remains the backstop. */ export declare function checkInterruptingCalls(topLevelNode: AgencyNode, contextLabel: string, effectsByFunction: Record): TypeCheckError[]; /** * Decide whether a top-level node is a post-declaration mutation * against one of the known static names, and produce a diagnostic if * so. Two shapes are detected: * * 1. `staticName = ...` — a bare assignment whose target is a * known static, where the assignment is NOT itself the static's * declaration. Mutations inside nested `node` / `function` * bodies are NOT checked here; the type-checker already rejects * reassignment of any `const` via `constReassignment`, so the * mutation case for statics inside per-run code is covered. * 2. `staticName.(...)` — a top-level method call * on a known static using one of the names listed in * `MUTATING_METHODS`. Compile-time best-effort; runtime * `__deepFreeze` is still the source of truth. * * Caller is responsible for filtering to top-level nodes; this * helper does not walk recursively. Same shape as PR 2's * `nodeFromTopLevel` so the validator can drive both with one loop. */ export declare function checkStaticMutation(node: AgencyNode, staticNames: Record): TypeCheckError | null;