@tangle-network/agent-runtime 3.0.39 → 3.0.40

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 (54) hide show
  1. package/dist/{activation-BbQGq4Py.js → activation-n22lMRhH.js} +2 -2
  2. package/dist/{activation-BbQGq4Py.js.map → activation-n22lMRhH.js.map} +1 -1
  3. package/dist/agent.js +4 -4
  4. package/dist/{coordination-manager-B3mF1nMA.js → coordination-manager-C_ohXf63.js} +6 -6
  5. package/dist/{coordination-manager-B3mF1nMA.js.map → coordination-manager-C_ohXf63.js.map} +1 -1
  6. package/dist/{coordination-map-routing-BllzcZov.js → coordination-map-routing-2_hUlTnz.js} +2 -2
  7. package/dist/{coordination-map-routing-BllzcZov.js.map → coordination-map-routing-2_hUlTnz.js.map} +1 -1
  8. package/dist/{delegate-DR2gtTHa.js → delegate-BYLjG7Ev.js} +2 -2
  9. package/dist/{delegate-DR2gtTHa.js.map → delegate-BYLjG7Ev.js.map} +1 -1
  10. package/dist/durable.js +7 -7
  11. package/dist/{graph-BBQ6L1Mc.js → graph-T1-PBhLx.js} +6 -6
  12. package/dist/{graph-BBQ6L1Mc.js.map → graph-T1-PBhLx.js.map} +1 -1
  13. package/dist/{graph-registry-D6y6zffC.js → graph-registry-BoaUV5g8.js} +3 -3
  14. package/dist/{graph-registry-D6y6zffC.js.map → graph-registry-BoaUV5g8.js.map} +1 -1
  15. package/dist/{graph-registry-rV9mwxQO.js → graph-registry-EGeo_moB.js} +1 -1
  16. package/dist/{improve-fCd7c9dZ.js → improve-BqMfcxh1.js} +7 -7
  17. package/dist/{improve-fCd7c9dZ.js.map → improve-BqMfcxh1.js.map} +1 -1
  18. package/dist/index.js +9 -9
  19. package/dist/intelligence.js +5 -5
  20. package/dist/{jsonl-file-BBP9Dz9w.js → jsonl-file-CbxMVnUj.js} +16 -18
  21. package/dist/jsonl-file-CbxMVnUj.js.map +1 -0
  22. package/dist/kernel.js +12 -12
  23. package/dist/{loop-runner-DshmaiYp.js → loop-runner-CGa71-66.js} +2 -2
  24. package/dist/{loop-runner-DshmaiYp.js.map → loop-runner-CGa71-66.js.map} +1 -1
  25. package/dist/loop-runner-bin.js +1 -1
  26. package/dist/mcp/bin.js +3 -3
  27. package/dist/mcp/index.js +5 -5
  28. package/dist/{provision-supervisor-s7XtrK3h.js → provision-supervisor-Dl6oYQDN.js} +5 -5
  29. package/dist/{provision-supervisor-s7XtrK3h.js.map → provision-supervisor-Dl6oYQDN.js.map} +1 -1
  30. package/dist/{run-cancellation-CRPdLJVP.js → run-cancellation-BzmmqlM8.js} +3 -3
  31. package/dist/{run-cancellation-CRPdLJVP.js.map → run-cancellation-BzmmqlM8.js.map} +1 -1
  32. package/dist/{runtime-BufkoSjF.js → runtime-DoUb4SOs.js} +15 -15
  33. package/dist/{runtime-BufkoSjF.js.map → runtime-DoUb4SOs.js.map} +1 -1
  34. package/dist/{scope-CpULJrAr.js → scope-BGWRFiYt.js} +2 -2
  35. package/dist/{scope-CpULJrAr.js.map → scope-BGWRFiYt.js.map} +1 -1
  36. package/dist/{search-executor-qcgra0sA.js → search-executor-DPBewC3S.js} +3 -3
  37. package/dist/{search-executor-qcgra0sA.js.map → search-executor-DPBewC3S.js.map} +1 -1
  38. package/dist/{server-CekOTeag.js → server-M9dG-WG9.js} +3 -3
  39. package/dist/{server-CekOTeag.js.map → server-M9dG-WG9.js.map} +1 -1
  40. package/dist/{structural-rollout-CSLfWHEN.js → structural-rollout-BylGQ_wK.js} +3 -3
  41. package/dist/{structural-rollout-CSLfWHEN.js.map → structural-rollout-BylGQ_wK.js.map} +1 -1
  42. package/dist/{supervise-Dszn1xVB.js → supervise-BfT708zt.js} +8 -8
  43. package/dist/{supervise-Dszn1xVB.js.map → supervise-BfT708zt.js.map} +1 -1
  44. package/dist/{supervision-discovery-1UUbaYC6.js → supervision-discovery-C2Tjw6LX.js} +3 -3
  45. package/dist/{supervision-discovery-1UUbaYC6.js.map → supervision-discovery-C2Tjw6LX.js.map} +1 -1
  46. package/dist/{supervisor-CWTFw-lP.js → supervisor-BDnqTl_R.js} +3 -3
  47. package/dist/{supervisor-CWTFw-lP.js.map → supervisor-BDnqTl_R.js.map} +1 -1
  48. package/dist/testing.js +11 -11
  49. package/dist/{top-web-CuLbTd93.js → top-web-Ms-SgnGN.js} +5 -5
  50. package/dist/{top-web-CuLbTd93.js.map → top-web-Ms-SgnGN.js.map} +1 -1
  51. package/dist/tui/bin.js +3 -3
  52. package/dist/tui/index.js +2 -2
  53. package/package.json +1 -1
  54. package/dist/jsonl-file-BBP9Dz9w.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { m as errMessage, u as detachedFrozen } from "./jsonl-file-BBP9Dz9w.js";
1
+ import { m as errMessage, u as detachedFrozen } from "./jsonl-file-CbxMVnUj.js";
2
2
  // src/mcp/tools/coordination-json.ts
3
3
  /** Stringify a findings payload for a routed delivery; never throws (a cyclic payload degrades to
4
4
  * its String form rather than killing the settle path). */
@@ -362,4 +362,4 @@ function resolveJsonPointer(document, pointer) {
362
362
  }
363
363
  export { admitRuntimeSpawn as a, workerSettlement as i, resolveJsonPointer as n, safeJsonText as o, textBytes as r, createMapRouting as t };
364
364
 
