@wrongstack/core 0.1.10 → 0.2.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 (42) hide show
  1. package/dist/{agent-bridge-6KPqsFx6.d.ts → agent-bridge-DmBiCipY.d.ts} +1 -1
  2. package/dist/{compactor-B4mQZXf2.d.ts → compactor-DSl2FK7a.d.ts} +1 -1
  3. package/dist/{config-BU9f_5yH.d.ts → config-DXrqb41m.d.ts} +1 -1
  4. package/dist/{context-BmM2xGUZ.d.ts → context-u0bryklF.d.ts} +8 -0
  5. package/dist/coordination/index.d.ts +210 -12
  6. package/dist/coordination/index.js +941 -67
  7. package/dist/coordination/index.js.map +1 -1
  8. package/dist/defaults/index.d.ts +18 -18
  9. package/dist/defaults/index.js +953 -41
  10. package/dist/defaults/index.js.map +1 -1
  11. package/dist/{events-BMNaEFZl.d.ts → events-B6Q03pTu.d.ts} +73 -1
  12. package/dist/execution/index.d.ts +11 -11
  13. package/dist/index.d.ts +61 -28
  14. package/dist/index.js +1077 -48
  15. package/dist/index.js.map +1 -1
  16. package/dist/infrastructure/index.d.ts +6 -6
  17. package/dist/kernel/index.d.ts +9 -9
  18. package/dist/kernel/index.js.map +1 -1
  19. package/dist/{mcp-servers-Dzgg4x1w.d.ts → mcp-servers-BA1Ofmfj.d.ts} +3 -3
  20. package/dist/models/index.d.ts +2 -2
  21. package/dist/{multi-agent-fmkRHtof.d.ts → multi-agent-BDfkxL5C.d.ts} +71 -3
  22. package/dist/observability/index.d.ts +2 -2
  23. package/dist/{path-resolver-DBjaoXFq.d.ts → path-resolver-Crkt8wTQ.d.ts} +2 -2
  24. package/dist/{plugin-DJk6LL8B.d.ts → plugin-CoYYZKdn.d.ts} +19 -6
  25. package/dist/{renderer-rk_1Swwc.d.ts → renderer-0A2ZEtca.d.ts} +1 -1
  26. package/dist/sdd/index.d.ts +3 -3
  27. package/dist/{secret-scrubber-CicHLN4G.d.ts → secret-scrubber-3TLUkiCV.d.ts} +1 -1
  28. package/dist/{secret-scrubber-DF88luOe.d.ts → secret-scrubber-CwYliRWd.d.ts} +1 -1
  29. package/dist/security/index.d.ts +20 -4
  30. package/dist/security/index.js +13 -1
  31. package/dist/security/index.js.map +1 -1
  32. package/dist/{selector-BbJqiEP4.d.ts → selector-BRqzvugb.d.ts} +1 -1
  33. package/dist/{session-reader-Drq8RvJu.d.ts → session-reader-C3x96CDR.d.ts} +1 -1
  34. package/dist/{skill-DhfSizKv.d.ts → skill-Bx8jxznf.d.ts} +1 -1
  35. package/dist/storage/index.d.ts +164 -6
  36. package/dist/storage/index.js +273 -1
  37. package/dist/storage/index.js.map +1 -1
  38. package/dist/{system-prompt-BC_8ypCG.d.ts → system-prompt-CG9jU5-5.d.ts} +9 -1
  39. package/dist/{tool-executor-CpuJPYm9.d.ts → tool-executor-CYdZdtno.d.ts} +4 -4
  40. package/dist/types/index.d.ts +15 -15
  41. package/dist/utils/index.d.ts +1 -1
  42. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { n as BridgeTransport, o as BridgeMessage, A as AgentBridge, p as AgentBridgeConfig } from './multi-agent-fmkRHtof.js';
1
+ import { p as BridgeTransport, q as BridgeMessage, A as AgentBridge, r as AgentBridgeConfig } from './multi-agent-BDfkxL5C.js';
2
2
 
