agent-tempo 1.7.0-beta.9 → 2.0.0-beta.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 (171) hide show
  1. package/CLAUDE.md +27 -14
  2. package/README.md +23 -16
  3. package/dashboard/dist/assets/index-BbR7zIdK.js.map +1 -1
  4. package/dashboard/package.json +1 -1
  5. package/dist/activities/hard-terminate.d.ts +2 -2
  6. package/dist/activities/hard-terminate.js +3 -9
  7. package/dist/activities/maestro.d.ts +8 -13
  8. package/dist/activities/maestro.js +0 -10
  9. package/dist/activities/outbox.js +14 -2
  10. package/dist/activities/resolve.d.ts +83 -18
  11. package/dist/activities/resolve.js +139 -26
  12. package/dist/adapters/base.js +3 -0
  13. package/dist/cli/command-center-command.js +25 -2
  14. package/dist/cli/commands.d.ts +36 -0
  15. package/dist/cli/commands.js +167 -28
  16. package/dist/cli/daemon-command.js +19 -33
  17. package/dist/cli/help-text.js +7 -7
  18. package/dist/cli/home-command.d.ts +26 -0
  19. package/dist/cli/home-command.js +156 -0
  20. package/dist/cli/mcp.d.ts +26 -2
  21. package/dist/cli/mcp.js +33 -4
  22. package/dist/cli/removed-verbs.d.ts +0 -4
  23. package/dist/cli/removed-verbs.js +23 -12
  24. package/dist/cli/sa-preflight.d.ts +0 -14
  25. package/dist/cli/sa-preflight.js +1 -17
  26. package/dist/cli/startup.d.ts +1 -10
  27. package/dist/cli/startup.js +8 -42
  28. package/dist/cli.js +51 -85
  29. package/dist/client/core.js +13 -15
  30. package/dist/client/index.d.ts +2 -1
  31. package/dist/client/interface.d.ts +5 -14
  32. package/dist/client/subscribe.d.ts +10 -0
  33. package/dist/client/subscribe.js +2 -0
  34. package/dist/client/with-spawn.d.ts +9 -4
  35. package/dist/client/with-spawn.js +7 -10
  36. package/dist/config.d.ts +0 -13
  37. package/dist/constants.d.ts +22 -0
  38. package/dist/constants.js +23 -1
  39. package/dist/daemon.d.ts +44 -7
  40. package/dist/daemon.js +106 -8
  41. package/dist/http/auth.d.ts +3 -21
  42. package/dist/http/auth.js +10 -31
  43. package/dist/http/deliverability.d.ts +68 -0
  44. package/dist/http/deliverability.js +78 -0
  45. package/dist/http/event-types.d.ts +5 -4
  46. package/dist/http/orphans.d.ts +3 -3
  47. package/dist/http/orphans.js +3 -3
  48. package/dist/http/qa.js +8 -1
  49. package/dist/http/server.d.ts +0 -5
  50. package/dist/http/server.js +69 -29
  51. package/dist/http/writes.d.ts +1 -1
  52. package/dist/http/writes.js +49 -4
  53. package/dist/palette/index.d.ts +6 -7
  54. package/dist/palette/index.js +6 -7
  55. package/dist/pi/install.d.ts +15 -0
  56. package/dist/pi/install.js +35 -0
  57. package/dist/pi/mission-control/actions.d.ts +97 -3
  58. package/dist/pi/mission-control/actions.js +153 -3
  59. package/dist/pi/mission-control/board.d.ts +84 -0
  60. package/dist/pi/mission-control/board.js +62 -1
  61. package/dist/pi/mission-control/extension.d.ts +199 -1
  62. package/dist/pi/mission-control/extension.js +503 -13
  63. package/dist/pi/mission-control/render.d.ts +25 -0
  64. package/dist/pi/mission-control/render.js +131 -12
  65. package/dist/pi/workflow-client.d.ts +14 -16
  66. package/dist/pi/workflow-client.js +18 -44
  67. package/dist/spawn.d.ts +43 -26
  68. package/dist/spawn.js +64 -37
  69. package/dist/tools/cue.js +12 -0
  70. package/dist/tools/ensemble.js +33 -2
  71. package/dist/tools/recruit.js +8 -26
  72. package/dist/types.d.ts +15 -6
  73. package/dist/upgrade/boot-guard.d.ts +95 -0
  74. package/dist/upgrade/boot-guard.js +88 -0
  75. package/dist/upgrade/from-upgrade.d.ts +95 -0
  76. package/dist/upgrade/from-upgrade.js +330 -0
  77. package/dist/upgrade/phase-engine.js +4 -1
  78. package/dist/utils/duration.d.ts +3 -6
  79. package/dist/utils/duration.js +3 -6
  80. package/dist/utils/format-hosts.d.ts +1 -1
  81. package/dist/utils/format-hosts.js +0 -2
  82. package/dist/utils/grpc-shutdown-guard.js +0 -4
  83. package/dist/utils/hosts.d.ts +4 -10
  84. package/dist/utils/hosts.js +12 -28
  85. package/dist/utils/sdk-probe.d.ts +12 -0
  86. package/dist/utils/sdk-probe.js +28 -0
  87. package/dist/utils/search-attributes.d.ts +27 -18
  88. package/dist/utils/search-attributes.js +39 -18
  89. package/dist/utils/visibility-deadline.d.ts +16 -0
  90. package/dist/utils/visibility-deadline.js +16 -0
  91. package/dist/workflows/maestro-signals.d.ts +0 -13
  92. package/dist/workflows/maestro-signals.js +6 -14
  93. package/dist/workflows/maestro.js +27 -32
  94. package/dist/workflows/scheduler.js +7 -1
  95. package/dist/workflows/session.js +44 -110
  96. package/dist/workflows/signals.d.ts +9 -1
  97. package/dist/workflows/signals.js +8 -6
  98. package/package.json +8 -9
  99. package/workflow-bundle.js +239 -182
  100. package/dist/cli/legacy-migration.d.ts +0 -35
  101. package/dist/cli/legacy-migration.js +0 -341
  102. package/dist/client/ensure-conductor-spawned.d.ts +0 -35
  103. package/dist/client/ensure-conductor-spawned.js +0 -48
  104. package/dist/tui/App.d.ts +0 -85
  105. package/dist/tui/App.js +0 -1791
  106. package/dist/tui/bootstrap-types.d.ts +0 -46
  107. package/dist/tui/bootstrap-types.js +0 -7
  108. package/dist/tui/commands.d.ts +0 -71
  109. package/dist/tui/commands.js +0 -1375
  110. package/dist/tui/components/ChatView.d.ts +0 -35
  111. package/dist/tui/components/ChatView.js +0 -54
  112. package/dist/tui/components/CommandPalette.d.ts +0 -21
  113. package/dist/tui/components/CommandPalette.js +0 -67
  114. package/dist/tui/components/ConversationStream.d.ts +0 -114
  115. package/dist/tui/components/ConversationStream.js +0 -307
  116. package/dist/tui/components/CreateEnsembleWizard.d.ts +0 -19
  117. package/dist/tui/components/CreateEnsembleWizard.js +0 -223
  118. package/dist/tui/components/DestroyConfirmModal.d.ts +0 -17
  119. package/dist/tui/components/DestroyConfirmModal.js +0 -62
  120. package/dist/tui/components/ErrorView.d.ts +0 -31
  121. package/dist/tui/components/ErrorView.js +0 -129
  122. package/dist/tui/components/HomeView.d.ts +0 -54
  123. package/dist/tui/components/HomeView.js +0 -306
  124. package/dist/tui/components/LoadLineupModal.d.ts +0 -18
  125. package/dist/tui/components/LoadLineupModal.js +0 -79
  126. package/dist/tui/components/MainView.d.ts +0 -21
  127. package/dist/tui/components/MainView.js +0 -107
  128. package/dist/tui/components/NewEnsembleModal.d.ts +0 -9
  129. package/dist/tui/components/NewEnsembleModal.js +0 -73
  130. package/dist/tui/components/Picker.d.ts +0 -23
  131. package/dist/tui/components/Picker.js +0 -70
  132. package/dist/tui/components/PlayerDetailView.d.ts +0 -26
  133. package/dist/tui/components/PlayerDetailView.js +0 -118
  134. package/dist/tui/components/PromptArea.d.ts +0 -50
  135. package/dist/tui/components/PromptArea.js +0 -303
  136. package/dist/tui/components/RecruitWizard.d.ts +0 -17
  137. package/dist/tui/components/RecruitWizard.js +0 -221
  138. package/dist/tui/components/RestoreConfirmModal.d.ts +0 -18
  139. package/dist/tui/components/RestoreConfirmModal.js +0 -71
  140. package/dist/tui/components/ScheduleWizard.d.ts +0 -19
  141. package/dist/tui/components/ScheduleWizard.js +0 -259
  142. package/dist/tui/components/Splash.d.ts +0 -23
  143. package/dist/tui/components/Splash.js +0 -221
  144. package/dist/tui/components/StatusBar.d.ts +0 -48
  145. package/dist/tui/components/StatusBar.js +0 -128
  146. package/dist/tui/components/StatusOverlay.d.ts +0 -15
  147. package/dist/tui/components/StatusOverlay.js +0 -76
  148. package/dist/tui/components/TitleBar.d.ts +0 -10
  149. package/dist/tui/components/TitleBar.js +0 -21
  150. package/dist/tui/index.d.ts +0 -15
  151. package/dist/tui/index.js +0 -162
  152. package/dist/tui/ink-context.d.ts +0 -18
  153. package/dist/tui/ink-context.js +0 -59
  154. package/dist/tui/ink-loader.d.ts +0 -26
  155. package/dist/tui/ink-loader.js +0 -42
  156. package/dist/tui/removed-commands.d.ts +0 -9
  157. package/dist/tui/removed-commands.js +0 -22
  158. package/dist/tui/sse-handler.d.ts +0 -52
  159. package/dist/tui/sse-handler.js +0 -157
  160. package/dist/tui/store.d.ts +0 -598
  161. package/dist/tui/store.js +0 -753
  162. package/dist/tui/utils/format.d.ts +0 -56
  163. package/dist/tui/utils/format.js +0 -155
  164. package/dist/tui/utils/fullscreen.d.ts +0 -23
  165. package/dist/tui/utils/fullscreen.js +0 -71
  166. package/dist/tui/utils/history.d.ts +0 -10
  167. package/dist/tui/utils/history.js +0 -85
  168. package/dist/tui/utils/platform.d.ts +0 -45
  169. package/dist/tui/utils/platform.js +0 -258
  170. package/dist/tui/utils/theme.d.ts +0 -21
  171. package/dist/tui/utils/theme.js +0 -24
