@sema-agent/core 7.45.0 → 7.46.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 +246 -1
- package/dist/agents/extra-tool-names.d.ts +65 -0
- package/dist/agents/extra-tool-names.js +124 -0
- package/dist/agents/subagent.d.ts +17 -5
- package/dist/agents/subagent.js +33 -25
- package/dist/agents/tool-filter.d.ts +17 -1
- package/dist/agents/tool-filter.js +7 -0
- package/dist/core/agent-config-dir.d.ts +20 -0
- package/dist/core/agent-config-dir.js +49 -0
- package/dist/core/allow-entry.d.ts +5 -3
- package/dist/core/allow-entry.js +3 -1
- package/dist/core/ask-origin.js +1 -1
- package/dist/core/checkpoint-store.d.ts +39 -2
- package/dist/core/effective-path-target.d.ts +136 -4
- package/dist/core/effective-path-target.js +110 -2
- package/dist/core/engine-notice.d.ts +5 -0
- package/dist/core/gate-fold.js +3 -0
- package/dist/core/gate-lanes.js +9 -3
- package/dist/core/governance-codes.d.ts +3 -1
- package/dist/core/governance-codes.js +3 -0
- package/dist/core/hooks.d.ts +3 -0
- package/dist/core/path-rule-binding.d.ts +65 -0
- package/dist/core/path-rule-binding.js +99 -0
- package/dist/core/permission-rule-model.d.ts +47 -18
- package/dist/core/permission-rule-model.js +38 -42
- package/dist/core/permission-rule-provider.d.ts +7 -0
- package/dist/core/permission-rule-provider.js +10 -3
- package/dist/core/permission-rule-store.d.ts +8 -0
- package/dist/core/permission-rule-store.js +6 -2
- package/dist/core/permission-rule-sync.js +2 -2
- package/dist/core/permission-rules.d.ts +22 -40
- package/dist/core/permission-rules.js +50 -43
- package/dist/core/runner/child-tree.d.ts +97 -0
- package/dist/core/runner/child-tree.js +104 -0
- package/dist/core/runner/construction-doors.d.ts +5 -0
- package/dist/core/runner/construction-doors.js +6 -0
- package/dist/core/runner/contracts.d.ts +46 -0
- package/dist/core/runner/permission-rule-lanes.d.ts +34 -25
- package/dist/core/runner/permission-rule-lanes.js +18 -12
- package/dist/core/runner/persisted-path-rows.d.ts +31 -7
- package/dist/core/runner/persisted-path-rows.js +31 -12
- package/dist/core/runner/prepare-ask-lane.d.ts +4 -0
- package/dist/core/runner/prepare-ask-lane.js +4 -2
- package/dist/core/runner/prepare-execution-env.d.ts +5 -2
- package/dist/core/runner/prepare-execution-env.js +10 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +3 -0
- package/dist/core/runner/prepare-gate-stations.js +2 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +8 -4
- package/dist/core/runner/prepare-hands-readface.js +6 -6
- package/dist/core/runner/prepare-inherited-gate.d.ts +8 -1
- package/dist/core/runner/prepare-inherited-gate.js +8 -2
- package/dist/core/runner/prepare-park-ask.d.ts +3 -0
- package/dist/core/runner/prepare-park-ask.js +5 -3
- package/dist/core/runner/prepare-policy-chain.d.ts +14 -2
- package/dist/core/runner/prepare-policy-chain.js +11 -4
- package/dist/core/runner/prepare-suspend-saga.d.ts +10 -0
- package/dist/core/runner/prepare-suspend-saga.js +7 -1
- package/dist/core/runner/prepare-task.js +37 -18
- package/dist/core/runner/prepare-turn-wiring.d.ts +2 -0
- package/dist/core/runner/prepare-turn-wiring.js +2 -1
- package/dist/core/runner/prepare-workspace-restore.d.ts +3 -0
- package/dist/core/runner/prepare-workspace-restore.js +1 -0
- package/dist/core/runner/resume-apply.js +17 -3
- package/dist/core/runner/resume-checkpoint-screen.js +13 -0
- package/dist/core/runner/run-leg.js +5 -1
- package/dist/core/runner/runtask.js +2 -2
- package/dist/core/runner/sub-agent-deny-lists.d.ts +1 -1
- package/dist/core/runner/write-protection-station.d.ts +3 -2
- package/dist/core/runner/write-protection-station.js +1 -0
- package/dist/core/runner-deps.d.ts +14 -0
- package/dist/core/sensitive-path-policy.d.ts +8 -0
- package/dist/core/sensitive-path-policy.js +18 -2
- package/dist/core/shell-wrapper-projection.d.ts +11 -0
- package/dist/core/shell-wrapper-projection.js +56 -0
- package/dist/core/shell-wrapper-table.d.ts +144 -34
- package/dist/core/shell-wrapper-table.js +40 -20
- package/dist/core/synthetic-read-verdict.d.ts +3 -0
- package/dist/core/synthetic-read-verdict.js +3 -1
- package/dist/core/tool-catalog-entries.d.ts +21 -0
- package/dist/core/tool-catalog-entries.js +9 -0
- package/dist/core/tool-policy.d.ts +30 -8
- package/dist/core/tool-policy.js +9 -7
- package/dist/core/tool-spec.d.ts +3 -2
- package/dist/core/write-protect.d.ts +4 -0
- package/dist/core/write-protect.js +30 -9
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -2
- package/dist/orchestration/run-spec.js +8 -7
- package/dist/orchestration/workflow.js +1 -1
- package/dist/shell/lex.d.ts +7 -0
- package/dist/shell/lex.js +17 -0
- package/dist/tools/fs/bash-program-position.d.ts +8 -87
- package/dist/tools/fs/bash-program-position.js +33 -69
- package/dist/tools/fs/bash-readonly-classifier.d.ts +17 -444
- package/dist/tools/fs/bash-readonly-classifier.js +169 -1225
- package/dist/tools/fs/index.d.ts +3 -2
- package/dist/tools/fs/program-read-model.d.ts +694 -0
- package/dist/tools/fs/program-read-model.js +1252 -0
- package/dist/tools/fs/program-read-model.rows.d.ts +18 -0
- package/dist/tools/fs/program-read-model.rows.js +613 -0
- package/dist/tools/fs/read-deny-home.d.ts +19 -1
- package/dist/tools/fs/read-deny-home.js +62 -24
- package/dist/tools/fs/read-deny.d.ts +54 -14
- package/dist/tools/fs/read-deny.js +104 -50
- package/dist/tools/fs/removal-targets.d.ts +7 -6
- package/dist/tools/fs/removal-targets.js +22 -22
- package/dist/tools/fs/safety.d.ts +3 -0
- package/dist/tools/fs/safety.js +10 -3
- package/dist/tools/fs/shell-read-argv.d.ts +85 -0
- package/dist/tools/fs/shell-read-argv.js +386 -0
- package/dist/tools/fs/shell-read-bindings.d.ts +273 -0
- package/dist/tools/fs/shell-read-bindings.js +746 -0
- package/dist/tools/fs/shell-read-check.js +23 -15
- package/dist/tools/fs/shell-read-establish.js +79 -5
- package/dist/tools/fs/shell-read-judge.d.ts +11 -1
- package/dist/tools/fs/shell-read-judge.js +9 -1
- package/dist/tools/fs/shell-read-plan.d.ts +31 -7
- package/dist/tools/fs/shell-read-plan.js +299 -393
- package/dist/tools/fs/shell-read-word.d.ts +29 -26
- package/dist/tools/fs/shell-read-word.js +30 -38
- package/dist/tools/fs/shell-read-write-targets.d.ts +15 -64
- package/dist/tools/fs/shell-read-write-targets.js +83 -136
- package/dist/tools/fs/shell-reentry-text.d.ts +38 -6
- package/dist/tools/fs/shell-reentry-text.js +90 -53
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +17 -3
- package/wire-changes/core@7.46.0.json +1522 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withArgsReading } from "../effective-path-target.js";
|
|
1
2
|
import { policyAskClassOf } from "../ask-class.js";
|
|
2
3
|
import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
3
4
|
import { classifierUnavailableSeat } from "./classifier-ladder.js";
|
|
@@ -24,7 +25,7 @@ import { createLiveSessionRules, createSessionRulePolicy } from "./session-rule-
|
|
|
24
25
|
import { thrownText } from "../thrown-value.js";
|
|
25
26
|
import { heldBy, heldValues, seatOf, wireOf } from "../tool-name-readings.js";
|
|
26
27
|
export async function preparePolicyChain(input) {
|
|
27
|
-
const { 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, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, readFace, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
|
|
28
|
+
const { spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight, pathRuleAnchors, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, announceRuleRowsDropped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider, readFace, permissionMode, scratchpadDir, toolRosterDeltas, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef } = input;
|
|
28
29
|
const ancestorArbitrations = new Map();
|
|
29
30
|
const arbitrateInherited = (ask, toolCallId, judged) => {
|
|
30
31
|
const verdict = arbitrateByMode(permissionMode.current, judged.classification, { origin: judged.origin, ...askMandateMember(ancestorFacts(judged.ask.action === "ask" ? judged.ask : undefined)) });
|
|
@@ -315,7 +316,7 @@ export async function preparePolicyChain(input) {
|
|
|
315
316
|
};
|
|
316
317
|
};
|
|
317
318
|
const inheritedAskEvidence = inheritedAskRuleEvidence(deps.permissionRuleStore);
|
|
318
|
-
const listFacts = { root: taskRootFinal, sessionId, liveCwd: () => handsCwdRef?.current,
|
|
319
|
+
const listFacts = { root: taskRootFinal, sessionId, liveCwd: () => handsCwdRef?.current, anchors: pathRuleAnchors.leg };
|
|
319
320
|
const skillGrantLane = skillGrants.lane(listFacts);
|
|
320
321
|
const allowEntryLanes = { request: allowedToolTables.request.lane(listFacts), deployment: allowedToolTables.deployment.lane(listFacts) };
|
|
321
322
|
const { personal: permissionRuleLane, org: permissionRuleOrgLane } = createPermissionRuleLanes({
|
|
@@ -324,6 +325,9 @@ export async function preparePolicyChain(input) {
|
|
|
324
325
|
principal: spec.principal,
|
|
325
326
|
sessionId,
|
|
326
327
|
root: taskRootFinal,
|
|
328
|
+
rootCanonical: pathRuleAnchors.leg.root,
|
|
329
|
+
chainTop: pathRuleAnchors.chainTop,
|
|
330
|
+
leads: headLeads,
|
|
327
331
|
liveCwd: () => handsCwdRef?.current,
|
|
328
332
|
home: executionEnv.homeDir,
|
|
329
333
|
questionToolMounted,
|
|
@@ -331,6 +335,7 @@ export async function preparePolicyChain(input) {
|
|
|
331
335
|
onRevisionDefect: (message) => deps.onError?.(new Error(message), { phase: "config", sessionId }),
|
|
332
336
|
onDisclosure: (message) => emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message, ts: Date.now() })),
|
|
333
337
|
onStoreUnreadable: announceRuleStoreSkipped,
|
|
338
|
+
onRowsDropped: announceRuleRowsDropped,
|
|
334
339
|
signal: abortController.signal,
|
|
335
340
|
stripsAllow: (rule, req) => permissionMode.current === "auto" && autoStrippedRule(rule, req),
|
|
336
341
|
});
|
|
@@ -366,7 +371,8 @@ export async function preparePolicyChain(input) {
|
|
|
366
371
|
}
|
|
367
372
|
let re;
|
|
368
373
|
try {
|
|
369
|
-
|
|
374
|
+
const editReq = withArgsReading(creq, editArgs, csignal ?? abortController.signal);
|
|
375
|
+
re = refuseOutOfContractDecision(await pol.check(editReq !== undefined ? await editReq : { ...creq, args: editArgs }, csignal ?? abortController.signal));
|
|
370
376
|
}
|
|
371
377
|
catch (err) {
|
|
372
378
|
return vetoed({
|
|
@@ -646,7 +652,8 @@ export async function preparePolicyChain(input) {
|
|
|
646
652
|
}
|
|
647
653
|
}
|
|
648
654
|
const recheckLayers = [...recheckPrefix, ...postEmitterSameInstanceAdapters];
|
|
649
|
-
const
|
|
655
|
+
const finalRead = withArgsReading(req, decision.updatedInput, signal);
|
|
656
|
+
const finalReq = finalRead !== undefined ? await finalRead : { ...req, args: decision.updatedInput };
|
|
650
657
|
let asked;
|
|
651
658
|
const revalidated = {};
|
|
652
659
|
let restated;
|
|
@@ -118,6 +118,10 @@ export interface PrepareSuspendSagaInput {
|
|
|
118
118
|
reminderMark: string;
|
|
119
119
|
/** borrowed-readonly — the hand's live tracked cwd, or undefined; `current` is read at mint time. Not written here. */
|
|
120
120
|
handsCwdRef: CwdRef | undefined;
|
|
121
|
+
/** borrowed-readonly — the hands' root (the `root` every adjudicated request of the leg carries), or undefined (hands-less). */
|
|
122
|
+
handsRoot: string | undefined;
|
|
123
|
+
/** borrowed-readonly — the home the leg's caller policies installed `~/` at (absolute), or undefined. */
|
|
124
|
+
handsHome: string | undefined;
|
|
121
125
|
/** borrowed-readonly — the active EnterWorktree session seat, or undefined; `current` is read at mint time. */
|
|
122
126
|
worktreeSessionRef: Prepared["worktreeSessionRef"];
|
|
123
127
|
/** borrowed-readonly — the resumed leg's not-yet-delivered continuation content; its orphan obituaries fold into this
|
|
@@ -140,6 +144,12 @@ export interface PrepareSuspendSagaInput {
|
|
|
140
144
|
permissionMode: PermissionModeController;
|
|
141
145
|
/** borrowed-readonly — the inherited admitted org scopes, or undefined (copied onto the row). */
|
|
142
146
|
inheritedAdmittedOrgScopes: readonly string[] | undefined;
|
|
147
|
+
/** borrowed-readonly — the chain's top leg's anchors this leg carries (absent on a leg that is its own top): recorded on
|
|
148
|
+
* the data half so a resumed child judges the person's global / session rows and `~/` rows where its chain did. */
|
|
149
|
+
inheritedPathRuleAnchors: InheritedGate["pathRuleAnchors"];
|
|
150
|
+
/** borrowed-readonly — where each parent constraint this leg runs under was installed (position for position), recorded on
|
|
151
|
+
* the data half so a resume that re-supplies the chain uninstalled installs each entry there. */
|
|
152
|
+
inheritedPathRuleInstallations: InheritedGate["pathRuleInstallations"];
|
|
143
153
|
/** borrowed-readonly — this leg's OWN org verdict seat; `current` is read at mint time. Not written here. */
|
|
144
154
|
ownOrgVerdictRef: {
|
|
145
155
|
current: OwnOrgAdmissionVerdict | undefined;
|
|
@@ -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, skillGrantCheckpointSection, 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, handsRoot, handsHome, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors, inheritedPathRuleInstallations, 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 = () => {
|
|
@@ -115,6 +115,8 @@ export function prepareSuspendSaga(input) {
|
|
|
115
115
|
repairBundle: repairBundleForCheckpoint(parkedSpendMicroUsd),
|
|
116
116
|
workspaceHandle,
|
|
117
117
|
handsCwd: handsCwdRef?.current,
|
|
118
|
+
handsRoot,
|
|
119
|
+
handsHome,
|
|
118
120
|
activeWorktree: worktreeSessionRef?.current ? { ...worktreeSessionRef.current } : undefined,
|
|
119
121
|
runningBackgroundTasks: (() => {
|
|
120
122
|
const live = defaultTaskRegistry
|
|
@@ -142,6 +144,8 @@ export function prepareSuspendSaga(input) {
|
|
|
142
144
|
inheritedShellGate !== undefined ||
|
|
143
145
|
modeRecorded ||
|
|
144
146
|
inheritedAdmittedOrgScopes !== undefined ||
|
|
147
|
+
inheritedPathRuleAnchors !== undefined ||
|
|
148
|
+
inheritedPathRuleInstallations !== undefined ||
|
|
145
149
|
ownOrgVerdictRef.current !== undefined ||
|
|
146
150
|
orgGovernedProvenance ||
|
|
147
151
|
requiresParentConstraint
|
|
@@ -151,6 +155,8 @@ export function prepareSuspendSaga(input) {
|
|
|
151
155
|
...(modeRecorded ? { permissionMode: declaredMode } : {}),
|
|
152
156
|
...(permissionMode.prePlanMode !== undefined ? { prePlanMode: permissionMode.prePlanMode } : {}),
|
|
153
157
|
...(inheritedAdmittedOrgScopes !== undefined ? { admittedOrgScopes: [...inheritedAdmittedOrgScopes] } : {}),
|
|
158
|
+
...(inheritedPathRuleAnchors !== undefined ? { pathRuleAnchors: { ...inheritedPathRuleAnchors } } : {}),
|
|
159
|
+
...(inheritedPathRuleInstallations !== undefined ? { pathRuleInstallations: inheritedPathRuleInstallations.map((r) => (r === null ? null : { ...r })) } : {}),
|
|
154
160
|
...(ownOrgVerdictRef.current !== undefined
|
|
155
161
|
? { ownAdmittedOrgScopes: [...ownOrgVerdictRef.current.scopes], ownAdmittedOrgWriteScope: ownOrgVerdictRef.current.writeScope }
|
|
156
162
|
: {}),
|
|
@@ -8,7 +8,9 @@ import { brainToRuntime } from "../runtime.js";
|
|
|
8
8
|
import { hasSessionFork } from "../session.js";
|
|
9
9
|
import { SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
10
10
|
import { callerToolMembership } from "../../agents/inherited-tool-pool.js";
|
|
11
|
-
import {
|
|
11
|
+
import { toolPolicyPathRules, toolPolicyWriteTargetGuard } from "../tool-policy.js";
|
|
12
|
+
import { bindPathRules, createHeadLeads } from "../path-rule-binding.js";
|
|
13
|
+
import { whereItsAnsweredPrefixLeads } from "../../tools/fs/read-deny-home.js";
|
|
12
14
|
import { loadAnnounceOnceLedger } from "./announce-once-ledger.js";
|
|
13
15
|
import { isValidReminderMark, mintReminderMark } from "../reminder-mint.js";
|
|
14
16
|
import { clampPermissionMode } from "../ask-origin.js";
|
|
@@ -16,17 +18,18 @@ import { modePolicyOf, modeRequestAfterResume, refusePermissionModeDoors } from
|
|
|
16
18
|
import { resolveOutputStyleFrame } from "../output-style.js";
|
|
17
19
|
import { recordedModeSeed } from "../checkpoint-store.js";
|
|
18
20
|
import { emitTrace } from "../trace.js";
|
|
19
|
-
import { persistedPathRowsOfTask, ruleStoreUnreadableNotice } from "./persisted-path-rows.js";
|
|
21
|
+
import { persistedPathRowsOfTask, ruleRowsDroppedNotice, ruleStoreUnreadableNotice } from "./persisted-path-rows.js";
|
|
20
22
|
import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
|
|
21
23
|
import { STALL_FIRST_BYTE_MS, STALL_FIRST_TOKEN_MS, STALL_IDLE_MS, withBrainCallGuardrail } from "../../brain/timeout.js";
|
|
22
24
|
import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
|
|
23
25
|
import { OUTPUT_TOOL_NAME, SKILL_TOOL_NAME, createOutputTool } from "./synthetic-tools.js";
|
|
24
|
-
import { skillGateWiring } from "../skill-grant.js";
|
|
26
|
+
import { compileSkillGrant, skillGateWiring } from "../skill-grant.js";
|
|
27
|
+
import { legCallTargetStamp } from "../effective-path-target.js";
|
|
25
28
|
import { AllowEntryTable, screenAllowedToolsValue } from "../allow-entry.js";
|
|
26
29
|
import { compileOutputSchema } from "./strict-output-schema.js";
|
|
27
30
|
import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
|
|
28
31
|
import { foldAdmissionFreeze } from "../memory-admission.js";
|
|
29
|
-
import { deploymentCanRerootChild } from "./child-tree.js";
|
|
32
|
+
import { chainAnchorRecords, chainPolicyOnLeg, chainTopAnchors, deploymentCanRerootChild } from "./child-tree.js";
|
|
30
33
|
import { prepareMemory } from "./prepare-memory.js";
|
|
31
34
|
import { prepareMemoryEngineSession } from "./prepare-memory-engine-session.js";
|
|
32
35
|
import { prepareDeferClassify } from "./prepare-defer-classify.js";
|
|
@@ -40,6 +43,7 @@ export { runGuardChain } from "./prepare-context-lane.js";
|
|
|
40
43
|
import { preparePromptAssembly } from "./prepare-prompt-assembly.js";
|
|
41
44
|
import { limitConfigError, prepareConfigDoors } from "./prepare-config-doors.js";
|
|
42
45
|
import { prepareSafetyScan } from "./prepare-safety-scan.js";
|
|
46
|
+
import { isAbsolutePathForm } from "../../tools/fs/safety.js";
|
|
43
47
|
import { prepareAcquireReconcile } from "./prepare-acquire-reconcile.js";
|
|
44
48
|
import { settleBranchWriteBack } from "./branch-writeback.js";
|
|
45
49
|
import { prepareHandsMount, resolveHandsLessReadFace } from "./prepare-hands-readface.js";
|
|
@@ -347,7 +351,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
347
351
|
throw e;
|
|
348
352
|
}
|
|
349
353
|
const rollback = createRollbackStack((e) => deps.onError?.(e, { phase: "config", sessionId }));
|
|
350
|
-
const { executionEnv, ownedEnvSeat, ownedEnvObservedAt, handsEnabled, taskRootInitial } = await prepareExecutionEnv({ deps, spec, internals, resume, placementRootResolved, sessionId, forgetOnThrow, rollback });
|
|
354
|
+
const { executionEnv, ownedEnvSeat, ownedEnvObservedAt, handsEnabled, taskRootInitial, placement } = await prepareExecutionEnv({ deps, spec, internals, resume, placementRootResolved, sessionId, forgetOnThrow, rollback });
|
|
351
355
|
const externalContentTargetActive = executionEnv.externalContentTarget === true || resume?.seed.externalContentTarget === true;
|
|
352
356
|
const abortController = new AbortController();
|
|
353
357
|
if (spec.signal?.aborted)
|
|
@@ -400,8 +404,15 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
400
404
|
}
|
|
401
405
|
}
|
|
402
406
|
const ownedEnv = ownedEnvSeat.current;
|
|
403
|
-
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
407
|
+
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, placement, abortController, sessionId });
|
|
404
408
|
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
409
|
+
const legHome = executionEnv.homeDir;
|
|
410
|
+
const legAnchors = { root: taskRootCanonical, ...(legHome !== undefined && isAbsolutePathForm(legHome) ? { home: legHome } : {}) };
|
|
411
|
+
const chainTop = chainTopAnchors({ leg: legAnchors, live: internals?.inheritedGate?.pathRuleAnchors, seed: resume?.seed.inheritedGate?.pathRuleAnchors, placement, rebase: rebaseRestoredPath });
|
|
412
|
+
const onLeg = chainPolicyOnLeg({ leg: legAnchors, chainTop, placement, chain: (internals?.inheritedGate?.parentConstraints ?? []).map((c) => c.policy), installations: { live: internals?.inheritedGate?.pathRuleInstallations, seed: resume?.seed.inheritedGate?.pathRuleInstallations }, rebase: rebaseRestoredPath });
|
|
413
|
+
const [installedToolPolicy, installedBaseEdit] = [lockedPreflight.toolPolicy, lockedPreflight.basePolicyForResumeEdit].map(onLeg.own);
|
|
414
|
+
const installedPreflight = { ...lockedPreflight, toolPolicy: installedToolPolicy, basePolicyForResumeEdit: installedBaseEdit };
|
|
415
|
+
const headLeads = createHeadLeads((part) => whereItsAnsweredPrefixLeads(executionEnv, part));
|
|
405
416
|
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, request: fileHistoryRequest, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
406
417
|
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillGrants, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, bindPermissionModeSeat, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
407
418
|
const allowedToolTables = { request: new AllowEntryTable(), deployment: new AllowEntryTable() };
|
|
@@ -411,14 +422,19 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
411
422
|
let readDenyAdditionsNormalized = [];
|
|
412
423
|
let handsLessResolvedFace;
|
|
413
424
|
let handsLessResolvedWriteFace;
|
|
414
|
-
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, askSeat: doors.askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, 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 });
|
|
425
|
+
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, askSeat: doors.askSeat, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { chainTop, onLeg: onLeg.chained }, checkpointSeat, toolFaceSnapshot, mountsCallerTool, promptProfile, resolvedInteractionPosture, permissionModeSeat, handsEnabled, reportUsage, harnessRef, skillGrants, requestAllowedTools: allowedToolTables.request, 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 });
|
|
415
426
|
bindPermissionModeSeat(permissionMode);
|
|
416
427
|
const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
|
|
417
|
-
const
|
|
428
|
+
const announceRuleRowsDropped = ruleRowsDroppedNotice(deps.onNotice, { sessionId, runId });
|
|
429
|
+
const persistedPathRowsRead = persistedPathRowsOfTask({ deps, principal: spec.principal, sessionId, root: taskRootFinal, rootCanonical: taskRootCanonical, leads: headLeads, chainTop, taskId: hostTaskId, handsEnabled, onRowsDropped: announceRuleRowsDropped, signals: [abortController.signal, ...(spec.signal !== undefined ? [spec.signal] : [])], onUnread: announceRuleStoreSkipped });
|
|
418
430
|
const persistedPathRows = persistedPathRowsRead === undefined ? { readDirectories: [], denyRows: [] } : await persistedPathRowsRead;
|
|
419
|
-
const
|
|
431
|
+
const policyDenyRows = toolPolicyPathRules([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors).filter((r) => r.faces.length > 0 && r.behavior === "deny");
|
|
432
|
+
for (const r of policyDenyRows)
|
|
433
|
+
if (r.unanchored !== undefined)
|
|
434
|
+
emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message: `the deny rule ${r.rule} needs a ${r.unanchored.join(" / ")} base this task does not declare — the shell's file commands and the search tools do not judge it on this leg (the gate asks)`, ts: Date.now() }));
|
|
435
|
+
const effectivePathDenyRules = [...policyDenyRows.filter((r) => r.unanchored === undefined), ...persistedPathRows.denyRows];
|
|
420
436
|
const writeProtectionJudgeRef = {};
|
|
421
|
-
const writeGuards = { protection: () => writeProtectionJudgeRef.current, target: toolPolicyWriteTargetGuard([
|
|
437
|
+
const writeGuards = { protection: () => writeProtectionJudgeRef.current, target: toolPolicyWriteTargetGuard([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
|
|
422
438
|
const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDeciderRef, autoModeDenialTrackingRef, autoModeArmingRef, armAutoMode, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, askSeat: doors.askSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, parentSpecSeat, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, permissionMode, readDenyEntries: () => ({ entries: readDenyMatcher?.entries ?? [], ruleRows: effectivePathDenyRules }), peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized });
|
|
423
439
|
const tools = roster.tools;
|
|
424
440
|
const pausedRef = {};
|
|
@@ -556,7 +572,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
556
572
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
557
573
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
558
574
|
}
|
|
559
|
-
const handsReadFaceInput = { permissionMode,
|
|
575
|
+
const handsReadFaceInput = { permissionMode, denyRuleRows: effectivePathDenyRules, headLeads, writeGuards, persistedReadDirectories: persistedPathRows.readDirectories, handsEnabled, executionEnv, taskRootFinal, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
560
576
|
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
561
577
|
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, shellReadCheck, shellReadAdmission, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
562
578
|
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
@@ -737,7 +753,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
737
753
|
releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
|
|
738
754
|
}
|
|
739
755
|
}
|
|
740
|
-
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, 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, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, readFace: () => resolvedReadFace, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
756
|
+
const { hooks, hookTimeoutMs, preToolUseObservational, ownGatePreToolUse, basePolicyForResumeEdit, denyNarrowingPolicy, skillGrantLane, allowEntryLanes, policyLayers, effectivePolicy, inheritedUnavailableAsks, inheritedAskGrants, askSourceIdentity, riskAxesOf, ruleOffersOf, grantBindingOf, permissionRuleLane, permissionRuleOrgLane, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, foldAskClasses, ancestorSandboxAdmissions, ancestorArbitrations } = await preparePolicyChain({ spec, deps, internals, sessionId, runId, hostTaskId, taskRootFinal, additionalRootsCanonical, executionEnv, lockedPreflight: installedPreflight, pathRuleAnchors: { leg: legAnchors, chainTop }, headLeads, tools, harnessTools, toolEffects, egressTools, irreversibilityTier, axisExplicitNegatives, shellGatedTools, toolMarkSources, envHandToolNames, handsCwdRef, readDenyMatcher, announceRuleStoreSkipped, announceRuleRowsDropped, questionToolMounted, runtimeCaps, inheritedAncestorRules, ancestorSessionRulesRef, inheritedParentConstraints, seedInheritedGate, skillGrants, skillSpecs, allowedToolTables, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, autoModeDecider: () => autoModeDeciderRef.current, readFace: () => resolvedReadFace, permissionMode, scratchpadDir: spec.envFacts?.scratchpadDir, toolRosterDeltas: rosterSeat, stopForDenialLimit, delegation, abortController, now, ownSessionRulesRef });
|
|
741
757
|
const { onAsk, preToolContexts, blockedToolCalls, gateOutcomes, batchHaltRef, blockedTracked, incompleteSuspendAdapter, durableSuspendInfraReady, resourceSuspendEligible, usageGovernance, durableApproval, wiringManifest, writeProtection, parkLaneArmed, gateMachineryActive, hookIdentity, hookEnvFace, sessionBoxBound } = prepareWiringManifest({ spec, deps, askSeat: doors.askSeat, 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, liveInheritedGate, delegation, toolRoster, readDenyBuiltinTiersActive: handsReadFace.readDenyBuiltinTiersActive, lspManagerWired, lspDiagnosticsLive: lspDiagnostics !== undefined, fileHistoryFact, sessionBox });
|
|
742
758
|
const writeProtectionCheck = writeProtection?.check;
|
|
743
759
|
writeProtectionJudgeRef.current = writeProtection?.judgeTarget;
|
|
@@ -747,18 +763,21 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
747
763
|
return undefined;
|
|
748
764
|
});
|
|
749
765
|
}
|
|
750
|
-
const
|
|
751
|
-
const
|
|
766
|
+
const listPathRows = () => skillSpecs.flatMap((s) => compileSkillGrant(s, "model").rows).flatMap((r) => (r.behavior === "deny" && r.compiled.kind === "path" ? [r.compiled.rule] : []));
|
|
767
|
+
const stampCallTarget = attachmentRootCanonical === undefined ? undefined : legCallTargetStamp({ env: executionEnv, root: attachmentRootCanonical, cwd: () => handsCwdRef?.current, judgesPaths: () => effectivePolicy?.pathRules !== undefined || basePolicyForResumeEdit?.pathRules !== undefined || permissionRuleLane !== undefined || listPathRows().length > 0, leads: () => headLeads.resolve([...toolPolicyPathRules([effectivePolicy, basePolicyForResumeEdit, ...(inheritedParentConstraints ?? []).map((c) => c.policy)], legAnchors), ...bindPathRules(listPathRows().map((rule) => ({ parsed: rule, ruleText: rule.rule })), legAnchors)]) });
|
|
768
|
+
const { askLane } = prepareAskLane({ gateMachineryActive, abortController, effectivePolicy, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, tools, inheritedUnavailableAsks, inheritedAskGrants, onAsk, humanReviewRef, now, ruleOffersOf, grantBindingOf, askSourceIdentity, riskAxesOf, autoModeDenialTracking: autoModeDenialTrackingRef, spec, deps, sessionId, runId, hooks, hookTimeoutMs, notifyOwnHookCrash, grantReadRoot: handsReadFace.grantReadRoot });
|
|
769
|
+
const inheritedAnchorRecords = chainAnchorRecords(chainTop, inheritedParentConstraints ?? []);
|
|
770
|
+
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, skillGrantCheckpointSection, reminderMark, handsCwdRef, handsRoot: attachmentRootCanonical, handsHome: attachmentRootCanonical !== undefined ? legAnchors.home : undefined, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, ancestorRulesNow, inheritedShellGate, permissionMode, inheritedAdmittedOrgScopes, inheritedPathRuleAnchors: chainTop !== legAnchors ? inheritedAnchorRecords.pathRuleAnchors : undefined, inheritedPathRuleInstallations: inheritedAnchorRecords.pathRuleInstallations, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
752
771
|
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 });
|
|
753
|
-
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
772
|
+
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, handsRoot: attachmentRootCanonical, stampCallTarget, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, irreversibilityTier, toolMarkSources, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, grantBindingOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
754
773
|
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() })), allowEntries: { deploymentAllows: { ...allowEntryLanes.deployment, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "deployment", ...info, entries: [...info.entries], ts: Date.now() })) }, requestAllows: { ...allowEntryLanes.request, onAllowed: (info) => emitTrace(deps.tracer, () => ({ kind: "permission.allowed_tools_allowed", version: 1, taskId: hostTaskId, source: "request", ...info, entries: [...info.entries], ts: Date.now() })) } } });
|
|
755
|
-
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.
|
|
774
|
+
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, stampCallTarget, readDenyInForce: () => ({ tiers: handsReadFace.readDenyBuiltinTiersActive, rows: [...readDenyAdditionsNormalized.map((e) => e.pattern), ...handsReadFaceInput.denyRuleRows.filter((r) => r.faces.includes("read")).map((r) => r.rule)] }), hookEnvFace, writeProtectionCheck, shellReadCheck, readFace: () => resolvedReadFace, 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 });
|
|
756
775
|
const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
|
|
757
776
|
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 } : {}) });
|
|
758
777
|
const preparedHolder = {};
|
|
759
|
-
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, callerPolicy:
|
|
778
|
+
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, callerPolicy: installedToolPolicy, inheritedPolicies: (inheritedParentConstraints ?? []).map((c) => c.policy), persistedRuleLane: permissionRuleLane, orgRuleLane: permissionRuleOrgLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
760
779
|
await onceLedger.settle(session, announcedListingsRef);
|
|
761
|
-
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, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), 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 } : {}) });
|
|
780
|
+
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, ...(attachmentRootCanonical !== undefined ? { handsRoot: attachmentRootCanonical } : {}), ...(stampCallTarget !== undefined ? { stampCallTarget } : {}), 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 } : {}) });
|
|
762
781
|
rollback.commit();
|
|
763
782
|
commitModeSeats(abortController.signal);
|
|
764
783
|
const prepared = buildPrepared();
|
|
@@ -92,6 +92,8 @@ export interface PrepareTurnWiringInput {
|
|
|
92
92
|
persistedRuleLane: Prepared["persistedRuleLane"];
|
|
93
93
|
/** borrowed-readonly — the org rule lane, or undefined (a layer of the judge). */
|
|
94
94
|
orgRuleLane: Prepared["permissionRuleOrg"];
|
|
95
|
+
/** borrowed-readonly — the leg's target-reading stamp, or undefined (hands-less): the visibility judge stamps its request. */
|
|
96
|
+
stampCallTarget: Prepared["stampCallTarget"];
|
|
95
97
|
/** borrowed-readonly — the run's abort controller; only `signal` (the deny door's and the stat's signal). */
|
|
96
98
|
abortController: Pick<AbortController, "signal">;
|
|
97
99
|
/** borrowed-readonly — the per-task identity (the background listing's owner). */
|
|
@@ -13,7 +13,7 @@ import { PROMPT_HASH_SALT } from "./prompt-hash-salt.js";
|
|
|
13
13
|
import { CHANGED_FILES_MTIME_EPS_MS } from "./turn-attachments.js";
|
|
14
14
|
import { thrownText } from "../thrown-value.js";
|
|
15
15
|
export function prepareTurnWiring(input) {
|
|
16
|
-
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, callerPolicy, inheritedPolicies, persistedRuleLane, orgRuleLane, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
|
|
16
|
+
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, callerPolicy, inheritedPolicies, persistedRuleLane, orgRuleLane, stampCallTarget, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder } = input;
|
|
17
17
|
const cacheBreakDetector = deps.cacheBreakDetection === false ? undefined : new CacheBreakDetector();
|
|
18
18
|
const cacheFingerprint = cacheBreakDetector
|
|
19
19
|
? { systemPrompt: systemPromptSeat.current, tools: toolsToFingerprintInputs(harnessTools) }
|
|
@@ -109,6 +109,7 @@ export function prepareTurnWiring(input) {
|
|
|
109
109
|
inheritedPolicies,
|
|
110
110
|
...(persistedRuleLane !== undefined ? { persistedRuleLane } : {}),
|
|
111
111
|
...(orgRuleLane !== undefined ? { orgRuleLane } : {}),
|
|
112
|
+
...(stampCallTarget !== undefined ? { stampCallTarget } : {}),
|
|
112
113
|
signal: abortController.signal,
|
|
113
114
|
});
|
|
114
115
|
const changedFilesReadDenied = async (paths) => {
|
|
@@ -29,6 +29,9 @@ export interface PrepareWorkspaceRestoreInput {
|
|
|
29
29
|
* driver). Dead after this call by design (R-5): later phases read the returned
|
|
30
30
|
* `taskRootFinal`, never this spelling. */
|
|
31
31
|
taskRootInitial: string;
|
|
32
|
+
/** borrowed-readonly — where a delegated child landed against where it was asked (the execution-env phase's one
|
|
33
|
+
* judgment), reported beside the root it resolved; absent on a leg no delegation caller placed. */
|
|
34
|
+
placement?: import("./contracts.js").ChildPlacement | undefined;
|
|
32
35
|
/** borrowed-readonly — prepare's abort seat; only `.signal` is read (kept as the object so the
|
|
33
36
|
* moved body's `abortController.signal` spelling stays verbatim). */
|
|
34
37
|
abortController: {
|
|
@@ -115,6 +115,7 @@ export async function prepareWorkspaceRestore(input) {
|
|
|
115
115
|
isolated: internals.isolation === "worktree",
|
|
116
116
|
remote: workspaceEnv !== undefined &&
|
|
117
117
|
(isRemoteExecutionEnv(workspaceEnv) || workspaceEnv.hostLocalPaths === false),
|
|
118
|
+
...(input.placement !== undefined ? { placement: input.placement } : {}),
|
|
118
119
|
});
|
|
119
120
|
}
|
|
120
121
|
catch {
|
|
@@ -4,8 +4,10 @@ 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
6
|
import { mintHookInvocationIdentity, resolveHookTimeoutMs, runHookSeat } from "../hooks.js";
|
|
7
|
+
import { chainPolicyOnLeg, chainTopAnchors } from "./child-tree.js";
|
|
7
8
|
import { checkToolPolicyProjection, policyCannotAnswer, refuseOutOfContractDecision } from "../tool-policy.js";
|
|
8
9
|
import { callFaceSeat, parkedCallFaceOf } from "../tool-roster.js";
|
|
10
|
+
import { readCallTarget } from "../effective-path-target.js";
|
|
9
11
|
import { inlineUntrusted } from "../untrusted-text.js";
|
|
10
12
|
import { deepJsonEqual, describeSuppliedValue } from "./decide-continuation.js";
|
|
11
13
|
import { orgVerdictBeforeClaim } from "./permission-rule-lanes.js";
|
|
@@ -110,14 +112,16 @@ export async function resumeApply(input) {
|
|
|
110
112
|
resourceSpentMicroUsd: cp.resourceLedger?.spentMicroUsd ?? 0,
|
|
111
113
|
suspendCount: cp.suspendCount ?? 0,
|
|
112
114
|
};
|
|
113
|
-
const
|
|
115
|
+
const editedCall = {
|
|
114
116
|
toolName: cp.pendingAction.toolName,
|
|
115
117
|
args: editedArgs,
|
|
116
118
|
toolCallId: cp.pendingAction.toolCallId,
|
|
117
119
|
budget: editBudget,
|
|
118
120
|
...callFaceSeat(parkedCallFaceOf(cp.pendingAction)),
|
|
119
121
|
...(cp.state.handsCwd !== undefined ? { cwd: cp.state.handsCwd } : {}),
|
|
122
|
+
...(cp.state.handsRoot !== undefined ? { root: cp.state.handsRoot } : {}),
|
|
120
123
|
};
|
|
124
|
+
const editedReq = { ...editedCall, targetReading: await readCallTarget(undefined, editedCall) };
|
|
121
125
|
const ig = cp.state.inheritedGate;
|
|
122
126
|
if (ig?.requiresParentConstraint === true) {
|
|
123
127
|
const chain = ig.constraintChain;
|
|
@@ -139,10 +143,20 @@ export async function resumeApply(input) {
|
|
|
139
143
|
const editBasePolicy = toolPolicyLocked
|
|
140
144
|
? (runner.deps.basePolicyForResumeEdit ?? runner.deps.toolPolicy)
|
|
141
145
|
: (config.basePolicyForResumeEdit ?? runner.deps.basePolicyForResumeEdit ?? config.toolPolicy ?? runner.deps.toolPolicy);
|
|
142
|
-
|
|
146
|
+
const rowLeg = { ...(typeof cp.state.handsRoot === "string" ? { root: cp.state.handsRoot } : {}), ...(typeof cp.state.handsHome === "string" ? { home: cp.state.handsHome } : {}) };
|
|
147
|
+
const asRecorded = (p) => p;
|
|
148
|
+
const installedEditBase = chainPolicyOnLeg({
|
|
149
|
+
leg: rowLeg,
|
|
150
|
+
chainTop: chainTopAnchors({ leg: rowLeg, live: internals?.inheritedGate?.pathRuleAnchors, seed: cp.state.inheritedGate?.pathRuleAnchors, placement: undefined, rebase: asRecorded }),
|
|
151
|
+
placement: undefined,
|
|
152
|
+
chain: (internals?.inheritedGate?.parentConstraints ?? []).map((c) => c.policy),
|
|
153
|
+
installations: { live: internals?.inheritedGate?.pathRuleInstallations, seed: cp.state.inheritedGate?.pathRuleInstallations },
|
|
154
|
+
rebase: asRecorded,
|
|
155
|
+
}).own(editBasePolicy);
|
|
156
|
+
if (installedEditBase !== undefined) {
|
|
143
157
|
let rechecked;
|
|
144
158
|
try {
|
|
145
|
-
rechecked = refuseOutOfContractDecision(await raceEditAbort(Promise.resolve(
|
|
159
|
+
rechecked = refuseOutOfContractDecision(await raceEditAbort(Promise.resolve(installedEditBase.check(editedReq, editSignal))));
|
|
146
160
|
}
|
|
147
161
|
catch (err) {
|
|
148
162
|
if (err instanceof CheckpointError)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { persistedReadDenyEntryProblem } from "../../tools/fs/read-deny.js";
|
|
2
|
+
import { isAbsolutePathForm } from "../../tools/fs/safety.js";
|
|
2
3
|
import { isAskOrigin } from "../ask-origin.js";
|
|
3
4
|
import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, MAX_SUPPORTED_CHECKPOINT_VERSION, realApprovalOrgFact } from "../checkpoint-store.js";
|
|
4
5
|
import { constraintChainDigest, constraintChainEntryOfSuppliedLayer } from "../tool-policy.js";
|
|
5
6
|
import { readFrozenSkillGrants } from "../skill-grant.js";
|
|
7
|
+
import { chainInstallationGaps, chainInstallationRefusal } from "./child-tree.js";
|
|
6
8
|
export function resumeCheckpointScreen(input) {
|
|
7
9
|
const { cp, resumeSignal, internals, runner } = input;
|
|
8
10
|
const { realApproval: realApprovalRow, face: faceRow, f012: f012Row } = CHECKPOINT_FEATURES;
|
|
@@ -49,6 +51,11 @@ export function resumeCheckpointScreen(input) {
|
|
|
49
51
|
}
|
|
50
52
|
if (readFrozenSkillGrants(cp.state.skillGrants) === undefined)
|
|
51
53
|
throw new CheckpointError("checkpoint.invalid_outcome", "this checkpoint carries a skill-grant section (state.skillGrants) that does not read as grant rows under this engine — a damaged section, or a row an earlier release wrote whose entry this release reads as nothing (an entry with a surrounding space, say) — refusing to resume without the grant rows and refusals it carries; the checkpoint stays pending: finish it on a worker of the release that parked it, or expire it", { reason: "skill_grants_damaged" });
|
|
54
|
+
for (const field of ["handsRoot", "handsHome", "handsCwd"]) {
|
|
55
|
+
const coordinate = cp.state[field];
|
|
56
|
+
if (coordinate !== undefined && (typeof coordinate !== "string" || !isAbsolutePathForm(coordinate)))
|
|
57
|
+
throw new CheckpointError("checkpoint.invalid_outcome", `this checkpoint's state.${field} is not an absolute path — refusing to resume a row whose hands' coordinates are damaged (corruption guard), the checkpoint stays pending`, { reason: "hands_coordinates_damaged" });
|
|
58
|
+
}
|
|
52
59
|
}
|
|
53
60
|
if (realApprovalOrgFact(preCasGateBit) !== undefined && runner.deps.permissionRuleStore?.partitions.org !== true) {
|
|
54
61
|
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" });
|
|
@@ -106,6 +113,12 @@ export function resumeCheckpointScreen(input) {
|
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
}
|
|
116
|
+
const resupplied = (internals?.inheritedGate?.parentConstraints ?? []).map((pc) => pc.policy);
|
|
117
|
+
if (resupplied.length > 0) {
|
|
118
|
+
const gaps = chainInstallationGaps(resupplied, { live: internals?.inheritedGate?.pathRuleInstallations, seed: cp.state.inheritedGate?.pathRuleInstallations }, (p) => p);
|
|
119
|
+
if (gaps.length > 0)
|
|
120
|
+
throw chainInstallationRefusal(gaps, true);
|
|
121
|
+
}
|
|
109
122
|
const resumeInternals = internals?.inheritedGate?.parentConstraints !== undefined
|
|
110
123
|
? {
|
|
111
124
|
...internals,
|
|
@@ -614,7 +614,8 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
614
614
|
}
|
|
615
615
|
const executedArgs = humanRewrite !== undefined ? resolvedArgs : screened !== undefined ? screened.args : resolvedArgs;
|
|
616
616
|
const unseen = !deepJsonEqual(executedArgs, pendingAction.args);
|
|
617
|
-
|
|
617
|
+
let beltReading;
|
|
618
|
+
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 } : {}), ...(prepared.handsRoot !== undefined ? { root: prepared.handsRoot } : {}), ...advertisedWritableRootsSeat(prepared.advertisedWritableDirs), ...(beltReading !== undefined ? { targetReading: beltReading } : {}) });
|
|
618
619
|
const unjudgeable = unseen ? chainCannotJudge(resume.cp.state.inheritedGate) : undefined;
|
|
619
620
|
if (unjudgeable !== undefined) {
|
|
620
621
|
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);
|
|
@@ -627,6 +628,9 @@ async function resolvePendingCall(runner, prepared, resume, emit, emitCommitted,
|
|
|
627
628
|
resourceSpentMicroUsd: prepared.resourceLedger?.spentMicroUsd ?? 0,
|
|
628
629
|
suspendCount: resume.cp.suspendCount ?? 0,
|
|
629
630
|
};
|
|
631
|
+
const beltStamped = prepared.stampCallTarget?.(beltReq(), prepared.abortController.signal);
|
|
632
|
+
if (beltStamped !== undefined)
|
|
633
|
+
beltReading = (await beltStamped).targetReading;
|
|
630
634
|
if (unseen && prepared.basePolicyForResumeEdit) {
|
|
631
635
|
const rechecked = refuseOutOfContractDecision(await prepared.basePolicyForResumeEdit.check(beltReq(), prepared.abortController.signal));
|
|
632
636
|
const personUnanswered = policyCannotAnswer(rechecked, outcome.hostDecision.decidedBy);
|
|
@@ -45,7 +45,7 @@ import { streamLifecycleVerbs } from "./stream-lifecycle-verbs.js";
|
|
|
45
45
|
import { streamHaltVerbs } from "./stream-halt-verbs.js";
|
|
46
46
|
import { streamModeVerb } from "./stream-mode-verb.js";
|
|
47
47
|
import { runNotificationLane } from "./run-notification-lane.js";
|
|
48
|
-
import {
|
|
48
|
+
import { assertRunnerDepsDoors } from "./construction-doors.js";
|
|
49
49
|
import { runLeg } from "./run-leg.js";
|
|
50
50
|
import { runTerminalAdoption } from "./run-terminal-adoption.js";
|
|
51
51
|
import { runSettleAndTeardown } from "./run-settle-and-teardown.js";
|
|
@@ -77,7 +77,7 @@ export class Runner {
|
|
|
77
77
|
static PARENT_CONSTRAINT_REGISTRY_CAP = 1024;
|
|
78
78
|
depsSeat;
|
|
79
79
|
constructor(deps) {
|
|
80
|
-
|
|
80
|
+
assertRunnerDepsDoors(deps);
|
|
81
81
|
const runner = this;
|
|
82
82
|
this.depsSeat = { get deps() { return runner.deps; } };
|
|
83
83
|
this.deps = withDeploymentAllowedTools(deps);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* list a deployment writes — the task's own definitions (`TaskSpec.agents`), the definitions a mounted delegation tool carries
|
|
4
4
|
* (the `authored` faces — the engine's built-ins name tools of other vocabularies and are not judged) and its tool-level list.
|
|
5
5
|
* Universe = the task's assembled roster plus every mounted delegation tool's pool, names and aliases; a pool the engine cannot
|
|
6
|
-
* list (an `extraTools` factory) turns the refusals that need a roster into host notices. A tool's own lists are judged where
|
|
6
|
+
* list (an `extraTools` factory with no declared roster) turns the refusals that need a roster into host notices. A tool's own lists are judged where
|
|
7
7
|
* the tool is mounted: only a tool a deployment mounted (depth 0) publishes them (`authored`, `agentToolLevelAllowTools`, `agentToolLevelDenyTools`), the
|
|
8
8
|
* engine's nested copy for a delegated child carries neither.
|
|
9
9
|
*
|
|
@@ -33,8 +33,9 @@ export interface LegWriteProtection extends WriteProtectionMount {
|
|
|
33
33
|
export declare function mountWriteProtection(input: {
|
|
34
34
|
/** borrowed-readonly — the deployment seats: the table (`writeProtectedPaths`; absent ⇒ the default
|
|
35
35
|
* table, `[]` ⇒ opted out), the data root the memory library is materialized under
|
|
36
|
-
* (`memoryEngineDir`; absent ⇒ the resolver's env/default chain)
|
|
37
|
-
|
|
36
|
+
* (`memoryEngineDir`; absent ⇒ the resolver's env/default chain), the configuration root the host
|
|
37
|
+
* declared (`agentConfigDir`) and the operator sink. */
|
|
38
|
+
deps: Pick<RunnerDeps, "writeProtectedPaths" | "memoryEngineDir" | "agentConfigDir" | "onNotice">;
|
|
38
39
|
/** The HANDS' environment, or `undefined` with no hands — the driver's own predicate, not a second
|
|
39
40
|
* reading of the env seats, so the judge sees exactly the environment the write tools do. */
|
|
40
41
|
env: ExecutionEnv | undefined;
|
|
@@ -6,6 +6,7 @@ export function mountWriteProtection(input) {
|
|
|
6
6
|
const announced = new Set();
|
|
7
7
|
const matcher = compileWriteProtection(input.deps.writeProtectedPaths, {
|
|
8
8
|
...(input.deps.memoryEngineDir !== undefined ? { dataRoot: input.deps.memoryEngineDir } : {}),
|
|
9
|
+
...(input.deps.agentConfigDir !== undefined ? { agentConfigDir: input.deps.agentConfigDir } : {}),
|
|
9
10
|
...(input.env !== undefined ? { env: input.env } : {}),
|
|
10
11
|
rootPath: input.rootPath,
|
|
11
12
|
onViewAbsent: (absence) => {
|
|
@@ -227,6 +227,20 @@ export interface RunnerDeps {
|
|
|
227
227
|
* ignored). Same deployment-only seat, clamp argument and checkpoint posture as the tiers key.
|
|
228
228
|
*/
|
|
229
229
|
readDenyBuiltinExclude?: readonly string[];
|
|
230
|
+
/**
|
|
231
|
+
* Where the host keeps the agent's configuration directory when it is not `<home>/.sema` — an ABSOLUTE path of an
|
|
232
|
+
* existing directory, resolved by the host (the engine reads no environment variable for it). The rows of the
|
|
233
|
+
* `agent-config` tier that name that directory (`~/.sema/settings.json`, `~/.sema/settings.local.json`,
|
|
234
|
+
* `~/.sema/engine-data/.env`, `~/.sema/config-lkg-*.json`) are then ALSO placed at the same files below this root, so the model can neither read
|
|
235
|
+
* nor (through the write-protection table and a wired `createSensitivePathPolicy({ agentConfigDir })`) rewrite the
|
|
236
|
+
* relocated settings; the default `~/.sema` location stays refused. Rows of the home's dotted family (`~/.sema.*`)
|
|
237
|
+
* and the external tools' files are not part of the directory and stay anchored at the home. A symlink the root is
|
|
238
|
+
* reached through is followed (the target is guarded too). ABSENT = today's behaviour, the literal `~/.sema` under
|
|
239
|
+
* the declared and account homes. A value that is not a string, is empty or relative, or names no existing directory
|
|
240
|
+
* refuses `new Runner` with `config.agent_config_dir_invalid` — never read as absent. DEPLOYMENT seat only (no
|
|
241
|
+
* TaskSpec twin) and fixed at construction: `swapDeps` does not carry it.
|
|
242
|
+
*/
|
|
243
|
+
agentConfigDir?: string;
|
|
230
244
|
/**
|
|
231
245
|
* backlog #286 (#279 — CC 2.1.233 `DANGEROUS_FILES`/`DANGEROUS_DIRECTORIES`/
|
|
232
246
|
* `DANGEROUS_DIRECTORY_PATHS` parity): the WRITE-protection table. DEFAULT-ON: a path-confinable
|
|
@@ -155,6 +155,14 @@ export declare function createSensitivePathPolicy(opts: {
|
|
|
155
155
|
* gate and the transcript gate keep speaking about the same directory.
|
|
156
156
|
*/
|
|
157
157
|
dataRoot?: string;
|
|
158
|
+
/**
|
|
159
|
+
* The host's configuration root when it keeps the agent's configuration directory somewhere other than the home's
|
|
160
|
+
* `.sema` — the same absolute directory it hands the Runner (`RunnerDeps.agentConfigDir`). Every pattern that opens with
|
|
161
|
+
* the `.sema` segment (`.sema/settings.json`, `.sema/hooks`, …) then also guards the same tail below this root; the
|
|
162
|
+
* patterns themselves keep guarding every `.sema` anywhere. Absent ⇒ the list is judged as it stands. A value that is not
|
|
163
|
+
* the absolute path of an existing directory throws (`config.agent_config_dir_invalid`).
|
|
164
|
+
*/
|
|
165
|
+
agentConfigDir?: string;
|
|
158
166
|
/** Override the guarded tool set (default: `Write`, `Edit`, `MultiEdit`-legacy → Edit, `NotebookEdit`). */
|
|
159
167
|
tools?: string[];
|
|
160
168
|
}): ToolPolicy;
|