@tangle-network/agent-runtime 0.72.0 → 0.74.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/agent.d.ts +34 -2
  2. package/dist/agent.js +5 -3
  3. package/dist/agent.js.map +1 -1
  4. package/dist/analyst-loop.d.ts +1 -1
  5. package/dist/analyst-loop.js +3 -2
  6. package/dist/{chunk-P5OKDSLB.js → chunk-IODKUOBA.js} +5 -3
  7. package/dist/{chunk-P5OKDSLB.js.map → chunk-IODKUOBA.js.map} +1 -1
  8. package/dist/chunk-JPURCA2O.js +266 -0
  9. package/dist/chunk-JPURCA2O.js.map +1 -0
  10. package/dist/{chunk-VYXBFWHZ.js → chunk-MRWXCFV5.js} +2 -2
  11. package/dist/chunk-NBV35BR6.js +68 -0
  12. package/dist/chunk-NBV35BR6.js.map +1 -0
  13. package/dist/chunk-O2UPHN7X.js +114 -0
  14. package/dist/chunk-O2UPHN7X.js.map +1 -0
  15. package/dist/{chunk-HXVMLRYU.js → chunk-QKNBYHMK.js} +7 -7
  16. package/dist/{chunk-PHKNOAOU.js → chunk-SA5GCF2X.js} +25 -7
  17. package/dist/chunk-SA5GCF2X.js.map +1 -0
  18. package/dist/{chunk-VLF5RHEQ.js → chunk-T2HVQVB4.js} +1 -66
  19. package/dist/chunk-T2HVQVB4.js.map +1 -0
  20. package/dist/{chunk-55WKGOGU.js → chunk-ZKMOIEOB.js} +123 -149
  21. package/dist/chunk-ZKMOIEOB.js.map +1 -0
  22. package/dist/{coordination-CFVF0OzX.d.ts → coordination-DEVknvQo.d.ts} +9 -2
  23. package/dist/generator-YkAQrOoD.d.ts +382 -0
  24. package/dist/index.d.ts +13 -167
  25. package/dist/index.js +21 -267
  26. package/dist/index.js.map +1 -1
  27. package/dist/intelligence.d.ts +1 -1
  28. package/dist/lifecycle.d.ts +868 -0
  29. package/dist/lifecycle.js +979 -0
  30. package/dist/lifecycle.js.map +1 -0
  31. package/dist/local-harness-BE_h8szs.d.ts +93 -0
  32. package/dist/{loop-runner-bin-B7biH0Gk.d.ts → loop-runner-bin-BPthX22l.d.ts} +2 -2
  33. package/dist/loop-runner-bin.d.ts +6 -5
  34. package/dist/loop-runner-bin.js +7 -5
  35. package/dist/loops.d.ts +47 -10
  36. package/dist/loops.js +7 -3
  37. package/dist/mcp/bin.js +7 -5
  38. package/dist/mcp/bin.js.map +1 -1
  39. package/dist/mcp/index.d.ts +8 -6
  40. package/dist/mcp/index.js +8 -5
  41. package/dist/mcp/index.js.map +1 -1
  42. package/dist/mcp-serve-verifier-CT1KLTG_.d.ts +162 -0
  43. package/dist/{openai-tools-DOI5mKNw.d.ts → openai-tools-D-VCAEmw.d.ts} +1 -1
  44. package/dist/profiles.d.ts +1 -1
  45. package/dist/{types-K8-xkiw1.d.ts → types-YimN9PQP.d.ts} +80 -1
  46. package/dist/{worktree-JXGJ1MxQ.d.ts → worktree-CtuEQ7bZ.d.ts} +2 -93
  47. package/dist/{worktree-fanout-DJHQy7Ux.d.ts → worktree-fanout-Cdez8GR7.d.ts} +16 -5
  48. package/package.json +6 -1
  49. package/dist/chunk-55WKGOGU.js.map +0 -1
  50. package/dist/chunk-PHKNOAOU.js.map +0 -1
  51. package/dist/chunk-VLF5RHEQ.js.map +0 -1
  52. /package/dist/{chunk-VYXBFWHZ.js.map → chunk-MRWXCFV5.js.map} +0 -0
  53. /package/dist/{chunk-HXVMLRYU.js.map → chunk-QKNBYHMK.js.map} +0 -0