package/CLAUDE.md CHANGED
@@ -88,7 +88,7 @@ src/
88
88
  │ ├── inner-loop-routes.ts # 3 inner-loop HTTP routes: POST /inner/ingest + GET /inner/presence (INGRESS, loopback + X-Ingest-Token, uniform 403); GET /inner (EGRESS operator SSE, requireTier(3))
89
89
  │ ├── doorbell.ts # DoorbellRegistry — in-process Map<"{ensemble}:{playerId}", Set<waiter>>; ring-with-no-listener drops on floor; level-triggered coalescing; never throws (T1.1 PR-1, #776)
90
90
  │ ├── doorbell-routes.ts # GET /doorbell/:ensemble/:playerId SSE route — content-free ding events; loopback + X-Ingest-Token auth (same ingress model as inner-loop); NO event IDs / Last-Event-ID / replay by design; :ka keepalive every 15s (T1.1 PR-1, #776)
91
- │ ├── auth.ts # 3e MD-E RBAC: two-token model (readToken T1 / adminToken T1+T2+T3 env-var-only); loadRbacTokens; requireTier(tier, input) → TierGuardResult; tierForToken; loadReadToken (env>config>legacy httpToken>auto-gen); loadAdminToken (env-only); TLS/legacy startup warnings in startHttpServer
91
+ │ ├── auth.ts # 3e MD-E RBAC: two-token model (readToken T1 / adminToken T1+T2+T3 env-var-only); loadRbacTokens; requireTier(tier, input) → TierGuardResult; tierForToken; loadReadToken (env>config>auto-gen); loadAdminToken (env-only); TLS startup warning in startHttpServer
92
92
  │ ├── cors.ts / responses.ts / event-id.ts / port-file.ts / index.ts