365
- //# sourceMappingURL=coordination-map-routing-BllzcZov.js.map
365
+ //# sourceMappingURL=coordination-map-routing-2_hUlTnz.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"coordination-map-routing-BllzcZov.js","names":[],"sources":["../src/mcp/tools/coordination-json.ts","../src/mcp/tools/coordination-runtime-spawn.ts","../src/mcp/tools/coordination-map-routing.ts"],"sourcesContent":["/** Stringify a findings payload for a routed delivery; never throws (a cyclic payload degrades to\n * its String form rather than killing the settle path). */\nexport function safeJsonText(value: unknown): string {\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n","import { errMessage } from '../../runtime/supervise/error-message'\nimport type { SpawnAdmission } from './coordination-contracts'\n\n/** What a keyed runtime spawn (a flow's entry or route, a map's item or join) became. */\nexport type RuntimeSpawnOutcome =\n /** `committed`: the key's done settlement is already on disk, so nothing ran and the caller\n * settles that result itself; no settlement drain will ever carry it. */\n | { readonly workerId: string; readonly committed: boolean }\n /** The key and its one replacement both have a prior worker started without a terminal receipt. */\n | { readonly inDoubt: true }\n | { readonly refused: string; readonly code?: string }\n\n/**\n * Admit one keyed runtime spawn. A key whose prior worker is in doubt (started in a dead process\n * with no terminal receipt) is re-admitted once under `<key>#2`, the replacement key the\n * `spawn_worker` contract names; a replacement that is in doubt too is reported, never retried.\n */\nexport async function admitRuntimeSpawn(\n admitSpawn: (input: SpawnAdmission) => Promise<unknown>,\n input: SpawnAdmission & { readonly key: string },\n): Promise<RuntimeSpawnOutcome> {\n for (const key of [input.key, `${input.key}#2`]) {\n let response: unknown\n try {\n response = await admitSpawn({ ...input, key })\n } catch (error) {\n return { refused: errMessage(error) }\n }\n const started = response as Partial<\n Record<'workerId' | 'resumed' | 'error' | 'reason', unknown>\n >\n if (typeof started.workerId === 'string') {\n return { workerId: started.workerId, committed: started.resumed === 'completed' }\n }\n if (started.error !== 'in-doubt') {\n return {\n refused: typeof started.reason === 'string' ? started.reason : 'spawn refused',\n ...(typeof started.error === 'string' ? { code: started.error } : {}),\n }\n }\n }\n return { inDoubt: true }\n}\n","import type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { Scope, Settled } from '../../runtime'\nimport { errMessage } from '../../runtime/supervise/error-message'\nimport type { EventBus } from '../../runtime/supervise/event-bus'\nimport { detachedFrozen } from '../../runtime/supervise/snapshot'\nimport type {\n CoordinationToolsOptions,\n SettledWorker,\n SpawnAdmission,\n} from './coordination-contracts'\nimport type { CoordinationEvent } from './coordination-events'\nimport { safeJsonText } from './coordination-json'\nimport type { MapOnSettleRoute, MapTraversalEvent } from './coordination-map-contracts'\nimport { admitRuntimeSpawn } from './coordination-runtime-spawn'\n\ninterface MapExpansion {\n readonly route: MapOnSettleRoute\n readonly sourceWorker: string\n /** The source node's 1-based done-settle count: its spawns' keys are\n * `map:<edge>#<expansion>:<index>` and `map:<edge>#<expansion>:join`. */\n readonly expansion: number\n readonly items: ReadonlyArray<unknown>\n readonly settlements: Array<WorkerSettlement | undefined>\n /** The next index to start. */\n next: number\n inFlight: number\n /** Set by a failed item under all-or-refuse: no further item starts. */\n stopped: boolean\n finished: boolean\n}\n\ninterface MapMember {\n readonly expansion: MapExpansion\n readonly role: 'item' | 'join'\n readonly index?: number\n readonly bytes: number\n}\n\ntype MapDeps = {\n readonly opts: CoordinationToolsOptions\n readonly bus: EventBus<CoordinationEvent>\n readonly admitSpawn: (input: SpawnAdmission) => Promise<unknown>\n /** The node a worker of this manager runs, by profile name. */\n readonly nodeOf: (workerId: string) => string | undefined\n /** Run a committed spawn's journaled settle through the live settle path. */\n readonly settleCommitted: (workerId: string, node: string) => Promise<void>\n /** End a flow whose map spawn is in doubt twice, at the node and source worker named. */\n readonly endInDoubt: (node: string, source: string) => Promise<void>\n}\n\n/** The map state one manager owns; every function below reads and writes it by reference. */\ntype MapState = MapDeps & {\n readonly mapRoutes: ReadonlyArray<MapOnSettleRoute>\n readonly mapMembers: Map<string, MapMember>\n readonly liveExpansions: Map<string, number>\n}\n\n// ── Map routes: fan-out over a run-time list, then one join ──\n// A map's items and its join are runtime spawns, like analyst runs: each takes the admission a\n// `spawn_worker` call takes, so the pool, the pre-flight and the pinning authority judge it, and\n// no manager turn is spent starting it.\nexport function createMapRouting(deps: MapDeps) {\n const state: MapState = {\n ...deps,\n mapRoutes: deps.opts.mapOnSettle ?? [],\n mapMembers: new Map(),\n liveExpansions: new Map(),\n }\n return {\n isItem: (workerId: string) => state.mapMembers.get(workerId)?.role === 'item',\n settleMapMember: settleMapMember.bind(null, state),\n expandMaps: expandMaps.bind(null, state),\n runMapStep: runMapStep.bind(null, state),\n }\n}\n\nexport const textBytes = (value: unknown): number => Buffer.byteLength(safeJsonText(value), 'utf8')\n\nasync function publishMap(\n { bus }: MapState,\n event: MapTraversalEvent,\n wake = false,\n): Promise<void> {\n const record = detachedFrozen<CoordinationEvent>({ type: 'map', map: event })\n if (wake) await bus.publish(record)\n else await bus.publish(record, { queue: false })\n}\n\n// The run's worker-slot bound, or undefined when only the pool bounds concurrency.\nfunction workerSlotBound({ opts }: MapState): number | undefined {\n const capacity = (opts.scope as Partial<Scope<unknown>>).workerCapacity\n if (capacity === undefined || capacity.freeSlots === null) return undefined\n return capacity.working + capacity.freeSlots\n}\n\n// A started spawn is a map member until it settles. A committed one (its key's done settlement\n// is on disk from a prior process) settles at once through the live settle path, so a restarted\n// manager re-expanding a map runs only the items with no done settlement, then the join once.\n// A spawn in doubt twice is refused, and ends a flow.\nasync function startMapSpawn(\n state: MapState,\n expansion: MapExpansion,\n role: 'item' | 'join',\n profile: AgentProfile,\n task: unknown,\n index: number | undefined,\n): Promise<{ readonly workerId: string } | { readonly refused: string }> {\n const { opts } = state\n const { route } = expansion\n const name = typeof profile.name === 'string' && profile.name.length > 0 ? profile.name : 'worker'\n const spawned = await admitRuntimeSpawn(state.admitSpawn, {\n profile,\n args: {\n label: index === undefined ? name : `${name}#${index}`,\n ...(role === 'item' && route.itemBudget !== undefined ? { budget: route.itemBudget } : {}),\n },\n task,\n key: `map:${route.edge}#${expansion.expansion}:${index ?? 'join'}`,\n continuity: { continuity: 'fresh' },\n successorOf: undefined,\n preflightProfile: () =>\n opts.resolveSpawnProfile ? detachedFrozen(opts.resolveSpawnProfile(profile)) : profile,\n resourcesFromPath: [],\n defaultLabel: name,\n map: Object.freeze({ edge: route.edge, role, ...(index === undefined ? {} : { index }) }),\n })\n if ('inDoubt' in spawned) {\n await state.endInDoubt(name, expansion.sourceWorker)\n return { refused: `in-doubt:${name}` }\n }\n if ('refused' in spawned) return spawned\n state.mapMembers.set(spawned.workerId, {\n expansion,\n role,\n ...(index === undefined ? {} : { index }),\n bytes: textBytes(task),\n })\n if (role === 'item') expansion.inFlight += 1\n if (spawned.committed) await state.settleCommitted(spawned.workerId, name)\n return { workerId: spawned.workerId }\n}\n\n// A graph item starts the way `run_graph` starts a graph: the run prepares the same root profile.\nasync function mapItemProfile(\n { opts }: MapState,\n route: MapOnSettleRoute,\n): Promise<{ readonly profile: AgentProfile } | { readonly refused: string }> {\n if ('profile' in route.item) return { profile: route.item.profile }\n if (!opts.graphs) {\n return { refused: 'a graph item starts through run_graph, which this manager does not serve' }\n }\n const prepared = await opts.graphs.prepare({ graph: route.item.graph })\n return prepared.ok ? { profile: detachedFrozen(prepared.profile) } : { refused: prepared.reason }\n}\n\n/** Record an item that never ran, and tell the manager. */\nasync function recordUnstartedItem(\n state: MapState,\n expansion: MapExpansion,\n index: number,\n reason: string,\n): Promise<void> {\n expansion.settlements[index] = { outcome: 'unpropagated', reason }\n await publishMap(state, {\n edge: expansion.route.edge,\n phase: 'item',\n outcome: 'unpropagated',\n sourceWorker: expansion.sourceWorker,\n index,\n bytes: 0,\n reason,\n })\n}\n\nasync function startMapItem(\n state: MapState,\n expansion: MapExpansion,\n index: number,\n): Promise<void> {\n const { route } = expansion\n const resolved = await mapItemProfile(state, route)\n const started =\n 'refused' in resolved\n ? resolved\n : await startMapSpawn(\n state,\n expansion,\n 'item',\n resolved.profile,\n expansion.items[index],\n index,\n )\n if ('workerId' in started) return\n if (route.onItemFailure === 'all-or-refuse') expansion.stopped = true\n await recordUnstartedItem(state, expansion, index, `item spawn refused: ${started.refused}`)\n}\n\n// Start items until the concurrency cap is reached, the list is exhausted, or all-or-refuse\n// stopped the map; once nothing is in flight, the map finishes.\nasync function pumpMap(state: MapState, expansion: MapExpansion): Promise<void> {\n const { route, items } = expansion\n while (\n !expansion.stopped &&\n expansion.inFlight < route.concurrency &&\n expansion.next < items.length\n ) {\n const index = expansion.next\n expansion.next += 1\n await startMapItem(state, expansion, index)\n }\n if (expansion.inFlight === 0) await finishMap(state, expansion)\n}\n\n// Every item settled or was never started: record the unstarted ones, then start the join with\n// the ordered results, or refuse it. `closed` names why a manager that already stopped does not\n// run the join; nobody would read it.\nasync function finishMap(state: MapState, expansion: MapExpansion, closed?: string): Promise<void> {\n if (expansion.finished) return\n expansion.finished = true\n const { route, items, sourceWorker } = expansion\n for (let index = expansion.next; index < items.length; index += 1) {\n const reason = closed ?? 'not started: all-or-refuse stopped this map after an item failed'\n await recordUnstartedItem(state, expansion, index, reason)\n }\n expansion.next = items.length\n const { results, failures } = collectJoinInputs(expansion)\n const refusal =\n closed ??\n (route.onItemFailure === 'all-or-refuse' && failures.length > 0\n ? `all-or-refuse: ${failures.length} of ${items.length} items did not deliver (${failures\n .map((failure) => `#${failure.index} ${failure.outcome}: ${failure.reason}`)\n .join('; ')}); the join did not run`\n : undefined)\n if (refusal !== undefined) {\n // No settlement follows a refused join, so this event is what wakes the manager.\n await publishMap(\n state,\n {\n edge: route.edge,\n phase: 'join',\n outcome: 'unpropagated',\n sourceWorker,\n bytes: 0,\n reason: refusal,\n },\n closed === undefined,\n )\n return\n }\n const task = { map: route.edge, source: sourceWorker, items: items.length, results, failures }\n const started = await startMapSpawn(state, expansion, 'join', route.join, task, undefined)\n if ('refused' in started) {\n await publishMap(\n state,\n {\n edge: route.edge,\n phase: 'join',\n outcome: 'unpropagated',\n sourceWorker,\n bytes: 0,\n reason: `join spawn refused: ${started.refused}`,\n },\n true,\n )\n }\n // A started join is recorded when it settles; its outcome is not known before.\n}\n\n/** Split an expansion's settlements into the delivered results and the failures, in item order. */\nfunction collectJoinInputs(expansion: MapExpansion) {\n const results: Array<{ index: number; item: unknown; result: unknown }> = []\n const failures: Array<{ index: number; item: unknown; outcome: string; reason: string }> = []\n expansion.items.forEach((item, index) => {\n const settlement = expansion.settlements[index]\n if (settlement?.outcome === 'delivered') {\n results.push({ index, item, result: settlement.result })\n } else {\n failures.push({\n index,\n item,\n outcome: settlement?.outcome ?? 'unpropagated',\n reason: settlement?.reason ?? 'never settled',\n })\n }\n })\n return { results, failures }\n}\n\n// A map item or join settled. `advance` is false once the manager stopped: no further item or\n// join starts, and what never started is recorded as such.\nasync function settleMapMember(\n state: MapState,\n settled: Settled<unknown>,\n worker: SettledWorker,\n advance: boolean,\n): Promise<void> {\n const member = state.mapMembers.get(worker.id)\n if (member === undefined) return\n state.mapMembers.delete(worker.id)\n const { expansion, role, index, bytes } = member\n const settlement = workerSettlement(settled, worker)\n await publishMap(state, {\n edge: expansion.route.edge,\n phase: role,\n outcome: settlement.outcome,\n sourceWorker: expansion.sourceWorker,\n ...(index === undefined ? {} : { index }),\n workerId: worker.id,\n bytes,\n ...(settlement.reason === undefined ? {} : { reason: settlement.reason }),\n })\n if (role === 'join' || index === undefined) return\n expansion.inFlight -= 1\n expansion.settlements[index] = settlement\n if (settlement.outcome !== 'delivered' && expansion.route.onItemFailure === 'all-or-refuse') {\n expansion.stopped = true\n }\n if (advance) await pumpMap(state, expansion)\n else if (expansion.inFlight === 0) {\n await finishMap(state, expansion, 'not started: the manager stopped before this map finished')\n }\n}\n\n// The expansion number of a source's done settle. A settle a prior process committed keeps the\n// number it had there (its rank among the resumed done settles of that node), so a replay\n// re-derives the keys that process journaled. A new settle counts on past every prior settle and\n// every journaled expansion: a root-driven graph replays no prior settle, and its driver may\n// label a worker other than by its node.\nfunction expansionOf(state: MapState, source: string, workerId: string): number {\n const resume = state.opts.scope.resume\n const labels = new Map(resume?.view.nodes.map((node) => [node.id, node.label]) ?? [])\n const prior = (resume?.settled ?? [])\n .filter((s) => s.kind === 'done' && labels.get(s.handle.id) === source)\n .map((s) => s.handle.id)\n const rank = prior.indexOf(workerId)\n if (rank >= 0) return rank + 1\n let journaled = 0\n for (const route of state.mapRoutes) {\n if (route.from !== source) continue\n const prefix = `key:map:${route.edge}#`\n for (const node of resume?.view.nodes ?? []) {\n if (!node.assignmentId?.startsWith(prefix)) continue\n const n = Number.parseInt(node.assignmentId.slice(prefix.length), 10)\n if (Number.isSafeInteger(n)) journaled = Math.max(journaled, n)\n }\n }\n const live = (state.liveExpansions.get(source) ?? 0) + 1\n state.liveExpansions.set(source, live)\n return Math.max(prior.length, journaled) + live\n}\n\n/** The list a map expands over, or the reason no item runs. */\nfunction resolveMapItems(\n state: MapState,\n out: unknown,\n route: MapOnSettleRoute,\n): { readonly items: ReadonlyArray<unknown> } | { readonly refusal: string } {\n const selected = resolveJsonPointer(out, route.pointer)\n if (!selected.found) {\n return {\n refusal: `pointer ${JSON.stringify(route.pointer)} does not resolve in the source result: ${selected.reason}; no item ran`,\n }\n }\n const items = selected.value\n if (!Array.isArray(items)) {\n return {\n refusal: `pointer ${JSON.stringify(route.pointer)} resolves to ${items === null ? 'null' : typeof items}, not an array; no item ran`,\n }\n }\n if (items.length > route.maxItems) {\n return {\n refusal: `max-items-exceeded: the list holds ${items.length} items and this map admits at most ${route.maxItems}; no item ran`,\n }\n }\n const slots = workerSlotBound(state)\n if (slots !== undefined && route.concurrency > slots) {\n return {\n refusal: `concurrency-unsatisfiable: concurrency ${route.concurrency} exceeds this run's ${slots} worker slots, so the cap could never be honored; no item ran`,\n }\n }\n return { items }\n}\n\n// A source settled `done`: expand every map that names it.\nasync function expandMaps(\n state: MapState,\n settled: Settled<unknown>,\n worker: SettledWorker,\n): Promise<void> {\n const { mapRoutes } = state\n if (settled.kind !== 'done' || mapRoutes.length === 0) return\n const name = state.nodeOf(worker.id)\n if (name === undefined || !mapRoutes.some((route) => route.from === name)) return\n const expansion = expansionOf(state, name, worker.id)\n for (const route of mapRoutes) {\n if (route.from !== name) continue\n const resolved = resolveMapItems(state, settled.out, route)\n if ('refusal' in resolved) {\n await publishMap(\n state,\n {\n edge: route.edge,\n phase: 'expand',\n outcome: 'unpropagated',\n sourceWorker: worker.id,\n bytes: 0,\n reason: resolved.refusal,\n },\n true,\n )\n continue\n }\n const { items } = resolved\n await publishMap(state, {\n edge: route.edge,\n phase: 'expand',\n outcome: items.length === 0 ? 'empty' : 'delivered',\n sourceWorker: worker.id,\n bytes: textBytes(items),\n items: items.length,\n ...(items.length === 0 ? { reason: 'the list is empty; the join runs with no results' } : {}),\n })\n await pumpMap(state, {\n route,\n sourceWorker: worker.id,\n expansion,\n items: detachedFrozen(items),\n settlements: [],\n next: 0,\n inFlight: 0,\n stopped: false,\n finished: false,\n })\n }\n}\n\n// Map steps run on the settlement path, which must never be taken down by them.\nasync function runMapStep(\n { opts }: MapState,\n step: () => Promise<void>,\n worker: SettledWorker,\n): Promise<void> {\n try {\n await step()\n } catch (error) {\n console.error('Runtime map step failed', {\n managerId: opts.scope.view.root,\n worker: worker.id,\n error: errMessage(error),\n })\n }\n}\n\n/** What one settle delivered. A settle is usable (`delivered`) when it settled `done`, its\n * deliverable check did not reject it, and its result is defined; maps and routes both read\n * results through this one rule. */\ninterface WorkerSettlement {\n readonly outcome: 'delivered' | 'empty' | 'failed' | 'unpropagated'\n readonly result?: unknown\n readonly reason?: string\n}\n\nexport function workerSettlement(\n settled: Settled<unknown>,\n worker: SettledWorker,\n): WorkerSettlement {\n if (settled.kind !== 'done' || worker.status !== 'done') {\n return { outcome: 'failed', reason: worker.status === 'down' ? worker.reason : 'down' }\n }\n if (worker.valid === false) {\n return { outcome: 'failed', reason: 'its deliverable check rejected the result' }\n }\n if (settled.out === undefined) return { outcome: 'empty', reason: 'it settled with no result' }\n return { outcome: 'delivered', result: settled.out }\n}\n\n/** Resolve an RFC 6901 JSON pointer (`''` is the whole document). */\nexport function resolveJsonPointer(\n document: unknown,\n pointer: string,\n):\n | { readonly found: true; readonly value: unknown }\n | { readonly found: false; readonly reason: string } {\n if (pointer === '') return { found: true, value: document }\n if (!pointer.startsWith('/')) {\n return { found: false, reason: 'a JSON pointer is empty or starts with \"/\"' }\n }\n let value = document\n for (const raw of pointer.slice(1).split('/')) {\n const token = raw.replaceAll('~1', '/').replaceAll('~0', '~')\n if (Array.isArray(value)) {\n if (!/^(0|[1-9]\\d*)$/.test(token) || Number(token) >= value.length) {\n return {\n found: false,\n reason: `no index ${JSON.stringify(token)} in an array of ${value.length}`,\n }\n }\n value = value[Number(token)]\n } else if (typeof value === 'object' && value !== null && Object.hasOwn(value, token)) {\n value = (value as Record<string, unknown>)[token]\n } else {\n return { found: false, reason: `no member ${JSON.stringify(token)}` }\n }\n }\n return { found: true, value }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"coordination-map-routing-2_hUlTnz.js","names":[],"sources":["../src/mcp/tools/coordination-json.ts","../src/mcp/tools/coordination-runtime-spawn.ts","../src/mcp/tools/coordination-map-routing.ts"],"sourcesContent":["/** Stringify a findings payload for a routed delivery; never throws (a cyclic payload degrades to\n * its String form rather than killing the settle path). */\nexport function safeJsonText(value: unknown): string {\n if (typeof value === 'string') return value\n try {\n return JSON.stringify(value) ?? String(value)\n } catch {\n return String(value)\n }\n}\n","import { errMessage } from '../../runtime/supervise/error-message'\nimport type { SpawnAdmission } from './coordination-contracts'\n\n/** What a keyed runtime spawn (a flow's entry or route, a map's item or join) became. */\nexport type RuntimeSpawnOutcome =\n /** `committed`: the key's done settlement is already on disk, so nothing ran and the caller\n * settles that result itself; no settlement drain will ever carry it. */\n | { readonly workerId: string; readonly committed: boolean }\n /** The key and its one replacement both have a prior worker started without a terminal receipt. */\n | { readonly inDoubt: true }\n | { readonly refused: string; readonly code?: string }\n\n/**\n * Admit one keyed runtime spawn. A key whose prior worker is in doubt (started in a dead process\n * with no terminal receipt) is re-admitted once under `<key>#2`, the replacement key the\n * `spawn_worker` contract names; a replacement that is in doubt too is reported, never retried.\n */\nexport async function admitRuntimeSpawn(\n admitSpawn: (input: SpawnAdmission) => Promise<unknown>,\n input: SpawnAdmission & { readonly key: string },\n): Promise<RuntimeSpawnOutcome> {\n for (const key of [input.key, `${input.key}#2`]) {\n let response: unknown\n try {\n response = await admitSpawn({ ...input, key })\n } catch (error) {\n return { refused: errMessage(error) }\n }\n const started = response as Partial<\n Record<'workerId' | 'resumed' | 'error' | 'reason', unknown>\n >\n if (typeof started.workerId === 'string') {\n return { workerId: started.workerId, committed: started.resumed === 'completed' }\n }\n if (started.error !== 'in-doubt') {\n return {\n refused: typeof started.reason === 'string' ? started.reason : 'spawn refused',\n ...(typeof started.error === 'string' ? { code: started.error } : {}),\n }\n }\n }\n return { inDoubt: true }\n}\n","import type { AgentProfile } from '@tangle-network/agent-interface'\nimport type { Scope, Settled } from '../../runtime'\nimport { errMessage } from '../../runtime/supervise/error-message'\nimport type { EventBus } from '../../runtime/supervise/event-bus'\nimport { detachedFrozen } from '../../runtime/supervise/snapshot'\nimport type {\n CoordinationToolsOptions,\n SettledWorker,\n SpawnAdmission,\n} from './coordination-contracts'\nimport type { CoordinationEvent } from './coordination-events'\nimport { safeJsonText } from './coordination-json'\nimport type { MapOnSettleRoute, MapTraversalEvent } from './coordination-map-contracts'\nimport { admitRuntimeSpawn } from './coordination-runtime-spawn'\n\ninterface MapExpansion {\n readonly route: MapOnSettleRoute\n readonly sourceWorker: string\n /** The source node's 1-based done-settle count: its spawns' keys are\n * `map:<edge>#<expansion>:<index>` and `map:<edge>#<expansion>:join`. */\n readonly expansion: number\n readonly items: ReadonlyArray<unknown>\n readonly settlements: Array<WorkerSettlement | undefined>\n /** The next index to start. */\n next: number\n inFlight: number\n /** Set by a failed item under all-or-refuse: no further item starts. */\n stopped: boolean\n finished: boolean\n}\n\ninterface MapMember {\n readonly expansion: MapExpansion\n readonly role: 'item' | 'join'\n readonly index?: number\n readonly bytes: number\n}\n\ntype MapDeps = {\n readonly opts: CoordinationToolsOptions\n readonly bus: EventBus<CoordinationEvent>\n readonly admitSpawn: (input: SpawnAdmission) => Promise<unknown>\n /** The node a worker of this manager runs, by profile name. */\n readonly nodeOf: (workerId: string) => string | undefined\n /** Run a committed spawn's journaled settle through the live settle path. */\n readonly settleCommitted: (workerId: string, node: string) => Promise<void>\n /** End a flow whose map spawn is in doubt twice, at the node and source worker named. */\n readonly endInDoubt: (node: string, source: string) => Promise<void>\n}\n\n/** The map state one manager owns; every function below reads and writes it by reference. */\ntype MapState = MapDeps & {\n readonly mapRoutes: ReadonlyArray<MapOnSettleRoute>\n readonly mapMembers: Map<string, MapMember>\n readonly liveExpansions: Map<string, number>\n}\n\n// ── Map routes: fan-out over a run-time list, then one join ──\n// A map's items and its join are runtime spawns, like analyst runs: each takes the admission a\n// `spawn_worker` call takes, so the pool, the pre-flight and the pinning authority judge it, and\n// no manager turn is spent starting it.\nexport function createMapRouting(deps: MapDeps) {\n const state: MapState = {\n ...deps,\n mapRoutes: deps.opts.mapOnSettle ?? [],\n mapMembers: new Map(),\n liveExpansions: new Map(),\n }\n return {\n isItem: (workerId: string) => state.mapMembers.get(workerId)?.role === 'item',\n settleMapMember: settleMapMember.bind(null, state),\n expandMaps: expandMaps.bind(null, state),\n runMapStep: runMapStep.bind(null, state),\n }\n}\n\nexport const textBytes = (value: unknown): number => Buffer.byteLength(safeJsonText(value), 'utf8')\n\nasync function publishMap(\n { bus }: MapState,\n event: MapTraversalEvent,\n wake = false,\n): Promise<void> {\n const record = detachedFrozen<CoordinationEvent>({ type: 'map', map: event })\n if (wake) await bus.publish(record)\n else await bus.publish(record, { queue: false })\n}\n\n// The run's worker-slot bound, or undefined when only the pool bounds concurrency.\nfunction workerSlotBound({ opts }: MapState): number | undefined {\n const capacity = (opts.scope as Partial<Scope<unknown>>).workerCapacity\n if (capacity === undefined || capacity.freeSlots === null) return undefined\n return capacity.working + capacity.freeSlots\n}\n\n// A started spawn is a map member until it settles. A committed one (its key's done settlement\n// is on disk from a prior process) settles at once through the live settle path, so a restarted\n// manager re-expanding a map runs only the items with no done settlement, then the join once.\n// A spawn in doubt twice is refused, and ends a flow.\nasync function startMapSpawn(\n state: MapState,\n expansion: MapExpansion,\n role: 'item' | 'join',\n profile: AgentProfile,\n task: unknown,\n index: number | undefined,\n): Promise<{ readonly workerId: string } | { readonly refused: string }> {\n const { opts } = state\n const { route } = expansion\n const name = typeof profile.name === 'string' && profile.name.length > 0 ? profile.name : 'worker'\n const spawned = await admitRuntimeSpawn(state.admitSpawn, {\n profile,\n args: {\n label: index === undefined ? name : `${name}#${index}`,\n ...(role === 'item' && route.itemBudget !== undefined ? { budget: route.itemBudget } : {}),\n },\n task,\n key: `map:${route.edge}#${expansion.expansion}:${index ?? 'join'}`,\n continuity: { continuity: 'fresh' },\n successorOf: undefined,\n preflightProfile: () =>\n opts.resolveSpawnProfile ? detachedFrozen(opts.resolveSpawnProfile(profile)) : profile,\n resourcesFromPath: [],\n defaultLabel: name,\n map: Object.freeze({ edge: route.edge, role, ...(index === undefined ? {} : { index }) }),\n })\n if ('inDoubt' in spawned) {\n await state.endInDoubt(name, expansion.sourceWorker)\n return { refused: `in-doubt:${name}` }\n }\n if ('refused' in spawned) return spawned\n state.mapMembers.set(spawned.workerId, {\n expansion,\n role,\n ...(index === undefined ? {} : { index }),\n bytes: textBytes(task),\n })\n if (role === 'item') expansion.inFlight += 1\n if (spawned.committed) await state.settleCommitted(spawned.workerId, name)\n return { workerId: spawned.workerId }\n}\n\n// A graph item starts the way `run_graph` starts a graph: the run prepares the same root profile.\nasync function mapItemProfile(\n { opts }: MapState,\n route: MapOnSettleRoute,\n): Promise<{ readonly profile: AgentProfile } | { readonly refused: string }> {\n if ('profile' in route.item) return { profile: route.item.profile }\n if (!opts.graphs) {\n return { refused: 'a graph item starts through run_graph, which this manager does not serve' }\n }\n const prepared = await opts.graphs.prepare({ graph: route.item.graph })\n return prepared.ok ? { profile: detachedFrozen(prepared.profile) } : { refused: prepared.reason }\n}\n\n/** Record an item that never ran, and tell the manager. */\nasync function recordUnstartedItem(\n state: MapState,\n expansion: MapExpansion,\n index: number,\n reason: string,\n): Promise<void> {\n expansion.settlements[index] = { outcome: 'unpropagated', reason }\n await publishMap(state, {\n edge: expansion.route.edge,\n phase: 'item',\n outcome: 'unpropagated',\n sourceWorker: expansion.sourceWorker,\n index,\n bytes: 0,\n reason,\n })\n}\n\nasync function startMapItem(\n state: MapState,\n expansion: MapExpansion,\n index: number,\n): Promise<void> {\n const { route } = expansion\n const resolved = await mapItemProfile(state, route)\n const started =\n 'refused' in resolved\n ? resolved\n : await startMapSpawn(\n state,\n expansion,\n 'item',\n resolved.profile,\n expansion.items[index],\n index,\n )\n if ('workerId' in started) return\n if (route.onItemFailure === 'all-or-refuse') expansion.stopped = true\n await recordUnstartedItem(state, expansion, index, `item spawn refused: ${started.refused}`)\n}\n\n// Start items until the concurrency cap is reached, the list is exhausted, or all-or-refuse\n// stopped the map; once nothing is in flight, the map finishes.\nasync function pumpMap(state: MapState, expansion: MapExpansion): Promise<void> {\n const { route, items } = expansion\n while (\n !expansion.stopped &&\n expansion.inFlight < route.concurrency &&\n expansion.next < items.length\n ) {\n const index = expansion.next\n expansion.next += 1\n await startMapItem(state, expansion, index)\n }\n if (expansion.inFlight === 0) await finishMap(state, expansion)\n}\n\n// Every item settled or was never started: record the unstarted ones, then start the join with\n// the ordered results, or refuse it. `closed` names why a manager that already stopped does not\n// run the join; nobody would read it.\nasync function finishMap(state: MapState, expansion: MapExpansion, closed?: string): Promise<void> {\n if (expansion.finished) return\n expansion.finished = true\n const { route, items, sourceWorker } = expansion\n for (let index = expansion.next; index < items.length; index += 1) {\n const reason = closed ?? 'not started: all-or-refuse stopped this map after an item failed'\n await recordUnstartedItem(state, expansion, index, reason)\n }\n expansion.next = items.length\n const { results, failures } = collectJoinInputs(expansion)\n const refusal =\n closed ??\n (route.onItemFailure === 'all-or-refuse' && failures.length > 0\n ? `all-or-refuse: ${failures.length} of ${items.length} items did not deliver (${failures\n .map((failure) => `#${failure.index} ${failure.outcome}: ${failure.reason}`)\n .join('; ')}); the join did not run`\n : undefined)\n if (refusal !== undefined) {\n // No settlement follows a refused join, so this event is what wakes the manager.\n await publishMap(\n state,\n {\n edge: route.edge,\n phase: 'join',\n outcome: 'unpropagated',\n sourceWorker,\n bytes: 0,\n reason: refusal,\n },\n closed === undefined,\n )\n return\n }\n const task = { map: route.edge, source: sourceWorker, items: items.length, results, failures }\n const started = await startMapSpawn(state, expansion, 'join', route.join, task, undefined)\n if ('refused' in started) {\n await publishMap(\n state,\n {\n edge: route.edge,\n phase: 'join',\n outcome: 'unpropagated',\n sourceWorker,\n bytes: 0,\n reason: `join spawn refused: ${started.refused}`,\n },\n true,\n )\n }\n // A started join is recorded when it settles; its outcome is not known before.\n}\n\n/** Split an expansion's settlements into the delivered results and the failures, in item order. */\nfunction collectJoinInputs(expansion: MapExpansion) {\n const results: Array<{ index: number; item: unknown; result: unknown }> = []\n const failures: Array<{ index: number; item: unknown; outcome: string; reason: string }> = []\n expansion.items.forEach((item, index) => {\n const settlement = expansion.settlements[index]\n if (settlement?.outcome === 'delivered') {\n results.push({ index, item, result: settlement.result })\n } else {\n failures.push({\n index,\n item,\n outcome: settlement?.outcome ?? 'unpropagated',\n reason: settlement?.reason ?? 'never settled',\n })\n }\n })\n return { results, failures }\n}\n\n// A map item or join settled. `advance` is false once the manager stopped: no further item or\n// join starts, and what never started is recorded as such.\nasync function settleMapMember(\n state: MapState,\n settled: Settled<unknown>,\n worker: SettledWorker,\n advance: boolean,\n): Promise<void> {\n const member = state.mapMembers.get(worker.id)\n if (member === undefined) return\n state.mapMembers.delete(worker.id)\n const { expansion, role, index, bytes } = member\n const settlement = workerSettlement(settled, worker)\n await publishMap(state, {\n edge: expansion.route.edge,\n phase: role,\n outcome: settlement.outcome,\n sourceWorker: expansion.sourceWorker,\n ...(index === undefined ? {} : { index }),\n workerId: worker.id,\n bytes,\n ...(settlement.reason === undefined ? {} : { reason: settlement.reason }),\n })\n if (role === 'join' || index === undefined) return\n expansion.inFlight -= 1\n expansion.settlements[index] = settlement\n if (settlement.outcome !== 'delivered' && expansion.route.onItemFailure === 'all-or-refuse') {\n expansion.stopped = true\n }\n if (advance) await pumpMap(state, expansion)\n else if (expansion.inFlight === 0) {\n await finishMap(state, expansion, 'not started: the manager stopped before this map finished')\n }\n}\n\n// The expansion number of a source's done settle. A settle a prior process committed keeps the\n// number it had there (its rank among the resumed done settles of that node), so a replay\n// re-derives the keys that process journaled. A new settle counts on past every prior settle and\n// every journaled expansion: a root-driven graph replays no prior settle, and its driver may\n// label a worker other than by its node.\nfunction expansionOf(state: MapState, source: string, workerId: string): number {\n const resume = state.opts.scope.resume\n const labels = new Map(resume?.view.nodes.map((node) => [node.id, node.label]) ?? [])\n const prior = (resume?.settled ?? [])\n .filter((s) => s.kind === 'done' && labels.get(s.handle.id) === source)\n .map((s) => s.handle.id)\n const rank = prior.indexOf(workerId)\n if (rank >= 0) return rank + 1\n let journaled = 0\n for (const route of state.mapRoutes) {\n if (route.from !== source) continue\n const prefix = `key:map:${route.edge}#`\n for (const node of resume?.view.nodes ?? []) {\n if (!node.assignmentId?.startsWith(prefix)) continue\n const n = Number.parseInt(node.assignmentId.slice(prefix.length), 10)\n if (Number.isSafeInteger(n)) journaled = Math.max(journaled, n)\n }\n }\n const live = (state.liveExpansions.get(source) ?? 0) + 1\n state.liveExpansions.set(source, live)\n return Math.max(prior.length, journaled) + live\n}\n\n/** The list a map expands over, or the reason no item runs. */\nfunction resolveMapItems(\n state: MapState,\n out: unknown,\n route: MapOnSettleRoute,\n): { readonly items: ReadonlyArray<unknown> } | { readonly refusal: string } {\n const selected = resolveJsonPointer(out, route.pointer)\n if (!selected.found) {\n return {\n refusal: `pointer ${JSON.stringify(route.pointer)} does not resolve in the source result: ${selected.reason}; no item ran`,\n }\n }\n const items = selected.value\n if (!Array.isArray(items)) {\n return {\n refusal: `pointer ${JSON.stringify(route.pointer)} resolves to ${items === null ? 'null' : typeof items}, not an array; no item ran`,\n }\n }\n if (items.length > route.maxItems) {\n return {\n refusal: `max-items-exceeded: the list holds ${items.length} items and this map admits at most ${route.maxItems}; no item ran`,\n }\n }\n const slots = workerSlotBound(state)\n if (slots !== undefined && route.concurrency > slots) {\n return {\n refusal: `concurrency-unsatisfiable: concurrency ${route.concurrency} exceeds this run's ${slots} worker slots, so the cap could never be honored; no item ran`,\n }\n }\n return { items }\n}\n\n// A source settled `done`: expand every map that names it.\nasync function expandMaps(\n state: MapState,\n settled: Settled<unknown>,\n worker: SettledWorker,\n): Promise<void> {\n const { mapRoutes } = state\n if (settled.kind !== 'done' || mapRoutes.length === 0) return\n const name = state.nodeOf(worker.id)\n if (name === undefined || !mapRoutes.some((route) => route.from === name)) return\n const expansion = expansionOf(state, name, worker.id)\n for (const route of mapRoutes) {\n if (route.from !== name) continue\n const resolved = resolveMapItems(state, settled.out, route)\n if ('refusal' in resolved) {\n await publishMap(\n state,\n {\n edge: route.edge,\n phase: 'expand',\n outcome: 'unpropagated',\n sourceWorker: worker.id,\n bytes: 0,\n reason: resolved.refusal,\n },\n true,\n )\n continue\n }\n const { items } = resolved\n await publishMap(state, {\n edge: route.edge,\n phase: 'expand',\n outcome: items.length === 0 ? 'empty' : 'delivered',\n sourceWorker: worker.id,\n bytes: textBytes(items),\n items: items.length,\n ...(items.length === 0 ? { reason: 'the list is empty; the join runs with no results' } : {}),\n })\n await pumpMap(state, {\n route,\n sourceWorker: worker.id,\n expansion,\n items: detachedFrozen(items),\n settlements: [],\n next: 0,\n inFlight: 0,\n stopped: false,\n finished: false,\n })\n }\n}\n\n// Map steps run on the settlement path, which must never be taken down by them.\nasync function runMapStep(\n { opts }: MapState,\n step: () => Promise<void>,\n worker: SettledWorker,\n): Promise<void> {\n try {\n await step()\n } catch (error) {\n console.error('Runtime map step failed', {\n managerId: opts.scope.view.root,\n worker: worker.id,\n error: errMessage(error),\n })\n }\n}\n\n/** What one settle delivered. A settle is usable (`delivered`) when it settled `done`, its\n * deliverable check did not reject it, and its result is defined; maps and routes both read\n * results through this one rule. */\ninterface WorkerSettlement {\n readonly outcome: 'delivered' | 'empty' | 'failed' | 'unpropagated'\n readonly result?: unknown\n readonly reason?: string\n}\n\nexport function workerSettlement(\n settled: Settled<unknown>,\n worker: SettledWorker,\n): WorkerSettlement {\n if (settled.kind !== 'done' || worker.status !== 'done') {\n return { outcome: 'failed', reason: worker.status === 'down' ? worker.reason : 'down' }\n }\n if (worker.valid === false) {\n return { outcome: 'failed', reason: 'its deliverable check rejected the result' }\n }\n if (settled.out === undefined) return { outcome: 'empty', reason: 'it settled with no result' }\n return { outcome: 'delivered', result: settled.out }\n}\n\n/** Resolve an RFC 6901 JSON pointer (`''` is the whole document). */\nexport function resolveJsonPointer(\n document: unknown,\n pointer: string,\n):\n | { readonly found: true; readonly value: unknown }\n | { readonly found: false; readonly reason: string } {\n if (pointer === '') return { found: true, value: document }\n if (!pointer.startsWith('/')) {\n return { found: false, reason: 'a JSON pointer is empty or starts with \"/\"' }\n }\n let value = document\n for (const raw of pointer.slice(1).split('/')) {\n const token = raw.replaceAll('~1', '/').replaceAll('~0', '~')\n if (Array.isArray(value)) {\n if (!/^(0|[1-9]\\d*)$/.test(token) || Number(token) >= value.length) {\n return {\n found: false,\n reason: `no index ${JSON.stringify(token)} in an array of ${value.length}`,\n }\n }\n value = value[Number(token)]\n } else if (typeof value === 'object' && value !== null && Object.hasOwn(value, token)) {\n value = (value as Record<string, unknown>)[token]\n } else {\n return { found: false, reason: `no member ${JSON.stringify(token)}` }\n }\n }\n return { found: true, value }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { i as ConfigError } from "./errors-AzSuGI23.js";
2
- import { t as supervise } from "./supervise-Dszn1xVB.js";
2
+ import { t as supervise } from "./supervise-BfT708zt.js";
3
3
  import { agentProfileSchema } from "@tangle-network/agent-interface";