@@ -0,0 +1,162 @@
1
+ import { AnalystFinding } from '@tangle-network/agent-eval';
2
+ import { L as LocalHarness, r as runLocalHarness } from './local-harness-BE_h8szs.js';
3
+ import { LabeledScenarioStore, WorktreeAdapter, SurfaceProposer } from '@tangle-network/agent-eval/campaign';
4
+
5
+ /**
6
+ * @experimental
7
+ *
8
+ * `improvementDriver` — the ONE reflective/agentic improvement proposer for
9
+ * agent-eval's improvement loop. It implements `SurfaceProposer` and owns
10
+ * the candidate lifecycle (worktree create → generate → finalize/discard,
11
+ * × populationSize); it delegates the only thing that genuinely varies — HOW
12
+ * a candidate change is produced — to a pluggable `CandidateGenerator`.
13
+ *
14
+ * There is no separate "analyst driver" vs "autoresearch driver": those are
15
+ * the SAME driver at two settings of a dial.
16
+ * - cheap reflective path → `reflectiveGenerator` (shots=1, no sandbox;
17
+ * applies pre-drafted patches)
18
+ * - full agentic path → `agenticGenerator` (shots=N, multi-shot
19
+ * verify-in-session loop; an agent reads code +
20
+ * report, edits, and re-tries on verifier failure)
21
+ * Both emit changes into a worktree the driver finalizes into a
22
+ * `CodeSurface{ worktreeRef }` the loop measures on the holdout. See
23
+ * agent-eval's `docs/design/self-improvement-engine.md`.
24
+ */
25
+
26
+ /** The byte-producing seam — the ONE thing that differs between the cheap
27
+ * reflective path and the full agentic path. A generator makes (uncommitted)
28
+ * changes inside `worktreePath`; the driver commits them via the worktree
29
+ * adapter's `finalize`. */
30
+ interface CandidateGenerator {
31
+ kind: string;
32
+ generate(args: {
33
+ /** The candidate worktree — a fresh checkout of baseRef. Write changes here. */
34
+ worktreePath: string;
35
+ /** Phase-2 research report (analyst findings + diff), opaque. */
36
+ report: unknown;
37
+ /** Findings resolved from the report or the loop context. */
38
+ findings: AnalystFinding[];
39
+ /** Handle to all captured data, to ground the change. */
40
+ dataset?: LabeledScenarioStore;
41
+ /** DEPTH: max iterations the generator may take (agentic uses this; the
42
+ * reflective generator ignores it). */
43
+ maxShots: number;
44
+ signal: AbortSignal;
45
+ }): Promise<{
46
+ applied: boolean;
47
+ summary: string;
48
+ }>;
49
+ }
50
+ interface ImprovementDriverOptions {
51
+ worktree: WorktreeAdapter;
52
+ generator: CandidateGenerator;
53
+ /** Base ref candidate worktrees fork from. Default `main`. */
54
+ baseRef?: string;
55
+ }
56
+ declare function improvementDriver(opts: ImprovementDriverOptions): SurfaceProposer<AnalystFinding>;
57
+
58
+ /**
59
+ * @experimental
60
+ *
61
+ * `agenticGenerator` — the full-agentic `CandidateGenerator`: the
62
+ * `shots=N, sandbox=on` setting of the one `improvementDriver`. It runs a real
63
+ * coding harness (claude / codex / opencode) inside the candidate worktree the
64
+ * driver already created, letting the agent read the codebase + the research
65
+ * report and make the change in place. The driver then commits the worktree
66
+ * into a `CodeSurface`.
67
+ *
68
+ * Mechanism: identical to the proven Phase-2.8 in-process executor — spawn the
69
+ * harness as a subprocess with `cwd` = the worktree, on the same filesystem,
70
+ * so edits land in place (no sandbox-mount round-trip). `runLocalHarness` is
71
+ * the verified primitive. The OUTER sandbox is the improvement loop's own
72
+ * execution context; the generator does not nest a second sandbox per
73
+ * candidate (which would reintroduce a host↔sandbox worktree-transport
74
+ * problem that does not need solving here).
75
+ *
76
+ * `maxShots` is the DEPTH dial — a multi-shot verify-in-session loop, NOT the
77
+ * kernel `runLoop`. Each shot runs one full harness session in the (persistent)
78
+ * worktree; between shots the loop refines based on what the last shot produced:
79
+ * - empty tree → "you changed nothing, make the edits" → retry
80
+ * - dirty + `verify` fails → feed the verifier's failure into the next shot
81
+ * (the worktree persists, so the harness RESUMES atop its own failing
82
+ * edits with the error in hand — no `--resume` session plumbing needed,
83
+ * and harness-agnostic across claude/codex/opencode)
84
+ * - dirty + `verify` ok (or no verifier configured) → return the candidate
85
+ * A candidate that never verifies within `maxShots` is discarded (`applied:
86
+ * false`), never shipped — if you configured a verifier, a non-passing tree is
87
+ * not a candidate. With no verifier the legacy behavior holds: first dirty shot
88
+ * is the candidate.
89
+ */
90
+
91
+ /** Outcome of verifying a candidate worktree. `feedback` (compiler errors,
92
+ * failing test output) is fed into the next shot when `ok` is false. */
93
+ interface VerifyResult {
94
+ ok: boolean;
95
+ feedback?: string;
96
+ }
97
+ /** Verifies the edited worktree. Sync or async; throws only on a setup fault
98
+ * (a candidate that fails verification returns `{ok:false}`, it does not
99
+ * throw). */
100
+ type Verifier = (worktreePath: string) => Promise<VerifyResult> | VerifyResult;
101
+ interface AgenticGeneratorOptions {
102
+ /** Local coding harness to run in the worktree. Default `claude`. */
103
+ harness?: LocalHarness;
104
+ /** Per-shot wall-clock timeout (ms). Default = `runLocalHarness` default (5m). */
105
+ timeoutMs?: number;
106
+ /** Build the harness task prompt from the report + findings. Override for
107
+ * domain phrasing; the default turns findings into a concrete coder task. */
108
+ buildPrompt?: (args: {
109
+ report: unknown;
110
+ findings: AnalystFinding[];
111
+ }) => string;
112
+ /** Verify the worktree after each dirtying shot. When set, a candidate that
113
+ * fails verification is NOT returned — the failure feeds the next shot
114
+ * (verify-in-session), up to `maxShots`; a candidate that never verifies is
115
+ * discarded (`applied:false`), never shipped. Omitted ⇒ legacy behavior:
116
+ * the first dirty shot is the candidate. See `commandVerifier`. */
117
+ verify?: Verifier;
118
+ /** Test seam — inject the harness runner (defaults to `runLocalHarness`). */
119
+ runHarness?: typeof runLocalHarness;
120
+ /** Test seam — inject the worktree-dirty check (defaults to `git status`). */
121
+ isDirty?: (worktreePath: string) => boolean;
122
+ }
123
+ declare function agenticGenerator(opts?: AgenticGeneratorOptions): CandidateGenerator;
124
+ /** A `Verifier` that runs a command in the worktree: exit 0 ⇒ ok, any other
125
+ * exit ⇒ failed with stdout+stderr as feedback. The common case — verify by
126
+ * `tsc --noEmit`, `pnpm build`, or a test command. A timeout is treated as a
127
+ * FAILED candidate (a change that hangs the build is a bad change); a missing
128
+ * binary or spawn fault throws (a setup bug, not a failed candidate — no
129
+ * silent fallback). */
130
+ declare function commandVerifier(command: string, args?: string[], timeoutMs?: number): Verifier;
131
+
132
+ /**
133
+ * `mcpServeVerifier` — the intrinsic verifier for a built MCP server: the
134
+ * boot-and-probe checker named in docs/artifact-lifecycle-frontier.md. A
135
+ * generated MCP server is only a candidate if it actually *serves* — so this
136
+ * boots it over stdio (the default local MCP transport) and runs the real
137
+ * handshake: `initialize` → `notifications/initialized` → `tools/list`, and
138
+ * asserts the server answers with at least `minTools` tools.
139
+ *
140
+ * Outcomes follow the `Verifier` contract: a server that fails to start, exits
141
+ * early, errors the handshake, times out, or exposes no tools is a FAILED
142
+ * candidate (`{ok:false}`, fed back into the next generation shot); a missing
143
+ * start binary or spawn fault THROWS (a setup bug, never a silent fallback).
144
+ *
145
+ * Protocol matches the runtime's own stdio MCP server (src/mcp/server.ts):
146
+ * newline-delimited JSON-RPC 2.0, protocol version 2024-11-05.
147
+ */
148
+
149
+ interface McpServeSpec {
150
+ /** Command that starts the built MCP server in the worktree (stdio transport). */
151
+ command: string;
152
+ args?: string[];
153
+ /** Extra env for the server process (merged over `process.env`). */
154
+ env?: Record<string, string>;
155
+ /** Handshake timeout (ms). Default 30s. */
156
+ timeoutMs?: number;
157
+ /** Minimum tools the server must expose to pass. Default 1. */
158
+ minTools?: number;
159
+ }
160
+ declare function mcpServeVerifier(spec: McpServeSpec): Verifier;
161
+
162
+ export { type AgenticGeneratorOptions as A, type CandidateGenerator as C, type ImprovementDriverOptions as I, type McpServeSpec as M, type Verifier as V, type VerifyResult as a, agenticGenerator as b, commandVerifier as c, improvementDriver as i, mcpServeVerifier as m };
@@ -1,4 +1,4 @@
1
- import { O as OpenAIChatTool } from './types-K8-xkiw1.js';
1
+ import { O as OpenAIChatTool } from './types-YimN9PQP.js';
2
2
 
