@wrongstack/core 0.277.2 → 0.280.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 (83) hide show
  1. package/dist/{agent-bridge-BFJ2ODzI.d.ts → agent-bridge-DXC6QDJ4.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-BimKihiC.d.ts → agent-subagent-runner-PoqNKiR4.d.ts} +563 -471
  3. package/dist/{compactor-D3BGw26y.d.ts → compactor-U3agvUIG.d.ts} +1 -1
  4. package/dist/{config-DAOjriz9.d.ts → config-Cr3312zc.d.ts} +102 -4
  5. package/dist/coordination/index.d.ts +1087 -998
  6. package/dist/coordination/index.js +12235 -12052
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +31 -30
  9. package/dist/defaults/index.js +403 -189
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{brain-CCfuEOdp.d.ts → events-Bs2fmldo.d.ts} +117 -112
  12. package/dist/execution/index.d.ts +27 -19
  13. package/dist/execution/index.js +216 -63
  14. package/dist/execution/index.js.map +1 -1
  15. package/dist/execution/prompt-enhancer.d.ts +1 -1
  16. package/dist/execution/prompt-enhancer.js.map +1 -1
  17. package/dist/extension/index.d.ts +8 -7
  18. package/dist/{global-mailbox-Dr4cTKqL.d.ts → global-mailbox-Ct7IorLJ.d.ts} +84 -6
  19. package/dist/{goal-store-C1uH4srH.d.ts → goal-store-C4F6DjC0.d.ts} +1 -1
  20. package/dist/hq/index.d.ts +504 -7
  21. package/dist/hq/index.js +1069 -20
  22. package/dist/hq/index.js.map +1 -1
  23. package/dist/{index-DJXj-dcr.d.ts → index-kidebiDh.d.ts} +8 -5
  24. package/dist/{index-cMEmzCVN.d.ts → index-nP09-oP2.d.ts} +2 -2
  25. package/dist/index.d.ts +153 -76
  26. package/dist/index.js +5791 -3163
  27. package/dist/index.js.map +1 -1
  28. package/dist/infrastructure/index.d.ts +7 -6
  29. package/dist/kernel/index.d.ts +14 -13
  30. package/dist/kernel/index.js +31 -15
  31. package/dist/kernel/index.js.map +1 -1
  32. package/dist/{mailbox-types-DTl7bRH3.d.ts → mailbox-types-BGZWrYTJ.d.ts} +38 -0
  33. package/dist/{mcp-servers-CFb60-pH.d.ts → mcp-servers-D910X5_r.d.ts} +3 -3
  34. package/dist/models/index.d.ts +5 -5
  35. package/dist/models/index.js.map +1 -1
  36. package/dist/{models-registry-5Ufn7f2m.d.ts → models-registry-CLkoOcHk.d.ts} +1 -1
  37. package/dist/{multi-agent-coordinator-CcrcncvG.d.ts → multi-agent-coordinator-CieyUoEL.d.ts} +1 -1
  38. package/dist/{null-fleet-bus-C9KsYyrI.d.ts → null-fleet-bus-DkdmZJ_W.d.ts} +464 -464
  39. package/dist/observability/index.d.ts +3 -2
  40. package/dist/{path-resolver-CEeX9I7O.d.ts → path-resolver-XfZ9eLxG.d.ts} +3 -3
  41. package/dist/{permission-DbsGOA1C.d.ts → permission-Dx6dIqS2.d.ts} +2 -7
  42. package/dist/{permission-policy-BpEea3r7.d.ts → permission-policy-C8vJcnX5.d.ts} +2 -2
  43. package/dist/{pipeline-CEjBjzVA.d.ts → pipeline-BwAP21_4.d.ts} +9 -4
  44. package/dist/{provider-model-resolve-BpfXp3Jj.d.ts → provider-model-resolve-CwQNZWt_.d.ts} +3 -3
  45. package/dist/{provider-runner-CnOSr5BN.d.ts → provider-runner-CYHFImzV.d.ts} +3 -3
  46. package/dist/{retry-policy-Git9WF6d.d.ts → retry-policy-D4feSLk3.d.ts} +1 -1
  47. package/dist/sdd/index.d.ts +11 -10
  48. package/dist/sdd/index.js +2 -2
  49. package/dist/sdd/index.js.map +1 -1
  50. package/dist/secret-scrubber-3MHDDAtm.d.ts +6 -0
  51. package/dist/{secret-vault-DDSMHqIm.d.ts → secret-vault-CImt2XrR.d.ts} +1 -1
  52. package/dist/security/index.d.ts +6 -5
  53. package/dist/security/index.js.map +1 -1
  54. package/dist/{selector-Cq72C0Oy.d.ts → selector-Dy-MzKp1.d.ts} +1 -1
  55. package/dist/{session-event-bridge-DG94B3Bk.d.ts → session-event-bridge-CqdiGnfU.d.ts} +1 -1
  56. package/dist/{session-reader-BzT-iMQT.d.ts → session-reader-Hk0WbNm9.d.ts} +1 -1
  57. package/dist/{skill-DGIXCtdv.d.ts → skill-DHniprNl.d.ts} +15 -1
  58. package/dist/skills/index.d.ts +472 -26
  59. package/dist/skills/index.js +872 -129
  60. package/dist/skills/index.js.map +1 -1
  61. package/dist/storage/index.d.ts +27 -14
  62. package/dist/storage/index.js +264 -85
  63. package/dist/storage/index.js.map +1 -1
  64. package/dist/{strategy-compactor-Bt_ZH6R0.d.ts → strategy-compactor-CQwhbErd.d.ts} +32 -17
  65. package/dist/{todos-checkpoint-CH1pcua9.d.ts → todos-checkpoint-Bk2uP7Ex.d.ts} +6 -6
  66. package/dist/{context-DPlA6kid.d.ts → tool-BkOgs_KL.d.ts} +306 -286
  67. package/dist/{tool-executor-SVFq7IOR.d.ts → tool-executor-SiE1wlZo.d.ts} +9 -9
  68. package/dist/tools/index.d.ts +2 -2
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/types/index.d.ts +22 -21
  71. package/dist/types/index.js +7 -9
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/utils/index.d.ts +30 -4
  74. package/dist/utils/index.js +50 -1
  75. package/dist/utils/index.js.map +1 -1
  76. package/dist/{worktree-manager-C4YIf1Fa.d.ts → worktree-manager-BjOFF6bt.d.ts} +1 -1
  77. package/dist/{wstack-paths-_NrRovdr.d.ts → wstack-paths-CMl_cYgq.d.ts} +8 -0
  78. package/package.json +1 -1
  79. package/skills/mailbox-bridge/SKILL.md +1 -0
  80. package/skills/plugin-author/SKILL.md +350 -0
  81. package/skills/sdd/SKILL.md +134 -134
  82. package/skills/skill-creator/SKILL.md +45 -7
  83. package/skills/wrongstack-mailbox/SKILL.md +40 -21