4
4
  import { computeFindingId, makeFinding } from "@tangle-network/agent-eval";
5
5
  // src/runtime/supervise/authoring.ts
@@ -205,4 +205,4 @@ async function delegate(intent, opts) {
205
205
  }
206
206
  export { defaultProfileRichnessThresholds as a, assessAuthoredProfile as i, delegate as n, profileRichnessFinding as o, asAuthoredProfile as r, supervisorInstructions as s, defaultDelegateBudget as t };
207
207
 
208
- //# sourceMappingURL=delegate-DR2gtTHa.js.map
208
+ //# sourceMappingURL=delegate-BYLjG7Ev.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"delegate-DR2gtTHa.js","names":[],"sources":["../src/runtime/supervise/authoring.ts","../src/runtime/supervise/delegate.ts"],"sourcesContent":["/**\n *\n * The supervisor's intelligence is AUTHORING the agents it spawns — not pressing buttons.\n *\n * Every agent here is three things: instructions, tools, and a model — its\n * `AgentProfile`. The supervisor's job is to WRITE those profiles: read the task, decompose it,\n * and for each sub-task author a tailored worker recipe. `supervisorInstructions` is the how-to the\n * supervisor reads; canonical Runtime executors materialize the resulting profile.\n *\n * The skill is the single OPTIMIZABLE surface: edit it → the supervisor designs better agents.\n * That is the self-improvement lever (the prompt/skill lever), not the execution plumbing.\n *\n * @experimental\n */\n\nimport { type AnalystFinding, computeFindingId, makeFinding } from '@tangle-network/agent-eval'\nimport {\n type AgentProfile,\n type AgentProfilePrompt,\n agentProfileSchema,\n} from '@tangle-network/agent-interface'\n\n/** What the supervisor AUTHORS per sub-task: one complete canonical profile whose name and\n * task-specific guidance are present. Every other `AgentProfile` axis is preserved exactly. */\nexport type AuthoredProfile = AgentProfile & {\n readonly name: string\n readonly prompt: AgentProfilePrompt\n}\n\n/** Narrow an untyped `spawn_worker` profile argument to an `AuthoredProfile`, or null if the\n * supervisor failed to author one (empty/placeholder profile — a skill violation worth catching). */\nexport function asAuthoredProfile(raw: unknown): AuthoredProfile | null {\n const parsed = agentProfileSchema.safeParse(raw)\n if (!parsed.success) return null\n if (!resolveSystemPrompt(parsed.data).trim()) return null\n return {\n ...parsed.data,\n name:\n typeof parsed.data.name === 'string' && parsed.data.name.length > 0\n ? parsed.data.name\n : 'worker',\n prompt: { ...parsed.data.prompt },\n }\n}\n\n/** The supervisor skill: an explicit profile-authoring instruction, never an implicit Runtime\n * policy. Editing this text changes how a profile designs the descendants it spawns. */\nexport function supervisorInstructions(opts?: { goal?: string }): string {\n return [\n 'Your delegation craft is AUTHORING: a spawned worker is exactly as good as the profile you write.',\n '',\n 'For the task you are given:',\n '1. DECOMPOSE it into the smallest set of sub-tasks a single focused worker can each deliver.',\n '2. For EACH sub-task, AUTHOR a worker by calling spawn_worker with a COMPLETE `profile`:',\n ' • name and description: who this specialist is and why it exists.',\n ' • prompt.appendSystemPrompt: rich additive instructions for THIS sub-task — exact output, process, evidence, and what \"done\" means.',\n ' • model.default, model.reasoningEffort, and harness: choose the execution system deliberately when the task benefits from it.',\n ' • tools, mcp, resources.skills/files/instructions, hooks, subagents, permissions, and modes: grant or attach every capability the worker needs; omit an axis only when it is intentionally unnecessary.',\n ' • tools.agent_runtime_coordination_spawn_worker: true ONLY when this child should author and drive descendants. Add only the other agent_runtime_coordination_<verb> tools it will call, such as observe_agent or steer_agent.',\n ' • A child with spawn_worker MUST carry this complete profile-authoring instruction as an immutable resources.skills entry with resources.failOnError: true, so it can author its own descendants from the same contract.',\n ' • metadata may describe the work, but it never grants recursion or selects a Runtime execution path.',\n ' NEVER spawn a worker with an empty profile. The quality of the worker IS the quality of the profile you write.',\n '3. End your turn while your workers run: Runtime wakes you with each settled worker. A settlement says valid:true only if the deployable check passed.',\n '4. If a worker did NOT deliver, AUTHOR A NEW profile whose prompt.appendSystemPrompt names the SPECIFIC failure and how to fix it — never just retry the same profile.',\n \"5. read_journal to re-read YOUR OWN record before you decide the next move: every spawn you made, every settle, every question and answer, every steer, every analyst finding — oldest first, this node only, including what you did before a restart. Use it to see what you already tried instead of trying it again. It is paged: pass the returned nextRow as the next call's sinceRow, narrow with kinds, and raise limit/maxBytes only as far as you will actually read. A truncated:true page means a bound cut it short — keep paging before you conclude you have read everything.\",\n '6. AUTHOR YOUR OWN LENS when the questions you can already ask of a settled trace do not cover the failure you are chasing: define_analyst takes an id, a description, an area, the question in your own words, the instructions for answering it with trace evidence, and the smallest toolGroup that can answer it (model is the seat it runs on; omit it for the run default). It is DATA, never code. Then run_analyst it on any settled worker like a lens the run shipped with, and read the finding. list_analysts shows what you have. Define a lens when you need a different question asked — not a second copy of a question already on the menu.',\n '7. EVERY refusal you get back carries a `reason` naming the exact unmet condition. Read it and change that condition — a spawn refused for budget-exhausted needs a smaller budget or the refund of a settled worker, an invalid-profile needs the named field fixed, a submit_result refused because the check THREW is a broken check to report, not a result to resubmit. Never repeat a call that was refused without changing what it was refused for.',\n '8. ask_parent ONLY when you genuinely cannot decide, and then READ ITS OUTCOME. \"queued-for-parent\" means an inbox above you now holds the question. \"no-parent\" means no inbox above you is configured to receive it: the question is still on the run record for anyone watching, but nothing will route an answer back to you, so do not block. Decide it with answer_question, or answer_question with deferReason to record that it stays open, and carry on — a blocking question left undecided also refuses your stop.',\n '9. Once the work is delivered, end your turn with nothing left running.',\n ...(opts?.goal ? ['', `The goal: ${opts.goal}`] : []),\n ].join('\\n')\n}\n\n// ── Profile-richness gate ────────────────────────────────────────────────────\n//\n// The supervisor's product is the worker PROFILE it authors. The failure mode the existing\n// gates miss: `asAuthoredProfile` / `local-harness` only reject a FULLY EMPTY system prompt —\n// a two-sentence stub passes. `assessAuthoredProfile` OBSERVES the authored artifact (it reads\n// no judge verdict, so it steers cleanly past `assertTraceDerivedFindings`) and flags THIN:\n// a short/few-line system prompt, OR no tools, OR no skills, OR no MCP when the task needs one.\n// It emits a real `AnalystFinding` so it rides the SAME coordination bus the driver pulls via\n// receives in its next wake — the supervisor can self-correct and re-author richer.\n\n/** Thresholds below which a system prompt is treated as a thin stub. Tunable per call. */\nexport interface ProfileRichnessThresholds {\n /** A prompt shorter than this many characters is thin (default 600). */\n readonly minSystemPromptChars: number\n /** A prompt with fewer than this many non-blank lines is thin (default 6). */\n readonly minSystemPromptLines: number\n}\n\n/** Default thresholds for `ProfileRichnessThresholds` — 600 chars / 6 lines minimum system prompt. */\nexport const defaultProfileRichnessThresholds: ProfileRichnessThresholds = {\n minSystemPromptChars: 600,\n minSystemPromptLines: 6,\n}\n\n/** Per-field verdict on one authored profile — the raw material the bench renders + scores. */\nexport interface ProfileRichness {\n readonly name: string\n /** Resolved authored guidance from replacement, addition and instruction sections. */\n readonly systemPrompt: string\n readonly systemPromptChars: number\n readonly systemPromptLines: number\n readonly sentenceCount: number\n readonly hasDescription: boolean\n readonly hasTools: boolean\n readonly hasSkills: boolean\n readonly hasMcp: boolean\n readonly hasSubagents: boolean\n /** 0..1 — fraction of richness signals present (prompt-depth + the four levers). */\n readonly richness: number\n /** True when the supervisor authored a stub instead of a real profile. */\n readonly thin: boolean\n /** The specific reasons it is thin (empty when rich) — used in the finding's action. */\n readonly reasons: string[]\n}\n\n/** Read authored guidance without requiring replacement of native coding instructions. */\nfunction resolveSystemPrompt(profile: AgentProfile): string {\n const pr = (profile as { prompt?: unknown }).prompt\n if (typeof pr === 'string') return pr\n if (pr && typeof pr === 'object') {\n const o = pr as { systemPrompt?: unknown; system?: unknown }\n return [\n Reflect.get(o, 'systemPrompt'),\n Reflect.get(o, 'appendSystemPrompt'),\n ...(Array.isArray(Reflect.get(o, 'instructions')) ? Reflect.get(o, 'instructions') : []),\n Reflect.get(o, 'system'),\n ]\n .filter((value) => typeof value === 'string')\n .join('\\n\\n')\n }\n return ''\n}\n\n/** OBSERVE one authored `AgentProfile` and score its richness (no judge verdict is read). The task\n * context (`needsMcp`) lets a domain say \"this work needs a data/tool MCP\" so a missing MCP counts. */\nexport function assessAuthoredProfile(\n profile: AgentProfile,\n opts?: { needsMcp?: boolean; thresholds?: Partial<ProfileRichnessThresholds> },\n): ProfileRichness {\n const th = { ...defaultProfileRichnessThresholds, ...(opts?.thresholds ?? {}) }\n const systemPrompt = resolveSystemPrompt(profile)\n const trimmed = systemPrompt.trim()\n const systemPromptChars = trimmed.length\n const systemPromptLines = trimmed\n ? trimmed.split('\\n').filter((l) => l.trim().length > 0).length\n : 0\n const sentenceCount = trimmed\n ? (trimmed.match(/[.!?](\\s|$)/g) ?? []).length || (trimmed ? 1 : 0)\n : 0\n const hasDescription =\n typeof profile.description === 'string' && profile.description.trim().length > 0\n const tools = (profile as { tools?: Record<string, unknown> }).tools\n const hasTools = !!tools && Object.keys(tools).length > 0\n const skills = (profile.resources as { skills?: unknown[] } | undefined)?.skills\n const hasSkills = Array.isArray(skills) && skills.length > 0\n const mcp = (profile as { mcp?: Record<string, unknown> }).mcp\n const hasMcp = !!mcp && Object.keys(mcp).length > 0\n const subagents = (profile as { subagents?: Record<string, unknown> }).subagents\n const hasSubagents = !!subagents && Object.keys(subagents).length > 0\n\n const reasons: string[] = []\n const promptThin =\n systemPromptChars < th.minSystemPromptChars || systemPromptLines < th.minSystemPromptLines\n if (promptThin)\n reasons.push(\n `system prompt is thin (${systemPromptChars} chars, ${systemPromptLines} lines; need ≥${th.minSystemPromptChars} chars and ≥${th.minSystemPromptLines} lines)`,\n )\n if (!hasTools)\n reasons.push('no tools granted (a worker can only act through the tools you grant it)')\n if (!hasSkills) reasons.push('no skills attached (no reusable how-to notes injected)')\n if (opts?.needsMcp && !hasMcp) reasons.push('no MCP server, but the task needs data/tool access')\n\n // Richness = fraction of signals present. Prompt-depth is one signal; the four levers are the rest.\n const signals = [!promptThin, hasTools, hasSkills, hasDescription, opts?.needsMcp ? hasMcp : true]\n const richness = signals.filter(Boolean).length / signals.length\n // THIN ⟺ the prompt is a stub OR the worker has no levers at all (no tools AND no skills AND no mcp).\n const thin = promptThin || (!hasTools && !hasSkills && !hasMcp)\n\n return {\n name: profile.name ?? 'worker',\n systemPrompt,\n systemPromptChars,\n systemPromptLines,\n sentenceCount,\n hasDescription,\n hasTools,\n hasSkills,\n hasMcp,\n hasSubagents,\n richness,\n thin,\n reasons,\n }\n}\n\n/** Turn a {@link ProfileRichness} verdict into a bus-routable `AnalystFinding` (area `profile-quality`).\n * Severity scales with thinness; the recommended action names the MISSING lever so the supervisor can\n * re-author. `subject` = the worker name so per-worker findings diff cleanly across re-authors. */\nexport function profileRichnessFinding(\n richness: ProfileRichness,\n opts?: { analystId?: string; runId?: string },\n): AnalystFinding {\n const analyst_id = opts?.analystId ?? 'profile-richness'\n const subject = richness.name\n const claim = richness.thin\n ? `Worker \"${richness.name}\" was authored as a THIN profile: ${richness.reasons.join('; ')}.`\n : `Worker \"${richness.name}\" was authored as a rich profile (richness ${(richness.richness * 100).toFixed(0)}%).`\n const severity: AnalystFinding['severity'] = richness.thin\n ? richness.richness < 0.25\n ? 'high'\n : 'medium'\n : 'info'\n return makeFinding({\n analyst_id,\n severity,\n area: 'profile-quality',\n claim,\n subject,\n confidence: 0.9,\n evidence_refs: [\n {\n kind: 'metric',\n uri: `profile:${subject}`,\n excerpt: `chars=${richness.systemPromptChars} lines=${richness.systemPromptLines} tools=${richness.hasTools} skills=${richness.hasSkills} mcp=${richness.hasMcp} richness=${richness.richness.toFixed(2)}`,\n },\n ],\n ...(richness.thin\n ? { recommended_action: `Re-author \"${richness.name}\" with: ${richness.reasons.join('; ')}.` }\n : {}),\n id_basis: computeFindingId({\n analyst_id,\n area: 'profile-quality',\n subject,\n claim: `richness:${richness.thin ? 'thin' : 'rich'}`,\n }),\n })\n}\n","/**\n *\n * `delegate` — the one generic delegation verb. You hand it an INTENT (what you want done) and it\n * hands that intent to a default AUTHORING supervisor: a router-brained supervisor whose standing\n * instruction is `supervisorInstructions()` (the authoring-agent-profiles skill). The supervisor\n * DECOMPOSES the intent and AUTHORS the worker profile it needs per sub-task — there is NO hardcoded\n * coder/researcher profile here. That is the whole point: `delegate('fix the failing test', …)` and\n * `delegate('research X and cite sources', …)` route through the SAME front door; the supervisor\n * writes a code-shaped or research-shaped worker on its own.\n *\n * It is a thin wrapper over `supervise()` — the one front door — so the conserved-budget pool, the\n * completion oracle (`deliverable`), the coordination toolbox, and equal-compute accounting all come\n * for free; nothing is hand-rolled. The result is `supervise()`'s `SupervisedResult` returned\n * UNCHANGED, so its `spentTotal` (`{ iterations, tokens, usd, ms }`) rides straight back to the\n * caller on BOTH paths — a `winner` carries the delivered worker's spend, a `no-winner` carries the\n * spend incurred before it failed. That cost channel means a `delegate()` caller always learns what\n * the delegation actually spent.\n *\n * @experimental\n */\n\nimport { ConfigError } from '../../errors'\nimport type { RouterTransportConfig } from '../router-http-transport'\nimport type { DeliverableSpec } from './completion-gate'\nimport type { ExecutorConfig } from './runtime'\nimport { supervise } from './supervise'\nimport type { SupervisorProfile } from './supervisor-agent'\nimport type { Budget, SupervisedResult } from './types'\n\n/** The conserved pool a `delegate()` call applies when the caller does not pass its own `budget`.\n * A modest token ceiling + a small iteration ceiling — generous enough for a few-worker decompose,\n * bounded enough that an unsupervised intent cannot run away. Callers override via `opts.budget`. */\nexport const defaultDelegateBudget: Budget = { maxIterations: 50, maxTokens: 200_000 }\n\n/** Inputs to {@link delegate}. The intent is the first positional arg; everything here is optional\n * with explicit execution identity, so the common call names one exact supervisor profile. */\nexport interface DelegateOptions<Out = unknown> {\n /** The completion oracle (settled ⟺ delivered) the authored workers settle against. Strongly\n * recommended — without it the supervisor trusts a worker's self-report. For a code intent,\n * `patchDelivered()` is the canonical example; for a free-form answer, a content check. */\n readonly deliverable?: DeliverableSpec<Out>\n /** WHERE the authored workers run — the worker-execution backend (`router-tools` / `sandbox` /\n * `cli-worktree` / …). The supervisor authors the worker PROFILE; this is the substrate it runs\n * on. Provide this OR `makeWorkerAgent`-style wiring through `supervise()` is unavailable. */\n readonly backend?: ExecutorConfig\n /** The conserved compute pool for the whole delegation. Defaults to {@link defaultDelegateBudget}. */\n readonly budget?: Budget\n /** Exact executable authoring supervisor. Model, prompt, harness, and provider live here. */\n readonly supervisorProfile: SupervisorProfile\n /** Router endpoint/auth for a `cli-base` supervisor; contains no behavioral settings. */\n readonly router: RouterTransportConfig\n /** Restrict the run to this subset of models (forwarded to `supervise()`). */\n readonly allowedModels?: readonly string[]\n readonly runId?: string\n}\n\n/**\n * Delegate an INTENT to a default authoring supervisor and return its `SupervisedResult` unchanged.\n *\n * The supervisor authors + spawns whatever worker the intent needs over the conserved-budget pool;\n * `result.spentTotal` reports what the whole delegation actually cost. A `winner` result carries the\n * authored worker's delivered output; a `no-winner` result names why (never a fabricated success).\n */\nexport async function delegate<Out = unknown>(\n intent: string,\n opts: DelegateOptions<Out>,\n): Promise<SupervisedResult<Out>> {\n if (typeof intent !== 'string' || intent.trim().length === 0) {\n throw new ConfigError('delegate: `intent` must be a non-empty string')\n }\n return supervise(opts.supervisorProfile, intent, {\n budget: opts.budget ?? defaultDelegateBudget,\n ...(opts.backend ? { backend: opts.backend } : {}),\n ...(opts.deliverable ? { deliverable: opts.deliverable as DeliverableSpec<unknown> } : {}),\n router: opts.router,\n ...(opts.allowedModels ? { allowedModels: opts.allowedModels } : {}),\n ...(opts.runId ? { runId: opts.runId } : {}),\n }) as Promise<SupervisedResult<Out>>\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"delegate-BYLjG7Ev.js","names":[],"sources":["../src/runtime/supervise/authoring.ts","../src/runtime/supervise/delegate.ts"],"sourcesContent":["/**\n *\n * The supervisor's intelligence is AUTHORING the agents it spawns — not pressing buttons.\n *\n * Every agent here is three things: instructions, tools, and a model — its\n * `AgentProfile`. The supervisor's job is to WRITE those profiles: read the task, decompose it,\n * and for each sub-task author a tailored worker recipe. `supervisorInstructions` is the how-to the\n * supervisor reads; canonical Runtime executors materialize the resulting profile.\n *\n * The skill is the single OPTIMIZABLE surface: edit it → the supervisor designs better agents.\n * That is the self-improvement lever (the prompt/skill lever), not the execution plumbing.\n *\n * @experimental\n */\n\nimport { type AnalystFinding, computeFindingId, makeFinding } from '@tangle-network/agent-eval'\nimport {\n type AgentProfile,\n type AgentProfilePrompt,\n agentProfileSchema,\n} from '@tangle-network/agent-interface'\n\n/** What the supervisor AUTHORS per sub-task: one complete canonical profile whose name and\n * task-specific guidance are present. Every other `AgentProfile` axis is preserved exactly. */\nexport type AuthoredProfile = AgentProfile & {\n readonly name: string\n readonly prompt: AgentProfilePrompt\n}\n\n/** Narrow an untyped `spawn_worker` profile argument to an `AuthoredProfile`, or null if the\n * supervisor failed to author one (empty/placeholder profile — a skill violation worth catching). */\nexport function asAuthoredProfile(raw: unknown): AuthoredProfile | null {\n const parsed = agentProfileSchema.safeParse(raw)\n if (!parsed.success) return null\n if (!resolveSystemPrompt(parsed.data).trim()) return null\n return {\n ...parsed.data,\n name:\n typeof parsed.data.name === 'string' && parsed.data.name.length > 0\n ? parsed.data.name\n : 'worker',\n prompt: { ...parsed.data.prompt },\n }\n}\n\n/** The supervisor skill: an explicit profile-authoring instruction, never an implicit Runtime\n * policy. Editing this text changes how a profile designs the descendants it spawns. */\nexport function supervisorInstructions(opts?: { goal?: string }): string {\n return [\n 'Your delegation craft is AUTHORING: a spawned worker is exactly as good as the profile you write.',\n '',\n 'For the task you are given:',\n '1. DECOMPOSE it into the smallest set of sub-tasks a single focused worker can each deliver.',\n '2. For EACH sub-task, AUTHOR a worker by calling spawn_worker with a COMPLETE `profile`:',\n ' • name and description: who this specialist is and why it exists.',\n ' • prompt.appendSystemPrompt: rich additive instructions for THIS sub-task — exact output, process, evidence, and what \"done\" means.',\n ' • model.default, model.reasoningEffort, and harness: choose the execution system deliberately when the task benefits from it.',\n ' • tools, mcp, resources.skills/files/instructions, hooks, subagents, permissions, and modes: grant or attach every capability the worker needs; omit an axis only when it is intentionally unnecessary.',\n ' • tools.agent_runtime_coordination_spawn_worker: true ONLY when this child should author and drive descendants. Add only the other agent_runtime_coordination_<verb> tools it will call, such as observe_agent or steer_agent.',\n ' • A child with spawn_worker MUST carry this complete profile-authoring instruction as an immutable resources.skills entry with resources.failOnError: true, so it can author its own descendants from the same contract.',\n ' • metadata may describe the work, but it never grants recursion or selects a Runtime execution path.',\n ' NEVER spawn a worker with an empty profile. The quality of the worker IS the quality of the profile you write.',\n '3. End your turn while your workers run: Runtime wakes you with each settled worker. A settlement says valid:true only if the deployable check passed.',\n '4. If a worker did NOT deliver, AUTHOR A NEW profile whose prompt.appendSystemPrompt names the SPECIFIC failure and how to fix it — never just retry the same profile.',\n \"5. read_journal to re-read YOUR OWN record before you decide the next move: every spawn you made, every settle, every question and answer, every steer, every analyst finding — oldest first, this node only, including what you did before a restart. Use it to see what you already tried instead of trying it again. It is paged: pass the returned nextRow as the next call's sinceRow, narrow with kinds, and raise limit/maxBytes only as far as you will actually read. A truncated:true page means a bound cut it short — keep paging before you conclude you have read everything.\",\n '6. AUTHOR YOUR OWN LENS when the questions you can already ask of a settled trace do not cover the failure you are chasing: define_analyst takes an id, a description, an area, the question in your own words, the instructions for answering it with trace evidence, and the smallest toolGroup that can answer it (model is the seat it runs on; omit it for the run default). It is DATA, never code. Then run_analyst it on any settled worker like a lens the run shipped with, and read the finding. list_analysts shows what you have. Define a lens when you need a different question asked — not a second copy of a question already on the menu.',\n '7. EVERY refusal you get back carries a `reason` naming the exact unmet condition. Read it and change that condition — a spawn refused for budget-exhausted needs a smaller budget or the refund of a settled worker, an invalid-profile needs the named field fixed, a submit_result refused because the check THREW is a broken check to report, not a result to resubmit. Never repeat a call that was refused without changing what it was refused for.',\n '8. ask_parent ONLY when you genuinely cannot decide, and then READ ITS OUTCOME. \"queued-for-parent\" means an inbox above you now holds the question. \"no-parent\" means no inbox above you is configured to receive it: the question is still on the run record for anyone watching, but nothing will route an answer back to you, so do not block. Decide it with answer_question, or answer_question with deferReason to record that it stays open, and carry on — a blocking question left undecided also refuses your stop.',\n '9. Once the work is delivered, end your turn with nothing left running.',\n ...(opts?.goal ? ['', `The goal: ${opts.goal}`] : []),\n ].join('\\n')\n}\n\n// ── Profile-richness gate ────────────────────────────────────────────────────\n//\n// The supervisor's product is the worker PROFILE it authors. The failure mode the existing\n// gates miss: `asAuthoredProfile` / `local-harness` only reject a FULLY EMPTY system prompt —\n// a two-sentence stub passes. `assessAuthoredProfile` OBSERVES the authored artifact (it reads\n// no judge verdict, so it steers cleanly past `assertTraceDerivedFindings`) and flags THIN:\n// a short/few-line system prompt, OR no tools, OR no skills, OR no MCP when the task needs one.\n// It emits a real `AnalystFinding` so it rides the SAME coordination bus the driver pulls via\n// receives in its next wake — the supervisor can self-correct and re-author richer.\n\n/** Thresholds below which a system prompt is treated as a thin stub. Tunable per call. */\nexport interface ProfileRichnessThresholds {\n /** A prompt shorter than this many characters is thin (default 600). */\n readonly minSystemPromptChars: number\n /** A prompt with fewer than this many non-blank lines is thin (default 6). */\n readonly minSystemPromptLines: number\n}\n\n/** Default thresholds for `ProfileRichnessThresholds` — 600 chars / 6 lines minimum system prompt. */\nexport const defaultProfileRichnessThresholds: ProfileRichnessThresholds = {\n minSystemPromptChars: 600,\n minSystemPromptLines: 6,\n}\n\n/** Per-field verdict on one authored profile — the raw material the bench renders + scores. */\nexport interface ProfileRichness {\n readonly name: string\n /** Resolved authored guidance from replacement, addition and instruction sections. */\n readonly systemPrompt: string\n readonly systemPromptChars: number\n readonly systemPromptLines: number\n readonly sentenceCount: number\n readonly hasDescription: boolean\n readonly hasTools: boolean\n readonly hasSkills: boolean\n readonly hasMcp: boolean\n readonly hasSubagents: boolean\n /** 0..1 — fraction of richness signals present (prompt-depth + the four levers). */\n readonly richness: number\n /** True when the supervisor authored a stub instead of a real profile. */\n readonly thin: boolean\n /** The specific reasons it is thin (empty when rich) — used in the finding's action. */\n readonly reasons: string[]\n}\n\n/** Read authored guidance without requiring replacement of native coding instructions. */\nfunction resolveSystemPrompt(profile: AgentProfile): string {\n const pr = (profile as { prompt?: unknown }).prompt\n if (typeof pr === 'string') return pr\n if (pr && typeof pr === 'object') {\n const o = pr as { systemPrompt?: unknown; system?: unknown }\n return [\n Reflect.get(o, 'systemPrompt'),\n Reflect.get(o, 'appendSystemPrompt'),\n ...(Array.isArray(Reflect.get(o, 'instructions')) ? Reflect.get(o, 'instructions') : []),\n Reflect.get(o, 'system'),\n ]\n .filter((value) => typeof value === 'string')\n .join('\\n\\n')\n }\n return ''\n}\n\n/** OBSERVE one authored `AgentProfile` and score its richness (no judge verdict is read). The task\n * context (`needsMcp`) lets a domain say \"this work needs a data/tool MCP\" so a missing MCP counts. */\nexport function assessAuthoredProfile(\n profile: AgentProfile,\n opts?: { needsMcp?: boolean; thresholds?: Partial<ProfileRichnessThresholds> },\n): ProfileRichness {\n const th = { ...defaultProfileRichnessThresholds, ...(opts?.thresholds ?? {}) }\n const systemPrompt = resolveSystemPrompt(profile)\n const trimmed = systemPrompt.trim()\n const systemPromptChars = trimmed.length\n const systemPromptLines = trimmed\n ? trimmed.split('\\n').filter((l) => l.trim().length > 0).length\n : 0\n const sentenceCount = trimmed\n ? (trimmed.match(/[.!?](\\s|$)/g) ?? []).length || (trimmed ? 1 : 0)\n : 0\n const hasDescription =\n typeof profile.description === 'string' && profile.description.trim().length > 0\n const tools = (profile as { tools?: Record<string, unknown> }).tools\n const hasTools = !!tools && Object.keys(tools).length > 0\n const skills = (profile.resources as { skills?: unknown[] } | undefined)?.skills\n const hasSkills = Array.isArray(skills) && skills.length > 0\n const mcp = (profile as { mcp?: Record<string, unknown> }).mcp\n const hasMcp = !!mcp && Object.keys(mcp).length > 0\n const subagents = (profile as { subagents?: Record<string, unknown> }).subagents\n const hasSubagents = !!subagents && Object.keys(subagents).length > 0\n\n const reasons: string[] = []\n const promptThin =\n systemPromptChars < th.minSystemPromptChars || systemPromptLines < th.minSystemPromptLines\n if (promptThin)\n reasons.push(\n `system prompt is thin (${systemPromptChars} chars, ${systemPromptLines} lines; need ≥${th.minSystemPromptChars} chars and ≥${th.minSystemPromptLines} lines)`,\n )\n if (!hasTools)\n reasons.push('no tools granted (a worker can only act through the tools you grant it)')\n if (!hasSkills) reasons.push('no skills attached (no reusable how-to notes injected)')\n if (opts?.needsMcp && !hasMcp) reasons.push('no MCP server, but the task needs data/tool access')\n\n // Richness = fraction of signals present. Prompt-depth is one signal; the four levers are the rest.\n const signals = [!promptThin, hasTools, hasSkills, hasDescription, opts?.needsMcp ? hasMcp : true]\n const richness = signals.filter(Boolean).length / signals.length\n // THIN ⟺ the prompt is a stub OR the worker has no levers at all (no tools AND no skills AND no mcp).\n const thin = promptThin || (!hasTools && !hasSkills && !hasMcp)\n\n return {\n name: profile.name ?? 'worker',\n systemPrompt,\n systemPromptChars,\n systemPromptLines,\n sentenceCount,\n hasDescription,\n hasTools,\n hasSkills,\n hasMcp,\n hasSubagents,\n richness,\n thin,\n reasons,\n }\n}\n\n/** Turn a {@link ProfileRichness} verdict into a bus-routable `AnalystFinding` (area `profile-quality`).\n * Severity scales with thinness; the recommended action names the MISSING lever so the supervisor can\n * re-author. `subject` = the worker name so per-worker findings diff cleanly across re-authors. */\nexport function profileRichnessFinding(\n richness: ProfileRichness,\n opts?: { analystId?: string; runId?: string },\n): AnalystFinding {\n const analyst_id = opts?.analystId ?? 'profile-richness'\n const subject = richness.name\n const claim = richness.thin\n ? `Worker \"${richness.name}\" was authored as a THIN profile: ${richness.reasons.join('; ')}.`\n : `Worker \"${richness.name}\" was authored as a rich profile (richness ${(richness.richness * 100).toFixed(0)}%).`\n const severity: AnalystFinding['severity'] = richness.thin\n ? richness.richness < 0.25\n ? 'high'\n : 'medium'\n : 'info'\n return makeFinding({\n analyst_id,\n severity,\n area: 'profile-quality',\n claim,\n subject,\n confidence: 0.9,\n evidence_refs: [\n {\n kind: 'metric',\n uri: `profile:${subject}`,\n excerpt: `chars=${richness.systemPromptChars} lines=${richness.systemPromptLines} tools=${richness.hasTools} skills=${richness.hasSkills} mcp=${richness.hasMcp} richness=${richness.richness.toFixed(2)}`,\n },\n ],\n ...(richness.thin\n ? { recommended_action: `Re-author \"${richness.name}\" with: ${richness.reasons.join('; ')}.` }\n : {}),\n id_basis: computeFindingId({\n analyst_id,\n area: 'profile-quality',\n subject,\n claim: `richness:${richness.thin ? 'thin' : 'rich'}`,\n }),\n })\n}\n","/**\n *\n * `delegate` — the one generic delegation verb. You hand it an INTENT (what you want done) and it\n * hands that intent to a default AUTHORING supervisor: a router-brained supervisor whose standing\n * instruction is `supervisorInstructions()` (the authoring-agent-profiles skill). The supervisor\n * DECOMPOSES the intent and AUTHORS the worker profile it needs per sub-task — there is NO hardcoded\n * coder/researcher profile here. That is the whole point: `delegate('fix the failing test', …)` and\n * `delegate('research X and cite sources', …)` route through the SAME front door; the supervisor\n * writes a code-shaped or research-shaped worker on its own.\n *\n * It is a thin wrapper over `supervise()` — the one front door — so the conserved-budget pool, the\n * completion oracle (`deliverable`), the coordination toolbox, and equal-compute accounting all come\n * for free; nothing is hand-rolled. The result is `supervise()`'s `SupervisedResult` returned\n * UNCHANGED, so its `spentTotal` (`{ iterations, tokens, usd, ms }`) rides straight back to the\n * caller on BOTH paths — a `winner` carries the delivered worker's spend, a `no-winner` carries the\n * spend incurred before it failed. That cost channel means a `delegate()` caller always learns what\n * the delegation actually spent.\n *\n * @experimental\n */\n\nimport { ConfigError } from '../../errors'\nimport type { RouterTransportConfig } from '../router-http-transport'\nimport type { DeliverableSpec } from './completion-gate'\nimport type { ExecutorConfig } from './runtime'\nimport { supervise } from './supervise'\nimport type { SupervisorProfile } from './supervisor-agent'\nimport type { Budget, SupervisedResult } from './types'\n\n/** The conserved pool a `delegate()` call applies when the caller does not pass its own `budget`.\n * A modest token ceiling + a small iteration ceiling — generous enough for a few-worker decompose,\n * bounded enough that an unsupervised intent cannot run away. Callers override via `opts.budget`. */\nexport const defaultDelegateBudget: Budget = { maxIterations: 50, maxTokens: 200_000 }\n\n/** Inputs to {@link delegate}. The intent is the first positional arg; everything here is optional\n * with explicit execution identity, so the common call names one exact supervisor profile. */\nexport interface DelegateOptions<Out = unknown> {\n /** The completion oracle (settled ⟺ delivered) the authored workers settle against. Strongly\n * recommended — without it the supervisor trusts a worker's self-report. For a code intent,\n * `patchDelivered()` is the canonical example; for a free-form answer, a content check. */\n readonly deliverable?: DeliverableSpec<Out>\n /** WHERE the authored workers run — the worker-execution backend (`router-tools` / `sandbox` /\n * `cli-worktree` / …). The supervisor authors the worker PROFILE; this is the substrate it runs\n * on. Provide this OR `makeWorkerAgent`-style wiring through `supervise()` is unavailable. */\n readonly backend?: ExecutorConfig\n /** The conserved compute pool for the whole delegation. Defaults to {@link defaultDelegateBudget}. */\n readonly budget?: Budget\n /** Exact executable authoring supervisor. Model, prompt, harness, and provider live here. */\n readonly supervisorProfile: SupervisorProfile\n /** Router endpoint/auth for a `cli-base` supervisor; contains no behavioral settings. */\n readonly router: RouterTransportConfig\n /** Restrict the run to this subset of models (forwarded to `supervise()`). */\n readonly allowedModels?: readonly string[]\n readonly runId?: string\n}\n\n/**\n * Delegate an INTENT to a default authoring supervisor and return its `SupervisedResult` unchanged.\n *\n * The supervisor authors + spawns whatever worker the intent needs over the conserved-budget pool;\n * `result.spentTotal` reports what the whole delegation actually cost. A `winner` result carries the\n * authored worker's delivered output; a `no-winner` result names why (never a fabricated success).\n */\nexport async function delegate<Out = unknown>(\n intent: string,\n opts: DelegateOptions<Out>,\n): Promise<SupervisedResult<Out>> {\n if (typeof intent !== 'string' || intent.trim().length === 0) {\n throw new ConfigError('delegate: `intent` must be a non-empty string')\n }\n return supervise(opts.supervisorProfile, intent, {\n budget: opts.budget ?? defaultDelegateBudget,\n ...(opts.backend ? { backend: opts.backend } : {}),\n ...(opts.deliverable ? { deliverable: opts.deliverable as DeliverableSpec<unknown> } : {}),\n router: opts.router,\n ...(opts.allowedModels ? { allowedModels: opts.allowedModels } : {}),\n ...(opts.runId ? { runId: opts.runId } : {}),\n }) as Promise<SupervisedResult<Out>>\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,kBAAkB,KAAsC;CACtE,MAAM,SAAS,mBAAmB,UAAU,GAAG;CAC/C,IAAI,CAAC,OAAO,SAAS,OAAO;CAC5B,IAAI,CAAC,oBAAoB,OAAO,IAAI,CAAC,CAAC,KAAK,GAAG,OAAO;CACrD,OAAO;EACL,GAAG,OAAO;EACV,MACE,OAAO,OAAO,KAAK,SAAS,YAAY,OAAO,KAAK,KAAK,SAAS,IAC9D,OAAO,KAAK,OACZ;EACN,QAAQ,EAAE,GAAG,OAAO,KAAK,OAAO;CAClC;AACF;;;AAIA,SAAgB,uBAAuB,MAAkC;CACvE,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,GAAI,MAAM,OAAO,CAAC,IAAI,aAAa,KAAK,MAAM,IAAI,CAAC;CACrD,CAAC,CAAC,KAAK,IAAI;AACb;;AAqBA,MAAa,mCAA8D;CACzE,sBAAsB;CACtB,sBAAsB;AACxB;;AAwBA,SAAS,oBAAoB,SAA+B;CAC1D,MAAM,KAAM,QAAiC;CAC7C,IAAI,OAAO,OAAO,UAAU,OAAO;CACnC,IAAI,MAAM,OAAO,OAAO,UAAU;EAChC,MAAM,IAAI;EACV,OAAO;GACL,QAAQ,IAAI,GAAG,cAAc;GAC7B,QAAQ,IAAI,GAAG,oBAAoB;GACnC,GAAI,MAAM,QAAQ,QAAQ,IAAI,GAAG,cAAc,CAAC,IAAI,QAAQ,IAAI,GAAG,cAAc,IAAI,CAAC;GACtF,QAAQ,IAAI,GAAG,QAAQ;EACzB,CAAC,CACE,QAAQ,UAAU,OAAO,UAAU,QAAQ,CAAC,CAC5C,KAAK,MAAM;CAChB;CACA,OAAO;AACT;;;AAIA,SAAgB,sBACd,SACA,MACiB;CACjB,MAAM,KAAK;EAAE,GAAG;EAAkC,GAAI,MAAM,cAAc,CAAC;CAAG;CAC9E,MAAM,eAAe,oBAAoB,OAAO;CAChD,MAAM,UAAU,aAAa,KAAK;CAClC,MAAM,oBAAoB,QAAQ;CAClC,MAAM,oBAAoB,UACtB,QAAQ,MAAM,IAAI,CAAC,CAAC,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SACvD;CACJ,MAAM,gBAAgB,WACjB,QAAQ,MAAM,cAAc,KAAK,CAAC,EAAA,CAAG,WAAW,UAAU,IAAI,KAC/D;CACJ,MAAM,iBACJ,OAAO,QAAQ,gBAAgB,YAAY,QAAQ,YAAY,KAAK,CAAC,CAAC,SAAS;CACjF,MAAM,QAAS,QAAgD;CAC/D,MAAM,WAAW,CAAC,CAAC,SAAS,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS;CACxD,MAAM,SAAU,QAAQ,WAAkD;CAC1E,MAAM,YAAY,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS;CAC3D,MAAM,MAAO,QAA8C;CAC3D,MAAM,SAAS,CAAC,CAAC,OAAO,OAAO,KAAK,GAAG,CAAC,CAAC,SAAS;CAClD,MAAM,YAAa,QAAoD;CACvE,MAAM,eAAe,CAAC,CAAC,aAAa,OAAO,KAAK,SAAS,CAAC,CAAC,SAAS;CAEpE,MAAM,UAAoB,CAAC;CAC3B,MAAM,aACJ,oBAAoB,GAAG,wBAAwB,oBAAoB,GAAG;CACxE,IAAI,YACF,QAAQ,KACN,0BAA0B,kBAAkB,UAAU,kBAAkB,gBAAgB,GAAG,qBAAqB,cAAc,GAAG,qBAAqB,QACxJ;CACF,IAAI,CAAC,UACH,QAAQ,KAAK,yEAAyE;CACxF,IAAI,CAAC,WAAW,QAAQ,KAAK,wDAAwD;CACrF,IAAI,MAAM,YAAY,CAAC,QAAQ,QAAQ,KAAK,oDAAoD;CAGhG,MAAM,UAAU;EAAC,CAAC;EAAY;EAAU;EAAW;EAAgB,MAAM,WAAW,SAAS;CAAI;CACjG,MAAM,WAAW,QAAQ,OAAO,OAAO,CAAC,CAAC,SAAS,QAAQ;CAE1D,MAAM,OAAO,cAAe,CAAC,YAAY,CAAC,aAAa,CAAC;CAExD,OAAO;EACL,MAAM,QAAQ,QAAQ;EACtB;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;;;;AAKA,SAAgB,uBACd,UACA,MACgB;CAChB,MAAM,aAAa,MAAM,aAAa;CACtC,MAAM,UAAU,SAAS;CACzB,MAAM,QAAQ,SAAS,OACnB,WAAW,SAAS,KAAK,oCAAoC,SAAS,QAAQ,KAAK,IAAI,EAAE,KACzF,WAAW,SAAS,KAAK,8CAA8C,SAAS,WAAW,IAAA,CAAK,QAAQ,CAAC,EAAE;CAC/G,MAAM,WAAuC,SAAS,OAClD,SAAS,WAAW,MAClB,SACA,WACF;CACJ,OAAO,YAAY;EACjB;EACA;EACA,MAAM;EACN;EACA;EACA,YAAY;EACZ,eAAe,CACb;GACE,MAAM;GACN,KAAK,WAAW;GAChB,SAAS,SAAS,SAAS,kBAAkB,SAAS,SAAS,kBAAkB,SAAS,SAAS,SAAS,UAAU,SAAS,UAAU,OAAO,SAAS,OAAO,YAAY,SAAS,SAAS,QAAQ,CAAC;EACzM,CACF;EACA,GAAI,SAAS,OACT,EAAE,oBAAoB,cAAc,SAAS,KAAK,UAAU,SAAS,QAAQ,KAAK,IAAI,EAAE,GAAG,IAC3F,CAAC;EACL,UAAU,iBAAiB;GACzB;GACA,MAAM;GACN;GACA,OAAO,YAAY,SAAS,OAAO,SAAS;EAC9C,CAAC;CACH,CAAC;AACH;;;;;;;;;;;;;;;;;;;;;;;;;AC/MA,MAAa,wBAAgC;CAAE,eAAe;CAAI,WAAW;AAAQ;;;;;;;;AA+BrF,eAAsB,SACpB,QACA,MACgC;CAChC,IAAI,OAAO,WAAW,YAAY,OAAO,KAAK,CAAC,CAAC,WAAW,GACzD,MAAM,IAAI,YAAY,+CAA+C;CAEvE,OAAO,UAAU,KAAK,mBAAmB,QAAQ;EAC/C,QAAQ,KAAK,UAAU;EACvB,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;EAChD,GAAI,KAAK,cAAc,EAAE,aAAa,KAAK,YAAwC,IAAI,CAAC;EACxF,QAAQ,KAAK;EACb,GAAI,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,IAAI,CAAC;EAClE,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;CAC5C,CAAC;AACH"}
package/dist/durable.js CHANGED
@@ -1,16 +1,16 @@
1
- import { Di as assertValidBudget, L as FileSpawnJournal, Ut as loadSpawnForest, Yt as FileResultBlobStore, _ as supervisorRunDir, a as readRootStream, gi as contentAddress, hn as observerRecordDigest, mn as createFileObserverHooks, o as readRootStreamReceipt, pn as FileObserverJournal, qr as runtimeFailureCause, xr as authoredProfileDigest, y as workerCancellationsDir } from "./scope-CpULJrAr.js";
1
+ import { Di as assertValidBudget, L as FileSpawnJournal, Ut as loadSpawnForest, Yt as FileResultBlobStore, _ as supervisorRunDir, a as readRootStream, gi as contentAddress, hn as observerRecordDigest, mn as createFileObserverHooks, o as readRootStreamReceipt, pn as FileObserverJournal, qr as runtimeFailureCause, xr as authoredProfileDigest, y as workerCancellationsDir } from "./scope-BGWRFiYt.js";
2
2
  import { f as RuntimeRunStateError, m as ValidationError } from "./errors-AzSuGI23.js";