3
3
  /**
4
4
  * @experimental
@@ -1,6 +1,6 @@
1
1
  import { a as UiFinding, U as UiLens } from './substrate-rNj6TDc3.js';
2
2
  export { C as CoderTask, b as UI_FINDING_SEVERITIES, c as UI_LENSES, d as UiFindingScreenshot, e as UiFindingSeverity, f as coderTaskToPrompt } from './substrate-rNj6TDc3.js';
3
- import { S as SandboxClient, a as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-K8-xkiw1.js';
3
+ import { S as SandboxClient, b as OutputAdapter, V as Validator, A as AgentRunSpec } from './types-YimN9PQP.js';
4
4
  import { SandboxEvent } from '@tangle-network/sandbox';
5
5
  import { AgentProfile } from '@tangle-network/agent-interface';
6
6
  import '@tangle-network/agent-eval';
@@ -763,9 +763,15 @@ interface AgentRunSpec<Task> {
763
763
  * files, or seed datasets. The hook is part of the runtime surface so loop
764
764
  * consumers do not hand-roll Sandbox SDK orchestration just to prepare a
765
765
  * workspace before the agent sees it.
766
+ *
767
+ * `ctx.recordMount` records what was placed into the box so the run carries a
768
+ * provenance manifest (`LoopResult.provenance.mounts`). It is optional and
769
+ * provenance-only — the kernel never reads box contents and attaches no
770
+ * meaning to the entries; not calling it simply leaves the manifest empty.
766
771
  */
