@wrongstack/core 0.257.2 → 0.264.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/{agent-bridge-BrxWHEOm.d.ts → agent-bridge-D8sa1vtv.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-US741uBH.d.ts → agent-subagent-runner-c9DLkaas.d.ts} +31 -9
  3. package/dist/{brain-TjEEwSpw.d.ts → brain-O1IdKPaK.d.ts} +59 -2
  4. package/dist/{compactor-C5sT4U7I.d.ts → compactor-BBy0rCtB.d.ts} +1 -1
  5. package/dist/{config-DuAu23zm.d.ts → config-Dz2F3H2K.d.ts} +7 -1
  6. package/dist/{context-CGdgA0q6.d.ts → context-BGSpZNSE.d.ts} +33 -0
  7. package/dist/coordination/index.d.ts +1681 -15
  8. package/dist/coordination/index.js +2826 -405
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +25 -25
  11. package/dist/defaults/index.js +2258 -1433
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/dispatcher-types.d-BBeXBQgS.d.ts +66 -0
  14. package/dist/execution/index.d.ts +15 -15
  15. package/dist/execution/index.js +502 -398
  16. package/dist/execution/index.js.map +1 -1
  17. package/dist/execution/prompt-enhancer.d.ts +2 -2
  18. package/dist/execution/prompt-enhancer.js +7 -1
  19. package/dist/execution/prompt-enhancer.js.map +1 -1
  20. package/dist/extension/index.d.ts +6 -6
  21. package/dist/extension/index.js.map +1 -1
  22. package/dist/{goal-preamble-CznHTZqP.d.ts → goal-preamble-DzjFuN3p.d.ts} +21 -9
  23. package/dist/{goal-store-CV9Yz2X_.d.ts → goal-store-CxWmCGbH.d.ts} +4 -2
  24. package/dist/{index-CC0Mcm05.d.ts → index-CYIQrXVF.d.ts} +8 -8
  25. package/dist/{index-CitPrI3a.d.ts → index-CbLSI66_.d.ts} +5 -5
  26. package/dist/index.d.ts +50 -94
  27. package/dist/index.js +16009 -12406
  28. package/dist/index.js.map +1 -1
  29. package/dist/infrastructure/index.d.ts +6 -6
  30. package/dist/kernel/index.d.ts +9 -9
  31. package/dist/kernel/index.js +6 -1
  32. package/dist/kernel/index.js.map +1 -1
  33. package/dist/{llm-selector-CJ4SyAFE.d.ts → llm-selector-DzxuZnNz.d.ts} +2 -2
  34. package/dist/{mcp-servers-D8YnLaEp.d.ts → mcp-servers-DC4QRPUI.d.ts} +3 -3
  35. package/dist/models/index.d.ts +5 -5
  36. package/dist/models/index.js +6 -1
  37. package/dist/models/index.js.map +1 -1
  38. package/dist/{models-registry-ByZCdFuQ.d.ts → models-registry-B_siPxqN.d.ts} +1 -1
  39. package/dist/{multi-agent-coordinator-DqTUEAeC.d.ts → multi-agent-coordinator-CK5Jdj9K.d.ts} +2 -2
  40. package/dist/{null-fleet-bus-B5mfTJXT.d.ts → null-fleet-bus-DgvD4SCO.d.ts} +13 -8
  41. package/dist/observability/index.d.ts +2 -2
  42. package/dist/observability/index.js +8 -3
  43. package/dist/observability/index.js.map +1 -1
  44. package/dist/{parallel-eternal-engine-C0juOszP.d.ts → parallel-eternal-engine-bK0JQBR_.d.ts} +13 -9
  45. package/dist/{path-resolver-CbkT-RMU.d.ts → path-resolver-BPEDlN38.d.ts} +3 -3
  46. package/dist/{permission-CwBBpCoF.d.ts → permission-4yvGmMRB.d.ts} +1 -1
  47. package/dist/{permission-policy-B8rSu908.d.ts → permission-policy-C6XpsBOy.d.ts} +3 -2
  48. package/dist/{pipeline-JG8XoudC.d.ts → pipeline-CXCeMz8J.d.ts} +58 -3
  49. package/dist/{plan-templates-DPiQMkBz.d.ts → plan-templates-BvzRBkJc.d.ts} +32 -11
  50. package/dist/{provider-runner-hM7EXlLI.d.ts → provider-runner-C5aQpDWE.d.ts} +3 -3
  51. package/dist/{retry-policy-Tg7LXkoK.d.ts → retry-policy-CFhdtRzz.d.ts} +1 -1
  52. package/dist/sdd/index.d.ts +8 -8
  53. package/dist/sdd/index.js +59 -31
  54. package/dist/sdd/index.js.map +1 -1
  55. package/dist/{secret-vault-gxtFZYBt.d.ts → secret-vault-CxiVLbt1.d.ts} +1 -1
  56. package/dist/security/index.d.ts +4 -4
  57. package/dist/security/index.js +238 -204
  58. package/dist/security/index.js.map +1 -1
  59. package/dist/{selector-DWsqVjGf.d.ts → selector-gIuhRTkN.d.ts} +1 -1
  60. package/dist/{session-event-bridge-BAFWdgQ3.d.ts → session-event-bridge-DkvvrpDt.d.ts} +8 -2
  61. package/dist/{session-reader-CqRvaL5v.d.ts → session-reader-KdfVwkKP.d.ts} +1 -1
  62. package/dist/skills/index.js +67 -64
  63. package/dist/skills/index.js.map +1 -1
  64. package/dist/storage/index.d.ts +50 -22
  65. package/dist/storage/index.js +1654 -525
  66. package/dist/storage/index.js.map +1 -1
  67. package/dist/tools/index.d.ts +57 -0
  68. package/dist/tools/index.js +411 -0
  69. package/dist/tools/index.js.map +1 -0
  70. package/dist/types/index.d.ts +19 -19
  71. package/dist/types/index.js +711 -694
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/utils/error.d.ts +7 -0
  74. package/dist/utils/error.js +8 -0
  75. package/dist/utils/error.js.map +1 -0
  76. package/dist/utils/index.d.ts +7 -67
  77. package/dist/utils/index.js +17 -5
  78. package/dist/utils/index.js.map +1 -1
  79. package/package.json +5 -1
  80. package/skills/output-standards/SKILL.md +14 -9
  81. package/skills/output-standards/SKILL.save.md +3 -2
  82. package/dist/package-outdated-watcher-BSgR_kK-.d.ts +0 -581
