@sema-agent/core 7.18.0 → 7.20.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 +276 -2
- package/dist/agents/subagent.js +12 -20
- package/dist/agents/teacher.js +2 -5
- package/dist/agents/verify.js +21 -10
- package/dist/brain/anthropic.js +8 -3
- package/dist/brain/open-responses.js +12 -4
- package/dist/brain/openai.js +7 -2
- package/dist/brain/reasoning.d.ts +13 -13
- package/dist/brain/reasoning.js +2 -2
- package/dist/brain/stream-engine.d.ts +4 -0
- package/dist/brain/stream-engine.js +6 -1
- package/dist/brain/stream-shared.d.ts +3 -0
- package/dist/brain/stream-shared.js +1 -0
- package/dist/core/ask-origin.d.ts +16 -0
- package/dist/core/ask-origin.js +8 -0
- package/dist/core/auto-mode-arming.d.ts +6 -0
- package/dist/core/auto-mode-arming.js +5 -5
- package/dist/core/auto-mode-defaults.d.ts +43 -15
- package/dist/core/auto-mode-defaults.js +4 -1
- package/dist/core/auto-mode.d.ts +74 -26
- package/dist/core/auto-mode.js +80 -11
- package/dist/core/checkpoint-store.d.ts +7 -0
- package/dist/core/checkpoint-store.js +2 -2
- package/dist/core/child-clamp-seats.d.ts +79 -0
- package/dist/core/child-clamp-seats.js +29 -0
- package/dist/core/engine-notice.d.ts +89 -41
- package/dist/core/fs-write-gate-policy.d.ts +17 -9
- package/dist/core/fs-write-gate-policy.js +51 -4
- package/dist/core/gate-bounded-await.d.ts +38 -0
- package/dist/core/gate-bounded-await.js +53 -0
- package/dist/core/gate-fold.js +20 -48
- package/dist/core/gate-lanes.js +17 -9
- package/dist/core/gate-outcome.d.ts +34 -6
- package/dist/core/gate-outcome.js +7 -0
- package/dist/core/governance-codes.d.ts +16 -1
- package/dist/core/governance-codes.js +18 -0
- package/dist/core/hooks.d.ts +8 -8
- package/dist/core/memory-engine/engine.d.ts +14 -9
- package/dist/core/memory-engine/engine.js +21 -8
- package/dist/core/memory-engine/layout.d.ts +31 -0
- package/dist/core/memory-engine/layout.js +68 -3
- package/dist/core/memory-engine/types.d.ts +24 -0
- package/dist/core/memory.d.ts +19 -0
- package/dist/core/memory.js +12 -0
- package/dist/core/read-root-candidate.d.ts +12 -0
- package/dist/core/read-root-candidate.js +24 -0
- package/dist/core/remote-env.d.ts +32 -0
- package/dist/core/remote-env.js +4 -1
- package/dist/core/roles.d.ts +9 -1
- package/dist/core/roles.js +4 -0
- package/dist/core/runner/advertised-writable-dirs.d.ts +59 -1
- package/dist/core/runner/advertised-writable-dirs.js +51 -3
- package/dist/core/runner/announce-once-ledger.d.ts +15 -0
- package/dist/core/runner/announce-once-ledger.js +8 -0
- package/dist/core/runner/classifier-ladder.d.ts +154 -11
- package/dist/core/runner/classifier-ladder.js +170 -10
- package/dist/core/runner/contracts.d.ts +46 -1
- package/dist/core/runner/denial-limit-arms.d.ts +14 -1
- package/dist/core/runner/denial-limit-arms.js +7 -6
- package/dist/core/runner/env-capability-census.d.ts +30 -0
- package/dist/core/runner/env-capability-census.js +38 -0
- package/dist/core/runner/forward-sink.d.ts +32 -0
- package/dist/core/runner/forward-sink.js +41 -0
- package/dist/core/runner/gate-exit.d.ts +4 -0
- package/dist/core/runner/gate-exit.js +4 -1
- package/dist/core/runner/git-status-frame.d.ts +0 -9
- package/dist/core/runner/listing-fold.d.ts +57 -0
- package/dist/core/runner/listing-fold.js +75 -0
- package/dist/core/runner/prepare-ask-lane.js +1 -0
- package/dist/core/runner/prepare-caps-and-workflow.js +20 -31
- package/dist/core/runner/prepare-config-doors.d.ts +6 -0
- package/dist/core/runner/prepare-config-doors.js +8 -10
- package/dist/core/runner/prepare-execution-env.d.ts +1 -1
- package/dist/core/runner/prepare-execution-env.js +2 -0
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -0
- package/dist/core/runner/prepare-gate-stations.js +6 -2
- package/dist/core/runner/prepare-hands-readface.d.ts +4 -0
- package/dist/core/runner/prepare-hands-readface.js +3 -5
- package/dist/core/runner/prepare-listings.d.ts +3 -0
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory.js +7 -1
- package/dist/core/runner/prepare-policy-chain.js +5 -5
- package/dist/core/runner/prepare-project-context.d.ts +5 -1
- package/dist/core/runner/prepare-project-context.js +3 -2
- package/dist/core/runner/prepare-prompt-inputs.d.ts +2 -2
- package/dist/core/runner/prepare-run-refs.d.ts +4 -2
- package/dist/core/runner/prepare-run-refs.js +5 -4
- package/dist/core/runner/prepare-task.js +8 -6
- package/dist/core/runner/resume-apply.js +3 -3
- package/dist/core/runner/run-clock-and-content.js +3 -7
- package/dist/core/runner/run-harness-handlers.js +10 -10
- package/dist/core/runner/run-leg.js +31 -16
- package/dist/core/runner/run-settle-and-teardown.js +2 -5
- package/dist/core/runner/run-turn-boundary.js +44 -25
- package/dist/core/runner/runtask.js +2 -1
- package/dist/core/runner/synthetic-tools.d.ts +41 -29
- package/dist/core/runner/synthetic-tools.js +25 -40
- package/dist/core/runner/task-root-canonical.d.ts +45 -0
- package/dist/core/runner/task-root-canonical.js +18 -0
- package/dist/core/runner/turn-attachments.d.ts +160 -53
- package/dist/core/runner/turn-attachments.js +153 -51
- package/dist/core/safe-notify.d.ts +5 -0
- package/dist/core/safe-notify.js +24 -2
- package/dist/core/sensitive-path-policy.d.ts +84 -17
- package/dist/core/sensitive-path-policy.js +37 -19
- package/dist/core/skill-listing-budget.d.ts +106 -0
- package/dist/core/skill-listing-budget.js +57 -0
- package/dist/core/skills-directory.js +17 -10
- package/dist/core/task-registry.js +2 -1
- package/dist/core/task-spec.d.ts +29 -2
- package/dist/core/tool-policy.d.ts +31 -5
- package/dist/core/tool-policy.js +45 -32
- package/dist/core/tool-spec.d.ts +37 -4
- package/dist/core/types.d.ts +1 -1
- package/dist/core/write-protect.d.ts +105 -20
- package/dist/core/write-protect.js +89 -32
- package/dist/index.d.ts +8 -7
- package/dist/index.js +6 -5
- package/dist/orchestration/workflow-primitives.js +10 -20
- package/dist/stores/file/memory-store.d.ts +5 -2
- package/dist/stores/file/memory-store.js +8 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +40 -2
- package/dist/tools/fs/bash-readonly-classifier.js +376 -41
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +19 -28
- package/dist/tools/fs/fs-shared.d.ts +22 -0
- package/dist/tools/fs/fs-shared.js +30 -0
- package/dist/tools/fs/index.d.ts +1 -1
- package/dist/tools/fs/index.js +1 -1
- package/dist/tools/fs/read-deny.d.ts +4 -3
- package/dist/tools/fs/safety.d.ts +15 -0
- package/dist/tools/fs/safety.js +7 -0
- package/package.json +2 -1
- package/test/export-surface.snapshot.json +31 -5
- package/wire-changes/core@7.18.0.json +1273 -0
- package/wire-changes/core@7.19.0.json +457 -0
- package/wire-changes/core@7.20.0.json +568 -0
|
@@ -78,6 +78,7 @@ import { ToolRosterDeltaSeat } from "../tool-roster.js";
|
|
|
78
78
|
import { faceOf } from "../tool-roster.js";
|
|
79
79
|
import { catalogEntriesNamed, pathTargetOf } from "../tool-registry.js";
|
|
80
80
|
import { AdvertisedWritableDirs } from "./advertised-writable-dirs.js";
|
|
81
|
+
import { resolveTaskRootCanonical } from "./task-root-canonical.js";
|
|
81
82
|
import { createStructuredProjector } from "./tool-output-projection.js";
|
|
82
83
|
function warnCompactionWindowHazard(tracer, spec, model, compModel, hostTaskId) {
|
|
83
84
|
if (compModel === undefined)
|
|
@@ -365,6 +366,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
365
366
|
}
|
|
366
367
|
const ownedEnv = ownedEnvSeat.current;
|
|
367
368
|
const { taskRootFinal, rebaseRestoredPath } = await prepareWorkspaceRestore({ ownedEnv, deps, spec, internals, resume, taskRootInitial, abortController, sessionId });
|
|
369
|
+
const { canonical: taskRootCanonical } = await resolveTaskRootCanonical({ env: executionEnv, given: taskRootFinal, onNotice: deps.onNotice, sessionId, runId });
|
|
368
370
|
const { trackFileEdit, fileHistoryBoundary, restoredFilePaths, rewindNotes, fileHistoryEnabled, historyScope, historyRoot, historyFs } = await prepareFileHistory({ deps, spec, internals, executionEnv, taskRootFinal, handsEnabled, sessionId, session, resumeAtBeforeParentId, abortController });
|
|
369
371
|
const { noteFileEdited, editedFilesSnapshot, harnessRef, toolProgressRef, skillScope, forwardEvent, reviewRequestRef, requestReview, stopRequestedRef, requestStopAfterTurn, planModeRef, enterPlanMode, subagentRetain, worktreeIsolation } = prepareRunRefs({ spec, internals, executionEnv, taskRootFinal });
|
|
370
372
|
let resolvedReadFace;
|
|
@@ -438,7 +440,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
438
440
|
const callIssuedAtRef = {};
|
|
439
441
|
const workCutRef = { continuation: false, abortedBeforeTurnEnd: false };
|
|
440
442
|
const advertisedWritableDirs = handsEnabled
|
|
441
|
-
? new AdvertisedWritableDirs(executionEnv, (dir, reason) => deps.onError?.(new Error(`${dir.advertiser} advertised writable directory skipped
|
|
443
|
+
? new AdvertisedWritableDirs(executionEnv, (dir, reason) => deps.onError?.(new Error(`${dir.advertiser} advertised writable directory skipped: ${dir.path} — ${reason}`), { phase: "config", sessionId }), taskRootCanonical, [...(spec.additionalDirectories ?? []), ...(spec.additionalReadDirectories ?? [])])
|
|
442
444
|
: undefined;
|
|
443
445
|
const handsWriteHalfPlanned = handsEnabled && handsWriteHalfMounts({ readOnly: spec.handsReadOnly === true });
|
|
444
446
|
const memoryPairNameDomain = new Set();
|
|
@@ -508,7 +510,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
508
510
|
if (internals?.ownOrgAdmissionRef !== undefined && ownOrgVerdictRef.current !== undefined) {
|
|
509
511
|
internals.ownOrgAdmissionRef.current = ownOrgVerdictRef.current;
|
|
510
512
|
}
|
|
511
|
-
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
513
|
+
const handsReadFaceInput = { handsEnabled, executionEnv, taskRootFinal, taskRootCanonical, rebaseRestoredPath, resume, session, sessionId, hostTaskId, taskScope, fullShellReachable, effectiveShellGate, toolFaceSnapshot, model, spec, deps, internals, memoryWriteGate, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), firstPartyOffload, roster, egressTools, irreversibilityTier, irreversibleTools, reversibilityProbes, reminderMark, reminderDisclosureCounts, ...(trackFileEdit !== undefined ? { trackFileEdit } : {}), onFileEdited: noteFileEdited, harnessRef, toolProgressRef, ...(restoredFilePaths.length > 0 ? { restoredFilePaths } : {}) };
|
|
512
514
|
const handsReadFace = handsEnabled ? await prepareHandsMount(handsReadFaceInput) : resolveHandsLessReadFace(handsReadFaceInput);
|
|
513
515
|
const { readFileStateForCheckpoint, seedContextFiles, handsCwdRef, workspaceStateSettle, wsSnapshot, rebaseWsPath, backgroundTaskToolsActive, additionalRootsCanonical, additionalReadRootsCanonical, attachmentRootCanonical, readDenyMatcher, envHandToolNames, sealReadStateSeat } = handsReadFace;
|
|
514
516
|
resolvedReadFace = handsReadFace.resolvedReadFace;
|
|
@@ -574,7 +576,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
574
576
|
deps.onError?.(err instanceof Error ? err : new Error(String(err)), { phase: "config", sessionId });
|
|
575
577
|
}
|
|
576
578
|
}
|
|
577
|
-
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 });
|
|
579
|
+
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, skillListingBudget: doors.skillListingBudget });
|
|
578
580
|
const { memoryBlock: memoryBlockWithProject, instructionSources, projectInstructionContent, hasSkillManifest, skillsListing, sharedMemoryPairMounted, memoryEnginePairMounted } = projectContext;
|
|
579
581
|
const { provider, featureFlags, userSystemPrompt, userAppendSystemPrompt, mcpInstructionsBlock, envFacts, tzValid, userTz, gitStatusRef } = await preparePromptInputs({ spec, deps, failClosedReason: selfOrchestrationFailClosedReason(spec, deps), lockedPreflight, selfOrchestrationActive, executionEnv, reminderMark, resolvedReadFace, resolvedWriteFace, toolFaceSnapshot, promptProfile, fableMitigations, internals, thinking, ownedEnv, delegation, resolvedRole, mcp, model, externalContentTargetActive, resume, handsEnabled, taskRootFinal, additionalRootsCanonical, additionalReadRootsCanonical, sessionId, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}) });
|
|
580
582
|
const { deferred, memoryBlock, toolSearch: toolSearchPolicy } = prepareDeferClassify({ spec, deps, roster, toolFaceSnapshot, handsEnabled, fullShellReachable, promptProfile, model, mcp, a2a, sharedMemoryPairMounted, memoryEnginePairMounted, memoryBlock: memoryBlockWithProject, memoryRecallSegment, onceLedger, sessionId });
|
|
@@ -590,7 +592,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
590
592
|
declaredCards: toolRoster.entries.flatMap((e) => e.renderHints?.resultCards ?? []),
|
|
591
593
|
onUndeclared: (type) => deliverEngineNotice(deps.onNotice, { code: "config.tool_card_undeclared", message: `a tool minted a \`details.type\` card ${JSON.stringify(type)} its definition never declared — dropped from tool_end.structured (declare it on the definition's catalog row or the caller's renderHints.resultCards)`, detail: { type, sessionId, runId } }),
|
|
592
594
|
});
|
|
593
|
-
const { agentListing, announcedListingsRef, dateChange } = prepareListings({ spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingRideRef, renderWithDate, envFacts, tzValid, userTz });
|
|
595
|
+
const { agentListing, announcedListingsRef, dateChange } = prepareListings({ spec, tools, onceLedger, sessionId, toolFaceSnapshot, activeTools, resume, skillsListing, listingBudget: doors.skillListingBudget, listingRideRef, renderWithDate, envFacts, tzValid, userTz });
|
|
594
596
|
const lastBrainContextRef = {};
|
|
595
597
|
const requestLossyRef = { current: false };
|
|
596
598
|
const staleOffloadWrittenRefs = new Set();
|
|
@@ -699,12 +701,12 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
|
|
|
699
701
|
const { saga } = prepareSuspendSaga({ gateMachineryActive, abortController, harness, checkpointStore, deps, sessionId, hostTaskId, taskScope, liveSpendRef, resume, nestedStats, internals, activeTools, outputRef, readFileStateForCheckpoint, faceCheckpointSection, writeFaceCheckpointSection, reminderMark, handsCwdRef, worktreeSessionRef, undeliveredContinuationRef, inheritedParentConstraints, seedInheritedGate, inheritedAncestorRules, inheritedShellGate, autoModeIntent, inheritedAdmittedOrgScopes, ownOrgVerdictRef, orgGovernedProvenance, announcedListingsRef, gitStatusRef, hookIdentity, placementRootResolved, externalContentTargetActive, remoteEnvFailures, memoryEngineSession, suspendLoopRef, ownedEnv, incompleteSuspendAdapter });
|
|
700
702
|
const { suspendForResource, suspendForPlatformLimit, suspendForReview } = prepareBoundaryParks({ saga, spec, checkpointStore, abortController, harness, session, sessions, sessionId, deps, priorLedger, maxSlices, maxSuspends, resourceTotal, priorSuspendCount, suspendChainBase, humanReviewRef, liveSpendRef, now, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, pausedRef, remoteEnvFailures, resourceSuspendEligible, durableSuspendInfraReady, incompleteSuspendAdapter });
|
|
701
703
|
const { parkAsk } = prepareParkAsk({ askLane, saga, spec, deps, sessionId, checkpointStore, toolRosterDeltas: rosterSeat, parkLaneArmed, contentAskRoutable, liveQuestionFace, mountedQuestionTool, contentAskBindings, lateStrandedAnswers, discloseStrandedAnswers, onAsk, runtimeCaps, inheritedUnavailableAsks, basePolicyForResumeEdit, budgetSnapshot, handsCwdRef, advertisedWritableDirs, offloadStore, ownedEnv, incompleteSuspendAdapter, session, sessions, suspendChainBase, maxSuspends, remoteEnvFailures, shellGatedTools, effectiveShellGate, durableApproval, priorLedger, liveSpendRef, resourceTotal, faceCheckpointState, f012CheckpointState, orgAdmissionCheckpointState, ruleOffersOf, now, humanReviewRef, abortController, harness, pausedRef });
|
|
702
|
-
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash });
|
|
704
|
+
prepareGateStations({ askLane, parkAsk, tools, toolRosterDeltas: rosterSeat, toolEffects, deps, toolCallGateArmedRef, effectivePolicy, hooks, egressTools, irreversibleTools, spec, complianceDenies, harness, blockedToolCalls, inheritedAskGrants, inheritedUnavailableAsks, foldAskClasses, ancestorSandboxAdmissions, preToolContexts, gateOutcomes, batchHaltRef, blockedTracked, hookIdentity, reminderMark, planModeRef, hostTaskId, sessionId, ownGatePreToolUse, hookTimeoutMs, handsCwdRef, hookEnvFace, handsEnv: handsEnabled ? executionEnv : undefined, taskRootFinal, irreversibilityTier, reversibilityProbes, abortController, shellGatedTools, autoModeDecider, autoModeDenialTracking, stopForDenialLimit, permissionRuleLane, permissionRuleOrgLane, questionToolMounted, sandboxAdmissionArmed, sandboxBoundaryCapable, emitSandboxAdmitted, delegation, notifyOwnHookCrash });
|
|
703
705
|
const { microCompact, charsPerToken } = prepareContextLane({ model, deps, sessionId, runId, hostTaskId, offloadStore, microCompactKnob, harness, batchHaltRef, gitStatusRef, requestLossyRef, trimPressureRef });
|
|
704
706
|
const preparedHolder = {};
|
|
705
707
|
const { cacheBreakDetector, cacheFingerprint, promptOverheadTokens, readTaskFile, normalizeAttachmentPath, isDedupStubResult, recentlyReadFiles, onCompactionApplied, detectExternalChanges, listBackgroundTasks, centerCompactionCandidate, effectiveReadFaceObserved, effectiveWriteFaceObserved, effectiveReadDenyObserved } = prepareTurnWiring({ deps, systemPromptSeat, harnessTools, fpRef, model, epochArtifactDigestForSnapshot, promptProfile, fableMitigations, systemBlocks, thinking, spec, sessionId, turnSnapshotRef, promptManifest, charsPerToken, handsEnabled, executionEnv, attachmentRootCanonical, additionalRootsCanonical, additionalReadRootsCanonical, readDenyMatcher, resolvedReadFace, handsCwdRef, readFileStateForCheckpoint, denyNarrowingPolicy, abortController, hostTaskId, taskScope, buildAssembleInputs, centerAdoptionRef, harnessRef, epochDeclaredSections, carrierReadFace, carrierWriteFace, readDenyAdditionsNormalized, preparedHolder });
|
|
706
708
|
await onceLedger.settle(session, announcedListingsRef);
|
|
707
|
-
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, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(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, undeliveredContinuationRef, 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 } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
709
|
+
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, effectiveWriteFace: effectiveWriteFaceObserved } : {}), ...(effectiveReadDenyObserved !== undefined ? { effectiveReadDenyPatterns: effectiveReadDenyObserved } : {}), effectiveMemoryScopes: memoryEffectiveScopes, cwdRef: handsCwdRef, toolProgressRef, ...(advertisedWritableDirs !== undefined ? { advertisedWritableDirs } : {}), ...(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, undeliveredContinuationRef, 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, frameReceipts: { pending: [], listingSnapshotOwed: false }, gitStatusRef, listBackgroundTasks, hookIdentity, hookTimeoutMs, ...(turnSnapshotRef.current !== undefined ? { turnSnapshot: turnSnapshotRef.current } : {}), ...(centerCompactionCandidate !== undefined ? { centerCompactionCandidate } : {}), ...(toolDisclosureSeat !== undefined ? { toolDisclosure: toolDisclosureSeat } : {}) });
|
|
708
710
|
rollback.commit();
|
|
709
711
|
const prepared = buildPrepared();
|
|
710
712
|
preparedHolder.current = prepared;
|
|
@@ -2,6 +2,7 @@ import { snapshotActorAssertion } from "../../internal/llm.js";
|
|
|
2
2
|
import { isAskOrigin } from "../ask-origin.js";
|
|
3
3
|
import { ASK_USER_QUESTION_TOOL_NAME } from "../ask-question.js";
|
|
4
4
|
import { CheckpointError, remainingBudgetMicroUsd } from "../checkpoint-store.js";
|
|
5
|
+
import { settledByPerson } from "../gate-outcome.js";
|
|
5
6
|
import { cloneObserverInput, mintHookInvocationIdentity, resolveHookTimeoutMs, runHookSeat } from "../hooks.js";
|
|
6
7
|
import { checkToolPolicyProjection, refuseOutOfContractDecision } from "../tool-policy.js";
|
|
7
8
|
import { callFaceSeat, parkedCallFaceOf } from "../tool-roster.js";
|
|
@@ -170,10 +171,9 @@ export async function resumeApply(input) {
|
|
|
170
171
|
throw new CheckpointError("checkpoint.unsupported_version", "this checkpoint's pending approval carries no origin word (a row minted before the ask's origin was persisted on the park) — its settlement cannot be recorded; the checkpoint stays pending", { reason: "origin_missing" });
|
|
171
172
|
}
|
|
172
173
|
const facts = plainPolicyOutcome.hostDecision;
|
|
173
|
-
const approverCell = facts.approver !== undefined ? { approver: facts.approver } : {};
|
|
174
174
|
const settlement = facts.decidedBy === "sla_timeout"
|
|
175
|
-
? { kind: "park_sla_expired", who: { party: "host", ...
|
|
176
|
-
:
|
|
175
|
+
? { kind: "park_sla_expired", who: { party: "host", ...(facts.approver !== undefined ? { approver: facts.approver } : {}) }, when: Date.now() }
|
|
176
|
+
: settledByPerson(plainPolicyOutcome.decision === "allow" ? "human_allowed" : "human_refused", facts.approver, plainPolicyOutcome.decision === "deny" ? plainPolicyOutcome.reason : undefined);
|
|
177
177
|
plainPolicyOutcome = { ...plainPolicyOutcome, gateOutcome: mintGateOutcome({ ...(plainPolicyOutcome.decision === "deny" ? { deniedBy: "ask_resolution" } : {}), settled: { settlement, origin: parkedOrigin } }) };
|
|
178
178
|
}
|
|
179
179
|
const outcomeForStore = plainPolicyOutcome ?? plainReviewOutcome ?? plainParkOutcome;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { startTimeout } from "./clock-and-limits.js";
|
|
2
|
+
import { forwardSafely } from "./forward-sink.js";
|
|
2
3
|
export function runClockAndContent(input) {
|
|
3
4
|
const { spec, prepared, queue, internals, rs, ident, parentToolCallId, startedToolCallIds } = input;
|
|
4
5
|
const effectiveTimeoutMs = spec.limits?.maxWalltimeMs;
|
|
@@ -7,13 +8,8 @@ export function runClockAndContent(input) {
|
|
|
7
8
|
const timeout = startTimeout(prepared.harness, prepared.abortController, walltimeMonotonicDeadline !== undefined ? walltimeMonotonicDeadline - performance.now() : undefined, prepared.suspendForResource !== undefined);
|
|
8
9
|
const pushContent = (e) => {
|
|
9
10
|
queue.push(e);
|
|
10
|
-
if (parentToolCallId !== undefined
|
|
11
|
-
|
|
12
|
-
internals.onForwardEvent(e);
|
|
13
|
-
}
|
|
14
|
-
catch {
|
|
15
|
-
}
|
|
16
|
-
}
|
|
11
|
+
if (parentToolCallId !== undefined)
|
|
12
|
+
forwardSafely(internals, e);
|
|
17
13
|
};
|
|
18
14
|
const ownCommittedTailRef = { current: undefined };
|
|
19
15
|
const emitCommitted = (entryId, role, toolCallId) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createSafeNotifier, observeThenableRejection } from "../safe-notify.js";
|
|
2
|
+
import { forwardSafely } from "./forward-sink.js";
|
|
2
3
|
import { emitTrace } from "../trace.js";
|
|
3
4
|
import { primaryActivityArg } from "../arg-summary.js";
|
|
4
5
|
import { readDegradation } from "../../brain/degrading.js";
|
|
@@ -58,17 +59,20 @@ export function createHarnessHandlers(input) {
|
|
|
58
59
|
}
|
|
59
60
|
if (event.entryId !== undefined && m.role === "user")
|
|
60
61
|
prepared.fileHistoryBoundary?.begin(event.entryId);
|
|
61
|
-
if (event.entryId !== undefined && m.role === "user" && prepared.
|
|
62
|
-
const pr = prepared.gitStatusRef.pendingReceipt;
|
|
62
|
+
if (event.entryId !== undefined && m.role === "user" && prepared.frameReceipts.pending.length > 0) {
|
|
63
63
|
const c = m.content;
|
|
64
64
|
const text = typeof c === "string"
|
|
65
65
|
? c
|
|
66
66
|
: Array.isArray(c) && c.length >= 1 && c[0].type === "text"
|
|
67
67
|
? c[0].text
|
|
68
68
|
: undefined;
|
|
69
|
-
if (text
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
if (text !== undefined) {
|
|
70
|
+
const settled = prepared.frameReceipts.pending.filter((r) => r.text === text);
|
|
71
|
+
if (settled.length > 0) {
|
|
72
|
+
prepared.frameReceipts.pending = prepared.frameReceipts.pending.filter((r) => r.text !== text);
|
|
73
|
+
for (const r of settled)
|
|
74
|
+
r.commit(event.entryId);
|
|
75
|
+
}
|
|
72
76
|
}
|
|
73
77
|
}
|
|
74
78
|
if (rs.degrade.degraded === undefined && m.role === "assistant") {
|
|
@@ -309,11 +313,7 @@ export function createHarnessHandlers(input) {
|
|
|
309
313
|
...ident(),
|
|
310
314
|
};
|
|
311
315
|
queue.push(progress);
|
|
312
|
-
|
|
313
|
-
internals?.onForwardEvent?.(progress);
|
|
314
|
-
}
|
|
315
|
-
catch {
|
|
316
|
-
}
|
|
316
|
+
forwardSafely(internals, progress);
|
|
317
317
|
}
|
|
318
318
|
emitTrace(rs.telemetry.tracer, () => ({ kind: "turn.end", version: 1, taskId: rs.telemetry.taskId, turn: stats.turns, ts: Date.now() }));
|
|
319
319
|
rs.turn.turnUsage = undefined;
|
|
@@ -26,7 +26,9 @@ import { maybeHumanRejectionHalt } from "./prepare-gate-stations.js";
|
|
|
26
26
|
import { nextHumanInputSeq } from "./steer-admission.js";
|
|
27
27
|
import { settleTeardownLeg } from "./teardown-bounded.js";
|
|
28
28
|
import { toolEndBodyFrom, toolResultMsg } from "./tool-end-body.js";
|
|
29
|
-
import {
|
|
29
|
+
import { announceListingTruncation } from "../skill-listing-budget.js";
|
|
30
|
+
import { attachmentEnvelopeTags, commitAgentListing, commitSkillsListing, reduceToolEnd, renderAgentListingFrame, renderOrphanedBackgroundTasks, renderSkillsListingFrame, stampWriteAnchor } from "./turn-attachments.js";
|
|
31
|
+
import { flushOwedAnnouncedSnapshot } from "./announce-once-ledger.js";
|
|
30
32
|
export async function runLeg(input) {
|
|
31
33
|
const { spec, queue, prepared, resume, rs, isDelegatedChild, entryActor, effectiveTimeoutMs, timeout, pushContent, ident, emitCommitted, writeFamilyOf, startedToolCallIds, announceWorkspaceMove, withBrainSinks, flushGitMirror, loopLatch, notificationLane, unsubscribeTaskNotifications, unsubGitRetry, unsubBoundary, unsub, runner, next } = input;
|
|
32
34
|
let final;
|
|
@@ -233,7 +235,8 @@ export async function runLeg(input) {
|
|
|
233
235
|
if (gitResumeDelivered !== undefined) {
|
|
234
236
|
const delivered = gitResumeDelivered;
|
|
235
237
|
prepared.gitStatusRef.protectedText = delivered.wrapped;
|
|
236
|
-
prepared.
|
|
238
|
+
prepared.frameReceipts.pending.push({
|
|
239
|
+
source: "git_status",
|
|
237
240
|
text: continuation,
|
|
238
241
|
commit: (entryId) => {
|
|
239
242
|
prepared.gitStatusRef.announced = { kind: delivered.kind, hash: delivered.hash, entryId };
|
|
@@ -241,7 +244,7 @@ export async function runLeg(input) {
|
|
|
241
244
|
rs.attach.attachmentsInjected += 1;
|
|
242
245
|
prepared.gitStatusRef.mirrorOwed = { kind: delivered.kind, hash: delivered.hash, entryId };
|
|
243
246
|
},
|
|
244
|
-
};
|
|
247
|
+
});
|
|
245
248
|
}
|
|
246
249
|
const pending = resume.cp.pendingAction;
|
|
247
250
|
const rejectionHalt = pending.kind === "tool_approval" && resume.outcome.gate === "policy_ask"
|
|
@@ -335,31 +338,33 @@ export async function runLeg(input) {
|
|
|
335
338
|
const attach = rs.attach.attachState;
|
|
336
339
|
if (rs.attach.agentListingOn && prepared.agentListing !== undefined) {
|
|
337
340
|
const listing = prepared.agentListing;
|
|
338
|
-
const
|
|
339
|
-
if (
|
|
341
|
+
const frame = renderAgentListingFrame(attach, listing.entries, listing.toolName, listing.models, listing.budget);
|
|
342
|
+
if (frame !== undefined) {
|
|
340
343
|
firstFrames.push({
|
|
341
344
|
source: "agent_listing",
|
|
342
|
-
body,
|
|
345
|
+
body: frame.text,
|
|
343
346
|
commit: () => {
|
|
344
347
|
commitAgentListing(attach, listing.entries, listing.models);
|
|
345
348
|
prepared.announcedListingsRef.agents = listing.entries.map((e) => e.name);
|
|
346
349
|
if (listing.models !== undefined)
|
|
347
350
|
prepared.announcedListingsRef.models = [...listing.models];
|
|
348
351
|
},
|
|
352
|
+
disclose: () => announceListingTruncation(runner.deps.onNotice, { listing: "agents", total: frame.listed, nameOnly: frame.nameOnly, dropped: frame.dropped, budget: listing.budget, sessionId: prepared.sessionId }),
|
|
349
353
|
});
|
|
350
354
|
}
|
|
351
355
|
}
|
|
352
356
|
if (rs.attach.skillsListingOn && prepared.skillsListing !== undefined) {
|
|
353
357
|
const listing = prepared.skillsListing;
|
|
354
|
-
const
|
|
355
|
-
if (
|
|
358
|
+
const frame = renderSkillsListingFrame(attach, listing.entries, listing.budget);
|
|
359
|
+
if (frame !== undefined) {
|
|
356
360
|
firstFrames.push({
|
|
357
361
|
source: "skills_listing",
|
|
358
|
-
body,
|
|
362
|
+
body: frame.text,
|
|
359
363
|
commit: () => {
|
|
360
364
|
commitSkillsListing(attach, listing.entries);
|
|
361
365
|
prepared.announcedListingsRef.skills = listing.entries.map((e) => e.name);
|
|
362
366
|
},
|
|
367
|
+
disclose: () => announceListingTruncation(runner.deps.onNotice, { listing: "skills", total: frame.listed, nameOnly: frame.nameOnly, dropped: frame.dropped, budget: listing.budget, sessionId: prepared.sessionId }),
|
|
363
368
|
});
|
|
364
369
|
}
|
|
365
370
|
}
|
|
@@ -415,7 +420,8 @@ export async function runLeg(input) {
|
|
|
415
420
|
if (delivered.standalone)
|
|
416
421
|
await prepared.harness.nextTurn(delivered.wrapped, { engineMinted: true });
|
|
417
422
|
prepared.gitStatusRef.protectedText = delivered.wrapped;
|
|
418
|
-
prepared.
|
|
423
|
+
prepared.frameReceipts.pending.push({
|
|
424
|
+
source: "git_status",
|
|
419
425
|
text: delivered.standalone ? delivered.wrapped : effectiveObjective,
|
|
420
426
|
commit: (entryId) => {
|
|
421
427
|
prepared.gitStatusRef.announced = { kind: delivered.kind, hash: delivered.hash, entryId };
|
|
@@ -423,15 +429,21 @@ export async function runLeg(input) {
|
|
|
423
429
|
rs.attach.attachmentsInjected += 1;
|
|
424
430
|
prepared.gitStatusRef.mirrorOwed = { kind: delivered.kind, hash: delivered.hash, entryId };
|
|
425
431
|
},
|
|
426
|
-
};
|
|
432
|
+
});
|
|
427
433
|
}
|
|
428
434
|
for (const f of firstFrames) {
|
|
429
|
-
|
|
430
|
-
|
|
435
|
+
prepared.frameReceipts.pending.push({
|
|
436
|
+
source: f.source,
|
|
437
|
+
text: effectiveObjective,
|
|
438
|
+
commit: () => {
|
|
439
|
+
f.commit();
|
|
440
|
+
queue.push({ type: "steering_injected", source: f.source, preview: redactThenCut(f.body, 220), ...ident() });
|
|
441
|
+
rs.attach.attachmentsInjected += 1;
|
|
442
|
+
prepared.frameReceipts.listingSnapshotOwed = true;
|
|
443
|
+
f.disclose();
|
|
444
|
+
},
|
|
445
|
+
});
|
|
431
446
|
}
|
|
432
|
-
rs.attach.attachmentsInjected += firstFrames.length;
|
|
433
|
-
if (firstFrames.length > 0 && prepared.announcedSnapshotRecovered)
|
|
434
|
-
await prepared.session.appendAnnouncedListing(prepared.announcedListingsRef).catch(() => undefined);
|
|
435
447
|
const enginePrefixChars = effectiveObjective.length - projectedObjective.length;
|
|
436
448
|
queue.push({
|
|
437
449
|
...buildHumanInputEvent({
|
|
@@ -475,6 +487,9 @@ export async function runLeg(input) {
|
|
|
475
487
|
timeout.clear();
|
|
476
488
|
prepared.lspDiagnostics?.registry.releaseRun(prepared.lspDiagnostics.runIdent);
|
|
477
489
|
prepared.toolProgressRef.current?.clear();
|
|
490
|
+
if (prepared.frameReceipts.listingSnapshotOwed) {
|
|
491
|
+
await settleTeardownLeg(() => flushOwedAnnouncedSnapshot(prepared), "announced-listing snapshot (leg exit)", (e) => runner.deps.onError?.(e, { phase: "degraded", sessionId: prepared.sessionId }));
|
|
492
|
+
}
|
|
478
493
|
prepared.abortController.abort();
|
|
479
494
|
prepared.releaseSignal();
|
|
480
495
|
strandedHumanAnswers = prepared.settleContentAskBindings();
|
|
@@ -12,6 +12,7 @@ import { emitTrace } from "../trace.js";
|
|
|
12
12
|
import { deliverEngineNotice } from "../types.js";
|
|
13
13
|
import { assembleResult } from "./assemble-result.js";
|
|
14
14
|
import { discloseUnconsumedHalt } from "./halt-attribution.js";
|
|
15
|
+
import { forwardSafely } from "./forward-sink.js";
|
|
15
16
|
import { TIMER_LATENESS_REPORT_MS } from "./clock-and-limits.js";
|
|
16
17
|
import { resumeDecisionWasNegative } from "./decide-continuation.js";
|
|
17
18
|
import { drainForwardedFramesBeforeDone, forwardsSubagentEvents } from "./prepare-run-refs.js";
|
|
@@ -276,11 +277,7 @@ export async function runSettleAndTeardown(input) {
|
|
|
276
277
|
...ident(),
|
|
277
278
|
};
|
|
278
279
|
queue.push(terminalTick);
|
|
279
|
-
|
|
280
|
-
internals?.onForwardEvent?.(terminalTick);
|
|
281
|
-
}
|
|
282
|
-
catch {
|
|
283
|
-
}
|
|
280
|
+
forwardSafely(internals, terminalTick);
|
|
284
281
|
}
|
|
285
282
|
if (manualCompactRef.waiters.length > 0) {
|
|
286
283
|
queue.push({ type: "compaction_outcome", outcome: "mooted", trigger: "manual", reason: "task_ending", ...ident() });
|
|
@@ -4,7 +4,8 @@ import { eventDefaultOn } from "../../prompt-assembly/event-registry.js";
|
|
|
4
4
|
import { DEFAULT_COMPACTION_INSTRUCTIONS, isCompactionManualCancel, maybeCompact, nextTrimForceBackoff, recordCompactionAndCheckRapidRefill } from "../auto-compaction.js";
|
|
5
5
|
import { emitTrace } from "../trace.js";
|
|
6
6
|
import { redactThenCut } from "../../agents/subagent-steps.js";
|
|
7
|
-
import { ATTACHMENT_BYTE_CAP, CHANGED_FILES_MAX, TOTAL_TOKENS_REMINDER_DEFAULT_MODE, attachmentEnvelopeTags, clipToBytes, collectDateChange, collectDueAttachments, collectInstructionsChange, commitAgentListing, commitInstructionsChange, commitSkillsListing, rebaseCadenceWindows,
|
|
7
|
+
import { ATTACHMENT_BYTE_CAP, CHANGED_FILES_MAX, TOTAL_TOKENS_REMINDER_DEFAULT_MODE, attachmentEnvelopeTags, clipToBytes, collectDateChange, collectDueAttachments, collectInstructionsChange, commitAgentListing, commitInstructionsChange, commitSkillsListing, isIntactSource, rebaseCadenceWindows, renderAgentListingFrame, renderMcpDroppedTools, renderMcpInstructionsDelta, selectMcpDroppedBatch, renderSkillsListingFrame, renderToolsDelta } from "./turn-attachments.js";
|
|
8
|
+
import { announceListingTruncation } from "../skill-listing-budget.js";
|
|
8
9
|
import { buildWorkingFileAttachments, centerAdoptionOption, contextInstructionFilesOption, emitInputTruncated, forkContextOption } from "./compaction-call-options.js";
|
|
9
10
|
import { hookSeatExpiredError, runHookSeat } from "../hooks.js";
|
|
10
11
|
import { sanitizeUntrustedText, SHELLED_BODY_ENVELOPE_TAGS } from "../untrusted-text.js";
|
|
@@ -202,6 +203,7 @@ export function createTurnBoundary(input) {
|
|
|
202
203
|
}
|
|
203
204
|
let boundaryAttachmentBytes = 0;
|
|
204
205
|
let attachmentsPayload;
|
|
206
|
+
const listingCommits = [];
|
|
205
207
|
if ((rs.attach.dateState !== undefined ||
|
|
206
208
|
rs.attach.instrState !== undefined ||
|
|
207
209
|
rs.attach.sizeGuidelineState !== undefined ||
|
|
@@ -213,6 +215,7 @@ export function createTurnBoundary(input) {
|
|
|
213
215
|
!prepared.abortController.signal.aborted) {
|
|
214
216
|
const due = [];
|
|
215
217
|
if (rs.attach.attachState !== undefined) {
|
|
218
|
+
const attachState = rs.attach.attachState;
|
|
216
219
|
const changedFilesOn = Boolean(rs.attach.attachmentsCfg?.changedFiles);
|
|
217
220
|
let changed;
|
|
218
221
|
if (changedFilesOn && prepared.detectExternalChanges !== undefined) {
|
|
@@ -263,6 +266,10 @@ export function createTurnBoundary(input) {
|
|
|
263
266
|
const undiscoveredTools = toolSearchReminderOn
|
|
264
267
|
? [...prepared.deferredToolNames].filter((n) => !prepared.activeTools.has(n)).sort()
|
|
265
268
|
: undefined;
|
|
269
|
+
const receiptPending = (source) => prepared.frameReceipts.pending.some((r) => r.source === source);
|
|
270
|
+
const agentListingDue = rs.attach.agentListingOn && prepared.agentListing !== undefined && !receiptPending("agent_listing");
|
|
271
|
+
const skillsListingDue = rs.attach.skillsListingOn && prepared.skillsListing !== undefined && !receiptPending("skills_listing");
|
|
272
|
+
const listingBudget = prepared.skillsListing?.budget ?? prepared.agentListing?.budget;
|
|
266
273
|
due.push(...collectDueAttachments(rs.attach.attachState, {
|
|
267
274
|
turn: stats.turns,
|
|
268
275
|
cadenceTurn: rs.counters.cadenceTurns,
|
|
@@ -306,14 +313,15 @@ export function createTurnBoundary(input) {
|
|
|
306
313
|
? { readdedToolsSwappedUnderStatic: pendingReaddedTools.filter((n) => prepared.staticFaceFor?.(n) !== true) }
|
|
307
314
|
: {}),
|
|
308
315
|
...(mcpToolsDelta !== undefined ? { mcpToolsDelta } : {}),
|
|
309
|
-
...(
|
|
316
|
+
...(agentListingDue
|
|
310
317
|
? {
|
|
311
318
|
agentListing: prepared.agentListing.entries,
|
|
312
319
|
agentToolName: prepared.agentListing.toolName,
|
|
313
320
|
...(prepared.agentListing.models !== undefined ? { agentModels: prepared.agentListing.models } : {}),
|
|
314
321
|
}
|
|
315
322
|
: {}),
|
|
316
|
-
...(
|
|
323
|
+
...(skillsListingDue ? { skillsListing: prepared.skillsListing.entries } : {}),
|
|
324
|
+
...(listingBudget !== undefined ? { listingBudget } : {}),
|
|
317
325
|
...(mcpAdds !== undefined || mcpRemovals !== undefined
|
|
318
326
|
? { mcpInstructions: { added: mcpAdds ?? [], removed: mcpRemovals ?? [] } }
|
|
319
327
|
: {}),
|
|
@@ -363,30 +371,36 @@ export function createTurnBoundary(input) {
|
|
|
363
371
|
announcedOnceDirty = true;
|
|
364
372
|
}
|
|
365
373
|
}
|
|
366
|
-
if (
|
|
374
|
+
if (agentListingDue && due.some((a) => a.source === "agent_listing")) {
|
|
367
375
|
const listing = prepared.agentListing;
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
prepared.announcedListingsRef.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
376
|
+
const frame = renderAgentListingFrame(attachState, listing.entries, listing.toolName, listing.models, listing.budget);
|
|
377
|
+
listingCommits.push({
|
|
378
|
+
source: "agent_listing",
|
|
379
|
+
commit: () => {
|
|
380
|
+
commitAgentListing(attachState, listing.entries, listing.models);
|
|
381
|
+
prepared.announcedListingsRef.agents = listing.entries.map((e) => e.name);
|
|
382
|
+
if (listing.models !== undefined)
|
|
383
|
+
prepared.announcedListingsRef.models = [...listing.models];
|
|
384
|
+
prepared.frameReceipts.listingSnapshotOwed = true;
|
|
385
|
+
announceListingTruncation(deps.runner.deps.onNotice, { listing: "agents", total: frame.listed, nameOnly: frame.nameOnly, dropped: frame.dropped, budget: listing.budget, sessionId: prepared.sessionId });
|
|
386
|
+
},
|
|
387
|
+
});
|
|
377
388
|
}
|
|
378
|
-
if (
|
|
389
|
+
if (skillsListingDue && due.some((a) => a.source === "skills_listing")) {
|
|
379
390
|
const listing = prepared.skillsListing;
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
391
|
+
const frame = renderSkillsListingFrame(attachState, listing.entries, listing.budget);
|
|
392
|
+
listingCommits.push({
|
|
393
|
+
source: "skills_listing",
|
|
394
|
+
commit: () => {
|
|
395
|
+
commitSkillsListing(attachState, listing.entries);
|
|
396
|
+
prepared.announcedListingsRef.skills = listing.entries.map((e) => e.name);
|
|
397
|
+
prepared.frameReceipts.listingSnapshotOwed = true;
|
|
398
|
+
announceListingTruncation(deps.runner.deps.onNotice, { listing: "skills", total: frame.listed, nameOnly: frame.nameOnly, dropped: frame.dropped, budget: listing.budget, sessionId: prepared.sessionId });
|
|
399
|
+
},
|
|
400
|
+
});
|
|
387
401
|
}
|
|
388
|
-
if (announcedOnceDirty
|
|
389
|
-
|
|
402
|
+
if (announcedOnceDirty)
|
|
403
|
+
prepared.frameReceipts.listingSnapshotOwed = true;
|
|
390
404
|
}
|
|
391
405
|
if (rs.attach.dateState !== undefined && rs.turn.lastTurnHadToolCalls) {
|
|
392
406
|
const today = prepared.dateChange.today();
|
|
@@ -429,7 +443,8 @@ export function createTurnBoundary(input) {
|
|
|
429
443
|
if (due.length > 0) {
|
|
430
444
|
attachmentsPayload = due.map((a) => mintSystemReminder(sanitizeUntrustedText(a.body, attachmentEnvelopeTags(a.source)), prepared.reminderMark)).join("\n");
|
|
431
445
|
for (const a of due)
|
|
432
|
-
|
|
446
|
+
if (!isIntactSource(a.source))
|
|
447
|
+
boundaryAttachmentBytes += Buffer.byteLength(a.body, "utf8");
|
|
433
448
|
rs.attach.attachmentsInjected += due.length;
|
|
434
449
|
for (const a of due) {
|
|
435
450
|
queue.push({ type: "steering_injected", source: a.source, preview: redactThenCut(a.body, 220), ...ident() });
|
|
@@ -473,7 +488,11 @@ export function createTurnBoundary(input) {
|
|
|
473
488
|
}
|
|
474
489
|
if ((attachmentsPayload !== undefined || batchContextBlock !== undefined) && prepared.batchHaltRef.current === undefined) {
|
|
475
490
|
const payload = attachmentsPayload !== undefined && batchContextBlock !== undefined ? `${attachmentsPayload}\n${batchContextBlock}` : (attachmentsPayload ?? batchContextBlock);
|
|
476
|
-
|
|
491
|
+
for (const c of listingCommits)
|
|
492
|
+
prepared.frameReceipts.pending.push({ source: c.source, text: payload, commit: c.commit });
|
|
493
|
+
void prepared.harness.steer(payload, { engineMinted: true }).catch(() => {
|
|
494
|
+
prepared.frameReceipts.pending = prepared.frameReceipts.pending.filter((r) => r.text !== payload);
|
|
495
|
+
});
|
|
477
496
|
}
|
|
478
497
|
const forceManual = manualCompactRef.requested;
|
|
479
498
|
if ((!withinTaskCompaction && !forceManual) ||
|
|
@@ -50,6 +50,7 @@ import { runToolMountFacts } from "./run-tool-mount-facts.js";
|
|
|
50
50
|
import { runReasoningSeat } from "./run-reasoning-seat.js";
|
|
51
51
|
import { runClockAndContent } from "./run-clock-and-content.js";
|
|
52
52
|
import { createToolProgressLane } from "./tool-progress-lane.js";
|
|
53
|
+
import { createForwardSinkScope } from "./forward-sink.js";
|
|
53
54
|
import { runBrainSinks } from "./run-brain-sinks.js";
|
|
54
55
|
import { runCompactionMachinery } from "./run-compaction-machinery.js";
|
|
55
56
|
import { runStopAndFinalVerify } from "./run-stop-and-final-verify.js";
|
|
@@ -344,7 +345,7 @@ export class Runner {
|
|
|
344
345
|
manualCompactRef,
|
|
345
346
|
taskIdRef,
|
|
346
347
|
resume,
|
|
347
|
-
internals: { ...(internals ?? {}), detachHub },
|
|
348
|
+
internals: { ...(internals ?? {}), detachHub, forwardScope: createForwardSinkScope(this.deps.onNotice) },
|
|
348
349
|
notifyRef,
|
|
349
350
|
captureOptOutRef,
|
|
350
351
|
entryActor,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type TSchema } from "typebox";
|
|
2
2
|
import type { AgentTool } from "../../internal/harness-types.js";
|
|
3
3
|
import type { SkillManifest } from "../types.js";
|
|
4
|
+
import { type ResolvedSkillListingBudget } from "../skill-listing-budget.js";
|
|
4
5
|
import type { ActiveSkillScope } from "./active-skill-scope.js";
|
|
5
6
|
/** Reserved name of the injected structured-output tool (CC 2.1.187 `StructuredOutput`; batch-A rename — old
|
|
6
7
|
* "submit_output" is canonicalized for pre-rename durable state). */
|
|
@@ -57,15 +58,6 @@ export declare const SKILL_TOOL_NAME = "Skill";
|
|
|
57
58
|
* an oversized skill is excluded from the disclosure block and the tool, with an operator-visible config error. The compaction-time retention caps are a
|
|
58
59
|
* different door, deliberately. */
|
|
59
60
|
export declare const SKILL_CONTENT_MAX_CHARS: number;
|
|
60
|
-
/** Total listing-block cap in UTF-8 BYTES — [c209-C] R2 C4①: the old 8000-CHAR cap measured a
|
|
61
|
-
* different coordinate than the bundle's `ATTACHMENT_BYTE_CAP` (8192 UTF-8 bytes) and counted only
|
|
62
|
-
* the description lines (fence framing + name-only tail rode free), so a near-cap frame could
|
|
63
|
-
* exceed the bundle cap, get clip-mangled every boundary, never pass the intact-survival commit
|
|
64
|
-
* predicate, and REPLAY FOREVER. The cap is now enforced byte-exact over the WHOLE rendered block
|
|
65
|
-
* (fences, headers, markers, joiners included), so `buildSkillsBlock` output always fits the
|
|
66
|
-
* bundle cap solo and an intact commit is always reachable. MUST stay ≤ ATTACHMENT_BYTE_CAP
|
|
67
|
-
* (turn-attachments.ts; not imported here — that module imports this one — pinned by test instead). */
|
|
68
|
-
export declare const SKILLS_BLOCK_MAX_BYTES = 8000;
|
|
69
61
|
/** Total per-invoke cap for a skill's inlined attachments (`SkillSpec.files`) — an ATTACHMENT-face budget, distinct from the (gone) body truncation door:
|
|
70
62
|
* the body is delivered untruncated at invoke time (CC parity), while attachments ride along bounded and truncation-disclosed. */
|
|
71
63
|
export declare const SKILL_ATTACHMENTS_MAX_CHARS = 50000;
|
|
@@ -123,31 +115,51 @@ export declare const SKILLS_LISTING_PROBE_HEADER = "The following skills are ava
|
|
|
123
115
|
/** [c209-C] One skill's disclosure line — `- name: description[(files 尾缀)]` with the per-skill
|
|
124
116
|
* description cap. Single-sourced so the skills_listing DELTA frame (turn-attachments) renders adds
|
|
125
117
|
* with byte-identical line shape to the initial `<skills>` block. */
|
|
126
|
-
export declare function skillListingLine(s: SkillListingEntry): string;
|
|
118
|
+
export declare function skillListingLine(s: SkillListingEntry, descMaxChars?: number): string;
|
|
119
|
+
/** What one {@link renderSkillsBlock} call produced: the block, and which skills the budget degraded. */
|
|
120
|
+
export interface SkillsBlockRender {
|
|
121
|
+
/** The rendered block — what {@link buildSkillsBlock} returns. */
|
|
122
|
+
text: string;
|
|
123
|
+
/** Skills listed WITHOUT their description (tier B's unspent candidates, or every listed name under
|
|
124
|
+
* tier C), in display order. Raw names: this is host-facing structured data, not prompt text. */
|
|
125
|
+
nameOnly: readonly string[];
|
|
126
|
+
/** Skills the block could not list at all (tier C's overflow tail). The `Skill` tool still serves them. */
|
|
127
|
+
dropped: readonly string[];
|
|
128
|
+
}
|
|
129
|
+
/** The text-only face of {@link renderSkillsBlock} — the `<skills>` BLOCK's face, not the listing
|
|
130
|
+
* family's: the drift frame renders its own arms through the shared tier engine
|
|
131
|
+
* ({@link renderSkillLinesWithin}), which is where "one ruler for every frame" lives. */
|
|
132
|
+
export declare function buildSkillsBlock(skills: ReadonlyArray<SkillListingEntry>, budget?: ResolvedSkillListingBudget): string | undefined;
|
|
127
133
|
/** Render the `<skills>` disclosure block (metadata only — bodies stay behind the tool).
|
|
128
134
|
* [c209-C] REVERSAL: no longer composed into the stable system prompt — this is now the RENDERER for
|
|
129
135
|
* the `skills_listing` initial frame (first-user-turn reminder / boundary re-announce), so the
|
|
130
136
|
* cached prefix carries zero skill bytes (design/C §2.3; CC 209 classic ships the same listing as a
|
|
131
|
-
* first-turn reminder
|
|
137
|
+
* first-turn reminder). `budget` absent ⇒ the seat reader's no-knob answer ({@link SKILL_LISTING_DEFAULT_BUDGET}).
|
|
138
|
+
*
|
|
139
|
+
* The fence and its four header lines are this lane's frame; the budget arithmetic and the three
|
|
140
|
+
* degradation tiers belong to {@link renderSkillLinesWithin}, which the drift frame renders through
|
|
141
|
+
* as well. {@link buildSkillsBlock} is the text-only face; this one additionally reports what the
|
|
142
|
+
* budget cost, for the disclosure lane. */
|
|
143
|
+
export declare function renderSkillsBlock(skills: ReadonlyArray<SkillListingEntry>, budget?: ResolvedSkillListingBudget): SkillsBlockRender | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* The skills VOCABULARY of the one folding engine (`listing-fold.ts` `foldListingWithin`): the full
|
|
146
|
+
* `- name: description` line, the name-only line, the block's cap marker and its overflow count line,
|
|
147
|
+
* measured byte-exact inside a caller-supplied FRAME — the engine both {@link renderSkillsBlock} and
|
|
148
|
+
* the drift frame's ADD arm render through, so the initial `<skills>` block and a later "new skills are
|
|
149
|
+
* now available" announcement degrade by the same rules against the same number — the number the seat
|
|
150
|
+
* reader resolved (`@contract skills.listing_budget_enforced_as_declared`), which is the frame's whole
|
|
151
|
+
* bound: the listing is an intact-class attachment, so no delivery lane measures it a second time.
|
|
132
152
|
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
* the ones that lose their description are the low-priority ones, not the alphabetically late
|
|
144
|
-
* ones. This replaces the prior "longest full-line PREFIX" cut, which had two defects the
|
|
145
|
-
* anchor does not: the surviving set was decided by name sort order (a skill named `zip-deploy`
|
|
146
|
-
* lost its description to `aardvark-lint` for no reason connected to either skill), and one
|
|
147
|
-
* oversized description truncated the block at itself instead of being skipped over;
|
|
148
|
-
* C. even all-name-only overflows (pathological name census) → list what fits and close with an
|
|
149
|
-
* honest `(… +N more skills …)` count line — the tool still serves all of them. */
|
|
150
|
-
export declare function buildSkillsBlock(skills: ReadonlyArray<SkillListingEntry>): string | undefined;
|
|
153
|
+
* Tier B follows CC 220 `sbs` @317547-317586 (reserve the marker + every name-only line, then spend
|
|
154
|
+
* the slack on descriptions in {@link SkillListingEntry.declaredRank} order); tier C closes with an
|
|
155
|
+
* honest `(… +N more skills …)` count line — the tool still serves all of them.
|
|
156
|
+
*/
|
|
157
|
+
export declare function renderSkillLinesWithin(skills: ReadonlyArray<SkillListingEntry>, opts: {
|
|
158
|
+
/** The whole frame's byte budget — honoured as given; the seat reader is the one place that decides it. */
|
|
159
|
+
blockMaxBytes: number;
|
|
160
|
+
descMaxChars: number;
|
|
161
|
+
frame: (lines: readonly string[]) => string;
|
|
162
|
+
}): SkillsBlockRender | undefined;
|
|
151
163
|
/**
|
|
152
164
|
* The injected `skill` tool: returns a skill's full body as a tool result.
|
|
153
165
|
*
|