@tangle-network/agent-runtime 0.115.1 → 0.117.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 (88) hide show
  1. package/README.md +7 -1
  2. package/dist/{activation-Bt_XVkjK.js → activation-BZ2FyX0O.js} +3 -3
  3. package/dist/{activation-Bt_XVkjK.js.map → activation-BZ2FyX0O.js.map} +1 -1
  4. package/dist/agent.d.ts +3 -64
  5. package/dist/agent.js +5 -207
  6. package/dist/agent.js.map +1 -1
  7. package/dist/{analyst-loop-BoNIG2hA.js → analyst-loop-DvSciOfB.js} +2 -2
  8. package/dist/{analyst-loop-BoNIG2hA.js.map → analyst-loop-DvSciOfB.js.map} +1 -1
  9. package/dist/analyst-loop.js +1 -1
  10. package/dist/candidate-execution/index.d.ts +3 -3
  11. package/dist/candidate-execution/index.js +5 -5
  12. package/dist/{candidate-execution-CfpJrd3o.js → candidate-execution-PX61zXd2.js} +4 -4
  13. package/dist/{candidate-execution-CfpJrd3o.js.map → candidate-execution-PX61zXd2.js.map} +1 -1
  14. package/dist/{environment-provider-Cygthiy3.d.ts → environment-provider-CTZjdIUg.d.ts} +661 -34
  15. package/dist/{environment-provider-CCaEhA-l.js → environment-provider-CzcEyRL7.js} +140 -31
  16. package/dist/environment-provider-CzcEyRL7.js.map +1 -0
  17. package/dist/environment-provider.d.ts +1 -1
  18. package/dist/environment-provider.js +1 -1
  19. package/dist/{improvement-cycle-tEswzEPr.js → improvement-cycle-Bcqz8rZI.js} +160 -19
  20. package/dist/improvement-cycle-Bcqz8rZI.js.map +1 -0
  21. package/dist/{index-DZukewLl.d.ts → index-BHSYaWrC.d.ts} +3 -3
  22. package/dist/{index-K7nucOmw.d.ts → index-BTUG4Xln.d.ts} +8 -7
  23. package/dist/{index-BUWd8QJq.d.ts → index-DPWJxSRa.d.ts} +884 -497
  24. package/dist/{index-C-FYUuFG.d.ts → index-X2YwyWkc.d.ts} +2 -2
  25. package/dist/index.d.ts +9 -10
  26. package/dist/index.js +12 -13
  27. package/dist/index.js.map +1 -1
  28. package/dist/intelligence.d.ts +10 -9
  29. package/dist/intelligence.js +15 -9
  30. package/dist/intelligence.js.map +1 -1
  31. package/dist/kernel.d.ts +4 -4
  32. package/dist/kernel.js +8 -8
  33. package/dist/{knowledge-CUXQE8Sq.js → knowledge-CDlrayRc.js} +7 -7
  34. package/dist/knowledge-CDlrayRc.js.map +1 -0
  35. package/dist/knowledge.d.ts +1 -1
  36. package/dist/knowledge.js +1 -1
  37. package/dist/{local-harness-BnB1E9nM.d.ts → local-harness-t6cDWDQ2.d.ts} +3 -105
  38. package/dist/{loop-runner-bin-DzJz48Fb.js → loop-runner-bin-BxhhDtmG.js} +4 -4
  39. package/dist/{loop-runner-bin-DzJz48Fb.js.map → loop-runner-bin-BxhhDtmG.js.map} +1 -1
  40. package/dist/{loop-runner-bin-BZl5vp7t.d.ts → loop-runner-bin-oyL7it5O.d.ts} +3 -3
  41. package/dist/loop-runner-bin.d.ts +1 -1
  42. package/dist/loop-runner-bin.js +1 -1
  43. package/dist/mcp/bin.js +43 -10
  44. package/dist/mcp/bin.js.map +1 -1
  45. package/dist/mcp/index.d.ts +4 -43
  46. package/dist/mcp/index.js +5 -205
  47. package/dist/mcp/index.js.map +1 -1
  48. package/dist/{openai-tools-CynwZMZd.js → openai-tools-CO9X36zy.js} +2 -2
  49. package/dist/{openai-tools-CynwZMZd.js.map → openai-tools-CO9X36zy.js.map} +1 -1
  50. package/dist/{prepare-BHQBb02e.js → prepare-BbI6qGOW.js} +5 -2
  51. package/dist/prepare-BbI6qGOW.js.map +1 -0
  52. package/dist/primeintellect/index.d.ts +1 -1
  53. package/dist/{protected-model-port-BP6Z4eau.d.ts → protected-model-port-B0yXMpLL.d.ts} +10 -2
  54. package/dist/{protected-model-port-DqAH1Z2M.js → protected-model-port-COnyZfML.js} +2 -2
  55. package/dist/{protected-model-port-DqAH1Z2M.js.map → protected-model-port-COnyZfML.js.map} +1 -1
  56. package/dist/{redact-BRaHUFMf.d.ts → redact-BEtQtvd6.d.ts} +2 -2
  57. package/dist/{runtime-BatQajPB.js → runtime-Ce39zfqn.js} +145 -53
  58. package/dist/runtime-Ce39zfqn.js.map +1 -0
  59. package/dist/{sandbox-events-DeI5xX8P.js → sandbox-events-Yhd1GYWl.js} +4 -2
  60. package/dist/sandbox-events-Yhd1GYWl.js.map +1 -0
  61. package/dist/spawn-journal-B_mu_oH2.js +857 -0
  62. package/dist/spawn-journal-B_mu_oH2.js.map +1 -0
  63. package/dist/{structural-rollout-DEf37yQy.js → structural-rollout-DLwW69R4.js} +4 -4
  64. package/dist/structural-rollout-DLwW69R4.js.map +1 -0
  65. package/dist/{supervise-B7TIJR3D.js → supervise-U7_K5yuV.js} +2645 -829
  66. package/dist/supervise-U7_K5yuV.js.map +1 -0
  67. package/dist/{supervisor-DzQu5Ydu.js → supervisor-CAXiCKnX.js} +3802 -967
  68. package/dist/supervisor-CAXiCKnX.js.map +1 -0
  69. package/dist/testing.js +98 -76
  70. package/dist/testing.js.map +1 -1
  71. package/dist/{workspace-archive-DXzJq7WP.js → workspace-archive-CqPIijFA.js} +2 -2
  72. package/dist/{workspace-archive-DXzJq7WP.js.map → workspace-archive-CqPIijFA.js.map} +1 -1
  73. package/package.json +1 -1
  74. package/dist/environment-provider-CCaEhA-l.js.map +0 -1
  75. package/dist/improvement-cycle-tEswzEPr.js.map +0 -1
  76. package/dist/knowledge-CUXQE8Sq.js.map +0 -1
  77. package/dist/otel-export-CPZTSADj.js +0 -852
  78. package/dist/otel-export-CPZTSADj.js.map +0 -1
  79. package/dist/prepare-BHQBb02e.js.map +0 -1
  80. package/dist/runtime-BatQajPB.js.map +0 -1
  81. package/dist/sandbox-events-DeI5xX8P.js.map +0 -1
  82. package/dist/spawn-journal-DCPbicXB.js +0 -457
  83. package/dist/spawn-journal-DCPbicXB.js.map +0 -1
  84. package/dist/structural-rollout-DEf37yQy.js.map +0 -1
  85. package/dist/supervise-B7TIJR3D.js.map +0 -1
  86. package/dist/supervisor-DzQu5Ydu.js.map +0 -1
  87. package/dist/trace-propagation-B-pL7xn_.js +0 -57
  88. package/dist/trace-propagation-B-pL7xn_.js.map +0 -1
@@ -1,7 +1,8 @@
1
+ import { d as AgentTaskStatus, o as AgentRuntimeEvent, x as RuntimeStreamEvent } from "./types-C9j4qg6l.js";
1
2
  import { l as RuntimeHooks } from "./runtime-hooks-sbRpjStq.js";
2
- import { E as SandboxClient, v as LoopTokenUsage } from "./types-DnNGJ5Gz.js";
3
- import { DefaultVerdict, ToolSpan } from "@tangle-network/agent-eval";
4
- import { AgentProfile as AgentProfile$1, AgentProfileValidationResult } from "@tangle-network/agent-interface";
3
+ import { E as SandboxClient, v as LoopTokenUsage, y as LoopTraceEmitter } from "./types-DnNGJ5Gz.js";
4
+ import { ControlEvalResult, DefaultVerdict, KnowledgeReadinessReport, KnowledgeRequirement, ToolSpan } from "@tangle-network/agent-eval";
5
+ import { AgentProfile as AgentProfile$1, AgentProfileValidationResult, Sha256Digest } from "@tangle-network/agent-interface";
5
6
  import { BackendType, CreateSandboxOptions, Sandbox } from "@tangle-network/sandbox";
