UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

930 lines (929 loc) • 43.4 kB
import { createHash } from "node:crypto"; import { closeSync, existsSync, fsyncSync, linkSync, lstatSync, openSync, readFileSync, readdirSync, renameSync, unlinkSync, writeFileSync } from "node:fs"; import { basename, dirname, join } from "node:path"; import { QUARANTINE_DIR, appendChallengeEvents, enqueueMemoryAnnouncement, ensureDirExists, v1MemoryPathKeyResolver, lineageContributionsOfSession, lockedStrictUpdate, markSessionPolluted, readProjectionDebts, readSessionPollution, readStrictSidecar, ControlPlaneCorruptError } from "./layout.js"; import { thrownText } from "../thrown-value.js"; export const DELEGATION_SETTLEMENT_FILE = "delegation-settlement.json"; function reqStr(v) { return typeof v === "string" && v.length > 0; } function safeBasename(v) { return typeof v === "string" && v.length > 0 && !v.includes("/") && !v.includes("\\") && v !== "." && v !== ".."; } function safeRelPath(v) { if (typeof v !== "string" || v.length === 0 || v.startsWith("/") || v.startsWith("\\") || /^[A-Za-z]:/.test(v)) return false; return v.split(/[\/\\]/).every((seg) => seg.length > 0 && seg !== "." && seg !== ".."); } const SETTLEMENT_EVENT_STATUSES = new Set(["clean", "external", "expired", "void", "unattestable"]); function coerceSettlement(raw) { if (raw === undefined) return { version: 1, rows: [], events: [], effects: {} }; const rec = raw; if (typeof rec !== "object" || rec === null || !Array.isArray(rec.rows) || !Array.isArray(rec.events) || typeof rec.effects !== "object" || rec.effects === null || Array.isArray(rec.effects)) { throw new ControlPlaneCorruptError("memory delegation-settlement ledger has the wrong shape"); } if (rec.version !== 1) throw new ControlPlaneCorruptError(`memory delegation-settlement ledger has an unrecognized version (${String(rec.version)}) — refusing (fail-closed)`); for (const r of rec.rows) { const row = r; if (typeof row !== "object" || row === null || !reqStr(row.settleId) || !reqStr(row.sessionId) || typeof row.launchedAt !== "number" || !Number.isFinite(row.launchedAt) || (row.lane !== "background" && row.lane !== "sync") || (row.status !== "pending" && row.status !== "unattestable") || (row.toolUseId !== undefined && !reqStr(row.toolUseId))) { throw new ControlPlaneCorruptError("memory delegation-settlement ledger: a row is malformed (unknown status/lane, missing id, or a non-finite timestamp) — refusing (fail-closed; an unevaluable row must not fold as clean)"); } } for (const e of rec.events) { const ev = e; const kindOk = ev?.kind === "settle" || ev?.kind === "admin-resolve" || ev?.kind === "annotation"; const statusOk = ev?.status === undefined || SETTLEMENT_EVENT_STATUSES.has(ev.status); if (typeof ev !== "object" || ev === null || !reqStr(ev.settleId) || !reqStr(ev.eventId) || typeof ev.at !== "number" || !Number.isFinite(ev.at) || !kindOk || !statusOk || (ev.kind === "settle" && ev.status === undefined) || (ev.kind === "admin-resolve" && (ev.status === undefined || !reqStr(ev.requestId)))) { throw new ControlPlaneCorruptError("memory delegation-settlement ledger: an event is malformed (unknown kind/status, missing ids, an unattributed admin ruling, or a non-finite timestamp) — refusing (fail-closed)"); } } for (const [k, v] of Object.entries(rec.effects)) { if (!reqStr(k) || !reqStr(v)) throw new ControlPlaneCorruptError("memory delegation-settlement ledger: an effects watermark entry is malformed — refusing (fail-closed)"); } return rec; } export function syncSettleId(sessionId, toolCallId) { return `sync:${encodeURIComponent(sessionId)}:${encodeURIComponent(toolCallId)}`; } export function registerDelegationLaunch(controlDir, input) { lockedStrictUpdate(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger", coerceSettlement, (rec) => { if (rec.rows.some((r) => r.settleId === input.settleId)) return { result: undefined }; rec.rows.push({ settleId: input.settleId, sessionId: input.sessionId, launchedAt: input.now(), lane: "background", status: "pending", ...(input.toolUseId !== undefined ? { toolUseId: input.toolUseId } : {}) }); return { next: rec, result: undefined }; }); } export function recordSyncUnattestable(controlDir, input) { const settleId = syncSettleId(input.sessionId, input.toolCallId); lockedStrictUpdate(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger", coerceSettlement, (rec) => { if (rec.rows.some((r) => r.settleId === settleId)) return { result: undefined }; rec.rows.push({ settleId, sessionId: input.sessionId, launchedAt: input.now(), lane: "sync", status: "unattestable" }); return { next: rec, result: undefined }; }); } export function settleDelegation(controlDir, input) { const eventId = input.eventId ?? `settle:${input.settleId}:${input.status}`; lockedStrictUpdate(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger", coerceSettlement, (rec) => { if (rec.events.some((e) => e.eventId === eventId)) return { result: undefined }; rec.events.push({ settleId: input.settleId, eventId, at: input.now(), kind: "settle", status: input.status, ...(input.note !== undefined ? { note: input.note } : {}) }); return { next: rec, result: undefined }; }); } export function resolveSettlementRecord(controlDir, input) { if (typeof input.requestId !== "string" || input.requestId.length === 0) { const e = new Error("resolveSettlement requires a non-empty requestId (the audit attribution of who resolved) — refused, never defaulted."); e.code = "memory.settlement_resolve_unattributed"; throw e; } if (input.to !== "clean" && input.to !== "external") { const e = new Error(`resolveSettlement verdict must be "clean" or "external" (got ${JSON.stringify(input.to)}) — refused loudly, never folded.`); e.code = "memory.settlement_resolve_invalid"; throw e; } const eventId = `admin:${input.requestId}:${input.settleId}:${input.to}`; lockedStrictUpdate(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger", coerceSettlement, (rec) => { if (!rec.rows.some((r) => r.settleId === input.settleId)) { const e = new Error(`resolveSettlement: unknown settleId ${JSON.stringify(input.settleId)}`); e.code = "memory.settlement_resolve_unknown"; throw e; } if (rec.events.some((e2) => e2.eventId === eventId)) return { result: undefined }; rec.events.push({ settleId: input.settleId, eventId, at: input.now(), kind: "admin-resolve", status: input.to, requestId: input.requestId }); return { next: rec, result: undefined }; }); } function foldOne(row, events) { let effective = row.status; let everExternal = false; let terminalEventId; let adminRuled = false; for (const e of events) { const s = e.status; if (s === undefined) continue; if (e.kind === "settle") { if (s === "external") { everExternal = true; if (effective !== "external" && (effective !== "clean" || adminRuled)) { effective = "external"; terminalEventId = e.eventId; } } else if (s === "clean" || s === "void") { if (effective === "pending") { effective = s; terminalEventId = e.eventId; } } else if (s === "expired" || s === "unattestable") { if (effective === "pending") { effective = s; terminalEventId = e.eventId; } } } else if (e.kind === "admin-resolve") { adminRuled = true; if (s === "external") { everExternal = true; effective = "external"; terminalEventId = e.eventId; } else if (s === "clean") { effective = "clean"; terminalEventId = e.eventId; } } } return { row, effective, everExternal, ...(terminalEventId !== undefined ? { terminalEventId } : {}) }; } export function effectiveSettlements(controlDir) { const rec = coerceSettlement(readStrictSidecar(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger")); const bySettle = new Map(); for (const e of rec.events) { const arr = bySettle.get(e.settleId); if (arr === undefined) bySettle.set(e.settleId, [e]); else arr.push(e); } return rec.rows.map((row) => foldOne(row, bySettle.get(row.settleId) ?? [])); } export function sessionSettlements(controlDir, sessionId) { return effectiveSettlements(controlDir).filter((s) => s.row.sessionId === sessionId); } export function classifySessionSettlements(rows) { let sawPending = false; let exposedCause; let reason; for (const s of rows) { if (s.effective === "external") { exposedCause = "observed"; reason = "a delegated child of this session settled with an observed external-content attestation"; break; } if (s.effective === "unattestable" || s.effective === "expired") { if (exposedCause === undefined) { exposedCause = "static"; reason = s.effective === "unattestable" ? "a delegation of this session delivered without a provable attestation (permanently unprovable is not clean)" : "a delegation of this session never settled inside its evidence window (expired unprovable is not clean)"; } continue; } if (s.effective === "pending") sawPending = true; } if (exposedCause !== undefined) return { state: "exposed", cause: exposedCause, ...(reason !== undefined ? { reason } : {}) }; if (sawPending) return { state: "pending" }; return { state: "clean" }; } export function expireOverdueSettlements(controlDir, input) { const overdue = effectiveSettlements(controlDir).filter((s) => s.effective === "pending" && input.now() - s.row.launchedAt > input.timeoutMs); for (const s of overdue) settleDelegation(controlDir, { settleId: s.row.settleId, status: "expired", now: input.now }); return overdue.map((s) => s.row.settleId); } export function replayExternalSettlementEffects(controlDir, input) { const applied = []; const folded = effectiveSettlements(controlDir).filter((s) => s.effective === "external" && s.terminalEventId !== undefined); if (folded.length === 0) return applied; const rec = coerceSettlement(readStrictSidecar(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger")); for (const s of folded) { if (rec.effects[s.row.settleId] === s.terminalEventId) continue; const sessionId = s.row.sessionId; const outcome = markSessionPolluted(controlDir, sessionId, "a delegated child of this session settled external after launch (delegation settlement account)", input.now, "observed"); if (outcome === "unpersisted") continue; try { const swept = lineageContributionsOfSession(controlDir, sessionId); const contributions = input.carry ? swept.filter((c) => c.marked !== true) : swept; appendChallengeEvents(controlDir, contributions.map((c) => ({ eventId: `settlement:${s.row.settleId}:${s.terminalEventId}:${c.entryId}`, entryId: c.entryId, reason: "challenged: the contributing session's delegation settled external", challengedRev: c.lastRev, })), input.now); } catch { continue; } try { enqueueMemoryAnnouncement(controlDir, { kind: "gate", at: input.now(), items: [`delegation settlement: a background delegation of session ${JSON.stringify(sessionId)} settled EXTERNAL after launch — the session is marked and its unmarked committed contributions are challenged`], }); } catch { } lockedStrictUpdate(controlDir, DELEGATION_SETTLEMENT_FILE, "memory delegation-settlement ledger", coerceSettlement, (r) => { r.effects[s.row.settleId] = s.terminalEventId; return { next: r, result: undefined }; }); applied.push({ settleId: s.row.settleId, sessionId }); } return applied; } export const SESSION_ACCOUNTS_FILE = "session-accounts.json"; function malformedAccountRow(row) { return (typeof row !== "object" || row === null || !reqStr(row.sessionId) || typeof row.openedAt !== "number" || !Number.isFinite(row.openedAt) || !Array.isArray(row.unattributed) || (row.closedAt !== undefined && (typeof row.closedAt !== "number" || !Number.isFinite(row.closedAt))) || (row.terminatedAt !== undefined && (typeof row.terminatedAt !== "number" || !Number.isFinite(row.terminatedAt))) || (row.leg !== undefined && !reqStr(row.leg)) || (row.unadjudicated !== undefined && row.unadjudicated !== true)); } function isUnattributedMember(x) { return typeof x === "object" && x !== null && reqStr(x.scope) && safeRelPath(x.rel); } function coerceSessionAccounts(raw) { if (raw === undefined) return { version: 2, rows: [] }; const rec = raw; if (typeof rec !== "object" || rec === null || !Array.isArray(rec.rows)) throw new ControlPlaneCorruptError("memory session-account ledger has the wrong shape"); if (rec.version !== 1 && rec.version !== 2) throw new ControlPlaneCorruptError(`memory session-account ledger has an unrecognized version (${String(rec.version)}) — refusing (fail-closed)`); const bad = () => { throw new ControlPlaneCorruptError("memory session-account ledger: a row is malformed — refusing (fail-closed; an unevaluable row must not read as adjudicated)"); }; const rows = rec.rows; for (const r of rows) { const row = r; if (malformedAccountRow(row)) bad(); const members = Array.isArray(row.unattributed) ? row.unattributed : bad(); if (rec.version === 1) { if (members.some((x) => typeof x !== "string")) bad(); } else { if (!members.every(isUnattributedMember)) bad(); if (row.unattributable !== undefined && (!Array.isArray(row.unattributable) || row.unattributable.some((x) => typeof x !== "string"))) bad(); if (row.writeScope !== undefined && !reqStr(row.writeScope)) bad(); } } return rec.version === 1 ? { version: 1, rows: rows } : { version: 2, rows: rows }; } function convertSessionAccounts(read, controlDir) { if (read.version === 2) return { rec: read, converted: false }; const resolve = v1MemoryPathKeyResolver(controlDir); const rows = read.rows.map((r) => { const unattributed = []; const unattributable = []; for (const relPath of r.unattributed) { const key = resolve(relPath); if (key === undefined) unattributable.push(relPath); else unattributed.push(key); } return { sessionId: r.sessionId, openedAt: r.openedAt, unattributed, ...(unattributable.length > 0 ? { unattributable } : {}), ...(r.closedAt !== undefined ? { closedAt: r.closedAt } : {}), ...(r.unadjudicated !== undefined ? { unadjudicated: r.unadjudicated } : {}), }; }); return { rec: { version: 2, rows }, converted: true }; } export function convertV1SidecarKeys(controlDir) { readProjectionDebts(controlDir); readHolds(controlDir); readSessionAccountsConverted(controlDir); } function readSessionAccountsConverted(controlDir) { const read = coerceSessionAccounts(readStrictSidecar(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger")); if (read.version === 2) return read; return lockedStrictUpdate(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger", coerceSessionAccounts, (again) => { const { rec, converted } = convertSessionAccounts(again, controlDir); return converted ? { next: rec, result: rec } : { result: rec }; }); } export function foreignDanglingSessionAccounts(controlDir, selfSessionId) { const rec = readSessionAccountsConverted(controlDir); return rec.rows.filter((r) => r.sessionId !== selfSessionId && (r.closedAt === undefined || r.unadjudicated === true)); } export function openLayerWriters(controlDir, selfLeg) { const open = readSessionAccountsConverted(controlDir).rows.filter((r) => (selfLeg === undefined || r.leg !== selfLeg) && (r.writeScope !== undefined ? r.terminatedAt === undefined : r.closedAt === undefined)); return { scopes: new Set(open.flatMap((r) => (r.writeScope !== undefined ? [r.writeScope] : []))), unscoped: open.filter((r) => r.writeScope === undefined).length }; } export function sessionAccountLeg(controlDir, sessionId) { return readSessionAccountsConverted(controlDir).rows.find((r) => r.sessionId === sessionId)?.leg; } export function sessionAccountWriteHome(controlDir, sessionId) { const read = coerceSessionAccounts(readStrictSidecar(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger")); if (read.version !== 2) return undefined; const row = read.rows.find((r) => r.sessionId === sessionId); return row?.writeScope === undefined ? undefined : { writeScope: row.writeScope, openedAt: row.openedAt }; } export function emptyUnattributedSet() { return { has: () => false, empty: true }; } function memberKey(scope, rel) { return JSON.stringify([scope, rel]); } export function openSessionAccount(controlDir, input) { lockedStrictUpdate(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger", coerceSessionAccounts, (read) => { const { rec } = convertSessionAccounts(read, controlDir); const row = rec.rows.find((r) => r.sessionId === input.sessionId); if (row !== undefined && input.writeScope !== undefined) row.writeScope = input.writeScope; if (row !== undefined) { delete row.terminatedAt; if (input.leg !== undefined) row.leg = input.leg; else delete row.leg; } if (row === undefined) { rec.rows.push({ sessionId: input.sessionId, openedAt: input.now(), ...(input.writeScope !== undefined ? { writeScope: input.writeScope } : {}), ...(input.leg !== undefined ? { leg: input.leg } : {}), unattributed: [...input.unattributed] }); } else if (row.closedAt !== undefined && row.unadjudicated === undefined) { row.openedAt = input.now(); delete row.closedAt; row.unattributed = [...input.unattributed]; } else { row.openedAt = input.now(); delete row.closedAt; delete row.unadjudicated; const merged = new Map(row.unattributed.map((m) => [memberKey(m.scope, m.rel), m])); for (const m of input.unattributed) merged.set(memberKey(m.scope, m.rel), { scope: m.scope, rel: m.rel }); row.unattributed = [...merged.values()]; } return { next: rec, result: undefined }; }); } export function sessionUnattributedSet(controlDir, sessionId) { const row = readSessionAccountsConverted(controlDir).rows.find((r) => r.sessionId === sessionId); if (row === undefined) return emptyUnattributedSet(); const all = (row.unattributable?.length ?? 0) > 0; const keys = new Set(row.unattributed.map((m) => memberKey(m.scope, m.rel))); return { has: (scope, rel) => all || keys.has(memberKey(scope, rel.split("\\").join("/"))), empty: !all && keys.size === 0 }; } export function closeSessionAccount(controlDir, input) { return lockedStrictUpdate(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger", coerceSessionAccounts, (read) => { const { rec } = convertSessionAccounts(read, controlDir); const row = rec.rows.find((r) => r.sessionId === input.sessionId); if (row === undefined) return { result: "absent" }; if (input.leg !== undefined && row.leg !== input.leg) return { result: "stale" }; row.closedAt = input.now(); delete row.unadjudicated; for (const r of rec.rows) delete r.unadjudicated; return { next: rec, result: "written" }; }); } export function terminateSessionAccount(controlDir, input) { return lockedStrictUpdate(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger", coerceSessionAccounts, (read) => { const { rec } = convertSessionAccounts(read, controlDir); const row = rec.rows.find((r) => r.sessionId === input.sessionId); if (row === undefined) return { result: "absent" }; if (input.leg !== undefined && row.leg !== input.leg) return { result: "stale" }; row.terminatedAt = input.now(); return { next: rec, result: "written" }; }); } export function resolveSessionAccountRecord(controlDir, input) { if (typeof input.requestId !== "string" || input.requestId.length === 0) { const e = new Error("resolveSessionAccount requires a non-empty requestId (the audit attribution of who closed) — refused, never defaulted."); e.code = "memory.session_account_resolve_unattributed"; throw e; } lockedStrictUpdate(controlDir, SESSION_ACCOUNTS_FILE, "memory session-account ledger", coerceSessionAccounts, (read) => { const { rec } = convertSessionAccounts(read, controlDir); const row = rec.rows.find((r) => r.sessionId === input.sessionId); if (row === undefined) { const e = new Error(`resolveSessionAccount: unknown sessionId ${JSON.stringify(input.sessionId)}`); e.code = "memory.session_account_resolve_unknown"; throw e; } row.closedAt = input.now(); row.unadjudicated = true; row.terminatedAt = row.closedAt; return { next: rec, result: undefined }; }); } export const HOLDS_FILE = "holds.json"; export const HOLD_DIR = "hold"; const HOLD_STATUSES = new Set(["capturing", "held", "released", "disposed"]); const HOLD_TERMINALS = new Set(["dirty", "expired", "conflict", "discarded", "capture_lost"]); function coerceHolds(raw) { if (raw === undefined) return { version: 2, rows: [] }; const rec = raw; if (typeof rec !== "object" || rec === null || !Array.isArray(rec.rows)) throw new ControlPlaneCorruptError("memory instruction-hold ledger has the wrong shape"); if (rec.version !== 1 && rec.version !== 2) throw new ControlPlaneCorruptError(`memory instruction-hold ledger has an unrecognized version (${String(rec.version)}) — refusing (fail-closed)`); const v1 = rec.version === 1; const rows = []; const raws = rec.rows; for (const r of raws) { const row = r; if (typeof row !== "object" || row === null || !reqStr(row.holdId) || !reqStr(row.sessionId) || (row.op !== "add" && row.op !== "update") || !safeRelPath(row.slug) || !reqStr(row.scope) || !reqStr(row.captureName) || !reqStr(row.contentDigest) || typeof row.capturedAt !== "number" || !Number.isFinite(row.capturedAt) || !Array.isArray(row.settleIds) || row.settleIds.some((x) => typeof x !== "string") || !HOLD_STATUSES.has(row.status) || (row.disposition !== undefined && (typeof row.disposition !== "object" || row.disposition === null || !HOLD_TERMINALS.has(row.disposition.terminal) || (row.disposition.quarantineName !== undefined && !safeBasename(row.disposition.quarantineName)))) || (row.resolved !== undefined && row.resolved !== "release" && row.resolved !== "discard") || (row.resolvedAt !== undefined && (typeof row.resolvedAt !== "number" || !Number.isSafeInteger(row.resolvedAt) || row.resolvedAt < 0 || row.resolvedAt >= 2 ** 50 || row.resolved === undefined)) || (row.entryId !== undefined && typeof row.entryId !== "string") || (row.baseRev !== undefined && typeof row.baseRev !== "string") || (row.op === "update" && (!reqStr(row.entryId) || !reqStr(row.baseRev))) || (v1 ? !safeRelPath(row.relPath) : !safeRelPath(row.rel)) || !safeBasename(row.captureName)) { throw new ControlPlaneCorruptError("memory instruction-hold ledger: a row is malformed — refusing (fail-closed; an unevaluable hold must not read as settled)"); } if (v1) { const { relPath: _relPath, ...rest } = row; rows.push({ ...rest, rel: `${row.slug}.md` }); } else { rows.push(row); } } return { version: 2, rows }; } function holdsOnDiskAreV1(raw) { return typeof raw === "object" && raw !== null && raw.version === 1; } export function readHolds(controlDir) { const raw = readStrictSidecar(controlDir, HOLDS_FILE, "memory instruction-hold ledger"); if (!holdsOnDiskAreV1(raw)) return coerceHolds(raw).rows; return lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (again) => ({ next: again, result: again.rows })); } function sha256(buf) { return createHash("sha256").update(buf).digest("hex"); } let stagingSeq = 0; function uniqueStagingName(holdId, now) { stagingSeq += 1; return `${holdId}.staging-${now()}-${process.pid}-${stagingSeq}`; } function stagingGenerationPattern(holdId) { return new RegExp(`^${holdId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.staging-\\d+-\\d+-\\d+(?:\\.claim-\\d+-\\d+)*$`); } function claimStaging(stagingPath) { stagingSeq += 1; const claimed = `${stagingPath}.claim-${process.pid}-${stagingSeq}`; try { renameSync(stagingPath, claimed); return claimed; } catch { return stagingPath; } } function dropStaging(claimedPath) { try { unlinkSync(claimedPath); } catch { } } export function stagingPathBeside(absPath, stagingName) { return join(dirname(absPath), stagingName); } function writeCustodyVerified(dest, bytes) { try { const fd = openSync(dest, "wx", 0o600); try { writeFileSync(fd, bytes); fsyncSync(fd); } finally { closeSync(fd); } return sha256(readFileSync(dest)) === sha256(bytes); } catch { return false; } } export function retireStagingToCustody(claimedPath, custodyDir, stagingName) { const unsettled = (why) => ({ settled: false, at: `${claimedPath} (${why})` }); let bytes; try { bytes = readFileSync(claimedPath); ensureDirExists(custodyDir); } catch { return unsettled("the staged bytes could not be read into the control plane"); } if (!writeCustodyVerified(join(custodyDir, stagingName), bytes)) return unsettled("the control-plane custody copy could not be written"); try { unlinkSync(claimedPath); } catch { return unsettled("a copy reached the control plane; this one could not be removed"); } return { settled: true, at: `${basename(custodyDir)}/${stagingName} in the memory control plane` }; } export function noReplaceRestore(stagingPath, destPath) { try { linkSync(stagingPath, destPath); } catch (err) { if (err.code !== "EEXIST") { try { writeFileSync(destPath, readFileSync(stagingPath), { flag: "wx" }); } catch (err2) { return err2.code === "EEXIST" ? "kept" : "stranded"; } try { unlinkSync(stagingPath); } catch { } return "restored"; } return "kept"; } try { unlinkSync(stagingPath); } catch { } return "restored"; } export function openInstructionHold(controlDir, input) { const holdId = `hold-${input.now()}-${createHash("sha256").update(`${input.sessionId}\n${input.rel}\n${input.content}`).digest("hex").slice(0, 12)}`; const buf = Buffer.from(input.content, "utf8"); const digest = sha256(buf); const captureName = `${holdId}.md`; const holdDir = join(controlDir, HOLD_DIR); let thirdWriterStrandedAt; const refuse = (rawReason, terminal) => { const reason = thirdWriterStrandedAt === undefined ? rawReason : `${rawReason}; a concurrent writer's bytes are preserved at ${thirdWriterStrandedAt}`; try { disposeHold(controlDir, { holdId, terminal, now: input.now }); } catch { } return { ok: false, holdId, reason }; }; try { lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { if (rec.rows.some((r) => r.holdId === holdId)) return { result: undefined }; rec.rows.push({ holdId, sessionId: input.sessionId, ...(input.entryId !== undefined ? { entryId: input.entryId } : {}), op: input.op, ...(input.baseRev !== undefined ? { baseRev: input.baseRev } : {}), rel: input.rel, slug: input.slug, scope: input.scope, captureName, contentDigest: digest, capturedAt: input.now(), settleIds: [...input.settleIds], status: "capturing", }); return { next: rec, result: undefined }; }); } catch (err) { return { ok: false, reason: `hold ledger refused: ${thrownText(err)}` }; } try { ensureDirExists(holdDir); } catch (err) { return refuse(`hold capture failed: ${thrownText(err)}`, "capture_lost"); } if (!writeCustodyVerified(join(holdDir, captureName), buf)) { return refuse("hold capture verification failed (the custody copy could not be written, made durable, or hashed back to the captured digest)", "capture_lost"); } const stagingName = uniqueStagingName(holdId, input.now); const stagingPath = stagingPathBeside(input.absPath, stagingName); try { renameSync(input.absPath, stagingPath); } catch (err) { const code = err.code; if (code === "ENOENT") { } else { return refuse(`hold removal failed (${code ?? "rename error"}): the plane file was not moved`, "discarded"); } } const claimedPath = existsSync(stagingPath) ? claimStaging(stagingPath) : stagingPath; if (existsSync(claimedPath)) { const moved = readFileSync(claimedPath); if (sha256(moved) === digest) { dropStaging(claimedPath); } else { const restore = noReplaceRestore(claimedPath, input.absPath); if (restore !== "restored") { const retired = retireStagingToCustody(claimedPath, holdDir, stagingName); if (restore === "stranded" || !retired.settled) thirdWriterStrandedAt = retired.at; } } } try { lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { const row = rec.rows.find((r) => r.holdId === holdId); if (row === undefined || row.status !== "capturing") return { result: undefined }; row.status = "held"; return { next: rec, result: undefined }; }); } catch (err) { return refuse(`hold ledger flip refused: ${thrownText(err)}`, "discarded"); } return { ok: true, holdId, ...(thirdWriterStrandedAt !== undefined ? { thirdWriterStrandedAt } : {}) }; } export function reconcileHolds(controlDir, input) { const holdDir = join(controlDir, HOLD_DIR); const discloseStranded = (holdId, rel, at) => { try { enqueueMemoryAnnouncement(controlDir, { kind: "gate", at: input.now(), items: [`instruction hold ${holdId}: a concurrent writer's bytes for ${JSON.stringify(rel)} could not be restored onto the plane — they are preserved at ${at} for host recovery`], }); } catch { console.warn(`[sema] instruction hold ${holdId}: concurrent-writer bytes preserved at ${at} could not be restored or announced`); } }; const finishRemoval = (row, plane) => { const stagingName = uniqueStagingName(row.holdId, input.now); renameSync(plane, stagingPathBeside(plane, stagingName)); const staging = claimStaging(stagingPathBeside(plane, stagingName)); if (sha256(readFileSync(staging)) === row.contentDigest) { dropStaging(staging); return; } const restore = noReplaceRestore(staging, plane); if (restore === "restored") return; const retired = retireStagingToCustody(staging, holdDir, stagingName); if (restore === "stranded" || !retired.settled) discloseStranded(row.holdId, row.rel, retired.at); }; const seatListing = new Map(); const listSeat = (seatDir) => { const cached = seatListing.get(seatDir); if (cached !== undefined) return cached; let names; try { names = readdirSync(seatDir); } catch { names = []; } seatListing.set(seatDir, names); return names; }; const sweepStagingGenerations = (row, plane, custody) => { const seatDir = dirname(plane); const pattern = stagingGenerationPattern(row.holdId); for (const name of listSeat(seatDir)) { if (!pattern.test(name)) continue; const staged = claimStaging(join(seatDir, name)); let bytes; try { if (!lstatSync(staged).isFile()) continue; bytes = readFileSync(staged); } catch { continue; } if (sha256(bytes) === row.contentDigest) { if (custody === "holds" || (custody === "absent" && writeCustodyVerified(join(holdDir, row.captureName), bytes))) { dropStaging(staged); continue; } } discloseStranded(row.holdId, row.rel, retireStagingToCustody(staged, holdDir, name).at); } }; const rows = readHolds(controlDir).filter((r) => r.status === "capturing"); for (const row of rows) { const custody = join(holdDir, row.captureName); let custodyBytes; try { custodyBytes = readFileSync(custody); } catch { custodyBytes = undefined; } const custodyState = custodyBytes === undefined ? "absent" : sha256(custodyBytes) === row.contentDigest ? "holds" : "mismatch"; try { sweepStagingGenerations(row, join(input.homeOf(row.scope), row.rel), custodyState); } catch { } let terminalLost = false; if (existsSync(custody)) { const bytes = custodyBytes ?? readFileSync(custody); if (sha256(bytes) !== row.contentDigest) { terminalLost = true; } else { const plane = join(input.homeOf(row.scope), row.rel); if (existsSync(plane)) { try { finishRemoval(row, plane); } catch { } } } } else { const plane = join(input.homeOf(row.scope), row.rel); if (existsSync(plane)) { const bytes = readFileSync(plane); if (sha256(bytes) === row.contentDigest) { try { ensureDirExists(holdDir); if (!writeCustodyVerified(custody, bytes)) throw new Error("the custody copy could not be written or made durable"); finishRemoval(row, plane); } catch { terminalLost = true; } } else { terminalLost = true; } } else { terminalLost = true; } } lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { const r = rec.rows.find((x) => x.holdId === row.holdId); if (r === undefined || r.status !== "capturing") return { result: undefined }; if (terminalLost) { r.status = "disposed"; r.disposition = { terminal: "capture_lost" }; } else { r.status = "held"; } return { next: rec, result: undefined }; }); } } export function disposeHold(controlDir, input) { const rows = readHolds(controlDir); const row = rows.find((r) => r.holdId === input.holdId); if (row === undefined || row.status === "disposed" || row.status === "released") return { ok: false }; const custody = join(controlDir, HOLD_DIR, row.captureName); const quarantineName = `${input.now()}-hold-${row.captureName}`; const qDir = join(controlDir, QUARANTINE_DIR); let moved = false; try { ensureDirExists(qDir); renameSync(custody, join(qDir, quarantineName)); moved = true; } catch { moved = existsSync(join(qDir, quarantineName)); } lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { const r = rec.rows.find((x) => x.holdId === input.holdId); if (r === undefined || r.status === "disposed" || r.status === "released") return { result: undefined }; r.status = "disposed"; r.disposition = { terminal: input.terminal, ...(moved ? { quarantineName } : {}) }; return { next: rec, result: undefined }; }); return { ok: true, ...(moved ? { quarantineName } : {}) }; } export function markHoldReleased(controlDir, input) { const captureName = lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { const r = rec.rows.find((x) => x.holdId === input.holdId); if (r === undefined || (r.status !== "held" && !(r.status === "disposed" && r.disposition?.terminal === "expired"))) return { result: undefined }; r.status = "released"; delete r.resolved; delete r.resolvedAt; return { next: rec, result: r.captureName }; }); if (captureName === undefined) return; try { unlinkSync(join(controlDir, HOLD_DIR, captureName)); } catch { } } export function resolveHoldRecord(controlDir, input) { if (typeof input.requestId !== "string" || input.requestId.length === 0) { const e = new Error("resolveHold requires a non-empty requestId (the audit attribution of who resolved) — refused, never defaulted."); e.code = "memory.hold_resolve_unattributed"; throw e; } if (input.action !== "release" && input.action !== "discard") { const e = new Error(`resolveHold action must be "release" or "discard" (got ${JSON.stringify(input.action)}) — refused loudly, never folded.`); e.code = "memory.hold_resolve_invalid"; throw e; } lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { const r = rec.rows.find((x) => x.holdId === input.holdId); if (r === undefined) { const e = new Error(`resolveHold: unknown holdId ${JSON.stringify(input.holdId)}`); e.code = "memory.hold_resolve_unknown"; throw e; } if (r.status !== "held" && !(r.status === "disposed" && r.disposition?.terminal === "expired" && input.action === "release")) { const e = new Error(`resolveHold: hold ${JSON.stringify(input.holdId)} is ${r.status}${r.disposition !== undefined ? ` (${r.disposition.terminal})` : ""} — only a held row, or an expired disposition (release), can be resolved`); e.code = "memory.hold_resolve_invalid_state"; throw e; } r.resolved = input.action; const nextGeneration = Math.max(input.now(), 0, (r.resolvedAt ?? 0) + 1); if (!Number.isSafeInteger(nextGeneration) || nextGeneration < 0 || nextGeneration >= 2 ** 50) { const e = new Error(`resolveHold: hold ${JSON.stringify(input.holdId)} cannot mint a fresh verdict generation (${String(nextGeneration)} — an exhausted window, a deranged clock, or a corrupt ledger row) — refused, never written.`); e.code = "memory.hold_resolve_invalid_state"; throw e; } r.resolvedAt = nextGeneration; return { next: rec, result: undefined }; }); } export function clearHoldResolution(controlDir, input) { lockedStrictUpdate(controlDir, HOLDS_FILE, "memory instruction-hold ledger", coerceHolds, (rec) => { const r = rec.rows.find((x) => x.holdId === input.holdId); if (r === undefined || r.resolved === undefined || r.resolvedAt !== input.ifResolvedAt) return { result: undefined }; delete r.resolved; delete r.resolvedAt; return { next: rec, result: undefined }; }); } export function readHoldCustody(controlDir, row) { const seats = [join(controlDir, HOLD_DIR, row.captureName), ...(row.disposition?.quarantineName !== undefined ? [join(controlDir, QUARANTINE_DIR, row.disposition.quarantineName)] : [])]; for (const seat of seats) { try { const bytes = readFileSync(seat); if (sha256(bytes) === row.contentDigest) return bytes.toString("utf8"); } catch { } } return undefined; } export function sessionBlocksCleanRelease(controlDir, sessionId) { if (readSessionPollution(controlDir, sessionId) !== undefined) return true; return sessionSettlements(controlDir, sessionId).some((s) => s.effective !== "clean" && s.effective !== "void"); }