3
3
  import { Y as errorMessage } from "./workspace-streams-8ALHaZzx.js";
4
- import { n as isNoEntError } from "./jsonl-file-BBP9Dz9w.js";
5
- import { Dt as failedItems, Ot as isFiniteNumber, i as RunParkedError, r as assertResumeLimits, s as readRunParking } from "./supervisor-CWTFw-lP.js";
4
+ import { t as isNoEntError } from "./jsonl-file-CbxMVnUj.js";
5
+ import { Dt as failedItems, Ot as isFiniteNumber, i as RunParkedError, r as assertResumeLimits, s as readRunParking } from "./supervisor-BDnqTl_R.js";
6
6
  import { a as writeAtomicDurableFile, c as mutateRunClaim, i as syncDurableDirectory, l as runGenerationPath, r as publishExclusiveDurableFile, s as fenceRunWrite, u as runWithWriteClaim } from "./durable-file-DstVeHcj.js";
7
7
  import { a as withPursuitContext, t as composeRuntimeHooks } from "./runtime-hooks-CsW2pfFk.js";
8
8
  import { a as applyExactAgentProfileDiff } from "./profile-ClvuI8aY.js";
9
- import { a as runCancelRequestFile, h as rootCoordinationOwner, o as runCancellationFile, v as FileCoordinationLog } from "./run-cancellation-CRPdLJVP.js";
10
- import { a as superviseRootProfile, p as runToolSpans, t as supervise } from "./supervise-Dszn1xVB.js";
11
- import { a as graphExecutionOptions, i as superviseAgentGraph } from "./graph-BBQ6L1Mc.js";
9
+ import { a as runCancelRequestFile, h as rootCoordinationOwner, o as runCancellationFile, v as FileCoordinationLog } from "./run-cancellation-BzmmqlM8.js";
10
+ import { a as superviseRootProfile, p as runToolSpans, t as supervise } from "./supervise-BfT708zt.js";
11
+ import { a as graphExecutionOptions, i as superviseAgentGraph } from "./graph-T1-PBhLx.js";
12
12
  import { n as handleChatTurn, t as deriveExecutionId } from "./execution-handle-Bd2_nUB6.js";