93
93
  ├── reconcile/
94
94
  │ └── orphans.ts # Shared orphan-query helper (daemon reconcile-on-boot + CLI restore)
@@ -131,11 +131,6 @@ src/
131
131
  │ │ └── index.ts # Barrel — re-exports Controller, BoardModel, renderBoard, MissionControlActions, and public types
132
132
  │ ├── probe.ts / pi-types.ts / index.ts # optional-dep preflight, hand-written ExtensionAPI decls, barrel
133
133
  │ └── README.md # Pi integration findings (abrupt-death/MD-A, D12a, Phase 2 singleton/teardown) + carry-items
134
- ├── tui/
135
- │ ├── App.tsx / store.ts / commands.ts # TUI root, state, slash commands
136
- │ ├── sse-handler.ts # SSE event → TUI store dispatch mapping (PR-4a of #94/#95)
137
- │ ├── components/ # Ink components — see docs/tui.md for inventory
138
- │ └── utils/ # format, platform, theme, fullscreen, history
139
134
  ├── utils/
140
135
  │ ├── validation.ts / worktree.ts / safe-path.ts / duration.ts / search-attributes.ts
141
136
  │ ├── attachment-format.ts / recall-format.ts # Shared display formatters (attachment-info, recall)
@@ -153,8 +148,10 @@ src/
153
148
  └── config.ts # Env var handling
154
149
  ```
155
150
 
156
- See [docs/tui-performance.md](docs/tui-performance.md) for Ink/React performance notes when
157
- touching `src/tui/`.
151
+ > **The Ink/React terminal UI (`src/tui/`) was deleted in #789.** The interactive
152
+ > operator surface is now the command-center mission-control board
153
+ > (`agent-tempo command-center`, `src/pi/mission-control/`) plus the web dashboard
154
+ > (`dashboard/`). A bare `agent-tempo` runs bootstrap + `status` + hints (no TUI).
158
155
 
159
156
  ## Development
160
157
 
@@ -169,11 +166,27 @@ npm run check:all # runs every CI gate locally (build, tests, drift checks, li
169
166
  > pre-bundles workflows into `workflow-bundle.js` so all workers use identical code.
170
167
 
171
168
  > **Two test directories.** Mocha tests live in `test/` (Temporal workflow integration
172
- > suites, wire-protocol drift detector). Vitest tests live in `tests/` (TUI components,
173
- > TempoClient fallback paths). Both are first-class targets — when doing call-site
169
+ > suites, wire-protocol drift detector). Vitest tests live in `tests/` (pure-logic
170
+ > units client, cli, http, pi, tools, …). Both are first-class targets — when doing call-site
174
171
  > surveys or migrations, always grep **both** `test/` and `tests/` or you will miss
175
172
  > mocks and assertions that only live in one directory.
176
173
 
174
+ > **Windows `**`-glob false-negative (#707) — a zero-match can read as "clean".**
175
+ > On Windows, a ripgrep glob with a **leading directory segment before `**`**
176
+ > silently matches **zero** files: `Grep ... glob="src/**/*.ts"` returns *"No
177
+ > files found"* even when matches exist — a false negative that looks identical
178
+ > to "searched and found nothing." This bites call-site surveys, drift checks,
179
+ > and any "prove a symbol is absent" decision. **Reliable forms** (use these):
180
+ > path-scope instead — `Grep path="src" type="ts"` — or drop the leading dir —
181
+ > `glob="**/*.ts"`; or just `Read` the file when you know the path. A bare
182
+ > recursive `**/*.ext` works; `dir/**/*.ext` is the broken shape.
183
+ > The bug is in the search-tool layer, not this repo — **no repo check shells a
184
+ > `**` glob.** Repo lint/drift/conformance checks enumerate via `fs` recursion
185
+ > or `git ls-files` (never a shelled `**` glob) and now **assert a non-zero file
186
+ > count** (#707) so a future enumeration breakage fails loud instead of passing
187
+ > as "clean." Hold that bar for any new source-scanning check: *a check that
188
+ > scans nothing must never report success.*
189
+
177
190
  > **Test-only hooks live with the module they reset and follow the
178
191
  > `__<verb><Noun>ForTests` naming convention** — see
179
192
  > [docs/adr/0006-test-hooks-naming.md](docs/adr/0006-test-hooks-naming.md). The
@@ -206,15 +219,15 @@ daemon worker notes, `npx ts-node` dev runner).
206
219
  - **Outbox**: Outbound requests (cue, report, recruit, restart, detach, destroy, …) go through the session's workflow outbox instead of directly signaling other workflows. The dispatch loop processes entries via activities, decoupling tools from cross-workflow signaling.
207
220
  - **Attachment phase** (v0.26): Seven phases tracked on the session workflow — `booting → attached → processing | awaiting → draining → detached → gone`. The phase is authoritative for lifecycle truth: adapters drive it via `claimAttachment` / `adapterExited` / `forceDetach` / `destroy`, and the workflow publishes it on the `ClaudeTempoAttachmentState` search attribute. Replaced the v0.25 `ClaudeTempoStatus` heuristic (removed in v0.26). See [docs/concepts.md](docs/concepts.md) for the phase table and [docs/ops/v0.26-migration.md](docs/ops/v0.26-migration.md) for the upgrade path.
208
221
  - **Adapter heartbeat observability** (#249): After `claimAttachment`, the base adapter logs `first heartbeat scheduled in Xms` then `heartbeat#1 delivered` on the first tick. Every 10 ticks it emits `heartbeats-delivered=N / phase-ticks=N` breadcrumbs. Any silent guard trip in `tickHeartbeat` / `tickPhaseWatcher` now emits a structured `guard tripped: {stopped, reconnecting, …}` log instead of silently orphaning the timer. The phase-watcher emits `WARNING: heartbeat staleness` when `lastHeartbeatAt` falls more than 2× `heartbeatMs` behind `now`. Grep `[agent-tempo:adapter]` to confirm loop health without parsing Temporal history.