767
772
  prepareBox?: (box: SandboxInstance, ctx: {
768
773
  signal: AbortSignal;
774
+ recordMount: MountRecorder;
769
775
  }) => Promise<void> | void;
770
776
  /**
771
777
  * Per-spec stable name. Surfaced in trace events and the default winner
@@ -801,6 +807,75 @@ interface LoopTokenUsage {
801
807
  input: number;
802
808
  output: number;
803
809
  }
810
+ /**
811
+ * One mounted resource recorded during box preparation — a pure provenance
812
+ * record of what the caller placed into a box before the agent saw it. The
813
+ * kernel never reads box contents itself (it does not know what was mounted);
814
+ * the caller, which owns the bytes inside `prepareBox`, supplies each entry via
815
+ * `recordMount`. Carries no domain semantics — just where the resource landed,
816
+ * its content fingerprint, its size, and where it came from — so a run is
817
+ * auditable after the fact ("what exactly was this agent given?").
818
+ *
819
+ * @experimental
820
+ */
821
+ interface MountManifestEntry {
822
+ /** Destination path inside the box where the resource was placed. */
823
+ path: string;
824
+ /** Hex SHA-256 of the mounted bytes. The caller computes it from the bytes
825
+ * it wrote — the kernel does not hash box contents. */
826
+ sha256: string;
827
+ /** Size of the mounted resource in bytes. */
828
+ bytes: number;
829
+ /** Free-form origin of the resource (e.g. a repo ref, a corpus id, a local
830
+ * path, a URL). Provenance only — the kernel attaches no meaning to it. */
831
+ source: string;
832
+ }
833
+ /**
834
+ * A record of one candidate-selection decision: which iteration the selector
835
+ * picked (or rejected) and why. Pure audit trail of the SELECTOR role — it
836
+ * carries the selector's identity, the candidate's score, and an optional
837
+ * human-readable reason, with no domain semantics. The kernel emits one receipt
838
+ * per scored candidate at finalize so a run answers "why did THIS one win?".
839
+ *
840
+ * @experimental
841
+ */
842
+ interface SelectionReceipt {
843
+ /** Iteration index this receipt is about. */
844
+ candidateIndex: number;
845
+ /** True for the iteration the selector chose as winner; false otherwise. */
846
+ selected: boolean;
847
+ /** The candidate's verdict score, when it has one. */
848
+ score?: number;
849
+ /** Why this candidate was (or was not) selected, when the selector states it. */
850
+ reason?: string;
851
+ /** Identity of the selector that produced this receipt — `'caller'` (an
852
+ * explicit `selectWinner`), `'driver'` (a driver-authored winner), or
853
+ * `'default'` (the kernel's best-valid-score argmax). */
854
+ selector: 'caller' | 'driver' | 'default';
855
+ }
856
+ /**
857
+ * Domain-free run provenance: a manifest of what was mounted into the run's
858
+ * boxes and the receipts for how the winner was selected. Surfaced on
859
+ * `LoopResult` purely for run auditability — nothing in the kernel branches on
860
+ * it. Empty arrays when the caller recorded no mounts and there was no
861
+ * candidate to select.
862
+ *
863
+ * @experimental
864
+ */
865
+ interface RunProvenance {
866
+ /** Every resource recorded via `prepareBox`'s `recordMount`, in record order. */
867
+ mounts: MountManifestEntry[];
868
+ /** One receipt per scored candidate at finalize, in iteration order. */
869
+ selectionReceipts: SelectionReceipt[];
870
+ }
871
+ /**
872
+ * Records a mounted resource into the run's provenance manifest. Passed to
873
+ * `prepareBox` so the caller — which owns the bytes it writes into the box —
874
+ * declares what it mounted without the kernel having to inspect box contents.
875
+ *
876
+ * @experimental
877
+ */
878
+ type MountRecorder = (entry: MountManifestEntry) => void;
804
879
  /** @experimental */