13
- import { a as parseSettleRecord, c as settleRecordDigest, d as projectPursuit, i as SettledRunDirectoryError, l as writeFailureRecord, n as FAILURE_RECORD_FILE, o as readFailureRecord, r as SETTLE_RECORD_FILE, s as readSettleRecord, t as discoverDurableSupervisionRun, u as writeSettleRecord } from "./supervision-discovery-1UUbaYC6.js";
13
+ import { a as parseSettleRecord, c as settleRecordDigest, d as projectPursuit, i as SettledRunDirectoryError, l as writeFailureRecord, n as FAILURE_RECORD_FILE, o as readFailureRecord, r as SETTLE_RECORD_FILE, s as readSettleRecord, t as discoverDurableSupervisionRun, u as writeSettleRecord } from "./supervision-discovery-C2Tjw6LX.js";
14
14
  import { agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, sha256Bytes } from "@tangle-network/agent-interface";
15
15
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
16
16
  import { closeSync, existsSync, fstatSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, unlinkSync } from "node:fs";
@@ -1,11 +1,11 @@
1
- import { Gr as runtimeFlowBrain, gi as contentAddress } from "./scope-CpULJrAr.js";
1
+ import { Gr as runtimeFlowBrain, gi as contentAddress } from "./scope-BGWRFiYt.js";
2
2
  import { i as ConfigError, m as ValidationError } from "./errors-AzSuGI23.js";
