@sema-agent/core 7.44.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 +418 -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 +65 -38
- package/dist/agents/tool-filter.d.ts +82 -5
- package/dist/agents/tool-filter.js +134 -4
- package/dist/core/agent-config-dir.d.ts +20 -0
- package/dist/core/agent-config-dir.js +49 -0
- package/dist/core/agent-definition.d.ts +2 -2
- package/dist/core/allow-entry.d.ts +30 -4
- package/dist/core/allow-entry.js +32 -5
- package/dist/core/ask-origin.d.ts +23 -4
- package/dist/core/ask-origin.js +11 -5
- package/dist/core/checkpoint-store.d.ts +41 -4
- package/dist/core/decision-receipt.js +1 -1
- package/dist/core/effective-path-target.d.ts +143 -10
- package/dist/core/effective-path-target.js +113 -9
- package/dist/core/engine-notice.d.ts +25 -3
- package/dist/core/engine-notice.js +12 -6
- package/dist/core/gate-fold.js +3 -0
- package/dist/core/gate-lanes.js +11 -3
- package/dist/core/gate-outcome.d.ts +5 -0
- package/dist/core/gate-outcome.js +2 -0
- package/dist/core/governance-codes.d.ts +3 -1
- package/dist/core/governance-codes.js +3 -0
- package/dist/core/hooks.d.ts +5 -0
- package/dist/core/memory-engine/content-origin.d.ts +0 -34
- package/dist/core/memory-engine/content-origin.js +9 -4
- package/dist/core/memory-engine/layout.d.ts +5 -1
- package/dist/core/memory-engine/layout.js +1 -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 -36
- package/dist/core/permission-rules.js +50 -40
- package/dist/core/real-approval.d.ts +9 -6
- package/dist/core/real-approval.js +5 -5
- package/dist/core/runner/child-tree.d.ts +110 -0
- package/dist/core/runner/child-tree.js +107 -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 +54 -2
- 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 +6 -0
- package/dist/core/runner/prepare-ask-lane.js +4 -2
- package/dist/core/runner/prepare-config-doors.js +3 -1
- package/dist/core/runner/prepare-execution-env.d.ts +5 -2
- package/dist/core/runner/prepare-execution-env.js +11 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +6 -0
- package/dist/core/runner/prepare-gate-stations.js +3 -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-listings.d.ts +4 -4
- package/dist/core/runner/prepare-listings.js +2 -22
- package/dist/core/runner/prepare-park-ask.d.ts +5 -0
- package/dist/core/runner/prepare-park-ask.js +6 -4
- package/dist/core/runner/prepare-policy-chain.d.ts +16 -2
- package/dist/core/runner/prepare-policy-chain.js +14 -5
- 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 +41 -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/resume-policy-outcome.js +2 -1
- package/dist/core/runner/run-leg.js +5 -1
- package/dist/core/runner/run-notification-lane.js +2 -2
- package/dist/core/runner/runtask.d.ts +2 -0
- package/dist/core/runner/runtask.js +4 -2
- package/dist/core/runner/stream-steer-verb.js +2 -2
- package/dist/core/runner/sub-agent-deny-lists.d.ts +32 -0
- package/dist/core/runner/sub-agent-deny-lists.js +121 -0
- package/dist/core/runner/synthetic-tools.d.ts +1 -1
- package/dist/core/runner/synthetic-tools.js +3 -2
- 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/session-policy-store.d.ts +6 -2
- package/dist/core/session-policy-store.js +2 -1
- 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/skill-grant.d.ts +10 -2
- package/dist/core/skill-grant.js +20 -4
- package/dist/core/synthetic-read-verdict.d.ts +3 -0
- package/dist/core/synthetic-read-verdict.js +3 -1
- package/dist/core/task-notification.d.ts +12 -1
- package/dist/core/task-notification.js +13 -1
- package/dist/core/task-spec.d.ts +5 -3
- 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 +45 -12
- package/dist/core/tool-policy.js +18 -20
- package/dist/core/tool-spec.d.ts +23 -4
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.js +1 -1
- package/dist/core/write-protect.d.ts +4 -0
- package/dist/core/write-protect.js +30 -9
- package/dist/index.d.ts +10 -6
- package/dist/index.js +9 -5
- package/dist/orchestration/run-spec.js +8 -7
- package/dist/orchestration/workflow.js +3 -2
- 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 +83 -0
- package/dist/tools/fs/removal-targets.js +236 -0
- 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 -37
- 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 +49 -3
- package/wire-changes/core@7.45.0.json +1084 -0
- 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, 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)) });
|
|
@@ -305,15 +306,17 @@ export async function preparePolicyChain(input) {
|
|
|
305
306
|
const grantBindingOf = (call, args) => skillGrantBindingMembers(call, args, skillSpecs, SKILL_TOOL_NAME);
|
|
306
307
|
const inheritedStationFacts = (call) => {
|
|
307
308
|
const seat = seatMarksOf(call);
|
|
309
|
+
const face = readFace();
|
|
308
310
|
return {
|
|
309
311
|
...INHERITED_STATION_FACTS,
|
|
310
312
|
mandateMarks: { egress: seat.egress, shellGated: false, ...(seat.tier === "always" && !seat.shellGated ? { irreversibility: "always" } : {}) },
|
|
311
313
|
...(seat.sources.size > 0 ? { toolMarkSources: seat.sources } : {}),
|
|
312
314
|
...(deps.a2a?.isolatePeers === true ? { a2aIsolatePeers: true } : {}),
|
|
315
|
+
...(face !== undefined ? { readFace: face } : {}),
|
|
313
316
|
};
|
|
314
317
|
};
|
|
315
318
|
const inheritedAskEvidence = inheritedAskRuleEvidence(deps.permissionRuleStore);
|
|
316
|
-
const listFacts = { root: taskRootFinal, sessionId, liveCwd: () => handsCwdRef?.current,
|
|
319
|
+
const listFacts = { root: taskRootFinal, sessionId, liveCwd: () => handsCwdRef?.current, anchors: pathRuleAnchors.leg };
|
|
317
320
|
const skillGrantLane = skillGrants.lane(listFacts);
|
|
318
321
|
const allowEntryLanes = { request: allowedToolTables.request.lane(listFacts), deployment: allowedToolTables.deployment.lane(listFacts) };
|
|
319
322
|
const { personal: permissionRuleLane, org: permissionRuleOrgLane } = createPermissionRuleLanes({
|
|
@@ -322,6 +325,9 @@ export async function preparePolicyChain(input) {
|
|
|
322
325
|
principal: spec.principal,
|
|
323
326
|
sessionId,
|
|
324
327
|
root: taskRootFinal,
|
|
328
|
+
rootCanonical: pathRuleAnchors.leg.root,
|
|
329
|
+
chainTop: pathRuleAnchors.chainTop,
|
|
330
|
+
leads: headLeads,
|
|
325
331
|
liveCwd: () => handsCwdRef?.current,
|
|
326
332
|
home: executionEnv.homeDir,
|
|
327
333
|
questionToolMounted,
|
|
@@ -329,6 +335,7 @@ export async function preparePolicyChain(input) {
|
|
|
329
335
|
onRevisionDefect: (message) => deps.onError?.(new Error(message), { phase: "config", sessionId }),
|
|
330
336
|
onDisclosure: (message) => emitTrace(deps.tracer, () => ({ kind: "permission.rule_store_unreadable", version: 1, taskId: hostTaskId, message, ts: Date.now() })),
|
|
331
337
|
onStoreUnreadable: announceRuleStoreSkipped,
|
|
338
|
+
onRowsDropped: announceRuleRowsDropped,
|
|
332
339
|
signal: abortController.signal,
|
|
333
340
|
stripsAllow: (rule, req) => permissionMode.current === "auto" && autoStrippedRule(rule, req),
|
|
334
341
|
});
|
|
@@ -364,7 +371,8 @@ export async function preparePolicyChain(input) {
|
|
|
364
371
|
}
|
|
365
372
|
let re;
|
|
366
373
|
try {
|
|
367
|
-
|
|
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));
|
|
368
376
|
}
|
|
369
377
|
catch (err) {
|
|
370
378
|
return vetoed({
|
|
@@ -616,7 +624,7 @@ export async function preparePolicyChain(input) {
|
|
|
616
624
|
...instrumentedChain,
|
|
617
625
|
...(rewriteCapableLayers ? narrowingLayers : []),
|
|
618
626
|
];
|
|
619
|
-
const integrityGuardLayers = [createTranscriptIntegrityPolicy(), createUnverifiableDeletePolicy()];
|
|
627
|
+
const integrityGuardLayers = [createTranscriptIntegrityPolicy(), createUnverifiableDeletePolicy({ removalSeat: { env: executionEnv, additionalRoots: () => additionalRootsCanonical } })];
|
|
620
628
|
const guardedPolicyLayers = rewriteCapableLayers
|
|
621
629
|
? [...integrityGuardLayers, ...policyLayers, modeGateLayer, ...integrityGuardLayers]
|
|
622
630
|
: [...integrityGuardLayers, ...policyLayers, modeGateLayer];
|
|
@@ -644,7 +652,8 @@ export async function preparePolicyChain(input) {
|
|
|
644
652
|
}
|
|
645
653
|
}
|
|
646
654
|
const recheckLayers = [...recheckPrefix, ...postEmitterSameInstanceAdapters];
|
|
647
|
-
const
|
|
655
|
+
const finalRead = withArgsReading(req, decision.updatedInput, signal);
|
|
656
|
+
const finalReq = finalRead !== undefined ? await finalRead : { ...req, args: decision.updatedInput };
|
|
648
657
|
let asked;
|
|
649
658
|
const revalidated = {};
|
|
650
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,16 +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";
|
|
32
|
+
import { chainAnchorRecords, chainPolicyOnLeg, chainTopAnchors, deploymentCanRerootChild } from "./child-tree.js";
|
|
29
33
|
import { prepareMemory } from "./prepare-memory.js";
|
|
30
34
|
import { prepareMemoryEngineSession } from "./prepare-memory-engine-session.js";
|
|
31
35
|
import { prepareDeferClassify } from "./prepare-defer-classify.js";
|
|
@@ -39,6 +43,7 @@ export { runGuardChain } from "./prepare-context-lane.js";
|
|
|
39
43
|
import { preparePromptAssembly } from "./prepare-prompt-assembly.js";
|
|
40
44
|
import { limitConfigError, prepareConfigDoors } from "./prepare-config-doors.js";
|
|
41
45
|
import { prepareSafetyScan } from "./prepare-safety-scan.js";
|
|
46
|
+
import { isAbsolutePathForm } from "../../tools/fs/safety.js";
|
|
42
47
|
import { prepareAcquireReconcile } from "./prepare-acquire-reconcile.js";
|
|
43
48
|
import { settleBranchWriteBack } from "./branch-writeback.js";
|
|
44
49
|
import { prepareHandsMount, resolveHandsLessReadFace } from "./prepare-hands-readface.js";
|
|
@@ -346,7 +351,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
346
351
|
throw e;
|
|
347
352
|
}
|
|
348
353
|
const rollback = createRollbackStack((e) => deps.onError?.(e, { phase: "config", sessionId }));
|
|
349
|
-
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 });
|
|
350
355
|
const externalContentTargetActive = executionEnv.externalContentTarget === true || resume?.seed.externalContentTarget === true;
|
|
351
356
|
const abortController = new AbortController();
|
|
352
357
|
if (spec.signal?.aborted)
|
|
@@ -363,9 +368,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
363
368
|
e.code = "isolation.unavailable";
|
|
364
369
|
throw e;
|
|
365
370
|
};
|
|
366
|
-
if (
|
|
371
|
+
if (!deploymentCanRerootChild(deps)) {
|
|
367
372
|
failIsolation("no executionEnvFactory is configured (a static/shared execution env cannot mint a per-agent worktree)");
|
|
368
373
|
}
|
|
374
|
+
else if (ownedEnvSeat.current === undefined) {
|
|
375
|
+
failIsolation("the executionEnvFactory returned no env instead of a worktree-rooted env");
|
|
376
|
+
}
|
|
369
377
|
else if (ownedEnvSeat.current === deps.executionEnv) {
|
|
370
378
|
ownedEnvSeat.current = undefined;
|
|
371
379
|
failIsolation("the executionEnvFactory returned the shared static env instead of a worktree-rooted env");
|
|
@@ -396,8 +404,15 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
396
404
|
}
|
|
397
405
|
}
|
|
398
406
|
const ownedEnv = ownedEnvSeat.current;
|
|
399
|
-
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 });
|
|
400
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));
|
|
401
416
|
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, fileHistoryFact, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, request: fileHistoryRequest, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, abortController });
|
|
402
417
|
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillGrants, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, bindPermissionModeSeat, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
403
418
|
const allowedToolTables = { request: new AllowEntryTable(), deployment: new AllowEntryTable() };
|
|
@@ -407,14 +422,19 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
407
422
|
let readDenyAdditionsNormalized = [];
|
|
408
423
|
let handsLessResolvedFace;
|
|
409
424
|
let handsLessResolvedWriteFace;
|
|
410
|
-
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 });
|
|
411
426
|
bindPermissionModeSeat(permissionMode);
|
|
412
427
|
const announceRuleStoreSkipped = ruleStoreUnreadableNotice(deps.onNotice, { sessionId, runId });
|
|
413
|
-
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 });
|
|
414
430
|
const persistedPathRows = persistedPathRowsRead === undefined ? { readDirectories: [], denyRows: [] } : await persistedPathRowsRead;
|
|
415
|
-
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];
|
|
416
436
|
const writeProtectionJudgeRef = {};
|
|
417
|
-
const writeGuards = { protection: () => writeProtectionJudgeRef.current, target: toolPolicyWriteTargetGuard([
|
|
437
|
+
const writeGuards = { protection: () => writeProtectionJudgeRef.current, target: toolPolicyWriteTargetGuard([installedToolPolicy, ...(inheritedParentConstraints ?? []).map((c) => c.policy)]) };
|
|
418
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 });
|
|
419
439
|
const tools = roster.tools;
|
|
420
440
|
const pausedRef = {};
|
|
@@ -552,7 +572,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
552
572
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
553
573
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
554
574
|
}
|
|
555
|
-
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 } : {}) };
|
|
556
576
|
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
557
577
|
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, shellReadCheck, shellReadAdmission, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
558
578
|
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
@@ -733,7 +753,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
733
753
|
releaseSignal = () => sig.removeEventListener("abort", onExternalAbort);
|
|
734
754
|
}
|
|
735
755
|
}
|
|
736
|
-
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, 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 });
|
|
737
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 });
|
|
738
758
|
const writeProtectionCheck = writeProtection?.check;
|
|
739
759
|
writeProtectionJudgeRef.current = writeProtection?.judgeTarget;
|
|
@@ -743,18 +763,21 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
743
763
|
return undefined;
|
|
744
764
|
});
|
|
745
765
|
}
|
|
746
|
-
const
|
|
747
|
-
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 });
|
|
748
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 });
|
|
749
|
-
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, 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 });
|
|
750
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() })) } } });
|
|
751
|
-
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 });
|
|
752
775
|
const postureFrameRef = { report: (err) => deps.onError?.(err, { phase: "degraded", sessionId }) };
|
|
753
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 } : {}) });
|
|
754
777
|
const preparedHolder = {};
|
|
755
|
-
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 });
|
|
756
779
|
await onceLedger.settle(session, announcedListingsRef);
|
|
757
|
-
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 } : {}) });
|
|
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 } : {}) });
|
|
758
781
|
rollback.commit();
|
|
759
782
|
commitModeSeats(abortController.signal);
|
|
760
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,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { canonicalizeCapturedPlainData, classifyQuestionOutcome, isLiveQuestionFace } from "../ask-question.js";
|
|
2
|
+
import { isHostDecider } from "../gate-outcome.js";
|
|
2
3
|
import { CHECKPOINT_FEATURES, CheckpointError, checkpointVersionOf, winnerFromOutcome } from "../checkpoint-store.js";
|
|
3
4
|
import { policyCannotAnswer, screenApproverAttribution } from "../tool-policy.js";
|
|
4
5
|
import { sanitizeUntrustedText } from "../untrusted-text.js";
|
|
@@ -52,7 +53,7 @@ export function resumePolicyOutcome(input) {
|
|
|
52
53
|
throw new CheckpointError("checkpoint.invalid_outcome", `resume carries no hostDecision — a policy_ask decide names who decided it ({ decidedBy: "person" | "sla_timeout" | "policy", approver? }); refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
|
|
53
54
|
}
|
|
54
55
|
const decidedBy = hostDecisionRaw.decidedBy;
|
|
55
|
-
if (decidedBy
|
|
56
|
+
if (!isHostDecider(decidedBy)) {
|
|
56
57
|
throw new CheckpointError("checkpoint.invalid_outcome", `resume hostDecision.decidedBy "${describeSuppliedValue(decidedBy)}" is outside the closed set — it is exactly "person", "sla_timeout" or "policy"; refusing pre-CAS, the checkpoint stays pending`, { field: "hostDecision" });
|
|
57
58
|
}
|
|
58
59
|
const cannotAllow = decision !== "allow"
|
|
@@ -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);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createPeerInboundChainRef, createPeerSelfRef } from "../../agents/peer-admission.js";
|
|
2
2
|
import { boundInputHashOf } from "../canonical-json.js";
|
|
3
|
-
import { createLiveNotificationLane, DurableAppendObligations, isDelegatedAgentTerminal, isTerminalTaskNotification, renderTaskNotificationXml, routeOrParkNotification, SystemInjectionQueue, taskNotificationDedupKey } from "../task-notification.js";
|
|
3
|
+
import { createLiveNotificationLane, DurableAppendObligations, injectionLaneOf, isDelegatedAgentTerminal, isTerminalTaskNotification, renderTaskNotificationXml, routeOrParkNotification, SystemInjectionQueue, taskNotificationDedupKey } from "../task-notification.js";
|
|
4
4
|
import { ToolDetachHub } from "../tool-detach.js";
|
|
5
5
|
import { pendingContentAskCallId } from "./decide-continuation.js";
|
|
6
6
|
export function runNotificationLane(input) {
|
|
@@ -76,7 +76,7 @@ async function runNotificationLaneAs(input, obligations) {
|
|
|
76
76
|
engineNoteKey: taskNotificationDedupKey(item.payload),
|
|
77
77
|
...(item.payload.task_type !== "external" && isTerminalTaskNotification(item.payload) ? { capPreferred: true } : {}),
|
|
78
78
|
};
|
|
79
|
-
const deliver = item.priority === "
|
|
79
|
+
const deliver = injectionLaneOf(item.priority) === "followUp"
|
|
80
80
|
? notificationHarness.followUp(xml, noteOptions)
|
|
81
81
|
: notificationHarness.steer(xml, { ...noteOptions, ...(item.priority === "now" ? { immediate: true } : {}) });
|
|
82
82
|
void deliver.then(() => item.onDisposition?.("queued"), () => {
|
|
@@ -68,6 +68,8 @@ export declare class Runner implements RunnerSelfSeat {
|
|
|
68
68
|
* thin compositions OVER the Runner (`runGoal`) can emit at their terminal state without reaching
|
|
69
69
|
* into private deps. */
|
|
70
70
|
emitTaskOutcome(outcome: TaskOutcome): void;
|
|
71
|
+
/** Whether a child this Runner runs can be placed in another tree: {@link RunnerSelfSeat.canRerootChild}. */
|
|
72
|
+
canRerootChild(): boolean;
|
|
71
73
|
/** The deployment agent catalog (RunnerDeps.agents/builtinAgents), exposed READ-ONLY
|
|
72
74
|
* so the Agent-tool lane (`createSubagentTool`) defaults to the SAME registry the workflow lane
|
|
73
75
|
* consumes (single source; the types.ts "pass the same array" follow-on made structural). The array
|
|
@@ -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";
|
|
@@ -62,6 +62,7 @@ import { runCompactionMachinery } from "./run-compaction-machinery.js";
|
|
|
62
62
|
import { runStopAndFinalVerify } from "./run-stop-and-final-verify.js";
|
|
63
63
|
import { runRecoveryLanes } from "./run-recovery-lanes.js";
|
|
64
64
|
import { runGitLane } from "./run-git-lane.js";
|
|
65
|
+
import { deploymentCanRerootChild } from "./child-tree.js";
|
|
65
66
|
import { thrownText } from "../thrown-value.js";
|
|
66
67
|
export class Runner {
|
|
67
68
|
deps;
|
|
@@ -76,7 +77,7 @@ export class Runner {
|
|
|
76
77
|
static PARENT_CONSTRAINT_REGISTRY_CAP = 1024;
|
|
77
78
|
depsSeat;
|
|
78
79
|
constructor(deps) {
|
|
79
|
-
|
|
80
|
+
assertRunnerDepsDoors(deps);
|
|
80
81
|
const runner = this;
|
|
81
82
|
this.depsSeat = { get deps() { return runner.deps; } };
|
|
82
83
|
this.deps = withDeploymentAllowedTools(deps);
|
|
@@ -125,6 +126,7 @@ export class Runner {
|
|
|
125
126
|
emitTaskOutcome(outcome) {
|
|
126
127
|
emitTaskOutcome(this.deps, outcome);
|
|
127
128
|
}
|
|
129
|
+
canRerootChild() { return deploymentCanRerootChild(this.deps); }
|
|
128
130
|
get agentCatalog() {
|
|
129
131
|
return {
|
|
130
132
|
...(this.deps.agents ? { agents: [...this.deps.agents] } : {}),
|