UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

772 lines (771 loc) • 38 kB
import { randomBytes, randomUUID } from "node:crypto"; import { uuidv7 } from "../internal/harness.js"; import { PROBE_CAUSE_PATH_MAX, PROBE_REASON_MAX, inlineUntrusted, sanitizeUntrustedText } from "./untrusted-text.js"; import { carriesBidiControls } from "./tool-policy.js"; import { readDenialLimitFallback } from "./auto-mode.js"; import { isAskOrigin, isPersistedRuleMandate } from "./ask-origin.js"; import { checkpointExecutionRecorded, executionRecordDisposition, ExecutionOutcomeConflictError, } from "./checkpoint-execution-record.js"; import { renderUntrustedCommandText, stripFormatCharacters } from "./permission-rule-model.js"; import { redactSecrets } from "./untrusted-egress.js"; import { steerPriorityOf } from "./task-notification.js"; import { ASK_USER_QUESTION_TOOL_NAME } from "./ask-question.js"; import { isPermissionMode } from "./ask-origin.js"; import { wireOf } from "./tool-name-readings.js"; export function mintCheckpointToken() { return randomBytes(16).toString("hex"); } export function mintCheckpointId() { return `cp_${randomUUID()}`; } export { PROBE_REASON_MAX } from "./untrusted-text.js"; const PROBE_CAUSE_MAX_SHOWN = 8; export function normalizeProbeCause(value) { if (!isPlainRecord(value)) return undefined; const code = safeDataValue(value, "code"); if (typeof code !== "string" || code.trim().length === 0) return undefined; const family = (raw) => { if (!isPlainRecord(raw)) return undefined; const shownRaw = safeDataValue(raw, "shown"); if (!Array.isArray(shownRaw)) return undefined; const shown = shownRaw .filter((p) => typeof p === "string") .slice(0, PROBE_CAUSE_MAX_SHOWN) .map((p) => inlineUntrusted(p, PROBE_CAUSE_PATH_MAX)); const totalRaw = safeDataValue(raw, "total"); const total = typeof totalRaw === "number" && Number.isFinite(totalRaw) ? Math.max(0, Math.floor(totalRaw)) : shown.length; return { shown, total: Math.max(total, shown.length) }; }; const roots = family(safeDataValue(value, "roots")); if (roots === undefined) return undefined; const further = family(safeDataValue(value, "further")); return { code: inlineUntrusted(code, PROBE_REASON_MAX), roots, ...(further !== undefined && further.total > 0 ? { further } : {}), }; } export function riskSeverity(axes) { const egress = axes.egress === true; const irreversible = axes.irreversible === true; if (irreversible && egress) return 5; if (irreversible) return 4; if (egress) return 3; if (axes.shell === true) return 3; return 2; } const SUMMARY_CMD_MAX = 200; const SUMMARY_VALUE_MAX = 120; const SUMMARY_TOTAL_MAX = 200; const PATH_MAX = 200; const MAX_TOUCHED_PATHS = 8; const MAX_DIGEST_KEYS = 16; const MAX_DIGEST_SCAN_KEYS = 256; export const MAX_TOOL_INPUT_PREVIEW_CHARS = 512; const BIDI_BACKFILL_MAX_CHARS = 32_000; const BIDI_BACKFILL_MAX_NODES = 512; export const MAX_PENDING_STEER_CHARS = 16_000; export const PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES = 48_000; export const MAX_PENDING_STEER_ENTRIES = Math.floor(PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES / MAX_PENDING_STEER_CHARS); export const PENDING_STEER_FROZEN_FIELDS = Object.freeze(["text", "trusted", "actor", "seq", "inputId", "priority"]); export function isPlainRecord(x) { try { if (x === null || typeof x !== "object" || Array.isArray(x)) return false; const p = Object.getPrototypeOf(x); return p === Object.prototype || p === null; } catch { return false; } } export function safeDataValue(obj, key) { try { const d = Object.getOwnPropertyDescriptor(obj, key); return d && "value" in d ? d.value : undefined; } catch { return undefined; } } function safeKeys(obj) { try { return Object.keys(obj); } catch { return []; } } function fsPathArg(args) { if (!isPlainRecord(args)) return undefined; const fp = safeDataValue(args, "file_path"); if (typeof fp === "string" && fp.length > 0) return fp; const p = safeDataValue(args, "path"); return typeof p === "string" && p.length > 0 ? p : undefined; } export function buildRiskDescriptor(input) { const { toolName } = input; try { const { args, safety, shellGated } = input; const egress = safety?.egress === true; const shell = shellGated === true; const irreversible = !shell && safety?.irreversible === true; const axes = {}; if (egress) axes.egress = true; if (irreversible) axes.irreversible = true; if (shell) axes.shell = true; let summary; if (shell || toolName === "Bash") { const cmd = isPlainRecord(args) ? safeDataValue(args, "command") : undefined; if (typeof cmd === "string" && cmd.length > 0) summary = renderUntrustedCommandText(stripFormatCharacters(redactSecrets(cmd)), SUMMARY_CMD_MAX); const bg = isPlainRecord(args) ? safeDataValue(args, "run_in_background") : undefined; if (bg === true) summary = `[background persistent process — no per-step recheck] ${summary ?? ""}`.trimEnd(); } else if (isPlainRecord(args)) { { const parts = []; for (const key of safeKeys(args).slice(0, MAX_DIGEST_SCAN_KEYS).sort().slice(0, MAX_DIGEST_KEYS)) { if (key === "__proto__" || key === "constructor" || key === "prototype") continue; const v = safeDataValue(args, key); if (typeof v === "string" || typeof v === "number" || typeof v === "boolean") { const encDigest = (s) => s.replace(/%/g, "%25").replace(/=/g, "%3D").replace(/ /g, "%20"); const k = encDigest(renderUntrustedCommandText(key, 40)); const val = encDigest(renderUntrustedCommandText(stripFormatCharacters(redactSecrets(String(v))), SUMMARY_VALUE_MAX)); parts.push(`${k}=${val}`); } } if (parts.length > 0) summary = renderUntrustedCommandText(parts.join(" "), SUMMARY_TOTAL_MAX); } } const touched = []; if (!shell && toolName !== "Bash") { const p = fsPathArg(args); if (p !== undefined) touched.push(renderUntrustedCommandText(p, PATH_MAX)); } const touchedPaths = touched.length > 0 ? touched.slice(0, MAX_TOUCHED_PATHS) : undefined; return { severity: riskSeverity(axes), axes, toolName, ...(input.shellGated && input.shellGateDoctrine !== undefined ? { shellGateDoctrine: input.shellGateDoctrine } : {}), ...(input.allowRuleShadowed !== undefined && input.allowRuleShadowed.length > 0 ? { allowRuleShadowed: input.allowRuleShadowed.map((r) => ({ member: r.member, entries: r.entries.map((e) => renderUntrustedCommandText(e, 200)), ...(r.omitted !== undefined ? { omitted: r.omitted } : {}) })) } : {}), ...(input.probeReason !== undefined ? { probeReason: inlineUntrusted(input.probeReason, PROBE_REASON_MAX) } : {}), ...(() => { if (input.probeCause === undefined) return {}; const cause = normalizeProbeCause(input.probeCause); return cause !== undefined ? { probeCause: cause } : {}; })(), ...(summary !== undefined ? { summary } : {}), ...(touchedPaths !== undefined ? { touchedPaths } : {}), }; } catch { return { severity: 2, axes: {}, toolName: typeof toolName === "string" ? toolName : "" }; } } export function realApprovalOrgFact(bit) { if (bit === undefined) return undefined; if (bit.org !== undefined) return bit.org; return bit.origin === "org_rule" ? "rule" : bit.origin === "org_unavailable" ? "unavailable" : undefined; } export const CHECKPOINT_FEATURES = { baseline: { version: 1, introduced: "design/49", recordedOn: (_cp) => true, writes: "the row itself" }, resource: { version: 2, introduced: "design/74", recordedOn: (cp) => cp.gate.kind === "resource_limit", writes: "resourceLedger; gate/pendingAction kind resource_limit" }, binding: { version: 3, introduced: "design/80", recordedOn: (cp) => cp.pendingAction.kind === "tool_approval" || cp.pendingAction.kind === "plan_review", writes: "pendingAction.boundCallId + boundInputHash on a tool_approval; a plan_review carries the stamp only" }, token: { version: 5, introduced: "design/164", recordedOn: (cp) => cp.resourceLedger?.totalTokens !== undefined, writes: "resourceLedger.totalTokens" }, orgAdmission: { version: 6, introduced: "org-admission", recordedOn: (cp) => cp.state.inheritedGate?.admittedOrgScopes !== undefined || cp.state.inheritedGate?.ownAdmittedOrgScopes !== undefined || cp.state.inheritedGate?.ownAdmittedOrgWriteScope !== undefined || cp.state.inheritedGate?.orgAdmissionGoverned === true, writes: "inheritedGate.admittedOrgScopes / ownAdmittedOrgScopes / ownAdmittedOrgWriteScope / orgAdmissionGoverned", }, f012: { version: 7, introduced: "F-012", recordedOn: (cp) => cp.state.inheritedGate?.constraintChain !== undefined || cp.state.delegationProvenance !== undefined, writes: "inheritedGate.constraintChain + constraintDigest together; delegationProvenance" }, realApproval: { version: 8, introduced: "#130/#120", recordedOn: (cp) => cp.gate.kind === "irreversible_ask" && cp.gate.realApproval !== undefined, writes: "gate.realApproval (a well-formed bit) + pendingAction.requiresRealApproval; from v9: readFace.realApproval = true beside it" }, face: { version: 9, introduced: "design/199", recordedOn: (cp) => cp.state.readFace !== undefined, writes: "state.readFace { face, denyEntries? } for a non-default posture; realApproval: true only at the mint whose gate carries the bit (a hands-less re-park never carries the seed's marker forward)" }, }; export const CURRENT_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.baseline.version; export const RESOURCE_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.resource.version; export const BINDING_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.binding.version; export const TOKEN_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.token.version; export const ORG_ADMISSION_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.orgAdmission.version; export const F012_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.f012.version; export const REAL_APPROVAL_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.realApproval.version; export const FACE_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.face.version; export const MAX_SUPPORTED_CHECKPOINT_VERSION = CHECKPOINT_FEATURES.face.version; export function checkpointVersionFor(presence) { let version = CHECKPOINT_FEATURES.baseline.version; for (const feature of Object.keys(CHECKPOINT_FEATURES)) { const row = CHECKPOINT_FEATURES[feature]; if (presence[feature] === true && row.version > version) version = row.version; } return version; } export function checkpointVersionOf(cp) { return cp.version ?? 0; } function finiteBound(v) { return v !== undefined && Number.isFinite(v) ? v : undefined; } function finiteSpend(v) { return v !== undefined && Number.isFinite(v) ? v : undefined; } export function debitLedger(prior, slice, total, opts) { return { totalBudgetMicroUsd: finiteBound(prior?.totalBudgetMicroUsd) ?? finiteBound(total?.totalBudgetMicroUsd), totalTokens: finiteBound(prior?.totalTokens) ?? finiteBound(total?.totalTokens), spentMicroUsd: (finiteSpend(prior?.spentMicroUsd) ?? 0) + Math.max(0, finiteSpend(slice.costMicroUsd) ?? 0), spentTokens: (finiteSpend(prior?.spentTokens) ?? 0) + Math.max(0, finiteSpend(slice.tokens) ?? 0), spentTurns: (finiteSpend(prior?.spentTurns) ?? 0) + Math.max(0, finiteSpend(slice.turns) ?? 0), spentWalltimeMs: (finiteSpend(prior?.spentWalltimeMs) ?? 0) + Math.max(0, finiteSpend(slice.walltimeMs) ?? 0), sliceCount: (prior?.sliceCount ?? 0) + (opts?.countSlice === false ? 0 : 1), }; } export function remainingBudgetMicroUsd(ledger) { const total = ledger?.totalBudgetMicroUsd; if (total === undefined || !Number.isFinite(total)) return undefined; const spent = ledger?.spentMicroUsd; if (spent !== undefined && !Number.isFinite(spent)) return 0; return Math.max(0, total - (spent ?? 0)); } export function remainingTokens(ledger) { const total = ledger?.totalTokens; if (total === undefined || !Number.isFinite(total)) return undefined; const spent = ledger?.spentTokens; if (spent !== undefined && !Number.isFinite(spent)) return 0; return Math.max(0, total - (spent ?? 0)); } export function summarizeCheckpoint(cp) { const riskDescriptor = cp.gate.kind === "human" || cp.gate.kind === "irreversible_ask" ? cp.gate.riskDescriptor : undefined; const severity = riskDescriptor !== undefined ? riskSeverity(riskDescriptor.axes) : undefined; const tool = cp.pendingAction.kind === "tool_approval" ? cp.pendingAction : undefined; let toolInput; if (tool !== undefined) { try { const raw = JSON.stringify(tool.args); if (typeof raw === "string") { toolInput = raw.length > MAX_TOOL_INPUT_PREVIEW_CHARS ? `${raw.slice(0, MAX_TOOL_INPUT_PREVIEW_CHARS)}…` : raw; } } catch { toolInput = undefined; } } const hasBidi = tool !== undefined && (tool.hasBidiControls === true || carriesBidiControls([toolInput, tool.preview], { maxNodes: BIDI_BACKFILL_MAX_NODES, maxChars: BIDI_BACKFILL_MAX_CHARS })); return { token: cp.token, ...(cp.checkpointId !== undefined ? { checkpointId: cp.checkpointId } : {}), sessionId: cp.sessionId, scope: cp.scope, gateKind: cp.gate.kind, ...(severity !== undefined ? { severity } : {}), ...(cp.resourceLedger !== undefined ? { spentMicroUsd: cp.resourceLedger.spentMicroUsd } : {}), ...(cp.deadline !== undefined ? { deadline: cp.deadline } : {}), createdAt: cp.createdAt, ...(cp.sourceTaskId !== undefined ? { sourceTaskId: cp.sourceTaskId } : {}), ...(cp.principal !== undefined ? { principal: cp.principal } : {}), ...(tool !== undefined ? { toolCallId: tool.toolCallId, toolName: tool.toolName } : {}), ...(tool !== undefined && wireOf("park.contentKindProjection", tool) === ASK_USER_QUESTION_TOOL_NAME ? { contentKind: "content_ask" } : {}), ...(toolInput !== undefined ? { toolInput } : {}), ...(cp.state.workspaceHandle !== undefined ? { restoreMode: cp.state.workspaceHandle.restoreMode === "park_only" ? "park_only" : "snapshot" } : {}), ...(tool?.preview !== undefined ? { preview: tool.preview } : {}), ...(tool?.previewWithheld === "oversize" || tool?.previewWithheld === "unavailable" ? { previewWithheld: tool.previewWithheld } : {}), ...(tool?.requiresRealApproval === true ? { requiresRealApproval: true } : {}), ...(tool?.mandated === true ? { mandated: true } : {}), ...(tool?.authoredBy === "deployment" ? { authoredBy: "deployment" } : {}), ...(() => { const fb = readDenialLimitFallback(tool?.denialLimitFallback); return fb !== undefined ? { denialLimitFallback: fb } : {}; })(), ...(() => { const origin = tool?.origin; const mandate = tool?.mandate; return { ...(isAskOrigin(origin) ? { origin } : {}), ...(isPersistedRuleMandate(mandate) ? { mandate } : {}) }; })(), ...(hasBidi ? { hasBidiControls: true } : {}), }; } export const CHECKPOINT_CONFIG_REFUSAL_CODES = Object.freeze(["config.spec_retired_key", "config.output_style_invalid", "config.permission_mode_invalid", "config.shell_gate_value_retired"]); export const isCheckpointConfigRefusalCode = (word) => CHECKPOINT_CONFIG_REFUSAL_CODES.some((w) => w === word); export class CheckpointError extends Error { code; detail; constructor(code, message, detail) { super(message); this.code = code; this.detail = detail; this.name = "CheckpointError"; } } export function resolveDeclaredFidelity(store, storeName) { const declared = store?.fidelity; if (declared === undefined) return "json"; if (declared === "structured-clone" || declared === "json") return declared; const e = new Error(`${storeName}.fidelity declares ${JSON.stringify(declared)} — not a recognized StoreFidelity ` + `("structured-clone" | "json"). Fix the declaration; an unparseable fidelity cannot be folded to either arm.`); e.code = "config.store_fidelity_invalid"; throw e; } export function encodeAtFidelity(fidelity, value) { if (fidelity === "structured-clone") return { ok: true, value }; try { const encoded = JSON.stringify(value); return { ok: true, value: encoded === undefined ? undefined : JSON.parse(encoded) }; } catch (err) { return { ok: false, cause: err }; } } const MAX_SAME_VALUE_DEPTH = 256; export function samePlainValue(a, b) { return sameValueAt(a, b, 0, new Map(), new Map()); } function sameValueAt(a, b, depth, aToB, bToA) { if (Object.is(a, b)) return true; if (depth >= MAX_SAME_VALUE_DEPTH) return false; if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false; try { const pairedWithA = aToB.get(a); const pairedWithB = bToA.get(b); if (pairedWithA !== undefined || pairedWithB !== undefined) return pairedWithA === b && pairedWithB === a; aToB.set(a, b); bToA.set(b, a); const proto = Object.getPrototypeOf(a); if (proto !== Object.getPrototypeOf(b)) return false; if (proto !== Object.prototype && proto !== Array.prototype) return false; if (Object.isExtensible(a) !== Object.isExtensible(b)) return false; const ka = Reflect.ownKeys(a); const kb = Reflect.ownKeys(b); if (ka.length !== kb.length) return false; for (let i = 0; i < ka.length; i++) { const k = ka[i]; if (k !== kb[i]) return false; const da = Object.getOwnPropertyDescriptor(a, k); const db = Object.getOwnPropertyDescriptor(b, k); if (da === undefined || db === undefined) return false; if (!("value" in da) || !("value" in db)) return false; if (da.enumerable !== db.enumerable || da.writable !== db.writable || da.configurable !== db.configurable) return false; if (!sameValueAt(da.value, db.value, depth + 1, aToB, bToA)) return false; } return true; } catch { return false; } } export function resolveCheckpointStore(spec, deps) { if (Object.is(spec.checkpointStore, null)) throw retiredCheckpointStoreNull(); if (spec.checkpointStore === "disabled") return undefined; if (spec.checkpointStore !== undefined) { if (spec.checkpointStore.execution?.outcome !== true) throw checkpointStoreExecutionUndeclared("TaskSpec.checkpointStore", spec.checkpointStore); return spec.checkpointStore; } if (deps.checkpointStore !== undefined && deps.checkpointStore.execution?.outcome !== true) { throw checkpointStoreExecutionUndeclared("RunnerDeps.checkpointStore", deps.checkpointStore); } return deps.checkpointStore; } export function checkpointStoreExecutionUndeclared(seat, store) { const ctor = store.constructor?.name; const name = typeof ctor === "string" && ctor.length > 0 && ctor !== "Object" ? ` (${ctor})` : ""; const e = new Error(`${seat}: the wired CheckpointStore${name} does not declare \`execution = { outcome: true }\` — the execution-outcome ` + "record (recordExecutionOutcome, and reopen refusing a recorded row) is a required member of the store contract; " + "a store without it cannot record how a resumed approval was disposed, so the run is refused here rather than " + "resolving rows no reader can settle. Implement the verb and add the declaration (the in-tree stores and the " + "store-contract kit are the reference)."); e.code = "config.invalid_checkpoint_store"; return e; } export function retiredCheckpointStoreNull() { const e = new Error('TaskSpec.checkpointStore: null is not a value any more — write checkpointStore: "disabled" to run without a ' + "checkpoint store (the per-run durable off switch), or leave the field unset to use the deployment's store."); e.code = "config.invalid_checkpoint_store"; return e; } export function winnerFromOutcome(outcome) { if (outcome.gate === "plan_review" || outcome.gate === "dry_run_review") { const editedPlan = outcome.gate === "plan_review" ? outcome.editedPlan : undefined; return { boundCallId: `gate:${outcome.gate}`, decision: outcome.decision, ...(editedPlan !== undefined ? { updatedInput: editedPlan } : {}), ...(outcome.reason !== undefined ? { reason: outcome.reason } : {}), }; } if (outcome.gate !== "policy_ask") return undefined; return { boundCallId: outcome.boundCallId, decision: outcome.decision, ...(outcome.updatedInput === undefined ? {} : { updatedInput: outcome.updatedInput }), ...(outcome.answer === undefined ? {} : { answer: outcome.answer }), ...(outcome.gateOutcome === undefined ? {} : { gateOutcome: outcome.gateOutcome }), ...(outcome.reason === undefined ? {} : { reason: outcome.reason }), }; } const CHECKPOINT_CONTROL_CHARS_RE = /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/; export function validatePendingSteer(steer) { if (steer === null || typeof steer !== "object") { throw new CheckpointError("steering.invalid_content", `steering entry must be an object carrying text/trusted (got ${steer === null ? "null" : typeof steer})`); } const allowed = new Set(PENDING_STEER_FROZEN_FIELDS.filter((f) => f !== "seq")); for (const key of Object.keys(steer)) { if (!allowed.has(key)) { throw new CheckpointError("steering.invalid_content", `unknown steering field "${key}" — the persisted entry shape is frozen (${[...allowed].join(", ")}); ` + `a field this worker does not know would be dropped silently on the parked leg`); } } const text = steer.text; const trusted = steer.trusted; const actor = steer.actor; const inputId = steer.inputId; const priority = steer.priority; if (typeof text !== "string") { throw new CheckpointError("steering.invalid_content", "steering text must be a string"); } if (typeof trusted !== "boolean") { throw new CheckpointError("steering.invalid_content", "steering trusted must be a boolean stated by the caller"); } if (inputId !== undefined && typeof inputId !== "string") { throw new CheckpointError("steering.invalid_content", "steering inputId must be a string when supplied"); } if (priority !== undefined && priority !== "now" && priority !== "next" && priority !== "later") { throw new CheckpointError("steering.invalid_content", `steering priority "${typeof priority === "string" ? priority : priority === null ? "null" : typeof priority}" is outside the injection-priority domain ("now", "next", "later")`); } const actorTwin = actor === undefined ? undefined : captureActorAssertion(actor); if (inputId !== undefined && (inputId === "" || inputId.length > MAX_STEER_INPUT_ID_CHARS)) { throw new CheckpointError("steering.invalid_content", `steering inputId must be a non-empty string of at most ${MAX_STEER_INPUT_ID_CHARS} characters`); } if (sanitizeUntrustedText(text) !== text) { throw new CheckpointError("steering.invalid_content", "steering text must not contain a system-reminder break-out tag"); } if (CHECKPOINT_CONTROL_CHARS_RE.test(text)) { throw new CheckpointError("steering.invalid_content", "steering text must not contain control characters"); } if (text.length > MAX_PENDING_STEER_CHARS) { throw new CheckpointError("steering.invalid_content", `steering text must be at most ${MAX_PENDING_STEER_CHARS} characters (got ${text.length})`); } return { text, trusted, ...(actorTwin !== undefined ? { actor: actorTwin } : {}), inputId: inputId ?? uuidv7(), ...(priority !== undefined ? { priority: priority } : {}), }; } export const MAX_ACTOR_FIELD_CHARS = 256; export const MAX_STEER_INPUT_ID_CHARS = 128; export const ACTOR_ASSERTION_FROZEN_FIELDS = Object.freeze(["id", "hostAsserted", "issuer"]); function captureActorAssertion(actor) { if (actor === null || typeof actor !== "object") { throw new CheckpointError("steering.invalid_content", `actor must be an object carrying the attribution fields (got ${actor === null ? "null" : typeof actor})`); } const supplied = actor; const allowed = new Set(ACTOR_ASSERTION_FROZEN_FIELDS); for (const key of Object.keys(actor)) { if (!allowed.has(key)) { throw new CheckpointError("steering.invalid_content", `unknown actor field "${key}" — the persisted actor shape is frozen (${[...allowed].join(", ")})`); } } const id = supplied.id; const hostAsserted = supplied.hostAsserted; const issuer = supplied.issuer; if (typeof id !== "string" || id === "" || id.length > MAX_ACTOR_FIELD_CHARS) { throw new CheckpointError("steering.invalid_content", `actor.id must be a non-empty namespaced string of at most ${MAX_ACTOR_FIELD_CHARS} characters (e.g. "slack:U123")`); } if (typeof hostAsserted !== "boolean") { throw new CheckpointError("steering.invalid_content", "actor.hostAsserted must be a boolean stated by the host"); } if (issuer !== undefined && (typeof issuer !== "string" || issuer === "" || issuer.length > MAX_ACTOR_FIELD_CHARS)) { throw new CheckpointError("steering.invalid_content", `actor.issuer must be a non-empty string of at most ${MAX_ACTOR_FIELD_CHARS} characters`); } for (const [field, value] of [ ["id", id], ["issuer", issuer], ]) { if (value === undefined) continue; if (sanitizeUntrustedText(value) !== value || CHECKPOINT_CONTROL_CHARS_RE.test(value)) { throw new CheckpointError("steering.invalid_content", `actor.${field} must not contain control characters or a system-reminder break-out tag`); } } return { id, hostAsserted, ...(issuer !== undefined ? { issuer } : {}) }; } export function readPendingSteerQueue(state) { if (state.pendingSteer !== undefined) { throw new CheckpointError("checkpoint.unsupported_version", "this checkpoint carries a parked steer in the retired pre-queue single seat (`state.pendingSteer`), which this engine does not read — decide the parked instruction on the host's surface and, if it still applies, park it again with setPendingSteer", { reason: "seat_retired" }); } return [...(state.pendingSteerQueue ?? [])].sort((a, b) => a.seq - b.seq); } function samePendingSteerPayload(a, b) { return (a.text === b.text && a.trusted === b.trusted && steerPriorityOf(a) === steerPriorityOf(b) && a.actor?.id === b.actor?.id && a.actor?.hostAsserted === b.actor?.hostAsserted && a.actor?.issuer === b.actor?.issuer); } export function appendPendingSteer(state, entry) { const current = readPendingSteerQueue(state); const collision = current.find((e) => e.inputId === entry.inputId); if (collision !== undefined) { if (!samePendingSteerPayload(collision, entry)) { throw new CheckpointError("steering.duplicate_input_id", `a different steering instruction is already parked under inputId "${entry.inputId}" — ` + `re-issue this one with a fresh inputId (an identical payload would have been an idempotent retry)`); } return current; } const nextSeq = current.reduce((max, e) => Math.max(max, e.seq), 0) + 1; const next = [...current, { ...entry, seq: nextSeq }]; const totalEntries = next.length; if (totalEntries > MAX_PENDING_STEER_ENTRIES) { throw new CheckpointError("steering.queue_full", `the parked steering queue already holds ${totalEntries - 1} entries (max ${MAX_PENDING_STEER_ENTRIES}) — ` + `deliver or remove a parked steer before adding another`); } const bytes = Buffer.byteLength(JSON.stringify({ pendingSteerQueue: next }), "utf8"); if (bytes > PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES) { throw new CheckpointError("steering.queue_full", `the parked steering queue would serialize to ${bytes} bytes (max ${PENDING_STEER_QUEUE_BYTE_BUDGET_BYTES}) — ` + `deliver or remove a parked steer before adding another`); } return next; } export function checkpointRowMatches(cp, scope, status) { return cp !== undefined && cp.scope === scope && cp.status === status; } export function checkpointOccMatches(cp, expect) { return expect === undefined || (cp.rev ?? 0) === expect.rev; } export class InMemoryCheckpointStore { retention = "none"; durability = "process-local"; fidelity = "structured-clone"; redecision = { reopen: true }; execution = { outcome: true }; cps = new Map(); fault = null; async put(token, cp) { if (this.cps.has(token)) { throw new CheckpointError("checkpoint.already_exists", `checkpoint token already exists`); } this.cps.set(token, structuredClone(cp)); } async get(token) { const cp = this.cps.get(token); return cp ? structuredClone(cp) : null; } claimLossFrom(cp, scope) { if (cp === undefined || cp.scope !== scope) return { claimed: false, current: { status: "absent" } }; return { claimed: false, current: { status: cp.status, rev: cp.rev ?? 0, ...(cp.resolvedOutcome !== undefined ? { resolvedOutcome: structuredClone(cp.resolvedOutcome) } : {}), }, }; } claimResolveCore(token, scope, outcome, expect) { const cp = this.cps.get(token); if (!checkpointRowMatches(cp, scope, "pending")) { return this.claimLossFrom(cp, scope); } if (!checkpointOccMatches(cp, expect)) { return this.claimLossFrom(cp, scope); } const winner = winnerFromOutcome(outcome); const winnerClone = winner ? structuredClone(winner) : undefined; cp.status = "resolved"; cp.rev = (cp.rev ?? 0) + 1; if (winnerClone) cp.resolvedOutcome = winnerClone; cp.reopenReason = undefined; return { claimed: true }; } claimExpireCore(token, scope) { const cp = this.cps.get(token); if (!checkpointRowMatches(cp, scope, "pending")) { return this.claimLossFrom(cp, scope); } cp.status = "expired"; return { claimed: true }; } async resolve(token, scope, outcome, expect) { if (this.fault === "resolve-before-commit") { this.fault = null; throw new Error("injected fault: resolve before commit"); } if (!checkpointRowMatches(this.cps.get(token), scope, "pending")) { return false; } const out = this.claimResolveCore(token, scope, outcome, expect); if (out.claimed && this.fault === "resolve-after-commit") { this.fault = null; throw new Error("injected fault: resolve after commit"); } return out.claimed; } async claimTerminal(token, scope, intent) { if (this.fault === "claim-before-commit" || (intent.kind === "resolve" && this.fault === "resolve-before-commit")) { const name = this.fault === "claim-before-commit" ? "claim" : "resolve"; this.fault = null; throw new Error(`injected fault: ${name} before commit`); } const out = intent.kind === "resolve" ? this.claimResolveCore(token, scope, intent.outcome, intent.expect) : this.claimExpireCore(token, scope); if (out.claimed && (this.fault === "claim-after-commit" || (intent.kind === "resolve" && this.fault === "resolve-after-commit"))) { const name = this.fault === "claim-after-commit" ? "claim" : "resolve"; this.fault = null; throw new Error(`injected fault: ${name} after commit`); } return out; } async recordExecutionOutcome(token, scope, gate) { const cp = this.cps.get(token); const disposition = executionRecordDisposition(cp, scope, gate); if (disposition === "conflict") throw new ExecutionOutcomeConflictError(cp.executionOutcome, gate); if (disposition !== "commit") return disposition; const record = structuredClone(gate); cp.executionOutcome = record; cp.executionAtMs = Date.now(); return "recorded"; } async reopen(token, scope, reason) { const cp = this.cps.get(token); if (!checkpointRowMatches(cp, scope, "resolved") || checkpointExecutionRecorded(cp)) { return false; } cp.status = "pending"; cp.rev = (cp.rev ?? 0) + 1; cp.reopenReason = reason; return true; } async setPendingSteer(token, scope, steer) { const clean = validatePendingSteer(steer); const cp = this.cps.get(token); if (!checkpointRowMatches(cp, scope, "pending")) { return false; } cp.state.pendingSteerQueue = appendPendingSteer(cp.state, clean); return true; } async expire(token, scope) { if (!checkpointRowMatches(this.cps.get(token), scope, "pending")) { return false; } return this.claimExpireCore(token, scope).claimed; } async reap(scope, cutoff) { let n = 0; for (const cp of this.cps.values()) { const deadlinePassed = cp.deadline !== undefined && (Number.isFinite(cp.deadline) ? cp.deadline <= cutoff : true); if (cp.scope === scope && cp.status === "pending" && deadlinePassed) { cp.status = "expired"; n++; } } return n; } async listByScope(scope) { const out = []; for (const cp of this.cps.values()) { if (cp.scope === scope && cp.status === "pending") out.push(summarizeCheckpoint(cp)); } return out; } async listScopes() { const out = new Set(); for (const cp of this.cps.values()) if (cp.status === "pending") out.add(cp.scope); return [...out]; } testInjectFault(mode) { this.fault = mode; } get size() { return this.cps.size; } } const RETIRED_MODE_SEED_MEMBERS = Object.freeze([ ["autoModeRequested", () => true], ["approverPosture", () => true], ["shellGate", (v) => v !== "always"], ]); export function refuseRetiredModeSeed(state) { const gate = state.inheritedGate; if (gate === undefined) return; for (const [key, retired] of RETIRED_MODE_SEED_MEMBERS) { const value = gate[key]; if (value === undefined || !retired(value)) continue; const shown = typeof value === "string" ? JSON.stringify(value.slice(0, 40)) : typeof value === "boolean" ? String(value) : typeof value; throw new CheckpointError("checkpoint.unsupported_version", `this checkpoint's inheritedGate carries the retired mode-seed member \`${key}\` (${shown}), written before 7.34.0 and read by no engine since 7.39.0 — resume it once on an engine at 7.38.x or earlier (which reads it into \`permissionMode\`), or expire the row (\`CheckpointStore.expire\`); nothing was consumed`, { reason: "seat_retired" }); } } export function recordedModeSeed(gate) { if (gate === undefined) return {}; const refusal = (message) => { const e = new Error(message); e.code = "config.permission_mode_invalid"; return e; }; const { permissionMode, prePlanMode, shellGate } = gate; if (permissionMode !== undefined && !isPermissionMode(permissionMode)) throw refusal(`the checkpoint row's inheritedGate.permissionMode is ${JSON.stringify(permissionMode)}, not a permission mode — the row cannot be resumed under a mode this engine does not know`); if (prePlanMode !== undefined && (!isPermissionMode(prePlanMode) || prePlanMode === "plan")) throw refusal(`the checkpoint row's inheritedGate.prePlanMode is ${JSON.stringify(prePlanMode)}, not a permission mode a plan can return to`); return { ...(permissionMode !== undefined ? { permissionMode } : {}), ...(prePlanMode !== undefined ? { prePlanMode } : {}), ...(shellGate !== undefined ? { shellGate } : {}) }; }