@@ -1,5 +1,5 @@
1
- import { T as Tool, n as TextBlock, g as ContentBlock } from './context-CGdgA0q6.js';
2
- import { H as HookEvent, e as HookMatcher, I as InProcessHook, S as ShellHook, f as HookEntry } from './config-DuAu23zm.js';
1
+ import { T as Tool, n as TextBlock, g as ContentBlock } from './context-BGSpZNSE.js';
2
+ import { H as HookEvent, e as HookMatcher, I as InProcessHook, S as ShellHook, f as HookEntry } from './config-Dz2F3H2K.js';
3
3
 
4
4
  /**
5
5
  * Mailbox — persistent inter-agent messaging system with cross-session support.
@@ -196,6 +196,18 @@ interface MailboxAckInput {
196
196
  /** Optional outcome summary. */
197
197
  outcome?: string | undefined;
198
198
  }
199
+ /**
200
+ * Batch acknowledgment input — applies a batch of acks under a single file
201
+ * lock + single file rewrite. Each entry has the same shape as
202
+ * {@link MailboxAckInput} minus the per-batch defaults documented on
203
+ * `ackMany`. Use this when an agent is acking several fresh messages at
204
+ * once (the common case in the mailbox loop) — it collapses N full-file
205
+ * rewrites into one.
206
+ */
207
+ interface MailboxAckBatchInput {
208
+ /** Ack entries to apply. */
209
+ acks: MailboxAckInput[];
210
+ }
199
211
  interface AgentRegistrationInput {
200
212
  agentId: string;
201
213
  sessionId: string;
@@ -239,6 +251,28 @@ interface AgentHeartbeatInput {
239
251
  iterations?: number | undefined;
240
252
  toolCalls?: number | undefined;
241
253
  }
254
+ interface PurgeOptions {
255
+ /**
256
+ * Purge completed messages older than this many milliseconds.
257
+ * Default: 1 day (86_400_000 ms)
258
+ */
259
+ completedMaxAgeMs?: number | undefined;
260
+ /**
261
+ * Purge incomplete messages older than this many milliseconds.
262
+ * Default: 7 days (604_800_000 ms)
263
+ */
264
+ incompleteMaxAgeMs?: number | undefined;
265
+ }
266
+ interface PurgeResult {
267
+ /** Messages removed because they were completed and too old. */
268
+ completedPurged: number;
269
+ /** Messages removed because they were incomplete and too old. */
270
+ incompletePurged: number;
271
+ /** Total messages removed. */
272
+ totalPurged: number;
273
+ /** Messages remaining in the mailbox after purge. */
274
+ remaining: number;
275
+ }
242
276
  interface Mailbox {
243
277
  /** Send a message. Returns the created message. */
244
278
  send(input: MailboxSendInput): Promise<MailboxMessage>;
@@ -246,6 +280,17 @@ interface Mailbox {
246
280
  query(query: MailboxQuery): Promise<MailboxMessage[]>;
247
281
  /** Acknowledge a message (read/complete). Returns updated message. */
248
282
  ack(input: MailboxAckInput): Promise<MailboxMessage | null>;
283
+ /**
284
+ * Acknowledge many messages in one shot. Acquires the file lock once and
285
+ * rewrites the message file once, regardless of how many acks are in the
286
+ * batch. Returns the messages that were actually updated (messages whose
287
+ * ids are not in the file are skipped silently).
288
+ *
289
+ * This is the preferred path when an agent has multiple fresh messages
290
+ * to receipt at once — the per-message {@link ack} path does a full
291
+ * read-modify-rewrite of the mailbox file for every call.
292
+ */
293
+ ackMany(input: MailboxAckBatchInput): Promise<MailboxMessage[]>;
249
294
  /** Get a snapshot of online/offline agents and their current tasks. */
250
295
  getAgentStatuses(): Promise<MailboxAgentStatus[]>;
251
296
  /**
@@ -275,6 +320,16 @@ interface Mailbox {
275
320
  * Agents and read receipts are preserved; only messages are cleared.
276
321
  */
277
322
  clearAll(): Promise<void>;
323
+ /**
324
+ * Purge orphaned and stale messages from the mailbox.
325
+ *
326
+ * Stale messages are:
327
+ * - Completed messages older than `completedMaxAgeMs` (default: 1 day)
328
+ * - Incomplete messages older than `incompleteMaxAgeMs` (default: 7 days)
329
+ *
330
+ * This does NOT touch agent registrations or client registry.
331
+ */
332
+ purgeStale(opts?: PurgeOptions): Promise<PurgeResult>;
278
333
  /**
279
334
  * Register a client (REPL/TUI/WebUI). Called once per client on startup.
280
335
  * Subsequent calls are idempotent — they update lastSeenAt.
@@ -530,4 +585,4 @@ declare class Pipeline<T> {
530
585
  private ensureUnique;
531
586
  }
532
587
 
533
- export { type AgentRegistrationInput as A, type BuildContext as B, Container as C, type Decorator as D, type Factory as F, HookRegistry as H, type MiddlewareHandler as M, type NextFn as N, Pipeline as P, type ReadonlyPipeline as R, type SystemPromptBuilder as S, type Token as T, type Renderer as a, type Mailbox as b, type MailboxSendInput as c, type MailboxMessage as d, type MailboxQuery as e, type MailboxAckInput as f, type MailboxAgentStatus as g, type AgentHeartbeatInput as h, type ClientRegistrationInput as i, type ClientHeartbeatInput as j, type ClientStatus as k, type MailboxMessageType as l, type MailboxTaskContext as m, type ReadReceipts as n, type RegisteredAgent as o, normalizeRecipient as p, type ModelCapabilities as q, type BindOptions as r, type Middleware as s, type PipelineOptions as t, hookMatcherMatches as u };
588
+ export { type AgentHeartbeatInput as A, type BuildContext as B, Container as C, type Decorator as D, type Factory as F, HookRegistry as H, type MiddlewareHandler as M, type NextFn as N, Pipeline as P, type ReadonlyPipeline as R, type SystemPromptBuilder as S, type Token as T, type Renderer as a, type ModelCapabilities as b, type Mailbox as c, type MailboxMessage as d, type AgentRegistrationInput as e, type BindOptions as f, type MailboxAckInput as g, type MailboxAgentStatus as h, type MailboxMessageType as i, type MailboxQuery as j, type MailboxSendInput as k, type MailboxTaskContext as l, type Middleware as m, type PipelineOptions as n, type ReadReceipts as o, type RegisteredAgent as p, hookMatcherMatches as q, normalizeRecipient as r, type MailboxAckBatchInput as s, type PurgeOptions as t, type PurgeResult as u, type ClientRegistrationInput as v, type ClientHeartbeatInput as w, type ClientStatus as x };
@@ -1,9 +1,9 @@
1
- import { E as EventBus, M as MemoryScope, k as MemoryEntry, l as MemoryStore, m as MemoryRelevanceContext, S as ScoredEntry } from './brain-TjEEwSpw.js';
2
- import { S as SecretScrubber } from './permission-CwBBpCoF.js';
3
- import { i as SessionStore, h as SessionMetadata, a as SessionWriter, p as ResumedSession, q as SessionData, r as SessionSummary, g as ContentBlock, S as SessionEvent, s as TodoItem, t as ConversationState } from './context-CGdgA0q6.js';
4
- import { A as AttachmentStore, a as AddAttachmentInput, b as AttachmentRef, c as Attachment } from './session-reader-CqRvaL5v.js';
1
+ import { E as EventBus, M as MemoryScope, b as MemoryEntry, c as MemoryStore, d as MemoryRelevanceContext, S as ScoredEntry } from './brain-O1IdKPaK.js';
2
+ import { S as SecretScrubber } from './permission-4yvGmMRB.js';
3
+ import { i as SessionStore, h as SessionMetadata, a as SessionWriter, p as ResumedSession, q as SessionData, r as SessionSummary, g as ContentBlock, S as SessionEvent, s as TodoItem, t as ConversationState } from './context-BGSpZNSE.js';
4
+ import { A as AttachmentStore, a as AddAttachmentInput, b as AttachmentRef, c as Attachment } from './session-reader-KdfVwkKP.js';
5
5
  import { W as WstackPaths } from './wstack-paths-CJjEwPXn.js';
6
- import { i as ConfigStore, h as Config, j as ConfigLoader, k as SyncConfig } from './config-DuAu23zm.js';
6
+ import { i as ConfigStore, h as Config, j as ConfigLoader, k as SyncConfig } from './config-Dz2F3H2K.js';
7
7
  import { S as SecretVault } from './secret-vault-BJDY28ev.js';
8
8
 
9
9
  interface SessionStoreOptions {
@@ -25,6 +25,9 @@ declare class DefaultSessionStore implements SessionStore {
25
25
  private readonly events?;
26
26
  private readonly secretScrubber?;
27
27
  constructor(opts: SessionStoreOptions);
28
+ private emitRead;
29
+ private emitWrite;
30
+ private emitError;
28
31
  /** Absolute path to the session index file. */
29
32
  private get indexFile();
30
33
  /** Join session ID to its absolute path within the store directory. */
@@ -108,8 +111,12 @@ interface PersistedQueueItem {
108
111
  */
109
112
  declare class QueueStore {
110
113
  private readonly file;
114
+ private readonly events;
115
+ private readonly traceId;
111
116
  constructor(opts: {
112
117
  dir: string;
118
+ events?: EventBus;
119
+ traceId?: string;
113
120
  });
114
121
  write(items: PersistedQueueItem[]): Promise<void>;
115
122
  read(): Promise<PersistedQueueItem[]>;
@@ -198,6 +205,7 @@ interface MemoryStoreOptions {
198
205
  declare class DefaultMemoryStore implements MemoryStore {
199
206
  private readonly files;
200
207
  private readonly events?;
208
+ private traceId?;
201
209
  private readonly backend;
202
210
  /**
203
211
  * Per-scope serialization queue. `remember` / `forget` / `consolidate` /
@@ -249,7 +257,16 @@ declare class DefaultMemoryStore implements MemoryStore {
249
257
  forget(query: string, scope?: MemoryScope): Promise<number>;
250
258
  consolidate(scope: MemoryScope): Promise<void>;
251
259
  clear(scope?: MemoryScope): Promise<void>;
252
- /** Mirror current memory content to the persistent backup directory. */
260
+ /**
261
+ * Return a new MemoryStore proxy that carries `traceId` on every storage
262
+ * event. The original store is left unchanged — callers that need a
263
+ * trace-decorated view (e.g. session-run tools) receive the proxy while
264
+ * the singleton remains trace-free for boot-time use.
265
+ *
266
+ * The proxy implements the full `MemoryStore` interface; all other
267
+ * properties (backend, etc.) are delegated to the original store.
268
+ */
269
+ withTraceId(traceId: string): MemoryStore;
253
270
  private mirrorBackup;
254
271
  }
255
272
 
@@ -296,12 +313,16 @@ interface ConfigLoaderOptions {
296
313
  vault?: SecretVault | undefined;
297
314
  /** Extra sources merged after the built-in layers. */
298
315
  sources?: ConfigSource[] | undefined;
316
+ events?: EventBus;
317
+ traceId?: string;
299
318
  }
300
319
  declare class DefaultConfigLoader implements ConfigLoader {
301
320
  private readonly paths;
302
321
  private readonly strict;
303
322
  private readonly vault;
304
323
  private readonly extraSources;
324
+ private readonly events;
325
+ private readonly traceId;
305
326
  constructor(opts: ConfigLoaderOptions);
306
327
  load(opts?: {
307
328
  cliFlags?: Partial<Config> | undefined;
@@ -544,12 +565,12 @@ type TodosCheckpointDetach = () => Promise<void>;
544
565
  /** Read a checkpoint from disk. Returns null when the file doesn't
545
566
  * exist or is corrupt — callers treat both cases as "no prior state".
546
567
  */
547
- declare function loadTodosCheckpoint(filePath: string): Promise<TodoItem[] | null>;
568
+ declare function loadTodosCheckpoint(filePath: string, events?: EventBus, traceId?: string): Promise<TodoItem[] | null>;
548
569
  /** Write the checkpoint atomically. Best-effort: a write failure is
549
570
  * logged but does not throw — losing one checkpoint shouldn't bring
550
571
  * down the agent run.
551
572
  */
552
- declare function saveTodosCheckpoint(filePath: string, sessionId: string, todos: readonly TodoItem[]): Promise<void>;
573
+ declare function saveTodosCheckpoint(filePath: string, sessionId: string, todos: readonly TodoItem[], events?: EventBus, traceId?: string): Promise<void>;
553
574
  /**
554
575
  * Subscribe a `ConversationState` so every `todos_replaced` mutation
555
576
  * triggers an atomic write to disk. Returns the unsubscribe function.
@@ -558,7 +579,7 @@ declare function saveTodosCheckpoint(filePath: string, sessionId: string, todos:
558
579
  * marking three items done in the same tool call) coalesces into one
559
580
  * disk hit.
560
581
  */
561
- declare function attachTodosCheckpoint(state: ConversationState, filePath: string, sessionId: string): TodosCheckpointDetach;
582
+ declare function attachTodosCheckpoint(state: ConversationState, filePath: string, sessionId: string, events?: EventBus, traceId?: string): TodosCheckpointDetach;
562
583
 
563
584
  /**
564
585
  * Plan items are the strategic counterpart to todos. Where `ctx.todos`
@@ -586,8 +607,8 @@ interface PlanFile {
586
607
  updatedAt: string;
587
608
  items: PlanItem[];
588
609
  }
589
- declare function loadPlan(filePath: string): Promise<PlanFile | null>;
590
- declare function savePlan(filePath: string, plan: PlanFile): Promise<void>;
610
+ declare function loadPlan(filePath: string, events?: EventBus): Promise<PlanFile | null>;
611
+ declare function savePlan(filePath: string, plan: PlanFile, events?: EventBus): Promise<void>;
591
612
  /** Create a new PlanFile when none exists on disk. */
592
613
  declare function emptyPlan(sessionId: string, title?: string): PlanFile;
593
614
  declare function addPlanItem(plan: PlanFile, title: string, details?: string | undefined): {
@@ -1,8 +1,8 @@
1
- import { E as EventBus } from './brain-TjEEwSpw.js';
1
+ import { E as EventBus } from './brain-O1IdKPaK.js';
2
2
  import { L as Logger } from './logger-B63L5bTg.js';
3
3
  import { T as Tracer } from './observability-D-HZN_mF.js';
4
- import { P as Provider, R as Request, C as Context, b as Response } from './context-CGdgA0q6.js';
5
- import { R as RetryPolicy } from './retry-policy-Tg7LXkoK.js';
4
+ import { P as Provider, R as Request, C as Context, b as Response } from './context-BGSpZNSE.js';
5
+ import { R as RetryPolicy } from './retry-policy-CFhdtRzz.js';
6
6
 
7
7
  /**
8
8
  * Options passed to a ProviderRunner when calling the provider.
@@ -1,4 +1,4 @@
1
- import { C as Context, b as Response, e as ProviderError } from './context-CGdgA0q6.js';
1
+ import { C as Context, b as Response, e as ProviderError } from './context-BGSpZNSE.js';
2
2
 
3
3
  type RecoveryDecision = {
4
4
  /**
@@ -1,15 +1,15 @@
1
1
  import { h as Specification, S as SpecAnalysis, g as SpecValidationResult, e as SpecStatus, f as SpecTemplate, b as SpecRequirement } from '../spec-TBi3Jr6T.js';
2
2
  import { d as TaskGraph, e as TaskNode, i as TaskFilter, j as TaskSort, c as TaskProgress, T as TaskType, a as TaskPriority } from '../task-graph-u1q9Jkyk.js';
3
- import { E as EventBus } from '../brain-TjEEwSpw.js';
4
- import { D as DoneCondition, g as Agent, h as AgentFactory, f as TaskResult } from '../agent-subagent-runner-US741uBH.js';
5
- import '../context-CGdgA0q6.js';
6
- import '../index-CitPrI3a.js';
3
+ import { E as EventBus } from '../brain-O1IdKPaK.js';
4
+ import { D as DoneCondition, g as Agent, h as AgentFactory, f as TaskResult } from '../agent-subagent-runner-c9DLkaas.js';
5
+ import '../context-BGSpZNSE.js';
6
+ import '../index-CbLSI66_.js';
7
7
  import '../logger-B63L5bTg.js';
8
- import '../pipeline-JG8XoudC.js';
9
- import '../config-DuAu23zm.js';
8
+ import '../pipeline-CXCeMz8J.js';
9
+ import '../config-Dz2F3H2K.js';
10
10
  import '../observability-D-HZN_mF.js';
11
- import '../permission-CwBBpCoF.js';
12
- import '../retry-policy-Tg7LXkoK.js';
11
+ import '../permission-4yvGmMRB.js';
12
+ import '../retry-policy-CFhdtRzz.js';
13
13
 
14
14
  declare class SpecParser {
15
15
  parse(content: string): Specification;
package/dist/sdd/index.js CHANGED
@@ -80,7 +80,12 @@ async function withFileLock(targetPath, fn, opts = {}) {
80
80
  await handle.writeFile(`${process.pid}:${Date.now()}`);
81
81
  break;
82
82
  } catch (err) {
83
- if (err.code !== "EEXIST") throw err;
83
+ const code = err.code;
84
+ if (code === "ENOENT") {
85
+ await fs.mkdir(dir, { recursive: true });
86
+ continue;
87
+ }
88
+ if (code !== "EEXIST") throw err;
84
89
  try {
85
90
  const stat2 = await fs.stat(lockPath);
86
91
  if (Date.now() - stat2.mtimeMs > staleMs) {
@@ -622,6 +627,35 @@ function topologicalSort(graph) {
622
627
  return result;
623
628
  }
624
629
 
630
+ // src/utils/error.ts
631
+ function toErrorMessage(err) {
632
+ return err instanceof Error ? err.message : String(err);
633
+ }
634
+
635
+ // src/utils/string.ts
636
+ function truncate(s, max) {
637
+ return s.length <= max ? s : `${s.slice(0, max - 1)}\u2026`;
638
+ }
639
+
640
+ // src/utils/expect-defined.ts
641
+ function expectDefined(value, label) {
642
+ if (value === null || value === void 0) {
643
+ const err = new Error("Expected value to be defined");
644
+ err.name = "ExpectDefinedError";
645
+ throw err;
646
+ }
647
+ return value;
648
+ }
649
+
650
+ // src/utils/assert-never.ts
651
+ function assertNever(x, message) {
652
+ const err = new Error(
653
+ `Unhandled case: ${JSON.stringify(x)}`
654
+ );
655
+ err.name = "AssertNeverError";
656
+ throw err;
657
+ }
658
+
625
659
  // src/types/errors.ts
626
660
  var ERROR_CODES = {
627
661
  // Provider
@@ -929,7 +963,7 @@ var TaskTracker = class {
929
963
  this.opts.onPersistError ? this.opts.onPersistError(err) : console.warn(JSON.stringify({
930
964
  level: "warn",
931
965
  event: "task_tracker.save_graph_failed",
932
- message: err instanceof Error ? err.message : String(err),
966
+ message: toErrorMessage(err),
933
967
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
934
968
  }));
935
969
  });
@@ -1358,16 +1392,6 @@ var TaskGraphStore = class {
1358
1392
  }
1359
1393
  };
1360
1394
 
1361
- // src/utils/expect-defined.ts
1362
- function expectDefined(value, label) {
1363
- if (value === null || value === void 0) {
1364
- const err = new Error("Expected value to be defined");
1365
- err.name = "ExpectDefinedError";
1366
- throw err;
1367
- }
1368
- return value;
1369
- }
1370
-
1371
1395
  // src/sdd/spec-builder.ts
1372
1396
  function buildQuestioningPrompt(session, min, max) {
1373
1397
  const answered = session.answers.length;
@@ -1609,7 +1633,7 @@ var AISpecBuilder = class {
1609
1633
  * ENOSPC / EACCES doesn't silently strand session edits in memory. */
1610
1634
  autoSave() {
1611
1635
  this.saveSession().catch((err) => {
1612
- const detail = err instanceof Error ? err.message : String(err);
1636
+ const detail = toErrorMessage(err);
1613
1637
  process.emitWarning(
1614
1638
  `SpecBuilder autoSave failed: ${detail}`,
1615
1639
  "SpecBuilderWarning"
@@ -2021,11 +2045,6 @@ function templateToMarkdown(template, title) {
2021
2045
  return lines.join("\n");
2022
2046
  }
2023
2047
 
2024
- // src/utils/string.ts
2025
- function truncate(s, max) {
2026
- return s.length <= max ? s : `${s.slice(0, max - 1)}\u2026`;
2027
- }
2028
-
2029
2048
  // src/sdd/task-visualizer.ts
2030
2049
  var STATUS_ICON = {
2031
2050
  pending: "\u25CB",
@@ -2348,15 +2367,6 @@ function computeParallelGroups(graph, blockedByMap) {
2348
2367
  return groups;
2349
2368
  }
2350
2369
 
2351
- // src/utils/assert-never.ts
2352
- function assertNever(x, message) {
2353
- const err = new Error(
2354
- `Unhandled case: ${JSON.stringify(x)}`
2355
- );
2356
- err.name = "AssertNeverError";
2357
- throw err;
2358
- }
2359
-
2360
2370
  // src/sdd/spec-versioning.ts
2361
2371
  var SpecVersioning = class {
2362
2372
  versions = /* @__PURE__ */ new Map();
@@ -3125,6 +3135,20 @@ var SubagentBudget = class _SubagentBudget {
3125
3135
  };
3126
3136
 
3127
3137
  // src/coordination/agent-subagent-runner.ts
3138
+ function withDisabledToolFiltering(factory) {
3139
+ return async (config) => {
3140
+ const result = await factory(config);
3141
+ const disabled = config.disabledTools ?? [];
3142
+ if (disabled.length === 0) return result;
3143
+ const registry = result.agent.tools;
3144
+ if (registry && typeof registry.unregister === "function") {
3145
+ for (const toolName of disabled) {
3146
+ registry.unregister(toolName);
3147
+ }
3148
+ }
3149
+ return result;
3150
+ };
3151
+ }
3128
3152
  function makeAgentSubagentRunner(opts) {
3129
3153
  const format = opts.formatTaskInput ?? defaultFormatTaskInput;
3130
3154
  return async (task, ctx) => {
@@ -3402,7 +3426,7 @@ function classifySubagentError(err, hints = {}) {
3402
3426
  const baseMessage2 = err.describe();
3403
3427
  return providerErrorToSubagentError(err, baseMessage2, cause);
3404
3428
  }
3405
- const baseMessage = err instanceof Error ? err.message : String(err);
3429
+ const baseMessage = toErrorMessage(err);
3406
3430
  if (err instanceof BudgetExceededError) {
3407
3431
  const map = {
3408
3432
  iterations: "budget_iterations",
@@ -7012,7 +7036,9 @@ var SddParallelRun = class {
7012
7036
  doneCondition: { type: "all_tasks_done" }
7013
7037
  };
7014
7038
  this.coordinator = new DefaultMultiAgentCoordinator(config);
7015
- const runner = makeAgentSubagentRunner({ factory: this.opts.subagentFactory ?? this.defaultFactory() });
7039
+ const baseFactory = this.opts.subagentFactory ?? this.defaultFactory();
7040
+ const filteredFactory = withDisabledToolFiltering(baseFactory);
7041
+ const runner = makeAgentSubagentRunner({ factory: filteredFactory });
7016
7042
  this.coordinator.setRunner?.(runner);
7017
7043
  }
7018
7044
  defaultFactory() {
@@ -7054,7 +7080,9 @@ var SddParallelRun = class {
7054
7080
  id: subagentId,
7055
7081
  name: subagentId,
7056
7082
  role: "executor",
7057
- timeoutMs: this.timeoutMs
7083
+ timeoutMs: this.timeoutMs,
7084
+ // Disable delegation — subagents are leaf workers, not orchestrators
7085
+ disabledTools: ["delegate"]
7058
7086
  })
7059
7087
  );
7060
7088
  const spawnResults = await Promise.all(spawns);
@@ -7099,7 +7127,7 @@ var SddParallelRun = class {
7099
7127
  const failCount = results.length - successCount;
7100
7128
  for (let i = 0; i < results.length; i++) {
7101
7129
  const result = expectDefined(results[i]);
7102
- const taskId = expectDefined(taskIds[i]);
7130
+ const taskId = expectDefined(tasks[i]).id;
7103
7131
  if (result.status === "success") {
7104
7132
  this.opts.tracker.updateNodeStatus(taskId, "completed");
7105
7133
  this.retryMap.delete(taskId);