From f0599bf4c33886b52f9874584b4f1be0f9f565dc Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Fri, 21 Aug 2026 10:28:55 -0700 Subject: [PATCH 1/5] fix(vocabulary): close the nine drift items that needed a decision The bridge reasoning check read a private copy of the cli-bridge effort map and the copy was stale. It expected codex to apply `minimal` for `none` and `high` for `xhigh` and `ultracode`; cli-bridge 0.3.0 applies `none`, `xhigh` and `ultra`. A mismatch throws, so three of the seven rungs refused a legitimate codex run. Its default arm asserted the canonical rung for eleven more harnesses whose receipts carry `applied: null`, refusing those too. Both halves now read `nativeReasoningControl` from @tangle-network/agent-interface 1.6.0, the same table the bridge argv builders read. The two test fakes echoed the same stale map, which is why the drift survived; each now transcribes cli-bridge instead. An in-process worker is no longer journaled as a sandbox sibling: the two loop trace types carry `in-process`, and `PlacementInfo` maps it to `local`. A cost or latency breakdown split by placement counted every local run in the sandbox bucket. `ImproveSurface` is derived from `AgentImprovementSurface`, so what `improve()` produces is a subset of what a proposal can name by construction. `improvementSurfaceValues` gains the rollout-policy value, and `opaqueProfileSlice` stops folding the same extension into `agent-profile`, which would have reported two changed surfaces for one edit. One `PursuitStatus` replaces `PursuitRunStatus` and `PursuitNodeStatus`: they disagreed on the word for a failure in the same file, so joining run rows to node rows split one failure population into two. `down` wins because the journal writes it. Deleted: `Restart` and `SpawnOpts.restart`, which the supervisor dropped silently while the keyed-spawn contract already owns retry; `restartCount`, which nothing could increment and which replay overwrote with 0 anyway; `CoderReview.recommendation`, which promised traces the delegate has no run id to emit and which selection never read; `UsageClass`, whose declaration was its only occurrence. `memory-store.provision` narrows to the one backend anything names. `ResearchSource` is deduped rather than deleted: it has a live reader through `DelegationArgs`. `interactive-session-not-started` is kept and documented: it is the Executor port's vocabulary, and its first-party emitter is #773, blocked upstream. Closes #954 --- docs/api/durable.md | 22 ++++------ docs/api/index.md | 23 +++++------ docs/api/intelligence.md | 16 ++------ docs/api/mcp.md | 33 +++++++-------- docs/api/primitive-catalog.md | 20 ++++----- docs/api/profiles.md | 3 +- docs/api/runtime.md | 20 +++------ docs/canonical-api.md | 4 +- package.json | 4 +- pnpm-lock.yaml | 34 +++++++-------- pnpm-workspace.yaml | 2 +- src/durable/index.ts | 3 +- src/durable/observer-projection.ts | 25 +++++------ src/durable/spawn-journal.ts | 3 -- src/improvement/improve-types.ts | 32 +++++++-------- src/intelligence/capability.ts | 4 +- src/intelligence/improvement-surfaces.ts | 11 +++++ src/intelligence/index.ts | 5 --- src/mcp/delegates.ts | 4 +- src/mcp/in-process-executor.ts | 2 +- src/mcp/types.ts | 4 +- src/profiles/researcher.ts | 4 +- src/runtime/environment-provider.ts | 4 +- src/runtime/index.ts | 1 - src/runtime/supervise/bridge-executor.test.ts | 18 +++++--- src/runtime/supervise/runtime.ts | 41 ++++--------------- src/runtime/supervise/scope.ts | 7 ---- src/runtime/supervise/types.ts | 11 +++-- src/runtime/types.ts | 7 +++- .../fixtures/agent-improvement-proposal.json | 10 ++--- .../agent-profile-improvement-proposal.json | 6 +-- .../supervise-full-profile-bridge.test.ts | 40 +++++++++++++++--- tests/kernel/supervise.test.ts | 2 - tests/mcp/coder-delegate-selection.test.ts | 2 - tests/mcp/detached-turn.test.ts | 2 +- 35 files changed, 205 insertions(+), 224 deletions(-) diff --git a/docs/api/durable.md b/docs/api/durable.md index 5dfafbc3..12d837aa 100644 --- a/docs/api/durable.md +++ b/docs/api/durable.md @@ -650,7 +650,7 @@ entries sum to `inclusive` by construction. ##### status -> `readonly` **status**: [`PursuitRunStatus`](#pursuitrunstatus) +> `readonly` **status**: [`PursuitStatus`](#pursuitstatus) ##### settledAt? @@ -750,7 +750,7 @@ The runner that executed this node — the executor's own name, not a harness gu ##### status -> `readonly` **status**: [`PursuitNodeStatus`](#pursuitnodestatus) +> `readonly` **status**: [`PursuitStatus`](#pursuitstatus) ##### settledAt? @@ -866,10 +866,6 @@ Content-addressed pointer to this node's persisted tool trace, or why there is n > `readonly` `optional` **infra?**: `boolean` -##### restartCount? - -> `readonly` `optional` **restartCount?**: `number` - ##### wait? > `readonly` `optional` **wait?**: `unknown` @@ -1807,9 +1803,13 @@ already knowing the root node or coordination run id stored inside it. *** -### PursuitRunStatus +### PursuitStatus -> **PursuitRunStatus** = `"running"` \| `"done"` \| `"failed"` +> **PursuitStatus** = `"running"` \| `"done"` \| `"down"` + +One settled projection status, shared by runs and nodes. `down` is the journal's own word for a +failure (a settlement is journaled as `kind: 'down'`, cancellation included), so a consumer can +join run rows to node rows on `status` and read one failure population instead of two. *** @@ -1829,12 +1829,6 @@ rest; `unknown` = nothing priced it, so `usd` is a floor and never the cost. Where and how a node's execution was placed, read off its execution-binding receipt. -*** - -### PursuitNodeStatus - -> **PursuitNodeStatus** = `"running"` \| `"done"` \| `"down"` - ## Functions ### handleChatTurn() diff --git a/docs/api/index.md b/docs/api/index.md index fe6a0cc3..ddae67cb 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -11324,13 +11324,16 @@ git worktree through a pluggable `CandidateGenerator`. ### ImproveSurface -> **ImproveSurface** = `"prompt"` \| `"skills"` \| `"tools"` \| `"mcp"` \| `"hooks"` \| `"subagents"` \| `"agent-profile"` \| `"memory"` \| `"code"` \| `"rollout-policy"` +> **ImproveSurface** = `Exclude`\<`AgentImprovementSurface`, `"knowledge"`\> -The executable agent lever `improve` optimizes. Profile fields remain -portable AgentProfile coordinates; implementation and orchestration files -use the code surface so a winner can be sealed into an exact candidate. -`rollout-policy` is the inference-time structuralRollout dials -(`profile.extensions['structural-rollout']`). +The executable agent lever `improve` optimizes — every surface a proposal can name +(`AgentImprovementSurface`) except `knowledge`, which the corpus lane owns and `improve` +does not produce. Deriving it means every surface `improve` produces can also be reported, which +is the property that lets a result reach a review or a gate. + +Profile fields remain portable AgentProfile coordinates; implementation and orchestration files +use the code surface so a winner can be sealed into an exact candidate. `rollout-policy` is the +inference-time structuralRollout dials (`profile.extensions['structural-rollout']`). *** @@ -12046,7 +12049,7 @@ Content-addressed pointer to a persisted `WorkerToolTraceArtifact`. ### Settled -> **Settled**\<`Out`\> = \{ `kind`: `"done"`; `handle`: [`Handle`](runtime.md#handle-3)\<`Out`\>; `out`: `Out`; `outRef`: `string`; `verdict?`: `DefaultVerdict`; `spent`: [`Spend`](#spend); `providerModel?`: [`ProviderModelExecutionEvidence`](#providermodelexecutionevidence); `trace`: [`WorkerTraceEvidence`](#workertraceevidence); `settledAt?`: `number`; `seq`: `number`; \} \| \{ `kind`: `"down"`; `handle`: [`Handle`](runtime.md#handle-3)\<`Out`\>; `reason`: `string`; `infra`: `boolean`; `restartCount`: `number`; `trace`: [`WorkerTraceEvidence`](#workertraceevidence); `providerModel?`: [`ProviderModelExecutionEvidence`](#providermodelexecutionevidence); `settledAt?`: `number`; `seq`: `number`; \} +> **Settled**\<`Out`\> = \{ `kind`: `"done"`; `handle`: [`Handle`](runtime.md#handle-3)\<`Out`\>; `out`: `Out`; `outRef`: `string`; `verdict?`: `DefaultVerdict`; `spent`: [`Spend`](#spend); `providerModel?`: [`ProviderModelExecutionEvidence`](#providermodelexecutionevidence); `trace`: [`WorkerTraceEvidence`](#workertraceevidence); `settledAt?`: `number`; `seq`: `number`; \} \| \{ `kind`: `"down"`; `handle`: [`Handle`](runtime.md#handle-3)\<`Out`\>; `reason`: `string`; `infra`: `boolean`; `trace`: [`WorkerTraceEvidence`](#workertraceevidence); `providerModel?`: [`ProviderModelExecutionEvidence`](#providermodelexecutionevidence); `settledAt?`: `number`; `seq`: `number`; \} A settled child, delivered by `scope.next()`. `seq` is the monotonic cursor order `next()` yielded this settlement (B2) — NOT wall-clock — and replay delivers strictly @@ -12114,7 +12117,7 @@ Epoch ms parsed from the durable settlement record when available. ##### Type Literal -\{ `kind`: `"down"`; `handle`: [`Handle`](runtime.md#handle-3)\<`Out`\>; `reason`: `string`; `infra`: `boolean`; `restartCount`: `number`; `trace`: [`WorkerTraceEvidence`](#workertraceevidence); `providerModel?`: [`ProviderModelExecutionEvidence`](#providermodelexecutionevidence); `settledAt?`: `number`; `seq`: `number`; \} +\{ `kind`: `"down"`; `handle`: [`Handle`](runtime.md#handle-3)\<`Out`\>; `reason`: `string`; `infra`: `boolean`; `trace`: [`WorkerTraceEvidence`](#workertraceevidence); `providerModel?`: [`ProviderModelExecutionEvidence`](#providermodelexecutionevidence); `settledAt?`: `number`; `seq`: `number`; \} ###### kind @@ -12134,10 +12137,6 @@ Epoch ms parsed from the durable settlement record when available. True = infrastructure failure (excluded from merge `n` / equal-k), not a bad result. -###### restartCount - -> **restartCount**: `number` - ###### trace > **trace**: [`WorkerTraceEvidence`](#workertraceevidence) diff --git a/docs/api/intelligence.md b/docs/api/intelligence.md index 0d55f226..c844cea0 100644 --- a/docs/api/intelligence.md +++ b/docs/api/intelligence.md @@ -3889,7 +3889,7 @@ never inlined here. ### DeliveryBinding -> **DeliveryBinding** = \{ `kind`: `"inline"`; `content`: [`ContentRef`](#contentref); \} \| \{ `kind`: `"file"`; `path`: `string`; `content`: [`ContentRef`](#contentref); `executable?`: `boolean`; \} \| \{ `kind`: `"http"`; `url`: `string`; `method?`: `string`; `auth?`: [`CapabilityAuth`](#capabilityauth); \} \| \{ `kind`: `"sandbox-code"`; `entry`: `string`; `code`: [`ContentRef`](#contentref); `runtime?`: `string`; `harness?`: `string`; \} \| \{ `kind`: `"mcp-stdio"`; `command`: `string`; `args?`: `string`[]; `env?`: `Record`\<`string`, `string`\>; `cwd?`: `string`; \} \| \{ `kind`: `"mcp-remote"`; `url`: `string`; `transport`: `"http"` \| `"sse"`; `headers?`: `Record`\<`string`, `string`\>; \} \| \{ `kind`: `"process-on-infra"`; `host`: [`HostSpec`](#hostspec); `inner`: [`DeliveryBinding`](#deliverybinding); \} \| \{ `kind`: `"rag-index"`; `index`: [`ContentRef`](#contentref); `embedModel`: `string`; `topK?`: `number`; \} \| \{ `kind`: `"memory-store"`; `provision`: `"sqlite"` \| `"neo4j"` \| `"vector"`; `seed?`: [`ContentRef`](#contentref); \} \| \{ `kind`: `"wasm"`; `module`: [`ContentRef`](#contentref); `exports`: `string`[]; \} \| \{ `kind`: `"a2a"`; `endpoint`: `string`; `card`: [`ContentRef`](#contentref); `auth?`: [`CapabilityAuth`](#capabilityauth); \} +> **DeliveryBinding** = \{ `kind`: `"inline"`; `content`: [`ContentRef`](#contentref); \} \| \{ `kind`: `"file"`; `path`: `string`; `content`: [`ContentRef`](#contentref); `executable?`: `boolean`; \} \| \{ `kind`: `"http"`; `url`: `string`; `method?`: `string`; `auth?`: [`CapabilityAuth`](#capabilityauth); \} \| \{ `kind`: `"sandbox-code"`; `entry`: `string`; `code`: [`ContentRef`](#contentref); `runtime?`: `string`; `harness?`: `string`; \} \| \{ `kind`: `"mcp-stdio"`; `command`: `string`; `args?`: `string`[]; `env?`: `Record`\<`string`, `string`\>; `cwd?`: `string`; \} \| \{ `kind`: `"mcp-remote"`; `url`: `string`; `transport`: `"http"` \| `"sse"`; `headers?`: `Record`\<`string`, `string`\>; \} \| \{ `kind`: `"process-on-infra"`; `host`: [`HostSpec`](#hostspec); `inner`: [`DeliveryBinding`](#deliverybinding); \} \| \{ `kind`: `"rag-index"`; `index`: [`ContentRef`](#contentref); `embedModel`: `string`; `topK?`: `number`; \} \| \{ `kind`: `"memory-store"`; `provision`: `"sqlite"`; `seed?`: [`ContentRef`](#contentref); \} \| \{ `kind`: `"wasm"`; `module`: [`ContentRef`](#contentref); `exports`: `string`[]; \} \| \{ `kind`: `"a2a"`; `endpoint`: `string`; `card`: [`ContentRef`](#contentref); `auth?`: [`CapabilityAuth`](#capabilityauth); \} How a capability is backed. OPEN tagged union — THE extension point. All arms are typed even when the resolver does not yet admit them; an un-admitted arm @@ -4042,16 +4042,6 @@ The portable profile changes that the measured-profile contract permits. *** -### UsageClass - -> **UsageClass** = `"inference"` \| `"intelligence"` - -Usage class for billing. Base-stream tokens bill `'inference'`; every - intelligence spawn (analyst, corpus, loop) bills `'intelligence'`. The - billing line falls on the spawn line. - -*** - ### AgentImprovementProfileActivationTarget > **AgentImprovementProfileActivationTarget** = `Omit`\<[`AgentImprovementActivationTargetPlan`](#agentimprovementactivationtargetplan), `"surface"`\> & `object` @@ -4931,7 +4921,7 @@ Bind caller-owned target identities to the exact source state Runtime measured. ##### surfaces -readonly `AgentImprovementSurface`[] +readonly (`"knowledge"` \| `"prompt"` \| `"tools"` \| `"mcp"` \| `"subagents"` \| `"hooks"` \| `"skills"` \| `"code"` \| `"memory"` \| `"agent-profile"` \| `"rollout-policy"`)[] ##### experiment @@ -4961,7 +4951,7 @@ Return whether a measured surface can be delivered through an agent profile. ##### surface -`AgentImprovementSurface` +`"knowledge"` \| `"prompt"` \| `"tools"` \| `"mcp"` \| `"subagents"` \| `"hooks"` \| `"skills"` \| `"code"` \| `"memory"` \| `"agent-profile"` \| `"rollout-policy"` #### Returns diff --git a/docs/api/mcp.md b/docs/api/mcp.md index 70a6a272..f3c3a443 100644 --- a/docs/api/mcp.md +++ b/docs/api/mcp.md @@ -811,14 +811,6 @@ Structured review verdict over a coder candidate. Gate: only approved candidates are eligible to win. -##### recommendation - -> **recommendation**: `"ship"` \| `"reject"` \| `"approve-with-nits"` \| `"changes-requested"` - -**`Experimental`** - -Reviewer's recommendation — surfaced in traces. - ##### readiness > **readiness**: `number` @@ -833,6 +825,9 @@ Readiness 0..1, used by the `highest-readiness` winner-selection strategy. **`Experimental`** +The reviewer's own words. Selection reads `approved` and `readiness`; anything a reviewer + wants a caller to READ belongs here, because nothing else on this type is surfaced. + *** ### DetachedSessionDelegateOptions @@ -2007,10 +2002,14 @@ Which harness handled this delegation. ##### kind -> **kind**: `"sibling"` \| `"fleet"` +> **kind**: `"sibling"` \| `"fleet"` \| `"in-process"` **`Experimental`** +`in-process` is a local harness CLI in the caller's own process tree — no sandbox, no fleet. + It is a placement in its own right so a cost or latency breakdown split by placement does not + count local runs in the sandbox bucket. + ###### Inherited from [`LoopSandboxPlacement`](runtime.md#loopsandboxplacement).[`kind`](runtime.md#kind-16) @@ -4547,7 +4546,7 @@ Best-effort hint — coder loops can take minutes-to-hours. ##### sources? -> `optional` **sources?**: [`ResearchSource`](#researchsource)[] +> `optional` **sources?**: [`ResearchSource`](profiles.md#researchsource)[] **`Experimental`** @@ -5644,14 +5643,6 @@ The synchronous result the `delegate` tool returns to the calling agent: the del *** -### ResearchSource - -> **ResearchSource** = `"web"` \| `"corpus"` \| `"twitter"` \| `"github"` \| `"docs"` - -**`Experimental`** - -*** - ### DelegationResultPayload > **DelegationResultPayload** = \{ `profile`: `"coder"`; `output`: [`CoderOutput`](#coderoutput); \} \| \{ `profile`: `"researcher"`; `output`: [`ResearchOutputShape`](#researchoutputshape); \} \| \{ `profile`: `"ui-auditor"`; `output`: [`UiAuditorDelegationOutput`](#uiauditordelegationoutput); \} @@ -7673,3 +7664,9 @@ Re-exports [WorkerSpawnContext](runtime.md#workerspawncontext) ### WorkerWatchOptions Re-exports [WorkerWatchOptions](runtime.md#workerwatchoptions) + +*** + +### ResearchSource + +Re-exports [ResearchSource](profiles.md#researchsource) diff --git a/docs/api/primitive-catalog.md b/docs/api/primitive-catalog.md index 2a371d25..5f728a86 100644 --- a/docs/api/primitive-catalog.md +++ b/docs/api/primitive-catalog.md @@ -7,7 +7,7 @@ # Primitive catalog — the never-stale anti-reinvention inventory -> **GENERATED** from `@tangle-network/agent-runtime@0.156.0` and `@tangle-network/agent-eval@0.163.2` by `scripts/gen-primitive-catalog.mjs`. Do NOT hand-edit — run `pnpm run docs:api`. This is the mechanical companion to the JUDGMENT in `canonical-api.md` (§2 decision table + §1.5 AgentProfile law): that doc says WHICH primitive to reach for and what NOT to build; this catalog proves WHAT exists. Per-symbol signatures + `file:line` live in the per-module pages under `docs/api/`. +> **GENERATED** from `@tangle-network/agent-runtime@0.157.0` and `@tangle-network/agent-eval@0.163.2` by `scripts/gen-primitive-catalog.mjs`. Do NOT hand-edit — run `pnpm run docs:api`. This is the mechanical companion to the JUDGMENT in `canonical-api.md` (§2 decision table + §1.5 AgentProfile law): that doc says WHICH primitive to reach for and what NOT to build; this catalog proves WHAT exists. Per-symbol signatures + `file:line` live in the per-module pages under `docs/api/`. ## 1. agent-runtime — own public surface @@ -257,7 +257,7 @@ Import from `@tangle-network/agent-runtime` — 440 exports. | `ImproveMethodOptions` | type | Complete-method configuration for every non-code profile surface. | | `ImproveOptions` | type | The canonical improvement API: complete methods for profiles, worktrees for code. | | `ImproveProfileAgent` | type | Runs one exact materialized profile on one scenario. | -| `ImproveSurface` | type | The executable agent lever `improve` optimizes. Profile fields remain | +| `ImproveSurface` | type | The executable agent lever `improve` optimizes — every surface a proposal can name | | `OfficialGepaOptions` | type | Official GEPA configuration plus bounded Runtime findings context. | | `OfficialSkillOptOptions` | type | Official SkillOpt configuration plus bounded Runtime findings context. | | `OpenAIChatResponseFormat` | type | `response_format` parameter for OpenAI-compatible chat endpoints. Use | @@ -370,7 +370,7 @@ Import from `@tangle-network/agent-runtime/conversation` — 54 exports. ### Product chat turns — edge-safe streaming, persistence, and stable execution IDs -Import from `@tangle-network/agent-runtime/durable` — 34 exports. +Import from `@tangle-network/agent-runtime/durable` — 33 exports. | Symbol | Kind | Summary | |---|---|---| @@ -398,8 +398,9 @@ Import from `@tangle-network/agent-runtime/durable` — 34 exports. | `RunChatTurnInput` | interface | Inputs for one streamed product chat turn. | | `PursuitCostProvenance` | type | Where a node's dollar figure came from. `reported` = a provider billed all of it; `estimated` = | | `PursuitNodePlacement` | type | Where and how a node's execution was placed, read off its execution-binding receipt. | +| `PursuitStatus` | type | One settled projection status, shared by runs and nodes. `down` is the journal's own word for a | -**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `DurableCoordinationStreamIdentity`, `ObserverJournal`, `PursuitNodeProjection`, `PursuitProjection`, `PursuitRunProjection`, `SupervisedPursuitResult`, `SupervisePursuitOptions`, `ObserverRecordKind`, `PursuitNodeStatus`, `PursuitRunStatus`. +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `DurableCoordinationStreamIdentity`, `ObserverJournal`, `PursuitNodeProjection`, `PursuitProjection`, `PursuitRunProjection`, `SupervisedPursuitResult`, `SupervisePursuitOptions`, `ObserverRecordKind`. ### Bounded tool calls for browser and edge runtimes @@ -418,7 +419,7 @@ Import from `@tangle-network/agent-runtime/tool-loop` — 12 exports. ### Intelligence SDK — Observe + provable-OFF billing -Import from `@tangle-network/agent-runtime/intelligence` — 172 exports. +Import from `@tangle-network/agent-runtime/intelligence` — 171 exports. | Symbol | Kind | Summary | |---|---|---| @@ -549,13 +550,12 @@ Import from `@tangle-network/agent-runtime/intelligence` — 172 exports. | `PullOutcome` | type | Typed outcome for the pull — inspect `succeeded` before `value`. A 404 | | `Redactor` | type | A redactor maps an arbitrary trace value to a safe-to-export value. Pure; | | `SubmitAgentImprovementProposalOutcome` | type | Typed result for proposal submission. A successful result contains the | -| `UsageClass` | type | Usage class for billing. Base-stream tokens bill `'inference'`; every | **Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AgentCandidateExperimentCellPlacement`, `AgentImprovementActivationResultStore`, `AgentImprovementActivationTargetPlan`, `AgentImprovementProfileReplacement`, `AgentImprovementProfileStateDigestInput`, `AgentImprovementProfileStateResolverInput`, `AgentImprovementProposal`, `AgentImprovementTargetProfileDiffOptions`, `AgentProfileImprovementActivationTargetPlan`, `CreateAgentImprovementActivationOptions`, `CreateAgentImprovementActivationResultOptions`, `CreateAgentImprovementProposalOptions`, `CreateExactProcessCandidateExperimentExecutorOptions`, `ExactProcessCandidateExperimentExecution`, `ExactProcessCandidateExperimentExecutor`, `ExecuteAgentCandidateExperimentCellOptions`, `ExecuteAgentImprovementActivationInput`, `ExecuteAgentImprovementActivationOptions`, `OptimizationActivationReceipt`, `OptimizationReceiptCost`, `ProposeAgentImprovementOptions`, `ProposeAgentImprovementResult`, `ProposeAgentProfileImprovementResult`, `ProposeAuthoredAgentProfileImprovementResult`, `PullCertifiedOptions`, `ReviewAgentImprovementInput`, `RunAgentCandidateExperimentOptions`, `RunAgentCandidateExperimentResult`, `SealedCandidateActivationTransitionInput`, `VerifyCandidateExecutionEvidenceOptions`, `AgentImprovementActivationIntent`, `AgentImprovementActivationOutcome`, `AgentImprovementActivationTargetIdentity`, `AgentImprovementActivationTransitionInput`, `AgentImprovementAnalysisOptions`, `AgentImprovementProfileActivationInput`, `AgentImprovementProfileActivationPreparation`, `AgentImprovementProfileActivationTarget`, `AgentImprovementProfileSurface`, `AgentImprovementProfileTargetState`, `AgentImprovementProfileTargetTransition`, `AgentImprovementReviewDecision`, `AgentProfileImprovementActivationOperation`, `AgentProfileMeasuredSurface`. ### Execution kernel — recursive atom, supervision, executors, round-synchronous loop -Import from `@tangle-network/agent-runtime/kernel` — 837 exports. +Import from `@tangle-network/agent-runtime/kernel` — 836 exports. | Symbol | Kind | Summary | |---|---|---| @@ -1185,7 +1185,6 @@ Import from `@tangle-network/agent-runtime/kernel` — 837 exports. | `ReservationRejection` | type | Why a reservation was refused. `budget-exhausted` means the pool ran out of a channel it | | `ResolveDriveHarness` | type | Resolve an external harness for one exact Runtime-owned manager identity. | | `ResolveSupervisorTools` | type | Product policy for the tools one exact supervisor node may call. Resolved once per node. | -| `Restart` | type | OTP child-spec restart class. | | `RetainedInteractiveAdmission` | type | Durable records for one exact native coding-agent process. | | `RetainedInteractiveAdmissionHook` | type | Persist each exact interactive record before the runtime proceeds. | | `RetainedInteractiveEnvironmentInput` | type | Environment and exact AgentProfile used to start one native coding-agent process. | @@ -1335,7 +1334,7 @@ Import from `@tangle-network/agent-runtime/profiles` — 42 exports. | `UiFinding` | interface | A single UI audit finding — the unit of work a contributor can act on. | | `UiFindingScreenshot` | interface | Pointer to a screenshot referenced by a finding (workspace-relative path). | | `KnowledgeUpdate` | type | A proposed write to the knowledge base. The profile does NOT apply | -| `ResearchSource` | type | Source families a researcher profile may prefer for a task. | +| `ResearchSource` | type | Source families a researcher profile may prefer for a task. One owner: the delegation | | `UiFindingSeverity` | type | Severity scale. | | `UiLens` | type | Canonical audit lenses. Each lens scopes a finding to a single class of | @@ -1618,9 +1617,10 @@ Import from `@tangle-network/agent-runtime/mcp` — 213 exports. | `DriveTurnTick` | type | Structural mirror of the sandbox SDK's `TurnDriveResult` (>= 0.6). | | `GitRunner` | type | Pluggable git runner (sync) — replaceable in tests. | | `LocalHarness` | type | Local coding harness available inside the sandbox — a narrowing of the shared `HarnessType` | +| `ResearchSource` | type | Source families a researcher profile may prefer for a task. One owner: the delegation | | `UiAuditorDelegate` | type | UI-auditor delegate — fully consumer-injected. agent-runtime ships no | -**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AnalystRegistry`, `CappedDelegationTrace`, `CoderOutput`, `CoderReview`, `CoordinationToolsOptions`, `CreateKbGateOptions`, `CreateMemoryToolServerOptions`, `CreateWorktreeOptions`, `DelegateCodeArgs`, `DelegateCodeResult`, `DelegateFeedbackArgs`, `DelegateFeedbackHandlerOptions`, `DelegateFeedbackResult`, `DelegateHandlerOptions`, `DelegateResearchArgs`, `DelegateResearchConfig`, `DelegateResearchResult`, `DelegateRunCtx`, `DelegateUiAuditArgs`, `DelegateUiAuditConfig`, `DelegateUiAuditHandlerOptions`, `DelegateUiAuditResult`, `DelegationError`, `DelegationExecutor`, `DelegationFeedbackSnapshot`, `DelegationHistoryArgs`, `DelegationHistoryEntry`, `DelegationHistoryHandlerOptions`, `DelegationHistoryResult`, `DelegationProgress`, `DelegationResumeContext`, `DelegationRunContext`, `DelegationStatusArgs`, `DelegationStatusHandlerOptions`, `DelegationStatusResult`, `DelegationStore`, `DelegationTaskQueueOptions`, `DelegationTraceCaps`, `DetachedSessionDelegateOptions`, `DetachedTurn`, `DetachedTurnResumeDriverOptions`, `DetectExecutorArgs`, `DiffOptions`, `DiffResult`, `FactCandidate`, `FactJudge`, `FactJudgeVerdict`, `FeedbackEvent`, `FeedbackRating`, `FeedbackRefersTo`, `FeedbackStore`, `FileDelegationStoreOptions`, `FleetWorkspaceExecutorOptions`, `InProcessExecutorDescribePlacement`, `InProcessExecutorOptions`, `KbGateResult`, `LocalHarnessResult`, `McpServer`, `McpServerOptions`, `Question`, `QuestionOption`, `QuestionRecord`, `RemoveWorktreeOptions`, `RunDetachedTurnOptions`, `RunLocalHarnessOptions`, `SettleDetachedCoderTurnOptions`, `SiblingSandboxExecutorOptions`, `StdioToolServer`, `StdioToolServerOptions`, `SubmitInput`, `SubmitOutput`, `TraceContext`, `WorktreeHandle`, `CoderDelegate`, `DelegationProfile`, `DelegationStatus`, `DetachedWinnerSelection`, `MakeWorkerAgent`, `QuestionDecision`, `QuestionEscalationTarget`, `QuestionLevel`, `QuestionPolicy`, `QuestionUrgency`, `ResearchSource`, `UiAuditLensFilter`. +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AnalystRegistry`, `CappedDelegationTrace`, `CoderOutput`, `CoderReview`, `CoordinationToolsOptions`, `CreateKbGateOptions`, `CreateMemoryToolServerOptions`, `CreateWorktreeOptions`, `DelegateCodeArgs`, `DelegateCodeResult`, `DelegateFeedbackArgs`, `DelegateFeedbackHandlerOptions`, `DelegateFeedbackResult`, `DelegateHandlerOptions`, `DelegateResearchArgs`, `DelegateResearchConfig`, `DelegateResearchResult`, `DelegateRunCtx`, `DelegateUiAuditArgs`, `DelegateUiAuditConfig`, `DelegateUiAuditHandlerOptions`, `DelegateUiAuditResult`, `DelegationError`, `DelegationExecutor`, `DelegationFeedbackSnapshot`, `DelegationHistoryArgs`, `DelegationHistoryEntry`, `DelegationHistoryHandlerOptions`, `DelegationHistoryResult`, `DelegationProgress`, `DelegationResumeContext`, `DelegationRunContext`, `DelegationStatusArgs`, `DelegationStatusHandlerOptions`, `DelegationStatusResult`, `DelegationStore`, `DelegationTaskQueueOptions`, `DelegationTraceCaps`, `DetachedSessionDelegateOptions`, `DetachedTurn`, `DetachedTurnResumeDriverOptions`, `DetectExecutorArgs`, `DiffOptions`, `DiffResult`, `FactCandidate`, `FactJudge`, `FactJudgeVerdict`, `FeedbackEvent`, `FeedbackRating`, `FeedbackRefersTo`, `FeedbackStore`, `FileDelegationStoreOptions`, `FleetWorkspaceExecutorOptions`, `InProcessExecutorDescribePlacement`, `InProcessExecutorOptions`, `KbGateResult`, `LocalHarnessResult`, `McpServer`, `McpServerOptions`, `Question`, `QuestionOption`, `QuestionRecord`, `RemoveWorktreeOptions`, `RunDetachedTurnOptions`, `RunLocalHarnessOptions`, `SettleDetachedCoderTurnOptions`, `SiblingSandboxExecutorOptions`, `StdioToolServer`, `StdioToolServerOptions`, `SubmitInput`, `SubmitOutput`, `TraceContext`, `WorktreeHandle`, `CoderDelegate`, `DelegationProfile`, `DelegationStatus`, `DetachedWinnerSelection`, `MakeWorkerAgent`, `QuestionDecision`, `QuestionEscalationTarget`, `QuestionLevel`, `QuestionPolicy`, `QuestionUrgency`, `UiAuditLensFilter`. ### Supervisor TUI — live terminal view over the on-disk run layout diff --git a/docs/api/profiles.md b/docs/api/profiles.md index 65c40b26..684e4664 100644 --- a/docs/api/profiles.md +++ b/docs/api/profiles.md @@ -952,7 +952,8 @@ Optional judge commentary (debug / triage aid). **`Experimental`** -Source families a researcher profile may prefer for a task. +Source families a researcher profile may prefer for a task. One owner: the delegation + vocabulary (`DelegateResearchArgs.sources`) re-exports this type rather than restating it. *** diff --git a/docs/api/runtime.md b/docs/api/runtime.md index ad744066..13972624 100644 --- a/docs/api/runtime.md +++ b/docs/api/runtime.md @@ -17257,10 +17257,6 @@ Opaque seams the registry threads through; a built-in narrows what it needs. Manager-scoped semantic assignment identity. Unlike `key`, this names every spawn, including unkeyed siblings, so product traces can join authorization, node, and backend execution. -##### restart? - -> `readonly` `optional` **restart?**: [`Restart`](#restart) - ##### shutdown? > `readonly` `optional` **shutdown?**: `number` \| `"brutalKill"` \| `"infinity"` @@ -19749,7 +19745,11 @@ idle-drop. Applies to the default fresh-box path too, not only when ##### kind -> **kind**: `"sibling"` \| `"fleet"` +> **kind**: `"sibling"` \| `"fleet"` \| `"in-process"` + +`in-process` is a local harness CLI in the caller's own process tree — no sandbox, no fleet. + It is a placement in its own right so a cost or latency breakdown split by placement does not + count local runs in the sandbox bucket. ##### sandboxId? @@ -19915,7 +19915,7 @@ they write lands on it directly. ##### placement -> **placement**: `"sibling"` \| `"fleet"` +> **placement**: `"sibling"` \| `"fleet"` \| `"in-process"` ##### sandboxId? @@ -22202,14 +22202,6 @@ construction args without pre-instantiating; it never bypasses exact-profile val *** -### Restart - -> **Restart** = `"temporary"` \| `"transient"` \| `"permanent"` - -OTP child-spec restart class. - -*** - ### NodeStatus > **NodeStatus** = `"pending"` \| `"acquiring"` \| `"running"` \| `"waiting"` \| `"done"` \| `"failed"` \| `"cancelled"` diff --git a/docs/canonical-api.md b/docs/canonical-api.md index ea49192a..65ee6323 100644 --- a/docs/canonical-api.md +++ b/docs/canonical-api.md @@ -4,11 +4,11 @@ Generated signatures and the complete export list live in docs/api/. Run pnpm docs:freshness after editing this file. --> -> **Version 0.156.0.** +> **Version 0.157.0.** > [`docs/api/primitive-catalog.md`](./api/primitive-catalog.md) lists every export and import path. > `agent-eval` must satisfy `>=0.163.2 <0.164.0`. > `sandbox` must satisfy `>=0.31.0 <0.32.0`. -> Portable profile and tool-part types come from `@tangle-network/agent-interface` `^1.4.0`. +> Portable profile and tool-part types come from `@tangle-network/agent-interface` `^1.6.0`. > > **`./kernel` is the execution kernel**: `package.json` maps it to `src/runtime/index.ts`. Everything below labelled `/kernel` lives there — the recursive atom (`Scope`/`Supervisor`), the executor registry, budget conservation, the finalizer seam, analyst wiring, and the round-synchronous loop. > diff --git a/package.json b/package.json index 43c2f85f..b831a61d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tangle-network/agent-runtime", - "version": "0.156.0", + "version": "0.157.0", "description": "Shared task-lifecycle skeleton for agents: a recursive loop kernel for chat turns, one-shot tasks, and multi-attempt loops, with trace capture and eval-gated self-improvement. Domain behavior lives in adapters; scoring and ship-gates in @tangle-network/agent-eval.", "homepage": "https://github.com/tangle-network/agent-runtime#readme", "repository": { @@ -174,7 +174,7 @@ "packageManager": "pnpm@11.17.0", "peerDependencies": { "@tangle-network/agent-eval": ">=0.163.2 <0.164.0", - "@tangle-network/agent-interface": "^1.4.0", + "@tangle-network/agent-interface": "^1.6.0", "@tangle-network/sandbox": ">=0.31.0 <0.32.0" }, "peerDependenciesMeta": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e5a9998b..ea297f4a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,8 +19,8 @@ catalogs: specifier: '>=0.163.2 <0.164.0' version: 0.163.2 '@tangle-network/agent-interface': - specifier: ^1.4.0 - version: 1.4.0 + specifier: ^1.6.0 + version: 1.6.0 '@tangle-network/agent-knowledge': specifier: ^10.7.0 version: 10.7.0 @@ -58,10 +58,10 @@ importers: version: 0.9.4(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)) '@tangle-network/agent-knowledge': specifier: 'catalog:' - version: 10.7.0(@tangle-network/agent-eval@0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)))(@tangle-network/agent-interface@1.4.0) + version: 10.7.0(@tangle-network/agent-eval@0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)))(@tangle-network/agent-interface@1.6.0) '@tangle-network/agent-profile-materialize': specifier: 'catalog:' - version: 0.17.1(@tangle-network/agent-interface@1.4.0) + version: 0.17.1(@tangle-network/agent-interface@1.6.0) '@tangle-network/agent-trace-contract': specifier: 'catalog:' version: 1.0.2 @@ -83,7 +83,7 @@ importers: version: 0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)) '@tangle-network/agent-interface': specifier: 'catalog:' - version: 1.4.0 + version: 1.6.0 '@tangle-network/sandbox': specifier: 'catalog:' version: 0.31.0(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3))(viem@2.54.6(typescript@6.0.3)(zod@4.4.3)) @@ -134,10 +134,10 @@ importers: version: 0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)) '@tangle-network/agent-interface': specifier: 'catalog:' - version: 1.4.0 + version: 1.6.0 '@tangle-network/agent-knowledge': specifier: 'catalog:' - version: 10.7.0(@tangle-network/agent-eval@0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)))(@tangle-network/agent-interface@1.4.0) + version: 10.7.0(@tangle-network/agent-eval@0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)))(@tangle-network/agent-interface@1.6.0) '@tangle-network/agent-runtime': specifier: workspace:^ version: link:.. @@ -1265,8 +1265,8 @@ packages: engines: {node: '>=20'} hasBin: true - '@tangle-network/agent-interface@1.4.0': - resolution: {integrity: sha512-oUN5Ok0DJuNXIwlpi/ZHLeOUQq/LSAAa1Boe4RTt7S4feAWGddya1fTgQogHbnRiHEswFHdw2wvpEb8qyVx49g==} + '@tangle-network/agent-interface@1.6.0': + resolution: {integrity: sha512-DzdRAOTuPacezJlvOo+Xu5fWdoE9sJg90CDDo+SOCUJmfxrg38bEgCQz8ujr4r0Z5ABG2DlazMFRG/1/XoQ0HQ==} '@tangle-network/agent-knowledge@10.7.0': resolution: {integrity: sha512-zBrDmwAZzvpGm3YzlVXnjrAPgG/bhGsLFl9FXJn2XjwmI4x5ziX9xrHVlHEnG+LCCjAkwu7dn1I+976H+v8/nA==} @@ -3361,7 +3361,7 @@ snapshots: '@tangle-network/agent-core@0.9.4(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3))': dependencies: - '@tangle-network/agent-interface': 1.4.0 + '@tangle-network/agent-interface': 1.6.0 zod: 4.4.3 optionalDependencies: '@modelcontextprotocol/sdk': 1.30.0(supports-color@10.2.2)(zod@4.4.3) @@ -3371,7 +3371,7 @@ snapshots: '@asteasolutions/zod-to-openapi': 9.1.0(zod@4.4.3) '@hono/node-server': 2.0.12(hono@4.12.32) '@tangle-network/agent-core': 0.9.4(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)) - '@tangle-network/agent-interface': 1.4.0 + '@tangle-network/agent-interface': 1.6.0 '@tangle-network/agent-trace-contract': 1.0.2 hono: 4.12.32 linear-sum-assignment: 1.0.9 @@ -3380,30 +3380,30 @@ snapshots: transitivePeerDependencies: - '@modelcontextprotocol/sdk' - '@tangle-network/agent-interface@1.4.0': + '@tangle-network/agent-interface@1.6.0': dependencies: '@noble/hashes': 1.8.0 spdx-expression-parse: 5.0.0 zod: 4.4.3 - '@tangle-network/agent-knowledge@10.7.0(@tangle-network/agent-eval@0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)))(@tangle-network/agent-interface@1.4.0)': + '@tangle-network/agent-knowledge@10.7.0(@tangle-network/agent-eval@0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)))(@tangle-network/agent-interface@1.6.0)': dependencies: '@tangle-network/agent-eval': 0.163.2(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)) - '@tangle-network/agent-interface': 1.4.0 + '@tangle-network/agent-interface': 1.6.0 '@types/proper-lockfile': 4.1.4 proper-lockfile: 4.1.2 zod: 4.4.3 - '@tangle-network/agent-profile-materialize@0.17.1(@tangle-network/agent-interface@1.4.0)': + '@tangle-network/agent-profile-materialize@0.17.1(@tangle-network/agent-interface@1.6.0)': dependencies: - '@tangle-network/agent-interface': 1.4.0 + '@tangle-network/agent-interface': 1.6.0 '@tangle-network/agent-trace-contract@1.0.2': {} '@tangle-network/sandbox@0.31.0(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3))(viem@2.54.6(typescript@6.0.3)(zod@4.4.3))': dependencies: '@tangle-network/agent-core': 0.9.4(@modelcontextprotocol/sdk@1.30.0(supports-color@10.2.2)(zod@4.4.3)) - '@tangle-network/agent-interface': 1.4.0 + '@tangle-network/agent-interface': 1.6.0 zod: 4.4.3 optionalDependencies: '@modelcontextprotocol/sdk': 1.30.0(supports-color@10.2.2)(zod@4.4.3) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e714f487..8c054d20 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -21,7 +21,7 @@ catalog: '@tangle-network/agent-core': '>=0.9.4 <0.10.0' '@types/node': 26.1.1 '@tangle-network/agent-eval': '>=0.163.2 <0.164.0' - '@tangle-network/agent-interface': ^1.4.0 + '@tangle-network/agent-interface': ^1.6.0 '@tangle-network/agent-knowledge': ^10.7.0 '@tangle-network/agent-profile-materialize': '>=0.17.1 <0.18.0' '@tangle-network/agent-trace-contract': ^1.0.2 diff --git a/src/durable/index.ts b/src/durable/index.ts index cb2a10c5..6788b1f6 100644 --- a/src/durable/index.ts +++ b/src/durable/index.ts @@ -49,13 +49,12 @@ export { type PursuitNodeCost, type PursuitNodePlacement, type PursuitNodeProjection, - type PursuitNodeStatus, type PursuitNodeTiming, type PursuitNodeUsage, type PursuitProjection, type PursuitRunProjection, - type PursuitRunStatus, type PursuitRunTotals, + type PursuitStatus, projectPursuit, } from './observer-projection' export { diff --git a/src/durable/observer-projection.ts b/src/durable/observer-projection.ts index b7ebe2e2..e869b04a 100644 --- a/src/durable/observer-projection.ts +++ b/src/durable/observer-projection.ts @@ -11,7 +11,12 @@ import { addSpend, cloneSpend, zeroSpend } from '../runtime/util' import type { RuntimeDecisionKind, RuntimeHookTarget } from '../runtime-hooks' import { type ObserverRecord, verifyObserverRecords } from './observer-journal' -export type PursuitRunStatus = 'running' | 'done' | 'failed' +/** + * One settled projection status, shared by runs and nodes. `down` is the journal's own word for a + * failure (a settlement is journaled as `kind: 'down'`, cancellation included), so a consumer can + * join run rows to node rows on `status` and read one failure population instead of two. + */ +export type PursuitStatus = 'running' | 'done' | 'down' /** * Where a node's dollar figure came from. `reported` = a provider billed all of it; `estimated` = @@ -81,7 +86,7 @@ export interface PursuitRunTotals { export interface PursuitRunProjection { readonly runId: string - readonly status: PursuitRunStatus + readonly status: PursuitStatus readonly settledAt?: number readonly error?: string readonly firstSequence: number @@ -97,8 +102,6 @@ export interface PursuitRunProjection { readonly spendGaps?: ReadonlyArray } -export type PursuitNodeStatus = 'running' | 'done' | 'down' - export interface PursuitNodeProjection { readonly id: string readonly parentId?: string @@ -111,7 +114,7 @@ export interface PursuitNodeProjection { readonly assignmentId?: string readonly identity?: unknown readonly budget?: unknown - readonly status: PursuitNodeStatus + readonly status: PursuitStatus readonly settledAt?: number /** The child work this node reported at settlement. Absent until a terminal record lands. */ readonly spent?: Spend @@ -144,7 +147,6 @@ export interface PursuitNodeProjection { readonly valid?: boolean readonly reason?: string readonly infra?: boolean - readonly restartCount?: number readonly wait?: unknown readonly firstSequence: number readonly lastSequence: number @@ -170,7 +172,7 @@ export interface PursuitProjection { type MutableRun = { runId: string - status: PursuitRunStatus + status: PursuitStatus settledAt?: number error?: string firstSequence: number @@ -195,7 +197,7 @@ type MutableNode = { assignmentId?: string identity?: unknown budget?: unknown - status: PursuitNodeStatus + status: PursuitStatus startedAt?: number settledAt?: number spent?: Spend @@ -218,7 +220,6 @@ type MutableNode = { valid?: boolean reason?: string infra?: boolean - restartCount?: number wait?: unknown firstSequence: number lastSequence: number @@ -342,8 +343,10 @@ function projectRunActivity(run: MutableRun, record: ObserverRecord): void { run.settledAt = record.observedAt return } + // The `agent.run` hook payload spells a failure `failed`; the projection spells every + // settled failure `down`, the journal's word, so run and node rows join on one vocabulary. if (event.phase !== 'error' && status !== 'failed') return - run.status = 'failed' + run.status = 'down' run.settledAt = record.observedAt const error = stringField(payload, 'error') if (error) run.error = error @@ -437,8 +440,6 @@ function projectNodeActivity(nodes: Map, record: ObserverRe if (reason) node.reason = reason const infra = booleanField(payload, 'infra') if (infra !== undefined) node.infra = infra - const restartCount = numberField(payload, 'restartCount') - if (restartCount !== undefined) node.restartCount = restartCount if (payload && Object.hasOwn(payload, 'wait')) node.wait = payload.wait attachSettlementEvidence(node, payload) } diff --git a/src/durable/spawn-journal.ts b/src/durable/spawn-journal.ts index 215b7c70..5548e5a2 100644 --- a/src/durable/spawn-journal.ts +++ b/src/durable/spawn-journal.ts @@ -879,7 +879,6 @@ export async function replaySpawnTree( handle: handleFor(ev.id, 'cancelled'), reason: 'wait cancelled', infra: false, - restartCount: 0, trace: { status: 'unavailable', reason: 'not-an-executor' }, ...settlementTime(ev.at), seq: ev.seq, @@ -910,7 +909,6 @@ export async function replaySpawnTree( handle: handleFor(ev.id, 'cancelled'), reason: ev.reason, infra: false, - restartCount: 0, trace: { status: 'unavailable', reason: 'execution-did-not-start' }, ...settlementTime(ev.at), seq: ev.seq, @@ -927,7 +925,6 @@ export async function replaySpawnTree( // pre-field convention and the generic text keeps still-older reasonless journals usable. reason: ev.reason ?? ev.verdict?.notes ?? 'child down', infra: ev.infra === true, - restartCount: 0, ...(ev.providerModel === undefined ? {} : { providerModel: copyProviderModelEvidence(ev.providerModel) }), diff --git a/src/improvement/improve-types.ts b/src/improvement/improve-types.ts index 1432557c..cc1d5ec6 100644 --- a/src/improvement/improve-types.ts +++ b/src/improvement/improve-types.ts @@ -13,27 +13,25 @@ import type { SelfImproveOptions, SelfImproveResult, } from '@tangle-network/agent-eval/contract' -import type { AgentProfile, AgentProfileDiff, Sha256Digest } from '@tangle-network/agent-interface' +import type { + AgentImprovementSurface, + AgentProfile, + AgentProfileDiff, + Sha256Digest, +} from '@tangle-network/agent-interface' import type { AgenticGeneratorExecutorForWorktree, Verifier } from './agentic-generator' import type { CandidateGenerator } from './improvement-driver' import type { ReadonlyAgentProfile } from './profile-types' -/** The executable agent lever `improve` optimizes. Profile fields remain - * portable AgentProfile coordinates; implementation and orchestration files - * use the code surface so a winner can be sealed into an exact candidate. - * `rollout-policy` is the inference-time structuralRollout dials - * (`profile.extensions['structural-rollout']`). */ -export type ImproveSurface = - | 'prompt' - | 'skills' - | 'tools' - | 'mcp' - | 'hooks' - | 'subagents' - | 'agent-profile' - | 'memory' - | 'code' - | 'rollout-policy' +/** The executable agent lever `improve` optimizes — every surface a proposal can name + * (`AgentImprovementSurface`) except `knowledge`, which the corpus lane owns and `improve` + * does not produce. Deriving it means every surface `improve` produces can also be reported, which + * is the property that lets a result reach a review or a gate. + * + * Profile fields remain portable AgentProfile coordinates; implementation and orchestration files + * use the code surface so a winner can be sealed into an exact candidate. `rollout-policy` is the + * inference-time structuralRollout dials (`profile.extensions['structural-rollout']`). */ +export type ImproveSurface = Exclude export type ImproveProfileSurface = Exclude diff --git a/src/intelligence/capability.ts b/src/intelligence/capability.ts index 50084fae..1d914fd9 100644 --- a/src/intelligence/capability.ts +++ b/src/intelligence/capability.ts @@ -129,7 +129,9 @@ export type DeliveryBinding = | { kind: 'process-on-infra'; host: HostSpec; inner: DeliveryBinding } // INFRA class — deliver = a provisioned store + a connection (standing cost). | { kind: 'rag-index'; index: ContentRef; embedModel: string; topK?: number } - | { kind: 'memory-store'; provision: 'sqlite' | 'neo4j' | 'vector'; seed?: ContentRef } + // `sqlite` is the only backend a manifest may name: nothing provisions another, and the whole + // arm is refused at resolve time until it clears the E3 admission bar. + | { kind: 'memory-store'; provision: 'sqlite'; seed?: ContentRef } // EXTENSION POINTS — future arms, additive and agent-invisible. | { kind: 'wasm'; module: ContentRef; exports: string[] } | { kind: 'a2a'; endpoint: string; card: ContentRef; auth?: CapabilityAuth } diff --git a/src/intelligence/improvement-surfaces.ts b/src/intelligence/improvement-surfaces.ts index 8d959e84..158afe14 100644 --- a/src/intelligence/improvement-surfaces.ts +++ b/src/intelligence/improvement-surfaces.ts @@ -24,6 +24,10 @@ import { omitUndefinedObjectFields, parseExactAgentProfile, } from '../candidate-execution/profile' +import { + ROLLOUT_POLICY_EXTENSION, + structuralRolloutPolicyFromProfile, +} from '../improvement/rollout-policy' const changedSurfaceOrder: readonly AgentImprovementSurface[] = [ 'prompt', @@ -36,6 +40,7 @@ const changedSurfaceOrder: readonly AgentImprovementSurface[] = [ 'memory', 'code', 'knowledge', + 'rollout-policy', ] /** Agent improvement surfaces delivered as exact `AgentProfileDiff` replacements. */ @@ -737,6 +742,7 @@ function improvementSurfaceValues( }, code: bundle.code, knowledge: bundle.knowledge ?? null, + 'rollout-policy': structuralRolloutPolicyFromProfile(profile) ?? null, } } @@ -747,9 +753,13 @@ function opaqueProfileSlice(profile: AgentProfile): unknown { mcp: _mcp, hooks: _hooks, subagents: _subagents, + extensions, resources, ...opaqueProfile } = profile + // The rollout policy is its own surface, so it must not also ride in this slice: one edit to it + // would otherwise report two changed surfaces. + const { [ROLLOUT_POLICY_EXTENSION]: _rolloutPolicy, ...opaqueExtensions } = extensions ?? {} const { instructions: _instructions, skills: _skills, @@ -759,6 +769,7 @@ function opaqueProfileSlice(profile: AgentProfile): unknown { } = resources ?? {} return { ...opaqueProfile, + ...(Object.keys(opaqueExtensions).length > 0 ? { extensions: opaqueExtensions } : {}), ...(Object.keys(opaqueResources).length > 0 ? { resources: opaqueResources } : {}), } } diff --git a/src/intelligence/index.ts b/src/intelligence/index.ts index 0704481d..f9e34f57 100644 --- a/src/intelligence/index.ts +++ b/src/intelligence/index.ts @@ -239,11 +239,6 @@ export type { } from './with-intelligence' export { withIntelligence } from './with-intelligence' -/** Usage class for billing. Base-stream tokens bill `'inference'`; every - * intelligence spawn (analyst, corpus, loop) bills `'intelligence'`. The - * billing line falls on the spawn line. */ -export type UsageClass = 'inference' | 'intelligence' - /** * The per-class cost split carried by every trace and outcome. `off` ⇒ * `intelligenceUsd: 0` by construction — there is no intelligence spawn to diff --git a/src/mcp/delegates.ts b/src/mcp/delegates.ts index 9bc6f3aa..d476b682 100644 --- a/src/mcp/delegates.ts +++ b/src/mcp/delegates.ts @@ -96,10 +96,10 @@ export type UiAuditorDelegate = ( export interface CoderReview { /** Gate: only approved candidates are eligible to win. */ approved: boolean - /** Reviewer's recommendation — surfaced in traces. */ - recommendation: 'ship' | 'approve-with-nits' | 'changes-requested' | 'reject' /** Readiness 0..1, used by the `highest-readiness` winner-selection strategy. */ readiness: number + /** The reviewer's own words. Selection reads `approved` and `readiness`; anything a reviewer + * wants a caller to READ belongs here, because nothing else on this type is surfaced. */ notes?: string } diff --git a/src/mcp/in-process-executor.ts b/src/mcp/in-process-executor.ts index 254de80a..f9fbd0e7 100644 --- a/src/mcp/in-process-executor.ts +++ b/src/mcp/in-process-executor.ts @@ -212,7 +212,7 @@ export function createInProcessExecutor(options: InProcessExecutorOptions): Dele const sandboxId = (box as unknown as { id?: string }).id const meta = (box as VirtualSandbox).__inProcess return { - kind: 'sibling', + kind: 'in-process', sandboxId, worktreePath: meta?.worktree?.path, harness: meta?.harness, diff --git a/src/mcp/types.ts b/src/mcp/types.ts index 86d2e6fc..2826f856 100644 --- a/src/mcp/types.ts +++ b/src/mcp/types.ts @@ -14,6 +14,7 @@ */ import type { CoderTask } from '../profiles/coder' +import type { ResearchSource } from '../profiles/researcher' import type { UiFinding, UiLens } from '../profiles/ui-auditor/substrate' import type { DelegationTraceSpan } from './delegation-trace' import type { CoderOutput } from './detached-coder' @@ -72,8 +73,7 @@ export interface DelegateCodeResult { estimatedDurationMs?: number } -/** @experimental */ -export type ResearchSource = 'web' | 'corpus' | 'twitter' | 'github' | 'docs' +export type { ResearchSource } /** @experimental */ export interface DelegateResearchConfig { diff --git a/src/profiles/researcher.ts b/src/profiles/researcher.ts index a5a53232..cccbf5d0 100644 --- a/src/profiles/researcher.ts +++ b/src/profiles/researcher.ts @@ -34,7 +34,9 @@ import type { Validator, } from '../runtime/types' -/** Source families a researcher profile may prefer for a task. @experimental */ +/** Source families a researcher profile may prefer for a task. One owner: the delegation + * vocabulary (`DelegateResearchArgs.sources`) re-exports this type rather than restating it. + * @experimental */ export type ResearchSource = 'web' | 'corpus' | 'twitter' | 'github' | 'docs' /** Task contract for a source-grounded research agent. @experimental */ diff --git a/src/runtime/environment-provider.ts b/src/runtime/environment-provider.ts index 881ac68d..d1169f0f 100644 --- a/src/runtime/environment-provider.ts +++ b/src/runtime/environment-provider.ts @@ -1698,7 +1698,9 @@ function placementInfoFromLoopPlacement( ): PlacementInfo { if (!placement) return { kind: 'sandbox', sandboxId: String(box.id) } return { - kind: placement.kind === 'fleet' ? 'fleet' : 'sandbox', + // `in-process` runs in the caller's own process tree, which `PlacementInfo` names `local`. + kind: + placement.kind === 'fleet' ? 'fleet' : placement.kind === 'in-process' ? 'local' : 'sandbox', ...(placement.sandboxId ? { sandboxId: placement.sandboxId } : { sandboxId: String(box.id) }), ...(placement.fleetId ? { fleetId: placement.fleetId } : {}), ...(placement.machineId ? { machineId: placement.machineId } : {}), diff --git a/src/runtime/index.ts b/src/runtime/index.ts index fac25c3c..a0c10b2a 100644 --- a/src/runtime/index.ts +++ b/src/runtime/index.ts @@ -967,7 +967,6 @@ export type { ProfileMaterializationReceipt, ProviderModelAttemptEvidence, ProviderModelExecutionEvidence, - Restart, ResultBlobStore, ResumedKeyState, ResumedWork, diff --git a/src/runtime/supervise/bridge-executor.test.ts b/src/runtime/supervise/bridge-executor.test.ts index abd01511..a5720ced 100644 --- a/src/runtime/supervise/bridge-executor.test.ts +++ b/src/runtime/supervise/bridge-executor.test.ts @@ -47,6 +47,15 @@ function respondBridgeCapabilities(req: IncomingMessage, res: ServerResponse): b return true } +/** + * What cli-bridge 0.3.0 really puts in `reasoningEffort.applied`, transcribed from the argv + * builders that spawn each CLI and NOT from `nativeReasoningControl`. Reading the shared table + * here would make this test assert that the runtime agrees with itself, which is how a stale + * codex expectation survived long enough to refuse three of the seven rungs in production. + * + * A harness with no case plumbs no thinking flag, so its receipt carries `null` — gemini derives + * its budget from the model, and the rest read no reasoning effort at all. + */ function appliedReasoning(harness: string, requested: ReasoningEffort | null): string | null { if (requested === null) return null if (harness === 'pi') { @@ -57,18 +66,15 @@ function appliedReasoning(harness: string, requested: ReasoningEffort | null): s if (requested === 'none' || requested === 'minimal') return 'low' return requested === 'ultracode' ? 'max' : requested } - if (harness === 'codex') { - if (requested === 'none') return 'minimal' - return requested === 'xhigh' || requested === 'ultracode' ? 'high' : requested - } + if (harness === 'codex') return requested === 'ultracode' ? 'ultra' : requested if (harness === 'kimi-code') { if (requested === 'medium') return null return requested === 'none' || requested === 'minimal' || requested === 'low' ? '--no-thinking' : '--thinking' } - if (harness === 'gemini') return null - return requested + if (harness === 'opencode') return requested + return null } function bridgeProfileReceipt(body: Record): Record { diff --git a/src/runtime/supervise/runtime.ts b/src/runtime/supervise/runtime.ts index d3cac22a..ea3f6a65 100644 --- a/src/runtime/supervise/runtime.ts +++ b/src/runtime/supervise/runtime.ts @@ -37,6 +37,8 @@ import { AgentTurnInputSchema, agentProfileSchema, canonicalAgentProfileDigest, + harnessTypeSchema, + nativeReasoningControl, profileMaterializationAxes, REASONING_EFFORTS, type ReasoningEffort, @@ -3579,7 +3581,13 @@ function assertBridgeProfileMaterialization( ) } const expectedRequested = profile.model?.reasoningEffort ?? null - const expectedApplied = expectedBridgeAppliedReasoning(raw.harness, expectedRequested) + // `@tangle-network/agent-interface` owns the canonical-effort → native-control map, and the + // cli-bridge argv builders read the same one: the acknowledgement is checked against what the + // process must have received, and a renamed rung moves both sides together. + const receiptHarness = harnessTypeSchema.safeParse(raw.harness) + const expectedApplied = receiptHarness.success + ? nativeReasoningControl(receiptHarness.data, expectedRequested) + : null if (requested !== expectedRequested || applied !== expectedApplied) { throw new ValidationError( `bridgeExecutor: bridge materialized reasoning effort ${JSON.stringify({ requested, applied })}, expected ${JSON.stringify({ requested: expectedRequested, applied: expectedApplied })}`, @@ -3858,37 +3866,6 @@ function bridgeInferenceMoney(value: unknown, field: string): number { return value } -/** Expected native control for the bridge backends that can emit the v2 acknowledgement. These - * mappings mirror the actual cli-bridge argv functions, so the acknowledgement is checked against - * what the process must have received rather than merely echoing the canonical request. */ -function expectedBridgeAppliedReasoning( - harness: string, - requested: ReasoningEffort | null, -): string | null { - if (requested === null) return null - switch (harness) { - case 'pi': - if (requested === 'none') return 'off' - return requested === 'ultracode' ? 'xhigh' : requested - case 'claude-code': - if (requested === 'none' || requested === 'minimal') return 'low' - return requested === 'ultracode' ? 'max' : requested - case 'codex': - if (requested === 'none') return 'minimal' - return requested === 'xhigh' || requested === 'ultracode' ? 'high' : requested - case 'kimi-code': - if (requested === 'medium') return null - return requested === 'none' || requested === 'minimal' || requested === 'low' - ? '--no-thinking' - : '--thinking' - case 'gemini': - return null - default: - // OpenCode and bridge backends with direct reasoning variants preserve the canonical label. - return requested - } -} - /** * Decode the OpenAI-shaped `tool_calls` of one delta into the shared `ToolStepInput` currency, * through the SAME `decodeOpenAiPart` adapter the sandbox/parts trace source uses — the wire shape diff --git a/src/runtime/supervise/scope.ts b/src/runtime/supervise/scope.ts index c6ebcff0..1d3557bc 100644 --- a/src/runtime/supervise/scope.ts +++ b/src/runtime/supervise/scope.ts @@ -332,7 +332,6 @@ type PreSeqSettled = kind: 'down' reason: string infra: boolean - restartCount: number trace: WorkerTraceEvidence providerModel?: import('./types').ProviderModelExecutionEvidence /** A CRASHED driver child's partial OWN-inference subtree total — re-homed on the down path @@ -1214,7 +1213,6 @@ export function createScope(args: ScopeArgs): Scope { kind: 'down', reason: resolution.reason, infra: false, - restartCount: 0, trace: { status: 'unavailable', reason: 'not-an-executor' }, } } @@ -1234,7 +1232,6 @@ export function createScope(args: ScopeArgs): Scope { kind: 'down', reason: errMessage(err), infra: true, - restartCount: 0, trace: { status: 'unavailable', reason: 'not-an-executor' }, } }) @@ -1825,7 +1822,6 @@ async function finalizeSettlement( reason: settlement.reason, infra: settlement.infra, spent: child.spent, - restartCount: settlement.restartCount, ...settledNodeEvidence(child, settlement, settledAt), }, }, @@ -1836,7 +1832,6 @@ async function finalizeSettlement( handle, reason: settlement.reason, infra: settlement.infra, - restartCount: settlement.restartCount, ...(settlement.providerModel ? { providerModel: settlement.providerModel } : {}), trace: settlement.trace, settledAt, @@ -1977,7 +1972,6 @@ async function finalizeWait( handle, reason: settlement.reason, infra: settlement.infra, - restartCount: settlement.restartCount, trace: settlement.trace, settledAt, seq, @@ -2505,7 +2499,6 @@ function downRecord( kind: 'down', reason, infra, - restartCount: 0, trace, ...(providerModel ? { providerModel } : {}), ...(metered ? { metered } : {}), diff --git a/src/runtime/supervise/types.ts b/src/runtime/supervise/types.ts index 9690af75..0b7f73f8 100644 --- a/src/runtime/supervise/types.ts +++ b/src/runtime/supervise/types.ts @@ -235,7 +235,11 @@ export type WorkerInteractiveUnavailableReason = /** The executor is backed by a runner whose provider publishes no interactive-session contract * (the local CLI Bridge today), so no process can be attached to even though one is running. */ | 'provider-has-no-interactive-contract' - /** The runner supports interactive sessions but this execution was not started in one. */ + /** The runner supports interactive sessions but this execution was not started in one. Part of + * the `Executor` PORT vocabulary: `Scope.interactive` keeps whatever reason an executor's own + * `interactive()` returns, so any executor — including one implemented outside this package — + * answers with it. No first-party executor emits it yet: the sandbox arm must first ask its + * provider whether it supports control, which agent-runtime#773 tracks. */ | 'interactive-session-not-started' /** @@ -646,9 +650,6 @@ export interface Spend { // ── Node lifecycle ──────────────────────────────────────────────────────────── -/** OTP child-spec restart class. */ -export type Restart = 'temporary' | 'transient' | 'permanent' - /** `'acquiring'` is first-class (M1): a node spends real time + reaps an orphan box * during sandbox acquire BEFORE it is `running`, so abort must be defined over it. * `'waiting'` is first-class for the opposite reason: a wait-state node holds NO executor, NO @@ -672,7 +673,6 @@ export interface SpawnOpts { /** Manager-scoped semantic assignment identity. Unlike `key`, this names every spawn, including * unkeyed siblings, so product traces can join authorization, node, and backend execution. */ readonly assignmentId?: string - readonly restart?: Restart /** Teardown grace handed to the executor when this node is reaped. */ readonly shutdown?: number | 'brutalKill' | 'infinity' /** @@ -772,7 +772,6 @@ export type Settled = reason: string /** True = infrastructure failure (excluded from merge `n` / equal-k), not a bad result. */ infra: boolean - restartCount: number /** Partial structured tool evidence captured before this failure was journaled. */ trace: WorkerTraceEvidence /** Partial provider model evidence survives an aborted or failed execution. */ diff --git a/src/runtime/types.ts b/src/runtime/types.ts index 91c34210..17081272 100644 --- a/src/runtime/types.ts +++ b/src/runtime/types.ts @@ -431,7 +431,10 @@ export interface LoopLineageOptions { /** @stable */ export interface LoopSandboxPlacement { - kind: 'sibling' | 'fleet' + /** `in-process` is a local harness CLI in the caller's own process tree — no sandbox, no fleet. + * It is a placement in its own right so a cost or latency breakdown split by placement does not + * count local runs in the sandbox bucket. */ + kind: 'sibling' | 'fleet' | 'in-process' sandboxId?: string fleetId?: string machineId?: string @@ -530,7 +533,7 @@ export interface LoopIterationStartedPayload { export interface LoopIterationDispatchPayload { iterationIndex: number agentRunName: string - placement: 'sibling' | 'fleet' + placement: 'sibling' | 'fleet' | 'in-process' /** Set on every placement. Lets analyst loops correlate per-iteration logs. */ sandboxId?: string /** Set only when `placement === 'fleet'`. */ diff --git a/src/testing/fixtures/agent-improvement-proposal.json b/src/testing/fixtures/agent-improvement-proposal.json index e4027f30..f8466f58 100644 --- a/src/testing/fixtures/agent-improvement-proposal.json +++ b/src/testing/fixtures/agent-improvement-proposal.json @@ -1,6 +1,6 @@ { "changedSurfaces": ["prompt"], - "digest": "sha256:f6e9f4b77f5c03a3baf17ca5d1720d239628b4f4955c947ccd46ea8dfbb83a7b", + "digest": "sha256:5850c431171467cf14149848a863fc3473c3f799c2e461bae32993185af72db1", "evaluation": { "decision": { "contributingChecks": [ @@ -4882,7 +4882,7 @@ ], "metadata": { "fixture": "agent-improvement-proposal", - "runtimeVersion": "0.156.0" + "runtimeVersion": "0.157.0" }, "objectives": [ { @@ -4993,8 +4993,8 @@ "baselineContentHash": "sha256:5c21ee53e513fc604cb09754e21c392b24a424da0ef37dbf8f1ee4a8a0b08f09", "candidateContentHash": "sha256:60fcbb1c728194bd51d7d19cb732d1c3f1881dce7e0a6266b41c8b98cfd65693", "kind": "agent-eval-loop", - "recordDigest": "sha256:39eaffbd7882500276c0257592b70d9302f52d59fe8957c151c8b8634cb5a3b7", - "runId": "agent-runtime-0.156.0-proposal-fixture", + "recordDigest": "sha256:005cb52698917bc6dbbc07479e233b861e12a300fa36d66997b1789752b9b878", + "runId": "agent-runtime-0.157.0-proposal-fixture", "schema": "agent-candidate-experiment" } }, @@ -5021,5 +5021,5 @@ ], "kind": "agent-improvement-proposal", "proposedAt": "2026-07-10T01:00:00.000Z", - "runId": "agent-runtime-0.156.0-proposal-fixture" + "runId": "agent-runtime-0.157.0-proposal-fixture" } diff --git a/src/testing/fixtures/agent-profile-improvement-proposal.json b/src/testing/fixtures/agent-profile-improvement-proposal.json index 4fb7fcdd..f839160e 100644 --- a/src/testing/fixtures/agent-profile-improvement-proposal.json +++ b/src/testing/fixtures/agent-profile-improvement-proposal.json @@ -1,6 +1,6 @@ { "changedSurfaces": ["prompt", "skills"], - "digest": "sha256:96f20ae462f52bfc53ebd4de16c8b62e2cb7a175afa71771ec828d0e235172c0", + "digest": "sha256:148df84f38cd5aaba9b0812f9bbf235199cc6925432a68407984c35c21e7d09f", "evaluation": { "decision": { "contributingChecks": [ @@ -1715,7 +1715,7 @@ ], "metadata": { "fixture": "agent-profile-improvement-proposal", - "runtimeVersion": "0.156.0" + "runtimeVersion": "0.157.0" }, "objectives": [ { @@ -1826,7 +1826,7 @@ "baselineContentHash": "sha256:21c495a37c418c10bde64fbaa188beddeed31f1f051ea60a6a6582a9ee0db704", "candidateContentHash": "sha256:103f77bc8481601eef1ad5fe6ba84a40dffabc3a44f421f8c8559121edab84e9", "kind": "agent-eval-loop", - "recordDigest": "sha256:a3a017b662373c1789f1499ab1c5e4e59493de6811871759c9d3b07fc8459dda", + "recordDigest": "sha256:92c1ebdf25712275e6f80314e52325966ac89f31bf691e522fe11bdae5e7825c", "runId": "profile-improvement-1", "schema": "agent-profile-improvement-experiment" } diff --git a/tests/kernel/supervise-full-profile-bridge.test.ts b/tests/kernel/supervise-full-profile-bridge.test.ts index 6146aace..5dd87568 100644 --- a/tests/kernel/supervise-full-profile-bridge.test.ts +++ b/tests/kernel/supervise-full-profile-bridge.test.ts @@ -158,6 +158,39 @@ function numberSseDataFrames(body: string): string { return body.replace(/^data: (?!\[DONE\])/gmu, () => `id: ${++seq}\ndata: `) } +/** + * What cli-bridge 0.3.0 really puts in `reasoningEffort.applied`, transcribed from the argv + * builders that spawn each CLI — claude.ts, codex.ts, pi.ts, kimi.ts and opencode.ts — and NOT + * from `nativeReasoningControl`. Reading the shared table here would make this test assert that + * the runtime agrees with itself: the previous version of this fake echoed the runtime's own + * mapping, which is how a stale codex expectation survived long enough to refuse three of the + * seven rungs in production. + * + * A harness with no case plumbs no thinking flag, so its receipt carries `null`. + */ +function fakeBridgeAppliedReasoning(harness: string, requested: string | null): string | null { + if (requested === null) return null + switch (harness) { + case 'claude-code': + if (requested === 'none' || requested === 'minimal') return 'low' + return requested === 'ultracode' ? 'max' : requested + case 'codex': + return requested === 'ultracode' ? 'ultra' : requested + case 'pi': + if (requested === 'none') return 'off' + return requested === 'ultracode' ? 'xhigh' : requested + case 'kimi-code': + if (requested === 'medium') return null + return requested === 'none' || requested === 'minimal' || requested === 'low' + ? '--no-thinking' + : '--thinking' + case 'opencode': + return requested + default: + return null + } +} + function respondWithBridgeStream( res: ServerResponse, request: BridgeRequest, @@ -186,12 +219,7 @@ function respondWithBridgeStream( .join('\n') const parts = request.model.split('/') const requested = request.agent_profile.model?.reasoningEffort ?? null - const applied = - requested === 'none' - ? 'minimal' - : requested === 'xhigh' || requested === 'ultracode' - ? 'high' - : requested + const applied = fakeBridgeAppliedReasoning(parts[0] ?? '', requested) const receipt = `data: ${JSON.stringify({ profile_materialization: { schema: 'cli-bridge.profile-materialization.v2', diff --git a/tests/kernel/supervise.test.ts b/tests/kernel/supervise.test.ts index 4a7a3991..8725b1ff 100644 --- a/tests/kernel/supervise.test.ts +++ b/tests/kernel/supervise.test.ts @@ -1511,7 +1511,6 @@ describe('settledToIteration adapter', () => { handle: { id: 'run:s0', label: 'x', status: 'failed', abort() {} }, reason: 'boom', infra: false, - restartCount: 0, seq: 0, } expect(() => settledToIteration(down)).toThrow(/cannot adapt a 'down'/) @@ -1750,7 +1749,6 @@ describe('WidenGate default', () => { handle: { id: 'run:s1', label: 'b', status: 'failed', abort() {} }, reason: 'x', infra: false, - restartCount: 0, seq: 1, } // Even a near-perfect verdict does not widen under the flat default. diff --git a/tests/mcp/coder-delegate-selection.test.ts b/tests/mcp/coder-delegate-selection.test.ts index 82c4cf75..51fd9864 100644 --- a/tests/mcp/coder-delegate-selection.test.ts +++ b/tests/mcp/coder-delegate-selection.test.ts @@ -71,7 +71,6 @@ const codexWorker = workerProfile('codex') // Reviewer that approves both but rates the BIG candidate more ready. const readinessReviewer: CoderReviewer = (output) => ({ approved: true, - recommendation: 'ship', readiness: output.branch === 'big' ? 0.9 : 0.4, }) @@ -102,7 +101,6 @@ describe('detachedSessionDelegate — reviewer gate + winner selection', () => { it('rejects when the reviewer approves nothing (fails loud, no winner)', async () => { const rejectAll: CoderReviewer = (): CoderReview => ({ approved: false, - recommendation: 'changes-requested', readiness: 0, }) const delegate = detachedSessionDelegate({ diff --git a/tests/mcp/detached-turn.test.ts b/tests/mcp/detached-turn.test.ts index acedd95c..625f09e5 100644 --- a/tests/mcp/detached-turn.test.ts +++ b/tests/mcp/detached-turn.test.ts @@ -383,7 +383,7 @@ describe('settleDetachedCoderTurn', () => { task: coderTaskFromArgs(codeArgs), sessionId: 's', signal: new AbortController().signal, - reviewer: () => ({ approved: false, recommendation: 'reject', readiness: 0 }), + reviewer: () => ({ approved: false, readiness: 0 }), }, ), ).rejects.toThrow(/validation \+ review/) From 786c77e7e6cd7ca310475d232a0385b10cb68200 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Fri, 21 Aug 2026 10:29:53 -0700 Subject: [PATCH 2/5] chore(release): 0.157.0 and bench 0.8.23 --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ bench/CHANGELOG.md | 8 ++++++++ bench/package.json | 2 +- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c242a94..3512f4a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Changelog +## 0.157.0 + +### The bridge reasoning check refused runs it should have admitted + +`bridgeExecutor` compared the effort a cli-bridge materialization receipt reports as `applied` against a private copy of the bridge's own mapping, and the copy was stale. It expected codex to apply `minimal` for `none` and `high` for both `xhigh` and `ultracode`; cli-bridge 0.3.0 applies `none`, `xhigh` and `ultra`. A mismatch throws `ValidationError`, so **three of the seven rungs refused a legitimate codex run**. The same switch's default arm asserted the canonical rung for eleven further harnesses, none of which plumbs a thinking flag, so their receipts carried `applied: null` and those runs were refused too. + +The map now has one owner: `nativeReasoningControl` in `@tangle-network/agent-interface` 1.6.0, which the cli-bridge argv builders read as well. Interface moves to `^1.6.0` — a consumer that pins it itself must move it with this package. + +### An in-process worker is no longer recorded as a sandbox sibling + +`LoopSandboxPlacement.kind` and `LoopIterationDispatchPayload.placement` now carry `'in-process'`, and `PlacementInfo` maps it to its existing `'local'` kind. A consumer that switches exhaustively over either union must add the arm. In exchange, a cost or latency breakdown split by placement stops counting every local worktree-CLI iteration in the sandbox bucket. + +### One word for a failed projection row + +`PursuitRunStatus` and `PursuitNodeStatus` are replaced by one `PursuitStatus = 'running' | 'done' | 'down'`. They disagreed on the word for a failure in the same file, so a consumer joining run rows to node rows on `status` reported two failure populations where there is one. Read `PursuitStatus` and expect `down` on both. + +### `improve()` can no longer produce a surface a proposal cannot name + +`ImproveSurface` is now `Exclude`, and Interface 1.6.0 adds `rollout-policy` to the proposal vocabulary. A rollout-policy improvement can now reach a review or a gate. A consumer switching exhaustively over `AgentImprovementSurface` must add that arm. + +### Removed + +`Restart` and `SpawnOpts.restart` are gone. The supervisor never read the option, and the retry story already has an owner: a keyed spawn is idempotent per key, and a key whose prior attempt settled `down` spawns fresh and says so. A caller passing `restart` should use `key`. + +`restartCount` is gone from the `down` settlement and from `PursuitNodeProjection`. Nothing could increment it, and replay overwrote whatever a journal carried with `0`. + +`CoderReview.recommendation` is gone. Selection reads `approved` and `readiness`; a reviewer that wants a caller to read something puts it in `notes`. + +`UsageClass` is gone. `UsageSplit` carries the same idea as two named number fields. + +`DeliveryBinding`'s `memory-store` arm narrows `provision` to `'sqlite'`. Nothing provisioned the other two, and the whole arm is still refused at resolve time until it clears the E3 admission bar. + ## 0.156.0 ### Two MCP tool vocabularies now match what the tools accept diff --git a/bench/CHANGELOG.md b/bench/CHANGELOG.md index 1c1710a8..532a3f6e 100644 --- a/bench/CHANGELOG.md +++ b/bench/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.8.23 + +### Interface 1.6.0 cohort + +The Interface catalog range becomes `^1.6.0`, matching the Runtime cohort. Bench resolves Interface through the catalog, so its published manifest states the new range. Nothing in bench changes behavior. + +A consumer that pins Interface itself must move it with this package. + ## 0.8.22 ### Eval 0.163.2 and Knowledge 10.7.0 cohort diff --git a/bench/package.json b/bench/package.json index 519efe7b..a5559987 100644 --- a/bench/package.json +++ b/bench/package.json @@ -1,6 +1,6 @@ { "name": "@tangle-network/agent-bench", - "version": "0.8.22", + "version": "0.8.23", "type": "module", "description": "Benchmark adapters and execution for agent-runtime across coding, tool-use, RAG, memory, browser, and terminal tasks.", "repository": { From ffca7e852fd3d0dc13260f81f2b627bbda8f0ce0 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Fri, 21 Aug 2026 10:33:29 -0700 Subject: [PATCH 3/5] ci(cohort): pin the packed-cohort Interface archive to 1.6.0 --- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9da5db7..89974009 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: tangle-network/agent-sdk - ref: e1f7458e2424f12a6f1e3b11e4c3d7c7568d31d5 # @tangle-network/agent-interface@1.4.0 + ref: 57a073cf53bbdd44ddc97855a60aa78afb522f5c # @tangle-network/agent-interface@1.6.0 path: .cohort/agent-sdk persist-credentials: false diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index df911240..e4c4a478 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -135,7 +135,7 @@ jobs: uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: repository: tangle-network/agent-sdk - ref: e1f7458e2424f12a6f1e3b11e4c3d7c7568d31d5 # @tangle-network/agent-interface@1.4.0 + ref: 57a073cf53bbdd44ddc97855a60aa78afb522f5c # @tangle-network/agent-interface@1.6.0 path: .cohort/agent-sdk persist-credentials: false From 2032c38ccac0283553ea64fa0cb2e1e9cdf8496e Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Fri, 21 Aug 2026 10:36:42 -0700 Subject: [PATCH 4/5] test(observer-projection): expect the projection's own failure word --- src/durable/tests/observer-projection.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/durable/tests/observer-projection.test.ts b/src/durable/tests/observer-projection.test.ts index 738844a4..f77dbad6 100644 --- a/src/durable/tests/observer-projection.test.ts +++ b/src/durable/tests/observer-projection.test.ts @@ -274,9 +274,11 @@ describe('projectPursuit', () => { first.digest, ) + // The hook payload above spells the failure `failed`; the projection spells every settled + // failure `down`, so run rows and node rows join on one vocabulary. expect(projectPursuit([first, second]).runs[0]).toMatchObject({ runId: 'run:failed', - status: 'failed', + status: 'down', settledAt: 20, error: 'driver crashed', }) From 7e6e14df0c66d3e4e6c99aa51cf1f15b6bb6c372 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Fri, 21 Aug 2026 10:41:24 -0700 Subject: [PATCH 5/5] chore(api-surface): record the vocabulary export changes --- api-surface.json | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/api-surface.json b/api-surface.json index 28e17b2b..59bb1aa2 100644 --- a/api-surface.json +++ b/api-surface.json @@ -179,7 +179,7 @@ "ImproveRuntimeCodeGeneratorOptions": "type c26225cf7ca3", "ImproveScenarioPartitions": "type 37a3508406b1", "ImproveSkillsOptions": "type c1f5a69faefc", - "ImproveSurface": "type 3f2b092bf994", + "ImproveSurface": "type b711b683b151", "ImprovementCandidate": "type 0c22a91c6396", "ImprovementCodeCandidate": "type 588fa6d3b2f5", "ImprovementMaterializedProfilePopulationCandidate": "type 4eee039de8cf", @@ -305,7 +305,7 @@ "SanitizedKnowledgeRequirement": "type e4173a7b55fc", "Scope": "type f0ce3d119b61", "ServerSentEventOptions": "type c80818c13fcd", - "Settled": "type eb6156d23c49", + "Settled": "type 81db5667280b", "Spend": "type 477830045ea7", "SpendChannel": "type 978ffae337cd", "SpendGap": "type d24924855c35", @@ -696,14 +696,13 @@ "PursuitCostProvenance": "type fc5f37082627", "PursuitNodeCost": "type 2ae084b090ba", "PursuitNodePlacement": "type 744e7b45dc01", - "PursuitNodeProjection": "type 5de867d96865", - "PursuitNodeStatus": "type 8a9aa4ae39bb", + "PursuitNodeProjection": "type b65f68454746", "PursuitNodeTiming": "type 8cb37b8dca25", "PursuitNodeUsage": "type 951e957775ab", "PursuitProjection": "type 8d4e8a08d707", - "PursuitRunProjection": "type f8a85518fe71", - "PursuitRunStatus": "type 348aeaec7737", + "PursuitRunProjection": "type 0e7976e29987", "PursuitRunTotals": "type 87a99709fb0a", + "PursuitStatus": "type 8a9aa4ae39bb", "RunChatTurnInput": "type 3aafc346a44b", "SupervisePursuitError": "value aed1ebc9dee4", "SupervisePursuitOptions": "type 924edac7d1c5", @@ -822,7 +821,7 @@ "CreateExactProcessCandidateExperimentExecutorOptions": "type 6d390c45f62a", "CreateProtectedExactProcessCandidateExperimentExecutorOptions": "type e3f99118627f", "CredentialRef": "type bbeb8385d87f", - "DeliveryBinding": "type 18071122fdce", + "DeliveryBinding": "type fe13ba1a9eeb", "DeliveryBindingKind": "type 6cac2248f99b", "DiffProvenance": "type 59fdd1fa068b", "DoctorReport": "value 4c7af8631629", @@ -876,7 +875,6 @@ "TraceHandle": "value c8036504bae7", "TraceMeta": "value 8b8e2b85391f", "TraceOutcome": "value 7cdb1762b1ab", - "UsageClass": "value e0768cba5521", "UsageSplit": "value 225059e1632c", "VerifyCandidateExecutionEvidenceOptions": "type 2362ba397119", "agentImprovementProfileDiffs": "value 87c549d6cba8", @@ -1167,7 +1165,7 @@ "LoopDecisionPayload": "type ea64035c87e0", "LoopDispatchOptions": "type 93bf5cd3e058", "LoopEndedPayload": "type cec1d3954f09", - "LoopIterationDispatchPayload": "type f0dc44349879", + "LoopIterationDispatchPayload": "type efd3fa34642f", "LoopIterationEndedPayload": "type 4735d9d988bd", "LoopIterationStartedPayload": "type 36344ffaa2f1", "LoopLineageOptions": "type 18651bcfeab9", @@ -1175,7 +1173,7 @@ "LoopPlanDescription": "type 76b21ce0ef26", "LoopPlanPayload": "type 43448c05358d", "LoopResult": "type b7a972830ef0", - "LoopSandboxPlacement": "type 421626d96863", + "LoopSandboxPlacement": "type a99e4be1736f", "LoopShape": "type 8925f5e259c9", "LoopStartedPayload": "type a552ef7496eb", "LoopTeardownFailedPayload": "type fb0d53e63ba3", @@ -1280,7 +1278,6 @@ "ResolvedMcpServerLaunch": "type 38c483055998", "ResolvedSupervisorProfile": "type a1c298f11bc0", "ResourceRequest": "type 20dbb23e8101", - "Restart": "type a79f668a67a2", "ResultBlobStore": "type 69e6e03b75ab", "ResumedKeyState": "type 018905da27e4", "ResumedWork": "type 57b7c709155a", @@ -1350,7 +1347,7 @@ "SessionCapableBox": "type 9db08b40cab8", "SessionMessageLike": "type 726215634de7", "SessionTraceBox": "type b8d989093064", - "Settled": "type eb6156d23c49", + "Settled": "type 81db5667280b", "ShapeBudget": "type a1cb1a8d0995", "ShapeContext": "type a266c1b7e746", "ShapeRegistry": "type b567a5be55ec", @@ -1364,7 +1361,7 @@ "SpawnForestNode": "type f34c534f338c", "SpawnForestTree": "type bdd3bb0899f1", "SpawnJournal": "type c71410408358", - "SpawnOpts": "type 958db7343613", + "SpawnOpts": "type 903c3a01c5cb", "SpawnPreflight": "type 8e8b479089d3", "SpawnPreflightContext": "type 21972a19ec24", "SpawnPrior": "type f5b562b41ed4", @@ -1801,7 +1798,7 @@ "CappedDelegationTrace": "type fada988fa702", "CoderDelegate": "type 7fdce199433b", "CoderOutput": "type c88522397afb", - "CoderReview": "type e3287950fa5b", + "CoderReview": "type 99fca1bca0a7", "CoderReviewer": "type b9d158a04c16", "CodexExecutionDiagnosticError": "value fd413034adc8", "CodexExecutionEvidence": "type f21dfe544a92",