@sema-agent/core
Version:
Stateless, task-oriented AI agent core
218 lines (217 loc) • 17.9 kB
TypeScript
/**
* PrepareTask's WIRING-MANIFEST phase, verbatim from the driver: the run's own frozen approver
* seat, the loud ungated-write warning (hand band / destructive MCP / first-party write tools with no effect-aware gate,
* deduped per deployment and tool-set shape), the PreToolUse context stash and the blocked-call set, the settlement and
* bare-rejection sidebands, the turn halt fact, the suspend infrastructure predicates (restore surface gap, durable
* infra, the task-axis lane with its INACTIVE line), usage governance, the platform-suspend arming, the synthesized
* durableApproval, the effective wiring manifest, the peer lane's ask fold and drain binding, the park predicate as ONE
* named const, the durable-gate-unavailable notice, the hook identity mint and the hook env face. The four helpers only
* this segment called moved with it (usage governance, the per-deployment warn ledger, the MCP manifest projection, the
* durable-gate notice). The interface is the dependency list the segment had implicitly.
*
* SYNCHRONOUS FUNCTION, SYNCHRONOUS CALL: the stretch has no await, so the phase adds no yield between the policy-chain
* station before it and the gate registration after it (a stretch with no await is extracted as a sync
* function). Read-stability of the host handles for the call: {@link RunInternals} (`@contract prepare.deps-read-stable`).
*
* One read changed spelling and nothing else: the manifest's MCP face read `mcp?.statuses ?? []` while `mcp` had long
* been the protocol-tools phase's non-null handle; the optional chain was dead and is now the plain member read.
*/
import type { AgentHarness, ExecutionEnv } from "../../internal/harness.js";
import { type PeerLaneRefs } from "../../agents/peer-session-drain.js";
import type { SessionBoxBinding } from "../task-notification.js";
import type { OnQuestion } from "../ask-question.js";
import type { CheckpointStore } from "../checkpoint-store.js";
import { type HookEnvCapabilities, type HookInvocationIdentity, type Hooks } from "../hooks.js";
import type { LockedPreflight } from "../locked-config.js";
import type { MaterializedMcp } from "../mcp.js";
import type { SessionStore } from "../session.js";
import { type ToolResultStore } from "../tool-result-store.js";
import { type OnAsk, type ToolPolicy } from "../tool-policy.js";
import type { GateOutcome } from "../gate-outcome.js";
import type { RunnerDeps, RuntimeCaps, TaskSpec, ToolEffect, ToolExecuteContext } from "../types.js";
import { type LegWriteProtection } from "./write-protection-station.js";
import { type UsageWindow } from "../usage-window-store.js";
import type { ToolRoster } from "../tool-roster.js";
import { type AutoModeArmFact, type WiringManifest, type WiringManifestMcpEntry } from "../wiring-manifest.js";
import { type PermissionModeController } from "../mode-policy.js";
import type { AnnounceOnceSink, Prepared, PrepareResume, RunInternals, UsageGovernance } from "./contracts.js";
export interface PrepareWiringManifestInput {
/** borrowed-readonly — the REBOUND spec. Read: `onAsk` (the own seat), `onQuestion` (the question seam), `handsReadOnly` / `tools` (the ungated scan),
* `resourceSuspend` (the task-axis lane), `durableApproval` / `principal` (the synthesis and the notice), `interactiveTools` /
* `mcp` / `checkpointStore` (manifest cells and the notice's cause), `enablePlanMode` (the gate-machinery predicate's
* plan-mode term). Never mutated. */
spec: Pick<TaskSpec, "onAsk" | "onQuestion" | "handsReadOnly" | "tools" | "resourceSuspend" | "durableApproval" | "principal" | "interactiveTools" | "mcp" | "checkpointStore" | "enablePlanMode" | "hooks" | "peerPresence">;
/** borrowed-readonly — the deployment seats, whole: `onAsk` (the seat's deps half), `onError` (the warning), `executionEnv`
* (the hook-env predicate), `checkpointStore` (durable infra), the manifest's dozen wiring facts (`backgroundAgentStore`,
* `permissionRuleStore`, `permissionRuleSyncWired`, `onBackgroundChildEvent`, `lockedConfig`, `compliancePostureResolver`,
* `memoryScopeAdmission`, `retentionPolicy`, `onElicit`), `onNotice`, the write-protection judge's compile seats
* (`writeProtectedPaths`, `memoryEngineDir`), and the usage-governance seats (`usageWindowStore`,
* `now`, `onUsageGovernance`…) the helper reads through the whole record. */
deps: RunnerDeps;
/** borrowed-readonly — the trusted spawn-side channel: `questionFaceStripped`, `isDelegatedChild`, `onTaskNotification`,
* `peerSelfRef`, `explicitAgentName` (the drain + the identity), `insideFork` / `agentName` / `spawnAgentType` / `parentToolCallId` (the identity). */
internals: Pick<RunInternals, "questionFaceStripped" | "isDelegatedChild" | "onTaskNotification" | "peerSelfRef" | "explicitAgentName" | "spawnAgentType" | "insideFork" | "agentName" | "parentToolCallId"> | undefined;
/** borrowed-readonly — the resume leg, or undefined (the manifest's leg derivation reads presence only). */
resume: Pick<PrepareResume, "seed"> | undefined;
/** borrowed-readonly — the acquired session id. */
sessionId: string;
/** borrowed-readonly — the run's invocation id. */
runId: string;
/** borrowed-readonly — the per-task identity (the hook identity's taskId). */
hostTaskId: string;
/** borrowed-readonly — the registry scope the peer drain binds under. */
taskScope: string;
/** borrowed-readonly — the resolved hook record (`spec.hooks ?? deps.hooks`): the effect-aware-gate term, the tracked flag and the hook-env consumer test. */
hooks: Hooks | undefined;
/** borrowed-readonly — whether the deployment declared its screening face observational (then it is no gate). */
preToolUseObservational: boolean;
/** borrowed-readonly — the caller-facing policy layers; only their COUNT is read (an effect-aware gate exists). */ policyLayers: ReadonlyArray<unknown>;
/** borrowed-readonly — the policy chain's effective policy, or undefined; only its PRESENCE is read (the first term of the
* gate-machinery predicate below). Never called here. */
effectivePolicy: ToolPolicy | undefined;
/** borrowed-readonly — whether an execution env is wired (the hand band exists at all). */
handsEnabled: boolean;
/** borrowed-readonly — the resolved task root: the base a `base: "root"` write tool's relative spelling resolves against. */
taskRootFinal: string;
/** borrowed-readonly — the materialized MCP handle: `tools` (the destructive-ungated scan) and `statuses` (the manifest face). */
mcp: Pick<MaterializedMcp, "tools" | "statuses">;
/** borrowed-readonly — the assembled safety vocabulary (the ungated scans and the manifest's armed cell). Read only. */
irreversibleTools: ReadonlySet<string>;
/** borrowed-readonly — see `irreversibleTools`. */
egressTools: ReadonlySet<string>;
/** borrowed-readonly — the hands phase mounted the shell READ STATION (a real shell was mounted): the gate
* machinery must run for it, under every doctrine — the read-only face's containment IS that station. */
shellReadStationArmed: boolean;
/** borrowed-readonly — the effect collection; read only here (the ungated scans). */
toolEffects: ReadonlyMap<string, ToolEffect>;
/** borrowed-readonly — the per-task owned env when a factory minted one (durable infra, the hook-env predicate). */
ownedEnv: ExecutionEnv | undefined;
/** borrowed-readonly — the run's resolved env (the hook env face is built over it). */
executionEnv: ExecutionEnv;
/** borrowed-readonly — the run's offload store, or undefined (a volatile store disqualifies durable suspend). */
offloadStore: ToolResultStore | undefined;
/** borrowed-readonly — the once-per-session ledger's operator sink (the INACTIVE line, once per session). */
onceLedger: Pick<AnnounceOnceSink, "onError">;
/** borrowed-readonly — the resolved usage windows, or undefined. */
usageWindows: readonly UsageWindow[] | undefined;
/** borrowed-readonly — the env-lifetime suspend instant, or undefined (platform-suspend arming). */
envLifetimeSuspendAt: number | undefined;
/** borrowed-readonly — the resolved per-principal entitlements (forceDurableGate). */
runtimeCaps: RuntimeCaps | undefined;
/** borrowed-readonly — the resolved interaction posture (a manifest cell). */
resolvedInteractionPosture: ToolExecuteContext["interactionPosture"];
/** borrowed-readonly — the question-face phase's durable-face decision (the composition-lie detector reuses it). */
durableQuestionFace: boolean;
/** borrowed-readonly — the live question face, or undefined (the notice's effective fact). */
liveQuestionFace: OnQuestion | undefined;
/** borrowed-readonly — the leg's checkpoint store, resolved once by the question-face phase. */
checkpointStore: CheckpointStore | undefined;
/** borrowed-readonly — the session store (durability declaration and transcript tier). */
sessions: SessionStore;
/** borrowed-readonly — the model gate's per-leg read face, or undefined. */
modelGateManifest: WiringManifest["modelGate"];
/** borrowed-readonly — the leg's minted tool roster: rides the manifest's `tools` section and is the
* source of the hand band's write-capable names for the ungated-write warning (what actually MOUNTED). */
toolRoster: ToolRoster;
/** borrowed-readonly — from the read-face phase: the built-in read-deny TIERS that leg's own
* resolution materially activated; relayed onto the manifest (present iff non-empty), never
* re-derived from `deps` here (which by this phase sits past that phase's await). */
readDenyBuiltinTiersActive: readonly string[];
/** borrowed-readonly — from the LSP phase's manager fold: gates the manifest's LSP section (absent ⇒ byte-identical manifest). */ lspManagerWired: boolean;
/** borrowed-readonly — from the LSP phase: is the diagnostics lane live? The `lane` word's only input. */ lspDiagnosticsLive: boolean;
/** borrowed-readonly — from the file-history phase's one fold of the two off switches: the manifest's word, relayed. */ fileHistoryFact: NonNullable<WiringManifest["fileHistory"]>;
/** borrowed-readonly — the arming outcome the caps phase reads live (the manifest's auto-mode face at this leg's start). */
autoModeArmReason: () => AutoModeArmFact;
/** borrowed-readonly — the leg's live permission-mode seat: its receipt at this leg's start rides the manifest, and the
* peer lane reads the effective mode through the refs filled here. */
permissionMode: PermissionModeController;
/** borrowed-readonly — the frozen preflight; only `mcp` (the declared servers the manifest face joins). */
lockedPreflight: Pick<LockedPreflight, "mcp">;
/** borrowed-mutable — the peer lane's late-bound facts. Writer here: `askEffective` ← the manifest's ask derivation (the
* one fold of this session's permission-mode class). */
peerLaneRefs: PeerLaneRefs;
/** borrowed-mutable — #1036's settlement seam, minted by the orchestrator. This phase writes
* its two predicate seats (`boxBacked` / `wantsEffects`) when it binds the drain; the ledgers
* themselves are written later, by the harness receipt sink, the compaction commit beat and the
* drain's own passes. */
frameSettlement: import("../frame-settlement.js").FrameSettlement;
/** borrowed-readonly — the session-box drain's mount verdict (prepare-task's one judgment): present ⇒ this leg drains its own box. */
sessionBox: SessionBoxBinding | undefined;
/** borrowed-readonly — the built harness the peer drain binds to. */
harness: AgentHarness;
/** borrowed-readonly — the durable-suspend holder; the drain's parked predicate reads `token` at run time. Not written here. */
pausedRef: Prepared["pausedRef"];
/** borrowed-readonly — the FROZEN approver seat (the notice's liveApprover fact). */
frozenOnAsk: OnAsk | undefined;
/** borrowed-readonly — the LIVE half of the inherited chain (the notice reads its content mandates). */
liveInheritedGate: RunInternals["inheritedGate"];
/** borrowed-readonly — the effective delegation facts (the identity's isDelegatedChild). */
delegation: {
isDelegatedChild: boolean;
};
}
export interface PrepareWiringManifestResult {
/** owned — the run's own approver seat (spec over deps), read by the gate-fold station. */
onAsk: OnAsk | undefined;
/** borrowed-mutable — PreToolUse `additionalContext` per call id. Writers: the gate (phase 1 stash), the post-tool handler
* (one-shot drain). */
preToolContexts: Map<string, string[]>;
/** borrowed-mutable — the call ids the gate blocked or suspended (`Prepared.blockedToolCalls`). Writers: the gate; readers
* delete one-shot. */
blockedToolCalls: Set<string>;
/** borrowed-mutable — the gate-outcome sideband (`Prepared.gateOutcomes`). Writer: the gate station; the frame mint reads and
* deletes. Nothing else may write it. */
gateOutcomes: Map<string, GateOutcome>;
/** borrowed-mutable — the turn's halt fact (`Prepared.batchHaltRef`). Writer: the judgment site; cleared at the next request. */
batchHaltRef: Prepared["batchHaltRef"];
/** owned — whether any consumer of the blocked set is wired (populate only then). */
blockedTracked: boolean;
/** owned — the restore-surface gap of a declared-suspendable adapter, or undefined for a complete / non-suspendable one. */
incompleteSuspendAdapter: readonly ("resumeVM" | "postResumeInit")[] | undefined;
/** owned — the infrastructure half of suspend eligibility (no task opt-in in it). */
durableSuspendInfraReady: boolean;
/** owned — the task-axis lane: the infrastructure plus the caller's opt-in. */
resourceSuspendEligible: boolean;
/** owned — the run's usage-governance handle, or undefined (`Prepared.usageGovernance`). */
usageGovernance: UsageGovernance | undefined;
/** owned — whether the suspend saga must be armed for a PLATFORM cause. */
platformSuspendArmed: boolean;
/** owned — the effective durable-approval opt-in: the caller's, or the scope synthesized for a forced durable gate. */
durableApproval: TaskSpec["durableApproval"];
/** owned — this leg's EFFECTIVE wiring manifest (`Prepared.wiringManifest`). */
wiringManifest: WiringManifest;
/** owned — the leg's write-protection judge, or undefined when the table was emptied (no judge, no tighten mounted):
* its gate input (`check`) for the gate station and its target judge for the shell station — one compile, never two. */
writeProtection: LegWriteProtection | undefined;
/** owned — THE park predicate as one named const (`parkLane.effective === true`). */
parkLaneArmed: boolean;
/** owned — THE gate-machinery activation predicate as one named const: a policy, a screening hook, an egress or
* irreversible tool, an eligible resource lane, an armed platform lane, or plan mode. The ask lane, the suspend saga,
* the boundary parks, the park closure and the gate station are built exactly when it holds. */
gateMachineryActive: boolean;
/** owned — THE identity mint of this leg (`Prepared.hookIdentity`), one frozen envelope every hook station reuses. */
hookIdentity: HookInvocationIdentity;
/** owned — the read-only env capability face every hook context carries, or undefined (no hook consumer, or no env wired). */
hookEnvFace: HookEnvCapabilities | undefined;
/** owned — the session box this leg's drain was BOUND on (the mount judgment ∧ an injector to drain into); the notification
* lane binds the park seat on exactly this value, so "parked here" and "drained there" are one fact. */
sessionBoxBound: SessionBoxBinding | undefined;
}
/**
* The wiring manifest's per-server MCP read face for one leg ({@link WiringManifest.mcp}): every
* server the leg's FROZEN entry snapshot declared, in declaration order, joined by name to this leg's
* materialization statuses. Pure projection — no connection logic, no second look at any transport:
* · a status `connected` ⇒ `connected` with the mounted roster size (the intake's post-filter count);
* · a status `failed` ⇒ `failed` with the failure record the materialization stamped (`errorCode`/`delivered`/
* `httpStatus` = the MCP vocabulary's `McpFailure` spread flat) and the remote text SECRET-REDACTED (an HTTP endpoint's error body rides the SDK's message
* verbatim, and a body that echoes the bearer it rejected must not reach a stream consumer),
* then neutralized + bounded to the reminder's own 240 (the same bound the once-per-session
* ledger applies to that text — one face, one width);
* · no status at all ⇒ `skipped` (the declaration stands, this leg produced no attempt record for it).
* `source` is echoed from the declaration (single-line, bounded; core reads nothing off it), and
* `liveness` is the status record's own observation deep-copied (see {@link WiringManifestMcpEntry.liveness}).
* The entries are fresh objects so the manifest never aliases the status records the refresh face mutates.
*/
export declare function mcpManifestEntries(entries: ReadonlyArray<import("../types.js").McpServerSpec> | undefined, statuses: ReadonlyArray<import("../mcp.js").McpServerStatus>): WiringManifestMcpEntry[];
/** The M18 phase body — prepareTask's wiring-manifest stretch, verbatim (see the module header). */
export declare function prepareWiringManifest(input: PrepareWiringManifestInput): PrepareWiringManifestResult;