From dc1b6460cec6e17d83a130fee38c6869dacede98 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Fri, 10 Jul 2026 23:27:26 -0600 Subject: [PATCH 1/5] feat(intelligence): improve every agent surface --- README.md | 6 +- docs/api/agent.md | 90 +- docs/api/index.md | 1014 +++++++++++------- docs/api/intelligence.md | 446 ++++++-- docs/api/primitive-catalog.md | 90 +- docs/concepts.md | 4 +- docs/intelligence-sdk.md | 7 +- package.json | 13 +- pnpm-lock.yaml | 48 +- scripts/gen-primitive-catalog.mjs | 1 + skills/build-with-agent-runtime/SKILL.md | 2 +- src/agent/surfaces.ts | 106 +- src/candidate-execution/index.ts | 1 + src/candidate-execution/prepare.ts | 8 + src/candidate-execution/types.ts | 7 + src/improvement/improve.test.ts | 185 +++- src/improvement/improve.ts | 302 ++++-- src/improvement/improvement-driver.ts | 29 +- src/improvement/index.ts | 14 +- src/index.ts | 2 + src/intelligence/index.ts | 178 ++- src/intelligence/with-intelligence.test.ts | 80 +- src/intelligence/with-intelligence.ts | 144 ++- src/otel-export.ts | 109 +- tests/agent.test.ts | 58 + tests/candidate-execution-prepare.test.ts | 9 + tests/helpers/candidate-execution-fixture.ts | 13 +- tests/improve.test.ts | 3 +- tests/improvement-driver.test.ts | 32 + tests/otel-export.test.ts | 57 + tsup.config.ts | 1 + 31 files changed, 2300 insertions(+), 759 deletions(-) diff --git a/README.md b/README.md index 1223ec21..6c68c27b 100644 --- a/README.md +++ b/README.md @@ -68,13 +68,15 @@ const result = await supervise( ### Improve an agent -`improve` optimizes one part of an agent (its prompt, skills, or code) and **only ships a change if it beats the current agent on tasks it never practiced on**. Registering an agent for self-improvement cannot ship a worse candidate unless the caller supplies a bad measurement. +`improve` optimizes one part of an agent and **only ships a change if it beats the current agent on tasks it never practiced on**. +It accepts prompt, skill document, tool, MCP, hook, subagent, workflow, rollout-policy, whole-profile, and code surfaces through one call. +Prompt and skill-document optimization have built-in generators; structured surfaces take an explicit generator, and code runs from isolated incumbent and candidate checkouts. ```ts import { improve } from '@tangle-network/agent-runtime' const { profile, shipped, lift } = await improve(baseProfile, findings, { - surface: 'prompt', // what to optimize: prompt | skills | code + surface: 'prompt', // or skills/tools/mcp/hooks/subagents/workflow/agent-profile/code gate: 'holdout', // certified on a held-back exam, never the practice set scenarios, judge, agent, // how to measure a candidate }) diff --git a/docs/api/agent.md b/docs/api/agent.md index 5e682aec..e919cbfb 100644 --- a/docs/api/agent.md +++ b/docs/api/agent.md @@ -865,7 +865,7 @@ Required for `mode === 'open-pr'` — the GH owner/repo (`tangle-network/tax-age ##### allowCreateForKinds? -> `optional` **allowCreateForKinds?**: readonly (`"memory"` \| `"knowledge.wiki"` \| `"knowledge.claim"` \| `"knowledge.raw"` \| `"knowledge.stale"` \| `"system-prompt"` \| `"tool-doc"` \| `"new-tool"` \| `"rag"` \| `"scaffolding"` \| `"output-schema"` \| `"websearch.outdated"` \| `"prior-run-summary"` \| `"cluster"`)[] +> `optional` **allowCreateForKinds?**: readonly (`"code"` \| `"mcp"` \| `"memory"` \| `"workflow"` \| `"agent-profile"` \| `"rollout-policy"` \| `"skill"` \| `"hook"` \| `"subagent"` \| `"knowledge.wiki"` \| `"knowledge.claim"` \| `"knowledge.raw"` \| `"knowledge.stale"` \| `"system-prompt"` \| `"tool-doc"` \| `"new-tool"` \| `"rag"` \| `"scaffolding"` \| `"output-schema"` \| `"websearch.outdated"` \| `"prior-run-summary"` \| `"cluster"`)[] Defined in: [agent/improvement-adapter.ts:100](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/improvement-adapter.ts#L100) @@ -1544,11 +1544,75 @@ Defined in: [agent/surfaces.ts:55](https://github.com/tangle-network/agent-runti Optional: single file defining the output schema (Zod / JSON Schema). +##### skills? + +> `optional` **skills?**: `string` + +Defined in: [agent/surfaces.ts:57](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L57) + +Optional: directory containing Agent Skill packages. + +##### mcp? + +> `optional` **mcp?**: `string` + +Defined in: [agent/surfaces.ts:59](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L59) + +Optional: directory containing MCP server/tool configuration. + +##### hooks? + +> `optional` **hooks?**: `string` + +Defined in: [agent/surfaces.ts:61](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L61) + +Optional: directory containing hook definitions. + +##### subagents? + +> `optional` **subagents?**: `string` + +Defined in: [agent/surfaces.ts:63](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L63) + +Optional: directory containing subagent definitions. + +##### workflows? + +> `optional` **workflows?**: `string` + +Defined in: [agent/surfaces.ts:65](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L65) + +Optional: directory containing orchestration/workflow policies. + +##### rolloutPolicy? + +> `optional` **rolloutPolicy?**: `string` + +Defined in: [agent/surfaces.ts:67](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L67) + +Optional: single file containing rollout-policy settings. + +##### agentProfile? + +> `optional` **agentProfile?**: `string` + +Defined in: [agent/surfaces.ts:69](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L69) + +Optional: single canonical AgentProfile file. + +##### code? + +> `optional` **code?**: `string` + +Defined in: [agent/surfaces.ts:71](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L71) + +Optional: source root for code findings. + *** ### ResolvedSurface -Defined in: [agent/surfaces.ts:58](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L58) +Defined in: [agent/surfaces.ts:74](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L74) #### Properties @@ -1556,7 +1620,7 @@ Defined in: [agent/surfaces.ts:58](https://github.com/tangle-network/agent-runti > **absolutePath**: `string` -Defined in: [agent/surfaces.ts:60](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L60) +Defined in: [agent/surfaces.ts:76](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L76) Absolute filesystem path the operator can `cat` / `vim`. @@ -1564,7 +1628,7 @@ Absolute filesystem path the operator can `cat` / `vim`. > **repoRelativePath**: `string` -Defined in: [agent/surfaces.ts:62](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L62) +Defined in: [agent/surfaces.ts:78](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L78) Repo-relative path for PR descriptions, diffs, audit logs. @@ -1572,7 +1636,7 @@ Repo-relative path for PR descriptions, diffs, audit logs. > **exists**: `boolean` -Defined in: [agent/surfaces.ts:64](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L64) +Defined in: [agent/surfaces.ts:80](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L80) Whether the path currently exists on disk. @@ -1580,7 +1644,7 @@ Whether the path currently exists on disk. > **intent**: `"edit-existing"` \| `"create-new"` -Defined in: [agent/surfaces.ts:66](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L66) +Defined in: [agent/surfaces.ts:82](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L82) The substrate's intent: edit an existing file or create a new one. @@ -1588,7 +1652,7 @@ The substrate's intent: edit an existing file or create a new one. ### SurfaceValidationIssue -Defined in: [agent/surfaces.ts:191](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L191) +Defined in: [agent/surfaces.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L262) Validate that every declared surface exists on disk under `repoRoot`. @@ -1603,19 +1667,19 @@ the loop produces 20 minutes later). > **surface**: keyof [`AgentSurfaces`](#agentsurfaces) -Defined in: [agent/surfaces.ts:192](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L192) +Defined in: [agent/surfaces.ts:263](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L263) ##### path > **path**: `string` -Defined in: [agent/surfaces.ts:193](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L193) +Defined in: [agent/surfaces.ts:264](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L264) ##### reason > **reason**: `"missing"` \| `"not-directory"` \| `"not-file"` -Defined in: [agent/surfaces.ts:194](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L194) +Defined in: [agent/surfaces.ts:265](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L265) ## Type Aliases @@ -1993,7 +2057,7 @@ resolves only after the iterator drains. > **resolveSubjectPath**(`subject`, `surfaces`, `repoRoot`): [`ResolvedSurface`](#resolvedsurface) \| `null` -Defined in: [agent/surfaces.ts:86](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L86) +Defined in: [agent/surfaces.ts:102](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L102) Resolve a parsed `FindingSubject` to the file path the substrate should edit (or create) on disk. @@ -2035,7 +2099,7 @@ it's the whole point. > **validateSurfaces**(`surfaces`, `repoRoot`): readonly [`SurfaceValidationIssue`](#surfacevalidationissue)[] -Defined in: [agent/surfaces.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L198) +Defined in: [agent/surfaces.ts:269](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L269) Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits. @@ -2059,7 +2123,7 @@ readonly [`SurfaceValidationIssue`](#surfacevalidationissue)[] > **renderSurfaceIssues**(`issues`, `repoRoot`): `string` -Defined in: [agent/surfaces.ts:247](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L247) +Defined in: [agent/surfaces.ts:343](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L343) Format a list of surface validation issues into a human-readable error string. diff --git a/docs/api/index.md b/docs/api/index.md index d1b23f1e..5178a308 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -2512,29 +2512,55 @@ different preparation, even when both reservations report the same digest. *** -### AgentCandidateProtectedModelReservation +### AgentCandidateBenchmarkGraderIdentity Defined in: [candidate-execution/types.ts:154](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L154) #### Properties +##### name + +> **name**: `string` + +Defined in: [candidate-execution/types.ts:155](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L155) + +##### version + +> **version**: `string` + +Defined in: [candidate-execution/types.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L156) + +##### artifact + +> **artifact**: `AgentCandidateArtifactRef` + +Defined in: [candidate-execution/types.ts:157](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L157) + +*** + +### AgentCandidateProtectedModelReservation + +Defined in: [candidate-execution/types.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L160) + +#### Properties + ##### preparationId > **preparationId**: `string` -Defined in: [candidate-execution/types.ts:155](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L155) +Defined in: [candidate-execution/types.ts:161](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L161) ##### digest > **digest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L156) +Defined in: [candidate-execution/types.ts:162](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L162) ##### expiresAtMs > **expiresAtMs**: `number` -Defined in: [candidate-execution/types.ts:158](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L158) +Defined in: [candidate-execution/types.ts:164](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L164) Evaluator service must expire and revoke this reservation at this epoch millisecond. @@ -2542,7 +2568,7 @@ Evaluator service must expire and revoke this reservation at this epoch millisec > **enforcedLimits**: [`AgentCandidateModelLimits`](#agentcandidatemodellimits) -Defined in: [candidate-execution/types.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L160) +Defined in: [candidate-execution/types.ts:166](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L166) The gateway must stop calls before any one of these limits is exceeded. @@ -2550,7 +2576,7 @@ The gateway must stop calls before any one of these limits is exceeded. > **network**: `AgentCandidateModelAccessNetwork` -Defined in: [candidate-execution/types.ts:162](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L162) +Defined in: [candidate-execution/types.ts:168](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L168) Exact public endpoint exception; every other candidate destination stays blocked. @@ -2558,7 +2584,7 @@ Exact public endpoint exception; every other candidate destination stays blocked ### AgentCandidateProtectedModelActivation -Defined in: [candidate-execution/types.ts:165](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L165) +Defined in: [candidate-execution/types.ts:171](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L171) #### Properties @@ -2566,7 +2592,7 @@ Defined in: [candidate-execution/types.ts:165](https://github.com/tangle-network > **env**: `Readonly`\<`Record`\<`string`, `string`\>\> -Defined in: [candidate-execution/types.ts:167](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L167) +Defined in: [candidate-execution/types.ts:173](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L173) Injected only into the trusted executor after all pre-launch checks pass. @@ -2574,7 +2600,7 @@ Injected only into the trusted executor after all pre-launch checks pass. ### AgentCandidateProtectedModelCall -Defined in: [candidate-execution/types.ts:171](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L171) +Defined in: [candidate-execution/types.ts:177](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L177) One evaluator-gateway call in the final, revoked model-access ledger. @@ -2584,13 +2610,13 @@ One evaluator-gateway call in the final, revoked model-access ledger. > **callId**: `string` -Defined in: [candidate-execution/types.ts:172](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L172) +Defined in: [candidate-execution/types.ts:178](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L178) ##### generationId > **generationId**: `string` -Defined in: [candidate-execution/types.ts:174](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L174) +Defined in: [candidate-execution/types.ts:180](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L180) Router-generated public response identity. @@ -2598,7 +2624,7 @@ Router-generated public response identity. > **traceSpanId**: `string` -Defined in: [candidate-execution/types.ts:176](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L176) +Defined in: [candidate-execution/types.ts:182](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L182) Exact protected agent-eval LLM span produced from the router ledger. @@ -2606,55 +2632,55 @@ Exact protected agent-eval LLM span produced from the router ledger. > **status**: `"failed"` \| `"succeeded"` -Defined in: [candidate-execution/types.ts:177](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L177) +Defined in: [candidate-execution/types.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L183) ##### model > **model**: `string` -Defined in: [candidate-execution/types.ts:178](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L178) +Defined in: [candidate-execution/types.ts:184](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L184) ##### startedAtMs > **startedAtMs**: `number` -Defined in: [candidate-execution/types.ts:179](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L179) +Defined in: [candidate-execution/types.ts:185](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L185) ##### endedAtMs > **endedAtMs**: `number` -Defined in: [candidate-execution/types.ts:180](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L180) +Defined in: [candidate-execution/types.ts:186](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L186) ##### inputTokens > **inputTokens**: `number` -Defined in: [candidate-execution/types.ts:181](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L181) +Defined in: [candidate-execution/types.ts:187](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L187) ##### outputTokens > **outputTokens**: `number` -Defined in: [candidate-execution/types.ts:182](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L182) +Defined in: [candidate-execution/types.ts:188](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L188) ##### cachedInputTokens > **cachedInputTokens**: `number` -Defined in: [candidate-execution/types.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L183) +Defined in: [candidate-execution/types.ts:189](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L189) ##### reasoningTokens > **reasoningTokens**: `number` -Defined in: [candidate-execution/types.ts:184](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L184) +Defined in: [candidate-execution/types.ts:190](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L190) ##### costUsdNanos > **costUsdNanos**: `number` -Defined in: [candidate-execution/types.ts:186](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L186) +Defined in: [candidate-execution/types.ts:192](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L192) Integer billionths of one US dollar; avoids floating-point ledger drift. @@ -2662,7 +2688,7 @@ Integer billionths of one US dollar; avoids floating-point ledger drift. ### AgentCandidateProtectedModelSettlement -Defined in: [candidate-execution/types.ts:189](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L189) +Defined in: [candidate-execution/types.ts:195](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L195) #### Properties @@ -2670,31 +2696,31 @@ Defined in: [candidate-execution/types.ts:189](https://github.com/tangle-network > **preparationId**: `string` -Defined in: [candidate-execution/types.ts:190](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L190) +Defined in: [candidate-execution/types.ts:196](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L196) ##### grantDigest > **grantDigest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:191](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L191) +Defined in: [candidate-execution/types.ts:197](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L197) ##### closed > **closed**: `true` -Defined in: [candidate-execution/types.ts:192](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L192) +Defined in: [candidate-execution/types.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L198) ##### calls > **calls**: readonly [`AgentCandidateProtectedModelCall`](#agentcandidateprotectedmodelcall)[] -Defined in: [candidate-execution/types.ts:193](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L193) +Defined in: [candidate-execution/types.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L199) *** ### AgentCandidateMemoryResetResult -Defined in: [candidate-execution/types.ts:196](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L196) +Defined in: [candidate-execution/types.ts:202](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L202) #### Properties @@ -2702,43 +2728,43 @@ Defined in: [candidate-execution/types.ts:196](https://github.com/tangle-network > **preparationId**: `string` -Defined in: [candidate-execution/types.ts:197](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L197) +Defined in: [candidate-execution/types.ts:203](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L203) ##### accessDigest > **accessDigest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L198) +Defined in: [candidate-execution/types.ts:204](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L204) ##### expiresAtMs > **expiresAtMs**: `number` -Defined in: [candidate-execution/types.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L199) +Defined in: [candidate-execution/types.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L205) ##### evidence > **evidence**: `AgentCandidateCapturedArtifact` -Defined in: [candidate-execution/types.ts:200](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L200) +Defined in: [candidate-execution/types.ts:206](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L206) ##### emptyStateDigest > **emptyStateDigest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:201](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L201) +Defined in: [candidate-execution/types.ts:207](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L207) ##### beforeState > **beforeState**: `AgentCandidateWorkspaceSnapshotEvidence` -Defined in: [candidate-execution/types.ts:202](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L202) +Defined in: [candidate-execution/types.ts:208](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L208) *** ### AgentCandidateMemoryPort -Defined in: [candidate-execution/types.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L205) +Defined in: [candidate-execution/types.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L211) #### Methods @@ -2746,7 +2772,7 @@ Defined in: [candidate-execution/types.ts:205](https://github.com/tangle-network > **reset**(`input`): `Promise`\<[`AgentCandidateMemoryResetResult`](#agentcandidatememoryresetresult)\> -Defined in: [candidate-execution/types.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L211) +Defined in: [candidate-execution/types.ts:217](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L217) Reset and reserve exact task memory without returning live access. The service must scope the reservation to `preparationId`, automatically @@ -2788,7 +2814,7 @@ revoke it at `expiresAtMs`, and never reuse it for another preparation. > **activate**(`input`): `Promise`\<\{ `env`: `Readonly`\<`Record`\<`string`, `string`\>\>; \}\> -Defined in: [candidate-execution/types.ts:223](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L223) +Defined in: [candidate-execution/types.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L229) Create live scoped access only after the execution attempt is durably claimed. Activation must match the exact preparation/access pair and may not extend expiry. @@ -2825,7 +2851,7 @@ Activation must match the exact preparation/access pair and may not extend expir > **close**(`input`): `Promise`\<\{ `closed`: `true`; \}\> -Defined in: [candidate-execution/types.ts:235](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L235) +Defined in: [candidate-execution/types.ts:241](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L241) Revoke evaluator-owned access after process death or a failed preparation. Must be idempotent and concurrency-safe for the exact preparation/access @@ -2863,7 +2889,7 @@ pair and must never close a different preparation. ### AgentCandidateExecutionPorts -Defined in: [candidate-execution/types.ts:244](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L244) +Defined in: [candidate-execution/types.ts:250](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L250) #### Extends @@ -2895,31 +2921,31 @@ Defined in: [candidate-execution/types.ts:71](https://github.com/tangle-network/ > **workspaces**: [`AgentCandidateWorkspacePort`](#agentcandidateworkspaceport) -Defined in: [candidate-execution/types.ts:245](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L245) +Defined in: [candidate-execution/types.ts:251](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L251) ##### containers > **containers**: [`AgentCandidateContainerPort`](#agentcandidatecontainerport) -Defined in: [candidate-execution/types.ts:246](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L246) +Defined in: [candidate-execution/types.ts:252](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L252) ##### models > **models**: [`AgentCandidateModelPort`](#agentcandidatemodelport) -Defined in: [candidate-execution/types.ts:247](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L247) +Defined in: [candidate-execution/types.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L253) ##### memory > **memory**: [`AgentCandidateMemoryPort`](#agentcandidatememoryport) -Defined in: [candidate-execution/types.ts:248](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L248) +Defined in: [candidate-execution/types.ts:254](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L254) *** ### AgentCandidateTaskExecution -Defined in: [candidate-execution/types.ts:251](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L251) +Defined in: [candidate-execution/types.ts:257](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L257) #### Properties @@ -2927,37 +2953,37 @@ Defined in: [candidate-execution/types.ts:251](https://github.com/tangle-network > **executionId**: `string` -Defined in: [candidate-execution/types.ts:252](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L252) +Defined in: [candidate-execution/types.ts:258](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L258) ##### benchmark > **benchmark**: `string` -Defined in: [candidate-execution/types.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L253) +Defined in: [candidate-execution/types.ts:259](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L259) ##### benchmarkVersion > **benchmarkVersion**: `string` -Defined in: [candidate-execution/types.ts:254](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L254) +Defined in: [candidate-execution/types.ts:260](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L260) ##### taskId > **taskId**: `string` -Defined in: [candidate-execution/types.ts:255](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L255) +Defined in: [candidate-execution/types.ts:261](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L261) ##### splitDigest > **splitDigest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:256](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L256) +Defined in: [candidate-execution/types.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L262) ##### instruction > **instruction**: `string` -Defined in: [candidate-execution/types.ts:258](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L258) +Defined in: [candidate-execution/types.ts:264](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L264) Exact agent-visible task instruction. The runtime rejects malformed Unicode. @@ -2965,7 +2991,7 @@ Exact agent-visible task instruction. The runtime rejects malformed Unicode. > **repository**: `object` -Defined in: [candidate-execution/types.ts:259](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L259) +Defined in: [candidate-execution/types.ts:265](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L265) ###### identity @@ -2987,13 +3013,13 @@ Defined in: [candidate-execution/types.ts:259](https://github.com/tangle-network > **attempt**: `AgentCandidateAttemptPolicy` -Defined in: [candidate-execution/types.ts:265](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L265) +Defined in: [candidate-execution/types.ts:271](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L271) ##### model > **model**: `object` -Defined in: [candidate-execution/types.ts:266](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L266) +Defined in: [candidate-execution/types.ts:272](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L272) ###### requested @@ -3003,11 +3029,17 @@ Defined in: [candidate-execution/types.ts:266](https://github.com/tangle-network > **reasoningEffort**: `ReasoningEffort` +##### grader + +> **grader**: [`AgentCandidateBenchmarkGraderIdentity`](#agentcandidatebenchmarkgraderidentity) + +Defined in: [candidate-execution/types.ts:276](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L276) + ##### executionRoots > **executionRoots**: `object` -Defined in: [candidate-execution/types.ts:271](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L271) +Defined in: [candidate-execution/types.ts:278](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L278) Absolute paths inside the evaluator-owned execution environment. @@ -3023,7 +3055,7 @@ Absolute paths inside the evaluator-owned execution environment. > **stagingRoots**: `object` -Defined in: [candidate-execution/types.ts:276](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L276) +Defined in: [candidate-execution/types.ts:283](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L283) Host-side staging roots. These are verified but never signed as container paths. @@ -3043,25 +3075,25 @@ Host-side staging roots. These are verified but never signed as container paths. > **workspace**: `AgentCandidateWorkspaceSnapshotEvidence` -Defined in: [candidate-execution/types.ts:281](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L281) +Defined in: [candidate-execution/types.ts:288](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L288) ##### evaluatorTaskContainer? > `optional` **evaluatorTaskContainer?**: [`ResolvedAgentCandidateContainer`](#resolvedagentcandidatecontainer) -Defined in: [candidate-execution/types.ts:282](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L282) +Defined in: [candidate-execution/types.ts:289](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L289) ##### limits > **limits**: `AgentCandidateExecutionLimits` -Defined in: [candidate-execution/types.ts:283](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L283) +Defined in: [candidate-execution/types.ts:290](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L290) *** ### VerifiedAgentCandidate -Defined in: [candidate-execution/types.ts:286](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L286) +Defined in: [candidate-execution/types.ts:293](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L293) #### Properties @@ -3069,25 +3101,25 @@ Defined in: [candidate-execution/types.ts:286](https://github.com/tangle-network > `readonly` **bundle**: `AgentCandidateBundleV1` -Defined in: [candidate-execution/types.ts:287](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L287) +Defined in: [candidate-execution/types.ts:294](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L294) ##### materializedTree? > `readonly` `optional` **materializedTree?**: `string` -Defined in: [candidate-execution/types.ts:288](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L288) +Defined in: [candidate-execution/types.ts:295](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L295) ##### \[verifiedCandidateBrand\] > `readonly` **\[verifiedCandidateBrand\]**: `true` -Defined in: [candidate-execution/types.ts:289](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L289) +Defined in: [candidate-execution/types.ts:296](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L296) *** ### CanonicalCandidateDocument -Defined in: [candidate-execution/types.ts:292](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L292) +Defined in: [candidate-execution/types.ts:299](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L299) #### Type Parameters @@ -3101,13 +3133,13 @@ Defined in: [candidate-execution/types.ts:292](https://github.com/tangle-network > `readonly` **value**: `T` -Defined in: [candidate-execution/types.ts:293](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L293) +Defined in: [candidate-execution/types.ts:300](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L300) ##### bytes > `readonly` **bytes**: `Uint8Array` -Defined in: [candidate-execution/types.ts:295](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L295) +Defined in: [candidate-execution/types.ts:302](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L302) Canonical UTF-8 bytes of `value` with its top-level digest omitted. @@ -3115,13 +3147,13 @@ Canonical UTF-8 bytes of `value` with its top-level digest omitted. > `readonly` **digest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:296](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L296) +Defined in: [candidate-execution/types.ts:303](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L303) *** ### PreparedAgentCandidateLaunch -Defined in: [candidate-execution/types.ts:299](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L299) +Defined in: [candidate-execution/types.ts:306](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L306) #### Properties @@ -3129,13 +3161,13 @@ Defined in: [candidate-execution/types.ts:299](https://github.com/tangle-network > **executable**: `string` -Defined in: [candidate-execution/types.ts:300](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L300) +Defined in: [candidate-execution/types.ts:307](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L307) ##### args > **args**: readonly `string`[] -Defined in: [candidate-execution/types.ts:302](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L302) +Defined in: [candidate-execution/types.ts:309](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L309) Complete fixed argv, including profile materializer flags but excluding task delivery. @@ -3143,13 +3175,13 @@ Complete fixed argv, including profile materializer flags but excluding task del > **env**: `Readonly`\<`Record`\<`string`, `string`\>\> -Defined in: [candidate-execution/types.ts:303](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L303) +Defined in: [candidate-execution/types.ts:310](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L310) ##### flags > **flags**: readonly `string`[] -Defined in: [candidate-execution/types.ts:305](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L305) +Defined in: [candidate-execution/types.ts:312](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L312) Informational subset already present at the tail of `args`; executors must not append twice. @@ -3157,13 +3189,13 @@ Informational subset already present at the tail of `args`; executors must not a > **cwd**: `string` -Defined in: [candidate-execution/types.ts:306](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L306) +Defined in: [candidate-execution/types.ts:313](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L313) *** ### PreparedAgentCandidateInstruction -Defined in: [candidate-execution/types.ts:309](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L309) +Defined in: [candidate-execution/types.ts:316](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L316) #### Properties @@ -3171,19 +3203,19 @@ Defined in: [candidate-execution/types.ts:309](https://github.com/tangle-network > **bytes**: `Uint8Array` -Defined in: [candidate-execution/types.ts:310](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L310) +Defined in: [candidate-execution/types.ts:317](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L317) ##### delivery > **delivery**: `AgentCandidateInstructionDelivery` -Defined in: [candidate-execution/types.ts:311](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L311) +Defined in: [candidate-execution/types.ts:318](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L318) *** ### PreparedAgentCandidateTrace -Defined in: [candidate-execution/types.ts:314](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L314) +Defined in: [candidate-execution/types.ts:321](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L321) #### Properties @@ -3191,25 +3223,25 @@ Defined in: [candidate-execution/types.ts:314](https://github.com/tangle-network > **runId**: `string` -Defined in: [candidate-execution/types.ts:315](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L315) +Defined in: [candidate-execution/types.ts:322](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L322) ##### tags > **tags**: `Readonly`\<`Record`\<`string`, `string`\>\> -Defined in: [candidate-execution/types.ts:316](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L316) +Defined in: [candidate-execution/types.ts:323](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L323) ##### env > **env**: `Readonly`\<`Record`\<`string`, `string`\>\> -Defined in: [candidate-execution/types.ts:317](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L317) +Defined in: [candidate-execution/types.ts:324](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L324) *** ### PreparedAgentCandidateExecution -Defined in: [candidate-execution/types.ts:320](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L320) +Defined in: [candidate-execution/types.ts:327](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L327) #### Properties @@ -3217,19 +3249,19 @@ Defined in: [candidate-execution/types.ts:320](https://github.com/tangle-network > `readonly` **bundle**: `AgentCandidateBundleV1` -Defined in: [candidate-execution/types.ts:321](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L321) +Defined in: [candidate-execution/types.ts:328](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L328) ##### executionId > `readonly` **executionId**: `string` -Defined in: [candidate-execution/types.ts:322](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L322) +Defined in: [candidate-execution/types.ts:329](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L329) ##### roots > `readonly` **roots**: `object` -Defined in: [candidate-execution/types.ts:323](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L323) +Defined in: [candidate-execution/types.ts:330](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L330) ###### execution @@ -3263,7 +3295,7 @@ Defined in: [candidate-execution/types.ts:323](https://github.com/tangle-network > `readonly` **profilePlan**: `object` -Defined in: [candidate-execution/types.ts:334](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L334) +Defined in: [candidate-execution/types.ts:341](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L341) ###### value @@ -3281,7 +3313,7 @@ Defined in: [candidate-execution/types.ts:334](https://github.com/tangle-network > `readonly` **executionPlan**: `object` -Defined in: [candidate-execution/types.ts:339](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L339) +Defined in: [candidate-execution/types.ts:346](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L346) ###### value @@ -3295,31 +3327,31 @@ Defined in: [candidate-execution/types.ts:339](https://github.com/tangle-network > `readonly` **materializationReceipt**: [`CanonicalCandidateDocument`](#canonicalcandidatedocument)\<`AgentCandidateMaterializationReceiptV1`\> -Defined in: [candidate-execution/types.ts:343](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L343) +Defined in: [candidate-execution/types.ts:350](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L350) ##### launch > `readonly` **launch**: [`PreparedAgentCandidateLaunch`](#preparedagentcandidatelaunch) -Defined in: [candidate-execution/types.ts:344](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L344) +Defined in: [candidate-execution/types.ts:351](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L351) ##### instruction > `readonly` **instruction**: [`PreparedAgentCandidateInstruction`](#preparedagentcandidateinstruction) -Defined in: [candidate-execution/types.ts:345](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L345) +Defined in: [candidate-execution/types.ts:352](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L352) ##### resolvedModel > `readonly` **resolvedModel**: `AgentCandidateResolvedModel` -Defined in: [candidate-execution/types.ts:346](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L346) +Defined in: [candidate-execution/types.ts:353](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L353) ##### knowledge? > `readonly` `optional` **knowledge?**: `object` -Defined in: [candidate-execution/types.ts:347](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L347) +Defined in: [candidate-execution/types.ts:354](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L354) ###### snapshotId @@ -3337,25 +3369,25 @@ Defined in: [candidate-execution/types.ts:347](https://github.com/tangle-network > `readonly` **trace**: [`PreparedAgentCandidateTrace`](#preparedagentcandidatetrace) -Defined in: [candidate-execution/types.ts:352](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L352) +Defined in: [candidate-execution/types.ts:359](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L359) ##### memory > `readonly` **memory**: `AgentCandidateEffectiveMemory` -Defined in: [candidate-execution/types.ts:353](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L353) +Defined in: [candidate-execution/types.ts:360](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L360) ##### \[preparedCandidateBrand\] > `readonly` **\[preparedCandidateBrand\]**: `true` -Defined in: [candidate-execution/types.ts:354](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L354) +Defined in: [candidate-execution/types.ts:361](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L361) *** ### AgentCandidateProtectedRunCapture -Defined in: [candidate-execution/types.ts:357](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L357) +Defined in: [candidate-execution/types.ts:364](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L364) #### Properties @@ -3363,19 +3395,19 @@ Defined in: [candidate-execution/types.ts:357](https://github.com/tangle-network > **executionId**: `string` -Defined in: [candidate-execution/types.ts:358](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L358) +Defined in: [candidate-execution/types.ts:365](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L365) ##### termination > **termination**: `AgentCandidateTermination` -Defined in: [candidate-execution/types.ts:359](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L359) +Defined in: [candidate-execution/types.ts:366](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L366) *** ### AgentCandidateExecutorTaskOutcomeCapture -Defined in: [candidate-execution/types.ts:363](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L363) +Defined in: [candidate-execution/types.ts:370](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L370) Raw evaluator capture made only after the candidate process is dead. @@ -3385,7 +3417,7 @@ Raw evaluator capture made only after the candidate process is dead. > **resultTree**: `string` -Defined in: [candidate-execution/types.ts:365](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L365) +Defined in: [candidate-execution/types.ts:372](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L372) Claimed final tree. The runtime recomputes it independently from `gitDiff`. @@ -3393,7 +3425,7 @@ Claimed final tree. The runtime recomputes it independently from `gitDiff`. > **afterState**: `AgentCandidateWorkspaceManifestMaterialV1` -Defined in: [candidate-execution/types.ts:367](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L367) +Defined in: [candidate-execution/types.ts:374](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L374) Complete evaluator-captured workspace description after candidate execution. @@ -3401,7 +3433,7 @@ Complete evaluator-captured workspace description after candidate execution. > **archive**: `Uint8Array` -Defined in: [candidate-execution/types.ts:369](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L369) +Defined in: [candidate-execution/types.ts:376](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L376) Reproducible workspace archive corresponding to `afterState`. @@ -3409,7 +3441,7 @@ Reproducible workspace archive corresponding to `afterState`. > **gitDiff**: `Uint8Array` -Defined in: [candidate-execution/types.ts:371](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L371) +Defined in: [candidate-execution/types.ts:378](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L378) Exact binary patch from the signed task base to `afterState`. @@ -3417,7 +3449,7 @@ Exact binary patch from the signed task base to `afterState`. ### AgentCandidateExecutorMemoryCapture -Defined in: [candidate-execution/types.ts:375](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L375) +Defined in: [candidate-execution/types.ts:382](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L382) Raw isolated-memory capture made only after access has been revoked. @@ -3427,19 +3459,19 @@ Raw isolated-memory capture made only after access has been revoked. > `readonly` **afterState**: `AgentCandidateWorkspaceManifestMaterialV1` -Defined in: [candidate-execution/types.ts:376](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L376) +Defined in: [candidate-execution/types.ts:383](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L383) ##### archive > `readonly` **archive**: `Uint8Array` -Defined in: [candidate-execution/types.ts:377](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L377) +Defined in: [candidate-execution/types.ts:384](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L384) *** ### AgentCandidateExecutorFinalCapture -Defined in: [candidate-execution/types.ts:381](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L381) +Defined in: [candidate-execution/types.ts:388](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L388) Idempotent executor result after process death and trace drain. @@ -3449,19 +3481,19 @@ Idempotent executor result after process death and trace drain. > `readonly` **stopped**: `true` -Defined in: [candidate-execution/types.ts:382](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L382) +Defined in: [candidate-execution/types.ts:389](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L389) ##### taskOutcome? > `readonly` `optional` **taskOutcome?**: [`AgentCandidateExecutorTaskOutcomeCapture`](#agentcandidateexecutortaskoutcomecapture) -Defined in: [candidate-execution/types.ts:383](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L383) +Defined in: [candidate-execution/types.ts:390](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L390) ##### memoryAfter? > `readonly` `optional` **memoryAfter?**: [`AgentCandidateExecutorMemoryCapture`](#agentcandidateexecutormemorycapture) -Defined in: [candidate-execution/types.ts:385](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L385) +Defined in: [candidate-execution/types.ts:392](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L392) Required only when the prepared candidate uses isolated task memory. @@ -3469,7 +3501,7 @@ Required only when the prepared candidate uses isolated task memory. ### VerifiedAgentCandidateTaskOutcome -Defined in: [candidate-execution/types.ts:389](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L389) +Defined in: [candidate-execution/types.ts:396](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L396) Branded task outcome that has survived independent patch and tree verification. @@ -3479,7 +3511,7 @@ Branded task outcome that has survived independent patch and tree verification. > `readonly` **evidence**: `AgentCandidateTaskOutcomeEvidence` & `object` -Defined in: [candidate-execution/types.ts:390](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L390) +Defined in: [candidate-execution/types.ts:397](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L397) ###### Type Declaration @@ -3491,19 +3523,19 @@ Defined in: [candidate-execution/types.ts:390](https://github.com/tangle-network > `readonly` **patch**: `Uint8Array` -Defined in: [candidate-execution/types.ts:393](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L393) +Defined in: [candidate-execution/types.ts:400](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L400) ##### \[verifiedTaskOutcomeBrand\] > `readonly` **\[verifiedTaskOutcomeBrand\]**: `true` -Defined in: [candidate-execution/types.ts:394](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L394) +Defined in: [candidate-execution/types.ts:401](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L401) *** ### AgentCandidateBenchmarkGraderPort -Defined in: [candidate-execution/types.ts:406](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L406) +Defined in: [candidate-execution/types.ts:413](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L413) Evaluator-owned executable grader, pinned by immutable implementation bytes. @@ -3519,19 +3551,19 @@ copying an expected digest from ambient configuration. > `readonly` **name**: `string` -Defined in: [candidate-execution/types.ts:407](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L407) +Defined in: [candidate-execution/types.ts:414](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L414) ##### version > `readonly` **version**: `string` -Defined in: [candidate-execution/types.ts:408](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L408) +Defined in: [candidate-execution/types.ts:415](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L415) ##### artifact > `readonly` **artifact**: `AgentCandidateArtifactRef` -Defined in: [candidate-execution/types.ts:409](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L409) +Defined in: [candidate-execution/types.ts:416](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L416) #### Methods @@ -3539,7 +3571,7 @@ Defined in: [candidate-execution/types.ts:409](https://github.com/tangle-network > **run**(`input`): `Promise`\<\{ `evaluation`: `BenchmarkEvaluation`; `evidence`: `Uint8Array`; `binding`: \{ `implementationDigest`: `` `sha256:${string}` ``; `taskOutcomeDigest`: `` `sha256:${string}` ``; `outputDigest`: `` `sha256:${string}` ``; \}; \}\> -Defined in: [candidate-execution/types.ts:410](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L410) +Defined in: [candidate-execution/types.ts:417](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L417) ###### Parameters @@ -3585,7 +3617,7 @@ Frozen result deadline; runners must stop work and side effects when aborted. ### AgentCandidateExecutorRequest -Defined in: [candidate-execution/types.ts:438](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L438) +Defined in: [candidate-execution/types.ts:445](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L445) One detached request passed to the trusted environment-specific executor. @@ -3595,13 +3627,13 @@ One detached request passed to the trusted environment-specific executor. > `readonly` **executionId**: `string` -Defined in: [candidate-execution/types.ts:439](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L439) +Defined in: [candidate-execution/types.ts:446](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L446) ##### inputs > `readonly` **inputs**: `object` -Defined in: [candidate-execution/types.ts:441](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L441) +Defined in: [candidate-execution/types.ts:448](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L448) Immutable bytes from which the executor creates fresh isolated workspaces. @@ -3625,7 +3657,7 @@ Immutable bytes from which the executor creates fresh isolated workspaces. > `readonly` **roots**: `object` -Defined in: [candidate-execution/types.ts:448](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L448) +Defined in: [candidate-execution/types.ts:455](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L455) ###### taskRoot @@ -3639,7 +3671,7 @@ Defined in: [candidate-execution/types.ts:448](https://github.com/tangle-network > `readonly` **profilePlan**: `object` -Defined in: [candidate-execution/types.ts:449](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L449) +Defined in: [candidate-execution/types.ts:456](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L456) ###### value @@ -3657,7 +3689,7 @@ Defined in: [candidate-execution/types.ts:449](https://github.com/tangle-network > `readonly` **executionPlan**: `object` -Defined in: [candidate-execution/types.ts:450](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L450) +Defined in: [candidate-execution/types.ts:457](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L457) ###### value @@ -3671,31 +3703,31 @@ Defined in: [candidate-execution/types.ts:450](https://github.com/tangle-network > `readonly` **materializationReceipt**: [`CanonicalCandidateDocument`](#canonicalcandidatedocument)\<`AgentCandidateMaterializationReceiptV1`\> -Defined in: [candidate-execution/types.ts:451](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L451) +Defined in: [candidate-execution/types.ts:458](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L458) ##### launch > `readonly` **launch**: [`PreparedAgentCandidateLaunch`](#preparedagentcandidatelaunch) -Defined in: [candidate-execution/types.ts:452](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L452) +Defined in: [candidate-execution/types.ts:459](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L459) ##### instruction > `readonly` **instruction**: [`PreparedAgentCandidateInstruction`](#preparedagentcandidateinstruction) -Defined in: [candidate-execution/types.ts:453](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L453) +Defined in: [candidate-execution/types.ts:460](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L460) ##### resolvedModel > `readonly` **resolvedModel**: `AgentCandidateResolvedModel` -Defined in: [candidate-execution/types.ts:454](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L454) +Defined in: [candidate-execution/types.ts:461](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L461) ##### hardLimits > `readonly` **hardLimits**: `Pick`\<`AgentCandidateExecutionLimits`, `"timeoutMs"`\> -Defined in: [candidate-execution/types.ts:456](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L456) +Defined in: [candidate-execution/types.ts:463](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L463) Mechanically enforced by the runtime plus executor process-death acknowledgement. @@ -3703,7 +3735,7 @@ Mechanically enforced by the runtime plus executor process-death acknowledgement > `readonly` **observedLimits**: `Pick`\<`AgentCandidateExecutionLimits`, `"maxSteps"`\> -Defined in: [candidate-execution/types.ts:458](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L458) +Defined in: [candidate-execution/types.ts:465](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L465) Validity bound checked against protected traces; generic black-box executors cannot preempt it. @@ -3711,7 +3743,7 @@ Validity bound checked against protected traces; generic black-box executors can > `readonly` `optional` **knowledge?**: `object` -Defined in: [candidate-execution/types.ts:459](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L459) +Defined in: [candidate-execution/types.ts:466](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L466) ###### snapshotId @@ -3729,19 +3761,19 @@ Defined in: [candidate-execution/types.ts:459](https://github.com/tangle-network > `readonly` **trace**: [`PreparedAgentCandidateTrace`](#preparedagentcandidatetrace) -Defined in: [candidate-execution/types.ts:460](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L460) +Defined in: [candidate-execution/types.ts:467](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L467) ##### memory > `readonly` **memory**: `AgentCandidateEffectiveMemory` -Defined in: [candidate-execution/types.ts:461](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L461) +Defined in: [candidate-execution/types.ts:468](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L468) *** ### AgentCandidateExecutorPort -Defined in: [candidate-execution/types.ts:472](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L472) +Defined in: [candidate-execution/types.ts:479](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L479) Executes one prepared request inside an evaluator-owned isolation boundary. @@ -3756,7 +3788,7 @@ no candidate-authored usage or score fields. > **execute**(`request`, `context`): `Promise`\<[`AgentCandidateProtectedRunCapture`](#agentcandidateprotectedruncapture)\> -Defined in: [candidate-execution/types.ts:473](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L473) +Defined in: [candidate-execution/types.ts:480](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L480) ###### Parameters @@ -3790,7 +3822,7 @@ Absolute epoch-millisecond deadline owned by the runtime. > **stopAndCapture**(`request`, `context`): `Promise`\<[`AgentCandidateExecutorFinalCapture`](#agentcandidateexecutorfinalcapture)\> -Defined in: [candidate-execution/types.ts:490](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L490) +Defined in: [candidate-execution/types.ts:497](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L497) Kill any process/container still associated with the request, drain trace writes, and capture the final task workspace before teardown. @@ -3834,7 +3866,7 @@ Absolute execution deadline; a later stop acknowledgement cannot produce success ### AgentCandidateExecutorStopRequest -Defined in: [candidate-execution/types.ts:504](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L504) +Defined in: [candidate-execution/types.ts:511](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L511) Opaque process identity used for termination without re-exposing launch credentials. @@ -3844,19 +3876,19 @@ Opaque process identity used for termination without re-exposing launch credenti > `readonly` **executionId**: `string` -Defined in: [candidate-execution/types.ts:505](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L505) +Defined in: [candidate-execution/types.ts:512](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L512) ##### executionPlanDigest > `readonly` **executionPlanDigest**: `` `sha256:${string}` `` -Defined in: [candidate-execution/types.ts:506](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L506) +Defined in: [candidate-execution/types.ts:513](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L513) *** ### AgentCandidateExecutorWorkspaceInput -Defined in: [candidate-execution/types.ts:509](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L509) +Defined in: [candidate-execution/types.ts:516](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L516) #### Properties @@ -3864,19 +3896,19 @@ Defined in: [candidate-execution/types.ts:509](https://github.com/tangle-network > `readonly` **snapshot**: `AgentCandidateWorkspaceSnapshotEvidence` -Defined in: [candidate-execution/types.ts:510](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L510) +Defined in: [candidate-execution/types.ts:517](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L517) ##### files > `readonly` **files**: readonly [`AgentCandidateExecutorWorkspaceFile`](#agentcandidateexecutorworkspacefile)[] -Defined in: [candidate-execution/types.ts:511](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L511) +Defined in: [candidate-execution/types.ts:518](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L518) *** ### AgentCandidateExecutorWorkspaceFile -Defined in: [candidate-execution/types.ts:514](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L514) +Defined in: [candidate-execution/types.ts:521](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L521) #### Properties @@ -3884,25 +3916,25 @@ Defined in: [candidate-execution/types.ts:514](https://github.com/tangle-network > `readonly` **path**: `string` -Defined in: [candidate-execution/types.ts:515](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L515) +Defined in: [candidate-execution/types.ts:522](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L522) ##### mode > `readonly` **mode**: `420` \| `493` -Defined in: [candidate-execution/types.ts:516](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L516) +Defined in: [candidate-execution/types.ts:523](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L523) ##### bytes > `readonly` **bytes**: `Uint8Array` -Defined in: [candidate-execution/types.ts:517](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L517) +Defined in: [candidate-execution/types.ts:524](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L524) *** ### AgentCandidateExecutorProfileFile -Defined in: [candidate-execution/types.ts:520](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L520) +Defined in: [candidate-execution/types.ts:527](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L527) #### Properties @@ -3910,19 +3942,19 @@ Defined in: [candidate-execution/types.ts:520](https://github.com/tangle-network > `readonly` **path**: `string` -Defined in: [candidate-execution/types.ts:521](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L521) +Defined in: [candidate-execution/types.ts:528](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L528) ##### mode > `readonly` **mode**: `420` \| `493` -Defined in: [candidate-execution/types.ts:522](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L522) +Defined in: [candidate-execution/types.ts:529](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L529) ##### bytes > `readonly` **bytes**: `Uint8Array` -Defined in: [candidate-execution/types.ts:523](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L523) +Defined in: [candidate-execution/types.ts:530](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L530) *** @@ -5452,13 +5484,10 @@ Defined in: [improvement/agentic-generator.ts:58](https://github.com/tangle-netw `@tangle-network/agent-runtime` improvement — the CODE-surface proposer for agent-eval's improvement loop. -The ONE entry point for optimization is agent-eval's `selfImprove` -(`@tangle-network/agent-eval/contract`) — text/config surfaces, held-out gated, -with `analyzeGeneration` for analyst-fed reflection and `analyzeRuns` / -`fromOtelSpans` / `partitionRunsByAuthoringModel` for production intake + -cohorting. This module supplies only the one genuinely runtime-specific piece: -a CODE-surface `SurfaceProposer` you pass to `selfImprove` as `proposer`, which -mutates a git worktree via a pluggable `CandidateGenerator`: +The public entry point is `improve()`, a profile-aware facade over agent-eval's +`selfImprove`. This module also supplies the runtime-specific code candidate +producer, which mutates an isolated git worktree via a pluggable +`CandidateGenerator`: - `reflectiveGenerator` — cheap, no sandbox, applies pre-drafted patches - `agenticGenerator` — full coding harness in the worktree, multi-shot @@ -5573,202 +5602,111 @@ Test seam — inject the worktree-dirty check (defaults to `git status`). *** -### ImproveOptions - -Defined in: [improvement/improve.ts:78](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L78) +### ImproveSkillsOptions -#### Type Parameters - -##### TScenario - -`TScenario` *extends* `Scenario` - -##### TArtifact - -`TArtifact` +Defined in: [improvement/improve.ts:143](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L143) #### Properties -##### surface? - -> `optional` **surface?**: [`ImproveSurface`](#improvesurface) +##### document -Defined in: [improvement/improve.ts:81](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L81) +> **document**: `string` -Which profile lever to optimize. Default `'prompt'`. Selects the default - generator + the baseline-surface extraction shape. - -##### generator? - -> `optional` **generator?**: `SurfaceProposer`\<`unknown`\> - -Defined in: [improvement/improve.ts:85](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L85) - -The `SurfaceProposer` that mutates the surface. When unset, the facade - picks the default for `surface` (`gepaProposer` for prompt, `skillOptProposer` - for skills); surfaces with no default REQUIRE this (fail-loud otherwise). - -##### gate? - -> `optional` **gate?**: `"none"` \| `"holdout"` - -Defined in: [improvement/improve.ts:88](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L88) - -Gate mode. `'holdout'` (default) runs the held-out promotion gate; - `'none'` is a baseline-only run (`budget.generations = 0`). - -##### scenarios - -> **scenarios**: `TScenario`[] - -Defined in: [improvement/improve.ts:90](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L90) - -Scenarios to evaluate against. Passthrough to `selfImprove`. - -##### judge - -> **judge**: `JudgeConfig`\<`TArtifact`, `TScenario`\> - -Defined in: [improvement/improve.ts:92](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L92) +Defined in: [improvement/improve.ts:145](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L145) -Judge that scores artifacts. Passthrough to `selfImprove`. +The skill document's current text — the baseline `skillOptProposer` patches. -##### agent +##### writeBack? -> **agent**: (`surface`, `scenario`, `ctx`) => `Promise`\<`TArtifact`\> +> `optional` **writeBack?**: (`winnerDocument`) => `void` -Defined in: [improvement/improve.ts:95](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L95) +Defined in: [improvement/improve.ts:149](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L149) -The agent under improvement — same shape as `selfImprove.agent`: it takes - the current surface + scenario + ctx and returns the artifact to judge. +Persist the shipped winner document (write the file the profile ref points at). + Called only on a ship verdict. When omitted, the winner is still returned in + `result.raw.winner.surface` for the caller to materialize. ###### Parameters -###### surface - -`MutableSurface` - -###### scenario - -`TScenario` - -###### ctx +###### winnerDocument -`DispatchContext` +`string` ###### Returns -`Promise`\<`TArtifact`\> - -##### budget? - -> `optional` **budget?**: `SelfImproveBudget` - -Defined in: [improvement/improve.ts:97](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L97) - -Budget + loop shape. Passthrough; `gate: 'none'` forces `generations = 0`. +`void` -##### llm? +*** -> `optional` **llm?**: `SelfImproveLlm` +### ImproveCodeOptions -Defined in: [improvement/improve.ts:100](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L100) +Defined in: [improvement/improve.ts:152](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L152) -LLM config. Passthrough to `selfImprove` AND used to construct the default - reflective proposer (`gepaProposer`/`skillOptProposer`) when `generator` is unset. +#### Properties -##### allowedModels? +##### repoRoot -> `optional` **allowedModels?**: readonly `string`[] +> **repoRoot**: `string` -Defined in: [improvement/improve.ts:104](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L104) +Defined in: [improvement/improve.ts:154](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L154) -Restrict the run to this subset of models. When set, the reflection model - (`llm.model`, or the default when unset) must be a member, or `improve()` throws - a `ConfigError` before the generator is built. Unset = unrestricted. +Repo root candidate worktrees fork from. -##### runDir? +##### baseRef? -> `optional` **runDir?**: `string` +> `optional` **baseRef?**: `string` -Defined in: [improvement/improve.ts:110](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L110) +Defined in: [improvement/improve.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L156) -Run directory passthrough to `selfImprove`. Pass a REAL path to make the loop - durable: campaign cells + the loop provenance record land on the filesystem as - they complete, so a multi-hour search survives a process/infra death instead of - losing every generation with it (the default `mem://` run keeps everything - in-process). +Base ref candidates fork from. Default `main`. -##### analyzeGeneration? +##### worktreeDir? -> `optional` **analyzeGeneration?**: ((`input`) => `Promise`\<`unknown`[]\>) \| `null` +> `optional` **worktreeDir?**: `string` -Defined in: [improvement/improve.ts:118](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L118) +Defined in: [improvement/improve.ts:158](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L158) -Per-generation findings producer passthrough (see selfImprove.analyzeGeneration). - DEFAULT: the built-in failure distiller — after each generation it turns the - worst-scoring/errored cells into structured findings ({ scenario, composite, - notes, error }) for the NEXT proposal round, so the proposer reasons over what - actually failed instead of a static seed. Pass your own producer (e.g. a - trace-analyst over the runDir's traces) to replace it; pass `null` to disable - and keep the static `findings` all the way through. +Directory worktrees are created under. Default `/.worktrees`. -##### rawTraceContext? +##### harness? -> `optional` **rawTraceContext?**: `boolean` +> `optional` **harness?**: [`LocalHarness`](mcp.md#localharness) -Defined in: [improvement/improve.ts:128](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L128) +Defined in: [improvement/improve.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L160) -META-HARNESS mode: instead of the ~400-char distilled findings, feed the - proposer RAW-TRACE FILESYSTEM CONTEXT — the PATHS into the prior generation's - real run traces under `runDir` (per-cell `spans.jsonl` event logs + - `cached-result.json` scores + artifacts) plus a `grep`/`cat`-to-diagnose - instruction — so the coding agent reads the actual failures itself rather than - a pre-summary. Requires a REAL `runDir` (that is where the traces live). - Ignored when `analyzeGeneration` is set explicitly (that wins) or is `null` - (disabled). Equivalent to `analyzeGeneration: rawTraceDistiller()`; this flag - is the one-line enable. Default `false` (the distiller stays the default). +Coding harness the agentic generator runs in each worktree. Default `claude`. -##### code? +##### verify? -> `optional` **code?**: `ImproveCodeOptions` +> `optional` **verify?**: [`Verifier`](#verifier) -Defined in: [improvement/improve.ts:136](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L136) +Defined in: [improvement/improve.ts:163](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L163) -CODE-surface wiring with prompt-parity DX: name `surface: 'code'`, point at a - repo, and the facade assembles the whole candidate pipeline — git worktrees - (`gitWorktreeAdapter`) driven by `improvementDriver` with the full agentic - generator (a real coding harness edits each candidate worktree; a `verify` - hook gates candidates before they are ever measured). Ignored when - `opts.generator` is supplied. Without either, `surface: 'code'` still fails - loud — there is no safe zero-config repo to invent. +Verify a candidate worktree before it becomes a measurable surface; failures + feed the next shot (see `agenticGenerator.verify` / `commandVerifier`). -##### skills? +##### timeoutMs? -> `optional` **skills?**: `ImproveSkillsOptions` +> `optional` **timeoutMs?**: `number` -Defined in: [improvement/improve.ts:143](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L143) +Defined in: [improvement/improve.ts:165](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L165) -SKILLS-surface wiring for real skill-DOCUMENT optimization. Without this, - `surface: 'skills'` optimizes the profile's skills REFS array (file pointers) - — which `skillOptProposer` (a document patcher) cannot meaningfully edit. - Provide the document CONTENT to optimize + a `writeBack` to persist the - shipped winner (the profile ref points at a file the caller owns). This is - what makes skillOpt reachable through improve(). +Per-shot wall-clock timeout for the harness (ms). -##### storage? +##### generator? -> `optional` **storage?**: `CampaignStorage` +> `optional` **generator?**: [`CandidateGenerator`](#candidategenerator) -Defined in: [improvement/improve.ts:145](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L145) +Defined in: [improvement/improve.ts:168](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L168) -Storage passthrough to `selfImprove`; overrides the default chosen from `runDir`. +Byte-producer override — the test seam and the escape hatch for custom + candidate production. When set, `harness`/`verify`/`timeoutMs` are unused. *** ### ImproveResult -Defined in: [improvement/improve.ts:176](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L176) +Defined in: [improvement/improve.ts:171](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L171) #### Type Parameters @@ -5786,7 +5724,7 @@ Defined in: [improvement/improve.ts:176](https://github.com/tangle-network/agent > **profile**: `AgentProfile` -Defined in: [improvement/improve.ts:179](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L179) +Defined in: [improvement/improve.ts:174](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L174) The profile after improvement: the winner surface applied back into the matching field when the gate shipped, else the input profile unchanged. @@ -5795,7 +5733,7 @@ The profile after improvement: the winner surface applied back into the > **shipped**: `boolean` -Defined in: [improvement/improve.ts:181](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L181) +Defined in: [improvement/improve.ts:176](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L176) True when `gateDecision === 'ship'`. @@ -5803,7 +5741,7 @@ True when `gateDecision === 'ship'`. > **lift**: `number` -Defined in: [improvement/improve.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L183) +Defined in: [improvement/improve.ts:178](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L178) Held-out lift (`winner − baseline` composite). @@ -5811,7 +5749,7 @@ Held-out lift (`winner − baseline` composite). > **gateDecision**: `"ship"` \| `"hold"` \| `"need_more_work"` \| `"model_ceiling"` \| `"arch_ceiling"` -Defined in: [improvement/improve.ts:185](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L185) +Defined in: [improvement/improve.ts:180](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L180) The five-valued gate verdict from `selfImprove`. @@ -5819,7 +5757,7 @@ The five-valued gate verdict from `selfImprove`. > **raw**: `SelfImproveResult`\<`TScenario`, `TArtifact`\> -Defined in: [improvement/improve.ts:187](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L187) +Defined in: [improvement/improve.ts:182](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L182) Full `selfImprove` result for advanced inspection. @@ -5827,7 +5765,7 @@ Full `selfImprove` result for advanced inspection. ### CandidateGenerator -Defined in: [improvement/improvement-driver.ts:36](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L36) +Defined in: [improvement/improvement-driver.ts:37](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L37) The byte-producing seam — the ONE thing that differs between the cheap reflective path and the full agentic path. A generator makes (uncommitted) @@ -5840,13 +5778,13 @@ The byte-producing seam — the ONE thing that differs between the cheap > **kind**: `string` -Defined in: [improvement/improvement-driver.ts:37](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L37) +Defined in: [improvement/improvement-driver.ts:38](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L38) ##### proposesWithoutFindings? > `optional` **proposesWithoutFindings?**: `boolean` -Defined in: [improvement/improvement-driver.ts:48](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L48) +Defined in: [improvement/improvement-driver.ts:49](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L49) Whether this generator can produce a candidate from an EMPTY findings set and no phase-2 report — i.e. it draws its change signal from the repo and @@ -5865,7 +5803,7 @@ Whether this generator can produce a candidate from an EMPTY findings set > **generate**(`args`): `Promise`\<\{ `applied`: `boolean`; `summary`: `string`; \}\> -Defined in: [improvement/improvement-driver.ts:49](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L49) +Defined in: [improvement/improvement-driver.ts:50](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L50) ###### Parameters @@ -5914,7 +5852,7 @@ DEPTH: max iterations the generator may take (agentic uses this; the ### ImprovementDriverOptions -Defined in: [improvement/improvement-driver.ts:65](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L65) +Defined in: [improvement/improvement-driver.ts:66](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L66) #### Properties @@ -5922,21 +5860,51 @@ Defined in: [improvement/improvement-driver.ts:65](https://github.com/tangle-net > **worktree**: `WorktreeAdapter` -Defined in: [improvement/improvement-driver.ts:66](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L66) +Defined in: [improvement/improvement-driver.ts:67](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L67) ##### generator > **generator**: [`CandidateGenerator`](#candidategenerator) -Defined in: [improvement/improvement-driver.ts:67](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L67) +Defined in: [improvement/improvement-driver.ts:68](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L68) ##### baseRef? -> `optional` **baseRef?**: `string` +> `optional` **baseRef?**: `string` + +Defined in: [improvement/improvement-driver.ts:70](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L70) + +Base ref candidate worktrees fork from. Default `main`. + +*** + +### ManagedImprovementDriver + +Defined in: [improvement/improvement-driver.ts:73](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L73) + +#### Extends + +- `SurfaceProposer`\<`AnalystFinding`\> + +#### Methods + +##### cleanup() + +> **cleanup**(`retainWorktreeRefs?`): `Promise`\<`void`\> + +Defined in: [improvement/improvement-driver.ts:75](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L75) + +Remove every finalized candidate except explicitly retained winners. + +###### Parameters + +###### retainWorktreeRefs? + +readonly `string`[] -Defined in: [improvement/improvement-driver.ts:69](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L69) +###### Returns -Base ref candidate worktrees fork from. Default `main`. +`Promise`\<`void`\> *** @@ -7034,16 +7002,7 @@ Defined in: [model-resolution.ts:82](https://github.com/tangle-network/agent-run ### OtelExportConfig -Defined in: [otel-export.ts:12](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L12) - -OTEL span exporter — streams LoopTraceEvents to an OTLP/HTTP collector. - -Reads OTEL_EXPORTER_OTLP_ENDPOINT + OTEL_EXPORTER_OTLP_HEADERS from env -when no explicit config is given. Keeps the runtime dep-free from -@opentelemetry/sdk-trace-base — minimal OTLP/JSON serializer. - -The exporter accepts both raw OtelSpan objects and LoopTraceEvents -(which get converted to OTLP spans automatically). +Defined in: [otel-export.ts:15](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L15) #### Properties @@ -7051,7 +7010,7 @@ The exporter accepts both raw OtelSpan objects and LoopTraceEvents > `optional` **endpoint?**: `string` -Defined in: [otel-export.ts:14](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L14) +Defined in: [otel-export.ts:17](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L17) OTLP endpoint. Reads OTEL_EXPORTER_OTLP_ENDPOINT env by default. @@ -7059,7 +7018,7 @@ OTLP endpoint. Reads OTEL_EXPORTER_OTLP_ENDPOINT env by default. > `optional` **headers?**: `Record`\<`string`, `string`\> -Defined in: [otel-export.ts:16](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L16) +Defined in: [otel-export.ts:19](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L19) OTLP headers. Reads OTEL_EXPORTER_OTLP_HEADERS env by default. @@ -7067,7 +7026,7 @@ OTLP headers. Reads OTEL_EXPORTER_OTLP_HEADERS env by default. > `optional` **batchSize?**: `number` -Defined in: [otel-export.ts:18](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L18) +Defined in: [otel-export.ts:21](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L21) Batch size before flush. Default 64. @@ -7075,7 +7034,7 @@ Batch size before flush. Default 64. > `optional` **flushIntervalMs?**: `number` -Defined in: [otel-export.ts:20](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L20) +Defined in: [otel-export.ts:23](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L23) Flush interval ms. Default 5000. @@ -7083,7 +7042,7 @@ Flush interval ms. Default 5000. > `optional` **resourceAttributes?**: `Record`\<`string`, `string` \| `number` \| `boolean`\> -Defined in: [otel-export.ts:22](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L22) +Defined in: [otel-export.ts:25](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L25) Resource attributes stamped on every export. @@ -7091,7 +7050,7 @@ Resource attributes stamped on every export. > `optional` **serviceName?**: `string` -Defined in: [otel-export.ts:24](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L24) +Defined in: [otel-export.ts:27](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L27) Service name. Default 'agent-runtime'. @@ -7099,7 +7058,7 @@ Service name. Default 'agent-runtime'. ### OtelExporter -Defined in: [otel-export.ts:27](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L27) +Defined in: [otel-export.ts:30](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L30) #### Methods @@ -7107,7 +7066,7 @@ Defined in: [otel-export.ts:27](https://github.com/tangle-network/agent-runtime/ > **exportSpan**(`span`): `void` -Defined in: [otel-export.ts:29](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L29) +Defined in: [otel-export.ts:32](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L32) Export a span. @@ -7125,7 +7084,7 @@ Export a span. > **flush**(): `Promise`\<`void`\> -Defined in: [otel-export.ts:31](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L31) +Defined in: [otel-export.ts:34](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L34) Force flush pending spans. @@ -7137,7 +7096,7 @@ Force flush pending spans. > **shutdown**(): `Promise`\<`void`\> -Defined in: [otel-export.ts:33](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L33) +Defined in: [otel-export.ts:36](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L36) Shutdown cleanly. @@ -7149,7 +7108,7 @@ Shutdown cleanly. ### OtelSpan -Defined in: [otel-export.ts:36](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L36) +Defined in: [otel-export.ts:39](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L39) #### Properties @@ -7157,55 +7116,55 @@ Defined in: [otel-export.ts:36](https://github.com/tangle-network/agent-runtime/ > **traceId**: `string` -Defined in: [otel-export.ts:37](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L37) +Defined in: [otel-export.ts:40](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L40) ##### spanId > **spanId**: `string` -Defined in: [otel-export.ts:38](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L38) +Defined in: [otel-export.ts:41](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L41) ##### parentSpanId? > `optional` **parentSpanId?**: `string` -Defined in: [otel-export.ts:39](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L39) +Defined in: [otel-export.ts:42](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L42) ##### name > **name**: `string` -Defined in: [otel-export.ts:40](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L40) +Defined in: [otel-export.ts:43](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L43) ##### kind? > `optional` **kind?**: `number` -Defined in: [otel-export.ts:41](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L41) +Defined in: [otel-export.ts:44](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L44) ##### startTimeUnixNano > **startTimeUnixNano**: `string` -Defined in: [otel-export.ts:42](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L42) +Defined in: [otel-export.ts:45](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L45) ##### endTimeUnixNano > **endTimeUnixNano**: `string` -Defined in: [otel-export.ts:43](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L43) +Defined in: [otel-export.ts:46](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L46) ##### attributes? > `optional` **attributes?**: [`OtelAttribute`](#otelattribute)[] -Defined in: [otel-export.ts:44](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L44) +Defined in: [otel-export.ts:47](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L47) ##### status? > `optional` **status?**: `object` -Defined in: [otel-export.ts:45](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L45) +Defined in: [otel-export.ts:48](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L48) ###### code @@ -7219,7 +7178,7 @@ Defined in: [otel-export.ts:45](https://github.com/tangle-network/agent-runtime/ ### OtelAttribute -Defined in: [otel-export.ts:48](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L48) +Defined in: [otel-export.ts:51](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L51) #### Properties @@ -7227,13 +7186,13 @@ Defined in: [otel-export.ts:48](https://github.com/tangle-network/agent-runtime/ > **key**: `string` -Defined in: [otel-export.ts:49](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L49) +Defined in: [otel-export.ts:52](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L52) ##### value > **value**: `object` -Defined in: [otel-export.ts:50](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L50) +Defined in: [otel-export.ts:53](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L53) ###### stringValue? @@ -7253,9 +7212,126 @@ Defined in: [otel-export.ts:50](https://github.com/tangle-network/agent-runtime/ *** +### RuntimeEventOtelOptions + +Defined in: [otel-export.ts:230](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L230) + +#### Stable + +#### Extends + +- [`RuntimeTelemetryOptions`](#runtimetelemetryoptions) + +#### Properties + +##### redact? + +> `optional` **redact?**: (`value`) => `unknown` + +Defined in: [otel-export.ts:232](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L232) + +Final customer redactor applied after the schema-aware runtime sanitizer. + +###### Parameters + +###### value + +`unknown` + +###### Returns + +`unknown` + +##### includeInputs? + +> `optional` **includeInputs?**: `boolean` + +Defined in: [sanitize.ts:35](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L35) + +Include raw task inputs. Off by default because task inputs often contain +customer facts, credentials, source text, or internal IDs. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeInputs`](#includeinputs-1) + +##### includeRequirementDescriptions? + +> `optional` **includeRequirementDescriptions?**: `boolean` + +Defined in: [sanitize.ts:37](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L37) + +Include requirement descriptions. Secret requirements are always redacted. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeRequirementDescriptions`](#includerequirementdescriptions-1) + +##### includeEvidenceIds? + +> `optional` **includeEvidenceIds?**: `boolean` + +Defined in: [sanitize.ts:39](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L39) + +Include evidence IDs. Off by default; counts are safer for shared reports. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeEvidenceIds`](#includeevidenceids-1) + +##### includeUserAnswers? + +> `optional` **includeUserAnswers?**: `boolean` + +Defined in: [sanitize.ts:41](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L41) + +Include user answers from question preflight. Off by default. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeUserAnswers`](#includeuseranswers-1) + +##### includeControlPayloads? + +> `optional` **includeControlPayloads?**: `boolean` + +Defined in: [sanitize.ts:43](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L43) + +Include action payloads and action results for control steps. Off by default. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeControlPayloads`](#includecontrolpayloads-1) + +##### includeMetadata? + +> `optional` **includeMetadata?**: `boolean` + +Defined in: [sanitize.ts:45](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L45) + +Include task metadata. Off by default because metadata may carry IDs or policy internals. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeMetadata`](#includemetadata-1) + +##### includeEvalDetails? + +> `optional` **includeEvalDetails?**: `boolean` + +Defined in: [sanitize.ts:47](https://github.com/tangle-network/agent-runtime/blob/main/src/sanitize.ts#L47) + +Include eval detail/evidence strings. Off by default because validators may echo private input. + +###### Inherited from + +[`RuntimeTelemetryOptions`](#runtimetelemetryoptions).[`includeEvalDetails`](#includeevaldetails-1) + +*** + ### LoopSpanNode -Defined in: [otel-export.ts:231](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L231) +Defined in: [otel-export.ts:334](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L334) Sink-neutral node in a reconstructed loop span tree. The root node's `parentSpanId` is `undefined` — sinks decide how to parent it (the OTEL @@ -7268,19 +7344,19 @@ leaves it as the tree root). > **spanId**: `string` -Defined in: [otel-export.ts:232](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L232) +Defined in: [otel-export.ts:335](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L335) ##### parentSpanId? > `optional` **parentSpanId?**: `string` -Defined in: [otel-export.ts:233](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L233) +Defined in: [otel-export.ts:336](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L336) ##### name > **name**: `string` -Defined in: [otel-export.ts:235](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L235) +Defined in: [otel-export.ts:338](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L338) `'loop'` | `'loop.round'` | `'loop.iteration'`. @@ -7288,7 +7364,7 @@ Defined in: [otel-export.ts:235](https://github.com/tangle-network/agent-runtime > **kind**: `"loop"` \| `"round"` \| `"branch"` -Defined in: [otel-export.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L237) +Defined in: [otel-export.ts:340](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L340) Topology level: loop root, plan round, or iteration branch. @@ -7296,25 +7372,25 @@ Topology level: loop root, plan round, or iteration branch. > **startMs**: `number` -Defined in: [otel-export.ts:238](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L238) +Defined in: [otel-export.ts:341](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L341) ##### endMs > **endMs**: `number` -Defined in: [otel-export.ts:239](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L239) +Defined in: [otel-export.ts:342](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L342) ##### attrs > **attrs**: `Record`\<`string`, `string` \| `number` \| `boolean`\> -Defined in: [otel-export.ts:240](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L240) +Defined in: [otel-export.ts:343](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L343) ##### error > **error**: `boolean` -Defined in: [otel-export.ts:242](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L242) +Defined in: [otel-export.ts:345](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L345) True when the iteration carried an error — maps to OTEL status code 2. @@ -7322,7 +7398,7 @@ True when the iteration carried an error — maps to OTEL status code 2. ### EvalRunGeneration -Defined in: [otel-export.ts:558](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L558) +Defined in: [otel-export.ts:661](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L661) #### Properties @@ -7330,7 +7406,7 @@ Defined in: [otel-export.ts:558](https://github.com/tangle-network/agent-runtime > **index**: `number` -Defined in: [otel-export.ts:560](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L560) +Defined in: [otel-export.ts:663](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L663) 0-based ordinal of this generation within the run (required by ingest). @@ -7338,7 +7414,7 @@ Defined in: [otel-export.ts:560](https://github.com/tangle-network/agent-runtime > **surfaceHash**: `string` -Defined in: [otel-export.ts:562](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L562) +Defined in: [otel-export.ts:665](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L665) Identity of the proposed surface change (content-addressed hash). @@ -7346,7 +7422,7 @@ Identity of the proposed surface change (content-addressed hash). > `optional` **surface?**: `unknown` -Defined in: [otel-export.ts:564](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L564) +Defined in: [otel-export.ts:667](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L667) Arbitrary provenance for this generation (rationale, evidence, source). @@ -7354,7 +7430,7 @@ Arbitrary provenance for this generation (rationale, evidence, source). > `optional` **cells?**: `unknown`[] -Defined in: [otel-export.ts:566](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L566) +Defined in: [otel-export.ts:669](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L669) Per-scenario results; empty until the generation is measured. @@ -7362,7 +7438,7 @@ Per-scenario results; empty until the generation is measured. > **compositeMean**: `number` -Defined in: [otel-export.ts:568](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L568) +Defined in: [otel-export.ts:671](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L671) Mean composite score (0 when unmeasured — pair with labels.measured). @@ -7370,19 +7446,19 @@ Mean composite score (0 when unmeasured — pair with labels.measured). > **costUsd**: `number` -Defined in: [otel-export.ts:569](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L569) +Defined in: [otel-export.ts:672](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L672) ##### durationMs > **durationMs**: `number` -Defined in: [otel-export.ts:570](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L570) +Defined in: [otel-export.ts:673](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L673) *** ### EvalRunEvent -Defined in: [otel-export.ts:573](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L573) +Defined in: [otel-export.ts:676](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L676) #### Properties @@ -7390,19 +7466,19 @@ Defined in: [otel-export.ts:573](https://github.com/tangle-network/agent-runtime > **runId**: `string` -Defined in: [otel-export.ts:574](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L574) +Defined in: [otel-export.ts:677](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L677) ##### runDir > **runDir**: `string` -Defined in: [otel-export.ts:575](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L575) +Defined in: [otel-export.ts:678](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L678) ##### timestamp > **timestamp**: `string` -Defined in: [otel-export.ts:577](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L577) +Defined in: [otel-export.ts:680](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L680) ISO timestamp. @@ -7410,61 +7486,61 @@ ISO timestamp. > **status**: `"started"` \| `"baseline-complete"` \| `"generation-complete"` \| `"gate-decided"` \| `"finished"` \| `"errored"` -Defined in: [otel-export.ts:578](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L578) +Defined in: [otel-export.ts:681](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L681) ##### labels? > `optional` **labels?**: `Record`\<`string`, `string`\> -Defined in: [otel-export.ts:585](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L585) +Defined in: [otel-export.ts:688](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L688) ##### baseline? > `optional` **baseline?**: [`EvalRunGeneration`](#evalrungeneration) -Defined in: [otel-export.ts:586](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L586) +Defined in: [otel-export.ts:689](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L689) ##### generations? > `optional` **generations?**: [`EvalRunGeneration`](#evalrungeneration)[] -Defined in: [otel-export.ts:587](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L587) +Defined in: [otel-export.ts:690](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L690) ##### gateDecision? > `optional` **gateDecision?**: `"ship"` \| `"hold"` \| `"need_more_work"` \| `"model_ceiling"` \| `"arch_ceiling"` -Defined in: [otel-export.ts:588](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L588) +Defined in: [otel-export.ts:691](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L691) ##### holdoutLift? > `optional` **holdoutLift?**: `number` -Defined in: [otel-export.ts:589](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L589) +Defined in: [otel-export.ts:692](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L692) ##### totalCostUsd > **totalCostUsd**: `number` -Defined in: [otel-export.ts:590](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L590) +Defined in: [otel-export.ts:693](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L693) ##### totalDurationMs > **totalDurationMs**: `number` -Defined in: [otel-export.ts:591](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L591) +Defined in: [otel-export.ts:694](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L694) ##### errorMessage? > `optional` **errorMessage?**: `string` -Defined in: [otel-export.ts:592](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L592) +Defined in: [otel-export.ts:695](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L695) *** ### EvalRunsExportConfig -Defined in: [otel-export.ts:595](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L595) +Defined in: [otel-export.ts:698](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L698) #### Properties @@ -7472,7 +7548,7 @@ Defined in: [otel-export.ts:595](https://github.com/tangle-network/agent-runtime > `optional` **apiKey?**: `string` -Defined in: [otel-export.ts:597](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L597) +Defined in: [otel-export.ts:700](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L700) Bearer key — tenant is resolved server-side from it. Reads TANGLE_API_KEY. @@ -7480,7 +7556,7 @@ Bearer key — tenant is resolved server-side from it. Reads TANGLE_API_KEY. > `optional` **base?**: `string` -Defined in: [otel-export.ts:599](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L599) +Defined in: [otel-export.ts:702](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L702) Intelligence base. Reads TANGLE_INTELLIGENCE_URL env, else prod. @@ -7488,7 +7564,7 @@ Intelligence base. Reads TANGLE_INTELLIGENCE_URL env, else prod. > `optional` **idempotencyKey?**: `string` -Defined in: [otel-export.ts:601](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L601) +Defined in: [otel-export.ts:704](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L704) Idempotency-Key header (e.g. the runId) — safe retries + upsert. @@ -7496,7 +7572,7 @@ Idempotency-Key header (e.g. the runId) — safe retries + upsert. ### EvalRunsExportResult -Defined in: [otel-export.ts:604](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L604) +Defined in: [otel-export.ts:707](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L707) #### Properties @@ -7504,25 +7580,25 @@ Defined in: [otel-export.ts:604](https://github.com/tangle-network/agent-runtime > **ok**: `boolean` -Defined in: [otel-export.ts:605](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L605) +Defined in: [otel-export.ts:708](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L708) ##### status > **status**: `number` -Defined in: [otel-export.ts:606](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L606) +Defined in: [otel-export.ts:709](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L709) ##### accepted > **accepted**: `number` -Defined in: [otel-export.ts:607](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L607) +Defined in: [otel-export.ts:710](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L710) ##### rejected > **rejected**: `object`[] -Defined in: [otel-export.ts:608](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L608) +Defined in: [otel-export.ts:711](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L711) ###### index @@ -8283,6 +8359,10 @@ Defined in: [sanitize.ts:30](https://github.com/tangle-network/agent-runtime/blo #### Stable +#### Extended by + +- [`RuntimeEventOtelOptions`](#runtimeeventoteloptions) + #### Properties ##### includeInputs? @@ -10196,7 +10276,7 @@ Limits mechanically enforced by the evaluator-owned model gateway. > **AgentCandidateRunFinalization** = \{ `succeeded`: `true`; `receipt`: [`CanonicalCandidateDocument`](#canonicalcandidatedocument)\<`AgentCandidateRunReceiptV2`\>; `artifacts`: \{ `modelSettlement`: `AgentCandidateArtifactRef`; `taskOutcome`: `AgentCandidateArtifactRef`; `benchmarkResult`: `AgentCandidateArtifactRef`; `runReceipt`: `AgentCandidateArtifactRef`; \}; \} \| \{ `succeeded`: `false`; `reason`: `string`; `partial`: \{ `executionId`: `string`; `bundleDigest`: `Sha256Digest`; `executionPlanDigest`: `Sha256Digest`; `materializationReceiptDigest`: `Sha256Digest`; `termination?`: `AgentCandidateTermination`; \}; `usage`: `AgentCandidateSpend` \| `null`; \} -Defined in: [candidate-execution/types.ts:526](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L526) +Defined in: [candidate-execution/types.ts:533](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L533) #### Union Members @@ -10396,9 +10476,9 @@ Verifies the edited worktree. Sync or async; throws only on a setup fault ### ImproveSurface -> **ImproveSurface** = `"prompt"` \| `"skills"` \| `"tools"` \| `"mcp"` \| `"hooks"` \| `"code"` \| `"rollout-policy"` +> **ImproveSurface** = `"prompt"` \| `"skills"` \| `"tools"` \| `"mcp"` \| `"hooks"` \| `"subagents"` \| `"workflow"` \| `"agent-profile"` \| `"code"` \| `"rollout-policy"` -Defined in: [improvement/improve.ts:69](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L69) +Defined in: [improvement/improve.ts:75](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L75) The agent-profile lever `improve` optimizes. Mirrors the AgentProfile-law profile levers; `code` is the implementation-tier surface, `rollout-policy` @@ -10407,6 +10487,112 @@ The agent-profile lever `improve` optimizes. Mirrors the AgentProfile-law *** +### ImproveOptions + +> **ImproveOptions**\<`TScenario`, `TArtifact`\> = `Omit`\<`SelfImproveOptions`\<`TScenario`, `TArtifact`\>, `"analyzeGeneration"` \| `"baselineSurface"` \| `"findings"` \| `"gate"` \| `"proposer"`\> & `object` + +Defined in: [improvement/improve.ts:87](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L87) + +#### Type Declaration + +##### surface? + +> `optional` **surface?**: [`ImproveSurface`](#improvesurface) + +Which profile lever to optimize. Default `'prompt'`. Selects the default + generator + the baseline-surface extraction shape. + +##### generator? + +> `optional` **generator?**: `SurfaceProposer` + +The `SurfaceProposer` that mutates the surface. When unset, the facade + picks the default for `surface` (`gepaProposer` for prompt, `skillOptProposer` + for skills); surfaces with no default REQUIRE this (fail-loud otherwise). + +##### gate? + +> `optional` **gate?**: `"holdout"` \| `"none"` + +Gate mode. `'holdout'` (default) runs the held-out promotion gate; + `'none'` is a baseline-only run (`budget.generations = 0`). + +##### allowedModels? + +> `optional` **allowedModels?**: readonly `string`[] + +Restrict the run to this subset of models. When set, the reflection model + (`llm.model`, or the default when unset) must be a member, or `improve()` throws + a `ConfigError` before the generator is built. Unset = unrestricted. + +##### analyzeGeneration? + +> `optional` **analyzeGeneration?**: `SelfImproveOptions`\<`TScenario`, `TArtifact`\>\[`"analyzeGeneration"`\] \| `null` + +Per-generation findings producer passthrough (see selfImprove.analyzeGeneration). + DEFAULT: the built-in failure distiller — after each generation it turns the + worst-scoring/errored cells into structured findings ({ scenario, composite, + notes, error }) for the NEXT proposal round, so the proposer reasons over what + actually failed instead of a static seed. Pass your own producer (e.g. a + trace-analyst over the runDir's traces) to replace it; pass `null` to disable + and keep the static `findings` all the way through. + +##### rawTraceContext? + +> `optional` **rawTraceContext?**: `boolean` + +META-HARNESS mode: instead of the ~400-char distilled findings, feed the + proposer RAW-TRACE FILESYSTEM CONTEXT — the PATHS into the prior generation's + real run traces under `runDir` (per-cell `spans.jsonl` event logs + + `cached-result.json` scores + artifacts) plus a `grep`/`cat`-to-diagnose + instruction — so the coding agent reads the actual failures itself rather than + a pre-summary. Requires a REAL `runDir` (that is where the traces live). + Ignored when `analyzeGeneration` is set explicitly (that wins) or is `null` + (disabled). Equivalent to `analyzeGeneration: rawTraceDistiller()`; this flag + is the one-line enable. Default `false` (the distiller stays the default). + +##### code? + +> `optional` **code?**: [`ImproveCodeOptions`](#improvecodeoptions) + +CODE-surface wiring: name `surface: 'code'`, point at a repo, and the + facade assembles the whole candidate pipeline — an isolated incumbent plus git worktrees + (`gitWorktreeAdapter`) driven by `improvementDriver` with the full agentic + generator (a real coding harness edits each candidate worktree; a `verify` + hook gates candidates before they are ever measured). Ignored when + `opts.generator` is supplied. Required for every code run because a real + repository and base ref are necessary to measure the incumbent. + +##### skills? + +> `optional` **skills?**: [`ImproveSkillsOptions`](#improveskillsoptions) + +SKILLS-surface wiring for real skill-DOCUMENT optimization. Without this, + `surface: 'skills'` optimizes the profile's skills REFS array (file pointers) + — which `skillOptProposer` (a document patcher) cannot meaningfully edit. + Provide the document CONTENT to optimize + a `writeBack` to persist the + shipped winner (the profile ref points at a file the caller owns). This is + what makes skillOpt reachable through improve(). + +##### promotionGate? + +> `optional` **promotionGate?**: `SelfImproveOptions`\<`TScenario`, `TArtifact`\>\[`"gate"`\] + +Custom held-back-exam decision. The string `gate` above controls whether + the exam runs; this callback controls how its evidence decides promotion. + +#### Type Parameters + +##### TScenario + +`TScenario` *extends* `Scenario` + +##### TArtifact + +`TArtifact` + +*** + ### KnowledgeReadinessCheckResult > **KnowledgeReadinessCheckResult** = `boolean` \| \{ `ready`: `boolean`; `summary?`: `string`; `metadata?`: `Record`\<`string`, `unknown`\>; \} @@ -10970,7 +11156,7 @@ MUST map this to `RunRecord.error` rather than recording silent > `const` **CANDIDATE\_TRACE\_TAGS**: `object` -Defined in: [candidate-execution/types.ts:552](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L552) +Defined in: [candidate-execution/types.ts:559](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L559) Protected trace tags that bind a run to one prepared candidate execution. @@ -10998,7 +11184,7 @@ Protected trace tags that bind a run to one prepared candidate execution. > `const` **CANDIDATE\_TRACE\_ENV**: `object` -Defined in: [candidate-execution/types.ts:560](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L560) +Defined in: [candidate-execution/types.ts:567](https://github.com/tangle-network/agent-runtime/blob/main/src/candidate-execution/types.ts#L567) Environment keys used to propagate immutable candidate trace identity. @@ -11205,7 +11391,7 @@ Default Tangle Router base URL used when no env override is set. > `const` **INTELLIGENCE\_WIRE\_VERSION**: `"2026-05-26.v1"` = `'2026-05-26.v1'` -Defined in: [otel-export.ts:556](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L556) +Defined in: [otel-export.ts:659](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L659) Wire version the eval-runs ingest enforces (X-Tangle-Wire-Version + body). @@ -12206,7 +12392,7 @@ Build the starting instruction for a coder agent tasked with implementing a new > **improve**\<`TScenario`, `TArtifact`\>(`profile`, `findings`, `opts`): `Promise`\<[`ImproveResult`](#improveresult)\<`TScenario`, `TArtifact`\>\> -Defined in: [improvement/improve.ts:401](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L401) +Defined in: [improvement/improve.ts:465](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improve.ts#L465) Run the held-out-gated self-improvement loop on ONE profile surface. @@ -12256,9 +12442,9 @@ Optimize the system prompt, default holdout gate: ### improvementDriver() -> **improvementDriver**(`opts`): `SurfaceProposer`\<`AnalystFinding`\> +> **improvementDriver**(`opts`): [`ManagedImprovementDriver`](#managedimprovementdriver) -Defined in: [improvement/improvement-driver.ts:73](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L73) +Defined in: [improvement/improvement-driver.ts:79](https://github.com/tangle-network/agent-runtime/blob/main/src/improvement/improvement-driver.ts#L79) The one reflective/agentic improvement proposer (`SurfaceProposer`): owns the candidate worktree lifecycle and delegates HOW a change is produced to a pluggable `CandidateGenerator`. @@ -12270,7 +12456,7 @@ The one reflective/agentic improvement proposer (`SurfaceProposer`): owns the ca #### Returns -`SurfaceProposer`\<`AnalystFinding`\> +[`ManagedImprovementDriver`](#managedimprovementdriver) *** @@ -12996,7 +13182,7 @@ Injectable catalog loader — overridden in tests. > **createOtelExporter**(`config?`): [`OtelExporter`](#otelexporter) \| `undefined` -Defined in: [otel-export.ts:81](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L81) +Defined in: [otel-export.ts:84](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L84) Create an OTEL exporter. Returns undefined when no endpoint is configured. @@ -13016,7 +13202,7 @@ Create an OTEL exporter. Returns undefined when no endpoint is configured. > **loopEventToOtelSpan**(`event`, `traceId`, `parentSpanId?`): [`OtelSpan`](#otelspan) -Defined in: [otel-export.ts:162](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L162) +Defined in: [otel-export.ts:165](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L165) Convert a LoopTraceEvent into an OtelSpan for export. @@ -13054,11 +13240,43 @@ Convert a LoopTraceEvent into an OtelSpan for export. *** +### buildRuntimeEventOtelSpans() + +> **buildRuntimeEventOtelSpans**(`events`, `traceId`, `parentSpanId?`, `options?`): [`OtelSpan`](#otelspan)[] + +Defined in: [otel-export.ts:261](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L261) + +Convert normalized runtime events into lossless, redacted child spans. + +#### Parameters + +##### events + +readonly [`RuntimeStreamEvent`](#runtimestreamevent)[] + +##### traceId + +`string` + +##### parentSpanId? + +`string` + +##### options? + +[`RuntimeEventOtelOptions`](#runtimeeventoteloptions) = `{}` + +#### Returns + +[`OtelSpan`](#otelspan)[] + +*** + ### buildLoopOtelSpans() > **buildLoopOtelSpans**(`events`, `traceId`, `rootParentSpanId?`): [`OtelSpan`](#otelspan)[] -Defined in: [otel-export.ts:261](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L261) +Defined in: [otel-export.ts:364](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L364) Build a nested, real-duration OTLP span tree for ONE loop run from its full ordered `LoopTraceEvent` stream. Unlike `loopEventToOtelSpan` (one flat, @@ -13099,7 +13317,7 @@ readonly `object`[] > **buildLoopSpanNodes**(`events`): [`LoopSpanNode`](#loopspannode)[] -Defined in: [otel-export.ts:292](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L292) +Defined in: [otel-export.ts:395](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L395) Sink-neutral core behind [buildLoopOtelSpans](#buildloopotelspans): reconstruct the loop → round → branch span tree from one run's ordered `LoopTraceEvent` @@ -13124,7 +13342,7 @@ readonly `object`[] > **exportEvalRuns**(`events`, `config?`): `Promise`\<[`EvalRunsExportResult`](#evalrunsexportresult)\> -Defined in: [otel-export.ts:619](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L619) +Defined in: [otel-export.ts:722](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L722) Ship self-improvement eval-run events to Tangle Intelligence. Unlike the best-effort span exporter, this RESOLVES with the ingest verdict (accepted / diff --git a/docs/api/intelligence.md b/docs/api/intelligence.md index dc6d4ace..7d2c4564 100644 --- a/docs/api/intelligence.md +++ b/docs/api/intelligence.md @@ -1078,7 +1078,7 @@ Intelligence-class spend ceiling. `0` refuses every intelligence spawn; `null` u ### UsageSplit -Defined in: [intelligence/index.ts:120](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L120) +Defined in: [intelligence/index.ts:125](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L125) The per-class cost split carried by every trace and outcome. `off` ⇒ `intelligenceUsd: 0` by construction — there is no intelligence spawn to @@ -1090,7 +1090,7 @@ bill. This is a classification on the trace, NOT a budget-pool split. > **inferenceUsd**: `number` -Defined in: [intelligence/index.ts:122](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L122) +Defined in: [intelligence/index.ts:127](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L127) Base-stream (model) spend in USD. @@ -1098,7 +1098,7 @@ Base-stream (model) spend in USD. > **intelligenceUsd**: `number` -Defined in: [intelligence/index.ts:124](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L124) +Defined in: [intelligence/index.ts:129](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L129) Intelligence-spawn spend in USD. Provably `0` at the OFF tier. @@ -1106,7 +1106,7 @@ Intelligence-spawn spend in USD. Provably `0` at the OFF tier. ### RunRecord -Defined in: [intelligence/index.ts:134](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L134) +Defined in: [intelligence/index.ts:139](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L139) The typed record `withIntelligence` sends per call — serialized through the shipped OTLP builders to the plane's `/v1/otlp` ingest. `input`/`output` are @@ -1120,43 +1120,43 @@ tree under the same `traceId`. > **runId**: `string` -Defined in: [intelligence/index.ts:135](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L135) +Defined in: [intelligence/index.ts:140](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L140) ##### traceId > **traceId**: `string` -Defined in: [intelligence/index.ts:136](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L136) +Defined in: [intelligence/index.ts:141](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L141) ##### project > **project**: `string` -Defined in: [intelligence/index.ts:137](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L137) +Defined in: [intelligence/index.ts:142](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L142) ##### target > **target**: `string` -Defined in: [intelligence/index.ts:138](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L138) +Defined in: [intelligence/index.ts:143](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L143) ##### input > **input**: `unknown` -Defined in: [intelligence/index.ts:139](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L139) +Defined in: [intelligence/index.ts:144](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L144) ##### output > **output**: `unknown` -Defined in: [intelligence/index.ts:140](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L140) +Defined in: [intelligence/index.ts:145](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L145) ##### outcome > **outcome**: `object` -Defined in: [intelligence/index.ts:141](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L141) +Defined in: [intelligence/index.ts:146](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L146) ###### success? @@ -1174,25 +1174,119 @@ Defined in: [intelligence/index.ts:141](https://github.com/tangle-network/agent- > `optional` **model?**: `string` -Defined in: [intelligence/index.ts:146](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L146) +Defined in: [intelligence/index.ts:151](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L151) ##### provider? > `optional` **provider?**: `string` -Defined in: [intelligence/index.ts:147](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L147) +Defined in: [intelligence/index.ts:152](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L152) ##### loopEvents? > `optional` **loopEvents?**: [`LoopTraceEvent`](runtime.md#looptraceevent)[] -Defined in: [intelligence/index.ts:148](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L148) +Defined in: [intelligence/index.ts:153](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L153) + +##### runtimeEvents? + +> `optional` **runtimeEvents?**: [`RuntimeStreamEvent`](index.md#runtimestreamevent)[] + +Defined in: [intelligence/index.ts:154](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L154) + +##### profile? + +> `optional` **profile?**: `AgentProfile` + +Defined in: [intelligence/index.ts:155](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L155) + +##### sessionId? + +> `optional` **sessionId?**: `string` + +Defined in: [intelligence/index.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L156) + +##### harness? + +> `optional` **harness?**: `string` + +Defined in: [intelligence/index.ts:157](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L157) + +##### repository? + +> `optional` **repository?**: `string` + +Defined in: [intelligence/index.ts:158](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L158) + +##### commitSha? + +> `optional` **commitSha?**: `string` + +Defined in: [intelligence/index.ts:159](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L159) + +##### timing? + +> `optional` **timing?**: `object` + +Defined in: [intelligence/index.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L160) + +###### startedAt + +> **startedAt**: `number` + +###### completedAt + +> **completedAt**: `number` + +###### durationMs + +> **durationMs**: `number` + +##### tokens? + +> `optional` **tokens?**: `object` + +Defined in: [intelligence/index.ts:161](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L161) + +###### input + +> **input**: `number` + +###### output + +> **output**: `number` + +###### cachedInput? + +> `optional` **cachedInput?**: `number` + +###### reasoning? + +> `optional` **reasoning?**: `number` + +##### error? + +> `optional` **error?**: `object` + +Defined in: [intelligence/index.ts:167](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L167) + +###### name + +> **name**: `string` + +###### message + +> **message**: `string` + +###### code? + +> `optional` **code?**: `string` *** ### RunReport -Defined in: [intelligence/index.ts:157](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L157) +Defined in: [intelligence/index.ts:176](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L176) What an agent reports (via `applied.record`) to enrich the [RunRecord](#runrecord) sent for its call. All optional — an un-recorded run still sends input/output @@ -1205,49 +1299,119 @@ as pure inference (the base stream). > `optional` **success?**: `boolean` -Defined in: [intelligence/index.ts:158](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L158) +Defined in: [intelligence/index.ts:177](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L177) ##### score? > `optional` **score?**: `number` -Defined in: [intelligence/index.ts:159](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L159) +Defined in: [intelligence/index.ts:178](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L178) ##### usage? > `optional` **usage?**: `Partial`\<[`UsageSplit`](#usagesplit)\> -Defined in: [intelligence/index.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L160) +Defined in: [intelligence/index.ts:179](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L179) ##### costUsd? > `optional` **costUsd?**: `number` -Defined in: [intelligence/index.ts:161](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L161) +Defined in: [intelligence/index.ts:180](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L180) ##### model? > `optional` **model?**: `string` -Defined in: [intelligence/index.ts:162](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L162) +Defined in: [intelligence/index.ts:181](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L181) ##### provider? > `optional` **provider?**: `string` -Defined in: [intelligence/index.ts:163](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L163) +Defined in: [intelligence/index.ts:182](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L182) ##### loopEvents? > `optional` **loopEvents?**: [`LoopTraceEvent`](runtime.md#looptraceevent)[] -Defined in: [intelligence/index.ts:164](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L164) +Defined in: [intelligence/index.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L183) + +##### runtimeEvents? + +> `optional` **runtimeEvents?**: [`RuntimeStreamEvent`](index.md#runtimestreamevent)[] + +Defined in: [intelligence/index.ts:184](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L184) + +##### profile? + +> `optional` **profile?**: `AgentProfile` + +Defined in: [intelligence/index.ts:185](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L185) + +##### sessionId? + +> `optional` **sessionId?**: `string` + +Defined in: [intelligence/index.ts:186](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L186) + +##### harness? + +> `optional` **harness?**: `string` + +Defined in: [intelligence/index.ts:187](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L187) + +##### commitSha? + +> `optional` **commitSha?**: `string` + +Defined in: [intelligence/index.ts:188](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L188) + +##### tokens? + +> `optional` **tokens?**: `object` + +Defined in: [intelligence/index.ts:189](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L189) + +###### input + +> **input**: `number` + +###### output + +> **output**: `number` + +###### cachedInput? + +> `optional` **cachedInput?**: `number` + +###### reasoning? + +> `optional` **reasoning?**: `number` + +##### error? + +> `optional` **error?**: `object` + +Defined in: [intelligence/index.ts:190](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L190) + +###### name + +> **name**: `string` + +###### message + +> **message**: `string` + +###### code? + +> `optional` **code?**: `string` *** ### RepoConfig -Defined in: [intelligence/index.ts:170](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L170) +Defined in: [intelligence/index.ts:196](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L196) Repo coordinates a product may declare for the (later) Gated-PR mode. The Observe slice only records their PRESENCE for `doctor()`; it never touches @@ -1259,25 +1423,25 @@ Repo coordinates a product may declare for the (later) Gated-PR mode. The > **owner**: `string` -Defined in: [intelligence/index.ts:171](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L171) +Defined in: [intelligence/index.ts:197](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L197) ##### name > **name**: `string` -Defined in: [intelligence/index.ts:172](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L172) +Defined in: [intelligence/index.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L198) ##### baseBranch > **baseBranch**: `string` -Defined in: [intelligence/index.ts:173](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L173) +Defined in: [intelligence/index.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L199) *** ### IntelligenceConfig -Defined in: [intelligence/index.ts:179](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L179) +Defined in: [intelligence/index.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L205) Client configuration. `project` + `apiKey` are the Observe minimum; the rest tune effort, endpoint, redaction, and (for `doctor()` readiness) @@ -1293,7 +1457,7 @@ Client configuration. `project` + `apiKey` are the Observe minimum; the > **project**: `string` -Defined in: [intelligence/index.ts:181](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L181) +Defined in: [intelligence/index.ts:207](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L207) Stable project id — the tenant dimension every trace is tagged with. @@ -1301,7 +1465,7 @@ Stable project id — the tenant dimension every trace is tagged with. > `optional` **apiKey?**: `string` -Defined in: [intelligence/index.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L183) +Defined in: [intelligence/index.ts:209](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L209) Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. @@ -1309,7 +1473,7 @@ Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. > `optional` **effort?**: [`EffortTier`](#efforttier) \| \{ `tier`: [`EffortTier`](#efforttier); `overrides?`: `Partial`\<[`EffortSettings`](#effortsettings)\>; \} -Defined in: [intelligence/index.ts:185](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L185) +Defined in: [intelligence/index.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L211) Effort tier (default `'standard'`) plus optional per-field overrides. @@ -1317,7 +1481,7 @@ Effort tier (default `'standard'`) plus optional per-field overrides. > `optional` **baseUrl?**: `string` -Defined in: [intelligence/index.ts:193](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L193) +Defined in: [intelligence/index.ts:219](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L219) The ONE Tangle Intelligence base URL — both the send (OTLP `/v1/otlp`) and receive (`/v1/profiles/:target/composed`) paths derive from it. Reads @@ -1329,7 +1493,7 @@ key the ingest requires); absent a key, export is a no-op. > `optional` **redact?**: `false` \| [`Redactor`](#redactor) -Defined in: [intelligence/index.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L199) +Defined in: [intelligence/index.ts:225](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L225) Redaction hook run over every exported input/output. A function replaces the default scrubber; `false` opts out entirely (raw fidelity, caller has @@ -1339,7 +1503,7 @@ sanitized upstream); omitted ⇒ the built-in `defaultRedactor`. > `optional` **surfaces?**: `string`[] -Defined in: [intelligence/index.ts:201](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L201) +Defined in: [intelligence/index.ts:227](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L227) Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. @@ -1347,7 +1511,7 @@ Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. > `optional` **checks?**: `string`[] -Defined in: [intelligence/index.ts:203](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L203) +Defined in: [intelligence/index.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L229) Verification checks a later PR mode would gate on. Recorded for `doctor()` only. @@ -1355,15 +1519,39 @@ Verification checks a later PR mode would gate on. Recorded for `doctor()` only. > `optional` **repo?**: [`RepoConfig`](#repoconfig) -Defined in: [intelligence/index.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L205) +Defined in: [intelligence/index.ts:231](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L231) Repo access a later PR mode would need. Recorded for `doctor()` only. +##### profile? + +> `optional` **profile?**: `AgentProfile` + +Defined in: [intelligence/index.ts:233](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L233) + +Full canonical profile used for this agent. Exported redacted with a stable hash. + +##### commitSha? + +> `optional` **commitSha?**: `string` + +Defined in: [intelligence/index.ts:235](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L235) + +Commit that produced the running agent, when known. + +##### runtimeTelemetry? + +> `optional` **runtimeTelemetry?**: [`RuntimeTelemetryOptions`](index.md#runtimetelemetryoptions) + +Defined in: [intelligence/index.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L237) + +Runtime-event payload policy. Tool inputs/results remain off unless explicitly enabled. + *** ### TraceMeta -Defined in: [intelligence/index.ts:209](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L209) +Defined in: [intelligence/index.ts:241](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L241) Metadata describing one traced run. `runId`/`traceId` default to fresh ids. @@ -1373,7 +1561,7 @@ Metadata describing one traced run. `runId`/`traceId` default to fresh ids. > `optional` **input?**: `unknown` -Defined in: [intelligence/index.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L211) +Defined in: [intelligence/index.ts:243](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L243) The run's input — exported through the redactor. @@ -1381,7 +1569,7 @@ The run's input — exported through the redactor. > `optional` **runId?**: `string` -Defined in: [intelligence/index.ts:213](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L213) +Defined in: [intelligence/index.ts:245](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L245) Stable run id. Defaults to a fresh id. @@ -1389,7 +1577,7 @@ Stable run id. Defaults to a fresh id. > `optional` **traceId?**: `string` -Defined in: [intelligence/index.ts:215](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L215) +Defined in: [intelligence/index.ts:247](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L247) 32-hex trace id. Defaults to a fresh id. @@ -1397,7 +1585,7 @@ Defined in: [intelligence/index.ts:215](https://github.com/tangle-network/agent- > `optional` **model?**: `string` -Defined in: [intelligence/index.ts:217](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L217) +Defined in: [intelligence/index.ts:249](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L249) Model id, when known — stamped on the span. @@ -1405,7 +1593,7 @@ Model id, when known — stamped on the span. > `optional` **provider?**: `string` -Defined in: [intelligence/index.ts:219](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L219) +Defined in: [intelligence/index.ts:251](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L251) Provider name, when known — stamped on the span. @@ -1413,7 +1601,7 @@ Provider name, when known — stamped on the span. > `optional` **labels?**: `Record`\<`string`, `string` \| `number` \| `boolean`\> -Defined in: [intelligence/index.ts:221](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L221) +Defined in: [intelligence/index.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L253) Arbitrary extra labels (string/number/boolean) stamped on the span. @@ -1421,7 +1609,7 @@ Arbitrary extra labels (string/number/boolean) stamped on the span. ### TraceHandle -Defined in: [intelligence/index.ts:230](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L230) +Defined in: [intelligence/index.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L262) The trace handle a `traceRun` body records into. `recordOutput` captures the agent's result (redacted on export); `recordOutcome` captures the scored @@ -1434,7 +1622,7 @@ an un-recorded run still exports a span with whatever was set. > **recordOutput**(`output`): `void` -Defined in: [intelligence/index.ts:232](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L232) +Defined in: [intelligence/index.ts:264](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L264) Capture the run's output. Exported through the redactor. @@ -1452,7 +1640,7 @@ Capture the run's output. Exported through the redactor. > **recordOutcome**(`outcome`): `void` -Defined in: [intelligence/index.ts:239](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L239) +Defined in: [intelligence/index.ts:271](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L271) Capture the run's outcome. `usage` defaults to inference-only (`intelligenceUsd: 0`) — the OFF baseline; an intelligence-enabled run @@ -1487,7 +1675,7 @@ treated as pure inference. ### RecordTraceMeta -Defined in: [intelligence/index.ts:248](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L248) +Defined in: [intelligence/index.ts:280](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L280) Metadata for [IntelligenceClient.recordTrace](#recordtrace). @@ -1497,7 +1685,7 @@ Metadata for [IntelligenceClient.recordTrace](#recordtrace). > `optional` **traceId?**: `string` -Defined in: [intelligence/index.ts:250](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L250) +Defined in: [intelligence/index.ts:282](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L282) 32-hex trace id to anchor every span to. Defaults to a fresh id. @@ -1505,7 +1693,7 @@ Defined in: [intelligence/index.ts:250](https://github.com/tangle-network/agent- > `optional` **rootParentSpanId?**: `string` -Defined in: [intelligence/index.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L253) +Defined in: [intelligence/index.ts:285](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L285) Span id of an enclosing span the loop root should parent under (e.g. a `traceRun` span). Omitted ⇒ the loop root is the trace root. @@ -1514,7 +1702,7 @@ Span id of an enclosing span the loop root should parent under (e.g. a ### TraceOutcome -Defined in: [intelligence/index.ts:258](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L258) +Defined in: [intelligence/index.ts:290](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L290) The resolved outcome of one traced run, surfaced on the export span and available to the caller for downstream billing assertions. @@ -1525,25 +1713,25 @@ The resolved outcome of one traced run, surfaced on the export span and > **runId**: `string` -Defined in: [intelligence/index.ts:259](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L259) +Defined in: [intelligence/index.ts:291](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L291) ##### traceId > **traceId**: `string` -Defined in: [intelligence/index.ts:260](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L260) +Defined in: [intelligence/index.ts:292](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L292) ##### project > **project**: `string` -Defined in: [intelligence/index.ts:261](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L261) +Defined in: [intelligence/index.ts:293](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L293) ##### effort > **effort**: [`EffortSettings`](#effortsettings) -Defined in: [intelligence/index.ts:263](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L263) +Defined in: [intelligence/index.ts:295](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L295) The resolved effort settings this run executed under. @@ -1551,7 +1739,7 @@ The resolved effort settings this run executed under. > **intelligenceOff**: `boolean` -Defined in: [intelligence/index.ts:265](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L265) +Defined in: [intelligence/index.ts:297](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L297) True when this run ran as pure passthrough (the OFF floor). @@ -1559,19 +1747,19 @@ True when this run ran as pure passthrough (the OFF floor). > `optional` **success?**: `boolean` -Defined in: [intelligence/index.ts:266](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L266) +Defined in: [intelligence/index.ts:298](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L298) ##### score? > `optional` **score?**: `number` -Defined in: [intelligence/index.ts:267](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L267) +Defined in: [intelligence/index.ts:299](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L299) ##### usage > **usage**: [`UsageSplit`](#usagesplit) -Defined in: [intelligence/index.ts:269](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L269) +Defined in: [intelligence/index.ts:301](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L301) Per-class billing split. `intelligenceUsd` is `0` at the OFF tier. @@ -1579,7 +1767,7 @@ Per-class billing split. `intelligenceUsd` is `0` at the OFF tier. ### IntelligenceClient -Defined in: [intelligence/index.ts:273](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L273) +Defined in: [intelligence/index.ts:305](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L305) The Observe-mode Intelligence client. @@ -1589,7 +1777,7 @@ The Observe-mode Intelligence client. > `readonly` **project**: `string` -Defined in: [intelligence/index.ts:275](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L275) +Defined in: [intelligence/index.ts:307](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L307) The resolved project id. @@ -1597,7 +1785,7 @@ The resolved project id. > `readonly` **effort**: [`EffortSettings`](#effortsettings) -Defined in: [intelligence/index.ts:277](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L277) +Defined in: [intelligence/index.ts:309](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L309) The resolved effort settings. @@ -1607,7 +1795,7 @@ The resolved effort settings. > **traceRun**\<`T`\>(`meta`, `fn`): `Promise`\<`T`\> -Defined in: [intelligence/index.ts:283](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L283) +Defined in: [intelligence/index.ts:315](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L315) Run `fn` under a trace, export one span best-effort, and return whatever `fn` returns. Telemetry-export failures are swallowed; an error THROWN by @@ -1637,7 +1825,7 @@ Run `fn` under a trace, export one span best-effort, and return whatever > **recordTrace**(`events`, `meta?`): `string` -Defined in: [intelligence/index.ts:293](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L293) +Defined in: [intelligence/index.ts:325](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L325) Export a run's full loop topology — the ordered `LoopTraceEvent` stream a `runLoop`/`Supervisor` run emits — as a nested OTLP span tree (loop → round → @@ -1665,7 +1853,7 @@ readonly [`LoopTraceEvent`](runtime.md#looptraceevent)[] > **exportRunRecord**(`record`): `string` -Defined in: [intelligence/index.ts:301](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L301) +Defined in: [intelligence/index.ts:333](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L333) Send one typed [RunRecord](#runrecord) — the run's flat span (input/output/outcome/ usage/model/provider, redacted) plus, when `loopEvents` are present, the @@ -1687,7 +1875,7 @@ Best-effort: export failures are swallowed. Returns the record's `traceId`. > **freshRunId**(): `string` -Defined in: [intelligence/index.ts:303](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L303) +Defined in: [intelligence/index.ts:335](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L335) Mint a fresh run id (`run-`). @@ -1699,7 +1887,7 @@ Mint a fresh run id (`run-`). > **freshTraceId**(): `string` -Defined in: [intelligence/index.ts:305](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L305) +Defined in: [intelligence/index.ts:337](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L337) Mint a fresh 32-hex trace id. @@ -1711,7 +1899,7 @@ Mint a fresh 32-hex trace id. > **doctor**(): [`DoctorReport`](#doctorreport) -Defined in: [intelligence/index.ts:311](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L311) +Defined in: [intelligence/index.ts:343](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L343) Network-free readiness report: which adoption modes are reachable given this config. Observe is always reachable; Recommend needs outcomes; PR @@ -1725,7 +1913,7 @@ needs checks + surfaces + repo. > **flush**(): `Promise`\<`void`\> -Defined in: [intelligence/index.ts:313](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L313) +Defined in: [intelligence/index.ts:345](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L345) Flush any pending export spans. Best-effort; resolves even if export fails. @@ -1737,7 +1925,7 @@ Flush any pending export spans. Best-effort; resolves even if export fails. ### ModeReadiness -Defined in: [intelligence/index.ts:317](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L317) +Defined in: [intelligence/index.ts:349](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L349) One mode's readiness verdict. @@ -1747,13 +1935,13 @@ One mode's readiness verdict. > **ready**: `boolean` -Defined in: [intelligence/index.ts:318](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L318) +Defined in: [intelligence/index.ts:350](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L350) ##### missing > **missing**: `string`[] -Defined in: [intelligence/index.ts:320](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L320) +Defined in: [intelligence/index.ts:352](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L352) Inputs this mode still needs, when not ready. Empty when ready. @@ -1761,7 +1949,7 @@ Inputs this mode still needs, when not ready. Empty when ready. ### DoctorReport -Defined in: [intelligence/index.ts:324](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L324) +Defined in: [intelligence/index.ts:356](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L356) The `doctor()` readiness report — Mode-readiness without any network call. @@ -1771,19 +1959,19 @@ The `doctor()` readiness report — Mode-readiness without any network call. > **project**: `string` -Defined in: [intelligence/index.ts:325](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L325) +Defined in: [intelligence/index.ts:357](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L357) ##### effort > **effort**: [`EffortSettings`](#effortsettings) -Defined in: [intelligence/index.ts:326](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L326) +Defined in: [intelligence/index.ts:358](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L358) ##### exportConfigured > **exportConfigured**: `boolean` -Defined in: [intelligence/index.ts:328](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L328) +Defined in: [intelligence/index.ts:360](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L360) True when an OTLP endpoint is configured (export will actually ship). @@ -1791,7 +1979,7 @@ True when an OTLP endpoint is configured (export will actually ship). > **modes**: `object` -Defined in: [intelligence/index.ts:329](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L329) +Defined in: [intelligence/index.ts:361](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L361) ###### observe @@ -2026,11 +2214,25 @@ What the hook hands the agent each run. Additive over the prompt-only #### Properties +##### runId + +> **runId**: `string` + +Defined in: [intelligence/with-intelligence.ts:55](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L55) + +Stable ids shared by the run span and every nested runtime/loop span. + +##### traceId + +> **traceId**: `string` + +Defined in: [intelligence/with-intelligence.ts:56](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L56) + ##### certified > **certified**: [`CertifiedProfile`](#certifiedprofile) \| `null` -Defined in: [intelligence/with-intelligence.ts:56](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L56) +Defined in: [intelligence/with-intelligence.ts:59](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L59) The certified profile in effect (null when none promoted / pull failed — fail-closed: the agent runs on its base surface). @@ -2039,7 +2241,7 @@ The certified profile in effect (null when none promoted / pull failed — > **proposals**: [`ProposedProfileDiff`](#proposedprofilediff)[] -Defined in: [intelligence/with-intelligence.ts:62](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L62) +Defined in: [intelligence/with-intelligence.ts:65](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L65) The promoted, gate-certified profile diffs — surfaced for a human or the gated `improve()` loop. NEVER auto-applied by this hook. Empty when none. @@ -2050,7 +2252,7 @@ The promoted, gate-certified profile diffs — surfaced for a human or the > **composePrompt**(`base`): `string` -Defined in: [intelligence/with-intelligence.ts:59](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L59) +Defined in: [intelligence/with-intelligence.ts:62](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L62) Fold the certified prompt surface into a base system prompt (the promoted prompt). The consumer opts in by calling it. @@ -2069,7 +2271,7 @@ Fold the certified prompt surface into a base system prompt (the promoted > **applyProfile**(`base`): `AgentProfile` -Defined in: [intelligence/with-intelligence.ts:66](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L66) +Defined in: [intelligence/with-intelligence.ts:69](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L69) Fold every proposal into `base` via `applyAgentProfileDiff`, in promotion order, and return the result. The caller invokes this EXPLICITLY (it is the @@ -2089,7 +2291,7 @@ Fold every proposal into `base` via `applyAgentProfileDiff`, in promotion > **record**(`report`): `void` -Defined in: [intelligence/with-intelligence.ts:70](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L70) +Defined in: [intelligence/with-intelligence.ts:73](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L73) Enrich the [RunRecord](#runrecord) sent for this call — outcome, usage split, model/provider, and the loop event stream. Optional; an un-recorded run @@ -2109,7 +2311,7 @@ Enrich the [RunRecord](#runrecord) sent for this call — outcome, usage split, ### IntelligenceHookConfig -Defined in: [intelligence/with-intelligence.ts:80](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L80) +Defined in: [intelligence/with-intelligence.ts:83](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L83) `withIntelligence` config = the Observe config plus the pull target, refresh cadence, and a proposals callback. One base URL (`baseUrl` / @@ -2125,7 +2327,7 @@ Defined in: [intelligence/with-intelligence.ts:80](https://github.com/tangle-net > **project**: `string` -Defined in: [intelligence/index.ts:181](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L181) +Defined in: [intelligence/index.ts:207](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L207) Stable project id — the tenant dimension every trace is tagged with. @@ -2137,7 +2339,7 @@ Stable project id — the tenant dimension every trace is tagged with. > `optional` **apiKey?**: `string` -Defined in: [intelligence/index.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L183) +Defined in: [intelligence/index.ts:209](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L209) Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. @@ -2149,7 +2351,7 @@ Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. > `optional` **effort?**: [`EffortTier`](#efforttier) \| \{ `tier`: [`EffortTier`](#efforttier); `overrides?`: `Partial`\<[`EffortSettings`](#effortsettings)\>; \} -Defined in: [intelligence/index.ts:185](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L185) +Defined in: [intelligence/index.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L211) Effort tier (default `'standard'`) plus optional per-field overrides. @@ -2161,7 +2363,7 @@ Effort tier (default `'standard'`) plus optional per-field overrides. > `optional` **baseUrl?**: `string` -Defined in: [intelligence/index.ts:193](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L193) +Defined in: [intelligence/index.ts:219](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L219) The ONE Tangle Intelligence base URL — both the send (OTLP `/v1/otlp`) and receive (`/v1/profiles/:target/composed`) paths derive from it. Reads @@ -2177,7 +2379,7 @@ key the ingest requires); absent a key, export is a no-op. > `optional` **redact?**: `false` \| [`Redactor`](#redactor) -Defined in: [intelligence/index.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L199) +Defined in: [intelligence/index.ts:225](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L225) Redaction hook run over every exported input/output. A function replaces the default scrubber; `false` opts out entirely (raw fidelity, caller has @@ -2191,7 +2393,7 @@ sanitized upstream); omitted ⇒ the built-in `defaultRedactor`. > `optional` **surfaces?**: `string`[] -Defined in: [intelligence/index.ts:201](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L201) +Defined in: [intelligence/index.ts:227](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L227) Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. @@ -2203,7 +2405,7 @@ Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. > `optional` **checks?**: `string`[] -Defined in: [intelligence/index.ts:203](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L203) +Defined in: [intelligence/index.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L229) Verification checks a later PR mode would gate on. Recorded for `doctor()` only. @@ -2215,7 +2417,7 @@ Verification checks a later PR mode would gate on. Recorded for `doctor()` only. > `optional` **repo?**: [`RepoConfig`](#repoconfig) -Defined in: [intelligence/index.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L205) +Defined in: [intelligence/index.ts:231](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L231) Repo access a later PR mode would need. Recorded for `doctor()` only. @@ -2223,11 +2425,47 @@ Repo access a later PR mode would need. Recorded for `doctor()` only. [`IntelligenceConfig`](#intelligenceconfig).[`repo`](#repo) +##### profile? + +> `optional` **profile?**: `AgentProfile` + +Defined in: [intelligence/index.ts:233](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L233) + +Full canonical profile used for this agent. Exported redacted with a stable hash. + +###### Inherited from + +[`IntelligenceConfig`](#intelligenceconfig).[`profile`](#profile-2) + +##### commitSha? + +> `optional` **commitSha?**: `string` + +Defined in: [intelligence/index.ts:235](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L235) + +Commit that produced the running agent, when known. + +###### Inherited from + +[`IntelligenceConfig`](#intelligenceconfig).[`commitSha`](#commitsha-2) + +##### runtimeTelemetry? + +> `optional` **runtimeTelemetry?**: [`RuntimeTelemetryOptions`](index.md#runtimetelemetryoptions) + +Defined in: [intelligence/index.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L237) + +Runtime-event payload policy. Tool inputs/results remain off unless explicitly enabled. + +###### Inherited from + +[`IntelligenceConfig`](#intelligenceconfig).[`runtimeTelemetry`](#runtimetelemetry) + ##### target? > `optional` **target?**: `string` -Defined in: [intelligence/with-intelligence.ts:82](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L82) +Defined in: [intelligence/with-intelligence.ts:85](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L85) Pull target. Defaults to `project`. @@ -2235,7 +2473,7 @@ Pull target. Defaults to `project`. > `optional` **refreshMs?**: `number` -Defined in: [intelligence/with-intelligence.ts:84](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L84) +Defined in: [intelligence/with-intelligence.ts:87](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L87) Min interval between certified-profile pulls. Default 5m. @@ -2243,7 +2481,7 @@ Min interval between certified-profile pulls. Default 5m. > `optional` **timeoutMs?**: `number` -Defined in: [intelligence/with-intelligence.ts:86](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L86) +Defined in: [intelligence/with-intelligence.ts:89](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L89) Per-pull timeout in ms (fail-closed on a hung plane). Default 10000. @@ -2251,7 +2489,7 @@ Per-pull timeout in ms (fail-closed on a hung plane). Default 10000. > `optional` **fetchImpl?**: (`input`, `init?`) => `Promise`\<`Response`\> -Defined in: [intelligence/with-intelligence.ts:88](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L88) +Defined in: [intelligence/with-intelligence.ts:91](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L91) fetch impl for the pull (tests). Defaults to global fetch. @@ -2273,7 +2511,7 @@ fetch impl for the pull (tests). Defaults to global fetch. > `optional` **onProposals?**: (`proposals`) => `void` -Defined in: [intelligence/with-intelligence.ts:91](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L91) +Defined in: [intelligence/with-intelligence.ts:94](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L94) Notified when a refresh delivers a NEW set of promoted proposals (by provenance content hash). Surfaces diffs without auto-applying them. @@ -2416,7 +2654,7 @@ Per-field overrides applied on top of a tier preset. Any subset of the > **UsageClass** = `"inference"` \| `"intelligence"` -Defined in: [intelligence/index.ts:113](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L113) +Defined in: [intelligence/index.ts:118](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L118) Usage class for billing. Base-stream tokens bill `'inference'`; every intelligence spawn (analyst, corpus, loop) bills `'intelligence'`. The @@ -2449,7 +2687,7 @@ A redactor maps an arbitrary trace value to a safe-to-export value. Pure; > **IntelligenceAgent**\<`I`, `O`\> = (`input`, `applied`) => `Promise`\<`O`\> -Defined in: [intelligence/with-intelligence.ts:75](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L75) +Defined in: [intelligence/with-intelligence.ts:78](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L78) An agent wrapped by [withIntelligence](#withintelligence): receives the input plus the intelligence delivered for this run. @@ -2484,7 +2722,7 @@ An agent wrapped by [withIntelligence](#withintelligence): receives the input pl > **IntelligenceWrapped**\<`I`, `O`\> = (`input`) => `Promise`\<`O`\> & `object` -Defined in: [intelligence/with-intelligence.ts:96](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L96) +Defined in: [intelligence/with-intelligence.ts:99](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L99) The wrapped agent — same `(input) => Promise` shape, plus a manual `refresh()` and a `proposals()` accessor for the currently-promoted diffs. @@ -2507,6 +2745,16 @@ The wrapped agent — same `(input) => Promise` shape, plus a manual [`ProposedProfileDiff`](#proposedprofilediff)[] +##### flush() + +> **flush**(): `Promise`\<`void`\> + +Flush buffered trace spans before a short-lived process exits. + +###### Returns + +`Promise`\<`void`\> + #### Type Parameters ##### I @@ -2764,7 +3012,7 @@ compile to `withAnalyst: true`, the tier's `fanout`, and `withLoops: true`. > **createIntelligenceClient**(`config`): [`IntelligenceClient`](#intelligenceclient) -Defined in: [intelligence/index.ts:387](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L387) +Defined in: [intelligence/index.ts:415](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L415) Create an Observe-mode Intelligence client. Resolves effort, the base URL, and the redactor up front; the exporter is built lazily and is `undefined` when no @@ -2902,7 +3150,7 @@ Lower a plane `CertifiedProfile` straight into a `ResolvedSurface` via > **withIntelligence**\<`I`, `O`\>(`agent`, `config`): [`IntelligenceWrapped`](#intelligencewrapped)\<`I`, `O`\> -Defined in: [intelligence/with-intelligence.ts:110](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L110) +Defined in: [intelligence/with-intelligence.ts:169](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/with-intelligence.ts#L169) Wrap an agent so it (a) RECEIVES the tenant's certified profile — the prompt surface to fold and the promoted profile diffs as proposals — and (b) SENDS a diff --git a/docs/api/primitive-catalog.md b/docs/api/primitive-catalog.md index a51e9295..58e57a94 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.91.0` and `@tangle-network/agent-eval@0.108.1` 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.91.0` and `@tangle-network/agent-eval@0.113.0` 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 @@ -15,7 +15,7 @@ Every subpath this package declares in `package.json` `exports`. Reach for these ### Root — task lifecycle, conversation, RSI verbs, observability -Import from `@tangle-network/agent-runtime` — 317 exports. +Import from `@tangle-network/agent-runtime` — 323 exports. | Symbol | Kind | Summary | |---|---|---| @@ -26,6 +26,7 @@ Import from `@tangle-network/agent-runtime` — 317 exports. | `buildForwardHeaders` | function | Build the headers to emit on an outbound participant call, given the | | `buildLoopOtelSpans` | function | Build a nested, real-duration OTLP span tree for ONE loop run from its full | | `buildLoopSpanNodes` | function | Sink-neutral core behind {@link buildLoopOtelSpans}: reconstruct the | +| `buildRuntimeEventOtelSpans` | function | Convert normalized runtime events into lossless, redacted child spans. | | `candidateExecutionClaim` | function | Extract the complete durable claim from a prepared execution. | | `cleanModelId` | function | Trim a candidate model id; `undefined` for non-strings and blanks. | | `commandVerifier` | function | A `Verifier` that runs a command in the worktree: exit 0 ⇒ ok, any other | @@ -204,7 +205,7 @@ Import from `@tangle-network/agent-runtime` — 317 exports. | `ToolLoopStopReason` | type | Why the loop stopped. `completed` = model finished naturally; `stuck-loop` = | | `Verifier` | type | Verifies the edited worktree. Sync or async; throws only on a setup fault | -**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AgentAdapter`, `AgentBackendContext`, `AgentBackendInput`, `AgentCandidateContainerPort`, `AgentCandidateExecutionAttemptRef`, `AgentCandidateExecutionPorts`, `AgentCandidateExecutorProfileFile`, `AgentCandidateExecutorWorkspaceFile`, `AgentCandidateExecutorWorkspaceInput`, `AgentCandidateMemoryPort`, `AgentCandidateMemoryResetResult`, `AgentCandidateModelPort`, `AgentCandidateProtectedModelActivation`, `AgentCandidateProtectedModelReservation`, `AgentCandidateProtectedModelSettlement`, `AgentCandidateProtectedRunCapture`, `AgentCandidateTaskExecution`, `AgentCandidateVerificationPorts`, `AgentExecutionBackend`, `AgenticGeneratorOptions`, `AgentKnowledgeProvider`, `AgentKnowledgeReadinessCheckOptions`, `AgentTaskContext`, `AgentTaskRunResult`, `AgentTaskSpec`, `BackendCallPolicy`, `CanonicalCandidateDocument`, `ChatTurnHooks`, `ChatTurnResult`, `ControlBudget`, `ControlEvalResult`, `ControlRunResult`, `ControlStep`, `Conversation`, `ConversationDriveState`, `ConversationJournal`, `ConversationParticipant`, `ConversationPolicy`, `ConversationResult`, `ConversationTurn`, `CreateProtectedAgentCandidateModelPortOptions`, `D1StmtLike`, `DataAcquisitionPlan`, `DelegatedLoopResult`, `DisposePreparedAgentCandidateOptions`, `EvalRunEvent`, `EvalRunGeneration`, `EvalRunsExportConfig`, `EvalRunsExportResult`, `ExecutePreparedAgentCandidateOptions`, `FileAgentCandidateExecutionClaimStoreOptions`, `HaltContext`, `HaltSignal`, `ImprovementDriverOptions`, `ImproveOptions`, `ImproveResult`, `KnowledgeImprovementJobMeasurement`, `KnowledgeImprovementJobResult`, `KnowledgeReadinessCheckInput`, `KnowledgeReadinessReport`, `KnowledgeRequirement`, `LoopRunnerCliArgs`, `LoopRunnerCliResult`, `OtelAttribute`, `OtelExporter`, `OtelSpan`, `PersonaConversationResult`, `PrepareAgentCandidateExecutionOptions`, `PreparedAgentCandidateExecution`, `PreparedAgentCandidateInstruction`, `PreparedAgentCandidateLaunch`, `PreparedAgentCandidateTrace`, `RecoverExpiredAgentCandidateOptions`, `ResearchLoopResult`, `ResearchLoopRunnerOptions`, `ResolveAgentBackendOptions`, `ResolvedAgentCandidateContainer`, `ResolvedChatModel`, `RunChatTurnInput`, `RunConversationOptions`, `RunDelegatedLoopOptions`, `RunKnowledgeImprovementJobOptions`, `RunPersonaConfig`, `RunPersonaConversationOptions`, `RuntimeDecisionEvidenceRef`, `RuntimeDecisionPoint`, `RuntimeEventCollector`, `RuntimeHookContext`, `RuntimeHookErrorContext`, `RuntimeHookEvent`, `RuntimeRunHandle`, `RuntimeRunPersistenceAdapter`, `RuntimeRunRow`, `RuntimeSessionStore`, `RuntimeStreamEventCollector`, `RuntimeTelemetryOptions`, `RunToolLoopOptions`, `SanitizedKnowledgeReadinessReport`, `StreamToolLoopOptions`, `SupervisedKnowledgeUpdateInput`, `SupervisedKnowledgeUpdateOptions`, `SupervisedKnowledgeUpdateResult`, `ToolLoopResult`, `VerifiedAgentCandidate`, `VetoedFact`, `WorktreeLoopRunnerOptions`, `AgentCandidateModelGrantActivateInput`, `AgentCandidateModelGrantReserveInput`, `AgentCandidateModelGrantSettleInput`, `AgentCandidateOutputPurpose`, `AgentCandidateRetryRejection`, `AgentCandidateRunFinalization`, `AgentRuntimeEvent`, `AgentRuntimeEventSink`, `AgentTaskStatus`, `AuthSource`, `ControlDecision`, `ConversationStreamEvent`, `DelegatedLoopMode`, `DelegatedLoopRegistry`, `DelegatedLoopRunner`, `ForwardHeaderName`, `HaltPredicate`, `HaltReason`, `KnowledgeReadinessCheck`, `KnowledgeReadinessCheckResult`, `RuntimeDecisionKind`, `RuntimeHookTarget`, `RuntimeStreamEvent`, `StreamToolLoopYield`, `SupervisedKnowledgeUpdater`, `ToolLoopEvent`, `TurnOrder`. +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AgentAdapter`, `AgentBackendContext`, `AgentBackendInput`, `AgentCandidateBenchmarkGraderIdentity`, `AgentCandidateContainerPort`, `AgentCandidateExecutionAttemptRef`, `AgentCandidateExecutionPorts`, `AgentCandidateExecutorProfileFile`, `AgentCandidateExecutorWorkspaceFile`, `AgentCandidateExecutorWorkspaceInput`, `AgentCandidateMemoryPort`, `AgentCandidateMemoryResetResult`, `AgentCandidateModelPort`, `AgentCandidateProtectedModelActivation`, `AgentCandidateProtectedModelReservation`, `AgentCandidateProtectedModelSettlement`, `AgentCandidateProtectedRunCapture`, `AgentCandidateTaskExecution`, `AgentCandidateVerificationPorts`, `AgentExecutionBackend`, `AgenticGeneratorOptions`, `AgentKnowledgeProvider`, `AgentKnowledgeReadinessCheckOptions`, `AgentTaskContext`, `AgentTaskRunResult`, `AgentTaskSpec`, `BackendCallPolicy`, `CanonicalCandidateDocument`, `ChatTurnHooks`, `ChatTurnResult`, `ControlBudget`, `ControlEvalResult`, `ControlRunResult`, `ControlStep`, `Conversation`, `ConversationDriveState`, `ConversationJournal`, `ConversationParticipant`, `ConversationPolicy`, `ConversationResult`, `ConversationTurn`, `CreateProtectedAgentCandidateModelPortOptions`, `D1StmtLike`, `DataAcquisitionPlan`, `DelegatedLoopResult`, `DisposePreparedAgentCandidateOptions`, `EvalRunEvent`, `EvalRunGeneration`, `EvalRunsExportConfig`, `EvalRunsExportResult`, `ExecutePreparedAgentCandidateOptions`, `FileAgentCandidateExecutionClaimStoreOptions`, `HaltContext`, `HaltSignal`, `ImproveCodeOptions`, `ImprovementDriverOptions`, `ImproveResult`, `ImproveSkillsOptions`, `KnowledgeImprovementJobMeasurement`, `KnowledgeImprovementJobResult`, `KnowledgeReadinessCheckInput`, `KnowledgeReadinessReport`, `KnowledgeRequirement`, `LoopRunnerCliArgs`, `LoopRunnerCliResult`, `ManagedImprovementDriver`, `OtelAttribute`, `OtelExporter`, `OtelSpan`, `PersonaConversationResult`, `PrepareAgentCandidateExecutionOptions`, `PreparedAgentCandidateExecution`, `PreparedAgentCandidateInstruction`, `PreparedAgentCandidateLaunch`, `PreparedAgentCandidateTrace`, `RecoverExpiredAgentCandidateOptions`, `ResearchLoopResult`, `ResearchLoopRunnerOptions`, `ResolveAgentBackendOptions`, `ResolvedAgentCandidateContainer`, `ResolvedChatModel`, `RunChatTurnInput`, `RunConversationOptions`, `RunDelegatedLoopOptions`, `RunKnowledgeImprovementJobOptions`, `RunPersonaConfig`, `RunPersonaConversationOptions`, `RuntimeDecisionEvidenceRef`, `RuntimeDecisionPoint`, `RuntimeEventCollector`, `RuntimeEventOtelOptions`, `RuntimeHookContext`, `RuntimeHookErrorContext`, `RuntimeHookEvent`, `RuntimeRunHandle`, `RuntimeRunPersistenceAdapter`, `RuntimeRunRow`, `RuntimeSessionStore`, `RuntimeStreamEventCollector`, `RuntimeTelemetryOptions`, `RunToolLoopOptions`, `SanitizedKnowledgeReadinessReport`, `StreamToolLoopOptions`, `SupervisedKnowledgeUpdateInput`, `SupervisedKnowledgeUpdateOptions`, `SupervisedKnowledgeUpdateResult`, `ToolLoopResult`, `VerifiedAgentCandidate`, `VetoedFact`, `WorktreeLoopRunnerOptions`, `AgentCandidateModelGrantActivateInput`, `AgentCandidateModelGrantReserveInput`, `AgentCandidateModelGrantSettleInput`, `AgentCandidateOutputPurpose`, `AgentCandidateRetryRejection`, `AgentCandidateRunFinalization`, `AgentRuntimeEvent`, `AgentRuntimeEventSink`, `AgentTaskStatus`, `AuthSource`, `ControlDecision`, `ConversationStreamEvent`, `DelegatedLoopMode`, `DelegatedLoopRegistry`, `DelegatedLoopRunner`, `ForwardHeaderName`, `HaltPredicate`, `HaltReason`, `ImproveOptions`, `KnowledgeReadinessCheck`, `KnowledgeReadinessCheckResult`, `RuntimeDecisionKind`, `RuntimeHookTarget`, `RuntimeStreamEvent`, `StreamToolLoopYield`, `SupervisedKnowledgeUpdater`, `ToolLoopEvent`, `TurnOrder`. ### Vertical agent — manifest + improvement adapter @@ -855,6 +856,58 @@ Import from `@tangle-network/agent-runtime/platform` — 20 exports. **Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AuthorizeUrlOptions`, `CatalogResult`, `ConnectionHealth`, `ConnectionHealthResult`, `ExchangeCodeResult`, `ExecInput`, `MintTokenInput`, `MintTokenResult`, `PlatformHubStatus`, `StartAuthInput`, `StartAuthResult`. +### Candidate execution — immutable prepare, run, grade, and receipt + +Import from `@tangle-network/agent-runtime/candidate-execution` — 78 exports. + +| Symbol | Kind | Summary | +|---|---|---| +| `candidateExecutionClaim` | function | Extract the complete durable claim from a prepared execution. | +| `createProtectedAgentCandidateModelPort` | function | Bind a protected model-grant service to the immutable candidate runtime. | +| `disposePreparedAgentCandidateExecution` | function | Revoke reservations held by a prepared candidate that will not be executed. | +| `executePreparedAgentCandidate` | function | Executes and finalizes one durably claimed candidate without exposing an unproven result. | +| `persistCandidateOutputArtifact` | function | Persist evaluator evidence, read it back, and bind the returned locator to the exact bytes. | +| `prepareAgentCandidateExecution` | function | Materializes a verified candidate into one immutable evaluator-owned execution plan. | +| `recoverExpiredAgentCandidateExecution` | function | Close an expired crashed attempt from persisted non-secret handles, then record failure. | +| `verifyAgentCandidateBundle` | function | Verifies every digest, resource, workspace, and Git object in a candidate bundle. | +| `CANDIDATE_TRACE_ENV` | const | Environment keys used to propagate immutable candidate trace identity. | +| `CANDIDATE_TRACE_TAGS` | const | Protected trace tags that bind a run to one prepared candidate execution. | +| `FileAgentCandidateExecutionClaimStore` | class | Cross-process lifecycle implemented as fsynced, create-if-absent records. | +| `InMemoryAgentCandidateExecutionClaimStore` | class | Single-process lifecycle implementation. | +| `AgentCandidateArtifactPort` | interface | Reads one content-addressed object from the closed S3/IPFS locator set. | +| `AgentCandidateBenchmarkGraderPort` | interface | Evaluator-owned executable grader, pinned by immutable implementation bytes. | +| `AgentCandidateExecutionAttemptRecord` | interface | Persisted state available to a fresh trusted recovery worker after a crash. | +| `AgentCandidateExecutionClaim` | interface | Immutable signed identity stored for one execution attempt. | +| `AgentCandidateExecutionClaimStore` | interface | Atomic one-shot store for candidate execution attempts. | +| `AgentCandidateExecutionCleanupHandles` | interface | Non-secret identities a trusted recovery worker needs to close an abandoned attempt. | +| `AgentCandidateExecutionLease` | interface | Secret capability required to finish the acquired attempt. | +| `AgentCandidateExecutionRecoveryEvidence` | interface | Trusted, independently observed closure facts for one expired winning lease. | +| `AgentCandidateExecutionUsage` | interface | Exact fixed-point usage proven by the closed evaluator model ledger. | +| `AgentCandidateExecutorFinalCapture` | interface | Idempotent executor result after process death and trace drain. | +| `AgentCandidateExecutorMemoryCapture` | interface | Raw isolated-memory capture made only after access has been revoked. | +| `AgentCandidateExecutorPort` | interface | Executes one prepared request inside an evaluator-owned isolation boundary. | +| `AgentCandidateExecutorRequest` | interface | One detached request passed to the trusted environment-specific executor. | +| `AgentCandidateExecutorStopRequest` | interface | Opaque process identity used for termination without re-exposing launch credentials. | +| `AgentCandidateExecutorTaskOutcomeCapture` | interface | Raw evaluator capture made only after the candidate process is dead. | +| `AgentCandidateModelGrantClient` | interface | Narrow transport contract for a service that owns scoped model credentials | +| `AgentCandidateOutputArtifactPort` | interface | Durable content-addressed evidence store controlled only by the evaluator. | +| `AgentCandidateProtectedModelCall` | interface | One evaluator-gateway call in the final, revoked model-access ledger. | +| `AgentCandidateRepositoryPort` | interface | Resolves a declared GitHub repository to an already-present local Git object store. | +| `AgentCandidateWorkspacePort` | interface | Materializes an already-verified workspace archive. | +| `VerifiedAgentCandidateTaskOutcome` | interface | Branded task outcome that has survived independent patch and tree verification. | +| `AgentCandidateExecutionClaimResult` | type | Result of atomically claiming one execution attempt. | +| `AgentCandidateExecutionFailureClass` | type | Only the first class is retryable, and only when the closed model ledger has zero calls. | +| `AgentCandidateExecutionFinishResult` | type | Result of atomically recording an attempt's terminal facts. | +| `AgentCandidateExecutionPhase` | type | Monotonic durable phase: the second value means candidate code could have started. | +| `AgentCandidateExecutionPhaseResult` | type | Result of crossing the irreversible candidate-may-run boundary. | +| `AgentCandidateExecutionStageResult` | type | Result of durably staging the one immutable terminal outbox entry. | +| `AgentCandidateExecutionTerminalRecord` | type | Durable terminal record for one acquired execution attempt. | +| `AgentCandidateExecutionTerminalResult` | type | Evaluator-owned terminal facts staged durably before the terminal CAS. | +| `AgentCandidateModelGrantReservation` | type | Secret-free response from the service's reservation endpoint. | +| `AgentCandidateModelLimits` | type | Limits mechanically enforced by the evaluator-owned model gateway. | + +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AgentCandidateBenchmarkGraderIdentity`, `AgentCandidateContainerPort`, `AgentCandidateExecutionAttemptRef`, `AgentCandidateExecutionPorts`, `AgentCandidateExecutorProfileFile`, `AgentCandidateExecutorWorkspaceFile`, `AgentCandidateExecutorWorkspaceInput`, `AgentCandidateMemoryPort`, `AgentCandidateMemoryResetResult`, `AgentCandidateModelPort`, `AgentCandidateProtectedModelActivation`, `AgentCandidateProtectedModelReservation`, `AgentCandidateProtectedModelSettlement`, `AgentCandidateProtectedRunCapture`, `AgentCandidateTaskExecution`, `AgentCandidateVerificationPorts`, `CanonicalCandidateDocument`, `CreateProtectedAgentCandidateModelPortOptions`, `DisposePreparedAgentCandidateOptions`, `ExecutePreparedAgentCandidateOptions`, `FileAgentCandidateExecutionClaimStoreOptions`, `PrepareAgentCandidateExecutionOptions`, `PreparedAgentCandidateExecution`, `PreparedAgentCandidateInstruction`, `PreparedAgentCandidateLaunch`, `PreparedAgentCandidateTrace`, `RecoverExpiredAgentCandidateOptions`, `ResolvedAgentCandidateContainer`, `VerifiedAgentCandidate`, `AgentCandidateModelGrantActivateInput`, `AgentCandidateModelGrantReserveInput`, `AgentCandidateModelGrantSettleInput`, `AgentCandidateOutputPurpose`, `AgentCandidateRetryRejection`, `AgentCandidateRunFinalization`. + ### MCP servers — delegate / coordination / detached-session Import from `@tangle-network/agent-runtime/mcp` — 170 exports. @@ -1033,7 +1086,7 @@ Import from `@tangle-network/agent-eval` — 10 exports. ### STATISTICS — significance, intervals, effect size -Import from `@tangle-network/agent-eval` — 49 exports. +Import from `@tangle-network/agent-eval` — 50 exports. | Symbol | Kind | Summary | |---|---|---| @@ -1072,24 +1125,29 @@ Import from `@tangle-network/agent-eval` — 49 exports. | `ProportionInterval` | interface | A binomial proportion estimate with a confidence interval. | | `RiskDifferenceResult` | interface | A paired binary effect size (treatment rate − control rate) with a CI. | -**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `BootstrapOptions`, `BootstrapResult`, `CorpusAgreementOptions`, `CorpusAgreementPerDimension`, `CorpusAgreementReport`, `CorpusScoreRecord`, `EProcess`, `EProcessOptions`, `EProcessState`, `EProcessStep`, `PairedBootstrapOptions`, `PairedBootstrapResult`, `WeightedCompositeInput`, `WeightedCompositeResult`, `CliffsMagnitude`. +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `BootstrapOptions`, `BootstrapResult`, `ClusterBootstrapInterval`, `CorpusAgreementOptions`, `CorpusAgreementPerDimension`, `CorpusAgreementReport`, `CorpusScoreRecord`, `EProcess`, `EProcessOptions`, `EProcessState`, `EProcessStep`, `PairedBootstrapOptions`, `PairedBootstrapResult`, `WeightedCompositeInput`, `WeightedCompositeResult`, `CliffsMagnitude`. ### CAMPAIGN — profile matrix, gates, improvement loop -Import from `@tangle-network/agent-eval/campaign` — 261 exports. +Import from `@tangle-network/agent-eval/campaign` — 279 exports. | Symbol | Kind | Summary | |---|---|---| | `aceProposer` | function | Append-only context engineering proposer: grows a skill playbook by appending generation-tagged lessons without merging or overwriting prior entries. | +| `acquireSingleRunLock` | function | Acquire the lock or throw naming the live holder. A stale lock (holder pid | | `applySkillPatch` | function | Apply a SkillOpt patch to a text surface. Ops apply in array order against | +| `assertCodeSurfaceIdentity` | function | Fail when a code surface does not carry a complete immutable identity. | | `buildAnalystSurfaceDispatch` | function | Build the `dispatchWithSurface(surface, scenario, ctx)` the improvement loop | | `buildEvidenceVector` | function | The Evidence Bus. For each objective, pair candidate vs baseline by full | | `buildLoopProvenanceRecord` | function | Build the durable provenance record from a completed loop result. | | `callbackGovernor` | function | The LLM-supervisor slot: a governor whose `decide` defers to a caller-supplied | | `campaignBreakdown` | function | Per-candidate evidence a reflective/patch proposer grounds its next proposal | | `campaignMeanComposite` | function | Mean composite across a campaign: per cell, the mean of its judges' | +| `classifyUngroundedLiterals` | function | Scan revised artifact text for single-quoted single-word literals (the | +| `codeSurfaceIdentityMaterial` | function | Canonical, location-independent identity of a finalized code candidate. | | `compareProposers` | function | Run a head-to-head lift benchmark across surface proposers on a shared holdout, returning per-proposer lift CIs and pairwise "who wins" verdicts. | | `composeGate` | function | Compose gates — all must `ship` for the composite to `ship`. First | +| `compositeProposer` | function | Fan the population budget across N proposers and merge their candidates into | | `countSentenceEdits` | function | Sentence-level edit distance — count distinct add/remove ops between | | `defaultProductionGate` | function | Opinionated production gate composing held-out significance, red-team, reward-hacking, and canary checks into a single `Gate.decide` decision. | | `defaultRenderDiff` | function | Default surface diff renderer: produces a unified baseline/winner text diff for prompt surfaces or a worktree-ref summary for code surfaces. | @@ -1115,6 +1173,7 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `heuristicGovernor` | function | The reference deterministic policy an agent {@link Governor} can replace. | | `inMemoryCampaignStorage` | function | In-memory storage for filesystem-less runtimes. Artifacts + trace spans | | `isProposedCandidate` | function | Type guard: a proposal carrying its rationale vs a bare | +| `isTransientTransportFailure` | function | True when the error text describes an infrastructure hiccup that should be | | `labelTrustRank` | function | Ordinal rank for a label-trust tier; absent ⇒ `unverified` (rank 0). | | `lineageNodeId` | function | Deterministic node id: a hash of the node's lineage + content + proposer. | | `llmJudge` | function | Build a campaign-shaped `JudgeConfig` whose `score()` makes ONE LLM call | @@ -1140,7 +1199,8 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `provenanceSpansPath` | function | Canonical path for the durable OTLP spans JSONL file under a loop run directory. | | `renderScoreboardMarkdown` | function | Render the scoreboard as a launch-readiness Markdown document — the literal | | `resolveRunDir` | function | Resolve a campaign `runDir`. An absolute path is honored as-is (the caller | -| `resolveWorktreePath` | function | Resolve a `CodeSurface`'s worktreeRef to a directory the measurement can | +| `resolveWorktreePath` | function | Resolve a code candidate for evaluation only after verifying its immutable | +| `rolloutArgumentDiff` | function | Deterministic per-field diff of call arguments between passing and failing | | `runCampaign` | function | Core campaign orchestrator: fan scenarios through dispatch, score with judges, aggregate bootstrap CIs, and persist reproducible `CampaignResult` records. | | `runEval` | function | Simplest evaluation preset: run scenarios through dispatch, score with judges, and return a `CampaignResult` — no optimizer, no gate, no PR. | | `runImprovementLoop` | function | Gated-promotion shell over `runOptimization`: scores the winner against the baseline on a holdout set, runs the release gate, and optionally opens a PR. | @@ -1157,11 +1217,12 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `sequentialPairedGate` | function | Anytime-valid sequential paired gate. Conforms to the existing `Gate` | | `skillOptEntry` | function | SkillOpt patch-mode hill-climb. Runs findings-BLIND: `runSkillOpt` owns its | | `skillOptProposer` | function | SkillOpt proposer: proposes bounded, anchored patch operations (add/delete/replace) on a skill document, conforming to both the patch-native `SkillOptProposer` and the generic `SurfaceProposer` interf | -| `surfaceContentHash` | function | Stable sha256 (full hex) of a surface's effective text. Code surfaces hash | -| `surfaceHash` | function | Short (16-char) sha256 fingerprint of a `MutableSurface`: hashes text content for prompt surfaces, or the worktree + base ref pair for code surfaces. | +| `surfaceContentHash` | function | Full SHA-256 content identity for a prompt or finalized code surface. | +| `surfaceHash` | function | Short loop key derived from the same content identity as provenance. | | `tangleTracesRoot` | function | The shared, out-of-repo root for campaign/benchmark run bundles. Keeping run | | `traceAnalystProposer` | function | Wrap agent-eval's trace-analyst registry as a SurfaceProposer (prompt-tier). | | `userStoryScoreboard` | function | Flatten story verdicts into the per-requirement scoreboard — the literal | +| `verifyCodeSurface` | function | Verify a finalized code surface against its current checkout. This rejects | | `paretoPolicy` | const | The default strategy: symmetric multi-objective Pareto significance. Ship iff | | `FsLabeledScenarioStore` | class | Filesystem `LabeledScenarioStore`: appends one JSONL file per source with provenance and | | `LabeledScenarioStoreError` | class | Typed rejection from a labeled-scenario store (bad provenance, rate limit, invalid sample args) — carries a stable string `code`. | @@ -1176,7 +1237,8 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `CampaignCostMeter` | interface | Cell-scoped cost meter. NOTHING is captured automatically — | | `CampaignStorage` | interface | `CampaignStorage` — the filesystem seam `runCampaign` writes through | | `CampaignTraceWriter` | interface | Scoped trace writer handed to each dispatch — every span | -| `CodeSurface` | interface | A tier-4 code surface — a candidate change to the agent's | +| `CodeSurface` | interface | A tier-4 code surface — a finalized candidate change to the agent's | +| `CompositeProposerOptions` | interface | `compositeProposer` — run N proposers TOGETHER on the same surface. | | `DefaultProductionGateOptions` | interface | `defaultProductionGate` — composes the substrate's existing safety | | `DispatchContext` | interface | Context handed to every dispatch invocation. Scoped — every | | `EvolutionaryProposerOptions` | interface | `evolutionaryProposer` — adapts a stateless `Mutator` (population mutation: | @@ -1190,6 +1252,7 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `JudgeScore` | interface | The canonical judge verdict shape — one declaration, shared by campaign | | `LabeledScenarioWrite` | interface | Required-provenance write. The store rejects writes that | | `LineageNode` | interface | Lineage DAG — a git-graph of improvement candidates. | +| `LoopProvenanceCandidate` | interface | Loop provenance — the durable, queryable record of WHAT a self-improvement | | `LoopProvenanceRecord` | interface | The durable provenance record. Aligns to the hosted `EvalRunEvent` path but | | `MemoryCurationProposerOptions` | interface | `memoryCurationProposer` — a CURATOR `SurfaceProposer`, the complement to the | | `Mutator` | interface | Stateless surface mutation — given findings + current | @@ -1206,6 +1269,7 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `ProposedCandidate` | interface | A proposer output carrying the surface AND the WHY behind | | `ProposerEntry` | interface | What an optimizer produced: the surface it promoted + what it cost to get | | `RejectedEdit` | interface | A patch that was tried and not accepted — fed back to the model so it does | +| `RolloutCall` | interface | One tool/action call observed in a rollout: a name plus its arguments. | | `RunCampaignOptions` | interface | `runCampaign` — Pass A substrate primitive. ONE function that orchestrates | | `RunEvalOptions` | interface | `runEval` — the simplest preset over `runCampaign`. No optimizer, no | | `RunLineageLoopSeed` | interface | A seed track: the initial surface + track identity. Unlike | @@ -1214,15 +1278,17 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `ScenarioSignal` | interface | Per-scenario observation: the composite scores each candidate earned on it. | | `ScoreboardRow` | interface | One row of the launch scoreboard — story × requirement → PASS/FAIL. | | `ScoreboardSummary` | interface | Launch-readiness headline counts rolled up from the per-requirement rows. | +| `ScoredRollout` | interface | A scored rollout: its calls plus the scalar outcome used to split pass/fail. | | `SessionScript` | interface | One session within a multi-session journey. Dispatch is | +| `SingleRunLockOptions` | interface | Single-run lock for evaluations that share one mutable environment. | | `SkillOptEvidence` | interface | Evidence the optimizer reflects on: where the current surface is weakest. | | `SkillPatch` | interface | A named, attributable bundle of ops the optimizer proposes as one edit. | | `SurfaceProposer` | interface | A surface-improvement strategy. Given the current best | | `SurfaceScore` | interface | The measured fitness of one surface — the value recorded on a DAG node. | | `TraceAnalystProposerOptions` | interface | `traceAnalystProposer` — wraps agent-eval's OWN trace-analyst engine | +| `TransientFailureOptions` | interface | Transient-transport-failure classification for dispatch retry policies. | | `UserStory` | interface | A user story = a runnable product journey plus the requirements that define | | `UserStoryVerdict` | interface | A scored user story — the completion verdict plus its human title. | -| `Worktree` | interface | VCS-pluggable worktree adapter. One improvement = one worktree, PR-like | | `AxisVerdict` | type | Per-axis verdict from the good-direction paired bootstrap. | | `CampaignTokenUsage` | type | Token usage accumulated for a cell. Aliased to the canonical `RunTokenUsage` | | `DispatchFn` | type | One function: scenario + ctx → artifact. Dispatcher chooses | @@ -1241,7 +1307,7 @@ Import from `@tangle-network/agent-eval/campaign` — 261 exports. | `SequentialDecision` | type | Anytime-valid sequential promotion gate — an e-process (betting | | `SkillPatchOp` | type | A single bounded edit against a skill surface. | -**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AcceptedEdit`, `ApplySkillPatchResult`, `AxisEvidence`, `BuildAnalystSurfaceDispatchOptions`, `BuildEvidenceVectorOptions`, `BuildLoopProvenanceArgs`, `CampaignAggregates`, `CampaignBreakdown`, `CampaignCellResult`, `CampaignResult`, `CampaignRunPlan`, `CampaignRunPlanCell`, `CompareProposersOptions`, `DimensionRegression`, `DiscriminationScore`, `EmitLoopProvenanceArgs`, `EmitLoopProvenanceResult`, `EvalFixture`, `EvalFixtureFile`, `EvalFixtureLoadOptions`, `EvalFixtureScenario`, `EvidenceVector`, `FailureModeRecallJudgeOptions`, `FapoAttributionSignals`, `FapoFailureCluster`, `FapoProposerOptions`, `FapoReviewInput`, `FapoReviewIssue`, `FapoReviewResult`, `FapoScopeContract`, `GateContext`, `GateResult`, `GenerationRecord`, `GepaProposerOptions`, `GitWorktreeAdapterOptions`, `Governor`, `GovernorContext`, `HeldOutGateOptions`, `HeldoutSignificance`, `HeldoutSignificanceOptions`, `HeuristicGovernorOptions`, `JudgeAggregate`, `JudgeDimension`, `LabeledScenarioRecord`, `LabeledScenarioSampleArgs`, `LabeledScenarioStore`, `LineageEdge`, `LineageGraph`, `LineageStore`, `LlmJudgeOptions`, `LoadEvalFixtureScenariosOptions`, `LoopProvenanceBackend`, `LoopProvenanceCandidate`, `NeutralizationGateOptions`, `OpenAutoPrResult`, `OptimizerConfig`, `ParameterCandidate`, `ParameterChange`, `ParameterSweepProposerOptions`, `ParetoSignificanceGateOptions`, `PlanCampaignRunOptions`, `PlanEvalFixtureRunOptions`, `PowerPreflight`, `ProfileSummary`, `PromotionObjective`, `ProposePatchesArgs`, `ProposerComparison`, `ProposerPairwise`, `ProposerScore`, `RunImprovementLoopResult`, `RunLineageLoopOptions`, `RunLineageLoopResult`, `RunLineageOptions`, `RunLineageResult`, `RunLineageSeed`, `RunLineageStepResult`, `RunOptimizationResult`, `RunProfileMatrixOptions`, `RunProfileMatrixResult`, `RunSkillOptResult`, `ScenarioAggregate`, `ScenarioRollup`, `ScoreboardRenderOptions`, `SequentialDecideFn`, `SequentialDecideOptions`, `SequentialObservation`, `SequentialPairedGate`, `SequentialPairedGateOptions`, `SkillOptEpochRecord`, `SkillOptProposer`, `SkillOptProposerOptions`, `SkillPatchRejection`, `TraceSpan`, `WorktreeAdapter`, `EvalFixtureRunPlan`, `EvalFixtureValidationMode`, `GovernorOp`, `JsonPrimitive`, `JsonValue`, `RedactionStatus`, `RunOptimizationOptions`. +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AcceptedEdit`, `ApplySkillPatchResult`, `AxisEvidence`, `BuildAnalystSurfaceDispatchOptions`, `BuildEvidenceVectorOptions`, `BuildLoopProvenanceArgs`, `CampaignAggregates`, `CampaignBreakdown`, `CampaignCellResult`, `CampaignResult`, `CampaignRunPlan`, `CampaignRunPlanCell`, `CodeSurfaceVerification`, `CompareProposersOptions`, `DimensionRegression`, `DiscriminationScore`, `EmitLoopProvenanceArgs`, `EmitLoopProvenanceResult`, `EvalFixture`, `EvalFixtureFile`, `EvalFixtureLoadOptions`, `EvalFixtureScenario`, `EvidenceVector`, `FailureModeRecallJudgeOptions`, `FapoAttributionSignals`, `FapoFailureCluster`, `FapoProposerOptions`, `FapoReviewInput`, `FapoReviewIssue`, `FapoReviewResult`, `FapoScopeContract`, `GateContext`, `GateResult`, `GenerationRecord`, `GepaProposerOptions`, `GitWorktreeAdapterOptions`, `Governor`, `GovernorContext`, `HeldOutGateOptions`, `HeldoutSignificance`, `HeldoutSignificanceOptions`, `HeuristicGovernorOptions`, `JudgeAggregate`, `JudgeDimension`, `LabeledScenarioRecord`, `LabeledScenarioSampleArgs`, `LabeledScenarioStore`, `LineageEdge`, `LineageGraph`, `LineageStore`, `LlmJudgeOptions`, `LoadEvalFixtureScenariosOptions`, `LoopProvenanceBackend`, `NeutralizationGateOptions`, `OpenAutoPrResult`, `OptimizerConfig`, `ParameterCandidate`, `ParameterChange`, `ParameterSweepProposerOptions`, `ParetoSignificanceGateOptions`, `PlanCampaignRunOptions`, `PlanEvalFixtureRunOptions`, `PowerPreflight`, `ProfileSummary`, `PromotionObjective`, `ProposePatchesArgs`, `ProposerComparison`, `ProposerPairwise`, `ProposerScore`, `RolloutArgumentDiff`, `RolloutArgumentDiffOptions`, `RunImprovementLoopResult`, `RunLineageLoopOptions`, `RunLineageLoopResult`, `RunLineageOptions`, `RunLineageResult`, `RunLineageSeed`, `RunLineageStepResult`, `RunOptimizationResult`, `RunProfileMatrixOptions`, `RunProfileMatrixResult`, `RunSkillOptResult`, `ScenarioAggregate`, `ScenarioRollup`, `ScoreboardRenderOptions`, `SequentialDecideFn`, `SequentialDecideOptions`, `SequentialObservation`, `SequentialPairedGate`, `SequentialPairedGateOptions`, `SingleRunLock`, `SkillOptEpochRecord`, `SkillOptProposer`, `SkillOptProposerOptions`, `SkillPatchRejection`, `TraceSpan`, `UngroundedLiteralReport`, `Worktree`, `WorktreeAdapter`, `EvalFixtureRunPlan`, `EvalFixtureValidationMode`, `GovernorOp`, `JsonPrimitive`, `JsonValue`, `RedactionStatus`, `RunOptimizationOptions`. ### TOKEN / USAGE — usage extraction + run-record usage types diff --git a/docs/concepts.md b/docs/concepts.md index 3130b9c5..fa3926f5 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -97,8 +97,8 @@ execution state. ## The agent manifest -`defineAgent(...)` is how a vertical declares the **surfaces** (prompt, -skills, tools — the levers `agent-eval`'s analyst loop can edit), the +`defineAgent(...)` is how a vertical declares the **surfaces** (the full +`AgentProfile`: prompt, skills, tools, MCP, hooks, subagents, and extensions), the **knowledge** requirements, the **rubric**, and the **run** function that ties it all together. The manifest is what the eval harness benchmarks, what the analyst loop improves, and (in time) what the diff --git a/docs/intelligence-sdk.md b/docs/intelligence-sdk.md index dc3177cf..fcc43b3d 100644 --- a/docs/intelligence-sdk.md +++ b/docs/intelligence-sdk.md @@ -47,6 +47,8 @@ The delivery code enforces the same framing: a `CertifiedArtifact` carries its h - `effort` — a tier name or `{ tier, overrides }`; default `standard`. See [Effort tiers](#effort-tiers-and-the-off-billing-floor). - `baseUrl` — the ONE Tangle Intelligence base URL both send (`/v1/otlp`) and receive (`/v1/profiles/:target/composed`) derive from. Reads `TANGLE_INTELLIGENCE_URL` when omitted, else `https://intelligence.tangle.tools`. Send ships only when an `apiKey` is present; absent a tenant key, export is a no-op — best-effort by construction. - `redact` — a `Redactor` replaces the default scrubber; `false` opts out loudly; omitted ⇒ `defaultRedactor`. See [Redaction](#redaction). +- `profile` / `commitSha` — the canonical agent configuration and code revision to attach to every run. +- `runtimeTelemetry` — controls whether raw tool inputs/results and other sensitive runtime payloads are included; identities, status, token use, cost, and failures are always retained. - `surfaces` / `checks` / `repo` — declared for `IntelligenceClient.doctor()` readiness only. The client surface: @@ -57,7 +59,7 @@ The client surface: - `client.flush()` — flush pending spans; resolves even if export fails. The best-effort law: telemetry-export failures are swallowed — a live agent never fails because Intelligence is down — but an error thrown by the agent itself propagates unchanged. -Every span carries the billing split as attributes (`tangle.usage.inference_usd`, `tangle.usage.intelligence_usd`, `tangle.effort.intelligence_off`); inputs/outputs pass through the redactor and are bounded to a 4 KB preview on the span. +Every span carries the billing split as attributes (`tangle.usage.inference_usd`, `tangle.usage.intelligence_usd`, `tangle.effort.intelligence_off`); inputs, outputs, and opted-in runtime payloads pass through the redactor and are exported without content truncation. ## Two lanes: traces UP, certified artifacts DOWN @@ -88,7 +90,8 @@ export const agent = withIntelligence( ) ``` -Each call refreshes the certified profile (window-respecting), hands the agent an `AppliedIntelligence` handle (`certified`, `composePrompt`, `proposals`, `applyProfile`, `record`), and SENDs a typed `RunRecord` for the run. +Each call refreshes the certified profile (window-respecting), hands the agent an `AppliedIntelligence` handle (`runId`, `traceId`, `certified`, `composePrompt`, `proposals`, `applyProfile`, `record`), and SENDs a typed `RunRecord` for the run. +The run record includes timing, failures, profile/config hash, repository revision, model, tokens, costs, runtime events, and loop events when supplied; thrown agent errors are exported before being rethrown. The promoted profile diffs surface as `agent.proposals()` / the `onProposals` callback — the hook NEVER auto-applies them; `applied.applyProfile(base)` folds them only when the caller explicitly asks. When the plane promotes a new gate-certified surface, the next refresh delivers it to the running agent; when the plane is unreachable, the agent runs on its base surface. diff --git a/package.json b/package.json index 2ad3bcf4..bc2a3082 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,11 @@ "import": "./dist/platform.js", "default": "./dist/platform.js" }, + "./candidate-execution": { + "types": "./dist/candidate-execution/index.d.ts", + "import": "./dist/candidate-execution/index.js", + "default": "./dist/candidate-execution/index.js" + }, "./mcp": { "types": "./dist/mcp/index.d.ts", "import": "./dist/mcp/index.js", @@ -99,8 +104,8 @@ }, "devDependencies": { "@biomejs/biome": "^2.4.15", - "@tangle-network/agent-eval": "^0.108.1", - "@tangle-network/agent-interface": "^0.24.0", + "@tangle-network/agent-eval": "^0.113.0", + "@tangle-network/agent-interface": "^0.25.0", "@tangle-network/sandbox": "^0.9.7", "@types/node": "^25.9.3", "playwright": "^1.61.0", @@ -130,7 +135,7 @@ "packageManager": "pnpm@10.28.0", "peerDependencies": { "@tangle-network/agent-eval": ">=0.101.0 <1.0.0", - "@tangle-network/agent-interface": ">=0.24.0 <1.0.0", + "@tangle-network/agent-interface": ">=0.25.0 <1.0.0", "@tangle-network/sandbox": ">=0.8.0 <1.0.0", "playwright": "^1.40.0" }, @@ -143,7 +148,7 @@ } }, "dependencies": { - "@tangle-network/agent-knowledge": "^1.11.1", + "@tangle-network/agent-knowledge": "^1.11.2", "@tangle-network/agent-profile-materialize": "0.3.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 326efe80..375155a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@tangle-network/agent-knowledge': - specifier: ^1.11.1 - version: 1.11.1(typescript@5.9.3) + specifier: ^1.11.2 + version: 1.11.2(typescript@5.9.3) '@tangle-network/agent-profile-materialize': specifier: 0.3.0 version: 0.3.0 @@ -19,11 +19,11 @@ importers: specifier: ^2.4.15 version: 2.4.15 '@tangle-network/agent-eval': - specifier: ^0.108.1 - version: 0.108.1(typescript@5.9.3) + specifier: ^0.113.0 + version: 0.113.0(typescript@5.9.3) '@tangle-network/agent-interface': - specifier: ^0.24.0 - version: 0.24.0 + specifier: ^0.25.0 + version: 0.25.0 '@tangle-network/sandbox': specifier: ^0.9.7 version: 0.9.7(viem@2.54.6(typescript@5.9.3)(zod@4.4.3)) @@ -643,14 +643,11 @@ packages: '@tangle-network/agent-core@0.3.8': resolution: {integrity: sha512-bZfVpdiFjXbcQwSxSQABdtXEmUuapWChCcXrHkP6fAnwqEy9hWEfeZLlMZUy+1XaOfpTaMLUOEAwYhXfN018wQ==} - '@tangle-network/agent-eval@0.108.1': - resolution: {integrity: sha512-5T6XKtqcxB8OrR1c8V4EGZk+gQizxmVVQKLCkxTlnMh2lApV+e0EIbEUpKZzD9HmCQSgRY8a2tW3hCTFBuZAyg==} + '@tangle-network/agent-eval@0.113.0': + resolution: {integrity: sha512-1KhW6l69arpanK8vamnvJueD+ZwEO4A7BMF5qpkPLXUVVNcrUail0GWp3M5SpAjQdACa3HTuVdexXuEpZt5sQg==} engines: {node: '>=20'} hasBin: true - '@tangle-network/agent-interface@0.10.1': - resolution: {integrity: sha512-yehY/0EgKvu8lG6jIVoZCtMPLkj8VEWwasuAtuph2RaB9MKE5wuxRF647O6jw8KufNZ3aQ2UVVWpZ19dGCbs6w==} - '@tangle-network/agent-interface@0.13.0': resolution: {integrity: sha512-CeTPGRLoXqpt0h+BCyFgZPkfU1zyRpWmqfD+85i/uk+uvbqxkfI+JprfKVf3tBsQuCgJPSjPt5qjdW8n3h2BVg==} @@ -660,11 +657,14 @@ packages: '@tangle-network/agent-interface@0.21.0': resolution: {integrity: sha512-jDxhVJgxymrvU1RLWxWKueuaWQIpBAfrW8BuVTB5m2Y4eFMLo1SawDBEMDLdZN4/Gf34xrFrsRk+PAj9brGKMQ==} - '@tangle-network/agent-interface@0.24.0': - resolution: {integrity: sha512-iaHWNTYne49cBYXwb72NjGDw5bjT2KVJlfawXygbvkqnfUsQG57BS++Yjf/XYvwJJdDeEaGs+Xvy8SWYkvu0qA==} + '@tangle-network/agent-interface@0.22.0': + resolution: {integrity: sha512-7fsJhNdvTmOB1X9E2owl06jzyrqaN+jMkOPVKbK7dvNqQvf627PowCtL/edhUqEEv+K0FWtkwG3R3xqjX7VNZg==} + + '@tangle-network/agent-interface@0.25.0': + resolution: {integrity: sha512-bMKjyjk8bk2651HleiTEUOTPgNE2bWxCEl9VBVUyub/UkP87Y09byXOxeDEsNGc4TIT19Y5Uo0b+k1kRWXkMVQ==} - '@tangle-network/agent-knowledge@1.11.1': - resolution: {integrity: sha512-2vvNHHsb4TQFnY+SrL7rYaMhwTxTK8R/lD9IAteonmgwcE5amhpPQZqftw+UDMl1d6OBe4QX+Qv1pNmWQDXzqQ==} + '@tangle-network/agent-knowledge@1.11.2': + resolution: {integrity: sha512-sJLLYai35JIHou0YgcPg5I4WCz90vhIUmyF+DQ5GtMBDB+KT92y+rwvLQ4MojIZCTq3p/xv8C3SEhkuqCfzVsw==} engines: {node: '>=20'} hasBin: true @@ -1625,12 +1625,12 @@ snapshots: '@tangle-network/agent-interface': 0.17.1 zod: 4.4.3 - '@tangle-network/agent-eval@0.108.1(typescript@5.9.3)': + '@tangle-network/agent-eval@0.113.0(typescript@5.9.3)': dependencies: '@asteasolutions/zod-to-openapi': 8.5.0(zod@4.4.3) '@ax-llm/ax': 19.0.45(zod@4.4.3) '@hono/node-server': 2.0.8(hono@4.12.28) - '@tangle-network/agent-interface': 0.10.1 + '@tangle-network/agent-interface': 0.22.0 '@tangle-network/tcloud': 0.4.14(typescript@5.9.3)(zod@4.4.3) hono: 4.12.28 zod: 4.4.3 @@ -1643,10 +1643,6 @@ snapshots: - typescript - utf-8-validate - '@tangle-network/agent-interface@0.10.1': - dependencies: - zod: 4.4.3 - '@tangle-network/agent-interface@0.13.0': dependencies: zod: 4.4.3 @@ -1659,13 +1655,17 @@ snapshots: dependencies: zod: 4.4.3 - '@tangle-network/agent-interface@0.24.0': + '@tangle-network/agent-interface@0.22.0': + dependencies: + zod: 4.4.3 + + '@tangle-network/agent-interface@0.25.0': dependencies: zod: 4.4.3 - '@tangle-network/agent-knowledge@1.11.1(typescript@5.9.3)': + '@tangle-network/agent-knowledge@1.11.2(typescript@5.9.3)': dependencies: - '@tangle-network/agent-eval': 0.108.1(typescript@5.9.3) + '@tangle-network/agent-eval': 0.113.0(typescript@5.9.3) zod: 4.4.3 transitivePeerDependencies: - '@mastra/core' diff --git a/scripts/gen-primitive-catalog.mjs b/scripts/gen-primitive-catalog.mjs index 9516bb28..bd2cd68f 100644 --- a/scripts/gen-primitive-catalog.mjs +++ b/scripts/gen-primitive-catalog.mjs @@ -71,6 +71,7 @@ const ownSurfaceLabels = { './knowledge': 'Knowledge orchestration — supervised KB updates', './profiles': 'Built-in agent profiles', './platform': 'Platform glue', + './candidate-execution': 'Candidate execution — immutable prepare, run, grade, and receipt', './mcp': 'MCP servers — delegate / coordination / detached-session', } // ./loops is an intentional alias of ./runtime (same source) — list it once as ./loops, diff --git a/skills/build-with-agent-runtime/SKILL.md b/skills/build-with-agent-runtime/SKILL.md index e4154bd6..f8141210 100644 --- a/skills/build-with-agent-runtime/SKILL.md +++ b/skills/build-with-agent-runtime/SKILL.md @@ -92,7 +92,7 @@ to its native default (`HARNESS_NATIVE_MODEL`) — never silently dropped. | **Spawn N coding agents on isolated git worktrees, keep the one whose patch passes checks** | `worktreeFanout` + `createWorktreeCliExecutor` + `gateOnDeliverable(DeliverableSpec)` over a raw `WorktreePatchArtifact`, winner via `selectValidWinner` — `/loops` — NOT a hand-rolled spawn-loop / "coder" role | canonical-api §3.1 / §5 | | **Sandbox coding rollout** (fresh box/round, or persistent+resume) | `runLoop(options)` / `openSandboxRun(client, opts, deliverable)` — `/loops` | canonical-api §3.1 | | **Optimize a CODE surface** in a gated loop | `improvementDriver({ worktree, generator })` — root `.` | canonical-api §3.4 | -| **Optimize a PROMPT/config surface** (one call) — START HERE | `improve(profile, findings, { surface, gate })` — root `.` (the one pluggable RSI verb; picks the default proposer from `surface` — `gepaProposer` for prompt, `skillOptProposer` for skills — and wraps `selfImprove`; drop to `selfImprove({ agent, scenarios, judge, baselineSurface })` from `agent-eval/contract` only for the lower-level loop) | canonical-api §3.4 | +| **Optimize any agent/code surface** (one call) — START HERE | `improve(profile, findings, { surface, gate })` — root `.`; prompt and skill-document surfaces have built-in proposers, config/whole-profile surfaces accept a proposer, rollout policy enumerates bounded variants, and code gets isolated incumbent/candidate worktrees; drop to `selfImprove({ agent, scenarios, judge, baselineSurface })` only for lower-level control | canonical-api §3.4 | | **Gate: ship/hold a candidate** (campaign ctx) | `defaultProductionGate` / `heldOutGate` / `composeGate` — `agent-eval/contract`; `neutralizationGate` (footprint-matched PLACEBO gate — proves a held-out lift is CONTENT, not added prompt/mount footprint) — `agent-eval/campaign` | canonical-api §3.4 | | **Gate: ship/hold from a `BenchmarkReport`** (per-task cells) | `promotionGate({ report, incumbent, candidate })` — `/loops` | canonical-api §3.4 | | **Run the full multi-generation flywheel + certify** | `runStrategyEvolution(config)` — `/loops` | canonical-api §3.4 | diff --git a/src/agent/surfaces.ts b/src/agent/surfaces.ts index c86e5210..d73f7459 100644 --- a/src/agent/surfaces.ts +++ b/src/agent/surfaces.ts @@ -13,7 +13,7 @@ * refuses to route those subjects rather than fabricating a target. */ -import { existsSync } from 'node:fs' +import { existsSync, statSync } from 'node:fs' import { isAbsolute, join } from 'node:path' import type { FindingSubject } from '@tangle-network/agent-eval' @@ -53,6 +53,22 @@ export interface AgentSurfaces { rag?: string /** Optional: single file defining the output schema (Zod / JSON Schema). */ outputSchema?: string + /** Optional: directory containing Agent Skill packages. */ + skills?: string + /** Optional: directory containing MCP server/tool configuration. */ + mcp?: string + /** Optional: directory containing hook definitions. */ + hooks?: string + /** Optional: directory containing subagent definitions. */ + subagents?: string + /** Optional: directory containing orchestration/workflow policies. */ + workflows?: string + /** Optional: single file containing rollout-policy settings. */ + rolloutPolicy?: string + /** Optional: single canonical AgentProfile file. */ + agentProfile?: string + /** Optional: source root for code findings. */ + code?: string } export interface ResolvedSurface { @@ -123,7 +139,7 @@ function candidatePathsForSubject( // Claims land in a per-topic claims directory under the knowledge root. return [join(surfaces.knowledge, 'claims', `${slugify(subject.topic)}.md`)] case 'knowledge.raw': - return [join(surfaces.knowledge, 'raw', `${subject.sourceId}.md`)] + return optionalPath(safeJoin(join(surfaces.knowledge, 'raw'), `${subject.sourceId}.md`)) case 'system-prompt': { const slug = slugify(subject.section) // Prefer flat layout for create-new (canonical); probe skill-dir layout @@ -135,6 +151,13 @@ function candidatePathsForSubject( join(surfaces.systemPrompt, slug, 'index.md'), ] } + case 'skill': { + if (!surfaces.skills) return [] + return [ + join(surfaces.skills, subject.name, 'SKILL.md'), + join(surfaces.skills, `${subject.name}.md`), + ] + } case 'tool-doc': if (subject.aspect) { return [join(surfaces.tools, subject.tool, `${slugify(subject.aspect)}.md`)] @@ -147,9 +170,46 @@ function candidatePathsForSubject( ] case 'new-tool': return [join(surfaces.tools, subject.name, 'README.md')] + case 'mcp': + if (!surfaces.mcp) return [] + return subject.tool + ? [join(surfaces.mcp, subject.server, `${subject.tool}.md`)] + : [ + join(surfaces.mcp, `${subject.server}.json`), + join(surfaces.mcp, subject.server, 'README.md'), + ] + case 'hook': + if (!surfaces.hooks) return [] + return [ + join(surfaces.hooks, `${subject.name}.md`), + join(surfaces.hooks, `${subject.name}.json`), + ] + case 'subagent': + if (!surfaces.subagents) return [] + return [ + join(surfaces.subagents, `${subject.name}.md`), + join(surfaces.subagents, `${subject.name}.yaml`), + join(surfaces.subagents, `${subject.name}.json`), + ] + case 'workflow': + if (!surfaces.workflows) return [] + return [ + join(surfaces.workflows, `${subject.name}.md`), + join(surfaces.workflows, `${subject.name}.yaml`), + join(surfaces.workflows, `${subject.name}.json`), + ] + case 'rollout-policy': + return surfaces.rolloutPolicy ? [surfaces.rolloutPolicy] : [] + case 'agent-profile': + return surfaces.agentProfile ? [surfaces.agentProfile] : [] + case 'code': { + if (!surfaces.code) return [] + const path = safeJoin(surfaces.code, subject.path) + return path ? [path] : [] + } case 'rag': if (!surfaces.rag) return [] - return [join(surfaces.rag, subject.corpus, `${subject.docId}.md`)] + return optionalPath(safeJoin(join(surfaces.rag, subject.corpus), `${subject.docId}.md`)) case 'memory': if (!surfaces.memory) return [] return [join(surfaces.memory, `${slugify(subject.key)}.json`)] @@ -170,6 +230,17 @@ function candidatePathsForSubject( } } +function safeJoin(root: string, child: string): string | null { + if (child.includes('\0') || isAbsolute(child)) return null + const segments = child.replace(/\\/g, '/').split('/') + if (segments.some((segment) => segment === '..')) return null + return join(root, ...segments) +} + +function optionalPath(path: string | null): string[] { + return path ? [path] : [] +} + function slugify(s: string): string { return ( s @@ -207,8 +278,22 @@ export function validateSurfaces( 'knowledge', ] const fileSurfaces: ReadonlyArray = ['rubric'] - const optionalDirSurfaces: ReadonlyArray = ['scaffolding', 'memory', 'rag'] - const optionalFileSurfaces: ReadonlyArray = ['outputSchema'] + const optionalDirSurfaces: ReadonlyArray = [ + 'scaffolding', + 'memory', + 'rag', + 'skills', + 'mcp', + 'hooks', + 'subagents', + 'workflows', + 'code', + ] + const optionalFileSurfaces: ReadonlyArray = [ + 'outputSchema', + 'rolloutPolicy', + 'agentProfile', + ] for (const key of dirSurfaces) { const p = surfaces[key] as string | undefined @@ -219,6 +304,8 @@ export function validateSurfaces( const abs = isAbsolute(p) ? p : join(repoRoot, p) if (!existsSync(abs)) { issues.push({ surface: key, path: p, reason: 'missing' }) + } else if (!statSync(abs).isDirectory()) { + issues.push({ surface: key, path: p, reason: 'not-directory' }) } } for (const key of fileSurfaces) { @@ -230,6 +317,8 @@ export function validateSurfaces( const abs = isAbsolute(p) ? p : join(repoRoot, p) if (!existsSync(abs)) { issues.push({ surface: key, path: p, reason: 'missing' }) + } else if (!statSync(abs).isFile()) { + issues.push({ surface: key, path: p, reason: 'not-file' }) } } for (const key of [...optionalDirSurfaces, ...optionalFileSurfaces]) { @@ -238,6 +327,13 @@ export function validateSurfaces( const abs = isAbsolute(p) ? p : join(repoRoot, p) if (!existsSync(abs)) { issues.push({ surface: key, path: p, reason: 'missing' }) + continue + } + const expectedDirectory = optionalDirSurfaces.includes(key) + if (expectedDirectory && !statSync(abs).isDirectory()) { + issues.push({ surface: key, path: p, reason: 'not-directory' }) + } else if (!expectedDirectory && !statSync(abs).isFile()) { + issues.push({ surface: key, path: p, reason: 'not-file' }) } } return issues diff --git a/src/candidate-execution/index.ts b/src/candidate-execution/index.ts index 6dad4f9a..224c606d 100644 --- a/src/candidate-execution/index.ts +++ b/src/candidate-execution/index.ts @@ -51,6 +51,7 @@ export { } from './recover' export { type AgentCandidateArtifactPort, + type AgentCandidateBenchmarkGraderIdentity, type AgentCandidateBenchmarkGraderPort, type AgentCandidateContainerPort, type AgentCandidateExecutionPorts, diff --git a/src/candidate-execution/prepare.ts b/src/candidate-execution/prepare.ts index 2761dfa5..3613598f 100644 --- a/src/candidate-execution/prepare.ts +++ b/src/candidate-execution/prepare.ts @@ -289,6 +289,7 @@ export async function prepareAgentCandidateExecution( }, routes, }, + grader: task.grader, launch: { executable: baseLaunch.executable, args: baseLaunch.args, @@ -567,6 +568,13 @@ function assertTaskInput( } usdToNanos(limits.maxCostUsd, 'task maxCostUsd') if (!task.model.requested.trim()) throw new Error('evaluator model request must be non-empty') + if (!task.grader.name.trim() || !task.grader.version.trim()) { + throw new Error('evaluator benchmark grader identity must be non-empty') + } + if (!Number.isInteger(task.grader.artifact.byteLength) || task.grader.artifact.byteLength <= 0) { + throw new Error('evaluator benchmark grader artifact must be non-empty') + } + sha256DigestSchema.parse(task.grader.artifact.sha256) if (task.evaluatorTaskContainer) { if ( task.evaluatorTaskContainer.source !== 'evaluator-task-container' || diff --git a/src/candidate-execution/types.ts b/src/candidate-execution/types.ts index 50c52062..9c5d9cc5 100644 --- a/src/candidate-execution/types.ts +++ b/src/candidate-execution/types.ts @@ -151,6 +151,12 @@ export type AgentCandidateModelLimits = Pick< 'maxModelCalls' | 'maxInputTokens' | 'maxOutputTokens' | 'maxCostUsd' > +export interface AgentCandidateBenchmarkGraderIdentity { + name: string + version: string + artifact: AgentCandidateArtifactRef +} + export interface AgentCandidateProtectedModelReservation { preparationId: string digest: Sha256Digest @@ -267,6 +273,7 @@ export interface AgentCandidateTaskExecution { requested: string reasoningEffort: ReasoningEffort } + grader: AgentCandidateBenchmarkGraderIdentity /** Absolute paths inside the evaluator-owned execution environment. */ executionRoots: { taskRoot: string diff --git a/src/improvement/improve.test.ts b/src/improvement/improve.test.ts index 758770fe..8c030407 100644 --- a/src/improvement/improve.test.ts +++ b/src/improvement/improve.test.ts @@ -40,6 +40,15 @@ const judge: JudgeConfig<{ text: string }, Scenario> = { score: () => ({ dimensions: { q: 0.5 }, composite: 0.5, notes: '' }), } +const improvementJudge: JudgeConfig<{ text: string }, Scenario> = { + name: 'improvement-judge', + dimensions: [{ key: 'q', description: 'contains the measured improvement marker' }], + score: ({ artifact }) => { + const score = artifact.text.includes('improved') ? 1 : 0 + return { dimensions: { q: score }, composite: score, notes: '' } + }, +} + // The agent reports a token-bearing cost so the backend-integrity guard treats // it as a real backend. Without `ctx.cost.observeTokens`, the default // `expectUsage: 'assert'` reads the cell as a silent-zero stub and throws. @@ -88,6 +97,7 @@ describe('improve() — default proposer resolution (substrate export drift guar scenarios, judge, agent: stubAgent, + skills: { document: '# Fixture skill\n\nCheck the result.\n' }, }) expect(result.gateDecision).toBe('hold') @@ -95,6 +105,18 @@ describe('improve() — default proposer resolution (substrate export drift guar expect(result.profile.resources?.skills).toEqual([]) }) + it("surface 'skills' fails loud when the default document optimizer receives only resource refs", async () => { + await expect( + improve(skillProfile(), [], { + surface: 'skills', + gate: 'none', + scenarios, + judge, + agent: stubAgent, + }), + ).rejects.toThrow(/requires opts\.skills\.document/) + }) + it('a real runDir makes the loop durable: provenance lands on the filesystem', async () => { const { mkdtempSync, existsSync, rmSync } = await import('node:fs') const { tmpdir } = await import('node:os') @@ -149,7 +171,7 @@ describe('improve() — default proposer resolution (substrate export drift guar } const skillProfileWithRef = (): AgentProfile => ({ name: 'fixture-agent', - resources: { skills: [{ path: 'or-skills.md' } as never] }, + resources: { skills: [{ kind: 'github', path: 'or-skills.md' }] }, }) const result = await improve(skillProfileWithRef(), [], { @@ -180,11 +202,145 @@ describe('improve() — default proposer resolution (substrate export drift guar } }) + it.each([ + { + surface: 'subagents' as const, + profile: { name: 'fixture-agent', subagents: {} }, + winner: JSON.stringify({ reviewer: { prompt: 'improved review instructions' } }), + read: (profile: AgentProfile) => profile.subagents?.reviewer?.prompt, + expected: 'improved review instructions', + }, + { + surface: 'workflow' as const, + profile: { name: 'fixture-agent', extensions: { 'tangle.workflow': {} } }, + winner: JSON.stringify({ marker: 'improved', phases: ['inspect', 'implement', 'verify'] }), + read: (profile: AgentProfile) => profile.extensions?.['tangle.workflow']?.phases, + expected: ['inspect', 'implement', 'verify'], + }, + { + surface: 'agent-profile' as const, + profile: { name: 'fixture-agent', prompt: { systemPrompt: 'baseline' } }, + winner: JSON.stringify({ + name: 'fixture-agent', + prompt: { systemPrompt: 'improved whole profile' }, + }), + read: (profile: AgentProfile) => profile.prompt?.systemPrompt, + expected: 'improved whole profile', + }, + ])('applies a valid shipped $surface winner to the AgentProfile', async (fixture) => { + const result = await improve(fixture.profile, [{ finding: 'surface needs improvement' }], { + surface: fixture.surface, + scenarios, + judge: improvementJudge, + agent: stubAgent, + generator: { + kind: `stub-${fixture.surface}`, + propose: async () => [ + { surface: fixture.winner, label: 'candidate', rationale: 'test candidate' }, + ], + }, + promotionGate: { + name: 'test-ship', + decide: async () => ({ + decision: 'ship', + reasons: ['test candidate'], + contributingGates: [], + }), + }, + budget: { generations: 1, populationSize: 1, holdoutFraction: 0.25 }, + }) + + expect(result.shipped).toBe(true) + expect(fixture.read(result.profile)).toEqual(fixture.expected) + }) + + it('rejects a shipped config that cannot form a valid AgentProfile', async () => { + await expect( + improve( + { name: 'fixture-agent', subagents: {} }, + [{ finding: 'surface needs improvement' }], + { + surface: 'subagents', + scenarios, + judge: improvementJudge, + agent: stubAgent, + generator: { + kind: 'stub-invalid-subagent', + propose: async () => [ + { + surface: JSON.stringify({ reviewer: { prompt: 'improved', maxSteps: 'many' } }), + label: 'candidate', + rationale: 'invalid candidate', + }, + ], + }, + promotionGate: { + name: 'test-ship', + decide: async () => ({ + decision: 'ship', + reasons: ['exercise validation'], + contributingGates: [], + }), + }, + budget: { generations: 1, populationSize: 1, holdoutFraction: 0.25 }, + }, + ), + ).rejects.toThrow(/valid AgentProfile/) + }) + + it('forwards evaluation controls to the shared self-improvement loop', async () => { + const progressKinds: string[] = [] + let provenanceCalls = 0 + let decisionCalls = 0 + const result = await improve(promptProfile(), [{ finding: 'prompt needs improvement' }], { + surface: 'prompt', + scenarios, + judge: improvementJudge, + agent: stubAgent, + generator: { + kind: 'stub-controls', + propose: async () => [ + { surface: 'improved prompt', label: 'candidate', rationale: 'test candidate' }, + ], + }, + promotionGate: { + name: 'test-hold', + decide: async () => { + decisionCalls += 1 + return { decision: 'hold', reasons: ['test hold'], contributingGates: [] } + }, + }, + onProgress: (event) => progressKinds.push(event.kind), + onProvenance: () => { + provenanceCalls += 1 + }, + collectWorkerRecords: () => [], + expectUsage: 'assert', + captureSource: 'eval-run', + autoOnPromote: 'none', + budget: { generations: 1, populationSize: 1, holdoutFraction: 0.25 }, + }) + + expect(result.gateDecision).toBe('hold') + expect(decisionCalls).toBe(1) + expect(provenanceCalls).toBe(1) + expect(progressKinds).toContain('baseline.completed') + expect(progressKinds).toContain('gate.decided') + }) + it('a surface with no zero-config default still fails loud with ConfigError', async () => { // The default-proposer map covers prompt + skills only; the config surfaces // (tools/mcp/hooks/code) require a caller-supplied generator. This is the // designed boundary the proposer migration must NOT erase. - const configSurfaces: ImproveSurface[] = ['tools', 'mcp', 'hooks', 'code'] + const configSurfaces: ImproveSurface[] = [ + 'tools', + 'mcp', + 'hooks', + 'subagents', + 'workflow', + 'agent-profile', + 'code', + ] for (const surface of configSurfaces) { await expect( improve(promptProfile(), [], { surface, gate: 'none', scenarios, judge, agent: stubAgent }), @@ -221,12 +377,14 @@ describe('improve() — default proposer resolution (substrate export drift guar }) expect(typeof result.gateDecision).toBe('string') expect(findingsSeen.length).toBeGreaterThanOrEqual(2) - // Generation 1 proposes from the static seed; generation 2 must propose from the - // DISTILLED failures of generation 1's cells (scenario 'b' + the judge's reason). - expect(JSON.stringify(findingsSeen[0])).toContain('static-seed-finding') - const secondRound = JSON.stringify(findingsSeen[1]) - expect(secondRound).toContain('"scenario":"b"') - expect(secondRound).toContain('not a permutation') + // Current selfImprove analyzes the baseline before generation 1, so every + // proposal round starts from measured failures instead of wasting a round + // on the static seed. + for (const seen of findingsSeen) { + const round = JSON.stringify(seen) + expect(round).toContain('"scenario":"b"') + expect(round).toContain('not a permutation') + } }) it("surface 'code' + opts.code assembles the worktree pipeline and measures a candidate", async () => { @@ -276,13 +434,20 @@ describe('improve() — default proposer resolution (substrate export drift guar // loop measured them (code surfaces reached the agent), and the gate decided. expect(generatorCalls).toBeGreaterThanOrEqual(1) expect(typeof result.gateDecision).toBe('string') - const sawCodeSurface = measured.some( + const codeSurfaces = measured.filter( (m) => typeof m === 'object' && m !== null && 'worktreeRef' in (m as Record), ) - expect(sawCodeSurface).toBe(true) + expect(codeSurfaces.length).toBeGreaterThanOrEqual(2) + expect( + codeSurfaces.some((surface) => + String((surface as { worktreeRef: string }).worktreeRef).includes('incumbent-baseline'), + ), + ).toBe(true) // A code winner is a worktree ref, not a profile field — profile unchanged. expect(result.profile.prompt?.systemPrompt).toBe('be careful') + expect(result.shipped).toBe(false) + expect(String(git('worktree list --porcelain')).match(/^worktree /gm)).toHaveLength(1) } finally { rmSync(repoRoot, { recursive: true, force: true }) } diff --git a/src/improvement/improve.ts b/src/improvement/improve.ts index cfcd9b07..c52bc789 100644 --- a/src/improvement/improve.ts +++ b/src/improvement/improve.ts @@ -12,17 +12,20 @@ * * - `surface: 'prompt'` → `gepaProposer` mutates `profile.prompt.systemPrompt`. * - `surface: 'skills'` → `skillOptProposer` mutates a skills document string. + * - `surface: 'agent-profile'` → caller-supplied proposer mutates the complete + * canonical AgentProfile JSON in one candidate. * - `surface: 'rollout-policy'` → `rolloutPolicyProposer` mutates the * inference-time `StructuralRolloutPolicy` dials ({ k, repairRounds, testgen }) * persisted in `profile.extensions['structural-rollout']` — deterministic * bounded neighbor enumeration; the held-out gate does the deciding. No-op * (nothing proposed, nothing shipped) when the profile has no such extension. - * - `surface` ∈ {`tools`, `mcp`, `hooks`, `code`} → no zero-config default + * - `surface` ∈ {`tools`, `mcp`, `hooks`, `subagents`, `workflow`, `agent-profile`, `code`} → no zero-config default * proposer exists (a code/config proposer needs caller-supplied wiring — a * worktree repo root, a candidate generator, a serializer). The facade * requires an explicit `opts.generator` for these and throws a `ConfigError` * otherwise. This is a designed boundary, not a missing default: there is - * no safe value the facade could invent for those seams. + * no safe value the facade could invent for those surfaces. Code also + * requires `opts.code.repoRoot` so its incumbent is a real isolated checkout. * * Everything else (`scenarios`, `judge`, `agent`, `budget`, `llm`) passes * straight through to `selfImprove`. @@ -36,8 +39,7 @@ import { skillOptProposer, } from '@tangle-network/agent-eval/campaign' import { - type DispatchContext, - type JudgeConfig, + type CodeSurface, type MutableSurface, type Scenario, type SelfImproveBudget, @@ -47,12 +49,16 @@ import { type SurfaceProposer, selfImprove, } from '@tangle-network/agent-eval/contract' -import type { AgentProfile } from '@tangle-network/agent-interface' +import { type AgentProfile, agentProfileSchema } from '@tangle-network/agent-interface' import { ConfigError } from '../errors' import type { LocalHarness } from '../mcp/local-harness' import { assertModelAllowed } from '../runtime/supervise/model-policy' import { agenticGenerator, type Verifier } from './agentic-generator' -import { type CandidateGenerator, improvementDriver } from './improvement-driver' +import { + type CandidateGenerator, + improvementDriver, + type ManagedImprovementDriver, +} from './improvement-driver' import { rawTraceDistiller } from './raw-trace-distiller' import { applyRolloutPolicyToProfile, @@ -72,10 +78,16 @@ export type ImproveSurface = | 'tools' | 'mcp' | 'hooks' + | 'subagents' + | 'workflow' + | 'agent-profile' | 'code' | 'rollout-policy' -export interface ImproveOptions { +export type ImproveOptions = Omit< + SelfImproveOptions, + 'analyzeGeneration' | 'baselineSurface' | 'findings' | 'gate' | 'proposer' +> & { /** Which profile lever to optimize. Default `'prompt'`. Selects the default * generator + the baseline-surface extraction shape. */ surface?: ImproveSurface @@ -86,28 +98,10 @@ export interface ImproveOptions { /** Gate mode. `'holdout'` (default) runs the held-out promotion gate; * `'none'` is a baseline-only run (`budget.generations = 0`). */ gate?: 'holdout' | 'none' - /** Scenarios to evaluate against. Passthrough to `selfImprove`. */ - scenarios: TScenario[] - /** Judge that scores artifacts. Passthrough to `selfImprove`. */ - judge: JudgeConfig - /** The agent under improvement — same shape as `selfImprove.agent`: it takes - * the current surface + scenario + ctx and returns the artifact to judge. */ - agent: (surface: MutableSurface, scenario: TScenario, ctx: DispatchContext) => Promise - /** Budget + loop shape. Passthrough; `gate: 'none'` forces `generations = 0`. */ - budget?: SelfImproveBudget - /** LLM config. Passthrough to `selfImprove` AND used to construct the default - * reflective proposer (`gepaProposer`/`skillOptProposer`) when `generator` is unset. */ - llm?: SelfImproveLlm /** Restrict the run to this subset of models. When set, the reflection model * (`llm.model`, or the default when unset) must be a member, or `improve()` throws * a `ConfigError` before the generator is built. Unset = unrestricted. */ allowedModels?: readonly string[] - /** Run directory passthrough to `selfImprove`. Pass a REAL path to make the loop - * durable: campaign cells + the loop provenance record land on the filesystem as - * they complete, so a multi-hour search survives a process/infra death instead of - * losing every generation with it (the default `mem://` run keeps everything - * in-process). */ - runDir?: string /** Per-generation findings producer passthrough (see selfImprove.analyzeGeneration). * DEFAULT: the built-in failure distiller — after each generation it turns the * worst-scoring/errored cells into structured findings ({ scenario, composite, @@ -126,13 +120,13 @@ export interface ImproveOptions { * (disabled). Equivalent to `analyzeGeneration: rawTraceDistiller()`; this flag * is the one-line enable. Default `false` (the distiller stays the default). */ rawTraceContext?: boolean - /** CODE-surface wiring with prompt-parity DX: name `surface: 'code'`, point at a - * repo, and the facade assembles the whole candidate pipeline — git worktrees + /** CODE-surface wiring: name `surface: 'code'`, point at a repo, and the + * facade assembles the whole candidate pipeline — an isolated incumbent plus git worktrees * (`gitWorktreeAdapter`) driven by `improvementDriver` with the full agentic * generator (a real coding harness edits each candidate worktree; a `verify` * hook gates candidates before they are ever measured). Ignored when - * `opts.generator` is supplied. Without either, `surface: 'code'` still fails - * loud — there is no safe zero-config repo to invent. */ + * `opts.generator` is supplied. Required for every code run because a real + * repository and base ref are necessary to measure the incumbent. */ code?: ImproveCodeOptions /** SKILLS-surface wiring for real skill-DOCUMENT optimization. Without this, * `surface: 'skills'` optimizes the profile's skills REFS array (file pointers) @@ -141,8 +135,9 @@ export interface ImproveOptions { * shipped winner (the profile ref points at a file the caller owns). This is * what makes skillOpt reachable through improve(). */ skills?: ImproveSkillsOptions - /** Storage passthrough to `selfImprove`; overrides the default chosen from `runDir`. */ - storage?: SelfImproveOptions['storage'] + /** Custom held-back-exam decision. The string `gate` above controls whether + * the exam runs; this callback controls how its evidence decides promotion. */ + promotionGate?: SelfImproveOptions['gate'] } export interface ImproveSkillsOptions { @@ -190,6 +185,7 @@ export interface ImproveResult { /** Default model id for the reflective drivers when `llm.model` is unset — a model the Tangle * router actually serves (callers should pass their own `llm.model`). */ const defaultReflectionModel = 'deepseek-v4-flash' +const workflowExtension = 'tangle.workflow' /** The reflective proposers (`gepaProposer`/`skillOptProposer`) take a full * `LlmClientOptions`; `SelfImproveLlm` is the thin user-facing subset. */ @@ -238,6 +234,12 @@ function baselineSurfaceFor( return JSON.stringify(profile.mcp ?? {}) case 'hooks': return JSON.stringify(profile.hooks ?? {}) + case 'subagents': + return JSON.stringify(profile.subagents ?? {}) + case 'workflow': + return JSON.stringify(profile.extensions?.[workflowExtension] ?? {}) + case 'agent-profile': + return JSON.stringify(profile) case 'rollout-policy': { // Empty surface when the profile never opted into structural rollout: the // proposer reads it as "propose nothing", so the loop runs baseline-only and @@ -246,10 +248,9 @@ function baselineSurfaceFor( return policy ? serializeRolloutPolicy(policy) : '' } case 'code': - // A code surface is produced by the caller's generator from a worktree; - // the facade has no worktree ref to seed, so the baseline is the empty - // string (the driver opens its own worktree off `baseRef`). - return '' + throw new ConfigError( + 'improve(): code requires the isolated baseline created from opts.code.repoRoot', + ) } } @@ -301,33 +302,67 @@ function generationFailureDistiller( } } -/** Assemble the code-surface proposer from `opts.code`: git worktrees + the - * improvement driver + (by default) the full agentic generator. Returns - * `undefined` when the surface is not `code` or no code options were given — - * the caller then falls through to the fail-loud ConfigError. */ -function codeProposerFor( - surface: ImproveSurface, - code: ImproveCodeOptions | undefined, -): SurfaceProposer | undefined { - if (surface !== 'code' || !code) return undefined - const generator = - code.generator ?? - agenticGenerator({ - ...(code.harness ? { harness: code.harness } : {}), - ...(code.verify ? { verify: code.verify } : {}), - ...(code.timeoutMs ? { timeoutMs: code.timeoutMs } : {}), - }) - return improvementDriver({ - worktree: gitWorktreeAdapter({ - repoRoot: code.repoRoot, - ...(code.worktreeDir ? { worktreeDir: code.worktreeDir } : {}), - }), - generator, - ...(code.baseRef ? { baseRef: code.baseRef } : {}), - }) as SurfaceProposer +interface PreparedCodeRun { + baseline: CodeSurface + proposer: SurfaceProposer + cleanup(retainedWinner?: MutableSurface): Promise } -/** Parse a JSON winner surface (`skills`/`tools`/`mcp`/`hooks`) with a typed, +function isCodeSurface(surface: MutableSurface | undefined): surface is CodeSurface { + return typeof surface === 'object' && surface !== null && surface.kind === 'code' +} + +/** Create a clean incumbent checkout and the candidate producer for a code run. */ +async function prepareCodeRun( + code: ImproveCodeOptions, + proposerOverride?: SurfaceProposer, +): Promise { + const baseRef = code.baseRef ?? 'main' + const worktree = gitWorktreeAdapter({ + repoRoot: code.repoRoot, + ...(code.worktreeDir ? { worktreeDir: code.worktreeDir } : {}), + }) + const baselineWorktree = await worktree.create({ baseRef, label: 'incumbent-baseline' }) + const baseline = await worktree.finalize(baselineWorktree, 'Incumbent code checkout') + let managed: ManagedImprovementDriver | undefined + if (!proposerOverride) { + const generator = + code.generator ?? + agenticGenerator({ + ...(code.harness ? { harness: code.harness } : {}), + ...(code.verify ? { verify: code.verify } : {}), + ...(code.timeoutMs ? { timeoutMs: code.timeoutMs } : {}), + }) + managed = improvementDriver({ worktree, generator, baseRef }) + } + const proposer = proposerOverride ?? managed + if (!proposer) { + throw new ConfigError('improve(): code candidate generator could not be constructed') + } + + return { + baseline, + proposer, + async cleanup(retainedWinner) { + const errors: unknown[] = [] + try { + await managed?.cleanup(isCodeSurface(retainedWinner) ? [retainedWinner.worktreeRef] : []) + } catch (cause) { + errors.push(cause) + } + try { + await worktree.discard(baselineWorktree) + } catch (cause) { + errors.push(cause) + } + if (errors.length > 0) { + throw new AggregateError(errors, 'improve(): failed to clean code improvement worktrees') + } + }, + } +} + +/** Parse a JSON winner surface (`skills`/`tools`/`mcp`/`hooks`/`subagents`/`workflow`/`agent-profile`) with a typed, * contextual error. A malformed generator output must fail loud here, not throw * a raw `SyntaxError` to the caller after a ship verdict. */ function parseWinnerJson(winner: string, surface: ImproveSurface): T { @@ -354,20 +389,41 @@ function applyWinnerToProfile( // caller materializes it from `raw.winner.surface`; the returned profile is // unchanged for that lever. if (typeof winner !== 'string') return profile + let candidate: AgentProfile switch (surface) { case 'prompt': - return { ...profile, prompt: { ...profile.prompt, systemPrompt: winner } } + candidate = { ...profile, prompt: { ...profile.prompt, systemPrompt: winner } } + break case 'skills': - return { + candidate = { ...profile, resources: { ...profile.resources, skills: parseWinnerJson(winner, surface) }, } + break case 'tools': - return { ...profile, tools: parseWinnerJson(winner, surface) } + candidate = { ...profile, tools: parseWinnerJson(winner, surface) } + break case 'mcp': - return { ...profile, mcp: parseWinnerJson(winner, surface) } + candidate = { ...profile, mcp: parseWinnerJson(winner, surface) } + break case 'hooks': - return { ...profile, hooks: parseWinnerJson(winner, surface) } + candidate = { ...profile, hooks: parseWinnerJson(winner, surface) } + break + case 'subagents': + candidate = { ...profile, subagents: parseWinnerJson(winner, surface) } + break + case 'workflow': + candidate = { + ...profile, + extensions: { + ...profile.extensions, + [workflowExtension]: parseWinnerJson(winner, surface), + }, + } + break + case 'agent-profile': + candidate = parseWinnerJson(winner, surface) + break case 'rollout-policy': { // Parse + re-validate the winner against the policy's own invariants — a // custom generator's malformed dial must fail loud, not persist silently. @@ -378,11 +434,19 @@ function applyWinnerToProfile( `(integer k >= 1, repairRounds >= 0, testgen >= 0), so it cannot be applied: ${winner}`, ) } - return applyRolloutPolicyToProfile(profile, policy) + candidate = applyRolloutPolicyToProfile(profile, policy) + break } case 'code': return profile } + const parsed = agentProfileSchema.safeParse(candidate) + if (!parsed.success) { + throw new ConfigError( + `improve(): the shipped '${surface}' winner does not produce a valid AgentProfile: ${parsed.error.message}`, + ) + } + return parsed.data } /** @@ -403,55 +467,95 @@ export async function improve( findings: unknown[], opts: ImproveOptions, ): Promise> { - const surface = opts.surface ?? 'prompt' - const gate = opts.gate ?? 'holdout' + const { + surface = 'prompt', + gate = 'holdout', + generator, + allowedModels, + rawTraceContext, + code, + skills, + promotionGate, + analyzeGeneration, + ...sharedOptions + } = opts - // Fail loud before the generator is built: the reflection model must be in the allowed subset - // (no-op when allowedModels is unset). - assertModelAllowed(opts.llm?.model ?? defaultReflectionModel, opts.allowedModels) + const parsedProfile = agentProfileSchema.safeParse(profile) + if (!parsedProfile.success) { + throw new ConfigError( + `improve(): input is not a valid AgentProfile: ${parsedProfile.error.message}`, + ) + } + if (surface === 'skills' && !generator && !skills) { + throw new ConfigError( + 'improve(): the default skills optimizer requires opts.skills.document; pass the skill text or an explicit generator that understands resource refs', + ) + } + const usesReflectionModel = !generator && (surface === 'prompt' || surface === 'skills') + if (usesReflectionModel) { + assertModelAllowed(sharedOptions.llm?.model ?? defaultReflectionModel, allowedModels) + } + let preparedCode: PreparedCodeRun | undefined + if (surface === 'code') { + if (!code) { + throw new ConfigError( + "improve(): surface 'code' requires opts.code.repoRoot so the incumbent can run from an isolated checkout", + ) + } + preparedCode = await prepareCodeRun(code, generator) + } const proposer = - opts.generator ?? defaultGeneratorFor(surface, opts.llm) ?? codeProposerFor(surface, opts.code) + preparedCode?.proposer ?? generator ?? defaultGeneratorFor(surface, sharedOptions.llm) if (!proposer) { throw new ConfigError( - surface === 'code' - ? `improve(): surface 'code' needs either opts.generator or opts.code ({ repoRoot, ... }) — there is no safe zero-config repo to invent` - : `improve(): surface '${surface}' has no default generator — pass opts.generator (a SurfaceProposer) explicitly`, + `improve(): surface '${surface}' has no default generator — pass opts.generator (a SurfaceProposer) explicitly`, ) } const budget: SelfImproveBudget = - gate === 'none' ? { ...opts.budget, generations: 0 } : { ...opts.budget } + gate === 'none' ? { ...sharedOptions.budget, generations: 0 } : { ...sharedOptions.budget } - const raw = await selfImprove({ - agent: opts.agent, - scenarios: opts.scenarios, - judge: opts.judge, - baselineSurface: baselineSurfaceFor(profile, surface, opts.skills), - proposer, - budget, - llm: opts.llm, - findings, - ...(opts.runDir !== undefined ? { runDir: opts.runDir } : {}), - ...(opts.storage !== undefined ? { storage: opts.storage } : {}), - ...(opts.analyzeGeneration === null - ? {} - : { - analyzeGeneration: - opts.analyzeGeneration ?? - (opts.rawTraceContext - ? rawTraceDistiller({ fallbackFindings: findings }) - : generationFailureDistiller(findings)), - }), - }) + let raw: SelfImproveResult + try { + raw = await selfImprove({ + ...sharedOptions, + baselineSurface: preparedCode?.baseline ?? baselineSurfaceFor(profile, surface, skills), + proposer, + budget, + findings, + ...(promotionGate !== undefined ? { gate: promotionGate } : {}), + ...(analyzeGeneration === null + ? {} + : { + analyzeGeneration: + analyzeGeneration ?? + (rawTraceContext + ? rawTraceDistiller({ fallbackFindings: findings }) + : generationFailureDistiller(findings)), + }), + }) + } catch (cause) { + if (!preparedCode) throw cause + try { + await preparedCode.cleanup() + } catch (cleanupCause) { + throw new AggregateError( + [cause, cleanupCause], + 'improve(): code improvement failed and its worktrees could not be cleaned', + ) + } + throw cause + } const shipped = raw.gateDecision === 'ship' + await preparedCode?.cleanup(shipped ? raw.winner.surface : undefined) // When a skill DOCUMENT was optimized, the winner is document text — persist it // via writeBack (the profile ref points at the caller's file, unchanged) rather // than parsing it as a refs array. Otherwise use the standard field write-back. - const usedSkillDocument = surface === 'skills' && opts.skills !== undefined + const usedSkillDocument = surface === 'skills' && skills !== undefined if (shipped && usedSkillDocument && typeof raw.winner.surface === 'string') { - opts.skills?.writeBack?.(raw.winner.surface) + skills?.writeBack?.(raw.winner.surface) } const nextProfile = shipped && !usedSkillDocument diff --git a/src/improvement/improvement-driver.ts b/src/improvement/improvement-driver.ts index 60733e15..8f574bcb 100644 --- a/src/improvement/improvement-driver.ts +++ b/src/improvement/improvement-driver.ts @@ -26,6 +26,7 @@ import type { LabeledScenarioStore, ProposeContext, SurfaceProposer, + Worktree, WorktreeAdapter, } from '@tangle-network/agent-eval/campaign' @@ -69,9 +70,15 @@ export interface ImprovementDriverOptions { baseRef?: string } +export interface ManagedImprovementDriver extends SurfaceProposer { + /** Remove every finalized candidate except explicitly retained winners. */ + cleanup(retainWorktreeRefs?: readonly string[]): Promise +} + /** The one reflective/agentic improvement proposer (`SurfaceProposer`): owns the candidate worktree lifecycle and delegates HOW a change is produced to a pluggable `CandidateGenerator`. */ -export function improvementDriver(opts: ImprovementDriverOptions): SurfaceProposer { +export function improvementDriver(opts: ImprovementDriverOptions): ManagedImprovementDriver { const baseRef = opts.baseRef ?? 'main' + const finalized = new Map() return { kind: `improvement:${opts.generator.kind}`, @@ -115,7 +122,9 @@ export function improvementDriver(opts: ImprovementDriverOptions): SurfacePropos await opts.worktree.discard(wt) continue } - surfaces.push(await opts.worktree.finalize(wt, summary)) + const surface = await opts.worktree.finalize(wt, summary) + surfaces.push(surface) + finalized.set(surface.worktreeRef, wt) } catch (err) { // Best-effort cleanup; never mask the original failure. await opts.worktree.discard(wt).catch(() => {}) @@ -124,6 +133,22 @@ export function improvementDriver(opts: ImprovementDriverOptions): SurfacePropos } return surfaces }, + async cleanup(retainWorktreeRefs = []) { + const retained = new Set(retainWorktreeRefs) + const errors: unknown[] = [] + for (const [worktreeRef, worktree] of finalized) { + if (retained.has(worktreeRef)) continue + try { + await opts.worktree.discard(worktree) + finalized.delete(worktreeRef) + } catch (cause) { + errors.push(cause) + } + } + if (errors.length > 0) { + throw new AggregateError(errors, 'improvementDriver: failed to discard candidate worktrees') + } + }, } } diff --git a/src/improvement/index.ts b/src/improvement/index.ts index 321cef8d..e4547308 100644 --- a/src/improvement/index.ts +++ b/src/improvement/index.ts @@ -2,13 +2,10 @@ * `@tangle-network/agent-runtime` improvement — the CODE-surface proposer for * agent-eval's improvement loop. * - * The ONE entry point for optimization is agent-eval's `selfImprove` - * (`@tangle-network/agent-eval/contract`) — text/config surfaces, held-out gated, - * with `analyzeGeneration` for analyst-fed reflection and `analyzeRuns` / - * `fromOtelSpans` / `partitionRunsByAuthoringModel` for production intake + - * cohorting. This module supplies only the one genuinely runtime-specific piece: - * a CODE-surface `SurfaceProposer` you pass to `selfImprove` as `proposer`, which - * mutates a git worktree via a pluggable `CandidateGenerator`: + * The public entry point is `improve()`, a profile-aware facade over agent-eval's + * `selfImprove`. This module also supplies the runtime-specific code candidate + * producer, which mutates an isolated git worktree via a pluggable + * `CandidateGenerator`: * - `reflectiveGenerator` — cheap, no sandbox, applies pre-drafted patches * - `agenticGenerator` — full coding harness in the worktree, multi-shot */ @@ -22,8 +19,10 @@ export { } from './agentic-generator' export { mcpBuildPrompt, toolBuildPrompt } from './build-prompts' export { + type ImproveCodeOptions, type ImproveOptions, type ImproveResult, + type ImproveSkillsOptions, type ImproveSurface, improve, } from './improve' @@ -31,6 +30,7 @@ export { type CandidateGenerator, type ImprovementDriverOptions, improvementDriver, + type ManagedImprovementDriver, } from './improvement-driver' export { type McpServeSpec, mcpServeVerifier } from './mcp-serve-verifier' export { diff --git a/src/index.ts b/src/index.ts index a3410db3..9482c9b1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -176,11 +176,13 @@ export type { OtelExportConfig, OtelExporter, OtelSpan, + RuntimeEventOtelOptions, } from './otel-export' // ── OTEL export + trace propagation + eval-run provenance ──────────── export { buildLoopOtelSpans, buildLoopSpanNodes, + buildRuntimeEventOtelSpans, createOtelExporter, exportEvalRuns, INTELLIGENCE_WIRE_VERSION, diff --git a/src/intelligence/index.ts b/src/intelligence/index.ts index c89016ed..5dd8438c 100644 --- a/src/intelligence/index.ts +++ b/src/intelligence/index.ts @@ -23,13 +23,18 @@ * @experimental */ +import { contentHash } from '@tangle-network/agent-eval' +import type { AgentProfile } from '@tangle-network/agent-interface' import { buildLoopOtelSpans, + buildRuntimeEventOtelSpans, createOtelExporter, flatOtelSpan, type OtelExporter, } from '../otel-export' import type { LoopTraceEvent } from '../runtime/types' +import type { RuntimeTelemetryOptions } from '../sanitize' +import type { RuntimeStreamEvent } from '../types' import { resolveIntelligenceBaseUrl } from './delivery' import { defaultEffortTier, @@ -146,6 +151,20 @@ export interface RunRecord { model?: string provider?: string loopEvents?: LoopTraceEvent[] + runtimeEvents?: RuntimeStreamEvent[] + profile?: AgentProfile + sessionId?: string + harness?: string + repository?: string + commitSha?: string + timing?: { startedAt: number; completedAt: number; durationMs: number } + tokens?: { + input: number + output: number + cachedInput?: number + reasoning?: number + } + error?: { name: string; message: string; code?: string } } /** @@ -162,6 +181,13 @@ export interface RunReport { model?: string provider?: string loopEvents?: LoopTraceEvent[] + runtimeEvents?: RuntimeStreamEvent[] + profile?: AgentProfile + sessionId?: string + harness?: string + commitSha?: string + tokens?: RunRecord['tokens'] + error?: RunRecord['error'] } /** Repo coordinates a product may declare for the (later) Gated-PR mode. The @@ -203,6 +229,12 @@ export interface IntelligenceConfig { checks?: string[] /** Repo access a later PR mode would need. Recorded for `doctor()` only. */ repo?: RepoConfig + /** Full canonical profile used for this agent. Exported redacted with a stable hash. */ + profile?: AgentProfile + /** Commit that produced the running agent, when known. */ + commitSha?: string + /** Runtime-event payload policy. Tool inputs/results remain off unless explicitly enabled. */ + runtimeTelemetry?: RuntimeTelemetryOptions } /** Metadata describing one traced run. `runId`/`traceId` default to fresh ids. */ @@ -347,12 +379,8 @@ function freshRunId(): string { return `run-${randomHex(16)}` } -/** Serialize a redacted value to a bounded string for a span attribute. - * `loopEventToOtelSpan` only stamps string/number/boolean payload fields, so a - * structured input/output must be flattened here. Bounded to keep span - * attributes small; the full payload is the consumer's own store, not the span. */ -const previewMaxChars = 4096 -function previewJson(value: unknown): string { +/** Serialize a redacted value without dropping customer trace content. */ +function serializeJson(value: unknown): string { let s: string if (typeof value === 'string') s = value else { @@ -362,7 +390,7 @@ function previewJson(value: unknown): string { s = String(value) } } - return s.length > previewMaxChars ? `${s.slice(0, previewMaxChars)}…[truncated]` : s + return s } function randomHex(chars: number): string { @@ -416,24 +444,24 @@ export function createIntelligenceClient(config: IntelligenceConfig): Intelligen function exportTrace(meta: TraceMeta, outcome: TraceOutcome, output: unknown): void { const ex = getExporter() if (!ex) return - const labels: Record = { - project: config.project, - 'tangle.effort.intelligence_off': outcome.intelligenceOff, - 'tangle.usage.inference_usd': outcome.usage.inferenceUsd, - 'tangle.usage.intelligence_usd': outcome.usage.intelligenceUsd, - ...(meta.model ? { 'gen_ai.request.model': meta.model } : {}), - ...(meta.provider ? { 'provider.name': meta.provider } : {}), - ...(typeof outcome.success === 'boolean' - ? { 'tangle.outcome.success': outcome.success } - : {}), - ...(typeof outcome.score === 'number' ? { 'tangle.outcome.score': outcome.score } : {}), - ...(meta.labels ?? {}), - } - const redactedInput = meta.input !== undefined ? redactor(meta.input) : undefined - const redactedOutput = output !== undefined ? redactor(output) : undefined - if (redactedInput !== undefined) labels['tangle.input'] = previewJson(redactedInput) - if (redactedOutput !== undefined) labels['tangle.output'] = previewJson(redactedOutput) try { + const labels: Record = { + project: config.project, + 'tangle.effort.intelligence_off': outcome.intelligenceOff, + 'tangle.usage.inference_usd': outcome.usage.inferenceUsd, + 'tangle.usage.intelligence_usd': outcome.usage.intelligenceUsd, + ...(meta.model ? { 'gen_ai.request.model': meta.model } : {}), + ...(meta.provider ? { 'provider.name': meta.provider } : {}), + ...(typeof outcome.success === 'boolean' + ? { 'tangle.outcome.success': outcome.success } + : {}), + ...(typeof outcome.score === 'number' ? { 'tangle.outcome.score': outcome.score } : {}), + ...(meta.labels ?? {}), + } + const redactedInput = meta.input !== undefined ? redactor(meta.input) : undefined + const redactedOutput = output !== undefined ? redactor(output) : undefined + if (redactedInput !== undefined) labels['tangle.input'] = serializeJson(redactedInput) + if (redactedOutput !== undefined) labels['tangle.output'] = serializeJson(redactedOutput) // Flat span with VERBATIM attribute keys — the plane's session/model/ // cost readers exact-match `tangle.sessionId` / `gen_ai.request.model`, // so the loop-namespacing builder must not be used here. @@ -453,36 +481,92 @@ export function createIntelligenceClient(config: IntelligenceConfig): Intelligen function exportRunRecord(record: RunRecord): string { const ex = getExporter() if (!ex) return record.traceId - // Clamp the OFF billing invariant on export — the proof holds even if a - // caller mis-reports an intelligence split at the OFF tier. - const intelligenceUsd = intelligenceOff ? 0 : record.outcome.usage.intelligenceUsd - const labels: Record = { - project: record.project, - 'tangle.target': record.target, - 'tangle.effort.intelligence_off': intelligenceOff, - 'tangle.usage.inference_usd': record.outcome.usage.inferenceUsd, - 'tangle.usage.intelligence_usd': intelligenceUsd, - ...(record.model ? { 'gen_ai.request.model': record.model } : {}), - ...(record.provider ? { 'provider.name': record.provider } : {}), - ...(typeof record.outcome.success === 'boolean' - ? { 'tangle.outcome.success': record.outcome.success } - : {}), - ...(typeof record.outcome.score === 'number' - ? { 'tangle.outcome.score': record.outcome.score } - : {}), - } - const redactedInput = record.input !== undefined ? redactor(record.input) : undefined - const redactedOutput = record.output !== undefined ? redactor(record.output) : undefined - if (redactedInput !== undefined) labels['tangle.input'] = previewJson(redactedInput) - if (redactedOutput !== undefined) labels['tangle.output'] = previewJson(redactedOutput) try { + // Clamp the OFF billing invariant on export — the proof holds even if a + // caller mis-reports an intelligence split at the OFF tier. + const intelligenceUsd = intelligenceOff ? 0 : record.outcome.usage.intelligenceUsd + const repository = + record.repository ?? (config.repo ? `${config.repo.owner}/${config.repo.name}` : undefined) + const labels: Record = { + project: record.project, + 'tangle.target': record.target, + 'tangle.effort.intelligence_off': intelligenceOff, + 'tangle.usage.inference_usd': record.outcome.usage.inferenceUsd, + 'tangle.usage.intelligence_usd': intelligenceUsd, + ...(record.model ? { 'gen_ai.request.model': record.model } : {}), + ...(record.provider ? { 'provider.name': record.provider } : {}), + ...(record.sessionId + ? { + 'tangle.sessionId': record.sessionId, + 'gen_ai.conversation.id': record.sessionId, + } + : {}), + ...(record.harness ? { 'tangle.agent.harness': record.harness } : {}), + ...(repository ? { 'vcs.repository.name': repository } : {}), + ...(record.commitSha ? { 'vcs.ref.head.revision': record.commitSha } : {}), + ...(record.timing + ? { + 'tangle.started_at_ms': record.timing.startedAt, + 'tangle.completed_at_ms': record.timing.completedAt, + 'tangle.duration_ms': record.timing.durationMs, + } + : {}), + ...(record.tokens + ? { + 'gen_ai.usage.input_tokens': record.tokens.input, + 'gen_ai.usage.output_tokens': record.tokens.output, + ...(record.tokens.cachedInput !== undefined + ? { 'gen_ai.usage.cache_read_input_tokens': record.tokens.cachedInput } + : {}), + ...(record.tokens.reasoning !== undefined + ? { 'gen_ai.usage.reasoning_tokens': record.tokens.reasoning } + : {}), + } + : {}), + ...(typeof record.outcome.success === 'boolean' + ? { 'tangle.outcome.success': record.outcome.success } + : {}), + ...(typeof record.outcome.score === 'number' + ? { 'tangle.outcome.score': record.outcome.score } + : {}), + ...(record.error + ? { + 'error.type': record.error.code ?? record.error.name, + 'error.message': serializeJson(redactor(record.error.message)), + } + : {}), + ...(record.runtimeEvents + ? { 'tangle.runtime.event_count': record.runtimeEvents.length } + : {}), + } + if (record.profile) { + labels['tangle.agent.profile'] = serializeJson(redactor(record.profile)) + labels['tangle.agent.profile_hash'] = contentHash(record.profile) + if (record.profile.name) labels['gen_ai.agent.name'] = record.profile.name + } + const redactedInput = record.input !== undefined ? redactor(record.input) : undefined + const redactedOutput = record.output !== undefined ? redactor(record.output) : undefined + if (redactedInput !== undefined) labels['tangle.input'] = serializeJson(redactedInput) + if (redactedOutput !== undefined) labels['tangle.output'] = serializeJson(redactedOutput) + const now = Date.now() const runSpan = flatOtelSpan( 'tangle.intelligence.run', { 'tangle.runId': record.runId, ...labels }, record.traceId, - Date.now(), + record.timing?.startedAt ?? now, + undefined, + record.timing?.completedAt ?? now, ) ex.exportSpan(runSpan) + if (record.runtimeEvents && record.runtimeEvents.length > 0) { + const spans = buildRuntimeEventOtelSpans( + record.runtimeEvents, + record.traceId, + runSpan.spanId, + { ...config.runtimeTelemetry, redact: redactor }, + ) + for (const span of spans) ex.exportSpan(span) + } // The loop topology (when present) exports under the SAME traceId, parented // under the run span — reusing the shipped builder, never a second one. if (record.loopEvents && record.loopEvents.length > 0) { diff --git a/src/intelligence/with-intelligence.test.ts b/src/intelligence/with-intelligence.test.ts index 09d6538d..4c257a23 100644 --- a/src/intelligence/with-intelligence.test.ts +++ b/src/intelligence/with-intelligence.test.ts @@ -206,6 +206,7 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { it('ships one run span carrying target + usage split + model, best-effort', async () => { vi.useFakeTimers() try { + const longInput = 'x'.repeat(5000) const posts: unknown[] = [] const otlpSpy = vi.fn(async (_url: unknown, init: unknown) => { const body = (init as { body?: string })?.body @@ -217,11 +218,30 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { const pull = vi.fn(async () => jsonResponse(COMPOSED)) as unknown as typeof fetch const agent = withIntelligence( async (_input: { q: string }, a) => { + expect(a.runId).toMatch(/^run-/) + expect(a.traceId).toHaveLength(32) a.record({ success: true, usage: { inferenceUsd: 0.002, intelligenceUsd: 0 }, model: 'kimi-k2', provider: 'moonshot', + sessionId: 'session-1', + runtimeEvents: [ + { + type: 'tool_call', + toolName: 'mcp__linear__linear_graphql', + toolCallId: 'call-1', + args: { query: longInput }, + }, + { + type: 'llm_call', + model: 'kimi-k2', + tokensIn: 11, + tokensOut: 7, + costUsd: 0.002, + latencyMs: 250, + }, + ], }) return 'answer' }, @@ -231,11 +251,18 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { apiKey: 'k', baseUrl: 'https://plane.test', fetchImpl: pull, + profile: { + name: 'support-agent', + prompt: { systemPrompt: 'Handle support requests.' }, + tools: { mcp__linear__linear_graphql: true }, + }, + commitSha: 'a'.repeat(40), + repo: { owner: 'tangle-network', name: 'support', baseBranch: 'main' }, + runtimeTelemetry: { includeControlPayloads: true }, }, ) - await agent({ q: 'refund please' }) - // Force the exporter's interval flush so the batched span POSTs. - await vi.advanceTimersByTimeAsync(6000) + await agent({ q: longInput }) + await agent.flush() expect(posts.length).toBeGreaterThan(0) const attrs = attrsOf(posts[0]) @@ -245,6 +272,20 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { expect(attrs['tangle.usage.intelligence_usd']).toBe(0) expect(attrs['tangle.outcome.success']).toBe(true) expect(attrs['gen_ai.request.model']).toBe('kimi-k2') + expect(attrs['tangle.sessionId']).toBe('session-1') + expect(attrs['vcs.repository.name']).toBe('tangle-network/support') + expect(attrs['vcs.ref.head.revision']).toBe('a'.repeat(40)) + expect(attrs['gen_ai.usage.input_tokens']).toBe(11) + expect(attrs['gen_ai.usage.output_tokens']).toBe(7) + expect(String(attrs['tangle.input'])).toContain(longInput) + expect(String(attrs['tangle.input'])).not.toContain('[truncated]') + expect(JSON.parse(String(attrs['tangle.agent.profile']))).toMatchObject({ + name: 'support-agent', + tools: { mcp__linear__linear_graphql: true }, + }) + expect(attrs['tangle.agent.profile_hash']).toEqual(expect.any(String)) + expect(attrs['tool.name']).toBe('mcp__linear__linear_graphql') + expect(String(attrs['tool.input'])).toContain(longInput) } finally { vi.useRealTimers() } @@ -267,4 +308,37 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { vi.unstubAllEnvs() } }) + + it('exports a failed run before rethrowing the agent error', async () => { + vi.useFakeTimers() + try { + const posts: unknown[] = [] + vi.stubGlobal( + 'fetch', + vi.fn(async (_url: unknown, init: unknown) => { + const body = (init as { body?: string })?.body + if (body) posts.push(JSON.parse(body)) + return { ok: true, status: 200, async json() {} } as unknown as Response + }), + ) + const pull = vi.fn(async () => jsonResponse(COMPOSED)) as unknown as typeof fetch + const agent = withIntelligence( + async () => { + throw Object.assign(new Error('provider exhausted'), { code: 'rate_limit' }) + }, + { project: 'support-agent', apiKey: 'k', baseUrl: 'https://plane.test', fetchImpl: pull }, + ) + + await expect(agent(null)).rejects.toThrow('provider exhausted') + await agent.flush() + + const attrs = attrsOf(posts[0]) + expect(attrs['tangle.outcome.success']).toBe(false) + expect(attrs['error.type']).toBe('rate_limit') + expect(attrs['error.message']).toBe('provider exhausted') + expect(attrs['tangle.duration_ms']).toEqual(expect.any(Number)) + } finally { + vi.useRealTimers() + } + }) }) diff --git a/src/intelligence/with-intelligence.ts b/src/intelligence/with-intelligence.ts index 2c1fe939..69160a50 100644 --- a/src/intelligence/with-intelligence.ts +++ b/src/intelligence/with-intelligence.ts @@ -51,6 +51,9 @@ import { * `proposals`/`applyProfile` surface the promoted profile DIFFS — never * auto-applied; `record` enriches the {@link RunRecord} that is sent. */ export interface AppliedIntelligence { + /** Stable ids shared by the run span and every nested runtime/loop span. */ + runId: string + traceId: string /** The certified profile in effect (null when none promoted / pull failed — * fail-closed: the agent runs on its base surface). */ certified: CertifiedProfile | null @@ -96,6 +99,62 @@ export interface IntelligenceHookConfig extends IntelligenceConfig { export type IntelligenceWrapped = ((input: I) => Promise) & { refresh(): Promise proposals(): ProposedProfileDiff[] + /** Flush buffered trace spans before a short-lived process exits. */ + flush(): Promise +} + +interface RuntimeEventSummary { + inferenceUsd: number + inputTokens: number + outputTokens: number + model?: string + sessionId?: string + success?: boolean + error?: RunRecord['error'] +} + +function summarizeRuntimeEvents( + events: NonNullable, +): RuntimeEventSummary { + const summary: RuntimeEventSummary = { inferenceUsd: 0, inputTokens: 0, outputTokens: 0 } + for (const event of events) { + if ('session' in event && event.session) summary.sessionId = event.session.id + if (event.type === 'llm_call') { + summary.model = event.model + summary.inferenceUsd += event.costUsd ?? 0 + summary.inputTokens += event.tokensIn ?? 0 + summary.outputTokens += event.tokensOut ?? 0 + } else if (event.type === 'backend_error') { + summary.success = false + summary.error = { + name: event.error?.kind ?? 'BackendError', + message: event.message, + ...(event.error?.status !== undefined ? { code: String(event.error.status) } : {}), + } + } else if (event.type === 'final') { + summary.success = event.status === 'completed' + if (event.error) { + summary.error = { + name: event.error.kind, + message: event.error.message, + ...(event.error.status !== undefined ? { code: String(event.error.status) } : {}), + } + } + } + } + return summary +} + +function runError(cause: unknown): NonNullable { + if (cause instanceof Error) { + const code = (cause as Error & { code?: unknown }).code + return { + name: cause.name || 'Error', + message: cause.message, + ...(typeof code === 'string' || typeof code === 'number' ? { code: String(code) } : {}), + } + } + return { name: 'Error', message: String(cause) } } /** @@ -142,11 +201,16 @@ export function withIntelligence( } const wrapped = (async (input: I): Promise => { + const runId = client.freshRunId() + const traceId = client.freshTraceId() + const startedAt = Date.now() await refresh() const certified = source.current() const proposals = currentProposals() const report: RunReport = {} const applied: AppliedIntelligence = { + runId, + traceId, certified, composePrompt: (base: string) => composeCertifiedPrompt(base, certified), proposals, @@ -155,34 +219,68 @@ export function withIntelligence( record: (r: RunReport) => Object.assign(report, r), } - const output = await agent(input, applied) - - const usage = { - inferenceUsd: report.usage?.inferenceUsd ?? report.costUsd ?? 0, - intelligenceUsd: report.usage?.intelligenceUsd ?? 0, + function exportCompleted(output: unknown, caught?: unknown): void { + const completedAt = Date.now() + const eventSummary = summarizeRuntimeEvents(report.runtimeEvents ?? []) + const error = report.error ?? (caught !== undefined ? runError(caught) : eventSummary.error) + const tokens = + report.tokens ?? + (eventSummary.inputTokens > 0 || eventSummary.outputTokens > 0 + ? { input: eventSummary.inputTokens, output: eventSummary.outputTokens } + : undefined) + const profile = report.profile ?? config.profile + const record: RunRecord = { + runId, + traceId, + project: config.project, + target, + input, + output, + outcome: { + success: + report.success ?? + (caught !== undefined ? false : (eventSummary.success ?? error === undefined)), + ...(report.score !== undefined ? { score: report.score } : {}), + usage: { + inferenceUsd: report.usage?.inferenceUsd ?? report.costUsd ?? eventSummary.inferenceUsd, + intelligenceUsd: report.usage?.intelligenceUsd ?? 0, + }, + }, + timing: { startedAt, completedAt, durationMs: completedAt - startedAt }, + ...((report.model ?? eventSummary.model) + ? { model: report.model ?? eventSummary.model } + : {}), + ...(report.provider !== undefined ? { provider: report.provider } : {}), + ...(report.loopEvents !== undefined ? { loopEvents: report.loopEvents } : {}), + ...(report.runtimeEvents !== undefined ? { runtimeEvents: report.runtimeEvents } : {}), + ...(profile !== undefined ? { profile } : {}), + ...((report.sessionId ?? eventSummary.sessionId) + ? { sessionId: report.sessionId ?? eventSummary.sessionId } + : {}), + ...((report.harness ?? profile?.harness) + ? { harness: report.harness ?? profile?.harness } + : {}), + ...((report.commitSha ?? config.commitSha) + ? { commitSha: report.commitSha ?? config.commitSha } + : {}), + ...(tokens !== undefined ? { tokens } : {}), + ...(error !== undefined ? { error } : {}), + } + client.exportRunRecord(record) } - const record: RunRecord = { - runId: client.freshRunId(), - traceId: client.freshTraceId(), - project: config.project, - target, - input, - output, - outcome: { - ...(report.success !== undefined ? { success: report.success } : {}), - ...(report.score !== undefined ? { score: report.score } : {}), - usage, - }, - ...(report.model !== undefined ? { model: report.model } : {}), - ...(report.provider !== undefined ? { provider: report.provider } : {}), - ...(report.loopEvents !== undefined ? { loopEvents: report.loopEvents } : {}), + + try { + const output = await agent(input, applied) + exportCompleted(output) + return output + } catch (cause) { + exportCompleted(undefined, cause) + throw cause } - // Best-effort: a send failure never fails the agent's turn. - client.exportRunRecord(record) - return output }) as IntelligenceWrapped wrapped.refresh = refresh wrapped.proposals = currentProposals + wrapped.flush = client.flush return wrapped } diff --git a/src/otel-export.ts b/src/otel-export.ts index 92509aac..81c65850 100644 --- a/src/otel-export.ts +++ b/src/otel-export.ts @@ -9,6 +9,9 @@ * (which get converted to OTLP spans automatically). */ +import { type RuntimeTelemetryOptions, sanitizeRuntimeStreamEvent } from './sanitize' +import type { RuntimeStreamEvent } from './types' + export interface OtelExportConfig { /** OTLP endpoint. Reads OTEL_EXPORTER_OTLP_ENDPOINT env by default. */ endpoint?: string @@ -207,21 +210,121 @@ export function flatOtelSpan( traceId: string, timestampMs: number, parentSpanId?: string, + endTimestampMs = timestampMs, ): OtelSpan { - const ts = msToNs(timestampMs) + const start = msToNs(timestampMs) + const end = msToNs(Math.max(timestampMs, endTimestampMs)) return { traceId: padTraceId(traceId), spanId: generateSpanId(), parentSpanId: parentSpanId ? padSpanId(parentSpanId) : undefined, name, kind: 1, - startTimeUnixNano: ts, - endTimeUnixNano: ts, + startTimeUnixNano: start, + endTimeUnixNano: end, attributes: toAttributes(attributes), status: { code: 1 }, } } +export interface RuntimeEventOtelOptions extends RuntimeTelemetryOptions { + /** Final customer redactor applied after the schema-aware runtime sanitizer. */ + redact?: (value: unknown) => unknown +} + +function eventTimestampMs(event: RuntimeStreamEvent): number { + if ('timestamp' in event && typeof event.timestamp === 'string') { + const parsed = Date.parse(event.timestamp) + if (Number.isFinite(parsed)) return parsed + } + return Date.now() +} + +function serialized(value: unknown): string { + try { + return JSON.stringify(value) ?? String(value) + } catch { + return String(value) + } +} + +function mcpIdentity(toolName: string): { server?: string; tool?: string } { + if (!toolName.startsWith('mcp__')) return {} + const [, server, ...toolParts] = toolName.split('__') + return { + ...(server ? { server } : {}), + ...(toolParts.length > 0 ? { tool: toolParts.join('__') } : {}), + } +} + +/** Convert normalized runtime events into lossless, redacted child spans. */ +export function buildRuntimeEventOtelSpans( + events: ReadonlyArray, + traceId: string, + parentSpanId?: string, + options: RuntimeEventOtelOptions = {}, +): OtelSpan[] { + return events.map((event) => { + const sanitized = sanitizeRuntimeStreamEvent(event, options) + const safe = options.redact ? options.redact(sanitized) : sanitized + const record = + safe && typeof safe === 'object' && !Array.isArray(safe) + ? (safe as Record) + : { value: safe } + const attrs: Record = { + 'tangle.runtime.event_type': event.type, + 'tangle.runtime.event': serialized(record), + } + let name = `tangle.runtime.${event.type}` + + if (event.type === 'tool_call' || event.type === 'tool_result') { + name = `agent.${event.type}` + attrs['tool.name'] = event.toolName + if (event.toolCallId) attrs['tool.call_id'] = event.toolCallId + const mcp = mcpIdentity(event.toolName) + if (mcp.server) attrs['mcp.server'] = mcp.server + if (mcp.tool) attrs['mcp.tool.name'] = mcp.tool + const payload = event.type === 'tool_call' ? record.args : record.result + if (payload !== undefined) { + attrs[event.type === 'tool_call' ? 'tool.input' : 'tool.output'] = serialized(payload) + } + } else if (event.type === 'llm_call') { + name = 'gen_ai.client.inference' + attrs['gen_ai.request.model'] = event.model + if (event.tokensIn !== undefined) attrs['gen_ai.usage.input_tokens'] = event.tokensIn + if (event.tokensOut !== undefined) attrs['gen_ai.usage.output_tokens'] = event.tokensOut + if (event.costUsd !== undefined) attrs['tangle.cost.usd'] = event.costUsd + if (event.latencyMs !== undefined) attrs['tangle.latency_ms'] = event.latencyMs + if (event.finishReason !== undefined) + attrs['gen_ai.response.finish_reasons'] = event.finishReason + } else if (event.type === 'backend_error') { + attrs['error.type'] = event.error?.kind ?? 'backend' + attrs['error.message'] = event.message + } else if (event.type === 'final') { + attrs['tangle.outcome.status'] = event.status + attrs['tangle.outcome.reason'] = event.reason + if (event.error) { + attrs['error.type'] = event.error.kind + attrs['error.message'] = event.error.message + } + } + + const startMs = eventTimestampMs(event) + const endMs = + event.type === 'llm_call' && event.latencyMs !== undefined + ? startMs + event.latencyMs + : startMs + const span = flatOtelSpan(name, attrs, traceId, startMs, parentSpanId, endMs) + if ( + event.type === 'backend_error' || + (event.type === 'final' && event.status !== 'completed') + ) { + span.status = { code: 2, message: attrs['error.message']?.toString() ?? event.type } + } + return span + }) +} + /** * Sink-neutral node in a reconstructed loop span tree. The root node's * `parentSpanId` is `undefined` — sinks decide how to parent it (the OTEL diff --git a/tests/agent.test.ts b/tests/agent.test.ts index bca2e3f5..24c4a53c 100644 --- a/tests/agent.test.ts +++ b/tests/agent.test.ts @@ -167,6 +167,14 @@ describe('resolveSubjectPath', () => { knowledge: '.agent-knowledge', personas: 'personas', rag: 'rag', + skills: 'skills', + mcp: 'mcp', + hooks: 'hooks', + subagents: 'agents', + workflows: 'workflows', + rolloutPolicy: 'rollout-policy.json', + agentProfile: 'agent-profile.json', + code: 'src', } it('routes system-prompt subject to /
.md', () => { @@ -195,6 +203,37 @@ describe('resolveSubjectPath', () => { expect(r?.repoRelativePath).toBe('tools/list_invoices/examples.md') }) + it.each([ + [{ kind: 'skill', name: 'linear-close' } as const, 'skills/linear-close/SKILL.md'], + [ + { kind: 'mcp', server: 'linear', tool: 'update_issue' } as const, + 'mcp/linear/update_issue.md', + ], + [{ kind: 'hook', name: 'pre-dispatch' } as const, 'hooks/pre-dispatch.md'], + [{ kind: 'subagent', name: 'reviewer' } as const, 'agents/reviewer.md'], + [{ kind: 'workflow', name: 'linear-task' } as const, 'workflows/linear-task.md'], + [{ kind: 'rollout-policy', field: 'k' } as const, 'rollout-policy.json'], + [{ kind: 'agent-profile', field: 'prompt.systemPrompt' } as const, 'agent-profile.json'], + [{ kind: 'code', path: 'workers/dispatch.ts' } as const, 'src/workers/dispatch.ts'], + ])('routes the %s finding to its declared surface', (subject, expected) => { + expect(resolveSubjectPath(subject, surfaces, tmpRoot)?.repoRelativePath).toBe(expected) + }) + + it('rejects a code finding that escapes its declared source root', () => { + expect( + resolveSubjectPath({ kind: 'code', path: '../../secrets.env' }, surfaces, tmpRoot), + ).toBeNull() + }) + + it('rejects raw-knowledge and RAG findings that escape their declared roots', () => { + expect( + resolveSubjectPath({ kind: 'knowledge.raw', sourceId: '../../secrets' }, surfaces, tmpRoot), + ).toBeNull() + expect( + resolveSubjectPath({ kind: 'rag', corpus: 'irs', docId: '../../secrets' }, surfaces, tmpRoot), + ).toBeNull() + }) + it('returns null when subject targets an undeclared optional surface', () => { const noRag = { ...surfaces, rag: undefined } const r = resolveSubjectPath({ kind: 'rag', corpus: 'irs', docId: 'foo' }, noRag, tmpRoot) @@ -576,6 +615,25 @@ describe('validateSurfaces', () => { expect(flagged).toHaveLength(1) expect(flagged[0]!.surface).toBe('rag') }) + + it('distinguishes files from directories instead of treating existence as valid', () => { + writeFileSync(join(tmpRoot, 'not-a-directory'), 'file\n') + mkdirSync(join(tmpRoot, 'not-a-file')) + const issues = validateSurfaces( + { + systemPrompt: 'prompts', + tools: 'not-a-directory', + rubric: 'not-a-file', + knowledge: '.agent-knowledge', + personas: 'personas', + }, + tmpRoot, + ) + expect(issues).toEqual([ + { surface: 'tools', path: 'not-a-directory', reason: 'not-directory' }, + { surface: 'rubric', path: 'not-a-file', reason: 'not-file' }, + ]) + }) }) describe('AgentRunInvocation streaming contract', () => { diff --git a/tests/candidate-execution-prepare.test.ts b/tests/candidate-execution-prepare.test.ts index 65cb7fb3..f27711c7 100644 --- a/tests/candidate-execution-prepare.test.ts +++ b/tests/candidate-execution-prepare.test.ts @@ -266,6 +266,15 @@ function fixture(active = false): { }, attempt: { number: 1, maxAttempts: 1, retryPolicy: 'none' }, model: { requested: 'provider/model', reasoningEffort: 'high' }, + grader: { + name: 'fixture-executable-grader', + version: '1.0.0', + artifact: { + locator: { kind: 's3', bucket: 'candidate-test-artifacts', key: 'grader/fixture' }, + sha256: sha('a'), + byteLength: 1, + }, + }, executionRoots: { taskRoot: '/workspace/task', ...(active ? { candidateRoot: '/opt/candidate' } : {}), diff --git a/tests/helpers/candidate-execution-fixture.ts b/tests/helpers/candidate-execution-fixture.ts index 3b74bddc..8f663049 100644 --- a/tests/helpers/candidate-execution-fixture.ts +++ b/tests/helpers/candidate-execution-fixture.ts @@ -29,6 +29,8 @@ const roots: string[] = [] export const candidateSha = (character: string): Sha256Digest => `sha256:${character.repeat(64)}` +const fixtureGraderBytes = Buffer.from('fixture executable grader', 'utf8') + export function cleanupCandidateFixtures(): void { for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true }) } @@ -228,7 +230,7 @@ export function createCandidateOutputFixture(): { stored.set(sha256, detached) return ref } - const graderArtifact = put(Buffer.from('fixture executable grader', 'utf8'), 'grader') + const graderArtifact = put(fixtureGraderBytes, 'grader') return { outputArtifacts: { put: async ({ bytes, purpose }) => put(bytes, purpose), @@ -357,6 +359,15 @@ export function createCandidateExecutionFixture(active = false): CandidateExecut }, attempt: { number: 1, maxAttempts: 1, retryPolicy: 'none' }, model: { requested: 'provider/model', reasoningEffort: 'high' }, + grader: { + name: 'fixture-executable-grader', + version: '1.0.0', + artifact: { + locator: { kind: 's3', bucket: 'candidate-test-artifacts', key: 'grader/fixture' }, + sha256: sha256Bytes(fixtureGraderBytes), + byteLength: fixtureGraderBytes.byteLength, + }, + }, executionRoots: { taskRoot: '/workspace/task', ...(active ? { candidateRoot: '/opt/candidate' } : {}), diff --git a/tests/improve.test.ts b/tests/improve.test.ts index 0226afd4..b74d8746 100644 --- a/tests/improve.test.ts +++ b/tests/improve.test.ts @@ -110,7 +110,7 @@ describe('improve() — facade over selfImprove', () => { await expect( improve(profile, [], { surface: 'prompt', - generator: scriptedWinner, + gate: 'none', scenarios, judge, agent, @@ -125,7 +125,6 @@ describe('improve() — facade over selfImprove', () => { const out = await improve(profile, [], { surface: 'prompt', gate: 'none', - generator: scriptedWinner, scenarios, judge, agent, diff --git a/tests/improvement-driver.test.ts b/tests/improvement-driver.test.ts index 9696999d..93b16f37 100644 --- a/tests/improvement-driver.test.ts +++ b/tests/improvement-driver.test.ts @@ -194,4 +194,36 @@ describe('improvementDriver — reflective generator', () => { // worktree remains. expect(git(['worktree', 'list'], repoRoot).split('\n').length).toBe(1) }) + + it('attempts every candidate cleanup even when one discard fails', async () => { + let created = 0 + const discardAttempts: string[] = [] + const driver = improvementDriver({ + generator: { + kind: 'cleanup-stub', + proposesWithoutFindings: true, + async generate() { + return { applied: true, summary: 'candidate' } + }, + }, + worktree: { + async create({ baseRef }) { + const id = String(created++) + return { path: `/tmp/candidate-${id}`, branch: `candidate-${id}`, baseRef } + }, + async finalize(worktree) { + return { kind: 'code', worktreeRef: worktree.path, baseRef: worktree.baseRef } + }, + async discard(worktree) { + discardAttempts.push(worktree.path) + if (worktree.path.endsWith('-0')) throw new Error('first discard failed') + }, + }, + baseRef: 'main', + }) + + await driver.propose({ ...ctxWith([]), populationSize: 2 }) + await expect(driver.cleanup()).rejects.toThrow(/failed to discard candidate worktrees/) + expect(discardAttempts).toEqual(['/tmp/candidate-0', '/tmp/candidate-1']) + }) }) diff --git a/tests/otel-export.test.ts b/tests/otel-export.test.ts index 44702fa7..3439663b 100644 --- a/tests/otel-export.test.ts +++ b/tests/otel-export.test.ts @@ -1,6 +1,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest' import { buildLoopOtelSpans, + buildRuntimeEventOtelSpans, createOtelExporter, exportEvalRuns, INTELLIGENCE_WIRE_VERSION, @@ -21,6 +22,62 @@ function attrMap(span: OtelSpan): Record { + it('preserves opted-in MCP tool payloads and LLM usage without truncation', () => { + const longQuery = 'q'.repeat(5000) + const spans = buildRuntimeEventOtelSpans( + [ + { + type: 'tool_call', + toolName: 'mcp__linear__linear_graphql', + toolCallId: 'call-1', + args: { query: longQuery }, + timestamp: '2026-07-10T00:00:00.000Z', + }, + { + type: 'llm_call', + model: 'anthropic/claude-sonnet-4.6', + tokensIn: 12, + tokensOut: 7, + costUsd: 0.004, + latencyMs: 350, + timestamp: '2026-07-10T00:00:01.000Z', + }, + ], + 'a'.repeat(32), + 'b'.repeat(16), + { includeControlPayloads: true }, + ) + + const tool = attrMap(spans[0]!) + expect(tool['tool.name']).toBe('mcp__linear__linear_graphql') + expect(tool['mcp.server']).toBe('linear') + expect(tool['mcp.tool.name']).toBe('linear_graphql') + expect(String(tool['tool.input'])).toContain(longQuery) + expect(String(tool['tangle.runtime.event'])).not.toContain('[truncated]') + + const llm = attrMap(spans[1]!) + expect(llm['gen_ai.request.model']).toBe('anthropic/claude-sonnet-4.6') + expect(llm['gen_ai.usage.input_tokens']).toBe(12) + expect(llm['gen_ai.usage.output_tokens']).toBe(7) + expect(llm['tangle.cost.usd']).toBe(0.004) + expect(BigInt(spans[1]!.endTimeUnixNano) - BigInt(spans[1]!.startTimeUnixNano)).toBe( + 350_000_000n, + ) + }) + + it('omits control payloads by default while retaining tool identity', () => { + const [span] = buildRuntimeEventOtelSpans( + [{ type: 'tool_call', toolName: 'search', args: { secret: 'value' } }], + 'a'.repeat(32), + ) + const attrs = attrMap(span!) + expect(attrs['tool.name']).toBe('search') + expect(attrs['tool.input']).toBeUndefined() + expect(String(attrs['tangle.runtime.event'])).not.toContain('value') + }) +}) + describe('buildLoopOtelSpans — nested GenAI topology tree', () => { // One dynamic-loop run: round 0 fans out 2 branches (with rationale), then stops. const events = [ diff --git a/tsup.config.ts b/tsup.config.ts index 5d4f4f49..100602eb 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -12,6 +12,7 @@ export default defineConfig({ knowledge: 'src/knowledge/index.ts', profiles: 'src/profiles/index.ts', platform: 'src/platform/index.ts', + 'candidate-execution/index': 'src/candidate-execution/index.ts', 'mcp/index': 'src/mcp/index.ts', 'mcp/bin': 'src/mcp/bin.ts', 'loop-runner-bin': 'src/loop-runner-bin.ts', From 338660dd06e1dc56c83caa4fc1cdb452a1b41e8d Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Sat, 11 Jul 2026 01:29:07 -0600 Subject: [PATCH 2/5] feat(intelligence): ship reviewable improvement lifecycle --- docs/api/README.md | 1 + docs/api/candidate-execution.md | 475 ++++++++++++ docs/api/intelligence.md | 852 ++++++++++++++++++--- docs/api/mcp.md | 2 +- docs/api/primitive-catalog.md | 11 +- docs/canonical-api.md | 7 +- package.json | 4 +- pnpm-lock.yaml | 19 +- src/candidate-execution/bundle.ts | 17 + src/intelligence/improvement-cycle.ts | 506 ++++++++++++ src/intelligence/index.ts | 98 ++- src/intelligence/with-intelligence.test.ts | 53 ++ src/intelligence/with-intelligence.ts | 3 + tests/improvement-cycle.test.ts | 330 ++++++++ typedoc.json | 1 + 15 files changed, 2236 insertions(+), 143 deletions(-) create mode 100644 docs/api/candidate-execution.md create mode 100644 src/candidate-execution/bundle.ts create mode 100644 src/intelligence/improvement-cycle.ts create mode 100644 tests/improvement-cycle.test.ts diff --git a/docs/api/README.md b/docs/api/README.md index 4a62f568..4d679de6 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -8,6 +8,7 @@ - [agent](agent.md) - [analyst-loop](analyst-loop.md) +- [candidate-execution](candidate-execution.md) - [index](index.md) - [intelligence](intelligence.md) - [knowledge](knowledge.md) diff --git a/docs/api/candidate-execution.md b/docs/api/candidate-execution.md new file mode 100644 index 00000000..4c5c878d --- /dev/null +++ b/docs/api/candidate-execution.md @@ -0,0 +1,475 @@ +[**@tangle-network/agent-runtime**](README.md) + +*** + +[@tangle-network/agent-runtime](README.md) / candidate-execution + +# candidate-execution + +## References + +### AgentCandidateExecutionAttemptRecord + +Re-exports [AgentCandidateExecutionAttemptRecord](index.md#agentcandidateexecutionattemptrecord) + +*** + +### AgentCandidateExecutionAttemptRef + +Re-exports [AgentCandidateExecutionAttemptRef](index.md#agentcandidateexecutionattemptref) + +*** + +### AgentCandidateExecutionClaim + +Re-exports [AgentCandidateExecutionClaim](index.md#agentcandidateexecutionclaim) + +*** + +### AgentCandidateExecutionClaimResult + +Re-exports [AgentCandidateExecutionClaimResult](index.md#agentcandidateexecutionclaimresult) + +*** + +### AgentCandidateExecutionClaimStore + +Re-exports [AgentCandidateExecutionClaimStore](index.md#agentcandidateexecutionclaimstore) + +*** + +### AgentCandidateExecutionCleanupHandles + +Re-exports [AgentCandidateExecutionCleanupHandles](index.md#agentcandidateexecutioncleanuphandles) + +*** + +### AgentCandidateExecutionFailureClass + +Re-exports [AgentCandidateExecutionFailureClass](index.md#agentcandidateexecutionfailureclass) + +*** + +### AgentCandidateExecutionFinishResult + +Re-exports [AgentCandidateExecutionFinishResult](index.md#agentcandidateexecutionfinishresult) + +*** + +### AgentCandidateExecutionLease + +Re-exports [AgentCandidateExecutionLease](index.md#agentcandidateexecutionlease) + +*** + +### AgentCandidateExecutionPhase + +Re-exports [AgentCandidateExecutionPhase](index.md#agentcandidateexecutionphase) + +*** + +### AgentCandidateExecutionPhaseResult + +Re-exports [AgentCandidateExecutionPhaseResult](index.md#agentcandidateexecutionphaseresult) + +*** + +### AgentCandidateExecutionRecoveryEvidence + +Re-exports [AgentCandidateExecutionRecoveryEvidence](index.md#agentcandidateexecutionrecoveryevidence) + +*** + +### AgentCandidateExecutionStageResult + +Re-exports [AgentCandidateExecutionStageResult](index.md#agentcandidateexecutionstageresult) + +*** + +### AgentCandidateExecutionTerminalRecord + +Re-exports [AgentCandidateExecutionTerminalRecord](index.md#agentcandidateexecutionterminalrecord) + +*** + +### AgentCandidateExecutionTerminalResult + +Re-exports [AgentCandidateExecutionTerminalResult](index.md#agentcandidateexecutionterminalresult) + +*** + +### AgentCandidateExecutionUsage + +Re-exports [AgentCandidateExecutionUsage](index.md#agentcandidateexecutionusage) + +*** + +### AgentCandidateRetryRejection + +Re-exports [AgentCandidateRetryRejection](index.md#agentcandidateretryrejection) + +*** + +### InMemoryAgentCandidateExecutionClaimStore + +Re-exports [InMemoryAgentCandidateExecutionClaimStore](index.md#inmemoryagentcandidateexecutionclaimstore) + +*** + +### FileAgentCandidateExecutionClaimStore + +Re-exports [FileAgentCandidateExecutionClaimStore](index.md#fileagentcandidateexecutionclaimstore) + +*** + +### FileAgentCandidateExecutionClaimStoreOptions + +Re-exports [FileAgentCandidateExecutionClaimStoreOptions](index.md#fileagentcandidateexecutionclaimstoreoptions) + +*** + +### candidateExecutionClaim + +Re-exports [candidateExecutionClaim](index.md#candidateexecutionclaim) + +*** + +### DisposePreparedAgentCandidateOptions + +Re-exports [DisposePreparedAgentCandidateOptions](index.md#disposepreparedagentcandidateoptions) + +*** + +### disposePreparedAgentCandidateExecution + +Re-exports [disposePreparedAgentCandidateExecution](index.md#disposepreparedagentcandidateexecution) + +*** + +### ExecutePreparedAgentCandidateOptions + +Re-exports [ExecutePreparedAgentCandidateOptions](index.md#executepreparedagentcandidateoptions) + +*** + +### executePreparedAgentCandidate + +Re-exports [executePreparedAgentCandidate](index.md#executepreparedagentcandidate) + +*** + +### persistCandidateOutputArtifact + +Re-exports [persistCandidateOutputArtifact](index.md#persistcandidateoutputartifact) + +*** + +### PrepareAgentCandidateExecutionOptions + +Re-exports [PrepareAgentCandidateExecutionOptions](index.md#prepareagentcandidateexecutionoptions) + +*** + +### prepareAgentCandidateExecution + +Re-exports [prepareAgentCandidateExecution](index.md#prepareagentcandidateexecution) + +*** + +### AgentCandidateModelGrantActivateInput + +Re-exports [AgentCandidateModelGrantActivateInput](index.md#agentcandidatemodelgrantactivateinput) + +*** + +### AgentCandidateModelGrantClient + +Re-exports [AgentCandidateModelGrantClient](index.md#agentcandidatemodelgrantclient) + +*** + +### AgentCandidateModelGrantReservation + +Re-exports [AgentCandidateModelGrantReservation](index.md#agentcandidatemodelgrantreservation) + +*** + +### AgentCandidateModelGrantReserveInput + +Re-exports [AgentCandidateModelGrantReserveInput](index.md#agentcandidatemodelgrantreserveinput) + +*** + +### AgentCandidateModelGrantSettleInput + +Re-exports [AgentCandidateModelGrantSettleInput](index.md#agentcandidatemodelgrantsettleinput) + +*** + +### CreateProtectedAgentCandidateModelPortOptions + +Re-exports [CreateProtectedAgentCandidateModelPortOptions](index.md#createprotectedagentcandidatemodelportoptions) + +*** + +### createProtectedAgentCandidateModelPort + +Re-exports [createProtectedAgentCandidateModelPort](index.md#createprotectedagentcandidatemodelport) + +*** + +### RecoverExpiredAgentCandidateOptions + +Re-exports [RecoverExpiredAgentCandidateOptions](index.md#recoverexpiredagentcandidateoptions) + +*** + +### recoverExpiredAgentCandidateExecution + +Re-exports [recoverExpiredAgentCandidateExecution](index.md#recoverexpiredagentcandidateexecution) + +*** + +### AgentCandidateArtifactPort + +Re-exports [AgentCandidateArtifactPort](index.md#agentcandidateartifactport) + +*** + +### AgentCandidateBenchmarkGraderIdentity + +Re-exports [AgentCandidateBenchmarkGraderIdentity](index.md#agentcandidatebenchmarkgraderidentity) + +*** + +### AgentCandidateBenchmarkGraderPort + +Re-exports [AgentCandidateBenchmarkGraderPort](index.md#agentcandidatebenchmarkgraderport) + +*** + +### AgentCandidateContainerPort + +Re-exports [AgentCandidateContainerPort](index.md#agentcandidatecontainerport) + +*** + +### AgentCandidateExecutionPorts + +Re-exports [AgentCandidateExecutionPorts](index.md#agentcandidateexecutionports) + +*** + +### AgentCandidateExecutorFinalCapture + +Re-exports [AgentCandidateExecutorFinalCapture](index.md#agentcandidateexecutorfinalcapture) + +*** + +### AgentCandidateExecutorMemoryCapture + +Re-exports [AgentCandidateExecutorMemoryCapture](index.md#agentcandidateexecutormemorycapture) + +*** + +### AgentCandidateExecutorPort + +Re-exports [AgentCandidateExecutorPort](index.md#agentcandidateexecutorport) + +*** + +### AgentCandidateExecutorProfileFile + +Re-exports [AgentCandidateExecutorProfileFile](index.md#agentcandidateexecutorprofilefile) + +*** + +### AgentCandidateExecutorRequest + +Re-exports [AgentCandidateExecutorRequest](index.md#agentcandidateexecutorrequest) + +*** + +### AgentCandidateExecutorStopRequest + +Re-exports [AgentCandidateExecutorStopRequest](index.md#agentcandidateexecutorstoprequest) + +*** + +### AgentCandidateExecutorTaskOutcomeCapture + +Re-exports [AgentCandidateExecutorTaskOutcomeCapture](index.md#agentcandidateexecutortaskoutcomecapture) + +*** + +### AgentCandidateExecutorWorkspaceFile + +Re-exports [AgentCandidateExecutorWorkspaceFile](index.md#agentcandidateexecutorworkspacefile) + +*** + +### AgentCandidateExecutorWorkspaceInput + +Re-exports [AgentCandidateExecutorWorkspaceInput](index.md#agentcandidateexecutorworkspaceinput) + +*** + +### AgentCandidateMemoryPort + +Re-exports [AgentCandidateMemoryPort](index.md#agentcandidatememoryport) + +*** + +### AgentCandidateMemoryResetResult + +Re-exports [AgentCandidateMemoryResetResult](index.md#agentcandidatememoryresetresult) + +*** + +### AgentCandidateModelLimits + +Re-exports [AgentCandidateModelLimits](index.md#agentcandidatemodellimits) + +*** + +### AgentCandidateModelPort + +Re-exports [AgentCandidateModelPort](index.md#agentcandidatemodelport) + +*** + +### AgentCandidateOutputArtifactPort + +Re-exports [AgentCandidateOutputArtifactPort](index.md#agentcandidateoutputartifactport) + +*** + +### AgentCandidateOutputPurpose + +Re-exports [AgentCandidateOutputPurpose](index.md#agentcandidateoutputpurpose) + +*** + +### AgentCandidateProtectedModelActivation + +Re-exports [AgentCandidateProtectedModelActivation](index.md#agentcandidateprotectedmodelactivation) + +*** + +### AgentCandidateProtectedModelCall + +Re-exports [AgentCandidateProtectedModelCall](index.md#agentcandidateprotectedmodelcall) + +*** + +### AgentCandidateProtectedModelReservation + +Re-exports [AgentCandidateProtectedModelReservation](index.md#agentcandidateprotectedmodelreservation) + +*** + +### AgentCandidateProtectedModelSettlement + +Re-exports [AgentCandidateProtectedModelSettlement](index.md#agentcandidateprotectedmodelsettlement) + +*** + +### AgentCandidateProtectedRunCapture + +Re-exports [AgentCandidateProtectedRunCapture](index.md#agentcandidateprotectedruncapture) + +*** + +### AgentCandidateRepositoryPort + +Re-exports [AgentCandidateRepositoryPort](index.md#agentcandidaterepositoryport) + +*** + +### AgentCandidateRunFinalization + +Re-exports [AgentCandidateRunFinalization](index.md#agentcandidaterunfinalization) + +*** + +### AgentCandidateTaskExecution + +Re-exports [AgentCandidateTaskExecution](index.md#agentcandidatetaskexecution) + +*** + +### AgentCandidateVerificationPorts + +Re-exports [AgentCandidateVerificationPorts](index.md#agentcandidateverificationports) + +*** + +### AgentCandidateWorkspacePort + +Re-exports [AgentCandidateWorkspacePort](index.md#agentcandidateworkspaceport) + +*** + +### CANDIDATE\_TRACE\_ENV + +Re-exports [CANDIDATE_TRACE_ENV](index.md#candidate_trace_env) + +*** + +### CANDIDATE\_TRACE\_TAGS + +Re-exports [CANDIDATE_TRACE_TAGS](index.md#candidate_trace_tags) + +*** + +### CanonicalCandidateDocument + +Re-exports [CanonicalCandidateDocument](index.md#canonicalcandidatedocument) + +*** + +### PreparedAgentCandidateExecution + +Re-exports [PreparedAgentCandidateExecution](index.md#preparedagentcandidateexecution) + +*** + +### PreparedAgentCandidateInstruction + +Re-exports [PreparedAgentCandidateInstruction](index.md#preparedagentcandidateinstruction) + +*** + +### PreparedAgentCandidateLaunch + +Re-exports [PreparedAgentCandidateLaunch](index.md#preparedagentcandidatelaunch) + +*** + +### PreparedAgentCandidateTrace + +Re-exports [PreparedAgentCandidateTrace](index.md#preparedagentcandidatetrace) + +*** + +### ResolvedAgentCandidateContainer + +Re-exports [ResolvedAgentCandidateContainer](index.md#resolvedagentcandidatecontainer) + +*** + +### VerifiedAgentCandidate + +Re-exports [VerifiedAgentCandidate](index.md#verifiedagentcandidate) + +*** + +### VerifiedAgentCandidateTaskOutcome + +Re-exports [VerifiedAgentCandidateTaskOutcome](index.md#verifiedagentcandidatetaskoutcome) + +*** + +### verifyAgentCandidateBundle + +Re-exports [verifyAgentCandidateBundle](index.md#verifyagentcandidatebundle) diff --git a/docs/api/intelligence.md b/docs/api/intelligence.md index 7d2c4564..77144d12 100644 --- a/docs/api/intelligence.md +++ b/docs/api/intelligence.md @@ -1076,9 +1076,465 @@ Intelligence-class spend ceiling. `0` refuses every intelligence spawn; `null` u *** +### AgentImprovementProposal + +Defined in: intelligence/improvement-cycle.ts:61 + +#### Type Parameters + +##### TScenario + +`TScenario` *extends* `Scenario` = `Scenario` + +##### TArtifact + +`TArtifact` = `unknown` + +#### Properties + +##### schemaVersion + +> **schemaVersion**: `1` + +Defined in: intelligence/improvement-cycle.ts:65 + +##### kind + +> **kind**: `"agent-improvement-proposal"` + +Defined in: intelligence/improvement-cycle.ts:66 + +##### runId + +> **runId**: `string` + +Defined in: intelligence/improvement-cycle.ts:67 + +##### surface + +> **surface**: [`ImproveSurface`](index.md#improvesurface) + +Defined in: intelligence/improvement-cycle.ts:68 + +##### proposedAt + +> **proposedAt**: `string` + +Defined in: intelligence/improvement-cycle.ts:69 + +##### baselineProfileHash + +> **baselineProfileHash**: `string` + +Defined in: intelligence/improvement-cycle.ts:70 + +##### candidateProfile + +> **candidateProfile**: `AgentProfile` + +Defined in: intelligence/improvement-cycle.ts:71 + +##### candidateProfileHash + +> **candidateProfileHash**: `string` + +Defined in: intelligence/improvement-cycle.ts:72 + +##### findings + +> **findings**: `AnalystFinding`[] + +Defined in: intelligence/improvement-cycle.ts:73 + +##### evaluation + +> **evaluation**: [`AgentImprovementEvaluation`](#agentimprovementevaluation)\<`TScenario`, `TArtifact`\> + +Defined in: intelligence/improvement-cycle.ts:74 + +##### candidateBundle? + +> `optional` **candidateBundle?**: `AgentCandidateBundleV1` + +Defined in: intelligence/improvement-cycle.ts:75 + +##### digest + +> **digest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:76 + +*** + +### AgentImprovementReview + +Defined in: intelligence/improvement-cycle.ts:81 + +#### Properties + +##### schemaVersion + +> **schemaVersion**: `1` + +Defined in: intelligence/improvement-cycle.ts:82 + +##### kind + +> **kind**: `"agent-improvement-review"` + +Defined in: intelligence/improvement-cycle.ts:83 + +##### proposalDigest + +> **proposalDigest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:84 + +##### candidateBundleDigest? + +> `optional` **candidateBundleDigest?**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:85 + +##### decision + +> **decision**: [`AgentImprovementReviewDecision`](#agentimprovementreviewdecision) + +Defined in: intelligence/improvement-cycle.ts:86 + +##### reviewedBy + +> **reviewedBy**: `string` + +Defined in: intelligence/improvement-cycle.ts:87 + +##### reviewedAt + +> **reviewedAt**: `string` + +Defined in: intelligence/improvement-cycle.ts:88 + +##### reason + +> **reason**: `string` + +Defined in: intelligence/improvement-cycle.ts:89 + +##### feedback? + +> `optional` **feedback?**: `string` + +Defined in: intelligence/improvement-cycle.ts:90 + +##### digest + +> **digest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:91 + +*** + +### CandidateExecutionEvidence + +Defined in: intelligence/improvement-cycle.ts:94 + +#### Properties + +##### proposalDigest + +> **proposalDigest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:95 + +##### reviewDigest + +> **reviewDigest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:96 + +##### bundleDigest + +> **bundleDigest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:97 + +##### executionId + +> **executionId**: `string` + +Defined in: intelligence/improvement-cycle.ts:98 + +##### executionPlanDigest + +> **executionPlanDigest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:99 + +##### materializationReceiptDigest + +> **materializationReceiptDigest**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:100 + +##### succeeded + +> **succeeded**: `boolean` + +Defined in: intelligence/improvement-cycle.ts:101 + +##### runReceiptDigest? + +> `optional` **runReceiptDigest?**: `` `sha256:${string}` `` + +Defined in: intelligence/improvement-cycle.ts:102 + +*** + +### ProposeAgentImprovementOptions + +Defined in: intelligence/improvement-cycle.ts:105 + +#### Type Parameters + +##### TScenario + +`TScenario` *extends* `Scenario` + +##### TArtifact + +`TArtifact` + +#### Properties + +##### runId + +> **runId**: `string` + +Defined in: intelligence/improvement-cycle.ts:106 + +##### profile + +> **profile**: `AgentProfile` + +Defined in: intelligence/improvement-cycle.ts:107 + +##### analysis + +> **analysis**: `Omit`\<[`RunAnalystLoopOpts`](analyst-loop.md#runanalystloopopts), `"runId"` \| `"improvementAdapter"` \| `"autoApply"`\> + +Defined in: intelligence/improvement-cycle.ts:108 + +##### improvement + +> **improvement**: [`ImproveOptions`](index.md#improveoptions)\<`TScenario`, `TArtifact`\> + +Defined in: intelligence/improvement-cycle.ts:109 + +##### buildCandidate? + +> `optional` **buildCandidate?**: (`input`) => `AgentCandidateBundleInput` \| `Promise`\<`AgentCandidateBundleInput`\> + +Defined in: intelligence/improvement-cycle.ts:115 + +Optional environment adapter that freezes an executable bundle after the +measured comparison recommends the candidate. Runtime validates and +computes the bundle digest; adapters never implement hashing themselves. + +###### Parameters + +###### input + +###### analysis + +[`RunAnalystLoopResult`](analyst-loop.md#runanalystloopresult) + +###### improvement + +[`ImproveResult`](index.md#improveresult)\<`TScenario`, `TArtifact`\> + +###### Returns + +`AgentCandidateBundleInput` \| `Promise`\<`AgentCandidateBundleInput`\> + +##### now? + +> `optional` **now?**: () => `Date` + +Defined in: intelligence/improvement-cycle.ts:119 + +###### Returns + +`Date` + +*** + +### ProposeAgentImprovementResult + +Defined in: intelligence/improvement-cycle.ts:122 + +#### Type Parameters + +##### TScenario + +`TScenario` *extends* `Scenario` + +##### TArtifact + +`TArtifact` + +#### Properties + +##### analysis + +> **analysis**: [`RunAnalystLoopResult`](analyst-loop.md#runanalystloopresult) + +Defined in: intelligence/improvement-cycle.ts:123 + +##### improvement + +> **improvement**: [`ImproveResult`](index.md#improveresult)\<`TScenario`, `TArtifact`\> + +Defined in: intelligence/improvement-cycle.ts:124 + +##### proposal + +> **proposal**: [`AgentImprovementProposal`](#agentimprovementproposal)\<`TScenario`, `TArtifact`\> + +Defined in: intelligence/improvement-cycle.ts:125 + +*** + +### ReviewAgentImprovementInput + +Defined in: intelligence/improvement-cycle.ts:128 + +#### Properties + +##### decision + +> **decision**: [`AgentImprovementReviewDecision`](#agentimprovementreviewdecision) + +Defined in: intelligence/improvement-cycle.ts:129 + +##### reviewedBy + +> **reviewedBy**: `string` + +Defined in: intelligence/improvement-cycle.ts:130 + +##### reason + +> **reason**: `string` + +Defined in: intelligence/improvement-cycle.ts:131 + +##### feedback? + +> `optional` **feedback?**: `string` + +Defined in: intelligence/improvement-cycle.ts:132 + +##### now? + +> `optional` **now?**: () => `Date` + +Defined in: intelligence/improvement-cycle.ts:133 + +###### Returns + +`Date` + +*** + +### ExecuteApprovedAgentCandidateOptions + +Defined in: intelligence/improvement-cycle.ts:136 + +#### Properties + +##### proposal + +> **proposal**: [`AgentImprovementProposal`](#agentimprovementproposal) + +Defined in: intelligence/improvement-cycle.ts:137 + +##### review + +> **review**: [`AgentImprovementReview`](#agentimprovementreview) + +Defined in: intelligence/improvement-cycle.ts:138 + +##### authorizeReview + +> **authorizeReview**: (`review`, `proposal`) => `boolean` \| `Promise`\<`boolean`\> + +Defined in: intelligence/improvement-cycle.ts:140 + +Product-owned authentication check for the persisted approval record. + +###### Parameters + +###### review + +[`AgentImprovementReview`](#agentimprovementreview) + +###### proposal + +[`AgentImprovementProposal`](#agentimprovementproposal) + +###### Returns + +`boolean` \| `Promise`\<`boolean`\> + +##### task + +> **task**: [`AgentCandidateTaskExecution`](index.md#agentcandidatetaskexecution) + +Defined in: intelligence/improvement-cycle.ts:144 + +##### ports + +> **ports**: [`AgentCandidateExecutionPorts`](index.md#agentcandidateexecutionports) + +Defined in: intelligence/improvement-cycle.ts:145 + +##### preparation? + +> `optional` **preparation?**: [`PrepareAgentCandidateExecutionOptions`](index.md#prepareagentcandidateexecutionoptions) + +Defined in: intelligence/improvement-cycle.ts:146 + +##### execution + +> **execution**: [`ExecutePreparedAgentCandidateOptions`](index.md#executepreparedagentcandidateoptions) + +Defined in: intelligence/improvement-cycle.ts:147 + +*** + +### ExecuteApprovedAgentCandidateResult + +Defined in: intelligence/improvement-cycle.ts:150 + +#### Properties + +##### finalization + +> **finalization**: [`AgentCandidateRunFinalization`](index.md#agentcandidaterunfinalization) + +Defined in: intelligence/improvement-cycle.ts:151 + +##### evidence + +> **evidence**: [`CandidateExecutionEvidence`](#candidateexecutionevidence) + +Defined in: intelligence/improvement-cycle.ts:152 + +*** + ### UsageSplit -Defined in: [intelligence/index.ts:125](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L125) +Defined in: [intelligence/index.ts:140](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L140) The per-class cost split carried by every trace and outcome. `off` ⇒ `intelligenceUsd: 0` by construction — there is no intelligence spawn to @@ -1090,7 +1546,7 @@ bill. This is a classification on the trace, NOT a budget-pool split. > **inferenceUsd**: `number` -Defined in: [intelligence/index.ts:127](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L127) +Defined in: [intelligence/index.ts:142](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L142) Base-stream (model) spend in USD. @@ -1098,7 +1554,7 @@ Base-stream (model) spend in USD. > **intelligenceUsd**: `number` -Defined in: [intelligence/index.ts:129](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L129) +Defined in: [intelligence/index.ts:144](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L144) Intelligence-spawn spend in USD. Provably `0` at the OFF tier. @@ -1106,7 +1562,7 @@ Intelligence-spawn spend in USD. Provably `0` at the OFF tier. ### RunRecord -Defined in: [intelligence/index.ts:139](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L139) +Defined in: [intelligence/index.ts:154](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L154) The typed record `withIntelligence` sends per call — serialized through the shipped OTLP builders to the plane's `/v1/otlp` ingest. `input`/`output` are @@ -1120,43 +1576,43 @@ tree under the same `traceId`. > **runId**: `string` -Defined in: [intelligence/index.ts:140](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L140) +Defined in: [intelligence/index.ts:155](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L155) ##### traceId > **traceId**: `string` -Defined in: [intelligence/index.ts:141](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L141) +Defined in: [intelligence/index.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L156) ##### project > **project**: `string` -Defined in: [intelligence/index.ts:142](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L142) +Defined in: [intelligence/index.ts:157](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L157) ##### target > **target**: `string` -Defined in: [intelligence/index.ts:143](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L143) +Defined in: [intelligence/index.ts:158](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L158) ##### input > **input**: `unknown` -Defined in: [intelligence/index.ts:144](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L144) +Defined in: [intelligence/index.ts:159](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L159) ##### output > **output**: `unknown` -Defined in: [intelligence/index.ts:145](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L145) +Defined in: [intelligence/index.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L160) ##### outcome > **outcome**: `object` -Defined in: [intelligence/index.ts:146](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L146) +Defined in: [intelligence/index.ts:161](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L161) ###### success? @@ -1174,61 +1630,61 @@ Defined in: [intelligence/index.ts:146](https://github.com/tangle-network/agent- > `optional` **model?**: `string` -Defined in: [intelligence/index.ts:151](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L151) +Defined in: [intelligence/index.ts:166](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L166) ##### provider? > `optional` **provider?**: `string` -Defined in: [intelligence/index.ts:152](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L152) +Defined in: [intelligence/index.ts:167](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L167) ##### loopEvents? > `optional` **loopEvents?**: [`LoopTraceEvent`](runtime.md#looptraceevent)[] -Defined in: [intelligence/index.ts:153](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L153) +Defined in: [intelligence/index.ts:168](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L168) ##### runtimeEvents? > `optional` **runtimeEvents?**: [`RuntimeStreamEvent`](index.md#runtimestreamevent)[] -Defined in: [intelligence/index.ts:154](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L154) +Defined in: [intelligence/index.ts:169](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L169) ##### profile? > `optional` **profile?**: `AgentProfile` -Defined in: [intelligence/index.ts:155](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L155) +Defined in: [intelligence/index.ts:170](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L170) ##### sessionId? > `optional` **sessionId?**: `string` -Defined in: [intelligence/index.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L156) +Defined in: [intelligence/index.ts:171](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L171) ##### harness? > `optional` **harness?**: `string` -Defined in: [intelligence/index.ts:157](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L157) +Defined in: [intelligence/index.ts:172](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L172) ##### repository? > `optional` **repository?**: `string` -Defined in: [intelligence/index.ts:158](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L158) +Defined in: [intelligence/index.ts:173](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L173) ##### commitSha? > `optional` **commitSha?**: `string` -Defined in: [intelligence/index.ts:159](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L159) +Defined in: [intelligence/index.ts:174](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L174) ##### timing? > `optional` **timing?**: `object` -Defined in: [intelligence/index.ts:160](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L160) +Defined in: [intelligence/index.ts:175](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L175) ###### startedAt @@ -1246,7 +1702,7 @@ Defined in: [intelligence/index.ts:160](https://github.com/tangle-network/agent- > `optional` **tokens?**: `object` -Defined in: [intelligence/index.ts:161](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L161) +Defined in: [intelligence/index.ts:176](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L176) ###### input @@ -1268,7 +1724,7 @@ Defined in: [intelligence/index.ts:161](https://github.com/tangle-network/agent- > `optional` **error?**: `object` -Defined in: [intelligence/index.ts:167](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L167) +Defined in: [intelligence/index.ts:182](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L182) ###### name @@ -1282,11 +1738,19 @@ Defined in: [intelligence/index.ts:167](https://github.com/tangle-network/agent- > `optional` **code?**: `string` +##### candidateExecution? + +> `optional` **candidateExecution?**: [`CandidateExecutionEvidence`](#candidateexecutionevidence) + +Defined in: [intelligence/index.ts:184](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L184) + +Exact proposal → review → execution → receipt linkage for candidate runs. + *** ### RunReport -Defined in: [intelligence/index.ts:176](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L176) +Defined in: [intelligence/index.ts:193](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L193) What an agent reports (via `applied.record`) to enrich the [RunRecord](#runrecord) sent for its call. All optional — an un-recorded run still sends input/output @@ -1299,79 +1763,79 @@ as pure inference (the base stream). > `optional` **success?**: `boolean` -Defined in: [intelligence/index.ts:177](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L177) +Defined in: [intelligence/index.ts:194](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L194) ##### score? > `optional` **score?**: `number` -Defined in: [intelligence/index.ts:178](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L178) +Defined in: [intelligence/index.ts:195](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L195) ##### usage? > `optional` **usage?**: `Partial`\<[`UsageSplit`](#usagesplit)\> -Defined in: [intelligence/index.ts:179](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L179) +Defined in: [intelligence/index.ts:196](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L196) ##### costUsd? > `optional` **costUsd?**: `number` -Defined in: [intelligence/index.ts:180](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L180) +Defined in: [intelligence/index.ts:197](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L197) ##### model? > `optional` **model?**: `string` -Defined in: [intelligence/index.ts:181](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L181) +Defined in: [intelligence/index.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L198) ##### provider? > `optional` **provider?**: `string` -Defined in: [intelligence/index.ts:182](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L182) +Defined in: [intelligence/index.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L199) ##### loopEvents? > `optional` **loopEvents?**: [`LoopTraceEvent`](runtime.md#looptraceevent)[] -Defined in: [intelligence/index.ts:183](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L183) +Defined in: [intelligence/index.ts:200](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L200) ##### runtimeEvents? > `optional` **runtimeEvents?**: [`RuntimeStreamEvent`](index.md#runtimestreamevent)[] -Defined in: [intelligence/index.ts:184](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L184) +Defined in: [intelligence/index.ts:201](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L201) ##### profile? > `optional` **profile?**: `AgentProfile` -Defined in: [intelligence/index.ts:185](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L185) +Defined in: [intelligence/index.ts:202](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L202) ##### sessionId? > `optional` **sessionId?**: `string` -Defined in: [intelligence/index.ts:186](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L186) +Defined in: [intelligence/index.ts:203](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L203) ##### harness? > `optional` **harness?**: `string` -Defined in: [intelligence/index.ts:187](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L187) +Defined in: [intelligence/index.ts:204](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L204) ##### commitSha? > `optional` **commitSha?**: `string` -Defined in: [intelligence/index.ts:188](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L188) +Defined in: [intelligence/index.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L205) ##### tokens? > `optional` **tokens?**: `object` -Defined in: [intelligence/index.ts:189](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L189) +Defined in: [intelligence/index.ts:206](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L206) ###### input @@ -1393,7 +1857,7 @@ Defined in: [intelligence/index.ts:189](https://github.com/tangle-network/agent- > `optional` **error?**: `object` -Defined in: [intelligence/index.ts:190](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L190) +Defined in: [intelligence/index.ts:207](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L207) ###### name @@ -1407,11 +1871,17 @@ Defined in: [intelligence/index.ts:190](https://github.com/tangle-network/agent- > `optional` **code?**: `string` +##### candidateExecution? + +> `optional` **candidateExecution?**: [`CandidateExecutionEvidence`](#candidateexecutionevidence) + +Defined in: [intelligence/index.ts:208](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L208) + *** ### RepoConfig -Defined in: [intelligence/index.ts:196](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L196) +Defined in: [intelligence/index.ts:214](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L214) Repo coordinates a product may declare for the (later) Gated-PR mode. The Observe slice only records their PRESENCE for `doctor()`; it never touches @@ -1423,25 +1893,25 @@ Repo coordinates a product may declare for the (later) Gated-PR mode. The > **owner**: `string` -Defined in: [intelligence/index.ts:197](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L197) +Defined in: [intelligence/index.ts:215](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L215) ##### name > **name**: `string` -Defined in: [intelligence/index.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L198) +Defined in: [intelligence/index.ts:216](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L216) ##### baseBranch > **baseBranch**: `string` -Defined in: [intelligence/index.ts:199](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L199) +Defined in: [intelligence/index.ts:217](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L217) *** ### IntelligenceConfig -Defined in: [intelligence/index.ts:205](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L205) +Defined in: [intelligence/index.ts:223](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L223) Client configuration. `project` + `apiKey` are the Observe minimum; the rest tune effort, endpoint, redaction, and (for `doctor()` readiness) @@ -1457,7 +1927,7 @@ Client configuration. `project` + `apiKey` are the Observe minimum; the > **project**: `string` -Defined in: [intelligence/index.ts:207](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L207) +Defined in: [intelligence/index.ts:225](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L225) Stable project id — the tenant dimension every trace is tagged with. @@ -1465,7 +1935,7 @@ Stable project id — the tenant dimension every trace is tagged with. > `optional` **apiKey?**: `string` -Defined in: [intelligence/index.ts:209](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L209) +Defined in: [intelligence/index.ts:227](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L227) Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. @@ -1473,7 +1943,7 @@ Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. > `optional` **effort?**: [`EffortTier`](#efforttier) \| \{ `tier`: [`EffortTier`](#efforttier); `overrides?`: `Partial`\<[`EffortSettings`](#effortsettings)\>; \} -Defined in: [intelligence/index.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L211) +Defined in: [intelligence/index.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L229) Effort tier (default `'standard'`) plus optional per-field overrides. @@ -1481,7 +1951,7 @@ Effort tier (default `'standard'`) plus optional per-field overrides. > `optional` **baseUrl?**: `string` -Defined in: [intelligence/index.ts:219](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L219) +Defined in: [intelligence/index.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L237) The ONE Tangle Intelligence base URL — both the send (OTLP `/v1/otlp`) and receive (`/v1/profiles/:target/composed`) paths derive from it. Reads @@ -1493,7 +1963,7 @@ key the ingest requires); absent a key, export is a no-op. > `optional` **redact?**: `false` \| [`Redactor`](#redactor) -Defined in: [intelligence/index.ts:225](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L225) +Defined in: [intelligence/index.ts:243](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L243) Redaction hook run over every exported input/output. A function replaces the default scrubber; `false` opts out entirely (raw fidelity, caller has @@ -1503,7 +1973,7 @@ sanitized upstream); omitted ⇒ the built-in `defaultRedactor`. > `optional` **surfaces?**: `string`[] -Defined in: [intelligence/index.ts:227](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L227) +Defined in: [intelligence/index.ts:245](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L245) Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. @@ -1511,7 +1981,7 @@ Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. > `optional` **checks?**: `string`[] -Defined in: [intelligence/index.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L229) +Defined in: [intelligence/index.ts:247](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L247) Verification checks a later PR mode would gate on. Recorded for `doctor()` only. @@ -1519,7 +1989,7 @@ Verification checks a later PR mode would gate on. Recorded for `doctor()` only. > `optional` **repo?**: [`RepoConfig`](#repoconfig) -Defined in: [intelligence/index.ts:231](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L231) +Defined in: [intelligence/index.ts:249](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L249) Repo access a later PR mode would need. Recorded for `doctor()` only. @@ -1527,7 +1997,7 @@ Repo access a later PR mode would need. Recorded for `doctor()` only. > `optional` **profile?**: `AgentProfile` -Defined in: [intelligence/index.ts:233](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L233) +Defined in: [intelligence/index.ts:251](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L251) Full canonical profile used for this agent. Exported redacted with a stable hash. @@ -1535,7 +2005,7 @@ Full canonical profile used for this agent. Exported redacted with a stable hash > `optional` **commitSha?**: `string` -Defined in: [intelligence/index.ts:235](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L235) +Defined in: [intelligence/index.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L253) Commit that produced the running agent, when known. @@ -1543,15 +2013,26 @@ Commit that produced the running agent, when known. > `optional` **runtimeTelemetry?**: [`RuntimeTelemetryOptions`](index.md#runtimetelemetryoptions) -Defined in: [intelligence/index.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L237) +Defined in: [intelligence/index.ts:255](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L255) Runtime-event payload policy. Tool inputs/results remain off unless explicitly enabled. +##### payloadAttributes? + +> `optional` **payloadAttributes?**: `"metadata"` \| `"full"` + +Defined in: [intelligence/index.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L262) + +Payloads are metadata-only by default: the run span carries a stable hash +and UTF-8 byte count, but not the redacted content. Set `full` only when +the configured OTLP destination is approved to receive complete redacted +inputs, outputs, and profiles. + *** ### TraceMeta -Defined in: [intelligence/index.ts:241](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L241) +Defined in: [intelligence/index.ts:266](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L266) Metadata describing one traced run. `runId`/`traceId` default to fresh ids. @@ -1561,7 +2042,7 @@ Metadata describing one traced run. `runId`/`traceId` default to fresh ids. > `optional` **input?**: `unknown` -Defined in: [intelligence/index.ts:243](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L243) +Defined in: [intelligence/index.ts:268](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L268) The run's input — exported through the redactor. @@ -1569,7 +2050,7 @@ The run's input — exported through the redactor. > `optional` **runId?**: `string` -Defined in: [intelligence/index.ts:245](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L245) +Defined in: [intelligence/index.ts:270](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L270) Stable run id. Defaults to a fresh id. @@ -1577,7 +2058,7 @@ Stable run id. Defaults to a fresh id. > `optional` **traceId?**: `string` -Defined in: [intelligence/index.ts:247](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L247) +Defined in: [intelligence/index.ts:272](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L272) 32-hex trace id. Defaults to a fresh id. @@ -1585,7 +2066,7 @@ Defined in: [intelligence/index.ts:247](https://github.com/tangle-network/agent- > `optional` **model?**: `string` -Defined in: [intelligence/index.ts:249](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L249) +Defined in: [intelligence/index.ts:274](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L274) Model id, when known — stamped on the span. @@ -1593,7 +2074,7 @@ Model id, when known — stamped on the span. > `optional` **provider?**: `string` -Defined in: [intelligence/index.ts:251](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L251) +Defined in: [intelligence/index.ts:276](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L276) Provider name, when known — stamped on the span. @@ -1601,7 +2082,7 @@ Provider name, when known — stamped on the span. > `optional` **labels?**: `Record`\<`string`, `string` \| `number` \| `boolean`\> -Defined in: [intelligence/index.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L253) +Defined in: [intelligence/index.ts:278](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L278) Arbitrary extra labels (string/number/boolean) stamped on the span. @@ -1609,7 +2090,7 @@ Arbitrary extra labels (string/number/boolean) stamped on the span. ### TraceHandle -Defined in: [intelligence/index.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L262) +Defined in: [intelligence/index.ts:287](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L287) The trace handle a `traceRun` body records into. `recordOutput` captures the agent's result (redacted on export); `recordOutcome` captures the scored @@ -1622,7 +2103,7 @@ an un-recorded run still exports a span with whatever was set. > **recordOutput**(`output`): `void` -Defined in: [intelligence/index.ts:264](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L264) +Defined in: [intelligence/index.ts:289](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L289) Capture the run's output. Exported through the redactor. @@ -1640,7 +2121,7 @@ Capture the run's output. Exported through the redactor. > **recordOutcome**(`outcome`): `void` -Defined in: [intelligence/index.ts:271](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L271) +Defined in: [intelligence/index.ts:296](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L296) Capture the run's outcome. `usage` defaults to inference-only (`intelligenceUsd: 0`) — the OFF baseline; an intelligence-enabled run @@ -1675,7 +2156,7 @@ treated as pure inference. ### RecordTraceMeta -Defined in: [intelligence/index.ts:280](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L280) +Defined in: [intelligence/index.ts:305](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L305) Metadata for [IntelligenceClient.recordTrace](#recordtrace). @@ -1685,7 +2166,7 @@ Metadata for [IntelligenceClient.recordTrace](#recordtrace). > `optional` **traceId?**: `string` -Defined in: [intelligence/index.ts:282](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L282) +Defined in: [intelligence/index.ts:307](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L307) 32-hex trace id to anchor every span to. Defaults to a fresh id. @@ -1693,7 +2174,7 @@ Defined in: [intelligence/index.ts:282](https://github.com/tangle-network/agent- > `optional` **rootParentSpanId?**: `string` -Defined in: [intelligence/index.ts:285](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L285) +Defined in: [intelligence/index.ts:310](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L310) Span id of an enclosing span the loop root should parent under (e.g. a `traceRun` span). Omitted ⇒ the loop root is the trace root. @@ -1702,7 +2183,7 @@ Span id of an enclosing span the loop root should parent under (e.g. a ### TraceOutcome -Defined in: [intelligence/index.ts:290](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L290) +Defined in: [intelligence/index.ts:315](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L315) The resolved outcome of one traced run, surfaced on the export span and available to the caller for downstream billing assertions. @@ -1713,25 +2194,25 @@ The resolved outcome of one traced run, surfaced on the export span and > **runId**: `string` -Defined in: [intelligence/index.ts:291](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L291) +Defined in: [intelligence/index.ts:316](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L316) ##### traceId > **traceId**: `string` -Defined in: [intelligence/index.ts:292](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L292) +Defined in: [intelligence/index.ts:317](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L317) ##### project > **project**: `string` -Defined in: [intelligence/index.ts:293](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L293) +Defined in: [intelligence/index.ts:318](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L318) ##### effort > **effort**: [`EffortSettings`](#effortsettings) -Defined in: [intelligence/index.ts:295](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L295) +Defined in: [intelligence/index.ts:320](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L320) The resolved effort settings this run executed under. @@ -1739,7 +2220,7 @@ The resolved effort settings this run executed under. > **intelligenceOff**: `boolean` -Defined in: [intelligence/index.ts:297](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L297) +Defined in: [intelligence/index.ts:322](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L322) True when this run ran as pure passthrough (the OFF floor). @@ -1747,19 +2228,19 @@ True when this run ran as pure passthrough (the OFF floor). > `optional` **success?**: `boolean` -Defined in: [intelligence/index.ts:298](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L298) +Defined in: [intelligence/index.ts:323](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L323) ##### score? > `optional` **score?**: `number` -Defined in: [intelligence/index.ts:299](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L299) +Defined in: [intelligence/index.ts:324](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L324) ##### usage > **usage**: [`UsageSplit`](#usagesplit) -Defined in: [intelligence/index.ts:301](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L301) +Defined in: [intelligence/index.ts:326](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L326) Per-class billing split. `intelligenceUsd` is `0` at the OFF tier. @@ -1767,7 +2248,7 @@ Per-class billing split. `intelligenceUsd` is `0` at the OFF tier. ### IntelligenceClient -Defined in: [intelligence/index.ts:305](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L305) +Defined in: [intelligence/index.ts:330](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L330) The Observe-mode Intelligence client. @@ -1777,7 +2258,7 @@ The Observe-mode Intelligence client. > `readonly` **project**: `string` -Defined in: [intelligence/index.ts:307](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L307) +Defined in: [intelligence/index.ts:332](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L332) The resolved project id. @@ -1785,7 +2266,7 @@ The resolved project id. > `readonly` **effort**: [`EffortSettings`](#effortsettings) -Defined in: [intelligence/index.ts:309](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L309) +Defined in: [intelligence/index.ts:334](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L334) The resolved effort settings. @@ -1795,7 +2276,7 @@ The resolved effort settings. > **traceRun**\<`T`\>(`meta`, `fn`): `Promise`\<`T`\> -Defined in: [intelligence/index.ts:315](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L315) +Defined in: [intelligence/index.ts:340](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L340) Run `fn` under a trace, export one span best-effort, and return whatever `fn` returns. Telemetry-export failures are swallowed; an error THROWN by @@ -1825,7 +2306,7 @@ Run `fn` under a trace, export one span best-effort, and return whatever > **recordTrace**(`events`, `meta?`): `string` -Defined in: [intelligence/index.ts:325](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L325) +Defined in: [intelligence/index.ts:350](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L350) Export a run's full loop topology — the ordered `LoopTraceEvent` stream a `runLoop`/`Supervisor` run emits — as a nested OTLP span tree (loop → round → @@ -1853,7 +2334,7 @@ readonly [`LoopTraceEvent`](runtime.md#looptraceevent)[] > **exportRunRecord**(`record`): `string` -Defined in: [intelligence/index.ts:333](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L333) +Defined in: [intelligence/index.ts:358](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L358) Send one typed [RunRecord](#runrecord) — the run's flat span (input/output/outcome/ usage/model/provider, redacted) plus, when `loopEvents` are present, the @@ -1875,7 +2356,7 @@ Best-effort: export failures are swallowed. Returns the record's `traceId`. > **freshRunId**(): `string` -Defined in: [intelligence/index.ts:335](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L335) +Defined in: [intelligence/index.ts:360](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L360) Mint a fresh run id (`run-`). @@ -1887,7 +2368,7 @@ Mint a fresh run id (`run-`). > **freshTraceId**(): `string` -Defined in: [intelligence/index.ts:337](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L337) +Defined in: [intelligence/index.ts:362](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L362) Mint a fresh 32-hex trace id. @@ -1899,7 +2380,7 @@ Mint a fresh 32-hex trace id. > **doctor**(): [`DoctorReport`](#doctorreport) -Defined in: [intelligence/index.ts:343](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L343) +Defined in: [intelligence/index.ts:368](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L368) Network-free readiness report: which adoption modes are reachable given this config. Observe is always reachable; Recommend needs outcomes; PR @@ -1913,7 +2394,7 @@ needs checks + surfaces + repo. > **flush**(): `Promise`\<`void`\> -Defined in: [intelligence/index.ts:345](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L345) +Defined in: [intelligence/index.ts:370](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L370) Flush any pending export spans. Best-effort; resolves even if export fails. @@ -1925,7 +2406,7 @@ Flush any pending export spans. Best-effort; resolves even if export fails. ### ModeReadiness -Defined in: [intelligence/index.ts:349](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L349) +Defined in: [intelligence/index.ts:374](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L374) One mode's readiness verdict. @@ -1935,13 +2416,13 @@ One mode's readiness verdict. > **ready**: `boolean` -Defined in: [intelligence/index.ts:350](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L350) +Defined in: [intelligence/index.ts:375](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L375) ##### missing > **missing**: `string`[] -Defined in: [intelligence/index.ts:352](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L352) +Defined in: [intelligence/index.ts:377](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L377) Inputs this mode still needs, when not ready. Empty when ready. @@ -1949,7 +2430,7 @@ Inputs this mode still needs, when not ready. Empty when ready. ### DoctorReport -Defined in: [intelligence/index.ts:356](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L356) +Defined in: [intelligence/index.ts:381](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L381) The `doctor()` readiness report — Mode-readiness without any network call. @@ -1959,19 +2440,19 @@ The `doctor()` readiness report — Mode-readiness without any network call. > **project**: `string` -Defined in: [intelligence/index.ts:357](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L357) +Defined in: [intelligence/index.ts:382](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L382) ##### effort > **effort**: [`EffortSettings`](#effortsettings) -Defined in: [intelligence/index.ts:358](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L358) +Defined in: [intelligence/index.ts:383](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L383) ##### exportConfigured > **exportConfigured**: `boolean` -Defined in: [intelligence/index.ts:360](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L360) +Defined in: [intelligence/index.ts:385](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L385) True when an OTLP endpoint is configured (export will actually ship). @@ -1979,7 +2460,7 @@ True when an OTLP endpoint is configured (export will actually ship). > **modes**: `object` -Defined in: [intelligence/index.ts:361](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L361) +Defined in: [intelligence/index.ts:386](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L386) ###### observe @@ -2327,7 +2808,7 @@ Defined in: [intelligence/with-intelligence.ts:83](https://github.com/tangle-net > **project**: `string` -Defined in: [intelligence/index.ts:207](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L207) +Defined in: [intelligence/index.ts:225](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L225) Stable project id — the tenant dimension every trace is tagged with. @@ -2339,7 +2820,7 @@ Stable project id — the tenant dimension every trace is tagged with. > `optional` **apiKey?**: `string` -Defined in: [intelligence/index.ts:209](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L209) +Defined in: [intelligence/index.ts:227](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L227) Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. @@ -2351,7 +2832,7 @@ Bearer key for the Intelligence ingest. Reads `TANGLE_API_KEY` when omitted. > `optional` **effort?**: [`EffortTier`](#efforttier) \| \{ `tier`: [`EffortTier`](#efforttier); `overrides?`: `Partial`\<[`EffortSettings`](#effortsettings)\>; \} -Defined in: [intelligence/index.ts:211](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L211) +Defined in: [intelligence/index.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L229) Effort tier (default `'standard'`) plus optional per-field overrides. @@ -2363,7 +2844,7 @@ Effort tier (default `'standard'`) plus optional per-field overrides. > `optional` **baseUrl?**: `string` -Defined in: [intelligence/index.ts:219](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L219) +Defined in: [intelligence/index.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L237) The ONE Tangle Intelligence base URL — both the send (OTLP `/v1/otlp`) and receive (`/v1/profiles/:target/composed`) paths derive from it. Reads @@ -2379,7 +2860,7 @@ key the ingest requires); absent a key, export is a no-op. > `optional` **redact?**: `false` \| [`Redactor`](#redactor) -Defined in: [intelligence/index.ts:225](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L225) +Defined in: [intelligence/index.ts:243](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L243) Redaction hook run over every exported input/output. A function replaces the default scrubber; `false` opts out entirely (raw fidelity, caller has @@ -2393,7 +2874,7 @@ sanitized upstream); omitted ⇒ the built-in `defaultRedactor`. > `optional` **surfaces?**: `string`[] -Defined in: [intelligence/index.ts:227](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L227) +Defined in: [intelligence/index.ts:245](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L245) Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. @@ -2405,7 +2886,7 @@ Mutable surfaces a later PR mode would edit. Recorded for `doctor()` only. > `optional` **checks?**: `string`[] -Defined in: [intelligence/index.ts:229](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L229) +Defined in: [intelligence/index.ts:247](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L247) Verification checks a later PR mode would gate on. Recorded for `doctor()` only. @@ -2417,7 +2898,7 @@ Verification checks a later PR mode would gate on. Recorded for `doctor()` only. > `optional` **repo?**: [`RepoConfig`](#repoconfig) -Defined in: [intelligence/index.ts:231](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L231) +Defined in: [intelligence/index.ts:249](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L249) Repo access a later PR mode would need. Recorded for `doctor()` only. @@ -2429,19 +2910,19 @@ Repo access a later PR mode would need. Recorded for `doctor()` only. > `optional` **profile?**: `AgentProfile` -Defined in: [intelligence/index.ts:233](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L233) +Defined in: [intelligence/index.ts:251](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L251) Full canonical profile used for this agent. Exported redacted with a stable hash. ###### Inherited from -[`IntelligenceConfig`](#intelligenceconfig).[`profile`](#profile-2) +[`IntelligenceConfig`](#intelligenceconfig).[`profile`](#profile-3) ##### commitSha? > `optional` **commitSha?**: `string` -Defined in: [intelligence/index.ts:235](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L235) +Defined in: [intelligence/index.ts:253](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L253) Commit that produced the running agent, when known. @@ -2453,7 +2934,7 @@ Commit that produced the running agent, when known. > `optional` **runtimeTelemetry?**: [`RuntimeTelemetryOptions`](index.md#runtimetelemetryoptions) -Defined in: [intelligence/index.ts:237](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L237) +Defined in: [intelligence/index.ts:255](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L255) Runtime-event payload policy. Tool inputs/results remain off unless explicitly enabled. @@ -2461,6 +2942,21 @@ Runtime-event payload policy. Tool inputs/results remain off unless explicitly e [`IntelligenceConfig`](#intelligenceconfig).[`runtimeTelemetry`](#runtimetelemetry) +##### payloadAttributes? + +> `optional` **payloadAttributes?**: `"metadata"` \| `"full"` + +Defined in: [intelligence/index.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L262) + +Payloads are metadata-only by default: the run span carries a stable hash +and UTF-8 byte count, but not the redacted content. Set `full` only when +the configured OTLP destination is approved to receive complete redacted +inputs, outputs, and profiles. + +###### Inherited from + +[`IntelligenceConfig`](#intelligenceconfig).[`payloadAttributes`](#payloadattributes) + ##### target? > `optional` **target?**: `string` @@ -2650,11 +3146,37 @@ Per-field overrides applied on top of a tier preset. Any subset of the *** +### AgentImprovementEvaluation + +> **AgentImprovementEvaluation**\<`TScenario`, `TArtifact`\> = `Pick`\<`SelfImproveResult`\<`TScenario`, `TArtifact`\>, `"baseline"` \| `"winner"` \| `"lift"` \| `"diff"` \| `"provenance"` \| `"gateDecision"` \| `"generationsExplored"` \| `"durationMs"` \| `"totalCostUsd"` \| `"insight"` \| `"power"`\> + +Defined in: intelligence/improvement-cycle.ts:46 + +#### Type Parameters + +##### TScenario + +`TScenario` *extends* `Scenario` + +##### TArtifact + +`TArtifact` + +*** + +### AgentImprovementReviewDecision + +> **AgentImprovementReviewDecision** = `"approve"` \| `"reject"` \| `"request-changes"` + +Defined in: intelligence/improvement-cycle.ts:79 + +*** + ### UsageClass > **UsageClass** = `"inference"` \| `"intelligence"` -Defined in: [intelligence/index.ts:118](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L118) +Defined in: [intelligence/index.ts:133](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L133) Usage class for billing. Base-stream tokens bill `'inference'`; every intelligence spawn (analyst, corpus, loop) bills `'intelligence'`. The @@ -3008,11 +3530,125 @@ compile to `withAnalyst: true`, the tier's `fanout`, and `withLoops: true`. *** +### proposeAgentImprovement() + +> **proposeAgentImprovement**\<`TScenario`, `TArtifact`\>(`options`): `Promise`\<[`ProposeAgentImprovementResult`](#proposeagentimprovementresult)\<`TScenario`, `TArtifact`\>\> + +Defined in: intelligence/improvement-cycle.ts:156 + +Analyze one run and produce one measured, review-only improvement proposal. + +#### Type Parameters + +##### TScenario + +`TScenario` *extends* `Scenario` + +##### TArtifact + +`TArtifact` + +#### Parameters + +##### options + +[`ProposeAgentImprovementOptions`](#proposeagentimprovementoptions)\<`TScenario`, `TArtifact`\> + +#### Returns + +`Promise`\<[`ProposeAgentImprovementResult`](#proposeagentimprovementresult)\<`TScenario`, `TArtifact`\>\> + +*** + +### reviewAgentImprovementProposal() + +> **reviewAgentImprovementProposal**(`inputProposal`, `input`): [`AgentImprovementReview`](#agentimprovementreview) + +Defined in: intelligence/improvement-cycle.ts:198 + +Persist an approve/reject/change-request decision bound to one exact proposal. + +#### Parameters + +##### inputProposal + +[`AgentImprovementProposal`](#agentimprovementproposal) + +##### input + +[`ReviewAgentImprovementInput`](#reviewagentimprovementinput) + +#### Returns + +[`AgentImprovementReview`](#agentimprovementreview) + +*** + +### executeApprovedAgentCandidate() + +> **executeApprovedAgentCandidate**(`options`): `Promise`\<[`ExecuteApprovedAgentCandidateResult`](#executeapprovedagentcandidateresult)\> + +Defined in: intelligence/improvement-cycle.ts:228 + +Verify, materialize, run, grade, and receipt only the exact approved bundle. + +#### Parameters + +##### options + +[`ExecuteApprovedAgentCandidateOptions`](#executeapprovedagentcandidateoptions) + +#### Returns + +`Promise`\<[`ExecuteApprovedAgentCandidateResult`](#executeapprovedagentcandidateresult)\> + +*** + +### verifyAgentImprovementProposal() + +> **verifyAgentImprovementProposal**(`input`): [`AgentImprovementProposal`](#agentimprovementproposal) + +Defined in: intelligence/improvement-cycle.ts:270 + +Validate a proposal's schema, profile, sealed bundle, and canonical digest. + +#### Parameters + +##### input + +`unknown` + +#### Returns + +[`AgentImprovementProposal`](#agentimprovementproposal) + +*** + +### verifyAgentImprovementReview() + +> **verifyAgentImprovementReview**(`input`): [`AgentImprovementReview`](#agentimprovementreview) + +Defined in: intelligence/improvement-cycle.ts:442 + +Validate a review's decision fields and canonical digest. + +#### Parameters + +##### input + +`unknown` + +#### Returns + +[`AgentImprovementReview`](#agentimprovementreview) + +*** + ### createIntelligenceClient() > **createIntelligenceClient**(`config`): [`IntelligenceClient`](#intelligenceclient) -Defined in: [intelligence/index.ts:415](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L415) +Defined in: [intelligence/index.ts:452](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/index.ts#L452) Create an Observe-mode Intelligence client. Resolves effort, the base URL, and the redactor up front; the exporter is built lazily and is `undefined` when no diff --git a/docs/api/mcp.md b/docs/api/mcp.md index 5da2ec5d..b2d846d4 100644 --- a/docs/api/mcp.md +++ b/docs/api/mcp.md @@ -833,7 +833,7 @@ Gate: only approved candidates are eligible to win. ##### recommendation -> **recommendation**: `"ship"` \| `"approve-with-nits"` \| `"changes-requested"` \| `"reject"` +> **recommendation**: `"ship"` \| `"reject"` \| `"approve-with-nits"` \| `"changes-requested"` Defined in: [mcp/delegates.ts:102](https://github.com/tangle-network/agent-runtime/blob/main/src/mcp/delegates.ts#L102) diff --git a/docs/api/primitive-catalog.md b/docs/api/primitive-catalog.md index 58e57a94..ef5b4f40 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.91.0` and `@tangle-network/agent-eval@0.113.0` 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.92.0` and `@tangle-network/agent-eval@0.113.0` 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 @@ -251,7 +251,7 @@ Import from `@tangle-network/agent-runtime/agent` — 48 exports. ### Intelligence SDK — Observe + provable-OFF billing -Import from `@tangle-network/agent-runtime/intelligence` — 68 exports. +Import from `@tangle-network/agent-runtime/intelligence` — 83 exports. | Symbol | Kind | Summary | |---|---|---| @@ -262,13 +262,18 @@ Import from `@tangle-network/agent-runtime/intelligence` — 68 exports. | `createCertifiedPromptSource` | function | Create the cached certified-prompt source — the ONE module-scope-cache + | | `createIntelligenceClient` | function | Create an Observe-mode Intelligence client. Resolves effort, the base URL, and | | `defaultRedactor` | function | The built-in redactor. Walks objects and arrays; replaces values under | +| `executeApprovedAgentCandidate` | function | Verify, materialize, run, grade, and receipt only the exact approved bundle. | | `isIntelligenceOff` | function | True when these settings admit NO intelligence spawn — the passthrough | | `manifestFromProfile` | function | Lower the EXISTING plane wire (`CertifiedProfile`) into a `CapabilityManifest`. | | `normalizeCertifiedProfile` | function | Deserialize the composed-endpoint response into a `CertifiedProfile`. The | +| `proposeAgentImprovement` | function | Analyze one run and produce one measured, review-only improvement proposal. | | `pullCertified` | function | Pull the certified composed profile for a target. Fail-closed: a network | | `resolveEffort` | function | Compile a named tier (plus optional per-field overrides) into the flat | | `resolveIntelligenceBaseUrl` | function | Resolve the ONE Intelligence base URL — the single knob both the send and | | `resolveRedactor` | function | Resolve the redactor a client uses. A caller-supplied hook replaces the | +| `reviewAgentImprovementProposal` | function | Persist an approve/reject/change-request decision bound to one exact proposal. | +| `verifyAgentImprovementProposal` | function | Validate a proposal's schema, profile, sealed bundle, and canonical digest. | +| `verifyAgentImprovementReview` | function | Validate a review's decision fields and canonical digest. | | `withIntelligence` | function | Wrap an agent so it (a) RECEIVES the tenant's certified profile — the prompt | | `defaultEffortTier` | const | The default tier when a client declares no effort. `'standard'` turns | | `CapabilityNotAdmittedError` | class | A binding kind whose resolver case is typed but not yet admitted (rag-index, | @@ -323,7 +328,7 @@ Import from `@tangle-network/agent-runtime/intelligence` — 68 exports. | `Redactor` | type | A redactor maps an arbitrary trace value to a safe-to-export value. Pure; | | `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): `PullCertifiedOptions`. +**Undocumented supporting types** (add a TSDoc line at the declaration to earn a table row): `AgentImprovementProposal`, `AgentImprovementReview`, `CandidateExecutionEvidence`, `ExecuteApprovedAgentCandidateOptions`, `ExecuteApprovedAgentCandidateResult`, `ProposeAgentImprovementOptions`, `ProposeAgentImprovementResult`, `PullCertifiedOptions`, `ReviewAgentImprovementInput`, `AgentImprovementEvaluation`, `AgentImprovementReviewDecision`. ### Recursive atom + loop kernel (alias of ./runtime) diff --git a/docs/canonical-api.md b/docs/canonical-api.md index b3afe9ab..ac72bfe4 100644 --- a/docs/canonical-api.md +++ b/docs/canonical-api.md @@ -2,7 +2,7 @@ -> **Version 0.91.0.** The export inventory + per-symbol signatures live in the generated `docs/api/` reference: **`docs/api/primitive-catalog.md`** is the never-stale, grouped list of every primitive to reuse (own surface + the agent-eval judge / authenticity / verification / statistics / campaign / token-usage surfaces), with each one's import path and one-line summary read live from source; the per-module pages hold the full signatures. The pinned substrate is agent-eval `>=0.101.0 <1.0.0`; the sandbox substrate that materializes profiles into harness shapes is `@tangle-network/sandbox` (peer `>=0.8.0 <1.0.0`). The neutral contract types (`AgentProfile`, `AgentProfileMcpServer`, `HarnessType`, `ReasoningEffort`, `Part`/`ToolPart`/`ToolState`, plus environment-provider types) are owned by **`@tangle-network/agent-interface`** (peer `>=0.24.0 <1.0.0`) — the single source of truth. Substrate primitives are re-exported through `@tangle-network/agent-eval/contract` (or `/campaign`), not local to this package — the catalog's §2 shows exactly which subpath each lives under. +> **Version 0.92.0.** The export inventory + per-symbol signatures live in the generated `docs/api/` reference: **`docs/api/primitive-catalog.md`** is the never-stale, grouped list of every primitive to reuse (own surface + the agent-eval judge / authenticity / verification / statistics / campaign / token-usage surfaces), with each one's import path and one-line summary read live from source; the per-module pages hold the full signatures. The pinned substrate is agent-eval `>=0.101.0 <1.0.0`; the sandbox substrate that materializes profiles into harness shapes is `@tangle-network/sandbox` (peer `>=0.8.0 <1.0.0`). The neutral contract types (`AgentProfile`, `AgentProfileMcpServer`, `HarnessType`, `ReasoningEffort`, `Part`/`ToolPart`/`ToolState`, plus environment-provider types) are owned by **`@tangle-network/agent-interface`** (peer `>=0.25.0 <1.0.0`) — the single source of truth. Substrate primitives are re-exported through `@tangle-network/agent-eval/contract` (or `/campaign`), not local to this package — the catalog's §2 shows exactly which subpath each lives under. > > **`./loops` is the runtime barrel** — `package.json` maps it to `src/runtime/index.ts`. Everything below labelled `/loops` is the recursive-atom + loop-kernel surface. > @@ -86,7 +86,7 @@ A general "loop" primitive is the single most common modelling error in this rep | Pick the **chat backend an in-process turn runs on** (`router`/`tcloud`/`cli-bridge`/`sandbox`) from a product flag | `resolveAgentBackend({ backend })` — root `.` | the copy-pasted `backend-name → createOpenAICompatibleBackend` branch every eval product hand-rolled (the copies drift) | | Pick / register a leaf backend, or bring your own agent | `createExecutor({ backend })` / `createExecutorRegistry()` / implement `Executor` — `/loops` | a per-vendor adapter or closed `inline\|sandbox\|cli` switch (won't report through the `UsageEvent` channel) | | Evolve a **prompt/string** surface | `gepaProposer({ llm, model, target })` (default inside `selfImprove`; the skill-surface twin is `skillOptProposer`, same source) — `agent-eval/campaign` | a hand-rolled prompt-mutation reflection loop with its own Pareto bookkeeping | -| Self-improve a profile (one pluggable verb) — START HERE (self-improvement) | `improve(profile, findings, { surface, gate })` — root `.` (the RSI verb; defaults the generator from `surface`, wraps `selfImprove`) | a bespoke optimize loop, or calling `selfImprove`/a skill-optimizer directly for the common case | +| Self-improve a profile (one pluggable verb) — START HERE (self-improvement) | `improve(profile, findings, { surface, gate })` — root `.`; prompt and skill-document surfaces have built-in generators, tools/MCP/hooks/subagents/workflow/whole-profile take an explicit generator, rollout policy is deterministic, and code gets isolated incumbent/candidate worktrees | a bespoke optimize loop, calling `selfImprove`/a skill optimizer directly for the common case, or comparing code against an empty/string stand-in | | Measure **one profile artifact's marginal lift** (with-vs-without, score+cost) / catalog artifacts | `measureMarginalLift(...)` / `ArtifactRegistry` (`applyArtifact` is the one `ArtifactKind`→`AgentProfile`-field bridge) — `/lifecycle` | a hand-rolled with/without ablation loop, or a per-kind `if kind==='skill'…` profile-field switch | | Run the **whole artifact lifecycle** — generate→measure→promote→store→compose, then drift-watch/dedupe the live set — over ANY profile surface (skill/prompt/tool/MCP) | `runLifecycle({ baseline, generators, evalRunner, gate })` then `composeProfile(registry, base, query)`; maintain with `driftWatch(...)` / `dedupeArtifacts(...)` — `/lifecycle` | a per-surface improve loop, a hand-rolled promote→compose step, or re-running `measureMarginalLift` without the registry/gate spine. The ONLY per-surface code is a thin `CandidateGenerator` (`skillGenerator` distills, `promptGenerator`/`buildableGenerator` for the rest) | | Run the self-improvement loop with full substrate control | `selfImprove({ agent, scenarios, judge, baselineSurface })` — `agent-eval/contract` | a bespoke optimize loop or a parallel skill-optimizer | @@ -110,6 +110,9 @@ A general "loop" primitive is the single most common modelling error in this rep | Have a **supervisor spawn + live-drive workers in a backend you choose** and observe/steer/resume them | the **coordination MCP** — `createCoordinationTools` / `serveCoordinationMcp` over a live `Scope`; each worker's leaf is `createExecutor({ backend })` — `/mcp`,`/loops` | `detachedSessionDelegate` — own-sandbox-session only, one-shot, no live steer/recursion/conserved-budget | | Stand up a vertical agent in the eval loop | `defineAgent(manifest)` + `createSurfaceImprovementAdapter` — `/agent` | a per-vertical manifest parser, surface-validator, or bespoke `ImprovementAdapter` | | Observe + deliver Intelligence on a live agent (send RunRecords + receive certified profile/diffs) | `withIntelligence(agent, { project, target })` — `/intelligence` (proposals surfaced, never auto-applied; `effort: 'off'` proves inference-only billing) | a custom trace-wrapper, a second receive path, or hand-rolled effort/tier config | +| Turn trace evidence into one measured, review-only agent proposal | `proposeAgentImprovement({ analysis, profile, improvement })` — `/intelligence` | manually joining analysts, optimizers, evidence, uncertainty, and candidate identity | +| Record approve/reject/change-request feedback against one exact proposal | `reviewAgentImprovementProposal(proposal, review)` — `/intelligence` | a mutable status row that is not bound to candidate bytes | +| Execute and grade only an authenticated approved candidate | `executeApprovedAgentCandidate(options)` — `/intelligence`; low-level ports live at `/candidate-execution` | product-local claim/retry/isolation/receipt orchestration | | Fold **certified prompt additions into a system prompt you assemble yourself** (product chat routes) | `createCertifiedPromptSource({ target })` → `source.compose(base)` — `/intelligence` (cached, coalesced, fail-closed; `withIntelligence` rides the same source) | a module-scope cache + refresh-window + keep-last-known loop around `pullCertified` in product wiring | | Improve a KB with runtime agents, candidate workspaces, readiness checks, and measured supervised spend | `runKnowledgeImprovementJob(options)` from `/knowledge` | hand-wiring `improveKnowledgeBase` + a supervised updater + a readiness callback in every product | diff --git a/package.json b/package.json index bc2a3082..28124340 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tangle-network/agent-runtime", - "version": "0.91.0", + "version": "0.92.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": { @@ -149,6 +149,6 @@ }, "dependencies": { "@tangle-network/agent-knowledge": "^1.11.2", - "@tangle-network/agent-profile-materialize": "0.3.0" + "@tangle-network/agent-profile-materialize": "0.3.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 375155a9..38d4b547 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^1.11.2 version: 1.11.2(typescript@5.9.3) '@tangle-network/agent-profile-materialize': - specifier: 0.3.0 - version: 0.3.0 + specifier: 0.3.1 + version: 0.3.1 devDependencies: '@biomejs/biome': specifier: ^2.4.15 @@ -654,9 +654,6 @@ packages: '@tangle-network/agent-interface@0.17.1': resolution: {integrity: sha512-B7dRJTo0HSUtgBCB1VMwkTFYkLUaRr/4BcRglrQuGhGUwOzKv1RYyMejOVh5M3a5AagY9N79f7GYbjcA3UmnIA==} - '@tangle-network/agent-interface@0.21.0': - resolution: {integrity: sha512-jDxhVJgxymrvU1RLWxWKueuaWQIpBAfrW8BuVTB5m2Y4eFMLo1SawDBEMDLdZN4/Gf34xrFrsRk+PAj9brGKMQ==} - '@tangle-network/agent-interface@0.22.0': resolution: {integrity: sha512-7fsJhNdvTmOB1X9E2owl06jzyrqaN+jMkOPVKbK7dvNqQvf627PowCtL/edhUqEEv+K0FWtkwG3R3xqjX7VNZg==} @@ -668,8 +665,8 @@ packages: engines: {node: '>=20'} hasBin: true - '@tangle-network/agent-profile-materialize@0.3.0': - resolution: {integrity: sha512-zEVNjhfDFGPUjlSqwFitlzEjczerkw60ucxUGsjmz7LhUw7kI86SxCCpfK0rBmeaHjhDYNQfVE7VTwEJxAfyfg==} + '@tangle-network/agent-profile-materialize@0.3.1': + resolution: {integrity: sha512-yA/DaxmC+DsHdPl00iovR3tg80lQY1ukkHgGViLtzFYY7O46yZR9Ykhw/tMGTFYWFi5bzqjmr0NShSxdNmSzcQ==} '@tangle-network/sandbox@0.9.7': resolution: {integrity: sha512-9pCwJ5MlF7RUpp0AQKQDFyR0yu+E0udEhWkqhrlb/RuoJxlt72zVPuzO4FnMb1MZTkfjStmomC3k5xQyqi1YSA==} @@ -1651,10 +1648,6 @@ snapshots: dependencies: zod: 4.4.3 - '@tangle-network/agent-interface@0.21.0': - dependencies: - zod: 4.4.3 - '@tangle-network/agent-interface@0.22.0': dependencies: zod: 4.4.3 @@ -1676,9 +1669,9 @@ snapshots: - typescript - utf-8-validate - '@tangle-network/agent-profile-materialize@0.3.0': + '@tangle-network/agent-profile-materialize@0.3.1': dependencies: - '@tangle-network/agent-interface': 0.21.0 + '@tangle-network/agent-interface': 0.22.0 '@tangle-network/sandbox@0.9.7(viem@2.54.6(typescript@5.9.3)(zod@4.4.3))': dependencies: diff --git a/src/candidate-execution/bundle.ts b/src/candidate-execution/bundle.ts new file mode 100644 index 00000000..1f2ea483 --- /dev/null +++ b/src/candidate-execution/bundle.ts @@ -0,0 +1,17 @@ +import type { AgentCandidateBundle } from '@tangle-network/agent-interface' +import { agentCandidateBundleSchema } from '@tangle-network/agent-interface' + +import { canonicalCandidateDigest, immutableCandidateValue, omitTopLevelDigest } from './digest' + +export type AgentCandidateBundleInput = Omit + +/** Validate and content-address a candidate bundle before it crosses an approval boundary. */ +export function sealAgentCandidateBundle(input: AgentCandidateBundleInput): AgentCandidateBundle { + const digest = canonicalCandidateDigest(input) + const parsed = agentCandidateBundleSchema.parse({ ...input, digest }) + const parsedDigest = canonicalCandidateDigest(omitTopLevelDigest(parsed)) + if (parsedDigest !== digest) { + throw new Error('candidate bundle changed while validating its canonical wire shape') + } + return immutableCandidateValue(parsed) +} diff --git a/src/intelligence/improvement-cycle.ts b/src/intelligence/improvement-cycle.ts new file mode 100644 index 00000000..d8686236 --- /dev/null +++ b/src/intelligence/improvement-cycle.ts @@ -0,0 +1,506 @@ +import { type AnalystFinding, assertNoJudgeVerdict } from '@tangle-network/agent-eval/analyst' +import type { Scenario, SelfImproveResult } from '@tangle-network/agent-eval/contract' +import type { + AgentCandidateBundle, + AgentCandidateConfigValue, + AgentCandidateProfile, + AgentCandidateResourceRef, + AgentProfile, + Sha256Digest, +} from '@tangle-network/agent-interface' +import { agentCandidateBundleSchema, agentProfileSchema } from '@tangle-network/agent-interface' +import { runAnalystLoop } from '../analyst-loop' +import type { RunAnalystLoopOpts, RunAnalystLoopResult } from '../analyst-loop/types' +import { + type AgentCandidateBundleInput, + sealAgentCandidateBundle, +} from '../candidate-execution/bundle' +import { + canonicalCandidateBytes, + canonicalCandidateDigest, + canonicalCandidateDocument, + immutableCandidateValue, + omitTopLevelDigest, +} from '../candidate-execution/digest' +import { + type ExecutePreparedAgentCandidateOptions, + executePreparedAgentCandidate, +} from '../candidate-execution/execute' +import { + type PrepareAgentCandidateExecutionOptions, + prepareAgentCandidateExecution, +} from '../candidate-execution/prepare' +import type { + AgentCandidateExecutionPorts, + AgentCandidateRunFinalization, + AgentCandidateTaskExecution, +} from '../candidate-execution/types' +import { verifyAgentCandidateBundle } from '../candidate-execution/verify' +import { + type ImproveOptions, + type ImproveResult, + type ImproveSurface, + improve, +} from '../improvement/improve' + +export type AgentImprovementEvaluation = Pick< + SelfImproveResult, + | 'baseline' + | 'winner' + | 'lift' + | 'diff' + | 'provenance' + | 'gateDecision' + | 'generationsExplored' + | 'durationMs' + | 'totalCostUsd' + | 'insight' + | 'power' +> + +export interface AgentImprovementProposal< + TScenario extends Scenario = Scenario, + TArtifact = unknown, +> { + schemaVersion: 1 + kind: 'agent-improvement-proposal' + runId: string + surface: ImproveSurface + proposedAt: string + baselineProfileHash: string + candidateProfile: AgentProfile + candidateProfileHash: string + findings: AnalystFinding[] + evaluation: AgentImprovementEvaluation + candidateBundle?: AgentCandidateBundle + digest: Sha256Digest +} + +export type AgentImprovementReviewDecision = 'approve' | 'reject' | 'request-changes' + +export interface AgentImprovementReview { + schemaVersion: 1 + kind: 'agent-improvement-review' + proposalDigest: Sha256Digest + candidateBundleDigest?: Sha256Digest + decision: AgentImprovementReviewDecision + reviewedBy: string + reviewedAt: string + reason: string + feedback?: string + digest: Sha256Digest +} + +export interface CandidateExecutionEvidence { + proposalDigest: Sha256Digest + reviewDigest: Sha256Digest + bundleDigest: Sha256Digest + executionId: string + executionPlanDigest: Sha256Digest + materializationReceiptDigest: Sha256Digest + succeeded: boolean + runReceiptDigest?: Sha256Digest +} + +export interface ProposeAgentImprovementOptions { + runId: string + profile: AgentProfile + analysis: Omit + improvement: ImproveOptions + /** + * Optional environment adapter that freezes an executable bundle after the + * measured comparison recommends the candidate. Runtime validates and + * computes the bundle digest; adapters never implement hashing themselves. + */ + buildCandidate?: (input: { + analysis: RunAnalystLoopResult + improvement: ImproveResult + }) => AgentCandidateBundleInput | Promise + now?: () => Date +} + +export interface ProposeAgentImprovementResult { + analysis: RunAnalystLoopResult + improvement: ImproveResult + proposal: AgentImprovementProposal +} + +export interface ReviewAgentImprovementInput { + decision: AgentImprovementReviewDecision + reviewedBy: string + reason: string + feedback?: string + now?: () => Date +} + +export interface ExecuteApprovedAgentCandidateOptions { + proposal: AgentImprovementProposal + review: AgentImprovementReview + /** Product-owned authentication check for the persisted approval record. */ + authorizeReview: ( + review: AgentImprovementReview, + proposal: AgentImprovementProposal, + ) => boolean | Promise + task: AgentCandidateTaskExecution + ports: AgentCandidateExecutionPorts + preparation?: PrepareAgentCandidateExecutionOptions + execution: ExecutePreparedAgentCandidateOptions +} + +export interface ExecuteApprovedAgentCandidateResult { + finalization: AgentCandidateRunFinalization + evidence: CandidateExecutionEvidence +} + +/** Analyze one run and produce one measured, review-only improvement proposal. */ +export async function proposeAgentImprovement( + options: ProposeAgentImprovementOptions, +): Promise> { + if (options.improvement.skills?.writeBack) { + throw new Error('proposeAgentImprovement cannot write a skill before human approval') + } + const analysis = await runAnalystLoop({ + ...options.analysis, + runId: options.runId, + }) + const findings = assertNoJudgeVerdict( + analysis.analystResult.findings, + 'proposeAgentImprovement findings', + ) + const improvement = await improve(options.profile, [...findings], options.improvement) + const candidateBundle = + improvement.shipped && options.buildCandidate + ? sealAgentCandidateBundle(await options.buildCandidate({ analysis, improvement })) + : undefined + if (candidateBundle) assertCandidateProfileBinding(improvement.profile, candidateBundle.profile) + const surface = options.improvement.surface ?? 'prompt' + const evaluation = canonicalJsonValue(improvementEvaluation(improvement.raw)) + const proposalFindings = canonicalJsonValue([...findings]) + const withoutDigest = { + schemaVersion: 1 as const, + kind: 'agent-improvement-proposal' as const, + runId: options.runId, + surface, + proposedAt: (options.now ?? (() => new Date()))().toISOString(), + baselineProfileHash: canonicalCandidateDigest(options.profile), + candidateProfile: improvement.profile, + candidateProfileHash: canonicalCandidateDigest(improvement.profile), + findings: proposalFindings, + evaluation, + ...(candidateBundle ? { candidateBundle } : {}), + } + const proposal = + canonicalCandidateDocument>(withoutDigest).value + return { analysis, improvement, proposal } +} + +/** Persist an approve/reject/change-request decision bound to one exact proposal. */ +export function reviewAgentImprovementProposal( + inputProposal: AgentImprovementProposal, + input: ReviewAgentImprovementInput, +): AgentImprovementReview { + const proposal = verifyAgentImprovementProposal(inputProposal) + if (!input.reviewedBy.trim()) throw new Error('candidate review requires reviewedBy') + if (!input.reason.trim()) throw new Error('candidate review requires a reason') + if (input.decision === 'approve') { + if (proposal.evaluation.gateDecision !== 'ship') { + throw new Error('candidate cannot be approved without a passing measured comparison') + } + if (!proposal.candidateBundle) { + throw new Error('candidate cannot be approved until an executable bundle is sealed') + } + } + const withoutDigest = { + schemaVersion: 1 as const, + kind: 'agent-improvement-review' as const, + proposalDigest: proposal.digest, + ...(proposal.candidateBundle ? { candidateBundleDigest: proposal.candidateBundle.digest } : {}), + decision: input.decision, + reviewedBy: input.reviewedBy, + reviewedAt: (input.now ?? (() => new Date()))().toISOString(), + reason: input.reason, + ...(input.feedback === undefined ? {} : { feedback: input.feedback }), + } + return canonicalCandidateDocument(withoutDigest).value +} + +/** Verify, materialize, run, grade, and receipt only the exact approved bundle. */ +export async function executeApprovedAgentCandidate( + options: ExecuteApprovedAgentCandidateOptions, +): Promise { + const proposal = verifyAgentImprovementProposal(options.proposal) + const review = verifyAgentImprovementReview(options.review) + if (review.decision !== 'approve') throw new Error('candidate review is not an approval') + if (review.proposalDigest !== proposal.digest) { + throw new Error('candidate approval does not match the proposed improvement') + } + const bundle = proposal.candidateBundle + if (!bundle) throw new Error('approved proposal does not contain an executable candidate bundle') + if (review.candidateBundleDigest !== bundle.digest) { + throw new Error('candidate approval does not match the executable bundle') + } + if (!(await options.authorizeReview(review, proposal))) { + throw new Error('candidate approval was not authorized by the configured authority') + } + + const verified = await verifyAgentCandidateBundle(bundle, options.ports) + const prepared = await prepareAgentCandidateExecution( + verified, + options.task, + options.ports, + options.preparation, + ) + const finalization = await executePreparedAgentCandidate(prepared, options.execution) + return { + finalization, + evidence: { + proposalDigest: proposal.digest, + reviewDigest: review.digest, + bundleDigest: bundle.digest, + executionId: prepared.executionId, + executionPlanDigest: prepared.executionPlan.value.digest, + materializationReceiptDigest: prepared.materializationReceipt.digest, + succeeded: finalization.succeeded, + ...(finalization.succeeded ? { runReceiptDigest: finalization.receipt.digest } : {}), + }, + } +} + +/** Validate a proposal's schema, profile, sealed bundle, and canonical digest. */ +export function verifyAgentImprovementProposal(input: unknown): AgentImprovementProposal { + if ( + !isRecord(input) || + input.kind !== 'agent-improvement-proposal' || + input.schemaVersion !== 1 + ) { + throw new Error('invalid agent improvement proposal') + } + const proposal = input as unknown as AgentImprovementProposal + const parsedProfile = parseExactAgentProfile(proposal.candidateProfile) + if (proposal.candidateProfileHash !== canonicalCandidateDigest(parsedProfile)) { + throw new Error('proposal candidateProfileHash does not match candidateProfile') + } + if (!Array.isArray(proposal.findings)) throw new Error('proposal findings must be an array') + if (!isSha256Digest(proposal.digest)) throw new Error('proposal digest is invalid') + if (proposal.candidateBundle) { + const parsedBundle = agentCandidateBundleSchema.parse(proposal.candidateBundle) + const sealed = sealAgentCandidateBundle(omitTopLevelDigest(parsedBundle)) + if (sealed.digest !== parsedBundle.digest) + throw new Error('proposal candidate bundle digest is invalid') + assertCandidateProfileBinding(parsedProfile, sealed.profile) + } + const actual = canonicalCandidateDigest(omitTopLevelDigest(proposal)) + if (actual !== proposal.digest) + throw new Error('agent improvement proposal digest does not match') + return immutableCandidateValue(proposal) +} + +function parseExactAgentProfile(input: unknown): AgentProfile { + const parsed = agentProfileSchema.parse(input) as AgentProfile + if ( + !Buffer.from(canonicalCandidateBytes(input)).equals( + Buffer.from(canonicalCandidateBytes(parsed)), + ) + ) { + throw new Error('proposal candidate profile contains fields unsupported by sealed candidates') + } + return parsed +} + +function assertCandidateProfileBinding( + measuredInput: AgentProfile, + bundled: AgentCandidateProfile, +): void { + const measured = parseExactAgentProfile(measuredInput) + if (measured.connections || measured.metadata || measured.extensions) { + throw new Error('proposal candidate profile contains fields unsupported by sealed candidates') + } + const normalized = candidateProfileAsAgentProfile(bundled) + if (canonicalCandidateDigest(measured) !== canonicalCandidateDigest(normalized)) { + throw new Error('proposal candidateProfile does not match candidateBundle.profile') + } +} + +function candidateProfileAsAgentProfile(candidate: AgentCandidateProfile): AgentProfile { + const value = candidate as unknown as Record + const output: Record = {} + for (const key of [ + 'name', + 'description', + 'version', + 'tags', + 'prompt', + 'harness', + 'permissions', + 'tools', + 'confidential', + ]) { + if (value[key] !== undefined) output[key] = value[key] + } + if (candidate.model) output.model = { ...candidate.model } + if (candidate.mcp) { + output.mcp = Object.fromEntries( + Object.entries(candidate.mcp).map(([name, server]) => [ + name, + { + ...server, + ...(server.args ? { args: server.args.map(publicValue) } : {}), + ...(server.env ? { env: mapPublicValues(server.env) } : {}), + }, + ]), + ) + } + if (candidate.subagents) output.subagents = mapRecord(candidate.subagents) + if (candidate.modes) output.modes = mapRecord(candidate.modes) + if (candidate.hooks) { + output.hooks = Object.fromEntries( + Object.entries(candidate.hooks).map(([event, hooks]) => [ + event, + hooks.map((hook) => ({ + ...hook, + command: [hook.executable, ...(hook.args ?? []).map(publicValue)] + .map(shellQuote) + .join(' '), + ...(hook.env ? { env: mapPublicValues(hook.env) } : {}), + })), + ]), + ) + } + if (candidate.resources) { + if (candidate.resources.failOnError !== true) { + throw new Error('proposal candidate profile contains fields unsupported by sealed candidates') + } + output.resources = { + failOnError: true, + ...(candidate.resources.files + ? { + files: candidate.resources.files.map((file) => ({ + ...file, + resource: publicResource(file.resource), + })), + } + : {}), + ...(candidate.resources.tools + ? { tools: candidate.resources.tools.map(publicResource) } + : {}), + ...(candidate.resources.skills + ? { skills: candidate.resources.skills.map(publicResource) } + : {}), + ...(candidate.resources.agents + ? { agents: candidate.resources.agents.map(publicResource) } + : {}), + ...(candidate.resources.commands + ? { commands: candidate.resources.commands.map(publicResource) } + : {}), + ...(candidate.resources.instructions !== undefined + ? { + instructions: + typeof candidate.resources.instructions === 'string' + ? candidate.resources.instructions + : publicResource(candidate.resources.instructions), + } + : {}), + } + } + return output as AgentProfile +} + +function publicResource(resource: AgentCandidateResourceRef): unknown { + if (resource.kind === 'inline') { + return { kind: 'inline', name: resource.name, content: resource.content } + } + return { + kind: 'github', + repository: `${resource.repository.owner}/${resource.repository.repo}`, + path: resource.path, + ref: resource.commit, + ...(resource.name ? { name: resource.name } : {}), + } +} + +function publicValue(value: AgentCandidateConfigValue): string { + return value.value +} + +function mapPublicValues( + values: Record, +): Record { + return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, publicValue(value)])) +} + +function mapRecord(values: Record): Record { + return Object.fromEntries( + Object.entries(values).map(([key, value]) => [key, { ...value }]), + ) as Record +} + +function shellQuote(value: string): string { + return /^[A-Za-z0-9_./:@%+=,-]+$/.test(value) ? value : `'${value.replaceAll("'", `'"'"'`)}'` +} + +/** Validate a review's decision fields and canonical digest. */ +export function verifyAgentImprovementReview(input: unknown): AgentImprovementReview { + if (!isRecord(input) || input.kind !== 'agent-improvement-review' || input.schemaVersion !== 1) { + throw new Error('invalid agent improvement review') + } + const review = input as unknown as AgentImprovementReview + if (!isSha256Digest(review.digest) || !isSha256Digest(review.proposalDigest)) { + throw new Error('candidate review digest is invalid') + } + if (review.candidateBundleDigest !== undefined && !isSha256Digest(review.candidateBundleDigest)) { + throw new Error('candidate review bundle digest is invalid') + } + if (!['approve', 'reject', 'request-changes'].includes(review.decision)) { + throw new Error('candidate review decision is invalid') + } + const actual = canonicalCandidateDigest(omitTopLevelDigest(review)) + if (actual !== review.digest) throw new Error('agent improvement review digest does not match') + return immutableCandidateValue(review) +} + +function improvementEvaluation( + result: SelfImproveResult, +): AgentImprovementEvaluation { + return { + baseline: result.baseline, + winner: result.winner, + lift: result.lift, + diff: result.diff, + provenance: result.provenance, + gateDecision: result.gateDecision, + generationsExplored: result.generationsExplored, + durationMs: result.durationMs, + totalCostUsd: result.totalCostUsd, + insight: result.insight, + ...(result.power === undefined ? {} : { power: result.power }), + } +} + +function isRecord(value: unknown): value is Record { + return value !== null && typeof value === 'object' && !Array.isArray(value) +} + +function isSha256Digest(value: unknown): value is Sha256Digest { + return typeof value === 'string' && /^sha256:[a-f0-9]{64}$/.test(value) +} + +function canonicalJsonValue(value: T, path = '$'): T { + if (value === null || typeof value === 'string' || typeof value === 'boolean') return value + if (typeof value === 'number') { + if (!Number.isFinite(value)) throw new Error(`non-finite number at ${path}`) + return value + } + if (Array.isArray(value)) { + return value.map((entry, index) => { + if (entry === undefined) throw new Error(`undefined array entry at ${path}[${index}]`) + return canonicalJsonValue(entry, `${path}[${index}]`) + }) as T + } + if (typeof value === 'object') { + const entries = Object.entries(value as Record) + .filter(([, entry]) => entry !== undefined) + .map(([key, entry]) => [key, canonicalJsonValue(entry, `${path}.${key}`)]) + return Object.fromEntries(entries) as T + } + throw new Error(`unsupported proposal value at ${path}`) +} diff --git a/src/intelligence/index.ts b/src/intelligence/index.ts index 5dd8438c..a29d0540 100644 --- a/src/intelligence/index.ts +++ b/src/intelligence/index.ts @@ -1,10 +1,10 @@ /** * - * Tangle Intelligence SDK — the Observe + Mode-0 product layer. + * Tangle Intelligence SDK — trace capture plus reviewable improvement. * - * A thin, best-effort wrapper over the shipped trace-export substrate - * (`createOtelExporter` in `../otel-export`). It does exactly two things in - * this slice: + * The client keeps live-agent trace delivery best-effort. The separate + * improvement-cycle exports analyze completed traces, measure one candidate, + * bind human review, and execute only an approved immutable bundle. * * 1. OBSERVE — wrap a generic agent and export one trace span per call to * Tangle Intelligence, swallowing every export failure so a live agent @@ -15,11 +15,6 @@ * and at OFF `intelligenceUsd` is provably `0` — the mechanism that proves * an OFF customer paid inference-only. * - * Behavior-changing intelligence (analyst steer, candidate promotion, loops) - * is a LATER phase and is NOT built here. This wrapper only Observes and passes - * through; there is no abort path, so the only fail-soft surface is the - * telemetry export. - * * @experimental */ @@ -44,6 +39,7 @@ import { isIntelligenceOff, resolveEffort, } from './effort' +import type { CandidateExecutionEvidence } from './improvement-cycle' import { type Redactor, resolveRedactor } from './redact' export type { @@ -97,6 +93,25 @@ export { isIntelligenceOff, resolveEffort, } from './effort' +export type { + AgentImprovementEvaluation, + AgentImprovementProposal, + AgentImprovementReview, + AgentImprovementReviewDecision, + CandidateExecutionEvidence, + ExecuteApprovedAgentCandidateOptions, + ExecuteApprovedAgentCandidateResult, + ProposeAgentImprovementOptions, + ProposeAgentImprovementResult, + ReviewAgentImprovementInput, +} from './improvement-cycle' +export { + executeApprovedAgentCandidate, + proposeAgentImprovement, + reviewAgentImprovementProposal, + verifyAgentImprovementProposal, + verifyAgentImprovementReview, +} from './improvement-cycle' export type { Redactor } from './redact' export { defaultRedactor, resolveRedactor } from './redact' export type { ProvisionedHost, ResolveCtx } from './resolver' @@ -165,6 +180,8 @@ export interface RunRecord { reasoning?: number } error?: { name: string; message: string; code?: string } + /** Exact proposal → review → execution → receipt linkage for candidate runs. */ + candidateExecution?: CandidateExecutionEvidence } /** @@ -188,6 +205,7 @@ export interface RunReport { commitSha?: string tokens?: RunRecord['tokens'] error?: RunRecord['error'] + candidateExecution?: CandidateExecutionEvidence } /** Repo coordinates a product may declare for the (later) Gated-PR mode. The @@ -235,6 +253,13 @@ export interface IntelligenceConfig { commitSha?: string /** Runtime-event payload policy. Tool inputs/results remain off unless explicitly enabled. */ runtimeTelemetry?: RuntimeTelemetryOptions + /** + * Payloads are metadata-only by default: the run span carries a stable hash + * and UTF-8 byte count, but not the redacted content. Set `full` only when + * the configured OTLP destination is approved to receive complete redacted + * inputs, outputs, and profiles. + */ + payloadAttributes?: 'metadata' | 'full' } /** Metadata describing one traced run. `runId`/`traceId` default to fresh ids. */ @@ -393,6 +418,18 @@ function serializeJson(value: unknown): string { return s } +function addPayloadAttributes( + labels: Record, + key: string, + value: unknown, + includeFullPayload: boolean, +): void { + const serialized = serializeJson(value) + labels[`${key}_hash`] = contentHash(serialized) + labels[`${key}_bytes`] = Buffer.byteLength(serialized, 'utf8') + if (includeFullPayload) labels[key] = serialized +} + function randomHex(chars: number): string { const bytes = new Uint8Array(Math.ceil(chars / 2)) if (typeof globalThis.crypto?.getRandomValues === 'function') { @@ -419,6 +456,7 @@ export function createIntelligenceClient(config: IntelligenceConfig): Intelligen const effort = resolveEffortConfig(config.effort) const intelligenceOff = isIntelligenceOff(effort) const redactor = resolveRedactor(config.redact) + const includeFullPayload = config.payloadAttributes === 'full' const apiKey = config.apiKey ?? (typeof process !== 'undefined' ? process.env.TANGLE_API_KEY : undefined) // The ONE base URL drives both send and receive; the OTLP ingest lives at @@ -460,8 +498,12 @@ export function createIntelligenceClient(config: IntelligenceConfig): Intelligen } const redactedInput = meta.input !== undefined ? redactor(meta.input) : undefined const redactedOutput = output !== undefined ? redactor(output) : undefined - if (redactedInput !== undefined) labels['tangle.input'] = serializeJson(redactedInput) - if (redactedOutput !== undefined) labels['tangle.output'] = serializeJson(redactedOutput) + if (redactedInput !== undefined) { + addPayloadAttributes(labels, 'tangle.input', redactedInput, includeFullPayload) + } + if (redactedOutput !== undefined) { + addPayloadAttributes(labels, 'tangle.output', redactedOutput, includeFullPayload) + } // Flat span with VERBATIM attribute keys — the plane's session/model/ // cost readers exact-match `tangle.sessionId` / `gen_ai.request.model`, // so the loop-namespacing builder must not be used here. @@ -538,16 +580,44 @@ export function createIntelligenceClient(config: IntelligenceConfig): Intelligen ...(record.runtimeEvents ? { 'tangle.runtime.event_count': record.runtimeEvents.length } : {}), + ...(record.candidateExecution + ? { + 'tangle.candidate.proposal_digest': record.candidateExecution.proposalDigest, + 'tangle.candidate.review_digest': record.candidateExecution.reviewDigest, + 'tangle.candidate.bundle_digest': record.candidateExecution.bundleDigest, + 'tangle.candidate.execution_id': record.candidateExecution.executionId, + 'tangle.candidate.execution_plan_digest': + record.candidateExecution.executionPlanDigest, + 'tangle.candidate.materialization_receipt_digest': + record.candidateExecution.materializationReceiptDigest, + 'tangle.candidate.succeeded': record.candidateExecution.succeeded, + ...(record.candidateExecution.runReceiptDigest + ? { + 'tangle.candidate.run_receipt_digest': + record.candidateExecution.runReceiptDigest, + } + : {}), + } + : {}), } if (record.profile) { - labels['tangle.agent.profile'] = serializeJson(redactor(record.profile)) + addPayloadAttributes( + labels, + 'tangle.agent.profile', + redactor(record.profile), + includeFullPayload, + ) labels['tangle.agent.profile_hash'] = contentHash(record.profile) if (record.profile.name) labels['gen_ai.agent.name'] = record.profile.name } const redactedInput = record.input !== undefined ? redactor(record.input) : undefined const redactedOutput = record.output !== undefined ? redactor(record.output) : undefined - if (redactedInput !== undefined) labels['tangle.input'] = serializeJson(redactedInput) - if (redactedOutput !== undefined) labels['tangle.output'] = serializeJson(redactedOutput) + if (redactedInput !== undefined) { + addPayloadAttributes(labels, 'tangle.input', redactedInput, includeFullPayload) + } + if (redactedOutput !== undefined) { + addPayloadAttributes(labels, 'tangle.output', redactedOutput, includeFullPayload) + } const now = Date.now() const runSpan = flatOtelSpan( 'tangle.intelligence.run', diff --git a/src/intelligence/with-intelligence.test.ts b/src/intelligence/with-intelligence.test.ts index 4c257a23..e38e4478 100644 --- a/src/intelligence/with-intelligence.test.ts +++ b/src/intelligence/with-intelligence.test.ts @@ -242,6 +242,16 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { latencyMs: 250, }, ], + candidateExecution: { + proposalDigest: `sha256:${'1'.repeat(64)}`, + reviewDigest: `sha256:${'2'.repeat(64)}`, + bundleDigest: `sha256:${'3'.repeat(64)}`, + executionId: 'candidate-execution-1', + executionPlanDigest: `sha256:${'4'.repeat(64)}`, + materializationReceiptDigest: `sha256:${'5'.repeat(64)}`, + succeeded: true, + runReceiptDigest: `sha256:${'6'.repeat(64)}`, + }, }) return 'answer' }, @@ -259,6 +269,7 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { commitSha: 'a'.repeat(40), repo: { owner: 'tangle-network', name: 'support', baseBranch: 'main' }, runtimeTelemetry: { includeControlPayloads: true }, + payloadAttributes: 'full', }, ) await agent({ q: longInput }) @@ -279,6 +290,8 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { expect(attrs['gen_ai.usage.output_tokens']).toBe(7) expect(String(attrs['tangle.input'])).toContain(longInput) expect(String(attrs['tangle.input'])).not.toContain('[truncated]') + expect(attrs['tangle.input_hash']).toEqual(expect.any(String)) + expect(attrs['tangle.input_bytes']).toBeGreaterThan(5000) expect(JSON.parse(String(attrs['tangle.agent.profile']))).toMatchObject({ name: 'support-agent', tools: { mcp__linear__linear_graphql: true }, @@ -286,6 +299,9 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { expect(attrs['tangle.agent.profile_hash']).toEqual(expect.any(String)) expect(attrs['tool.name']).toBe('mcp__linear__linear_graphql') expect(String(attrs['tool.input'])).toContain(longInput) + expect(attrs['tangle.candidate.execution_id']).toBe('candidate-execution-1') + expect(attrs['tangle.candidate.proposal_digest']).toBe(`sha256:${'1'.repeat(64)}`) + expect(attrs['tangle.candidate.run_receipt_digest']).toBe(`sha256:${'6'.repeat(64)}`) } finally { vi.useRealTimers() } @@ -309,6 +325,43 @@ describe('withIntelligence — SEND (a typed RunRecord to /v1/otlp)', () => { } }) + it('exports payload hashes and byte counts without content by default', async () => { + vi.useFakeTimers() + try { + const posts: unknown[] = [] + vi.stubGlobal( + 'fetch', + vi.fn(async (_url: unknown, init: unknown) => { + const body = (init as { body?: string })?.body + if (body) posts.push(JSON.parse(body)) + return { ok: true, status: 200, async json() {} } as unknown as Response + }), + ) + const pull = vi.fn(async () => jsonResponse(COMPOSED)) as unknown as typeof fetch + const agent = withIntelligence(async () => 'private output', { + project: 'support-agent', + apiKey: 'k', + baseUrl: 'https://plane.test', + fetchImpl: pull, + profile: { name: 'support-agent' }, + }) + + await agent('private input') + await agent.flush() + + const attrs = attrsOf(posts[0]) + expect(attrs['tangle.input']).toBeUndefined() + expect(attrs['tangle.output']).toBeUndefined() + expect(attrs['tangle.agent.profile']).toBeUndefined() + expect(attrs['tangle.input_hash']).toEqual(expect.any(String)) + expect(attrs['tangle.input_bytes']).toBeGreaterThan(0) + expect(attrs['tangle.output_hash']).toEqual(expect.any(String)) + expect(attrs['tangle.agent.profile_hash']).toEqual(expect.any(String)) + } finally { + vi.useRealTimers() + } + }) + it('exports a failed run before rethrowing the agent error', async () => { vi.useFakeTimers() try { diff --git a/src/intelligence/with-intelligence.ts b/src/intelligence/with-intelligence.ts index 69160a50..56c458bd 100644 --- a/src/intelligence/with-intelligence.ts +++ b/src/intelligence/with-intelligence.ts @@ -265,6 +265,9 @@ export function withIntelligence( : {}), ...(tokens !== undefined ? { tokens } : {}), ...(error !== undefined ? { error } : {}), + ...(report.candidateExecution !== undefined + ? { candidateExecution: report.candidateExecution } + : {}), } client.exportRunRecord(record) } diff --git a/tests/improvement-cycle.test.ts b/tests/improvement-cycle.test.ts new file mode 100644 index 00000000..f87b0bc3 --- /dev/null +++ b/tests/improvement-cycle.test.ts @@ -0,0 +1,330 @@ +import { type AnalystFinding, InMemoryTraceStore } from '@tangle-network/agent-eval' +import type { + DispatchContext, + JudgeConfig, + MutableSurface, + Scenario, + SurfaceProposer, +} from '@tangle-network/agent-eval/contract' +import { afterEach, describe, expect, it, vi } from 'vitest' +import type { AnalystRegistryLike } from '../src/analyst-loop/types' +import { InMemoryAgentCandidateExecutionClaimStore } from '../src/candidate-execution/claim' +import type { + AgentCandidateExecutorPort, + AgentCandidateExecutorRequest, +} from '../src/candidate-execution/types' +import { + executeApprovedAgentCandidate, + proposeAgentImprovement, + reviewAgentImprovementProposal, + verifyAgentImprovementProposal, + verifyAgentImprovementReview, +} from '../src/intelligence/improvement-cycle' +import { + cleanupCandidateFixtures, + createCandidateExecutionFixture, + createCandidateOutputFixture, + unchangedTaskOutcomeCapture, +} from './helpers/candidate-execution-fixture' + +interface DemoScenario extends Scenario { + kind: 'demo' +} + +const scenarios: DemoScenario[] = Array.from({ length: 12 }, (_, index) => ({ + id: `scenario-${index}`, + kind: 'demo' as const, +})) + +const finding: AnalystFinding = { + schema_version: '1.0.0', + finding_id: 'finding-1', + analyst_id: 'improvement', + produced_at: '2026-07-10T00:00:00.000Z', + severity: 'high', + area: 'prompt', + claim: 'The agent omits the required marker.', + evidence_refs: [{ kind: 'span', id: 'span-1' }], + recommended_action: 'Add the measured marker.', + confidence: 0.9, + subject: 'agent-profile:prompt.systemPrompt', +} + +const registry = (findings: AnalystFinding[]): AnalystRegistryLike => ({ + list: () => [{ id: 'improvement' }], + run: async (runId) => ({ + run_id: runId, + correlation_id: `correlation-${runId}`, + started_at: '2026-07-10T00:00:00.000Z', + ended_at: '2026-07-10T00:00:01.000Z', + findings, + per_analyst: [ + { + analyst_id: 'improvement', + status: 'ok', + findings_count: findings.length, + latency_ms: 1, + cost_usd: 0, + }, + ], + total_cost_usd: 0, + }), +}) + +const proposer: SurfaceProposer = { + kind: 'scripted', + propose: async () => [ + { surface: 'PROMOTED', label: 'measured winner', rationale: 'addresses finding-1' }, + ], +} + +const judge: JudgeConfig = { + name: 'literal-marker', + dimensions: [{ key: 'marker', description: 'Contains the required marker.' }], + score: ({ artifact }) => { + const composite = artifact.includes('PROMOTED') ? 1 : 0 + return { dimensions: { marker: composite }, composite, notes: '' } + }, +} + +async function agent( + surface: MutableSurface, + _scenario: DemoScenario, + context: DispatchContext, +): Promise { + context.cost.observe(0.0001, 'fixture') + context.cost.observeTokens({ input: 1, output: 1 }) + return String(surface) +} + +function fixtureProfile() { + return { + name: 'candidate', + prompt: { + systemPrompt: 'BASELINE', + instructions: ['Inspect the repository, implement the fix, and run tests.'], + }, + model: { default: 'provider/model', reasoningEffort: 'high' as const }, + harness: 'codex' as const, + resources: { failOnError: true as const }, + } +} + +function alignedBundle( + bundle: Omit['bundle'], 'digest'>, + profile: { prompt?: { systemPrompt?: string } }, +) { + return { + ...bundle, + profile: { + ...bundle.profile, + prompt: { + ...bundle.profile.prompt, + systemPrompt: profile.prompt?.systemPrompt, + }, + }, + } +} + +afterEach(() => { + cleanupCandidateFixtures() + vi.restoreAllMocks() +}) + +describe('agent improvement lifecycle', () => { + it('analyzes, measures, approves, executes, grades, and links one exact receipt', async () => { + const fixture = createCandidateExecutionFixture() + const { digest: _digest, ...bundleInput } = fixture.bundle + const profile = fixtureProfile() + const proposed = await proposeAgentImprovement({ + runId: 'analysis-run-1', + profile, + analysis: { registry: registry([finding]), inputs: {}, findingsStore: null, log: () => {} }, + improvement: { + surface: 'prompt', + generator: proposer, + scenarios, + judge, + agent, + budget: { generations: 1, populationSize: 2, reps: 3, holdoutFraction: 0.5 }, + }, + buildCandidate: ({ improvement }) => alignedBundle(bundleInput, improvement.profile), + now: () => new Date('2026-07-10T01:00:00.000Z'), + }) + + expect(proposed.proposal.evaluation.gateDecision).toBe('ship') + expect(proposed.proposal.evaluation.lift).toBeGreaterThan(0) + expect(proposed.proposal.findings).toEqual([finding]) + expect(proposed.proposal.candidateProfile.prompt?.systemPrompt).toBe('PROMOTED') + expect(proposed.proposal.candidateBundle?.digest).toMatch(/^sha256:[a-f0-9]{64}$/) + expect(verifyAgentImprovementProposal(proposed.proposal)).toEqual(proposed.proposal) + + const review = reviewAgentImprovementProposal(proposed.proposal, { + decision: 'approve', + reviewedBy: 'operator@example.com', + reason: 'Measured winner passed the held-back scenarios.', + now: () => new Date('2026-07-10T02:00:00.000Z'), + }) + expect(verifyAgentImprovementReview(review)).toEqual(review) + + const traceStore = new InMemoryTraceStore() + let request: AgentCandidateExecutorRequest | undefined + const executor: AgentCandidateExecutorPort = { + execute: async (input) => { + request = input + await traceStore.appendRun({ + runId: input.trace.runId, + scenarioId: 'approved-candidate', + startedAt: 100, + endedAt: 200, + status: 'completed', + tags: { ...input.trace.tags }, + }) + return { executionId: input.executionId, termination: { kind: 'exit', exitCode: 0 } } + }, + stopAndCapture: async () => ({ + stopped: true, + taskOutcome: unchangedTaskOutcomeCapture(fixture), + }), + } + const outputs = createCandidateOutputFixture() + const executed = await executeApprovedAgentCandidate({ + proposal: proposed.proposal, + review, + authorizeReview: async (candidateReview) => candidateReview.digest === review.digest, + task: fixture.task, + ports: fixture.ports, + execution: { + executor, + traceStore, + claimStore: new InMemoryAgentCandidateExecutionClaimStore(), + ...outputs, + }, + }) + + expect(request).toBeDefined() + expect(executed.finalization.succeeded).toBe(true) + expect(executed.evidence).toMatchObject({ + proposalDigest: proposed.proposal.digest, + reviewDigest: review.digest, + bundleDigest: proposed.proposal.candidateBundle?.digest, + executionId: fixture.task.executionId, + succeeded: true, + runReceiptDigest: expect.stringMatching(/^sha256:/), + }) + }) + + it('records rejection and refuses to execute it', async () => { + const fixture = createCandidateExecutionFixture() + const { digest: _digest, ...bundleInput } = fixture.bundle + const proposed = await proposeAgentImprovement({ + runId: 'analysis-run-2', + profile: fixtureProfile(), + analysis: { registry: registry([finding]), inputs: {}, findingsStore: null, log: () => {} }, + improvement: { + surface: 'prompt', + generator: proposer, + scenarios, + judge, + agent, + budget: { generations: 1, populationSize: 2, reps: 3, holdoutFraction: 0.5 }, + }, + buildCandidate: ({ improvement }) => alignedBundle(bundleInput, improvement.profile), + }) + const review = reviewAgentImprovementProposal(proposed.proposal, { + decision: 'reject', + reviewedBy: 'operator@example.com', + reason: 'The change is not appropriate for this deployment.', + feedback: 'Keep the baseline behavior.', + }) + + await expect( + executeApprovedAgentCandidate({ + proposal: proposed.proposal, + review, + authorizeReview: async () => true, + task: fixture.task, + ports: fixture.ports, + execution: { + executor: { + execute: async () => { + throw new Error('must not execute') + }, + stopAndCapture: async () => ({ stopped: true }), + }, + traceStore: new InMemoryTraceStore(), + claimStore: new InMemoryAgentCandidateExecutionClaimStore(), + ...createCandidateOutputFixture(), + }, + }), + ).rejects.toThrow('not an approval') + }) + + it('refuses a structurally valid approval that its authority does not recognize', async () => { + const fixture = createCandidateExecutionFixture() + const { digest: _digest, ...bundleInput } = fixture.bundle + const proposed = await proposeAgentImprovement({ + runId: 'analysis-run-unauthorized', + profile: fixtureProfile(), + analysis: { registry: registry([finding]), inputs: {}, findingsStore: null, log: () => {} }, + improvement: { + surface: 'prompt', + generator: proposer, + scenarios, + judge, + agent, + budget: { generations: 1, populationSize: 2, reps: 3, holdoutFraction: 0.5 }, + }, + buildCandidate: ({ improvement }) => alignedBundle(bundleInput, improvement.profile), + }) + const review = reviewAgentImprovementProposal(proposed.proposal, { + decision: 'approve', + reviewedBy: 'forged@example.com', + reason: 'Self-authored approval.', + }) + + await expect( + executeApprovedAgentCandidate({ + proposal: proposed.proposal, + review, + authorizeReview: async () => false, + task: fixture.task, + ports: fixture.ports, + execution: { + executor: { + execute: async () => { + throw new Error('must not execute') + }, + stopAndCapture: async () => ({ stopped: true }), + }, + traceStore: new InMemoryTraceStore(), + claimStore: new InMemoryAgentCandidateExecutionClaimStore(), + ...createCandidateOutputFixture(), + }, + }), + ).rejects.toThrow('not authorized') + }) + + it('rejects judge-derived findings before they can steer a proposal', async () => { + await expect( + proposeAgentImprovement({ + runId: 'analysis-run-3', + profile: fixtureProfile(), + analysis: { + registry: registry([{ ...finding, derived_from_judge: true }]), + inputs: {}, + findingsStore: null, + log: () => {}, + }, + improvement: { + surface: 'prompt', + generator: proposer, + scenarios, + judge, + agent, + budget: { generations: 1, populationSize: 2, reps: 3, holdoutFraction: 0.5 }, + }, + }), + ).rejects.toThrow(/judge/i) + }) +}) diff --git a/typedoc.json b/typedoc.json index 31f675d5..363a14f7 100644 --- a/typedoc.json +++ b/typedoc.json @@ -11,6 +11,7 @@ "src/knowledge/index.ts", "src/profiles/index.ts", "src/platform/index.ts", + "src/candidate-execution/index.ts", "src/mcp/index.ts" ], "entryPointStrategy": "resolve", From 41d6886141bc061d0a46760d7b8220a7e9abc4f4 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Sat, 11 Jul 2026 01:30:53 -0600 Subject: [PATCH 3/5] chore(release): prepare agent-runtime 0.92.1 --- docs/api/intelligence.md | 136 +++++++++++++++++----------------- docs/api/primitive-catalog.md | 2 +- package.json | 2 +- 3 files changed, 70 insertions(+), 70 deletions(-) diff --git a/docs/api/intelligence.md b/docs/api/intelligence.md index 77144d12..677c600d 100644 --- a/docs/api/intelligence.md +++ b/docs/api/intelligence.md @@ -1078,7 +1078,7 @@ Intelligence-class spend ceiling. `0` refuses every intelligence spawn; `null` u ### AgentImprovementProposal -Defined in: intelligence/improvement-cycle.ts:61 +Defined in: [intelligence/improvement-cycle.ts:61](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L61) #### Type Parameters @@ -1096,79 +1096,79 @@ Defined in: intelligence/improvement-cycle.ts:61 > **schemaVersion**: `1` -Defined in: intelligence/improvement-cycle.ts:65 +Defined in: [intelligence/improvement-cycle.ts:65](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L65) ##### kind > **kind**: `"agent-improvement-proposal"` -Defined in: intelligence/improvement-cycle.ts:66 +Defined in: [intelligence/improvement-cycle.ts:66](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L66) ##### runId > **runId**: `string` -Defined in: intelligence/improvement-cycle.ts:67 +Defined in: [intelligence/improvement-cycle.ts:67](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L67) ##### surface > **surface**: [`ImproveSurface`](index.md#improvesurface) -Defined in: intelligence/improvement-cycle.ts:68 +Defined in: [intelligence/improvement-cycle.ts:68](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L68) ##### proposedAt > **proposedAt**: `string` -Defined in: intelligence/improvement-cycle.ts:69 +Defined in: [intelligence/improvement-cycle.ts:69](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L69) ##### baselineProfileHash > **baselineProfileHash**: `string` -Defined in: intelligence/improvement-cycle.ts:70 +Defined in: [intelligence/improvement-cycle.ts:70](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L70) ##### candidateProfile > **candidateProfile**: `AgentProfile` -Defined in: intelligence/improvement-cycle.ts:71 +Defined in: [intelligence/improvement-cycle.ts:71](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L71) ##### candidateProfileHash > **candidateProfileHash**: `string` -Defined in: intelligence/improvement-cycle.ts:72 +Defined in: [intelligence/improvement-cycle.ts:72](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L72) ##### findings > **findings**: `AnalystFinding`[] -Defined in: intelligence/improvement-cycle.ts:73 +Defined in: [intelligence/improvement-cycle.ts:73](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L73) ##### evaluation > **evaluation**: [`AgentImprovementEvaluation`](#agentimprovementevaluation)\<`TScenario`, `TArtifact`\> -Defined in: intelligence/improvement-cycle.ts:74 +Defined in: [intelligence/improvement-cycle.ts:74](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L74) ##### candidateBundle? > `optional` **candidateBundle?**: `AgentCandidateBundleV1` -Defined in: intelligence/improvement-cycle.ts:75 +Defined in: [intelligence/improvement-cycle.ts:75](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L75) ##### digest > **digest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:76 +Defined in: [intelligence/improvement-cycle.ts:76](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L76) *** ### AgentImprovementReview -Defined in: intelligence/improvement-cycle.ts:81 +Defined in: [intelligence/improvement-cycle.ts:81](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L81) #### Properties @@ -1176,67 +1176,67 @@ Defined in: intelligence/improvement-cycle.ts:81 > **schemaVersion**: `1` -Defined in: intelligence/improvement-cycle.ts:82 +Defined in: [intelligence/improvement-cycle.ts:82](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L82) ##### kind > **kind**: `"agent-improvement-review"` -Defined in: intelligence/improvement-cycle.ts:83 +Defined in: [intelligence/improvement-cycle.ts:83](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L83) ##### proposalDigest > **proposalDigest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:84 +Defined in: [intelligence/improvement-cycle.ts:84](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L84) ##### candidateBundleDigest? > `optional` **candidateBundleDigest?**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:85 +Defined in: [intelligence/improvement-cycle.ts:85](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L85) ##### decision > **decision**: [`AgentImprovementReviewDecision`](#agentimprovementreviewdecision) -Defined in: intelligence/improvement-cycle.ts:86 +Defined in: [intelligence/improvement-cycle.ts:86](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L86) ##### reviewedBy > **reviewedBy**: `string` -Defined in: intelligence/improvement-cycle.ts:87 +Defined in: [intelligence/improvement-cycle.ts:87](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L87) ##### reviewedAt > **reviewedAt**: `string` -Defined in: intelligence/improvement-cycle.ts:88 +Defined in: [intelligence/improvement-cycle.ts:88](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L88) ##### reason > **reason**: `string` -Defined in: intelligence/improvement-cycle.ts:89 +Defined in: [intelligence/improvement-cycle.ts:89](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L89) ##### feedback? > `optional` **feedback?**: `string` -Defined in: intelligence/improvement-cycle.ts:90 +Defined in: [intelligence/improvement-cycle.ts:90](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L90) ##### digest > **digest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:91 +Defined in: [intelligence/improvement-cycle.ts:91](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L91) *** ### CandidateExecutionEvidence -Defined in: intelligence/improvement-cycle.ts:94 +Defined in: [intelligence/improvement-cycle.ts:94](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L94) #### Properties @@ -1244,55 +1244,55 @@ Defined in: intelligence/improvement-cycle.ts:94 > **proposalDigest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:95 +Defined in: [intelligence/improvement-cycle.ts:95](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L95) ##### reviewDigest > **reviewDigest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:96 +Defined in: [intelligence/improvement-cycle.ts:96](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L96) ##### bundleDigest > **bundleDigest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:97 +Defined in: [intelligence/improvement-cycle.ts:97](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L97) ##### executionId > **executionId**: `string` -Defined in: intelligence/improvement-cycle.ts:98 +Defined in: [intelligence/improvement-cycle.ts:98](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L98) ##### executionPlanDigest > **executionPlanDigest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:99 +Defined in: [intelligence/improvement-cycle.ts:99](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L99) ##### materializationReceiptDigest > **materializationReceiptDigest**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:100 +Defined in: [intelligence/improvement-cycle.ts:100](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L100) ##### succeeded > **succeeded**: `boolean` -Defined in: intelligence/improvement-cycle.ts:101 +Defined in: [intelligence/improvement-cycle.ts:101](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L101) ##### runReceiptDigest? > `optional` **runReceiptDigest?**: `` `sha256:${string}` `` -Defined in: intelligence/improvement-cycle.ts:102 +Defined in: [intelligence/improvement-cycle.ts:102](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L102) *** ### ProposeAgentImprovementOptions -Defined in: intelligence/improvement-cycle.ts:105 +Defined in: [intelligence/improvement-cycle.ts:105](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L105) #### Type Parameters @@ -1310,31 +1310,31 @@ Defined in: intelligence/improvement-cycle.ts:105 > **runId**: `string` -Defined in: intelligence/improvement-cycle.ts:106 +Defined in: [intelligence/improvement-cycle.ts:106](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L106) ##### profile > **profile**: `AgentProfile` -Defined in: intelligence/improvement-cycle.ts:107 +Defined in: [intelligence/improvement-cycle.ts:107](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L107) ##### analysis > **analysis**: `Omit`\<[`RunAnalystLoopOpts`](analyst-loop.md#runanalystloopopts), `"runId"` \| `"improvementAdapter"` \| `"autoApply"`\> -Defined in: intelligence/improvement-cycle.ts:108 +Defined in: [intelligence/improvement-cycle.ts:108](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L108) ##### improvement > **improvement**: [`ImproveOptions`](index.md#improveoptions)\<`TScenario`, `TArtifact`\> -Defined in: intelligence/improvement-cycle.ts:109 +Defined in: [intelligence/improvement-cycle.ts:109](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L109) ##### buildCandidate? > `optional` **buildCandidate?**: (`input`) => `AgentCandidateBundleInput` \| `Promise`\<`AgentCandidateBundleInput`\> -Defined in: intelligence/improvement-cycle.ts:115 +Defined in: [intelligence/improvement-cycle.ts:115](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L115) Optional environment adapter that freezes an executable bundle after the measured comparison recommends the candidate. Runtime validates and @@ -1360,7 +1360,7 @@ computes the bundle digest; adapters never implement hashing themselves. > `optional` **now?**: () => `Date` -Defined in: intelligence/improvement-cycle.ts:119 +Defined in: [intelligence/improvement-cycle.ts:119](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L119) ###### Returns @@ -1370,7 +1370,7 @@ Defined in: intelligence/improvement-cycle.ts:119 ### ProposeAgentImprovementResult -Defined in: intelligence/improvement-cycle.ts:122 +Defined in: [intelligence/improvement-cycle.ts:122](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L122) #### Type Parameters @@ -1388,25 +1388,25 @@ Defined in: intelligence/improvement-cycle.ts:122 > **analysis**: [`RunAnalystLoopResult`](analyst-loop.md#runanalystloopresult) -Defined in: intelligence/improvement-cycle.ts:123 +Defined in: [intelligence/improvement-cycle.ts:123](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L123) ##### improvement > **improvement**: [`ImproveResult`](index.md#improveresult)\<`TScenario`, `TArtifact`\> -Defined in: intelligence/improvement-cycle.ts:124 +Defined in: [intelligence/improvement-cycle.ts:124](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L124) ##### proposal > **proposal**: [`AgentImprovementProposal`](#agentimprovementproposal)\<`TScenario`, `TArtifact`\> -Defined in: intelligence/improvement-cycle.ts:125 +Defined in: [intelligence/improvement-cycle.ts:125](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L125) *** ### ReviewAgentImprovementInput -Defined in: intelligence/improvement-cycle.ts:128 +Defined in: [intelligence/improvement-cycle.ts:128](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L128) #### Properties @@ -1414,31 +1414,31 @@ Defined in: intelligence/improvement-cycle.ts:128 > **decision**: [`AgentImprovementReviewDecision`](#agentimprovementreviewdecision) -Defined in: intelligence/improvement-cycle.ts:129 +Defined in: [intelligence/improvement-cycle.ts:129](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L129) ##### reviewedBy > **reviewedBy**: `string` -Defined in: intelligence/improvement-cycle.ts:130 +Defined in: [intelligence/improvement-cycle.ts:130](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L130) ##### reason > **reason**: `string` -Defined in: intelligence/improvement-cycle.ts:131 +Defined in: [intelligence/improvement-cycle.ts:131](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L131) ##### feedback? > `optional` **feedback?**: `string` -Defined in: intelligence/improvement-cycle.ts:132 +Defined in: [intelligence/improvement-cycle.ts:132](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L132) ##### now? > `optional` **now?**: () => `Date` -Defined in: intelligence/improvement-cycle.ts:133 +Defined in: [intelligence/improvement-cycle.ts:133](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L133) ###### Returns @@ -1448,7 +1448,7 @@ Defined in: intelligence/improvement-cycle.ts:133 ### ExecuteApprovedAgentCandidateOptions -Defined in: intelligence/improvement-cycle.ts:136 +Defined in: [intelligence/improvement-cycle.ts:136](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L136) #### Properties @@ -1456,19 +1456,19 @@ Defined in: intelligence/improvement-cycle.ts:136 > **proposal**: [`AgentImprovementProposal`](#agentimprovementproposal) -Defined in: intelligence/improvement-cycle.ts:137 +Defined in: [intelligence/improvement-cycle.ts:137](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L137) ##### review > **review**: [`AgentImprovementReview`](#agentimprovementreview) -Defined in: intelligence/improvement-cycle.ts:138 +Defined in: [intelligence/improvement-cycle.ts:138](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L138) ##### authorizeReview > **authorizeReview**: (`review`, `proposal`) => `boolean` \| `Promise`\<`boolean`\> -Defined in: intelligence/improvement-cycle.ts:140 +Defined in: [intelligence/improvement-cycle.ts:140](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L140) Product-owned authentication check for the persisted approval record. @@ -1490,31 +1490,31 @@ Product-owned authentication check for the persisted approval record. > **task**: [`AgentCandidateTaskExecution`](index.md#agentcandidatetaskexecution) -Defined in: intelligence/improvement-cycle.ts:144 +Defined in: [intelligence/improvement-cycle.ts:144](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L144) ##### ports > **ports**: [`AgentCandidateExecutionPorts`](index.md#agentcandidateexecutionports) -Defined in: intelligence/improvement-cycle.ts:145 +Defined in: [intelligence/improvement-cycle.ts:145](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L145) ##### preparation? > `optional` **preparation?**: [`PrepareAgentCandidateExecutionOptions`](index.md#prepareagentcandidateexecutionoptions) -Defined in: intelligence/improvement-cycle.ts:146 +Defined in: [intelligence/improvement-cycle.ts:146](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L146) ##### execution > **execution**: [`ExecutePreparedAgentCandidateOptions`](index.md#executepreparedagentcandidateoptions) -Defined in: intelligence/improvement-cycle.ts:147 +Defined in: [intelligence/improvement-cycle.ts:147](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L147) *** ### ExecuteApprovedAgentCandidateResult -Defined in: intelligence/improvement-cycle.ts:150 +Defined in: [intelligence/improvement-cycle.ts:150](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L150) #### Properties @@ -1522,13 +1522,13 @@ Defined in: intelligence/improvement-cycle.ts:150 > **finalization**: [`AgentCandidateRunFinalization`](index.md#agentcandidaterunfinalization) -Defined in: intelligence/improvement-cycle.ts:151 +Defined in: [intelligence/improvement-cycle.ts:151](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L151) ##### evidence > **evidence**: [`CandidateExecutionEvidence`](#candidateexecutionevidence) -Defined in: intelligence/improvement-cycle.ts:152 +Defined in: [intelligence/improvement-cycle.ts:152](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L152) *** @@ -3150,7 +3150,7 @@ Per-field overrides applied on top of a tier preset. Any subset of the > **AgentImprovementEvaluation**\<`TScenario`, `TArtifact`\> = `Pick`\<`SelfImproveResult`\<`TScenario`, `TArtifact`\>, `"baseline"` \| `"winner"` \| `"lift"` \| `"diff"` \| `"provenance"` \| `"gateDecision"` \| `"generationsExplored"` \| `"durationMs"` \| `"totalCostUsd"` \| `"insight"` \| `"power"`\> -Defined in: intelligence/improvement-cycle.ts:46 +Defined in: [intelligence/improvement-cycle.ts:46](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L46) #### Type Parameters @@ -3168,7 +3168,7 @@ Defined in: intelligence/improvement-cycle.ts:46 > **AgentImprovementReviewDecision** = `"approve"` \| `"reject"` \| `"request-changes"` -Defined in: intelligence/improvement-cycle.ts:79 +Defined in: [intelligence/improvement-cycle.ts:79](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L79) *** @@ -3534,7 +3534,7 @@ compile to `withAnalyst: true`, the tier's `fanout`, and `withLoops: true`. > **proposeAgentImprovement**\<`TScenario`, `TArtifact`\>(`options`): `Promise`\<[`ProposeAgentImprovementResult`](#proposeagentimprovementresult)\<`TScenario`, `TArtifact`\>\> -Defined in: intelligence/improvement-cycle.ts:156 +Defined in: [intelligence/improvement-cycle.ts:156](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L156) Analyze one run and produce one measured, review-only improvement proposal. @@ -3564,7 +3564,7 @@ Analyze one run and produce one measured, review-only improvement proposal. > **reviewAgentImprovementProposal**(`inputProposal`, `input`): [`AgentImprovementReview`](#agentimprovementreview) -Defined in: intelligence/improvement-cycle.ts:198 +Defined in: [intelligence/improvement-cycle.ts:198](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L198) Persist an approve/reject/change-request decision bound to one exact proposal. @@ -3588,7 +3588,7 @@ Persist an approve/reject/change-request decision bound to one exact proposal. > **executeApprovedAgentCandidate**(`options`): `Promise`\<[`ExecuteApprovedAgentCandidateResult`](#executeapprovedagentcandidateresult)\> -Defined in: intelligence/improvement-cycle.ts:228 +Defined in: [intelligence/improvement-cycle.ts:228](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L228) Verify, materialize, run, grade, and receipt only the exact approved bundle. @@ -3608,7 +3608,7 @@ Verify, materialize, run, grade, and receipt only the exact approved bundle. > **verifyAgentImprovementProposal**(`input`): [`AgentImprovementProposal`](#agentimprovementproposal) -Defined in: intelligence/improvement-cycle.ts:270 +Defined in: [intelligence/improvement-cycle.ts:270](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L270) Validate a proposal's schema, profile, sealed bundle, and canonical digest. @@ -3628,7 +3628,7 @@ Validate a proposal's schema, profile, sealed bundle, and canonical digest. > **verifyAgentImprovementReview**(`input`): [`AgentImprovementReview`](#agentimprovementreview) -Defined in: intelligence/improvement-cycle.ts:442 +Defined in: [intelligence/improvement-cycle.ts:442](https://github.com/tangle-network/agent-runtime/blob/main/src/intelligence/improvement-cycle.ts#L442) Validate a review's decision fields and canonical digest. diff --git a/docs/api/primitive-catalog.md b/docs/api/primitive-catalog.md index ef5b4f40..cd6082f3 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.92.0` and `@tangle-network/agent-eval@0.113.0` 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.92.1` and `@tangle-network/agent-eval@0.113.0` 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 diff --git a/package.json b/package.json index 28124340..80b6c580 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tangle-network/agent-runtime", - "version": "0.92.0", + "version": "0.92.1", "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": { From 40d53334b8fdf7ca5d91657075a128c5d8f8bc5a Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Sat, 11 Jul 2026 01:39:40 -0600 Subject: [PATCH 4/5] docs(api): align canonical version --- docs/canonical-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/canonical-api.md b/docs/canonical-api.md index ac72bfe4..f0cee915 100644 --- a/docs/canonical-api.md +++ b/docs/canonical-api.md @@ -2,7 +2,7 @@ -> **Version 0.92.0.** The export inventory + per-symbol signatures live in the generated `docs/api/` reference: **`docs/api/primitive-catalog.md`** is the never-stale, grouped list of every primitive to reuse (own surface + the agent-eval judge / authenticity / verification / statistics / campaign / token-usage surfaces), with each one's import path and one-line summary read live from source; the per-module pages hold the full signatures. The pinned substrate is agent-eval `>=0.101.0 <1.0.0`; the sandbox substrate that materializes profiles into harness shapes is `@tangle-network/sandbox` (peer `>=0.8.0 <1.0.0`). The neutral contract types (`AgentProfile`, `AgentProfileMcpServer`, `HarnessType`, `ReasoningEffort`, `Part`/`ToolPart`/`ToolState`, plus environment-provider types) are owned by **`@tangle-network/agent-interface`** (peer `>=0.25.0 <1.0.0`) — the single source of truth. Substrate primitives are re-exported through `@tangle-network/agent-eval/contract` (or `/campaign`), not local to this package — the catalog's §2 shows exactly which subpath each lives under. +> **Version 0.92.1.** The export inventory + per-symbol signatures live in the generated `docs/api/` reference: **`docs/api/primitive-catalog.md`** is the never-stale, grouped list of every primitive to reuse (own surface + the agent-eval judge / authenticity / verification / statistics / campaign / token-usage surfaces), with each one's import path and one-line summary read live from source; the per-module pages hold the full signatures. The pinned substrate is agent-eval `>=0.101.0 <1.0.0`; the sandbox substrate that materializes profiles into harness shapes is `@tangle-network/sandbox` (peer `>=0.8.0 <1.0.0`). The neutral contract types (`AgentProfile`, `AgentProfileMcpServer`, `HarnessType`, `ReasoningEffort`, `Part`/`ToolPart`/`ToolState`, plus environment-provider types) are owned by **`@tangle-network/agent-interface`** (peer `>=0.25.0 <1.0.0`) — the single source of truth. Substrate primitives are re-exported through `@tangle-network/agent-eval/contract` (or `/campaign`), not local to this package — the catalog's §2 shows exactly which subpath each lives under. > > **`./loops` is the runtime barrel** — `package.json` maps it to `src/runtime/index.ts`. Everything below labelled `/loops` is the recursive-atom + loop-kernel surface. > From 2e8c889dc1922778c22f492a3f99c10683edc14f Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Sat, 11 Jul 2026 09:32:53 -0600 Subject: [PATCH 5/5] fix(security): harden improvement surface paths --- docs/api/agent.md | 12 +++--- docs/api/index.md | 64 +++++++++++++++---------------- src/agent/surfaces.ts | 80 ++++++++++++++++++++------------------- src/intelligence/index.ts | 1 - src/otel-export.ts | 32 +++++++++------- tests/agent.test.ts | 17 +++++++++ tests/otel-export.test.ts | 18 +++++++++ 7 files changed, 133 insertions(+), 91 deletions(-) diff --git a/docs/api/agent.md b/docs/api/agent.md index e919cbfb..97585ab7 100644 --- a/docs/api/agent.md +++ b/docs/api/agent.md @@ -1652,7 +1652,7 @@ The substrate's intent: edit an existing file or create a new one. ### SurfaceValidationIssue -Defined in: [agent/surfaces.ts:262](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L262) +Defined in: [agent/surfaces.ts:264](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L264) Validate that every declared surface exists on disk under `repoRoot`. @@ -1667,19 +1667,19 @@ the loop produces 20 minutes later). > **surface**: keyof [`AgentSurfaces`](#agentsurfaces) -Defined in: [agent/surfaces.ts:263](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L263) +Defined in: [agent/surfaces.ts:265](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L265) ##### path > **path**: `string` -Defined in: [agent/surfaces.ts:264](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L264) +Defined in: [agent/surfaces.ts:266](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L266) ##### reason > **reason**: `"missing"` \| `"not-directory"` \| `"not-file"` -Defined in: [agent/surfaces.ts:265](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L265) +Defined in: [agent/surfaces.ts:267](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L267) ## Type Aliases @@ -2099,7 +2099,7 @@ it's the whole point. > **validateSurfaces**(`surfaces`, `repoRoot`): readonly [`SurfaceValidationIssue`](#surfacevalidationissue)[] -Defined in: [agent/surfaces.ts:269](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L269) +Defined in: [agent/surfaces.ts:271](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L271) Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits. @@ -2123,7 +2123,7 @@ readonly [`SurfaceValidationIssue`](#surfacevalidationissue)[] > **renderSurfaceIssues**(`issues`, `repoRoot`): `string` -Defined in: [agent/surfaces.ts:343](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L343) +Defined in: [agent/surfaces.ts:345](https://github.com/tangle-network/agent-runtime/blob/main/src/agent/surfaces.ts#L345) Format a list of surface validation issues into a human-readable error string. diff --git a/docs/api/index.md b/docs/api/index.md index 5178a308..1895ecb1 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -7398,7 +7398,7 @@ True when the iteration carried an error — maps to OTEL status code 2. ### EvalRunGeneration -Defined in: [otel-export.ts:661](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L661) +Defined in: [otel-export.ts:667](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L667) #### Properties @@ -7406,7 +7406,7 @@ Defined in: [otel-export.ts:661](https://github.com/tangle-network/agent-runtime > **index**: `number` -Defined in: [otel-export.ts:663](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L663) +Defined in: [otel-export.ts:669](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L669) 0-based ordinal of this generation within the run (required by ingest). @@ -7414,7 +7414,7 @@ Defined in: [otel-export.ts:663](https://github.com/tangle-network/agent-runtime > **surfaceHash**: `string` -Defined in: [otel-export.ts:665](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L665) +Defined in: [otel-export.ts:671](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L671) Identity of the proposed surface change (content-addressed hash). @@ -7422,7 +7422,7 @@ Identity of the proposed surface change (content-addressed hash). > `optional` **surface?**: `unknown` -Defined in: [otel-export.ts:667](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L667) +Defined in: [otel-export.ts:673](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L673) Arbitrary provenance for this generation (rationale, evidence, source). @@ -7430,7 +7430,7 @@ Arbitrary provenance for this generation (rationale, evidence, source). > `optional` **cells?**: `unknown`[] -Defined in: [otel-export.ts:669](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L669) +Defined in: [otel-export.ts:675](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L675) Per-scenario results; empty until the generation is measured. @@ -7438,7 +7438,7 @@ Per-scenario results; empty until the generation is measured. > **compositeMean**: `number` -Defined in: [otel-export.ts:671](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L671) +Defined in: [otel-export.ts:677](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L677) Mean composite score (0 when unmeasured — pair with labels.measured). @@ -7446,19 +7446,19 @@ Mean composite score (0 when unmeasured — pair with labels.measured). > **costUsd**: `number` -Defined in: [otel-export.ts:672](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L672) +Defined in: [otel-export.ts:678](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L678) ##### durationMs > **durationMs**: `number` -Defined in: [otel-export.ts:673](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L673) +Defined in: [otel-export.ts:679](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L679) *** ### EvalRunEvent -Defined in: [otel-export.ts:676](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L676) +Defined in: [otel-export.ts:682](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L682) #### Properties @@ -7466,19 +7466,19 @@ Defined in: [otel-export.ts:676](https://github.com/tangle-network/agent-runtime > **runId**: `string` -Defined in: [otel-export.ts:677](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L677) +Defined in: [otel-export.ts:683](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L683) ##### runDir > **runDir**: `string` -Defined in: [otel-export.ts:678](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L678) +Defined in: [otel-export.ts:684](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L684) ##### timestamp > **timestamp**: `string` -Defined in: [otel-export.ts:680](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L680) +Defined in: [otel-export.ts:686](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L686) ISO timestamp. @@ -7486,61 +7486,61 @@ ISO timestamp. > **status**: `"started"` \| `"baseline-complete"` \| `"generation-complete"` \| `"gate-decided"` \| `"finished"` \| `"errored"` -Defined in: [otel-export.ts:681](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L681) +Defined in: [otel-export.ts:687](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L687) ##### labels? > `optional` **labels?**: `Record`\<`string`, `string`\> -Defined in: [otel-export.ts:688](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L688) +Defined in: [otel-export.ts:694](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L694) ##### baseline? > `optional` **baseline?**: [`EvalRunGeneration`](#evalrungeneration) -Defined in: [otel-export.ts:689](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L689) +Defined in: [otel-export.ts:695](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L695) ##### generations? > `optional` **generations?**: [`EvalRunGeneration`](#evalrungeneration)[] -Defined in: [otel-export.ts:690](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L690) +Defined in: [otel-export.ts:696](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L696) ##### gateDecision? > `optional` **gateDecision?**: `"ship"` \| `"hold"` \| `"need_more_work"` \| `"model_ceiling"` \| `"arch_ceiling"` -Defined in: [otel-export.ts:691](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L691) +Defined in: [otel-export.ts:697](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L697) ##### holdoutLift? > `optional` **holdoutLift?**: `number` -Defined in: [otel-export.ts:692](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L692) +Defined in: [otel-export.ts:698](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L698) ##### totalCostUsd > **totalCostUsd**: `number` -Defined in: [otel-export.ts:693](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L693) +Defined in: [otel-export.ts:699](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L699) ##### totalDurationMs > **totalDurationMs**: `number` -Defined in: [otel-export.ts:694](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L694) +Defined in: [otel-export.ts:700](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L700) ##### errorMessage? > `optional` **errorMessage?**: `string` -Defined in: [otel-export.ts:695](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L695) +Defined in: [otel-export.ts:701](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L701) *** ### EvalRunsExportConfig -Defined in: [otel-export.ts:698](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L698) +Defined in: [otel-export.ts:704](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L704) #### Properties @@ -7548,7 +7548,7 @@ Defined in: [otel-export.ts:698](https://github.com/tangle-network/agent-runtime > `optional` **apiKey?**: `string` -Defined in: [otel-export.ts:700](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L700) +Defined in: [otel-export.ts:706](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L706) Bearer key — tenant is resolved server-side from it. Reads TANGLE_API_KEY. @@ -7556,7 +7556,7 @@ Bearer key — tenant is resolved server-side from it. Reads TANGLE_API_KEY. > `optional` **base?**: `string` -Defined in: [otel-export.ts:702](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L702) +Defined in: [otel-export.ts:708](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L708) Intelligence base. Reads TANGLE_INTELLIGENCE_URL env, else prod. @@ -7564,7 +7564,7 @@ Intelligence base. Reads TANGLE_INTELLIGENCE_URL env, else prod. > `optional` **idempotencyKey?**: `string` -Defined in: [otel-export.ts:704](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L704) +Defined in: [otel-export.ts:710](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L710) Idempotency-Key header (e.g. the runId) — safe retries + upsert. @@ -7572,7 +7572,7 @@ Idempotency-Key header (e.g. the runId) — safe retries + upsert. ### EvalRunsExportResult -Defined in: [otel-export.ts:707](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L707) +Defined in: [otel-export.ts:713](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L713) #### Properties @@ -7580,25 +7580,25 @@ Defined in: [otel-export.ts:707](https://github.com/tangle-network/agent-runtime > **ok**: `boolean` -Defined in: [otel-export.ts:708](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L708) +Defined in: [otel-export.ts:714](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L714) ##### status > **status**: `number` -Defined in: [otel-export.ts:709](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L709) +Defined in: [otel-export.ts:715](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L715) ##### accepted > **accepted**: `number` -Defined in: [otel-export.ts:710](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L710) +Defined in: [otel-export.ts:716](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L716) ##### rejected > **rejected**: `object`[] -Defined in: [otel-export.ts:711](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L711) +Defined in: [otel-export.ts:717](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L717) ###### index @@ -11391,7 +11391,7 @@ Default Tangle Router base URL used when no env override is set. > `const` **INTELLIGENCE\_WIRE\_VERSION**: `"2026-05-26.v1"` = `'2026-05-26.v1'` -Defined in: [otel-export.ts:659](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L659) +Defined in: [otel-export.ts:665](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L665) Wire version the eval-runs ingest enforces (X-Tangle-Wire-Version + body). @@ -13342,7 +13342,7 @@ readonly `object`[] > **exportEvalRuns**(`events`, `config?`): `Promise`\<[`EvalRunsExportResult`](#evalrunsexportresult)\> -Defined in: [otel-export.ts:722](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L722) +Defined in: [otel-export.ts:728](https://github.com/tangle-network/agent-runtime/blob/main/src/otel-export.ts#L728) Ship self-improvement eval-run events to Tangle Intelligence. Unlike the best-effort span exporter, this RESOLVES with the ingest verdict (accepted / diff --git a/src/agent/surfaces.ts b/src/agent/surfaces.ts index d73f7459..ceee7ff8 100644 --- a/src/agent/surfaces.ts +++ b/src/agent/surfaces.ts @@ -14,7 +14,7 @@ */ import { existsSync, statSync } from 'node:fs' -import { isAbsolute, join } from 'node:path' +import { isAbsolute, join, relative, resolve, sep } from 'node:path' import type { FindingSubject } from '@tangle-network/agent-eval' /** @@ -134,70 +134,70 @@ function candidatePathsForSubject( switch (subject.kind) { case 'knowledge.wiki': case 'knowledge.stale': - return [join(surfaces.knowledge, `${subject.slug}.md`)] + return optionalPath(safeJoin(surfaces.knowledge, `${subject.slug}.md`)) case 'knowledge.claim': // Claims land in a per-topic claims directory under the knowledge root. - return [join(surfaces.knowledge, 'claims', `${slugify(subject.topic)}.md`)] + return optionalPath(safeJoin(surfaces.knowledge, 'claims', `${slugify(subject.topic)}.md`)) case 'knowledge.raw': - return optionalPath(safeJoin(join(surfaces.knowledge, 'raw'), `${subject.sourceId}.md`)) + return optionalPath(safeJoin(surfaces.knowledge, 'raw', `${subject.sourceId}.md`)) case 'system-prompt': { const slug = slugify(subject.section) // Prefer flat layout for create-new (canonical); probe skill-dir layout // in case the existing repo (tax/legal/gtm/creative) uses // `
/SKILL.md` already. return [ - join(surfaces.systemPrompt, `${slug}.md`), - join(surfaces.systemPrompt, slug, 'SKILL.md'), - join(surfaces.systemPrompt, slug, 'index.md'), - ] + safeJoin(surfaces.systemPrompt, `${slug}.md`), + safeJoin(surfaces.systemPrompt, slug, 'SKILL.md'), + safeJoin(surfaces.systemPrompt, slug, 'index.md'), + ].filter((path): path is string => path !== null) } case 'skill': { if (!surfaces.skills) return [] return [ - join(surfaces.skills, subject.name, 'SKILL.md'), - join(surfaces.skills, `${subject.name}.md`), - ] + safeJoin(surfaces.skills, subject.name, 'SKILL.md'), + safeJoin(surfaces.skills, `${subject.name}.md`), + ].filter((path): path is string => path !== null) } case 'tool-doc': if (subject.aspect) { - return [join(surfaces.tools, subject.tool, `${slugify(subject.aspect)}.md`)] + return optionalPath(safeJoin(surfaces.tools, subject.tool, `${slugify(subject.aspect)}.md`)) } // tool-doc default: `/README.md`; also probe `.md` for flat // tool-list repos. return [ - join(surfaces.tools, subject.tool, 'README.md'), - join(surfaces.tools, `${subject.tool}.md`), - ] + safeJoin(surfaces.tools, subject.tool, 'README.md'), + safeJoin(surfaces.tools, `${subject.tool}.md`), + ].filter((path): path is string => path !== null) case 'new-tool': - return [join(surfaces.tools, subject.name, 'README.md')] + return optionalPath(safeJoin(surfaces.tools, subject.name, 'README.md')) case 'mcp': if (!surfaces.mcp) return [] return subject.tool - ? [join(surfaces.mcp, subject.server, `${subject.tool}.md`)] + ? optionalPath(safeJoin(surfaces.mcp, subject.server, `${subject.tool}.md`)) : [ - join(surfaces.mcp, `${subject.server}.json`), - join(surfaces.mcp, subject.server, 'README.md'), - ] + safeJoin(surfaces.mcp, `${subject.server}.json`), + safeJoin(surfaces.mcp, subject.server, 'README.md'), + ].filter((path): path is string => path !== null) case 'hook': if (!surfaces.hooks) return [] return [ - join(surfaces.hooks, `${subject.name}.md`), - join(surfaces.hooks, `${subject.name}.json`), - ] + safeJoin(surfaces.hooks, `${subject.name}.md`), + safeJoin(surfaces.hooks, `${subject.name}.json`), + ].filter((path): path is string => path !== null) case 'subagent': if (!surfaces.subagents) return [] return [ - join(surfaces.subagents, `${subject.name}.md`), - join(surfaces.subagents, `${subject.name}.yaml`), - join(surfaces.subagents, `${subject.name}.json`), - ] + safeJoin(surfaces.subagents, `${subject.name}.md`), + safeJoin(surfaces.subagents, `${subject.name}.yaml`), + safeJoin(surfaces.subagents, `${subject.name}.json`), + ].filter((path): path is string => path !== null) case 'workflow': if (!surfaces.workflows) return [] return [ - join(surfaces.workflows, `${subject.name}.md`), - join(surfaces.workflows, `${subject.name}.yaml`), - join(surfaces.workflows, `${subject.name}.json`), - ] + safeJoin(surfaces.workflows, `${subject.name}.md`), + safeJoin(surfaces.workflows, `${subject.name}.yaml`), + safeJoin(surfaces.workflows, `${subject.name}.json`), + ].filter((path): path is string => path !== null) case 'rollout-policy': return surfaces.rolloutPolicy ? [surfaces.rolloutPolicy] : [] case 'agent-profile': @@ -209,13 +209,13 @@ function candidatePathsForSubject( } case 'rag': if (!surfaces.rag) return [] - return optionalPath(safeJoin(join(surfaces.rag, subject.corpus), `${subject.docId}.md`)) + return optionalPath(safeJoin(surfaces.rag, subject.corpus, `${subject.docId}.md`)) case 'memory': if (!surfaces.memory) return [] - return [join(surfaces.memory, `${slugify(subject.key)}.json`)] + return optionalPath(safeJoin(surfaces.memory, `${slugify(subject.key)}.json`)) case 'scaffolding': if (!surfaces.scaffolding) return [] - return [join(surfaces.scaffolding, `${slugify(subject.concern)}.md`)] + return optionalPath(safeJoin(surfaces.scaffolding, `${slugify(subject.concern)}.md`)) case 'output-schema': if (!surfaces.outputSchema) return [] return [surfaces.outputSchema] @@ -230,11 +230,13 @@ function candidatePathsForSubject( } } -function safeJoin(root: string, child: string): string | null { - if (child.includes('\0') || isAbsolute(child)) return null - const segments = child.replace(/\\/g, '/').split('/') - if (segments.some((segment) => segment === '..')) return null - return join(root, ...segments) +function safeJoin(root: string, ...children: string[]): string | null { + if (children.some((child) => child.includes('\0') || isAbsolute(child))) return null + const rootAbsolute = resolve(root) + const targetAbsolute = resolve(rootAbsolute, ...children) + const escaped = relative(rootAbsolute, targetAbsolute) + if (escaped === '..' || escaped.startsWith(`..${sep}`) || isAbsolute(escaped)) return null + return join(root, ...children) } function optionalPath(path: string | null): string[] { diff --git a/src/intelligence/index.ts b/src/intelligence/index.ts index a29d0540..d30e03b1 100644 --- a/src/intelligence/index.ts +++ b/src/intelligence/index.ts @@ -607,7 +607,6 @@ export function createIntelligenceClient(config: IntelligenceConfig): Intelligen redactor(record.profile), includeFullPayload, ) - labels['tangle.agent.profile_hash'] = contentHash(record.profile) if (record.profile.name) labels['gen_ai.agent.name'] = record.profile.name } const redactedInput = record.input !== undefined ? redactor(record.input) : undefined diff --git a/src/otel-export.ts b/src/otel-export.ts index 81c65850..a3333997 100644 --- a/src/otel-export.ts +++ b/src/otel-export.ts @@ -311,7 +311,7 @@ export function buildRuntimeEventOtelSpans( const startMs = eventTimestampMs(event) const endMs = - event.type === 'llm_call' && event.latencyMs !== undefined + event.type === 'llm_call' && event.latencyMs !== undefined && Number.isFinite(event.latencyMs) ? startMs + event.latencyMs : startMs const span = flatOtelSpan(name, attrs, traceId, startMs, parentSpanId, endMs) @@ -606,21 +606,27 @@ function parseHeadersFromEnv(): Record { } function toAttributes(record: Record): OtelAttribute[] { - return Object.entries(record).map(([key, value]) => ({ - key, - value: - typeof value === 'number' - ? Number.isInteger(value) - ? { intValue: value.toString() } - : { doubleValue: value } - : typeof value === 'boolean' - ? { boolValue: value } - : { stringValue: value }, - })) + return Object.entries(record).flatMap(([key, value]) => { + if (typeof value === 'number' && !Number.isFinite(value)) return [] + return [ + { + key, + value: + typeof value === 'number' + ? Number.isInteger(value) + ? { intValue: value.toString() } + : { doubleValue: value } + : typeof value === 'boolean' + ? { boolValue: value } + : { stringValue: value }, + }, + ] + }) } function msToNs(ms: number): string { - return (BigInt(Math.floor(ms)) * 1_000_000n).toString() + const safeMs = Number.isFinite(ms) ? ms : Date.now() + return (BigInt(Math.floor(safeMs)) * 1_000_000n).toString() } function padSpanId(id: string): string { diff --git a/tests/agent.test.ts b/tests/agent.test.ts index 24c4a53c..d1a52751 100644 --- a/tests/agent.test.ts +++ b/tests/agent.test.ts @@ -234,6 +234,23 @@ describe('resolveSubjectPath', () => { ).toBeNull() }) + it('rejects traversal in every profile surface derived from findings', () => { + const escaped = [ + { kind: 'skill', name: '../secrets' } as const, + { kind: 'tool-doc', tool: '../secrets' } as const, + { kind: 'new-tool', name: '../secrets' } as const, + { kind: 'mcp', server: '../secrets' } as const, + { kind: 'mcp', server: 'safe', tool: '../../secrets' } as const, + { kind: 'hook', name: '../secrets' } as const, + { kind: 'subagent', name: '../secrets' } as const, + { kind: 'workflow', name: '../secrets' } as const, + { kind: 'rag', corpus: '../../secrets', docId: 'entry' } as const, + ] + for (const subject of escaped) { + expect(resolveSubjectPath(subject, surfaces, tmpRoot)).toBeNull() + } + }) + it('returns null when subject targets an undeclared optional surface', () => { const noRag = { ...surfaces, rag: undefined } const r = resolveSubjectPath({ kind: 'rag', corpus: 'irs', docId: 'foo' }, noRag, tmpRoot) diff --git a/tests/otel-export.test.ts b/tests/otel-export.test.ts index 3439663b..fa502d8c 100644 --- a/tests/otel-export.test.ts +++ b/tests/otel-export.test.ts @@ -76,6 +76,24 @@ describe('buildRuntimeEventOtelSpans', () => { expect(attrs['tool.input']).toBeUndefined() expect(String(attrs['tangle.runtime.event'])).not.toContain('value') }) + + it('omits non-finite numeric attributes instead of emitting invalid OTLP JSON', () => { + const [span] = buildRuntimeEventOtelSpans( + [ + { + type: 'llm_call', + model: 'test', + costUsd: Number.NaN, + latencyMs: Number.POSITIVE_INFINITY, + }, + ], + 'a'.repeat(32), + ) + const attrs = attrMap(span!) + expect(attrs['tangle.cost.usd']).toBeUndefined() + expect(attrs['tangle.latency_ms']).toBeUndefined() + expect(JSON.stringify(span)).not.toContain('NaN') + }) }) describe('buildLoopOtelSpans — nested GenAI topology tree', () => {