UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

788 lines • 52.6 kB
import { argsAsTheToolReads, withArgsReading } from "./effective-path-target.js";
import { attest, attestationOf, decisionText, foldHookAsk, ownArgs, refusalOf, refuseOutOfContractDecision } from "./tool-policy.js";
import { arbitrateByMode, classifyAsk, decisionAskClassesOf, fileCommandOptionsSentence, persistedRuleMandateOf, ruleClearanceOf, safetyAxisOf, stampAskOrigin } from "./ask-origin.js";
import { classifierParseFailureDenyMessage, denialLimitFallbackMessage, rungDidNotRule, unarmedWindow } from "./auto-mode.js";
import { classifierNoRulingArm, settleNoRulingAsk } from "./classifier-unavailable-arm.js";
import { SETTLEMENT_NOBODY_JUDGED } from "./gate-outcome.js";
import { inlineUntrusted } from "./untrusted-text.js";
import { ASK_USER_QUESTION_TOOL_NAME } from "./ask-question.js";
import { applyPersistedTightening, disclosedRuleSet } from "./persisted-rule-arms.js";
import { skillAllowDecision, skillRowRefusal } from "./skill-grant.js";
import { allowRuleShadowOf } from "./allow-entry.js";
import { CD_GIT_COMPOUND_SENTENCE, changesDirectoryBeforeGit, readOnlyShellVerdict } from "./read-only-shell.js";
import { readShellCommand } from "./shell-lexer.js";
import { COMMAND_RULE_TOOL } from "./permission-rule-model.js";
import { catalogRuleFaceOf } from "./tool-registry.js";
import { callFaceSeat } from "./tool-roster.js";
import { heldBy, wireOf } from "./tool-name-readings.js";
import { asksUnstated, modeAcceptsFileCommand, permissionSeatAt, unstatedAskMessage } from "./mode-policy.js";
import { ORG_RULE_DECISION_REASON, ORG_UNAVAILABLE_DECISION_REASON, orgUnreadableClause } from "./permission-rule-org.js";
import { exitGate, passAskFace, unownedArgsMessage } from "./runner/gate-exit.js";
import { readOrgRuleLane, readPersistedRuleLane } from "./rule-lane-reads.js";
import { traceHookCrash } from "./gate-crash-trace.js";
import { createGateDeadline, awaitWriteProtectionJudgment, withGateTimeout } from "./gate-bounded-await.js";
import { readStationAnswer } from "./shell-read-silence.js";
import { agentIdOf, judgedInputOf, raiseToolCheck } from "./mods/stations.js";
import { readToolChecks } from "./tool-check-reading.js";
import { policyThrowLine, reportPolicyThrow } from "./runner/policy-throw.js";
const QUESTION_TOOL_NAMES = new Set([ASK_USER_QUESTION_TOOL_NAME]);
function parkWith(suspendAsk, parkArgs, carry) {
    return suspendAsk(...parkArgs, carry);
}
const ruleCallUnreadableOf = (lane) => lane?.unreadable === true && lane.reason !== undefined;
const ruleStoreUnreadableOf = (lane) => lane?.unreadable === true && lane.reason === undefined;
export async function runGateLanes(pass) {
    const { input, toolName, toolCallId, callSignal, ledger, notifier, screening, adjudicate, resolveAsk, suspendAsk } = pass;
    const boundedAwaitDeadlineMs = createGateDeadline(input, notifier);
    let orgRealApprovalRequired = false;
    let markedThisRound;
    let approvedWithArgs = false;
    let carriedOwnAsk;
    const takeApprovedEdit = (read) => {
        carriedOwnAsk = read.outstanding ?? (pass.decision.action === "ask" ? pass.decision : undefined);
        pass.decision = read.allow;
        approvedWithArgs = true;
    };
    const safetyOf = (d) => safetyAxisOf({ egress: input.egress, shellGated: input.shellGated, irreversibility: input.irreversibility, probeMandated: d.action === "ask" && d.probeMandated === true, probeUnanswered: pass.probeUnanswered === true, tightened: pass.tightenedBy });
    const realApprovalOf = (d, org) => {
        if (d.action !== "ask" || d.requiresRealApproval !== true)
            return undefined;
        if (d.origin === undefined)
            throw new Error(`a real-approval ask for "${toolName}" reached a park site with no origin word — the origin stamp precedes every park`);
        return { origin: d.origin, ...(org !== undefined ? { org } : {}) };
    };
    const carryOf = (d) => ({
        ...(callSignal !== undefined ? { signal: callSignal } : {}),
        ...(d.action === "ask" && d.denialLimitFallback !== undefined ? { denialLimitFallback: unarmedWindow(d.denialLimitFallback) } : {}),
        ...(d.action === "ask" && d.classifierNoRuling !== undefined ? { classifierNoRuling: d.classifierNoRuling } : {}),
        ...(d.action === "ask" && d.origin !== undefined ? { origin: d.origin } : {}),
        ...(d.action === "ask" && d.askClass !== undefined && d.classes !== undefined ? { askClass: d.askClass, classes: d.classes } : {}),
        ...(d.action === "ask" && d.mandated === true ? { mandated: true, ...(d.mandate !== undefined ? { mandate: d.mandate } : {}) } : {}),
        ...(d.action === "ask" && d.authoredBy === "deployment" ? { authoredBy: "deployment" } : {}),
    });
    const parkAsk = async (d, req, args, safety, liveFaceUnavailable, org) => {
        if (suspendAsk === undefined || d.action !== "ask")
            return undefined;
        const suspended = await parkWith(suspendAsk, [req, args, safety, liveFaceUnavailable, realApprovalOf(d, org), d.allowRuleShadowed, d.decisionReason, d.probeReason, d.probeCause, d.segmentCoverage, d.matchedAskRule, d.probeMandated], carryOf(d));
        if (suspended && "parkFailed" in suspended)
            pass.parkFailed = suspended.parkFailed;
        return suspended && !("parkFailed" in suspended) ? { suspend: suspended, preToolContext: pass.preToolContext } : undefined;
    };
    const markedUnresolvable = () => (markedThisRound ??= input.isMarkedUnresolvable?.(input.event.toolCallId) === true);
    const mandateMarksNow = () => ({
        egress: input.egress,
        shellGated: input.shellGated,
        irreversibility: input.irreversibility,
        requiresUserInteraction: input.requiresUserInteraction,
        probeUnanswered: pass.probeUnanswered === true,
        writeProtected: pass.writeProtected === true,
        targetUnresolved: pass.targetUnresolved === true,
    });
    const readFaceNow = input.readFace?.();
    const askOriginFacts = (org, lane) => ({
        contentQuestion: heldBy("lanes.contentQuestionClass", QUESTION_TOOL_NAMES, pass.req),
        markedUnresolvable: markedUnresolvable(),
        org,
        ...(ruleCallUnreadableOf(lane) ? { ruleCallUnreadable: true } : {}),
        ...(ruleStoreUnreadableOf(lane) ? { ruleStoreUnreadable: true } : {}),
        tightened: pass.tightenedBy,
        mandateMarks: mandateMarksNow(),
        ...(input.toolMarkSources !== undefined ? { toolMarkSources: input.toolMarkSources } : {}),
        ...(input.a2aIsolatePeers === true ? { a2aIsolatePeers: true } : {}),
        ...(readFaceNow !== undefined ? { readFace: readFaceNow } : {}),
        askFace: passAskFace(pass),
    });
    const classifyStanding = (unstamped, facts) => (pass.askClassification = classifyAsk(unstamped, facts));
    let orgTightenCount = 0;
    let orgEvidence = (() => {
        const w = input.orgRules === undefined ? "not_wired" : "not_adjudicated";
        return { revisionAbsent: w, ruleAbsent: w };
    })();
    const mintRuleEvidence = (personal) => ({
        ...(orgEvidence.revision !== undefined ? { orgRevision: orgEvidence.revision } : { orgRevisionAbsent: orgEvidence.revisionAbsent ?? "not_reported" }),
        ...(orgEvidence.rule !== undefined ? { orgRule: orgEvidence.rule } : { orgRuleAbsent: orgEvidence.ruleAbsent ?? "not_reported" }),
        ...(personal.dots !== undefined ? { personalRuleDots: personal.dots } : { personalRuleDotsAbsent: personal.dotsAbsent ?? "not_reported" }),
    });
    const applyOrgLayer = async (current, args) => {
        if (input.orgRules === undefined)
            return { decision: current, org: undefined };
        if (wireOf("lanes.orgContentAskExemption", pass.req) === ASK_USER_QUESTION_TOOL_NAME && input.orgRules.contentAskToolMounted === true)
            return { decision: current, org: undefined };
        let decided = current;
        const answer = await readOrgRuleLane(input.orgRules, Object.freeze({ toolName, args, toolCallId, ...callFaceSeat(pass.req.face) }), input.abortSignal);
        if (answer.status === "unavailable") {
            orgEvidence = { revisionAbsent: "unavailable", ruleAbsent: "unavailable" };
            orgRealApprovalRequired = true;
            await notifier.notifyAsync(() => input.orgRules?.onUnavailable?.({ toolName, toolCallId, message: answer.disclosures.join("; ") }), "toolGate.orgSnapshotUnavailable");
            const orgUnavailableMessage = `tool "${toolName}" needs approval: this deployment is org-governed and cannot currently adjudicate ` +
                `against an organization policy snapshot — every allow tightens to a real approval until it can`;
            if (decided.action === "allow") {
                decided = { action: "ask", message: orgUnavailableMessage, decisionReason: ORG_UNAVAILABLE_DECISION_REASON, requiresRealApproval: true };
                orgTightenCount += 1;
            }
            else if (decided.action === "ask" && decided.requiresRealApproval !== true) {
                decided = { ...decided, requiresRealApproval: true, ...(pass.tightenedBy !== undefined ? { message: orgUnavailableMessage } : {}) };
                orgTightenCount += 1;
            }
            return { decision: decided, org: "unavailable" };
        }
        const revisionCell = answer.revision !== undefined ? { revision: answer.revision } : { revisionAbsent: "not_reported" };
        if (answer.verdict === undefined) {
            orgEvidence = { ...revisionCell, ruleAbsent: "no_match" };
            return { decision: decided, org: undefined };
        }
        const { behavior, rule, unreadable } = answer.verdict;
        orgEvidence = { ...revisionCell, rule };
        if (behavior === "deny") {
            orgTightenCount += 1;
            pass.deniedBy = "org";
            pass.denyCause = undefined;
            return { decision: refusalOf({ action: "deny", message: `an organization policy rule (${rule}) denies this call${unreadable !== undefined ? `, ${orgUnreadableClause(unreadable)}` : ""}`, decisionReason: ORG_RULE_DECISION_REASON }, args), org: undefined };
        }
        if (decided.action === "deny")
            return { decision: decided, org: undefined };
        orgTightenCount += 1;
        orgRealApprovalRequired = true;
        const orgRuleMessage = unreadable !== undefined
            ? `an organization policy rule (${rule}) may reach this call, ${orgUnreadableClause(unreadable)} — a person must decide`
            : `an organization policy rule (${rule}) requires approval for this call`;
        return {
            decision: decided.action === "ask"
                ?
                    { ...decided, requiresRealApproval: true, ...(decided.requiresRealApproval !== true && pass.tightenedBy !== undefined ? { message: orgRuleMessage } : {}) }
                : { action: "ask", message: orgRuleMessage, decisionReason: ORG_RULE_DECISION_REASON, requiresRealApproval: true },
            org: "rule",
        };
    };
    const finalArgs = pass.policyRewrite !== undefined ? pass.policyRewrite : pass.currentInput;
    if (pass.decision.action === "deny")
        pass.decision = refusalOf(pass.decision, finalArgs);
    const orgAnswer = await applyOrgLayer(pass.decision, finalArgs);
    pass.decision = orgAnswer.decision;
    const readPersistedRules = (req) => readPersistedRuleLane(input.persistedRules, req, input.abortSignal);
    const laneReq = Object.freeze(pass.policyRewrite !== undefined ? await withArgsReading(pass.req, pass.policyRewrite, pass.callSignal ?? input.abortSignal) : { ...pass.req });
    const laneAnswer = input.persistedRules !== undefined && wireOf("lanes.persistedLaneSkip", pass.req) !== ASK_USER_QUESTION_TOOL_NAME ? await readPersistedRules(laneReq) : undefined;
    {
        const tightened = applyPersistedTightening(pass.decision, laneAnswer, laneReq);
        pass.decision = tightened.tightened === "deny" ? refusalOf(tightened.decision, laneReq.args) : tightened.decision;
        if (tightened.tightened === "deny")
            pass.deniedBy = "persisted_rule";
        if (tightened.tightened === "deny")
            pass.denyCause = undefined;
        const skillRefusal = pass.decision.action === "deny" ? undefined : skillRowRefusal(input.skillGrants, laneReq);
        if (skillRefusal !== undefined) {
            pass.decision = refusalOf(skillRefusal, laneReq.args);
            pass.deniedBy = "policy";
            pass.denyCause = undefined;
        }
    }
    let settledRefusal;
    const checkTool = async (standing, args, org, rewrite, mayClear) => {
        const agentId = agentIdOf(input.identity);
        const ceiling = org !== undefined ? { ceiling: "ask" } : {};
        const e = { tool: toolName, input: judgedInputOf(args), tool_use_id: toolCallId, ...(agentId !== undefined ? { agentId } : {}), ...ceiling };
        const signal = callSignal ?? input.abortSignal;
        const own = input.modBus;
        settledRefusal = undefined;
        const settleThroughLedger = (settle) => async (ask, call, sig) => {
            const read = ledger.fromDecision(await settle(ask, call, sig));
            if (read.decision.action === "deny")
                settledRefusal = { deniedBy: read.deniedBy ?? "policy", cause: ledger.causeOf(read.decision) };
            return read.decision;
        };
        const chains = [
            ...(own !== undefined ? [{ raise: (p) => raiseToolCheck(own, { ...e }, p, signal), ...(mayClear !== undefined ? { mayClear } : {}) }] : []),
            ...(input.inheritedToolChecks ?? []).map((c) => ({ raise: (p) => raiseToolCheck(c.bus, { ...e }, p, signal, c.judges), settle: settleThroughLedger(c.settle) })),
        ];
        const project = (current, clears) => {
            const reason = decisionText(current);
            const said = reason !== undefined ? { reason } : {};
            return current.action === "ask" ? { decision: "ask", ...said, classes: [...(current.classes ?? [])], mandated: clears?.() !== true, ...ceiling } : { decision: "allow", ...said, ...ceiling };
        };
        return await readToolChecks(chains, standing, { toolName, judged: args, rewrite, request: Object.freeze({ ...pass.req, args }), signal }, project);
    };
    const refuseByExtension = (deny) => {
        pass.decision = deny;
        pass.deniedBy = settledRefusal?.deniedBy ?? "hook";
        pass.denyCause = settledRefusal?.cause;
    };
    if (pass.decision.action === "allow") {
        const read = await checkTool(pass.decision, finalArgs, orgAnswer.org, pass.policyRewrite);
        if (read !== undefined)
            pass.toolCheckRaised = true;
        if (read?.kind === "denied")
            refuseByExtension(read.deny);
        else if (read?.kind === "asked")
            pass.decision = read.ask;
        else if (read?.kind === "approved")
            takeApprovedEdit(read);
    }
    if (pass.decision.action === "ask") {
        pass.decision = { ...pass.decision };
        if (pass.policyRewrite !== undefined) {
            pass.currentInput = pass.policyRewrite;
            pass.req = Object.freeze({ ...pass.req, args: pass.policyRewrite, ...(laneReq.targetReading !== undefined ? { targetReading: laneReq.targetReading } : {}) });
        }
        const ruleMayClear = () => ruleClearanceOf(pass.decision.action === "ask" ? pass.decision : undefined, mandateMarksNow()).ruleMayClear;
        const classMayClear = () => pass.decision.action === "ask" && classifyAsk(pass.decision, askOriginFacts(orgAnswer.org, laneAnswer)).row.ruleMayClear;
        let personalEvidence = { dotsAbsent: input.persistedRules === undefined ? "not_wired" : "not_adjudicated" };
        if (laneAnswer?.unreadable === true)
            personalEvidence = { dotsAbsent: "unavailable" };
        let laneCoverage;
        const questionTool = wireOf("lanes.allowLayerQuestionSkip", pass.req) === ASK_USER_QUESTION_TOOL_NAME;
        const allowLayerMayClear = () => !orgRealApprovalRequired &&
            pass.decision.action === "ask" &&
            pass.decision.requiresRealApproval !== true &&
            pass.decision.decisionReason !== "hook" &&
            !questionTool &&
            !markedUnresolvable();
        const unionDotsOf = (rules) => {
            const seen = new Set();
            const union = [];
            for (const r of rules) {
                if (r.dots === undefined || r.dots.length === 0)
                    return { dotsAbsent: "not_reported" };
                for (const d of r.dots) {
                    const key = JSON.stringify([d.actor, d.counter]);
                    if (!seen.has(key))
                        (seen.add(key), union.push(d));
                }
            }
            return { dots: union };
        };
        if (input.persistedRules && allowLayerMayClear()) {
            const answer = laneAnswer ?? {};
            laneCoverage = answer.coverage;
            personalEvidence = answer.hit?.behavior === "ask" ? unionDotsOf(answer.hit.rules) : { dotsAbsent: answer.unreadable === true ? "unavailable" : "no_match" };
        }
        const afterRuleClear = () => {
            if (input.permissionMode === undefined || input.permissionMode() === "auto")
                input.autoMode?.denialTracking?.recordAllow();
        };
        const mode = input.permissionMode?.();
        const rewrite = pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {};
        const listAllow = (decisionReason, whose, entries) => ({
            action: "allow",
            message: `${whose} allowedTools (${entries.map((e) => inlineUntrusted(e, 200)).join(", ")}) ${entries.length === 1 ? "covers" : "cover"} this call`,
            decisionReason,
            ...rewrite,
        });
        const storedAllows = laneAnswer?.hit?.behavior === "allow" ? laneAnswer.hit.rules : undefined;
        const members = [
            ["hook", () => (pass.hookAllowedBy !== undefined && pass.policyRewrite === undefined ? { entries: pass.hookAllowedBy, clear: () => ({ action: "allow", message: "a PreToolUse hook allowed this call", decisionReason: "hook" }), afterClear: async () => undefined } : undefined)],
            ["deployment", () => {
                    const hit = input.deploymentAllows?.allowing(pass.req, mode);
                    return hit && { entries: hit.entries, clear: () => listAllow("deployment_rule", "the deployment's", hit.entries), afterClear: () => notifier.notifyAsync(() => input.deploymentAllows?.onAllowed?.({ toolName: pass.req.toolName, toolCallId, entries: hit.entries }), "toolGate.allowedToolsResolved") };
                }],
            ["persisted", () => storedAllows && {
                    entries: storedAllows.map((r) => r.rule),
                    clear: () => ({ action: "allow", message: storedAllows.length === 1 ? `a persisted allow rule (${disclosedRuleSet(storedAllows)}) covers this call` : `persisted allow rules (${disclosedRuleSet(storedAllows)}) cover every segment of this call`, decisionReason: "persisted_rule", ...rewrite }),
                    afterClear: () => notifier.notifyAsync(() => input.persistedRules?.onResolved?.({ toolName: pass.req.toolName, toolCallId, rules: storedAllows.map((r) => r.rule) }), "toolGate.persistedRuleResolved"),
                    shadowed: () => (personalEvidence = unionDotsOf(storedAllows)),
                }],
            ["skill", () => {
                    const hit = input.skillGrants?.allowing(pass.req, mode);
                    return hit && { entries: hit.entries, clear: () => skillAllowDecision(hit, pass.policyRewrite), afterClear: () => notifier.notifyAsync(() => input.skillGrants?.onAllowed?.({ toolName: pass.req.toolName, toolCallId, ...hit }), "toolGate.skillGrantResolved") };
                }],
            ["request", () => {
                    const hit = input.requestAllows?.allowing(pass.req, mode);
                    return hit && { entries: hit.entries, clear: () => listAllow("request_rule", "this run's", hit.entries), afterClear: () => notifier.notifyAsync(() => input.requestAllows?.onAllowed?.({ toolName: pass.req.toolName, toolCallId, entries: hit.entries }), "toolGate.allowedToolsResolved") };
                }],
        ];
        const shadows = [];
        if (!questionTool) {
            for (const [member, match] of members) {
                if (pass.decision.action !== "ask")
                    break;
                const hit = match();
                if (hit === undefined)
                    continue;
                if (allowLayerMayClear() && ruleMayClear() && classMayClear()) {
                    pass.decision = hit.clear();
                    await hit.afterClear();
                    if (member !== "hook")
                        afterRuleClear();
                    break;
                }
                shadows.push(allowRuleShadowOf(member, hit.entries));
                hit.shadowed?.();
            }
        }
        if (pass.decision.action === "ask") {
            const { allowRuleShadowed: _claimed, ...standing } = pass.decision;
            pass.decision = shadows.length > 0 ? { ...standing, allowRuleShadowed: shadows } : standing;
        }
        const originFacts = askOriginFacts(orgAnswer.org, laneAnswer);
        let noRulingMinted = false;
        const fallbackAskOf = (standingAsk, fallback, latestBlockedAction) => {
            const { classifierNoRuling: _why, ...standing } = standingAsk;
            const fallbackAsk = { ...standing, message: denialLimitFallbackMessage(fallback, latestBlockedAction), decisionReason: "classifier", requiresRealApproval: true, denialLimitFallback: fallback };
            return stampAskOrigin(fallbackAsk, originFacts, classifyStanding(fallbackAsk, originFacts));
        };
        if (pass.decision.action === "ask") {
            const stamped = { ...pass.decision, ruleEvidence: mintRuleEvidence(personalEvidence), ...(laneCoverage !== undefined ? { segmentCoverage: laneCoverage } : {}) };
            pass.decision = stampAskOrigin(stamped, originFacts, classifyStanding(stamped, originFacts));
        }
        if (allowLayerMayClear() && pass.decision.action === "ask" && ruleMayClear() && classMayClear() && pass.probeBoundaryDeclined !== true && wireOf("lanes.readOnlyShellAllow", pass.req) === COMMAND_RULE_TOOL) {
            const commandParam = catalogRuleFaceOf(COMMAND_RULE_TOOL)?.primaryParams[0] ?? "command";
            const args = pass.req.args;
            const command = typeof args === "object" && args !== null && !Array.isArray(args) ? args[commandParam] : undefined;
            const backgrounded = typeof args === "object" && args !== null && args.run_in_background === true;
            const shape = typeof command === "string" ? readShellCommand(command) : undefined;
            if (typeof command === "string" && shape !== undefined && !backgrounded && readOnlyShellVerdict(command, shape, input.trackedCwd?.()).readOnly) {
                pass.decision = {
                    action: "allow",
                    message: "the command is read-only (upstream's read-only command tables) — allowed without asking",
                    decisionReason: "read_only",
                    ...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}),
                };
                await notifier.notifyAsync(() => input.onReadOnlyAllowed?.({ toolName: pass.req.toolName, toolCallId, command }), "toolGate.readOnlyAllowed");
                afterRuleClear();
            }
            else if (shape !== undefined && pass.tightenedBy === "shell_gate" && changesDirectoryBeforeGit(shape, input.trackedCwd?.())) {
                pass.decision = { ...pass.decision, message: CD_GIT_COMPOUND_SENTENCE };
            }
        }
        if (pass.toolCheckRaised !== true && pass.decision.action !== "deny") {
            const read = await checkTool(pass.decision, pass.currentInput, orgAnswer.org, pass.policyRewrite, () => allowLayerMayClear() && ruleMayClear() && classMayClear());
            if (read?.kind === "denied")
                refuseByExtension(read.deny);
            else if (read?.kind === "cleared")
                pass.decision = read.allow;
            else if (read?.kind === "asked") {
                const asked = read.minted ? { ...read.ask, ruleEvidence: mintRuleEvidence(personalEvidence) } : read.ask;
                if (read.marked === true)
                    markedThisRound = undefined;
                const facts = read.marked === true ? askOriginFacts(orgAnswer.org, laneAnswer) : originFacts;
                pass.decision = stampAskOrigin(asked, facts, classifyStanding(asked, facts));
            }
            else if (read?.kind === "shadowed" && pass.decision.action === "ask")
                pass.decision = { ...pass.decision, allowRuleShadowed: [...(pass.decision.allowRuleShadowed ?? []), ...read.shadows] };
            else if (read?.kind === "approved")
                takeApprovedEdit(read);
        }
        if (pass.decision.action === "ask")
            ledger.supersede();
        if (input.autoMode && pass.decision.action === "ask" && pass.decision.origin !== undefined && pass.askClassification?.row.classifierEligible === true && (input.permissionMode === undefined || input.permissionMode() === "auto")) {
            const classifySignal = callSignal ?? input.abortSignal;
            const heard = await input.autoMode.decider
                .decide({ req: pass.req, askMessage: decisionText(pass.decision) }, classifySignal)
                .catch(() => ({ kind: "unavailable", cause: "error" }));
            const verdict = heard.kind === "allow" && input.permissionMode !== undefined && input.permissionMode() !== "auto" ? undefined : heard;
            if (verdict !== undefined)
                pass.classifierRound = verdict.classifier;
            if (verdict?.kind === "allow") {
                input.autoMode.denialTracking?.recordAllow();
                pass.decision = {
                    action: "allow",
                    message: "auto-mode classifier allowed this call",
                    decisionReason: "classifier",
                    ...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}),
                };
            }
            else if (verdict !== undefined) {
                const noRuling = rungDidNotRule(verdict);
                const arm = noRuling !== undefined ? classifierNoRulingArm({ ask: pass.decision, req: pass.req, cause: noRuling, attribution: verdict.classifier, seat: input.autoMode.unavailable, aborted: classifySignal?.aborted === true }) : undefined;
                if (arm?.kind === "asked") {
                    noRulingMinted = true;
                    pass.decision = stampAskOrigin(arm.ask, originFacts, classifyStanding(arm.ask, originFacts));
                    pass.classifierRound = undefined;
                }
                else if (arm?.kind === "denied")
                    pass.decision = refusalOf(arm.deny, finalArgs);
                else {
                    const reason = verdict.kind === "block" ? (verdict.reason ? inlineUntrusted(verdict.reason) : "") : classifierParseFailureDenyMessage(verdict.classifier);
                    const category = verdict.kind === "block" && verdict.category ? inlineUntrusted(verdict.category) : "";
                    const tracked = input.autoMode.denialTracking?.recordBlock();
                    if (tracked?.limitReached === true) {
                        pass.decision = fallbackAskOf(pass.decision, tracked.fallback, reason || category || toolName);
                    }
                    else {
                        const denied = {
                            action: "deny",
                            message: verdict.kind === "block" ? `auto-mode classifier blocked this call${reason ? `: ${reason}` : category ? `: [${category}]` : ""}` : reason,
                            decisionReason: "classifier",
                        };
                        pass.decision = refusalOf(verdict.kind === "parse_error" ? attest(denied, pass.req, { classifierCause: "parse_error" }) : denied, finalArgs);
                    }
                }
            }
            if (pass.decision.action === "deny") {
                pass.deniedBy = "classifier";
                pass.denyCause = attestationOf(pass.decision, pass.req)?.classifierCause;
            }
        }
        if (input.sandboxAdmission !== undefined &&
            pass.decision.action === "ask" &&
            wireOf("lanes.sandboxQuestionSkip", pass.req) !== ASK_USER_QUESTION_TOOL_NAME &&
            input.isMarkedUnresolvable?.(input.event.toolCallId) !== true &&
            pass.decision.requiresRealApproval !== true &&
            pass.decision.decisionReason !== "hook" &&
            pass.decision.origin !== "ask_rule" &&
            pass.hookAsk === undefined &&
            input.egress !== true &&
            input.peerMessage !== true &&
            pass.askClassification?.row.sandboxAdmission === true &&
            pass.probeBoundaryDeclined !== true &&
            input.sandboxAdmission.boundaryCapable !== true) {
            const recorded = input.sandboxAdmission.askClassesOf(toolCallId);
            const admissible = recorded !== undefined && recorded.length > 0 && recorded.every((r) => r.cls === "sandbox_local");
            if (admissible) {
                const askClasses = recorded;
                input.sandboxAdmission.onAdmitted({ toolCallId, toolName, askClasses, boundary: "sandbox_internal" });
                pass.preToolContext.push(`permission.sandbox_admitted: this call's pending approval was auto-admitted because the deployment declares an isolated sandbox execution env and the request stays inside it. Recorded for audit.`);
                pass.decision = {
                    action: "allow",
                    message: "admitted inside the deployment-declared sandbox (permission.sandbox_admitted)",
                    decisionReason: "sandbox",
                    ...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}),
                };
            }
        }
        if (pass.decision.action === "ask" && input.permissionMode !== undefined && pass.askClassification !== undefined) {
            const standing = pass.decision;
            const mode = input.permissionMode();
            const fileCommandByWord = modeAcceptsFileCommand(mode, wireOf("lanes.modeFileCommand", pass.req), pass.policyRewrite ?? pass.currentInput);
            const verdict = arbitrateByMode(mode, pass.askClassification, { ...(standing.origin !== undefined ? { origin: standing.origin } : {}), ...(standing.mandate !== undefined ? { mandate: standing.mandate } : {}) }, { fileCommand: pass.shellWritesPlaced === true && fileCommandByWord });
            if (verdict.kind === "ask" && fileCommandByWord && pass.shellWritesPlaced !== true && pass.shellUnplacedOptions !== undefined && pass.askClassification.classes.size === 1 && pass.askClassification.classes.has("ordinary")) {
                pass.decision = { ...standing, message: fileCommandOptionsSentence(pass.shellUnplacedOptions.program) };
            }
            if (verdict.kind === "accepted") {
                ledger.supersede();
                pass.decision = { action: "allow", message: `accepted by the ${verdict.mode} permission mode (one of its file commands)`, decisionReason: "mode", ...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}) };
            }
            else if (verdict.kind === "released") {
                pass.arbitration = verdict;
                ledger.supersede();
                await notifier.notifyAsync(() => input.onModeReleased?.({ toolName, toolCallId, release: { mode: verdict.mode, askClass: verdict.askClass, classes: verdict.classes, ...(verdict.origin !== undefined ? { origin: verdict.origin } : {}), ...(verdict.mandate !== undefined ? { mandate: verdict.mandate } : {}), ...(verdict.reason !== undefined ? { reason: verdict.reason } : {}) }, ...(pass.shellReadUnestablished === true ? { readUnestablished: true } : {}) }), "toolGate.onModeReleased");
                pass.decision = {
                    action: "allow",
                    message: `released by the ${verdict.mode} permission mode (the ${verdict.askClass} ask was not put to anyone)`,
                    decisionReason: "mode",
                    ...(pass.policyRewrite !== undefined ? { updatedInput: pass.policyRewrite } : {}),
                };
            }
            else if (verdict.kind === "denied_by_mode") {
                pass.arbitration = verdict;
                pass.deniedBy = "mode";
                pass.denyCause = undefined;
                pass.decision = refusalOf({
                    action: "deny",
                    message: verdict.mode === "dontAsk"
                        ? `refused by the dontAsk permission mode: this call needed approval (${verdict.askClass}) and the mode answers no ask; run under a mode with an approver, or change the call`
                        : `refused by the bypassPermissions permission mode: the write-protection judge could not resolve this write's target, and with nobody to ask the mode refuses rather than releases it`,
                    decisionReason: "mode",
                }, finalArgs);
            }
        }
        const safety = safetyOf(pass.decision);
        if (suspendAsk && pass.decision.action === "ask") {
            const parked = await parkAsk(pass.decision, pass.req, pass.currentInput, safety, undefined, originFacts.org);
            if (parked)
                return parked;
        }
        if (pass.decision.action === "ask" && wireOf("lanes.contentAskRoute", pass.req) === ASK_USER_QUESTION_TOOL_NAME) {
            const outcome = input.resolveContentAsk !== undefined ? await (callSignal !== undefined ? input.resolveContentAsk(pass.req, callSignal) : input.resolveContentAsk(pass.req)) : { kind: "unavailable", parkDeclined: false };
            if (outcome.kind === "answered") {
                pass.decision = { action: "allow" };
            }
            else if (outcome.kind === "unavailable") {
                if (suspendAsk && outcome.parkDeclined && pass.parkFailed === undefined) {
                    const parked = await parkAsk(pass.decision, pass.req, pass.currentInput, safety, true, originFacts.org);
                    if (parked)
                        return parked;
                }
                if (pass.decision.origin === undefined)
                    throw new Error(`the content ask for "${toolName}" reached its refusal without an origin word`);
                ledger.set({ settlement: { kind: input.resolveContentAsk !== undefined ? "approver_unavailable" : "no_approver", who: { party: "none" }, when: Date.now() }, origin: pass.decision.origin });
                pass.deniedBy = "ask_resolution";
                pass.decision = refusalOf({
                    action: "deny",
                    message: "AskUserQuestion could not be parked for a durable human answer on this path (no checkpoint " +
                        "facility, or the suspend failed) and a synchronous permission approver cannot carry an answer — " +
                        "the question was NOT shown to anyone. Proceed with your best judgment and state the assumption " +
                        "you made.",
                }, finalArgs);
            }
            else {
                pass.decision = { action: "allow" };
            }
        }
        if (pass.decision.action === "ask") {
            let askBeforeResolve = pass.decision;
            const resolveOnce = (d) => (callSignal !== undefined ? resolveAsk(d, pass.req, callSignal) : resolveAsk(d, pass.req));
            let resolved = await resolveOnce(askBeforeResolve);
            const refallback = settleNoRulingAsk({ ask: askBeforeResolve, mintedHere: noRulingMinted, resolved: { action: resolved.action, settlement: attestationOf(resolved, pass.req)?.settlement }, tracker: input.autoMode?.denialTracking });
            if (refallback !== undefined && askBeforeResolve.action === "ask") {
                askBeforeResolve = fallbackAskOf(askBeforeResolve, refallback, toolName);
                resolved = await resolveOnce(askBeforeResolve);
            }
            resolved = ledger.fromResolved(resolved, askBeforeResolve, pass.req);
            if (resolved.action === "deny")
                pass.deniedBy = "ask_resolution";
            pass.decision = resolved.action === "deny" ? refusalOf(resolved, finalArgs) : resolved;
            if (resolved.action === "deny" && resolved.approverUnavailable === true && suspendAsk && pass.parkFailed === undefined) {
                const parked = await parkAsk(askBeforeResolve, pass.req, pass.currentInput, safety, true, originFacts.org);
                if (parked)
                    return parked;
            }
            if (askBeforeResolve.action === "ask" && askBeforeResolve.denialLimitFallback !== undefined) {
                if (pass.decision.action === "allow") {
                    input.autoMode?.denialTracking?.recordAllow();
                }
                else if ((resolved.action === "deny" &&
                    ledger.settled !== undefined &&
                    (SETTLEMENT_NOBODY_JUDGED[ledger.settled.settlement.kind] || ledger.settled.settlement.kind === "approver_unavailable")) ||
                    resolved.approverUnavailable === true) {
                    try {
                        input.onHeadlessDenialLimit?.({ toolName, toolCallId, fallback: unarmedWindow(askBeforeResolve.denialLimitFallback) });
                    }
                    catch {
                    }
                }
            }
            approvedWithArgs = pass.decision.action === "allow" && pass.decision.updatedInput !== undefined;
        }
    }
    if (approvedWithArgs && pass.decision.action === "allow" && pass.decision.updatedInput !== undefined) {
        let editArgs = pass.decision.updatedInput;
        let editDenied;
        let editRewrittenSinceHuman = false;
        let unanswered;
        const refusedAtResolution = (d) => { editDenied = d; pass.deniedBy = "ask_resolution"; };
        for (let round = 0;; round++) {
            const taken = ownArgs(editArgs);
            if (!taken.ok) {
                editDenied = { action: "deny", message: unownedArgsMessage(`the approved edit for "${toolName}"`, taken.reason) };
                pass.deniedBy = "policy";
                break;
            }
            editArgs = argsAsTheToolReads(pass.req, taken.value);
            if (round >= 3) {
                editDenied = {
                    action: "deny",
                    message: `the approval-edit chain for "${toolName}" exceeded the re-approval cap — denied fail-closed; re-submit the edited action directly`,
                };
                pass.deniedBy = "policy";
                break;
            }
            let editHookAsk;
            if (screening !== undefined) {
                const screened = await screening.screen(editArgs, `the approved edit for "${toolName}"`);
                if (screened.kind === "refused") {
                    editDenied = { action: "deny", message: screened.reason };
                    pass.deniedBy = "hook";
                    break;
                }
                const hr = screened.answer;
                if (hr) {
                    if (hr.additionalContext)
                        pass.preToolContext.push(hr.additionalContext);
                    if (hr.action === "deny") {
                        editDenied = { action: "deny", message: decisionText(hr) ?? `the approved edit for "${toolName}" was blocked by a PreToolUse hook` };
                        pass.deniedBy = "hook";
                        break;
                    }
                    if (hr.action === "ask") {
                        const { updatedInput: _adopted, ...ask } = hr;
                        editHookAsk = ask;
                    }
                    if (hr.updatedInput !== undefined) {
                        editArgs = argsAsTheToolReads(pass.req, hr.updatedInput);
                        editRewrittenSinceHuman = true;
                    }
                }
            }
            let recheck = { action: "allow" };
            if (adjudicate) {
                try {
                    const editReq = Object.freeze({ toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
                    recheck = refuseOutOfContractDecision(await (callSignal !== undefined ? adjudicate(editReq, callSignal) : adjudicate(editReq)));
                }
                catch (err) {
                    reportPolicyThrow((e) => traceHookCrash(input, e, notifier), "the tool policy's re-check of the approved edit", { toolName, toolCallId }, err, callSignal ?? input.abortSignal);
                    recheck = {
                        action: "deny",
                        message: `policy re-check of the approved edit for "${toolName}" errored: ${policyThrowLine(err)}`,
                    };
                }
            }
            {
                const attributed = ledger.classifierRoundOf(recheck);
                if (attributed !== undefined)
                    pass.classifierRound = attributed;
                const read = ledger.fromDecision(recheck);
                recheck = read.decision;
                if (recheck.action === "deny" && read.deniedBy !== undefined) {
                    editDenied = recheck;
                    pass.deniedBy = read.deniedBy;
                    pass.denyCause = ledger.causeOf(recheck);
                    break;
                }
            }
            if (recheck.updatedInput !== undefined) {
                editArgs = argsAsTheToolReads(pass.req, recheck.updatedInput);
                editRewrittenSinceHuman = true;
            }
            const editOrg = await applyOrgLayer(recheck, editArgs);
            recheck = editOrg.decision;
            if (recheck.action === "deny") {
                editDenied = recheck;
                break;
            }
            let editLane;
            const editLaneReq = Object.freeze(await withArgsReading(pass.req, editArgs, callSignal ?? input.abortSignal));
            if (input.persistedRules !== undefined && wireOf("lanes.persistedEditSkip", pass.req) !== ASK_USER_QUESTION_TOOL_NAME) {
                editLane = await readPersistedRules(editLaneReq);
                const editTightened = applyPersistedTightening(recheck, editLane, editLaneReq);
                recheck = editTightened.decision;
                if (editTightened.tightened === "deny")
                    pass.deniedBy = "persisted_rule";
                if (recheck.action === "deny") {
                    editDenied = recheck;
                    break;
                }
            }
            const editSkillRefusal = skillRowRefusal(input.skillGrants, editLaneReq);
            if (editSkillRefusal !== undefined) {
                editDenied = editSkillRefusal;
                pass.deniedBy = "policy";
                break;
            }
            if (recheck.action === "allow") {
                if (recheck.updatedInput !== undefined) {
                    editArgs = argsAsTheToolReads(pass.req, recheck.updatedInput);
                    editRewrittenSinceHuman = true;
                }
                if (editRewrittenSinceHuman && asksUnstated(recheck, permissionSeatAt(input, editArgs)?.seat, input.permissionMode?.())) {
                    recheck = { action: "ask", message: permissionSeatAt(input, editArgs)?.question ?? unstatedAskMessage(toolName) };
                    pass.tightenedBy = "unstated";
                }
            }
            if (recheck.updatedInput !== undefined) {
                editArgs = argsAsTheToolReads(pass.req, recheck.updatedInput);
                editRewrittenSinceHuman = true;
            }
            let editFacts;
            const stampEditAsk = (ask) => {
                const editAskSnapshot = { ...ask, ruleEvidence: mintRuleEvidence({ dotsAbsent: "not_adjudicated" }) };
                if (editFacts === undefined) {
                    markedThisRound = undefined;
                    editFacts = askOriginFacts(editOrg.org, editLane);
                }
                return stampAskOrigin(editAskSnapshot, editFacts, classifyStanding(editAskSnapshot, editFacts));
            };
            if (editHookAsk !== undefined)
                recheck = foldHookAsk(recheck, editHookAsk);
            let editDecision = recheck.action === "ask" ? stampEditAsk(recheck) : recheck;
            if (carriedOwnAsk !== undefined) {
                const { updatedInput: _theOriginalBytes, ...carried } = carriedOwnAsk;
                const rra = carried.requiresRealApproval === true ? { requiresRealApproval: true } : {};
                editDecision = stampEditAsk(editDecision.action === "ask" ? { ...editDecision, foldedAskClasses: [...(editDecision.foldedAskClasses ?? []), ...decisionAskClassesOf(carried), ...(carried.classes ?? [])], ...rra } : carried);
                carriedOwnAsk = undefined;
            }
            const editRead = await checkTool(editDecision, editArgs, editOrg.org, undefined);
            if (editRead?.kind === "denied") {
                refuseByExtension(editRead.deny);
                editDenied = editRead.deny;
                break;
            }
            if (editRead?.kind === "approved") {
                carriedOwnAsk = editRead.outstanding ?? (editDecision.action === "ask" ? editDecision : undefined);
                editArgs = editRead.allow.updatedInput;
                editRewrittenSinceHuman = false;
                continue;
            }
            if (editRead?.kind === "asked" && editRead.marked === true)
                editFacts = undefined;
            if (editRead?.kind === "asked")
                editDecision = stampEditAsk(editRead.ask);
            else if (editRead?.kind === "shadowed" && editDecision.action === "ask")
                editDecision = { ...editDecision, allowRuleShadowed: [...(editDecision.allowRuleShadowed ?? []), ...editRead.shadows] };
            if (editDecision.action !== "ask")
                break;
            const editAskDecision = editDecision;
            if (input.permissionMode !== undefined && pass.askClassification !== undefined) {
                const editVerdict = arbitrateByMode(input.permissionMode(), pass.askClassification, { ...(editAskDecision.origin !== undefined ? { origin: editAskDecision.origin } : {}), ...(editAskDecision.mandate !== undefined ? { mandate: editAskDecision.mandate } : {}) });
                if (editVerdict.kind === "released") {
                    ledger.supersede();
                    pass.arbitration = editVerdict;
                    await notifier.notifyAsync(() => input.onModeReleased?.({ toolName, toolCallId, release: { mode: editVerdict.mode, askClass: editVerdict.askClass, classes: editVerdict.classes, ...(editVerdict.origin !== undefined ? { origin: editVerdict.origin } : {}), ...(editVerdict.mandate !== undefined ? { mandate: editVerdict.mandate } : {}), ...(editVerdict.reason !== undefined ? { reason: editVerdict.reason } : {}) }, ...(pass.shellReadUnestablished === true ? { readUnestablished: true } : {}) }), "toolGate.onModeReleased");
                    break;
                }
                if (editVerdict.kind === "denied_by_mode") {
                    ledger.supersede();
                    pass.arbitration = editVerdict;
                    editDenied = { action: "deny", message: `the approved edit for "${toolName}" raised a new approval requirement that the ${editVerdict.mode} permission mode refuses`, decisionReason: "mode" };
                    pass.deniedBy = "mode";
                    break;
                }
            }
            const editAskReq = Object.freeze({ toolName, args: editArgs, toolCallId, ...(pass.req.face !== undefined ? { face: pass.req.face } : {}) });
            if (suspendAsk !== undefined && markedUnresolvable()) {
                unanswered = { ask: editAskDecision, req: editAskReq, org: editOrg.org };
                break;
            }
            const rr = ledger.fromResolved(await (callSignal !== undefined ? resolveAsk(editAskDecision, editAskReq, callSignal) : resolveAsk(editAskDecision, editAskReq)), editAskDecision, editAskReq);
            if (rr.action !== "allow") {
                refusedAtResolution(rr);
                if (rr.approverUnavailable === true)
                    unanswered = { ask: editAskDecision, req: editAskReq, org: editOrg.org, deny: rr };
                break;
            }
            if (rr.updatedInput === undefined) {
                editRewrittenSinceHuman = false;
                break;
            }
            editArgs = rr.updatedInput;
            editRewrittenSinceHuman = false;
        }
        const rejudged = () => editDenied === undefined || editDenied === unanswered?.deny;
        if (rejudged() && editRewrittenSinceHuman && input.writeProtectionCheck !== undefined) {
            const check = input.writeProtectionCheck;
            const verdict = await awaitWriteProtectionJudgment((deadline) => check(toolName, editArgs, pass.req.face, input.trackedCwd?.(), deadline), boundedAwaitDeadlineMs, callSignal ?? input.abortSignal);
            if (verdict !== undefined && verdict.kind !== "clear") {
                editDenied = {
                    action: "deny",
                    message: verdict.kind === "hit"
                        ? `the approved edit for "${toolName}" was rewritten by the restriction chain onto a write-protected path (table entry "${verdict.hit.name}") that no approval covers — denied fail-closed; re-submit the edited action directly`
                        : `the approved edit for "${toolName}" was rewritten by the restriction chain onto a target whose destination could not be determined (target_unresolved: ${verdict.cause}) — denied fail-closed; re-submit the edited action directly`,
                };
                pass.deniedBy = "write_protection";
            }
        }
        if (rejudged() && input.shellReadCheck !== undefined) {
            const station = input.shellReadCheck;
            const judged = station.judge(pass.req, editArgs, input.trackedCwd?.(), callSignal ?? input.abortSignal, { seat: "rejudge", toolCallId });
            if (judged !== null) {
                let verdict;
                try {
                    verdict = await withGateTimeout(judged, boundedAwaitDeadlineMs(), callSignal ?? input.abortSignal, "shellReadStation");
                }
                catch {
                    verdict = station.unanswered(pass.req, "the read station could not answer");
                }
                const reading = readStationAnswer(verdict, { toolName, toolCallId, report: (e) => traceHookCrash(input, e, notifier) });
                if (reading.kind !== "vouch") {
                    editDenied = {
                        action: "deny",
                        message: reading.verdict.sentence ?? `the approved edit for "${toolName}" reads where the read boundary does not vouch — denied fail-closed; re-submit the command as a fresh call and answer its card`,
                    };
                    pass.deniedBy = "read_boundary";
                    if (reading.verdict.details !== undefined)
                        pass.denyDetails = reading.verdict.details;
                }
            }
        }
        if (unanswered !== undefined && editDenied === unanswered.deny && pass.parkFailed === undefined) {
            const parked = await parkAsk(unanswered.ask, unanswered.req, editArgs, safetyOf(unanswered.ask), unanswered.deny !== undefined || undefined, unanswered.org);
            if (parked)
                return parked;
        }
        if (unanswered !== undefined && unanswered.deny === undefined && editDenied === undefined)
            refusedAtResolution(ledger.fromResolved(await (callSignal !== undefined ? resolveAsk(unanswered.ask, unanswered.req, callSignal) : resolveAsk(unanswered.ask, unanswered.req)), unanswered.ask, unanswered.req));
        pass.decision = editDenied !== undefined ? refusalOf(editDenied, editArgs) : { ...pass.decision, updatedInput: editArgs };
    }
    return await exitGate(pass);
}