3
3
  /**
4
4
  * In-memory pub/sub transport for agent-to-agent messaging.
@@ -1,4 +1,4 @@
1
- import { a0 as Context } from './context-BmM2xGUZ.js';
1
+ import { a0 as Context } from './context-u0bryklF.js';
2
2
 
3
3
  interface CompactReport {
4
4
  before: number;
@@ -1,5 +1,5 @@
1
1
  import { W as WireFamily } from './models-registry-Y2xbog0E.js';
2
- import { P as Permission } from './context-BmM2xGUZ.js';
2
+ import { P as Permission } from './context-u0bryklF.js';
3
3
 
4
4
  interface ContextConfig {
5
5
  warnThreshold: number;
@@ -659,6 +659,14 @@ interface SessionStore {
659
659
  }
660
660
  interface SessionWriter {
661
661
  readonly id: string;
662
+ /**
663
+ * Absolute path to the JSONL file this writer appends to, when one
664
+ * exists. In-memory writers (tests, ephemeral sessions) leave it
665
+ * undefined. Observability surfaces (`/fleet log`, FleetPanel) use
666
+ * this to tell the user *where* the transcript lives without
667
+ * having to recompute the path from session metadata.
668
+ */
669
+ readonly transcriptPath?: string;
662
670
  append(event: SessionEvent): Promise<void>;
663
671
  close(): Promise<void>;
664
672
  }