209
- - **Per-host task queues**: `host` param on `recruit`/`restart`/`migrate` routes to `agent-tempo-{hostname}` task queue. When `host` is set on `recruit`, a pre-flight check validates the target daemon is live and supports the requested agent type (`force: true` bypasses). Daemon boot profiles (hostname, platform, available player types) are advertised via the `hostProfile` signal and maintained in the global maestro's `hostProfiles` map — surfaced by the `hosts` MCP tool, `agent-tempo hosts` CLI, and `/hosts` TUI command (#274). See [docs/concepts.md](docs/concepts.md) for cross-machine recruiting details.
222
+ - **Per-host task queues**: `host` param on `recruit`/`restart`/`migrate` routes to `agent-tempo-{hostname}` task queue. When `host` is set on `recruit`, a pre-flight check validates the target daemon is live and supports the requested agent type (`force: true` bypasses). Daemon boot profiles (hostname, platform, available player types) are advertised via the `hostProfile` signal and maintained in the global maestro's `hostProfiles` map — surfaced by the `hosts` MCP tool, `agent-tempo hosts` CLI, and the `/hosts` command-center board command (#274). See [docs/concepts.md](docs/concepts.md) for cross-machine recruiting details.
210
223
  - **Wire protocol**: All signal/query/update names are documented in [`docs/WIRE-PROTOCOL.md`](docs/WIRE-PROTOCOL.md) and are stable — renaming or removing any is a breaking change. **Process**: update `docs/WIRE-PROTOCOL.md` in the same commit as any new signal, query, or update.
211
- - **Daemon**: Standalone background process (`src/daemon.ts`) that runs all Temporal workers and the HTTP/SSE event source (`src/http/`). Auto-started by any `agent-tempo` command. PID at `~/.agent-tempo/daemon.pid`; logs at `~/.agent-tempo/daemon.log`. Exposes local HTTP endpoints (`/v1/health`, `/v1/ensembles`, `/v1/state/:ensemble`, `/v1/events/:ensemble` SSE stream, etc.) consumed by the TUI and `TempoClient.subscribe()`. See [docs/SSE-PROTOCOL.md](docs/SSE-PROTOCOL.md).
224
+ - **Daemon**: Standalone background process (`src/daemon.ts`) that runs all Temporal workers and the HTTP/SSE event source (`src/http/`). Auto-started by any `agent-tempo` command. PID at `~/.agent-tempo/daemon.pid`; logs at `~/.agent-tempo/daemon.log`. Exposes local HTTP endpoints (`/v1/health`, `/v1/ensembles`, `/v1/state/:ensemble`, `/v1/events/:ensemble` SSE stream, etc.) consumed by the command-center board, the web dashboard, and `TempoClient.subscribe()`. See [docs/SSE-PROTOCOL.md](docs/SSE-PROTOCOL.md).
212
225
  - **Player types**: Reusable agent definitions in Claude Code's subagent format (`.md` files with YAML frontmatter). Three-tier lookup: project `.claude/agents/` → user `~/.claude/agents/` → shipped `examples/agents/`. Discover via `agent_types` tool or `agent-tempo agent-types` CLI. Shipped types: tempo-conductor, tempo-composer, tempo-soloist, tempo-tuner, tempo-critic, tempo-roadie, tempo-improv, tempo-liner.
213
226
  - **Dev mode** (`--dev` flag or `CLAUDE_TEMPO_DEV_MODE=1`): Isolated testing profile — flips home dir to `~/.agent-tempo-dev/`, HTTP port to 8474, Temporal namespace to `agent-tempo-dev`, task queue to `agent-tempo-dev`. Required to use the mock adapter. Post-#423 isolation guarantees: (1) `TEMPORAL_NAMESPACE` / `TEMPORAL_ADDRESS` shell env vars are ignored in dev mode — the dev namespace is not overridable by shell config, only CLI flags and `~/.agent-tempo-dev/config.json`. (2) `--dev down` will not kill the Temporal server if the prod profile is alive; use `--kill-shared-temporal` to override. Canonical entry point (no global install required): `node dist/cli.js --dev <verb>`. Quick E2E: `node dist/cli.js --dev daemon start && node dist/cli.js --dev up --lineup tempo-mock-jam`. See [docs/dev-mode.md](docs/dev-mode.md) for the full reference.