805
880
  interface Iteration<Task, Output> {
806
881
  /** 0-based iteration index assigned by the kernel. */
@@ -892,6 +967,10 @@ interface LoopResult<Task, Output, Decision> {
892
967
  * `ctx.cost.observeTokens` in a `runProfileMatrix` dispatch so the
893
968
  * integrity guard sees real LLM activity. */
894
969
  tokenUsage: LoopTokenUsage;
970
+ /** Domain-free run provenance for auditability: the mount manifest recorded
971
+ * during `prepareBox` and the selection receipts for how the winner was
972
+ * chosen. Always present; empty arrays when nothing was recorded. */
973
+ provenance: RunProvenance;
895
974
  }
896
975
  /**
897
976
  * Minimal sandbox client surface the kernel calls. Satisfied structurally by
@@ -1178,4 +1257,4 @@ interface ExecCtx {
1178
1257
  parentSpanId?: string;
1179
1258
  }
1180
1259
 
1181
- export { type LoopIterationDispatchPayload as $, type AgentRunSpec as A, type BackendErrorDetail as B, type RuntimeHookEvent as C, type RuntimeHookPhase as D, type ExecCtx as E, type RuntimeHookTarget as F, type RuntimeRunHandle as G, type RuntimeRunPersistenceAdapter as H, type Iteration as I, type RuntimeRunRow as J, type KnowledgeReadinessDecision as K, type LoopTokenUsage as L, composeRuntimeHooks as M, defineRuntimeHooks as N, type OpenAIChatTool as O, notifyRuntimeDecisionPoint as P, notifyRuntimeHookEvent as Q, type RuntimeStreamEvent as R, type SandboxClient as S, startRuntimeRun as T, type Driver as U, type Validator as V, type LoopWinner as W, type LoopLineageOptions as X, type LoopResult as Y, type LoopDecisionPayload as Z, type LoopEndedPayload as _, type OutputAdapter as a, type LoopIterationEndedPayload as a0, type LoopIterationStartedPayload as a1, type LoopPlanDescription as a2, type LoopPlanPayload as a3, type LoopStartedPayload as a4, type LoopTeardownFailedPayload as a5, type ValidationCtx as a6, type RuntimeHooks as b, type LoopTraceEvent as c, type LoopSandboxPlacement as d, type LoopTraceEmitter as e, type AgentBackendInput as f, type AgentExecutionBackend as g, type OpenAIChatToolChoice as h, type AgentBackendContext as i, type RunAgentTaskOptions as j, type AgentTaskRunResult as k, type RunAgentTaskStreamOptions as l, type AgentRuntimeEvent as m, type AgentTaskStatus as n, type RuntimeSessionStore as o, type RuntimeSession as p, type AgentAdapter as q, type AgentKnowledgeProvider as r, type AgentRuntimeEventSink as s, type AgentTaskContext as t, type AgentTaskSpec as u, type RuntimeDecisionEvidenceRef as v, type RuntimeDecisionKind as w, type RuntimeDecisionPoint as x, type RuntimeHookContext as y, type RuntimeHookErrorContext as z };
1260
+ export { type LoopEndedPayload as $, type AgentRunSpec as A, type BackendErrorDetail as B, type RuntimeHookEvent as C, type RuntimeHookPhase as D, type ExecCtx as E, type RuntimeHookTarget as F, type RuntimeRunHandle as G, type RuntimeRunPersistenceAdapter as H, type Iteration as I, type RuntimeRunRow as J, type KnowledgeReadinessDecision as K, type LoopTokenUsage as L, composeRuntimeHooks as M, defineRuntimeHooks as N, type OpenAIChatTool as O, notifyRuntimeDecisionPoint as P, notifyRuntimeHookEvent as Q, type RuntimeHooks as R, type SandboxClient as S, startRuntimeRun as T, type Driver as U, type Validator as V, type LoopWinner as W, type LoopLineageOptions as X, type LoopResult as Y, type MountRecorder as Z, type LoopDecisionPayload as _, type RuntimeStreamEvent as a, type LoopIterationDispatchPayload as a0, type LoopIterationEndedPayload as a1, type LoopIterationStartedPayload as a2, type LoopPlanDescription as a3, type LoopPlanPayload as a4, type LoopStartedPayload as a5, type LoopTeardownFailedPayload as a6, type MountManifestEntry as a7, type RunProvenance as a8, type SelectionReceipt as a9, type ValidationCtx as aa, type OutputAdapter as b, type LoopTraceEvent as c, type LoopSandboxPlacement as d, type LoopTraceEmitter as e, type AgentBackendInput as f, type AgentExecutionBackend as g, type OpenAIChatToolChoice as h, type AgentBackendContext as i, type RunAgentTaskOptions as j, type AgentTaskRunResult as k, type RunAgentTaskStreamOptions as l, type AgentRuntimeEvent as m, type AgentTaskStatus as n, type RuntimeSessionStore as o, type RuntimeSession as p, type AgentAdapter as q, type AgentKnowledgeProvider as r, type AgentRuntimeEventSink as s, type AgentTaskContext as t, type AgentTaskSpec as u, type RuntimeDecisionEvidenceRef as v, type RuntimeDecisionKind as w, type RuntimeDecisionPoint as x, type RuntimeHookContext as y, type RuntimeHookErrorContext as z };
@@ -1,98 +1,7 @@
1
- import { ChildProcess } from 'node:child_process';
2
1
  import { DefaultVerdict } from '@tangle-network/agent-eval';
3
2
  import { AgentProfile } from '@tangle-network/agent-interface';
4
3
  import { BackendType } from '@tangle-network/sandbox';
5
- import { L as LoopTokenUsage, b as RuntimeHooks } from './types-K8-xkiw1.js';
6
-
7
- /**
8
- * @experimental
9
- *
10
- * Subprocess wrappers for the local coding-harness CLIs installed in the
11
- * sandbox image (claude-code, codex, opencode). Used by the in-process
12
- * delegation executor (`createInProcessExecutor`) so a `delegate_code` call
13
- * spawns a real harness on a real git worktree instead of provisioning a
14
- * sibling sandbox.
15
- *
16
- * All harness invocations:
17
- * - run with `cwd` set to the worktree
18
- * - inherit env from the parent (the MCP server inside the sandbox has
19
- * the harness's auth already)
20
- * - capture stdout/stderr
21
- * - support cancellation via AbortSignal
22
- * - enforce a wall-clock timeout
23
- */
24
-
25
- /** Local coding harness available inside the sandbox. */
26
- type LocalHarness = 'claude' | 'codex' | 'opencode';
27
- /** @experimental */
28
- interface RunLocalHarnessOptions {
29
- harness: LocalHarness;
30
- /** Working directory for the subprocess (typically a worktree path). */
31
- cwd: string;
32
- /** Prompt forwarded as the harness CLI's task argument. */
33
- taskPrompt: string;
34
- /**
35
- * Pre-built command + args (e.g. from `harnessInvocation` so the full authored
36
- * `AgentProfile` — systemPrompt + model — reaches the harness). When set it OVERRIDES the
37
- * default prompt-only `buildArgs(taskPrompt)` path; `command` defaults to the harness's
38
- * default binary when only `args` is supplied. When absent the legacy prompt-only shape
39
- * is used unchanged.
40
- */
41
- invocation?: {
42
- command?: string;
43
- args: ReadonlyArray<string>;
44
- };
45
- /** Wall-clock kill deadline (ms). Default 5 min. Subprocess SIGTERMed on expiry. */
46
- timeoutMs?: number;
47
- /** Caller cancellation. SIGTERM is sent on abort. */
48
- signal?: AbortSignal;
49
- /** Override env (defaults to inheriting from the parent). */
50
- env?: NodeJS.ProcessEnv;
51
- /**
52
- * Test seam — inject a custom spawner so unit tests can mock the
53
- * subprocess without touching the OS. Defaults to node's `child_process.spawn`.
54
- */
55
- spawn?: (command: string, args: ReadonlyArray<string>, opts: {
56
- cwd: string;
57
- env: NodeJS.ProcessEnv;
58
- stdio: 'pipe';
59
- }) => ChildProcess;
60
- }
61
- /** @experimental */
62
- interface LocalHarnessResult {
63
- /** OS exit code. `null` when killed before exit. */
64
- exitCode: number | null;
65
- /** Concatenated stdout. */
66
- stdout: string;
67
- /** Concatenated stderr. */
68
- stderr: string;
69
- /** Set when the process exited via signal (timeout / abort). */
70
- killedBySignal: NodeJS.Signals | null;
71
- /** Wall-clock duration ms (spawn → exit). */
72
- durationMs: number;
73
- /** Set when timeoutMs elapsed before exit. */
74
- timedOut: boolean;
75
- }
76
- /**
77
- * Spawn a local coding harness CLI as a subprocess + collect its output.
78
- *
79
- * NOT responsible for parsing the harness's output or extracting a diff —
80
- * the in-process executor's `streamPrompt` orchestrates `git diff` against
81
- * the worktree after this resolves. This function is intentionally narrow:
82
- * spawn, wait, capture, return.
83
- *
84
- * Fails loud — throws when:
85
- * - `cwd` doesn't exist (subprocess emits ENOENT; surfaced as Error)
86
- * - the harness binary is not on PATH (ENOENT)
87
- *
88
- * Does NOT throw when:
89
- * - the subprocess exits non-zero (`result.exitCode` carries the code)
90
- * - the subprocess is aborted / timed out (`result.killedBySignal` /
91
- * `result.timedOut` carries the reason)
92
- *
93
- * @experimental
94
- */
95
- declare function runLocalHarness(options: RunLocalHarnessOptions): Promise<LocalHarnessResult>;
4
+ import { L as LoopTokenUsage, R as RuntimeHooks } from './types-YimN9PQP.js';
96
5
 
97
6
  /**
98
7
  * @experimental
@@ -699,4 +608,4 @@ declare function captureWorktreeDiff(options: DiffOptions): Promise<DiffResult>;
699
608
  /** @experimental */
700
609
  declare function removeWorktree(options: RemoveWorktreeOptions): Promise<void>;
701
610
 
702
- export { type AgentSpec as A, type Budget as B, type CreateWorktreeOptions as C, type DiffOptions as D, type ExecutorRegistry as E, type GitRunner as G, type LocalHarness as L, type NodeId as N, type RemoveWorktreeOptions as R, type SpawnJournal as S, type TreeView as T, type UsageEvent as U, type WorktreeHandle as W, type DiffResult as a, type LocalHarnessResult as b, type RunLocalHarnessOptions as c, captureWorktreeDiff as d, createWorktree as e, removeWorktree as f, type Agent as g, type ResultBlobStore as h, type RootHandle as i, type SupervisedResult as j, type Settled as k, type Spend as l, type Scope as m, type Executor as n, type DeliverableSpec as o, type ExecutorFactory as p, type SpawnEvent as q, runLocalHarness as r, type Supervisor as s, type ExecutorContext as t, type ExecutorResult as u, type SupervisorOpts as v, type WidenGate as w, gateOnDeliverable as x };
611
+ export { type AgentSpec as A, type Budget as B, type CreateWorktreeOptions as C, type DiffOptions as D, type ExecutorRegistry as E, type GitRunner as G, type NodeId as N, type RemoveWorktreeOptions as R, type SpawnJournal as S, type TreeView as T, type UsageEvent as U, type WorktreeHandle as W, type DiffResult as a, createWorktree as b, captureWorktreeDiff as c, type Agent as d, type ResultBlobStore as e, type RootHandle as f, type SupervisedResult as g, type Settled as h, type Spend as i, type Scope as j, type Executor as k, type DeliverableSpec as l, type ExecutorFactory as m, type SpawnEvent as n, type Supervisor as o, type ExecutorContext as p, type ExecutorResult as q, removeWorktree as r, type SupervisorOpts as s, type WidenGate as t, gateOnDeliverable as u };
@@ -1,8 +1,9 @@
1
1
  import { AgentProfile } from '@tangle-network/agent-interface';
2
2
  import { AnalystFinding, DefaultVerdict } from '@tangle-network/agent-eval';
3
- import { A as AgentSpec, E as ExecutorRegistry, B as Budget, g as Agent, S as SpawnJournal, h as ResultBlobStore, i as RootHandle, j as SupervisedResult, N as NodeId, k as Settled, l as Spend, m as Scope, L as LocalHarness, G as GitRunner, r as runLocalHarness, n as Executor, o as DeliverableSpec } from './worktree-JXGJ1MxQ.js';
4
- import { b as RuntimeHooks, I as Iteration } from './types-K8-xkiw1.js';
3
+ import { A as AgentSpec, E as ExecutorRegistry, B as Budget, d as Agent, S as SpawnJournal, e as ResultBlobStore, f as RootHandle, g as SupervisedResult, N as NodeId, h as Settled, i as Spend, j as Scope, G as GitRunner, k as Executor, l as DeliverableSpec } from './worktree-CtuEQ7bZ.js';
4
+ import { R as RuntimeHooks, I as Iteration } from './types-YimN9PQP.js';
5
5
  import { BackendType } from '@tangle-network/sandbox';
6
+ import { L as LocalHarness, r as runLocalHarness } from './local-harness-BE_h8szs.js';
6
7
 
7
8
  /**
8
9
  * @experimental
@@ -869,9 +870,12 @@ type WorktreeCheckRunner = (opts: {
869
870
  * result onto the `Executor` port (artifact + spend) and owns the teardown point. The §1.5 payload
870
871
  * (authored systemPrompt + model) reaches the harness inside the core, not here.
871
872
  *
872
- * Token accounting: a harness CLI does not surface usage, so this executor is `budgetExempt: true`
873
- * — its spend is NOT metered against the conserved pool and its iterations are EXCLUDED from the
874
- * equal-k arms by construction (mirrors `cliExecutor`).
873
+ * Token accounting: a harness CLI does not surface usage, so this executor defaults to
874
+ * `budgetExempt: true` — its spend is NOT metered against the conserved pool and its iterations are
875
+ * EXCLUDED from the equal-k arms by construction (mirrors `cliExecutor`). The exemption is an
876
+ * explicit, documented `budgetExempt` option rather than a buried hardcode: set it `false` ONLY for
877
+ * a harness that genuinely surfaces real token/usd usage to meter into the pool — otherwise the
878
+ * executor would meter a fabricated zero, which the no-silent-zeros rule forbids.
875
879
  */
876
880
 
877
881
  /** Terminal artifact of one worktree-CLI run — the canonical worktree-harness result (the captured
@@ -909,6 +913,13 @@ interface WorktreeCliExecutorOptions {
909
913
  /** Test seam — inject the verification-command runner so unit tests script test/typecheck
910
914
  * outcomes without spawning a real shell. Defaults to a `/bin/sh -c` spawn in the worktree. */
911
915
  runCommand?: WorktreeCheckRunner;
916
+ /**
917
+ * Exclude this leaf's spend from the conserved pool + equal-k arms. Defaults to `true` because a
918
+ * coding-harness CLI does not surface token usage, so metering it would record a fabricated zero
919
+ * (the no-silent-zeros rule forbids that). Set `false` ONLY for a harness that surfaces real
920
+ * token/usd usage worth metering — the executor would then debit the (real) spend it captures.
921
+ */
922
+ budgetExempt?: boolean;
912
923
  }
913
924
  /**
914
925
  * Build a worktree-CLI leaf `Executor`. Per-spawn (a fresh worktree + abort + teardown each), so a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-runtime",
3
- "version": "0.72.0",
3
+ "version": "0.74.0",
4
4
  "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.",
5
5
  "homepage": "https://github.com/tangle-network/agent-runtime#readme",
6
6
  "repository": {
@@ -39,6 +39,11 @@
39
39
  "import": "./dist/analyst-loop.js",
40
40
  "default": "./dist/analyst-loop.js"
41
41
  },
42
+ "./lifecycle": {
43
+ "types": "./dist/lifecycle.d.ts",
44
+ "import": "./dist/lifecycle.js",
45
+ "default": "./dist/lifecycle.js"
46
+ },
42
47
  "./profiles": {
43
48
  "types": "./dist/profiles.d.ts",
44
49
  "import": "./dist/profiles.js",