6
7
  import { AgentEnvironment, AgentEnvironmentCapabilities, AgentEnvironmentCapabilities as AgentEnvironmentCapabilities$1, AgentEnvironmentEvent, AgentEnvironmentProvider, AgentEnvironmentProvider as AgentEnvironmentProvider$1, AgentEnvironmentQuery, AgentEnvironmentStatus, AgentEnvironmentSummary, AgentProfileRef, AgentProfileRef as AgentProfileRef$1, AgentSession, AgentSessionRef, AgentSessionStatus, AgentTurnInput, AgentTurnInput as AgentTurnInput$1, AgentTurnResult, CheckpointRef, CheckpointRequest, CreateAgentEnvironmentInput, CreateAgentEnvironmentInput as CreateAgentEnvironmentInput$1, ExecRequest, ExecResult, ForkRequest, PlacementInfo, ResourceRequest, WorkspaceRequest } from "@tangle-network/agent-interface/environment-provider";
7
8
  //#region src/runtime/supervise/progress.d.ts
@@ -303,6 +304,377 @@ declare function waitUntil(spec: WaitSpec): number | undefined;
303
304
  /** Structural validation, independent of the run. Returns null when the spec is usable. */
304
305
  declare function validateWaitSpec(spec: WaitSpec): string | null;
305
306
  //#endregion
