@sema-agent/core 7.5.0 → 7.5.2
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 +44 -0
- package/dist/core/auto-mode.d.ts +9 -0
- package/dist/core/auto-mode.js +11 -0
- package/dist/core/checkpoint-store.js +5 -1
- package/dist/core/protocol-table.d.ts +5 -0
- package/dist/core/protocol-table.js +1 -0
- package/dist/core/runner/abort-race.d.ts +41 -0
- package/dist/core/runner/abort-race.js +38 -0
- package/dist/core/runner/checkpoint-scope.d.ts +44 -0
- package/dist/core/runner/checkpoint-scope.js +7 -0
- package/dist/core/runner/compaction-call-options.d.ts +1 -1
- package/dist/core/runner/content-ask-bindings.d.ts +27 -0
- package/dist/core/runner/content-ask-bindings.js +1 -0
- package/dist/core/runner/contracts.d.ts +1990 -0
- package/dist/core/runner/contracts.js +1 -0
- package/dist/core/runner/denial-limit-arms.d.ts +24 -1
- package/dist/core/runner/denial-limit-arms.js +21 -0
- package/dist/core/runner/derived-route-fallback.d.ts +34 -0
- package/dist/core/runner/derived-route-fallback.js +16 -0
- package/dist/core/runner/inherited-ask-grants.d.ts +46 -0
- package/dist/core/runner/inherited-ask-grants.js +29 -0
- package/dist/core/runner/park-commit.d.ts +108 -0
- package/dist/core/runner/park-commit.js +32 -0
- package/dist/core/runner/{prepare-permission-rules.d.ts → permission-rule-lanes.d.ts} +109 -3
- package/dist/core/runner/{prepare-permission-rules.js → permission-rule-lanes.js} +47 -1
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +1 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +110 -0
- package/dist/core/runner/prepare-ask-lane.js +133 -0
- package/dist/core/runner/prepare-boundary-parks.d.ts +105 -0
- package/dist/core/runner/prepare-boundary-parks.js +169 -0
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +170 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +255 -0
- package/dist/core/runner/prepare-config-doors.d.ts +2 -10
- package/dist/core/runner/prepare-context-lane.d.ts +119 -0
- package/dist/core/runner/prepare-context-lane.js +230 -0
- package/dist/core/runner/prepare-defer-classify.d.ts +86 -0
- package/dist/core/runner/prepare-defer-classify.js +107 -0
- package/dist/core/runner/prepare-delegation-surface.d.ts +104 -0
- package/dist/core/runner/prepare-delegation-surface.js +144 -0
- package/dist/core/runner/prepare-execution-env.d.ts +54 -0
- package/dist/core/runner/prepare-execution-env.js +86 -0
- package/dist/core/runner/prepare-file-history.d.ts +95 -0
- package/dist/core/runner/prepare-file-history.js +383 -0
- package/dist/core/runner/prepare-gate-stations.d.ts +177 -0
- package/dist/core/runner/prepare-gate-stations.js +290 -0
- package/dist/core/runner/prepare-hands-readface.d.ts +9 -11
- package/dist/core/runner/prepare-hands-readface.js +1 -1
- package/dist/core/runner/prepare-inherited-gate.d.ts +268 -0
- package/dist/core/runner/prepare-inherited-gate.js +266 -0
- package/dist/core/runner/prepare-listings.d.ts +77 -0
- package/dist/core/runner/prepare-listings.js +76 -0
- package/dist/core/runner/prepare-lsp.d.ts +55 -0
- package/dist/core/runner/prepare-lsp.js +27 -0
- package/dist/core/runner/prepare-memory-engine-session.d.ts +84 -0
- package/dist/core/runner/prepare-memory-engine-session.js +233 -0
- package/dist/core/runner/prepare-memory.d.ts +1 -1
- package/dist/core/runner/prepare-offload-wrappers.d.ts +62 -0
- package/dist/core/runner/prepare-offload-wrappers.js +45 -0
- package/dist/core/runner/prepare-park-ask.d.ts +164 -0
- package/dist/core/runner/prepare-park-ask.js +377 -0
- package/dist/core/runner/prepare-policy-chain.d.ts +208 -0
- package/dist/core/runner/prepare-policy-chain.js +584 -0
- package/dist/core/runner/prepare-project-context.d.ts +119 -0
- package/dist/core/runner/prepare-project-context.js +148 -0
- package/dist/core/runner/prepare-prompt-assembly.d.ts +95 -0
- package/dist/core/runner/prepare-prompt-assembly.js +162 -0
- package/dist/core/runner/prepare-prompt-inputs.d.ts +119 -0
- package/dist/core/runner/prepare-prompt-inputs.js +141 -0
- package/dist/core/runner/prepare-protocol-tools.d.ts +91 -0
- package/dist/core/runner/prepare-protocol-tools.js +179 -0
- package/dist/core/runner/prepare-question-face.d.ts +101 -0
- package/dist/core/runner/prepare-question-face.js +84 -0
- package/dist/core/runner/prepare-run-refs.d.ts +89 -0
- package/dist/core/runner/prepare-run-refs.js +39 -0
- package/dist/core/runner/prepare-safety-scan.d.ts +3 -7
- package/dist/core/runner/prepare-safety-scan.js +1 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +170 -0
- package/dist/core/runner/prepare-suspend-saga.js +308 -0
- package/dist/core/runner/prepare-task.d.ts +14 -1976
- package/dist/core/runner/prepare-task.js +182 -5162
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +111 -0
- package/dist/core/runner/prepare-tool-disclosure-mount.js +219 -0
- package/dist/core/runner/prepare-turn-wiring.d.ts +154 -0
- package/dist/core/runner/prepare-turn-wiring.js +201 -0
- package/dist/core/runner/prepare-wiring-manifest.d.ts +192 -0
- package/dist/core/runner/prepare-wiring-manifest.js +247 -0
- package/dist/core/runner/prepare-workspace-restore.d.ts +3 -56
- package/dist/core/runner/prepare-workspace-restore.js +4 -38
- package/dist/core/runner/prompt-hash-salt.d.ts +1 -0
- package/dist/core/runner/prompt-hash-salt.js +2 -0
- package/dist/core/runner/remote-env-retry.d.ts +29 -0
- package/dist/core/runner/remote-env-retry.js +16 -0
- package/dist/core/runner/rollback-stack.d.ts +32 -0
- package/dist/core/runner/rollback-stack.js +30 -0
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/workspace-path.d.ts +33 -0
- package/dist/core/runner/workspace-path.js +22 -0
- package/dist/core/session.d.ts +12 -0
- package/dist/core/session.js +3 -0
- package/dist/core/tool-policy.d.ts +16 -0
- package/dist/core/tool-policy.js +3 -0
- package/dist/core/types.d.ts +2 -2
- package/dist/core/write-protect.js +3 -2
- package/package.json +6 -2
- /package/dist/core/runner/{prepare-announce-once.d.ts → announce-once-ledger.d.ts} +0 -0
- /package/dist/core/runner/{prepare-announce-once.js → announce-once-ledger.js} +0 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { SEND_MESSAGE_TOOL_NAME } from "../../agents/send-message-tool.js";
|
|
2
|
+
import { complianceCallDenial } from "../compliance.js";
|
|
3
|
+
import { cloneObserverInput, formatHookFeedback, hookSeatExpiredError, runHookSeat, runToolGate } from "../hooks.js";
|
|
4
|
+
import { PRESENT_PLAN_TOOL_NAME } from "../present-plan-tool.js";
|
|
5
|
+
import { isApprovalSettledBy, isAskDenyResolution, screenApproverAttribution } from "../tool-policy.js";
|
|
6
|
+
import { emitTrace } from "../trace.js";
|
|
7
|
+
import { createWriteProtectionCheck } from "../write-protect.js";
|
|
8
|
+
import { PATH_CONFINABLE_WRITE_TOOLS } from "./session-rule-policy.js";
|
|
9
|
+
function screenGateSettlement(result, settling) {
|
|
10
|
+
const defects = [];
|
|
11
|
+
const reportedBy = result.settledBy;
|
|
12
|
+
let settledBy;
|
|
13
|
+
if (reportedBy !== undefined) {
|
|
14
|
+
if (!isApprovalSettledBy(reportedBy) || (!settling && reportedBy !== "human")) {
|
|
15
|
+
defects.push(`a tool-gate settlement reported settledBy "${String(reportedBy)}" on ${settling ? "a blocked" : "an executing"} call — ` +
|
|
16
|
+
`it is one of "human" / "timeout" / "aborted", and only "human" can be the source of a call that runs; the frame carries no source`);
|
|
17
|
+
}
|
|
18
|
+
else
|
|
19
|
+
settledBy = reportedBy;
|
|
20
|
+
}
|
|
21
|
+
const attribution = screenApproverAttribution(result.approver);
|
|
22
|
+
if (attribution.defect !== undefined) {
|
|
23
|
+
defects.push(`a tool-gate settlement reported an attribution this engine refuses: ${attribution.defect}; the frame carries no approver`);
|
|
24
|
+
}
|
|
25
|
+
const reportedResolution = result.resolution;
|
|
26
|
+
let resolution;
|
|
27
|
+
if (reportedResolution !== undefined) {
|
|
28
|
+
if (!isAskDenyResolution(reportedResolution) || !settling) {
|
|
29
|
+
defects.push(`a tool-gate settlement reported a deny resolution "${String(reportedResolution)}" on ${settling ? "a blocked" : "an executing"} call — ` +
|
|
30
|
+
`it is one of the closed ask-deny vocabulary and only a BLOCKED call can carry one; the frame carries no resolution`);
|
|
31
|
+
}
|
|
32
|
+
else
|
|
33
|
+
resolution = reportedResolution;
|
|
34
|
+
}
|
|
35
|
+
const reportedAutoDenied = result.autoDenied;
|
|
36
|
+
let autoDenied;
|
|
37
|
+
if (reportedAutoDenied === true) {
|
|
38
|
+
if (!settling)
|
|
39
|
+
defects.push("a tool-gate settlement reported autoDenied on an executing call — only a BLOCKED call can carry the marker; the frame carries none");
|
|
40
|
+
else
|
|
41
|
+
autoDenied = true;
|
|
42
|
+
}
|
|
43
|
+
const record = {
|
|
44
|
+
...(settledBy !== undefined ? { settledBy } : {}),
|
|
45
|
+
...(attribution.approver !== undefined ? { approver: attribution.approver } : {}),
|
|
46
|
+
...(resolution !== undefined ? { resolution } : {}),
|
|
47
|
+
...(autoDenied !== undefined ? { autoDenied } : {}),
|
|
48
|
+
};
|
|
49
|
+
return { ...(settledBy !== undefined || attribution.approver !== undefined || resolution !== undefined || autoDenied !== undefined ? { record } : {}), defects };
|
|
50
|
+
}
|
|
51
|
+
function maybeHumanRejectionHalt(input) {
|
|
52
|
+
if (!input.bare || input.settledBy !== "human" || input.isDelegatedChild)
|
|
53
|
+
return undefined;
|
|
54
|
+
return {
|
|
55
|
+
reason: `This tool call was NOT executed: the user rejected the "${input.toolName}" tool call in the same ` +
|
|
56
|
+
`assistant message, which stops the rest of the batch. Nothing was run for this call — ` +
|
|
57
|
+
`re-issue it after the user's direction only if it is still needed.`,
|
|
58
|
+
details: {
|
|
59
|
+
error: "gate.batch_halted",
|
|
60
|
+
code: "gate.batch_halted",
|
|
61
|
+
rejectedToolCallId: input.toolCallId,
|
|
62
|
+
rejectedToolName: input.toolName,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function prepareGateStations(input) {
|
|
67
|
+
const { askLane, parkAsk, tools, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, humanBareRejections, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, approvalSettlement, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedBash, shellGatedMonitor, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash } = input;
|
|
68
|
+
if (askLane !== undefined && parkAsk !== undefined) {
|
|
69
|
+
const { adjudicate, resolveAskBound, notifyPermissionDenied, notifyHookError } = askLane;
|
|
70
|
+
const { resolveContentAsk, suspendAsk } = parkAsk;
|
|
71
|
+
for (const t of tools) {
|
|
72
|
+
const eff = t.effect;
|
|
73
|
+
if (eff !== undefined && !toolEffects.has(t.name))
|
|
74
|
+
toolEffects.set(t.name, eff);
|
|
75
|
+
}
|
|
76
|
+
const writeProtectionCheck = createWriteProtectionCheck(deps.writeProtectedPaths, deps.memoryEngineDir !== undefined ? { dataRoot: deps.memoryEngineDir } : undefined);
|
|
77
|
+
const writeProtectionArmed = writeProtectionCheck !== undefined && tools.some((t) => PATH_CONFINABLE_WRITE_TOOLS.has(t.name));
|
|
78
|
+
toolCallGateArmedRef.armed =
|
|
79
|
+
effectivePolicy !== undefined ||
|
|
80
|
+
hooks?.preToolUse !== undefined ||
|
|
81
|
+
egressTools.size > 0 ||
|
|
82
|
+
irreversibleTools.size > 0 ||
|
|
83
|
+
spec.enablePlanMode === true ||
|
|
84
|
+
complianceDenies.has("web_fetch") ||
|
|
85
|
+
writeProtectionArmed;
|
|
86
|
+
if (toolCallGateArmedRef.armed) {
|
|
87
|
+
harness.on("tool_call", async (e) => {
|
|
88
|
+
blockedToolCalls.delete(e.toolCallId);
|
|
89
|
+
inheritedAskGrants.delete(e.toolCallId);
|
|
90
|
+
humanBareRejections.delete(e.toolCallId);
|
|
91
|
+
{
|
|
92
|
+
const complianceDeny = complianceCallDenial(complianceDenies, e.toolName);
|
|
93
|
+
if (complianceDeny !== undefined) {
|
|
94
|
+
if (blockedTracked)
|
|
95
|
+
blockedToolCalls.add(e.toolCallId);
|
|
96
|
+
if (notifyPermissionDenied) {
|
|
97
|
+
await notifyPermissionDenied({ toolName: e.toolName, input: cloneObserverInput(e.input), toolCallId: e.toolCallId, reason: complianceDeny, source: "safety", identity: hookIdentity });
|
|
98
|
+
}
|
|
99
|
+
return { block: true, reason: formatHookFeedback(complianceDeny, reminderMark), preToolContext: [] };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (planModeRef.active && (toolEffects.get(e.toolName) ?? "write") !== "read") {
|
|
103
|
+
if (blockedTracked)
|
|
104
|
+
blockedToolCalls.add(e.toolCallId);
|
|
105
|
+
const planDenyReason = `Plan mode is active — "${e.toolName}" is a write/mutating tool and is read-only-blocked. ` +
|
|
106
|
+
`Research with read-only tools, then call ${PRESENT_PLAN_TOOL_NAME} with your plan to get it approved before acting.`;
|
|
107
|
+
if (notifyPermissionDenied) {
|
|
108
|
+
await notifyPermissionDenied({ toolName: e.toolName, input: cloneObserverInput(e.input), toolCallId: e.toolCallId, reason: planDenyReason, source: "planMode", identity: hookIdentity });
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
block: true,
|
|
112
|
+
reason: formatHookFeedback(planDenyReason, reminderMark),
|
|
113
|
+
preToolContext: [],
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
let result;
|
|
117
|
+
let humanBareRejection = false;
|
|
118
|
+
try {
|
|
119
|
+
result = await runToolGate({
|
|
120
|
+
onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: hostTaskId, site: f.site, message: f.error.message, ts: Date.now() })),
|
|
121
|
+
event: e,
|
|
122
|
+
...(e.signal !== undefined ? { callSignal: e.signal } : {}),
|
|
123
|
+
identity: hookIdentity,
|
|
124
|
+
reminderMark,
|
|
125
|
+
preToolUse: ownGatePreToolUse,
|
|
126
|
+
hookTimeoutMs,
|
|
127
|
+
...(handsCwdRef !== undefined ? { trackedCwd: () => handsCwdRef.current } : {}),
|
|
128
|
+
...(hookEnvFace !== undefined ? { hookEnv: hookEnvFace } : {}),
|
|
129
|
+
adjudicate,
|
|
130
|
+
resolveAsk: resolveAskBound,
|
|
131
|
+
suspendAsk,
|
|
132
|
+
resolveContentAsk,
|
|
133
|
+
egress: egressTools.has(e.toolName),
|
|
134
|
+
peerMessage: e.toolName === SEND_MESSAGE_TOOL_NAME,
|
|
135
|
+
...(writeProtectionCheck !== undefined ? { writeProtectionCheck } : {}),
|
|
136
|
+
irreversibility: irreversibilityTier.get(e.toolName),
|
|
137
|
+
reversibilityProbe: reversibilityProbes.get(e.toolName),
|
|
138
|
+
abortSignal: abortController.signal,
|
|
139
|
+
...(notifyPermissionDenied ? { permissionDenied: notifyPermissionDenied } : {}),
|
|
140
|
+
onHookError: notifyHookError,
|
|
141
|
+
shellGated: (e.toolName === "Bash" && shellGatedBash) || (e.toolName === "Monitor" && shellGatedMonitor),
|
|
142
|
+
...(autoModeDecider ? { autoMode: { decider: autoModeDecider, ...(autoModeDenialTracking !== undefined ? { denialTracking: autoModeDenialTracking } : {}) } } : {}),
|
|
143
|
+
onHeadlessDenialLimit: stopForDenialLimit,
|
|
144
|
+
...(permissionRuleLane
|
|
145
|
+
? {
|
|
146
|
+
persistedRules: {
|
|
147
|
+
admits: permissionRuleLane.admits,
|
|
148
|
+
onResolved: (info) => emitTrace(deps.tracer, () => ({
|
|
149
|
+
kind: "permission.persisted_rule_allowed",
|
|
150
|
+
version: 2,
|
|
151
|
+
taskId: hostTaskId,
|
|
152
|
+
toolName: info.toolName,
|
|
153
|
+
toolCallId: info.toolCallId,
|
|
154
|
+
rules: [...info.rules],
|
|
155
|
+
ts: Date.now(),
|
|
156
|
+
})),
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
: {}),
|
|
160
|
+
...(permissionRuleOrgLane
|
|
161
|
+
? {
|
|
162
|
+
orgRules: {
|
|
163
|
+
adjudicate: permissionRuleOrgLane.adjudicate,
|
|
164
|
+
contentAskToolMounted: questionToolMounted,
|
|
165
|
+
onUnavailable: (info) => emitTrace(deps.tracer, () => ({
|
|
166
|
+
kind: "permission.org_snapshot_unavailable",
|
|
167
|
+
version: 1,
|
|
168
|
+
taskId: hostTaskId,
|
|
169
|
+
toolName: info.toolName,
|
|
170
|
+
toolCallId: info.toolCallId,
|
|
171
|
+
message: info.message,
|
|
172
|
+
ts: Date.now(),
|
|
173
|
+
})),
|
|
174
|
+
},
|
|
175
|
+
}
|
|
176
|
+
: {}),
|
|
177
|
+
isMarkedUnresolvable: (toolCallId) => inheritedUnavailableAsks.has(toolCallId),
|
|
178
|
+
...(sandboxAdmissionArmed
|
|
179
|
+
? {
|
|
180
|
+
sandboxAdmission: {
|
|
181
|
+
askClassesOf: (toolCallId) => foldAskClasses.get(toolCallId),
|
|
182
|
+
boundaryCapable: sandboxBoundaryCapable(e.toolName),
|
|
183
|
+
onAdmitted: emitSandboxAdmitted,
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
: {}),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
inheritedUnavailableAsks.delete(e.toolCallId);
|
|
191
|
+
inheritedAskGrants.delete(e.toolCallId);
|
|
192
|
+
foldAskClasses.delete(e.toolCallId);
|
|
193
|
+
humanBareRejection = humanBareRejections.delete(e.toolCallId);
|
|
194
|
+
}
|
|
195
|
+
const ancestorAdmitted = ancestorSandboxAdmissions.get(e.toolCallId);
|
|
196
|
+
ancestorSandboxAdmissions.delete(e.toolCallId);
|
|
197
|
+
if (ancestorAdmitted !== undefined && !result.block && !result.suspend) {
|
|
198
|
+
emitSandboxAdmitted({ toolCallId: e.toolCallId, toolName: e.toolName, askClasses: ancestorAdmitted, boundary: "sandbox_internal" });
|
|
199
|
+
result.preToolContext.push(`permission.sandbox_admitted: this call's inherited pending approval was auto-admitted because the deployment declares an isolated sandbox execution env and the request stays inside it. Recorded for audit.`);
|
|
200
|
+
}
|
|
201
|
+
if (!result.block && !result.suspend && result.preToolContext.length > 0) {
|
|
202
|
+
preToolContexts.set(e.toolCallId, result.preToolContext);
|
|
203
|
+
}
|
|
204
|
+
if (blockedTracked && (result.block || result.suspend)) {
|
|
205
|
+
blockedToolCalls.add(e.toolCallId);
|
|
206
|
+
}
|
|
207
|
+
const settlement = screenGateSettlement(result, result.block === true);
|
|
208
|
+
for (const defect of settlement.defects)
|
|
209
|
+
deps.onError?.(new Error(defect), { phase: "config", sessionId });
|
|
210
|
+
if (settlement.record !== undefined)
|
|
211
|
+
approvalSettlement.set(e.toolCallId, settlement.record);
|
|
212
|
+
if (result.block) {
|
|
213
|
+
const haltRemaining = maybeHumanRejectionHalt({
|
|
214
|
+
bare: humanBareRejection,
|
|
215
|
+
settledBy: result.settledBy,
|
|
216
|
+
isDelegatedChild: delegation.isDelegatedChild === true,
|
|
217
|
+
toolName: e.toolName,
|
|
218
|
+
toolCallId: e.toolCallId,
|
|
219
|
+
});
|
|
220
|
+
if (haltRemaining !== undefined) {
|
|
221
|
+
batchHaltRef.current = { rejectedToolCallId: e.toolCallId };
|
|
222
|
+
return { block: true, reason: result.reason, haltRemaining };
|
|
223
|
+
}
|
|
224
|
+
return { block: true, reason: result.reason };
|
|
225
|
+
}
|
|
226
|
+
return result.updatedInput !== undefined ? { updatedInput: result.updatedInput } : undefined;
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const toolResultStationArmed = Boolean(hooks?.postToolUse || hooks?.preToolUse || hooks?.postToolUseFailure);
|
|
231
|
+
if (toolResultStationArmed) {
|
|
232
|
+
harness.on("tool_result", async (e) => {
|
|
233
|
+
if (blockedToolCalls.delete(e.toolCallId)) {
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
let content = e.content;
|
|
237
|
+
let changed = false;
|
|
238
|
+
if (e.isError) {
|
|
239
|
+
if (hooks?.postToolUseFailure) {
|
|
240
|
+
let clonedDetails = e.details;
|
|
241
|
+
try {
|
|
242
|
+
clonedDetails = structuredClone(e.details);
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
}
|
|
246
|
+
const failureSeat = await runHookSeat("postToolUseFailure", { timeoutMs: hookTimeoutMs, signal: abortController.signal }, (sig) => hooks.postToolUseFailure(e.toolName, e.input, {
|
|
247
|
+
error: e.content
|
|
248
|
+
.filter((c) => c.type === "text")
|
|
249
|
+
.map((c) => c.text)
|
|
250
|
+
.join("\n"),
|
|
251
|
+
isInterrupt: abortController.signal.aborted || spec.signal?.aborted === true,
|
|
252
|
+
content: e.content.map((c) => ({ ...c })),
|
|
253
|
+
details: clonedDetails,
|
|
254
|
+
}, { toolCallId: e.toolCallId, toolName: e.toolName, signal: sig, ...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}), ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}), identity: hookIdentity }));
|
|
255
|
+
if (failureSeat.expired) {
|
|
256
|
+
notifyOwnHookCrash(hookSeatExpiredError("postToolUseFailure", hookTimeoutMs, failureSeat.cause, "the observation was abandoned and its additionalContext dropped; the failure result itself is unchanged"));
|
|
257
|
+
}
|
|
258
|
+
const patch = failureSeat.expired ? undefined : failureSeat.value;
|
|
259
|
+
if (patch?.additionalContext) {
|
|
260
|
+
content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext, reminderMark) }];
|
|
261
|
+
changed = true;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else if (hooks?.postToolUse) {
|
|
266
|
+
const successSeat = await runHookSeat("postToolUse", { timeoutMs: hookTimeoutMs, signal: abortController.signal }, (sig) => hooks.postToolUse(e.toolName, e.input, { content: e.content, details: e.details, isError: e.isError }, { toolCallId: e.toolCallId, toolName: e.toolName, signal: sig, ...(handsCwdRef?.current !== undefined ? { cwd: handsCwdRef.current } : {}), ...(hookEnvFace !== undefined ? { env: hookEnvFace } : {}), identity: hookIdentity }));
|
|
267
|
+
if (successSeat.expired) {
|
|
268
|
+
notifyOwnHookCrash(hookSeatExpiredError("postToolUse", hookTimeoutMs, successSeat.cause, "the seat was abandoned; the tool result is delivered to the model UNMODIFIED (no updatedOutput, no additionalContext)"));
|
|
269
|
+
}
|
|
270
|
+
const patch = successSeat.expired ? undefined : successSeat.value;
|
|
271
|
+
if (patch?.updatedOutput) {
|
|
272
|
+
content = patch.updatedOutput;
|
|
273
|
+
changed = true;
|
|
274
|
+
}
|
|
275
|
+
if (patch?.additionalContext) {
|
|
276
|
+
content = [...content, { type: "text", text: formatHookFeedback(patch.additionalContext, reminderMark) }];
|
|
277
|
+
changed = true;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const pre = preToolContexts.get(e.toolCallId);
|
|
281
|
+
if (pre) {
|
|
282
|
+
preToolContexts.delete(e.toolCallId);
|
|
283
|
+
content = [...content, ...pre.map((t) => ({ type: "text", text: formatHookFeedback(t, reminderMark) }))];
|
|
284
|
+
changed = true;
|
|
285
|
+
}
|
|
286
|
+
return changed ? { content } : undefined;
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
return { toolCallStationArmed: toolCallGateArmedRef.armed, toolResultStationArmed };
|
|
290
|
+
}
|
|
@@ -4,9 +4,7 @@ import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
|
4
4
|
import type { Model } from "../../internal/llm.js";
|
|
5
5
|
import type { AgentTool, ExecutionEnv, WorkspaceState } from "../../internal/harness.js";
|
|
6
6
|
import type { StoredSession } from "../session.js";
|
|
7
|
-
import type {
|
|
8
|
-
import type { PrepareSafetyScanResult } from "./prepare-safety-scan.js";
|
|
9
|
-
import type { PrepareResume, RunInternals } from "./prepare-task.js";
|
|
7
|
+
import type { IrreversibilityTier, PrepareResume, ReversibilityProbes, RunInternals, ToolFaceSnapshot } from "./contracts.js";
|
|
10
8
|
/** Test seam (mirrors `__resetMalformedNoticeSeatAnnouncement`): never called by production code.
|
|
11
9
|
* Deliberately asymmetric — it resets only the console latch: the WeakSet arm needs no seam
|
|
12
10
|
* because a test resets it by minting a fresh sink function (identity IS the ledger key), while
|
|
@@ -139,7 +137,7 @@ export interface PrepareHandsReadFaceInput {
|
|
|
139
137
|
effectiveShellGate: "off" | "classify" | "always";
|
|
140
138
|
/** borrowed-readonly — B-1's frozen task-start face snapshot; only `.exclude` is read here (the
|
|
141
139
|
* Monitor-mount honesty bit for the gh rate-limit hint, #181-F6). */
|
|
142
|
-
toolFaceSnapshot:
|
|
140
|
+
toolFaceSnapshot: ToolFaceSnapshot;
|
|
143
141
|
/** borrowed-readonly — B-1's resolved main model; read ONLY for its pdf capability profile
|
|
144
142
|
* (the Read tool's document-degradation fork). */
|
|
145
143
|
model: Model;
|
|
@@ -162,9 +160,9 @@ export interface PrepareHandsReadFaceInput {
|
|
|
162
160
|
* when no file restore ran. Fail-closed by construction — dropping a read record only ever
|
|
163
161
|
* produces refusals. */
|
|
164
162
|
restoredFilePaths?: readonly string[];
|
|
165
|
-
/** borrowed (ref cell; the REF itself is never replaced)
|
|
163
|
+
/** borrowed-readonly — (ref cell; the REF itself is never replaced) design/138 S2-C late-bound memory
|
|
166
164
|
* write gate: the band's beforeWrite closure reads `.current` call-time; prepareMemory (driver,
|
|
167
|
-
* after this phase) installs the gate. Declared in the driver because the SAME ref feeds
|
|
165
|
+
* after this phase) installs the gate — the one writer; this phase only reads. Declared in the driver because the SAME ref feeds
|
|
168
166
|
* prepareMemory. */
|
|
169
167
|
memoryWriteGateRef: {
|
|
170
168
|
current?: BeforeWriteHook;
|
|
@@ -185,13 +183,13 @@ export interface PrepareHandsReadFaceInput {
|
|
|
185
183
|
/** borrowed-mutable — the shellGate fold's tier write-back (`.get` for the provenance bit,
|
|
186
184
|
* monotonic `.set` — tighten-only). Same object B-2 returned; owner table lives on the B-2
|
|
187
185
|
* Result. */
|
|
188
|
-
irreversibilityTier:
|
|
186
|
+
irreversibilityTier: IrreversibilityTier;
|
|
189
187
|
/** borrowed-mutable — the shellGate fold `.add`s Bash/Monitor here. Same-object contract as
|
|
190
188
|
* above. */
|
|
191
|
-
irreversibleTools:
|
|
189
|
+
irreversibleTools: Set<string>;
|
|
192
190
|
/** borrowed-mutable — the classify doctrine's probe installs (`.set`, only where the doctrine
|
|
193
191
|
* owns the seat). Same-object contract as above. */
|
|
194
|
-
reversibilityProbes:
|
|
192
|
+
reversibilityProbes: ReversibilityProbes;
|
|
195
193
|
/** borrowed-readonly — design/319 (A ticket): the run's reminder provenance mark (minted/adopted
|
|
196
194
|
* by the driver's adoption ladder); threaded into the hands band so the fs-side engine mints
|
|
197
195
|
* (the Read cyber/dedup/offset/empty reminders, the gh rate-limit hint) stamp the same mark the
|
|
@@ -201,10 +199,10 @@ export interface PrepareHandsReadFaceInput {
|
|
|
201
199
|
* band's Read/notebook/PDF trailer outlets bump keys on it at tool-execute time (the driver owns
|
|
202
200
|
* the object and folds it into result stats). */
|
|
203
201
|
reminderDisclosureCounts: import("../reminder-disclosure.js").ReminderDisclosureCounts;
|
|
204
|
-
/** design/381
|
|
202
|
+
/** borrowed-readonly — design/381: the first-touch history hook prepare built (present iff a fileHistoryStore is
|
|
205
203
|
* wired and the run mounts a real fs env); threaded to the write band's trackFileEdit seat. */
|
|
206
204
|
trackFileEdit?: import("../types.js").TrackFileEditHook;
|
|
207
|
-
/** borrowed — the mutation lane's LANDED observation seat (the accumulator behind
|
|
205
|
+
/** borrowed-readonly — the mutation lane's LANDED observation seat (the accumulator behind
|
|
208
206
|
* `TaskResult.editedFiles`); threaded to the write band's onFileEdited seat. Unlike
|
|
209
207
|
* `trackFileEdit` it does NOT depend on a wired history store: it observes what this run's hands
|
|
210
208
|
* did, so it is present on every run that mounts the band. */
|
|
@@ -7,7 +7,7 @@ import { resolveKey, sha256 } from "../../tools/fs/safety.js";
|
|
|
7
7
|
import { normalizeFileText } from "../../tools/fs/encoding.js";
|
|
8
8
|
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
9
9
|
import { deliverEngineNotice } from "../types.js";
|
|
10
|
-
import { rebaseWorkspacePath } from "./
|
|
10
|
+
import { rebaseWorkspacePath } from "./workspace-path.js";
|
|
11
11
|
const readFaceClampAnnouncedSinks = new WeakSet();
|
|
12
12
|
let readFaceClampConsoleAnnounced = false;
|
|
13
13
|
export function __resetReadFaceClampAnnouncement() {
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/390 §1.2 M3b — prepareTask's INHERITED-GATE phase, verbatim from the driver: the live/seed fold of the
|
|
3
|
+
* chain this run inherits (ancestor rules rev-monotonic per (session, principal), shellGate by max rank, the
|
|
4
|
+
* re-supplied parent constraints with their rebuilt denial trackers, the auto-mode intent, the org-admission
|
|
5
|
+
* freeze with its tighten-only intersection and the monotonic governed bit), the effective shellGate against the
|
|
6
|
+
* spec, the three cells later phases fill for the children's chain (own session rules, own admitted org scopes,
|
|
7
|
+
* own org verdict), the checkpoint-section closures the suspend serializer reads (face / org / F-012 stamps), the
|
|
8
|
+
* FROZEN ask and question seats (spec over deps), the two delegation refs the memory phase binds late, the ONE
|
|
9
|
+
* child-chain assembly `inheritedGateForChildren`, the caller-tool ctx enrichment `enrichSpecToolCtx` shared by
|
|
10
|
+
* the roster wrap and the revival spawner, the denial-limit stop seat, and the full-shell reachability predicate.
|
|
11
|
+
* The interface is the dependency list the segment had implicitly (design/238 R-1).
|
|
12
|
+
*
|
|
13
|
+
* SYNCHRONOUS FUNCTION, SYNCHRONOUS CALL: the stretch has no await (the one `await` in it sits inside the
|
|
14
|
+
* `hostSessionFork` closure a tool calls later), so the phase adds no yield between the run-refs phase before it
|
|
15
|
+
* and the caps phase after it (design/390 §1.5: a stretch with no await is extracted as a sync function).
|
|
16
|
+
*
|
|
17
|
+
* LATE-BOUND SEATS. The closures minted here run long after this phase returns — at spawn time, at tool-call
|
|
18
|
+
* time, at suspend time — and several of the facts they read are resolved by LATER stations of the same prepare:
|
|
19
|
+
* the caps phase's `runtimeCaps` / fork verdict / observers grant / armed classifier trio, the hands mount's
|
|
20
|
+
* resolved face and deny additions, the policy-chain station's hook record and timeout, the wiring station's hook
|
|
21
|
+
* env face, the prompt-assembly station's center adoption, the memory phase's engine session. In the driver those
|
|
22
|
+
* were `let`s and later `const`s the closures captured by name; here each enters as a GETTER on the Input, and
|
|
23
|
+
* every closure reads it exactly where — and only when — the driver's closure read the variable (a head binding
|
|
24
|
+
* where the driver read a variable inside one synchronous evaluation; an in-place call where the driver's read
|
|
25
|
+
* sat behind a short-circuit). Read-stability of the host handles for the call: {@link RunInternals}
|
|
26
|
+
* (`@contract prepare.deps-read-stable`).
|
|
27
|
+
*
|
|
28
|
+
* Every cell that leaves here as `borrowed-mutable` carries its writer table on the Result member (design/238 R-3).
|
|
29
|
+
*/
|
|
30
|
+
import type { AgentHarness, ExecutionEnv } from "../../internal/harness.js";
|
|
31
|
+
import type { SubagentWorktreeIsolation } from "../../agents/subagent.js";
|
|
32
|
+
import { forkGovernanceDenial } from "../../agents/subagent.js";
|
|
33
|
+
import type { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
34
|
+
import type { PromptEpochArtifact } from "../../prompt-assembly/artifact.js";
|
|
35
|
+
import type { ReadFace } from "../../tools/fs/index.js";
|
|
36
|
+
import type { AutoModeArmingRecipe } from "../auto-mode-arming.js";
|
|
37
|
+
import type { AutoModeDecider, AutoModeDenialTracker } from "../auto-mode.js";
|
|
38
|
+
import { type OnQuestion } from "../ask-question.js";
|
|
39
|
+
import { type HookEnvCapabilities, type Hooks } from "../hooks.js";
|
|
40
|
+
import type { LockedPreflight } from "../locked-config.js";
|
|
41
|
+
import type { OwnOrgAdmissionVerdict } from "../memory-admission.js";
|
|
42
|
+
import type { DelegationContentSafety } from "../memory-engine/delegation-provenance.js";
|
|
43
|
+
import type { SessionPermissionRules } from "../session-policy-store.js";
|
|
44
|
+
import type { SessionStore } from "../session.js";
|
|
45
|
+
import { type OnAsk } from "../tool-policy.js";
|
|
46
|
+
import type { RunnerDeps, RuntimeCaps, TaskEvent, TaskSpec, ToolExecuteContext } from "../types.js";
|
|
47
|
+
import type { ActiveSkillScope } from "./active-skill-scope.js";
|
|
48
|
+
import type { InheritedGate, Prepared, PrepareResume, RunInternals, ToolFaceSnapshot } from "./contracts.js";
|
|
49
|
+
import { type StopForDenialLimit } from "./denial-limit-arms.js";
|
|
50
|
+
export interface PrepareInheritedGateInput {
|
|
51
|
+
/** borrowed-readonly — the REBOUND spec. Read: `shellGate` (the own doctrine the chain fold tightens), `durableApproval`
|
|
52
|
+
* (the mandate tests + the children's copy), `onAsk`/`onQuestion` (the frozen seats), `handsReadOnly` / `interactiveTools`
|
|
53
|
+
* / `oneShot` / `clientContext` / `principal` / `additionalDirectories` / `additionalReadDirectories` / `envFacts` /
|
|
54
|
+
* `memoryPersistenceCapable` / `getApiKeyAndHeaders` / `checkpointStore` / `backgroundScope` / `enablePlanMode` (the ctx
|
|
55
|
+
* enrichment's trusted seats). Never mutated. */
|
|
56
|
+
spec: Pick<TaskSpec, "shellGate" | "durableApproval" | "onAsk" | "onQuestion" | "handsReadOnly" | "interactiveTools" | "oneShot" | "clientContext" | "principal" | "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "memoryPersistenceCapable" | "getApiKeyAndHeaders" | "checkpointStore" | "backgroundScope" | "enablePlanMode">;
|
|
57
|
+
/** borrowed-readonly — the deployment seats: `autoMode.denialLimit` (the rebuilt trackers' bounds), `memoryScopeAdmission` /
|
|
58
|
+
* `deploymentMemoryScopes` / `compliancePostureResolver` (the governed-provenance bit), `onError` (the screening-face crash
|
|
59
|
+
* lane), `onNotice` (the stop seat's notice), `executionEnv` (the hook-env identity predicate), `delegationEntryCaps` (resolved
|
|
60
|
+
* and validated once here), `rosterStore` / `onBackgroundChildEvent` (ctx seats), `onAsk` / `onQuestion` (the deps half of the
|
|
61
|
+
* frozen seats). */
|
|
62
|
+
deps: Pick<RunnerDeps, "autoMode" | "memoryScopeAdmission" | "deploymentMemoryScopes" | "compliancePostureResolver" | "onError" | "onNotice" | "executionEnv" | "delegationEntryCaps" | "rosterStore" | "onBackgroundChildEvent" | "onAsk" | "onQuestion">;
|
|
63
|
+
/** borrowed-readonly — the trusted spawn-side channel: `inheritedGate` (the LIVE half of the chain fold), `ownOrgAdmissionRef`
|
|
64
|
+
* (the same-session continuation's freeze), `delegationProvenance` (the F-012 stamp), and the identity / peer / notification
|
|
65
|
+
* seats the ctx enrichment forwards. Never mutated. */
|
|
66
|
+
internals: Pick<RunInternals, "inheritedGate" | "ownOrgAdmissionRef" | "delegationProvenance" | "memoryCaptureAncestors" | "parentTaskId" | "parentSessionId" | "rootSessionId" | "placementRoot" | "explicitAgentName" | "peerSelfRef" | "peerInboundChainRef" | "onTaskNotification" | "onSubagentSpawn" | "insideFork"> | undefined;
|
|
67
|
+
/** borrowed-readonly — the resume leg, or undefined on a fresh one: `seed.inheritedGate` is the CHECKPOINT half of the chain
|
|
68
|
+
* fold (the trust floor the live half may only tighten), `seed.readFace` the hands-less re-park's carried section. */
|
|
69
|
+
resume: Pick<PrepareResume, "seed"> | undefined;
|
|
70
|
+
/** borrowed-readonly — the session store's fork face: `fork` / `release` are bound into the ctx's `hostSessionFork` (present
|
|
71
|
+
* only when the store can fork). */
|
|
72
|
+
sessions: Pick<SessionStore, "fork" | "release">;
|
|
73
|
+
/** borrowed-readonly — the acquired session id (the crash lane's context, the ctx seat, the ancestor chain's own row). */
|
|
74
|
+
sessionId: string;
|
|
75
|
+
/** borrowed-readonly — the run's invocation id (the stop seat's notice names it). */
|
|
76
|
+
runId: string;
|
|
77
|
+
/** borrowed-readonly — the per-task identity (`ctx.taskId`, the same fallback the runner uses). */
|
|
78
|
+
hostTaskId: string;
|
|
79
|
+
/** borrowed-readonly — the SETTLED task root (`ctx.parentCwd`). */
|
|
80
|
+
taskRootFinal: string;
|
|
81
|
+
/** borrowed-readonly — the run's resolved env: the full-shell predicate's kind test and the hook-env identity value. */
|
|
82
|
+
executionEnv: ExecutionEnv;
|
|
83
|
+
/** borrowed-readonly — the per-task owned env when a factory minted one (the hook-env identity predicate reads presence). */
|
|
84
|
+
ownedEnv: ExecutionEnv | undefined;
|
|
85
|
+
/** borrowed-readonly — the frozen preflight; only `toolPolicy` (the RESOLVED caller policy the children's chain carries). */
|
|
86
|
+
lockedPreflight: Pick<LockedPreflight, "toolPolicy">;
|
|
87
|
+
/** borrowed-readonly — the frozen tool-face snapshot (the ctx forwards exclude / defer / alwaysLoad / restoreGated; the
|
|
88
|
+
* full-shell predicate reads the exclusion of Bash). */
|
|
89
|
+
toolFaceSnapshot: ToolFaceSnapshot;
|
|
90
|
+
/** borrowed-readonly — the resolved prompt profile (ctx seat). */
|
|
91
|
+
promptProfile: ToolExecuteContext["promptProfile"];
|
|
92
|
+
/** borrowed-readonly — the resolved interaction posture (ctx seat; absent ⇒ no key). */
|
|
93
|
+
resolvedInteractionPosture: ToolExecuteContext["interactionPosture"];
|
|
94
|
+
/** borrowed-readonly — the task's own auto-mode intent seat, screened and snapshotted before the first await. */
|
|
95
|
+
autoModeSeat: boolean;
|
|
96
|
+
/** borrowed-readonly — whether an execution env is wired at all (the full-shell predicate's first term). */
|
|
97
|
+
handsEnabled: boolean;
|
|
98
|
+
/** borrowed-readonly — the nested-usage sink the ctx forwards. */
|
|
99
|
+
reportUsage: ToolExecuteContext["reportUsage"];
|
|
100
|
+
/** borrowed-readonly — the harness seat (the ctx's model / thinking snapshots read it call-time). Not written here. */
|
|
101
|
+
harnessRef: {
|
|
102
|
+
current?: AgentHarness;
|
|
103
|
+
};
|
|
104
|
+
/** borrowed-readonly — the per-task skill scope (the ctx's `activeSkillScope` snapshot reads it call-time). Not written here. */
|
|
105
|
+
skillScope: ActiveSkillScope;
|
|
106
|
+
/** borrowed-readonly — the filtered display-forwarding wrapper (ctx seat; absent ⇒ no key). */
|
|
107
|
+
forwardEvent: ((e: TaskEvent) => void) | undefined;
|
|
108
|
+
/** borrowed-readonly — the retain ledger (ctx seat; absent ⇒ no key). */
|
|
109
|
+
subagentRetain: SubagentRetainLedger | undefined;
|
|
110
|
+
/** borrowed-readonly — the worktree-isolation helper (ctx seat; absent ⇒ no key). */
|
|
111
|
+
worktreeIsolation: SubagentWorktreeIsolation | undefined;
|
|
112
|
+
/** borrowed-readonly — the three run-ref primitives the ctx exposes (plan mode only under `enablePlanMode`). */
|
|
113
|
+
requestReview: (opts?: {
|
|
114
|
+
reason?: string;
|
|
115
|
+
}) => void;
|
|
116
|
+
/** borrowed-readonly — see `requestReview`. */
|
|
117
|
+
requestStopAfterTurn: () => void;
|
|
118
|
+
/** borrowed-readonly — see `requestReview`. */
|
|
119
|
+
enterPlanMode: () => void;
|
|
120
|
+
/** borrowed-readonly — the leg's reminder mark (ctx seat). */
|
|
121
|
+
reminderMark: string;
|
|
122
|
+
/** borrowed-readonly — the leg's disclosure counters (ctx seat; the outlets that bump them are not in this phase). */
|
|
123
|
+
reminderDisclosureCounts: Prepared["reminderDisclosureCounts"];
|
|
124
|
+
/** borrowed-readonly — the file-history fixed point the ctx threads to delegation tools (only when enabled). */
|
|
125
|
+
fileHistoryEnabled: boolean;
|
|
126
|
+
/** borrowed-readonly — see `fileHistoryEnabled`. */
|
|
127
|
+
historyScope: string;
|
|
128
|
+
/** borrowed-readonly — see `fileHistoryEnabled`. */
|
|
129
|
+
historyRoot: string;
|
|
130
|
+
/** borrowed-readonly — see `fileHistoryEnabled`. */
|
|
131
|
+
historyFs: string;
|
|
132
|
+
/** borrowed-readonly — the driver's composition of the run's abort (controller + harness), the stop seat's headless arm.
|
|
133
|
+
* Composed by the driver because the harness is built after this phase; the seat only ever fires at run time. */
|
|
134
|
+
abortRun: () => void;
|
|
135
|
+
/** borrowed-readonly — LATE-BOUND: the per-principal entitlements the caps phase resolves after this one; read only inside
|
|
136
|
+
* `inheritedGateForChildren` (the two mandate tests), at spawn time. */
|
|
137
|
+
runtimeCaps: () => RuntimeCaps | undefined;
|
|
138
|
+
/** borrowed-readonly — LATE-BOUND: the resolved hook record (`spec.hooks ?? deps.hooks`), read inside the chain assembly for
|
|
139
|
+
* this task's own screening face. */
|
|
140
|
+
hooks: () => Hooks | undefined;
|
|
141
|
+
/** borrowed-readonly — LATE-BOUND: whether the deployment declared its screening face observational (then it rides no entry). */
|
|
142
|
+
preToolUseObservational: () => boolean;
|
|
143
|
+
/** borrowed-readonly — LATE-BOUND: the validated per-invocation hook bound the screening-face entry's policy runs under. */
|
|
144
|
+
hookTimeoutMs: () => number;
|
|
145
|
+
/** borrowed-readonly — LATE-BOUND: the hook-env capability face the screening-face entry's policy resolves paths in. */
|
|
146
|
+
hookEnvFace: () => HookEnvCapabilities | undefined;
|
|
147
|
+
/** borrowed-readonly — LATE-BOUND: the armed classifier (undefined = not armed), read where the chain freezes it onto both
|
|
148
|
+
* entries and where the ctx exposes the spawn-review seat. */
|
|
149
|
+
autoModeDecider: () => AutoModeDecider | undefined;
|
|
150
|
+
/** borrowed-readonly — LATE-BOUND: the denial tracker built beside the decider; rides wherever the decider rides. */
|
|
151
|
+
autoModeDenialTracking: () => AutoModeDenialTracker | undefined;
|
|
152
|
+
/** borrowed-readonly — LATE-BOUND: the serializable arming recipe (persistArming opt-in only). */
|
|
153
|
+
autoModeArming: () => AutoModeArmingRecipe | undefined;
|
|
154
|
+
/** borrowed-readonly — LATE-BOUND: the fork-governance verdict (ctx `forkAccess`, present only when denied). */
|
|
155
|
+
agentForkDenial: () => ReturnType<typeof forkGovernanceDenial>;
|
|
156
|
+
/** borrowed-readonly — LATE-BOUND: the observers grant (ctx `observersAllowed`, present only when explicitly granted). */
|
|
157
|
+
observersActive: () => boolean;
|
|
158
|
+
/** borrowed-readonly — LATE-BOUND: the hands mount's resolved read face (undefined until/unless hands mount). */
|
|
159
|
+
resolvedReadFace: () => ReadFace | undefined;
|
|
160
|
+
/** borrowed-readonly — LATE-BOUND: the normalized deny additions in force (empty until the hands mount resolves them). */
|
|
161
|
+
readDenyAdditionsNormalized: () => ReadonlyArray<{
|
|
162
|
+
pattern: string;
|
|
163
|
+
caseSensitive: boolean;
|
|
164
|
+
}>;
|
|
165
|
+
/** borrowed-readonly — LATE-BOUND: the hands-less legs' resolved face (the carrier's second source). */
|
|
166
|
+
handsLessResolvedFace: () => ReadFace | undefined;
|
|
167
|
+
/** borrowed-readonly — LATE-BOUND: the adopted center artifact (ctx `centerArtifactDigest` / `centerSourceRevision`). */
|
|
168
|
+
centerAdoption: () => {
|
|
169
|
+
artifact: PromptEpochArtifact;
|
|
170
|
+
sourceRevision?: string;
|
|
171
|
+
} | undefined;
|
|
172
|
+
/** borrowed-readonly — LATE-BOUND: the memory-engine session (the ctx's capture-floor getters read it at THEIR call time). */
|
|
173
|
+
memoryEngineSession: () => Prepared["memoryEngineSession"];
|
|
174
|
+
}
|
|
175
|
+
export interface PrepareInheritedGateResult {
|
|
176
|
+
/** owned — the LIVE half of the inherited chain as supplied (`internals.inheritedGate`); the durable-gate notice reads it. */
|
|
177
|
+
liveInheritedGate: RunInternals["inheritedGate"];
|
|
178
|
+
/** owned — the CHECKPOINT half (`resume.seed.inheritedGate`); the suspend serializer re-reads its frozen chain. */
|
|
179
|
+
seedInheritedGate: PrepareResume["seed"]["inheritedGate"];
|
|
180
|
+
/** owned — the rev-monotonic fold of the two halves' ancestor rules (live replaces per (session, principal) only at ≥ rev). */
|
|
181
|
+
inheritedAncestorRules: InheritedGate["ancestorRules"];
|
|
182
|
+
/** owned — the max-rank fold of the two halves' shellGate doctrines (before the spec's own is applied). */
|
|
183
|
+
inheritedShellGate: InheritedGate["shellGate"];
|
|
184
|
+
/** owned — the live parent constraints with a fresh denial tracker attached per rebuilt decider. */
|
|
185
|
+
inheritedParentConstraints: NonNullable<InheritedGate["parentConstraints"]>[number][] | undefined;
|
|
186
|
+
/** owned — the auto-mode INTENT (own seat ∨ live chain ∨ checkpoint bit); the arming site judges the other two arms. */
|
|
187
|
+
autoModeIntent: boolean;
|
|
188
|
+
/** owned — the seed ∩ live admitted org scopes (one side absent ⇒ the other; both absent ⇒ undefined). */
|
|
189
|
+
inheritedAdmittedOrgScopes: readonly string[] | undefined;
|
|
190
|
+
/** owned — the prior own org verdict: checkpoint ∩ same-session ref (either alone stands; neither ⇒ undefined). */
|
|
191
|
+
priorOwnOrgVerdict: OwnOrgAdmissionVerdict | undefined;
|
|
192
|
+
/** owned — the monotonic governed-provenance bit for this leg. */
|
|
193
|
+
orgGovernedProvenance: boolean;
|
|
194
|
+
/** owned — the spec's own shellGate tightened by the inherited doctrine. */
|
|
195
|
+
effectiveShellGate: "off" | "classify" | "always";
|
|
196
|
+
/** borrowed-mutable — THIS task's own session-rule snapshot for its children's chain. Writers (R-3): the policy-chain
|
|
197
|
+
* station's session-policy read, once per leg, when a store is wired and the task carries its own sessionId. Read by
|
|
198
|
+
* `inheritedGateForChildren` at spawn time. */
|
|
199
|
+
ownSessionRulesRef: {
|
|
200
|
+
current?: {
|
|
201
|
+
sessionId: string;
|
|
202
|
+
principal?: string;
|
|
203
|
+
rev: number;
|
|
204
|
+
rules: SessionPermissionRules;
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
/** borrowed-mutable — THIS task's own frozen admitted org scopes for its children's chain. Writers: the memory phase's
|
|
208
|
+
* admission door, once per leg. Read by the chain assembly (always emitted, empty = no org plane). */
|
|
209
|
+
memoryAdmittedOrgScopesRef: {
|
|
210
|
+
current: readonly string[];
|
|
211
|
+
};
|
|
212
|
+
/** borrowed-mutable — the SESSION-freeze record for the suspend writer (present iff this leg adjudicated an org plane).
|
|
213
|
+
* Writers: the memory phase's admission door. Readers: the org stamp predicate here and the suspend serializer. */
|
|
214
|
+
ownOrgVerdictRef: {
|
|
215
|
+
current: OwnOrgAdmissionVerdict | undefined;
|
|
216
|
+
};
|
|
217
|
+
/** owned — the org-admission checkpoint stamp predicate (inherited set ∨ own verdict ∨ governed). */
|
|
218
|
+
orgAdmissionCheckpointState: () => boolean;
|
|
219
|
+
/** owned — the read-face checkpoint section builder (hands-less resume carries the seed; every other leg mints from the live
|
|
220
|
+
* resolution; undefined for the default posture). */
|
|
221
|
+
faceCheckpointSection: () => {
|
|
222
|
+
face: "open" | "roots";
|
|
223
|
+
denyEntries?: Array<{
|
|
224
|
+
pattern: string;
|
|
225
|
+
caseSensitive: boolean;
|
|
226
|
+
}>;
|
|
227
|
+
} | undefined;
|
|
228
|
+
/** owned — the face stamp predicate (`faceCheckpointSection() !== undefined`). */
|
|
229
|
+
faceCheckpointState: () => boolean;
|
|
230
|
+
/** owned — the F-012 stamp predicate (opaque constraints present ∨ seed frozen chain ∨ provenance-armed). */
|
|
231
|
+
f012CheckpointState: () => boolean;
|
|
232
|
+
/** owned — the FROZEN approver seat (spec over deps) every station of this leg and its children's chain resolve at. */
|
|
233
|
+
frozenOnAsk: OnAsk | undefined;
|
|
234
|
+
/** owned — the env the screening face sees through `ctx.env` (identity half of a chain entry's `hookEnv`); the policy-chain
|
|
235
|
+
* station's pass-through arm compares against it. */
|
|
236
|
+
hookEnvSource: unknown;
|
|
237
|
+
/** owned — the deployment lane for a screening face that crashes while screening a descendant's call (phase "hook"). */
|
|
238
|
+
notifyOwnHookCrash: (err: unknown) => void;
|
|
239
|
+
/** owned — the FROZEN question seat (spec over deps), the content-ask twin of `frozenOnAsk`. */
|
|
240
|
+
frozenOnQuestion: OnQuestion | undefined;
|
|
241
|
+
/** borrowed-mutable — the delegation runtime-provenance arming face. Writer: the memory-engine-session phase
|
|
242
|
+
* (prepareMemoryEngineSession), once per leg when it arms. Read lazily by delegation tools through the ctx. */
|
|
243
|
+
provenanceForChildrenRef: {
|
|
244
|
+
current?: DelegationContentSafety;
|
|
245
|
+
};
|
|
246
|
+
/** borrowed-mutable — the delegation-settlement coordinates. Writer: the memory-engine-session phase, once per leg when the
|
|
247
|
+
* mounted session carries a settlement seat. Read lazily by delegation tools through the ctx. */
|
|
248
|
+
delegationSettlementRef: {
|
|
249
|
+
current?: {
|
|
250
|
+
controlDir: string;
|
|
251
|
+
sessionId: string;
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
/** owned — chain assembly SINGLE SITE: upstream chain + this task's own contribution, called by delegation tools at spawn. */
|
|
255
|
+
inheritedGateForChildren: () => InheritedGate;
|
|
256
|
+
/** owned — the ONE carrier expression both delegation mounts consume (resolved face ?? hands-less face). */
|
|
257
|
+
carrierReadFace: () => ReadFace | undefined;
|
|
258
|
+
/** owned — the full shell's structural reachability from spec-time facts. */
|
|
259
|
+
fullShellReachable: boolean;
|
|
260
|
+
/** borrowed-mutable — the gate's typed stop seat (`Prepared.gateStopRef`). Writers: `stopForDenialLimit` only. */
|
|
261
|
+
gateStopRef: Prepared["gateStopRef"];
|
|
262
|
+
/** owned — the ONE closure that fills the stop seat (the denial-limit fallback's headless arm). */
|
|
263
|
+
stopForDenialLimit: StopForDenialLimit;
|
|
264
|
+
/** owned — the caller-tool ctx enrichment shared by the roster wrap and the revival spawner. */
|
|
265
|
+
enrichSpecToolCtx: (ctx: ToolExecuteContext) => ToolExecuteContext;
|
|
266
|
+
}
|
|
267
|
+
/** The M3b phase body — prepareTask's inherited-gate stretch, verbatim (see the module header). */
|
|
268
|
+
export declare function prepareInheritedGate(input: PrepareInheritedGateInput): PrepareInheritedGateResult;
|