@sema-agent/core
Version:
Stateless, task-oriented AI agent core
273 lines (272 loc) • 13.5 kB
JavaScript
import { boundInputHashOf, canonicalize } from "./canonical-json.js";
import { mintCheckpointId, mintCheckpointToken, resolveCheckpointStore, resolveDeclaredFidelity } from "./checkpoint-store.js";
import { stampCheckpointRequirements } from "./checkpoint-requirements.js";
import { resolveDeclaredDurability } from "./wiring-manifest.js";
export const PARK_SELFCHECK_SCOPE_PREFIX = "sema:park-selfcheck:";
export const PARK_SELFCHECK_STEP_TIMEOUT_MS = 10_000;
export const PARK_SELFCHECK_ROW_TTL_MS = 60_000;
async function within(op, step) {
let timer;
try {
return await Promise.race([
Promise.resolve()
.then(op)
.then((ok) => ({ ok }))
.catch((threw) => ({ threw })),
new Promise((resolve) => {
timer = setTimeout(() => resolve({ timedOut: `${step} did not answer within ${PARK_SELFCHECK_STEP_TIMEOUT_MS}ms — a store that neither answers nor errors is the failure this probe exists to surface, not one it may wait on` }), PARK_SELFCHECK_STEP_TIMEOUT_MS);
}),
]);
}
finally {
if (timer !== undefined)
clearTimeout(timer);
}
}
function declaresDurable(store, name) {
try {
return resolveDeclaredDurability(store, name) === "durable";
}
catch {
return false;
}
}
export function durableParkGapOf(halves) {
if (!halves.checkpointWired)
return undefined;
if (halves.checkpointDurable && halves.sessionDurable)
return undefined;
if (halves.checkpointDurable && !halves.sessionDurable) {
return ("this deployment wires a checkpoint store that declares durability but a session store that does not " +
"(RunnerDeps.sessionStore — absent means the built-in in-memory store): a durable park needs BOTH halves, " +
"so a parked approval survives the restart while the conversation it resumes into does not, and a resume " +
"arriving afterwards finds the checkpoint and not the session");
}
if (!halves.checkpointDurable && halves.sessionDurable) {
return ("this deployment wires a session store that declares durability but a checkpoint store that does not " +
"(RunnerDeps.checkpointStore.durability): a durable park needs BOTH halves, so the conversation survives " +
"the restart while the parked approval that was to resume it does not");
}
return undefined;
}
export function durableParkGapFor(deps, spec = {}) {
const checkpointStore = resolveCheckpointStore(spec, deps);
return durableParkGapOf({
checkpointWired: checkpointStore !== undefined,
checkpointDurable: declaresDurable(checkpointStore, "checkpointStore"),
sessionDurable: declaresDurable(deps.sessionStore, "sessionStore"),
});
}
function syntheticCheckpoint(scope, fidelity) {
return stampCheckpointRequirements({
token: mintCheckpointToken(),
checkpointId: mintCheckpointId(),
scope,
sessionId: `${scope}:session`,
leafId: `${scope}:leaf`,
gate: { kind: "human", reason: "park wiring self-check (design/252 G-6) — no person is being asked", toolName: "SelfCheck" },
pendingAction: {
kind: "tool_approval",
toolCallId: `${scope}:call`,
toolName: "SelfCheck",
args: { probe: true, nested: { depth: 2, list: [1, 2, 3] } },
boundInputHash: boundInputHashOf({ probe: true, nested: { depth: 2, list: [1, 2, 3] } }),
hasBidiControls: true,
preview: { probe: true, note: "park wiring self-check display stub" },
previewWithheld: "oversize",
requiresRealApproval: true,
mandated: true,
denialLimitFallback: { consecutive: 3, total: 3, limit: "consecutive", autoDenyAfterMs: 0 },
origin: "denial_limit_fallback",
askClass: "denial_limit_fallback",
classes: ["denial_limit_fallback"],
batchToolCallIds: [`${scope}:call`],
completedCallIds: [],
},
state: { activeTools: ["SelfCheck"], nestedStats: { tokens: 0, turns: 0, tasks: 0, costMicroUsd: 0, anyUnpriced: false } },
status: "pending",
createdAt: Date.now(),
suspendCount: 1,
suspendedAt: Date.now(),
resourceLedger: { spentMicroUsd: 0, spentTokens: 0, spentTurns: 0, sliceCount: 1 },
humanReview: { count: 1, totalWaitMs: 0, gates: [{ kind: "human", waitMs: 0, decision: "approve", toolName: "SelfCheck", toolCallId: `${scope}:selfcheck-call`, toolArg: "park self-check probe" }] },
sourceTaskId: `${scope}:task`,
principal: `${scope}:principal`,
durableApproval: { scope, ttlMs: PARK_SELFCHECK_ROW_TTL_MS },
deadline: Date.now() + PARK_SELFCHECK_ROW_TTL_MS,
}, fidelity);
}
function faithfulnessDelta(sent, got) {
const project = (cp) => ({
token: cp.token,
checkpointId: cp.checkpointId,
scope: cp.scope,
sessionId: cp.sessionId,
leafId: cp.leafId,
gate: cp.gate,
pendingAction: cp.pendingAction,
state: cp.state,
deadline: cp.deadline,
createdAt: cp.createdAt,
version: cp.version,
requires: cp.requires,
requirementsDigest: cp.requirementsDigest,
suspendCount: cp.suspendCount,
suspendedAt: cp.suspendedAt,
resourceLedger: cp.resourceLedger,
humanReview: cp.humanReview,
sourceTaskId: cp.sourceTaskId,
principal: cp.principal,
durableApproval: cp.durableApproval,
});
const a = canonicalize(project(sent));
const b = canonicalize(project(got));
return a === b ? undefined : `the row came back different from the row that was filed (sent ${a}; read ${b})`;
}
export async function probeParkRoundTrip(deps, spec = {}) {
const gap = durableParkGapFor(deps, spec);
const gapCell = gap !== undefined ? { durableTopologyGap: gap } : {};
const store = resolveCheckpointStore(spec, deps);
if (store === undefined) {
return {
verdict: "not_probed",
findings: [],
summary: "no checkpoint store is wired on this assembly — there is no park lane to probe (the manifest reports the same fact as parkLane.capable: false)",
...gapCell,
};
}
const scope = `${PARK_SELFCHECK_SCOPE_PREFIX}${mintCheckpointToken()}`;
let fidelity;
try {
fidelity = resolveDeclaredFidelity(store, "checkpointStore");
}
catch {
const detail = "the checkpoint backend declares an unrecognized encoding fidelity — a park refuses rather than guess which values survive it";
return { verdict: "failed", findings: [{ code: "put_failed", detail }], scope, summary: `the park lane failed its round-trip self-check at "put_failed": ${detail}`, ...gapCell };
}
const cp = syntheticCheckpoint(scope, fidelity);
const said = (err) => {
try {
const m = err instanceof Error ? err.message : undefined;
return typeof m === "string" ? m : `a ${typeof err} the store threw`;
}
catch {
return "a value the store threw that could not be described";
}
};
const shown = (v) => {
try {
return typeof v === "string" ? JSON.stringify(v) : `a ${typeof v}`;
}
catch {
return "an undescribable value";
}
};
const fenceQuietly = async () => {
await within(async () => {
try {
await store.expire(cp.token, scope);
}
catch {
}
}, "the cleanup fence");
};
const failed = async (code, detail) => {
await fenceQuietly();
return { verdict: "failed", findings: [{ code, detail }], scope, summary: `the park lane failed its round-trip self-check at "${code}": ${detail}`, ...gapCell };
};
let putStarted;
const put = await within(() => {
const p = Promise.resolve().then(() => store.put(cp.token, cp));
putStarted = p;
return p;
}, "put");
if ("timedOut" in put) {
void putStarted?.catch(() => { }).then(() => store.expire(cp.token, scope)).catch(() => { });
return await failed("put_failed", put.timedOut);
}
if ("threw" in put)
return await failed("put_failed", `the checkpoint store refused to file a synthetic park: ${said(put.threw)}`);
const first = await within(() => store.get(cp.token), "get");
if ("timedOut" in first)
return await failed("row_not_readable", first.timedOut);
if ("threw" in first)
return await failed("row_not_readable", `the checkpoint store threw reading back the row it had just accepted: ${said(first.threw)}`);
const read = first.ok;
if (read === null)
return await failed("row_not_readable", "the checkpoint store accepted the row and then answered null for its own token — a park filed here would be unresumable");
if (typeof read !== "object")
return await failed("row_not_readable", `the checkpoint store answered ${read === undefined ? "undefined" : typeof read} for its own token — neither a checkpoint nor the absence of one`);
let delta;
let status;
try {
delta = faithfulnessDelta(cp, read);
status = read.status;
}
catch (err) {
return await failed("row_not_faithful", `the row the store returned could not be read for comparison: ${said(err)}`);
}
if (delta !== undefined)
return await failed("row_not_faithful", delta);
if (status !== "pending")
return await failed("row_not_pending", `the filed row came back with status ${shown(status)} — a park in any other status is one nobody can resolve`);
const enumerable = store.listByScope !== undefined;
if (store.listByScope !== undefined) {
const listByScope = store.listByScope.bind(store);
const listed = await within(() => listByScope(scope), "listByScope");
if ("timedOut" in listed)
return await failed("row_not_enumerable", listed.timedOut);
if ("threw" in listed)
return await failed("row_not_enumerable", `listByScope threw for the probe's own scope: ${said(listed.threw)}`);
let present;
try {
present = Array.isArray(listed.ok) && listed.ok.some((row) => row?.token === cp.token);
}
catch (err) {
return await failed("row_not_enumerable", `the listByScope result could not be read: ${said(err)}`);
}
if (!present)
return await failed("row_not_enumerable", `listByScope("${scope}") did not include the pending row it holds — an inbox enumerating this scope would show no approvals`);
}
const fence = await within(() => store.expire(cp.token, scope), "expire");
if ("timedOut" in fence)
return await failed("fence_failed", fence.timedOut);
if ("threw" in fence)
return await failed("fence_failed", `expire threw on the probe's own pending row: ${said(fence.threw)}`);
const fenced = fence.ok === true;
const second = await within(() => store.get(cp.token), "get (after the fence)");
if ("timedOut" in second)
return await failed("fence_not_durable", second.timedOut);
if ("threw" in second)
return await failed("fence_not_durable", `the store threw re-reading the fenced row: ${said(second.threw)}`);
const after = second.ok;
let afterStatus;
if (after !== null) {
if (typeof after !== "object")
return await failed("fence_not_durable", `the store answered ${after === undefined ? "undefined" : typeof after} re-reading the fenced row — neither a checkpoint nor the absence of one`);
try {
afterStatus = after.status;
}
catch (err) {
return await failed("fence_not_durable", `the fenced row's status could not be read: ${said(err)}`);
}
if (afterStatus !== "expired") {
return await failed(fenced ? "fence_not_durable" : "fence_failed", fenced
? `expire reported a win and the row reads ${shown(afterStatus)} — the contract's transition is pending → expired, so the CAS did not land`
: `expire lost an UNCONTENDED CAS and the row reads ${shown(afterStatus)} — the fence that keeps a checkpoint from being both reaped and resumed does not close here`);
}
}
const steps = `filed, read back${enumerable ? ", enumerated" : ""} and fenced`;
const notExercised = enumerable ? "" : " (this store implements no listByScope, so the inbox enumeration was NOT exercised)";
const casNote = fenced ? "" : " (the expire CAS reported a loss while the row closed — consistent with store housekeeping, but a backend that mis-reports CAS wins is not distinguished here)";
return {
verdict: "round_trip_ok",
findings: [],
...(fenced ? {} : { casLossObserved: true }),
scope,
summary: after === null
? `the park lane ${steps} a synthetic checkpoint${notExercised} — the row is no longer present (a deleting backend or its own housekeeping removed it), so nothing resumable remains${casNote}`
: `the park lane ${steps} a synthetic checkpoint${notExercised} — residual expired row in scope "${scope}"${casNote}`,
...gapCell,
};
}