@os-eco/overstory-cli 0.6.10 → 0.7.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 (66) hide show
  1. package/README.md +156 -274
  2. package/agents/lead.md +29 -19
  3. package/package.json +5 -3
  4. package/src/agents/hooks-deployer.test.ts +53 -0
  5. package/src/agents/hooks-deployer.ts +4 -4
  6. package/src/agents/manifest.test.ts +1 -0
  7. package/src/agents/overlay.test.ts +102 -0
  8. package/src/agents/overlay.ts +45 -6
  9. package/src/commands/completions.ts +3 -3
  10. package/src/commands/coordinator.ts +25 -13
  11. package/src/commands/costs.test.ts +1 -1
  12. package/src/commands/costs.ts +13 -20
  13. package/src/commands/dashboard.ts +38 -138
  14. package/src/commands/doctor.test.ts +1 -1
  15. package/src/commands/doctor.ts +2 -2
  16. package/src/commands/ecosystem.ts +2 -1
  17. package/src/commands/errors.test.ts +4 -5
  18. package/src/commands/errors.ts +4 -62
  19. package/src/commands/feed.test.ts +2 -2
  20. package/src/commands/feed.ts +12 -106
  21. package/src/commands/group.ts +4 -4
  22. package/src/commands/inspect.ts +10 -44
  23. package/src/commands/logs.ts +7 -63
  24. package/src/commands/mail.test.ts +63 -1
  25. package/src/commands/mail.ts +18 -1
  26. package/src/commands/merge.ts +2 -2
  27. package/src/commands/metrics.test.ts +2 -2
  28. package/src/commands/metrics.ts +3 -17
  29. package/src/commands/monitor.ts +19 -9
  30. package/src/commands/replay.test.ts +2 -2
  31. package/src/commands/replay.ts +12 -135
  32. package/src/commands/run.ts +7 -23
  33. package/src/commands/sling.test.ts +227 -27
  34. package/src/commands/sling.ts +120 -21
  35. package/src/commands/status.ts +5 -18
  36. package/src/commands/supervisor.ts +22 -12
  37. package/src/commands/trace.test.ts +5 -6
  38. package/src/commands/trace.ts +13 -111
  39. package/src/config.test.ts +22 -0
  40. package/src/config.ts +22 -0
  41. package/src/doctor/agents.test.ts +1 -0
  42. package/src/doctor/config-check.test.ts +1 -0
  43. package/src/doctor/consistency.test.ts +1 -0
  44. package/src/doctor/databases.test.ts +1 -0
  45. package/src/doctor/dependencies.test.ts +1 -0
  46. package/src/doctor/ecosystem.test.ts +1 -0
  47. package/src/doctor/logs.test.ts +1 -0
  48. package/src/doctor/merge-queue.test.ts +1 -0
  49. package/src/doctor/structure.test.ts +1 -0
  50. package/src/doctor/version.test.ts +1 -0
  51. package/src/index.ts +8 -4
  52. package/src/logging/format.ts +214 -0
  53. package/src/logging/theme.ts +132 -0
  54. package/src/metrics/store.test.ts +46 -0
  55. package/src/metrics/store.ts +11 -0
  56. package/src/mulch/client.test.ts +20 -0
  57. package/src/mulch/client.ts +312 -45
  58. package/src/runtimes/claude.test.ts +616 -0
  59. package/src/runtimes/claude.ts +218 -0
  60. package/src/runtimes/registry.test.ts +53 -0
  61. package/src/runtimes/registry.ts +33 -0
  62. package/src/runtimes/types.ts +125 -0
  63. package/src/types.ts +15 -0
  64. package/src/worktree/tmux.test.ts +28 -13
  65. package/src/worktree/tmux.ts +14 -28
  66. package/templates/overlay.md.tmpl +3 -1
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { dirname, resolve } from "node:path";
11
11
  import { AgentError } from "../errors.ts";
12
+ import type { ReadyState } from "../runtimes/types.ts";
12
13
 
