import type { ResolvedRole } from './config.js'; /** * Which environment variable a harness reads to pin the model it RUNS. * * This is not a convenience: for `claude-code` it is the only channel that * reaches the Claude Code ACP adapter. The adapter resolves its model in this * order — ANTHROPIC_MODEL, then * `settings.model`, then a resumed session's live model, then its first * catalogue entry. A role's declared model was therefore invisible to every * ACP role, and a fleet-wide `defaults.env.ANTHROPIC_MODEL` silently outranked * an explicitly requested one. */ /** The model-pin variable for a harness, or undefined if it pins no model by env. */ export declare function modelEnvVar(harness: string | undefined): string | undefined; export interface RoleModelEnvInput { harness: string; /** Already resolved by `resolveRoleModel` — may come from the fleet default. */ model: string | undefined; /** True when the resolved Brain named a model, including `model: null`. */ modelWasExplicit: boolean; defaultsEnv?: Record; roleEnv?: Record; authProxyBaseUrl?: string; } export interface RoleModelEnv { env: Record; /** * The model the harness will actually run. Equal to `env[pin]` for a harness * that pins by env, so anything reporting this value reports the runtime. */ model: string | undefined; } /** * Resolve a role's environment and its runtime model TOGETHER, so the two can * never disagree. * * Precedence, highest first: * 1. an explicit `model:` on the resolved Brain * 2. the role's own `env:` pin * 3. the fleet `defaults.model` * 4. the fleet `defaults.env` pin * * Inheriting the fleet default remains correct when the role names no model * (2, 3, 4); an explicitly named one wins (1). Where both are explicit and they * disagree, there is no defensible winner, so this refuses rather than picking * one silently — the silence is what let a day of "Fable" work run on Opus. * * `model: null` explicitly asks for no fleet-chosen model, so it also clears an * inherited pin instead of leaving one in place to act as a hidden default. */ export declare function resolveRoleModelEnv(input: RoleModelEnvInput, describe?: (message: string) => Error): RoleModelEnv; /** * The model a role will actually run, read back from the environment it was * resolved with. Use this wherever a model is reported to a human. */ export declare function effectiveRoleModel(role: ResolvedRole): string | undefined; /** * Move a role's env pin onto a new model. Anything that changes the model a * role runs after resolution — model-chain recovery is the live example — must * go through this, or it changes only the label. */ export declare function repinModelEnv(role: ResolvedRole, model: string | undefined): Record | undefined; /** * Last line of defence, at the exact point a child's environment is composed: * refuse to launch a role whose child would run a model other than the one the * role declares and the banner reports. A spawn that cannot keep those two in * agreement must fail loudly, not start and be believed. */ export declare function assertModelPinReachesChild(role: ResolvedRole, childEnv: Record): void;