307
+ //#region src/sanitize.d.ts
308
+ /** @stable */
309
+ interface RuntimeTelemetryOptions {
310
+ /**
311
+ * Include raw task inputs. Off by default because task inputs often contain
312
+ * customer facts, credentials, source text, or internal IDs.
313
+ */
314
+ includeInputs?: boolean;
315
+ /** Include requirement descriptions. Secret requirements are always redacted. */
316
+ includeRequirementDescriptions?: boolean;
317
+ /** Include evidence IDs. Off by default; counts are safer for shared reports. */
318
+ includeEvidenceIds?: boolean;
319
+ /** Include user answers from question preflight. Off by default. */
320
+ includeUserAnswers?: boolean;
321
+ /** Include action payloads and action results for control steps. Off by default. */
322
+ includeControlPayloads?: boolean;
323
+ /** Include task metadata. Off by default because metadata may carry IDs or policy internals. */
324
+ includeMetadata?: boolean;
325
+ /** Include eval detail/evidence strings. Off by default because validators may echo private input. */
326
+ includeEvalDetails?: boolean;
327
+ }
328
+ /** @stable */
329
+ interface SanitizedKnowledgeRequirement {
330
+ id: string;
331
+ description?: string;
332
+ requiredFor: string[];
333
+ category: KnowledgeRequirement['category'];
334
+ acquisitionMode: KnowledgeRequirement['acquisitionMode'];
335
+ importance: KnowledgeRequirement['importance'];
336
+ freshness: KnowledgeRequirement['freshness'];
337
+ sensitivity: KnowledgeRequirement['sensitivity'];
338
+ confidenceNeeded: number;
339
+ currentConfidence: number;
340
+ evidenceCount: number;
341
+ evidenceIds?: string[];
342
+ fallbackPolicy: KnowledgeRequirement['fallbackPolicy'];
343
+ }
344
+ /** @stable */
345
+ interface SanitizedKnowledgeReadinessReport {
346
+ taskId: string;
347
+ readinessScore: number;
348
+ recommendedAction: KnowledgeReadinessReport['recommendedAction'];
349
+ severity: KnowledgeReadinessReport['severity'];
350
+ reason: string;
351
+ blockingMissingRequirements: SanitizedKnowledgeRequirement[];
352
+ nonBlockingGaps: SanitizedKnowledgeRequirement[];
353
+ evidenceCount: number;
354
+ evidenceIds?: string[];
355
+ missingRequirementIds: string[];
356
+ }
357
+ /** Strip PII and large blobs from a `KnowledgeReadinessReport` for safe telemetry emission. @stable */
358
+ declare function sanitizeKnowledgeReadinessReport(report: KnowledgeReadinessReport, options?: RuntimeTelemetryOptions): SanitizedKnowledgeReadinessReport;
359
+ /** Reduce an `AgentRuntimeEvent` to a PII-safe, serializable plain object for telemetry. @stable */
360
+ declare function sanitizeAgentRuntimeEvent<TState, TAction, TActionResult, TEval extends ControlEvalResult>(event: AgentRuntimeEvent<TState, TAction, TActionResult, TEval>, options?: RuntimeTelemetryOptions): Record<string, unknown>;
361
+ /** Reduce a `RuntimeStreamEvent` to a PII-safe, serializable plain object for telemetry. @stable */
362
+ declare function sanitizeRuntimeStreamEvent(event: RuntimeStreamEvent, options?: RuntimeTelemetryOptions): Record<string, unknown>;
363
+ /** @stable */
364
+ interface RuntimeEventCollector<TState = unknown, TAction = unknown, TActionResult = unknown, TEval extends ControlEvalResult = ControlEvalResult> {
365
+ onEvent: (event: AgentRuntimeEvent<TState, TAction, TActionResult, TEval>) => void;
366
+ events: Array<Record<string, unknown>>;
367
+ }
368
+ /** @stable */
369
+ type RuntimeStreamEventSink = (event: RuntimeStreamEvent) => void;
370
+ /** @stable */
371
+ interface RuntimeStreamEventSummary {
372
+ /** Total count of sanitized events collected. */
373
+ eventCount: number;
374
+ /** Count of events per `type`. Useful for log-line summaries. */
375
+ eventCountsByType: Record<string, number>;
376
+ /** First session id observed in a `session_created` / `session_resumed` event, if any. */
377
+ firstSessionId?: string;
378
+ /** Last `final` event's status, if a final event was observed. */
379
+ finalStatus?: AgentTaskStatus;
380
+ /** Last `final` event's reason, if a final event was observed. */
381
+ finalReason?: string;
382
+ /** Concatenated `text_delta.text` across the stream, even when payloads are redacted. */
383
+ finalText: string;
384
+ }
385
+ /** @stable */
386
+ interface RuntimeStreamEventCollector {
387
+ onEvent: RuntimeStreamEventSink;
388
+ events: Array<Record<string, unknown>>;
389
+ /** Snapshot of a small streaming-flavored summary derived from collected events. */
390
+ summary(): RuntimeStreamEventSummary;
391
+ }
392
+ /** Build an in-memory collector that sanitizes and accumulates `AgentRuntimeEvent`s for inspection. @stable */
393
+ declare function createRuntimeEventCollector<TState = unknown, TAction = unknown, TActionResult = unknown, TEval extends ControlEvalResult = ControlEvalResult>(options?: RuntimeTelemetryOptions): RuntimeEventCollector<TState, TAction, TActionResult, TEval>;
394
+ /**
395
+ *
396
+ * Streaming-event counterpart of `createRuntimeEventCollector`. Pass each
397
+ * event yielded by `runAgentTaskStream` through `onEvent` and read the
398
+ * sanitized copies off `events`; the same `RuntimeTelemetryOptions` redaction
399
+ * flags apply. Kept distinct from `createRuntimeEventCollector` because the
400
+ * stream and non-stream event shapes overlap on `type` literals — dispatching
401
+ * on `type` alone would misroute events.
402
+ *
403
+ * @stable
404
+ */
405
+ declare function createRuntimeStreamEventCollector(options?: RuntimeTelemetryOptions): RuntimeStreamEventCollector;
406
+ //#endregion
407
+ //#region src/otel-export.d.ts
408
+ interface OtelExportConfig {
409
+ /** OTLP endpoint. Reads OTEL_EXPORTER_OTLP_ENDPOINT env by default. */
410
+ endpoint?: string;
411
+ /** OTLP headers. Reads OTEL_EXPORTER_OTLP_HEADERS env by default. */
412
+ headers?: Record<string, string>;
413
+ /** Batch size before flush. Default 64. */
414
+ batchSize?: number;
415
+ /** Flush interval ms. Default 5000. */
416
+ flushIntervalMs?: number;
417
+ /** Resource attributes stamped on every export. */
418
+ resourceAttributes?: Record<string, string | number | boolean>;
419
+ /** Service name. Default 'agent-runtime'. */
420
+ serviceName?: string;
421
+ }
422
+ interface OtelExporter {
423
+ /** Export a span. */
424
+ exportSpan(span: OtelSpan): void;
425
+ /** Force flush pending spans. */
426
+ flush(): Promise<void>;
427
+ /** Shutdown cleanly. */
428
+ shutdown(): Promise<void>;
429
+ }
430
+ interface OtelSpan {
431
+ traceId: string;
432
+ spanId: string;
433
+ parentSpanId?: string;
434
+ name: string;
435
+ kind?: number;
436
+ startTimeUnixNano: string;
437
+ endTimeUnixNano: string;
438
+ attributes?: OtelAttribute[];
439
+ status?: {
440
+ code: number;
441
+ message?: string;
442
+ };
443
+ }
444
+ interface OtelAttribute {
445
+ key: string;
446
+ value: {
447
+ stringValue?: string;
448
+ intValue?: string;
449
+ doubleValue?: number;
450
+ boolValue?: boolean;
451
+ };
452
+ }
453
+ /**
454
+ * Create an exporter that APPENDS spans to a local OpenInference-JSONL file, one complete span per
455
+ * line, instead of posting them to a collector.
456
+ *
457
+ * Why this exists beside {@link createOtelExporter}: that one needs an OTLP endpoint, so a run on a
458
+ * laptop, in CI, or inside a sandbox with no collector emits nothing and its per-turn shape is
459
+ * simply lost. The journal records the TREE (who spawned whom, what settled, what it spent); it
460
+ * does not record what happened inside a turn. A run whose tree is readable but whose turns are not
461
+ * is exactly the state that made an observability gap invisible until someone went looking.
462
+ *
463
+ * The line shape is the one `@tangle-network/traces` reads (`spans.otlp.jsonl`) and is a standard
464
+ * OpenInference representation, so the same file feeds any OpenInference tool with no conversion:
465
+ * snake_case identity fields, ISO-8601 times, `parent_span_id` empty at the root, and attributes as
466
+ * a plain object rather than OTLP's key/value array.
467
+ *
468
+ * Appends synchronously per span so a killed process keeps every span it had already finished —
469
+ * matching the spawn journal's durability posture, since a trace that only survives a clean exit is
470
+ * useless for the runs you most want to look at.
471
+ */
472
+ declare function createOpenInferenceFileExporter(filePath: string): OtelExporter;
473
+ /**
474
+ * Create an OTEL exporter. Returns undefined when no endpoint is configured.
475
+ */
476
+ declare function createOtelExporter(config?: OtelExportConfig): OtelExporter | undefined;
477
+ /**
478
+ * Convert a LoopTraceEvent into an OtelSpan for export.
479
+ */
480
+ declare function loopEventToOtelSpan(event: {
481
+ kind: string;
482
+ runId: string;
483
+ timestamp: number;
484
+ payload: object;
485
+ }, traceId: string, parentSpanId?: string): OtelSpan;
486
+ interface RuntimeEventOtelOptions extends RuntimeTelemetryOptions {
487
+ /** Final customer redactor applied after the schema-aware runtime sanitizer. */
488
+ redact?: (value: unknown) => unknown;
489
+ }
490
+ /** Convert normalized runtime events into lossless, redacted child spans. */
491
+ declare function buildRuntimeEventOtelSpans(events: ReadonlyArray<RuntimeStreamEvent>, traceId: string, parentSpanId?: string, options?: RuntimeEventOtelOptions): OtelSpan[];
492
+ /**
493
+ * Sink-neutral node in a reconstructed loop span tree. The root node's
494
+ * `parentSpanId` is `undefined` — sinks decide how to parent it (the OTEL
495
+ * mapper attaches the inherited delegation span; the delegation journal
496
+ * leaves it as the tree root).
497
+ */
498
+ interface LoopSpanNode {
499
+ spanId: string;
500
+ parentSpanId?: string;
501
+ /** `'loop'` | `'loop.round'` | `'loop.iteration'`. */
502
+ name: string;
503
+ /** Topology level: loop root, plan round, or iteration branch. */
504
+ kind: 'loop' | 'round' | 'branch';
505
+ startMs: number;
506
+ endMs: number;
507
+ attrs: Record<string, string | number | boolean>;
508
+ /** True when the iteration carried an error — maps to OTEL status code 2. */
509
+ error: boolean;
510
+ }
511
+ /**
512
+ * Build a nested, real-duration OTLP span tree for ONE loop run from its full
513
+ * ordered `LoopTraceEvent` stream. Unlike `loopEventToOtelSpan` (one flat,
514
+ * zero-duration span per event), this reconstructs the topology hierarchy a
515
+ * GenAI trace viewer renders natively:
516
+ *
517
+ * loop (invoke_workflow)
518
+ * └─ loop.round[k] (invoke_workflow) ← tangle.loop.move.{kind,width,rationale}
519
+ * ├─ loop.iteration[i] (invoke_agent) ← gen_ai.agent.name + usage + verdict + placement
520
+ * └─ …
521
+ *
522
+ * Attributes follow the current GenAI semconv (`gen_ai.*`) where they apply and
523
+ * a namespaced `tangle.loop.*` / `tangle.cost.usd` extension for topology /
524
+ * verdict / placement / cost (not yet standardized). Pure: feed it a buffered
525
+ * per-runId event array (e.g. flushed on `loop.ended`) and export the result.
526
+ */
527
+ declare function buildLoopOtelSpans(events: ReadonlyArray<{
528
+ kind: string;
529
+ runId: string;
530
+ timestamp: number;
531
+ payload: object;
532
+ }>, traceId: string, rootParentSpanId?: string): OtelSpan[];
533
+ /**
534
+ * Sink-neutral core behind {@link buildLoopOtelSpans}: reconstruct the
535
+ * loop → round → branch span tree from one run's ordered `LoopTraceEvent`
536
+ * stream. Consumed by the OTEL mapper above and by the MCP delegation
537
+ * journal's compact trace tee — one topology reconstruction, two sinks.
538
+ * Tolerates partial streams (a run that never reached `loop.ended` closes
539
+ * at the last observed event's timestamp).
540
+ */
541
+ declare function buildLoopSpanNodes(events: ReadonlyArray<{
542
+ kind: string;
543
+ runId: string;
544
+ timestamp: number;
545
+ payload: object;
546
+ }>): LoopSpanNode[];
547
+ /**
548
+ * Convert a flat record into the OTLP attribute list. Non-finite numbers are DROPPED (an OTLP
549
+ * `doubleValue` of `NaN`/`Infinity` is not representable), integers ride as `intValue`. Exported so
550
+ * a producer that mints its own `OtelSpan` (the supervisor span recorder) builds attributes exactly
551
+ * the way every span in this file does, rather than re-deriving the encoding.
552
+ */
553
+ declare function toOtelAttributes(record: Record<string, string | number | boolean>): OtelAttribute[];
554
+ /** Mint a fresh 16-hex-character OTLP span id. Exported so a producer that must know a span's id
555
+ * BEFORE the span closes (a node opened at spawn and parented by its children) uses this one
556
+ * generator instead of a second copy of it. */
557
+ declare function generateSpanId(): string;
558
+ /** Wire version the eval-runs ingest enforces (X-Tangle-Wire-Version + body). */
559
+ declare const INTELLIGENCE_WIRE_VERSION = "2026-05-26.v1";
560
+ interface EvalRunGeneration {
561
+ /** 0-based ordinal of this generation within the run (required by ingest). */
562
+ index: number;
563
+ /** Identity of the proposed surface change (content-addressed hash). */
564
+ surfaceHash: string;
565
+ /** Arbitrary provenance for this generation (rationale, evidence, source). */
566
+ surface?: unknown;
567
+ /** Per-scenario results; empty until the generation is measured. */
568
+ cells?: unknown[];
569
+ /** Mean composite score (0 when unmeasured — pair with labels.measured). */
570
+ compositeMean: number;
571
+ costUsd: number;
572
+ durationMs: number;
573
+ }
574
+ interface EvalRunEvent {
575
+ runId: string;
576
+ runDir: string;
577
+ /** ISO timestamp. */
578
+ timestamp: string;
579
+ status: 'started' | 'baseline-complete' | 'generation-complete' | 'gate-decided' | 'finished' | 'errored';
580
+ labels?: Record<string, string>;
581
+ baseline?: EvalRunGeneration;
582
+ generations?: EvalRunGeneration[];
583
+ gateDecision?: 'ship' | 'hold' | 'need_more_work' | 'model_ceiling' | 'arch_ceiling';
584
+ holdoutLift?: number;
585
+ totalCostUsd: number;
586
+ totalDurationMs: number;
587
+ errorMessage?: string;
588
+ }
589
+ interface EvalRunsExportConfig {
590
+ /** Bearer key — tenant is resolved server-side from it. Reads TANGLE_API_KEY. */
591
+ apiKey?: string;
592
+ /** Intelligence base. Reads TANGLE_INTELLIGENCE_URL env, else prod. */
593
+ base?: string;
594
+ /** Idempotency-Key header (e.g. the runId) — safe retries + upsert. */
595
+ idempotencyKey?: string;
596
+ }
597
+ interface EvalRunsExportResult {
598
+ ok: boolean;
599
+ status: number;
600
+ accepted: number;
601
+ rejected: Array<{
602
+ index: number;
603
+ reason: string;
604
+ }>;
605
+ }
606
+ /**
607
+ * Ship self-improvement eval-run events to Tangle Intelligence. Unlike the
608
+ * best-effort span exporter, this RESOLVES with the ingest verdict (accepted /
609
+ * rejected per event) so a consumer's loop can assert its provenance landed.
610
+ * Throws only on a missing key or network failure.
611
+ */
612
+ declare function exportEvalRuns(events: EvalRunEvent[], config?: EvalRunsExportConfig): Promise<EvalRunsExportResult>;
613
+ //#endregion
614
+ //#region src/mcp/trace-propagation.d.ts
615
+ interface TraceContext {
616
+ /** Trace id inherited from the parent process, or a fresh one. */
617
+ traceId: string;
618
+ /** Parent span id from the delegation that launched this MCP server. */
619
+ parentSpanId?: string;
620
+ }
621
+ /**
622
+ * Read trace context from the process environment.
623
+ * Returns a context with inherited ids or a freshly generated root.
624
+ */
625
+ declare function readTraceContextFromEnv(): TraceContext;
626
+ /**
627
+ * Create a LoopTraceEmitter that:
628
+ * 1. Parents all spans under the inherited PARENT_SPAN_ID.
629
+ * 2. Exports spans to OTEL when OTEL_EXPORTER_OTLP_ENDPOINT is set.
630
+ *
631
+ * Returns both the emitter and the optional exporter handle for shutdown.
632
+ */
633
+ declare function createPropagatingTraceEmitter(ctx: TraceContext): {
634
+ emitter: LoopTraceEmitter;
635
+ exporter: OtelExporter | undefined;
636
+ context: TraceContext;
637
+ };
638
+ /**
639
+ * Build env vars to pass to a child MCP subprocess so it inherits the
640
+ * current trace context.
641
+ */
642
+ declare function traceContextToEnv(ctx: TraceContext): Record<string, string>;
643
+ //#endregion
644
+ //#region src/runtime/supervise/worker-trace.d.ts
645
+ /**
646
+ * Seam key the `Scope` seeds a {@link TraceContext} under on each child's `ExecutorContext.seams`.
647
+ * Single-sourced here so the scope and every backend agree on it without a circular import — the
648
+ * same arrangement `nestedScopeSeamKey` uses.
649
+ */
650
+ declare const workerTraceSeamKey = "worker-trace";
651
+ /**
652
+ * Resolve the trace context a worker spawned BY `spawningNodeId` should inherit. `undefined` means
653
+ * this run records no spans, so nothing is stamped. Supplied by
654
+ * `SupervisorSpanRecorder.workerTrace` and threaded to the scope as `SupervisorOpts.workerTrace`.
655
+ */
656
+ type WorkerTraceResolver = (spawningNodeId: string) => TraceContext | undefined;
657
+ /**
658
+ * What the two readers below need off an `ExecutorContext` — its seam bag, and nothing else.
659
+ * Structural (not an `ExecutorContext` import) so this module stays free of the keystone type
660
+ * surface, and exported because it is part of a public signature.
661
+ */
662
+ interface WorkerTraceSeamCarrier {
663
+ readonly seams: Readonly<Record<string, unknown>>;
664
+ }
665
+ /**
666
+ * Read the inherited trace context off an `ExecutorContext`, or `undefined` when the run records no
667
+ * spans. Fails CLOSED on a malformed seam value (returns `undefined`) rather than stamping a
668
+ * half-formed id that would produce an unjoinable orphan span downstream.
669
+ */
670
+ declare function readWorkerTraceContext(ctx: WorkerTraceSeamCarrier): TraceContext | undefined;
671
+ /**
672
+ * The `TRACE_ID` / `PARENT_SPAN_ID` pair to merge into a worker's environment — EMPTY when the run
673
+ * records no spans, which is what keeps the untraced path byte-identical. Merge it BELOW the
674
+ * caller's own seam env so a deliberately-set id wins (see the precedence note above).
675
+ */
676
+ declare function workerTraceEnv(ctx: WorkerTraceSeamCarrier): Record<string, string>;
677
+ //#endregion
306
678
  //#region src/runtime/supervise/types.d.ts
