@sema-agent/core 7.40.1 → 7.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +188 -0
- package/dist/agents/agent-transcript-tool.d.ts +10 -2
- package/dist/agents/agent-transcript-tool.js +52 -26
- package/dist/agents/list-agents-tool.d.ts +17 -2
- package/dist/agents/list-agents-tool.js +28 -16
- package/dist/agents/peer-session-drain.d.ts +3 -1
- package/dist/agents/peer-session-drain.js +1 -0
- package/dist/agents/subagent-steps.d.ts +12 -2
- package/dist/agents/subagent-steps.js +8 -4
- package/dist/agents/subagent.d.ts +1 -17
- package/dist/agents/subagent.js +12 -24
- package/dist/core/agent-definition.d.ts +19 -40
- package/dist/core/agent-state.d.ts +91 -0
- package/dist/core/agent-state.js +79 -0
- package/dist/core/ask-origin.d.ts +28 -6
- package/dist/core/ask-origin.js +9 -5
- package/dist/core/ask-unresolvable-notice.d.ts +27 -4
- package/dist/core/ask-unresolvable-notice.js +8 -0
- package/dist/core/auto-promote.d.ts +14 -27
- package/dist/core/auto-promote.js +5 -5
- package/dist/core/checkpoint-store.d.ts +11 -12
- package/dist/core/decision-receipt.d.ts +5 -2
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/engine-notice.d.ts +7 -1
- package/dist/core/gate-crash-trace.d.ts +1 -1
- package/dist/core/gate-fold.js +7 -3
- package/dist/core/gate-lanes.js +22 -3
- package/dist/core/governance-codes.d.ts +3 -1
- package/dist/core/governance-codes.js +3 -0
- package/dist/core/hooks.d.ts +20 -6
- package/dist/core/hooks.js +28 -28
- package/dist/core/mcp-tool-meta.d.ts +24 -0
- package/dist/core/mcp-tool-meta.js +17 -0
- package/dist/core/mcp.d.ts +1 -6
- package/dist/core/mcp.js +6 -7
- package/dist/core/mode-policy.d.ts +25 -0
- package/dist/core/mode-policy.js +8 -0
- package/dist/core/protocol-table.d.ts +3 -0
- package/dist/core/protocol-table.js +3 -0
- package/dist/core/reminder-mint.d.ts +21 -1
- package/dist/core/reminder-mint.js +20 -0
- package/dist/core/retired-keys.d.ts +2 -1
- package/dist/core/retired-keys.js +13 -2
- package/dist/core/rule-denial-sentence.d.ts +2 -2
- package/dist/core/runner/call-hook-stations.d.ts +106 -0
- package/dist/core/runner/call-hook-stations.js +118 -0
- package/dist/core/runner/contracts.d.ts +35 -25
- package/dist/core/runner/gate-exit.d.ts +5 -1
- package/dist/core/runner/gate-exit.js +10 -6
- package/dist/core/runner/prepare-delegation-surface.d.ts +1 -0
- package/dist/core/runner/prepare-delegation-surface.js +4 -4
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -3
- package/dist/core/runner/prepare-gate-stations.js +13 -70
- package/dist/core/runner/prepare-inherited-gate.d.ts +6 -3
- package/dist/core/runner/prepare-inherited-gate.js +5 -3
- package/dist/core/runner/prepare-park-ask.d.ts +4 -0
- package/dist/core/runner/prepare-park-ask.js +4 -1
- package/dist/core/runner/prepare-policy-chain.d.ts +6 -5
- package/dist/core/runner/prepare-policy-chain.js +14 -25
- package/dist/core/runner/prepare-project-context.d.ts +15 -16
- package/dist/core/runner/prepare-project-context.js +15 -11
- package/dist/core/runner/prepare-run-refs.d.ts +8 -8
- package/dist/core/runner/prepare-run-refs.js +3 -3
- package/dist/core/runner/prepare-safety-scan.js +3 -3
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -1
- package/dist/core/runner/prepare-suspend-saga.js +2 -1
- package/dist/core/runner/prepare-task.js +14 -12
- package/dist/core/runner/prepare-turn-wiring.d.ts +3 -1
- package/dist/core/runner/prepare-turn-wiring.js +16 -13
- package/dist/core/runner/resume-admission.js +2 -1
- package/dist/core/runner/resume-apply.js +12 -23
- package/dist/core/runner/resume-checkpoint-screen.js +3 -0
- package/dist/core/runner/run-leg.js +61 -47
- package/dist/core/runner/runtask.d.ts +1 -1
- package/dist/core/runner/session-rule-policy.d.ts +7 -19
- package/dist/core/runner/session-rule-policy.js +1 -2
- package/dist/core/runner/skill-base-dir.d.ts +10 -0
- package/dist/core/runner/skill-base-dir.js +4 -0
- package/dist/core/runner/synthetic-tools.d.ts +11 -17
- package/dist/core/runner/synthetic-tools.js +7 -8
- package/dist/core/safety-axis-vocab.d.ts +2 -2
- package/dist/core/safety-axis-vocab.js +2 -0
- package/dist/core/session-policy-store.d.ts +63 -11
- package/dist/core/session-policy-store.js +52 -6
- package/dist/core/skill-grant.d.ts +239 -0
- package/dist/core/skill-grant.js +313 -0
- package/dist/core/skills-directory.d.ts +5 -34
- package/dist/core/skills-directory.js +9 -58
- package/dist/core/task-registry-agent.d.ts +14 -2
- package/dist/core/task-registry-agent.js +23 -8
- package/dist/core/task-registry-shared.d.ts +6 -0
- package/dist/core/task-registry.d.ts +16 -0
- package/dist/core/task-registry.js +19 -6
- package/dist/core/task-spec.d.ts +10 -0
- package/dist/core/tool-face.d.ts +3 -2
- package/dist/core/tool-name-aliases.d.ts +38 -12
- package/dist/core/tool-name-aliases.js +16 -0
- package/dist/core/tool-name-readings.d.ts +6 -2
- package/dist/core/tool-name-readings.js +6 -4
- package/dist/core/tool-policy.d.ts +2 -2
- package/dist/core/tool-registry.d.ts +1 -4
- package/dist/core/tool-registry.js +0 -3
- package/dist/core/tool-spec.d.ts +11 -13
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +15 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/engine/harness/agent-harness.d.ts +12 -1
- package/dist/engine/harness/agent-harness.js +17 -13
- package/dist/engine/loop/agent-loop.d.ts +16 -1
- package/dist/engine/loop/agent-loop.js +9 -15
- package/dist/engine/loop/types.d.ts +2 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.js +4 -2
- package/dist/stores/file/adoption/adopt.js +23 -16
- package/dist/stores/file/index.d.ts +8 -2
- package/dist/stores/file/index.js +2 -2
- package/dist/stores/file/mailbox-store.js +2 -2
- package/dist/stores/file/permission-rule-adopt.js +10 -1
- package/dist/stores/file/permission-rule-store.d.ts +6 -4
- package/dist/stores/file/permission-rule-store.js +127 -59
- package/dist/stores/file/session-policy-store.d.ts +86 -14
- package/dist/stores/file/session-policy-store.js +135 -118
- package/dist/stores/file/task-list-store.d.ts +5 -0
- package/dist/stores/file/task-list-store.js +18 -4
- package/dist/stores/file/usage-window-store.d.ts +9 -1
- package/dist/stores/file/usage-window-store.js +47 -33
- package/dist/tools/fs/safety.d.ts +1 -1
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +45 -5
- package/wire-changes/core@7.41.0.json +1865 -0
- package/dist/core/runner/active-skill-scope.d.ts +0 -58
- package/dist/core/runner/active-skill-scope.js +0 -133
- package/dist/core/skill-tool-specifier.d.ts +0 -80
- package/dist/core/skill-tool-specifier.js +0 -57
|
@@ -79,7 +79,7 @@ function stampPlacementRootSessionId(placementRootResolved) {
|
|
|
79
79
|
return placementValueOrAbsent(placementRootResolved);
|
|
80
80
|
}
|
|
81
81
|
export function prepareSuspendSaga(input) {
|
|
82
|
-
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
|
|
82
|
+
const { gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter } = input;
|
|
83
83
|
if (!gateMachineryActive)
|
|
84
84
|
return { saga: undefined };
|
|
85
85
|
const inFlightSpendMicroUsd = () => {
|
|
@@ -110,6 +110,7 @@ export function prepareSuspendSaga(input) {
|
|
|
110
110
|
readFileState: readFileStateForCheckpoint ? [...readFileStateForCheckpoint.entries()] : undefined,
|
|
111
111
|
readFace: faceCheckpointSection(),
|
|
112
112
|
writeFace: writeFaceCheckpointSection(),
|
|
113
|
+
skillGrants: skillGrantCheckpointSection(),
|
|
113
114
|
reminderMark,
|
|
114
115
|
repairBundle: repairBundleForCheckpoint(parkedSpendMicroUsd),
|
|
115
116
|
workspaceHandle,
|
|
@@ -20,7 +20,8 @@ import { persistedPathRowsOfTask, ruleStoreUnreadableNotice } from "./persisted-
|
|
|
20
20
|
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
21
21
|
import { STALL_FIRST_BYTE_MS, STALL_FIRST_TOKEN_MS, STALL_IDLE_MS, withBrainCallGuardrail } from "../../brain/timeout.js";
|
|
22
22
|
import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
|
|
23
|
-
import { OUTPUT_TOOL_NAME, createOutputTool } from "./synthetic-tools.js";
|
|
23
|
+
import { OUTPUT_TOOL_NAME, SKILL_TOOL_NAME, createOutputTool } from "./synthetic-tools.js";
|
|
24
|
+
import { skillGateWiring } from "../skill-grant.js";
|
|
24
25
|
import { compileOutputSchema } from "./strict-output-schema.js";
|
|
25
26
|
import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
|
|
26
27
|
import { foldAdmissionFreeze } from "../memory-admission.js";
|
|
@@ -396,14 +397,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
396
397
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
397
398
|
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
398
399
|
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, request: fileHistoryRequest, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
399
|
-
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef,
|
|
400
|
+
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillGrants, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, bindPermissionModeSeat, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
400
401
|
const legContextOverlay = () => runnerSelf?.contextOverlayOf?.(harnessRef.current?.getModelRef() ?? resolvedRole.modelRef);
|
|
401
402
|
let resolvedReadFace;
|
|
402
403
|
let resolvedWriteFace;
|
|
403
404
|
let readDenyAdditionsNormalized = [];
|
|
404
405
|
let handsLessResolvedFace;
|
|
405
406
|
let handsLessResolvedWriteFace;
|
|
406
|
-
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef,
|
|
407
|
+
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, permissionMode, commitModeSeats, endModeCeiling, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, ancestorSessionRulesRef, ancestorRulesNow, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, writeFaceCheckpointSection, skillGrantCheckpointSection, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, parentSpecSeat, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, carrierWriteFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDeciderRef.current, autoModeDenialTracking: () => autoModeDenialTrackingRef.current, autoModeArming: () => autoModeArmingRef.current, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, resolvedWriteFace: () => resolvedWriteFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, handsLessResolvedWriteFace: () => handsLessResolvedWriteFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
407
408
|
bindPermissionModeSeat(permissionMode);
|
|
408
409
|
const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
|
|
409
410
|
const persistedPathRowsRead = persistedPathRowsOfTask({ deps, principal: spec.principal, sessionId, root: taskRootFinal, home: executionEnv.homeDir, taskId: hostTaskId, handsEnabled, signals: [abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])], onUnread: announceRuleStoreSkipped });
|
|
@@ -558,7 +559,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
558
559
|
handsLessResolvedWriteFace = handsReadFace.handsLessResolvedWriteFace;
|
|
559
560
|
shellGatedTools = handsReadFace.shellGatedTools;
|
|
560
561
|
await armAutoMode();
|
|
561
|
-
const { worktreeSessionRef } = prepareDelegationSurface({ spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, taskRootCanonical, executionEnv, runnerSelf, backgroundTaskToolsActive, shellReadAdmission, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, sessionBox, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle });
|
|
562
|
+
const { worktreeSessionRef } = prepareDelegationSurface({ spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, taskRootCanonical, executionEnv, runnerSelf, backgroundTaskToolsActive, shellReadAdmission, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, sessionBox, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, checkpointSeat, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle });
|
|
562
563
|
const { liveQuestionFace, contentAskBindings, contentAskRoutable, lateStrandedAnswers, discloseStrandedAnswers, settleContentAskBindings, durableQuestionFace, questionToolMounted, mountedQuestionTool } = prepareQuestionFace({ frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks: () => inheritedUnavailableAsks });
|
|
563
564
|
if (spec.handsReadOnly !== true) {
|
|
564
565
|
const sessionScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
|
|
@@ -615,8 +616,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
615
616
|
deps.onError?.(asThrownError(err), { phase: "config", sessionId });
|
|
616
617
|
}
|
|
617
618
|
}
|
|
618
|
-
const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine,
|
|
619
|
-
const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent,
|
|
619
|
+
const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillGrants, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume, skillListingBudget: doors.skillListingBudget });
|
|
620
|
+
const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, skillSpecs, skillSeatOf, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
|
|
620
621
|
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, dateAnchor, gitStatusRef } = await preparePromptInputs({ spec, deps, contextOverlay: legContextOverlay(), failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace: resolvedWriteFace?.inForce(), toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, session, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
621
622
|
const { deferred, memoryBlock, toolSearch: toolSearchPolicy } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
|
|
622
623
|
prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, mcp, sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
|
|
@@ -729,7 +730,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
729
730
|
releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
|
|
730
731
|
}
|
|
731
732
|
}
|
|
732
|
-
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate,
|
|
733
|
+
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
733
734
|
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, internals, resume, sessionId, runId, hostTaskId, taskScope, hooks, preToolUseObservational, policyLayers, effectivePolicy, handsEnabled, taskRootFinal, mcp, irreversibleTools, egressTools, shellReadStationArmed: handsReadFace.shellReadStationArmed, toolEffects, ownedEnv, executionEnv, offloadStore, onceLedger, usageWindows, envLifetimeSuspendAt, runtimeCaps, resolvedInteractionPosture, durableQuestionFace, liveQuestionFace, checkpointStore, sessions, modelGateManifest, autoModeArmReason, permissionMode, lockedPreflight, peerLaneRefs, frameSettlement, harness, pausedRef, frozenOnAsk, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox });
|
|
734
735
|
const writeProtectionCheck = writeProtection?.check;
|
|
735
736
|
writeProtectionJudgeRef.current = writeProtection?.judgeTarget;
|
|
@@ -740,16 +741,17 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
740
741
|
});
|
|
741
742
|
}
|
|
742
743
|
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
|
|
743
|
-
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
744
|
+
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
744
745
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
745
|
-
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
746
|
-
|
|
746
|
+
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, skillSpecs, now, humanReviewRef, abortController, harness, pausedRef });
|
|
747
|
+
const seatInputsFor = skillGateWiring({ tools, skillToolName: SKILL_TOOL_NAME, seatOf: skillSeatOf, mode: () => permissionMode.current, lane: skillGrantLane, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.skill_allowed", version: 1, taskId: hostTaskId, ...info, entries: [...info.entries], ts: Date.now() })) });
|
|
748
|
+
const { approvedCallScreen } = prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, readDenyInForce: () => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...handsReadFaceInput.pathDenyRules.filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider: autoModeDeciderRef, autoModeDenialTracking: autoModeDenialTrackingRef, askRoute: { ...wiringManifest.ask, effective: askSeatEffective(wiringManifest) }, permissionMode, toolMarkSources, ...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}), ancestorArbitrations, runId, stopForDenialLimit, permissionRuleLane, seatInputsFor, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash, frameSettlement });
|
|
747
749
|
const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
|
|
748
750
|
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, toolRosterDeltas: rosterSeat, microCompactKnob, harness, batchHaltRef, gitStatusRef, postureFrameRef, requestLossyRef, trimPressureRef, contextOverlay: legContextOverlay, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}) });
|
|
749
751
|
const preparedHolder = {};
|
|
750
|
-
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
752
|
+
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants: skillGrantLane, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
751
753
|
await onceLedger.settle(session, announcedListingsRef);
|
|
752
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
754
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, registryAccess: { owner: hostTaskId, scope: taskScope }, reminderMark, reminderDisclosureCounts, fullShellReachable, approvalPosture: { get mode() { return permissionMode.current; }, askEffective: askSeatEffective(wiringManifest) }, ...(outputStyleFrame !== undefined ? { outputStyleFrame } : {}), permissionMode, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(mcpRedial !== undefined ? { mcpRedial } : {}), ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, skillGrants: skillGrantLane, skillSpecs, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, endModeCeiling, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, undeliveredContinuationRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, stopForDenialLimit, suspendForReview, ...(readFileStateForCheckpoint !== undefined ? { readFileState: readFileStateForCheckpoint } : {}), resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, frameReceipts: { pending: [], listingSnapshotOwed: false }, frameSettlement, ...(peerLaneRefs.boundaryRound !== undefined ? { peerBoundaryRound: peerLaneRefs.boundaryRound } : {}), gitStatusRef, postureFrameRef, listBackgroundTasks, hookIdentity, ...(sessionBoxBound !== undefined ? { sessionBox: sessionBoxBound } : {}), hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(shellReadCheck !== undefined ? { shellReadCheck } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}), ...(approvedCallScreen !== undefined ? { approvedCallScreen } : {}) });
|
|
753
755
|
rollback.commit();
|
|
754
756
|
commitModeSeats(abortController.signal);
|
|
755
757
|
const prepared = buildPrepared();
|
|
@@ -78,8 +78,10 @@ export interface PrepareTurnWiringInput {
|
|
|
78
78
|
/** borrowed-mutable — the live read-file state, or undefined. Writers here, at RUN time: `detectExternalChanges` evicts a
|
|
79
79
|
* not-found entry; `onCompactionApplied` applies a landed compaction to it. The hands phase mints it. */
|
|
80
80
|
readFileStateForCheckpoint: ReadFileState | undefined;
|
|
81
|
-
/** borrowed-readonly — the deny-narrowing fold, or undefined (the changed-files deny door's
|
|
81
|
+
/** borrowed-readonly — the deny-narrowing fold, or undefined (one of the changed-files deny door's two authorities). */
|
|
82
82
|
denyNarrowingPolicy: ToolPolicy | undefined;
|
|
83
|
+
/** borrowed-readonly — the skill lane: the run's skill deny rows (the deny door's other authority; only `denying` is read). */
|
|
84
|
+
skillGrants: Prepared["skillGrants"];
|
|
83
85
|
/** borrowed-readonly — the run's abort controller; only `signal` (the deny door's and the stat's signal). */
|
|
84
86
|
abortController: Pick<AbortController, "signal">;
|
|
85
87
|
/** borrowed-readonly — the per-task identity (the background listing's owner). */
|
|
@@ -12,7 +12,7 @@ import { PROMPT_HASH_SALT } from "./prompt-hash-salt.js";
|
|
|
12
12
|
import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
|
|
13
13
|
import { thrownText } from "../thrown-value.js";
|
|
14
14
|
export function prepareTurnWiring(input) {
|
|
15
|
-
const { deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
|
|
15
|
+
const { deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, skillGrants, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
|
|
16
16
|
const cacheBreakDetector = deps.cacheBreakDetection === false ? undefined : new CacheBreakDetector();
|
|
17
17
|
const cacheFingerprint = cacheBreakDetector
|
|
18
18
|
? { systemPrompt: systemPromptSeat.current, tools: toolsToFingerprintInputs(harnessTools) }
|
|
@@ -101,17 +101,20 @@ export function prepareTurnWiring(input) {
|
|
|
101
101
|
const onCompactionApplied = handsEnabled && readFileStateForCheckpoint
|
|
102
102
|
? (attachedComplete, preserveReadState) => applyContextShrinkToReadFileState(readFileStateForCheckpoint, { kind: "summarized", attachedComplete, ...(preserveReadState !== undefined ? { preserveKeys: preserveReadState } : {}) })
|
|
103
103
|
: undefined;
|
|
104
|
-
const changedFilesReadDenied =
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
104
|
+
const changedFilesReadDenied = async (path) => {
|
|
105
|
+
const probe = { toolName: "Read", args: { file_path: path }, toolCallId: "changed-files-visibility-probe" };
|
|
106
|
+
if (skillGrants.denying(probe) !== undefined)
|
|
107
|
+
return true;
|
|
108
|
+
if (denyNarrowingPolicy === undefined)
|
|
109
|
+
return false;
|
|
110
|
+
try {
|
|
111
|
+
const d = refuseOutOfContractDecision(await denyNarrowingPolicy.check(probe, abortController.signal));
|
|
112
|
+
return d.action === "deny";
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
115
118
|
const detectExternalChanges = handsEnabled && readFileStateForCheckpoint
|
|
116
119
|
? async (maxFiles) => {
|
|
117
120
|
const candidates = [...readFileStateForCheckpoint.entries()]
|
|
@@ -122,7 +125,7 @@ export function prepareTurnWiring(input) {
|
|
|
122
125
|
const changed = [];
|
|
123
126
|
const evicted = [];
|
|
124
127
|
for (const [path, entry] of candidates) {
|
|
125
|
-
if (
|
|
128
|
+
if (await changedFilesReadDenied(path))
|
|
126
129
|
continue;
|
|
127
130
|
try {
|
|
128
131
|
const info = await executionEnv.fileInfo(path, abortController.signal);
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { CheckpointError, readPendingSteerQueue, refuseRetiredModeSeed, resolveCheckpointStore, validatePendingSteer } from "../checkpoint-store.js";
|
|
2
2
|
import { refuseResumeDoors } from "../mode-policy.js";
|
|
3
3
|
import { describeSuppliedValue } from "./decide-continuation.js";
|
|
4
|
+
import { detachSkillLists } from "../skill-grant.js";
|
|
4
5
|
export async function resumeAdmission(input) {
|
|
5
6
|
const { token, outcome, taskConfig, runner, parentConstraintRegistry } = input;
|
|
6
7
|
let internals = input.internals;
|
|
7
8
|
if (outcome === null || typeof outcome !== "object") {
|
|
8
9
|
throw new CheckpointError("checkpoint.invalid_outcome", `resume outcome must be an object naming its gate (got ${outcome === null ? "null" : typeof outcome})`);
|
|
9
10
|
}
|
|
10
|
-
const config = typeof taskConfig === "object" && taskConfig !== null ? { ...taskConfig } : taskConfig;
|
|
11
|
+
const config = typeof taskConfig === "object" && taskConfig !== null ? { ...taskConfig, ...(Array.isArray(taskConfig.skills) ? { skills: detachSkillLists(taskConfig.skills) } : {}) } : taskConfig;
|
|
11
12
|
internals = internals !== undefined ? { ...internals } : undefined;
|
|
12
13
|
const store = resolveCheckpointStore(config, runner.deps);
|
|
13
14
|
if (!store) {
|
|
@@ -3,15 +3,19 @@ import { isAskOrigin } from "../ask-origin.js";
|
|
|
3
3
|
import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
4
4
|
import { CheckpointError, remainingBudgetMicroUsd } from "../checkpoint-store.js";
|
|
5
5
|
import { settledByDecider } from "../gate-outcome.js";
|
|
6
|
-
import {
|
|
6
|
+
import { mintHookInvocationIdentity, resolveHookTimeoutMs, runHookSeat } from "../hooks.js";
|
|
7
7
|
import { checkToolPolicyProjection, policyCannotAnswer, refuseOutOfContractDecision } from "../tool-policy.js";
|
|
8
8
|
import { callFaceSeat, parkedCallFaceOf } from "../tool-roster.js";
|
|
9
9
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
10
10
|
import { deepJsonEqual, describeSuppliedValue } from "./decide-continuation.js";
|
|
11
11
|
import { orgVerdictBeforeClaim } from "./permission-rule-lanes.js";
|
|
12
12
|
import { mintGateOutcome } from "./gate-exit.js";
|
|
13
|
+
import { chainCannotJudge } from "./call-hook-stations.js";
|
|
13
14
|
import { asThrownError, thrownText } from "../thrown-value.js";
|
|
14
15
|
import { wireOf } from "../tool-name-readings.js";
|
|
16
|
+
import { parkedSkillApprovalRefusal } from "../skill-grant.js";
|
|
17
|
+
import { SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, normalizeSkills } from "./synthetic-tools.js";
|
|
18
|
+
import { skillLoadReading } from "./skill-base-dir.js";
|
|
15
19
|
export async function resumeApply(input) {
|
|
16
20
|
const { cp, config, internals, outcomeGate, wakeMessage, resumeSignal, recheckGovernanceWindow, plainReviewOutcome, plainParkOutcome, runner, effectiveDelegationFacts } = input;
|
|
17
21
|
let plainPolicyOutcome = input.plainPolicyOutcome;
|
|
@@ -89,6 +93,12 @@ export async function resumeApply(input) {
|
|
|
89
93
|
p.then((v) => { editSignal.removeEventListener("abort", onAbort); resolve(v); }, (e) => { editSignal.removeEventListener("abort", onAbort); reject(e); });
|
|
90
94
|
});
|
|
91
95
|
};
|
|
96
|
+
if (plainPolicyOutcome?.decision === "allow" && cp.pendingAction.kind === "tool_approval") {
|
|
97
|
+
const servedSkills = normalizeSkills(config.skills).filter((s) => skillLoadReading(s, SKILL_CONTENT_MAX_CHARS).loads);
|
|
98
|
+
const skillRefusal = parkedSkillApprovalRefusal(cp.pendingAction, plainPolicyOutcome.updatedInput ?? cp.pendingAction.args, servedSkills, SKILL_TOOL_NAME);
|
|
99
|
+
if (skillRefusal !== undefined)
|
|
100
|
+
throw new CheckpointError("checkpoint.invalid_outcome", skillRefusal, { field: "boundGrantDigest" });
|
|
101
|
+
}
|
|
92
102
|
if (plainPolicyOutcome !== undefined &&
|
|
93
103
|
plainPolicyOutcome.decision === "allow" &&
|
|
94
104
|
plainPolicyOutcome.updatedInput !== undefined &&
|
|
@@ -111,13 +121,7 @@ export async function resumeApply(input) {
|
|
|
111
121
|
const ig = cp.state.inheritedGate;
|
|
112
122
|
if (ig?.requiresParentConstraint === true) {
|
|
113
123
|
const chain = ig.constraintChain;
|
|
114
|
-
const unprojectable =
|
|
115
|
-
? "the checkpoint predates the frozen projection chain (no constraintChain recorded)"
|
|
116
|
-
: chain.some((e) => "opaque" in e)
|
|
117
|
-
? "the inherited chain carries an OPAQUE layer (no projection exported)"
|
|
118
|
-
: chain.some((e) => !("opaque" in e) && e.requiresLiveRemainder)
|
|
119
|
-
? "an inherited chain layer declares a live remainder beyond its projection"
|
|
120
|
-
: undefined;
|
|
124
|
+
const unprojectable = chainCannotJudge(ig);
|
|
121
125
|
if (unprojectable !== undefined) {
|
|
122
126
|
throw new CheckpointError("resume.constraint_unprojectable", `the approver EDITED this call's input, but the inherited ancestor chain cannot re-adjudicate the edit statically: ${unprojectable}. ` +
|
|
123
127
|
"Refusing the edited resume pre-CAS (the checkpoint stays pending and remains decidable) — approve the shown input as-is, deny it, " +
|
|
@@ -156,21 +160,6 @@ export async function resumeApply(input) {
|
|
|
156
160
|
`refused pre-CAS (the checkpoint stays pending); re-submit the edited action so the rewrite is adjudicated and approved synchronously`);
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
|
-
const resumeHooks = config.hooks ?? runner.deps.hooks;
|
|
160
|
-
if (resumeHooks?.preToolUse !== undefined && resumeHooks.preToolUseObservational === true) {
|
|
161
|
-
try {
|
|
162
|
-
await raceEditAbort(Promise.resolve(resumeHooks.preToolUse(cp.pendingAction.toolName, cloneObserverInput(editedArgs), {
|
|
163
|
-
toolCallId: cp.pendingAction.toolCallId,
|
|
164
|
-
toolName: cp.pendingAction.toolName,
|
|
165
|
-
})));
|
|
166
|
-
}
|
|
167
|
-
catch (err) {
|
|
168
|
-
if (err instanceof CheckpointError)
|
|
169
|
-
throw err;
|
|
170
|
-
throw new CheckpointError("resume.constraint_rejected", `the declared-observational PreToolUse face threw while observing the approver's edited args (${thrownText(err)}) — ` +
|
|
171
|
-
"refused fail-closed pre-CAS (the checkpoint stays pending and remains decidable)");
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
163
|
}
|
|
175
164
|
const orgProvider = runner.deps.permissionRuleStore;
|
|
176
165
|
if (plainPolicyOutcome?.decision === "allow" && plainPolicyOutcome.hostDecision.decidedBy !== "person" && orgProvider?.partitions.org === true && cp.pendingAction.kind === "tool_approval") {
|
|
@@ -2,6 +2,7 @@ import { persistedReadDenyEntryProblem } from "../../tools/fs/read-deny.js";
|
|
|
2
2
|
import { isAskOrigin } from "../ask-origin.js";
|
|
3
3
|
import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, MAX_SUPPORTED_CHECKPOINT_VERSION, realApprovalOrgFact } from "../checkpoint-store.js";
|
|
4
4
|
import { constraintChainDigest, constraintChainEntryOfSuppliedLayer } from "../tool-policy.js";
|
|
5
|
+
import { readFrozenSkillGrants } from "../skill-grant.js";
|
|
5
6
|
export function resumeCheckpointScreen(input) {
|
|
6
7
|
const { cp, resumeSignal, internals, runner } = input;
|
|
7
8
|
const { realApproval: realApprovalRow, face: faceRow, f012: f012Row } = CHECKPOINT_FEATURES;
|
|
@@ -46,6 +47,8 @@ export function resumeCheckpointScreen(input) {
|
|
|
46
47
|
throw new CheckpointError("checkpoint.invalid_outcome", `this checkpoint carries a write-face section (state.writeFace) that is not well-formed — refusing to resume a damaged write-face row (corruption guard), the checkpoint stays pending`, { reason: "write_face_damaged" });
|
|
47
48
|
}
|
|
48
49
|
}
|
|
50
|
+
if (readFrozenSkillGrants(cp.state.skillGrants) === undefined)
|
|
51
|
+
throw new CheckpointError("checkpoint.invalid_outcome", "this checkpoint carries a skill-grant section (state.skillGrants) that does not read as grant rows — refusing to resume without the grant rows and refusals it carries (corruption guard), the checkpoint stays pending", { reason: "skill_grants_damaged" });
|
|
49
52
|
}
|
|
50
53
|
if (realApprovalOrgFact(preCasGateBit) !== undefined && runner.deps.permissionRuleStore?.partitions.org !== true) {
|
|
51
54
|
throw new CheckpointError("checkpoint.unsupported_version", `this checkpoint's approval was minted under organization governance (org ${String(realApprovalOrgFact(preCasGateBit))}, routed as ${String(preCasGateBit?.origin)}) and this worker has no org adjudication wiring (its permission-rule store carries no org partition) — a governed approval may only be redeemed where governance can be enforced; the checkpoint stays pending, resume it on an org-wired worker`, { reason: "governed_unwired" });
|
|
@@ -8,6 +8,8 @@ import { formatHookFeedback, hookSeatExpiredError, runHookSeat } from "../hooks.
|
|
|
8
8
|
import { buildAppliedHumanInputEvent, buildHumanInputEvent, projectHumanInput } from "../human-input-projection.js";
|
|
9
9
|
import { ORG_ADJUDICATION_TIMEOUT_MS, settleOrgVerdictWithin } from "../permission-rule-org.js";
|
|
10
10
|
import { applyPersistedTightening, disclosedRuleSet } from "../persisted-rule-arms.js";
|
|
11
|
+
import { parkedSkillApprovalRefusal, skillRowRefusal } from "../skill-grant.js";
|
|
12
|
+
import { SKILL_TOOL_NAME } from "./synthetic-tools.js";
|
|
11
13
|
import { computeCostMicroUsd } from "../pricing.js";
|
|
12
14
|
import { mintSystemReminder } from "../reminder-mint.js";
|
|
13
15
|
import { hasDestroy } from "../remote-env.js";
|
|
@@ -19,6 +21,7 @@ import { errorCodeOf } from "./assemble-result.js";
|
|
|
19
21
|
import { DEFAULT_PRECALL_OUTPUT_TOKENS, platformLimitTerminal } from "./clock-and-limits.js";
|
|
20
22
|
import { mintOutputStyleReminder, owedPostureText } from "./compaction-restate.js";
|
|
21
23
|
import { deepJsonEqual, resumeContinuation } from "./decide-continuation.js";
|
|
24
|
+
import { chainCannotJudge } from "./call-hook-stations.js";
|
|
22
25
|
import { settleExecutionRecord } from "./execution-record.js";
|
|
23
26
|
import { holdPrompt } from "./prompt-block.js";
|
|
24
27
|
import { mintGateOutcome } from "./gate-exit.js";
|
|
@@ -565,7 +568,8 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
565
568
|
if (decidedGate === undefined) {
|
|
566
569
|
throw new CheckpointError("checkpoint.invalid_outcome", "pending action reached the resolver with no settlement record on its decision (gateOutcome) — refusing to execute or settle a decision that carries no record");
|
|
567
570
|
}
|
|
568
|
-
const
|
|
571
|
+
const humanRewrite = wireOf("resume.questionArgsShown", pendingAction) === ASK_USER_QUESTION_TOOL_NAME ? undefined : outcome.updatedInput;
|
|
572
|
+
const resolvedArgs = humanRewrite !== undefined ? humanRewrite : pendingAction.args;
|
|
569
573
|
const pendingLabel = (() => { const l = prepared.tools.find((t) => t.name === pendingAction.toolName)?.label; return l !== undefined && l !== pendingAction.toolName ? { label: l } : {}; })();
|
|
570
574
|
const spelledName = pendingAction.names?.[0] ?? pendingAction.toolName;
|
|
571
575
|
emit({ type: "tool_start", toolCallId: pendingAction.toolCallId, toolName: spelledName, ...pendingLabel, args: resolvedArgs });
|
|
@@ -601,32 +605,41 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
601
605
|
if (outcome.decision !== "allow") {
|
|
602
606
|
throw new CheckpointError("checkpoint.invalid_outcome", `pending action reached the resolver with decision "${String(outcome.decision)}" — only "allow" executes and only "deny" injects a denial; refusing to execute`);
|
|
603
607
|
}
|
|
608
|
+
const screened = await prepared.approvedCallScreen?.({ toolCallId: pendingAction.toolCallId, toolName: pendingAction.toolName, args: structuredClone(resolvedArgs), decidedBy: outcome.hostDecision.decidedBy });
|
|
609
|
+
if (screened !== undefined && "refused" in screened) {
|
|
610
|
+
const hookDenial = formatHookFeedback(screened.refused, prepared.reminderMark);
|
|
611
|
+
await settleEnd(true, { content: hookDenial }, vetoed("hook"));
|
|
612
|
+
emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, hookDenial, true)), "toolResult", pendingAction.toolCallId);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
const executedArgs = humanRewrite !== undefined ? resolvedArgs : screened !== undefined ? screened.args : resolvedArgs;
|
|
616
|
+
const unseen = !deepJsonEqual(executedArgs, pendingAction.args);
|
|
617
|
+
const beltReq = () => ({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)), budget: beltBudget, ...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}), ...advertisedWritableRootsSeat(prepared.advertisedWritableDirs) });
|
|
618
|
+
const unjudgeable = unseen ? chainCannotJudge(resume.cp.state.inheritedGate) : undefined;
|
|
619
|
+
if (unjudgeable !== undefined) {
|
|
620
|
+
const chainDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: its input changed after the approval and the inherited ancestor chain cannot judge the changed input (${unjudgeable}). This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
|
|
621
|
+
await settleEnd(true, { content: chainDenial }, vetoed("policy"));
|
|
622
|
+
emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, chainDenial, true)), "toolResult", pendingAction.toolCallId);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
604
625
|
const beltBudget = {
|
|
605
626
|
resourceRemainingMicroUsd: remainingBudgetMicroUsd(prepared.resourceLedger),
|
|
606
627
|
resourceSpentMicroUsd: prepared.resourceLedger?.spentMicroUsd ?? 0,
|
|
607
628
|
suspendCount: resume.cp.suspendCount ?? 0,
|
|
608
629
|
};
|
|
609
|
-
if (
|
|
610
|
-
const rechecked = refuseOutOfContractDecision(await prepared.basePolicyForResumeEdit.check(
|
|
611
|
-
toolName: pendingAction.toolName,
|
|
612
|
-
args: resolvedArgs,
|
|
613
|
-
toolCallId: pendingAction.toolCallId,
|
|
614
|
-
budget: beltBudget,
|
|
615
|
-
...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}),
|
|
616
|
-
...advertisedWritableRootsSeat(prepared.advertisedWritableDirs),
|
|
617
|
-
...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)),
|
|
618
|
-
}, prepared.abortController.signal));
|
|
630
|
+
if (unseen && prepared.basePolicyForResumeEdit) {
|
|
631
|
+
const rechecked = refuseOutOfContractDecision(await prepared.basePolicyForResumeEdit.check(beltReq(), prepared.abortController.signal));
|
|
619
632
|
const personUnanswered = policyCannotAnswer(rechecked, outcome.hostDecision.decidedBy);
|
|
620
633
|
const beltUnsafe = rechecked.action === "deny" ||
|
|
621
|
-
(rechecked.updatedInput !== undefined && !deepJsonEqual(rechecked.updatedInput,
|
|
634
|
+
(rechecked.updatedInput !== undefined && !deepJsonEqual(rechecked.updatedInput, executedArgs)) ||
|
|
622
635
|
personUnanswered;
|
|
623
636
|
if (beltUnsafe) {
|
|
624
637
|
const why = rechecked.action === "deny"
|
|
625
638
|
? (rechecked.message ? `: ${rechecked.message}` : "")
|
|
626
639
|
: personUnanswered
|
|
627
|
-
? " (the
|
|
628
|
-
: " (the policy rewrote
|
|
629
|
-
const editedDenial = formatHookFeedback(
|
|
640
|
+
? " (the call as it would run requires a person's approval, and this decision was the deployment's policy)"
|
|
641
|
+
: " (the policy rewrote these bytes to a value that was not approved)";
|
|
642
|
+
const editedDenial = formatHookFeedback(`${outcome.updatedInput !== undefined ? "The approver EDITED this call's input; the edited call" : "A PreToolUse hook REWROTE this approved call's input; the rewritten call"} is refused by the deployment's tool policy and was not executed${why}.`, prepared.reminderMark);
|
|
630
643
|
await settleEnd(true, { content: editedDenial }, vetoed("policy"));
|
|
631
644
|
const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, editedDenial, true));
|
|
632
645
|
emitCommitted(eid, "toolResult", pendingAction.toolCallId);
|
|
@@ -644,7 +657,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
644
657
|
}
|
|
645
658
|
if (prepared.permissionRuleOrg !== undefined) {
|
|
646
659
|
const orgVerdict = prepared.permissionRuleOrg
|
|
647
|
-
.adjudicate({ toolName: pendingAction.toolName, args:
|
|
660
|
+
.adjudicate({ toolName: pendingAction.toolName, args: executedArgs, toolCallId: pendingAction.toolCallId, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)) })
|
|
648
661
|
.catch(() => ({ status: "unavailable", disclosures: ["the org adjudication face threw on resume"] }));
|
|
649
662
|
let orgWaitCancelled = false;
|
|
650
663
|
const org = await settleOrgVerdictWithin(orgVerdict, { status: "unavailable", disclosures: [`the org adjudication face did not answer within ${ORG_ADJUDICATION_TIMEOUT_MS}ms (or the task ended first)`] }, {
|
|
@@ -678,15 +691,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
678
691
|
}
|
|
679
692
|
}
|
|
680
693
|
if (prepared.denyNarrowingPolicy) {
|
|
681
|
-
const narrowed = refuseOutOfContractDecision(await prepared.denyNarrowingPolicy.check(
|
|
682
|
-
toolName: pendingAction.toolName,
|
|
683
|
-
args: resolvedArgs,
|
|
684
|
-
toolCallId: pendingAction.toolCallId,
|
|
685
|
-
...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)),
|
|
686
|
-
budget: beltBudget,
|
|
687
|
-
...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}),
|
|
688
|
-
...advertisedWritableRootsSeat(prepared.advertisedWritableDirs),
|
|
689
|
-
}, prepared.abortController.signal));
|
|
694
|
+
const narrowed = refuseOutOfContractDecision(await prepared.denyNarrowingPolicy.check(beltReq(), prepared.abortController.signal));
|
|
690
695
|
if (narrowed.action === "deny") {
|
|
691
696
|
const narrowedDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" is now denied by ${ruleSourcePhrase("narrowing")} and was not executed${narrowed.message ? `: ${narrowed.message}` : ""}.`, prepared.reminderMark);
|
|
692
697
|
await settleEnd(true, { content: narrowedDenial }, vetoed("policy"));
|
|
@@ -695,20 +700,19 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
695
700
|
return;
|
|
696
701
|
}
|
|
697
702
|
}
|
|
703
|
+
const skillRefusal = skillRowRefusal(prepared.skillGrants, beltReq());
|
|
704
|
+
if (skillRefusal !== undefined) {
|
|
705
|
+
const skillDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${skillRefusal.message}. This approval is spent — the call has to be re-issued.`, prepared.reminderMark);
|
|
706
|
+
await settleEnd(true, { content: skillDenial }, vetoed("policy"));
|
|
707
|
+
emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, skillDenial, true)), "toolResult", pendingAction.toolCallId);
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
698
710
|
if (prepared.persistedRuleLane !== undefined) {
|
|
699
711
|
const unreadable = { unreadable: true };
|
|
700
712
|
let laneWaitCancelled = false;
|
|
701
713
|
let laneRead;
|
|
702
714
|
try {
|
|
703
|
-
laneRead = Promise.resolve(prepared.persistedRuleLane.adjudicate(
|
|
704
|
-
toolName: pendingAction.toolName,
|
|
705
|
-
args: resolvedArgs,
|
|
706
|
-
toolCallId: pendingAction.toolCallId,
|
|
707
|
-
...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)),
|
|
708
|
-
budget: beltBudget,
|
|
709
|
-
...(prepared.cwdRef !== undefined ? { cwd: prepared.cwdRef.current } : {}),
|
|
710
|
-
...advertisedWritableRootsSeat(prepared.advertisedWritableDirs),
|
|
711
|
-
})).then((answer) => normalizePersistedRuleHit(answer));
|
|
715
|
+
laneRead = Promise.resolve(prepared.persistedRuleLane.adjudicate(beltReq())).then((answer) => normalizePersistedRuleHit(answer));
|
|
712
716
|
}
|
|
713
717
|
catch {
|
|
714
718
|
laneRead = Promise.resolve(unreadable);
|
|
@@ -729,11 +733,10 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
729
733
|
}
|
|
730
734
|
}
|
|
731
735
|
if (prepared.shellReadCheck !== undefined) {
|
|
732
|
-
const edited = outcome.updatedInput !== undefined && !deepJsonEqual(outcome.updatedInput, pendingAction.args);
|
|
733
736
|
const readCall = { toolName: pendingAction.toolName, ...callFaceSeat(parkedRowLiveFace(prepared.toolRosterDeltas.current, pendingAction)) };
|
|
734
|
-
const judged = prepared.shellReadCheck.judge(readCall,
|
|
737
|
+
const judged = prepared.shellReadCheck.judge(readCall, executedArgs, prepared.cwdRef?.current, prepared.abortController.signal, {
|
|
735
738
|
toolCallId: pendingAction.toolCallId,
|
|
736
|
-
...(
|
|
739
|
+
...(unseen ? { seat: "rejudge" } : {}),
|
|
737
740
|
});
|
|
738
741
|
if (judged !== null) {
|
|
739
742
|
let verdict;
|
|
@@ -745,7 +748,7 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
745
748
|
answered = false;
|
|
746
749
|
verdict = prepared.shellReadCheck.unanswered(readCall, "the read station could not answer on the resumed leg");
|
|
747
750
|
}
|
|
748
|
-
if (!answered || verdict.disposition === "refuse" || (
|
|
751
|
+
if (!answered || verdict.disposition === "refuse" || (unseen && verdict.disposition !== "vouch")) {
|
|
749
752
|
const readDenial = formatHookFeedback(`The approved tool call "${pendingAction.toolName}" was not executed: ${verdict.sentence ?? "the read boundary does not vouch for what it reads on this leg"} This approval is spent — the call has to be re-issued and approved again.`, prepared.reminderMark);
|
|
750
753
|
await settleEnd(true, { content: readDenial, ...(verdict.details !== undefined ? { details: verdict.details } : {}) }, vetoed("read_boundary"));
|
|
751
754
|
const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, readDenial, true));
|
|
@@ -755,16 +758,25 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
755
758
|
verdict.admit?.();
|
|
756
759
|
}
|
|
757
760
|
}
|
|
761
|
+
const grantRefusal = parkedSkillApprovalRefusal(pendingAction, executedArgs, prepared.skillSpecs, SKILL_TOOL_NAME, "execution");
|
|
762
|
+
if (grantRefusal !== undefined) {
|
|
763
|
+
const grantDenial = formatHookFeedback(grantRefusal, prepared.reminderMark);
|
|
764
|
+
await settleEnd(true, { content: grantDenial }, vetoed("policy"));
|
|
765
|
+
emitCommitted(await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, grantDenial, true)), "toolResult", pendingAction.toolCallId);
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
758
768
|
const tool = prepared.tools.find((t) => t.name === pendingAction.toolName);
|
|
759
769
|
if (!tool) {
|
|
760
770
|
const e = new Error(`the approved tool "${pendingAction.toolName}" is no longer available on resume`);
|
|
761
771
|
e.code = "resume.tool_unavailable";
|
|
762
772
|
throw e;
|
|
763
773
|
}
|
|
764
|
-
const args =
|
|
774
|
+
const args = executedArgs;
|
|
775
|
+
screened?.admit();
|
|
765
776
|
onExecuteStart?.(pendingAction.toolCallId);
|
|
766
777
|
prepared.toolProgressRef.current?.noteStart(pendingAction.toolCallId, pendingAction.toolName);
|
|
767
778
|
prepared.suspendProgressRef.executedApproved = true;
|
|
779
|
+
const finalize = (executed) => prepared.harness.finalizeToolCall({ type: "toolCall", id: pendingAction.toolCallId, name: spelledName, arguments: executedArgs }, executedArgs, executed);
|
|
768
780
|
let res;
|
|
769
781
|
try {
|
|
770
782
|
res = await tool.execute(pendingAction.toolCallId, args, prepared.abortController.signal);
|
|
@@ -772,21 +784,23 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
772
784
|
catch (err) {
|
|
773
785
|
const execError = `Error: ${thrownText(err)}`;
|
|
774
786
|
const marks = thrownMarksOf(err);
|
|
775
|
-
await
|
|
776
|
-
const
|
|
787
|
+
const failed = await finalize({ result: { content: [{ type: "text", text: execError }], details: marks ?? {} }, isError: true });
|
|
788
|
+
const failedText = failed.result.content.flatMap((c) => (c.type === "text" ? [c.text] : [])).join("\n");
|
|
789
|
+
await settleEnd(true, { content: failedText, ...(marks !== undefined ? { details: marks } : {}) });
|
|
790
|
+
const eid = await prepared.session.appendMessage(toolResultMsg(pendingAction.toolCallId, pendingAction.toolName, failedText, true));
|
|
777
791
|
emitCommitted(eid, "toolResult", pendingAction.toolCallId);
|
|
778
792
|
return;
|
|
779
793
|
}
|
|
780
|
-
const
|
|
781
|
-
await settleEnd(
|
|
782
|
-
onResolvedToolSuccess?.(pendingAction.toolName,
|
|
794
|
+
const ran = await finalize({ result: res, isError: res.isError === true });
|
|
795
|
+
await settleEnd(ran.isError, ran.result);
|
|
796
|
+
onResolvedToolSuccess?.(pendingAction.toolName, ran.isError ? undefined : ran.result.details);
|
|
783
797
|
const eid = await prepared.session.appendMessage({
|
|
784
798
|
role: "toolResult",
|
|
785
799
|
toolCallId: pendingAction.toolCallId,
|
|
786
800
|
toolName: pendingAction.toolName,
|
|
787
|
-
content:
|
|
788
|
-
details:
|
|
789
|
-
isError:
|
|
801
|
+
content: ran.result.content,
|
|
802
|
+
details: ran.result.details,
|
|
803
|
+
isError: ran.isError,
|
|
790
804
|
timestamp: Date.now(),
|
|
791
805
|
});
|
|
792
806
|
emitCommitted(eid, "toolResult", pendingAction.toolCallId);
|
|
@@ -241,7 +241,7 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
241
241
|
* re-supply; on the resumed leg the CHECKPOINT snapshot is the trust floor — live internals may only
|
|
242
242
|
* TIGHTEN it (per-entry rev-monotonic ancestorRules replacement, max-rank shellGate fold), never
|
|
243
243
|
* displace it wholesale. TRUST BOUNDARY: `internals` is the DEPLOYMENT trust channel (the same tier as
|
|
244
|
-
* `
|
|
244
|
+
* `inheritedSkillGrants` and every other RunInternals field) — the library caller is trusted to
|
|
245
245
|
* re-supply the genuine chain; a caller able to invoke resumeStream already holds full Runner
|
|
246
246
|
* authority, so constraint substitution here is outside the enforced threat model (the count check
|
|
247
247
|
* catches shape MISTAKES, not a untrusted trusted caller). */
|