@wrongstack/core 0.280.1 → 0.281.1

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 (95) hide show
  1. package/dist/{agent-subagent-runner-PoqNKiR4.d.ts → agent-subagent-runner-DyOSK2Wy.d.ts} +39 -8
  2. package/dist/{compactor-U3agvUIG.d.ts → compactor-BxddyCFu.d.ts} +1 -1
  3. package/dist/{config-Cr3312zc.d.ts → config-CN-vdDEI.d.ts} +82 -2
  4. package/dist/coordination/index.d.ts +203 -20
  5. package/dist/coordination/index.js +981 -52
  6. package/dist/coordination/index.js.map +1 -1
  7. package/dist/defaults/index.d.ts +26 -30
  8. package/dist/defaults/index.js +382 -30
  9. package/dist/defaults/index.js.map +1 -1
  10. package/dist/{events-Bs2fmldo.d.ts → events-C5hLU0AT.d.ts} +38 -2
  11. package/dist/execution/index.d.ts +16 -16
  12. package/dist/execution/index.js +161 -18
  13. package/dist/execution/index.js.map +1 -1
  14. package/dist/execution/prompt-enhancer.d.ts +1 -1
  15. package/dist/execution/prompt-enhancer.js +12 -3
  16. package/dist/execution/prompt-enhancer.js.map +1 -1
  17. package/dist/extension/index.d.ts +6 -6
  18. package/dist/{global-mailbox-Ct7IorLJ.d.ts → global-mailbox-CHM1QkCi.d.ts} +5 -2
  19. package/dist/{goal-store-C4F6DjC0.d.ts → goal-store-BLGZq16t.d.ts} +1 -1
  20. package/dist/hq/index.d.ts +6 -6
  21. package/dist/hq/index.js +35 -13
  22. package/dist/hq/index.js.map +1 -1
  23. package/dist/{index-nP09-oP2.d.ts → index-BEFWNZYs.d.ts} +1 -2
  24. package/dist/{index-kidebiDh.d.ts → index-C1E-_71T.d.ts} +6 -6
  25. package/dist/index.d.ts +44 -48
  26. package/dist/index.js +14855 -13944
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +60 -8
  29. package/dist/infrastructure/index.js.map +1 -1
  30. package/dist/kernel/index.d.ts +11 -11
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mcp-servers-D910X5_r.d.ts → mcp-servers-EKRAcJDi.d.ts} +97 -4
  33. package/dist/models/index.d.ts +4 -5
  34. package/dist/models/index.js +22 -5
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/{multi-agent-coordinator-CieyUoEL.d.ts → multi-agent-coordinator-IpHCuHUa.d.ts} +29 -1
  37. package/dist/{null-fleet-bus-DkdmZJ_W.d.ts → null-fleet-bus-ZBkKGR9j.d.ts} +105 -7
  38. package/dist/observability/index.d.ts +3 -3
  39. package/dist/{tool-executor-SiE1wlZo.d.ts → parallel-eternal-engine-Cc2CNgmv.d.ts} +6 -202
  40. package/dist/path-resolver-CMS5307d.d.ts +13 -0
  41. package/dist/{permission-Dx6dIqS2.d.ts → permission-B6YAtNFz.d.ts} +1 -1
  42. package/dist/{pipeline-BwAP21_4.d.ts → pipeline-E7_jqGyV.d.ts} +2 -2
  43. package/dist/{provider-model-resolve-CwQNZWt_.d.ts → provider-model-resolve-KgIdiEQ6.d.ts} +118 -5
  44. package/dist/{provider-runner-CYHFImzV.d.ts → provider-runner-DxWXNHL1.d.ts} +3 -3
  45. package/dist/{retry-policy-D4feSLk3.d.ts → retry-policy-V67lBOJz.d.ts} +2 -2
  46. package/dist/sdd/index.d.ts +9 -9
  47. package/dist/sdd/index.js +94 -10
  48. package/dist/sdd/index.js.map +1 -1
  49. package/dist/{permission-policy-C8vJcnX5.d.ts → secret-vault-D7jeyXUQ.d.ts} +119 -3
  50. package/dist/security/index.d.ts +5 -6
  51. package/dist/security/index.js +4 -1
  52. package/dist/security/index.js.map +1 -1
  53. package/dist/{selector-Dy-MzKp1.d.ts → selector-Bx2HgUkU.d.ts} +1 -1
  54. package/dist/{session-event-bridge-CqdiGnfU.d.ts → session-event-bridge-vA2fLV58.d.ts} +1 -1
  55. package/dist/{session-reader-Hk0WbNm9.d.ts → session-reader-B-Fi9L6I.d.ts} +1 -1
  56. package/dist/session-registry-Dvg7i_IA.d.ts +129 -0
  57. package/dist/storage/index.d.ts +71 -142
  58. package/dist/storage/index.js +161 -13
  59. package/dist/storage/index.js.map +1 -1
  60. package/dist/{todos-checkpoint-Bk2uP7Ex.d.ts → todos-checkpoint-B1QVkoa8.d.ts} +23 -5
  61. package/dist/{tool-BkOgs_KL.d.ts → tool-LVSLiE1s.d.ts} +18 -4
  62. package/dist/{strategy-compactor-CQwhbErd.d.ts → tool-executor-BWtYwuPI.d.ts} +210 -12
  63. package/dist/tools/index.d.ts +2 -2
  64. package/dist/tools/index.js.map +1 -1
  65. package/dist/types/index.d.ts +17 -41
  66. package/dist/types/index.js +182 -5085
  67. package/dist/types/index.js.map +1 -1
  68. package/dist/utils/index.d.ts +3 -3
  69. package/dist/utils/index.js +6 -1
  70. package/dist/utils/index.js.map +1 -1
  71. package/dist/{worktree-manager-BjOFF6bt.d.ts → worktree-manager-C6CIilTT.d.ts} +1 -1
  72. package/dist/{wstack-paths-CMl_cYgq.d.ts → wstack-paths-C3K40Qst.d.ts} +2 -0
  73. package/instructions/agents/shadow-agent.md +23 -84
  74. package/instructions/coordination/director-preamble.md +12 -3
  75. package/instructions/coordination/subagent-baseline.md +39 -46
  76. package/instructions/leader-after-task.md +10 -28
  77. package/instructions/llm/llm-selector.md +1 -2
  78. package/instructions/modes/brief-system.md +7 -33
  79. package/instructions/modes/brief.md +5 -20
  80. package/instructions/modes/teach-system.md +12 -72
  81. package/instructions/modes/teach.md +12 -49
  82. package/instructions/sections/tool/commit-hygiene.md +5 -5
  83. package/instructions/sections/tool/context-management-full.md +6 -6
  84. package/instructions/sections/tool/delegation-compact.md +1 -1
  85. package/instructions/sections/tool/delegation-full.md +19 -23
  86. package/instructions/sections/tool/mailbox-full.md +11 -31
  87. package/instructions/sections/tool/mcp-full-control.md +5 -7
  88. package/instructions/sections/tool/mcp-full-use.md +7 -7
  89. package/instructions/system.md +22 -38
  90. package/package.json +1 -29
  91. package/dist/agent-bridge-DXC6QDJ4.d.ts +0 -35
  92. package/dist/logger-D3lV0cUZ.d.ts +0 -101
  93. package/dist/models-registry-CLkoOcHk.d.ts +0 -108
  94. package/dist/path-resolver-XfZ9eLxG.d.ts +0 -67
  95. package/dist/secret-vault-CImt2XrR.d.ts +0 -118
@@ -371,6 +371,27 @@ function safeParse(input, maxBytes = 5e6) {
371
371
  };
372
372
  }
373
373
  }
