@tangle-network/agent-runtime 0.193.1 → 0.194.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/dist/{activation-BismttgN.js → activation-BQFIiyUG.js} +3 -3
- package/dist/{activation-BismttgN.js.map → activation-BQFIiyUG.js.map} +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +2 -2
- package/dist/candidate-execution/index.js +4 -4
- package/dist/{candidate-execution-BSkZErxD.js → candidate-execution-B6CDW-fp.js} +4 -4
- package/dist/{candidate-execution-BSkZErxD.js.map → candidate-execution-B6CDW-fp.js.map} +1 -1
- package/dist/{conversation-DILnmy84.js → conversation-BXPWMOSd.js} +4 -5
- package/dist/{conversation-DILnmy84.js.map → conversation-BXPWMOSd.js.map} +1 -1
- package/dist/conversation.d.ts +1 -1
- package/dist/conversation.js +1 -1
- package/dist/{coordination-driver-DujHiIGa.js → coordination-driver-iSN-m3VX.js} +281 -244
- package/dist/coordination-driver-iSN-m3VX.js.map +1 -0
- package/dist/{authoring-DWiqKSDY.js → delegate-DCC2muUd.js} +56 -13
- package/dist/delegate-DCC2muUd.js.map +1 -0
- package/dist/delegation-status-BlsbSeOB.js +358 -0
- package/dist/delegation-status-BlsbSeOB.js.map +1 -0
- package/dist/durable.d.ts +2 -2
- package/dist/durable.js +3 -3
- package/dist/{environment-provider-DEwsolvi.js → environment-provider-Dr-wfnHg.js} +422 -8
- package/dist/environment-provider-Dr-wfnHg.js.map +1 -0
- package/dist/{environment-provider-DpPGJfK-.d.ts → environment-provider-adVa6X7a.d.ts} +2 -2
- package/dist/environment-provider.d.ts +1 -1
- package/dist/environment-provider.js +1 -1
- package/dist/{graph-DORfp9WX.js → graph-DghidDx5.js} +138 -5
- package/dist/graph-DghidDx5.js.map +1 -0
- package/dist/graph.d.ts +3 -3
- package/dist/graph.js +4 -5
- package/dist/graph.js.map +1 -1
- package/dist/{improve-Bn1zpWHF.d.ts → improve-COGzLCiY.d.ts} +3 -3
- package/dist/{improvement-cycle-BbsiYcpH.js → improvement-cycle-DeS1ZC5B.js} +6 -6
- package/dist/{improvement-cycle-BbsiYcpH.js.map → improvement-cycle-DeS1ZC5B.js.map} +1 -1
- package/dist/{index-DV1lzp9p.d.ts → index-BEPjOPwH.d.ts} +49 -50
- package/dist/{index-Vz-13VZq.d.ts → index-CrBgLCIf.d.ts} +4 -4
- package/dist/{index-RM2oRI9s.d.ts → index-DO6DHgRP.d.ts} +2 -2
- package/dist/index.d.ts +8 -8
- package/dist/index.js +13 -13
- package/dist/intelligence.d.ts +5 -5
- package/dist/intelligence.js +6 -6
- package/dist/{executable-spec-DxuiDFAU.js → jsonl-file-Bh1Q9nt0.js} +59 -3
- package/dist/jsonl-file-Bh1Q9nt0.js.map +1 -0
- package/dist/kernel.d.ts +6 -6
- package/dist/kernel.js +11 -12
- package/dist/{knowledge-RW1pbZCH.js → knowledge-B5okOzBQ.js} +6 -6
- package/dist/{knowledge-RW1pbZCH.js.map → knowledge-B5okOzBQ.js.map} +1 -1
- package/dist/knowledge.d.ts +1 -1
- package/dist/knowledge.js +1 -1
- package/dist/{loop-runner-bin-CGraqNiA.d.ts → loop-runner-bin-Clc5IAwu.d.ts} +3 -3
- package/dist/{loop-runner-bin-sBwcyQTc.js → loop-runner-bin-U1J6x_UF.js} +3 -3
- package/dist/{loop-runner-bin-sBwcyQTc.js.map → loop-runner-bin-U1J6x_UF.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/{materialization-CekWK6OO.js → materialization-vZssF9Nx.js} +28 -3
- package/dist/materialization-vZssF9Nx.js.map +1 -0
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +4 -4
- package/dist/mcp/index.js +8 -8
- package/dist/mcp/index.js.map +1 -1
- package/dist/{openai-tools-6jUqkGG7.js → openai-tools-DmvmaG0a.js} +2 -2
- package/dist/{openai-tools-6jUqkGG7.js.map → openai-tools-DmvmaG0a.js.map} +1 -1
- package/dist/{prepare-B5fJ7mLS.js → prepare-C29kNAon.js} +9 -14
- package/dist/prepare-C29kNAon.js.map +1 -0
- package/dist/primeintellect/index.d.ts +1 -1
- package/dist/profiles.js +1 -1
- package/dist/{protected-model-port-B0xFSAjt.js → protected-model-port-CKYND416.js} +2 -2
- package/dist/{protected-model-port-B0xFSAjt.js.map → protected-model-port-CKYND416.js.map} +1 -1
- package/dist/{provision-supervisor-CddfH9mg.js → provision-supervisor-CRPbnJiB.js} +6 -8
- package/dist/{provision-supervisor-CddfH9mg.js.map → provision-supervisor-CRPbnJiB.js.map} +1 -1
- package/dist/{redact-D0OzQsyt.js → redact-BOU77QfQ.js} +1013 -24
- package/dist/redact-BOU77QfQ.js.map +1 -0
- package/dist/{researcher-hgPa5p9i.js → researcher-Cp4JRbFp.js} +2 -2
- package/dist/researcher-Cp4JRbFp.js.map +1 -0
- package/dist/{runtime-V91N6sPc.d.ts → runtime-B8x43nGP.d.ts} +5 -4
- package/dist/{runtime-ZM4i-jEF.js → runtime-BVrqSu0-.js} +22 -21
- package/dist/{runtime-ZM4i-jEF.js.map → runtime-BVrqSu0-.js.map} +1 -1
- package/dist/server-D6XmE1Du.js +1311 -0
- package/dist/server-D6XmE1Du.js.map +1 -0
- package/dist/{stream-agent-turn-1ahpdeIo.d.ts → stream-agent-turn-B-gtBlOy.d.ts} +2 -2
- package/dist/{stream-agent-turn-DWWe_7bh.js → stream-agent-turn-DOtEsvCV.js} +3 -3
- package/dist/{stream-agent-turn-DWWe_7bh.js.map → stream-agent-turn-DOtEsvCV.js.map} +1 -1
- package/dist/{structural-rollout-CktnUTCC.js → structural-rollout-BcPXFzVb.js} +16 -43
- package/dist/structural-rollout-BcPXFzVb.js.map +1 -0
- package/dist/{supervise-Dj6zd2C7.js → supervise-C0V3pZXK.js} +154 -1961
- package/dist/supervise-C0V3pZXK.js.map +1 -0
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +13 -13
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-CGez_ZHQ.d.ts → types-B_pNTBjK.d.ts} +5 -2
- package/dist/{workspace-archive-yAPDklLV.js → workspace-archive-BCezkeIk.js} +2 -2
- package/dist/{workspace-archive-yAPDklLV.js.map → workspace-archive-BCezkeIk.js.map} +1 -1
- package/package.json +1 -1
- package/skills/codemode/SKILL.md +2 -2
- package/skills/supervise/SKILL.md +24 -6
- package/dist/authoring-DWiqKSDY.js.map +0 -1
- package/dist/coordination-driver-DujHiIGa.js.map +0 -1
- package/dist/environment-provider-DEwsolvi.js.map +0 -1
- package/dist/executable-spec-DxuiDFAU.js.map +0 -1
- package/dist/graph-DORfp9WX.js.map +0 -1
- package/dist/jsonl-file-CDfsCI5s.js +0 -59
- package/dist/jsonl-file-CDfsCI5s.js.map +0 -1
- package/dist/materialization-CekWK6OO.js.map +0 -1
- package/dist/prepare-B5fJ7mLS.js.map +0 -1
- package/dist/redact-D0OzQsyt.js.map +0 -1
- package/dist/researcher-hgPa5p9i.js.map +0 -1
- package/dist/snapshot-CTAf4uuA.js +0 -26
- package/dist/snapshot-CTAf4uuA.js.map +0 -1
- package/dist/spawn-journal-B9eTmVAn.js +0 -999
- package/dist/spawn-journal-B9eTmVAn.js.map +0 -1
- package/dist/structural-rollout-CktnUTCC.js.map +0 -1
- package/dist/supervise-Dj6zd2C7.js.map +0 -1
- package/dist/util-mCNUeboW.js +0 -419
- package/dist/util-mCNUeboW.js.map +0 -1
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as assertBoundaryBinding, B as copyControlRef, C as runtimeOwnedScopeOwnerRuntime, D as detachedSnapshot, F as assertSequence, G as exactSessionCancel, H as exactContinuedControlRef, I as assertStableText, J as hasDurableCancel, K as exactSessionResult, L as assertWaitDuration, M as assertEventBinding, N as assertInteractionBinding, O as RetainedRunProviderContractError, P as assertResultBinding, R as awaitAbortable$1, S as runtimeOwnedPendingExecutorMaterialization, T as unknownMaterializationReceipt, U as exactControlRef, V as delay, W as exactSession, X as sameControlCoordinates, Y as isTerminalSessionStatus, Z as freshTurnInput, _ as runtimeOwnedDeferredExecutorRuntime, a as authoredProfileDigest, b as runtimeOwnedExecutorMaterialization, c as knownExecutionBindingReceipt, g as recordRuntimeOwnedProviderModel, h as recordRuntimeOwnedProviderIdentityConflict, j as assertCanonicalEventBinding, k as abortError, l as knownMaterializationReceipt, m as recordRuntimeOwnedProviderDispatchNotStarted, n as attestRuntimeOwnedExecutor, o as finalizeRuntimeOwnedPendingExecutor, p as recordRuntimeOwnedProviderAttemptStart, q as freezeControlRef, r as attestRuntimeOwnedPendingExecutor, s as inheritRuntimeOwnedExecutorAttestation, t as attestRuntimeOwnedDeferredExecutor, u as newExecutionAttemptId, w as unknownExecutionBindingReceipt, x as runtimeOwnedExecutorProviderEvidence, y as runtimeOwnedExecutorExecutionBinding, z as cancellationRequest } from "./materialization-vZssF9Nx.js";
|
|
2
2
|
import { c as RetainedInteractiveAdmissionError, d as RetainedRunDispatchBindingError, f as RuntimeRunStateError, l as RetainedInteractiveBindingError, m as ValidationError, r as BackendTransportError, u as RetainedRunAdmissionError } from "./errors-CDZ8XsVj.js";
|
|
3
|
-
import { n as detachedSnapshot } from "./snapshot-CTAf4uuA.js";
|
|
4
|
-
import { _ as captureWorkerTraceEvidence, a as aggregateProviderModelEvidence, c as loadSpawnForest, d as replaySpawnTree, f as attestNestedDriverTreeOwner, h as runtimeOwnedNestedDriverTreeRoot, l as materializeTreeView, m as nestedDriverTreeRoot, n as FileSpawnJournal, o as closesCursorSlot, p as driverRuntime, u as pendingWaits, x as contentAddress } from "./spawn-journal-B9eTmVAn.js";
|
|
5
|
-
import { _ as throwIfAborted, a as cloneTokenUsage, b as zeroSpend, d as randomSuffix, f as randomUuid, g as throwAbort, h as stringifySafe, l as mapWithConcurrency, m as sleep, n as addTokenUsage, o as deleteBoxSafe, p as roundBoxMinutes, r as chargedTokens, s as hasCompleteCacheBreakdown, t as addSpend, u as promptCacheTokenClasses, v as unmeteredSpend, x as zeroTokenUsage, y as withTimeout } from "./util-mCNUeboW.js";
|
|
6
3
|
import { _ as parseCodexUsageRecord, c as mapSandboxToolEvent, d as sandboxProgressEvents, h as parseCanonicalTransportEvent, i as createSandboxUsageLedger, l as notifySandboxEventObserver, m as extractTransportEventIdentity, r as createSandboxToolPartState, t as assertSandboxServedModel, u as sandboxEventServedBackend } from "./sandbox-events-DWeQRWxg.js";
|
|
7
|
-
import { n as executableAgentSpecSnapshot, r as projectSandboxOutcome, t as
|
|
4
|
+
import { a as executableAgentProfileSnapshot, i as writeAllBytes, n as parseCommittedJsonLines, o as executableAgentSpecSnapshot, r as prepareJsonlAppend, s as projectSandboxOutcome, t as isNoEntError } from "./jsonl-file-Bh1Q9nt0.js";
|
|
8
5
|
import { a as concreteProfileModel, c as profileModelExecutionSettings, d as agentHarness, l as profileProviderModel, o as enforceTokenLimits, s as profileBridgeWireModel, t as assertExecutableAgentProfile, u as resolveRouterRetryPolicy } from "./model-policy-Wf2MxXJ9.js";
|
|
9
|
-
import { c as
|
|
6
|
+
import { A as runAbortable, C as throwIfAborted, D as zeroTokenUsage, E as zeroSpend, O as abortError$1, S as throwAbort, T as withTimeout, _ as randomSuffix, b as sleep, c as addTokenUsage, d as cloneTokenUsage, f as deleteBoxSafe, g as promptCacheTokenClasses, h as mapWithConcurrency, i as resolveAgentEnvironmentProvider, k as linkAbort, l as chargedTokens, n as providerAsExecutor, p as hasCompleteCacheBreakdown, r as providerAsSandboxClient, s as addSpend, u as cloneSpend, v as randomUuid, w as unmeteredSpend, x as stringifySafe, y as roundBoxMinutes } from "./environment-provider-Dr-wfnHg.js";
|
|
10
7
|
import { i as notifyRuntimeHookEvent } from "./runtime-hooks-tXpAarhW.js";
|
|
11
8
|
import { n as assertNoSymlinkDescendant, r as publishExclusiveDurableFile } from "./durable-file-D24y9zg7.js";
|
|
12
9
|
import { AGENT_PROFILE_MATERIALIZATION_AXES, AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentNativeContextContinuationResultSchema, AgentTurnInputSchema, AgentTurnResultSchema, ContextTransferRequestSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, REASONING_EFFORTS, RuntimeEventEnvelopeSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionRunRef, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, exactAgentInteractiveSessionStart, harnessTypeSchema, nativeContextContinuationTurnDigest, nativeReasoningControl, profileMaterializationAxes, profileMaterializationAxes as profileMaterializationAxes$1, renderInputPartsAsText, sha256DigestSchema } from "@tangle-network/agent-interface";
|
|
13
|
-
import { estimateCost, isModelPriced } from "@tangle-network/agent-eval";
|
|
10
|
+
import { estimateCost, isModelPriced, isToolSpan, toolSpansToTraceAnalysisStore } from "@tangle-network/agent-eval";
|
|
14
11
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
15
12
|
import { appendFileSync, constants, createReadStream, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
16
13
|
import { access, chmod, copyFile, mkdir, mkdtemp, open, readFile, readdir, realpath, rm, rmdir, stat, symlink, writeFile } from "node:fs/promises";
|
|
@@ -649,7 +646,6 @@ function harnessProfileModel(harness, profile) {
|
|
|
649
646
|
if (provider !== nativeProvider) throw new Error(`harnessInvocation: ${harness} cannot materialize model provider ${JSON.stringify(provider)}; expected ${nativeProvider}`);
|
|
650
647
|
return model;
|
|
651
648
|
}
|
|
652
|
-
const DEFAULT_TIMEOUT_MS = 300 * 1e3;
|
|
653
649
|
const DEFAULT_MAX_OUTPUT_BYTES = 64 * 1024 * 1024;
|
|
654
650
|
const processKillGraceMs = 250;
|
|
655
651
|
const processGroupExitConfirmMs = 1e3;
|
|
@@ -713,7 +709,7 @@ async function runLocalHarness(options) {
|
|
|
713
709
|
if (options.codexReproducible && harness !== "codex") throw new Error("runLocalHarness: codexReproducible requires the Codex harness");
|
|
714
710
|
if (options.codexReproducible && !isSupportedCodexPlatform()) throw new Error(`runLocalHarness: codexReproducible does not support ${process.platform}/${process.arch}; supported: linux and darwin on x64 or arm64`);
|
|
715
711
|
if (options.codexReadDeniedPaths !== void 0 && !options.codexReproducible) throw new Error("runLocalHarness: codexReadDeniedPaths requires codexReproducible");
|
|
716
|
-
const timeoutMs = options.timeoutMs
|
|
712
|
+
const timeoutMs = options.timeoutMs;
|
|
717
713
|
const maxOutputBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
|
|
718
714
|
if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes < 0) throw new Error("runLocalHarness: maxOutputBytes must be a non-negative safe integer");
|
|
719
715
|
const spawnImpl = options.spawn ?? spawn;
|
|
@@ -812,7 +808,7 @@ async function runLocalHarness(options) {
|
|
|
812
808
|
}
|
|
813
809
|
return termination;
|
|
814
810
|
};
|
|
815
|
-
timer = timeoutMs > 0 ? setTimeout(() => {
|
|
811
|
+
timer = timeoutMs !== void 0 && timeoutMs > 0 ? setTimeout(() => {
|
|
816
812
|
timedOut = true;
|
|
817
813
|
terminate();
|
|
818
814
|
}, timeoutMs) : null;
|
|
@@ -6018,6 +6014,996 @@ function priceUnreceiptedWork(work) {
|
|
|
6018
6014
|
};
|
|
6019
6015
|
}
|
|
6020
6016
|
//#endregion
|
|
6017
|
+
//#region src/durable/content-address.ts
|
|
6018
|
+
/** Stable content address shared by result and trace artifacts. */
|
|
6019
|
+
function contentAddress(artifact) {
|
|
6020
|
+
return `sha256:${createHash("sha256").update(stableStringify(artifact), "utf-8").digest("hex")}`;
|
|
6021
|
+
}
|
|
6022
|
+
function stableStringify(value) {
|
|
6023
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
6024
|
+
if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
|
|
6025
|
+
return `{${Object.entries(value).filter(([, v]) => v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
6026
|
+
}
|
|
6027
|
+
//#endregion
|
|
6028
|
+
//#region src/runtime/supervise/trace-evidence.ts
|
|
6029
|
+
/**
|
|
6030
|
+
* Durable structured tool evidence for supervised workers.
|
|
6031
|
+
*
|
|
6032
|
+
* The executor-owned `TraceSource` is collected before teardown, snapshotted into the shared
|
|
6033
|
+
* content-addressed blob store, and only then referenced by a settlement. Analysis reconstructs
|
|
6034
|
+
* agent-eval's bounded `TraceAnalysisStore` from those exact bytes. Worker output is never accepted
|
|
6035
|
+
* as a substitute for tool evidence.
|
|
6036
|
+
*
|
|
6037
|
+
* @experimental
|
|
6038
|
+
*/
|
|
6039
|
+
/** Schema version for content-addressed worker tool-trace artifacts. */
|
|
6040
|
+
const WORKER_TOOL_TRACE_SCHEMA_VERSION = 1;
|
|
6041
|
+
/** Structural guard for the official bounded trace-analysis read contract. */
|
|
6042
|
+
function isTraceAnalysisStore(value) {
|
|
6043
|
+
if (value === null || typeof value !== "object") return false;
|
|
6044
|
+
const store = value;
|
|
6045
|
+
return typeof store.getOverview === "function" && typeof store.queryTraces === "function" && typeof store.countTraces === "function" && typeof store.viewTrace === "function" && typeof store.viewSpans === "function" && typeof store.searchTrace === "function" && typeof store.searchSpan === "function";
|
|
6046
|
+
}
|
|
6047
|
+
/** Collect and persist one executor's structured tool trace without changing its task outcome. */
|
|
6048
|
+
async function captureWorkerTraceEvidence(readSource, blobs, executed) {
|
|
6049
|
+
if (!executed) return unavailable$1("execution-did-not-start");
|
|
6050
|
+
if (readSource === void 0) return unavailable$1("executor-did-not-expose-trace-source");
|
|
6051
|
+
let source;
|
|
6052
|
+
try {
|
|
6053
|
+
source = readSource();
|
|
6054
|
+
} catch {
|
|
6055
|
+
return unavailable$1("trace-source-unavailable");
|
|
6056
|
+
}
|
|
6057
|
+
if (source === void 0) return unavailable$1("trace-source-unavailable");
|
|
6058
|
+
let collected;
|
|
6059
|
+
try {
|
|
6060
|
+
collected = await source.collect();
|
|
6061
|
+
} catch {
|
|
6062
|
+
return unavailable$1("trace-collection-failed");
|
|
6063
|
+
}
|
|
6064
|
+
if (!Array.isArray(collected) || collected.some((span) => !isToolSpanValue(span))) return unavailable$1("invalid-tool-spans");
|
|
6065
|
+
if (collected.length === 0) return unavailable$1("no-tool-spans-captured");
|
|
6066
|
+
let artifact;
|
|
6067
|
+
let traceRef;
|
|
6068
|
+
try {
|
|
6069
|
+
const snapshot = structuredClone(collected);
|
|
6070
|
+
toolSpansToTraceAnalysisStore(snapshot);
|
|
6071
|
+
artifact = {
|
|
6072
|
+
schemaVersion: 1,
|
|
6073
|
+
spans: snapshot
|
|
6074
|
+
};
|
|
6075
|
+
traceRef = contentAddress(artifact);
|
|
6076
|
+
} catch {
|
|
6077
|
+
return unavailable$1("invalid-tool-spans");
|
|
6078
|
+
}
|
|
6079
|
+
try {
|
|
6080
|
+
await blobs.put(traceRef, artifact);
|
|
6081
|
+
} catch {
|
|
6082
|
+
return unavailable$1("trace-persistence-failed");
|
|
6083
|
+
}
|
|
6084
|
+
return Object.freeze({
|
|
6085
|
+
status: "available",
|
|
6086
|
+
traceRef,
|
|
6087
|
+
spanCount: artifact.spans.length
|
|
6088
|
+
});
|
|
6089
|
+
}
|
|
6090
|
+
/** Rehydrate exact persisted spans through agent-eval's one bounded trace-analysis adapter. */
|
|
6091
|
+
async function workerTraceAnalysisStore(evidence, blobs) {
|
|
6092
|
+
if (evidence.status === "unavailable") return toolSpansToTraceAnalysisStore(void 0);
|
|
6093
|
+
const raw = await blobs.get(evidence.traceRef);
|
|
6094
|
+
if (raw === void 0) throw new ValidationError(`worker trace blob '${evidence.traceRef}' is missing; the settlement evidence is incomplete`);
|
|
6095
|
+
const artifact = parseWorkerToolTraceArtifact(raw, evidence.traceRef);
|
|
6096
|
+
if (artifact.spans.length !== evidence.spanCount) throw new ValidationError(`worker trace blob '${evidence.traceRef}' has ${artifact.spans.length} spans but its settlement records ${evidence.spanCount}`);
|
|
6097
|
+
return toolSpansToTraceAnalysisStore(artifact.spans);
|
|
6098
|
+
}
|
|
6099
|
+
/** Validate a stored trace artifact before an analyst or replay trusts it. */
|
|
6100
|
+
function parseWorkerToolTraceArtifact(value, traceRef = "<unknown>") {
|
|
6101
|
+
if (value === null || typeof value !== "object" || value.schemaVersion !== 1 || !Array.isArray(value.spans)) throw new ValidationError(`worker trace blob '${traceRef}' is not a version-1 tool trace artifact`);
|
|
6102
|
+
const spans = value.spans;
|
|
6103
|
+
if (spans.length === 0) return {
|
|
6104
|
+
schemaVersion: 1,
|
|
6105
|
+
spans
|
|
6106
|
+
};
|
|
6107
|
+
if (spans.some((span) => !isToolSpanValue(span))) throw new ValidationError(`worker trace blob '${traceRef}' contains a non-tool span`);
|
|
6108
|
+
return {
|
|
6109
|
+
schemaVersion: 1,
|
|
6110
|
+
spans
|
|
6111
|
+
};
|
|
6112
|
+
}
|
|
6113
|
+
function unavailable$1(reason) {
|
|
6114
|
+
return Object.freeze({
|
|
6115
|
+
status: "unavailable",
|
|
6116
|
+
reason
|
|
6117
|
+
});
|
|
6118
|
+
}
|
|
6119
|
+
function isToolSpanValue(value) {
|
|
6120
|
+
try {
|
|
6121
|
+
return isToolSpan(value);
|
|
6122
|
+
} catch {
|
|
6123
|
+
return false;
|
|
6124
|
+
}
|
|
6125
|
+
}
|
|
6126
|
+
//#endregion
|
|
6127
|
+
//#region src/runtime/supervise/tree-key.ts
|
|
6128
|
+
/** Runtime tag used only for a child that owns another supervised scope. */
|
|
6129
|
+
const driverRuntime = "driver";
|
|
6130
|
+
const nestedDriverTreeOwners = /* @__PURE__ */ new WeakSet();
|
|
6131
|
+
/** Canonical journal key for the scope owned by one nested driver node. */
|
|
6132
|
+
function nestedDriverTreeRoot(parentTreeRoot, driverNodeId) {
|
|
6133
|
+
return `${parentTreeRoot}/${driverNodeId}`;
|
|
6134
|
+
}
|
|
6135
|
+
/** Privately mark the exact recursive executor that will create a nested journal tree. */
|
|
6136
|
+
function attestNestedDriverTreeOwner(owner) {
|
|
6137
|
+
nestedDriverTreeOwners.add(owner);
|
|
6138
|
+
return owner;
|
|
6139
|
+
}
|
|
6140
|
+
/** Return the canonical owned tree only for an exact privately marked recursive executor. */
|
|
6141
|
+
function runtimeOwnedNestedDriverTreeRoot(owner, parentTreeRoot, driverNodeId) {
|
|
6142
|
+
return nestedDriverTreeOwners.has(owner) ? nestedDriverTreeRoot(parentTreeRoot, driverNodeId) : void 0;
|
|
6143
|
+
}
|
|
6144
|
+
//#endregion
|
|
6145
|
+
//#region src/durable/spawn-journal.ts
|
|
6146
|
+
/**
|
|
6147
|
+
*
|
|
6148
|
+
* Event-sourced spawn journal for the recursive execution atom (build steps 3 + 7).
|
|
6149
|
+
*
|
|
6150
|
+
* The supervision tree is journaled as an append-only event log: every `spawned`,
|
|
6151
|
+
* `settled`, and `cancelled` is recorded AFTER it is observed-committed (never
|
|
6152
|
+
* speculative), mirroring `ConversationJournal`'s begin/append/load shape. The log
|
|
6153
|
+
* holds only the THIN decision record — ids, parentage, budget, the spend a decision
|
|
6154
|
+
* consumed, and a content-addressed `outRef`. The payloads the driver branched on
|
|
6155
|
+
* (the `out` artifacts) live in a separate `ResultBlobStore`, keyed by `outRef`, so
|
|
6156
|
+
* the journal stays small (decisions) and replay rehydrates the exact `Settled` from
|
|
6157
|
+
* the blob store (evidence). This is the decision/payload split the replay argument
|
|
6158
|
+
* rests on (B1/B2).
|
|
6159
|
+
*
|
|
6160
|
+
* Replay determinism (B2): `seq` is the monotonic cursor order `scope.next()` yielded
|
|
6161
|
+
* each settlement — NOT wall-clock. `replaySpawnTree` sorts strictly by `seq` before
|
|
6162
|
+
* touching the blob store, so the order in which rehydration `get`s resolve can never
|
|
6163
|
+
* reorder the replayed `Settled[]`; the result is identical regardless of blob latency.
|
|
6164
|
+
*
|
|
6165
|
+
* @stable
|
|
6166
|
+
*/
|
|
6167
|
+
/**
|
|
6168
|
+
* Mint the content-addressed `outRef` for a result artifact: `sha256:<hex>` over a
|
|
6169
|
+
* stable JSON encoding. Producers call this to derive the `outRef` they journal and
|
|
6170
|
+
* `put`; the FS/in-mem stores re-derive it on `put` to verify the supplied ref
|
|
6171
|
+
* matches (fail loud on a mismatch — a forged ref breaks the replay invariant).
|
|
6172
|
+
*
|
|
6173
|
+
* Stable encoding: object keys are sorted recursively so two structurally-equal
|
|
6174
|
+
* artifacts hash identically regardless of key insertion order.
|
|
6175
|
+
*/
|
|
6176
|
+
/**
|
|
6177
|
+
* In-memory `ResultBlobStore`. Content-addressed: `put` verifies the supplied
|
|
6178
|
+
* `outRef` matches the artifact's hash so a stale/forged ref fails loud rather than
|
|
6179
|
+
* silently rehydrating the wrong payload. Idempotent on an identical re-put.
|
|
6180
|
+
*
|
|
6181
|
+
* @stable
|
|
6182
|
+
*/
|
|
6183
|
+
var InMemoryResultBlobStore = class {
|
|
6184
|
+
blobs = /* @__PURE__ */ new Map();
|
|
6185
|
+
async put(outRef, artifact) {
|
|
6186
|
+
assertContentAddress(outRef, artifact);
|
|
6187
|
+
this.blobs.set(outRef, artifact);
|
|
6188
|
+
}
|
|
6189
|
+
async get(outRef) {
|
|
6190
|
+
return this.blobs.has(outRef) ? this.blobs.get(outRef) : void 0;
|
|
6191
|
+
}
|
|
6192
|
+
};
|
|
6193
|
+
/**
|
|
6194
|
+
* FS `ResultBlobStore`. One JSON file per artifact under `dir`, named by a
|
|
6195
|
+
* filesystem-safe encoding of the `outRef` (`sha256:<hex>` → `sha256-<hex>.json`).
|
|
6196
|
+
* `put` fsyncs so a crash between writes never loses an acknowledged blob.
|
|
6197
|
+
*
|
|
6198
|
+
* @stable
|
|
6199
|
+
*/
|
|
6200
|
+
var FileResultBlobStore = class {
|
|
6201
|
+
dir;
|
|
6202
|
+
constructor(dir) {
|
|
6203
|
+
this.dir = dir;
|
|
6204
|
+
}
|
|
6205
|
+
async put(outRef, artifact) {
|
|
6206
|
+
assertContentAddress(outRef, artifact);
|
|
6207
|
+
const fs = await import("node:fs/promises");
|
|
6208
|
+
await fs.mkdir(this.dir, { recursive: true });
|
|
6209
|
+
const fh = await fs.open(this.blobPath(outRef), "w");
|
|
6210
|
+
try {
|
|
6211
|
+
await fh.write(JSON.stringify(artifact));
|
|
6212
|
+
await fh.sync();
|
|
6213
|
+
} finally {
|
|
6214
|
+
await fh.close();
|
|
6215
|
+
}
|
|
6216
|
+
}
|
|
6217
|
+
async get(outRef) {
|
|
6218
|
+
const fs = await import("node:fs/promises");
|
|
6219
|
+
let text;
|
|
6220
|
+
try {
|
|
6221
|
+
text = await fs.readFile(this.blobPath(outRef), "utf8");
|
|
6222
|
+
} catch (err) {
|
|
6223
|
+
if (isNoEntError(err)) return void 0;
|
|
6224
|
+
throw err;
|
|
6225
|
+
}
|
|
6226
|
+
return JSON.parse(text);
|
|
6227
|
+
}
|
|
6228
|
+
blobPath(outRef) {
|
|
6229
|
+
return `${this.dir}/${outRef.replace(/:/g, "-")}.json`;
|
|
6230
|
+
}
|
|
6231
|
+
};
|
|
6232
|
+
function assertContentAddress(outRef, artifact) {
|
|
6233
|
+
const expected = contentAddress(artifact);
|
|
6234
|
+
if (outRef !== expected) throw new Error(`blob outRef '${outRef}' does not match the artifact content hash '${expected}'; a content-addressed store refuses a mismatched ref (breaks the replay invariant)`);
|
|
6235
|
+
}
|
|
6236
|
+
/**
|
|
6237
|
+
* In-memory `SpawnJournal`. Appends are observed-committed only; the impl enforces
|
|
6238
|
+
* the corruption guards a durable replay rests on:
|
|
6239
|
+
* - an event before `beginTree` is a corrupted tree (fail loud),
|
|
6240
|
+
* - a duplicate `seq` within a tree is a corrupted cursor (fail loud) — two
|
|
6241
|
+
* settlements cannot share the cursor position replay orders by.
|
|
6242
|
+
*
|
|
6243
|
+
* @stable
|
|
6244
|
+
*/
|
|
6245
|
+
var InMemorySpawnJournal = class {
|
|
6246
|
+
trees = /* @__PURE__ */ new Map();
|
|
6247
|
+
async loadTree(root) {
|
|
6248
|
+
const tree = this.trees.get(root);
|
|
6249
|
+
if (!tree) return void 0;
|
|
6250
|
+
return tree.events.map((ev) => ({ ...ev }));
|
|
6251
|
+
}
|
|
6252
|
+
async beginTree(root, at) {
|
|
6253
|
+
const existing = this.trees.get(root);
|
|
6254
|
+
if (existing) {
|
|
6255
|
+
if (existing.begunAt !== at) throw new Error(`spawn tree '${root}' already begun at ${existing.begunAt}; refusing to overwrite with ${at}`);
|
|
6256
|
+
return;
|
|
6257
|
+
}
|
|
6258
|
+
this.trees.set(root, {
|
|
6259
|
+
begunAt: at,
|
|
6260
|
+
events: []
|
|
6261
|
+
});
|
|
6262
|
+
}
|
|
6263
|
+
async appendEvent(root, ev) {
|
|
6264
|
+
const tree = this.trees.get(root);
|
|
6265
|
+
if (!tree) throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`);
|
|
6266
|
+
assertSeqUnique(root, tree.events, ev);
|
|
6267
|
+
tree.events.push({ ...ev });
|
|
6268
|
+
}
|
|
6269
|
+
};
|
|
6270
|
+
/**
|
|
6271
|
+
* JSONL on disk. One line per record: the first record is `begin`, subsequent records
|
|
6272
|
+
* are `event` envelopes wrapping a `SpawnEvent`. `loadTree` replays the whole file,
|
|
6273
|
+
* filtering by `root`, and applies the same begin-precedes-events + unique-seq
|
|
6274
|
+
* corruption guards as the in-memory impl. Each append fsyncs so a crash between
|
|
6275
|
+
* writes never loses an acknowledged event.
|
|
6276
|
+
*
|
|
6277
|
+
* @stable
|
|
6278
|
+
*/
|
|
6279
|
+
var FileSpawnJournal = class {
|
|
6280
|
+
path;
|
|
6281
|
+
appendTail = Promise.resolve();
|
|
6282
|
+
constructor(path) {
|
|
6283
|
+
this.path = path;
|
|
6284
|
+
}
|
|
6285
|
+
async loadTree(root) {
|
|
6286
|
+
const fs = await import("node:fs/promises");
|
|
6287
|
+
let text;
|
|
6288
|
+
try {
|
|
6289
|
+
text = await fs.readFile(this.path, "utf8");
|
|
6290
|
+
} catch (err) {
|
|
6291
|
+
if (isNoEntError(err)) return void 0;
|
|
6292
|
+
throw err;
|
|
6293
|
+
}
|
|
6294
|
+
let begun = false;
|
|
6295
|
+
const events = [];
|
|
6296
|
+
for (const record of parseCommittedJsonLines(text, this.path)) {
|
|
6297
|
+
if (record.root !== root) continue;
|
|
6298
|
+
if (record.kind === "begin") begun = true;
|
|
6299
|
+
else {
|
|
6300
|
+
if (!begun) throw new Error(`spawn journal corrupted: event for tree '${root}' precedes its begin record`);
|
|
6301
|
+
assertSeqUnique(root, events, record.event);
|
|
6302
|
+
events.push(record.event);
|
|
6303
|
+
}
|
|
6304
|
+
}
|
|
6305
|
+
return begun ? events : void 0;
|
|
6306
|
+
}
|
|
6307
|
+
async beginTree(root, at) {
|
|
6308
|
+
const existing = await this.loadTreeBegin(root);
|
|
6309
|
+
if (existing) {
|
|
6310
|
+
if (existing !== at) throw new Error(`spawn tree '${root}' already begun in ${this.path} at ${existing}; refusing to overwrite with ${at}`);
|
|
6311
|
+
return;
|
|
6312
|
+
}
|
|
6313
|
+
await this.appendRecord({
|
|
6314
|
+
kind: "begin",
|
|
6315
|
+
root,
|
|
6316
|
+
at
|
|
6317
|
+
});
|
|
6318
|
+
}
|
|
6319
|
+
async appendEvent(root, ev) {
|
|
6320
|
+
const events = await this.loadTree(root);
|
|
6321
|
+
if (events === void 0) throw new Error(`appendEvent called for unknown spawn tree '${root}'; call beginTree first`);
|
|
6322
|
+
assertSeqUnique(root, events, ev);
|
|
6323
|
+
await this.appendRecord({
|
|
6324
|
+
kind: "event",
|
|
6325
|
+
root,
|
|
6326
|
+
event: ev
|
|
6327
|
+
});
|
|
6328
|
+
}
|
|
6329
|
+
async loadTreeBegin(root) {
|
|
6330
|
+
const fs = await import("node:fs/promises");
|
|
6331
|
+
let text;
|
|
6332
|
+
try {
|
|
6333
|
+
text = await fs.readFile(this.path, "utf8");
|
|
6334
|
+
} catch (err) {
|
|
6335
|
+
if (isNoEntError(err)) return void 0;
|
|
6336
|
+
throw err;
|
|
6337
|
+
}
|
|
6338
|
+
for (const record of parseCommittedJsonLines(text, this.path)) if (record.root === root && record.kind === "begin") return record.at;
|
|
6339
|
+
}
|
|
6340
|
+
async appendRecord(record) {
|
|
6341
|
+
const append = this.appendTail.then(() => this.writeRecord(record));
|
|
6342
|
+
this.appendTail = append.catch(() => void 0);
|
|
6343
|
+
return append;
|
|
6344
|
+
}
|
|
6345
|
+
async writeRecord(record) {
|
|
6346
|
+
const fs = await import("node:fs/promises");
|
|
6347
|
+
const path = await import("node:path");
|
|
6348
|
+
await fs.mkdir(path.dirname(this.path), { recursive: true });
|
|
6349
|
+
const needsSeparator = await prepareJsonlAppend(this.path);
|
|
6350
|
+
const fh = await fs.open(this.path, "a");
|
|
6351
|
+
try {
|
|
6352
|
+
await writeAllBytes(fh, `${needsSeparator ? "\n" : ""}${JSON.stringify(record)}\n`);
|
|
6353
|
+
await fh.sync();
|
|
6354
|
+
} finally {
|
|
6355
|
+
await fh.close();
|
|
6356
|
+
}
|
|
6357
|
+
}
|
|
6358
|
+
};
|
|
6359
|
+
/**
|
|
6360
|
+
* Load every journal tree owned by one recursive supervision run and flatten its nodes/events.
|
|
6361
|
+
*
|
|
6362
|
+
* Nested driver tree keys are a Runtime implementation detail; callers should use this reader
|
|
6363
|
+
* instead of deriving or scanning keys themselves. The reader follows only the explicit
|
|
6364
|
+
* `ownedTreeRoot` written after Runtime privately attested a recursive executor; the open runtime
|
|
6365
|
+
* string `driver` is never treated as ownership. Legacy records without `ownedTreeRoot` are
|
|
6366
|
+
* intentionally treated as leaves rather than guessing or scanning convention-derived keys.
|
|
6367
|
+
* This preserves each tree's independent cursor namespace on flattened events.
|
|
6368
|
+
* A driver whose subtree was never begun is reported in `missingTrees`; any spawned non-root node
|
|
6369
|
+
* without a terminal record is reported in `inDoubt`, matching resume's conservative lost-work
|
|
6370
|
+
* interpretation.
|
|
6371
|
+
*
|
|
6372
|
+
* This is a cold/quiescent reader, not a transaction across an actively mutating file. Every value
|
|
6373
|
+
* returned is a detached immutable snapshot, so later journal writes or caller mutation cannot
|
|
6374
|
+
* change the result already observed.
|
|
6375
|
+
*/
|
|
6376
|
+
async function loadSpawnForest(journal, root) {
|
|
6377
|
+
const rootEvents = await journal.loadTree(root);
|
|
6378
|
+
if (rootEvents === void 0) throw new Error(`loadSpawnForest: no journaled tree for root '${root}'`);
|
|
6379
|
+
const trees = [];
|
|
6380
|
+
const nodes = [];
|
|
6381
|
+
const events = [];
|
|
6382
|
+
const inDoubt = [];
|
|
6383
|
+
const missingTrees = [];
|
|
6384
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6385
|
+
const queue = [{
|
|
6386
|
+
root,
|
|
6387
|
+
events: rootEvents
|
|
6388
|
+
}];
|
|
6389
|
+
for (let cursor = 0; cursor < queue.length; cursor += 1) {
|
|
6390
|
+
const current = queue[cursor];
|
|
6391
|
+
if (visited.has(current.root)) throw new Error(`loadSpawnForest: recursive journal tree '${current.root}' was reached twice`);
|
|
6392
|
+
visited.add(current.root);
|
|
6393
|
+
const stableEvents = detachedSnapshot(current.events, `loadSpawnForest tree ${JSON.stringify(current.root)}`);
|
|
6394
|
+
const view = detachedSnapshot(materializeTreeView(current.ownerSpawn === void 0 || stableEvents.some((event) => event.kind === "spawned" && event.id === current.ownerSpawn?.id) ? [...stableEvents] : [ownedTreeRootSpawn(current.ownerSpawn), ...stableEvents]), `loadSpawnForest view ${JSON.stringify(current.root)}`);
|
|
6395
|
+
trees.push({
|
|
6396
|
+
root: current.root,
|
|
6397
|
+
...current.ownerNodeId === void 0 ? {} : { ownerNodeId: current.ownerNodeId },
|
|
6398
|
+
...current.parentTreeRoot === void 0 ? {} : { parentTreeRoot: current.parentTreeRoot },
|
|
6399
|
+
events: stableEvents,
|
|
6400
|
+
view
|
|
6401
|
+
});
|
|
6402
|
+
nodes.push(...view.nodes.filter((node) => current.ownerNodeId === void 0 || node.id !== current.ownerNodeId).map((node) => ({
|
|
6403
|
+
treeRoot: current.root,
|
|
6404
|
+
...node
|
|
6405
|
+
})));
|
|
6406
|
+
events.push(...stableEvents.map((event) => ({
|
|
6407
|
+
treeRoot: current.root,
|
|
6408
|
+
event
|
|
6409
|
+
})));
|
|
6410
|
+
const terminal = /* @__PURE__ */ new Set();
|
|
6411
|
+
for (const event of stableEvents) if (event.kind === "settled" || event.kind === "cancelled") terminal.add(event.id);
|
|
6412
|
+
const spawns = stableEvents.filter((event) => event.kind === "spawned").sort((a, b) => a.seq - b.seq || a.id.localeCompare(b.id));
|
|
6413
|
+
for (const spawn of spawns) {
|
|
6414
|
+
if (spawn.parent !== void 0 && !terminal.has(spawn.id)) inDoubt.push({
|
|
6415
|
+
treeRoot: current.root,
|
|
6416
|
+
nodeId: spawn.id,
|
|
6417
|
+
label: spawn.label,
|
|
6418
|
+
runtime: spawn.runtime
|
|
6419
|
+
});
|
|
6420
|
+
if (spawn.ownedTreeRoot === void 0) continue;
|
|
6421
|
+
const expectedRoot = nestedDriverTreeRoot(current.root, spawn.id);
|
|
6422
|
+
if (spawn.ownedTreeRoot !== expectedRoot) throw new Error(`loadSpawnForest: node '${spawn.id}' owns non-canonical tree '${spawn.ownedTreeRoot}'; expected '${expectedRoot}'`);
|
|
6423
|
+
const nestedRoot = spawn.ownedTreeRoot;
|
|
6424
|
+
const nestedEvents = await journal.loadTree(nestedRoot);
|
|
6425
|
+
if (nestedEvents === void 0) {
|
|
6426
|
+
missingTrees.push({
|
|
6427
|
+
parentTreeRoot: current.root,
|
|
6428
|
+
ownerNodeId: spawn.id,
|
|
6429
|
+
root: nestedRoot
|
|
6430
|
+
});
|
|
6431
|
+
continue;
|
|
6432
|
+
}
|
|
6433
|
+
queue.push({
|
|
6434
|
+
root: nestedRoot,
|
|
6435
|
+
events: nestedEvents,
|
|
6436
|
+
ownerNodeId: spawn.id,
|
|
6437
|
+
parentTreeRoot: current.root,
|
|
6438
|
+
ownerSpawn: spawn
|
|
6439
|
+
});
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
return detachedSnapshot({
|
|
6443
|
+
root,
|
|
6444
|
+
trees,
|
|
6445
|
+
nodes,
|
|
6446
|
+
events,
|
|
6447
|
+
inDoubt,
|
|
6448
|
+
missingTrees
|
|
6449
|
+
}, "loadSpawnForest result");
|
|
6450
|
+
}
|
|
6451
|
+
/** Owned journal trees record the owner's turns and descendants, but the owner's spawn belongs to
|
|
6452
|
+
* the parent tree. Supply a view-only parentless copy so strict materialization can fold root
|
|
6453
|
+
* metering without weakening its missing-spawn corruption check for ordinary event lists. */
|
|
6454
|
+
function ownedTreeRootSpawn(spawn) {
|
|
6455
|
+
const { parent: _parent, ownedTreeRoot: _ownedTreeRoot, ...root } = spawn;
|
|
6456
|
+
return root;
|
|
6457
|
+
}
|
|
6458
|
+
/**
|
|
6459
|
+
* Aggregate provider-served model evidence across one recursively owned journal forest.
|
|
6460
|
+
*
|
|
6461
|
+
* The parent tree records an owned driver's terminal summary, while that driver's own inference
|
|
6462
|
+
* and descendants live in its owned tree. This reducer follows the forest reader's explicit tree
|
|
6463
|
+
* edges and consumes each tree's metered attempts plus terminal leaf settlements exactly once.
|
|
6464
|
+
* A summary node is skipped because its owned tree supplies the source records. Plan materialization
|
|
6465
|
+
* is intentionally not read: it proves only what Runtime requested, not what a provider served.
|
|
6466
|
+
*
|
|
6467
|
+
* Missing legacy evidence, an unfinished node, an unopened owned tree, an identity conflict, and a
|
|
6468
|
+
* paid attempt without a qualified served snapshot all return unknown. An explicit
|
|
6469
|
+
* `providerDispatch: "not_started"` arm and Runtime accounting-only metered records are ignored
|
|
6470
|
+
* for served-model identity, while absent or malformed legacy data remains unknown here.
|
|
6471
|
+
*/
|
|
6472
|
+
function aggregateProviderModelEvidence(forest) {
|
|
6473
|
+
const attempts = [];
|
|
6474
|
+
const observedModels = /* @__PURE__ */ new Set();
|
|
6475
|
+
const canonicalModels = /* @__PURE__ */ new Set();
|
|
6476
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
6477
|
+
let reason;
|
|
6478
|
+
let sawProviderEvidence = false;
|
|
6479
|
+
for (const node of forest.nodes) nodes.set(forestNodeKey(node.treeRoot, node.id), node);
|
|
6480
|
+
if (forest.missingTrees.length > 0 || forest.inDoubt.length > 0) reason = "provider-model-missing";
|
|
6481
|
+
const markMissing = () => {
|
|
6482
|
+
reason ??= "provider-model-missing";
|
|
6483
|
+
};
|
|
6484
|
+
const markConflict = () => {
|
|
6485
|
+
reason = "provider-model-conflict";
|
|
6486
|
+
};
|
|
6487
|
+
const append = (raw) => {
|
|
6488
|
+
sawProviderEvidence = true;
|
|
6489
|
+
if (!isProviderEvidenceObject(raw)) {
|
|
6490
|
+
markMissing();
|
|
6491
|
+
return;
|
|
6492
|
+
}
|
|
6493
|
+
if (raw.status === "unknown") {
|
|
6494
|
+
if (raw.reason === "provider-model-conflict") markConflict();
|
|
6495
|
+
else if (!hasOnlyNotStartedAttempts(raw)) markMissing();
|
|
6496
|
+
} else if (raw.status !== "known") {
|
|
6497
|
+
markMissing();
|
|
6498
|
+
return;
|
|
6499
|
+
}
|
|
6500
|
+
if (!Array.isArray(raw.attempts) || !Array.isArray(raw.models)) {
|
|
6501
|
+
markMissing();
|
|
6502
|
+
return;
|
|
6503
|
+
}
|
|
6504
|
+
const declared = /* @__PURE__ */ new Set();
|
|
6505
|
+
for (const model of raw.models) if (typeof model !== "string" || model.length === 0) markMissing();
|
|
6506
|
+
else declared.add(model);
|
|
6507
|
+
const observedInRecord = /* @__PURE__ */ new Set();
|
|
6508
|
+
for (const rawAttempt of raw.attempts) {
|
|
6509
|
+
if (!isProviderAttemptEvidence(rawAttempt)) {
|
|
6510
|
+
markMissing();
|
|
6511
|
+
continue;
|
|
6512
|
+
}
|
|
6513
|
+
if (rawAttempt.identityConflict === true) markConflict();
|
|
6514
|
+
const observations = [...rawAttempt.observations];
|
|
6515
|
+
if (rawAttempt.providerDispatch === "not_started") {
|
|
6516
|
+
if (observations.length > 0) markMissing();
|
|
6517
|
+
attempts.push(Object.freeze({
|
|
6518
|
+
observations: Object.freeze([]),
|
|
6519
|
+
providerDispatch: "not_started",
|
|
6520
|
+
...rawAttempt.identityConflict === true ? { identityConflict: true } : {}
|
|
6521
|
+
}));
|
|
6522
|
+
continue;
|
|
6523
|
+
}
|
|
6524
|
+
if (observations.length === 0) {
|
|
6525
|
+
markMissing();
|
|
6526
|
+
attempts.push(Object.freeze({
|
|
6527
|
+
observations: Object.freeze([]),
|
|
6528
|
+
...rawAttempt.identityConflict === true ? { identityConflict: true } : {}
|
|
6529
|
+
}));
|
|
6530
|
+
continue;
|
|
6531
|
+
}
|
|
6532
|
+
let base;
|
|
6533
|
+
let snapshot;
|
|
6534
|
+
for (const model of observations) {
|
|
6535
|
+
if (typeof model !== "string" || model.length === 0) {
|
|
6536
|
+
markMissing();
|
|
6537
|
+
continue;
|
|
6538
|
+
}
|
|
6539
|
+
observedInRecord.add(model);
|
|
6540
|
+
observedModels.add(model);
|
|
6541
|
+
const identity = servedIdentityParts(model);
|
|
6542
|
+
if (identity === void 0) {
|
|
6543
|
+
markMissing();
|
|
6544
|
+
continue;
|
|
6545
|
+
}
|
|
6546
|
+
if (base !== void 0 && base !== identity.base) markConflict();
|
|
6547
|
+
if (snapshot !== void 0 && identity.snapshot !== void 0 && snapshot !== identity.snapshot) markConflict();
|
|
6548
|
+
base = identity.base;
|
|
6549
|
+
snapshot ??= identity.snapshot;
|
|
6550
|
+
if (identity.snapshot !== void 0) {
|
|
6551
|
+
canonicalModels.add(`${identity.base}@${identity.snapshot}`);
|
|
6552
|
+
if (canonicalModels.size > 1) markConflict();
|
|
6553
|
+
}
|
|
6554
|
+
}
|
|
6555
|
+
if (base === void 0 || snapshot === void 0) markMissing();
|
|
6556
|
+
attempts.push(Object.freeze({
|
|
6557
|
+
observations: Object.freeze(observations),
|
|
6558
|
+
...rawAttempt.identityConflict === true ? { identityConflict: true } : {}
|
|
6559
|
+
}));
|
|
6560
|
+
}
|
|
6561
|
+
if (declared.size !== observedInRecord.size || [...declared].some((model) => !observedInRecord.has(model))) markMissing();
|
|
6562
|
+
};
|
|
6563
|
+
const terminal = (treeRoot, event) => {
|
|
6564
|
+
const node = nodes.get(forestNodeKey(treeRoot, event.id));
|
|
6565
|
+
if (node === void 0) {
|
|
6566
|
+
markMissing();
|
|
6567
|
+
return;
|
|
6568
|
+
}
|
|
6569
|
+
if (node.ownedTreeRoot !== void 0) return;
|
|
6570
|
+
if (event.kind === "cancelled") {
|
|
6571
|
+
markMissing();
|
|
6572
|
+
return;
|
|
6573
|
+
}
|
|
6574
|
+
append(event.providerModel ?? node.providerModel);
|
|
6575
|
+
};
|
|
6576
|
+
for (const tree of forest.trees) for (const event of tree.events) if (event.kind === "metered") {
|
|
6577
|
+
if (event.accountingOnly === true) {
|
|
6578
|
+
if (event.providerModel !== void 0) markMissing();
|
|
6579
|
+
continue;
|
|
6580
|
+
}
|
|
6581
|
+
if (nodes.get(forestNodeKey(tree.root, event.id))?.ownedTreeRoot !== void 0) continue;
|
|
6582
|
+
const evidence = event.providerModel;
|
|
6583
|
+
if (evidence === void 0) markMissing();
|
|
6584
|
+
else append(evidence);
|
|
6585
|
+
} else if (event.kind === "settled" || event.kind === "cancelled") terminal(tree.root, event);
|
|
6586
|
+
if (!sawProviderEvidence || attempts.length === 0 || observedModels.size === 0) reason ??= "provider-model-missing";
|
|
6587
|
+
const models = Object.freeze([...observedModels]);
|
|
6588
|
+
const frozenAttempts = Object.freeze(attempts);
|
|
6589
|
+
return Object.freeze(reason === void 0 ? {
|
|
6590
|
+
status: "known",
|
|
6591
|
+
attempts: frozenAttempts,
|
|
6592
|
+
models
|
|
6593
|
+
} : {
|
|
6594
|
+
status: "unknown",
|
|
6595
|
+
attempts: frozenAttempts,
|
|
6596
|
+
models,
|
|
6597
|
+
reason
|
|
6598
|
+
});
|
|
6599
|
+
}
|
|
6600
|
+
function forestNodeKey(treeRoot, nodeId) {
|
|
6601
|
+
return `${treeRoot}\u0000${nodeId}`;
|
|
6602
|
+
}
|
|
6603
|
+
function isProviderEvidenceObject(value) {
|
|
6604
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && "status" in value;
|
|
6605
|
+
}
|
|
6606
|
+
function hasOnlyNotStartedAttempts(evidence) {
|
|
6607
|
+
return Array.isArray(evidence.attempts) && evidence.attempts.length > 0 && evidence.attempts.every((attempt) => isProviderAttemptEvidence(attempt) && attempt.providerDispatch === "not_started" && attempt.observations.length === 0 && attempt.identityConflict !== true);
|
|
6608
|
+
}
|
|
6609
|
+
function isProviderAttemptEvidence(value) {
|
|
6610
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && Array.isArray(value.observations) && (value.providerDispatch === void 0 || value.providerDispatch === "not_started");
|
|
6611
|
+
}
|
|
6612
|
+
function servedIdentityParts(model) {
|
|
6613
|
+
const at = model.lastIndexOf("@");
|
|
6614
|
+
const rawBase = at < 0 ? model : model.slice(0, at);
|
|
6615
|
+
const base = rawBase.slice(rawBase.lastIndexOf("/") + 1);
|
|
6616
|
+
if (base.length === 0) return void 0;
|
|
6617
|
+
const snapshot = at < 0 ? void 0 : model.slice(at + 1);
|
|
6618
|
+
if (snapshot !== void 0 && snapshot.length === 0) return void 0;
|
|
6619
|
+
return snapshot === void 0 ? { base } : {
|
|
6620
|
+
base,
|
|
6621
|
+
snapshot
|
|
6622
|
+
};
|
|
6623
|
+
}
|
|
6624
|
+
/**
|
|
6625
|
+
* Two `seq` namespaces share the journal: a `spawned` event's `seq` is the spawn ordinal
|
|
6626
|
+
* (the order children were created), and a `settled`/`cancelled` event's `seq` is the
|
|
6627
|
+
* monotonic CURSOR order `scope.next()` yielded that settlement (B2). The uniqueness
|
|
6628
|
+
* replay rests on is the cursor namespace — two settlements cannot share the position
|
|
6629
|
+
* replay orders by — so the guard checks only settled/cancelled events. A `spawned`
|
|
6630
|
+
* ordinal legitimately equals a later `settled` cursor seq and is not a collision.
|
|
6631
|
+
*/
|
|
6632
|
+
function assertSeqUnique(root, events, ev) {
|
|
6633
|
+
if (ev.kind === "materialized") {
|
|
6634
|
+
if (events.some((event) => event.kind === "materialized" && event.id === ev.id)) throw new Error(`spawn journal corrupted: duplicate materialization receipt for node '${ev.id}' in tree '${root}'`);
|
|
6635
|
+
if (!events.some((event) => event.kind === "spawned" && event.id === ev.id)) throw new Error(`spawn journal corrupted: materialization for node '${ev.id}' precedes its spawn in tree '${root}'`);
|
|
6636
|
+
}
|
|
6637
|
+
if (ev.kind === "execution-bound") {
|
|
6638
|
+
if (events.some((event) => event.kind === "execution-bound" && event.id === ev.id && event.binding.attemptId === ev.binding.attemptId)) throw new Error(`spawn journal corrupted: duplicate execution binding for node '${ev.id}' attempt '${ev.binding.attemptId}' in tree '${root}'`);
|
|
6639
|
+
if (!events.some((event) => event.kind === "materialized" && event.id === ev.id)) throw new Error(`spawn journal corrupted: execution binding for node '${ev.id}' precedes materialization in tree '${root}'`);
|
|
6640
|
+
}
|
|
6641
|
+
if (outsideCursorNamespace(ev)) return;
|
|
6642
|
+
if (events.some((e) => !outsideCursorNamespace(e) && e.seq === ev.seq)) throw new Error(`spawn journal corrupted: duplicate cursor seq ${ev.seq} in tree '${root}'; the cursor order replay relies on is not unique`);
|
|
6643
|
+
}
|
|
6644
|
+
/**
|
|
6645
|
+
* The records that CLOSE a node's cursor slot: a settlement, a cancellation, or a wait being
|
|
6646
|
+
* woken. The complement question to {@link outsideCursorNamespace}, and the one a resume needs —
|
|
6647
|
+
* a kind missing here leaves a finished node looking live, so its budget is never reclaimed and
|
|
6648
|
+
* its reservation is replayed as still in doubt.
|
|
6649
|
+
*/
|
|
6650
|
+
function closesCursorSlot(ev) {
|
|
6651
|
+
return ev.kind === "settled" || ev.kind === "cancelled" || ev.kind === "woken";
|
|
6652
|
+
}
|
|
6653
|
+
const outsideKinds = /* @__PURE__ */ new Set([
|
|
6654
|
+
"spawned",
|
|
6655
|
+
"waiting",
|
|
6656
|
+
"metered",
|
|
6657
|
+
"materialized",
|
|
6658
|
+
"execution-bound",
|
|
6659
|
+
"progress",
|
|
6660
|
+
"edge",
|
|
6661
|
+
"teardown-unconfirmed",
|
|
6662
|
+
"trace-unpropagated",
|
|
6663
|
+
"node-inputs-resolved",
|
|
6664
|
+
"edge-verdict",
|
|
6665
|
+
"join-state"
|
|
6666
|
+
]);
|
|
6667
|
+
/** True for a node-CREATION or informational record. Narrows, so a caller keeps the union's arms. */
|
|
6668
|
+
function outsideCursorNamespace(ev) {
|
|
6669
|
+
return outsideKinds.has(ev.kind);
|
|
6670
|
+
}
|
|
6671
|
+
/** True for a record inside the cursor namespace. Narrows to {@link CursorNamespaceEvent}. */
|
|
6672
|
+
function insideCursorNamespace(ev) {
|
|
6673
|
+
return !outsideKinds.has(ev.kind);
|
|
6674
|
+
}
|
|
6675
|
+
/**
|
|
6676
|
+
* Re-feed a journaled spawn tree in strict `seq` order, rehydrating each settled
|
|
6677
|
+
* child's `out` from the blob store by `outRef`, and return the `Settled[]` exactly
|
|
6678
|
+
* as `scope.next()` originally delivered them.
|
|
6679
|
+
*
|
|
6680
|
+
* Determinism (B2): the events are sorted by `seq` BEFORE any blob `get`, so the
|
|
6681
|
+
* replay order is the recorded cursor order regardless of how fast each rehydration
|
|
6682
|
+
* resolves. `at` (wall-clock) is never a replay input. Fail loud on a tree that was
|
|
6683
|
+
* never begun, a settled-done event missing its `outRef`, or a blob the store can't
|
|
6684
|
+
* rehydrate — a silent gap would let `act` branch on the wrong evidence.
|
|
6685
|
+
*
|
|
6686
|
+
* @stable
|
|
6687
|
+
*/
|
|
6688
|
+
async function replaySpawnTree(journal, blobs, root) {
|
|
6689
|
+
const events = await journal.loadTree(root);
|
|
6690
|
+
if (events === void 0) throw new Error(`replaySpawnTree: no journaled tree for root '${root}'`);
|
|
6691
|
+
const ordered = [...events].sort((a, b) => a.seq - b.seq);
|
|
6692
|
+
const labels = /* @__PURE__ */ new Map();
|
|
6693
|
+
const assignmentIds = /* @__PURE__ */ new Map();
|
|
6694
|
+
const identities = /* @__PURE__ */ new Map();
|
|
6695
|
+
const materializations = /* @__PURE__ */ new Map();
|
|
6696
|
+
const executionBindings = /* @__PURE__ */ new Map();
|
|
6697
|
+
for (const ev of ordered) {
|
|
6698
|
+
if (ev.kind === "spawned" || ev.kind === "waiting") labels.set(ev.id, ev.label);
|
|
6699
|
+
if (ev.kind === "spawned" && ev.assignmentId !== void 0) assignmentIds.set(ev.id, ev.assignmentId);
|
|
6700
|
+
if (ev.kind === "spawned" && ev.identity !== void 0) identities.set(ev.id, copyFrozenIdentity(ev.identity));
|
|
6701
|
+
if (ev.kind === "materialized") materializations.set(ev.id, ev.receipt);
|
|
6702
|
+
if (ev.kind === "execution-bound") {
|
|
6703
|
+
const bindings = executionBindings.get(ev.id) ?? [];
|
|
6704
|
+
bindings.push(ev.binding);
|
|
6705
|
+
executionBindings.set(ev.id, bindings);
|
|
6706
|
+
}
|
|
6707
|
+
}
|
|
6708
|
+
const handleFor = (id, status) => replayHandle(id, labels.get(id) ?? id, status, {
|
|
6709
|
+
assignmentId: assignmentIds.get(id),
|
|
6710
|
+
identity: identities.get(id),
|
|
6711
|
+
materialization: materializations.get(id),
|
|
6712
|
+
executionBindings: executionBindings.get(id)
|
|
6713
|
+
});
|
|
6714
|
+
const settlementTime = (at) => {
|
|
6715
|
+
const settledAt = Date.parse(at);
|
|
6716
|
+
return Number.isFinite(settledAt) ? { settledAt } : {};
|
|
6717
|
+
};
|
|
6718
|
+
const settled = [];
|
|
6719
|
+
for (const ev of ordered) {
|
|
6720
|
+
if (ev.kind === "spawned") continue;
|
|
6721
|
+
if (ev.kind === "waiting") continue;
|
|
6722
|
+
if (ev.kind === "metered") continue;
|
|
6723
|
+
if (ev.kind === "progress") continue;
|
|
6724
|
+
if (ev.kind === "materialized") continue;
|
|
6725
|
+
if (ev.kind === "execution-bound") continue;
|
|
6726
|
+
if (ev.kind === "edge") continue;
|
|
6727
|
+
if (ev.kind === "teardown-unconfirmed") continue;
|
|
6728
|
+
if (ev.kind === "trace-unpropagated") continue;
|
|
6729
|
+
if (ev.kind === "node-inputs-resolved") continue;
|
|
6730
|
+
if (ev.kind === "edge-verdict") continue;
|
|
6731
|
+
if (ev.kind === "join-state") continue;
|
|
6732
|
+
if (ev.kind === "woken") {
|
|
6733
|
+
if (ev.by === "cancelled" || ev.outRef === void 0) {
|
|
6734
|
+
settled.push({
|
|
6735
|
+
kind: "down",
|
|
6736
|
+
handle: handleFor(ev.id, "cancelled"),
|
|
6737
|
+
reason: "wait cancelled",
|
|
6738
|
+
infra: false,
|
|
6739
|
+
trace: {
|
|
6740
|
+
status: "unavailable",
|
|
6741
|
+
reason: "not-an-executor"
|
|
6742
|
+
},
|
|
6743
|
+
...settlementTime(ev.at),
|
|
6744
|
+
seq: ev.seq
|
|
6745
|
+
});
|
|
6746
|
+
continue;
|
|
6747
|
+
}
|
|
6748
|
+
const outcome = await blobs.get(ev.outRef);
|
|
6749
|
+
if (outcome === void 0) throw new Error(`replaySpawnTree: blob store has no wait outcome for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`);
|
|
6750
|
+
settled.push({
|
|
6751
|
+
kind: "done",
|
|
6752
|
+
handle: handleFor(ev.id, "done"),
|
|
6753
|
+
out: outcome,
|
|
6754
|
+
outRef: ev.outRef,
|
|
6755
|
+
spent: zeroSpend(),
|
|
6756
|
+
trace: {
|
|
6757
|
+
status: "unavailable",
|
|
6758
|
+
reason: "not-an-executor"
|
|
6759
|
+
},
|
|
6760
|
+
...settlementTime(ev.at),
|
|
6761
|
+
seq: ev.seq
|
|
6762
|
+
});
|
|
6763
|
+
continue;
|
|
6764
|
+
}
|
|
6765
|
+
if (ev.kind === "cancelled") {
|
|
6766
|
+
settled.push({
|
|
6767
|
+
kind: "down",
|
|
6768
|
+
handle: handleFor(ev.id, "cancelled"),
|
|
6769
|
+
reason: ev.reason,
|
|
6770
|
+
infra: false,
|
|
6771
|
+
trace: {
|
|
6772
|
+
status: "unavailable",
|
|
6773
|
+
reason: "execution-did-not-start"
|
|
6774
|
+
},
|
|
6775
|
+
...settlementTime(ev.at),
|
|
6776
|
+
seq: ev.seq
|
|
6777
|
+
});
|
|
6778
|
+
continue;
|
|
6779
|
+
}
|
|
6780
|
+
if (ev.status === "down") {
|
|
6781
|
+
const trace = traceEvidenceFor(ev);
|
|
6782
|
+
if (trace.status === "available") await workerTraceAnalysisStore(trace, blobs);
|
|
6783
|
+
settled.push({
|
|
6784
|
+
kind: "down",
|
|
6785
|
+
handle: handleFor(ev.id, "failed"),
|
|
6786
|
+
reason: ev.reason ?? ev.verdict?.notes ?? "child down",
|
|
6787
|
+
infra: ev.infra === true,
|
|
6788
|
+
...ev.providerModel === void 0 ? {} : { providerModel: copyProviderModelEvidence(ev.providerModel) },
|
|
6789
|
+
trace,
|
|
6790
|
+
...settlementTime(ev.at),
|
|
6791
|
+
seq: ev.seq
|
|
6792
|
+
});
|
|
6793
|
+
continue;
|
|
6794
|
+
}
|
|
6795
|
+
if (ev.outRef === void 0) throw new Error(`replaySpawnTree: settled-done event for '${ev.id}' (seq ${ev.seq}) has no outRef; cannot rehydrate the result the driver branched on`);
|
|
6796
|
+
const out = await blobs.get(ev.outRef);
|
|
6797
|
+
if (out === void 0) throw new Error(`replaySpawnTree: blob store has no artifact for outRef '${ev.outRef}' (node '${ev.id}', seq ${ev.seq})`);
|
|
6798
|
+
const trace = traceEvidenceFor(ev);
|
|
6799
|
+
if (trace.status === "available") await workerTraceAnalysisStore(trace, blobs);
|
|
6800
|
+
settled.push({
|
|
6801
|
+
kind: "done",
|
|
6802
|
+
handle: handleFor(ev.id, "done"),
|
|
6803
|
+
out,
|
|
6804
|
+
outRef: ev.outRef,
|
|
6805
|
+
verdict: ev.verdict,
|
|
6806
|
+
spent: cloneSpend(ev.spent),
|
|
6807
|
+
...ev.providerModel === void 0 ? {} : { providerModel: copyProviderModelEvidence(ev.providerModel) },
|
|
6808
|
+
trace,
|
|
6809
|
+
...settlementTime(ev.at),
|
|
6810
|
+
seq: ev.seq
|
|
6811
|
+
});
|
|
6812
|
+
}
|
|
6813
|
+
return settled;
|
|
6814
|
+
}
|
|
6815
|
+
function replayHandle(id, label, status, evidence = {}) {
|
|
6816
|
+
return Object.freeze({
|
|
6817
|
+
id,
|
|
6818
|
+
label,
|
|
6819
|
+
status,
|
|
6820
|
+
...evidence.assignmentId === void 0 ? {} : { assignmentId: evidence.assignmentId },
|
|
6821
|
+
...evidence.identity === void 0 ? {} : { identity: evidence.identity },
|
|
6822
|
+
...evidence.materialization === void 0 ? {} : { materialization: evidence.materialization },
|
|
6823
|
+
...evidence.executionBindings === void 0 ? {} : { executionBindings: Object.freeze([...evidence.executionBindings]) },
|
|
6824
|
+
abort() {
|
|
6825
|
+
throw new Error(`cannot abort node '${id}': replayed handles are terminal, not live`);
|
|
6826
|
+
}
|
|
6827
|
+
});
|
|
6828
|
+
}
|
|
6829
|
+
/** A replayed handle must not retain mutable references into the loaded journal event. */
|
|
6830
|
+
function copyFrozenIdentity(identity) {
|
|
6831
|
+
const correlation = identity.correlation === void 0 ? void 0 : Object.freeze({ ...identity.correlation });
|
|
6832
|
+
return Object.freeze({
|
|
6833
|
+
...identity.profileDigest === void 0 ? {} : { profileDigest: identity.profileDigest },
|
|
6834
|
+
...identity.taskDigest === void 0 ? {} : { taskDigest: identity.taskDigest },
|
|
6835
|
+
...identity.candidateDigest === void 0 ? {} : { candidateDigest: identity.candidateDigest },
|
|
6836
|
+
...correlation === void 0 ? {} : { correlation }
|
|
6837
|
+
});
|
|
6838
|
+
}
|
|
6839
|
+
/**
|
|
6840
|
+
* Materialize a recorded `TreeView` from a journaled event list for inspection. Folds
|
|
6841
|
+
* `spawned`/`settled`/`cancelled` into a per-node snapshot in `seq` order, then adds each
|
|
6842
|
+
* `metered` event's driver-inference spend onto its node in a separate additive pass so the view
|
|
6843
|
+
* matches the recorded cursor. It does not recover live executors or driver state after restart.
|
|
6844
|
+
*/
|
|
6845
|
+
function materializeTreeView(events) {
|
|
6846
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
6847
|
+
let root;
|
|
6848
|
+
const spawns = events.filter((ev) => ev.kind === "spawned" || ev.kind === "waiting").sort((a, b) => a.seq - b.seq);
|
|
6849
|
+
const settlements = events.filter((ev) => insideCursorNamespace(ev)).sort((a, b) => a.seq - b.seq);
|
|
6850
|
+
for (const ev of spawns) {
|
|
6851
|
+
if (ev.kind === "waiting") {
|
|
6852
|
+
nodes.set(ev.id, {
|
|
6853
|
+
id: ev.id,
|
|
6854
|
+
parent: ev.parent,
|
|
6855
|
+
label: ev.label,
|
|
6856
|
+
status: "waiting",
|
|
6857
|
+
runtime: "wait",
|
|
6858
|
+
budget: {
|
|
6859
|
+
maxIterations: 0,
|
|
6860
|
+
maxTokens: 0
|
|
6861
|
+
},
|
|
6862
|
+
spent: zeroSpend()
|
|
6863
|
+
});
|
|
6864
|
+
continue;
|
|
6865
|
+
}
|
|
6866
|
+
if (ev.parent === void 0 && root === void 0) root = ev.id;
|
|
6867
|
+
nodes.set(ev.id, {
|
|
6868
|
+
id: ev.id,
|
|
6869
|
+
parent: ev.parent,
|
|
6870
|
+
label: ev.label,
|
|
6871
|
+
status: "pending",
|
|
6872
|
+
runtime: ev.runtime,
|
|
6873
|
+
budget: ev.budget,
|
|
6874
|
+
...ev.ownedTreeRoot === void 0 ? {} : { ownedTreeRoot: ev.ownedTreeRoot },
|
|
6875
|
+
...ev.assignmentId === void 0 ? {} : { assignmentId: ev.assignmentId },
|
|
6876
|
+
...ev.identity ? { identity: ev.identity } : {},
|
|
6877
|
+
spent: zeroSpend()
|
|
6878
|
+
});
|
|
6879
|
+
}
|
|
6880
|
+
for (const ev of settlements) if (ev.kind === "settled") {
|
|
6881
|
+
const node = requireNode(nodes, ev.id);
|
|
6882
|
+
node.status = ev.status === "done" ? "done" : "failed";
|
|
6883
|
+
node.spent = cloneSpend(ev.spent);
|
|
6884
|
+
node.providerModel = copyProviderModelEvidence(ev.providerModel);
|
|
6885
|
+
node.outRef = ev.outRef;
|
|
6886
|
+
node.trace = traceEvidenceFor(ev);
|
|
6887
|
+
const settledAt = Date.parse(ev.at);
|
|
6888
|
+
if (Number.isFinite(settledAt)) node.settledAt = settledAt;
|
|
6889
|
+
} else if (ev.kind === "woken") {
|
|
6890
|
+
const node = requireNode(nodes, ev.id);
|
|
6891
|
+
node.status = ev.by === "cancelled" ? "cancelled" : "done";
|
|
6892
|
+
node.outRef = ev.outRef;
|
|
6893
|
+
node.trace = {
|
|
6894
|
+
status: "unavailable",
|
|
6895
|
+
reason: "not-an-executor"
|
|
6896
|
+
};
|
|
6897
|
+
const settledAt = Date.parse(ev.at);
|
|
6898
|
+
if (Number.isFinite(settledAt)) node.settledAt = settledAt;
|
|
6899
|
+
} else {
|
|
6900
|
+
const node = requireNode(nodes, ev.id);
|
|
6901
|
+
node.status = "cancelled";
|
|
6902
|
+
node.trace = {
|
|
6903
|
+
status: "unavailable",
|
|
6904
|
+
reason: "execution-did-not-start"
|
|
6905
|
+
};
|
|
6906
|
+
const settledAt = Date.parse(ev.at);
|
|
6907
|
+
if (Number.isFinite(settledAt)) node.settledAt = settledAt;
|
|
6908
|
+
}
|
|
6909
|
+
for (const ev of events) {
|
|
6910
|
+
if (ev.kind !== "materialized") continue;
|
|
6911
|
+
const node = requireNode(nodes, ev.id);
|
|
6912
|
+
node.materialization = ev.receipt;
|
|
6913
|
+
node.runtime = ev.receipt.runtime;
|
|
6914
|
+
}
|
|
6915
|
+
for (const ev of events) {
|
|
6916
|
+
if (ev.kind !== "execution-bound") continue;
|
|
6917
|
+
const node = requireNode(nodes, ev.id);
|
|
6918
|
+
node.executionBindings ??= [];
|
|
6919
|
+
node.executionBindings.push(ev.binding);
|
|
6920
|
+
}
|
|
6921
|
+
for (const ev of events) {
|
|
6922
|
+
if (ev.kind !== "metered") continue;
|
|
6923
|
+
const node = requireNode(nodes, ev.id);
|
|
6924
|
+
node.spent = addSpend(node.spent, ev.spend);
|
|
6925
|
+
}
|
|
6926
|
+
const snapshots = [...nodes.values()].map(freezeSnapshot);
|
|
6927
|
+
return {
|
|
6928
|
+
root: root ?? snapshots[0]?.id ?? "",
|
|
6929
|
+
nodes: snapshots,
|
|
6930
|
+
inFlight: snapshots.filter((n) => n.status === "running" || n.status === "acquiring").length,
|
|
6931
|
+
waiting: snapshots.filter((n) => n.status === "waiting").length
|
|
6932
|
+
};
|
|
6933
|
+
}
|
|
6934
|
+
/**
|
|
6935
|
+
* The waits a journaled tree shows as ARMED but never woken — what a resumed run re-arms with the
|
|
6936
|
+
* ORIGINAL absolute deadline. Reading it from the journal (rather than from any live state) is
|
|
6937
|
+
* what makes "SIGKILL a waiting tree, a new process keeps waiting to the same instant" true.
|
|
6938
|
+
*/
|
|
6939
|
+
function pendingWaits(events) {
|
|
6940
|
+
const woken = /* @__PURE__ */ new Set();
|
|
6941
|
+
for (const ev of events) if (ev.kind === "woken") woken.add(ev.id);
|
|
6942
|
+
const pending = [];
|
|
6943
|
+
for (const ev of events) {
|
|
6944
|
+
if (ev.kind !== "waiting" || woken.has(ev.id)) continue;
|
|
6945
|
+
pending.push({
|
|
6946
|
+
id: ev.id,
|
|
6947
|
+
label: ev.label,
|
|
6948
|
+
spec: ev.spec,
|
|
6949
|
+
armedAt: ev.armedAt,
|
|
6950
|
+
ordinal: ev.seq
|
|
6951
|
+
});
|
|
6952
|
+
}
|
|
6953
|
+
return pending.sort((a, b) => a.ordinal - b.ordinal);
|
|
6954
|
+
}
|
|
6955
|
+
/** Copy provider evidence at the journal boundary so replay never exposes mutable event state. */
|
|
6956
|
+
function copyProviderModelEvidence(evidence) {
|
|
6957
|
+
if (evidence === void 0) return void 0;
|
|
6958
|
+
const attempts = Object.freeze(evidence.attempts.map((attempt) => Object.freeze({
|
|
6959
|
+
observations: Object.freeze([...attempt.observations]),
|
|
6960
|
+
...attempt.identityConflict ? { identityConflict: true } : {},
|
|
6961
|
+
...attempt.providerDispatch === "not_started" ? { providerDispatch: "not_started" } : {}
|
|
6962
|
+
})));
|
|
6963
|
+
const models = Object.freeze([...evidence.models]);
|
|
6964
|
+
return Object.freeze(evidence.status === "unknown" ? {
|
|
6965
|
+
status: "unknown",
|
|
6966
|
+
attempts,
|
|
6967
|
+
models,
|
|
6968
|
+
reason: evidence.reason
|
|
6969
|
+
} : {
|
|
6970
|
+
status: "known",
|
|
6971
|
+
attempts,
|
|
6972
|
+
models
|
|
6973
|
+
});
|
|
6974
|
+
}
|
|
6975
|
+
function requireNode(nodes, id) {
|
|
6976
|
+
const node = nodes.get(id);
|
|
6977
|
+
if (!node) throw new Error(`spawn journal corrupted: settle/cancel for node '${id}' with no prior spawn`);
|
|
6978
|
+
return node;
|
|
6979
|
+
}
|
|
6980
|
+
function freezeSnapshot(node) {
|
|
6981
|
+
return {
|
|
6982
|
+
id: node.id,
|
|
6983
|
+
parent: node.parent,
|
|
6984
|
+
label: node.label,
|
|
6985
|
+
status: node.status,
|
|
6986
|
+
runtime: node.runtime,
|
|
6987
|
+
budget: node.budget,
|
|
6988
|
+
ownedTreeRoot: node.ownedTreeRoot,
|
|
6989
|
+
assignmentId: node.assignmentId,
|
|
6990
|
+
identity: node.identity,
|
|
6991
|
+
materialization: node.materialization,
|
|
6992
|
+
executionBindings: node.executionBindings === void 0 ? void 0 : Object.freeze([...node.executionBindings]),
|
|
6993
|
+
spent: node.spent,
|
|
6994
|
+
providerModel: node.providerModel,
|
|
6995
|
+
outRef: node.outRef,
|
|
6996
|
+
trace: node.trace,
|
|
6997
|
+
settledAt: node.settledAt
|
|
6998
|
+
};
|
|
6999
|
+
}
|
|
7000
|
+
function traceEvidenceFor(event) {
|
|
7001
|
+
return event.trace ?? {
|
|
7002
|
+
status: "unavailable",
|
|
7003
|
+
reason: "legacy-settlement-without-trace-evidence"
|
|
7004
|
+
};
|
|
7005
|
+
}
|
|
7006
|
+
//#endregion
|
|
6021
7007
|
//#region src/runtime/supervise/task-prompt.ts
|
|
6022
7008
|
/**
|
|
6023
7009
|
*
|
|
@@ -13916,12 +14902,11 @@ function createScope(args) {
|
|
|
13916
14902
|
if (pending !== void 0) {
|
|
13917
14903
|
if (profileDigest === void 0) throw new ValidationError("scope.spawn: a pending materialization requires a canonical authored profile");
|
|
13918
14904
|
if (pending.runtime !== executor.runtime || pending.binding.attemptId !== attemptId) throw new ValidationError("scope.spawn: pending executor did not bind the kernel-minted attempt id");
|
|
13919
|
-
|
|
14905
|
+
if (knownMaterializationReceipt({
|
|
13920
14906
|
authoredProfileDigest: profileDigest,
|
|
13921
14907
|
runtime: executor.runtime,
|
|
13922
14908
|
declaration: pending.declaration
|
|
13923
|
-
});
|
|
13924
|
-
if (plannedReceipt.status !== "known" || plannedReceipt.effectiveProfileDigest !== plannedReceipt.authoredProfileDigest) throw new ValidationError("scope.spawn: pending executor changed the authored AgentProfile before execution");
|
|
14909
|
+
}).status !== "known") throw new ValidationError("scope.spawn: pending executor returned an unknown receipt");
|
|
13925
14910
|
let recorded = false;
|
|
13926
14911
|
pendingEvidence = {
|
|
13927
14912
|
complete: async () => {
|
|
@@ -13935,7 +14920,6 @@ function createScope(args) {
|
|
|
13935
14920
|
declaration: acknowledged
|
|
13936
14921
|
});
|
|
13937
14922
|
if (finalReceipt.status !== "known") throw new ValidationError("scope.spawn: terminal materialization remained unknown");
|
|
13938
|
-
if (finalReceipt.effectiveProfileDigest !== finalReceipt.authoredProfileDigest) throw new ValidationError("scope.spawn: external executor changed the authored AgentProfile");
|
|
13939
14923
|
const finalBinding = knownExecutionBindingReceipt(finalReceipt, acknowledgedBinding);
|
|
13940
14924
|
await appendNodeMaterialization(args, id, ordinal, finalReceipt, finalBinding, now);
|
|
13941
14925
|
live.materialization = finalReceipt;
|
|
@@ -14428,7 +15412,6 @@ async function recordScopeOwnerMaterialization(scope, runtime, declaration, bind
|
|
|
14428
15412
|
let binding;
|
|
14429
15413
|
try {
|
|
14430
15414
|
if (bindingInput.attemptId !== state.attemptId) throw new ValidationError("scope owner execution binding does not use the kernel-minted attempt id");
|
|
14431
|
-
if (canonicalAgentProfileDigest(declaration.effectiveProfile) !== state.authoredProfileDigest) throw new ValidationError("scope owner stable effective profile conflicts with its admitted authored profile");
|
|
14432
15415
|
receipt = knownMaterializationReceipt({
|
|
14433
15416
|
authoredProfileDigest: state.authoredProfileDigest,
|
|
14434
15417
|
runtime,
|
|
@@ -15210,7 +16193,7 @@ function errMessage(err) {
|
|
|
15210
16193
|
* journal so the executor can run its `act` inside a nested scope. `act` fails loud if
|
|
15211
16194
|
* called directly — a driver child runs THROUGH its nested-scope executor, never as a root.
|
|
15212
16195
|
*/
|
|
15213
|
-
function driverChild(profile, driver, journal, execution) {
|
|
16196
|
+
function driverChild(profile, driver, journal, execution, acceptedSubmission) {
|
|
15214
16197
|
const name = profile.name ?? driver.name;
|
|
15215
16198
|
const spec = executableAgentSpecSnapshot({
|
|
15216
16199
|
profile,
|
|
@@ -15218,7 +16201,8 @@ function driverChild(profile, driver, journal, execution) {
|
|
|
15218
16201
|
...execution ? { execution } : {},
|
|
15219
16202
|
driverRuntime,
|
|
15220
16203
|
driver,
|
|
15221
|
-
journal
|
|
16204
|
+
journal,
|
|
16205
|
+
...acceptedSubmission ? { acceptedSubmission } : {}
|
|
15222
16206
|
}, "driverChild");
|
|
15223
16207
|
const deliver = driver.deliver?.bind(driver);
|
|
15224
16208
|
return {
|
|
@@ -15297,7 +16281,7 @@ const driverExecutorFactory = (rawSpec, ctx) => {
|
|
|
15297
16281
|
reported: childWork,
|
|
15298
16282
|
reservation: addSpend(childWork, meteredSpend ?? zeroSpend())
|
|
15299
16283
|
};
|
|
15300
|
-
const verdict = deriveDeliveryVerdict(settled, out);
|
|
16284
|
+
const verdict = deriveDeliveryVerdict(settled, out, spec.acceptedSubmission?.() === true);
|
|
15301
16285
|
artifact = {
|
|
15302
16286
|
outRef: `${driverRuntime}:${nestedRoot}`,
|
|
15303
16287
|
out,
|
|
@@ -15416,13 +16400,18 @@ async function safeRollup(journal, nestedRoot) {
|
|
|
15416
16400
|
return;
|
|
15417
16401
|
}
|
|
15418
16402
|
}
|
|
15419
|
-
/** Derive the driver child's delivery verdict from
|
|
15420
|
-
* manager's actual finalized output: `valid` iff
|
|
15421
|
-
*
|
|
16403
|
+
/** Derive the driver child's delivery verdict from an accepted direct submission, or from its
|
|
16404
|
+
* DIRECT children's settlements and the manager's actual finalized output: `valid` iff the
|
|
16405
|
+
* manager's own assignment check accepted a submission, or a direct child delivered AND the
|
|
16406
|
+
* finalizer returned a defined output;
|
|
15422
16407
|
* `score` = the best delivered score. Returns `undefined` when no child settled at all (the
|
|
15423
16408
|
* driver itself produced nothing to bubble a verdict from). Fail-closed: a child whose verdict
|
|
15424
16409
|
* carried no `valid` counts as not-delivered. */
|
|
15425
|
-
function deriveDeliveryVerdict(settled, finalizedOutput) {
|
|
16410
|
+
function deriveDeliveryVerdict(settled, finalizedOutput, acceptedSubmission) {
|
|
16411
|
+
if (acceptedSubmission) return {
|
|
16412
|
+
valid: true,
|
|
16413
|
+
score: 1
|
|
16414
|
+
};
|
|
15426
16415
|
let sawChild = false;
|
|
15427
16416
|
let anyValid = false;
|
|
15428
16417
|
let bestValidScore;
|
|
@@ -16414,6 +17403,6 @@ function resolveRedactor(redact) {
|
|
|
16414
17403
|
return (value) => defaultRedactor(redact(value));
|
|
16415
17404
|
}
|
|
16416
17405
|
//#endregion
|
|
16417
|
-
export { createBudgetPool as $,
|
|
17406
|
+
export { createBudgetPool as $, assertProfileMaterialization as $n, workerTraceAnalysisStore as $t, interactiveAdmissionSeamKey as A, flatOtelSpan as An, claimsAuthority as At, reconnectRetainedRun as B, sanitizeRuntimeStreamEvent as Bn, FileSpawnJournal as Bt, settledToIteration as C, INTELLIGENCE_WIRE_VERSION as Cn, DEFAULT_STALL_AFTER_MS as Ct, timerAt as D, createOpenInferenceFileExporter as Dn, AUTHORITY_MARKERS as Dt, pollFor as E, buildRuntimeEventOtelSpans as En, createInbox as Et, workerInteractiveBindingFile as F, toOtelAttributes as Fn, isLiveNodeStatus as Ft, destroyInteractiveEnvironment as G, removeWorktree as Gn, loadSpawnForest as Gt, startRetainedRun as H, runWorktreeHarness as Hn, InMemorySpawnJournal as Ht, workerInteractiveBindingsDir as I, createRuntimeEventCollector as In, isTerminalNodeStatus as It, queueOf as J, harnessSupportsReasoningEffort as Jn, replaySpawnTree as Jt, effectiveConcurrency as K, DEFAULT_LOCAL_HARNESS as Kn, materializeTreeView as Kt, reconnectRetainedInteractiveRun as L, createRuntimeStreamEventCollector as Ln, createInPlaceCliExecutor as Lt, workerInteractiveAdmissionFile as M, loopEventToOtelSpan as Mn, isPeerMailEnvelope as Mt, attachWorker as N, padSpanId as Nn, peerMailTools as Nt, validateWaitSpec as O, createOtelExporter as On, DEFAULT_PEER_MAIL_LIMITS as Ot, readWorkerInteractiveBinding as P, padTraceId as Pn, peerMailVerbNames as Pt, assertValidBudget as Q, AGENT_PROFILE_MATERIALIZATION_AXES as Qn, parseWorkerToolTraceArtifact as Qt, recoverRetainedInteractiveRun as R, sanitizeAgentRuntimeEvent as Rn, taskToPrompt as Rt, scopeOwnerExecutorNodeContext as S, traceContextToEnv as Sn, sandboxSessionTraceSource as St, isWaitOutcome as T, buildLoopSpanNodes as Tn, readWorkerProgress as Tt, startRetainedRunInEnvironment as U, captureWorktreeDiff as Un, closesCursorSlot as Ut, recoverRetainedRun as V, runSettledCommand as Vn, InMemoryResultBlobStore as Vt, retainedCreateMaterial as W, createWorktree as Wn, insideCursorNamespace as Wt, DEFAULT_SUCCESSFUL_SHUTDOWN_MS as X, parseCodexTokenUsage as Xn, captureWorkerTraceEvidence as Xt, rollingDispatch as Y, localHarnessExecutable as Yn, WORKER_TOOL_TRACE_SCHEMA_VERSION as Yt, teardownExecutor as Z, CodexExecutionDiagnosticError as Zn, isTraceAnalysisStore as Zt, createScope as _, harnessUsageIsEmpty as _n, workerTraceSeamKey as _t, createSupervisor as a, runAgentRounds as an, promptModelProfileMaterialization as ar, bridgeStopSignalKey as at, meterRuntimeOwnedProviderAttempt as b, mergeTraceEnv as bn, createPushTraceSource as bt, uncertainSpawnBudgets as c, acquireSandbox as cn, renderProfileMaterializationIssues as cr, cliWorktreeExecutor as ct, pickBestDelivered as d, routerBrain as dn, unsupportedProfileDimensions as dr, snapshotExecutorConfig as dt, contentAddress as en, controlProfileMaterialization as er, spendFromUsageEvents as et, runFinalizer as f, runBrainLoop as fn, validateProfileMaterialization as fr, createWorktreeCliExecutor as ft, beginScopeOwnerAttempt as g, createCodexRolloutStoreReader as gn, workerTraceHeaders as gt, withDriverExecutor as h, addHarnessUsage as hn, workerTraceEnv as ht, createRootHandle as i, isTerminalDecision as in, promptControlProfileMaterialization as ir, bridgeRuntimeAttachmentsKey as it, readWorkerInteractiveAdmissions as j, generateSpanId as jn, createPeerMailbox as jt, waitUntil as k, exportEvalRuns as kn, PEER_MAIL_WIRE_KEY as kt, bestDelivered as l, assertBoxlessPromptOptions as ln, renderUnsupported as lr, createExecutor as lt, driverChild as m, observedModelMatchesDeclared as mn, readWorkerTraceContext as mt, defaultRedactorIdentityMaterial as n, createSandboxForSpec as nn, fullProfileMaterialization as nr, bridgeAdmissionRefusal as nt, maxSeqOf as o, createSandboxLineage as on, promptOnlyProfileMaterialization as or, captureReusableExecutorConfig as ot, runTree as p, canonicalObservedModelParts as pn, worktreeCliProfileMaterialization as pr, WORKER_TRACE_PROPAGATION as pt, freeSlots as q, LOCAL_HARNESSES as qn, pendingWaits as qt, resolveRedactor as r, defaultSelectWinner as rn, profileMaterializationAxes$1 as rr, bridgeModelRouteRefusal as rt, sumMeasuredSpendFromEvents as s, probeSandboxCapabilities as sn, promptResourceProfileMaterialization as sr, cliInPlaceExecutor as st, defaultRedactor as t, TERMINAL_DECISIONS as tn, defineProfileMaterializationContract as tr, bindReusableExecutorExecutionId as tt, collectDelivered as u, readPromptOptions as un, sandboxActProfileMaterialization as ur, createExecutorRegistry as ut, deriveNodeExecutionIdentity as v, readCodexRolloutSession as vn, DEFAULT_SANDBOX_STEERING_MAX_TURNS as vt, createWaitProbes as w, buildLoopOtelSpans as wn, createActivityLog as wt, recordScopeOwnerMaterialization as x, readTraceContextFromEnv as xn, decodeToolPart as xt, meterRuntimeOwnedAccounting as y, createPropagatingTraceEmitter as yn, createSteerableSandboxSession as yt, startRetainedInteractiveRun as z, sanitizeKnowledgeReadinessReport as zn, FileResultBlobStore as zt };
|
|
16418
17407
|
|
|
16419
|
-
//# sourceMappingURL=redact-
|
|
17408
|
+
//# sourceMappingURL=redact-BOU77QfQ.js.map
|