@sema-agent/core 7.12.0 → 7.14.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 +124 -0
- package/dist/agents/subagent.d.ts +4 -9
- package/dist/agents/subagent.js +16 -12
- package/dist/agents/teacher.js +1 -1
- package/dist/brain/reasoning.d.ts +23 -0
- package/dist/brain/reasoning.js +35 -4
- package/dist/brain/stream-engine.js +35 -17
- package/dist/brain/timeout.d.ts +25 -4
- package/dist/brain/timeout.js +1 -1
- package/dist/core/ask-origin.d.ts +83 -9
- package/dist/core/ask-origin.js +31 -5
- package/dist/core/auto-mode.d.ts +3 -3
- package/dist/core/checkpoint-seat.d.ts +18 -0
- package/dist/core/checkpoint-seat.js +6 -0
- package/dist/core/checkpoint-store.d.ts +9 -16
- package/dist/core/checkpoint-store.js +7 -4
- package/dist/core/engine-notice.d.ts +21 -1
- package/dist/core/env-knob-announce.d.ts +16 -0
- package/dist/core/env-knob-announce.js +14 -0
- package/dist/core/gate-fold.js +2 -0
- package/dist/core/gate-lanes.d.ts +0 -40
- package/dist/core/gate-lanes.js +24 -29
- package/dist/core/gate-outcome.d.ts +42 -3
- package/dist/core/gate-outcome.js +22 -0
- package/dist/core/governance-codes.d.ts +1 -1
- package/dist/core/governance-codes.js +3 -1
- package/dist/core/hooks.d.ts +6 -17
- package/dist/core/hooks.js +7 -5
- package/dist/core/mcp.d.ts +3 -2
- package/dist/core/mcp.js +5 -11
- package/dist/core/memory-engine/engine.d.ts +2 -2
- package/dist/core/runner/advertised-writable-dirs.d.ts +74 -0
- package/dist/core/runner/advertised-writable-dirs.js +48 -0
- package/dist/core/runner/assemble-result.d.ts +50 -1
- package/dist/core/runner/assemble-result.js +4 -1
- package/dist/core/runner/compaction-seams.d.ts +42 -0
- package/dist/core/runner/compaction-seams.js +80 -0
- package/dist/core/runner/contracts.d.ts +44 -6
- package/dist/core/runner/denial-limit-arms.d.ts +7 -9
- package/dist/core/runner/denial-limit-arms.js +11 -12
- package/dist/core/runner/gate-exit.d.ts +15 -3
- package/dist/core/runner/gate-exit.js +6 -4
- package/dist/core/runner/permission-rule-lanes.d.ts +2 -1
- package/dist/core/runner/permission-rule-lanes.js +2 -1
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +34 -4
- package/dist/core/runner/prepare-caps-and-workflow.js +47 -12
- package/dist/core/runner/prepare-gate-stations.d.ts +1 -1
- package/dist/core/runner/prepare-hands-readface.d.ts +10 -4
- package/dist/core/runner/prepare-hands-readface.js +5 -14
- package/dist/core/runner/prepare-inherited-gate.d.ts +5 -3
- package/dist/core/runner/prepare-inherited-gate.js +1 -1
- package/dist/core/runner/prepare-memory.d.ts +31 -34
- package/dist/core/runner/prepare-memory.js +73 -51
- package/dist/core/runner/prepare-policy-chain.js +8 -4
- package/dist/core/runner/prepare-prompt-inputs.d.ts +4 -0
- package/dist/core/runner/prepare-prompt-inputs.js +2 -2
- package/dist/core/runner/prepare-protocol-tools.js +5 -0
- package/dist/core/runner/prepare-question-face.d.ts +10 -8
- package/dist/core/runner/prepare-question-face.js +1 -3
- package/dist/core/runner/prepare-safety-scan.js +11 -16
- package/dist/core/runner/prepare-task.d.ts +9 -1
- package/dist/core/runner/prepare-task.js +63 -49
- package/dist/core/runner/prepare-wiring-manifest.d.ts +2 -2
- package/dist/core/runner/prepare-wiring-manifest.js +1 -1
- package/dist/core/runner/resume-claim.d.ts +2 -2
- package/dist/core/runner/resume-preflight.d.ts +2 -2
- package/dist/core/runner/run-attachment-seats.d.ts +2 -2
- package/dist/core/runner/run-compaction-machinery.js +2 -0
- package/dist/core/runner/run-git-lane.d.ts +1 -1
- package/dist/core/runner/run-harness-handlers.js +5 -1
- package/dist/core/runner/run-identity-wiring.d.ts +7 -0
- package/dist/core/runner/run-identity-wiring.js +3 -1
- package/dist/core/runner/run-leg.d.ts +7 -5
- package/dist/core/runner/run-leg.js +256 -5
- package/dist/core/runner/run-notification-lane.d.ts +4 -3
- package/dist/core/runner/run-recovery-lanes.d.ts +4 -17
- package/dist/core/runner/run-recovery-lanes.js +5 -4
- package/dist/core/runner/run-settle-and-teardown.d.ts +14 -10
- package/dist/core/runner/run-settle-and-teardown.js +112 -4
- package/dist/core/runner/run-stop-and-final-verify.d.ts +2 -2
- package/dist/core/runner/run-terminal-adoption.d.ts +16 -16
- package/dist/core/runner/run-terminal-adoption.js +87 -7
- package/dist/core/runner/run-turn-boundary.js +5 -4
- package/dist/core/runner/runtask.d.ts +10 -90
- package/dist/core/runner/runtask.js +77 -596
- package/dist/core/runner/stream-lifecycle-verbs.js +10 -1
- package/dist/core/runner/stream-settle-backstop.js +1 -1
- package/dist/core/runtime-caps.d.ts +21 -0
- package/dist/core/runtime-caps.js +5 -1
- package/dist/core/task-event.d.ts +11 -2
- package/dist/core/task-registry-shared.js +8 -6
- package/dist/core/task-result.d.ts +15 -0
- package/dist/core/task-stream.d.ts +10 -1
- package/dist/core/terminal-cause.d.ts +6 -2
- package/dist/core/tool-face.d.ts +8 -0
- package/dist/core/tool-face.js +1 -0
- package/dist/core/tool-policy.d.ts +39 -31
- package/dist/core/tool-policy.js +29 -5
- package/dist/core/tool-registry.d.ts +11 -3
- package/dist/core/tool-registry.js +7 -1
- package/dist/core/tool-roster.d.ts +26 -0
- package/dist/core/tool-roster.js +40 -7
- package/dist/core/tool-spec.d.ts +13 -12
- package/dist/core/types.d.ts +2 -1
- package/dist/core/types.js +1 -0
- package/dist/core/wiring-manifest.d.ts +16 -9
- package/dist/core/wiring-manifest.js +8 -3
- package/dist/index.d.ts +8 -7
- package/dist/index.js +7 -6
- package/dist/orchestration/run-workflow-tool.d.ts +8 -8
- package/dist/orchestration/run-workflow-tool.js +1 -1
- package/dist/orchestration/workflow-primitives.d.ts +4 -3
- package/dist/orchestration/workflow-primitives.js +3 -3
- package/dist/orchestration/workflow-types.d.ts +14 -0
- package/dist/orchestration/workflow.d.ts +41 -4
- package/dist/orchestration/workflow.js +23 -5
- package/dist/server/http.js +2 -1
- package/dist/tools/fs/fs-shared.js +9 -3
- package/dist/tools/fs/read-deny.d.ts +24 -8
- package/dist/tools/fs/read-deny.js +20 -1
- package/package.json +2 -1
- package/test/export-surface.snapshot.json +35 -1
|
@@ -5,11 +5,12 @@ import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
|
5
5
|
import { cloneObserverInput, resolveHookTimeoutMs } from "../hooks.js";
|
|
6
6
|
import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "../permission-rules.js";
|
|
7
7
|
import { isIsolated } from "../remote-env.js";
|
|
8
|
-
import { askApproverIdentity, checkToolPolicyProjection, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, isLiveApproverSeat, resolveAsk, toolPolicyNameSets } from "../tool-policy.js";
|
|
8
|
+
import { askApproverIdentity, carryEngineAttestations, carryPrecedingSettlement, checkToolPolicyProjection, combinePolicies, createTranscriptIntegrityPolicy, createUnverifiableDeletePolicy, isLiveApproverSeat, resolveAsk, toolPolicyNameSets } from "../tool-policy.js";
|
|
9
9
|
import { RETIRED_TOOL_NAMES } from "../tool-name-aliases.js";
|
|
10
10
|
import { NAMESPACED_NAME_SHAPES, protocolOf } from "../protocol-table.js";
|
|
11
11
|
import { emitTrace } from "../trace.js";
|
|
12
12
|
import { createActiveSkillScopePolicy } from "./active-skill-scope.js";
|
|
13
|
+
import { probeMandatedAsk } from "../ask-origin.js";
|
|
13
14
|
import { headlessDenyAtFold, headlessDenyAtRecheck, inheritedAskCarry, judgeInheritedClassifier, lateAskSettlementObserver, settleDenialLimitFallback } from "./denial-limit-arms.js";
|
|
14
15
|
import { askGrantShapeOf } from "./inherited-ask-grants.js";
|
|
15
16
|
import { createPermissionRuleLanes, inheritedAskRuleEvidence, createRuleOffersOf } from "./permission-rule-lanes.js";
|
|
@@ -374,7 +375,7 @@ export async function preparePolicyChain(input) {
|
|
|
374
375
|
if (judged.kind === "deny")
|
|
375
376
|
return judged.result;
|
|
376
377
|
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
377
|
-
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq.toolName)) {
|
|
378
|
+
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq.toolName) && !probeMandatedAsk(inheritedAsk)) {
|
|
378
379
|
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
379
380
|
return { action: "allow" };
|
|
380
381
|
}
|
|
@@ -454,7 +455,7 @@ export async function preparePolicyChain(input) {
|
|
|
454
455
|
if (judged.kind === "deny")
|
|
455
456
|
return judged.result;
|
|
456
457
|
const { ask: inheritedAsk, fallback, mintedHere } = judged;
|
|
457
|
-
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq.toolName)) {
|
|
458
|
+
if (fallback === undefined && sandboxAdmissionArmed && policyAskClassOf(pc.policy) === "sandbox_local" && !sandboxBoundaryCapable(creq.toolName) && !probeMandatedAsk(inheritedAsk)) {
|
|
458
459
|
recordAncestorSandboxAdmission(creq.toolCallId, creq.toolName);
|
|
459
460
|
return decision.updatedInput !== undefined ? { action: "allow", updatedInput: decision.updatedInput } : { action: "allow" };
|
|
460
461
|
}
|
|
@@ -556,7 +557,10 @@ export async function preparePolicyChain(input) {
|
|
|
556
557
|
for (const layer of recheckLayers) {
|
|
557
558
|
const d = await layer.check(finalReq, signal);
|
|
558
559
|
if (d.action === "deny") {
|
|
559
|
-
|
|
560
|
+
const carried = { ...d, updatedInput: decision.updatedInput };
|
|
561
|
+
carryEngineAttestations(d, carried);
|
|
562
|
+
carryPrecedingSettlement(decision, carried);
|
|
563
|
+
return carried;
|
|
560
564
|
}
|
|
561
565
|
if (d.updatedInput !== undefined) {
|
|
562
566
|
return {
|
|
@@ -28,6 +28,7 @@ import type { MaterializedMcp } from "../mcp.js";
|
|
|
28
28
|
import type { ResolvedRole } from "../roles.js";
|
|
29
29
|
import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
30
30
|
import type { PrepareResume, PromptFeatureFlags, RunInternals, ToolFaceSnapshot } from "./contracts.js";
|
|
31
|
+
import type { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
|
|
31
32
|
import { type GitStatusLaneRef } from "./git-status-frame.js";
|
|
32
33
|
export interface PreparePromptInputsInput {
|
|
33
34
|
/** borrowed-readonly — the REBOUND spec (`spec′`). Read: `promptProvider`, `hooks` (flag), `systemPrompt`
|
|
@@ -90,6 +91,9 @@ export interface PreparePromptInputsInput {
|
|
|
90
91
|
additionalRootsCanonical: readonly string[];
|
|
91
92
|
/** borrowed-readonly — the canonical extra read-only roots (copied into the env facts). */
|
|
92
93
|
additionalReadRootsCanonical: readonly string[];
|
|
94
|
+
/** borrowed-readonly — #691: the advertised-writable-directory seat (hands only). The scratchpad section is
|
|
95
|
+
* rendered only when the seat did not SKIP the scratchpad — a directory the fence refused is not advertised. */
|
|
96
|
+
advertisedWritableDirs?: AdvertisedWritableDirs;
|
|
93
97
|
/** borrowed-readonly — the acquired session's id (operator-line context). */
|
|
94
98
|
sessionId: string;
|
|
95
99
|
}
|
|
@@ -4,7 +4,7 @@ import { probeGitStatusLane } from "./git-status-frame.js";
|
|
|
4
4
|
import { fenceMcpServerInstructions } from "./turn-attachments.js";
|
|
5
5
|
const ULTRA_REASONING_TIERS = new Set(["xhigh", "max"]);
|
|
6
6
|
export async function preparePromptInputs(input) {
|
|
7
|
-
const { spec, deps, failClosedReason, lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId } = input;
|
|
7
|
+
const { spec, deps, failClosedReason, lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, advertisedWritableDirs } = input;
|
|
8
8
|
const provider = spec.promptProvider ?? deps.promptProvider ?? defaultPromptProvider;
|
|
9
9
|
const promptPolicyEnabled = Boolean(lockedPreflight.toolPolicy);
|
|
10
10
|
const promptHooks = spec.hooks ?? deps.hooks;
|
|
@@ -51,7 +51,7 @@ export async function preparePromptInputs(input) {
|
|
|
51
51
|
envFacts.sandboxPkgSource = spec.envFacts.pkgSource;
|
|
52
52
|
if (spec.envFacts?.egress === "none" || spec.envFacts?.egress === "allowlist" || spec.envFacts?.egress === "full")
|
|
53
53
|
envFacts.sandboxEgress = spec.envFacts.egress;
|
|
54
|
-
if (spec.envFacts?.scratchpadDir)
|
|
54
|
+
if (spec.envFacts?.scratchpadDir && advertisedWritableDirs?.verdictOf("scratchpad") !== "skipped")
|
|
55
55
|
envFacts.scratchpadDir = spec.envFacts.scratchpadDir;
|
|
56
56
|
if (externalContentTargetActive)
|
|
57
57
|
envFacts.externalContentTarget = true;
|
|
@@ -3,12 +3,17 @@ import { materializeMcpTools } from "../mcp.js";
|
|
|
3
3
|
import { materializeA2aTools } from "../a2a.js";
|
|
4
4
|
import { deliverEngineNotice } from "../types.js";
|
|
5
5
|
import { RosterBuilder } from "../tool-roster.js";
|
|
6
|
+
import { TOOL_WIRE_NAME_MAX_CHARS } from "../tool-face.js";
|
|
6
7
|
import { REFRESH_MCP_TOOLS_TOOL_NAME, toolFace } from "../tool-catalog-entries.js";
|
|
7
8
|
import { MCP_NAMESPACE, A2A_NAMESPACE } from "../protocol-table.js";
|
|
8
9
|
import { mintNamespacePrefix } from "../protocol-naming.js";
|
|
9
10
|
import { applyMcpToolFaces } from "./tool-face-overlay.js";
|
|
10
11
|
export async function prepareProtocolTools(input) {
|
|
11
12
|
const { lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, abortController, rollback } = input;
|
|
13
|
+
const overPeer = (lockedPreflight.mcp ?? []).find((s) => s.name.length > TOOL_WIRE_NAME_MAX_CHARS);
|
|
14
|
+
if (overPeer !== undefined) {
|
|
15
|
+
throw Object.assign(new Error(`MCP server name ${JSON.stringify(overPeer.name.slice(0, 40) + "…")} is ${overPeer.name.length} characters; a peer rides every roster row of its tools and the roster's bound on a name is ${TOOL_WIRE_NAME_MAX_CHARS}.`), { code: "config.tool_name_too_long" });
|
|
16
|
+
}
|
|
12
17
|
const mcp = lockedPreflight.mcp?.length
|
|
13
18
|
? await materializeMcpTools(lockedPreflight.mcp, spec.principal, deps.onElicit, deps.mcpImageResizer, { reminderMark, counts: reminderDisclosureCounts }, mcpRevocationWiring(deps, runId))
|
|
14
19
|
: { tools: [], toolAxes: [], warnings: [], serverInstructions: [], instructionsDelta: { pendingAdds: [], pendingRemovals: [] }, droppedTools: [], statuses: [], refresh: async () => [], dispose: async () => { } };
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import type { AgentTool } from "../../internal/harness.js";
|
|
20
20
|
import { type OnQuestion } from "../ask-question.js";
|
|
21
|
-
import {
|
|
21
|
+
import type { CheckpointStore } from "../checkpoint-store.js";
|
|
22
22
|
import type { RunnerDeps, RuntimeCaps, TaskSpec } from "../types.js";
|
|
23
23
|
import type { PrepareResume } from "./contracts.js";
|
|
24
24
|
import { type ContentAskBinding } from "./content-ask-bindings.js";
|
|
@@ -28,13 +28,15 @@ export interface PrepareQuestionFaceInput {
|
|
|
28
28
|
/** borrowed-readonly — the run's frozen question seat (spec > deps), resolved once at the top of prepare;
|
|
29
29
|
* the mount predicate and the live-face derivation both read this one value. */
|
|
30
30
|
frozenOnQuestion: OnQuestion | undefined;
|
|
31
|
-
/** borrowed-readonly — the REBOUND spec. Read: `
|
|
32
|
-
* (the
|
|
33
|
-
*
|
|
34
|
-
spec: Pick<TaskSpec, "
|
|
35
|
-
/** borrowed-readonly — the deployment
|
|
36
|
-
*
|
|
37
|
-
deps: Pick<RunnerDeps, "
|
|
31
|
+
/** borrowed-readonly — the REBOUND spec. Read: `durableApproval` (the durable face's opt-in), `interactiveTools`
|
|
32
|
+
* (the override), `principal` (the tool's source identity), `interactiveQuestionFallback` (restores the
|
|
33
|
+
* continuation under a resolved posture). Never mutated. */
|
|
34
|
+
spec: Pick<TaskSpec, "durableApproval" | "interactiveTools" | "principal" | "interactiveQuestionFallback">;
|
|
35
|
+
/** borrowed-readonly — the deployment seat `onError` (the stranded-answer and synthetic-continuation operator
|
|
36
|
+
* lines; swallow-guarded). */
|
|
37
|
+
deps: Pick<RunnerDeps, "onError">;
|
|
38
|
+
/** borrowed-readonly — THE leg's checkpoint seat (minted once by the driver after the config doors); the mount face, the routability predicate, the manifest and suspendAsk all read this one value through the result. */
|
|
39
|
+
checkpointStore: CheckpointStore | undefined;
|
|
38
40
|
/** borrowed-readonly — the principal's resolved runtime caps as of this point (`forceDurableGate` is the
|
|
39
41
|
* mandate that outranks a live face only where a store exists to park the question). */
|
|
40
42
|
runtimeCaps: Pick<RuntimeCaps, "forceDurableGate"> | undefined;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { createAskUserQuestionTool, isLiveQuestionFace } from "../ask-question.js";
|
|
2
2
|
import { boundInputHashOf } from "../canonical-json.js";
|
|
3
|
-
import { resolveCheckpointStore } from "../checkpoint-store.js";
|
|
4
3
|
import { CONTENT_ASK_BINDING_CAP } from "./content-ask-bindings.js";
|
|
5
4
|
import { RosterBuilder } from "../tool-roster.js";
|
|
6
5
|
export { CONTENT_ASK_BINDING_CAP } from "./content-ask-bindings.js";
|
|
7
6
|
export function prepareQuestionFace(input) {
|
|
8
|
-
const { frozenOnQuestion, spec, deps, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks } = input;
|
|
7
|
+
const { frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks } = input;
|
|
9
8
|
const tools = roster.tools;
|
|
10
9
|
const onQuestion = frozenOnQuestion;
|
|
11
10
|
const liveQuestionFace = isLiveQuestionFace(onQuestion) ? onQuestion : undefined;
|
|
12
11
|
const contentAskBindings = new Map();
|
|
13
|
-
const checkpointStore = resolveCheckpointStore(spec, deps);
|
|
14
12
|
const questionParkStoreWired = checkpointStore !== undefined;
|
|
15
13
|
const questionDurableMandateBinding = runtimeCaps?.forceDurableGate === true && questionParkStoreWired;
|
|
16
14
|
const contentAskRoutable = (toolCallId) => liveQuestionFace !== undefined &&
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { NAMESPACED_NAME_SHAPES } from "../protocol-table.js";
|
|
2
2
|
import { engineCardTypes, handBandEffects } from "../tool-registry.js";
|
|
3
|
-
import {
|
|
4
|
-
import { callerCardIdOf, offendingResultCard, schemaKeyBoundProblem } from "../tool-roster.js";
|
|
3
|
+
import { callerCardIdOf, offendingResultCard, rosterMemberBoundProblem, schemaKeyBoundProblem } from "../tool-roster.js";
|
|
5
4
|
import { toolFaceProblem } from "./tool-face-overlay.js";
|
|
6
5
|
import { OFFLOAD_TOOL_NAME } from "../tool-result-store.js";
|
|
7
6
|
import { PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
|
|
@@ -16,23 +15,19 @@ export function prepareSafetyScan(input) {
|
|
|
16
15
|
const axisExplicitNegatives = new Map();
|
|
17
16
|
const reversibilityProbes = new Map();
|
|
18
17
|
for (const t of spec.tools ?? []) {
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
e
|
|
18
|
+
{
|
|
19
|
+
const bound = rosterMemberBoundProblem({
|
|
20
|
+
name: t.name,
|
|
21
|
+
aliases: t.aliases,
|
|
22
|
+
...(t.contract !== undefined ? { contractId: t.contract.contractId, implementationRevision: t.contract.implementationRevision } : {}),
|
|
23
|
+
...(typeof t.modelGate === "string" ? { modelGate: t.modelGate } : {}),
|
|
24
|
+
});
|
|
25
|
+
if (bound !== undefined) {
|
|
26
|
+
const e = new Error(`A caller tool cannot ride a roster row: ${bound.message}.`);
|
|
27
|
+
e.code = bound.code;
|
|
28
28
|
throw e;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
if (t.contract !== undefined && (t.contract.contractId.length > TOOL_CONTRACT_MAX_CHARS || t.contract.implementationRevision.length > TOOL_CONTRACT_MAX_CHARS)) {
|
|
32
|
-
const e = new Error(`Tool "${t.name}" declares a contract member over ${TOOL_CONTRACT_MAX_CHARS} characters (contractId ${t.contract.contractId.length}, implementationRevision ${t.contract.implementationRevision.length}) — the roster's bound.`);
|
|
33
|
-
e.code = "config.tool_contract_too_long";
|
|
34
|
-
throw e;
|
|
35
|
-
}
|
|
36
31
|
{
|
|
37
32
|
const keyProblem = schemaKeyBoundProblem(t.parameters);
|
|
38
33
|
if (keyProblem !== undefined) {
|
|
@@ -8,7 +8,7 @@ export { mcpManifestEntries } from "./prepare-wiring-manifest.js";
|
|
|
8
8
|
export { __resetMaterializeEnvAnnouncements } from "./prepare-tool-disclosure-mount.js";
|
|
9
9
|
export { fileHistoryFilesystemIdentity, resolveFileHistoryScope } from "./prepare-file-history.js";
|
|
10
10
|
import type { RunnerSelfSeat } from "./contracts.js";
|
|
11
|
-
import type { Prepared, PrepareResume, RunInternals } from "./contracts.js";
|
|
11
|
+
import type { Prepared, PrepareResume, PrepareTaskFn, RunInternals } from "./contracts.js";
|
|
12
12
|
export type { FileHistoryBoundarySeat, InheritedGate, Prepared, PreparedMicroCompact, PrepareResume, ResolvedWorkspace, RunInternals, UsageGovernance } from "./contracts.js";
|
|
13
13
|
import type { ExecutionEnv } from "../../internal/harness.js";
|
|
14
14
|
import type { RunnerDeps, TaskSpec } from "../types.js";
|
|
@@ -114,3 +114,11 @@ runnerSelf?: RunnerSelfSeat,
|
|
|
114
114
|
runIdSink?: {
|
|
115
115
|
runId?: string;
|
|
116
116
|
}): Promise<Prepared>;
|
|
117
|
+
/** design/393 S7 (#675) — the entry IS the contract the notification lane's seat names ({@link PrepareTaskFn}, contracts.ts):
|
|
118
|
+
* a signature change reds HERE, at the declaration, as `false` failing the `true` bound. IDENTITY, not assignability (review
|
|
119
|
+
* round 1): the parameter tuple (arity, optionality, each type) and the return type must be the SAME type in both directions —
|
|
120
|
+
* one-way `extends` let a dropped trailing parameter, an added optional one or a narrowed return slip through. Type-level only —
|
|
121
|
+
* nothing is emitted. */
|
|
122
|
+
type Holds<T extends true> = T;
|
|
123
|
+
type Same<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? true : false;
|
|
124
|
+
export type PrepareTaskIsTheContract = Holds<Same<Parameters<typeof prepareTask>, Parameters<PrepareTaskFn>>> & Holds<Same<ReturnType<typeof prepareTask>, ReturnType<PrepareTaskFn>>> & Holds<Same<ThisParameterType<typeof prepareTask>, ThisParameterType<PrepareTaskFn>>> & Holds<Same<typeof prepareTask, PrepareTaskFn>>;
|
|
@@ -68,12 +68,14 @@ import { defaultTaskRegistry } from "../task-registry.js";
|
|
|
68
68
|
import { announcePeerLaneMount } from "../../agents/peer-session-drain.js";
|
|
69
69
|
import { createSchedulerTools } from "../../tools/scheduler-tools.js";
|
|
70
70
|
import { selfOrchestrationFailClosedReason } from "../../orchestration/workflow-script-runner.js";
|
|
71
|
-
import { remainingBudgetMicroUsd } from "../checkpoint-store.js";
|
|
71
|
+
import { remainingBudgetMicroUsd, resolveCheckpointStore } from "../checkpoint-store.js";
|
|
72
|
+
import { checkpointSeatOf } from "../checkpoint-seat.js";
|
|
72
73
|
import { durableParkGapFor } from "../park-selfcheck.js";
|
|
73
74
|
import { deliverEngineNotice } from "../types.js";
|
|
74
75
|
import { ToolRosterDeltaSeat } from "../tool-roster.js";
|
|
75
76
|
import { faceOf } from "../tool-roster.js";
|
|
76
77
|
import { catalogEntriesNamed, pathTargetOf } from "../tool-registry.js";
|
|
78
|
+
import { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
|
|
77
79
|
import { createStructuredProjector } from "./tool-output-projection.js";
|
|
78
80
|
function warnCompactionWindowHazard(tracer, spec, model, compModel, hostTaskId) {
|
|
79
81
|
if (compModel === undefined)
|
|
@@ -257,6 +259,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
257
259
|
runIdSink.runId = runId;
|
|
258
260
|
const doors = prepareConfigDoors({ spec, deps, sessions, resume, internals });
|
|
259
261
|
spec = doors.spec;
|
|
262
|
+
const checkpointStore = resolveCheckpointStore(spec, deps), checkpointSeat = checkpointSeatOf(spec, checkpointStore);
|
|
260
263
|
const autoModeSeat = refuseInvalidAutoModeSeat(spec);
|
|
261
264
|
const { toolFaceSnapshot, promptProfile, lockedPreflight, resolvedInteractionPosture, microCompactKnob, resolvedRole, model, thinking, compModel, fableMitigations, memoryDelegationEvidence, memoryProvenance, memoryCapturePolicy, usageWindows, brainCallGuardrailRef, brainCallGuardrailMs } = doors;
|
|
262
265
|
announceToolModelGate(deps.onNotice, model.id, doors.modelGate);
|
|
@@ -366,8 +369,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
366
369
|
let resolvedReadFace;
|
|
367
370
|
let readDenyAdditionsNormalized = [];
|
|
368
371
|
let handsLessResolvedFace;
|
|
369
|
-
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, autoModeIntent, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, autoModeSeat, handsEnabled, reportUsage, harnessRef, skillScope, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDecider, autoModeDenialTracking: () => autoModeDenialTracking, autoModeArming: () => autoModeArming, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
370
|
-
const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDecider, autoModeDenialTracking, autoModeArming, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, 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, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized });
|
|
372
|
+
const { liveInheritedGate, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, inheritedParentConstraints, autoModeIntent, inheritedAdmittedOrgScopes, priorOwnOrgVerdict, orgGovernedProvenance, effectiveShellGate, ownSessionRulesRef, memoryAdmittedOrgScopesRef, ownOrgVerdictRef, orgAdmissionCheckpointState, faceCheckpointSection, faceCheckpointState, f012CheckpointState, frozenOnAsk, hookEnvSource, notifyOwnHookCrash, frozenOnQuestion, provenanceForChildrenRef, delegationSettlementRef, inheritedGateForChildren, carrierReadFace, fullShellReachable, gateStopRef, stopForDenialLimit, enrichSpecToolCtx } = prepareInheritedGate({ spec, deps, internals, resume, sessions, sessionId, runId, hostTaskId, taskRootFinal, executionEnv, ownedEnv, lockedPreflight, checkpointSeat, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, autoModeSeat, handsEnabled, reportUsage, harnessRef, skillScope, forwardEvent, subagentRetain, worktreeIsolation, requestReview, requestStopAfterTurn, enterPlanMode, reminderMark, reminderDisclosureCounts, fileHistoryEnabled, historyScope, historyRoot, historyFs, abortRun: () => { abortController.abort(); void harness.abort(); }, runtimeCaps: () => runtimeCaps, hooks: () => hooks, preToolUseObservational: () => preToolUseObservational, hookTimeoutMs: () => hookTimeoutMs, hookEnvFace: () => hookEnvFace, autoModeDecider: () => autoModeDecider, autoModeDenialTracking: () => autoModeDenialTracking, autoModeArming: () => autoModeArming, agentForkDenial: () => agentForkDenial, observersActive: () => observersActive, resolvedReadFace: () => resolvedReadFace, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized, handsLessResolvedFace: () => handsLessResolvedFace, centerAdoption: () => centerAdoptionRef.current, memoryEngineSession: () => memoryEngineSession });
|
|
373
|
+
const { roster, blockedRef, runtimeCaps, runtimeCapsFaulted, complianceDenies, complianceDegraded, agentForkDenial, observersActive, autoModeArmReason, autoModeDecider, autoModeDenialTracking, autoModeArming, selfOrchestrationActive, workflowToolsActive, workflowSizeGuideline } = await prepareCapsAndWorkflow({ spec, deps, internals, session, sessionId, runId, hostTaskId, taskScope, taskRootFinal, model, thinking, lockedPreflight, checkpointSeat, toolEffects, toolFaceSnapshot, promptProfile, resolvedInteractionPosture, harnessRef, frozenOnAsk, carrierReadFace, forwardEvent, inheritedGateForChildren, enrichSpecToolCtx, maybeOffload, requestReview, enterPlanMode, autoModeIntent, peerLaneActive, peerSendMessageBuiltIn, runnerSelf, memoryEngineSession: () => memoryEngineSession, centerAdoption: () => centerAdoptionRef.current, readDenyAdditionsNormalized: () => readDenyAdditionsNormalized });
|
|
371
374
|
const tools = roster.tools;
|
|
372
375
|
const pausedRef = {};
|
|
373
376
|
const remoteEnvFailures = [];
|
|
@@ -429,35 +432,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
429
432
|
const rosterSeat = new ToolRosterDeltaSeat();
|
|
430
433
|
const { mcp, a2a, rebuildHarnessToolsRef, contentOriginWrapRef, toolCallGateArmedRef } = await prepareProtocolTools({ lockedPreflight, spec, deps, reminderMark, reminderDisclosureCounts, runId, sessionId, onceLedger, roster, rosterSeat, remoteToolOffload, toolFaceSnapshot, toolEffects, axisExplicitNegatives, irreversibilityTier, irreversibleTools, egressTools, abortController, rollback });
|
|
431
434
|
const callIssuedAtRef = {};
|
|
435
|
+
const workCutRef = { continuation: false, abortedBeforeTurnEnd: false };
|
|
432
436
|
const memoryWriteGateRef = {};
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
readDenyAdditionsNormalized = handsReadFace.readDenyAdditionsNormalized;
|
|
438
|
-
handsLessResolvedFace = handsReadFace.handsLessResolvedFace;
|
|
439
|
-
shellGatedBash = handsReadFace.shellGatedBash;
|
|
440
|
-
shellGatedMonitor = handsReadFace.shellGatedMonitor;
|
|
441
|
-
const { worktreeSessionRef } = prepareDelegationSurface({ spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, executionEnv, runnerSelf, backgroundTaskToolsActive, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle });
|
|
442
|
-
const { checkpointStore, liveQuestionFace, contentAskBindings, contentAskRoutable, lateStrandedAnswers, discloseStrandedAnswers, settleContentAskBindings, durableQuestionFace, questionToolMounted, mountedQuestionTool } = prepareQuestionFace({ frozenOnQuestion, spec, deps, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks: () => inheritedUnavailableAsks });
|
|
443
|
-
if (spec.handsReadOnly !== true) {
|
|
444
|
-
const sessionScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
|
|
445
|
-
roster.mountAll(createSchedulerTools(executionEnv, {
|
|
446
|
-
scope: sessionScope,
|
|
447
|
-
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
448
|
-
...(sessionId !== undefined ? { sessionId } : {}),
|
|
449
|
-
requestStopAfterTurn,
|
|
450
|
-
}).map((t) => (envHandToolNames.add(t.name), t)), { source: "builtin", mountedBy: "scheduler" });
|
|
451
|
-
}
|
|
452
|
-
if (internals?.insideFork !== true &&
|
|
453
|
-
runnerSelf &&
|
|
454
|
-
sessionId !== undefined &&
|
|
455
|
-
hasSessionFork(runnerSelf.sessions) &&
|
|
456
|
-
agentForkDenial === "principal") {
|
|
457
|
-
deps.onError?.(new Error(`Fork DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowFork=false ` +
|
|
458
|
-
`(per-principal entitlement governance, not a misconfiguration — Agent(subagent_type:"fork") will refuse honestly)`), { phase: "config", sessionId });
|
|
459
|
-
}
|
|
460
|
-
const { lspDiagnostics, nudgeLspOnEdit, lspRunIdent } = prepareLsp({ spec, deps, executionEnv, taskRootFinal, handsEnabled, sessionId, handsCwdRef, roster, envHandToolNames });
|
|
437
|
+
const advertisedWritableDirs = handsEnabled
|
|
438
|
+
? new AdvertisedWritableDirs(executionEnv, (dir, reason) => deps.onError?.(new Error(`${dir.advertiser} advertised writable directory skipped (cannot canonicalize): ${dir.path} — ${reason}`), { phase: "config", sessionId }))
|
|
439
|
+
: undefined;
|
|
440
|
+
const handsWriteHalfPlanned = handsEnabled && spec.handsReadOnly !== true;
|
|
461
441
|
const memoryPairNameDomain = new Set();
|
|
462
442
|
for (const t of tools) {
|
|
463
443
|
memoryPairNameDomain.add(t.name);
|
|
@@ -476,14 +456,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
476
456
|
return { fault: true };
|
|
477
457
|
}
|
|
478
458
|
})();
|
|
479
|
-
const { memoryEngineSession,
|
|
459
|
+
const { memoryEngineSession, memoryTools, composeInjection: composeMemoryInjection, admittedOrgScopes: memoryAdmittedOrgScopes, ownOrgVerdict: memoryOwnOrgVerdict, effectiveMemoryScopes: memoryEffectiveScopes, } = await prepareMemory({
|
|
480
460
|
spec,
|
|
481
461
|
deps,
|
|
482
462
|
sessionId,
|
|
483
463
|
taskRootPath: taskRootFinal,
|
|
484
464
|
memoryWriteGateRef,
|
|
485
465
|
reminderMark,
|
|
486
|
-
writeToolsMounted: tools.some((t) => t.name === "Write") &&
|
|
466
|
+
writeToolsMounted: (handsWriteHalfPlanned || tools.some((t) => t.name === "Write")) &&
|
|
487
467
|
!(toolFaceSnapshot.exclude?.includes("Write") ?? false) &&
|
|
488
468
|
!(handsEnabled && isRemoteExecutionEnv(executionEnv) && spec.memoryPersistenceCapable !== true),
|
|
489
469
|
memoryProvenance,
|
|
@@ -502,20 +482,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
502
482
|
...(internals?.memoryCaptureQueryDir !== undefined ? { parentCaptureQueryDir: internals.memoryCaptureQueryDir } : {}),
|
|
503
483
|
...(internals?.memoryCaptureAncestors !== undefined ? { captureAncestors: internals.memoryCaptureAncestors } : {}),
|
|
504
484
|
memoryPersistenceDeclared: spec.memoryPersistenceCapable,
|
|
505
|
-
|
|
506
|
-
tools.some((t) => {
|
|
507
|
-
if (toolFaceSnapshot.exclude?.includes(t.name) ?? false)
|
|
508
|
-
return false;
|
|
509
|
-
const effect = (t.effect ?? toolEffects.get(t.name) ?? "write");
|
|
510
|
-
if (effect === "read")
|
|
511
|
-
return false;
|
|
512
|
-
const face = faceOf(t);
|
|
513
|
-
const pt = face.pathTarget ?? pathTargetOf(t.name);
|
|
514
|
-
const family = face.family ?? catalogEntriesNamed(t.name)[0]?.face.family;
|
|
515
|
-
if (!((pt !== undefined && pt.access !== "read") || family === "shell"))
|
|
516
|
-
return false;
|
|
517
|
-
return !(handsEnabled && isRemoteExecutionEnv(executionEnv));
|
|
518
|
-
}),
|
|
485
|
+
...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}),
|
|
519
486
|
memorySearchToolsPlanned,
|
|
520
487
|
admissionCtx: {
|
|
521
488
|
orgMemoryDenied: complianceDenies.has("org_memory_mount"),
|
|
@@ -539,6 +506,34 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
539
506
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
540
507
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
541
508
|
}
|
|
509
|
+
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGateRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
510
|
+
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
511
|
+
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
512
|
+
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
513
|
+
readDenyAdditionsNormalized = handsReadFace.readDenyAdditionsNormalized;
|
|
514
|
+
handsLessResolvedFace = handsReadFace.handsLessResolvedFace;
|
|
515
|
+
shellGatedBash = handsReadFace.shellGatedBash;
|
|
516
|
+
shellGatedMonitor = handsReadFace.shellGatedMonitor;
|
|
517
|
+
const { worktreeSessionRef } = prepareDelegationSurface({ spec, deps, internals, resume, sessionId, hostTaskId, taskScope, taskRootFinal, executionEnv, runnerSelf, backgroundTaskToolsActive, workflowToolsActive, peerLaneActive, peerSendMessageBuiltIn, peerLaneRefs, roster, toolEffects, axisExplicitNegatives, envHandToolNames, toolFaceSnapshot, firstPartyOffload, offloadStore, subagentRetain, enrichSpecToolCtx, handsCwdRef, wsSnapshot, rebaseWsPath, rebaseRestoredPath, workspaceStateSettle });
|
|
518
|
+
const { liveQuestionFace, contentAskBindings, contentAskRoutable, lateStrandedAnswers, discloseStrandedAnswers, settleContentAskBindings, durableQuestionFace, questionToolMounted, mountedQuestionTool } = prepareQuestionFace({ frozenOnQuestion, spec, deps, checkpointStore, runtimeCaps, resolvedInteractionPosture, resume, sessionId, roster, inheritedUnavailableAsks: () => inheritedUnavailableAsks });
|
|
519
|
+
if (spec.handsReadOnly !== true) {
|
|
520
|
+
const sessionScope = sessionId ?? spec.principal ?? spec.taskId ?? "default";
|
|
521
|
+
roster.mountAll(createSchedulerTools(executionEnv, {
|
|
522
|
+
scope: sessionScope,
|
|
523
|
+
...(spec.principal !== undefined ? { principal: spec.principal } : {}),
|
|
524
|
+
...(sessionId !== undefined ? { sessionId } : {}),
|
|
525
|
+
requestStopAfterTurn,
|
|
526
|
+
}).map((t) => (envHandToolNames.add(t.name), t)), { source: "builtin", mountedBy: "scheduler" });
|
|
527
|
+
}
|
|
528
|
+
if (internals?.insideFork !== true &&
|
|
529
|
+
runnerSelf &&
|
|
530
|
+
sessionId !== undefined &&
|
|
531
|
+
hasSessionFork(runnerSelf.sessions) &&
|
|
532
|
+
agentForkDenial === "principal") {
|
|
533
|
+
deps.onError?.(new Error(`Fork DENIED for principal "${spec.principal ?? ""}" by runtimeCaps.allowFork=false ` +
|
|
534
|
+
`(per-principal entitlement governance, not a misconfiguration — Agent(subagent_type:"fork") will refuse honestly)`), { phase: "config", sessionId });
|
|
535
|
+
}
|
|
536
|
+
const { lspDiagnostics, nudgeLspOnEdit, lspRunIdent } = prepareLsp({ spec, deps, executionEnv, taskRootFinal, handsEnabled, sessionId, handsCwdRef, roster, envHandToolNames });
|
|
542
537
|
if (internals?.delegationProvenance !== undefined && resume !== undefined) {
|
|
543
538
|
const live = internals.delegationProvenance.ref.current;
|
|
544
539
|
const seed = resume.seed.delegationProvenance;
|
|
@@ -552,6 +547,21 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
552
547
|
live.incomplete = true;
|
|
553
548
|
}
|
|
554
549
|
}
|
|
550
|
+
const rosterCanPersist = spec.memoryPersistenceCapable ??
|
|
551
|
+
tools.some((t) => {
|
|
552
|
+
if (toolFaceSnapshot.exclude?.includes(t.name) ?? false)
|
|
553
|
+
return false;
|
|
554
|
+
const effect = (t.effect ?? toolEffects.get(t.name) ?? "write");
|
|
555
|
+
if (effect === "read")
|
|
556
|
+
return false;
|
|
557
|
+
const face = faceOf(t);
|
|
558
|
+
const pt = face.pathTarget ?? pathTargetOf(t.name);
|
|
559
|
+
const family = face.family ?? catalogEntriesNamed(t.name)[0]?.face.family;
|
|
560
|
+
if (!((pt !== undefined && pt.access !== "read") || family === "shell"))
|
|
561
|
+
return false;
|
|
562
|
+
return !(handsEnabled && isRemoteExecutionEnv(executionEnv));
|
|
563
|
+
});
|
|
564
|
+
const { memoryBlock: memoryBlockFromEngine, recallDisciplineSegment: memoryRecallSegment, seedFiles: memorySeedFiles } = composeMemoryInjection({ rosterCanPersist });
|
|
555
565
|
if (memorySeedFiles?.length && seedContextFiles) {
|
|
556
566
|
try {
|
|
557
567
|
await seedContextFiles(memorySeedFiles);
|
|
@@ -562,7 +572,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
562
572
|
}
|
|
563
573
|
const projectContext = await prepareProjectContext({ deps, spec, internals, session, sessionId, hostTaskId, taskRootFinal, handsEnabled, delegation, seedContextFiles, memoryBlockFromEngine, skillScope, roster, toolFaceSnapshot, onceLedger, memoryTools, memoryEngineSession, memorySearchToolsPlanned, memoryPairExcludedName, memoryPairOccupiedName, resume });
|
|
564
574
|
const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, hasSkillManifest, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
|
|
565
|
-
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, gitStatusRef } = await preparePromptInputs({ spec, deps, failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId });
|
|
575
|
+
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, gitStatusRef } = await preparePromptInputs({ spec, deps, failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
566
576
|
const { deferred, memoryBlock } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
|
|
567
577
|
prepareMemoryEngineSession({ memoryEngineSession, internals, memoryDelegationEvidence, externalContentTargetActive, lockedPreflight, mcp, sessionId, runId, deps, provenanceForChildrenRef, delegationSettlementRef, spec, envHandToolNames, roster, contentOriginWrapRef });
|
|
568
578
|
const { systemPromptSeat, renderWithDate, systemBlocks, promptManifest, epochDeclaredSections, epochArtifactDigestForSnapshot, buildAssembleInputs, centerAdoptionRef } = await preparePromptAssembly({ session, deps, internals, resume, provider, userSystemPrompt, userAppendSystemPrompt, featureFlags, mcpInstructionsBlock, memoryBlock, envFacts, promptProfile, fableMitigations, tools, model, sessionId, reminderMark, onceLedger });
|
|
@@ -617,6 +627,10 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
617
627
|
},
|
|
618
628
|
...(spec.resilience !== undefined ? { resilience: spec.resilience } : {}),
|
|
619
629
|
loopTrace: (step) => {
|
|
630
|
+
if (step.kind === "continue")
|
|
631
|
+
workCutRef.continuation = true;
|
|
632
|
+
else
|
|
633
|
+
workCutRef.continuation = workCutRef.continuation && step.reason === "aborted_before_stream";
|
|
620
634
|
if (step.kind !== "continue")
|
|
621
635
|
return;
|
|
622
636
|
if (step.reason === "next_turn" || step.reason === "steer_injected" || step.reason === "follow_up_injected")
|
|
@@ -686,7 +700,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
686
700
|
const preparedHolder = {};
|
|
687
701
|
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, readDenyAdditionsNormalized, preparedHolder });
|
|
688
702
|
await onceLedger.settle(session, announcedListingsRef);
|
|
689
|
-
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, brainCallGuardrailRef, gateStopRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
703
|
+
const buildPrepared = () => ({ harness, session, sessionId, runId, reminderMark, reminderDisclosureCounts, editedFilesSnapshot, taskRootPath: taskRootFinal, model, thinking, compModel: effectiveCompModel, mcp, ...(a2a.tools.length > 0 ? { a2a } : {}), blockedRef, outputRef, abortController, conflictRef, blockedToolCalls, gateOutcomes, batchHaltRef, nestedStats, ...(rewindNotes.length > 0 ? { rewindNotes } : {}), ...(fileHistoryBoundary !== undefined ? { fileHistoryBoundary } : {}), ...(effectiveReadFaceObserved !== undefined ? { effectiveReadFace: effectiveReadFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, ...(worktreeSessionRef !== undefined ? { worktreeSessionRef } : {}), ...(workspaceStateSettle !== undefined ? { workspaceStateSettle } : {}), ...(sealReadStateSeat !== undefined ? { sealReadStateSeat } : {}), denyNarrowingPolicy, ...(permissionRuleLane !== undefined ? { persistedRuleLane: permissionRuleLane } : {}), ...(basePolicyForResumeEdit !== undefined ? { basePolicyForResumeEdit } : {}), ...(permissionRuleOrgLane !== undefined ? { permissionRuleOrg: permissionRuleOrgLane } : {}), releaseSignal, settleContentAskBindings, cacheBreakDetector, cacheFingerprint, wiringManifest, promptManifest, epochDeclaredSections, activeTools, ...(deferred.size > 0 ? { deferredToolNames: deferred } : {}), toolMaterializeStatic, deferDirectCall, ...(staticFaceForRef.current !== undefined ? { staticFaceFor: staticFaceForRef.current } : {}), ownedEnv, pausedRef, suspendProgressRef, remoteEnvFailures, reviewRequestRef, suspendLoopRef, suspendForResource, ...(suspendForPlatformLimit !== undefined ? { suspendForPlatformLimit } : {}), ...(envLifetimeSuspendAt !== undefined ? { envLifetimeSuspendAt } : {}), ...(usageGovernance !== undefined ? { usageGovernance } : {}), callIssuedAtRef, workCutRef, brainCallGuardrailRef, gateStopRef, suspendForReview, resourceLedger: priorLedger, liveSpendRef, humanReviewRef, now, tools, toolRoster, toolRosterDeltas: rosterSeat, structuredProjector, toolEffects, wakeRecovered, promptOverheadTokens, lastBrainContext, readTaskFile, recentlyReadFiles, normalizeAttachmentPath, isDedupStubResult, ...(onCompactionApplied ? { onCompactionApplied } : {}), compactionReuseRef, trimPressureRef, microCompact, ...(memoryEngineSession ? { memoryEngineSession } : {}), ...(subagentRetain ? { subagentRetain } : {}), ...(lspDiagnostics && nudgeLspOnEdit ? { lspDiagnostics: { registry: lspDiagnostics, nudge: nudgeLspOnEdit, runIdent: lspRunIdent } } : {}), planModeRef, stopRequestedRef, announcedSnapshotRecovered: onceLedger.recovered, ...(dateChange ? { dateChange } : {}), ...(instructionSources ? { instructionSources } : {}), ...(projectInstructionContent !== undefined ? { projectInstructionContent } : {}), ...(workflowSizeGuideline ? { workflowSizeGuideline } : {}), ...(detectExternalChanges ? { detectExternalChanges } : {}), ...(toolsDeltaRef ? { toolsDeltaRef } : {}), ...(agentListing ? { agentListing } : {}), ...(skillsListing ? { skillsListing } : {}), announcedListingsRef, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}) });
|
|
690
704
|
rollback.commit();
|
|
691
705
|
const prepared = buildPrepared();
|
|
692
706
|
preparedHolder.current = prepared;
|
|
@@ -30,7 +30,7 @@ import type { GateOutcome } from "../gate-outcome.js";
|
|
|
30
30
|
import type { RunnerDeps, RuntimeCaps, TaskSpec, ToolEffect, ToolExecuteContext } from "../types.js";
|
|
31
31
|
import { type UsageWindow } from "../usage-window-store.js";
|
|
32
32
|
import type { ToolRoster } from "../tool-roster.js";
|
|
33
|
-
import { type
|
|
33
|
+
import { type AutoModeArmFact, type WiringManifest, type WiringManifestMcpEntry } from "../wiring-manifest.js";
|
|
34
34
|
import type { AnnounceOnceSink, Prepared, PrepareResume, RunInternals, UsageGovernance } from "./contracts.js";
|
|
35
35
|
export interface PrepareWiringManifestInput {
|
|
36
36
|
/** borrowed-readonly — the REBOUND spec. Read: `onAsk` (the own seat), `onQuestion` (the question seam), `handsReadOnly` / `tools` (the ungated scan),
|
|
@@ -107,7 +107,7 @@ export interface PrepareWiringManifestInput {
|
|
|
107
107
|
* source of the hand band's write-capable names for the ungated-write warning (what actually MOUNTED). */
|
|
108
108
|
toolRoster: ToolRoster;
|
|
109
109
|
/** borrowed-readonly — the arming outcome the caps phase minted (the manifest's auto-mode face). */
|
|
110
|
-
autoModeArmReason:
|
|
110
|
+
autoModeArmReason: AutoModeArmFact;
|
|
111
111
|
/** borrowed-readonly — the frozen preflight; only `mcp` (the declared servers the manifest face joins). */
|
|
112
112
|
lockedPreflight: Pick<LockedPreflight, "mcp">;
|
|
113
113
|
/** borrowed-mutable — the peer lane's late-bound facts. Writer here: `askEffective` ← the manifest's ask derivation (the
|
|
@@ -199,7 +199,7 @@ export function prepareWiringManifest(input) {
|
|
|
199
199
|
memoryAdmissionWired: deps.memoryScopeAdmission !== undefined,
|
|
200
200
|
retentionPolicyWired: deps.retentionPolicy !== undefined,
|
|
201
201
|
...(modelGateManifest !== undefined ? { modelGate: modelGateManifest } : {}),
|
|
202
|
-
autoMode: {
|
|
202
|
+
autoMode: { ...autoModeArmReason },
|
|
203
203
|
mcp: mcpManifestEntries(lockedPreflight.mcp, mcp.statuses),
|
|
204
204
|
tools: toolRoster,
|
|
205
205
|
});
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* — the post-consume hook fires on the tick the win was read — and returns what that rung returns.
|
|
10
10
|
*/
|
|
11
11
|
import { type Checkpoint, type CheckpointStore, type CheckpointToken } from "../checkpoint-store.js";
|
|
12
|
-
import type { InheritedGate, ResumeRun } from "./contracts.js";
|
|
12
|
+
import type { InheritedGate, InstallingPhaseResult, ResumeRun } from "./contracts.js";
|
|
13
13
|
export interface ResumeClaimInput<R> {
|
|
14
14
|
/** borrowed-readonly — the checkpoint token being claimed. */
|
|
15
15
|
token: CheckpointToken;
|
|
@@ -27,6 +27,6 @@ export interface ResumeClaimInput<R> {
|
|
|
27
27
|
next: (claimed: ResumeClaimResult) => Promise<R>;
|
|
28
28
|
}
|
|
29
29
|
/** The claim's completion is its whole result: a lost CAS throws, so reaching `next` IS the win. */
|
|
30
|
-
export interface ResumeClaimResult {
|
|
30
|
+
export interface ResumeClaimResult extends InstallingPhaseResult {
|
|
31
31
|
}
|
|
32
32
|
export declare function resumeClaim<R>(input: ResumeClaimInput<R>): Promise<R>;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* returns what that rung returns.
|
|
11
11
|
*/
|
|
12
12
|
import { type Checkpoint, type CheckpointStore, type CheckpointToken } from "../checkpoint-store.js";
|
|
13
|
-
import type { InheritedGate, RunnerDepsSeat, SuspendReap } from "./contracts.js";
|
|
13
|
+
import type { InheritedGate, InstallingPhaseResult, RunnerDepsSeat, SuspendReap } from "./contracts.js";
|
|
14
14
|
export interface ResumePreflightInput<R> {
|
|
15
15
|
/** borrowed-readonly — the checkpoint token (handed to the deployment and to the settling CAS). */
|
|
16
16
|
token: CheckpointToken;
|
|
@@ -35,6 +35,6 @@ export interface ResumePreflightInput<R> {
|
|
|
35
35
|
next: (screened: ResumePreflightResult) => Promise<R>;
|
|
36
36
|
}
|
|
37
37
|
/** The preflight's completion is its whole result: every refusal throws, so reaching `next` IS the fact. */
|
|
38
|
-
export interface ResumePreflightResult {
|
|
38
|
+
export interface ResumePreflightResult extends InstallingPhaseResult {
|
|
39
39
|
}
|
|
40
40
|
export declare function resumePreflight<R>(input: ResumePreflightInput<R>): Promise<R>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TaskSpec } from "../types.js";
|
|
2
|
-
import type { Prepared, ResumeRun, RunnerDepsSeat, RunState } from "./contracts.js";
|
|
2
|
+
import type { InstallingPhaseResult, Prepared, ResumeRun, RunnerDepsSeat, RunState } from "./contracts.js";
|
|
3
3
|
export interface RunAttachmentSeatsInput<R> {
|
|
4
4
|
/** borrowed-readonly — the task spec: the attachments config and the `finalVerification` opt-in. */
|
|
5
5
|
spec: TaskSpec;
|
|
@@ -17,6 +17,6 @@ export interface RunAttachmentSeatsInput<R> {
|
|
|
17
17
|
next: (seats: RunAttachmentSeatsResult) => Promise<R>;
|
|
18
18
|
}
|
|
19
19
|
/** Nothing comes back: the lane's products are the `counters` / `attach` groups it wrote on the borrowed run state. */
|
|
20
|
-
export interface RunAttachmentSeatsResult {
|
|
20
|
+
export interface RunAttachmentSeatsResult extends InstallingPhaseResult {
|
|
21
21
|
}
|
|
22
22
|
export declare function runAttachmentSeats<R>(input: RunAttachmentSeatsInput<R>): Promise<R>;
|
|
@@ -11,6 +11,8 @@ export function runCompactionMachinery(input) {
|
|
|
11
11
|
const u = msg?.usage;
|
|
12
12
|
if (!u)
|
|
13
13
|
return;
|
|
14
|
+
if (msg.usageMissing === true)
|
|
15
|
+
stats.usageMissing = true;
|
|
14
16
|
const fam = cacheFamilyOf(m);
|
|
15
17
|
const price = runner.deps.pricing?.[m.id] ?? modelCostToPricing(m.cost);
|
|
16
18
|
const priced = isModelPriced(m, runner.deps.pricing);
|
|
@@ -52,7 +52,7 @@ export interface RunGitLaneInput {
|
|
|
52
52
|
runner: RunnerDepsSeat;
|
|
53
53
|
}
|
|
54
54
|
export interface RunGitLaneResult {
|
|
55
|
-
/** The parked-mirror flush — awaited at the serialization points (the
|
|
55
|
+
/** The parked-mirror flush — awaited at the serialization points: the `turn_boundary` subscription here is the regular station (the final boundary of a gracefully ending run included); the leg's post-prompt call is the fallback for a terminal that skipped it. */
|
|
56
56
|
flushGitMirror: () => Promise<void>;
|
|
57
57
|
/** The owed-frame retry's `turn_boundary` subscription; the driver's teardown releases it first. */
|
|
58
58
|
unsubGitRetry: () => void;
|
|
@@ -77,8 +77,10 @@ export function createHarnessHandlers(input) {
|
|
|
77
77
|
rs.degrade.recordDegraded({ from: deg.from, to: deg.to, reason: deg.reason, atTurn: stats.turns + 1, ...(deg.chain && { chain: deg.chain }) });
|
|
78
78
|
}
|
|
79
79
|
if (m.role === "assistant" && "usage" in m && m.usage) {
|
|
80
|
-
if (m.usageMissing)
|
|
80
|
+
if (m.usageMissing) {
|
|
81
81
|
rs.turn.turnUsageMissing = true;
|
|
82
|
+
stats.usageMissing = true;
|
|
83
|
+
}
|
|
82
84
|
const u = m.usage;
|
|
83
85
|
stats.tokens += u.totalTokens || 0;
|
|
84
86
|
const { totalInputTokens: turnTotal, uncachedInputTokens: turnUncached, costMicroUsd: turnCostMicroUsd, } = usageCostMicroUsd(rs.telemetry.cacheFamily, u, rs.telemetry.pricing);
|
|
@@ -281,6 +283,8 @@ export function createHarnessHandlers(input) {
|
|
|
281
283
|
};
|
|
282
284
|
const onTurnEnd = () => {
|
|
283
285
|
stats.turns += 1;
|
|
286
|
+
if (prepared.abortController.signal.aborted)
|
|
287
|
+
prepared.workCutRef.abortedBeforeTurnEnd = true;
|
|
284
288
|
const stopExtra = rs.turn.turnStopReason !== undefined ? { stopReason: rs.turn.turnStopReason } : {};
|
|
285
289
|
queue.push(rs.turn.turnUsage
|
|
286
290
|
? { type: "turn_end", usage: rs.turn.turnUsage, ...(rs.turn.turnUsageMissing ? { usageMissing: true } : {}), ...stopExtra, ...ident() }
|
|
@@ -73,5 +73,12 @@ export interface RunIdentityWiringResult {
|
|
|
73
73
|
followUp: number;
|
|
74
74
|
} | undefined;
|
|
75
75
|
};
|
|
76
|
+
/** #677 — did the run END with a person's steer / follow-up still pending (queued, or drained at the final boundary and
|
|
77
|
+
* never served)? A READ FACE over this lane's own `let`, written by the same undrained-inputs sink on BOTH its arms
|
|
78
|
+
* (park or not): the terminal-adoption lane folds it into the answer-settled verdict — a "stop" answer the person had
|
|
79
|
+
* already asked to continue past is not a settled answer, so a stop that cut that continuation is a stop on work. */
|
|
80
|
+
userInputLostAtEnd: {
|
|
81
|
+
readonly current: boolean;
|
|
82
|
+
};
|
|
76
83
|
}
|
|
77
84
|
export declare function runIdentityWiring(input: RunIdentityWiringInput): RunIdentityWiringResult;
|