@@ -1,15 +1,15 @@
1
- import { M as MultiAgentConfig, k as SubagentRunner, g as SubagentConfig, m as TaskSpec, l as TaskResult, d as CoordinatorStatus, e as MultiAgentCoordinator, f as SpawnResult, o as BridgeMessage, A as AgentBridge } from '../multi-agent-fmkRHtof.js';
2
- export { B as BudgetExceededError, a as BudgetKind, b as BudgetLimits, c as BudgetUsage, S as SubagentBudget } from '../multi-agent-fmkRHtof.js';
3
- import { u as Tool, q as SessionWriter, o as SessionStore } from '../context-BmM2xGUZ.js';
4
- import { I as InMemoryAgentBridge } from '../agent-bridge-6KPqsFx6.js';
5
- export { a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-6KPqsFx6.js';
6
- import { E as EventBus } from '../events-BMNaEFZl.js';
1
+ import { M as MultiAgentConfig, m as SubagentRunner, g as SubagentConfig, o as TaskSpec, n as TaskResult, d as CoordinatorStatus, e as MultiAgentCoordinator, f as SpawnResult, q as BridgeMessage, A as AgentBridge } from '../multi-agent-BDfkxL5C.js';
2
+ export { B as BudgetExceededError, a as BudgetKind, b as BudgetLimits, c as BudgetUsage, S as SubagentBudget } from '../multi-agent-BDfkxL5C.js';
3
+ import { q as SessionWriter, u as Tool, o as SessionStore } from '../context-u0bryklF.js';
4
+ import { I as InMemoryAgentBridge } from '../agent-bridge-DmBiCipY.js';
5
+ export { a as InMemoryBridgeTransport, c as createMessage } from '../agent-bridge-DmBiCipY.js';
6
+ import { E as EventBus } from '../events-B6Q03pTu.js';
7
7
  import { EventEmitter } from 'node:events';
8
- import { A as Agent, n as AgentInput } from '../plugin-DJk6LL8B.js';
8
+ import { A as Agent, n as AgentInput } from '../plugin-CoYYZKdn.js';
9
9
  import '../observability-BhnVLBLS.js';
10
- import '../renderer-rk_1Swwc.js';
11
- import '../secret-scrubber-CicHLN4G.js';
12
- import '../config-BU9f_5yH.js';
10
+ import '../renderer-0A2ZEtca.js';
11
+ import '../secret-scrubber-3TLUkiCV.js';
12
+ import '../config-DXrqb41m.js';
13
13
  import '../models-registry-Y2xbog0E.js';
14
14
  import '../logger-BMQgxvdy.js';
15
15
 
@@ -202,6 +202,29 @@ interface DirectorOptions {
202
202
  * `maxSpawnDepth` this bounds the chain.
203
203
  */
204
204
  spawnDepth?: number;
205
+ /**
206
+ * Absolute path to a director-state checkpoint file. When set, the
207
+ * director writes an incremental snapshot of pending/running/completed
208
+ * tasks + spawned subagents on every state mutation. Distinct from
209
+ * `manifestPath`: the manifest is a final record written on shutdown,
210
+ * the checkpoint is a live mirror useful for crash recovery and the
211
+ * `wstack resume` "you had N tasks in flight" banner.
212
+ */
213
+ stateCheckpointPath?: string;
214
+ /**
215
+ * Session writer the director should forward task lifecycle events to
216
+ * (`agent_spawned`, `task_created`, `task_completed`, `task_failed`).
217
+ * When omitted these events stay in-memory only — useful for tests but
218
+ * lossy in production. Production callers (the CLI) pass the same
219
+ * writer the host Agent uses so all events land in a single JSONL.
220
+ */
221
+ sessionWriter?: SessionWriter;
222
+ /**
223
+ * Debounce window for periodic manifest writes triggered by spawn/
224
+ * assign/complete events. Default: 2000ms. Pass 0 to disable periodic
225
+ * writes (the manifest will then only be written on `shutdown()`).
226
+ */
227
+ manifestDebounceMs?: number;
205
228
  }
206
229
  /**
207
230
  * Thrown by `Director.spawn()` when a configured spawn cap (`maxSpawns`,
@@ -262,7 +285,34 @@ declare class Director {
262
285
  readonly spawnDepth: number;
263
286
  /** Live spawn counter for `maxSpawns` enforcement. */
264
287
  private spawnCount;
288
+ /** Optional checkpoint mirror — writes the live task graph + roster to disk. */
289
+ private readonly stateCheckpoint;
290
+ /** Optional session writer for emitting task_* / agent_* lifecycle events. */
291
+ private readonly sessionWriter;
292
+ /** Debounce timer for periodic manifest writes. */
293
+ private manifestTimer;
294
+ private readonly manifestDebounceMs;
295
+ /** Resolves task descriptions back from `assign()` so completion events
296
+ * can also carry a human-readable title. */
297
+ private readonly taskDescriptions;
298
+ /** Snapshot of which subagent owns each task — drives state-checkpoint
299
+ * status updates without re-walking the manifest. */
300
+ private readonly taskOwners;
301
+ /**
302
+ * Handle to the coordinator-side `task.completed` listener so we can
303
+ * unsubscribe in `shutdown()`. Without this, repeated Director
304
+ * construction (e.g. tests, hot reloads) accumulates listeners on a
305
+ * cached coordinator and slowly drifts the EventEmitter past its
306
+ * default cap.
307
+ */
308
+ private taskCompletedListener;
265
309
  constructor(opts: DirectorOptions);
310
+ /** Best-effort session-writer append. Swallows failures — the director
311
+ * must not break a fleet run because the session JSONL handle closed. */
312
+ private appendSessionEvent;
313
+ /** Debounced manifest writer. A burst of spawn/assign/complete events
314
+ * collapses into one write. Set `manifestDebounceMs` to 0 to disable. */
315
+ private scheduleManifest;
266
316
  /**
267
317
  * Spawn a subagent. Identical to the coordinator's `spawn()` but
268
318
  * captures provider/model metadata for the usage aggregator and
@@ -317,6 +367,16 @@ declare class Director {
317
367
  * — calling shutdown twice is a no-op on the second invocation.
318
368
  */
319
369
  shutdown(): Promise<void>;
370
+ /**
371
+ * Funnel for shutdown-phase errors. We can't throw — `shutdown()` is
372
+ * called from process-exit paths where an uncaught throw would lose
373
+ * the manifest write that comes after. But we MUST NOT silently
374
+ * swallow either — a persistent bridge-close failure would otherwise
375
+ * mask a real bug. `process.emitWarning` is the right tier:
376
+ * surfaces on stderr by default, lets the host plug a warning
377
+ * listener for structured collection, and never affects exit code.
378
+ */
379
+ private logShutdownError;
320
380
  /**
321
381
  * Hand a task to the coordinator. Returns the assigned task id so
322
382
  * callers can wait on it via `awaitTasks([id])`. The coordinator's
@@ -353,6 +413,18 @@ declare class Director {
353
413
  */
354
414
  completedResults(): TaskResult[];
355
415
  snapshot(): FleetUsage;
416
+ /**
417
+ * Look up provider/model metadata for a spawned subagent. Returns
418
+ * undefined when the subagent id is unknown (not yet spawned, or
419
+ * already torn down). Callers — notably the TUI fleet panel — use
420
+ * this to render human-readable provider/model tags next to each
421
+ * subagent row without reaching into private state.
422
+ */
423
+ getSubagentMeta(id: string): {
424
+ provider?: string;
425
+ model?: string;
426
+ name?: string;
427
+ } | undefined;
356
428
  /**
357
429
  * Compose the leader/director-agent system prompt: fleet preamble +
358
430
  * (optional) roster summary + user base prompt. Pass the result to your
@@ -391,6 +463,78 @@ declare class Director {
391
463
  tools(roster?: Record<string, SubagentConfig>): Tool[];
392
464
  }
393
465
 
466
+ /**
467
+ * Opaque host interface so this factory doesn't have to depend on the
468
+ * CLI's `MultiAgentHost`. Any caller that exposes the same three
469
+ * methods can wire `delegate` — including test doubles.
470
+ */
471
+ interface DelegateHost {
472
+ /** True if a Director is already attached and running. */
473
+ isDirectorMode(): boolean;
474
+ /** Build (or return the cached) Director when director mode is on. */
475
+ ensureDirector(): Promise<Director | null>;
476
+ /**
477
+ * Force-promote a non-director session into director mode at runtime.
478
+ * Returns the Director, or null when promotion is impossible (e.g. a
479
+ * non-director coordinator has already spawned subagents in the
480
+ * legacy code path).
481
+ */
482
+ promoteToDirector(): Promise<Director | null>;
483
+ /**
484
+ * Optional: when promotion fails, return the human-readable reason.
485
+ * Used to render an actionable error to the calling model instead of
486
+ * the prior opaque "Director could not be activated" message.
487
+ * Implementations may return null when they don't track the reason.
488
+ */
489
+ getPromotionBlockReason?(): string | null;
490
+ }
491
+ interface CreateDelegateToolOptions {
492
+ host: DelegateHost;
493
+ /**
494
+ * Roster used to resolve `role` strings into full `SubagentConfig`s.
495
+ * Typically `FLEET_ROSTER`. When omitted, `delegate({ role })` calls
496
+ * fail and only the explicit `name + provider + model` path works.
497
+ */
498
+ roster?: Record<string, SubagentConfig>;
499
+ /**
500
+ * Default await timeout in milliseconds. `delegate` blocks until the
501
+ * subagent's task resolves; without a cap, a stuck worker would hang
502
+ * the host indefinitely. Set generously (default: 4 hours) so the
503
+ * orchestrator can run multi-step refactors / monorepo audits
504
+ * without being killed for being slow — the orchestrator must
505
+ * decide per-call when a task needs to be cut short.
506
+ */
507
+ defaultTimeoutMs?: number;
508
+ /**
509
+ * Absolute directory under which per-subagent JSONL transcripts live —
510
+ * matches `MultiAgentHostOptions.sessionsRoot`. When set, the delegate
511
+ * tool reads the subagent's transcript on timeout / budget-exhaustion
512
+ * to extract partial output, so the host LLM gets *something* useful
513
+ * back instead of just an error.
514
+ */
515
+ sessionsRoot?: string;
516
+ /**
517
+ * The directorRunId used to namespace transcripts (typically the host
518
+ * session id). Combined with `sessionsRoot` to locate per-subagent
519
+ * JSONLs at `<sessionsRoot>/<runId>/<subagentId>.jsonl`.
520
+ */
521
+ directorRunId?: string;
522
+ }
523
+ /**
524
+ * `delegate` — the only multi-agent tool a regular (non-director) agent
525
+ * ever needs. It bundles spawn + assign + await into a single call and
526
+ * transparently auto-promotes the host into director mode on first use.
527
+ *
528
+ * The model never has to ask "are we in director mode?" — it just calls
529
+ * `delegate({ role, task })` and gets back a `TaskResult`. The cost of
530
+ * that ergonomic packaging is that `delegate` cannot be used for
531
+ * parallel work as-is; the model must fire multiple `delegate` calls in
532
+ * parallel through the provider's parallel-tool-call surface, or escalate
533
+ * to the explicit `spawn_subagent` + `assign_task` + `await_tasks` flow
534
+ * when it wants fan-out it controls itself.
535
+ */
536
+ declare function createDelegateTool(opts: CreateDelegateToolOptions): Tool;
537
+
394
538
  interface MultiAgentCoordinatorOptions {
395
539
  /**
396
540
  * Callback that executes a task on behalf of a subagent. Required for
@@ -403,13 +547,28 @@ interface MultiAgentCoordinatorOptions {
403
547
  declare class DefaultMultiAgentCoordinator extends EventEmitter implements MultiAgentCoordinator {
404
548
  readonly coordinatorId: string;
405
549
  readonly config: MultiAgentConfig;
406
- private readonly runner?;
550
+ private runner?;
407
551
  private readonly subagents;
408
552
  private pendingTasks;
409
553
  private completedResults;
410
554
  private totalIterations;
411
555
  private inFlight;
556
+ /**
557
+ * Subagents currently being stopped. Set on entry to `stop()`, cleared
558
+ * once `recordCompletion` lands the terminal TaskResult. Used by
559
+ * `runDispatched` and `findIdleSubagent` to refuse mid-flight dispatch
560
+ * to a subagent the caller has already asked to terminate — closes the
561
+ * assign+terminate race where a fresh task could land on a worker that
562
+ * was about to be killed.
563
+ */
564
+ private readonly terminating;
412
565
  constructor(config: MultiAgentConfig, options?: MultiAgentCoordinatorOptions);
566
+ /**
567
+ * Replace the runner after construction. Used when the runner depends
568
+ * on infrastructure (e.g. FleetBus) that isn't available until after
569
+ * the coordinator's owning Director is built.
570
+ */
571
+ setRunner(runner: SubagentRunner): void;
413
572
  spawn(subagent: SubagentConfig): Promise<SpawnResult>;
414
573
  assign(task: TaskSpec): Promise<void>;
415
574
  delegate(to: string, msg: BridgeMessage): Promise<void>;
@@ -432,6 +591,28 @@ declare class DefaultMultiAgentCoordinator extends EventEmitter implements Multi
432
591
  private tryDispatchNext;
433
592
  private canDispatch;
434
593
  private findIdleSubagent;
594
+ /**
595
+ * Returns true iff at least one spawned subagent could still
596
+ * process a task. A "live" subagent is one that is not stopped
597
+ * AND not mid-termination — `running` workers count because they
598
+ * will eventually finish and become idle.
599
+ *
600
+ * When no subagent has ever been spawned, returns `true` so a
601
+ * pre-spawn `assign()` simply queues (legacy behaviour). The
602
+ * dead-end detection only fires after `stop()` has retired every
603
+ * spawned worker.
604
+ *
605
+ * Used by `tryDispatchNext` to detect a dead-end pending queue.
606
+ */
607
+ private hasLiveSubagent;
608
+ /**
609
+ * Drain every pending task with a synthetic `aborted_by_parent`
610
+ * completion event. Same shape as the `stopAll()` drain — we go
611
+ * around `recordCompletion` because pending tasks were never
612
+ * counted in `inFlight` and routing them through would trip the
613
+ * underflow guard on every task after the first.
614
+ */
615
+ private drainPendingAsAborted;
435
616
  private runDispatched;
436
617
  private executeWithTimeout;
437
618
  private recordCompletion;
@@ -450,6 +631,16 @@ interface AgentFactoryResult {
450
631
  agent: Agent;
451
632
  /** Event bus the factory wired to this agent — required for budget hookup. */
452
633
  events: EventBus;
634
+ /**
635
+ * Optional cleanup hook invoked in the runner's `finally` block once
636
+ * the task ends (success, failure, abort — same exit path). Factories
637
+ * that own resources scoped to a single task (per-subagent JSONL
638
+ * writers, transient providers, throwaway containers) implement this
639
+ * to close them deterministically instead of relying on GC. Errors
640
+ * thrown here are swallowed so a flaky cleanup can't mask the task's
641
+ * real result.
642
+ */
643
+ dispose?: () => Promise<void> | void;
453
644
  }
454
645
  interface AgentRunnerOptions {
455
646
  factory: AgentFactory;
@@ -459,6 +650,13 @@ interface AgentRunnerOptions {
459
650
  * input (e.g. JSON contracts, role-prefixed prompts).
460
651
  */
461
652
  formatTaskInput?: (task: TaskSpec, config: SubagentConfig) => AgentInput;
653
+ /**
654
+ * When set, the runner attaches the subagent's EventBus to this FleetBus
655
+ * on task start and detaches it when the task finishes. This is the
656
+ * injection seam that lets the TUI fleet panel observe subagent activity
657
+ * live — without it, FleetBus stays empty.
658
+ */
659
+ fleetBus?: FleetBus;
462
660
  }
463
661
  /**
464
662
  * Builds a `SubagentRunner` that drives a real `Agent` per task while honoring
@@ -691,4 +889,4 @@ declare const FLEET_ROSTER: Record<string, SubagentConfig>;
691
889
  /** Quick-access list for spawning all at once. */
692
890
  declare const ALL_FLEET_AGENTS: SubagentConfig[];
693
891
 
694
- export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, type AgentFactory, type AgentFactoryResult, type AgentRunnerOptions, BUG_HUNTER_AGENT, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, Director, DirectorBudgetError, type DirectorPromptParts, type DirectorSessionFactory, type DirectorSessionFactoryOptions, FLEET_ROSTER, FleetBus, type FleetEvent, type FleetHandler, type FleetUsage, FleetUsageAggregator, InMemoryAgentBridge, type MultiAgentCoordinatorOptions, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, type SubagentPromptParts, type SubagentUsageSnapshot, composeDirectorPrompt, composeSubagentPrompt, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs };
892
+ export { ALL_FLEET_AGENTS, AUDIT_LOG_AGENT, type AgentFactory, type AgentFactoryResult, type AgentRunnerOptions, BUG_HUNTER_AGENT, type CreateDelegateToolOptions, DEFAULT_DIRECTOR_PREAMBLE, DEFAULT_SUBAGENT_BASELINE, DefaultMultiAgentCoordinator, type DelegateHost, Director, DirectorBudgetError, type DirectorPromptParts, type DirectorSessionFactory, type DirectorSessionFactoryOptions, FLEET_ROSTER, FleetBus, type FleetEvent, type FleetHandler, type FleetUsage, FleetUsageAggregator, InMemoryAgentBridge, type MultiAgentCoordinatorOptions, REFACTOR_PLANNER_AGENT, SECURITY_SCANNER_AGENT, type SubagentPromptParts, type SubagentUsageSnapshot, composeDirectorPrompt, composeSubagentPrompt, createDelegateTool, makeAgentSubagentRunner, makeDirectorSessionFactory, rosterSummaryFromConfigs };