@sema-agent/core
Version:
Stateless, task-oriented AI agent core
55 lines (54 loc) • 3.86 kB
TypeScript
/**
* RB-476-A stage 2 (ruling 2026-08-02, RB-476 "no compatibility surface survives", replay
* resolution included) — the durable-name machinery this module used to hold is RETIRED:
*
* - `OLD_TO_NEW` (the Q6/design-108/design-115 persisted-name normalization) and the MCP `mcp__`
* prefix arm are gone: a persisted checkpoint/orphan/policy entry carrying a pre-rename name no
* longer resolves to the live roster. Old durable state misses LOUDLY (`resume.tool_unavailable`
* on a resumed checkpoint, a roster miss on replay) — by ruling, old sessions are sacrificed
* rather than carried.
* - `canonicalToolName` is gone with it: with the mapping cleared it was the identity function, and
* keeping an identity shim invites the next mapping to grow back silently.
* - `TOMBSTONED_TOOLS` (per-name re-education messages) is gone: a retired name now gets the same
* loud generic roster miss as any unknown tool.
*
* What REMAINS is validation data: {@link RETIRED_TOOL_NAMES} maps every name the engine ever
* retired to a one-line guidance string, and {@link judgeRuleToolName} is the ONE reading of it a rule's
* tool name gets. They exist because deleting the mapping flips stale POLICY entries from "silently
* matched" to "silently matches nothing" — and for a deny/requireApproval entry that direction WIDENS
* the surface. `validatePermissionRules` (permission-rules.ts) does NOT classify retired names itself:
* which names a deployment mounts its OWN tool under is a roster fact, and the judgment takes the roster.
* A deployment that mounts its OWN tool under one of these names is unaffected: the name is then in the
* roster and the judgment answers `current`.
*
* GRAMMAR of a guidance string, read by {@link judgeRuleToolName} and held by a pin: it opens with
* `renamed "<name>"` (a 1:1 successor — the judgment's `currentName`), `folded into "<name>"` (merged into a
* wider tool: writing it would deny more than the entry did, so it is no current name), or `removed — `.
*/
export declare const RETIRED_TOOL_NAMES: ReadonlyMap<string, string>;
/** The three answers {@link judgeRuleToolName} gives — a closed set. */
export declare const RULE_TOOL_NAME_VERDICTS: readonly ["current", "retired", "unprefixed_namespace"];
/**
* Whether a tool name written in a rule is a stale name — one that, against `roster`, names no tool and never can:
* - `current` — not a stale name: the roster mounts it, or it is neither retired nor a prefix-less `__` name. (Whether a
* current name matches anything THIS run is a different question — an unknown name is the prepare audit's advisory.)
* - `retired` — a name in {@link RETIRED_TOOL_NAMES} the roster does not mount; `guidance` is that table's line, and
* `currentName` the 1:1 successor when there is one (see the module header's grammar).
* - `unprefixed_namespace` — carries the `__` namespace separator with no protocol prefix. The roster cannot clear it:
* a caller tool name or alias carrying `__` is refused at prepare, every engine tool name is `__`-free, and every
* protocol tool is minted with its prefix.
*
* `roster` = the tool names (aliases included) the reader knows are mounted: a run's assembled roster at prepare, the
* names a deployment DECLARES it mounts its own tools under at a session-rule store (an empty set when it declares none).
*/
export type RuleToolNameVerdict = {
readonly kind: "current";
} | {
readonly kind: "retired";
readonly guidance: string;
readonly currentName?: string;
} | {
readonly kind: "unprefixed_namespace";
};
/** See {@link RuleToolNameVerdict}. Pure; the one answer to "is this rule's tool name a retired or prefix-less name". */
export declare function judgeRuleToolName(name: string, roster: ReadonlySet<string>): RuleToolNameVerdict;