307
679
  /** Options for `Scope.wait`. `label` is the wait's identity within its parent scope — it is what
308
680
  * a resumed run matches to re-adopt a journaled, still-unfired wait, so it must be stable across
@@ -323,6 +695,12 @@ interface WaitOpts {
323
695
  interface Agent<Task, Out> {
324
696
  readonly name: string;
325
697
  act(task: Task, scope: Scope<Out>): Promise<Out>;
698
+ /**
699
+ * Optional manager inbox. A parent or attached `RootHandle` uses this to deliver the same raw
700
+ * down-message accepted by executor inboxes. Return `false` when the manager has no live receive
701
+ * path; returning `true` means the message was accepted for the current manager session.
702
+ */
703
+ deliver?(msg: unknown): void | boolean;
326
704
  }
327
705
  /**
328
706
  * The leaf runtime — ONE open interface, not a closed union. `execute` returns a
@@ -335,16 +713,17 @@ interface Agent<Task, Out> {
335
713
  * Built-in implementations (in `runtime.ts`, NOT variants here): router/inline (a direct
336
714
  * Router/HTTP inference call, no box), sandbox (COMPOSES `runAgentRounds` as a leaf, forwarding
337
715
  * PR #150's optional `lineage` passthrough — does NOT reinvent checkpoint/fork), cli
338
- * (Halo/RLM subprocess; `budgetExempt`, excluded from equal-k by construction). A user's
716
+ * (Halo/RLM subprocess; `budgetExempt`, refused by budgeted supervision). A user's
339
717
  * own agent (mastra/agno/raw HTTP/anything) is first-class by implementing this interface.
340
718
  */
341
719
  interface Executor<Out> {
342
720
  /** Stable runtime tag for traces + the equal-k exemption check. */
343
721
  readonly runtime: Runtime;
344
722
  /**
345
- * When true, this executor's spend is NOT metered against the conserved pool and its
346
- * iterations are excluded from the equal-k assertion (a `cli` subprocess without
347
- * token accounting). Fail-loud everywhere else: a metered executor MUST report usage.
723
+ * When true, this executor cannot report the usage a conserved pool would need (for example, a
724
+ * subscription CLI with no token receipt). `Executor` can still be used directly, but `Scope`
725
+ * refuses it before `execute` so unknown compute can never appear as measured zero in a
726
+ * supervised or equal-resource run. A metered executor MUST report usage.
348
727
  */
349
728
  readonly budgetExempt?: boolean;
350
729
  /**
@@ -357,10 +736,10 @@ interface Executor<Out> {
357
736
  * Optional inbox: receive an out-of-band message from the driver mid-run (the `send`/`steer_agent`
358
737
  * verb). A streaming executor drains pending messages between turns and folds them into the next
359
738
  * step (a steer / interrupt / resume). A one-shot executor that can't be steered mid-flight omits
360
- * this; `Scope.send` then returns `false` for it. Never throws — a malformed message is the
361
- * executor's to ignore.
739
+ * this; `Scope.send` then returns `false` for it. Never throws — an inbox that rejects a malformed
740
+ * message returns `false`, and that refusal propagates to the caller.
362
741
  */
363
- deliver?(msg: unknown): void;
742
+ deliver?(msg: unknown): void | boolean;
364
743
  /**
365
744
  * Optional LIVE progress: what this worker is doing RIGHT NOW, read synchronously and
366
745
  * cheaply while `execute` is still streaming. The scope already derives activity timing,
@@ -399,6 +778,15 @@ interface Executor<Out> {
399
778
  verdict?: DefaultVerdict;
400
779
  spent: Spend;
401
780
  };
781
+ /**
782
+ * Optional accounting split for recursive executors.
783
+ * `reported` is the child-work spend written on this node's settlement; `reservation` is the
784
+ * whole amount reconciled against this node's parent reservation.
785
+ * They differ when a driver owns a nested allocation: its child work and own inference consume
786
+ * that allocation together, while the journal keeps those two categories separate.
787
+ * Valid after `execute` resolves or throws; ordinary leaf executors omit it.
788
+ */
789
+ accounting?(): ExecutorAccounting | undefined;
402
790
  /**
403
791
  * A driver-executor's OWN-inference subtree total (rolled up from its nested tree's `metered`
404
792
  * events) — the parent scope journals it as a `metered` event for this node on settle, on BOTH
@@ -409,6 +797,24 @@ interface Executor<Out> {
409
797
  */
410
798
  metered?(): Spend | undefined;
411
799
  }
800
+ /** Why Runtime cannot provide structured tool-call evidence for one settled execution. */
801
+ type WorkerTraceUnavailableReason = 'execution-did-not-start' | 'executor-did-not-expose-trace-source' | 'trace-source-unavailable' | 'no-tool-spans-captured' | 'invalid-tool-spans' | 'trace-collection-failed' | 'trace-persistence-failed' | 'legacy-settlement-without-trace-evidence' | 'not-an-executor';
802
+ /** Durable proof of a worker's structured tool trace, or the exact reason it is unavailable. */
803
+ type WorkerTraceEvidence = {
804
+ readonly status: 'available';
805
+ /** Content-addressed pointer to a persisted `WorkerToolTraceArtifact`. */
806
+ readonly traceRef: string;
807
+ readonly spanCount: number;
808
+ } | {
809
+ readonly status: 'unavailable';
810
+ readonly reason: WorkerTraceUnavailableReason;
811
+ };
812
+ /** Split used by a recursive executor when journaled child work differs from the full amount
813
+ * reconciled against its parent reservation. */
814
+ interface ExecutorAccounting {
815
+ readonly reported: Spend;
816
+ readonly reservation: Spend;
817
+ }
412
818
  /** Terminal artifact of a one-shot `Executor.execute`. */
