@sema-agent/core
Version:
Stateless, task-oriented AI agent core
436 lines (435 loc) • 26 kB
JavaScript
import { emitTrace } from "../trace.js";
import { StubExecutionEnv } from "../stub-env.js";
import { hasBackgroundShell } from "../background-shell.js";
import { defaultTaskRegistry } from "../task-registry.js";
import { bashReversibilityProbe, activeReadDenyBuiltinTiers, readDenyBuiltinConfigOf, compileReadDeny, compileWriteDeny, withRuleRowsWhereTheyLead, readDenySeat, createHandsToolkit, deploymentFaceClampNotice, pdfModelCapabilitiesOf, inheritSessionReadFileState, backgroundOutputReadExemption, resolveContainmentFace, seedReadFileStateFromContext, seedReadFileStateFromTranscript, } from "../../tools/fs/index.js";
import { resolveKey, sha256 } from "../../tools/fs/safety.js";
import { placeReadDenyAtHome, whereItsAnsweredPrefixLeads } from "../../tools/fs/read-deny-home.js";
import { createShellOverflowSpoolFence } from "../../tools/fs/fs-shared.js";
import { createShellReadStation } from "../../tools/fs/shell-read-check.js";
import { composeReadChecks, createFileReadStation } from "../../tools/fs/file-read-check.js";
import { readTargetToolNames } from "../tool-registry.js";
import { normalizeFileText } from "../../tools/fs/encoding.js";
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
import { deliverEngineNotice } from "../types.js";
import { readRootGrantOver, rootAdmittingArtifactStore } from "./read-root-grant.js";
import { sessionSeatAnchorHolds } from "./session-read-file-states.js";
import { rebaseWorkspacePath } from "./workspace-path.js";
import { RosterBuilder } from "../tool-roster.js";
import { modePolicyOf } from "../mode-policy.js";
const faceClampAnnouncedSinks = { read: new WeakSet(), write: new WeakSet() };
const faceClampConsoleAnnounced = { read: false, write: false };
function announceDeploymentFaceClamp(kind, sink) {
if (typeof sink === "function") {
if (faceClampAnnouncedSinks[kind].has(sink))
return;
faceClampAnnouncedSinks[kind].add(sink);
}
else {
if (faceClampConsoleAnnounced[kind])
return;
faceClampConsoleAnnounced[kind] = true;
}
deliverEngineNotice(sink, deploymentFaceClampNotice(kind));
}
export function __resetReadFaceClampAnnouncement() {
faceClampConsoleAnnounced.read = false;
faceClampConsoleAnnounced.write = false;
}
function assertStringArraySeat(value, seat, entryLaw) {
if (value === undefined)
return;
if (!Array.isArray(value)) {
const e = new Error(`${seat} must be an array or absent (got ${value === null ? "null" : typeof value}) — a non-array here would be iterated character by character, so it refuses loudly instead.`);
e.code = "config.read_face_seat";
throw e;
}
if (entryLaw !== "strings")
return;
const entries = value;
for (const entry of entries) {
if (typeof entry !== "string") {
const e = new Error(`${seat} entries must be strings (got ${entry === null ? "null" : typeof entry}).`);
e.code = "config.read_face_seat";
throw e;
}
}
}
function writeFaceReader(input, onDeploymentClamp) {
const { spec, deps, resume, fullShellReachable, permissionMode } = input;
const seats = { kind: "write", readOnlyMount: spec.handsReadOnly === true, orgGoverned: deps.permissionRuleStore?.partitions.org === true, fullShellReachable };
resolveContainmentFace({ ...seats, specFace: spec.writeFace, depsFace: deps.writeFace, ...(onDeploymentClamp !== undefined ? { onDeploymentClamp } : {}) });
const recorded = resume === undefined ? "live" : resume.seed.writeFace?.face;
const folded = (word) => (recorded === "roots" ? "roots" : word === "open" && recorded !== "open" && recorded !== "live" ? undefined : word);
const faceUnder = (modeFace) => resolveContainmentFace({ ...seats, specFace: folded(spec.writeFace), depsFace: folded(deps.writeFace), ...(modeFace !== undefined ? { modeFace } : {}) });
return { inForce: () => faceUnder(modePolicyOf(permissionMode.current).writeFace), fenced: faceUnder("open") === "roots" };
}
export function resolveHandsLessReadFace(input) {
const { resume, fullShellReachable, spec, deps } = input;
assertStringArraySeat(deps.readDenyPatterns, "RunnerDeps.readDenyPatterns", "compiler-owned");
assertStringArraySeat(spec.readDenyPatterns, "TaskSpec.readDenyPatterns", "compiler-owned");
let handsLessResolvedFace;
let handsLessResolvedWriteFace;
let readDenyAdditionsNormalized = [];
let readDenyBuiltinTiersActive = [];
{
const liveFace = resolveContainmentFace({
kind: "read",
specFace: spec.readFace,
depsFace: deps.readFace,
readOnlyMount: spec.handsReadOnly === true,
orgGoverned: deps.permissionRuleStore?.partitions.org === true,
fullShellReachable,
});
const seed = resume?.seed.readFace;
handsLessResolvedFace = resume !== undefined && (seed === undefined || seed.face === "roots") ? "roots" : liveFace;
handsLessResolvedWriteFace = writeFaceReader(input);
const denyAdditions = [...(deps.readDenyPatterns ?? []), ...(spec.readDenyPatterns ?? []), ...(seed?.denyEntries ?? [])];
readDenyBuiltinTiersActive = activeReadDenyBuiltinTiers(readDenyBuiltinConfigOf({ tiers: deps.readDenyBuiltinTiers, exclude: deps.readDenyBuiltinExclude }));
if (denyAdditions.length > 0) {
readDenyAdditionsNormalized = compileReadDeny(denyAdditions, "readDenyPatterns", { tiers: [] }).entries;
}
}
return {
readFileStateForCheckpoint: undefined,
seedContextFiles: undefined,
handsCwdRef: undefined,
workspaceStateSettle: undefined,
wsSnapshot: undefined,
rebaseWsPath: (p) => p,
backgroundTaskToolsActive: false,
shellReadCheck: undefined,
shellReadStationArmed: false,
shellReadAdmission: undefined,
resolvedReadFace: undefined,
resolvedWriteFace: undefined,
readDenyAdditionsNormalized,
readDenyBuiltinTiersActive,
handsLessResolvedFace,
handsLessResolvedWriteFace,
additionalRootsCanonical: [],
additionalReadRootsCanonical: [],
grantReadRoot: undefined,
artifactStoreRef: undefined,
attachmentRootCanonical: undefined,
readDenyMatcher: undefined,
envHandToolNames: new Set(),
shellGatedTools: new Set(),
sealReadStateSeat: undefined,
};
}
export async function prepareHandsMount(input) {
const envHandToolNames = new Set();
const { handsEnabled, executionEnv, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, advertisedWritableDirs, firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes } = input;
assertStringArraySeat(spec.additionalDirectories, "TaskSpec.additionalDirectories", "strings");
assertStringArraySeat(spec.additionalReadDirectories, "TaskSpec.additionalReadDirectories", "strings");
assertStringArraySeat(deps.readDenyPatterns, "RunnerDeps.readDenyPatterns", "compiler-owned");
assertStringArraySeat(spec.readDenyPatterns, "TaskSpec.readDenyPatterns", "compiler-owned");
let readFileStateForCheckpoint;
let sealReadStateSeat;
let seedContextFiles;
let handsCwdRef;
let workspaceStateSettle;
let wsSnapshot;
let rebaseWsPath = (p) => p;
let backgroundTaskToolsActive = false;
let shellReadStation;
let shellReadTools = new Set();
let fileReadStation;
let resolvedReadFace;
let resolvedWriteFace;
let readDenyAdditionsNormalized = [];
let readDenyBuiltinTiersActive = [];
let handsLessResolvedFace;
const handsLessResolvedWriteFace = undefined;
const shellGatedTools = new Set();
const additionalRootsCanonical = [];
const additionalReadRootsCanonical = [];
let grantReadRoot;
const artifactStoreRef = { current: undefined };
let attachmentRootCanonical;
let readDenyMatcher;
if (handsEnabled) {
const rootCanonical = taskRootCanonical;
attachmentRootCanonical = rootCanonical;
const canonicalizeExtraDirs = async (dirs, field, sink) => {
for (const dir of dirs ?? []) {
if (!dir || !dir.trim())
continue;
const c = await (advertisedWritableDirs?.canonicalizeDeclaredRoot(dir) ?? executionEnv.canonicalPath(dir));
if (c.ok) {
sink.push(c.value);
}
else {
deps.onError?.(new Error(`${field} entry skipped (cannot canonicalize): ${dir}`), {
phase: "config",
sessionId,
});
emitTrace(deps.tracer, () => ({
kind: "config.additional_directory_skipped",
version: 1,
taskId: hostTaskId,
entry: dir,
...(field !== "additionalDirectories" ? { field } : {}),
reason: `${c.error.code}: ${c.error.message}`,
ts: Date.now(),
}));
}
}
};
await canonicalizeExtraDirs(spec.additionalDirectories, "additionalDirectories", additionalRootsCanonical);
await canonicalizeExtraDirs(spec.additionalReadDirectories, "additionalReadDirectories", additionalReadRootsCanonical);
const standingCanonical = [];
await canonicalizeExtraDirs(input.persistedReadDirectories, "persistedReadRule", standingCanonical);
artifactStoreRef.standing = { keys: standingCanonical.filter((k) => !additionalReadRootsCanonical.includes(k) && !additionalRootsCanonical.includes(k)), readRoots: additionalReadRootsCanonical };
additionalReadRootsCanonical.push(...standingCanonical);
if (advertisedWritableDirs !== undefined) {
if (spec.envFacts?.scratchpadDir)
await advertisedWritableDirs.admit({ path: spec.envFacts.scratchpadDir, advertiser: "scratchpad", materializeMarker: ".sema-scratchpad" });
additionalRootsCanonical.push(...advertisedWritableDirs.roots);
}
for (const a of [additionalRootsCanonical, additionalReadRootsCanonical])
a.splice(0, a.length, ...new Set(a));
grantReadRoot = readRootGrantOver({ env: executionEnv, writeRoots: additionalRootsCanonical, readRoots: additionalReadRootsCanonical, artifactStore: artifactStoreRef });
const readFileState = new Map((resume?.seed.readFileState ?? []).map(([k, v]) => [rebaseRestoredPath(k), v]));
readFileStateForCheckpoint = readFileState;
seedContextFiles = async (files) => {
for (const f of files) {
const rk = await resolveKey(executionEnv, rootCanonical, f.path, undefined, undefined, [...additionalRootsCanonical, ...additionalReadRootsCanonical], undefined, undefined, resolvedReadFace);
if (rk.ok)
seedReadFileStateFromContext(readFileState, rk.key, f.content);
}
};
const handsIncludeShell = !(executionEnv instanceof StubExecutionEnv);
const handsReadOnly = spec.handsReadOnly === true;
backgroundTaskToolsActive = handsIncludeShell && !handsReadOnly && hasBackgroundShell(executionEnv);
wsSnapshot = resume !== undefined || !(handsIncludeShell && !handsReadOnly) ? undefined : await session.getWorkspaceState().catch(() => undefined);
rebaseWsPath = (p) => (wsSnapshot === undefined || wsSnapshot.taskRoot === rootCanonical ? p : rebaseWorkspacePath(p, wsSnapshot.taskRoot, rootCanonical));
if (handsIncludeShell && !handsReadOnly) {
handsCwdRef = { current: rootCanonical };
if (resume?.seed.handsCwd !== undefined)
handsCwdRef.current = rebaseRestoredPath(resume.seed.handsCwd);
else if (wsSnapshot?.handsCwd !== undefined)
handsCwdRef.current = rebaseWsPath(wsSnapshot.handsCwd);
workspaceStateSettle = {
rootCanonical,
restoredHandsCwd: handsCwdRef.current !== rootCanonical ? handsCwdRef.current : undefined,
...(resume !== undefined ? { baselineUnknown: true } : {}),
};
}
const seedReadFaceSection = resume?.seed.readFace;
const readDenyAdditions = [...(deps.readDenyPatterns ?? []), ...(spec.readDenyPatterns ?? []), ...(seedReadFaceSection?.denyEntries ?? [])];
const readDenyBuiltinCfg = readDenyBuiltinConfigOf({ tiers: deps.readDenyBuiltinTiers, exclude: deps.readDenyBuiltinExclude });
const pathDenyRules = await withRuleRowsWhereTheyLead(input.pathDenyRules, (head) => whereItsAnsweredPrefixLeads(executionEnv, head));
const readDenyPlacement = await placeReadDenyAtHome(executionEnv, (homes, linked) => compileReadDeny(readDenyAdditions, "readDenyPatterns", readDenyBuiltinCfg, pathDenyRules, homes, linked));
readDenyMatcher = readDenyPlacement.matcher;
readDenyBuiltinTiersActive = activeReadDenyBuiltinTiers(readDenyBuiltinCfg);
readDenyAdditionsNormalized = compileReadDeny(readDenyAdditions, "readDenyPatterns", { tiers: [] }).entries;
let liveReadFace = resolveContainmentFace({
kind: "read",
specFace: spec.readFace,
depsFace: deps.readFace,
readOnlyMount: handsReadOnly,
orgGoverned: deps.permissionRuleStore?.partitions.org === true,
fullShellReachable,
onDeploymentClamp: () => announceDeploymentFaceClamp("read", deps.onNotice),
});
if (resume !== undefined && (seedReadFaceSection === undefined || seedReadFaceSection.face === "roots"))
liveReadFace = "roots";
resolvedReadFace = liveReadFace;
resolvedWriteFace = writeFaceReader(input, () => announceDeploymentFaceClamp("write", deps.onNotice));
const sessionSeats = input.internals?.sessionReadStates;
let seatLeafId;
try {
seatLeafId = (await session.getStorage().getLeafId()) ?? null;
}
catch {
seatLeafId = undefined;
}
const judgeKey = async (path) => {
const rk = await resolveKey(executionEnv, rootCanonical, path, undefined, undefined, [...additionalRootsCanonical, ...additionalReadRootsCanonical], undefined, undefined, liveReadFace);
return rk.ok ? rk.key : undefined;
};
if (resume === undefined && spec.sessionId !== undefined) {
const seatRow = spec.resumeAt === undefined && seatLeafId !== undefined ? sessionSeats?.get(sessionId) : undefined;
const inheritedSeat = seatRow !== undefined && (await sessionSeatAnchorHolds((id) => session.getEntry(id), seatRow.anchorLeafId, seatLeafId))
? seatRow.state
: undefined;
if (inheritedSeat !== undefined) {
await inheritSessionReadFileState(readFileState, inheritedSeat, judgeKey);
}
else {
const prior = await session.buildContext().catch(() => undefined);
for (const rec of wholeFileRecordsFromTranscript(prior?.messages ?? [])) {
const rk = await judgeKey(rec.path);
if (rk !== undefined)
seedReadFileStateFromTranscript(readFileState, rk, rec.content, rec.at);
}
}
}
if (input.restoredFilePaths !== undefined) {
for (const abs of input.restoredFilePaths) {
const k = await judgeKey(abs);
if (k === undefined)
continue;
const entry = readFileState.get(k);
if (entry === undefined || entry.seededFromContext === true)
continue;
const cur = await executionEnv.readTextFile(abs);
if (cur.ok && entry.hash === sha256(normalizeFileText(cur.value)))
continue;
readFileState.delete(k);
}
}
if (seatLeafId !== undefined)
sessionSeats?.adopt(sessionId, readFileState, seatLeafId);
sealReadStateSeat =
sessionSeats !== undefined && seatLeafId !== undefined
? (ownCommittedTailEntryId) => {
if (ownCommittedTailEntryId !== undefined)
sessionSeats.reanchor(sessionId, readFileState, ownCommittedTailEntryId);
}
: undefined;
const denySeat = readDenySeat(readDenyMatcher);
const writeDeny = compileWriteDeny(pathDenyRules);
const writeDenySeat = writeDeny.ruleRows.length > 0 ? { writeDenyMatch: (p) => writeDeny.matchPath(p)?.pattern ?? null } : {};
const shellReadBoundary = () => ({
roots: [rootCanonical, ...additionalRootsCanonical, ...additionalReadRootsCanonical],
...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}),
...(executionEnv.homeDir !== undefined ? { homeDir: executionEnv.homeDir } : {}),
...denySeat,
...writeDenySeat,
writeRoots: [rootCanonical, ...additionalRootsCanonical],
...((judge) => (judge !== undefined ? { writeProtectionJudge: judge } : {}))(input.writeGuards?.protection()),
...(input.writeGuards?.target !== undefined ? { writeTargetGuard: input.writeGuards.target } : {}),
...(resolvedReadFace !== undefined ? { face: resolvedReadFace } : {}),
});
if (handsIncludeShell) {
const spoolFence = handsReadOnly ? createShellOverflowSpoolFence(executionEnv) : undefined;
const readonlyBoundary = () => spoolFence !== undefined ? { roots: [rootCanonical, ...additionalRootsCanonical, ...additionalReadRootsCanonical], cwd: rootCanonical, ...denySeat, ...writeDenySeat, alsoInside: spoolFence } : undefined;
shellReadTools = new Set(handsReadOnly ? ["Bash"] : backgroundTaskToolsActive ? ["Bash", "Monitor"] : ["Bash"]);
shellReadStation = createShellReadStation({
env: executionEnv,
tools: shellReadTools,
seatOf: () => (handsReadOnly ? "readonly" : "full_shell"),
boundaryOf: () => readonlyBoundary() ?? shellReadBoundary(), rootsCanonical: true,
homeViews: readDenyPlacement.matcher.homeViews,
});
}
if (!handsReadOnly) {
const bgOutputExempt = backgroundOutputReadExemption(defaultTaskRegistry, { taskOwner: hostTaskId, taskScope, ...(sessionId !== undefined ? { sessionId } : {}) }, executionEnv);
fileReadStation = createFileReadStation({
env: executionEnv,
rootCanonical,
roots: () => [...additionalRootsCanonical, ...additionalReadRootsCanonical],
...(readDenyMatcher !== undefined ? { readDeny: readDenyMatcher } : {}),
...(liveReadFace !== undefined ? { readFace: liveReadFace } : {}),
...("homeDir" in executionEnv && executionEnv.homeDir !== undefined ? { homeDir: executionEnv.homeDir } : {}),
tools: readTargetToolNames(),
excluded: (key) => artifactStoreRef.current !== undefined && rootAdmittingArtifactStore(artifactStoreRef.current, [key]) !== undefined,
exempt: (key) => bgOutputExempt?.(key) === true,
});
}
const band = createHandsToolkit(executionEnv, readFileState, rootCanonical, {
...(additionalRootsCanonical.length > 0 ? { additionalRoots: additionalRootsCanonical } : {}),
additionalReadRoots: additionalReadRootsCanonical,
...(readDenyAdditions.length > 0 ? { readDenyPatterns: readDenyAdditions } : {}),
...(pathDenyRules.length > 0 ? { pathDenyRules } : {}),
readDenyHomes: readDenyPlacement.homes,
readDenyHomeLinks: readDenyPlacement.linked,
...(readDenyBuiltinCfg.tiers !== undefined ? { readDenyBuiltinTiers: readDenyBuiltinCfg.tiers } : {}),
...(readDenyBuiltinCfg.exclude !== undefined ? { readDenyBuiltinExclude: readDenyBuiltinCfg.exclude } : {}),
readFace: liveReadFace,
writeFaceLive: resolvedWriteFace.inForce,
reminderMark: input.reminderMark,
reminderDisclosureCounts: input.reminderDisclosureCounts,
...(input.trackFileEdit !== undefined ? { trackFileEdit: input.trackFileEdit } : {}),
...(input.onFileEdited !== undefined ? { onFileEdited: input.onFileEdited } : {}),
includeShell: handsIncludeShell,
readOnly: handsReadOnly,
...(shellReadStation !== undefined ? { shellReadAdmission: shellReadStation.admit } : {}),
...(fileReadStation !== undefined ? { readAdmission: fileReadStation.admitted } : {}),
...(handsCwdRef ? { cwdRef: handsCwdRef } : {}),
taskRegistry: defaultTaskRegistry,
taskOwner: hostTaskId,
taskScope,
oneShot: spec.oneShot,
...(sessionId !== undefined ? { sessionId } : {}),
retainBackgroundProcesses: spec.retainBackgroundProcesses === true,
...(internals?.onTaskNotification !== undefined ? { taskNotification: internals.onTaskNotification } : {}),
...(internals?.detachHub !== undefined ? { detachHub: internals.detachHub } : {}),
onToolProgress: (body) => input.toolProgressRef.current?.emit(body),
queuedHumanInput: () => input.harnessRef.current?.hasPendingUserInput() === true,
...(deps.onNotice !== undefined ? { onNotice: deps.onNotice } : {}),
pdfModelCapabilities: pdfModelCapabilitiesOf(model),
...(deps.hands?.bashReadonlyAllow !== undefined ? { bashReadonlyAllow: deps.hands.bashReadonlyAllow } : {}),
...(deps.hands?.commitCoAuthor !== undefined ? { commitCoAuthor: deps.hands.commitCoAuthor } : {}),
...(deps.hands?.readImageDownsampler !== undefined ? { readImageDownsampler: deps.hands.readImageDownsampler } : {}),
...(deps.hands?.autoBackgroundOnTimeout !== undefined ? { autoBackgroundOnTimeout: deps.hands.autoBackgroundOnTimeout } : {}),
beforeWrite: async (w) => {
const deploymentGate = deps.hands?.beforeWrite;
if (deploymentGate) {
const verdict = await deploymentGate(w);
if (verdict !== undefined && verdict.ok === false)
return verdict;
}
return memoryWriteGate?.(w);
},
mountBackgroundTaskTools: false,
monitorToolActive: backgroundTaskToolsActive && !(toolFaceSnapshot.exclude?.includes("Monitor") ?? false),
});
{
const bandNames = new Set(band.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
const shadowed = (spec.tools ?? []).filter((t) => [t.name, ...(t.aliases ?? [])].some((n) => bandNames.has(n)));
if (shadowed.length > 0) {
const names = shadowed.map((t) => `"${t.name}"`).join(", ");
deps.onError?.(new Error(`spec.tools ${shadowed.length > 1 ? "entries" : "entry"} ${names} collide${shadowed.length > 1 ? "" : "s"} with the built-in hands tool band — the built-in wins (registered later; the harness tool Map is last-write-wins) and the caller tool never dispatches this task. Rename the caller tool, or don't inject executionEnv if you intend to replace the band.`), { phase: "config", sessionId });
}
}
roster.mountAll(band.map((t) => (envHandToolNames.add(t.name), firstPartyOffload(t))), { source: "builtin", mountedBy: "hands" });
const shellFloor = effectiveShellGate;
if (!(executionEnv instanceof StubExecutionEnv) && spec.handsReadOnly !== true) {
const installShellSeat = (name) => {
const tierBefore = irreversibilityTier.get(name);
const seatOwned = !egressTools.has(name) && tierBefore !== "always" && tierBefore !== "maybe";
const tier = shellFloor === "always" || tierBefore === "always" ? "always" : "maybe";
irreversibilityTier.set(name, tier);
irreversibleTools.add(name);
if (seatOwned && tier === "maybe")
reversibilityProbes.set(name, bashReversibilityProbe(undefined, shellReadBoundary));
if (seatOwned)
shellGatedTools.add(name);
};
installShellSeat("Bash");
if (backgroundTaskToolsActive)
installShellSeat("Monitor");
}
}
return {
readFileStateForCheckpoint,
seedContextFiles,
handsCwdRef,
workspaceStateSettle,
wsSnapshot,
rebaseWsPath,
backgroundTaskToolsActive,
shellReadCheck: composeReadChecks([...(shellReadStation !== undefined ? [{ check: shellReadStation.check, tools: shellReadTools }] : []), ...(fileReadStation !== undefined ? [fileReadStation] : [])]),
shellReadStationArmed: shellReadStation !== undefined,
shellReadAdmission: shellReadStation?.admit,
resolvedReadFace,
resolvedWriteFace,
handsLessResolvedWriteFace,
readDenyAdditionsNormalized,
readDenyBuiltinTiersActive,
handsLessResolvedFace,
additionalRootsCanonical,
additionalReadRootsCanonical,
grantReadRoot,
artifactStoreRef,
attachmentRootCanonical,
readDenyMatcher,
envHandToolNames,
shellGatedTools,
sealReadStateSeat,
};
}