13
14
  /**
14
15
  * Detect the directory containing the overstory binary.
@@ -435,58 +436,43 @@ export async function capturePaneContent(name: string, lines = 50): Promise<stri
435
436
  /**
436
437
  * Wait for a tmux session's TUI to become ready for input.
437
438
  *
438
- * Uses a two-phase readiness check:
439
- * 1. Phase 1 prompt indicator: detects or 'Try "' confirming Claude Code has started
440
- * 2. Phase 2 status bar: detects 'bypass permissions' or 'shift+tab' confirming full TUI render
441
- * Returns true only when BOTH phases have been observed.
442
- *
443
- * Additionally handles the workspace trust dialog: if 'trust this folder' is detected,
444
- * sends Enter to auto-confirm before continuing to wait for the real TUI. The trust
445
- * dialog check must precede phase checks since it replaces the normal TUI temporarily.
439
+ * Delegates all readiness detection to the provided `detectReady` callback,
440
+ * making this function runtime-agnostic. The callback inspects pane content
441
+ * and returns a ReadyState phase: "loading" (keep waiting), "dialog" (send
442
+ * Enter to dismiss, then continue), or "ready" (return true).
446
443
  *
447
444
  * @param name - Tmux session name to poll
445
+ * @param detectReady - Callback that inspects pane content and returns ReadyState
448
446
  * @param timeoutMs - Maximum time to wait before giving up (default 30s)
449
447
  * @param pollIntervalMs - Time between polls (default 500ms)
450
- * @returns true once both prompt indicator AND status bar text detected, false on timeout
448
+ * @returns true once detectReady returns { phase: "ready" }, false on timeout or dead session
451
449
  */
452
450
  export async function waitForTuiReady(
453
451
  name: string,
452
+ detectReady: (paneContent: string) => ReadyState,
454
453
  timeoutMs = 30_000,
455
454
  pollIntervalMs = 500,
456
455
  ): Promise<boolean> {
457
456
  const maxAttempts = Math.ceil(timeoutMs / pollIntervalMs);
458
- let promptSeen = false;
459
- let statusBarSeen = false;
460
- let trustHandled = false;
457
+ let dialogHandled = false;
461
458
 
462
459
  for (let i = 0; i < maxAttempts; i++) {
463
460
  const content = await capturePaneContent(name);
464
461
  if (content !== null) {
465
- // Trust dialog detection — must come before phase checks since it replaces normal TUI
466
- if (!trustHandled && content.includes("trust this folder")) {
462
+ const state = detectReady(content);
463
+
464
+ if (state.phase === "dialog" && !dialogHandled) {
467
465
  await sendKeys(name, "");
468
- trustHandled = true;
466
+ dialogHandled = true;
469
467
  await Bun.sleep(pollIntervalMs);
470
468
  continue;
471
469
  }
472
470
 
473
- // Phase 1: prompt indicator confirms Claude Code has started
474
- if (content.includes("\u276f") || content.includes('Try "')) {
475
- promptSeen = true;
476
- }
477
-
478
- // Phase 2: status bar text confirms full TUI render
479
- if (content.includes("bypass permissions") || content.includes("shift+tab")) {
480
- statusBarSeen = true;
481
- }
482
-
483
- // Return true only when both phases complete
484
- if (promptSeen && statusBarSeen) {
471
+ if (state.phase === "ready") {
485
472
  return true;
486
473
  }
487
474
  }
488
475
 
489
- // Check if session died — no point waiting if it's gone
490
476
  const alive = await isSessionAlive(name);
491
477
  if (!alive) {
492
478
  return false;
@@ -10,7 +10,7 @@
10
10
  ## Your Assignment
11
11
 
12
12
  - **Agent Name:** {{AGENT_NAME}}
13
- - **Task ID:** {{BEAD_ID}}
13
+ - **Task ID:** {{TASK_ID}}
14
14
  - **Spec:** {{SPEC_PATH}}
15
15
  - **Branch:** {{BRANCH_NAME}}
16
16
  - **Worktree:** {{WORKTREE_PATH}}
@@ -21,6 +21,8 @@
21
21
 
22
22
  {{SKIP_SCOUT}}
23
23
 
24
+ {{DISPATCH_OVERRIDES}}
25
+
24
26
  ## Working Directory
25
27
 
26
28
  Your worktree root is: `{{WORKTREE_PATH}}`