@@ -1,26 +1,27 @@
1
- import { E as EventBus, B as BrainArbiter, f as BrainDecisionOption, k as BrainRisk, h as BrainDecisionRequest, e as BrainDecision, i as BrainDecisionSource } from '../brain-CCfuEOdp.js';
2
- export { g as BrainDecisionQueue, j as BrainFallback, D as DefaultBrainArbiter, l as DefaultBrainArbiterOptions, H as HumanEscalatingBrainArbiter, O as ObservableBrainArbiter, w as formatHumanPrompt } from '../brain-CCfuEOdp.js';
3
- import { H as FleetManager, s as Director } from '../null-fleet-bus-C9KsYyrI.js';
4
- export { A as ACP_AGENTS, a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, h as BugFinding, C as CollabBudgetConfig, i as CollabBudgetOverrides, j as CollabBudgetWarningPayload, k as CollabDebugReport, l as CollabSession, m as CollabSessionOptions, n as CreateDelegateToolOptions, o as CriticConcern, p as CriticEvaluation, D as DEFAULT_DIRECTOR_PREAMBLE, q as DEFAULT_SUBAGENT_BASELINE, r as DelegateHost, t as DirectorAlert, u as DirectorAlertLevel, v as DirectorCancelCollabPayload, w as DirectorPromptParts, x as DirectorSessionFactory, y as DirectorSessionFactoryOptions, F as FLEET_ROSTER, z as FLEET_ROSTER_BUDGETS, E as FLEET_ROSTER_WITHACP, G as FleetCostCapError, I as FleetManagerOptions, J as FleetRosterBudget, K as FleetSpawnBudgetError, L as ICoordinator, M as IFleetManager, N as LargeAnswerStore, O as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, P as RefactorPhase, Q as RefactorPlan, S as SECURITY_SCANNER_AGENT, T as SharedFileEntry, U as SharedFileSnapshot, V as SubagentPromptParts, W as applyRosterBudget, X as attachAutoExtend, Y as composeDirectorPrompt, Z as composeSubagentPrompt, _ as createDelegateTool, $ as getAgentDefinition, a0 as makeAskResultTool, a1 as makeAskTool, a2 as makeAssignTool, a3 as makeAwaitTasksTool, a4 as makeCollabDebugTool, a5 as makeDirectorSessionFactory, a6 as makeFleetEmitTool, a7 as makeFleetHealthTool, a7 as makeFleetSessionTool, a7 as makeFleetStatusTool, a7 as makeFleetTool, a7 as makeFleetUsageTool, a8 as makeRollUpTool, a9 as makeSpawnTool, aa as makeTerminateAllTool, ab as makeTerminateTool, ac as makeWorkCompleteTool, ad as rosterSummaryFromConfigs } from '../null-fleet-bus-C9KsYyrI.js';
5
- import { b as AgentDefinition } from '../multi-agent-coordinator-CcrcncvG.js';
6
- export { T as AGENT_TOOL_PRESETS, c as AgentBudgetTier, d as AgentCapability, A as AgentPhase, e as DEFAULT_DISPATCH_ROLE, a as DefaultMultiAgentCoordinator, f as DispatchCandidate, D as DispatchClassifier, g as DispatchMethod, h as DispatchOptions, i as DispatchResult, H as HEAVY_BUDGET, L as LIGHT_BUDGET, M as MEDIUM_BUDGET, j as MultiAgentCoordinatorOptions, k as dispatchAgent, m as makeLLMClassifier, s as scoreAgents } from '../multi-agent-coordinator-CcrcncvG.js';
7
- import { F as FleetBus } from '../agent-subagent-runner-BimKihiC.js';
8
- export { i as AgentFactory, w as AgentFactoryResult, x as AgentRunnerOptions, y as BudgetExceededError, z as BudgetKind, E as BudgetLimits, G as BudgetNegotiationMode, H as BudgetThresholdDecision, I as BudgetThresholdHandler, J as BudgetThresholdSignal, K as BudgetUsage, N as DECISION_TIMEOUT_MS, O as FleetEvent, Q as FleetHandler, j as FleetUsage, k as FleetUsageAggregator, R as SubagentBudget, Z as SubagentUsageSnapshot, _ as TIMEOUT_PREEMPT_FRACTION, a0 as makeAgentSubagentRunner, a1 as withDisabledToolFiltering } from '../agent-subagent-runner-BimKihiC.js';
9
- export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-BFJ2ODzI.js';
10
- import { b as Mailbox, c as MailboxSendInput, M as MailboxMessage, d as MailboxQuery, e as MailboxAckInput, f as MailboxAckBatchInput, a as MailboxAgentStatus, A as AgentRegistrationInput, g as AgentHeartbeatInput, P as PurgeOptions, j as PurgeResult, C as ClientRegistrationInput, h as ClientHeartbeatInput, i as ClientStatus } from '../mailbox-types-DTl7bRH3.js';
11
- export { k as ClientSource, l as MailboxMessageType, m as MailboxTaskContext, R as ReadReceipts, n as RegisteredAgent, o as normalizeRecipient } from '../mailbox-types-DTl7bRH3.js';
12
- import { G as GlobalMailbox } from '../global-mailbox-Dr4cTKqL.js';
13
- export { aw as resolveProjectDir } from '../global-mailbox-Dr4cTKqL.js';
14
- import { C as Context, T as Tool } from '../context-DPlA6kid.js';
15
- import { A as AdaptiveConcurrencyConfig } from '../config-DAOjriz9.js';
1
+ export { I as InMemoryAgentBridge, a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DXC6QDJ4.js';
2
+ import { F as FleetBus } from '../agent-subagent-runner-PoqNKiR4.js';
3
+ export { i as AgentFactory, x as AgentFactoryResult, y as AgentRunnerOptions, z as BudgetExceededError, E as BudgetKind, G as BudgetLimits, H as BudgetNegotiationMode, I as BudgetThresholdDecision, J as BudgetThresholdHandler, K as BudgetThresholdSignal, L as BudgetUsage, O as DECISION_TIMEOUT_MS, Q as FleetEvent, R as FleetHandler, j as FleetUsage, k as FleetUsageAggregator, W as SubagentBudget, a0 as SubagentUsageSnapshot, a1 as TIMEOUT_PREEMPT_FRACTION, a3 as makeAgentSubagentRunner, a4 as withDisabledToolFiltering } from '../agent-subagent-runner-PoqNKiR4.js';
4
+ import { H as FleetManager, s as Director } from '../null-fleet-bus-DkdmZJ_W.js';
5
+ export { A as ACP_AGENTS, a as AGENTS_BY_PHASE, b as AGENT_CATALOG, c as ALL_AGENT_DEFINITIONS, d as ALL_FLEET_AGENTS, e as AUDIT_LOG_AGENT, f as AutoExtendCeiling, g as AutoExtendPolicy, B as BUG_HUNTER_AGENT, h as BugFinding, C as CollabBudgetConfig, i as CollabBudgetOverrides, j as CollabBudgetWarningPayload, k as CollabDebugReport, l as CollabSession, m as CollabSessionOptions, n as CreateDelegateToolOptions, o as CriticConcern, p as CriticEvaluation, D as DEFAULT_DIRECTOR_PREAMBLE, q as DEFAULT_SUBAGENT_BASELINE, r as DelegateHost, t as DirectorAlert, u as DirectorAlertLevel, v as DirectorCancelCollabPayload, w as DirectorPromptParts, x as DirectorSessionFactory, y as DirectorSessionFactoryOptions, F as FLEET_ROSTER, z as FLEET_ROSTER_BUDGETS, E as FLEET_ROSTER_WITHACP, G as FleetCostCapError, I as FleetManagerOptions, J as FleetRosterBudget, K as FleetSpawnBudgetError, L as ICoordinator, M as IFleetManager, N as LargeAnswerStore, O as NULL_FLEET_BUS, R as REFACTOR_PLANNER_AGENT, P as RefactorPhase, Q as RefactorPlan, S as SECURITY_SCANNER_AGENT, T as SharedFileEntry, U as SharedFileSnapshot, V as SubagentPromptParts, W as applyRosterBudget, X as attachAutoExtend, Y as composeDirectorPrompt, Z as composeSubagentPrompt, _ as createDelegateTool, $ as getAgentDefinition, a0 as makeAskResultTool, a1 as makeAskTool, a2 as makeAssignTool, a3 as makeAwaitTasksTool, a4 as makeCollabDebugTool, a5 as makeDirectorSessionFactory, a6 as makeFleetEmitTool, a7 as makeFleetHealthTool, a7 as makeFleetSessionTool, a7 as makeFleetStatusTool, a7 as makeFleetTool, a7 as makeFleetUsageTool, a8 as makeRollUpTool, a9 as makeSpawnTool, aa as makeTerminateAllTool, ab as makeTerminateTool, ac as makeWorkCompleteTool, ad as rosterSummaryFromConfigs } from '../null-fleet-bus-DkdmZJ_W.js';
6
+ import { E as EventBus, B as BrainArbiter, f as BrainDecisionOption, k as BrainRisk, h as BrainDecisionRequest, e as BrainDecision, i as BrainDecisionSource } from '../events-Bs2fmldo.js';
7
+ export { g as BrainDecisionQueue, j as BrainFallback, D as DefaultBrainArbiter, l as DefaultBrainArbiterOptions, H as HumanEscalatingBrainArbiter, O as ObservableBrainArbiter, w as formatHumanPrompt } from '../events-Bs2fmldo.js';
8
+ import { b as Mailbox, c as MailboxSendInput, M as MailboxMessage, d as MailboxQuery, e as MailboxAckInput, f as MailboxAckBatchInput, a as MailboxAgentStatus, A as AgentRegistrationInput, g as AgentHeartbeatInput, P as PurgeOptions, j as PurgeResult, C as ClientRegistrationInput, h as ClientHeartbeatInput, i as ClientStatus } from '../mailbox-types-BGZWrYTJ.js';
9
+ export { k as ClientSource, l as MailboxMessageType, m as MailboxTaskContext, R as ReadReceipts, n as RegisteredAgent, o as normalizeRecipient } from '../mailbox-types-BGZWrYTJ.js';
10
+ import { b as AgentDefinition } from '../multi-agent-coordinator-CieyUoEL.js';
11
+ export { T as AGENT_TOOL_PRESETS, c as AgentBudgetTier, d as AgentCapability, A as AgentPhase, e as DEFAULT_DISPATCH_ROLE, a as DefaultMultiAgentCoordinator, f as DispatchCandidate, D as DispatchClassifier, g as DispatchMethod, h as DispatchOptions, i as DispatchResult, H as HEAVY_BUDGET, L as LIGHT_BUDGET, M as MEDIUM_BUDGET, j as MultiAgentCoordinatorOptions, k as dispatchAgent, m as makeLLMClassifier, s as scoreAgents } from '../multi-agent-coordinator-CieyUoEL.js';
12
+ import { G as GlobalMailbox } from '../global-mailbox-Ct7IorLJ.js';
13
+ export { aA as resolveProjectDir } from '../global-mailbox-Ct7IorLJ.js';
14
+ import { C as Context, T as Tool } from '../tool-BkOgs_KL.js';
15
+ import { A as AdaptiveConcurrencyConfig } from '../config-Cr3312zc.js';
16
+ import { L as Logger } from '../logger-B63L5bTg.js';
17
+ import '../index-kidebiDh.js';
18
+ import '../pipeline-BwAP21_4.js';
19
+ import '../permission-Dx6dIqS2.js';
20
+ import '../observability-D-HZN_mF.js';
21
+ import '../secret-scrubber-3MHDDAtm.js';
22
+ import '../retry-policy-D4feSLk3.js';
16
23
  import 'node:events';
17
- import '../logger-B63L5bTg.js';
18
24
  import '../director-state-BfeCUbmk.js';
19
- import '../index-DJXj-dcr.js';
20
- import '../pipeline-CEjBjzVA.js';
21
- import '../observability-D-HZN_mF.js';
22
- import '../permission-DbsGOA1C.js';
23
- import '../retry-policy-Git9WF6d.js';
24
25
 
25
26
  /** Phase 1 · Discovery — map the territory before any work begins. */
26
27
  declare const DISCOVERY_AGENTS: AgentDefinition[];
@@ -49,72 +50,6 @@ declare const DELIVERY_AGENTS: AgentDefinition[];
49
50
  /** Phase 9 · Meta — agents that improve the agent system itself. */
50
51
  declare const META_AGENTS: AgentDefinition[];
51
52
 
52
- /**
53
- * DefaultMailbox — append-only JSONL inter-agent mailbox (per-session).
54
- *
55
- * Stores messages under `<sessionDir>/_mailbox.jsonl`. Every send appends
56
- * one line. Query reads and filters all lines. Ack rewrites changed
57
- * messages in-place via atomic write.
58
- *
59
- * For cross-session communication, use GlobalMailbox instead.
60
- *
61
- * @module DefaultMailbox
62
- */
63
-
64
- declare class DefaultMailbox implements Mailbox {
65
- private readonly filePath;
66
- private _messageCache;
67
- private _messageCacheMtime;
68
- private _messageCacheSize;
69
- /** Primary index: recipient → Set of messages (points into _messageCache). */
70
- private _byTo;
71
- /** Secondary index: sender → Set of messages (points into _messageCache). */
72
- private _byFrom;
73
- /** Counts malformed JSONL lines skipped during parsing for observability. */
74
- private _corruptionCount;
75
- constructor(sessionDir: string);
76
- get mailboxPath(): string;
77
- /** Returns the count of malformed JSONL lines encountered during reads. */
78
- get corruptionCount(): number;
79
- send(input: MailboxSendInput): Promise<MailboxMessage>;
80
- query(q: MailboxQuery): Promise<MailboxMessage[]>;
81
- ack(input: MailboxAckInput): Promise<MailboxMessage | null>;
82
- ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]>;
83
- getAgentStatuses(): Promise<MailboxAgentStatus[]>;
84
- getOnlineAgents(): Promise<MailboxAgentStatus[]>;
85
- registerAgent(_input: AgentRegistrationInput): Promise<void>;
86
- heartbeat(_input: AgentHeartbeatInput): Promise<void>;
87
- unreadCount(forAgentId: string): Promise<number>;
88
- close(): Promise<void>;
89
- clearAll(): Promise<void>;
90
- purgeStale(opts?: PurgeOptions): Promise<PurgeResult>;
91
- registerClient(_input: ClientRegistrationInput): Promise<void>;
92
- clientHeartbeat(_input: ClientHeartbeatInput): Promise<void>;
93
- getClientStatuses(): Promise<ClientStatus[]>;
94
- private _readAll;
95
- /**
96
- * Read only newly-appended bytes from the file and append them to the
97
- * in-memory cache, avoiding a full re-read when the file only grew.
98
- */
99
- private _readNewMessagesOnly;
100
- /** Parse a JSONL string into MailboxMessage[], including migration. */
101
- private _parseLines;
102
- /**
103
- * Stat the mailbox file under the assumption that we are holding the
104
- * file lock, and that a write to the file has just completed. Returns
105
- * the (mtimeMs, size) pair, or (-1, -1) if the file does not exist
106
- * (e.g. ackMany/purgeStale on a session that has never sent a message).
107
- */
108
- private _statUnderLockOrAbsent;
109
- private _readAllCached;
110
- private _setMessageCache;
111
- private _pushToCache;
112
- /** Rebuild both indexes from a full message list. */
113
- private _buildIndexes;
114
- /** Add a single message to both indexes. */
115
- private _indexMsg;
116
- }
117
-
118
53
  /**
119
54
  * BrainMonitor — the Brain's SELF-ACTIVATION layer.
120
55
  *
@@ -189,276 +124,124 @@ declare class BrainMonitor {
189
124
  }
190
125
 
191
126
  /**
192
- * Single-instance mailbox-bridge lock.
127
+ * dep-watcher — File-change → Mailbox bridge for dependency monitoring.
193
128
  *
194
- * Per-project isolation: each project (resolved via
195
- * `resolveProjectDir`) gets its own lock file under
196
- * `<projectDir>/.mailbox-bridge.lock`. Two projects on the same
197
- * machine never collide different slugs, different lock files,
198
- * and (with default port 0) different OS-assigned ports.
129
+ * Watches dependency manifest files (package.json, go.mod, Cargo.toml, etc.)
130
+ * and when they change (create/update), posts a message to the inter-agent
131
+ * mailbox. A tech-stack analysis agent can then pick up the message and
132
+ * run a full tech-stack validation, feeding results back to the coding LLM.
199
133
  *
200
- * The lock holds:
201
- * - pid process id of the owning `wstack mailbox serve`
202
- * - host, port what the owner actually bound (port may be OS-assigned)
203
- * - url convenience copy for callers
204
- * - token the bearer token (so external agents don't have to
205
- * re-read it from .mailbox.token separately)
206
- * - generation monotonically increasing counter; bumped on every
207
- * acquire. Lets a release() call identify whether the
208
- * current lock file still belongs to *this* process
209
- * (e.g. after a stale cleanup raced with us).
210
- * - spawnedAt ISO timestamp — for observability, not load-bearing.
134
+ * This module is a *config factory*, not a watcher itself. It produces
135
+ * configuration that the file-watcher plugin (`watch_start`) can consume,
136
+ * plus a callback that posts to a Mailbox instance.
211
137
  *
212
- * Concurrency model:
213
- * - `acquireOrJoin` is atomic via rename(2). Two concurrent spawns
214
- * race to write a tmpfile then rename; one wins, the other reads
215
- * the winner's lock and joins.
216
- * - PID liveness is checked via `process.kill(pid, 0)` (POSIX) or
217
- * `tasklist` (Windows). A live PID means another instance owns
218
- * this project; a dead PID means the lock is stale and gets cleaned.
219
- * - `release` is best-effort: a missing lock file at shutdown is
220
- * fine (someone else already took over). A generation mismatch means
221
- * we lost the race and another instance owns it now — also fine.
138
+ * Usage:
139
+ * const cfg = makeDependencyWatcherConfig({
140
+ * projectRoot: '/path/to/project',
141
+ * mailbox,
142
+ * targetAgent: 'tech-stack-agent',
143
+ * });
144
+ * // cfg.watchPaths → pass to watch_start
145
+ * // cfg.onChange → call on file-watcher:changed events
222
146
  *
223
- * Token persistence: the token in the lock always matches the token in
224
- * `.mailbox.token`, so an external agent that reads either file gets the
225
- * same value. While an instance stays alive, every joining caller
226
- * (`kind: 'joined'`) reuses that one token. A cold (re)start — no lock,
227
- * or a lock whose owner PID is dead/unhealthy — mints a FRESH token and
228
- * rewrites both files atomically. External agents must therefore re-read
229
- * `.mailbox.token` after a bridge restart (a stale token returns 401).
147
+ * @module dep-watcher
230
148
  */
