Skip to content

Commit 142bdc7

Browse files
NagyViktNagyVikt
andauthored
feat(codex-fleet): synthetic-data demo of 8-agent fleet (#160)
scripts/codex-fleet/demo/ — bring up the production tmux layout populated by fake plan / pane / counter / quality-score files so the real fleet-state / fleet-plan-tree / fleet-waves binaries render against synthetic data. No real codex sessions, no API spend. For design iteration: change a renderer, kill + restart the demo, see the result. Structure: - up.sh seeds /tmp/claude-viz/, spawns tmux session codex-fleet-demo with overview (8 worker panes) + fleet/plan/waves/watcher dashboard windows, starts tick simulator - down.sh tears tmux down, removes synthetic state, deletes runtime plan copy so working tree stays clean - tick.sh mutates the runtime plan every 3s (configurable via CODEX_FLEET_DEMO_TICK_INTERVAL): assign idle agents, advance claimed → in_progress → completed, refresh pane scrollback. Loops when all 12 tasks complete (set CODEX_FLEET_DEMO_LOOP=0 to stop) - agent-auth PATH shim so fleet-data::accounts::load_via_agent_auth() reads 8 synthetic accounts instead of the real binary - scenarios/refactor-wave/plan.json committed template; up.sh copies to openspec/plans/<slug>/ at runtime 8 agents named after herbs; clover is scripted to be "capped" so the PaneState::Capped branch is exercised. Plan has 12 tasks across 3 dependency waves modelled after the recent refactor PRs (#154-159). Usage: bash scripts/codex-fleet/demo/up.sh Prereqs: tmux, jq, release builds of fleet-state, fleet-plan-tree, fleet-waves (+ optionally fleet-watcher) under rust/target/release/. Co-authored-by: NagyVikt <nagy.viktordp@gmail.com>
1 parent cff98c8 commit 142bdc7

6 files changed

Lines changed: 893 additions & 0 deletions

File tree

scripts/codex-fleet/demo/README.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# codex-fleet demo
2+
3+
Bring up the production codex-fleet tmux layout driven by **synthetic data**
4+
— no real codex sessions spawned, no API spend, no GitHub touched. The
5+
existing `fleet-state`, `fleet-tab-strip`, `fleet-plan-tree`, and
6+
`fleet-waves` binaries render against fake plan/pane/heartbeat files, so
7+
what you see is exactly what the live fleet would look like with 8 agents
8+
mid-flight on a refactor wave.
9+
10+
Intended for design iteration: change a renderer, kill+restart the demo,
11+
see the result without paying for codex API calls.
12+
13+
## Run
14+
15+
```bash
16+
bash scripts/codex-fleet/demo/up.sh # bring up + auto-attach
17+
bash scripts/codex-fleet/demo/up.sh --no-attach
18+
bash scripts/codex-fleet/demo/up.sh --no-tick # static state, no animation
19+
bash scripts/codex-fleet/demo/down.sh # tear down
20+
```
21+
22+
Prereqs: `tmux`, `jq`, and release builds of `fleet-state`, `fleet-plan-tree`,
23+
`fleet-waves` (plus optionally `fleet-watcher`) in `rust/target/release/`
24+
(or debug fallback). Build with:
25+
26+
```bash
27+
cd rust && cargo build --release -p fleet-state -p fleet-plan-tree \
28+
-p fleet-waves -p fleet-watcher
29+
```
30+
31+
## Layout
32+
33+
Tmux session `codex-fleet-demo` on socket `codex-fleet-demo`:
34+
35+
- **overview** — 8 worker panes in a 4×2 grid. Each pane displays
36+
scripted scrollback the `fleet-data::scrape` parser will extract a
37+
runtime + model + headline from. Pane `@panel` options are set to
38+
`[codex-<aid>]` so `fleet-data::panes::list_panes` maps them to
39+
accounts.
40+
- **fleet**`fleet-state` worker list (image G reference design).
41+
Renders its own iOS tab strip inline (via `fleet_ui::tab_strip` reading
42+
`fleet-tab-counters.json`); the standalone `fleet-tab-strip` binary was
43+
removed by PR #107.
44+
- **plan**`fleet-plan-tree` topo levels view.
45+
- **waves**`fleet-waves` spawn-timeline view.
46+
- **watcher** *(if built)*`fleet-watcher` if the binary is available.
47+
48+
## Scenario
49+
50+
`scripts/codex-fleet/demo/scenarios/refactor-wave/plan.json` (committed
51+
template) — 12 tasks in 3 dependency waves modelled after the refactor
52+
PRs (#154#159): toposort/scrape/tab_strip splits + CliConvention trait +
53+
shell helper lib + dependent follow-ups + a final docs/smoke gate. 8
54+
agents (named after herbs) claim and complete tasks on a tick loop.
55+
56+
`up.sh` copies the template into
57+
`openspec/plans/demo-refactor-wave-2026-05-16/plan.json` so the
58+
dashboards can discover it via their normal `openspec/plans/<slug>/`
59+
lookup. `tick.sh` mutates that runtime copy in place; `down.sh` removes
60+
it, so the working tree stays clean across runs.
61+
62+
The `tick.sh` simulator mutates `plan.json` in place every 3s
63+
(configurable via `CODEX_FLEET_DEMO_TICK_INTERVAL`):
64+
65+
1. Assign next ready task to each idle agent.
66+
2. Bump runtime + rewrite pane scrollback (the workers' `tail -F` loops
67+
pick this up).
68+
3. After ~4s the task moves `claimed → in_progress`; after ~18s it
69+
completes.
70+
4. When all 12 tasks complete, loop back to wave 0 (set
71+
`CODEX_FLEET_DEMO_LOOP=0` to stop instead).
72+
73+
One agent (`clover`) is scripted to be "capped" when idle so the demo
74+
exercises `PaneState::Capped` rendering.
75+
76+
## Synthetic files written
77+
78+
| Path | Owner | Purpose |
79+
|------|-------|---------|
80+
| `/tmp/claude-viz/fleet-tab-counters.json` | `up.sh` + `tick.sh` | `fleet-tab-strip` counter badges |
81+
| `/tmp/claude-viz/fleet-quality-scores.json` | `up.sh` | `fleet-state` quality column |
82+
| `/tmp/claude-viz/plan-tree-pin.txt` | `up.sh` | Pins plan-tree to the demo plan |
83+
| `/tmp/claude-viz/demo-current-account` | `up.sh` | Marks the `*` row in agent-auth |
84+
| `/tmp/claude-viz/demo-panes/<aid>.txt` | `tick.sh` | Per-pane fake scrollback (workers `tail -F` these) |
85+
| `/tmp/claude-viz/demo-active` | `up.sh` | Sentinel; `tick.sh` exits when removed |
86+
| `/tmp/claude-viz/demo-tick.pid` | `up.sh` | PID of background tick simulator |
87+
| `openspec/plans/demo-refactor-wave-2026-05-16/plan.json` | committed | Plan fixture mutated in place by `tick.sh` |
88+
89+
`down.sh` removes everything in the table except the committed plan
90+
fixture.
91+
92+
## Shim
93+
94+
`scripts/codex-fleet/demo/agent-auth` is prepended to `$PATH` for the
95+
binaries. `fleet-data::accounts::load_via_agent_auth()` calls
96+
`agent-auth list` as a subprocess — the shim emits 8 synthetic rows that
97+
match the real parser's format.
98+
99+
## Extending
100+
101+
- **New scenario:** add `openspec/plans/<your-slug>/plan.json` and pass
102+
`CODEX_FLEET_DEMO_PLAN_SLUG=<your-slug>` (TODO: wire this through
103+
`up.sh` + `tick.sh` — currently hardcoded to `demo-refactor-wave-…`).
104+
- **Different worker count:** change `WORKERS` + `AIDS` in `up.sh` and
105+
`AIDS` in `tick.sh`. Tmux layout also needs adjustment past 8.
106+
- **Slow down / speed up:** `CODEX_FLEET_DEMO_TICK_INTERVAL=1` (faster)
107+
or `=10` (slower).
108+
109+
## Caveats
110+
111+
- The demo plan slug carries a date suffix so the "newest plan" picker in
112+
`fleet-plan-tree` selects it on a clean repo. If you have other plans
113+
with a newer date suffix, the `plan-tree-pin.txt` override kicks in.
114+
- `fleet-watcher` is not wired into the demo yet — its data dependencies
115+
overlap with `fleet-state` but it also looks at colony/auto-reviewer
116+
state that isn't faked here.
117+
- Workers' `current_command` shows `bash` (not `codex`), which
118+
`panes::classify` would flag as `Dead`. The classifier checks for
119+
"codex" in scrollback as an escape; the fixture text starts with
120+
`codex 0.42.0 — …` so this branch evaluates correctly. If you see
121+
Dead-state rendering, that's the cause.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env bash
2+
# Demo shim: fake `agent-auth list` output for codex-fleet/demo/up.sh.
3+
# Used via PATH override so fleet-data::accounts::load_via_agent_auth() reads
4+
# this instead of the real binary. Eight synthetic accounts with varied
5+
# 5h/weekly caps so the dashboard shows visual range.
6+
#
7+
# When invoked with a sub-command other than `list`, exit 0 silently — the
8+
# real binary supports more verbs, but the dashboards only call `list`.
9+
set -euo pipefail
10+
11+
if [[ "${1:-}" != "list" ]]; then
12+
exit 0
13+
fi
14+
15+
# Allow the tick simulator to flip the "current" account by writing the
16+
# email into this file. Defaults to admin-magnolia.
17+
current_file="${CODEX_FLEET_DEMO_CURRENT:-/tmp/claude-viz/demo-current-account}"
18+
current_email=""
19+
if [[ -r "$current_file" ]]; then
20+
current_email="$(head -1 "$current_file" | tr -d '[:space:]')"
21+
fi
22+
23+
print_row() {
24+
local email="$1" five_h="$2" weekly="$3"
25+
local marker=" "
26+
if [[ "$email" == "$current_email" ]]; then
27+
marker="*"
28+
fi
29+
printf "%s %-32s 5h=%s%% weekly=%s%%\n" "$marker" "$email" "$five_h" "$weekly"
30+
}
31+
32+
# 8 synthetic accounts. Caps tuned so the dashboards show variety: some
33+
# heavily loaded, some fresh, one near the limit.
34+
print_row admin-magnolia@example.dev 88 62
35+
print_row admin-sumac@example.dev 71 48
36+
print_row admin-yarrow@example.dev 59 35
37+
print_row admin-clover@example.dev 94 78
38+
print_row admin-thistle@example.dev 42 21
39+
print_row admin-fennel@example.dev 67 44
40+
print_row admin-mallow@example.dev 53 29
41+
print_row admin-borage@example.dev 81 56

scripts/codex-fleet/demo/down.sh

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env bash
2+
# Tear down the codex-fleet demo brought up by up.sh. Kills the tmux
3+
# session, stops the tick simulator, removes synthetic state. Does NOT
4+
# remove the openspec/plans/demo-refactor-wave-2026-05-16 fixture
5+
# (that's committed to the repo). Safe to run repeatedly.
6+
set -euo pipefail
7+
8+
SOCKET="${CODEX_FLEET_DEMO_SOCKET:-codex-fleet-demo}"
9+
SESSION="codex-fleet-demo"
10+
STATE_DIR="/tmp/claude-viz"
11+
DEMO_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
12+
REPO_ROOT="$(cd -- "$DEMO_DIR/../../.." && pwd)"
13+
PLAN_SLUG="demo-refactor-wave-2026-05-16"
14+
PLAN_RUNTIME="$REPO_ROOT/openspec/plans/$PLAN_SLUG/plan.json"
15+
16+
# Tick simulator
17+
if [[ -f "$STATE_DIR/demo-tick.pid" ]]; then
18+
pid="$(cat "$STATE_DIR/demo-tick.pid")"
19+
kill "$pid" 2>/dev/null || true
20+
rm -f "$STATE_DIR/demo-tick.pid"
21+
fi
22+
pkill -f 'codex-fleet/demo/tick.sh' 2>/dev/null || true
23+
24+
# Tmux session
25+
tmux -L "$SOCKET" kill-session -t "$SESSION" 2>/dev/null || true
26+
tmux -L "$SOCKET" kill-server 2>/dev/null || true
27+
28+
# Synthetic state files
29+
rm -f "$STATE_DIR/demo-active" \
30+
"$STATE_DIR/demo-current-account" \
31+
"$STATE_DIR/demo-tick.log" \
32+
"$STATE_DIR/fleet-tab-counters.json" \
33+
"$STATE_DIR/fleet-quality-scores.json" \
34+
"$STATE_DIR/plan-tree-pin.txt"
35+
rm -rf "$STATE_DIR/demo-panes"
36+
37+
# Runtime plan copy (template stays in scripts/codex-fleet/demo/scenarios/).
38+
if [[ -f "$PLAN_RUNTIME" ]]; then
39+
rm -f "$PLAN_RUNTIME"
40+
rmdir "$(dirname "$PLAN_RUNTIME")" 2>/dev/null || true
41+
fi
42+
43+
echo "demo down."

0 commit comments

Comments
 (0)