413
819
  interface ExecutorResult<Out> {
414
820
  outRef: string;
@@ -447,11 +853,12 @@ type UsageEvent = {
447
853
  * External executors can register additional runtime strings without widening this type. */
448
854
  type Runtime = 'router' | 'inline' | 'sandbox' | 'cli' | (string & {});
449
855
  /**
450
- * `AgentProfile` does NOT carry a `harness`/backend field `harness` lives on the
451
- * sandbox SDK's `BackendConfig`, not the portable profile. So an agent is mapped to its
452
- * executor through this MINIMAL wrapper, never by fabricating a field onto `AgentProfile`.
856
+ * `AgentProfile.harness` is a portable preference; this wrapper records the executor decision for
857
+ * one concrete run. A caller may honor the preference, override it for a comparison cell, or supply
858
+ * an executor directly, without changing the profile's behavioral identity.
453
859
  *
454
860
  * Resolution (in `runtime.ts`):
861
+ * - `executorFactory` present → BYO: build it after admission with the live context.
455
862
  * - `executor` present → BYO: use it verbatim (a user's own `Executor`).
456
863
  * - `harness === null` → router/inline: a direct Router call, no box.
457
864
  * - `harness` is a `BackendType` → sandbox: compose `runAgentRounds` against `profile` on that backend.
@@ -461,9 +868,121 @@ interface AgentSpec {
461
868
  readonly profile: AgentProfile$1;
462
869
  /** `null` selects router/inline; a `BackendType` selects the sandboxed harness. */
463
870
  readonly harness: BackendType | null;
871
+ /** Trusted candidate/campaign attribution supplied by the caller. Profile/task digests are
872
+ * computed by Scope from the exact values it executes and cannot be supplied here. */
873
+ readonly execution?: AgentExecutionRef;
874
+ /** Per-spawn factory carrying caller configuration. Constructed only after admission, with the
875
+ * real child signal and nested-scope context. */
876
+ readonly executorFactory?: ExecutorFactory<unknown>;
464
877
  /** Bring-your-own executor: when set, overrides harness-based resolution entirely. */
465
878
  readonly executor?: Executor<unknown>;
466
879
  }
880
+ /** Caller-owned identity beyond the exact profile/task bytes Scope can compute itself. */
881
+ interface AgentExecutionRef {
882
+ readonly candidateDigest?: Sha256Digest;
883
+ readonly correlation?: Readonly<Record<string, string>>;
884
+ }
885
+ /** Durable identity of one realized node. Missing digests mean the input was not canonical JSON. */
886
+ interface NodeExecutionIdentity extends AgentExecutionRef {
887
+ readonly profileDigest?: Sha256Digest;
888
+ readonly taskDigest?: Sha256Digest;
889
+ }
890
+ /** A named model carried into an execution, or an explicit reason the exact model is unknowable. */
891
+ type MaterializedModelIdentity = {
892
+ readonly status: 'known';
893
+ readonly id: string;
894
+ } | {
895
+ readonly status: 'unknown';
896
+ readonly reason: string;
897
+ };
898
+ /** External execution identity that operators can use to join this node to its backend. */
899
+ interface MaterializedExecutionIdentity {
900
+ /** Backend-native identity kind, for example `request`, `session`, `run`, `process`, or `tree`. */
901
+ readonly kind: string;
902
+ readonly id: string;
903
+ }
904
+ /**
905
+ * Data-only declaration from trusted executor code about the exact sealed plan `execute` uses.
906
+ * Scope snapshots this value and computes the durable receipt; callers never provide digests.
907
+ */
908
+ interface ExecutorMaterialization {
909
+ /** Complete profile after trusted runtime-owned attachments or backend overlays were applied. */
910
+ readonly effectiveProfile: AgentProfile$1;
911
+ /** Concrete backend or harness selected for this run. */
912
+ readonly backend: string;
913
+ /** Exact selected model, or an explicit unknown reason. */
914
+ readonly model: MaterializedModelIdentity;
915
+ /** Backend-native session/run/request/process identity. */
916
+ readonly execution: MaterializedExecutionIdentity;
917
+ /** Named implementation that turns the effective profile into executable backend inputs. */
918
+ readonly materializer: string;
919
+ /** Finite JSON describing the exact materialization plan. Persisted by digest only. */
920
+ readonly plan: unknown;
921
+ /** Trusted runtime-only attachments, such as the coordination MCP. Persisted by digest only. */
922
+ readonly platformAttachments?: unknown;
923
+ }
924
+ /** Volatile execution routing that is true for one attempt but is not profile identity. The full
925
+ * binding is hashed and discarded; only the safe structural descriptor is journaled. */
926
+ interface ExecutorExecutionBinding {
927
+ readonly attemptId: string;
928
+ readonly binding: unknown;
929
+ readonly descriptor: Readonly<Record<string, string | number | boolean | null>>;
930
+ }
931
+ /** Why exact materialization evidence is unavailable for a node. */
932
+ type UnknownMaterializationReason = 'executor-did-not-report' | 'invalid-executor-report' | 'root-agent-did-not-report';
933
+ /** What the kernel can prove about one node's actual execution plan. */
934
+ type ProfileMaterializationReceipt = {
935
+ readonly status: 'known';
936
+ readonly authoredProfileDigest: Sha256Digest;
937
+ readonly effectiveProfileDigest: Sha256Digest;
938
+ readonly materializationPlanDigest: Sha256Digest;
939
+ readonly platformAttachmentsDigest?: Sha256Digest;
940
+ readonly runtime: Runtime;
941
+ readonly backend: string;
942
+ readonly model: MaterializedModelIdentity;
943
+ readonly execution: MaterializedExecutionIdentity;
944
+ readonly materializer: string;
945
+ } | {
946
+ readonly status: 'unknown';
947
+ readonly authoredProfileDigest?: Sha256Digest;
948
+ readonly runtime: Runtime;
949
+ readonly reason: UnknownMaterializationReason;
950
+ };
951
+ /** One attempt's immutable link from a stable materialization plan to its actual transport. */
952
+ type ExecutionBindingReceipt = {
953
+ readonly status: 'known';
954
+ readonly attemptId: string;
955
+ readonly materializationReceiptDigest: Sha256Digest;
956
+ readonly bindingDigest: Sha256Digest;
957
+ readonly descriptor: Readonly<Record<string, string | number | boolean | null>>;
958
+ } | {
959
+ readonly status: 'unknown';
960
+ readonly attemptId: string;
961
+ readonly materializationReceiptDigest: Sha256Digest;
962
+ readonly reason: UnknownMaterializationReason;
963
+ };
964
+ /** Trusted root composition evidence. Generic `Agent.act` roots omit this and remain unknown. */
965
+ type RootMaterialization = {
966
+ readonly runtime: Runtime;
967
+ readonly declaration: ExecutorMaterialization;
968
+ readonly binding: Omit<ExecutorExecutionBinding, 'attemptId'>;
969
+ } | {
970
+ /** The runtime-owned external adapter will publish the exact declaration after its dynamic
971
+ * platform attachment (for example a coordination URL) exists and before paid work starts. */
972
+ readonly runtime: Runtime;
973
+ readonly declaration: 'deferred';
974
+ /** Exact admitted profile used to validate the stable effective identity at publication. */
975
+ readonly authoredProfile: AgentProfile$1;
976
+ };
977
+ /** Kernel-owned context for the concrete supervised node a factory is constructing. */
978
+ interface ExecutorNodeContext {
979
+ readonly rootId: NodeId;
980
+ readonly parentId: NodeId;
981
+ readonly nodeId: NodeId;
982
+ /** Kernel-minted identity for this concrete execution attempt. */
983
+ readonly attemptId: string;
984
+ readonly identity?: NodeExecutionIdentity;
985
+ }
467
986
  /**
468
987
  * Builds a fresh `Executor` for one spawn from the resolved spec. Per-spawn (not
469
988
  * shared) so each child owns its own box/abort/teardown lifecycle. A BYO factory lets a
@@ -475,6 +994,8 @@ type ExecutorFactory<Out> = (spec: AgentSpec, ctx: ExecutorContext) => Executor<
475
994
  * the factory reaching into module globals. */
476
995
  interface ExecutorContext {
477
996
  readonly signal: AbortSignal;
997
+ /** Present when Scope constructs the executor for a supervised node. */
998
+ readonly node?: ExecutorNodeContext;
478
999
  /** Opaque seams the registry threads through; a built-in narrows what it needs. */
479
1000
  readonly seams: Readonly<Record<string, unknown>>;
480
1001
  }
@@ -488,8 +1009,8 @@ interface ExecutorRegistry {
488
1009
  /** Register a factory for a named runtime. Throws on a duplicate name (fail loud). */
489
1010
  register<Out>(runtime: Runtime, factory: ExecutorFactory<Out>): void;
490
1011
  /**
491
- * Resolve a spec to a factory. Precedence: a BYO `spec.executor` → a trivial factory
492
- * returning it; else `harness === null` → the `'router'` factory; else a registered
1012
+ * Resolve a spec to a factory. Precedence: a BYO `spec.executorFactory` → `spec.executor`
1013
+ * `harness === null` → the `'router'` factory; else a registered
493
1014
  * factory for the harness-derived runtime. Returns a typed outcome — the caller
494
1015
  * inspects `succeeded` before `value` (no silent fallback).
495
1016
  */
@@ -538,6 +1059,9 @@ type NodeId = string;
538
1059
  interface SpawnOpts {
539
1060
  readonly budget: Budget;
540
1061
  readonly label: string;
1062
+ /** Manager-scoped semantic assignment identity. Unlike `key`, this names every spawn, including
1063
+ * unkeyed siblings, so product traces can join authorization, node, and backend execution. */
1064
+ readonly assignmentId?: string;
541
1065
  readonly restart?: Restart;
542
1066
  /** Teardown grace handed to the executor when this node is reaped. */
543
1067
  readonly shutdown?: number | 'brutalKill' | 'infinity';
@@ -554,13 +1078,17 @@ interface SpawnOpts {
554
1078
  readonly key?: string;
555
1079
  }
556
1080
  /** Fail-closed spawn rejections: an exhausted pool, a dollar request against a root that budgets
557
- * no dollars, an exceeded recursion ceiling, or a `key` that is still LIVE in this scope (the
558
- * same assignment may not run twice concurrently).
1081
+ * no dollars, an exceeded recursion ceiling, a full tree-wide worker allocation, or a `key` that
1082
+ * is still LIVE in this scope (the same assignment may not run twice concurrently).
559
1083
  *
560
1084
  * `usd-unbudgeted` is separate from `budget-exhausted` because the two call for opposite
561
1085
  * responses: an exhausted pool may admit a smaller request, while an unbudgeted dollar channel
562
- * refuses every amount until the ROOT budget names a `maxUsd`. */
563
- type SpawnRejection = 'budget-exhausted' | 'usd-unbudgeted' | 'depth-exceeded' | 'duplicate-key';
1086
+ * refuses every amount until the ROOT budget names a `maxUsd`.
1087
+ *
1088
+ * `below-runtime-floor` is separate for the same reason and points the opposite way from
1089
+ * `budget-exhausted`: the request is under what that harness spends before it reads its task, so
1090
+ * it is unsatisfiable at that SIZE and the fix is to RAISE it, never to retry smaller. */
1091
+ type SpawnRejection = 'budget-exhausted' | 'usd-unbudgeted' | 'below-runtime-floor' | 'depth-exceeded' | 'duplicate-key' | 'invalid-identity' | 'key-conflict' | 'max-live-workers' | 'scope-aborted';
564
1092
  /**
565
1093
  * What a KEYED spawn resolved to when the key had a prior attempt. Absent on a fresh key (and on
566
1094
  * every unkeyed spawn). `'completed'` is the exactly-once path: NOTHING was spawned — the handle
@@ -568,8 +1096,10 @@ type SpawnRejection = 'budget-exhausted' | 'usd-unbudgeted' | 'depth-exceeded' |
568
1096
  * `'lost'` DID spawn fresh: the prior attempt settled `down` (retried) or was journaled as
569
1097
  * started but never settled — the process died with it in flight and the built-in executors
570
1098
  * cannot re-attach to a dead process's work, so the result is explicitly in doubt (lost), never
571
- * silently duplicated. An executor that CAN re-attach to a still-running external execution (a
572
- * live sandbox box) extends this union with an adoption state; none of the built-ins can today.
1099
+ * silently duplicated. On restart, an in-doubt attempt's full declared reservation is charged and
1100
+ * its telemetry remains unknown; a fresh retry is admitted only from safely remaining capacity.
1101
+ * An executor that CAN re-attach to a still-running external execution extends this union with an
1102
+ * adoption state; none of the built-ins can today.
573
1103
  */
574
1104
  type SpawnPrior<Out = unknown> = {
575
1105
  readonly state: 'completed';
@@ -593,6 +1123,14 @@ interface Handle<Out> {
593
1123
  readonly id: NodeId;
594
1124
  readonly label: string;
595
1125
  readonly status: NodeStatus;
1126
+ /** Manager-scoped assignment identity supplied at admission. */
1127
+ readonly assignmentId?: string;
1128
+ /** Durable identity of the authorized profile/task/candidate represented by this handle. */
1129
+ readonly identity?: NodeExecutionIdentity;
1130
+ /** Stable execution plan once Runtime has committed it. */
1131
+ readonly materialization?: ProfileMaterializationReceipt;
1132
+ /** Immutable per-attempt backend bindings committed so far, oldest first. */
1133
+ readonly executionBindings?: ReadonlyArray<ExecutionBindingReceipt>;
596
1134
  abort(reason?: string): void;
597
1135
  /** Phantom: binds the handle to the child's output type so `spawn<C>` returns a
598
1136
  * `Handle<C>` distinct from a `Handle<other>`. Type-only — never present at runtime. */
@@ -610,6 +1148,10 @@ type Settled<Out> = {
610
1148
  outRef: string;
611
1149
  verdict?: DefaultVerdict;
612
1150
  spent: Spend;
1151
+ /** Structured tool evidence captured before this settlement was journaled. */
1152
+ trace: WorkerTraceEvidence;
1153
+ /** Epoch ms parsed from the durable settlement record when available. */
1154
+ settledAt?: number;
613
1155
  seq: number;
614
1156
  } | {
615
1157
  kind: 'down';
@@ -618,6 +1160,10 @@ type Settled<Out> = {
618
1160
  /** True = infrastructure failure (excluded from merge `n` / equal-k), not a bad result. */
619
1161
  infra: boolean;
620
1162
  restartCount: number;
1163
+ /** Partial structured tool evidence captured before this failure was journaled. */
1164
+ trace: WorkerTraceEvidence;
1165
+ /** Epoch ms parsed from the durable settlement/cancellation record when available. */
1166
+ settledAt?: number;
621
1167
  seq: number;
622
1168
  };
623
1169
  /**
@@ -628,13 +1174,17 @@ type Settled<Out> = {
628
1174
  */
629
1175
  interface Scope<Out> {
630
1176
  /**
631
- * Spawn a child. Reserves `opts.budget` from the conserved pool atomically; refunds the
632
- * unspent remainder on settle. Returns a typed outcome fail-closed on an exhausted
633
- * pool, an exceeded depth ceiling, or a still-live duplicate `key` (the caller inspects
634
- * `ok` before `handle`). A KEYED spawn whose key already settled `done` spends nothing:
635
- * it returns the committed result on `prior` instead of re-running (see `SpawnOpts.key`).
1177
+ * Spawn a child. For a fresh key or an unkeyed spawn, tree-wide worker admission happens before a
1178
+ * lazy factory is called, so a full worker allocation creates no worker, executor, or reservation.
1179
+ * Reserves `opts.budget` from the conserved pool atomically; refunds the unspent remainder on
1180
+ * settle. Returns a typed outcome fail-closed on an exhausted pool, an exceeded depth ceiling, a
1181
+ * full worker allocation, or a still-live duplicate `key` (the caller inspects `ok` before
1182
+ * `handle`). A KEYED spawn whose key already settled `done` invokes the factory only far enough to
1183
+ * prepare and authorize the exact profile/task identity, then compares that identity with the
1184
+ * journal. On a match it spends nothing, constructs no executor, reserves no budget, and runs no
1185
+ * work: it returns the committed result on `prior` (see `SpawnOpts.key`).
636
1186
  */
637
- spawn<C extends Out>(agent: Agent<unknown, C>, task: unknown, opts: SpawnOpts): {
1187
+ spawn<C extends Out>(agent: Agent<unknown, C> | (() => Agent<unknown, C>), task: unknown, opts: SpawnOpts): {
638
1188
  ok: true;
639
1189
  handle: Handle<C>;
640
1190
  prior?: SpawnPrior<C>;
@@ -736,13 +1286,21 @@ interface Scope<Out> {
736
1286
  /** Conserved-pool readouts (post-reservation). */
737
1287
  readonly budget: Readonly<{
738
1288
  tokensLeft: number;
1289
+ /** `false` once a turn settled without reporting its tokens: `tokensLeft` is then a ceiling,
1290
+ * not a measurement. */
1291
+ tokensKnown: boolean;
739
1292
  usdLeft: number;
740
1293
  usdCapped: boolean;
1294
+ usdKnown: boolean;
1295
+ iterationsLeft: number;
741
1296
  deadlineMs: number;
742
1297
  reservedTokens: number;
743
- /** Present and `false` once a turn settled without reporting its tokens: `tokensLeft` is then
744
- * a ceiling, not a measurement. Absent means every settled turn reported. */
745
- tokensKnown?: boolean;
1298
+ }>;
1299
+ /** One tree-wide view of simultaneous spawned work. Every nested scope reads the same counter;
1300
+ * the root agent itself is not a spawned worker. `freeSlots` is `null` when no limit is set. */
1301
+ readonly workerCapacity: Readonly<{
1302
+ live: number;
1303
+ freeSlots: number | null;
746
1304
  }>;
747
1305
  }
748
1306
  /**
@@ -784,6 +1342,8 @@ interface ResumedWork<Out> {
784
1342
  interface ResumedKeyState<Out = unknown> {
785
1343
  readonly id: NodeId;
786
1344
  readonly label: string;
1345
+ /** Identity recorded when this key was first admitted. Every reuse must match it exactly. */
1346
+ readonly identity?: NodeExecutionIdentity;
787
1347
  readonly state: 'completed' | 'down' | 'in-doubt';
788
1348
  /** The rehydrated settlement; absent exactly when `state` is `'in-doubt'`. */
789
1349
  readonly settled?: Settled<Out>;
@@ -795,10 +1355,23 @@ interface NodeSnapshot {
795
1355
  readonly status: NodeStatus;
796
1356
  readonly runtime: Runtime;
797
1357
  readonly budget: Budget;
1358
+ /** Exact nested journal tree owned by this node, when Runtime attested recursive ownership. */
1359
+ readonly ownedTreeRoot?: NodeId;
1360
+ /** Manager-scoped assignment identity, including deterministic ids for unkeyed siblings. */
1361
+ readonly assignmentId?: string;
1362
+ readonly identity?: NodeExecutionIdentity;
1363
+ /** Kernel-owned execution evidence. `unknown` is distinct from a known zero/empty plan. */
1364
+ readonly materialization?: ProfileMaterializationReceipt;
1365
+ /** Immutable attempt bindings, oldest first. A retried/resumed node may have more than one. */
1366
+ readonly executionBindings?: ReadonlyArray<ExecutionBindingReceipt>;
1367
+ /** Epoch ms of the terminal journal record; absent while live or when legacy evidence lacks it. */
1368
+ readonly settledAt?: number;
798
1369
  /** Conserved spend so far for this node. */
799
1370
  readonly spent: Spend;
800
1371
  /** `outRef` once the node is `done` (the replay/result pointer). */
801
1372
  readonly outRef?: string;
1373
+ /** Present on terminal executor nodes; legacy records carry an explicit unavailable reason. */
1374
+ readonly trace?: WorkerTraceEvidence;
802
1375
  }
803
1376
  /** The live tree — what `scope.view` / `RootHandle.view()` materialize for a viewer. */
804
1377
  interface TreeView {
@@ -821,8 +1394,31 @@ type SpawnEvent = {
821
1394
  /** The semantic spawn key (`SpawnOpts.key`), when the spawn carried one — what a resumed
822
1395
  * run matches to resolve the same assignment to its committed result. */
823
1396
  key?: string;
1397
+ /** Manager-scoped assignment identity used to join unkeyed and keyed work alike. */
1398
+ assignmentId?: string;
824
1399
  budget: Budget;
825
1400
  runtime: Runtime;
1401
+ /** Exact nested journal tree this node owns. Runtime writes this only after privately
1402
+ * attesting the executor as a recursive scope owner. Its absence means no tree is followed,
1403
+ * including records written before this field existed and caller leaves named `driver`. */
1404
+ ownedTreeRoot?: NodeId;
1405
+ /** Exact profile/task digests plus trusted candidate/campaign attribution when available. */
1406
+ identity?: NodeExecutionIdentity;
1407
+ seq: number;
1408
+ at: string;
1409
+ } | {
1410
+ /** Volatile transport/session binding for exactly one attempt. The full binding is retained
1411
+ * only by digest; descriptor fields are safe structural labels, never credential-bearing URLs. */
1412
+ kind: 'execution-bound';
1413
+ id: NodeId;
1414
+ binding: ExecutionBindingReceipt;
1415
+ seq: number;
1416
+ at: string;
1417
+ } | {
1418
+ /** Trusted runtime transformation from the authorized profile to actual wire bytes. */
1419
+ kind: 'materialized';
1420
+ id: NodeId;
1421
+ receipt: ProfileMaterializationReceipt;
826
1422
  seq: number;
827
1423
  at: string;
828
1424
  } | {
@@ -834,6 +1430,11 @@ type SpawnEvent = {
834
1430
  verdict?: DefaultVerdict;
835
1431
  spent: Spend;
836
1432
  infra?: boolean;
1433
+ /** Exact child failure. Present on every new `status: 'down'` record; optional only so
1434
+ * journals written before this field existed remain replayable. */
1435
+ reason?: string;
1436
+ /** Structured tool evidence. Optional only for journals written before trace capture. */
1437
+ trace?: WorkerTraceEvidence;
837
1438
  seq: number;
838
1439
  at: string;
839
1440
  } | {
@@ -909,6 +1510,11 @@ interface Supervisor<Task, Out> {
909
1510
  interface SupervisorOpts {
910
1511
  /** The root conserved-pool ceiling (tokens + usd + iterations + deadline). */
911
1512
  readonly budget: Budget;
1513
+ /** Exact root profile/task identity supplied by the one-call composition surface. */
1514
+ readonly rootIdentity?: NodeExecutionIdentity;
1515
+ /** Trusted composition evidence for a root whose `act` drives an external backend. A generic
1516
+ * root omits it and is durably marked unknown; model-facing Scope never receives this writer. */
1517
+ readonly rootMaterialization?: RootMaterialization;
912
1518
  /** Trace-correlation root + the journal/blob root key. */
913
1519
  readonly runId: NodeId;
914
1520
  /** Event source — defaults to the in-memory journal in the impl; pass JSONL/FS for durability. */
@@ -923,6 +1529,9 @@ interface SupervisorOpts {
923
1529
  readonly probes?: WaitProbeRegistry;
924
1530
  /** Runtime recursion-depth ceiling (paired with the conserved pool per R3). */
925
1531
  readonly maxDepth?: number;
1532
+ /** Hard tree-wide cap on simultaneously executing spawned workers. The root is excluded; every
1533
+ * nested driver and leaf shares this one allocation. Omit/`<= 0` leaves worker count uncapped. */
1534
+ readonly maxLiveWorkers?: number;
926
1535
  /**
927
1536
  * OTP intensity breaker: more than `maxRestarts` child restarts within `withinMs`
928
1537
  * trips the supervisor to `no-winner` rather than restarting forever.
@@ -945,6 +1554,15 @@ interface SupervisorOpts {
945
1554
  /** Lifecycle stream sink, threaded into the root `Scope` so every `spawn`/settle emits on the
946
1555
  * same `agent.spawn`/`agent.child` stream `runAgentRounds` feeds — one observable recursive tree. */
947
1556
  readonly hooks?: RuntimeHooks;
1557
+ /**
1558
+ * Trace context to hand DOWN to each spawned worker, so a worker in another process or on another
1559
+ * machine emits spans that join THIS run's trace instead of opening its own root. Supply
1560
+ * `SupervisorSpanRecorder.workerTrace`; the `Scope` seeds the resolved context onto every child's
1561
+ * `ExecutorContext` and the backends with an environment channel stamp it as
1562
+ * `TRACE_ID` / `PARENT_SPAN_ID` (see `worker-trace.ts` for the precedence rule and for which
1563
+ * backends propagate). Omit and no worker environment is touched at all.
1564
+ */
1565
+ readonly workerTrace?: WorkerTraceResolver;
948
1566
  }
949
1567
  /**
950
1568
  * A driver's `act()` rejection, normalized to a serializable triple so it survives the typed
@@ -1012,16 +1630,23 @@ type SupervisedResult<Out> = {
1012
1630
  * recoverable by the caller. A non-`Error` rejection is normalized, never dropped. */
1013
1631
  error: NoWinnerError;
1014
1632
  };
1015
- /** Live root handle — the substrate a chat/pi-viz client attaches to (Q2). `signal`
1016
- * delivers an out-of-band message to the running root; `view()` materializes the tree. */
1633
+ /** Live root handle — a chat/pi-viz client uses it to inspect and control one root run. */
1017
1634
  interface RootHandle<Out> {
1018
1635
  view(): TreeView;
1636
+ /** Optional for structural compatibility with existing view/signal/abort wrappers. Handles
1637
+ * minted by `createRootHandle` implement the required form in `SteerableRootHandle`. */
1638
+ deliver?(msg: unknown): boolean;
1019
1639
  signal(msg: RootSignal): void;
1020
1640
  abort(reason?: string): void;
1021
1641
  /** Phantom: binds the handle to the supervised run's output type. Type-only — never
1022
1642
  * present at runtime; lets `attach(h: RootHandle<Out>)` stay output-typed. */
1023
1643
  readonly __out?: Out;
1024
1644
  }
1645
+ /** A Runtime-minted root handle that can deliver raw steering or answers to a live manager inbox.
1646
+ * Delivery returns `false` when the manager has no receive path; detached calls fail loud. */
1647
+ interface SteerableRootHandle<Out> extends RootHandle<Out> {
1648
+ deliver(msg: unknown): boolean;
1649
+ }
1025
1650
  /** Out-of-band message to a running root. Open by intent — a client extends it. */
1026
1651
  type RootSignal = {
1027
1652
  kind: 'pause';
@@ -1091,6 +1716,8 @@ declare function resolveAgentEnvironmentProvider(provider: AgentEnvironmentProvi
1091
1716
  interface ProviderAsSandboxClientOptions {
1092
1717
  defaults?: Partial<CreateAgentEnvironmentInput>;
1093
1718
  requireTerminalEvent?: boolean;
1719
+ /** Require declared live continuation plus concrete session controls. */
1720
+ requireSession?: boolean;
1094
1721
  mapCreateOptions?: (options: CreateSandboxOptions | undefined) => Partial<CreateAgentEnvironmentInput>;
1095
1722
  }
1096
1723
  /** Adapt a neutral environment provider to the `SandboxClient` interface used by existing loop paths.
@@ -1123,5 +1750,5 @@ interface ProviderExecutorOptions {
1123
1750
  * @experimental */
1124
1751
  declare function providerAsExecutor(provider: AgentEnvironmentProvider, options?: ProviderExecutorOptions): ExecutorFactory<unknown>;
1125
1752
  //#endregion
1126
- export { ResumedWork as $, providerAsSandboxClient as A, SessionMessageLike as At, Executor as B, ExecutorProgress as Bt, ProviderAsSandboxClientOptions as C, WaitSpec as Ct, WorkspaceRequest as D, timerAt as Dt, SandboxClientProviderOptions as E, pollFor as Et, createTangleSandboxExactProcessProvider as F, decodeToolPart as Ft, Handle as G, ExecutorFactory as H, WorkerProgress as Ht, Agent as I, sandboxSessionTraceSource as It, NodeSnapshot as J, NoWinnerError as K, AgentSpec as L, ActivityLog as Lt, sandboxClientAsProvider as M, ToolStepInput as Mt, CreateTangleSandboxExactProcessProviderOptions as N, TraceSource as Nt, createAgentEnvironmentProviderRegistry as O, validateWaitSpec as Ot, SandboxControlClient as P, createPushTraceSource as Pt, ResumedKeyState as Q, Budget as R, ActivityNote as Rt, PlacementInfo as S, WaitRejection as St, ResourceRequest as T, isWaitOutcome as Tt, ExecutorRegistry as U, createActivityLog as Ut, ExecutorContext as V, ScopeProgressInput as Vt, ExecutorResult as W, readWorkerProgress as Wt, Restart as X, NodeStatus as Y, ResultBlobStore as Z, CheckpointRequest as _, WidenGate as _t, AgentEnvironmentProviderRef as a, SpawnEvent as at, ExecResult as b, WaitProbe as bt, AgentEnvironmentStatus as c, SpawnPrior as ct, AgentSession as d, SupervisedResult as dt, RootHandle as et, AgentSessionRef as f, Supervisor as ft, CheckpointRef as g, WaitOpts as gt, AgentTurnResult as h, UsageEvent as ht, AgentEnvironmentProvider$1 as i, Settled as it, resolveAgentEnvironmentProvider as j, SessionTraceBox as jt, providerAsExecutor as k, waitUntil as kt, AgentEnvironmentSummary as l, SpawnRejection as lt, AgentTurnInput$1 as m, TreeView as mt, AgentEnvironmentCapabilities$1 as n, Runtime as nt, AgentEnvironmentProviderRegistry as o, SpawnJournal as ot, AgentSessionStatus as p, SupervisorOpts as pt, NodeId as q, AgentEnvironmentEvent as r, Scope as rt, AgentEnvironmentQuery as s, SpawnOpts as st, AgentEnvironment as t, RootSignal as tt, AgentProfileRef$1 as u, Spend as ut, CreateAgentEnvironmentInput$1 as v, PendingWait as vt, ProviderExecutorOptions as w, createWaitProbes as wt, ForkRequest as x, WaitProbeRegistry as xt, ExecRequest as y, WaitOutcome as yt, DefaultVerdict as z, DEFAULT_STALL_AFTER_MS as zt };
1127
- //# sourceMappingURL=environment-provider-Cygthiy3.d.ts.map
1753
+ export { MaterializedModelIdentity as $, buildLoopOtelSpans as $t, providerAsSandboxClient as A, validateWaitSpec as An, WidenGate as At, DefaultVerdict as B, ActivityNote as Bn, readTraceContextFromEnv as Bt, ProviderAsSandboxClientOptions as C, WaitProbeRegistry as Cn, SupervisedResult as Ct, WorkspaceRequest as D, isWaitOutcome as Dn, UnknownMaterializationReason as Dt, SandboxClientProviderOptions as E, createWaitProbes as En, TreeView as Et, createTangleSandboxExactProcessProvider as F, TraceSource as Fn, readWorkerTraceContext as Ft, ExecutorExecutionBinding as G, createActivityLog as Gn, EvalRunsExportResult as Gt, Executor as H, ExecutorProgress as Hn, EvalRunEvent as Ht, Agent as I, createPushTraceSource as In, workerTraceEnv as It, ExecutorNodeContext as J, OtelAttribute as Jt, ExecutorFactory as K, readWorkerProgress as Kn, INTELLIGENCE_WIRE_VERSION as Kt, AgentExecutionRef as L, decodeToolPart as Ln, workerTraceSeamKey as Lt, sandboxClientAsProvider as M, SessionMessageLike as Mn, WorkerTraceUnavailableReason as Mt, CreateTangleSandboxExactProcessProviderOptions as N, SessionTraceBox as Nn, WorkerTraceResolver as Nt, createAgentEnvironmentProviderRegistry as O, pollFor as On, UsageEvent as Ot, SandboxControlClient as P, ToolStepInput as Pn, WorkerTraceSeamCarrier as Pt, MaterializedExecutionIdentity as Q, RuntimeEventOtelOptions as Qt, AgentSpec as R, sandboxSessionTraceSource as Rn, TraceContext as Rt, PlacementInfo as S, WaitProbe as Sn, SteerableRootHandle as St, ResourceRequest as T, WaitSpec as Tn, SupervisorOpts as Tt, ExecutorAccounting as U, ScopeProgressInput as Un, EvalRunGeneration as Ut, ExecutionBindingReceipt as V, DEFAULT_STALL_AFTER_MS as Vn, traceContextToEnv as Vt, ExecutorContext as W, WorkerProgress as Wn, EvalRunsExportConfig as Wt, ExecutorResult as X, OtelExporter as Xt, ExecutorRegistry as Y, OtelExportConfig as Yt, Handle as Z, OtelSpan as Zt, CheckpointRequest as _, sanitizeAgentRuntimeEvent as _n, SpawnJournal as _t, AgentEnvironmentProviderRef as a, generateSpanId as an, ProfileMaterializationReceipt as at, ExecResult as b, PendingWait as bn, SpawnRejection as bt, AgentEnvironmentStatus as c, RuntimeEventCollector as cn, ResumedKeyState as ct, AgentSession as d, RuntimeStreamEventSummary as dn, RootMaterialization as dt, buildLoopSpanNodes as en, NoWinnerError as et, AgentSessionRef as f, RuntimeTelemetryOptions as fn, RootSignal as ft, CheckpointRef as g, createRuntimeStreamEventCollector as gn, SpawnEvent as gt, AgentTurnResult as h, createRuntimeEventCollector as hn, Settled as ht, AgentEnvironmentProvider$1 as i, exportEvalRuns as in, NodeStatus as it, resolveAgentEnvironmentProvider as j, waitUntil as jn, WorkerTraceEvidence as jt, providerAsExecutor as k, timerAt as kn, WaitOpts as kt, AgentEnvironmentSummary as l, RuntimeStreamEventCollector as ln, ResumedWork as lt, AgentTurnInput$1 as m, SanitizedKnowledgeRequirement as mn, Scope as mt, AgentEnvironmentCapabilities$1 as n, createOpenInferenceFileExporter as nn, NodeId as nt, AgentEnvironmentProviderRegistry as o, loopEventToOtelSpan as on, Restart as ot, AgentSessionStatus as p, SanitizedKnowledgeReadinessReport as pn, Runtime as pt, ExecutorMaterialization as q, LoopSpanNode as qt, AgentEnvironmentEvent as r, createOtelExporter as rn, NodeSnapshot as rt, AgentEnvironmentQuery as s, toOtelAttributes as sn, ResultBlobStore as st, AgentEnvironment as t, buildRuntimeEventOtelSpans as tn, NodeExecutionIdentity as tt, AgentProfileRef$1 as u, RuntimeStreamEventSink as un, RootHandle as ut, CreateAgentEnvironmentInput$1 as v, sanitizeKnowledgeReadinessReport as vn, SpawnOpts as vt, ProviderExecutorOptions as w, WaitRejection as wn, Supervisor as wt, ForkRequest as x, WaitOutcome as xn, Spend as xt, ExecRequest as y, sanitizeRuntimeStreamEvent as yn, SpawnPrior as yt, Budget as z, ActivityLog as zn, createPropagatingTraceEmitter as zt };
1754
+ //# sourceMappingURL=environment-provider-CTZjdIUg.d.ts.map