3
- import { c as withJsonlFileLock, o as readCommittedJsonLines, t as appendCommittedJsonLine } from "./jsonl-file-BBP9Dz9w.js";
4
- import { Bt as defaultRunCommand } from "./supervisor-CWTFw-lP.js";
3
+ import { a as readCommittedJsonLines, c as appendCommittedJsonLine, s as withJsonlFileLock } from "./jsonl-file-CbxMVnUj.js";
4
+ import { Bt as defaultRunCommand } from "./supervisor-BDnqTl_R.js";
5
5
  import { v as harnessRunsAgent } from "./model-policy-JOcg3NRs.js";
6
6
  import { t as composeRuntimeHooks } from "./runtime-hooks-CsW2pfFk.js";
7
- import { f as createFileRunContext, m as withRunContext, p as createInMemoryRunContext } from "./coordination-manager-B3mF1nMA.js";
8
- import { C as flowRootProfile, E as validateFlowGraph, I as kernelPromptRegistry, O as graphRootProfile, S as createFlowRun, T as routeFlowOf, b as createGraphOverlay, i as profileGuidanceComposer, k as validateGraphTopology, r as superviseWithTestBrain, t as supervise, w as journaledGateDecider, x as GraphRouteError } from "./supervise-Dszn1xVB.js";
7
+ import { f as createFileRunContext, m as withRunContext, p as createInMemoryRunContext } from "./coordination-manager-C_ohXf63.js";
8
+ import { C as flowRootProfile, E as validateFlowGraph, I as kernelPromptRegistry, O as graphRootProfile, S as createFlowRun, T as routeFlowOf, b as createGraphOverlay, i as profileGuidanceComposer, k as validateGraphTopology, r as superviseWithTestBrain, t as supervise, w as journaledGateDecider, x as GraphRouteError } from "./supervise-BfT708zt.js";
9
9
  import { canonicalCandidateDigest } from "@tangle-network/agent-interface";
10
10
  import { mkdirSync, realpathSync } from "node:fs";
11
11
  import { isAbsolute, join, relative, resolve } from "node:path";
@@ -577,4 +577,4 @@ function superviseAgentGraph(graph, opts, brain) {
577
577
  }
578
578
  export { graphExecutionOptions as a, superviseAgentGraph as i, runGraph as n, runGraphWithTestBrain as r, GraphEdgeCapError as t };
579
579
 
580
- //# sourceMappingURL=graph-BBQ6L1Mc.js.map
580
+ //# sourceMappingURL=graph-T1-PBhLx.js.map