374
+ function safeStringify(value, pretty = false) {
375
+ const seen = /* @__PURE__ */ new WeakSet();
376
+ const replacer = (_k, v) => {
377
+ if (typeof v === "bigint") return v.toString();
378
+ if (v instanceof Error) {
379
+ return { name: v.name, message: v.message, stack: v.stack };
380
+ }
381
+ if (typeof v === "object" && v !== null) {
382
+ if (seen.has(v)) return "[Circular]";
383
+ seen.add(v);
384
+ }
385
+ return v;
386
+ };
387
+ try {
388
+ return JSON.stringify(value, replacer, pretty ? 2 : void 0) ?? "null";
389
+ } catch (err) {
390
+ return JSON.stringify({
391
+ __serialization_error: toErrorMessage(err)
392
+ });
393
+ }
394
+ }
374
395
  function sessionScopedPath(dir, sessionId, suffix) {
375
396
  if (!sessionId || sessionId.includes("\\") || sessionId.includes("..")) {
376
397
  throw invalid(sessionId);
@@ -1385,20 +1406,32 @@ var TOOLS = {
1385
1406
  /** Web research. */
1386
1407
  research: ["read", "grep", "glob", "search", "fetch", "mailbox"]
1387
1408
  };
1409
+ var promptCache = /* @__PURE__ */ new Map();
1410
+ var candidateCache = /* @__PURE__ */ new Map();
1388
1411
  function agentPrompt(id) {
1412
+ const envDir = process.env["WRONGSTACK_AGENT_INSTRUCTIONS_DIR"] ?? "";
1413
+ const cacheKey = `${envDir}\0${id}`;
1414
+ const cached = promptCache.get(cacheKey);
1415
+ if (cached !== void 0) return cached;
1389
1416
  const fileName = `${id}.md`;
1390
- for (const dir of agentPromptDirCandidates()) {
1417
+ let resolved = "";
1418
+ for (const dir of agentPromptDirCandidates(envDir)) {
1391
1419
  try {
1392
- return readFileSync(path9.join(dir, fileName), "utf8").trimEnd();
1420
+ resolved = readFileSync(path9.join(dir, fileName), "utf8").trimEnd();
1421
+ break;
1393
1422
  } catch {
1394
1423
  }
1395
1424
  }
1396
- return "";
1425
+ promptCache.set(cacheKey, resolved);
1426
+ return resolved;
1397
1427
  }
1398
- function agentPromptDirCandidates() {
1399
- const here = path9.dirname(fileURLToPath(import.meta.url));
1400
- const explicitDir = process.env["WRONGSTACK_AGENT_INSTRUCTIONS_DIR"];
1428
+ function agentPromptDirCandidates(envDir) {
1401
1429
  const globalRoot = process.env["WRONGSTACK_HOME"] || path9.join(os.homedir(), ".wrongstack");
1430
+ const candKey = `${envDir}\0${globalRoot}`;
1431
+ const cached = candidateCache.get(candKey);
1432
+ if (cached !== void 0) return cached;
1433
+ const here = path9.dirname(fileURLToPath(import.meta.url));
1434
+ const explicitDir = envDir || void 0;
1402
1435
  const candidates = [
1403
1436
  ...explicitDir ? [path9.resolve(explicitDir)] : [],
1404
1437
  path9.join(globalRoot, "instructions", "agents"),
@@ -1408,7 +1441,9 @@ function agentPromptDirCandidates() {
1408
1441
  path9.resolve(here, "../instructions/agents"),
1409
1442
  path9.resolve(here, "instructions/agents")
1410
1443
  ];
1411
- return candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));
1444
+ const ordered = candidates.sort((a, b) => Number(!isDirectory(a)) - Number(!isDirectory(b)));
1445
+ candidateCache.set(candKey, ordered);
1446
+ return ordered;
1412
1447
  }
1413
1448
  function isDirectory(candidate) {
1414
1449
  try {
@@ -4670,14 +4705,21 @@ var DirectorStateCheckpoint = class {
4670
4705
  }
4671
4706
  }
4672
4707
  };
4708
+ var textCache = /* @__PURE__ */ new Map();
4709
+ var rootCandidates;
4673
4710
  function readBundledInstructionText(relativePath) {
4711
+ const cached = textCache.get(relativePath);
4712
+ if (cached !== void 0) return cached;
4713
+ let resolved = "";
4674
4714
  for (const root of instructionRootCandidates()) {
4675
4715
  try {
4676
- return readFileSync(path9.join(root, relativePath), "utf8").trimEnd();
4716
+ resolved = readFileSync(path9.join(root, relativePath), "utf8").trimEnd();
4717
+ break;
4677
4718
  } catch {
4678
4719
  }
4679
4720
  }
4680
- return "";
4721
+ textCache.set(relativePath, resolved);
4722
+ return resolved;
4681
4723
  }
4682
4724
  function renderInstructionTemplate(template, values) {
4683
4725
  return template.replace(
@@ -4686,13 +4728,15 @@ function renderInstructionTemplate(template, values) {
4686
4728
  );
4687
4729
  }
4688
4730
  function instructionRootCandidates() {
4731
+ if (rootCandidates !== void 0) return rootCandidates;
4689
4732
  const here = path9.dirname(fileURLToPath(import.meta.url));
4690
4733
  const candidates = [
4691
4734
  path9.resolve(here, "../../instructions"),
4692
4735
  path9.resolve(here, "../instructions"),
4693
4736
  path9.resolve(here, "instructions")
4694
4737
  ];
4695
- return candidates.sort((a, b) => Number(!isDirectory2(a)) - Number(!isDirectory2(b)));
4738
+ rootCandidates = candidates.sort((a, b) => Number(!isDirectory2(a)) - Number(!isDirectory2(b)));
4739
+ return rootCandidates;
4696
4740
  }
4697
4741
  function isDirectory2(candidate) {
4698
4742
  try {
@@ -5012,13 +5056,31 @@ function makeAssignTool(director) {
5012
5056
  function makeAwaitTasksTool(director) {
5013
5057
  return {
5014
5058
  name: "await_tasks",
5015
- description: "Block until every named task completes. Returns the array of TaskResult.",
5059
+ description: 'Wait for assigned tasks. mode:"all" (default) blocks until EVERY named task completes and returns all results. mode:"any" returns as soon as AT LEAST ONE completes \u2014 use it for independent tasks so you can handle each finisher immediately (reassign work, spawn helpers) instead of idling on the slowest; call again with the returned `pending` ids to pick up the next finisher.',
5016
5060
  permission: "auto",
5017
5061
  mutating: false,
5018
5062
  capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
5019
- inputSchema: { type: "object", properties: { taskIds: { type: "array", items: { type: "string" }, description: "One or more task ids returned by `assign_task`." } }, required: ["taskIds"] },
5063
+ inputSchema: {
5064
+ type: "object",
5065
+ properties: {
5066
+ taskIds: { type: "array", items: { type: "string" }, description: "One or more task ids returned by `assign_task`." },
5067
+ mode: { type: "string", enum: ["all", "any"], description: '"all" (default): block until every task completes. "any": return on the first completion with the rest listed as pending.' },
5068
+ timeoutMs: { type: "number", minimum: 1, description: 'mode:"any" only \u2014 return {timedOut:true, completed:[]} if nothing completes within this window instead of blocking.' }
5069
+ },
5070
+ required: ["taskIds"]
5071
+ },
5020
5072
  async execute(input) {
5021
5073
  const i = input;
5074
+ if (i.mode === "any") {
5075
+ const r = await director.awaitTasksAny(i.taskIds, i.timeoutMs !== void 0 ? { timeoutMs: i.timeoutMs } : void 0);
5076
+ return {
5077
+ mode: "any",
5078
+ completed: r.completed,
5079
+ pending: r.pending,
5080
+ ...r.timedOut ? { timedOut: true } : {},
5081
+ ...r.pending.length > 0 ? { hint: 'Handle the completed results now. Re-call await_tasks with the pending ids (mode:"any") for the next finisher \u2014 or assign new work to the now-idle subagent first.' } : {}
5082
+ };
5083
+ }
5022
5084
  const results = await director.awaitTasks(i.taskIds);
5023
5085
  return { results };
5024
5086
  }
@@ -6104,6 +6166,30 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
6104
6166
  results() {
6105
6167
  return this.completedResults;
6106
6168
  }
6169
+ /** Defensive snapshot of the still-queued (not yet dispatched) tasks. */
6170
+ listPendingTasks() {
6171
+ return this.pendingTasks.map((t) => ({ ...t }));
6172
+ }
6173
+ /**
6174
+ * Re-pin a still-PENDING task to a different subagent (`undefined` =
6175
+ * unpin, any idle worker may take it), then try to dispatch. Returns
6176
+ * `false` when the task is not in the pending queue — already
6177
+ * dispatched, completed, or unknown. Running tasks can never be pulled;
6178
+ * they can only be steered or terminated. The mutation is synchronous
6179
+ * (same tick as the check), so it cannot race a concurrent dispatch:
6180
+ * `tryDispatchNext` runs on this same call stack or a later one.
6181
+ *
6182
+ * The task keeps its id, so waiters, the report-back notifier, and
6183
+ * checkpoint bookkeeping resolve unchanged when it eventually completes.
6184
+ */
6185
+ retargetPendingTask(taskId, subagentId) {
6186
+ const task = this.pendingTasks.find((t) => t.id === taskId);
6187
+ if (!task) return false;
6188
+ if (subagentId !== void 0 && !this.subagents.has(subagentId)) return false;
6189
+ task.subagentId = subagentId;
6190
+ this.tryDispatchNext();
6191
+ return true;
6192
+ }
6107
6193
  /**
6108
6194
  * Wait for one or more tasks to complete and return their results.
6109
6195
  * If a task is already done when called, returns immediately.
@@ -6131,6 +6217,43 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
6131
6217
  })
6132
6218
  );
6133
6219
  }
6220
+ /**
6221
+ * Wait until AT LEAST ONE of the named tasks completes. Returns every
6222
+ * requested result already available at that moment (drain-what's-done)
6223
+ * plus the ids still outstanding, so callers can loop "handle finishers,
6224
+ * re-await the remainder" instead of blocking on the whole batch.
6225
+ *
6226
+ * Unlike `awaitTasks`, this never rejects and deliberately does NOT
6227
+ * inherit `config.timeoutMs` — a "return whatever is done" call has no
6228
+ * business timing out unless the caller asks for a window explicitly.
6229
+ */
6230
+ async awaitTasksAny(taskIds, opts) {
6231
+ const ids = new Set(taskIds);
6232
+ const completed = this.completedResults.filter((r) => ids.has(r.taskId));
6233
+ if (completed.length > 0 || ids.size === 0) {
6234
+ const done = new Set(completed.map((r) => r.taskId));
6235
+ return { completed, pending: taskIds.filter((id) => !done.has(id)) };
6236
+ }
6237
+ return new Promise((resolve6) => {
6238
+ let timer;
6239
+ const handler = ({ result }) => {
6240
+ if (!ids.has(result.taskId)) return;
6241
+ if (timer) clearTimeout(timer);
6242
+ this.off("task.completed", handler);
6243
+ resolve6({
6244
+ completed: [result],
6245
+ pending: taskIds.filter((id) => id !== result.taskId)
6246
+ });
6247
+ };
6248
+ if (opts?.timeoutMs !== void 0) {
6249
+ timer = setTimeout(() => {
6250
+ this.off("task.completed", handler);
6251
+ resolve6({ completed: [], pending: [...taskIds], timedOut: true });
6252
+ }, opts.timeoutMs);
6253
+ }
6254
+ this.on("task.completed", handler);
6255
+ });
6256
+ }
6134
6257
  /**
6135
6258
  * Manual completion — for callers that drive subagents without a runner
6136
6259
  * (e.g. external orchestrators). When a runner is configured the coordinator
@@ -6755,6 +6878,13 @@ var Director = class _Director {
6755
6878
  * coordinator emits `task.completed` for a given task id. Each entry
6756
6879
  * is created lazily on first poll/await and cleared once consumed. */
6757
6880
  taskWaiters = /* @__PURE__ */ new Map();
6881
+ /** First-completion waiters registered by `awaitTasksAny`. Kept separate
6882
+ * from `taskWaiters` on purpose: a `taskWaiters` entry marks a result as
6883
+ * "will be delivered in-band" and suppresses the fire-and-forget
6884
+ * report-back — but an any-await only consumes ONE of its ids, so the
6885
+ * losers must stay eligible for the mailbox notifier. Entries carry an
6886
+ * optional timeout timer so `shutdown()` can clear them. */
6887
+ anyWaiters = /* @__PURE__ */ new Set();
6758
6888
  /** Cache of completed results in case the consumer asks AFTER the
6759
6889
  * coordinator already fired the event — `awaitTasks(['t-1'])` after
6760
6890
  * t-1 finished should resolve immediately, not hang. */
@@ -6776,6 +6906,8 @@ var Director = class _Director {
6776
6906
  roster;
6777
6907
  directorPreamble;
6778
6908
  subagentBaseline;
6909
+ /** See {@link DirectorOptions.taskResultNotifier}. */
6910
+ taskResultNotifier;
6779
6911
  /** Absolute path to the fleet's shared scratchpad directory, or null
6780
6912
  * when none was configured. Exposed as a readonly getter for callers
6781
6913
  * that need to surface the path to the user (e.g. the CLI logging
@@ -6873,6 +7005,7 @@ var Director = class _Director {
6873
7005
  this.roster = opts.roster;
6874
7006
  this.directorPreamble = opts.directorPreamble ?? DEFAULT_DIRECTOR_PREAMBLE;
6875
7007
  this.subagentBaseline = opts.subagentBaseline ?? DEFAULT_SUBAGENT_BASELINE;
7008
+ this.taskResultNotifier = opts.taskResultNotifier;
6876
7009
  this.sharedScratchpadPath = opts.sharedScratchpadPath ?? null;
6877
7010
  this.maxSpawns = opts.maxSpawns ?? Number.POSITIVE_INFINITY;
6878
7011
  this.maxSpawnDepth = opts.maxSpawnDepth ?? 2;
@@ -6945,8 +7078,38 @@ var Director = class _Director {
6945
7078
  waiter.resolve(r);
6946
7079
  this.taskWaiters.delete(r.taskId);
6947
7080
  }
7081
+ let anyConsumed = false;
7082
+ for (const aw of [...this.anyWaiters]) {
7083
+ if (!aw.ids.has(r.taskId)) continue;
7084
+ if (aw.timer) clearTimeout(aw.timer);
7085
+ this.anyWaiters.delete(aw);
7086
+ aw.resolve(r);
7087
+ anyConsumed = true;
7088
+ }
7089
+ const consumedInBand = !!waiter || anyConsumed;
6948
7090
  if (internalTask) return;
6949
7091
  const title = this.taskDescriptions.get(r.taskId) ?? payload.task.description ?? r.taskId;
7092
+ if (!consumedInBand && this.taskResultNotifier) {
7093
+ const resultText = typeof r.result === "string" ? r.result : r.result !== void 0 ? safeStringify(r.result) : void 0;
7094
+ try {
7095
+ void Promise.resolve(
7096
+ this.taskResultNotifier({
7097
+ taskId: r.taskId,
7098
+ title,
7099
+ status: r.status,
7100
+ subagentId: r.subagentId,
7101
+ subagentName: this.manifestEntries.get(r.subagentId)?.name,
7102
+ resultText,
7103
+ errorText: r.error ? `${r.error.kind}: ${r.error.message}` : void 0,
7104
+ iterations: r.iterations,
7105
+ toolCalls: r.toolCalls,
7106
+ durationMs: r.durationMs
7107
+ })
7108
+ ).catch(() => {
7109
+ });
7110
+ } catch {
7111
+ }
7112
+ }
6950
7113
  const failed = r.status !== "success";
6951
7114
  const errorString = r.error ? `${r.error.kind}: ${r.error.message}` : void 0;
6952
7115
  this.stateCheckpoint?.recordTaskStatus(r.taskId, {
@@ -7532,6 +7695,10 @@ var Director = class _Director {
7532
7695
  this.coordinator.off("task.completed", this.taskCompletedListener);
7533
7696
  this.taskCompletedListener = null;
7534
7697
  }
7698
+ for (const aw of this.anyWaiters) {
7699
+ if (aw.timer) clearTimeout(aw.timer);
7700
+ }
7701
+ this.anyWaiters.clear();
7535
7702
  if (this.toolExecFilter) {
7536
7703
  this.toolExecFilter();
7537
7704
  this.toolExecFilter = null;
@@ -7600,6 +7767,12 @@ var Director = class _Director {
7600
7767
  waiter.resolve(synthetic);
7601
7768
  this.taskWaiters.delete(taskWithId.id);
7602
7769
  }
7770
+ for (const aw of [...this.anyWaiters]) {
7771
+ if (!aw.ids.has(taskWithId.id)) continue;
7772
+ if (aw.timer) clearTimeout(aw.timer);
7773
+ this.anyWaiters.delete(aw);
7774
+ aw.resolve(synthetic);
7775
+ }
7603
7776
  return taskWithId.id;
7604
7777
  }
7605
7778
  if (task.subagentId) {
@@ -7670,6 +7843,85 @@ var Director = class _Director {
7670
7843
  })
7671
7844
  );
7672
7845
  }
7846
+ /**
7847
+ * Wait until AT LEAST ONE of the named tasks completes, then return every
7848
+ * requested result already cached plus the still-pending ids. This is the
7849
+ * leader's "handle whichever finishes next" primitive — unlike
7850
+ * `awaitTasks` it never blocks on the slowest sibling, and the siblings
7851
+ * that complete later still reach the leader through the fire-and-forget
7852
+ * report-back (see the consumed-in-band rule in `taskCompletedListener`).
7853
+ *
7854
+ * Deliberately does NOT register `taskWaiters` entries for the pending
7855
+ * ids: a `taskWaiters` entry would mark those results as in-band-consumed
7856
+ * and silence the mailbox notifier for results this caller never receives.
7857
+ *
7858
+ * With `timeoutMs`, resolves (never rejects) `{timedOut: true}` and zero
7859
+ * completions when the window elapses first.
7860
+ */
7861
+ awaitTasksAny(taskIds, opts) {
7862
+ const completed = taskIds.map((id) => this.completed.get(id)).filter((r) => r !== void 0);
7863
+ if (completed.length > 0 || taskIds.length === 0) {
7864
+ const done = new Set(completed.map((r) => r.taskId));
7865
+ return Promise.resolve({
7866
+ completed,
7867
+ pending: taskIds.filter((id) => !done.has(id))
7868
+ });
7869
+ }
7870
+ return new Promise((resolve6) => {
7871
+ const entry = {
7872
+ ids: new Set(taskIds),
7873
+ resolve: (r) => resolve6({
7874
+ completed: [r],
7875
+ pending: taskIds.filter((id) => id !== r.taskId)
7876
+ })
7877
+ };
7878
+ if (opts?.timeoutMs !== void 0) {
7879
+ entry.timer = setTimeout(() => {
7880
+ this.anyWaiters.delete(entry);
7881
+ resolve6({ completed: [], pending: [...taskIds], timedOut: true });
7882
+ }, opts.timeoutMs);
7883
+ }
7884
+ this.anyWaiters.add(entry);
7885
+ });
7886
+ }
7887
+ /** Defensive snapshot of tasks still queued (not yet dispatched). */
7888
+ listPendingTasks() {
7889
+ return this.coordinator.listPendingTasks();
7890
+ }
7891
+ /**
7892
+ * Re-pin a still-pending task to a different subagent (`undefined` =
7893
+ * unpin) — the rebalancing primitive used by the FleetSupervisor and
7894
+ * available to hosts. Only queued tasks can move; a dispatched task
7895
+ * returns `false` (steer or terminate its worker instead). Keeps
7896
+ * ownership bookkeeping (taskOwners, checkpoint, fleet manifest) in
7897
+ * sync with the coordinator's queue.
7898
+ */
7899
+ retargetPendingTask(taskId, subagentId) {
7900
+ const ok = this.coordinator.retargetPendingTask(taskId, subagentId);
7901
+ if (!ok) return false;
7902
+ if (subagentId) {
7903
+ this.taskOwners.set(taskId, subagentId);
7904
+ if (this.fleetManager) {
7905
+ this.fleetManager.addTaskToSubagent(subagentId, taskId);
7906
+ } else {
7907
+ const entry = this.manifestEntries.get(subagentId);
7908
+ if (entry && !entry.taskIds.includes(taskId)) entry.taskIds.push(taskId);
7909
+ }
7910
+ } else {
7911
+ this.taskOwners.delete(taskId);
7912
+ }
7913
+ const description = this.taskDescriptions.get(taskId) ?? taskId;
7914
+ this.fleetManager?.addPendingTask(taskId, subagentId ?? "", description);
7915
+ this.stateCheckpoint?.recordTaskAssigned({
7916
+ taskId,
7917
+ subagentId,
7918
+ description,
7919
+ status: "running",
7920
+ assignedAt: (/* @__PURE__ */ new Date()).toISOString()
7921
+ });
7922
+ this.scheduleManifest();
7923
+ return true;
7924
+ }
7673
7925
  async terminate(subagentId) {
7674
7926
  await this.coordinator.stop(subagentId);
7675
7927
  }
@@ -8595,6 +8847,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
8595
8847
  dir;
8596
8848
  events;
8597
8849
  secretScrubber;
8850
+ isSessionInUse;
8598
8851
  /**
8599
8852
  * In-memory cache for load() results, keyed by session ID. The cache is
8600
8853
  * invalidated when the file's mtimeMs or size changes (indicating the
@@ -8614,6 +8867,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
8614
8867
  this.dir = opts.dir;
8615
8868
  this.events = opts.events;
8616
8869
  this.secretScrubber = opts.secretScrubber;
8870
+ this.isSessionInUse = opts.isSessionInUse;
8617
8871
  }
8618
8872
  /**
8619
8873
  * Clear the load() cache. Useful for testing or when the caller knows
@@ -9505,19 +9759,74 @@ var DefaultSessionStore = class _DefaultSessionStore {
9505
9759
  });
9506
9760
  await this.writeTombstone(id);
9507
9761
  }
9762
+ /**
9763
+ * Read the session id currently marked active in `active.json`, or `null`
9764
+ * when the lock is absent/unreadable. Shared by {@link delete} and
9765
+ * {@link prune} to avoid clobbering a session a live process is writing to.
9766
+ */
9767
+ async readActiveSessionId() {
9768
+ try {
9769
+ const raw = await fsp7.readFile(path9.join(this.dir, "active.json"), "utf8");
9770
+ const active = JSON.parse(raw);
9771
+ return active.sessionId ?? null;
9772
+ } catch {
9773
+ return null;
9774
+ }
9775
+ }
9508
9776
  async delete(id) {
9777
+ const activeId = await this.readActiveSessionId();
9778
+ if (activeId && id === activeId) {
9779
+ throw new Error(
9780
+ `Session ${id} is currently active in this project and cannot be deleted. Resume or start another session first.`
9781
+ );
9782
+ }
9783
+ if (this.isSessionInUse) {
9784
+ const reason = await this.isSessionInUse(id);
9785
+ if (reason) {
9786
+ throw new Error(`Session ${id} is in use (${reason}) and cannot be deleted.`);
9787
+ }
9788
+ }
9509
9789
  await this.deleteSession(id);
9510
9790
  }
9791
+ async rename(id, name) {
9792
+ const trimmed = name.trim();
9793
+ const manifest = this.sessionPath(id, ".summary.json");
9794
+ const jsonlPath = this.sessionPath(id, ".jsonl");
9795
+ try {
9796
+ await fsp7.stat(jsonlPath);
9797
+ } catch (err) {
9798
+ const code = err?.code;
9799
+ if (code === "ENOENT") {
9800
+ throw new Error(`Session not found: ${id}`);
9801
+ }
9802
+ throw err;
9803
+ }
9804
+ const summary = await this.summaryFor(id);
9805
+ const { name: _drop, ...rest } = summary;
9806
+ const updated = trimmed ? { ...rest, name: trimmed } : rest;
9807
+ const t0 = Date.now();
9808
+ let outcome = "success";
9809
+ let errorMsg;
9810
+ try {
9811
+ await atomicWrite(manifest, JSON.stringify(updated), { mode: 384 });
9812
+ } catch (err) {
9813
+ outcome = "failure";
9814
+ errorMsg = toErrorMessage(err);
9815
+ this.emitError(id, manifest, "rename", errorMsg, false);
9816
+ throw err;
9817
+ } finally {
9818
+ this.emitWrite(id, manifest, "close", outcome, Date.now() - t0, void 0, errorMsg);
9819
+ }
9820
+ await this.appendToIndex(updated);
9821
+ this.invalidateShardManifestBySessionId(id);
9822
+ this._indexCache = null;
9823
+ this.clearLoadCache(id);
9824
+ return updated;
9825
+ }
9511
9826
  async prune(maxAgeDays = 30) {
9512
9827
  const cutoff = Date.now() - maxAgeDays * 864e5;
9513
9828
  let deleted = 0;
9514
- let activeSessionId = null;
9515
- try {
9516
- const raw = await fsp7.readFile(path9.join(this.dir, "active.json"), "utf8");
9517
- const active = JSON.parse(raw);
9518
- activeSessionId = active.sessionId ?? null;
9519
- } catch {
9520
- }
9829
+ const activeSessionId = await this.readActiveSessionId();
9521
9830
  const isPrunableJsonl = (name) => name.endsWith(".jsonl") && name !== "_index.jsonl" && name !== "_mailbox.jsonl" && !name.endsWith(".replay.jsonl") && !name.endsWith(".audit.jsonl");
9522
9831
  const pruneFile = async (dir, name, prefix) => {
9523
9832
  const jsonlPath = path9.join(dir, name);
@@ -11317,6 +11626,651 @@ function makeMailInboxTool(opts = {}) {
11317
11626
  }
11318
11627
  };
11319
11628
  }
11629
+
11630
+ // src/coordination/fleet-status-tool.ts
11631
+ var TASK_SNIPPET_CHARS = 120;
11632
+ function snippet(s) {
11633
+ if (!s) return void 0;
11634
+ return s.length > TASK_SNIPPET_CHARS ? `${s.slice(0, TASK_SNIPPET_CHARS)}\u2026` : s;
11635
+ }
11636
+ function makeFleetStatusTool(opts = {}) {
11637
+ const resolveMailbox = opts.resolveMailbox ?? ((ctx) => new GlobalMailbox(opts.projectDir ?? defaultResolveProjectDir(ctx), opts.events));
11638
+ return {
11639
+ name: "fleet_status",
11640
+ description: "Live snapshot of every agent working on this project (this process AND other terminals/TUIs/WebUIs): who is online, what task each is on, which tool is running, and progress counters. Check it before starting work that might overlap with a peer, when deciding whether to wait for someone or proceed, or when a task mentions another agent. Read-only. To talk to a peer, use mail_send with the returned id.",
11641
+ usageHint: "fleet_status (optionally: onlineOnly=false to include recently-offline agents)",
11642
+ category: "Coordination",
11643
+ permission: "auto",
11644
+ mutating: false,
11645
+ capabilities: [ToolCapabilities.COORDINATION_FLEET_READ],
11646
+ inputSchema: {
11647
+ type: "object",
11648
+ properties: {
11649
+ onlineOnly: {
11650
+ type: "boolean",
11651
+ description: "Only agents with a live heartbeat (default true)."
11652
+ }
11653
+ }
11654
+ },
11655
+ async execute(input, ctx) {
11656
+ const i = input ?? {};
11657
+ const onlineOnly = i.onlineOnly ?? true;
11658
+ const mb = resolveMailbox(ctx);
11659
+ const identity = resolveMailboxIdentity(ctx);
11660
+ try {
11661
+ await mb.registerAgent({
11662
+ agentId: identity.callerId,
11663
+ sessionId: identity.sessionId,
11664
+ name: identity.name,
11665
+ role: identity.role,
11666
+ pid: process.pid,
11667
+ source: ctx.meta["source"] ?? "cli"
11668
+ });
11669
+ await mb.heartbeat({ agentId: identity.callerId });
11670
+ } catch {
11671
+ }
11672
+ const statuses = await mb.getAgentStatuses().catch(() => []);
11673
+ const local = /* @__PURE__ */ new Map();
11674
+ try {
11675
+ for (const e of opts.getLocalAgents?.() ?? []) local.set(e.name, e);
11676
+ } catch {
11677
+ }
11678
+ const rows = statuses.filter((s) => onlineOnly ? s.online : true).map((s) => {
11679
+ const rich = local.get(s.name);
11680
+ return {
11681
+ id: s.agentId,
11682
+ name: s.name,
11683
+ role: s.role,
11684
+ you: s.agentId === identity.callerId,
11685
+ status: s.status,
11686
+ online: s.online,
11687
+ currentTask: snippet(s.currentTask),
11688
+ currentTool: rich?.currentTool ?? s.currentTool,
11689
+ iterations: rich?.iterations ?? s.iterations,
11690
+ toolCalls: rich?.toolCalls ?? s.toolCalls,
11691
+ lastSeenAt: s.lastSeenAt,
11692
+ ...rich?.ctxPct !== void 0 ? { ctxPct: rich.ctxPct } : {},
11693
+ ...rich?.costUsd !== void 0 ? { costUsd: rich.costUsd } : {}
11694
+ };
11695
+ });
11696
+ const peers = rows.filter((r) => !r.you);
11697
+ return {
11698
+ ok: true,
11699
+ you: identity.callerId,
11700
+ onlineCount: rows.filter((r) => r.online).length,
11701
+ agents: rows,
11702
+ summary: peers.length === 0 ? "No other agents are active on this project right now." : `${peers.length} peer agent(s): ${peers.map((p) => `${p.name} (${p.status}${p.currentTask ? ` \u2014 ${p.currentTask}` : ""})`).join("; ")}`
11703
+ };
11704
+ }
11705
+ };
11706
+ }
11707
+ var COLLAB_ID_PREFIXES = ["bug-hunter-", "refactor-planner-", "critic-"];
11708
+ var DEFAULTS = {
11709
+ intervalMs: 2e4,
11710
+ cooldownMs: 12e4,
11711
+ maxInterventionsPerSubagent: 3,
11712
+ pinnedWaitMs: 6e4,
11713
+ overloadPinnedThreshold: 2,
11714
+ backlogFactor: 2,
11715
+ stuckMs: 18e4,
11716
+ failureStreak: 2
11717
+ };
11718
+ var HISTORY_MAX = 100;
11719
+ var FleetSupervisor = class {
11720
+ constructor(opts) {
11721
+ this.opts = opts;
11722
+ const c = opts.config ?? {};
11723
+ this.cfg = {
11724
+ enabled: c.enabled !== false,
11725
+ intervalMs: c.intervalMs ?? DEFAULTS.intervalMs,
11726
+ cooldownMs: c.cooldownMs ?? DEFAULTS.cooldownMs,
11727
+ maxInterventionsPerSubagent: c.maxInterventionsPerSubagent ?? DEFAULTS.maxInterventionsPerSubagent,
11728
+ pinnedWaitMs: c.pinnedWaitMs ?? DEFAULTS.pinnedWaitMs,
11729
+ overloadPinnedThreshold: c.overloadPinnedThreshold ?? DEFAULTS.overloadPinnedThreshold,
11730
+ backlogFactor: c.backlogFactor ?? DEFAULTS.backlogFactor,
11731
+ stuckMs: c.stuckMs ?? DEFAULTS.stuckMs,
11732
+ failureStreak: c.failureStreak ?? DEFAULTS.failureStreak,
11733
+ allowSpawn: c.allowSpawn !== false,
11734
+ allowTerminate: c.allowTerminate === true
11735
+ };
11736
+ this.now = opts.now ?? Date.now;
11737
+ }
11738
+ opts;
11739
+ cfg;
11740
+ now;
11741
+ timer = null;
11742
+ offHandles = [];
11743
+ engaging = false;
11744
+ stopped = false;
11745
+ // ── observation state ─────────────────────────────────────────────────
11746
+ /** taskId → first tick timestamp we saw it pending. */
11747
+ pendingSince = /* @__PURE__ */ new Map();
11748
+ /** subagentId → last tool.executed timestamp (fleet-wide activity map). */
11749
+ lastActivityAt = /* @__PURE__ */ new Map();
11750
+ /** subagentId → consecutive non-success completions. */
11751
+ failStreaks = /* @__PURE__ */ new Map();
11752
+ /** Consecutive ticks the backlog condition held. */
11753
+ backlogTicks = 0;
11754
+ // ── rate-limit state ──────────────────────────────────────────────────
11755
+ /** `${kind}|${subject}` → last engagement ts. */
11756
+ lastEngagedAt = /* @__PURE__ */ new Map();
11757
+ interventionsBySubagent = /* @__PURE__ */ new Map();
11758
+ /** Tasks already retargeted once — never bounced twice. */
11759
+ retargetedTasks = /* @__PURE__ */ new Set();
11760
+ log = [];
11761
+ /** Idempotent; also re-arms after a stop() so `/supervisor on` works. */
11762
+ start() {
11763
+ if (!this.cfg.enabled || this.timer) return;
11764
+ this.stopped = false;
11765
+ this.offHandles.push(
11766
+ this.opts.fleet.filter("tool.executed", (e) => {
11767
+ this.lastActivityAt.set(e.subagentId, this.now());
11768
+ })
11769
+ );
11770
+ this.offHandles.push(
11771
+ this.opts.events.on("subagent.task_completed", (e) => {
11772
+ if (this.isCollab(e.subagentId)) return;
11773
+ if (e.status === "success") {
11774
+ this.failStreaks.delete(e.subagentId);
11775
+ } else {
11776
+ this.failStreaks.set(e.subagentId, (this.failStreaks.get(e.subagentId) ?? 0) + 1);
11777
+ }
11778
+ this.scheduleNudge();
11779
+ })
11780
+ );
11781
+ this.timer = setInterval(() => {
11782
+ void this.evaluate();
11783
+ }, this.cfg.intervalMs);
11784
+ this.timer.unref?.();
11785
+ }
11786
+ stop() {
11787
+ this.stopped = true;
11788
+ if (this.timer) clearInterval(this.timer);
11789
+ this.timer = null;
11790
+ if (this.nudgeTimer) clearTimeout(this.nudgeTimer);
11791
+ this.nudgeTimer = null;
11792
+ for (const off of this.offHandles.splice(0)) off();
11793
+ }
11794
+ history() {
11795
+ return this.log;
11796
+ }
11797
+ /** True while the evaluation loop is armed. */
11798
+ isRunning() {
11799
+ return this.timer !== null;
11800
+ }
11801
+ /** Resolved (defaulted) configuration — for status surfaces. */
11802
+ configSnapshot() {
11803
+ return { ...this.cfg };
11804
+ }
11805
+ nudgeTimer = null;
11806
+ scheduleNudge() {
11807
+ if (this.nudgeTimer || this.stopped || !this.cfg.enabled) return;
11808
+ this.nudgeTimer = setTimeout(() => {
11809
+ this.nudgeTimer = null;
11810
+ void this.evaluate();
11811
+ }, 5e3);
11812
+ this.nudgeTimer.unref?.();
11813
+ }
11814
+ isCollab(subagentId) {
11815
+ return COLLAB_ID_PREFIXES.some((p) => subagentId.startsWith(p));
11816
+ }
11817
+ /** One evaluation pass. Public for tests; production runs it on the tick. */
11818
+ async evaluate() {
11819
+ if (this.stopped || !this.cfg.enabled || this.engaging) return;
11820
+ if (this.opts.source.isWorkComplete()) return;
11821
+ const now = this.now();
11822
+ const subagents = this.opts.source.subagents().filter((s) => !this.isCollab(s.id));
11823
+ const pending = this.opts.source.listPendingTasks().filter((t) => !t.subagentId || !this.isCollab(t.subagentId));
11824
+ const pendingIds = new Set(pending.map((t) => t.id));
11825
+ for (const id of this.pendingSince.keys()) {
11826
+ if (!pendingIds.has(id)) this.pendingSince.delete(id);
11827
+ }
11828
+ for (const t of pending) {
11829
+ if (!this.pendingSince.has(t.id)) this.pendingSince.set(t.id, now);
11830
+ }
11831
+ const idle = subagents.filter((s) => s.status === "idle");
11832
+ const running = subagents.filter((s) => s.status === "running");
11833
+ const live = idle.length + running.length;
11834
+ for (const [subagentId, streak] of this.failStreaks) {
11835
+ if (streak >= this.cfg.failureStreak) {
11836
+ this.failStreaks.delete(subagentId);
11837
+ await this.engageFailureStreak(subagentId, streak);
11838
+ return;
11839
+ }
11840
+ }
11841
+ if (idle.length > 0) {
11842
+ const runningIds = new Set(running.map((s) => s.id));
11843
+ const pinnedByWorker = /* @__PURE__ */ new Map();
11844
+ for (const t of pending) {
11845
+ if (!t.subagentId || this.retargetedTasks.has(t.id)) continue;
11846
+ if (!runningIds.has(t.subagentId)) continue;
11847
+ const list = pinnedByWorker.get(t.subagentId) ?? [];
11848
+ list.push(t);
11849
+ pinnedByWorker.set(t.subagentId, list);
11850
+ }
11851
+ for (const [workerId, tasks] of pinnedByWorker) {
11852
+ const overloaded = tasks.length >= this.cfg.overloadPinnedThreshold;
11853
+ const starved = tasks.filter(
11854
+ (t) => now - (this.pendingSince.get(t.id) ?? now) >= this.cfg.pinnedWaitMs
11855
+ );
11856
+ if (overloaded || starved.length > 0) {
11857
+ const movable = overloaded ? tasks.slice(1) : starved;
11858
+ if (movable.length > 0) {
11859
+ await this.engageRebalance(
11860
+ overloaded ? "overloaded_worker" : "pinned_starvation",
11861
+ workerId,
11862
+ movable,
11863
+ idle.map((s) => s.id)
11864
+ );
11865
+ return;
11866
+ }
11867
+ }
11868
+ }
11869
+ }
11870
+ const backlogged = live > 0 && pending.length > this.cfg.backlogFactor * live;
11871
+ this.backlogTicks = backlogged ? this.backlogTicks + 1 : 0;
11872
+ if (backlogged && this.backlogTicks >= 2 && this.cfg.allowSpawn) {
11873
+ this.backlogTicks = 0;
11874
+ await this.engageBacklog(pending.length, live);
11875
+ return;
11876
+ }
11877
+ for (const s of running) {
11878
+ const lastSeen = this.lastActivityAt.get(s.id);
11879
+ if (lastSeen !== void 0 && now - lastSeen >= this.cfg.stuckMs) {
11880
+ this.lastActivityAt.set(s.id, now);
11881
+ await this.engageStuck(s);
11882
+ return;
11883
+ }
11884
+ }
11885
+ if (idle.length > 0 && pending.length > 0) {
11886
+ const oldest = Math.min(...pending.map((t) => this.pendingSince.get(t.id) ?? now));
11887
+ if (now - oldest >= this.cfg.pinnedWaitMs) {
11888
+ await this.engageIdleWithWork(idle.length, pending.length);
11889
+ }
11890
+ }
11891
+ }
11892
+ // ── engagements ────────────────────────────────────────────────────────
11893
+ cooldownOk(kind, subject) {
11894
+ const key = `${kind}|${subject}`;
11895
+ const last = this.lastEngagedAt.get(key) ?? 0;
11896
+ if (this.now() - last < this.cfg.cooldownMs) return false;
11897
+ this.lastEngagedAt.set(key, this.now());
11898
+ return true;
11899
+ }
11900
+ interventionBudgetOk(subagentId) {
11901
+ return (this.interventionsBySubagent.get(subagentId) ?? 0) < this.cfg.maxInterventionsPerSubagent;
11902
+ }
11903
+ recordIntervention(subagentId) {
11904
+ this.interventionsBySubagent.set(
11905
+ subagentId,
11906
+ (this.interventionsBySubagent.get(subagentId) ?? 0) + 1
11907
+ );
11908
+ }
11909
+ emitSignal(kind, detail, subagentId, taskId) {
11910
+ this.opts.events.emit("fleet.supervisor.signal", {
11911
+ sessionId: this.opts.sessionId?.(),
11912
+ kind,
11913
+ subagentId,
11914
+ taskId,
11915
+ detail
11916
+ });
11917
+ }
11918
+ record(entry) {
11919
+ this.log.push({ at: this.now(), ...entry });
11920
+ if (this.log.length > HISTORY_MAX) this.log.splice(0, this.log.length - HISTORY_MAX);
11921
+ this.opts.events.emit("fleet.supervisor.decision", {
11922
+ sessionId: this.opts.sessionId?.(),
11923
+ kind: entry.kind,
11924
+ proposedAction: entry.proposedAction,
11925
+ via: "brain",
11926
+ outcome: entry.outcome === "error" ? "skipped" : entry.outcome,
11927
+ rationale: entry.detail
11928
+ });
11929
+ }
11930
+ emitAction(action, ok, detail, subagentId, taskId) {
11931
+ this.opts.events.emit("fleet.supervisor.action", {
11932
+ sessionId: this.opts.sessionId?.(),
11933
+ action,
11934
+ subagentId,
11935
+ taskId,
11936
+ ok,
11937
+ detail
11938
+ });
11939
+ }
11940
+ /**
11941
+ * Ask the brain to approve a proposal. Same contract as BrainMonitor:
11942
+ * `source:'system'`, the rule's proposal `recommended:true`, fallback
11943
+ * 'ask_human' (routes to the LLM tier under the risk ceiling before any
11944
+ * human). Returns the chosen option id, or null for deny/escalate.
11945
+ */
11946
+ async decide(question, context, options, risk) {
11947
+ const request = {
11948
+ id: `fleetsup-${randomUUID()}`,
11949
+ sessionId: this.opts.sessionId?.(),
11950
+ source: "system",
11951
+ question,
11952
+ context,
11953
+ options,
11954
+ risk,
11955
+ fallback: "ask_human"
11956
+ };
11957
+ const decision = await this.opts.brain.decide(request);
11958
+ if (decision.type !== "answer") return { choice: null, decision };
11959
+ const choice = decision.optionId ?? options.find((o) => o.recommended)?.id ?? null;
11960
+ return { choice, decision };
11961
+ }
11962
+ async engageRebalance(kind, fromWorkerId, tasks, idleWorkerIds) {
11963
+ if (!this.cooldownOk(kind, fromWorkerId) || !this.interventionBudgetOk(fromWorkerId)) return;
11964
+ this.engaging = true;
11965
+ try {
11966
+ const taskList = tasks.map((t) => `- ${t.id}: ${t.description.slice(0, 80)}`).join("\n");
11967
+ this.emitSignal(
11968
+ kind,
11969
+ `${tasks.length} pending task(s) pinned to busy worker ${fromWorkerId} while ${idleWorkerIds.length} worker(s) idle`,
11970
+ fromWorkerId,
11971
+ tasks[0]?.id
11972
+ );
11973
+ const { choice, decision } = await this.decide(
11974
+ `Worker ${fromWorkerId} is busy with ${tasks.length} more task(s) queued behind it while ${idleWorkerIds.length} sibling worker(s) sit idle. Rebalance the queued tasks to the idle workers?`,
11975
+ `Queued behind ${fromWorkerId}:
11976
+ ${taskList}
11977
+ Idle workers: ${idleWorkerIds.join(", ")}`,
11978
+ [
11979
+ {
11980
+ id: "rebalance",
11981
+ label: "Move the queued task(s) to idle worker(s)",
11982
+ consequence: "Only unstarted tasks move; the running task is untouched.",
11983
+ risk: "low",
11984
+ recommended: true
11985
+ },
11986
+ { id: "wait", label: "Leave the queue as is", risk: "low" }
11987
+ ],
11988
+ "low"
11989
+ );
11990
+ if (choice !== "rebalance") {
11991
+ this.record({
11992
+ kind,
11993
+ subagentId: fromWorkerId,
11994
+ proposedAction: "retarget",
11995
+ outcome: decision.type === "answer" ? "denied" : "escalated",
11996
+ detail: decision.type === "answer" ? decision.rationale ?? decision.text : decision.type
11997
+ });
11998
+ return;
11999
+ }
12000
+ this.recordIntervention(fromWorkerId);
12001
+ const moved = [];
12002
+ for (let i = 0; i < tasks.length; i++) {
12003
+ const task = tasks[i];
12004
+ const target = idleWorkerIds[i % idleWorkerIds.length];
12005
+ if (!task || !target) continue;
12006
+ const ok = await this.opts.actions.retargetPendingTask(task.id, target);
12007
+ this.emitAction("retarget", ok, `\u2192 ${target}`, fromWorkerId, task.id);
12008
+ if (ok) {
12009
+ this.retargetedTasks.add(task.id);
12010
+ moved.push(`${task.id} \u2192 ${target}`);
12011
+ }
12012
+ }
12013
+ this.record({
12014
+ kind,
12015
+ subagentId: fromWorkerId,
12016
+ taskId: tasks[0]?.id,
12017
+ proposedAction: "retarget",
12018
+ outcome: "approved",
12019
+ detail: moved.length > 0 ? `moved ${moved.join(", ")}` : "nothing movable (already dispatched)"
12020
+ });
12021
+ if (moved.length > 0) {
12022
+ await this.opts.actions.steerAgent(
12023
+ fromWorkerId,
12024
+ "Workload reduced by fleet supervisor",
12025
+ `The fleet supervisor moved ${moved.length} of your queued task(s) to idle workers: ${moved.join(
12026
+ ", "
12027
+ )}. Do not start them \u2014 focus on your current task.`
12028
+ ).catch(() => {
12029
+ });
12030
+ await this.opts.actions.notifyLeader(
12031
+ "Fleet rebalanced",
12032
+ `Supervisor moved ${moved.length} queued task(s) off busy worker ${fromWorkerId}: ${moved.join(", ")}.`
12033
+ ).catch(() => {
12034
+ });
12035
+ }
12036
+ } catch {
12037
+ } finally {
12038
+ this.engaging = false;
12039
+ }
12040
+ }
12041
+ async engageBacklog(pendingCount, liveWorkers) {
12042
+ if (!this.cooldownOk("backlog", "fleet")) return;
12043
+ this.engaging = true;
12044
+ try {
12045
+ this.emitSignal(
12046
+ "backlog",
12047
+ `${pendingCount} pending tasks vs ${liveWorkers} live worker(s)`
12048
+ );
12049
+ const { choice, decision } = await this.decide(
12050
+ `The task queue is deep: ${pendingCount} pending tasks for ${liveWorkers} live worker(s). Spawn one additional helper worker to drain it?`,
12051
+ `Pending: ${pendingCount}, live workers: ${liveWorkers}, factor threshold: ${this.cfg.backlogFactor}x`,
12052
+ [
12053
+ {
12054
+ id: "spawn",
12055
+ label: "Spawn one helper worker",
12056
+ consequence: "One more subagent joins the fleet and takes queued work.",
12057
+ risk: "medium",
12058
+ recommended: true
12059
+ },
12060
+ { id: "wait", label: "Let the current fleet drain the queue", risk: "low" }
12061
+ ],
12062
+ "medium"
12063
+ );
12064
+ if (choice !== "spawn") {
12065
+ this.record({
12066
+ kind: "backlog",
12067
+ proposedAction: "spawn_helper",
12068
+ outcome: decision.type === "answer" ? "denied" : "escalated",
12069
+ detail: decision.type === "answer" ? decision.rationale ?? decision.text : decision.type
12070
+ });
12071
+ return;
12072
+ }
12073
+ const res = await this.opts.actions.spawnHelper({
12074
+ reason: `queue backlog: ${pendingCount} pending / ${liveWorkers} workers`
12075
+ });
12076
+ if ("subagentId" in res) {
12077
+ this.emitAction("spawn_helper", true, res.subagentId, res.subagentId);
12078
+ this.record({
12079
+ kind: "backlog",
12080
+ subagentId: res.subagentId,
12081
+ proposedAction: "spawn_helper",
12082
+ outcome: "approved",
12083
+ detail: `spawned ${res.subagentId}`
12084
+ });
12085
+ await this.opts.actions.notifyLeader(
12086
+ "Fleet helper spawned",
12087
+ `Supervisor spawned helper ${res.subagentId} to drain a ${pendingCount}-task backlog.`
12088
+ ).catch(() => {
12089
+ });
12090
+ } else {
12091
+ this.emitAction("spawn_helper", false, res.error);
12092
+ this.record({
12093
+ kind: "backlog",
12094
+ proposedAction: "spawn_helper",
12095
+ outcome: "error",
12096
+ detail: res.error
12097
+ });
12098
+ await this.opts.actions.notifyLeader(
12099
+ "Fleet backlog needs attention",
12100
+ `Queue is ${pendingCount} deep for ${liveWorkers} worker(s); supervisor could not spawn a helper (${res.error}). Consider rebalancing or finishing tasks before assigning more.`
12101
+ ).catch(() => {
12102
+ });
12103
+ }
12104
+ } catch {
12105
+ } finally {
12106
+ this.engaging = false;
12107
+ }
12108
+ }
12109
+ async engageStuck(s) {
12110
+ if (!this.cooldownOk("stuck_agent", s.id) || !this.interventionBudgetOk(s.id)) return;
12111
+ this.engaging = true;
12112
+ try {
12113
+ this.emitSignal(
12114
+ "stuck_agent",
12115
+ `no tool activity for \u2265${Math.round(this.cfg.stuckMs / 1e3)}s`,
12116
+ s.id
12117
+ );
12118
+ const { choice, decision } = await this.decide(
12119
+ `Worker ${s.name} (${s.id}) is marked running but produced no tool activity for over ${Math.round(this.cfg.stuckMs / 1e3)}s. Nudge it with a steer message?`,
12120
+ `Current task: ${s.currentTask ?? "unknown"}`,
12121
+ [
12122
+ {
12123
+ id: "steer",
12124
+ label: "Send a corrective steer to the worker",
12125
+ consequence: "A steer mail is injected before its next step.",
12126
+ risk: "low",
12127
+ recommended: true
12128
+ },
12129
+ { id: "wait", label: "Give it more time", risk: "low" }
12130
+ ],
12131
+ "medium"
12132
+ );
12133
+ if (choice !== "steer") {
12134
+ this.record({
12135
+ kind: "stuck_agent",
12136
+ subagentId: s.id,
12137
+ proposedAction: "steer",
12138
+ outcome: decision.type === "answer" ? "denied" : "escalated",
12139
+ detail: decision.type === "answer" ? decision.rationale ?? decision.text : decision.type
12140
+ });
12141
+ return;
12142
+ }
12143
+ this.recordIntervention(s.id);
12144
+ await this.opts.actions.steerAgent(
12145
+ s.id,
12146
+ "Progress check from fleet supervisor",
12147
+ `You appear stalled (no tool activity for ${Math.round(this.cfg.stuckMs / 1e3)}s on: ${s.currentTask ?? "your current task"}). If you are blocked, say so via mail_send to the leader and either narrow the scope or hand the task back \u2014 do not keep silently retrying the same step.`
12148
+ );
12149
+ this.emitAction("steer", true, "stuck nudge", s.id);
12150
+ await this.opts.actions.notifyLeader(
12151
+ `Worker ${s.name} may be stuck`,
12152
+ `No tool activity for ${Math.round(this.cfg.stuckMs / 1e3)}s. Supervisor nudged it; consider terminate_subagent + reassigning if it stays silent.`
12153
+ ).catch(() => {
12154
+ });
12155
+ this.record({
12156
+ kind: "stuck_agent",
12157
+ subagentId: s.id,
12158
+ proposedAction: "steer",
12159
+ outcome: "approved",
12160
+ detail: "steered + leader notified"
12161
+ });
12162
+ } catch {
12163
+ } finally {
12164
+ this.engaging = false;
12165
+ }
12166
+ }
12167
+ async engageFailureStreak(subagentId, streak) {
12168
+ if (!this.cooldownOk("failure_streak", subagentId) || !this.interventionBudgetOk(subagentId)) {
12169
+ return;
12170
+ }
12171
+ this.engaging = true;
12172
+ try {
12173
+ this.emitSignal("failure_streak", `${streak} consecutive failed/timeout tasks`, subagentId);
12174
+ const options = [
12175
+ {
12176
+ id: "steer",
12177
+ label: "Steer the worker to change approach",
12178
+ risk: "low",
12179
+ recommended: true
12180
+ },
12181
+ { id: "observe", label: "Keep observing", risk: "low" }
12182
+ ];
12183
+ if (this.cfg.allowTerminate) {
12184
+ options.push({
12185
+ id: "terminate",
12186
+ label: "Terminate the worker",
12187
+ consequence: "Its current task fails; pending pinned tasks need reassignment.",
12188
+ risk: "high"
12189
+ });
12190
+ }
12191
+ const { choice, decision } = await this.decide(
12192
+ `Worker ${subagentId} produced ${streak} consecutive failed/timed-out tasks. Intervene?`,
12193
+ `Consecutive failures: ${streak}`,
12194
+ options,
12195
+ "high"
12196
+ );
12197
+ if (choice === "terminate" && this.cfg.allowTerminate) {
12198
+ this.recordIntervention(subagentId);
12199
+ await this.opts.actions.terminate(subagentId);
12200
+ this.emitAction("terminate", true, `${streak} consecutive failures`, subagentId);
12201
+ await this.opts.actions.notifyLeader(
12202
+ `Worker ${subagentId} terminated`,
12203
+ `Supervisor terminated ${subagentId} after ${streak} consecutive failures. Reassign its pending work.`
12204
+ ).catch(() => {
12205
+ });
12206
+ this.record({
12207
+ kind: "failure_streak",
12208
+ subagentId,
12209
+ proposedAction: "terminate",
12210
+ outcome: "approved",
12211
+ detail: `terminated after ${streak} failures`
12212
+ });
12213
+ return;
12214
+ }
12215
+ if (choice === "steer") {
12216
+ this.recordIntervention(subagentId);
12217
+ await this.opts.actions.steerAgent(
12218
+ subagentId,
12219
+ "Change of approach required",
12220
+ `Your last ${streak} tasks failed. Stop, re-read the task, and take a different approach \u2014 if the task itself is impossible or under-specified, report that to the leader via mail_send instead of retrying.`
12221
+ );
12222
+ this.emitAction("steer", true, "failure streak", subagentId);
12223
+ await this.opts.actions.notifyLeader(
12224
+ `Worker ${subagentId} failing repeatedly`,
12225
+ `${streak} consecutive failures. Supervisor steered it; consider reassigning its work if the next task also fails.`
12226
+ ).catch(() => {
12227
+ });
12228
+ this.record({
12229
+ kind: "failure_streak",
12230
+ subagentId,
12231
+ proposedAction: "steer",
12232
+ outcome: "approved",
12233
+ detail: `steered after ${streak} failures`
12234
+ });
12235
+ return;
12236
+ }
12237
+ this.record({
12238
+ kind: "failure_streak",
12239
+ subagentId,
12240
+ proposedAction: this.cfg.allowTerminate ? "steer|terminate" : "steer",
12241
+ outcome: decision.type === "answer" ? "denied" : "escalated",
12242
+ detail: decision.type === "answer" ? decision.rationale ?? decision.text : decision.type
12243
+ });
12244
+ } catch {
12245
+ } finally {
12246
+ this.engaging = false;
12247
+ }
12248
+ }
12249
+ async engageIdleWithWork(idleCount, pendingCount) {
12250
+ if (!this.cooldownOk("idle_with_work", "fleet")) return;
12251
+ this.engaging = true;
12252
+ try {
12253
+ this.emitSignal(
12254
+ "idle_with_work",
12255
+ `${idleCount} idle worker(s) while ${pendingCount} task(s) cannot dispatch`
12256
+ );
12257
+ await this.opts.actions.notifyLeader(
12258
+ "Idle workers with undispatchable tasks",
12259
+ `${idleCount} worker(s) idle while ${pendingCount} task(s) stay pending (likely pinned to stopped/errored workers). Reassign them with assign_task or let the supervisor retarget by unpinning.`
12260
+ );
12261
+ this.emitAction("notify_leader", true, "idle_with_work");
12262
+ this.record({
12263
+ kind: "idle_with_work",
12264
+ proposedAction: "notify_leader",
12265
+ outcome: "approved",
12266
+ detail: `${idleCount} idle / ${pendingCount} pending`
12267
+ });
12268
+ } catch {
12269
+ } finally {
12270
+ this.engaging = false;
12271
+ }
12272
+ }
12273
+ };
11320
12274
  var MAILBOX_FILE2 = "_mailbox.jsonl";
11321
12275
  var LINE_SEPARATOR2 = "\n";
11322
12276
  var MESSAGE_CACHE_MAX_ENTRIES2 = 1e4;
@@ -12041,7 +12995,8 @@ function detectEcosystem(manifestPath) {
12041
12995
  if (name === "package.json") return "npm";
12042
12996
  if (name === "go.mod") return "go";
12043
12997
  if (name === "cargo.toml") return "cargo";
12044
- if (name === "pyproject.toml" || name === "requirements.txt" || name === "pipfile" || name === "pipfile.lock") return "pip";
12998
+ if (name === "pyproject.toml" || name === "requirements.txt" || name === "pipfile" || name === "pipfile.lock")
12999
+ return "pip";
12045
13000
  if (name === "gemfile" || name === "gemfile.lock") return "gem";
12046
13001
  if (name === "composer.json" || name === "composer.lock") return "composer";
12047
13002
  if (name.endsWith(".csproj") || name === "packages.config") return "nuget";
@@ -12050,7 +13005,7 @@ function detectEcosystem(manifestPath) {
12050
13005
  if (name === "pubspec.yaml" || name === "pubspec.lock") return "dart";
12051
13006
  if (name === "vcpkg.json") return "vcpkg";
12052
13007
  if (name === "conanfile.txt" || name === "conanfile.py") return "conan";
12053
- if (name === "cmakeLists.txt") return "cmake";
13008
+ if (name === "cmakelists.txt") return "cmake";
12054
13009
  return "unknown";
12055
13010
  }
12056
13011
  async function recordPackageAction(opts, entry) {
@@ -12081,9 +13036,7 @@ async function getPackageAuthor(opts, manifestPath, packageName) {
12081
13036
  async function getManifestPackages(opts, manifestPath) {
12082
13037
  const log = await loadLog(opts.storageDir, opts.projectRoot);
12083
13038
  const normalizedManifest = manifestPath.replace(/\\/g, "/");
12084
- return log.entries.filter(
12085
- (e) => e.manifestPath.replace(/\\/g, "/") === normalizedManifest
12086
- );
13039
+ return log.entries.filter((e) => e.manifestPath.replace(/\\/g, "/") === normalizedManifest);
12087
13040
  }
12088
13041
  async function getPackagesByAgent(opts, agentId) {
12089
13042
  const log = await loadLog(opts.storageDir, opts.projectRoot);
@@ -12130,7 +13083,7 @@ function parseOutdatedPackages(body) {
12130
13083
  latestVersion: cols[2] ?? "",
12131
13084
  wantedVersion: cols[3] ?? "",
12132
13085
  manifestPath: cols[4] ?? "",
12133
- ecosystem: detectEcosystem2(cols[4] ?? "")
13086
+ ecosystem: detectEcosystem(cols[4] ?? "")
12134
13087
  });
12135
13088
  }
12136
13089
  }
@@ -12151,20 +13104,6 @@ function parseOutdatedPackages(body) {
12151
13104
  }
12152
13105
  return results;
12153
13106
  }
12154
- function detectEcosystem2(manifestPath) {
12155
- const name = manifestPath.split("/").pop()?.split("\\").pop() ?? manifestPath;
12156
- if (name === "package.json") return "npm";
12157
- if (name === "go.mod") return "go";
12158
- if (name === "cargo.toml") return "cargo";
12159
- if (name === "pyproject.toml" || name === "requirements.txt") return "pip";
12160
- if (name === "gemfile" || name === "gemfile.lock") return "gem";
12161
- if (name === "composer.json" || name === "composer.lock") return "composer";
12162
- if (name.endsWith(".csproj") || name === "packages.config") return "nuget";
12163
- if (name === "mix.exs" || name === "mix.lock") return "elixir";
12164
- if (name === "pom.xml" || name.startsWith("build.gradle")) return "maven";
12165
- if (name === "pubspec.yaml" || name === "pubspec.lock") return "dart";
12166
- return "unknown";
12167
- }
12168
13107
  function startPackageOutdatedWatcher(opts) {
12169
13108
  const {
12170
13109
  mailbox,
@@ -12214,11 +13153,7 @@ function startPackageOutdatedWatcher(opts) {
12214
13153
  log(`[pkg-outdated-watcher] Processing ${entries.length} outdated package(s) from ${msg.from}`);
12215
13154
  for (const entry of entries) {
12216
13155
  try {
12217
- const author = await getPackageAuthor(
12218
- packageTrackerOpts,
12219
- entry.manifestPath,
12220
- entry.name
12221
- );
13156
+ const author = await getPackageAuthor(packageTrackerOpts, entry.manifestPath, entry.name);
12222
13157
  const notifyTarget = author?.agentId ?? "*";
12223
13158
  const notifyBody = buildNotifyBody(entry, author?.agentName);
12224
13159
  const notifyMsg = {
@@ -12273,13 +13208,7 @@ function buildNotifyBody(entry, authorName) {
12273
13208
  `This package appears to have been added by an agent no longer on record. Consider reviewing and updating it.`
12274
13209
  );
12275
13210
  }
12276
- lines.push(
12277
- "",
12278
- `Update with:`,
12279
- `\`\`\``,
12280
- `${getUpdateCommand(entry)}`,
12281
- `\`\`\``
12282
- );
13211
+ lines.push("", `Update with:`, `\`\`\``, `${getUpdateCommand(entry)}`, `\`\`\``);
12283
13212
  return lines.join("\n");
12284
13213
  }
12285
13214
  function getUpdateCommand(entry) {
@@ -15343,6 +16272,6 @@ ${input.detail}`
15343
16272
  }
15344
16273
  };
15345
16274
 
15346
- export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, TOOLS as AGENT_TOOL_PRESETS, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AdaptiveConcurrencyController, AgentMonitorService, AutonomousBrain, AutonomousCoordinator, BUG_HUNTER_AGENT, BUILD_AGENTS, BrainDecisionQueue, BrainMonitor, BudgetExceededError, BudgetThresholdSignal, ChangeManager, CollabSession, ConsensusProtocol, DECISION_TIMEOUT_MS, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_QUALITY_CHECKS, DEFAULT_SUBAGENT_BASELINE, DELIVERY_AGENTS, DEPENDENCY_FILE_PATTERNS, DISCOVERY_AGENTS, DOMAIN_AGENTS, DefaultBrainArbiter, DefaultMailbox, DefaultMultiAgentCoordinator, Director, DirectorAlertLevel, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetUsageAggregator, GlobalMailbox, HEAVY_BUDGET, HumanEscalatingBrainArbiter, InMemoryAgentBridge, InMemoryBridgeTransport, KNOWLEDGE_AGENTS, KnowledgeGraph, LIGHT_BUDGET, LargeAnswerStore, MAILBOX_BRIDGE_LOCK_FILENAME, MAILBOX_BRIDGE_TOKEN_FILENAME, MAILBOX_HEALTH_DEFAULT_FAILURE_THRESHOLD, MAILBOX_HEALTH_DEFAULT_FROM, MAILBOX_HEALTH_DEFAULT_INTERVAL_MS, MAILBOX_HEALTH_DEFAULT_TIMEOUT_MS, MEDIUM_BUDGET, META_AGENTS, MailboxHealthWatchdog, NULL_FLEET_BUS, ObservableBrainArbiter, PLANNING_AGENTS, REFACTOR_PLANNER_AGENT, REVIEW_AGENTS, SECURITY_SCANNER_AGENT, SubagentBudget, TIMEOUT_PREEMPT_FRACTION, TaskAuctioneer, TaskDAG, VERIFY_AGENTS, acquireOrJoin, actionToAckInput, applyRosterBudget, attachAutoExtend, attachDepWatcherBridge, buildDownAlert, buildRecoveryAlert, composeDirectorPrompt, composeSubagentPrompt, createAgentMonitorService, createDelegateTool, createMailboxHooks, createMessage, detectEcosystem, dispatchAgent, finalize, formatHumanPrompt, getAgentDefinition, getFullPackageLog, getManifestPackages, getPackageAuthor, getPackagesByAgent, mailboxSessionTag, makeAgentSubagentRunner, makeAskResultTool, makeAskTool, makeAssignTool, makeAwaitTasksTool, makeCollabDebugTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetTool as makeFleetHealthTool, makeFleetTool as makeFleetSessionTool, makeFleetTool as makeFleetStatusTool, makeFleetTool, makeFleetTool as makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateAllTool, makeTerminateTool, makeWorkCompleteTool, normalizeRecipient, readLiveLock, recordPackageAction, release, resolveMailboxIdentity, resolveProjectDir, rosterSummaryFromConfigs, scoreAgents, startPackageOutdatedWatcher, updatePackageOutdatedStatus, validateWatchdogOptions, withDisabledToolFiltering };
16275
+ export { ACP_AGENTS, AGENTS_BY_PHASE, AGENT_CATALOG, TOOLS as AGENT_TOOL_PRESETS, ALL_AGENT_DEFINITIONS, ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, AdaptiveConcurrencyController, AgentMonitorService, AutonomousBrain, AutonomousCoordinator, BUG_HUNTER_AGENT, BUILD_AGENTS, BrainDecisionQueue, BrainMonitor, BudgetExceededError, BudgetThresholdSignal, ChangeManager, CollabSession, ConsensusProtocol, DECISION_TIMEOUT_MS, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_DISPATCH_ROLE, DEFAULT_QUALITY_CHECKS, DEFAULT_SUBAGENT_BASELINE, DELIVERY_AGENTS, DEPENDENCY_FILE_PATTERNS, DISCOVERY_AGENTS, DOMAIN_AGENTS, DefaultBrainArbiter, DefaultMailbox, DefaultMultiAgentCoordinator, Director, DirectorAlertLevel, FLEET_ROSTER, FLEET_ROSTER_BUDGETS, FLEET_ROSTER_WITHACP, FleetBus, FleetCostCapError, FleetManager, FleetSpawnBudgetError, FleetSupervisor, FleetUsageAggregator, GlobalMailbox, HEAVY_BUDGET, HumanEscalatingBrainArbiter, InMemoryAgentBridge, InMemoryBridgeTransport, KNOWLEDGE_AGENTS, KnowledgeGraph, LIGHT_BUDGET, LargeAnswerStore, MAILBOX_BRIDGE_LOCK_FILENAME, MAILBOX_BRIDGE_TOKEN_FILENAME, MAILBOX_HEALTH_DEFAULT_FAILURE_THRESHOLD, MAILBOX_HEALTH_DEFAULT_FROM, MAILBOX_HEALTH_DEFAULT_INTERVAL_MS, MAILBOX_HEALTH_DEFAULT_TIMEOUT_MS, MEDIUM_BUDGET, META_AGENTS, MailboxHealthWatchdog, NULL_FLEET_BUS, ObservableBrainArbiter, PLANNING_AGENTS, REFACTOR_PLANNER_AGENT, REVIEW_AGENTS, SECURITY_SCANNER_AGENT, SubagentBudget, TIMEOUT_PREEMPT_FRACTION, TaskAuctioneer, TaskDAG, VERIFY_AGENTS, acquireOrJoin, actionToAckInput, applyRosterBudget, attachAutoExtend, attachDepWatcherBridge, buildDownAlert, buildRecoveryAlert, composeDirectorPrompt, composeSubagentPrompt, createAgentMonitorService, createDelegateTool, createMailboxHooks, createMessage, detectEcosystem, dispatchAgent, finalize, formatHumanPrompt, getAgentDefinition, getFullPackageLog, getManifestPackages, getPackageAuthor, getPackagesByAgent, mailboxSessionTag, makeAgentSubagentRunner, makeAskResultTool, makeAskTool, makeAssignTool, makeAwaitTasksTool, makeCollabDebugTool, makeDependencyWatcherConfig, makeDirectorSessionFactory, makeFleetEmitTool, makeFleetTool as makeFleetHealthTool, makeFleetTool as makeFleetSessionTool, makeFleetStatusTool, makeFleetTool, makeFleetTool as makeFleetUsageTool, makeLLMClassifier, makeMailInboxTool, makeMailSendTool, makeMailboxTool, makeRollUpTool, makeSpawnTool, makeTerminateAllTool, makeTerminateTool, makeWorkCompleteTool, normalizeRecipient, readLiveLock, recordPackageAction, release, resolveMailboxIdentity, resolveProjectDir, rosterSummaryFromConfigs, scoreAgents, startPackageOutdatedWatcher, updatePackageOutdatedStatus, validateWatchdogOptions, withDisabledToolFiltering };
15347
16276
  //# sourceMappingURL=index.js.map
15348
16277
  //# sourceMappingURL=index.js.map