@sema-agent/core 7.17.6 → 7.18.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 +165 -13
- package/dist/agents/send-message-tool.js +1 -0
- package/dist/agents/subagent.d.ts +1 -0
- package/dist/agents/subagent.js +5 -0
- package/dist/agents/teacher.js +1 -0
- package/dist/agents/verify.js +3 -0
- package/dist/brain/route-adjudicator.d.ts +18 -0
- package/dist/brain/route-adjudicator.js +16 -0
- package/dist/core/agent-definition.d.ts +10 -0
- package/dist/core/artifact-host.d.ts +41 -4
- package/dist/core/artifact-host.js +18 -2
- package/dist/core/auto-mode.d.ts +141 -45
- package/dist/core/auto-mode.js +109 -3
- package/dist/core/checkpoint-store.d.ts +16 -2
- package/dist/core/engine-notice.d.ts +47 -1
- package/dist/core/engine-notice.js +7 -0
- package/dist/core/gate-lanes.js +2 -1
- package/dist/core/gate-outcome.d.ts +17 -2
- package/dist/core/gate-outcome.js +16 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +8 -0
- package/dist/core/hook-seats.d.ts +66 -0
- package/dist/core/hook-seats.js +37 -0
- package/dist/core/runner/advertised-writable-dirs.d.ts +8 -3
- package/dist/core/runner/assemble-result.d.ts +2 -1
- package/dist/core/runner/assemble-result.js +1 -1
- package/dist/core/runner/classifier-ladder.d.ts +89 -0
- package/dist/core/runner/classifier-ladder.js +65 -0
- package/dist/core/runner/contracts.d.ts +69 -13
- package/dist/core/runner/decide-continuation.d.ts +1 -3
- package/dist/core/runner/decide-continuation.js +1 -7
- package/dist/core/runner/deferral-census.d.ts +52 -0
- package/dist/core/runner/deferral-census.js +44 -0
- package/dist/core/runner/derived-route-fallback.d.ts +8 -4
- package/dist/core/runner/derived-route-fallback.js +8 -3
- package/dist/core/runner/gate-exit.d.ts +12 -0
- package/dist/core/runner/gate-exit.js +6 -3
- package/dist/core/runner/prepare-artifact.d.ts +10 -2
- package/dist/core/runner/prepare-artifact.js +5 -4
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +30 -31
- package/dist/core/runner/prepare-config-doors.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.js +5 -3
- package/dist/core/runner/prepare-defer-classify.d.ts +13 -19
- package/dist/core/runner/prepare-defer-classify.js +8 -3
- package/dist/core/runner/prepare-gate-stations.d.ts +26 -0
- package/dist/core/runner/prepare-gate-stations.js +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +24 -7
- package/dist/core/runner/prepare-hands-readface.js +60 -24
- package/dist/core/runner/prepare-inherited-gate.d.ts +17 -4
- package/dist/core/runner/prepare-inherited-gate.js +10 -2
- package/dist/core/runner/prepare-lsp.d.ts +2 -2
- package/dist/core/runner/prepare-lsp.js +1 -1
- package/dist/core/runner/prepare-policy-chain.js +2 -0
- package/dist/core/runner/prepare-project-context.js +4 -2
- package/dist/core/runner/prepare-prompt-inputs.d.ts +4 -2
- package/dist/core/runner/prepare-prompt-inputs.js +4 -1
- package/dist/core/runner/prepare-run-refs.d.ts +9 -1
- package/dist/core/runner/prepare-run-refs.js +3 -2
- package/dist/core/runner/prepare-suspend-saga.d.ts +5 -0
- package/dist/core/runner/prepare-suspend-saga.js +5 -2
- package/dist/core/runner/prepare-task.js +18 -13
- package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +5 -0
- package/dist/core/runner/prepare-tool-disclosure-mount.js +10 -2
- package/dist/core/runner/prepare-turn-wiring.d.ts +8 -4
- package/dist/core/runner/prepare-turn-wiring.js +3 -2
- package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -5
- package/dist/core/runner/prepare-wiring-manifest.js +5 -2
- package/dist/core/runner/resume-checkpoint-screen.js +7 -0
- package/dist/core/runner/run-harness-handlers.js +4 -1
- package/dist/core/runner/run-identity-wiring.js +6 -2
- package/dist/core/runner/run-leg.d.ts +2 -0
- package/dist/core/runner/run-leg.js +35 -41
- package/dist/core/runner/run-notification-lane.js +55 -27
- package/dist/core/runner/run-settle-and-teardown.js +1 -0
- package/dist/core/runner/run-terminal-adoption.js +16 -13
- package/dist/core/runner/run-turn-boundary.js +3 -1
- package/dist/core/runner/runtask.d.ts +6 -5
- package/dist/core/runner/runtask.js +26 -14
- package/dist/core/runner/skill-base-dir.d.ts +54 -0
- package/dist/core/runner/skill-base-dir.js +42 -0
- package/dist/core/runner/synthetic-tools.d.ts +16 -19
- package/dist/core/runner/synthetic-tools.js +18 -10
- package/dist/core/runner/tool-defer-gate.d.ts +22 -9
- package/dist/core/runner/tool-defer-gate.js +15 -5
- package/dist/core/runner/tool-disclosure.d.ts +5 -0
- package/dist/core/runner/tool-disclosure.js +2 -0
- package/dist/core/runner/tool-progress-lane.d.ts +42 -0
- package/dist/core/runner/tool-progress-lane.js +61 -0
- package/dist/core/runner-deps.d.ts +48 -7
- package/dist/core/swappable-deps.d.ts +9 -7
- package/dist/core/swappable-deps.js +7 -3
- package/dist/core/task-event.d.ts +96 -29
- package/dist/core/task-notification.d.ts +142 -16
- package/dist/core/task-notification.js +106 -0
- package/dist/core/task-result.d.ts +9 -1
- package/dist/core/task-spec.d.ts +20 -3
- package/dist/core/tighten-task-spec.js +7 -5
- package/dist/core/tool-model-gate.d.ts +1 -1
- package/dist/core/tool-search-setting.d.ts +78 -0
- package/dist/core/tool-search-setting.js +90 -0
- package/dist/core/tool-spec.d.ts +8 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.js +1 -1
- package/dist/core/wiring-manifest.d.ts +46 -0
- package/dist/core/wiring-manifest.js +9 -1
- package/dist/engine/execution-env/node-execution-env.js +10 -4
- package/dist/engine/harness/agent-harness.d.ts +42 -0
- package/dist/engine/harness/agent-harness.js +61 -29
- package/dist/engine/loop/agent-loop.d.ts +68 -3
- package/dist/engine/loop/agent-loop.js +109 -16
- package/dist/index.d.ts +10 -5
- package/dist/index.js +9 -5
- package/dist/internal/harness.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +6 -1
- package/dist/orchestration/workflow-governance.d.ts +7 -1
- package/dist/orchestration/workflow-governance.js +9 -5
- package/dist/orchestration/workflow-primitives.d.ts +3 -0
- package/dist/orchestration/workflow-primitives.js +6 -1
- package/dist/orchestration/workflow-types.d.ts +48 -13
- package/dist/orchestration/workflow-types.js +1 -1
- package/dist/orchestration/workflow.js +45 -17
- package/dist/prompt-assembly/epoch.js +2 -0
- package/dist/prompt-assembly/packs/sema-default.js +2 -2
- package/dist/prompt-assembly/section-usage.d.ts +26 -0
- package/dist/prompt-assembly/section-usage.js +10 -0
- package/dist/prompt-assembly/types.d.ts +8 -6
- package/dist/prompts/default.d.ts +13 -0
- package/dist/prompts/default.js +16 -8
- package/dist/tools/artifact/artifact-text.d.ts +10 -1
- package/dist/tools/artifact/artifact-text.js +6 -3
- package/dist/tools/artifact/artifact-tool.d.ts +12 -2
- package/dist/tools/artifact/artifact-tool.js +203 -70
- package/dist/tools/artifact/conformance.d.ts +56 -0
- package/dist/tools/artifact/conformance.js +349 -0
- package/dist/tools/artifact/local-stub.js +1 -1
- package/dist/tools/artifact/reject-breaker.d.ts +28 -0
- package/dist/tools/artifact/reject-breaker.js +42 -0
- package/dist/tools/fs/bash-lexer.d.ts +132 -0
- package/dist/tools/fs/bash-lexer.js +563 -0
- package/dist/tools/fs/bash-program-position.d.ts +142 -0
- package/dist/tools/fs/bash-program-position.js +125 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +54 -16
- package/dist/tools/fs/bash-readonly-classifier.js +375 -530
- package/dist/tools/fs/containment-face.d.ts +89 -0
- package/dist/tools/fs/containment-face.js +81 -0
- package/dist/tools/fs/fs-bash.d.ts +46 -1
- package/dist/tools/fs/fs-bash.js +158 -22
- package/dist/tools/fs/fs-read.d.ts +1 -1
- package/dist/tools/fs/fs-search-tools.d.ts +3 -3
- package/dist/tools/fs/fs-write.d.ts +4 -3
- package/dist/tools/fs/fs-write.js +9 -9
- package/dist/tools/fs/index.d.ts +24 -5
- package/dist/tools/fs/index.js +18 -6
- package/dist/tools/fs/repo-map.d.ts +2 -2
- package/dist/tools/fs/safety.d.ts +3 -3
- package/dist/tools/fs/safety.js +4 -4
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +85 -9
- package/wire-changes/core@7.17.6.json +81 -0
- package/wire-changes/core@7.17.7.json +49 -0
- package/dist/tools/fs/read-face.d.ts +0 -68
- package/dist/tools/fs/read-face.js +0 -47
|
@@ -5,22 +5,20 @@ import { CROSS_SESSION_CLASSIFIER_RULE } from "../../agents/cross-session-envelo
|
|
|
5
5
|
import { createRunWorkflowTool } from "../../orchestration/run-workflow-tool.js";
|
|
6
6
|
import { isSelfOrchestrationActive } from "../../orchestration/workflow-script-runner.js";
|
|
7
7
|
import { resolveWorkflowSizeGuideline } from "../../orchestration/workflow-size-guideline.js";
|
|
8
|
-
import { thinkingOffExpressible } from "../../brain/reasoning.js";
|
|
9
8
|
import { autoModeArmingRecipeOf } from "../auto-mode-arming.js";
|
|
10
|
-
import { AUTO_MODE_CLASSIFIER_LOW_REASONING_BUDGET_TOKENS, AUTO_MODE_CLASSIFIER_MAX_TOKENS } from "../auto-mode-defaults.js";
|
|
11
9
|
import { buildAutoModePrompt, renderAutoModeAction, renderAutoModeWindow } from "../auto-mode-prompt.js";
|
|
12
|
-
import { createAutoModeDecider, createAutoModeDenialTracker } from "../auto-mode.js";
|
|
10
|
+
import { autoModeClassifierFallbackOf, autoModeRoundNotAsked, createAutoModeDecider, createAutoModeDenialTracker } from "../auto-mode.js";
|
|
13
11
|
import { checkpointStoreOfSeat } from "../checkpoint-seat.js";
|
|
14
12
|
import { COMPLIANCE_CAPABILITIES, WEB_FETCH_TOOL_NAME, resolveComplianceDenies } from "../compliance.js";
|
|
15
13
|
import { createPresentPlanTool, createEnterPlanModeTool } from "../present-plan-tool.js";
|
|
16
14
|
import { resolveTaskModel } from "../roles.js";
|
|
17
15
|
import { brainToRuntime } from "../runtime.js";
|
|
18
16
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
19
|
-
import { emitTrace } from "../trace.js";
|
|
20
17
|
import { defineTool, isDefineToolProduct, rebindDefineToolCtx } from "../tools.js";
|
|
21
18
|
const MOUNT_REMEDY = "author it as a plain-object ToolSpec (own `name` and `execute`), hand the defineTool product itself, or wrap a product through the supported wrapper form (a fresh object re-stamped with `stampDefineToolBrand` whose rebind re-wraps the rebound product)";
|
|
22
19
|
import { AUTO_MODE_DENY_SOURCES, isAutoModeDenySource } from "../runtime-caps.js";
|
|
23
20
|
import { derivedRouteFallsBack } from "./derived-route-fallback.js";
|
|
21
|
+
import { CLASSIFIER_LOW_SEAT, CLASSIFIER_OFF_SEAT, classifierLadderRungs, classifierRoundObserver, classifierRungSeat } from "./classifier-ladder.js";
|
|
24
22
|
import { REPORT_FINDINGS_TOOL_NAME, createReportBlockedTool, createReportFindingsTool } from "./synthetic-tools.js";
|
|
25
23
|
function classifierReplyText(reply) {
|
|
26
24
|
return reply.content
|
|
@@ -112,7 +110,7 @@ function autoModeArmReasonOf(intent, facePresent, caps, capsFaulted) {
|
|
|
112
110
|
return { armed: true, reason: "armed" };
|
|
113
111
|
}
|
|
114
112
|
export async function prepareCapsAndWorkflow(input) {
|
|
115
|
-
const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, carrierReadFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, autoModeIntent, peerLaneActive, peerSendMessageBuiltIn, runnerSelf } = input;
|
|
113
|
+
const { spec, deps, parentSpecSeat, checkpointSeat, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, carrierReadFace, carrierWriteFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, autoModeIntent, peerLaneActive, peerSendMessageBuiltIn, runnerSelf } = input;
|
|
116
114
|
const roster = new RosterBuilder(toolEffects);
|
|
117
115
|
for (const t of spec.tools ?? []) {
|
|
118
116
|
const mounted = mountCallerTool(t);
|
|
@@ -218,45 +216,45 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
218
216
|
catch {
|
|
219
217
|
classifierModel = model;
|
|
220
218
|
}
|
|
221
|
-
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId })) {
|
|
219
|
+
if (await derivedRouteFallsBack({ seat: "auto-mode-classifier", derived: classifierModel, primary: model, brain: deps.brain, getApiKeyAndHeaders: spec.getApiKeyAndHeaders, onNotice: deps.onNotice, sessionId, runId, onBrokenPairing: autoModeClassifierFallbackOf(am.classifierFallback) === "none" ? "refuse" : "fall_back" })) {
|
|
222
220
|
classifierModel = model;
|
|
223
221
|
}
|
|
224
222
|
const classifierLaneRule = peerLaneActive && peerSendMessageBuiltIn;
|
|
225
223
|
const classifierSystemPrompt = buildAutoModePrompt(classifierLaneRule ? { ...am, crossSessionMessagesRule: CROSS_SESSION_CLASSIFIER_RULE } : am);
|
|
226
224
|
const classifierRuntime = brainToRuntime(deps.brain);
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
const classifierSeat = thinkingOffExpressible(classifierModel) ? classifierOffSeat : classifierLowSeat;
|
|
225
|
+
const classifierRungs = classifierLadderRungs(am.classifierFallback, classifierModel, model);
|
|
226
|
+
const roundPrompt = new WeakMap();
|
|
230
227
|
autoModeDenialTracking = createAutoModeDenialTracker(am.denialLimit);
|
|
231
228
|
autoModeDecider = createAutoModeDecider({
|
|
232
229
|
...(am.timeoutMs !== undefined ? { timeoutMs: am.timeoutMs } : {}),
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
(
|
|
248
|
-
|
|
249
|
-
const
|
|
250
|
-
const
|
|
230
|
+
candidates: classifierRungs.map((m) => m.id),
|
|
231
|
+
onClassified: classifierRoundObserver({ tracer: deps.tracer, onNotice: deps.onNotice, taskId: hostTaskId, seatModelId: classifierModel.id, ...(sessionId !== undefined ? { sessionId } : {}), ...(runId !== undefined ? { runId } : {}) }),
|
|
232
|
+
classify: async (input, signal, rung) => {
|
|
233
|
+
const rungModel = rung !== undefined ? classifierRungs[rung.index] : undefined;
|
|
234
|
+
if (rung === undefined || rungModel === undefined) {
|
|
235
|
+
throw new Error(`the auto-mode classifier was asked at ladder position ${JSON.stringify(rung?.index)}, which this arming did not build`);
|
|
236
|
+
}
|
|
237
|
+
let build = rung.index > 0 ? roundPrompt.get(input) : undefined;
|
|
238
|
+
if (build === undefined) {
|
|
239
|
+
build = (async () => {
|
|
240
|
+
const ctx = await session.buildContext();
|
|
241
|
+
const known = ctx.messages.filter((m) => !isSyntheticApiErrorMessage(m) && (m.role === "user" || m.role === "assistant" || m.role === "toolResult"));
|
|
242
|
+
return renderAutoModeWindow(known, am.window) + renderAutoModeAction(input);
|
|
243
|
+
})();
|
|
244
|
+
roundPrompt.set(input, build);
|
|
245
|
+
}
|
|
246
|
+
const userPrompt = await build.catch((e) => { throw autoModeRoundNotAsked(e); });
|
|
247
|
+
const classifierAuth = await spec.getApiKeyAndHeaders?.(rungModel);
|
|
248
|
+
const request = (seat) => classifierRuntime.completeSimple(rungModel, { systemPrompt: classifierSystemPrompt, messages: [{ role: "user", content: userPrompt, timestamp: Date.now() }] }, {
|
|
251
249
|
signal,
|
|
252
250
|
...seat,
|
|
253
251
|
...(classifierAuth?.apiKey !== undefined ? { apiKey: classifierAuth.apiKey } : {}),
|
|
254
252
|
...(classifierAuth?.headers !== undefined ? { headers: classifierAuth.headers } : {}),
|
|
255
253
|
});
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
254
|
+
const rungSeat = classifierRungSeat(rungModel);
|
|
255
|
+
let response = await request(rungSeat);
|
|
256
|
+
if (rungSeat === CLASSIFIER_OFF_SEAT && classifierReplyEmptyAtCap(response))
|
|
257
|
+
response = await request(CLASSIFIER_LOW_SEAT);
|
|
260
258
|
return classifierReplyText(response);
|
|
261
259
|
},
|
|
262
260
|
});
|
|
@@ -325,6 +323,7 @@ export async function prepareCapsAndWorkflow(input) {
|
|
|
325
323
|
parentCwd: taskRootFinal,
|
|
326
324
|
parentThinking: () => childThinkingSeat(undefined, deploymentSubagentThinking(runnerSelf.agentCatalog?.roles), harnessRef.current?.getThinkingLevel() ?? thinking).thinking,
|
|
327
325
|
parentReadFace: () => carrierReadFace(),
|
|
326
|
+
parentWriteFace: () => carrierWriteFace(),
|
|
328
327
|
parentReadDenyPatterns: () => {
|
|
329
328
|
const readDenyAdditionsNormalized = input.readDenyAdditionsNormalized();
|
|
330
329
|
return readDenyAdditionsNormalized.length > 0 ? readDenyAdditionsNormalized : undefined;
|
|
@@ -115,7 +115,7 @@ export interface PrepareConfigDoorsInput {
|
|
|
115
115
|
/** borrowed-readonly — the caller's spec. NEVER mutated here: the per-task agents rebind returns a
|
|
116
116
|
* SHALLOW COPY on {@link PrepareConfigDoorsResult.spec} (only `tools` replaced). */
|
|
117
117
|
spec: TaskSpec;
|
|
118
|
-
/** borrowed-readonly — deployment seats. Read for:
|
|
118
|
+
/** borrowed-readonly — deployment seats. Read for: the two containment-face value screens, locked-config preflight,
|
|
119
119
|
* retention door, interaction-posture door (incl. `deps.onError` disclosure), usage windows,
|
|
120
120
|
* brain-call guardrail default, model/role maps. */
|
|
121
121
|
deps: RunnerDeps;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { resolveBrainCallGuardrailMs } from "../../brain/timeout.js";
|
|
2
|
-
import {
|
|
2
|
+
import { assertContainmentFaceValue } from "../../tools/fs/index.js";
|
|
3
3
|
import { MICRO_COMPACT_MACHINES } from "../context-edit.js";
|
|
4
4
|
import { assertNoRetiredRunnerDeps } from "./retired-runner-deps.js";
|
|
5
5
|
import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
@@ -196,8 +196,10 @@ export function prepareConfigDoors(input) {
|
|
|
196
196
|
throw e;
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
assertContainmentFaceValue(spec.readFace, "read", "spec");
|
|
200
|
+
assertContainmentFaceValue(deps.readFace, "read", "deps");
|
|
201
|
+
assertContainmentFaceValue(spec.writeFace, "write", "spec");
|
|
202
|
+
assertContainmentFaceValue(deps.writeFace, "write", "deps");
|
|
201
203
|
const memoryDelegationEvidenceRaw = deps.memoryDelegationEvidence;
|
|
202
204
|
if (memoryDelegationEvidenceRaw !== undefined && memoryDelegationEvidenceRaw !== "static-face" && memoryDelegationEvidenceRaw !== "attested-only") {
|
|
203
205
|
const evidence = memoryDelegationEvidenceRaw;
|
|
@@ -5,11 +5,10 @@ import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
|
5
5
|
import type { AnnounceOnceSink, ToolFaceSnapshot } from "./contracts.js";
|
|
6
6
|
import { RosterBuilder } from "../tool-roster.js";
|
|
7
7
|
export interface PrepareDeferClassifyInput {
|
|
8
|
-
/** borrowed-readonly — the REBOUND spec (`spec′`); only `tools` is read (the
|
|
9
|
-
* classifier judges: names for the full-schema filter, specs for the `defer` declarations). */
|
|
8
|
+
/** borrowed-readonly — the REBOUND spec (`spec′`); only `tools` is read (names for the full-schema filter, specs for the `defer` declarations). */
|
|
10
9
|
spec: Pick<TaskSpec, "tools" | "excludeAllTools">;
|
|
11
|
-
/** borrowed-readonly —
|
|
12
|
-
deps: Pick<RunnerDeps, "deferMode">;
|
|
10
|
+
/** borrowed-readonly — deps; `deferMode` (candidate widening) and `toolSearch` (rule ②'s gate) are the only seats read. */
|
|
11
|
+
deps: Pick<RunnerDeps, "deferMode" | "toolSearch">;
|
|
13
12
|
/** borrowed-mutable — the shared mount array (later refs alias it; in-place contract, never
|
|
14
13
|
* re-created). Mutated here, in order: `splice` of every excluded name; element REPLACEMENT with a
|
|
15
14
|
* shallow copy for the classic-profile description swap (the caller's ToolSpec object is never
|
|
@@ -17,21 +16,17 @@ export interface PrepareDeferClassifyInput {
|
|
|
17
16
|
* (element replacement with the wrapped object), the disclosure mount, the MCP refresh re-splice. Since
|
|
18
17
|
* Every one of those writes is a builder verb (`unmountWhere` / `replaceAt`). */
|
|
19
18
|
roster: RosterBuilder;
|
|
20
|
-
/** borrowed-readonly — the frozen task-start tool face: `exclude` (the valve), `defer` (operator
|
|
21
|
-
* defers, exact wire names), `alwaysLoad` (the inline pins). */
|
|
19
|
+
/** borrowed-readonly — the frozen task-start tool face: `exclude` (the valve), `defer` (operator defers, exact wire names), `alwaysLoad` (the pins). */
|
|
22
20
|
toolFaceSnapshot: Pick<ToolFaceSnapshot, "exclude" | "defer" | "alwaysLoad">;
|
|
23
|
-
/** borrowed-readonly — whether a real execution env is mounted (the full-shell invariant runs only
|
|
24
|
-
* where a shell could be on the roster). */
|
|
21
|
+
/** borrowed-readonly — whether a real execution env is mounted (the full-shell invariant runs only where a shell could be on the roster). */
|
|
25
22
|
handsEnabled: boolean;
|
|
26
|
-
/** borrowed-readonly — the spec-time precomputation the invariant checks the post-exclusion roster
|
|
27
|
-
* against: a mismatch is an engine bug, thrown. */
|
|
23
|
+
/** borrowed-readonly — the spec-time precomputation the invariant checks the post-exclusion roster against: a mismatch is an engine bug, thrown. */
|
|
28
24
|
fullShellReachable: boolean;
|
|
29
25
|
/** borrowed-readonly — the resolved prompt profile (`classic` swaps in `descriptionClassic`). */
|
|
30
26
|
promptProfile: "simple" | "classic";
|
|
31
27
|
/** borrowed-readonly — the resolved model (the deferral gate's threshold reads its context window). */
|
|
32
28
|
model: Model;
|
|
33
|
-
/** borrowed-readonly — the materialized MCP roster; only `tools` is read (protocol names
|
|
34
|
-
* remote-roster arm; `mcpAlwaysLoad` self-declarations, losing to an explicit operator defer). */
|
|
29
|
+
/** borrowed-readonly — the materialized MCP roster; only `tools` is read (protocol names; `mcpAlwaysLoad` self-declarations lose to an operator defer). */
|
|
35
30
|
mcp: Pick<MaterializedMcp, "tools">;
|
|
36
31
|
/** borrowed-readonly — the materialized A2A roster; only `tools` is read (protocol names). */
|
|
37
32
|
a2a: Pick<MaterializedA2a, "tools">;
|
|
@@ -39,15 +34,12 @@ export interface PrepareDeferClassifyInput {
|
|
|
39
34
|
sharedMemoryPairMounted: boolean;
|
|
40
35
|
/** borrowed-readonly — whether the engine-memory pair mounted (project-context phase). */
|
|
41
36
|
memoryEnginePairMounted: boolean;
|
|
42
|
-
/** borrowed-readonly — the memory block as the project-context phase left it
|
|
43
|
-
*
|
|
44
|
-
* {@link PrepareDeferClassifyResult.memoryBlock}; the input value itself is never mutated. */
|
|
37
|
+
/** borrowed-readonly — the memory block as the project-context phase left it; the engine pair's retraction strips the recall paragraph and returns the
|
|
38
|
+
* stripped value as {@link PrepareDeferClassifyResult.memoryBlock}. The input is never mutated. */
|
|
45
39
|
memoryBlock: string | undefined;
|
|
46
|
-
/** borrowed-readonly — the exact recall-discipline segment the memory phase composed (the strip
|
|
47
|
-
* removes THIS string, never a re-composition). */
|
|
40
|
+
/** borrowed-readonly — the exact recall-discipline segment the memory phase composed (the strip removes THIS string, never a re-composition). */
|
|
48
41
|
memoryRecallSegment: string | undefined;
|
|
49
|
-
/** borrowed-readonly — the once-per-session ledger's deduplicated operator sink (a retraction is
|
|
50
|
-
* session-level fact, announced once). */
|
|
42
|
+
/** borrowed-readonly — the once-per-session ledger's deduplicated operator sink (a retraction is announced once per session). */
|
|
51
43
|
onceLedger: AnnounceOnceSink;
|
|
52
44
|
/** borrowed-readonly — the acquired session's id (operator-line context). */
|
|
53
45
|
sessionId: string;
|
|
@@ -60,6 +52,8 @@ export interface PrepareDeferClassifyResult {
|
|
|
60
52
|
/** owned — the memory block after the engine pair's retraction strip (unchanged when no retraction
|
|
61
53
|
* ran). The driver binds it under the name the prompt assembly reads. */
|
|
62
54
|
memoryBlock: string | undefined;
|
|
55
|
+
/** owned — the gate policy this classification was MEASURED under; the census reports it from here, never a second reading of the seat. */
|
|
56
|
+
toolSearch: import("../tool-search-setting.js").ResolvedToolSearch;
|
|
63
57
|
}
|
|
64
58
|
/** The M11 phase body — prepareTask's tool-face fold + deferred classification, verbatim (module header). */
|
|
65
59
|
export declare function prepareDeferClassify(input: PrepareDeferClassifyInput): PrepareDeferClassifyResult;
|
|
@@ -4,8 +4,9 @@ import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
|
4
4
|
import { MEMORY_ENGINE_TOOL_NAMES } from "../memory-engine/tools.js";
|
|
5
5
|
import { SHARED_MEMORY_TOOL_NAMES } from "../shared-memory/types.js";
|
|
6
6
|
import { protocolOf } from "../protocol-table.js";
|
|
7
|
-
import {
|
|
7
|
+
import { classifyDeferredWithGate } from "./tool-defer-gate.js";
|
|
8
8
|
import { TOOL_SEARCH_NAME } from "./tool-disclosure.js";
|
|
9
|
+
import { resolveToolSearch, toolSearchSettingOf } from "../tool-search-setting.js";
|
|
9
10
|
import { RosterBuilder } from "../tool-roster.js";
|
|
10
11
|
function explicitlyDeferredMemoryTrio(mounted, roster, callerDeferNames) {
|
|
11
12
|
return mounted ? MEMORY_ENGINE_TOOL_NAMES.filter((n) => roster.some((t) => t.name === n) && (callerDeferNames ?? []).includes(n)) : [];
|
|
@@ -45,13 +46,16 @@ export function prepareDeferClassify(input) {
|
|
|
45
46
|
const mcpAlwaysLoadNames = mcp.tools
|
|
46
47
|
.filter((t) => t.mcpAlwaysLoad === true && !(toolFaceSnapshot.defer ?? []).includes(t.name))
|
|
47
48
|
.map((t) => t.name);
|
|
49
|
+
const resolvedToolSearch = resolveToolSearch(deps.toolSearch);
|
|
50
|
+
const toolSearchSeat = toolSearchSettingOf(resolvedToolSearch);
|
|
48
51
|
const classifyDeferredOverFace = (face, builtinDeferNames) => {
|
|
49
52
|
const mounted = new Set(face.map((t) => t.name));
|
|
50
|
-
const
|
|
53
|
+
const classified = classifyDeferredWithGate({
|
|
51
54
|
specs: spec.tools ?? [],
|
|
52
55
|
protocolToolNames,
|
|
53
56
|
fullTools: face,
|
|
54
57
|
deferMode: deps.deferMode,
|
|
58
|
+
toolSearch: toolSearchSeat,
|
|
55
59
|
model,
|
|
56
60
|
callerDeferNames: (toolFaceSnapshot.defer ?? []).filter((n) => mounted.has(n)),
|
|
57
61
|
builtinDeferNames: builtinDeferNames.filter((n) => mounted.has(n)),
|
|
@@ -61,6 +65,7 @@ export function prepareDeferClassify(input) {
|
|
|
61
65
|
...mcpAlwaysLoadNames,
|
|
62
66
|
],
|
|
63
67
|
});
|
|
68
|
+
const deferredSet = classified.deferred;
|
|
64
69
|
for (const n of [...deferredSet])
|
|
65
70
|
if (!mounted.has(n))
|
|
66
71
|
deferredSet.delete(n);
|
|
@@ -105,5 +110,5 @@ export function prepareDeferClassify(input) {
|
|
|
105
110
|
else {
|
|
106
111
|
deferred = classifyDeferredOverFace(tools, []);
|
|
107
112
|
}
|
|
108
|
-
return { deferred, memoryBlock };
|
|
113
|
+
return { deferred, memoryBlock, toolSearch: resolvedToolSearch };
|
|
109
114
|
}
|
|
@@ -28,12 +28,38 @@ import type { AutoModeDecider, AutoModeDenialTracker } from "../auto-mode.js";
|
|
|
28
28
|
import { type ComplianceCapability } from "../compliance.js";
|
|
29
29
|
import { type HookEnvCapabilities, type HookInvocationIdentity, type Hooks } from "../hooks.js";
|
|
30
30
|
import type { ToolPolicy } from "../tool-policy.js";
|
|
31
|
+
import { type GateOutcome } from "../gate-outcome.js";
|
|
31
32
|
import type { RunnerDeps, TaskSpec, ToolEffect } from "../types.js";
|
|
32
33
|
import type { CwdRef } from "../../tools/fs/fs-shared.js";
|
|
33
34
|
import type { AskLane, IrreversibilityTier, ParkAsk, Prepared, ReversibilityProbes } from "./contracts.js";
|
|
34
35
|
import type { StopForDenialLimit } from "./denial-limit-arms.js";
|
|
35
36
|
import type { PermissionRuleLanes } from "./permission-rule-lanes.js";
|
|
36
37
|
import { type ToolRosterDeltaSeat } from "../tool-roster.js";
|
|
38
|
+
/**
|
|
39
|
+
* The parent-thread human-rejection boundary — judged ONCE here, from the pass's own record (CC parity:
|
|
40
|
+
* the reference CLI's reject path aborts exactly when there is no feedback and the run is not a
|
|
41
|
+
* subagent; a rejection WITH the decider's note, and every delegated child — forks included — keep the
|
|
42
|
+
* continue / adapt-or-report posture): the final block IS a person's refusal (`deniedBy: ask_resolution`
|
|
43
|
+
* and a `human_refused` settlement — not a later fold layer's deny that merely followed a human
|
|
44
|
+
* interaction), the refusal carried NO note (`settlement.note` absent — a fact composed at the refusal,
|
|
45
|
+
* never re-derived from message text), and the run is not a delegated child (the raw trusted delegation
|
|
46
|
+
* facet — the same fact that selects the refusal text's posture, so the boundary and the words the model
|
|
47
|
+
* was told always agree). Policy/hook/classifier denies and window/abort settlements never satisfy it.
|
|
48
|
+
*
|
|
49
|
+
* Returns the loop directive that settles every never-started same-batch sibling: honest
|
|
50
|
+
* known-not-executed wording plus the machine mark (`error`/`code` twin — the wire errorCode lift
|
|
51
|
+
* reads `details.code`; `details.error` is the in-band mark result consumers grep) naming the
|
|
52
|
+
* rejected call. `undefined` = no boundary (the block stands alone, current behavior).
|
|
53
|
+
*/
|
|
54
|
+
export declare function maybeHumanRejectionHalt(input: {
|
|
55
|
+
gate: GateOutcome | undefined;
|
|
56
|
+
isDelegatedChild: boolean;
|
|
57
|
+
toolName: string;
|
|
58
|
+
toolCallId: string;
|
|
59
|
+
}): {
|
|
60
|
+
reason: string;
|
|
61
|
+
details: Record<string, unknown>;
|
|
62
|
+
} | undefined;
|
|
37
63
|
export interface PrepareGateStationsInput {
|
|
38
64
|
/** borrowed-readonly — the in-stream ask lane, or undefined when the gate machinery is inactive (then no `tool_call`
|
|
39
65
|
* station is built). Read: `adjudicate`, `resolveAskBound`, `notifyPermissionDenied`, `notifyHookError`. */
|
|
@@ -23,7 +23,7 @@ function screenGateResult(result) {
|
|
|
23
23
|
}
|
|
24
24
|
return defects.length > 0 ? { defects } : { gate, defects };
|
|
25
25
|
}
|
|
26
|
-
function maybeHumanRejectionHalt(input) {
|
|
26
|
+
export function maybeHumanRejectionHalt(input) {
|
|
27
27
|
const d = input.gate?.disposition;
|
|
28
28
|
const s = input.gate?.settlement;
|
|
29
29
|
const bare = d?.kind === "denied" && d.deniedBy === "ask_resolution" && s?.kind === "human_refused" && s.note === undefined;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type BeforeWriteHook, type CwdRef, type ReadDenyMatcher, type
|
|
1
|
+
import { type BeforeWriteHook, type CwdRef, type ReadDenyMatcher, type ContainmentFace } from "../../tools/fs/index.js";
|
|
2
2
|
import { type ReadFileState } from "../../tools/fs/safety.js";
|
|
3
3
|
import type { RunnerDeps, ShellGateDoctrine, TaskSpec } from "../types.js";
|
|
4
4
|
import type { Model } from "../../internal/llm.js";
|
|
5
|
-
import type { AgentTool, ExecutionEnv, WorkspaceState } from "../../internal/harness.js";
|
|
5
|
+
import type { AgentHarness, AgentTool, ExecutionEnv, WorkspaceState } from "../../internal/harness.js";
|
|
6
6
|
import type { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
|
|
7
7
|
import type { StoredSession } from "../session.js";
|
|
8
|
-
import type { IrreversibilityTier, PrepareResume, ReversibilityProbes, RunInternals, ToolFaceSnapshot } from "./contracts.js";
|
|
8
|
+
import type { IrreversibilityTier, PrepareResume, ReversibilityProbes, RunInternals, ToolFaceSnapshot, ToolProgressLane } from "./contracts.js";
|
|
9
9
|
import { RosterBuilder } from "../tool-roster.js";
|
|
10
10
|
/** Test seam (mirrors `__resetMalformedNoticeSeatAnnouncement`): never called by production code.
|
|
11
11
|
* Deliberately asymmetric — it resets only the console latch: the WeakSet arm needs no seam
|
|
@@ -145,16 +145,26 @@ export interface PrepareHandsReadFaceInput {
|
|
|
145
145
|
model: Model;
|
|
146
146
|
/** borrowed-readonly — the task-spec seats this phase reads, as a Pick over the SAME spec object
|
|
147
147
|
* (R-4). `tools` feeds only the band shadow check; `envFacts` only the advertised scratchpad. */
|
|
148
|
-
spec: Pick<TaskSpec, "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "handsReadOnly" | "readDenyPatterns" | "readFace" | "oneShot" | "resumeAt" | "sessionId" | "tools">;
|
|
148
|
+
spec: Pick<TaskSpec, "additionalDirectories" | "additionalReadDirectories" | "envFacts" | "handsReadOnly" | "readDenyPatterns" | "readFace" | "writeFace" | "oneShot" | "resumeAt" | "sessionId" | "tools">;
|
|
149
149
|
/** borrowed-readonly — the deployment seats this phase reads, as a Pick over the SAME deps
|
|
150
150
|
* object (R-4: `deps.onError?.()` keeps its receiver; a new deps read must widen this Pick).
|
|
151
151
|
* `readDenyBuiltinTiers`/`readDenyBuiltinExclude` are SNAPSHOTTED before the first await that
|
|
152
152
|
* precedes the toolkit compile (the caller retains these arrays by reference). */
|
|
153
|
-
deps: Pick<RunnerDeps, "onError" | "onNotice" | "tracer" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "readFace" | "permissionRuleStore" | "hands">;
|
|
153
|
+
deps: Pick<RunnerDeps, "onError" | "onNotice" | "tracer" | "readDenyPatterns" | "readDenyBuiltinTiers" | "readDenyBuiltinExclude" | "readFace" | "writeFace" | "permissionRuleStore" | "hands">;
|
|
154
154
|
/** borrowed-readonly — the trusted spawn-side seats the band forwards: the finished-command
|
|
155
155
|
* notification lane, the mid-flight detach hub, and the Runner's per-session
|
|
156
156
|
* read-state seats (absent on a standalone prepare ⇒ the transcript-replay rung covers alone). */
|
|
157
157
|
internals: Pick<RunInternals, "onTaskNotification" | "detachHub" | "sessionReadStates"> | undefined;
|
|
158
|
+
/** borrowed-mutable — the harness seat, read LIVE by the band's queued-human-input predicate (the shell's
|
|
159
|
+
* auto-backgrounding leg asks it mid-command). Late-bound: the band is built here, the harness later. */
|
|
160
|
+
harnessRef: {
|
|
161
|
+
current?: AgentHarness;
|
|
162
|
+
};
|
|
163
|
+
/** borrowed-mutable — the tool-progress lane's cell, read LIVE by the band's progress seat; same
|
|
164
|
+
* late-binding contract as {@link harnessRef}. Unbound ⇒ every tick through it is a silent no-op. */
|
|
165
|
+
toolProgressRef: {
|
|
166
|
+
current?: ToolProgressLane;
|
|
167
|
+
};
|
|
158
168
|
/** borrowed-readonly — ABSOLUTE paths this prepare's restore wrote, deleted,
|
|
159
169
|
* or failed to write. Every read-state seed above describes the PRE-restore tree, so these keys are
|
|
160
170
|
* dropped from the map: the engine replaced those bytes itself, and a surviving entry makes the
|
|
@@ -255,7 +265,14 @@ export interface PrepareHandsReadFaceResult {
|
|
|
255
265
|
/** write-back (D-3 hold) — the run's RESOLVED read face where hands mount; undefined ⇔ no hands
|
|
256
266
|
* (the hands-less value lives in `handsLessResolvedFace`). The driver assigns this onto its
|
|
257
267
|
* outer `let` for the call-time closures (ctx enrichment / checkpoint mint / envFacts). */
|
|
258
|
-
resolvedReadFace:
|
|
268
|
+
resolvedReadFace: ContainmentFace | undefined;
|
|
269
|
+
/** write-back — the run's RESOLVED WRITE face where hands mount; undefined ⇔ no hands (the
|
|
270
|
+
* hands-less value lives in `handsLessResolvedWriteFace`). The read seat's twin, resolved by the
|
|
271
|
+
* SAME order on its OWN seats — the two never read each other. */
|
|
272
|
+
resolvedWriteFace: ContainmentFace | undefined;
|
|
273
|
+
/** write-back — the hands-LESS legs' resolved WRITE face (the posture is a property of the RUN,
|
|
274
|
+
* not the mount): the delegation carriers and the checkpoint mint need it on every leg. */
|
|
275
|
+
handsLessResolvedWriteFace: ContainmentFace | undefined;
|
|
259
276
|
/** write-back (D-3 hold) — the NORMALIZED deny-set additions in force (deployment ∪ task ∪
|
|
260
277
|
* resume-seed; zero-builtin compile — the persisted/carrier form, never the judged union's
|
|
261
278
|
* post-dedup remainder). Driver assigns onto its outer `let`. */
|
|
@@ -265,7 +282,7 @@ export interface PrepareHandsReadFaceResult {
|
|
|
265
282
|
}>;
|
|
266
283
|
/** write-back (D-3 hold) — the hands-LESS legs' resolved face (the read posture is a
|
|
267
284
|
* property of the RUN, not the mount). Driver assigns onto its outer `let`. */
|
|
268
|
-
handsLessResolvedFace:
|
|
285
|
+
handsLessResolvedFace: ContainmentFace | undefined;
|
|
269
286
|
/** owned — the canonicalized write-capable extra roots (additionalDirectories + the advertised
|
|
270
287
|
* scratchpad), deduped; the driver's envFacts advertisement and attachment readers share the
|
|
271
288
|
* ARRAY identity. Settled here (no mutation after return). */
|
|
@@ -3,17 +3,31 @@ import { StubExecutionEnv } from "../stub-env.js";
|
|
|
3
3
|
import { hasBackgroundShell } from "../background-shell.js";
|
|
4
4
|
import { boundaryIsTheSandbox } from "../remote-env.js";
|
|
5
5
|
import { defaultTaskRegistry } from "../task-registry.js";
|
|
6
|
-
import { bashReadBoundaryProbe, bashReversibilityProbe, compileReadDeny, createHandsToolkit,
|
|
6
|
+
import { bashReadBoundaryProbe, bashReversibilityProbe, compileReadDeny, createHandsToolkit, deploymentFaceClampNotice, pdfModelCapabilitiesOf, resolveReadDenyBuiltins, inheritSessionReadFileState, resolveContainmentFace, seedReadFileStateFromContext, seedReadFileStateFromTranscript, } from "../../tools/fs/index.js";
|
|
7
7
|
import { resolveKey, sha256 } from "../../tools/fs/safety.js";
|
|
8
8
|
import { normalizeFileText } from "../../tools/fs/encoding.js";
|
|
9
9
|
import { wholeFileRecordsFromTranscript } from "./session-file-state-replay.js";
|
|
10
10
|
import { deliverEngineNotice } from "../types.js";
|
|
11
11
|
import { rebaseWorkspacePath } from "./workspace-path.js";
|
|
12
12
|
import { RosterBuilder } from "../tool-roster.js";
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const faceClampAnnouncedSinks = { read: new WeakSet(), write: new WeakSet() };
|
|
14
|
+
const faceClampConsoleAnnounced = { read: false, write: false };
|
|
15
|
+
function announceDeploymentFaceClamp(kind, sink) {
|
|
16
|
+
if (typeof sink === "function") {
|
|
17
|
+
if (faceClampAnnouncedSinks[kind].has(sink))
|
|
18
|
+
return;
|
|
19
|
+
faceClampAnnouncedSinks[kind].add(sink);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
if (faceClampConsoleAnnounced[kind])
|
|
23
|
+
return;
|
|
24
|
+
faceClampConsoleAnnounced[kind] = true;
|
|
25
|
+
}
|
|
26
|
+
deliverEngineNotice(sink, deploymentFaceClampNotice(kind));
|
|
27
|
+
}
|
|
15
28
|
export function __resetReadFaceClampAnnouncement() {
|
|
16
|
-
|
|
29
|
+
faceClampConsoleAnnounced.read = false;
|
|
30
|
+
faceClampConsoleAnnounced.write = false;
|
|
17
31
|
}
|
|
18
32
|
export class SessionReadFileStates {
|
|
19
33
|
seats = new Map();
|
|
@@ -82,17 +96,29 @@ export function resolveHandsLessReadFace(input) {
|
|
|
82
96
|
assertStringArraySeat(deps.readDenyPatterns, "RunnerDeps.readDenyPatterns", "compiler-owned");
|
|
83
97
|
assertStringArraySeat(spec.readDenyPatterns, "TaskSpec.readDenyPatterns", "compiler-owned");
|
|
84
98
|
let handsLessResolvedFace;
|
|
99
|
+
let handsLessResolvedWriteFace;
|
|
85
100
|
let readDenyAdditionsNormalized = [];
|
|
86
101
|
{
|
|
87
|
-
const liveFace =
|
|
88
|
-
|
|
89
|
-
|
|
102
|
+
const liveFace = resolveContainmentFace({
|
|
103
|
+
kind: "read",
|
|
104
|
+
specFace: spec.readFace,
|
|
105
|
+
depsFace: deps.readFace,
|
|
90
106
|
readOnlyMount: spec.handsReadOnly === true,
|
|
91
107
|
orgGoverned: deps.permissionRuleStore?.partitions.org === true,
|
|
92
108
|
fullShellReachable,
|
|
93
109
|
});
|
|
94
110
|
const seed = resume?.seed.readFace;
|
|
95
111
|
handsLessResolvedFace = resume !== undefined && (seed === undefined || seed.face === "roots") ? "roots" : liveFace;
|
|
112
|
+
const liveWriteFace = resolveContainmentFace({
|
|
113
|
+
kind: "write",
|
|
114
|
+
specFace: spec.writeFace,
|
|
115
|
+
depsFace: deps.writeFace,
|
|
116
|
+
readOnlyMount: spec.handsReadOnly === true,
|
|
117
|
+
orgGoverned: deps.permissionRuleStore?.partitions.org === true,
|
|
118
|
+
fullShellReachable,
|
|
119
|
+
});
|
|
120
|
+
const seedWrite = resume?.seed.writeFace;
|
|
121
|
+
handsLessResolvedWriteFace = resume !== undefined && (seedWrite === undefined || seedWrite.face === "roots") ? "roots" : liveWriteFace;
|
|
96
122
|
const denyAdditions = [...(deps.readDenyPatterns ?? []), ...(spec.readDenyPatterns ?? []), ...(seed?.denyEntries ?? [])];
|
|
97
123
|
resolveReadDenyBuiltins({
|
|
98
124
|
...(deps.readDenyBuiltinTiers !== undefined ? { tiers: deps.readDenyBuiltinTiers } : {}),
|
|
@@ -111,8 +137,10 @@ export function resolveHandsLessReadFace(input) {
|
|
|
111
137
|
rebaseWsPath: (p) => p,
|
|
112
138
|
backgroundTaskToolsActive: false,
|
|
113
139
|
resolvedReadFace: undefined,
|
|
140
|
+
resolvedWriteFace: undefined,
|
|
114
141
|
readDenyAdditionsNormalized,
|
|
115
142
|
handsLessResolvedFace,
|
|
143
|
+
handsLessResolvedWriteFace,
|
|
116
144
|
additionalRootsCanonical: [],
|
|
117
145
|
additionalReadRootsCanonical: [],
|
|
118
146
|
attachmentRootCanonical: undefined,
|
|
@@ -138,8 +166,10 @@ export async function prepareHandsMount(input) {
|
|
|
138
166
|
let rebaseWsPath = (p) => p;
|
|
139
167
|
let backgroundTaskToolsActive = false;
|
|
140
168
|
let resolvedReadFace;
|
|
169
|
+
let resolvedWriteFace;
|
|
141
170
|
let readDenyAdditionsNormalized = [];
|
|
142
171
|
let handsLessResolvedFace;
|
|
172
|
+
const handsLessResolvedWriteFace = undefined;
|
|
143
173
|
const shellGatedTools = new Set();
|
|
144
174
|
const additionalRootsCanonical = [];
|
|
145
175
|
const additionalReadRootsCanonical = [];
|
|
@@ -218,30 +248,31 @@ export async function prepareHandsMount(input) {
|
|
|
218
248
|
};
|
|
219
249
|
readDenyMatcher = compileReadDeny(readDenyAdditions, "readDenyPatterns", readDenyBuiltinCfg);
|
|
220
250
|
readDenyAdditionsNormalized = compileReadDeny(readDenyAdditions, "readDenyPatterns", { tiers: [] }).entries;
|
|
221
|
-
let liveReadFace =
|
|
222
|
-
|
|
223
|
-
|
|
251
|
+
let liveReadFace = resolveContainmentFace({
|
|
252
|
+
kind: "read",
|
|
253
|
+
specFace: spec.readFace,
|
|
254
|
+
depsFace: deps.readFace,
|
|
224
255
|
readOnlyMount: handsReadOnly,
|
|
225
256
|
orgGoverned: deps.permissionRuleStore?.partitions.org === true,
|
|
226
257
|
fullShellReachable,
|
|
227
|
-
onDeploymentClamp: () =>
|
|
228
|
-
const sink = deps.onNotice;
|
|
229
|
-
if (typeof sink === "function") {
|
|
230
|
-
if (readFaceClampAnnouncedSinks.has(sink))
|
|
231
|
-
return;
|
|
232
|
-
readFaceClampAnnouncedSinks.add(sink);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
if (readFaceClampConsoleAnnounced)
|
|
236
|
-
return;
|
|
237
|
-
readFaceClampConsoleAnnounced = true;
|
|
238
|
-
}
|
|
239
|
-
deliverEngineNotice(sink, deploymentReadFaceClampNotice());
|
|
240
|
-
},
|
|
258
|
+
onDeploymentClamp: () => announceDeploymentFaceClamp("read", deps.onNotice),
|
|
241
259
|
});
|
|
242
260
|
if (resume !== undefined && (seedReadFaceSection === undefined || seedReadFaceSection.face === "roots"))
|
|
243
261
|
liveReadFace = "roots";
|
|
244
262
|
resolvedReadFace = liveReadFace;
|
|
263
|
+
let liveWriteFace = resolveContainmentFace({
|
|
264
|
+
kind: "write",
|
|
265
|
+
specFace: spec.writeFace,
|
|
266
|
+
depsFace: deps.writeFace,
|
|
267
|
+
readOnlyMount: handsReadOnly,
|
|
268
|
+
orgGoverned: deps.permissionRuleStore?.partitions.org === true,
|
|
269
|
+
fullShellReachable,
|
|
270
|
+
onDeploymentClamp: () => announceDeploymentFaceClamp("write", deps.onNotice),
|
|
271
|
+
});
|
|
272
|
+
const seedWriteFaceSection = resume?.seed.writeFace;
|
|
273
|
+
if (resume !== undefined && (seedWriteFaceSection === undefined || seedWriteFaceSection.face === "roots"))
|
|
274
|
+
liveWriteFace = "roots";
|
|
275
|
+
resolvedWriteFace = liveWriteFace;
|
|
245
276
|
const sessionSeats = input.internals?.sessionReadStates;
|
|
246
277
|
let seatLeafId;
|
|
247
278
|
try {
|
|
@@ -308,6 +339,7 @@ export async function prepareHandsMount(input) {
|
|
|
308
339
|
...(readDenyBuiltinCfg.tiers !== undefined ? { readDenyBuiltinTiers: readDenyBuiltinCfg.tiers } : {}),
|
|
309
340
|
...(readDenyBuiltinCfg.exclude !== undefined ? { readDenyBuiltinExclude: readDenyBuiltinCfg.exclude } : {}),
|
|
310
341
|
readFace: liveReadFace,
|
|
342
|
+
writeFace: liveWriteFace,
|
|
311
343
|
reminderMark: input.reminderMark,
|
|
312
344
|
reminderDisclosureCounts: input.reminderDisclosureCounts,
|
|
313
345
|
...(input.trackFileEdit !== undefined ? { trackFileEdit: input.trackFileEdit } : {}),
|
|
@@ -323,6 +355,8 @@ export async function prepareHandsMount(input) {
|
|
|
323
355
|
...(sessionId !== undefined ? { sessionId } : {}),
|
|
324
356
|
...(internals?.onTaskNotification !== undefined ? { taskNotification: internals.onTaskNotification } : {}),
|
|
325
357
|
...(internals?.detachHub !== undefined ? { detachHub: internals.detachHub } : {}),
|
|
358
|
+
onToolProgress: (body) => input.toolProgressRef.current?.emit(body),
|
|
359
|
+
queuedHumanInput: () => input.harnessRef.current?.hasPendingUserInput() === true,
|
|
326
360
|
...(deps.onNotice !== undefined ? { onNotice: deps.onNotice } : {}),
|
|
327
361
|
pdfModelCapabilities: pdfModelCapabilitiesOf(model),
|
|
328
362
|
...(deps.hands?.bashReadonlyAllow !== undefined ? { bashReadonlyAllow: deps.hands.bashReadonlyAllow } : {}),
|
|
@@ -386,6 +420,8 @@ export async function prepareHandsMount(input) {
|
|
|
386
420
|
rebaseWsPath,
|
|
387
421
|
backgroundTaskToolsActive,
|
|
388
422
|
resolvedReadFace,
|
|
423
|
+
resolvedWriteFace,
|
|
424
|
+
handsLessResolvedWriteFace,
|
|
389
425
|
readDenyAdditionsNormalized,
|
|
390
426
|
handsLessResolvedFace,
|
|
391
427
|
additionalRootsCanonical,
|
|
@@ -32,7 +32,7 @@ import type { SubagentWorktreeIsolation } from "../../agents/subagent.js";
|
|
|
32
32
|
import { forkGovernanceDenial } from "../../agents/subagent.js";
|
|
33
33
|
import type { SubagentRetainLedger } from "../../agents/retain-ledger.js";
|
|
34
34
|
import type { PromptEpochArtifact } from "../../prompt-assembly/artifact.js";
|
|
35
|
-
import type {
|
|
35
|
+
import type { ContainmentFace } from "../../tools/fs/index.js";
|
|
36
36
|
import type { AutoModeArmingRecipe } from "../auto-mode-arming.js";
|
|
37
37
|
import type { AutoModeDecider, AutoModeDenialTracker } from "../auto-mode.js";
|
|
38
38
|
import { type OnQuestion } from "../ask-question.js";
|
|
@@ -159,14 +159,18 @@ export interface PrepareInheritedGateInput {
|
|
|
159
159
|
/** borrowed-readonly — LATE-BOUND: the observers grant (ctx `observersAllowed`, present only when explicitly granted). */
|
|
160
160
|
observersActive: () => boolean;
|
|
161
161
|
/** borrowed-readonly — LATE-BOUND: the hands mount's resolved read face (undefined until/unless hands mount). */
|
|
162
|
-
resolvedReadFace: () =>
|
|
162
|
+
resolvedReadFace: () => ContainmentFace | undefined;
|
|
163
|
+
/** borrowed-readonly — LATE-BOUND: the hands mount's resolved WRITE face (the read seat's twin). */
|
|
164
|
+
resolvedWriteFace: () => ContainmentFace | undefined;
|
|
163
165
|
/** borrowed-readonly — LATE-BOUND: the normalized deny additions in force (empty until the hands mount resolves them). */
|
|
164
166
|
readDenyAdditionsNormalized: () => ReadonlyArray<{
|
|
165
167
|
pattern: string;
|
|
166
168
|
caseSensitive: boolean;
|
|
167
169
|
}>;
|
|
168
170
|
/** borrowed-readonly — LATE-BOUND: the hands-less legs' resolved face (the carrier's second source). */
|
|
169
|
-
handsLessResolvedFace: () =>
|
|
171
|
+
handsLessResolvedFace: () => ContainmentFace | undefined;
|
|
172
|
+
/** borrowed-readonly — LATE-BOUND: the hands-less legs' resolved WRITE face (same second source, write seat). */
|
|
173
|
+
handsLessResolvedWriteFace: () => ContainmentFace | undefined;
|
|
170
174
|
/** borrowed-readonly — LATE-BOUND: the adopted center artifact (ctx `centerArtifactDigest` / `centerSourceRevision`). */
|
|
171
175
|
centerAdoption: () => {
|
|
172
176
|
artifact: PromptEpochArtifact;
|
|
@@ -230,6 +234,13 @@ export interface PrepareInheritedGateResult {
|
|
|
230
234
|
} | undefined;
|
|
231
235
|
/** owned — the face stamp predicate (`faceCheckpointSection() !== undefined`). */
|
|
232
236
|
faceCheckpointState: () => boolean;
|
|
237
|
+
/** owned — the WRITE-face checkpoint section builder: written ONLY for a non-default (open) write
|
|
238
|
+
* posture, so an absent section IS "roots" on every reader, including an engine that predates the
|
|
239
|
+
* seat. No version stamp rides it — dropping the section can only ever make a resume STRICTER
|
|
240
|
+
* (the opposite direction from the read section, whose deny additions a blind reader would lose). */
|
|
241
|
+
writeFaceCheckpointSection: () => {
|
|
242
|
+
face: "open" | "roots";
|
|
243
|
+
} | undefined;
|
|
233
244
|
/** owned — the F-012 stamp predicate (opaque constraints present ∨ seed frozen chain ∨ provenance-armed). */
|
|
234
245
|
f012CheckpointState: () => boolean;
|
|
235
246
|
/** owned — the FROZEN approver seat (spec over deps) every station of this leg and its children's chain resolve at. */
|
|
@@ -259,7 +270,9 @@ export interface PrepareInheritedGateResult {
|
|
|
259
270
|
/** owned — chain assembly SINGLE SITE: upstream chain + this task's own contribution, called by delegation tools at spawn. */
|
|
260
271
|
inheritedGateForChildren: () => InheritedGate;
|
|
261
272
|
/** owned — the ONE carrier expression both delegation mounts consume (resolved face ?? hands-less face). */
|
|
262
|
-
carrierReadFace: () =>
|
|
273
|
+
carrierReadFace: () => ContainmentFace | undefined;
|
|
274
|
+
/** owned — the same expression on the WRITE seat. */
|
|
275
|
+
carrierWriteFace: () => ContainmentFace | undefined;
|
|
263
276
|
/** owned — the full shell's structural reachability from spec-time facts. */
|
|
264
277
|
fullShellReachable: boolean;
|
|
265
278
|
/** borrowed-mutable — the gate's typed stop seat (`Prepared.gateStopRef`). Writers: `stopForDenialLimit` only. */
|