214
227
  - **Claude API adapter** (`agent: 'claude-api'`, #131): Headless adapter that drives sessions via the Anthropic Messages API (`@anthropic-ai/sdk`) — no terminal, no Claude Code CLI. Requires `ANTHROPIC_API_KEY` env var and the `@anthropic-ai/sdk` optional dependency. Default model `claude-opus-4-7` (overridable via `model` recruit arg or `CLAUDE_TEMPO_API_MODEL` env). Claude-API players have access to agent-tempo MCP tools (cue, report, recall, ensemble, …) but not file-edit/shell/web tools. See `src/adapters/claude-api/`.
215
228
  - **OpenCode adapter** (`agent: 'opencode'`, #449): Headless multi-provider adapter that drives sessions via [SST OpenCode](https://opencode.ai) as a managed subprocess — supports Anthropic, OpenAI, Bedrock, Vertex, Ollama, and ~70 other providers via OpenCode's `provider/model` selector. Requires OpenCode CLI (`npm install -g opencode-ai`) and the `@opencode-ai/sdk` optional dependency. Recruit with `model: 'provider/name'` (e.g. `'anthropic/claude-opus-4-7'`). Tool bridging is MCP-native — OpenCode spawns `dist/server.js` as its own stdio MCP child. Session state is persisted server-side by OpenCode; the adapter stashes the session id on workflow metadata for reconnect across `opencode serve` restarts. See `src/adapters/opencode/`.
216
229
  - **Claude Code headless adapter** (`agent: 'claude-code-headless'`, #520): Headless adapter that drives sessions via the official `claude` CLI as a per-turn `claude -p --output-format stream-json` subprocess. The whole point: turns bill against the host's existing Claude Code subscription extra-usage credits (Pro / Max plans) rather than a Console workspace API key — the only ToS-clean way for a third-party tool to tap that pool. Requires the `claude` binary on PATH AND a logged-in Claude Code session (`claude auth login`); recruit pre-flight rejects with an actionable error otherwise. Tool surface is the union of full Claude Code built-ins (Bash / Read / Write / Edit / Glob / Grep / WebSearch / WebFetch) and the agent-tempo MCP surface — registered via inline `--mcp-config` so `claude` spawns `dist/server.js` as its own MCP child (no in-process bridge). Recruit knobs: `permissionMode` (default `'acceptEdits'`) or `dangerouslySkipPermissions: true` (mutually exclusive). Sessions resume across restart via the existing `sessionId` metadata field — the same UUID is shared with the interactive `claude-code` adapter (per-cwd JSONL is per-cwd, not per-adapter). See `src/adapters/claude-code-headless/` and `examples/ensembles/tempo-headless-jam.yaml`.
217
- - **Pi adapter** (`agent: 'pi'`, #632 / #666): Two modes. **(1) Interactive conductor** (#666): `agent-tempo up --agent pi --ensemble <name>` launches `pi` in a real terminal with the agent-tempo extension auto-loaded (`pi -e dist/pi/extension.js`); the Pi session self-bootstraps its Temporal workflow and attaches as a conductor/player — no separate recruiter step. From the TUI, `/recruit-conductor` relaunches the active ensemble's conductor — set `conductor.agent: pi` in that ensemble's lineup to make it a Pi conductor. Requires `@earendil-works/pi-coding-agent` on Node ≥ 22.19. Recommended: `ANTHROPIC_API_KEY` (without it the session falls back to Pi's own auth/default model). The `AGENT_TEMPO_*` env is auto-wired by `up`; power users can invoke the extension directly with `pi -e dist/pi/extension.js`. The interactive `--model provider/model` selector (e.g. `'github-copilot/gpt-4o'`) remains a fast-follow. **(2) Headless player** (Phase 3a): `recruit` with `agent: 'pi'` — no terminal, no BaseAttachment; runs `createAgentSession` with an in-memory `SessionManager`; the module-scope singleton owns claim/heartbeat/tools/cue pump (MD-D). Per-player `model: 'provider/model'` on recruit (#734): built-in providers AND custom `~/.pi/agent/models.json` providers (lmstudio, ollama, vllm, …) both resolve, falling back to `AGENT_TEMPO_PI_MODEL` — enables hybrid ensembles (frontier-model conductor, local-model workers). Pi players run the full tool surface — incl. shell — with no permission layer, like the other adapters (the former `toolAccess`/`guardrailPolicy` knobs were removed). `noExtensions: true` stays: it blocks third-party disk/package extensions from loading into a recruited player (supply-chain hygiene). See `src/adapters/pi/` and `src/pi/headless.ts`.
230
+ - **Pi adapter** (`agent: 'pi'`, #632 / #666): Two modes. **(1) Interactive conductor** (#666): `agent-tempo up --agent pi --ensemble <name>` launches `pi` in a real terminal with the agent-tempo extension auto-loaded (`pi -e dist/pi/extension.js`); the Pi session self-bootstraps its Temporal workflow and attaches as a conductor/player — no separate recruiter step. Set `conductor.agent: pi` in that ensemble's lineup to make it a Pi conductor. Requires `@earendil-works/pi-coding-agent` on Node ≥ 22.19. Recommended: `ANTHROPIC_API_KEY` (without it the session falls back to Pi's own auth/default model). The `AGENT_TEMPO_*` env is auto-wired by `up`; power users can invoke the extension directly with `pi -e dist/pi/extension.js`. The interactive `--model provider/model` selector (e.g. `'github-copilot/gpt-4o'`) remains a fast-follow. **(2) Headless player** (Phase 3a): `recruit` with `agent: 'pi'` — no terminal, no BaseAttachment; runs `createAgentSession` with an in-memory `SessionManager`; the module-scope singleton owns claim/heartbeat/tools/cue pump (MD-D). Per-player `model: 'provider/model'` on recruit (#734): built-in providers AND custom `~/.pi/agent/models.json` providers (lmstudio, ollama, vllm, …) both resolve, falling back to `AGENT_TEMPO_PI_MODEL` — enables hybrid ensembles (frontier-model conductor, local-model workers). Pi players run the full tool surface — incl. shell — with no permission layer, like the other adapters (the former `toolAccess`/`guardrailPolicy` knobs were removed). `noExtensions: true` stays: it blocks third-party disk/package extensions from loading into a recruited player (supply-chain hygiene). See `src/adapters/pi/` and `src/pi/headless.ts`.
218
231
  - **Mission-control / Command-center** (3f, #700 P2): An interactive Pi TUI that is both a live ensemble board + operator controller and an LLM planner. Board side: HTTP-drives the daemon — coarse ensemble view via `/v1/events/:ensemble` SSE + fine per-player tail via `/inner` (T3); operator controls (cue/pause/play/restart/destroy) POST to the daemon write surface using `AGENT_TEMPO_HTTP_ADMIN_TOKEN`. Planner side: registers LLM tools (`ask` / `handoff` / `cue` / `recruit` / `observe_board`) via `MissionControlActions` — HTTP-backed, distinct from the player extension's `renderToPi` MCP surface. **Never claims attachment or registers as a player** — invisible to the ensemble. Launch with **`agent-tempo command-center [ensemble]`** (aliases: `cc`, `board`) — sets `AGENT_TEMPO_MISSION_CONTROL=1`. **Loopback auto-token** (#736): a local (loopback) daemon grants full trust without `AGENT_TEMPO_HTTP_ADMIN_TOKEN`; only a remote daemon requires explicit token configuration. **Role-gated and mutually exclusive** with the player extension (`resolvePiRole` discriminator: explicit `AGENT_TEMPO_PI_ROLE` → `PLAYER_NAME` present → `AGENT_TEMPO_MISSION_CONTROL` → `none`): a bare `pi` keeps both extensions dormant (plain coding session); a player session (`up --agent pi` / `recruit`) keeps the board dormant. Power users invoking `pi -e dist/pi/extension.js` directly without `PLAYER_NAME` also resolve to `none` (dormant) — set `AGENT_TEMPO_PI_ROLE=player` to force player mode. See `src/pi/mission-control/`.
219
232
  - **Command-center planner** (#700 P2): An inbox-less interactive Pi session (the operator's planning seat) that routes questions to players via correlated `cue` tags (`[Q <questionId>]`). Players answer with the `respond` MCP tool, which parks the answer on the per-ensemble maestro Q&A mailbox (TTL 1h, 20-slot cap). The planner is woken by an `answer` SSE event when the answer lands (`docs/SSE-PROTOCOL.md` §6). `/handoff` cues hand active work to a conductor (a registered player with a Temporal inbox). See `docs/concepts.md` for the Q&A mechanics.
220
233
  - **Mock adapter** (`agent: 'mock'`, dev mode only): Four modes: `echo` (echoes input), `scripted` (replays YAML scenario rules), `silent` (drains messages without replying — heartbeat-stale validation), `chaos` (probabilistic fail/crash injection via seeded PRNG). Only registered when `isDevMode()` is true; stripped from the npm tarball by `prepack`. See `src/adapters/mock/`.
@@ -222,7 +235,7 @@ daemon worker notes, `npx ts-node` dev runner).
222
235
  - **`upgrade-to-2` cutover** (#785, ratified migration protocol A2 — `docs/design/v2-scoping.md` §A.3): The 1.x → 2.0 migration verb. A 2.0 worker can never replay a 1.x-recorded run, so 2.0 ships behind a clean cutover: `agent-tempo upgrade-to-2` runs a six-phase protocol — **preflight** (enumerate ensembles; refuse if any connected daemon is below the 1.7.x version floor — `hostProfile.version` on the global maestro; covers same-host-stale-daemon, #801) → **pause** (brake the work *sources* — maestro + scheduler — leaving sessions live to drain) → **drain** (poll outboxes ≤60s; `--force-drain` records stragglers instead of stopping) → **snapshot** (freeze session dispatch, then capture continuity to `~/.agent-tempo/upgrade-snapshot-v1.json`) → **destroy** (idempotent teardown: peers → scheduler+maestro → conductor) → **done**. **Load-bearing invariant: SNAPSHOT strictly precedes DESTROY** (`destroyAndFinish` takes a persisted snapshot as a required arg); a crash leaves either everything intact or a durable snapshot + partial teardown, never destruction without capture. Resumable via the snapshot's phase stamp. The snapshot captures schedules (durable intent), #334 state slots (continuity), `sessionId` (resume pointer), the non-default recruit `model` (ad-hoc claude-api/opencode/pi continuity), and undelivered cues (operator review, NOT redelivered); coat-check is dropped (TTL-transient); gates/stages/worktrees are intentionally not captured (transient coordination state; worktree continuity rides `workDir`). **`src/upgrade/snapshot-v1.ts` is the cross-release interface the 2.0-side `up --from-upgrade` (#786) imports** — it is VERSIONED and deliberately Temporal-free; additive optional fields do NOT bump the version, only removed/renamed/retyped required fields do (with a 2.0 reader migration). CLI flags: `--yes` (skip confirm), `--dry-run` (print snapshot + destroy list, exit before pausing), `--force-drain`. The verb is crash-proof (`src/cli/upgrade-to-2-command.ts` dynamic-imports the Temporal-touching engine). See `src/upgrade/` and issue #785.
223
236
  - **Coat-check** (#318, ADR 0008): Per-ensemble transient content store on Maestro state. Solves the 100 KB cue body cap — stash a large artifact with `coat_check_put` (returns a ticket id) and attach the ticket to a `cue` via `attachmentTicket`; the recipient calls `coat_check_get` to pull the full body. Four MCP tools: `coat_check_put` (any player; max 32 KiB per entry, 20 slots per ensemble, TTL 7d default), `coat_check_get` (any player; bumps fetch-audit counters), `coat_check_list` (read-only survey; headers only, content omitted), `coat_check_evict` (owner or conductor). Saturation rejects with `CoatCheckSlotsFull` (no LRU eviction). See `src/tools/coat-check-*.ts` and [docs/adr/0008-coat-check-pattern.md](docs/adr/0008-coat-check-pattern.md).
224
237
  - **Lineup examples**: Six pre-built ensemble YAML files in `examples/ensembles/` — `tempo-big-band`, `tempo-dev-team`, `tempo-review-squad`, `tempo-jam-session`, `tempo-mock-jam` (dev-mode all-mock ensemble), `tempo-headless-jam` (#520 — all-`claude-code-headless` subscription-billed ensemble). Load with `agent-tempo up --lineup <name>` or the `load_lineup` tool.
225
- - **GitHub App identity** (`agent-tempo[bot]`): When a player writes to GitHub — issue comments, PR creation/merge, commits, labels, check runs — **use `./scripts/ensemble-gh`** instead of `gh`. The wrapper mints a short-lived installation token so the action is attributed to `agent-tempo[bot]`, not to the human maintainer, making the AI authorship visible. Plain `gh` is still correct for read-only local dev (`gh pr view`, `gh repo clone`, `gh auth status`). On Windows, invoke via `bash ./scripts/ensemble-gh` bare PowerShell silently no-ops with no error (see #741). Every bot-authored comment/PR body must include the AI attribution footer documented in [docs/github-app.md](docs/github-app.md).
238
+ - **GitHub App identity** (`agent-tempo[bot]`): When a player writes to GitHub — issue comments, PR creation/merge, commits, labels, check runs — **use `./scripts/ensemble-gh`** instead of `gh`. The wrapper mints a short-lived installation token so the action is attributed to `agent-tempo[bot]`, not to the human maintainer, making the AI authorship visible. Plain `gh` is still correct for read-only local dev (`gh pr view`, `gh repo clone`, `gh auth status`). On Windows, `./scripts/ensemble-gh` works directly from PowerShell via the `scripts/ensemble-gh.cmd` shim (#741); the `bash ./scripts/ensemble-gh` form also still works as an explicit fallback. Every bot-authored comment/PR body must include the AI attribution footer documented in [docs/github-app.md](docs/github-app.md).
226
239
 
227
240
  See [docs/concepts.md](docs/concepts.md) for the full glossary (Adapter, Attachment phases, Restart, Detach/Destroy, Migrate, Broadcast, Recall, Schedule, Lineup, Quality Gate, Worktree, Stage, Hold/Release, Pause/Resume, Maestro, TempoClient, Command-center planner, and more).
228
241
 
package/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  Multiple Claude Code sessions discover each other, exchange messages in real time, and coordinate work — across machines, not just localhost.
18
18
 
19
- Each session registers as a **player** in Temporal. Players discover each other with `ensemble`, send messages with `cue`, and coordinate via a **conductor** that connects to external interfaces like Discord, Telegram, or the built-in TUI.
19
+ Each session registers as a **player** in Temporal. Players discover each other with `ensemble`, send messages with `cue`, and coordinate via a **conductor** that connects to external interfaces like Discord, Telegram, or the built-in mission-control board.
20
20
 
21
21
  📖 **[Full documentation](docs/README.md)**
22
22
 
@@ -34,7 +34,7 @@ Each session registers as a **player** in Temporal. Players discover each other
34
34
  | 🔁 **Ensemble Lineups** | YAML configs that define a full team and recruit them all in one command |
35
35
  | ⏰ **Scheduling** | One-shot and recurring message schedules with fan-out and failure notifications |
36
36
  | 🎭 **Player Types** | Reusable agent definitions with 8 shipped types and three-tier lookup |
37
- | 🖥️ **Terminal UI** | Chat-focused TUI with slash commands, overlays, and interactive wizards |
37
+ | 🖥️ **Mission-control board** | Interactive operator board (`command-center`) live ensemble view + cue/pause/restart/destroy controls + an LLM planner |
38
38
  | 🌐 **Cross-machine** | Any session that can reach your Temporal server can join the ensemble |
39
39
  | ⏸️ **Hold / Pause / Resume** | Pre-warm a full team before delivering tasks; pause and resume mid-session |
40
40
  | 🤖 **Headless adapters** | Copilot bridge, Claude API, OpenCode, Claude Code headless (`claude -p` — bills against your Claude Code subscription), and Pi AI (headless player or interactive conductor) — mix providers and headless agents in the same ensemble |
@@ -66,7 +66,7 @@ This starts Temporal, registers the MCP server, launches the daemon, and opens a
66
66
  agent-tempo status # see who's active
67
67
  ```
68
68
 
69
- Or use the TUI to recruit players, or ask the conductor to `recruit` from inside Claude Code.
69
+ Or recruit players from the command-center board, or ask the conductor to `recruit` from inside Claude Code.
70
70
 
71
71
  ### Manual setup
72
72
 
@@ -118,7 +118,7 @@ agent-tempo daemon stop
118
118
  - **Lineup** — A YAML file that defines a full team and recruits them in one step
119
119
  - **Player Type** — A reusable agent definition (`.md` with YAML frontmatter) that gives a player a named role
120
120
 
121
- Players in one ensemble cannot see or message players in another. Launch `agent-tempo` to open the TUI and switch between ensembles, or target a specific ensemble directly:
121
+ Players in one ensemble cannot see or message players in another. Run `agent-tempo` for status across ensembles (or `agent-tempo command-center` for the live board), or target a specific ensemble directly:
122
122
 
123
123
  ```bash
124
124
  agent-tempo up frontend # provision and launch conductor in "frontend"
@@ -144,16 +144,18 @@ Tools available inside Claude Code sessions connected to agent-tempo:
144
144
  ## CLI
145
145
 
146
146
  ```bash
147
- agent-tempo # launch TUI (auto-provisions on first run)
147
+ agent-tempo # bootstrap + status + operator hints (auto-provisions on first run)
148
148
  agent-tempo up [ensemble] # provision infrastructure and launch conductor
149
149
  agent-tempo down [--destroy] # tear down infrastructure (--destroy also terminates workflows)
150
150
  agent-tempo status [ensemble] # list active sessions
151
- agent-tempo destroy <ensemble> # terminate all sessions in an ensemble
151
+ agent-tempo destroy [ensemble] # terminate all sessions in an ensemble (defaults to "default")
152
152
  agent-tempo restore <ensemble> # restore orphaned sessions on this host
153
153
  agent-tempo hosts # list daemons polling this Temporal namespace (--all/--json)
154
154
  agent-tempo recall <name> # read a player's message history (--limit/--offset/--preview/--json)
155
155
  agent-tempo attachment-info <name> # inspect a session's phase, holder, lease, and heartbeat age
156
156
  agent-tempo release [ensemble] # release held players (unlock + deliver tasks)
157
+ agent-tempo command-center # interactive operator board (aliases: cc, board)
158
+ agent-tempo dashboard # open the web dashboard (--pair for QR-code cross-device access)
157
159
  agent-tempo daemon <sub> # manage the worker daemon
158
160
  agent-tempo upgrade # update to latest
159
161
  ```
@@ -234,26 +236,31 @@ Key environment variables:
234
236
 
235
237
  📖 [Full configuration reference → docs/configuration.md](docs/configuration.md)
236
238
 
237
- ## Terminal UI
239
+ ## Mission-control board
240
+
241
+ The interactive operator surface is the **command-center board** — an interactive
242
+ Pi session that turns one terminal into a live ensemble dashboard + operator
243
+ controller:
238
244
 
239
245
  ```bash
240
- agent-tempo tui # multi-ensemble home screen
241
- agent-tempo tui --ensemble my-ensemble # direct ensemble mode
246
+ agent-tempo command-center # multi-ensemble board (aliases: cc, board)
247
+ agent-tempo command-center my-ensemble # scoped to one ensemble
242
248
  ```
243
249
 
244
- The TUI provides a chat-focused shell for managing your ensemble:
250
+ - **Live board** coarse ensemble view (player phases, parts, current tool, context %) over the daemon's SSE stream, plus a fine per-player tail
251
+ - **Operator commands** — `/cue`, `/pause`, `/play`, `/go` (release held), `/restart`, `/destroy`, `/reset`, `/hosts`, `/status`, `/attachment-info`, `/recall`, `/schedule`, `/unschedule`, and more
252
+ - **LLM planner** — `ask` / `handoff` / `recruit` / `observe_board` tools for an operator who wants to plan and delegate from the same seat
245
253
 
246
- - **Ensemble chat feed** — live aggregated view of conductor + player traffic; type bare text to message the conductor, `@player message` to message directly
247
- - **Slash commands** — `/recruit`, `/status`, `/schedule`, `/gates`, `/stages`, `/worktree`, `/go` (release held), `/pause`, `/play`, `/shutdown`, `/restore`, `/home`, and more; type `/help` for the full list
248
- - **Interactive overlays and wizards** — step-by-step flows for recruiting players, creating schedules, and managing ensembles
254
+ A bare `agent-tempo` (no command) auto-provisions infrastructure, prints live
255
+ `status`, and points you at the board + web dashboard.
249
256
 
250
- 📖 [TUI reference → docs/tui.md](docs/tui.md)
257
+ 📖 [Concepts → docs/concepts.md](docs/concepts.md) (Command-center)
251
258
 
252
259
  ## Copilot Integration
253
260
 
254
261
  > **Experimental** — subject to breaking changes.
255
262
 
256
- GitHub Copilot CLI sessions can join an ensemble using `--agent copilot`. Recruit one from the TUI:
263
+ GitHub Copilot CLI sessions can join an ensemble using `--agent copilot`. Recruit one from the command-center board or the conductor:
257
264
 
258
265
  ```
259
266
  /recruit copilot-1 --agent copilot
@@ -273,7 +280,7 @@ agent-tempo up --agent pi --ensemble <name>
273
280
 
274
281
  The Pi session self-bootstraps its Temporal workflow and attaches as a conductor or player. The `AGENT_TEMPO_*` environment is wired automatically. For power users, the underlying extension path is `dist/pi/extension.js` — invoke directly with `pi -e dist/pi/extension.js`.
275
282
 
276
- From the TUI, `/recruit-conductor` relaunches the active ensemble's conductor — set `conductor.agent: pi` in that ensemble's lineup to make it a Pi conductor.
283
+ Set `conductor.agent: pi` in that ensemble's lineup to make it a Pi conductor.
277
284
 
278
285
  **Prerequisites:** `@earendil-works/pi-coding-agent` on Node ≥ 22.19. Recommended: `ANTHROPIC_API_KEY` (without it the session falls back to Pi's own auth/default model).
279
286