231
- declare const MAILBOX_BRIDGE_LOCK_FILENAME = ".mailbox-bridge.lock";
232
- declare const MAILBOX_BRIDGE_TOKEN_FILENAME = ".mailbox.token";
233
- interface MailboxBridgeLock {
234
- pid: number;
235
- host: string;
236
- port: number;
237
- url: string;
238
- token: string;
239
- generation: number;
240
- spawnedAt: string;
149
+
150
+ /**
151
+ * Files that declare project dependencies. When any of these change
152
+ * (create/update), a mailbox message triggers a tech-stack audit.
153
+ */
154
+ declare const DEPENDENCY_FILE_PATTERNS: ReadonlyArray<string>;
155
+ interface DepWatchEntry {
156
+ /** Relative path from project root that changed. */
157
+ path: string;
158
+ /** Event type from the file watcher: 'change', 'add', 'delete' (rare). */
159
+ event: string;
160
+ /** ISO8601 timestamp of when the change was detected. */
161
+ timestamp: string;
241
162
  }
242
- type AcquireResult = {
243
- kind: 'acquired';
244
- lock: MailboxBridgeLock;
245
- tokenPath: string;
246
- } | {
247
- kind: 'joined';
248
- lock: MailboxBridgeLock;
249
- tokenPath: string;
250
- } | {
251
- kind: 'port-conflict';
252
- existing: MailboxBridgeLock;
253
- };
254
- interface AcquireOptions {
255
- /** Project dir (already resolved by caller via resolveProjectDir). */
256
- projectDir: string;
257
- /** Bind host. Required when acquiring. */
258
- host: string;
259
- /** Explicit port. Pass null/undefined to mean "OS-assigned" (read it after listen). */
260
- requestedPort: number | null;
261
- /** When true, fail loud on EADDRINUSE. When false, fall back to OS-assigned. */
262
- strictPort: boolean;
163
+ interface DependencyWatcherConfig {
164
+ /** Paths to pass to `watch_start` — the project-root-relative dependency files. */
165
+ watchPaths: string[];
166
+ /** Callback to invoke when a dependency file changes. Posts to mailbox. */
167
+ onChange: (entry: DepWatchEntry) => Promise<void>;
168
+ /** Debounce window in ms — multiple changes to the same file within this window are collapsed. */
169
+ debounceMs: number;
170
+ /** Cancel all in-flight debounce timers. Call when the file watcher is
171
+ * stopped (session end / project switch) so pending setTimeouts — each
172
+ * holding a closure over the mailbox + entry — don't leak. */
173
+ dispose: () => void;
174
+ }
175
+ interface DependencyWatcherOptions {
176
+ /** Absolute path to the project root. */
177
+ projectRoot: string;
178
+ /** The mailbox instance where messages will be posted. */
179
+ mailbox: Mailbox;
180
+ /** Agent id that should receive the tech-stack audit task. */
181
+ targetAgent?: string | undefined;
182
+ /** Agent id of the watcher (sender). */
183
+ watcherAgentId?: string | undefined;
184
+ /** Debounce window in ms. Default: 3000 (3 seconds). */
185
+ debounceMs?: number | undefined;
186
+ /** Only watch these specific patterns. Defaults to DEPENDENCY_FILE_PATTERNS. */
187
+ patterns?: string[] | undefined;
263
188
  }
264
189
  /**
265
- * Try to acquire the mailbox-bridge lock for `projectDir`. If another
266
- * instance is already alive and healthy, join it. Otherwise claim
267
- * the slot for ourselves.
268
- *
269
- * Two-phase contract:
270
- * 1. Caller invokes `acquireOrJoin(...)` BEFORE calling
271
- * `server.listen()`. The returned lock either:
272
- * - `kind: 'joined'` → another instance is alive, the caller
273
- * should NOT bind; just print the URL/token
274
- * and exit cleanly (return 0).
275
- * - `kind: 'acquired'` → caller is the owner, proceeds to bind.
276
- * - `kind: 'port-conflict'` → caller asked for an explicit port
277
- * that's already taken by an unrelated
278
- * process; we return the existing owner
279
- * but the caller decides what to do
280
- * (loud-fail).
281
- * 2. After `server.listen()` resolves with a real port, the caller
282
- * invokes `finalize(lock, boundPort)` to atomically write the
283
- * final lock + token file with the OS-assigned port.
190
+ * Build a dependency watcher configuration. The returned `watchPaths` can be
191
+ * passed directly to the `watch_start` tool, and `onChange` should be wired
192
+ * to the `file-watcher:changed` custom event.
284
193
  *
285
- * The two-phase split keeps the listen() call out of the lock module —
286
- * the caller owns the HTTP server instance; the lock module owns
287
- * the on-disk contract.
194
+ * When a dependency file changes, `onChange` posts a high-priority `assign`
195
+ * message to the mailbox targeting the tech-stack agent, with the changed
196
+ * file path and event type in the body.
288
197
  */
289
- declare function acquireOrJoin(opts: AcquireOptions): Promise<AcquireResult>;
198
+ declare function makeDependencyWatcherConfig(opts: DependencyWatcherOptions): DependencyWatcherConfig;
199
+
290
200
  /**
291
- * Phase 2 after server.listen() resolves, write the final lock
292
- * with the actually-bound port and the same token. Also writes the
293
- * .mailbox.token file with mode 0600 so external agents can read it.
201
+ * dep-watcher-bridgeBridges the file-watcher plugin's custom events
202
+ * to the dependency watcher mailbox pipeline.
294
203
  *
295
- * Returns the finalized lock so the caller can use the resolved URL.
296
- */
297
- declare function finalize(projectDir: string, tentative: MailboxBridgeLock, boundPort: number): Promise<MailboxBridgeLock>;
298
- /**
299
- * Phase 3 — best-effort cleanup on shutdown. Removes the lock + token
300
- * files IF this process is still the recorded owner (generation match).
204
+ * The file-watcher plugin emits `file-watcher:changed` custom events
205
+ * when files change. This module subscribes to those events, filters
206
+ * for dependency manifests (package.json, go.mod, etc.), and posts
207
+ * assign messages to the inter-agent mailbox for tech-stack audit.
301
208
  *
302
- * If the generation doesn't match, another acquire() has already
303
- * superseded us — we must NOT delete their lock.
304
- */
305
- declare function release(projectDir: string, generation: number): Promise<void>;
306
- /**
307
- * Read the lock file and return it, with enough information for the
308
- * caller to distinguish:
309
- * - 'live' — PID alive, /healthz reachable; safe to use.
310
- * - 'probe-failed' — PID alive (or recently was) but /healthz
311
- * unreachable. Caller can still return the URL
312
- * + token to the host so its request layer can
313
- * retry; the host's fetch timeout will surface
314
- * the real error if the bridge is truly dead.
315
- * - 'absent' — no lock file existed, or it was malformed
316
- * (cleaned up best-effort).
209
+ * Returns a dispose function that unsubscribes from the event bus.
317
210
  *
318
- * Distinguishing 'probe-failed' from 'absent' matters for the
319
- * "joined vs spawned" decision in tryAcquireMailboxBridge — we
320
- * don't want to spawn a second bridge just because /healthz flaked.
211
+ * @module dep-watcher-bridge
321
212
  */
322
- type LiveLockResult = {
323
- kind: 'live';
324
- lock: MailboxBridgeLock;
325
- } | {
326
- kind: 'probe-failed';
327
- lock: MailboxBridgeLock;
328
- } | {
329
- kind: 'absent';
330
- };
331
- declare function readLiveLock(projectDir: string): Promise<LiveLockResult>;
332
213
 
214
+ interface DepWatcherBridgeOptions {
215
+ /** The event bus to subscribe to (same bus the file-watcher plugin emits on). */
216
+ events: EventBus;
217
+ /** The mailbox instance where dep-change notifications will be posted. */
218
+ mailbox: Mailbox;
219
+ /** Absolute project root — used to build watch paths and match file patterns. */
220
+ projectRoot: string;
221
+ /** Agent id the tech-stack audit tasks should target. Default: 'tech-stack'. */
222
+ targetAgent?: string | undefined;
223
+ /** Agent id of the watcher/sender. Default: 'dep-watcher'. */
224
+ watcherAgentId?: string | undefined;
225
+ /** Debounce window in ms. Default: 3000 (3 seconds). */
226
+ debounceMs?: number | undefined;
227
+ }
333
228
  /**
334
- * MailboxHealthWatchdog — probes the mailbox HTTP bridge and posts a
335
- * status message when it goes down.
229
+ * Wire the file-watcher's `file-watcher:changed` events into the
230
+ * dependency watcher mailbox pipeline.
336
231
  *
337
- * Designed to be embedded inside the WrongStack REPL/TUI/WebUI process
338
- * NOT a standalone agent. WrongStack has its own cross-agent
339
- * coordination channel, so the cheapest reliable signal is "ask the
340
- * bridge if it's alive, and if it's not, tell the rest of the team
341
- * via the same channel the bridge exposes."
232
+ * Returns a dispose function. Call it to unsubscribe when the
233
+ * session ends or the watcher is no longer needed.
342
234
  *
343
235
  * Usage:
344
- *
345
- * const mailbox = new GlobalMailbox(projectDir);
346
- * const watchdog = new MailboxHealthWatchdog({
347
- * mailbox,
348
- * url: 'http://127.0.0.1:7788',
349
- * probeIntervalMs: 15_000,
350
- * onAlert: (event) => console.warn('mailbox bridge', event.kind),
236
+ * const dispose = attachDepWatcherBridge({
237
+ * events: ctx.events,
238
+ * mailbox: new DefaultMailbox(sessionDir),
239
+ * projectRoot: ctx.projectRoot,
351
240
  * });
352
- * await watchdog.start();
353
- * // ...later...
354
- * await watchdog.stop();
355
- *
356
- * The watchdog is a passive observer: it does NOT start the bridge.
357
- * Starting the bridge is the user's job (`wstack mailbox serve` or
358
- * `/mailbox-serve`). The watchdog then reports on what the user did.
359
- */
360
-
361
- interface MailboxHealthWatchdogOptions {
362
- /** Project mailbox to probe-and-report on. Required. */
363
- mailbox: GlobalMailbox;
364
- /** URL of the mailbox bridge (no trailing slash). Required. */
365
- url: string;
366
- /** Probe interval in milliseconds. Default: 15_000. */
367
- probeIntervalMs?: number;
368
- /** Per-probe timeout in milliseconds. Default: 3_000. */
369
- probeTimeoutMs?: number;
370
- /**
371
- * After this many consecutive failures the watchdog posts an alert.
372
- * Default: 2 (so a single transient timeout doesn't trigger spam).
373
- */
374
- failureThreshold?: number;
375
- /**
376
- * Optional callback for local observability — fired on every state
377
- * transition. The mailbox post is independent of this callback.
378
- */
379
- onAlert?: ((event: MailboxHealthEvent) => void) | undefined;
380
- /**
381
- * Agent id used to post the alert message. Default: 'mailbox-bridge-watchdog'.
382
- */
383
- from?: string;
384
- }
385
- type MailboxHealthEvent = {
386
- kind: 'probe-failed';
387
- status?: number;
388
- error?: string;
389
- } | {
390
- kind: 'alert-posted';
391
- consecutiveFailures: number;
392
- } | {
393
- kind: 'recovery-posted';
394
- downtimeMs: number;
395
- } | {
396
- kind: 'started';
397
- intervalMs: number;
398
- } | {
399
- kind: 'stopped';
400
- };
401
- declare const MAILBOX_HEALTH_DEFAULT_INTERVAL_MS = 15000;
402
- declare const MAILBOX_HEALTH_DEFAULT_TIMEOUT_MS = 3000;
403
- declare const MAILBOX_HEALTH_DEFAULT_FAILURE_THRESHOLD = 2;
404
- declare const MAILBOX_HEALTH_DEFAULT_FROM = "mailbox-bridge-watchdog";
405
- declare class MailboxHealthWatchdog {
406
- private readonly mailbox;
407
- private readonly url;
408
- private readonly intervalMs;
409
- private readonly timeoutMs;
410
- private readonly failureThreshold;
411
- private readonly from;
412
- private readonly onAlert?;
413
- private timer;
414
- private consecutiveFailures;
415
- private downSince;
416
- private alerting;
417
- private inFlight;
418
- private aborted;
419
- constructor(opts: MailboxHealthWatchdogOptions);
420
- /** Start probing on `intervalMs`. Idempotent — second call is a no-op. */
421
- start(): Promise<void>;
422
- /** Stop probing. Safe to call multiple times. */
423
- stop(): Promise<void>;
424
- /** True between start() and stop(). */
425
- isRunning(): boolean;
426
- /** Number of consecutive failed probes since the last successful probe. */
427
- get currentFailureStreak(): number;
428
- /** True iff the watchdog currently considers the bridge down. */
429
- isBridgeDown(): boolean;
430
- private emit;
431
- private tick;
432
- private probe;
433
- private recordSuccess;
434
- private recordFailure;
435
- private postDown;
436
- private postRecovery;
437
- }
438
- interface DownAlertInput {
439
- from: string;
440
- url: string;
441
- consecutiveFailures: number;
442
- }
443
- declare function buildDownAlert(input: DownAlertInput): MailboxSendInput;
444
- interface RecoveryAlertInput {
445
- from: string;
446
- url: string;
447
- downtimeMs: number;
448
- consecutiveFailures: number;
449
- }
450
- declare function buildRecoveryAlert(input: RecoveryAlertInput): MailboxSendInput;
451
- interface WatchdogConfig {
452
- probeIntervalMs: number;
453
- probeTimeoutMs: number;
454
- failureThreshold: number;
455
- }
456
- /**
457
- * Throws if the watchdog config is invalid. Called from the
458
- * MailboxHealthWatchdog constructor so misconfiguration fails fast
459
- * (at startup), not silently after the first probe.
241
+ * // ... session runs ...
242
+ * dispose(); // clean up on exit
460
243
  */
461
- declare function validateWatchdogOptions(cfg: WatchdogConfig): void;
244
+ declare function attachDepWatcherBridge(opts: DepWatcherBridgeOptions): () => void;
462
245
 
463
246
  /**
464
247
  * mailbox-tool — Tool that exposes the inter-agent mailbox to agents.
@@ -564,124 +347,271 @@ declare function makeMailSendTool(opts?: MailToolsOptions): Tool;
564
347
  declare function makeMailInboxTool(opts?: MailToolsOptions): Tool;
565
348
 
566
349
  /**
567
- * dep-watcherFile-change Mailbox bridge for dependency monitoring.
568
- *
569
- * Watches dependency manifest files (package.json, go.mod, Cargo.toml, etc.)
570
- * and when they change (create/update), posts a message to the inter-agent
571
- * mailbox. A tech-stack analysis agent can then pick up the message and
572
- * run a full tech-stack validation, feeding results back to the coding LLM.
350
+ * DefaultMailboxappend-only JSONL inter-agent mailbox (per-session).
573
351
  *
574
- * This module is a *config factory*, not a watcher itself. It produces
575
- * configuration that the file-watcher plugin (`watch_start`) can consume,
576
- * plus a callback that posts to a Mailbox instance.
352
+ * Stores messages under `<sessionDir>/_mailbox.jsonl`. Every send appends
353
+ * one line. Query reads and filters all lines. Ack rewrites changed
354
+ * messages in-place via atomic write.
577
355
  *
578
- * Usage:
579
- * const cfg = makeDependencyWatcherConfig({
580
- * projectRoot: '/path/to/project',
581
- * mailbox,
582
- * targetAgent: 'tech-stack-agent',
583
- * });
584
- * // cfg.watchPaths → pass to watch_start
585
- * // cfg.onChange → call on file-watcher:changed events
356
+ * For cross-session communication, use GlobalMailbox instead.
586
357
  *
587
- * @module dep-watcher
358
+ * @module DefaultMailbox
588
359
  */
589
360
 
361
+ declare class DefaultMailbox implements Mailbox {
362
+ private readonly filePath;
363
+ private _messageCache;
364
+ private _messageCacheMtime;
365
+ private _messageCacheSize;
366
+ /** Primary index: recipient → Set of messages (points into _messageCache). */
367
+ private _byTo;
368
+ /** Secondary index: sender → Set of messages (points into _messageCache). */
369
+ private _byFrom;
370
+ /** Counts malformed JSONL lines skipped during parsing for observability. */
371
+ private _corruptionCount;
372
+ constructor(sessionDir: string);
373
+ get mailboxPath(): string;
374
+ /** Returns the count of malformed JSONL lines encountered during reads. */
375
+ get corruptionCount(): number;
376
+ send(input: MailboxSendInput): Promise<MailboxMessage>;
377
+ query(q: MailboxQuery): Promise<MailboxMessage[]>;
378
+ ack(input: MailboxAckInput): Promise<MailboxMessage | null>;
379
+ softDelete(_mailId: string, _by: string): Promise<MailboxMessage | null>;
380
+ restore(_mailId: string): Promise<MailboxMessage | null>;
381
+ ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]>;
382
+ getAgentStatuses(): Promise<MailboxAgentStatus[]>;
383
+ getOnlineAgents(): Promise<MailboxAgentStatus[]>;
384
+ registerAgent(_input: AgentRegistrationInput): Promise<void>;
385
+ deregisterAgent(_agentId: string): Promise<void>;
386
+ heartbeat(_input: AgentHeartbeatInput): Promise<void>;
387
+ unreadCount(forAgentId: string): Promise<number>;
388
+ close(): Promise<void>;
389
+ clearAll(): Promise<void>;
390
+ purgeStale(opts?: PurgeOptions): Promise<PurgeResult>;
391
+ registerClient(_input: ClientRegistrationInput): Promise<void>;
392
+ clientHeartbeat(_input: ClientHeartbeatInput): Promise<void>;
393
+ getClientStatuses(): Promise<ClientStatus[]>;
394
+ private _readAll;
395
+ /**
396
+ * Read only newly-appended bytes from the file and append them to the
397
+ * in-memory cache, avoiding a full re-read when the file only grew.
398
+ */
399
+ private _readNewMessagesOnly;
400
+ /** Parse a JSONL string into MailboxMessage[], including migration. */
401
+ private _parseLines;
402
+ /**
403
+ * Stat the mailbox file under the assumption that we are holding the
404
+ * file lock, and that a write to the file has just completed. Returns
405
+ * the (mtimeMs, size) pair, or (-1, -1) if the file does not exist
406
+ * (e.g. ackMany/purgeStale on a session that has never sent a message).
407
+ */
408
+ private _statUnderLockOrAbsent;
409
+ private _readAllCached;
410
+ private _setMessageCache;
411
+ private _pushToCache;
412
+ /** Rebuild both indexes from a full message list. */
413
+ private _buildIndexes;
414
+ /** Add a single message to both indexes. */
415
+ private _indexMsg;
416
+ }
417
+
590
418
  /**
591
- * Files that declare project dependencies. When any of these change
592
- * (create/update), a mailbox message triggers a tech-stack audit.
419
+ * Mailbox message action helpers (skeleton).
420
+ *
421
+ * Phase 1 skeleton: declares the {@link MailboxMessageAction} union
422
+ * (the verb that a user or agent issues against a single message) and
423
+ * the per-action input shapes. The actual implementations
424
+ * ({@link GlobalMailbox.markRead}, {@link GlobalMailbox.acknowledge},
425
+ * {@link GlobalMailbox.softDelete}, {@link GlobalMailbox.restore}) are
426
+ * added in Phase 2 alongside the corresponding `GlobalMailbox`
427
+ * methods.
428
+ *
429
+ * Keeping the verb+input types in their own file means the WebUI
430
+ * client (Phase 3) and the server route handlers (Phase 4) can
431
+ * import them independently of the `GlobalMailbox` implementation,
432
+ * and a future "message actions" CLI subcommand only has to add
433
+ * one verb to a single place.
593
434
  */
594
- declare const DEPENDENCY_FILE_PATTERNS: ReadonlyArray<string>;
595
- interface DepWatchEntry {
596
- /** Relative path from project root that changed. */
597
- path: string;
598
- /** Event type from the file watcher: 'change', 'add', 'delete' (rare). */
599
- event: string;
600
- /** ISO8601 timestamp of when the change was detected. */
601
- timestamp: string;
602
- }
603
- interface DependencyWatcherConfig {
604
- /** Paths to pass to `watch_start` the project-root-relative dependency files. */
605
- watchPaths: string[];
606
- /** Callback to invoke when a dependency file changes. Posts to mailbox. */
607
- onChange: (entry: DepWatchEntry) => Promise<void>;
608
- /** Debounce window in ms multiple changes to the same file within this window are collapsed. */
609
- debounceMs: number;
610
- /** Cancel all in-flight debounce timers. Call when the file watcher is
611
- * stopped (session end / project switch) so pending setTimeouts — each
612
- * holding a closure over the mailbox + entry don't leak. */
613
- dispose: () => void;
614
- }
615
- interface DependencyWatcherOptions {
616
- /** Absolute path to the project root. */
617
- projectRoot: string;
618
- /** The mailbox instance where messages will be posted. */
619
- mailbox: Mailbox;
620
- /** Agent id that should receive the tech-stack audit task. */
621
- targetAgent?: string | undefined;
622
- /** Agent id of the watcher (sender). */
623
- watcherAgentId?: string | undefined;
624
- /** Debounce window in ms. Default: 3000 (3 seconds). */
625
- debounceMs?: number | undefined;
626
- /** Only watch these specific patterns. Defaults to DEPENDENCY_FILE_PATTERNS. */
627
- patterns?: string[] | undefined;
435
+
436
+ /**
437
+ * High-level verbs the WebUI/server route handlers expose. The
438
+ * mapping to underlying `MailboxAckInput` is straightforward:
439
+ * - `mark-read` → `ack({ read: true, completed: false })`
440
+ * - `acknowledge`→ `ack({ read: true, completed: true })`
441
+ * - `reopen` → `ack({ read: false, completed: false })`
442
+ * - `soft-delete`→ not an `ack` — a separate `Mailbox.softDelete()`
443
+ * that flips `deletedAt` to "now" (recoverable) and is filtered
444
+ * out of the default `query()`.
445
+ * - `restore` the inverse of `soft-delete`. Undoes a
446
+ * `softDelete` by clearing `deletedAt`.
447
+ */
448
+ type MailboxMessageAction = 'mark-read' | 'acknowledge' | 'reopen' | 'soft-delete' | 'restore';
449
+ /** Per-action request body sent from the WebUI server route. */
450
+ interface MailboxActionInput {
451
+ action: MailboxMessageAction;
452
+ mailId: string;
453
+ /** Acting agent / user. Required by the server to stamp
454
+ * `readBy` / `completedBy`. */
455
+ readerId: string;
456
+ /** Optional human note (e.g. "triaged — will follow up"). */
457
+ note?: string | undefined;
458
+ /** Optional idempotency key so retried requests don't double-apply
459
+ * the action. Phase 4 wires this through to the CLI. */
460
+ requestId?: string | undefined;
461
+ }
462
+ /** Per-action response. Echoes the action + the resulting message
463
+ * state so the UI can reconcile optimistic updates. */
464
+ interface MailboxActionResult {
465
+ action: MailboxMessageAction;
466
+ mailId: string;
467
+ /** Updated message snapshot. `null` if the message was already in
468
+ * the target state (e.g. `mark-read` on a message the user has
469
+ * already read) — the WebUI can ignore the result in that case. */
470
+ message: MailboxMessage | null;
471
+ /** True if the action actually mutated state; false if it was a
472
+ * no-op. Lets the WebUI decide whether to update its local copy. */
473
+ changed: boolean;
628
474
  }
629
475
  /**
630
- * Build a dependency watcher configuration. The returned `watchPaths` can be
631
- * passed directly to the `watch_start` tool, and `onChange` should be wired
632
- * to the `file-watcher:changed` custom event.
633
- *
634
- * When a dependency file changes, `onChange` posts a high-priority `assign`
635
- * message to the mailbox targeting the tech-stack agent, with the changed
636
- * file path and event type in the body.
476
+ * Convert a high-level action into the underlying
477
+ * {@link MailboxAckInput} the existing `GlobalMailbox.ack` already
478
+ * supports. `soft-delete` and `restore` do NOT go through `ack` —
479
+ * the caller must dispatch them to `GlobalMailbox.softDelete` /
480
+ * `GlobalMailbox.restore` instead. This helper returns `null` for
481
+ * those two so the type signature forces the caller to handle them
482
+ * separately.
637
483
  */
638
- declare function makeDependencyWatcherConfig(opts: DependencyWatcherOptions): DependencyWatcherConfig;
484
+ declare function actionToAckInput(action: Exclude<MailboxMessageAction, 'soft-delete' | 'restore'>, input: MailboxActionInput): MailboxAckInput;
639
485
 
640
486
  /**
641
- * dep-watcher-bridgeBridges the file-watcher plugin's custom events
642
- * to the dependency watcher mailbox pipeline.
487
+ * MailboxHealthWatchdogprobes the mailbox HTTP bridge and posts a
488
+ * status message when it goes down.
643
489
  *
644
- * The file-watcher plugin emits `file-watcher:changed` custom events
645
- * when files change. This module subscribes to those events, filters
646
- * for dependency manifests (package.json, go.mod, etc.), and posts
647
- * assign messages to the inter-agent mailbox for tech-stack audit.
490
+ * Designed to be embedded inside the WrongStack REPL/TUI/WebUI process —
491
+ * NOT a standalone agent. WrongStack has its own cross-agent
492
+ * coordination channel, so the cheapest reliable signal is "ask the
493
+ * bridge if it's alive, and if it's not, tell the rest of the team
494
+ * via the same channel the bridge exposes."
648
495
  *
649
- * Returns a dispose function that unsubscribes from the event bus.
496
+ * Usage:
650
497
  *
651
- * @module dep-watcher-bridge
498
+ * const mailbox = new GlobalMailbox(projectDir);
499
+ * const watchdog = new MailboxHealthWatchdog({
500
+ * mailbox,
501
+ * url: 'http://127.0.0.1:7788',
502
+ * probeIntervalMs: 15_000,
503
+ * onAlert: (event) => console.warn('mailbox bridge', event.kind),
504
+ * });
505
+ * await watchdog.start();
506
+ * // ...later...
507
+ * await watchdog.stop();
508
+ *
509
+ * The watchdog is a passive observer: it does NOT start the bridge.
510
+ * Starting the bridge is the user's job (`wstack mailbox serve` or
511
+ * `/mailbox-serve`). The watchdog then reports on what the user did.
652
512
  */
653
513
 
654
- interface DepWatcherBridgeOptions {
655
- /** The event bus to subscribe to (same bus the file-watcher plugin emits on). */
656
- events: EventBus;
657
- /** The mailbox instance where dep-change notifications will be posted. */
658
- mailbox: Mailbox;
659
- /** Absolute project root used to build watch paths and match file patterns. */
660
- projectRoot: string;
661
- /** Agent id the tech-stack audit tasks should target. Default: 'tech-stack'. */
662
- targetAgent?: string | undefined;
663
- /** Agent id of the watcher/sender. Default: 'dep-watcher'. */
664
- watcherAgentId?: string | undefined;
665
- /** Debounce window in ms. Default: 3000 (3 seconds). */
666
- debounceMs?: number | undefined;
514
+ interface MailboxHealthWatchdogOptions {
515
+ /** Project mailbox to probe-and-report on. Required. */
516
+ mailbox: GlobalMailbox;
517
+ /** URL of the mailbox bridge (no trailing slash). Required. */
518
+ url: string;
519
+ /** Probe interval in milliseconds. Default: 15_000. */
520
+ probeIntervalMs?: number;
521
+ /** Per-probe timeout in milliseconds. Default: 3_000. */
522
+ probeTimeoutMs?: number;
523
+ /**
524
+ * After this many consecutive failures the watchdog posts an alert.
525
+ * Default: 2 (so a single transient timeout doesn't trigger spam).
526
+ */
527
+ failureThreshold?: number;
528
+ /**
529
+ * Optional callback for local observability — fired on every state
530
+ * transition. The mailbox post is independent of this callback.
531
+ */
532
+ onAlert?: ((event: MailboxHealthEvent) => void) | undefined;
533
+ /**
534
+ * Agent id used to post the alert message. Default: 'mailbox-bridge-watchdog'.
535
+ */
536
+ from?: string;
667
537
  }
668
- /**
669
- * Wire the file-watcher's `file-watcher:changed` events into the
670
- * dependency watcher → mailbox pipeline.
671
- *
672
- * Returns a dispose function. Call it to unsubscribe when the
673
- * session ends or the watcher is no longer needed.
674
- *
675
- * Usage:
676
- * const dispose = attachDepWatcherBridge({
677
- * events: ctx.events,
678
- * mailbox: new DefaultMailbox(sessionDir),
679
- * projectRoot: ctx.projectRoot,
680
- * });
681
- * // ... session runs ...
682
- * dispose(); // clean up on exit
538
+ type MailboxHealthEvent = {
539
+ kind: 'probe-failed';
540
+ status?: number;
541
+ error?: string;
542
+ } | {
543
+ kind: 'alert-posted';
544
+ consecutiveFailures: number;
545
+ } | {
546
+ kind: 'recovery-posted';
547
+ downtimeMs: number;
548
+ } | {
549
+ kind: 'started';
550
+ intervalMs: number;
551
+ } | {
552
+ kind: 'stopped';
553
+ };
554
+ declare const MAILBOX_HEALTH_DEFAULT_INTERVAL_MS = 15000;
555
+ declare const MAILBOX_HEALTH_DEFAULT_TIMEOUT_MS = 3000;
556
+ declare const MAILBOX_HEALTH_DEFAULT_FAILURE_THRESHOLD = 2;
557
+ declare const MAILBOX_HEALTH_DEFAULT_FROM = "mailbox-bridge-watchdog";
558
+ declare class MailboxHealthWatchdog {
559
+ private readonly mailbox;
560
+ private readonly url;
561
+ private readonly intervalMs;
562
+ private readonly timeoutMs;
563
+ private readonly failureThreshold;
564
+ private readonly from;
565
+ private readonly onAlert?;
566
+ private timer;
567
+ private consecutiveFailures;
568
+ private downSince;
569
+ private alerting;
570
+ private inFlight;
571
+ private aborted;
572
+ constructor(opts: MailboxHealthWatchdogOptions);
573
+ /** Start probing on `intervalMs`. Idempotent — second call is a no-op. */
574
+ start(): Promise<void>;
575
+ /** Stop probing. Safe to call multiple times. */
576
+ stop(): Promise<void>;
577
+ /** True between start() and stop(). */
578
+ isRunning(): boolean;
579
+ /** Number of consecutive failed probes since the last successful probe. */
580
+ get currentFailureStreak(): number;
581
+ /** True iff the watchdog currently considers the bridge down. */
582
+ isBridgeDown(): boolean;
583
+ private emit;
584
+ private tick;
585
+ private probe;
586
+ private recordSuccess;
587
+ private recordFailure;
588
+ private postDown;
589
+ private postRecovery;
590
+ }
591
+ interface DownAlertInput {
592
+ from: string;
593
+ url: string;
594
+ consecutiveFailures: number;
595
+ }
596
+ declare function buildDownAlert(input: DownAlertInput): MailboxSendInput;
597
+ interface RecoveryAlertInput {
598
+ from: string;
599
+ url: string;
600
+ downtimeMs: number;
601
+ consecutiveFailures: number;
602
+ }
603
+ declare function buildRecoveryAlert(input: RecoveryAlertInput): MailboxSendInput;
604
+ interface WatchdogConfig {
605
+ probeIntervalMs: number;
606
+ probeTimeoutMs: number;
607
+ failureThreshold: number;
608
+ }
609
+ /**
610
+ * Throws if the watchdog config is invalid. Called from the
611
+ * MailboxHealthWatchdog constructor so misconfiguration fails fast
612
+ * (at startup), not silently after the first probe.
683
613
  */
684
- declare function attachDepWatcherBridge(opts: DepWatcherBridgeOptions): () => void;
614
+ declare function validateWatchdogOptions(cfg: WatchdogConfig): void;
685
615
 
686
616
  /**
687
617
  * mailbox-hooks — Tool-execution hooks for mailbox integration.
@@ -893,19 +823,330 @@ interface PackageOutdatedWatcherOptions {
893
823
  /** Called on errors. */
894
824
  onError?: ((err: unknown) => void) | undefined;
895
825
  }
896
- interface OutdatedNotifyMessage {
897
- from: string;
898
- to: string;
899
- subject: string;
900
- body: string;
901
- priority: 'high' | 'normal' | 'low';
826
+ interface OutdatedNotifyMessage {
827
+ from: string;
828
+ to: string;
829
+ subject: string;
830
+ body: string;
831
+ priority: 'high' | 'normal' | 'low';
832
+ }
833
+ /**
834
+ * Start the package outdated watcher.
835
+ *
836
+ * Returns a dispose function that stops polling and cleans up.
837
+ */
838
+ declare function startPackageOutdatedWatcher(opts: PackageOutdatedWatcherOptions): () => void;
839
+
840
+ /**
841
+ * Single-instance mailbox-bridge lock.
842
+ *
843
+ * Per-project isolation: each project (resolved via
844
+ * `resolveProjectDir`) gets its own lock file under
845
+ * `<projectDir>/.mailbox-bridge.lock`. Two projects on the same
846
+ * machine never collide — different slugs, different lock files,
847
+ * and (with default port 0) different OS-assigned ports.
848
+ *
849
+ * The lock holds:
850
+ * - pid process id of the owning `wstack mailbox serve`
851
+ * - host, port what the owner actually bound (port may be OS-assigned)
852
+ * - url convenience copy for callers
853
+ * - token the bearer token (so external agents don't have to
854
+ * re-read it from .mailbox.token separately)
855
+ * - generation monotonically increasing counter; bumped on every
856
+ * acquire. Lets a release() call identify whether the
857
+ * current lock file still belongs to *this* process
858
+ * (e.g. after a stale cleanup raced with us).
859
+ * - spawnedAt ISO timestamp — for observability, not load-bearing.
860
+ *
861
+ * Concurrency model:
862
+ * - `acquireOrJoin` is atomic via rename(2). Two concurrent spawns
863
+ * race to write a tmpfile then rename; one wins, the other reads
864
+ * the winner's lock and joins.
865
+ * - PID liveness is checked via `process.kill(pid, 0)` (POSIX) or
866
+ * `tasklist` (Windows). A live PID means another instance owns
867
+ * this project; a dead PID means the lock is stale and gets cleaned.
868
+ * - `release` is best-effort: a missing lock file at shutdown is
869
+ * fine (someone else already took over). A generation mismatch means
870
+ * we lost the race and another instance owns it now — also fine.
871
+ *
872
+ * Token persistence: the token in the lock always matches the token in
873
+ * `.mailbox.token`, so an external agent that reads either file gets the
874
+ * same value. While an instance stays alive, every joining caller
875
+ * (`kind: 'joined'`) reuses that one token. A cold (re)start — no lock,
876
+ * or a lock whose owner PID is dead/unhealthy — mints a FRESH token and
877
+ * rewrites both files atomically. External agents must therefore re-read
878
+ * `.mailbox.token` after a bridge restart (a stale token returns 401).
879
+ */
880
+ declare const MAILBOX_BRIDGE_LOCK_FILENAME = ".mailbox-bridge.lock";
881
+ declare const MAILBOX_BRIDGE_TOKEN_FILENAME = ".mailbox.token";
882
+ interface MailboxBridgeLock {
883
+ pid: number;
884
+ host: string;
885
+ port: number;
886
+ url: string;
887
+ token: string;
888
+ generation: number;
889
+ spawnedAt: string;
890
+ }
891
+ type AcquireResult = {
892
+ kind: 'acquired';
893
+ lock: MailboxBridgeLock;
894
+ tokenPath: string;
895
+ } | {
896
+ kind: 'joined';
897
+ lock: MailboxBridgeLock;
898
+ tokenPath: string;
899
+ } | {
900
+ kind: 'port-conflict';
901
+ existing: MailboxBridgeLock;
902
+ };
903
+ interface AcquireOptions {
904
+ /** Project dir (already resolved by caller via resolveProjectDir). */
905
+ projectDir: string;
906
+ /** Bind host. Required when acquiring. */
907
+ host: string;
908
+ /** Explicit port. Pass null/undefined to mean "OS-assigned" (read it after listen). */
909
+ requestedPort: number | null;
910
+ /** When true, fail loud on EADDRINUSE. When false, fall back to OS-assigned. */
911
+ strictPort: boolean;
912
+ }
913
+ /**
914
+ * Try to acquire the mailbox-bridge lock for `projectDir`. If another
915
+ * instance is already alive and healthy, join it. Otherwise claim
916
+ * the slot for ourselves.
917
+ *
918
+ * Two-phase contract:
919
+ * 1. Caller invokes `acquireOrJoin(...)` BEFORE calling
920
+ * `server.listen()`. The returned lock either:
921
+ * - `kind: 'joined'` → another instance is alive, the caller
922
+ * should NOT bind; just print the URL/token
923
+ * and exit cleanly (return 0).
924
+ * - `kind: 'acquired'` → caller is the owner, proceeds to bind.
925
+ * - `kind: 'port-conflict'` → caller asked for an explicit port
926
+ * that's already taken by an unrelated
927
+ * process; we return the existing owner
928
+ * but the caller decides what to do
929
+ * (loud-fail).
930
+ * 2. After `server.listen()` resolves with a real port, the caller
931
+ * invokes `finalize(lock, boundPort)` to atomically write the
932
+ * final lock + token file with the OS-assigned port.
933
+ *
934
+ * The two-phase split keeps the listen() call out of the lock module —
935
+ * the caller owns the HTTP server instance; the lock module owns
936
+ * the on-disk contract.
937
+ */
938
+ declare function acquireOrJoin(opts: AcquireOptions): Promise<AcquireResult>;
939
+ /**
940
+ * Phase 2 — after server.listen() resolves, write the final lock
941
+ * with the actually-bound port and the same token. Also writes the
942
+ * .mailbox.token file with mode 0600 so external agents can read it.
943
+ *
944
+ * Returns the finalized lock so the caller can use the resolved URL.
945
+ */
946
+ declare function finalize(projectDir: string, tentative: MailboxBridgeLock, boundPort: number): Promise<MailboxBridgeLock>;
947
+ /**
948
+ * Phase 3 — best-effort cleanup on shutdown. Removes the lock + token
949
+ * files IF this process is still the recorded owner (generation match).
950
+ *
951
+ * If the generation doesn't match, another acquire() has already
952
+ * superseded us — we must NOT delete their lock.
953
+ */
954
+ declare function release(projectDir: string, generation: number): Promise<void>;
955
+ /**
956
+ * Read the lock file and return it, with enough information for the
957
+ * caller to distinguish:
958
+ * - 'live' — PID alive, /healthz reachable; safe to use.
959
+ * - 'probe-failed' — PID alive (or recently was) but /healthz
960
+ * unreachable. Caller can still return the URL
961
+ * + token to the host so its request layer can
962
+ * retry; the host's fetch timeout will surface
963
+ * the real error if the bridge is truly dead.
964
+ * - 'absent' — no lock file existed, or it was malformed
965
+ * (cleaned up best-effort).
966
+ *
967
+ * Distinguishing 'probe-failed' from 'absent' matters for the
968
+ * "joined vs spawned" decision in tryAcquireMailboxBridge — we
969
+ * don't want to spawn a second bridge just because /healthz flaked.
970
+ */
971
+ type LiveLockResult = {
972
+ kind: 'live';
973
+ lock: MailboxBridgeLock;
974
+ }
975
+ /**
976
+ * The lock exists but isn't usable. `pidAlive` tells the caller
977
+ * which recovery to pick:
978
+ * - `pidAlive: false` — the owning process is dead (stale lock).
979
+ * Callers should treat this like `absent` and spawn a fresh
980
+ * bridge rather than surfacing a dead URL.
981
+ * - `pidAlive: true` — the process is alive but /healthz didn't
982
+ * respond (booting/wedged/PID-reuse). Callers may return the
983
+ * recorded URL/token and let a real request confirm liveness.
984
+ */
985
+ | {
986
+ kind: 'probe-failed';
987
+ lock: MailboxBridgeLock;
988
+ pidAlive: boolean;
989
+ } | {
990
+ kind: 'absent';
991
+ };
992
+ declare function readLiveLock(projectDir: string): Promise<LiveLockResult>;
993
+
994
+ /**
995
+ * Adaptive Concurrency Controller
996
+ *
997
+ * Automatically adjusts `maxConcurrent` based on:
998
+ * - Rate limit (429) errors → decrease concurrency
999
+ * - Sustained successful requests → increase concurrency
1000
+ *
1001
+ * This provides automatic backpressure without manual tuning.
1002
+ */
1003
+
1004
+ interface AdaptiveConcurrencyState {
1005
+ current: number;
1006
+ min: number;
1007
+ max: number;
1008
+ consecutiveSuccesses: number;
1009
+ consecutiveFailures: number;
1010
+ totalDecreases: number;
1011
+ totalIncreases: number;
1012
+ enabled: boolean;
1013
+ }
1014
+ /**
1015
+ * Adaptive Concurrency Controller
1016
+ *
1017
+ * Monitors fleet events for rate-limit (429) errors and adjusts concurrency
1018
+ * automatically to prevent overwhelming the API provider.
1019
+ */
1020
+ declare class AdaptiveConcurrencyController {
1021
+ private readonly config;
1022
+ private state;
1023
+ private readonly disposers;
1024
+ private stateChangeHandlers;
1025
+ private readonly logger;
1026
+ constructor(fleetBus: FleetBus, setMaxConcurrent: (n: number) => void, config?: Partial<AdaptiveConcurrencyConfig>, onStateChange?: (state: AdaptiveConcurrencyState) => void, logger?: Pick<Logger, 'warn'>);
1027
+ private setupEventHandlers;
1028
+ /**
1029
+ * Handle a rate limit (429) error - decrease concurrency
1030
+ */
1031
+ private handleRateLimit;
1032
+ /**
1033
+ * Force a decrease (e.g., manual trigger or other error types)
1034
+ */
1035
+ decrease(target?: number): void;
1036
+ /**
1037
+ * Get the current state
1038
+ */
1039
+ getState(): AdaptiveConcurrencyState;
1040
+ /**
1041
+ * Update configuration at runtime
1042
+ */
1043
+ updateConfig(config: Partial<AdaptiveConcurrencyConfig>): void;
1044
+ /**
1045
+ * Dispose of the controller and clean up event listeners
1046
+ */
1047
+ dispose(): void;
1048
+ private notifyStateChange;
1049
+ /**
1050
+ * Register a state change handler
1051
+ */
1052
+ onStateChange(handler: (state: AdaptiveConcurrencyState) => void): () => void;
1053
+ }
1054
+
1055
+ interface AgentTimelineEntry {
1056
+ /** Unique entry id (ULID or timestamp-based). */
1057
+ id: string;
1058
+ /** Subagent id this entry belongs to. */
1059
+ subagentId: string;
1060
+ /** Human-readable agent name/role. */
1061
+ agentName: string;
1062
+ /** ISO 8601 timestamp. */
1063
+ ts: string;
1064
+ /** Content type. */
1065
+ kind: 'text' | 'thinking' | 'tool_use' | 'tool_result' | 'error' | 'status' | 'system';
1066
+ /** The message content (text, tool summary, error message, status text). */
1067
+ content: string;
1068
+ /** Iteration index within the subagent's run. */
1069
+ iteration: number;
1070
+ /** For tool entries: tool name. */
1071
+ toolName?: string | undefined;
1072
+ /** For tool entries: whether the tool succeeded. */
1073
+ toolOk?: boolean | undefined;
1074
+ /** Running cost estimate. */
1075
+ costUsd?: number | undefined;
1076
+ }
1077
+ interface AgentVirtualSession {
1078
+ subagentId: string;
1079
+ agentName: string;
1080
+ createdAt: string;
1081
+ status: string;
1082
+ task?: string | undefined;
1083
+ /** Ordered transcript entries (newest last). */
1084
+ transcript: AgentTimelineEntry[];
1085
+ }
1086
+ interface AgentMonitorOptions {
1087
+ /** Parent/host session id for emitted agent timeline/status events. */
1088
+ sessionId?: string | undefined;
1089
+ /** The FleetBus to listen on for subagent events. Optional — set via `setFleetBus()` before `start()`. */
1090
+ fleetBus?: FleetBus | undefined;
1091
+ /** Local EventBus for emitting agent.timeline.* and agent.status_changed events. */
1092
+ events: EventBus;
1093
+ /** Directory where per-subagent JSONL transcripts will be written. */
1094
+ transcriptsDir: string;
1095
+ /** Maximum in-memory entries per subagent (ring buffer). Default 500. */
1096
+ maxEntriesPerAgent?: number;
1097
+ /** Whether agent stream is initially enabled. Default false. */
1098
+ streamEnabled?: boolean;
1099
+ /** Called for each new timeline entry — used by HQ publisher bridge. */
1100
+ onEntry?: ((entry: AgentTimelineEntry) => void) | undefined;
902
1101
  }
903
- /**
904
- * Start the package outdated watcher.
905
- *
906
- * Returns a dispose function that stops polling and cleans up.
907
- */
908
- declare function startPackageOutdatedWatcher(opts: PackageOutdatedWatcherOptions): () => void;
1102
+ declare class AgentMonitorService {
1103
+ private _fleetBus;
1104
+ private readonly _events;
1105
+ private readonly _sessionId;
1106
+ private readonly _transcriptsDir;
1107
+ private readonly _maxEntries;
1108
+ private _streamEnabled;
1109
+ private _onEntry;
1110
+ /** Per-subagent virtual sessions. */
1111
+ private readonly _sessions;
1112
+ /** Disposers for FleetBus subscriptions, keyed by subagentId. */
1113
+ private readonly _subscriptions;
1114
+ /** Generic fleet-wide subscription disposer. */
1115
+ private _fleetDisposer;
1116
+ /** Track whether service is running. */
1117
+ private _started;
1118
+ constructor(opts: AgentMonitorOptions);
1119
+ /** Set the FleetBus to listen on. Must be called before `start()`. */
1120
+ setFleetBus(bus: FleetBus): void;
1121
+ get streamEnabled(): boolean;
1122
+ /** Enable/disable streaming agent conversations to the main chat timeline. */
1123
+ setStreamEnabled(enabled: boolean): void;
1124
+ /** Get a snapshot of all known agent sessions. */
1125
+ getAllSessions(): AgentVirtualSession[];
1126
+ /** Get a specific agent's virtual session, or undefined. */
1127
+ getSession(subagentId: string): AgentVirtualSession | undefined;
1128
+ /** Get transcript entries for a specific agent, newest first. */
1129
+ getTranscript(subagentId: string, limit?: number): AgentTimelineEntry[];
1130
+ /** Set a callback for each new timeline entry (HQ bridge). */
1131
+ setOnEntry(handler: ((entry: AgentTimelineEntry) => void) | undefined): void;
1132
+ /** Start listening to FleetBus events. */
1133
+ start(): void;
1134
+ /** Stop listening and clean up all subscriptions. */
1135
+ stop(): void;
1136
+ /** Ensure a subagent is being tracked. Called when a subagent spawns. */
1137
+ trackSubagent(subagentId: string, agentName: string, task?: string): void;
1138
+ /** Mark a subagent as completed/failed/etc. Called on subagent finish. */
1139
+ completeSubagent(subagentId: string, status: 'completed' | 'failed' | 'timeout' | 'stopped' | 'budget_exhausted', summary?: string): void;
1140
+ private _routeEvent;
1141
+ private _addEntry;
1142
+ private _appendToFile;
1143
+ private _uid;
1144
+ private _formatToolUse;
1145
+ private _formatToolResult;
1146
+ private _stringifyForTimeline;
1147
+ private _capTimelineText;
1148
+ }
1149
+ declare function createAgentMonitorService(opts: AgentMonitorOptions): AgentMonitorService;
909
1150
 
910
1151
  type NodeType = 'fact' | 'goal' | 'decision' | 'change' | 'vote';
911
1152
  type FactCategory = 'bug' | 'refactor' | 'security' | 'test' | 'perf' | 'deps' | 'architecture' | 'quality';
@@ -1035,93 +1276,242 @@ interface NodeFilter {
1035
1276
  /** Only nodes added after this timestamp */
1036
1277
  since?: string;
1037
1278
  }
1038
- declare class KnowledgeGraph {
1039
- private readonly nodes;
1040
- private readonly index;
1041
- private readonly subs;
1042
- private readonly pendingDeliveries;
1043
- private readonly filePath;
1044
- private readonly graphFilePath;
1279
+ declare class KnowledgeGraph {
1280
+ private readonly nodes;
1281
+ private readonly index;
1282
+ private readonly subs;
1283
+ private readonly pendingDeliveries;
1284
+ private readonly filePath;
1285
+ private readonly graphFilePath;
1286
+ /**
1287
+ * Stable per-node insertion sequence. `nodes` (a Map) preserves insertion
1288
+ * order even across `update()` (Map.set on an existing key keeps its slot),
1289
+ * but the type index's `Set<string>` does NOT — `update()` removes then
1290
+ * re-adds a node's id, moving it to the set's tail. Index-routed queries sort
1291
+ * by this sequence so they return nodes in creation order, matching the old
1292
+ * `nodes.values()` scan that callers like decision-history `slice(-10)` rely on.
1293
+ */
1294
+ private readonly seq;
1295
+ private seqCounter;
1296
+ /** Assign a stable insertion sequence the first time a node id is seen. */
1297
+ private _trackSeq;
1298
+ /** Exposed for unit-testing only: read current index contents. */
1299
+ getIndex(): ReadonlyMap<string, ReadonlySet<string>>;
1300
+ constructor(sessionDir: string);
1301
+ /**
1302
+ * Add a node. Fires to all matching subscriptions synchronously.
1303
+ * Returns the node with its assigned id.
1304
+ */
1305
+ add(node: Omit<GraphNode, 'id'>): Promise<GraphNode>;
1306
+ /** Update an existing node by id. Returns updated node or null if not found. */
1307
+ update(id: string, patch: Partial<GraphNode>): Promise<GraphNode | null>;
1308
+ get(id: string): GraphNode | undefined;
1309
+ getAll(filter?: NodeFilter): GraphNode[];
1310
+ getGoals(filter?: Partial<{
1311
+ status: GoalStatus;
1312
+ assignee: string;
1313
+ priority: GoalPriority;
1314
+ }>): GoalNode[];
1315
+ getFacts(filter?: Partial<{
1316
+ category: FactCategory;
1317
+ severity: string;
1318
+ }>): FactNode[];
1319
+ getChanges(filter?: Partial<{
1320
+ status: ChangeStatus;
1321
+ }>): ChangeNode[];
1322
+ getOpenGoals(): GoalNode[];
1323
+ getTopLevelGoals(): GoalNode[];
1324
+ getBlockedGoals(): GoalNode[];
1325
+ getPendingChanges(): ChangeNode[];
1326
+ getDecisions(since?: string): DecisionNode[];
1327
+ searchFacts(query: string): FactNode[];
1328
+ getRelatedFacts(factId: string): FactNode[];
1329
+ /**
1330
+ * Subscribe to nodes matching a filter. Returns a channel id that can be
1331
+ * used to poll for new nodes since the last check.
1332
+ */
1333
+ subscribe(agentId: string, filter: NodeFilter): string;
1334
+ /**
1335
+ * Poll for new nodes delivered to a channel since last check.
1336
+ * Clears the delivery buffer after reading.
1337
+ */
1338
+ poll(channel: string): GraphNode[];
1339
+ unsubscribe(channel: string): void;
1340
+ /**
1341
+ * Create a quality gate result. Call this when a change is being proposed
1342
+ * so the change node carries the gate result.
1343
+ */
1344
+ static makeQualityGate(checks: {
1345
+ name: string;
1346
+ passed: boolean;
1347
+ detail?: string;
1348
+ }[]): QualityGateResult;
1349
+ /** Pure: compute the set of index keys a node would belong to. */
1350
+ private _indexKeys;
1351
+ /** Mutate the index: add a node's id to every set for the given keys. */
1352
+ private _addToIndex;
1353
+ /** Remove a node's id from all index sets for the given keys. */
1354
+ private _removeFromIndex;
1355
+ private _matches;
1356
+ private _deliver;
1357
+ private _persist;
1358
+ private _append;
1359
+ /** Rebuild in-memory state from the log file. Call on startup. */
1360
+ load(): Promise<void>;
1361
+ /** Snapshot for serialization. */
1362
+ snapshot(): {
1363
+ nodes: GraphNode[];
1364
+ subs: number;
1365
+ };
1366
+ }
1367
+
1368
+ type AutonomousDecisionType = 'spawn' | 'approve_change' | 'reject_change' | 'prioritize_goals' | 'escalate_task' | 'rollback_change' | 'retry_task' | 'merge_results' | 'decompose_goal' | 'assign_task';
1369
+ interface AutonomousDecisionRequest {
1370
+ id: string;
1371
+ source: BrainDecisionSource;
1372
+ decisionType: AutonomousDecisionType;
1373
+ question: string;
1374
+ context: {
1375
+ /** Relevant facts from the knowledge graph */
1376
+ facts?: FactNode[];
1377
+ /** Goals relevant to this decision */
1378
+ goals?: GoalNode[];
1379
+ /** Change being reviewed (for approval decisions) */
1380
+ change?: ChangeNode;
1381
+ /** Current fleet status */
1382
+ fleetStatus?: {
1383
+ running: number;
1384
+ idle: number;
1385
+ total: number;
1386
+ costSoFar: number;
1387
+ };
1388
+ /** Task that triggered this decision */
1389
+ taskDescription?: string;
1390
+ /** Error that triggered escalation, if any */
1391
+ error?: string;
1392
+ /** Number of times this task has been attempted */
1393
+ attempts?: number;
1394
+ };
1395
+ options: BrainDecisionOption[];
1396
+ risk: BrainRisk;
1397
+ /** Whether this decision requires consensus */
1398
+ requiresConsensus: boolean;
1399
+ }
1400
+ interface SpawnDecision {
1401
+ role: string;
1402
+ budget: {
1403
+ timeoutMs?: number;
1404
+ maxIterations?: number;
1405
+ maxToolCalls?: number;
1406
+ maxCostUsd?: number;
1407
+ };
1408
+ rationale: string;
1409
+ }
1410
+ interface ApprovalDecision {
1411
+ approved: boolean;
1412
+ rationale: string;
1413
+ waivers?: string[];
1414
+ conditions?: string[];
1415
+ }
1416
+ interface PrioritizationDecision {
1417
+ orderedGoals: string[];
1418
+ rationale: string;
1419
+ }
1420
+ interface EscalationDecision {
1421
+ action: 'retry' | 'delegate' | 'mark_failed' | 'ask_for_help';
1422
+ rationale: string;
1423
+ budgetAdjustment?: {
1424
+ increaseFactor?: number;
1425
+ newTimeoutMs?: number;
1426
+ addModel?: string;
1427
+ };
1428
+ }
1429
+ interface AutonomousBrainOptions {
1430
+ /** The LLM provider for making decisions */
1431
+ llmProvider: LLMProvider;
1432
+ graph: KnowledgeGraph;
1433
+ fleet?: FleetBus | undefined;
1434
+ /** Maximum retries before a task is marked failed. Default: 3. */
1435
+ maxRetries?: number | undefined;
1436
+ /** Risk threshold above which consensus is required. Default: 'high'. */
1437
+ consensusRiskThreshold?: BrainRisk | undefined;
1438
+ /** Self-improve: track decision history for learning. Default: true. */
1439
+ selfImprove?: boolean | undefined;
1440
+ }
1441
+ interface LLMProvider {
1442
+ /**
1443
+ * Generate a decision. Receives the full context as a structured prompt.
1444
+ * Returns the chosen option id and rationale.
1445
+ */
1446
+ decide(prompt: DecisionPrompt): Promise<{
1447
+ optionId: string;
1448
+ rationale: string;
1449
+ }>;
1450
+ }
1451
+ interface DecisionPrompt {
1452
+ decisionType: AutonomousDecisionType;
1453
+ question: string;
1454
+ context: string;
1455
+ options: BrainDecisionOption[];
1456
+ risk: BrainRisk;
1457
+ decisionHistory: DecisionNode[];
1458
+ /** Hints derived from self-improvement data */
1459
+ selfImproveHints?: string[];
1460
+ }
1461
+ declare class AutonomousBrain implements BrainArbiter {
1462
+ private readonly graph;
1463
+ private readonly fleetBus?;
1464
+ private readonly llmProvider;
1465
+ private readonly maxRetries;
1466
+ private readonly consensusRiskThreshold;
1467
+ private readonly selfImprove;
1468
+ /** Decision history for self-improvement and audit. */
1469
+ private decisionHistory;
1470
+ /** Tracks failure patterns for self-improvement. */
1471
+ private failurePatterns;
1472
+ private readonly RISK_ORDER;
1473
+ private _emit;
1474
+ constructor(opts: AutonomousBrainOptions);
1475
+ /** Implements BrainArbiter — bridges standard brain.ts interface to autonomous engine. */
1476
+ decide(request: BrainDecisionRequest): Promise<BrainDecision>;
1045
1477
  /**
1046
- * Stable per-node insertion sequence. `nodes` (a Map) preserves insertion
1047
- * order even across `update()` (Map.set on an existing key keeps its slot),
1048
- * but the type index's `Set<string>` does NOT — `update()` removes then
1049
- * re-adds a node's id, moving it to the set's tail. Index-routed queries sort
1050
- * by this sequence so they return nodes in creation order, matching the old
1051
- * `nodes.values()` scan that callers like decision-history `slice(-10)` rely on.
1478
+ * Primary autonomous decision engine receives AutonomousDecisionRequest,
1479
+ * queries the LLM, records the decision, and returns a BrainDecision.
1480
+ *
1481
+ * Specialized methods (decideSpawn, decideApproval, etc.) should call this
1482
+ * directly with a pre-built AutonomousDecisionRequest.
1052
1483
  */
1053
- private readonly seq;
1054
- private seqCounter;
1055
- /** Assign a stable insertion sequence the first time a node id is seen. */
1056
- private _trackSeq;
1057
- /** Exposed for unit-testing only: read current index contents. */
1058
- getIndex(): ReadonlyMap<string, ReadonlySet<string>>;
1059
- constructor(sessionDir: string);
1484
+ decideAuto(request: AutonomousDecisionRequest): Promise<BrainDecision>;
1060
1485
  /**
1061
- * Add a node. Fires to all matching subscriptions synchronously.
1062
- * Returns the node with its assigned id.
1486
+ * Decide whether to spawn a subagent, which role to use, and what budget.
1063
1487
  */
1064
- add(node: Omit<GraphNode, 'id'>): Promise<GraphNode>;
1065
- /** Update an existing node by id. Returns updated node or null if not found. */
1066
- update(id: string, patch: Partial<GraphNode>): Promise<GraphNode | null>;
1067
- get(id: string): GraphNode | undefined;
1068
- getAll(filter?: NodeFilter): GraphNode[];
1069
- getGoals(filter?: Partial<{
1070
- status: GoalStatus;
1071
- assignee: string;
1072
- priority: GoalPriority;
1073
- }>): GoalNode[];
1074
- getFacts(filter?: Partial<{
1075
- category: FactCategory;
1076
- severity: string;
1077
- }>): FactNode[];
1078
- getChanges(filter?: Partial<{
1079
- status: ChangeStatus;
1080
- }>): ChangeNode[];
1081
- getOpenGoals(): GoalNode[];
1082
- getTopLevelGoals(): GoalNode[];
1083
- getBlockedGoals(): GoalNode[];
1084
- getPendingChanges(): ChangeNode[];
1085
- getDecisions(since?: string): DecisionNode[];
1086
- searchFacts(query: string): FactNode[];
1087
- getRelatedFacts(factId: string): FactNode[];
1488
+ decideSpawn(source: BrainDecisionSource, taskDescription: string, availableFacts: FactNode[], fleetStatus: {
1489
+ running: number;
1490
+ idle: number;
1491
+ total: number;
1492
+ costSoFar: number;
1493
+ }): Promise<BrainDecision>;
1088
1494
  /**
1089
- * Subscribe to nodes matching a filter. Returns a channel id that can be
1090
- * used to poll for new nodes since the last check.
1495
+ * Decide whether to approve a proposed change.
1091
1496
  */
1092
- subscribe(agentId: string, filter: NodeFilter): string;
1497
+ decideApproval(source: BrainDecisionSource, change: ChangeNode, relevantFacts: FactNode[]): Promise<BrainDecision>;
1093
1498
  /**
1094
- * Poll for new nodes delivered to a channel since last check.
1095
- * Clears the delivery buffer after reading.
1499
+ * Decide how to handle a failed task.
1096
1500
  */
1097
- poll(channel: string): GraphNode[];
1098
- unsubscribe(channel: string): void;
1501
+ decideEscalation(source: BrainDecisionSource, taskId: string, error: string, attempts: number): Promise<BrainDecision>;
1099
1502
  /**
1100
- * Create a quality gate result. Call this when a change is being proposed
1101
- * so the change node carries the gate result.
1503
+ * Record the outcome of a decision for self-improvement.
1504
+ * Call this after a spawned agent completes or a change is applied.
1102
1505
  */
1103
- static makeQualityGate(checks: {
1104
- name: string;
1105
- passed: boolean;
1106
- detail?: string;
1107
- }[]): QualityGateResult;
1108
- /** Pure: compute the set of index keys a node would belong to. */
1109
- private _indexKeys;
1110
- /** Mutate the index: add a node's id to every set for the given keys. */
1111
- private _addToIndex;
1112
- /** Remove a node's id from all index sets for the given keys. */
1113
- private _removeFromIndex;
1114
- private _matches;
1115
- private _deliver;
1116
- private _persist;
1117
- private _append;
1118
- /** Rebuild in-memory state from the log file. Call on startup. */
1119
- load(): Promise<void>;
1120
- /** Snapshot for serialization. */
1121
- snapshot(): {
1122
- nodes: GraphNode[];
1123
- subs: number;
1124
- };
1506
+ recordOutcome(decisionId: string, outcome: 'success' | 'failure', _detail?: string): void;
1507
+ private _getSelfImproveHints;
1508
+ private _toAutonomous;
1509
+ private _inferDecisionType;
1510
+ private _serializeContext;
1511
+ private _loadHistory;
1512
+ private _recordDecision;
1513
+ private _inferRoles;
1514
+ private _changeRisk;
1125
1515
  }
1126
1516
 
1127
1517
  /**
@@ -1271,6 +1661,144 @@ declare class TaskDAG {
1271
1661
  private _wouldCycle;
1272
1662
  }
1273
1663
 
1664
+ interface TaskBid {
1665
+ id: string;
1666
+ taskId: string;
1667
+ agentId: string;
1668
+ agentName: string;
1669
+ agentRole: string;
1670
+ /** Dispatcher score for this task */
1671
+ score: number;
1672
+ /** Why this agent is a good fit */
1673
+ rationale: string;
1674
+ submittedAt: string;
1675
+ }
1676
+ interface TaskAuctionOptions {
1677
+ graph: KnowledgeGraph;
1678
+ fleet?: FleetBus | undefined;
1679
+ mailbox?: Mailbox | undefined;
1680
+ selfAgentId?: string | undefined;
1681
+ /** How long a bid window stays open before auto-awarding. Default: 30s */
1682
+ bidWindowMs?: number | undefined;
1683
+ /** Maximum concurrent tasks per agent. Default: 3 */
1684
+ maxTasksPerAgent?: number | undefined;
1685
+ /** Minimum confidence threshold for dispatcher scoring. Default: 0.3 */
1686
+ minConfidence?: number | undefined;
1687
+ /**
1688
+ * Maximum times a task can be republished when no bids are received.
1689
+ * After this, the task is marked as 'failed' with reason 'no_bids'.
1690
+ * Default: 3.
1691
+ */
1692
+ maxBidRetries?: number | undefined;
1693
+ }
1694
+ declare class TaskAuctioneer {
1695
+ private readonly graph;
1696
+ private readonly fleet?;
1697
+ private readonly mailbox?;
1698
+ private readonly selfAgentId;
1699
+ private readonly bidWindowMs;
1700
+ private readonly maxTasksPerAgent;
1701
+ private readonly minConfidence;
1702
+ private readonly maxBidRetries;
1703
+ /** Pending bids keyed by taskId. */
1704
+ private readonly pendingBids;
1705
+ /** Active bid windows keyed by taskId. */
1706
+ private readonly bidTimers;
1707
+ /** FleetBus subscription disposers, detached in dispose(). */
1708
+ private readonly unsubs;
1709
+ /** How many times a task has been republished with no bids received. */
1710
+ private readonly bidRetryCounts;
1711
+ /** Agent → current task count (from graph + in-flight). */
1712
+ private readonly agentTaskCounts;
1713
+ constructor(opts: TaskAuctionOptions);
1714
+ /**
1715
+ * Detach all FleetBus subscriptions and cancel any open bid-window timers.
1716
+ * Call when the owning coordinator stops/restarts so handlers and timers
1717
+ * don't accumulate across cycles.
1718
+ */
1719
+ dispose(): void;
1720
+ /**
1721
+ * Publish a new task to the auction. Creates a GoalNode and broadcasts
1722
+ * it to all online agents. Returns the goal id.
1723
+ *
1724
+ * If `targetAgent` is specified, the task is assigned directly without auction.
1725
+ */
1726
+ publishTask(input: {
1727
+ title: string;
1728
+ description: string;
1729
+ priority?: GoalPriority;
1730
+ tags?: string[];
1731
+ targetAgent?: string;
1732
+ parentGoal?: string;
1733
+ satisfiesGoals?: string[];
1734
+ /** Goal ids that must reach 'done' before this goal becomes workable. */
1735
+ blockedBy?: string[];
1736
+ deadline?: string;
1737
+ reward?: string;
1738
+ }): Promise<string>;
1739
+ /**
1740
+ * Submit a bid for a task. Called by agents who want to work on it.
1741
+ * Returns true if the bid was accepted, false if the task was already claimed.
1742
+ */
1743
+ bid(taskId: string, agent: {
1744
+ agentId: string;
1745
+ agentName: string;
1746
+ agentRole: string;
1747
+ }, rationale: string): Promise<boolean>;
1748
+ /**
1749
+ * Award a task to a specific agent. Called internally by the bid window
1750
+ * expiry, or can be called directly to force an award.
1751
+ */
1752
+ claim(taskId: string, agentId: string, agentName: string): Promise<boolean>;
1753
+ /**
1754
+ * Mark a task as done. Called by the agent when it finishes.
1755
+ */
1756
+ complete(taskId: string, _result?: string): Promise<void>;
1757
+ /**
1758
+ * Mark a task as failed. Optionally spawn a retry.
1759
+ */
1760
+ fail(taskId: string, error: string): Promise<void>;
1761
+ /**
1762
+ * Find the best available tasks for an agent based on its capabilities.
1763
+ * Returns tasks sorted by match score (best first).
1764
+ */
1765
+ findWork(_agentId: string, agentRole: string, limit?: number): Promise<{
1766
+ task: GoalNode;
1767
+ score: number;
1768
+ bids: number;
1769
+ }[]>;
1770
+ /** Get all pending tasks (available for bidding). */
1771
+ getPendingTasks(): GoalNode[];
1772
+ /** Get tasks assigned to a specific agent. */
1773
+ getTasksForAgent(agentId: string): GoalNode[];
1774
+ /** Get the current bid count for a task. */
1775
+ getBidCount(taskId: string): number;
1776
+ /** Get bids for a task. */
1777
+ getBids(taskId: string): TaskBid[];
1778
+ /** Get task stats for a project-wide dashboard. */
1779
+ getStats(): {
1780
+ total: number;
1781
+ pending: number;
1782
+ in_progress: number;
1783
+ done: number;
1784
+ failed: number;
1785
+ totalBids: number;
1786
+ avgBidsPerTask: number;
1787
+ };
1788
+ private _emit;
1789
+ private _broadcastTask;
1790
+ private _mailboxPublish;
1791
+ private _notifyAgent;
1792
+ private _startBidWindow;
1793
+ private _cancelBidWindow;
1794
+ private _evaluateBids;
1795
+ private _assignDirect;
1796
+ private _onBidEvent;
1797
+ private _onClaimedEvent;
1798
+ private _getAgentTaskCount;
1799
+ private agentTaskCount;
1800
+ }
1801
+
1274
1802
  /**
1275
1803
  * ConsensusProtocol — agent voting on proposed changes.
1276
1804
  *
@@ -1471,343 +1999,56 @@ declare class ChangeManager {
1471
1999
  private readonly checks;
1472
2000
  /** Track applied changes for rollback lookup. */
1473
2001
  private readonly appliedChanges;
1474
- constructor(opts: ChangeManagerOptions);
1475
- /**
1476
- * Propose a new code change. Creates a ChangeNode in the knowledge graph.
1477
- * Does NOT automatically initiate voting — call `submitForReview()` for that.
1478
- */
1479
- propose(input: ChangeProposal): Promise<ChangeNode>;
1480
- /**
1481
- * Submit an approved change for application.
1482
- * Returns the change node — actual file mutations are performed by agents
1483
- * acting on this node's data from the knowledge graph.
1484
- */
1485
- submitForReview(changeId: string): Promise<void>;
1486
- /**
1487
- * Apply an approved change. Updates the change node to 'applied'.
1488
- * Agents should watch for 'applied' status and perform the actual file mutations.
1489
- */
1490
- markApplied(changeId: string, appliedAt: string): Promise<ChangeNode | null>;
1491
- /**
1492
- * Mark a change as applied and trigger rollback for any satisfied goal
1493
- * that turns out to be broken.
1494
- */
1495
- markAppliedWithVerification(changeId: string, verify: () => Promise<QualityGateResult>): Promise<ApplyResult>;
1496
- /**
1497
- * Propose a rollback for an applied change. Creates a new change that
1498
- * reverses the original. Goes through full consensus.
1499
- */
1500
- proposeRollback(appliedChangeId: string, reason: string): Promise<ChangeNode | null>;
1501
- /**
1502
- * Mark a change as rolled back.
1503
- */
1504
- markRolledBack(changeId: string, rolledBackAt: string): Promise<ChangeNode | null>;
1505
- getPendingReviews(): ChangeNode[];
1506
- getAppliedChanges(): ChangeNode[];
1507
- getChange(id: string): ChangeNode | undefined;
1508
- getChangesForGoal(goalId: string): ChangeNode[];
1509
- /**
1510
- * Run quality gate checks. This is informational — actual test/lint/typecheck
1511
- * execution is done by agents spawned for this purpose. This method stores
1512
- * the result in the change node.
1513
- */
1514
- private _runQualityGate;
1515
- /**
1516
- * Update quality gate result for a change. Called by verify agents
1517
- * after running their checks.
1518
- */
1519
- updateQualityGate(changeId: string, checkName: string, result: {
1520
- passed: boolean;
1521
- detail?: string;
1522
- }): Promise<void>;
1523
- private _emit;
1524
- }
1525
-
1526
- type AutonomousDecisionType = 'spawn' | 'approve_change' | 'reject_change' | 'prioritize_goals' | 'escalate_task' | 'rollback_change' | 'retry_task' | 'merge_results' | 'decompose_goal' | 'assign_task';
1527
- interface AutonomousDecisionRequest {
1528
- id: string;
1529
- source: BrainDecisionSource;
1530
- decisionType: AutonomousDecisionType;
1531
- question: string;
1532
- context: {
1533
- /** Relevant facts from the knowledge graph */
1534
- facts?: FactNode[];
1535
- /** Goals relevant to this decision */
1536
- goals?: GoalNode[];
1537
- /** Change being reviewed (for approval decisions) */
1538
- change?: ChangeNode;
1539
- /** Current fleet status */
1540
- fleetStatus?: {
1541
- running: number;
1542
- idle: number;
1543
- total: number;
1544
- costSoFar: number;
1545
- };
1546
- /** Task that triggered this decision */
1547
- taskDescription?: string;
1548
- /** Error that triggered escalation, if any */
1549
- error?: string;
1550
- /** Number of times this task has been attempted */
1551
- attempts?: number;
1552
- };
1553
- options: BrainDecisionOption[];
1554
- risk: BrainRisk;
1555
- /** Whether this decision requires consensus */
1556
- requiresConsensus: boolean;
1557
- }
1558
- interface SpawnDecision {
1559
- role: string;
1560
- budget: {
1561
- timeoutMs?: number;
1562
- maxIterations?: number;
1563
- maxToolCalls?: number;
1564
- maxCostUsd?: number;
1565
- };
1566
- rationale: string;
1567
- }
1568
- interface ApprovalDecision {
1569
- approved: boolean;
1570
- rationale: string;
1571
- waivers?: string[];
1572
- conditions?: string[];
1573
- }
1574
- interface PrioritizationDecision {
1575
- orderedGoals: string[];
1576
- rationale: string;
1577
- }
1578
- interface EscalationDecision {
1579
- action: 'retry' | 'delegate' | 'mark_failed' | 'ask_for_help';
1580
- rationale: string;
1581
- budgetAdjustment?: {
1582
- increaseFactor?: number;
1583
- newTimeoutMs?: number;
1584
- addModel?: string;
1585
- };
1586
- }
1587
- interface AutonomousBrainOptions {
1588
- /** The LLM provider for making decisions */
1589
- llmProvider: LLMProvider;
1590
- graph: KnowledgeGraph;
1591
- fleet?: FleetBus | undefined;
1592
- /** Maximum retries before a task is marked failed. Default: 3. */
1593
- maxRetries?: number | undefined;
1594
- /** Risk threshold above which consensus is required. Default: 'high'. */
1595
- consensusRiskThreshold?: BrainRisk | undefined;
1596
- /** Self-improve: track decision history for learning. Default: true. */
1597
- selfImprove?: boolean | undefined;
1598
- }
1599
- interface LLMProvider {
1600
- /**
1601
- * Generate a decision. Receives the full context as a structured prompt.
1602
- * Returns the chosen option id and rationale.
1603
- */
1604
- decide(prompt: DecisionPrompt): Promise<{
1605
- optionId: string;
1606
- rationale: string;
1607
- }>;
1608
- }
1609
- interface DecisionPrompt {
1610
- decisionType: AutonomousDecisionType;
1611
- question: string;
1612
- context: string;
1613
- options: BrainDecisionOption[];
1614
- risk: BrainRisk;
1615
- decisionHistory: DecisionNode[];
1616
- /** Hints derived from self-improvement data */
1617
- selfImproveHints?: string[];
1618
- }
1619
- declare class AutonomousBrain implements BrainArbiter {
1620
- private readonly graph;
1621
- private readonly fleetBus?;
1622
- private readonly llmProvider;
1623
- private readonly maxRetries;
1624
- private readonly consensusRiskThreshold;
1625
- private readonly selfImprove;
1626
- /** Decision history for self-improvement and audit. */
1627
- private decisionHistory;
1628
- /** Tracks failure patterns for self-improvement. */
1629
- private failurePatterns;
1630
- private readonly RISK_ORDER;
1631
- private _emit;
1632
- constructor(opts: AutonomousBrainOptions);
1633
- /** Implements BrainArbiter — bridges standard brain.ts interface to autonomous engine. */
1634
- decide(request: BrainDecisionRequest): Promise<BrainDecision>;
1635
- /**
1636
- * Primary autonomous decision engine — receives AutonomousDecisionRequest,
1637
- * queries the LLM, records the decision, and returns a BrainDecision.
1638
- *
1639
- * Specialized methods (decideSpawn, decideApproval, etc.) should call this
1640
- * directly with a pre-built AutonomousDecisionRequest.
1641
- */
1642
- decideAuto(request: AutonomousDecisionRequest): Promise<BrainDecision>;
1643
- /**
1644
- * Decide whether to spawn a subagent, which role to use, and what budget.
1645
- */
1646
- decideSpawn(source: BrainDecisionSource, taskDescription: string, availableFacts: FactNode[], fleetStatus: {
1647
- running: number;
1648
- idle: number;
1649
- total: number;
1650
- costSoFar: number;
1651
- }): Promise<BrainDecision>;
1652
- /**
1653
- * Decide whether to approve a proposed change.
1654
- */
1655
- decideApproval(source: BrainDecisionSource, change: ChangeNode, relevantFacts: FactNode[]): Promise<BrainDecision>;
1656
- /**
1657
- * Decide how to handle a failed task.
1658
- */
1659
- decideEscalation(source: BrainDecisionSource, taskId: string, error: string, attempts: number): Promise<BrainDecision>;
1660
- /**
1661
- * Record the outcome of a decision for self-improvement.
1662
- * Call this after a spawned agent completes or a change is applied.
1663
- */
1664
- recordOutcome(decisionId: string, outcome: 'success' | 'failure', _detail?: string): void;
1665
- private _getSelfImproveHints;
1666
- private _toAutonomous;
1667
- private _inferDecisionType;
1668
- private _serializeContext;
1669
- private _loadHistory;
1670
- private _recordDecision;
1671
- private _inferRoles;
1672
- private _changeRisk;
1673
- }
1674
-
1675
- interface TaskBid {
1676
- id: string;
1677
- taskId: string;
1678
- agentId: string;
1679
- agentName: string;
1680
- agentRole: string;
1681
- /** Dispatcher score for this task */
1682
- score: number;
1683
- /** Why this agent is a good fit */
1684
- rationale: string;
1685
- submittedAt: string;
1686
- }
1687
- interface TaskAuctionOptions {
1688
- graph: KnowledgeGraph;
1689
- fleet?: FleetBus | undefined;
1690
- mailbox?: Mailbox | undefined;
1691
- selfAgentId?: string | undefined;
1692
- /** How long a bid window stays open before auto-awarding. Default: 30s */
1693
- bidWindowMs?: number | undefined;
1694
- /** Maximum concurrent tasks per agent. Default: 3 */
1695
- maxTasksPerAgent?: number | undefined;
1696
- /** Minimum confidence threshold for dispatcher scoring. Default: 0.3 */
1697
- minConfidence?: number | undefined;
1698
- /**
1699
- * Maximum times a task can be republished when no bids are received.
1700
- * After this, the task is marked as 'failed' with reason 'no_bids'.
1701
- * Default: 3.
1702
- */
1703
- maxBidRetries?: number | undefined;
1704
- }
1705
- declare class TaskAuctioneer {
1706
- private readonly graph;
1707
- private readonly fleet?;
1708
- private readonly mailbox?;
1709
- private readonly selfAgentId;
1710
- private readonly bidWindowMs;
1711
- private readonly maxTasksPerAgent;
1712
- private readonly minConfidence;
1713
- private readonly maxBidRetries;
1714
- /** Pending bids keyed by taskId. */
1715
- private readonly pendingBids;
1716
- /** Active bid windows keyed by taskId. */
1717
- private readonly bidTimers;
1718
- /** FleetBus subscription disposers, detached in dispose(). */
1719
- private readonly unsubs;
1720
- /** How many times a task has been republished with no bids received. */
1721
- private readonly bidRetryCounts;
1722
- /** Agent → current task count (from graph + in-flight). */
1723
- private readonly agentTaskCounts;
1724
- constructor(opts: TaskAuctionOptions);
2002
+ constructor(opts: ChangeManagerOptions);
1725
2003
  /**
1726
- * Detach all FleetBus subscriptions and cancel any open bid-window timers.
1727
- * Call when the owning coordinator stops/restarts so handlers and timers
1728
- * don't accumulate across cycles.
2004
+ * Propose a new code change. Creates a ChangeNode in the knowledge graph.
2005
+ * Does NOT automatically initiate voting call `submitForReview()` for that.
1729
2006
  */
1730
- dispose(): void;
2007
+ propose(input: ChangeProposal): Promise<ChangeNode>;
1731
2008
  /**
1732
- * Publish a new task to the auction. Creates a GoalNode and broadcasts
1733
- * it to all online agents. Returns the goal id.
1734
- *
1735
- * If `targetAgent` is specified, the task is assigned directly without auction.
2009
+ * Submit an approved change for application.
2010
+ * Returns the change node actual file mutations are performed by agents
2011
+ * acting on this node's data from the knowledge graph.
1736
2012
  */
1737
- publishTask(input: {
1738
- title: string;
1739
- description: string;
1740
- priority?: GoalPriority;
1741
- tags?: string[];
1742
- targetAgent?: string;
1743
- parentGoal?: string;
1744
- satisfiesGoals?: string[];
1745
- /** Goal ids that must reach 'done' before this goal becomes workable. */
1746
- blockedBy?: string[];
1747
- deadline?: string;
1748
- reward?: string;
1749
- }): Promise<string>;
2013
+ submitForReview(changeId: string): Promise<void>;
1750
2014
  /**
1751
- * Submit a bid for a task. Called by agents who want to work on it.
1752
- * Returns true if the bid was accepted, false if the task was already claimed.
2015
+ * Apply an approved change. Updates the change node to 'applied'.
2016
+ * Agents should watch for 'applied' status and perform the actual file mutations.
1753
2017
  */
1754
- bid(taskId: string, agent: {
1755
- agentId: string;
1756
- agentName: string;
1757
- agentRole: string;
1758
- }, rationale: string): Promise<boolean>;
2018
+ markApplied(changeId: string, appliedAt: string): Promise<ChangeNode | null>;
1759
2019
  /**
1760
- * Award a task to a specific agent. Called internally by the bid window
1761
- * expiry, or can be called directly to force an award.
2020
+ * Mark a change as applied and trigger rollback for any satisfied goal
2021
+ * that turns out to be broken.
1762
2022
  */
1763
- claim(taskId: string, agentId: string, agentName: string): Promise<boolean>;
2023
+ markAppliedWithVerification(changeId: string, verify: () => Promise<QualityGateResult>): Promise<ApplyResult>;
1764
2024
  /**
1765
- * Mark a task as done. Called by the agent when it finishes.
2025
+ * Propose a rollback for an applied change. Creates a new change that
2026
+ * reverses the original. Goes through full consensus.
1766
2027
  */
1767
- complete(taskId: string, _result?: string): Promise<void>;
2028
+ proposeRollback(appliedChangeId: string, reason: string): Promise<ChangeNode | null>;
1768
2029
  /**
1769
- * Mark a task as failed. Optionally spawn a retry.
2030
+ * Mark a change as rolled back.
1770
2031
  */
1771
- fail(taskId: string, error: string): Promise<void>;
2032
+ markRolledBack(changeId: string, rolledBackAt: string): Promise<ChangeNode | null>;
2033
+ getPendingReviews(): ChangeNode[];
2034
+ getAppliedChanges(): ChangeNode[];
2035
+ getChange(id: string): ChangeNode | undefined;
2036
+ getChangesForGoal(goalId: string): ChangeNode[];
1772
2037
  /**
1773
- * Find the best available tasks for an agent based on its capabilities.
1774
- * Returns tasks sorted by match score (best first).
2038
+ * Run quality gate checks. This is informational actual test/lint/typecheck
2039
+ * execution is done by agents spawned for this purpose. This method stores
2040
+ * the result in the change node.
1775
2041
  */
1776
- findWork(_agentId: string, agentRole: string, limit?: number): Promise<{
1777
- task: GoalNode;
1778
- score: number;
1779
- bids: number;
1780
- }[]>;
1781
- /** Get all pending tasks (available for bidding). */
1782
- getPendingTasks(): GoalNode[];
1783
- /** Get tasks assigned to a specific agent. */
1784
- getTasksForAgent(agentId: string): GoalNode[];
1785
- /** Get the current bid count for a task. */
1786
- getBidCount(taskId: string): number;
1787
- /** Get bids for a task. */
1788
- getBids(taskId: string): TaskBid[];
1789
- /** Get task stats for a project-wide dashboard. */
1790
- getStats(): {
1791
- total: number;
1792
- pending: number;
1793
- in_progress: number;
1794
- done: number;
1795
- failed: number;
1796
- totalBids: number;
1797
- avgBidsPerTask: number;
1798
- };
2042
+ private _runQualityGate;
2043
+ /**
2044
+ * Update quality gate result for a change. Called by verify agents
2045
+ * after running their checks.
2046
+ */
2047
+ updateQualityGate(changeId: string, checkName: string, result: {
2048
+ passed: boolean;
2049
+ detail?: string;
2050
+ }): Promise<void>;
1799
2051
  private _emit;
1800
- private _broadcastTask;
1801
- private _mailboxPublish;
1802
- private _notifyAgent;
1803
- private _startBidWindow;
1804
- private _cancelBidWindow;
1805
- private _evaluateBids;
1806
- private _assignDirect;
1807
- private _onBidEvent;
1808
- private _onClaimedEvent;
1809
- private _getAgentTaskCount;
1810
- private agentTaskCount;
1811
2052
  }
1812
2053
 
1813
2054
  /**
@@ -2038,156 +2279,4 @@ declare class AutonomousCoordinator {
2038
2279
  private _emit;
2039
2280
  }
2040
2281
 
2041
- interface AgentTimelineEntry {
2042
- /** Unique entry id (ULID or timestamp-based). */
2043
- id: string;
2044
- /** Subagent id this entry belongs to. */
2045
- subagentId: string;
2046
- /** Human-readable agent name/role. */
2047
- agentName: string;
2048
- /** ISO 8601 timestamp. */
2049
- ts: string;
2050
- /** Content type. */
2051
- kind: 'text' | 'tool_use' | 'tool_result' | 'error' | 'status' | 'system';
2052
- /** The message content (text, tool summary, error message, status text). */
2053
- content: string;
2054
- /** Iteration index within the subagent's run. */
2055
- iteration: number;
2056
- /** For tool entries: tool name. */
2057
- toolName?: string | undefined;
2058
- /** For tool entries: whether the tool succeeded. */
2059
- toolOk?: boolean | undefined;
2060
- /** Running cost estimate. */
2061
- costUsd?: number | undefined;
2062
- }
2063
- interface AgentVirtualSession {
2064
- subagentId: string;
2065
- agentName: string;
2066
- createdAt: string;
2067
- status: string;
2068
- task?: string | undefined;
2069
- /** Ordered transcript entries (newest last). */
2070
- transcript: AgentTimelineEntry[];
2071
- }
2072
- interface AgentMonitorOptions {
2073
- /** Parent/host session id for emitted agent timeline/status events. */
2074
- sessionId?: string | undefined;
2075
- /** The FleetBus to listen on for subagent events. Optional — set via `setFleetBus()` before `start()`. */
2076
- fleetBus?: FleetBus | undefined;
2077
- /** Local EventBus for emitting agent.timeline.* and agent.status_changed events. */
2078
- events: EventBus;
2079
- /** Directory where per-subagent JSONL transcripts will be written. */
2080
- transcriptsDir: string;
2081
- /** Maximum in-memory entries per subagent (ring buffer). Default 500. */
2082
- maxEntriesPerAgent?: number;
2083
- /** Whether agent stream is initially enabled. Default false. */
2084
- streamEnabled?: boolean;
2085
- /** Called for each new timeline entry — used by HQ publisher bridge. */
2086
- onEntry?: ((entry: AgentTimelineEntry) => void) | undefined;
2087
- }
2088
- declare class AgentMonitorService {
2089
- private _fleetBus;
2090
- private readonly _events;
2091
- private readonly _sessionId;
2092
- private readonly _transcriptsDir;
2093
- private readonly _maxEntries;
2094
- private _streamEnabled;
2095
- private _onEntry;
2096
- /** Per-subagent virtual sessions. */
2097
- private readonly _sessions;
2098
- /** Disposers for FleetBus subscriptions, keyed by subagentId. */
2099
- private readonly _subscriptions;
2100
- /** Generic fleet-wide subscription disposer. */
2101
- private _fleetDisposer;
2102
- /** Track whether service is running. */
2103
- private _started;
2104
- constructor(opts: AgentMonitorOptions);
2105
- /** Set the FleetBus to listen on. Must be called before `start()`. */
2106
- setFleetBus(bus: FleetBus): void;
2107
- get streamEnabled(): boolean;
2108
- /** Enable/disable streaming agent conversations to the main chat timeline. */
2109
- setStreamEnabled(enabled: boolean): void;
2110
- /** Get a snapshot of all known agent sessions. */
2111
- getAllSessions(): AgentVirtualSession[];
2112
- /** Get a specific agent's virtual session, or undefined. */
2113
- getSession(subagentId: string): AgentVirtualSession | undefined;
2114
- /** Get transcript entries for a specific agent, newest first. */
2115
- getTranscript(subagentId: string, limit?: number): AgentTimelineEntry[];
2116
- /** Set a callback for each new timeline entry (HQ bridge). */
2117
- setOnEntry(handler: ((entry: AgentTimelineEntry) => void) | undefined): void;
2118
- /** Start listening to FleetBus events. */
2119
- start(): void;
2120
- /** Stop listening and clean up all subscriptions. */
2121
- stop(): void;
2122
- /** Ensure a subagent is being tracked. Called when a subagent spawns. */
2123
- trackSubagent(subagentId: string, agentName: string, task?: string): void;
2124
- /** Mark a subagent as completed/failed/etc. Called on subagent finish. */
2125
- completeSubagent(subagentId: string, status: 'completed' | 'failed' | 'timeout' | 'stopped' | 'budget_exhausted', summary?: string): void;
2126
- private _routeEvent;
2127
- private _addEntry;
2128
- private _appendToFile;
2129
- private _uid;
2130
- }
2131
- declare function createAgentMonitorService(opts: AgentMonitorOptions): AgentMonitorService;
2132
-
2133
- /**
2134
- * Adaptive Concurrency Controller
2135
- *
2136
- * Automatically adjusts `maxConcurrent` based on:
2137
- * - Rate limit (429) errors → decrease concurrency
2138
- * - Sustained successful requests → increase concurrency
2139
- *
2140
- * This provides automatic backpressure without manual tuning.
2141
- */
2142
-
2143
- interface AdaptiveConcurrencyState {
2144
- current: number;
2145
- min: number;
2146
- max: number;
2147
- consecutiveSuccesses: number;
2148
- consecutiveFailures: number;
2149
- totalDecreases: number;
2150
- totalIncreases: number;
2151
- enabled: boolean;
2152
- }
2153
- /**
2154
- * Adaptive Concurrency Controller
2155
- *
2156
- * Monitors fleet events for rate-limit (429) errors and adjusts concurrency
2157
- * automatically to prevent overwhelming the API provider.
2158
- */
2159
- declare class AdaptiveConcurrencyController {
2160
- private readonly config;
2161
- private state;
2162
- private readonly disposers;
2163
- private stateChangeHandlers;
2164
- constructor(fleetBus: FleetBus, setMaxConcurrent: (n: number) => void, config?: Partial<AdaptiveConcurrencyConfig>, onStateChange?: (state: AdaptiveConcurrencyState) => void);
2165
- private setupEventHandlers;
2166
- /**
2167
- * Handle a rate limit (429) error - decrease concurrency
2168
- */
2169
- private handleRateLimit;
2170
- /**
2171
- * Force a decrease (e.g., manual trigger or other error types)
2172
- */
2173
- decrease(target?: number): void;
2174
- /**
2175
- * Get the current state
2176
- */
2177
- getState(): AdaptiveConcurrencyState;
2178
- /**
2179
- * Update configuration at runtime
2180
- */
2181
- updateConfig(config: Partial<AdaptiveConcurrencyConfig>): void;
2182
- /**
2183
- * Dispose of the controller and clean up event listeners
2184
- */
2185
- dispose(): void;
2186
- private notifyStateChange;
2187
- /**
2188
- * Register a state change handler
2189
- */
2190
- onStateChange(handler: (state: AdaptiveConcurrencyState) => void): () => void;
2191
- }
2192
-
2193
- export { type AcquireOptions, type AcquireResult, AdaptiveConcurrencyController, type AdaptiveConcurrencyState, AgentDefinition, AgentHeartbeatInput, type AgentMonitorOptions, AgentMonitorService, AgentRegistrationInput, type AgentTimelineEntry, type AgentVirtualSession, type ApplyResult, type ApprovalDecision, AutonomousBrain, type AutonomousBrainOptions, AutonomousCoordinator, type AutonomousCoordinatorOptions, type AutonomousDecisionRequest, type AutonomousDecisionType, BUILD_AGENTS, BrainArbiter, BrainDecision, BrainDecisionOption, BrainDecisionRequest, BrainDecisionSource, type BrainInterventionInput, BrainMonitor, type BrainMonitorOptions, BrainRisk, type ChangeFile, ChangeManager, type ChangeManagerOptions, type ChangeNode, type ChangeProposal, type ChangeStatus, ClientHeartbeatInput, ClientRegistrationInput, ClientStatus, type ConsensusOptions, ConsensusProtocol, type ConsensusResult, type CoordinatorEvent, type CoordinatorStats, type DAGEdgeEvent, type DAGEdgeHandler, type DAGNode, type DAGNodeStatus, DEFAULT_QUALITY_CHECKS, DELIVERY_AGENTS, DEPENDENCY_FILE_PATTERNS, DISCOVERY_AGENTS, DOMAIN_AGENTS, type DecisionNode, type DecisionPrompt, DefaultMailbox, type DepWatchEntry, type DepWatcherBridgeOptions, type DependencyWatcherConfig, Director, type DownAlertInput, type EscalationDecision, type FactCategory, type FactNode, FleetBus, FleetManager, GlobalMailbox, type GoalNode, type GoalPriority, type GoalStatus, type GraphSubscription, KNOWLEDGE_AGENTS, KnowledgeGraph, type LLMProvider, type LiveLockResult, 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, META_AGENTS, type MailToolsOptions, Mailbox, MailboxAckBatchInput, MailboxAckInput, MailboxAgentStatus, type MailboxBridgeLock, type MailboxHealthEvent, MailboxHealthWatchdog, type MailboxHealthWatchdogOptions, type MailboxHooksOptions, MailboxMessage, MailboxQuery, type MailboxResolver, MailboxSendInput, type MailboxToolOptions, type NodeFilter, type NodeType, type OutdatedNotifyMessage, PLANNING_AGENTS, type PackageAuthorEntry, type PackageAuthorLog, type PackageAuthorTrackerOptions, type PackageOutdatedEntry, type PackageOutdatedResult, type PackageOutdatedWatcherOptions, type PrioritizationDecision, PurgeOptions, PurgeResult, type QualityCheck, type QualityGateChecks, type QualityGateResult, type QuorumRule, REVIEW_AGENTS, type RecoveryAlertInput, type RollbackResult, type RunOptions, type RunnablesHandler, type SpawnDecision, type TaskAuctionOptions, TaskAuctioneer, type TaskBid, TaskDAG, VERIFY_AGENTS, type VoteNode, type VoteRecord, type VoteValue, type VoterConfig, type WatchdogConfig, acquireOrJoin, attachDepWatcherBridge, buildDownAlert, buildRecoveryAlert, createAgentMonitorService, createMailboxHooks, detectEcosystem, finalize, getFullPackageLog, getManifestPackages, getPackageAuthor, getPackagesByAgent, mailboxSessionTag, makeDependencyWatcherConfig, makeMailInboxTool, makeMailSendTool, makeMailboxTool, readLiveLock, recordPackageAction, release, resolveMailboxIdentity, startPackageOutdatedWatcher, updatePackageOutdatedStatus, validateWatchdogOptions };
2282
+ export { type AcquireOptions, type AcquireResult, AdaptiveConcurrencyController, type AdaptiveConcurrencyState, AgentDefinition, AgentHeartbeatInput, type AgentMonitorOptions, AgentMonitorService, AgentRegistrationInput, type AgentTimelineEntry, type AgentVirtualSession, type ApplyResult, type ApprovalDecision, AutonomousBrain, type AutonomousBrainOptions, AutonomousCoordinator, type AutonomousCoordinatorOptions, type AutonomousDecisionRequest, type AutonomousDecisionType, BUILD_AGENTS, BrainArbiter, BrainDecision, BrainDecisionOption, BrainDecisionRequest, BrainDecisionSource, type BrainInterventionInput, BrainMonitor, type BrainMonitorOptions, BrainRisk, type ChangeFile, ChangeManager, type ChangeManagerOptions, type ChangeNode, type ChangeProposal, type ChangeStatus, ClientHeartbeatInput, ClientRegistrationInput, ClientStatus, type ConsensusOptions, ConsensusProtocol, type ConsensusResult, type CoordinatorEvent, type CoordinatorStats, type DAGEdgeEvent, type DAGEdgeHandler, type DAGNode, type DAGNodeStatus, DEFAULT_QUALITY_CHECKS, DELIVERY_AGENTS, DEPENDENCY_FILE_PATTERNS, DISCOVERY_AGENTS, DOMAIN_AGENTS, type DecisionNode, type DecisionPrompt, DefaultMailbox, type DepWatchEntry, type DepWatcherBridgeOptions, type DependencyWatcherConfig, Director, type DownAlertInput, type EscalationDecision, type FactCategory, type FactNode, FleetBus, FleetManager, GlobalMailbox, type GoalNode, type GoalPriority, type GoalStatus, type GraphSubscription, KNOWLEDGE_AGENTS, KnowledgeGraph, type LLMProvider, type LiveLockResult, 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, META_AGENTS, type MailToolsOptions, Mailbox, MailboxAckBatchInput, MailboxAckInput, type MailboxActionInput, type MailboxActionResult, MailboxAgentStatus, type MailboxBridgeLock, type MailboxHealthEvent, MailboxHealthWatchdog, type MailboxHealthWatchdogOptions, type MailboxHooksOptions, MailboxMessage, type MailboxMessageAction, MailboxQuery, type MailboxResolver, MailboxSendInput, type MailboxToolOptions, type NodeFilter, type NodeType, type OutdatedNotifyMessage, PLANNING_AGENTS, type PackageAuthorEntry, type PackageAuthorLog, type PackageAuthorTrackerOptions, type PackageOutdatedEntry, type PackageOutdatedResult, type PackageOutdatedWatcherOptions, type PrioritizationDecision, PurgeOptions, PurgeResult, type QualityCheck, type QualityGateChecks, type QualityGateResult, type QuorumRule, REVIEW_AGENTS, type RecoveryAlertInput, type RollbackResult, type RunOptions, type RunnablesHandler, type SpawnDecision, type TaskAuctionOptions, TaskAuctioneer, type TaskBid, TaskDAG, VERIFY_AGENTS, type VoteNode, type VoteRecord, type VoteValue, type VoterConfig, type WatchdogConfig, acquireOrJoin, actionToAckInput, attachDepWatcherBridge, buildDownAlert, buildRecoveryAlert, createAgentMonitorService, createMailboxHooks, detectEcosystem, finalize, getFullPackageLog, getManifestPackages, getPackageAuthor, getPackagesByAgent, mailboxSessionTag, makeDependencyWatcherConfig, makeMailInboxTool, makeMailSendTool, makeMailboxTool, readLiveLock, recordPackageAction, release, resolveMailboxIdentity, startPackageOutdatedWatcher, updatePackageOutdatedStatus, validateWatchdogOptions };