diff --git a/.codex-fleet/active-plan b/.codex-fleet/active-plan new file mode 100644 index 0000000..1965bfe --- /dev/null +++ b/.codex-fleet/active-plan @@ -0,0 +1 @@ +codex-fleet-tui-improvements-2026-05-15 diff --git a/README.md b/README.md index 77ba284..4c0d2c7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ Ships with: while still holding a Colony claim; releases the claim so force-claim can re-route the work. - **`cap-swap-daemon.sh`** — replaces capped panes with healthy accounts - using a live `codex exec` probe (not the codex-auth meter — those are + using a live `codex exec` probe (not the agent-auth meter — those are different things). - **iOS-style tmux chrome** (`style-tabs.sh`, `watcher-board.sh`, etc.) — rounded pill tabs, clickable status row, six animated dashboards. @@ -43,11 +43,11 @@ Standard: Account / task layer: -- `codex` CLI + `codex-auth` (Anthropic Codex) +- `codex` CLI + `agent-auth` (Anthropic Codex) - `colony` CLI ([colonyq](https://github.com/colonyq)) for the task queue, plan publishing, and stranded-claim rescue. - One auth file per worker at `~/.codex/accounts/.json`. Generate - them with `codex-auth login` per account. + them with `agent-auth login` per account. ## Usage diff --git a/install.sh b/install.sh index c020d11..385f90a 100755 --- a/install.sh +++ b/install.sh @@ -67,7 +67,7 @@ cat </dev/null 2>&1; then printf ' [ok] %s -> %s\n' "$bin" "$(command -v "$bin")" else diff --git a/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/.openspec.yaml b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/.openspec.yaml new file mode 100644 index 0000000..9f70866 --- /dev/null +++ b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-05-15 diff --git a/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/proposal.md b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/proposal.md new file mode 100644 index 0000000..313eca3 --- /dev/null +++ b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/proposal.md @@ -0,0 +1,11 @@ +## Why + +- TODO: describe the user/problem outcome this change addresses. + +## What Changes + +- TODO: summarize the intended behavior and scope. + +## Impact + +- TODO: call out risks, rollout notes, and affected surfaces. diff --git a/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/specs/wip-pre-dispatch-sync/spec.md b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/specs/wip-pre-dispatch-sync/spec.md new file mode 100644 index 0000000..1b408bb --- /dev/null +++ b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/specs/wip-pre-dispatch-sync/spec.md @@ -0,0 +1,9 @@ +## ADDED Requirements + +### Requirement: wip-pre-dispatch-sync behavior +The system SHALL enforce wip-pre-dispatch-sync behavior as defined by this change. + +#### Scenario: Baseline acceptance +- **WHEN** wip-pre-dispatch-sync behavior is exercised +- **THEN** the expected outcome is produced +- **AND** regressions are covered by tests. diff --git a/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/tasks.md b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/tasks.md new file mode 100644 index 0000000..346b54e --- /dev/null +++ b/openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/tasks.md @@ -0,0 +1,34 @@ +## Definition of Done + +This change is complete only when **all** of the following are true: + +- Every checkbox below is checked. +- The agent branch reaches `MERGED` state on `origin` and the PR URL + state are recorded in the completion handoff. +- If any step blocks (test failure, conflict, ambiguous result), append a `BLOCKED:` line under section 4 explaining the blocker and **STOP**. Do not tick remaining cleanup boxes; do not silently skip the cleanup pipeline. + +## Handoff + +- Handoff: change=`agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00`; branch=`agent//`; scope=`TODO`; action=`continue this sandbox or finish cleanup after a usage-limit/manual takeover`. +- Copy prompt: Continue `agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00` on branch `agent//`. Work inside the existing sandbox, review `openspec/changes/agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00/tasks.md`, continue from the current state instead of creating a new sandbox, and when the work is done run `gx branch finish --branch agent// --base dev --via-pr --wait-for-merge --cleanup`. + +## 1. Specification + +- [ ] 1.1 Finalize proposal scope and acceptance criteria for `agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00`. +- [ ] 1.2 Define normative requirements in `specs/wip-pre-dispatch-sync/spec.md`. + +## 2. Implementation + +- [ ] 2.1 Implement scoped behavior changes. +- [ ] 2.2 Add/update focused regression coverage. + +## 3. Verification + +- [ ] 3.1 Run targeted project verification commands. +- [ ] 3.2 Run `openspec validate agent-claude-wip-pre-dispatch-sync-2026-05-16-00-00 --type change --strict`. +- [ ] 3.3 Run `openspec validate --specs`. + +## 4. Cleanup (mandatory; run before claiming completion) + +- [ ] 4.1 Run the cleanup pipeline: `gx branch finish --branch agent// --base dev --via-pr --wait-for-merge --cleanup`. This handles commit -> push -> PR create -> merge wait -> worktree prune in one invocation. +- [ ] 4.2 Record the PR URL and final merge state (`MERGED`) in the completion handoff. +- [ ] 4.3 Confirm the sandbox worktree is gone (`git worktree list` no longer shows the agent path; `git branch -a` shows no surviving local/remote refs for the branch). diff --git a/openspec/changes/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/CHANGE.md b/openspec/changes/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/CHANGE.md new file mode 100644 index 0000000..358e3dd --- /dev/null +++ b/openspec/changes/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/CHANGE.md @@ -0,0 +1,87 @@ +--- +base_root_hash: f43dddb0 +slug: codex-fleet-glass-menu-drop-tabstrip-2026-05-15 +--- + +# CHANGE · codex-fleet-glass-menu-drop-tabstrip-2026-05-15 + +## §P proposal +# Glass/transparent pane menu + drop the codex-fleet tab strip + overall design pass + +## Problem + +The operator wants two visible design changes plus a polish pass. (1) The right-click pane action menu currently renders as a solid two-tone card (#1C1C1E inner / #2C2C2E border) that sits opaquely on top of the underlying pane. The operator wants it transparent / glassmorphic — the terminal's background (kitty supports background_opacity) should bleed through, with only hairline strokes, fg-only text, and a subtle iOS-blue underline on the focused row. (2) The 5-tab strip rendered at the top of the overview window by the standalone `rust/fleet-tab-strip` binary (spawned via `scripts/codex-fleet/overview-header.sh` and `scripts/codex-fleet/full-bringup.sh`) is to be removed entirely — including the binary, its workspace member, the spawn sites, and the downstream tmux pane-iteration excludes in `plan-watcher.sh` and `full-bringup.sh` that assume a `[codex-fleet-tab-strip]` panel exists. The dashboards already render their own iOS-chrome page headers (per the ios_page_design.rs modules merged in the previous plan), so the tab pane is now redundant. (3) An accompanying design pass: same transparent treatment for `help-popup.sh`, comment cleanup in `style-tabs.sh`, and removal of the now-orphaned `fleet_ui::tab_strip` module. The 8 lanes are flat-parallel — every lane edits exactly one disjoint file path (or one new disjoint set), depends_on=[] on all of them, so any fleet of 8 workers can claim and ship in parallel without `task_claim_file` contention. No shared helpers are added; each lane inlines the small bit of ANSI/transparency logic it needs. + +## Acceptance criteria + +- All 8 sub-tasks land independently as 8 separate PRs against main with depends_on=[] honored; no two PRs touch the same file path. +- After Lane 0 ships, right-click on any codex-fleet pane renders the action menu with NO solid card background — the underlying pane's text shows through under the menu chrome (verified by sending Esc-prefixed paste of a known visible character before opening the menu). Hairline borders, title row, items, and shortcut chips all use fg-only ANSI; the focused row uses an iOS-blue underline rather than a fill. +- After Lane 1 ships, the help popup (prefix+Ctrl+H) renders with the same transparent treatment as Lane 0: hairline section dividers in #3A3A3C, section headers in iOS-blue fg, no solid card bg. +- After Lanes 2-5 ship, `bash scripts/codex-fleet/full-bringup.sh --n 4 --no-attach` brings up the overview window with NO `[codex-fleet-tab-strip]` pane at the top — the 4 workers occupy the full window. `tmux list-panes -t codex-fleet:0 -F '#{@panel}'` does not list the tab-strip panel. `plan-watcher.sh` no longer references it. `rust/Cargo.toml`'s `fleet-*` workspace glob no longer pulls in `fleet-tab-strip` because that directory is gone, and `cargo check --workspace` from `rust/` succeeds. +- After Lane 6 ships, `style-tabs.sh` no longer contains the 'in-binary tab strip is the navigation surface' branding in its echo / comments — the comments accurately describe the post-removal world (tmux status off by default, glass right-click menu is the canonical chrome layer). +- After Lane 7 ships, `rust/fleet-ui/src/lib.rs` no longer exports `pub mod tab_strip;`, `rust/fleet-ui/src/tab_strip.rs` is deleted, and `cargo check -p fleet-ui` succeeds. +- No regression in the existing dashboards: each `cargo check -p ` for fleet-state / fleet-plan-tree / fleet-waves / fleet-watcher still passes after their respective lanes (none of those crates' main.rs are edited by this plan, so this should be a no-op verification). +- Every PR's final note records: branch, files changed, command + output evidence (cargo check / shellcheck / bringup smoke), PR URL, MERGED state, and sandbox cleanup proof per the Guardex completion contract. + +## Sub-tasks + +### Sub-task 0: Glass pane action menu — transparent chrome, fg-only ANSI, iOS-blue focus underline + +Rewrite scripts/codex-fleet/bin/pane-context-menu.sh so the right-click action menu renders as a transparent / glassmorphic surface. Required changes: (1) Stop emitting solid bg SGR escapes — change the chrome helpers (draw_top / draw_bottom / draw_hairline / draw_blank / draw_header / draw_item) so every cell uses ONLY a 38;2;R;G;B foreground escape with NO 48;2;R;G;B background. Inline this directly inside the script — DO NOT modify scripts/codex-fleet/lib/ios-menu.sh. (2) Hairline borders (top, bottom, section dividers) use fg=#3A3A3C (iOS separator gray). (3) Item rows use fg=#FFFFFF for label, fg=#8E8E93 for icon column, fg=#AEAEB2 for shortcut chip text. The bracketing '[ K ]' chip becomes plain '· K' or 'K' in dim gray since there is no longer a card surface to contrast against. (4) Header row: fg=#FFFFFF bold for 'pane N · %ID', fg=#34C759 for the leading dot, fg=#34C759 bold for ' LIVE ' (no bg). (5) Focus indicator: the script today only reads ONE keystroke and dispatches — there is no live focus loop — so the 'focus row' is the row whose hotkey was just pressed. Add a brief 80ms 'feedback flash' where the chosen row briefly underlines (fg sequence: \033[4m … \033[24m) in iOS-blue before dispatching, then clears the popup. (6) Danger row (Kill pane) keeps fg=#FF3B30. Disabled rows use fg=#48484A. (7) Update the bottom hint line to 'press a hotkey · ? for help · esc cancels' in fg=#8E8E93. (8) Add a top-of-file comment describing the transparency model and a smoke-test stanza: `printf 'hello-bg\nhello-bg\nhello-bg' && CODEX_FLEET_MENU_LINE=demo bash scripts/codex-fleet/bin/pane-context-menu.sh '%0' < /dev/null` and capture the rendered output via `script` or terminal recording to attach as evidence in the PR. file_scope is exactly this one file — do not touch ios-menu.sh, help-popup.sh, or any other file. + +File scope: scripts/codex-fleet/bin/pane-context-menu.sh + +### Sub-task 1: Glass help popup — same transparent treatment as the action menu + +Rewrite scripts/codex-fleet/bin/help-popup.sh to match Lane 0's transparency model. Required: (1) Drop every 48;2;R;G;B bg SGR — chrome helpers (draw_top / draw_bottom / draw_hairline / draw_section / any item draw) emit fg only. (2) Section headers (e.g. 'TMUX', 'CONTEXT MENU', 'SPOTLIGHT', etc.) render in fg=#007AFF bold with NO bg. (3) Keybinding rows: left column (the keystroke) in fg=#FFCC00 bold (iOS yellow), right column (the description) in fg=#FFFFFF, separator dot in fg=#8E8E93. (4) Section dividers use fg=#3A3A3C hairlines. (5) Outer corner glyphs (╭ ╮ ╰ ╯) and edge bars (│ ─) also fg-only in #3A3A3C. (6) Bottom hint: 'any key closes · esc/q exits' in fg=#8E8E93. (7) Keep all currently listed bindings verbatim — this lane is purely visual. (8) Add a self-contained smoke test stanza at the top of the script (commented) showing how to invoke it standalone: `bash scripts/codex-fleet/bin/help-popup.sh < /dev/null` with a 1-byte stdin to dismiss. (9) file_scope is exactly this one file. + +File scope: scripts/codex-fleet/bin/help-popup.sh + +### Sub-task 2: Drop fleet-tab-strip pane spawn from overview-header.sh + +Make scripts/codex-fleet/overview-header.sh a backwards-compatible no-op. Required: (1) Keep the file in place (other scripts source it / call it by path) but the body should now: log 'overview-header: tab strip removed (see plan codex-fleet-glass-menu-drop-tabstrip-2026-05-15)', skip the binary location lookup, skip the split-window / select-pane / set-option calls, and exit 0. (2) Remove the BIN= lookup at lines 64-69, the warn at line 69, the split-window/select-pane block, and the `tmux set-option -p ... '@panel' '[codex-fleet-tab-strip]'` at line 91. Keep the `tmux list-panes -t "$target" -F '#{@panel}' | grep -qFx '[codex-fleet-tab-strip]'` idempotence guard as a comment + skip path (so re-run on an OLD session with the strip pane still alive doesn't double-add). (3) Add a top-of-file comment block explaining the removal and pointing to the plan slug. (4) shellcheck must remain clean: `shellcheck scripts/codex-fleet/overview-header.sh` exits 0. (5) file_scope is exactly this one file — DO NOT touch full-bringup.sh, plan-watcher.sh, or rust/fleet-tab-strip in this lane (other lanes own those files). + +File scope: scripts/codex-fleet/overview-header.sh + +### Sub-task 3: Drop fleet-tab-strip references from full-bringup.sh + +Edit scripts/codex-fleet/full-bringup.sh to fully remove every reference to the tab-strip pane. Required: (1) Delete lines 458-468 (STRIP_BIN=… block, the if-exists guard, HEADER_CMD= path, the warn line). Whatever currently consumes HEADER_CMD afterwards must be removed too — trace the variable forward and drop the spawn site cleanly. (2) Delete line 516 (`awk -F'|' '$1 == "[codex-fleet-tab-strip]" { print $2; exit }'`) and update the surrounding logic so it no longer needs to identify a 'header pane' — the worker grid simply occupies all panes in the window. (3) Delete line 527's awk filter (`'$1 != "[codex-fleet-tab-strip]"'`) — replace with a pass-through that lists all panes. (4) Add an inline comment near each removal pointing at the plan slug. (5) Smoke test: `bash -n scripts/codex-fleet/full-bringup.sh` parses clean, and `shellcheck` exits 0. (6) A live smoke run on a clean repo (`tmux -L test kill-server 2>/dev/null; CODEX_FLEET_TMUX_SOCKET=test bash scripts/codex-fleet/full-bringup.sh --n 2 --no-attach`) must succeed and `tmux -L test list-panes -t codex-fleet:0 -F '#{@panel}'` must NOT contain '[codex-fleet-tab-strip]'. Capture that exact command + its stdout/stderr into the PR description. (7) file_scope is exactly this one file. + +File scope: scripts/codex-fleet/full-bringup.sh + +### Sub-task 4: Drop the tab-strip-panel exclusion in plan-watcher.sh + +Edit scripts/codex-fleet/plan-watcher.sh: at line 134 (and any nearby lines that participate in the same loop) remove the `[ "$panel" = "[codex-fleet-tab-strip]" ] && continue` skip. Required: (1) Remove the conditional cleanly without breaking the surrounding while-read loop indentation. (2) Update the comment block at lines 127-130 ('the fleet-tab-strip header pane (panel == [codex-fleet-tab-strip])') to remove the bullet about excluding the header pane. (3) Verify with `bash -n scripts/codex-fleet/plan-watcher.sh` and `shellcheck scripts/codex-fleet/plan-watcher.sh`. (4) Run a 1-tick dry-run on the current session if any is up — but DO NOT start a long-running daemon. (5) file_scope is exactly this one file. + +File scope: scripts/codex-fleet/plan-watcher.sh + +### Sub-task 5: Delete the standalone fleet-tab-strip rust crate + +Delete the entire `rust/fleet-tab-strip/` Cargo crate. Required: (1) Remove rust/fleet-tab-strip/Cargo.toml and rust/fleet-tab-strip/src/main.rs (`git rm` both). (2) The workspace `rust/Cargo.toml` uses a `"fleet-*"` glob, so no edit there is strictly required — but VERIFY by running `cargo metadata --no-deps --manifest-path rust/Cargo.toml | jq '.packages[].name'` before and after, and confirm `fleet-tab-strip` is gone post-delete and that no other crate failed to resolve (the binary's `use fleet_ui::tab_strip::{Tab, TabHit, TabStrip}` is the only consumer of that import path; with the binary gone, the orphaned `fleet_ui::tab_strip` module is handled by Lane 7). (3) Run `cargo check --workspace --manifest-path rust/Cargo.toml` and capture the output as PR evidence — expected: success. (4) Update `rust/Cargo.lock` only if cargo writes to it as part of the check (let cargo handle it; DO NOT hand-edit the lockfile beyond what cargo produces). (5) file_scope is exactly these two source files — DO NOT touch rust/Cargo.toml in this lane (the glob keeps it stable; if cargo absolutely requires an edit, propose a follow-up PR rather than expanding scope). + +File scope: rust/fleet-tab-strip/Cargo.toml, rust/fleet-tab-strip/src/main.rs + +### Sub-task 6: Clean up style-tabs.sh comments + branding post-tab-strip-removal + +Edit scripts/codex-fleet/style-tabs.sh to remove dead branding about the in-binary tab strip. Required: (1) The current echo near the bottom contains 'in-binary tab strip is the navigation surface' as the default `status_state` description — update it to 'tmux status hidden — pane chrome is the navigation surface' (or similar accurate phrasing). (2) Find the long header docstring's reference to '`rust/fleet-ui::tab_strip`' as the in-binary tab strip and replace it with a note that the tab strip was removed in plan codex-fleet-glass-menu-drop-tabstrip-2026-05-15 and `CODEX_FLEET_TMUX_STATUS=on` re-enables the iOS-pill status bar for users who explicitly want chrome. (3) All tmux pill/format options stay in place — `style-tabs.sh` still configures status-style / window-status-current-format / etc. so the bar looks correct WHEN re-enabled. (4) `bash -n` and `shellcheck` must remain clean. (5) file_scope is exactly this one file — DO NOT touch overview-header.sh, full-bringup.sh, plan-watcher.sh, or any rust/ file. + +File scope: scripts/codex-fleet/style-tabs.sh + +### Sub-task 7: Remove orphaned fleet_ui::tab_strip module + +Delete the now-orphaned tab_strip module from the fleet-ui crate. Required: (1) Remove the `pub mod tab_strip;` declaration from rust/fleet-ui/src/lib.rs (line 14 per current grep). (2) Delete rust/fleet-ui/src/tab_strip.rs with `git rm`. (3) Run `cargo check -p fleet-ui --manifest-path rust/Cargo.toml` and capture the output as PR evidence (expected: success — Lane 5 already removed the only consumer at rust/fleet-tab-strip/src/main.rs). (4) Run `cargo check --workspace --manifest-path rust/Cargo.toml` as a regression smoke (expected: success). (5) Do NOT touch any other file in rust/fleet-ui/ (the chip / card / overlay / spotlight_filter modules remain intact). (6) file_scope is exactly these two files — do NOT touch any binary crate's main.rs, scripts/, or workspace manifest in this lane. + +File scope: rust/fleet-ui/src/lib.rs, rust/fleet-ui/src/tab_strip.rs + + +## §S delta +op|target|row +-|-|- + +## §T tasks +id|status|task|cites +-|-|-|- + +## §B bugs +id|status|task|cites +-|-|-|- diff --git a/openspec/changes/codex-fleet-ios-pages-design-pass-2026-05-15/CHANGE.md b/openspec/changes/codex-fleet-ios-pages-design-pass-2026-05-15/CHANGE.md new file mode 100644 index 0000000..b0da2df --- /dev/null +++ b/openspec/changes/codex-fleet-ios-pages-design-pass-2026-05-15/CHANGE.md @@ -0,0 +1,67 @@ +--- +base_root_hash: f43dddb0 +slug: codex-fleet-ios-pages-design-pass-2026-05-15 +--- + +# CHANGE · codex-fleet-ios-pages-design-pass-2026-05-15 + +## §P proposal +# iOS background chrome + design polish + live indicators across all 5 fleet pages + +## Problem + +All 5 fleet pages (fleet/waves/review/watcher/plan) already partially use the iOS palette (#007AFF · #34C759 · #FF3B30 · #FF9500) in their pills, chips, and status badges — but the PAGE-LEVEL chrome is still plain-black with no rounded card background, inconsistent header treatment, no live indicators that visually signal the data is fresh, and (on fleet) huge unused right-side space because ACTIVE/RESERVE stack vertically inside a fixed ~85-col card. The 'iOS palette · rounded cards' note in the watcher footer hints at the intent but the page bodies haven't been wrapped in iOS card chrome. This plan opens 5 parallel lanes — one per page — each adding a new _ios_design.rs ratatui module that delivers (a) an iOS-styled outer page card with palette gradient + 1px rounded border, (b) a consistent header strip matching the watcher footer palette stripe, (c) refined inner hierarchy and column-fill so no pane wastes width, and (d) an animated LiveIndicator sub-widget that pulses on tick. Wiring each new module into its crate's main.rs is intentionally OUT OF SCOPE here — that ships in a follow-up integration plan once all 5 land, so the 5 lanes have zero file_scope contention. + +## Acceptance criteria + +- All 5 tasks have depends_on=[] and file_scope disjoint — no two tasks list the same file. +- Each task lands a single NEW .rs module file inside its target crate; no edits to existing main.rs / lib.rs / shared helpers in this plan. +- Each module exports a public IosPageDesign ratatui Widget whose render(frame, area, state) consistently uses the iOS palette (#007AFF accent, #34C759 success, #FF3B30 destructive, #FF9500 warning) for status pills, headings, and dividers. +- Each module embeds a public LiveIndicator sub-widget that takes a tick counter / Instant and renders an animated state — pulsing dot when fresh (<2s since last update), steady when idle, fade/dim when stale (>10s). +- Each new module compiles standalone via cargo check -p and ships one insta snapshot test for the fresh-tick state and one for the stale-tick state. +- Each subtask description points at the matching reference screenshot so the agent can match palette/spacing/hierarchy intent. + +## Sub-tasks + +### Sub-task 0: fleet page · iOS bg + width-fill + live indicator + +Create rust/fleet-state/src/ios_page_design.rs implementing the full iOS-styled fleet cockpit page. Match the existing fleet cockpit content (ACTIVE / RESERVE / FOOTER sections currently rendered by scripts/codex-fleet/fleet-tick.sh into /tmp/claude-viz/live-fleet-state.txt) but: (1) wrap the page in a rounded iOS outer card with the palette gradient header, (2) lay out ACTIVE | RESERVE as two SIDE-BY-SIDE cards at panel width >= 180 cols (vertical fallback below 180) so the cockpit fills the pane instead of leaving the right ~60% black, (3) fix the white-bar artifact in the WORKING ON column by computing it from the actual claimed-task text, not a fixed-width sentinel, (4) add a LiveIndicator pulsing dot at the header that ticks every 1s. Snapshot tests: wide layout (200 cols), narrow layout (90 cols), fresh tick, stale tick. Do NOT touch fleet-state/main.rs or scripts/codex-fleet/fleet-tick.sh in this plan. + +File scope: rust/fleet-state/src/ios_page_design.rs + +### Sub-task 1: waves page · iOS bg + spawn-timeline polish + live indicator + +Create rust/fleet-waves/src/ios_page_design.rs implementing the iOS-styled waves spawn-timeline page. Match Image #22's content (W1..Wn wave cards each showing N tasks, done|partial|waiting state, progress rails) but wrap the whole page in a rounded iOS outer card with a header strip showing plan slug + 'parallel execution · live' badge + LiveIndicator. Wave cards become consistent iOS rounded cards with palette-mapped status: done=#34C759, partial=#FF9500, waiting=#FF3B30 outline, ready=#007AFF. Inner progress rails use the iOS green-fill style. Add a MAX PARALLEL / claimed / done / available counters strip in a single rounded sub-card. Snapshot tests: 8-wave layout, fresh+stale ticks. Do NOT touch fleet-waves/main.rs or scripts/codex-fleet/waves-anim-generic.sh. + +File scope: rust/fleet-waves/src/ios_page_design.rs + +### Sub-task 2: review page · iOS bg + approval queue polish + live indicator + +Create rust/fleet-ui/src/review_ios_page_design.rs implementing the iOS-styled review approval queue page. Match Image #24's content (REV-xxx card with risk/auth pills, AUTO-REVIEWER RATIONALE block, FILES TOUCHED list, A/V/D action row, Recent decisions sidebar) but wrap in rounded iOS outer card with palette stripe. The risk pill colors must map: low=#34C759, medium=#FF9500, high=#FF3B30; auth pill uses #007AFF for high, #34C759 for low. Recent-decisions chips use the same mapping. Add a LiveIndicator pulsing at the queue header showing 'auto-reviewer on · last '. Snapshot tests: pending REV card present, empty queue, fresh+stale ticks. Do NOT touch fleet-ui/lib.rs or any existing fleet-ui review code in this plan. + +File scope: rust/fleet-ui/src/review_ios_page_design.rs + +### Sub-task 3: watcher page · iOS bg + cap-pool polish + live indicator + +Create rust/fleet-watcher/src/ios_page_design.rs implementing the iOS-styled fleet-watcher page. Match Image #25's content exactly (FLEET WATCHER header, PANES/CAPPED/SWAPPED/RANKED 4-up summary cards, ACCOUNT POOL healthy/capped pills, FLEET PANES table, CAP POOL burned-accounts table with reset ETA, RECENT ACTIVITY log) but wrap in rounded iOS outer card with the palette footer stripe already mentioned in the bottom of Image #25 ('iOS palette · #007AFF / #34C759 / #FF3B30 / #FF9500 · rounded cards'). All status pills use the canonical palette: working=#007AFF, idle=gray, approval=#FF9500, capped/exhausted=#FF3B30. Add a LiveIndicator near 'last sweep · next in ' that pulses on each sweep. Snapshot tests: idle fleet, with-capped, fresh+stale ticks. Do NOT touch fleet-watcher/main.rs or scripts/codex-fleet/watcher-board.sh. + +File scope: rust/fleet-watcher/src/ios_page_design.rs + +### Sub-task 4: plan page · iOS bg + active-now + wave-strip + recent-merges polish + live indicator + +Create rust/fleet-plan-tree/src/ios_page_design.rs implementing the iOS-styled plan-tree page. Match Image #21's content (PLAN TREE header showing plan slug + N done/claimed/available, ACTIVE NOW agents-on-Colony-tasks list, WAVES W1->Wn strip with working/done/idle pills, RECENT MERGES git-log-oneline list at bottom) but wrap in rounded iOS outer card. ACTIVE NOW rows become palette-mapped: working=#007AFF dot, idle=gray, done=#34C759. WAVES strip pills follow waves page palette. RECENT MERGES list gets a subtle iOS-style left border accent (#007AFF). Add a LiveIndicator near the PLAN TREE header pulsing every 1s when fleet-data refresh is live. Snapshot tests: small plan (3 tasks), large plan (18 tasks), fresh+stale ticks. Do NOT touch fleet-plan-tree/main.rs or scripts/codex-fleet/plan-tree-anim.sh. + +File scope: rust/fleet-plan-tree/src/ios_page_design.rs + + +## §S delta +op|target|row +-|-|- + +## §T tasks +id|status|task|cites +-|-|-|- + +## §B bugs +id|status|task|cites +-|-|-|- diff --git a/openspec/changes/codex-fleet-overlay-modulesplit-2026-05-14/CHANGE.md b/openspec/changes/codex-fleet-overlay-modulesplit-2026-05-14/CHANGE.md index e2e426e..1e190a3 100644 --- a/openspec/changes/codex-fleet-overlay-modulesplit-2026-05-14/CHANGE.md +++ b/openspec/changes/codex-fleet-overlay-modulesplit-2026-05-14/CHANGE.md @@ -8,71 +8,51 @@ slug: codex-fleet-overlay-modulesplit-2026-05-14 ## §P proposal # Split rust/fleet-ui/src/overlay.rs into per-widget module files for parallel evolvability -## Motivation +## Problem -Phase 5 (codex-fleet-overlays-phase5-2026-05-14) lands all four iOS overlay widgets — ContextMenu, Spotlight, ActionSheet, SessionSwitcher — inlined into a single file at `rust/fleet-ui/src/overlay.rs`. That monolith ships a coherent first cut, but every subsequent widget tweak serializes behind a `task_claim_file` lock on overlay.rs. Four panes cannot edit four widgets concurrently; the fleet degenerates into a single-writer queue any time the overlays are in scope. This change splits each widget into its own module file so future widget evolution parallelizes across panes. - -## Scope - -Code-organization only. No behavior change, no visual change, no API change beyond the internal module path. All existing public re-exports (`fleet_ui::overlay::ContextMenu`, `fleet_ui::overlay::Spotlight`, etc.) continue to resolve. All four insta snapshots remain byte-identical. +Phase 5 (codex-fleet-overlays-phase5-2026-05-14) lands ContextMenu, Spotlight, ActionSheet, and SessionSwitcher as four widgets inlined into a single file: rust/fleet-ui/src/overlay.rs. While that monolith ships a coherent first cut, every future widget tweak — a Spotlight UX change, a SessionSwitcher card refresh, a ContextMenu palette swap — serializes behind a `task_claim_file` lock on overlay.rs. Four panes cannot edit four widgets concurrently; the fleet collapses to a single-writer queue any time the overlays are in scope. This plan, which runs after phase5's sub-0 (ContextMenu widget) ships, splits overlay.rs into a module tree where each widget owns its own file (`overlay/context_menu.rs`, `overlay/spotlight.rs`, `overlay/action_sheet.rs`, `overlay/session_switcher.rs`) and overlay.rs shrinks to a `mod` table plus the shared helpers (`centered_overlay`, `render_overlay`, `card_shadow`). Result: future widget changes can parallelize across four panes because they no longer share a file claim. ## Acceptance criteria -- `rust/fleet-ui/src/overlay/context_menu.rs` exists and contains only the ContextMenu widget + its tests. -- `rust/fleet-ui/src/overlay/spotlight.rs` exists and contains only the Spotlight widget + SpotlightState + its tests. -- `rust/fleet-ui/src/overlay/action_sheet.rs` exists and contains only the ActionSheet widget + its tests. -- `rust/fleet-ui/src/overlay/session_switcher.rs` exists and contains only the SessionSwitcher widget + its tests. -- `rust/fleet-ui/src/overlay.rs` becomes a mod table plus shared helpers (`centered_overlay`, `render_overlay`, `card_shadow`) and re-exports — no widget bodies remain. -- `cargo test -p fleet-ui` is green; the four overlay snapshot tests pass byte-identical. - -## Deltas - -New files: -- `rust/fleet-ui/src/overlay/context_menu.rs` — ContextMenu widget + inline tests -- `rust/fleet-ui/src/overlay/spotlight.rs` — Spotlight + SpotlightState + inline tests -- `rust/fleet-ui/src/overlay/action_sheet.rs` — ActionSheet widget + inline tests -- `rust/fleet-ui/src/overlay/session_switcher.rs` — SessionSwitcher widget + inline tests - -Modified files: -- `rust/fleet-ui/src/overlay.rs` — shrinks from full widget bodies down to `pub mod` declarations, shared helpers (`centered_overlay`, `render_overlay`, `card_shadow`), and re-exports. +- rust/fleet-ui/src/overlay/context_menu.rs exists and contains ONLY the ContextMenu widget plus its unit tests. +- rust/fleet-ui/src/overlay/spotlight.rs exists and contains ONLY the Spotlight widget + SpotlightState plus its unit tests. +- rust/fleet-ui/src/overlay/action_sheet.rs exists and contains ONLY the ActionSheet widget plus its unit tests. +- rust/fleet-ui/src/overlay/session_switcher.rs exists and contains ONLY the SessionSwitcher widget plus its unit tests. +- rust/fleet-ui/src/overlay.rs becomes a module tree (`pub mod context_menu;`, `pub mod spotlight;`, `pub mod action_sheet;`, `pub mod session_switcher;`) plus shared helpers (centered_overlay, render_overlay, card_shadow) and re-exports — no widget bodies remain. +- All four existing insta snapshot tests (overlay_context_menu, overlay_spotlight, overlay_action_sheet, overlay_session_switcher) still pass after the move; snapshot .snap files move alongside their test files. ## Sub-tasks ### Sub-task 0: Split ContextMenu into rust/fleet-ui/src/overlay/context_menu.rs -Create the new file and move the ContextMenu widget + inline tests out of overlay.rs. Add `pub mod context_menu;` + re-export to overlay.rs. +Create rust/fleet-ui/src/overlay/context_menu.rs and move the ContextMenu struct, its impl, and its inline unit/snapshot tests out of overlay.rs into the new file. Update overlay.rs to add `pub mod context_menu;` and re-export `ContextMenu` so downstream `use fleet_ui::overlay::ContextMenu;` keeps working. If the snapshot test currently lives in rust/fleet-ui/tests/overlay_context_menu.rs, leave it in place; if any context-menu-specific test lived inline in overlay.rs, lift it to the new module file. Run `cargo test -p fleet-ui` and confirm the context_menu snapshot still matches. File scope: rust/fleet-ui/src/overlay/context_menu.rs, rust/fleet-ui/src/overlay.rs, rust/fleet-ui/tests/overlay_context_menu.rs -### Sub-task 1: Split Spotlight into rust/fleet-ui/src/overlay/spotlight.rs (depends_on_files: 0) +### Sub-task 1: Split Spotlight into rust/fleet-ui/src/overlay/spotlight.rs -Create the new file and move Spotlight + SpotlightState out of overlay.rs. Shared overlay.rs claim serialized by `task_claim_file`. +Create rust/fleet-ui/src/overlay/spotlight.rs and move Spotlight + SpotlightState + their impls + inline tests out of overlay.rs into the new file. If sub-0 has already added `pub mod spotlight;` to overlay.rs's mod table, no overlay.rs edit is needed here; otherwise add the mod line and the re-export. File-level claim on overlay.rs is shared with sub-0/2/3 — `task_claim_file` serializes the actual writes, but dispatch is parallel. Run `cargo test -p fleet-ui` and confirm overlay_spotlight snapshot still passes. File scope: rust/fleet-ui/src/overlay/spotlight.rs, rust/fleet-ui/tests/overlay_spotlight.rs -### Sub-task 2: Split ActionSheet into rust/fleet-ui/src/overlay/action_sheet.rs (depends_on_files: 0) +### Sub-task 2: Split ActionSheet into rust/fleet-ui/src/overlay/action_sheet.rs -Create the new file and move ActionSheet out of overlay.rs. Shared overlay.rs claim serialized by `task_claim_file`. +Create rust/fleet-ui/src/overlay/action_sheet.rs and move the ActionSheet widget + its inline tests out of overlay.rs into the new file. If sub-0 has already added `pub mod action_sheet;` to overlay.rs, no overlay.rs edit is needed here; otherwise add the mod line and the re-export. Shares overlay.rs with sub-0/1/3 via `task_claim_file`. Run `cargo test -p fleet-ui` and confirm overlay_action_sheet snapshot still passes. File scope: rust/fleet-ui/src/overlay/action_sheet.rs, rust/fleet-ui/tests/overlay_action_sheet.rs -### Sub-task 3: Split SessionSwitcher into rust/fleet-ui/src/overlay/session_switcher.rs (depends_on_files: 0) +### Sub-task 3: Split SessionSwitcher into rust/fleet-ui/src/overlay/session_switcher.rs -Create the new file and move SessionSwitcher out of overlay.rs. Shared overlay.rs claim serialized by `task_claim_file`. +Create rust/fleet-ui/src/overlay/session_switcher.rs and move the SessionSwitcher widget + its inline tests out of overlay.rs into the new file. If sub-0 has already added `pub mod session_switcher;` to overlay.rs, no overlay.rs edit is needed here; otherwise add the mod line and the re-export. Shares overlay.rs with sub-0/1/2 via `task_claim_file`. Run `cargo test -p fleet-ui` and confirm overlay_session_switcher snapshot still passes. File scope: rust/fleet-ui/src/overlay/session_switcher.rs, rust/fleet-ui/tests/overlay_session_switcher.rs -### Sub-task 4: Cleanup overlay.rs (depends_on_artifacts: 0, 1, 2, 3) +### Sub-task 4: Cleanup overlay.rs — verify mod tree + remove any residual widget bodies (depends on: 0, 1, 2, 3) -Verify all four `pub mod` entries are in place, delete any residual widget bodies, re-run `cargo test -p fleet-ui`. Trivial cleanup gate. +Confirm rust/fleet-ui/src/overlay.rs now contains ONLY: (1) the four `pub mod` lines for context_menu/spotlight/action_sheet/session_switcher, (2) the shared helpers `centered_overlay`, `render_overlay`, `card_shadow`, and (3) any necessary re-exports. Delete any leftover widget code, dead imports, or stale tests. Run `cargo test -p fleet-ui` once more — all four overlay snapshots must still pass green. Final cleanup gate; trivial. File scope: rust/fleet-ui/src/overlay.rs -## Risks - -- **Snapshot test churn.** Even a stray whitespace difference between the source-moved-out-of-overlay.rs and the source-as-it-now-lives-in-context_menu.rs can shift formatting and break the insta snapshot. Mitigation: copy the widget body byte-for-byte, then run `cargo insta review` ONLY if a diff appears, and gate merge on zero unintended diffs. -- **Re-export breakage.** Downstream `use fleet_ui::overlay::ContextMenu;` paths must keep resolving. Mitigation: each sub-task adds the `pub use self::::;` re-export when it moves the widget out. -- **Concurrent edits to overlay.rs.** Sub-0/1/2/3 all touch overlay.rs's mod table. Mitigation: `task_claim_file` on overlay.rs serializes writes; dispatch stays parallel via the `depends_on_files: [0]` hint. ## §S delta op|target|row diff --git a/openspec/changes/codex-fleet-overlays-phase5-2026-05-14/CHANGE.md b/openspec/changes/codex-fleet-overlays-phase5-2026-05-14/CHANGE.md index ba0b81e..a925589 100644 --- a/openspec/changes/codex-fleet-overlays-phase5-2026-05-14/CHANGE.md +++ b/openspec/changes/codex-fleet-overlays-phase5-2026-05-14/CHANGE.md @@ -1,5 +1,5 @@ --- -base_root_hash: missing-spec-root +base_root_hash: f43dddb0 slug: codex-fleet-overlays-phase5-2026-05-14 --- diff --git a/openspec/changes/codex-fleet-tui-improvements-2026-05-15/CHANGE.md b/openspec/changes/codex-fleet-tui-improvements-2026-05-15/CHANGE.md new file mode 100644 index 0000000..7ee2941 --- /dev/null +++ b/openspec/changes/codex-fleet-tui-improvements-2026-05-15/CHANGE.md @@ -0,0 +1,118 @@ +--- +base_root_hash: f43dddb0 +slug: codex-fleet-tui-improvements-2026-05-15 +--- + +# CHANGE · codex-fleet-tui-improvements-2026-05-15 + +## §P proposal +# codex-fleet TUI improvements: supervisor classifier, cap-swap hand-off, plan validation, auto-reviewer, pane health, metrics viewer, renderer polish, inbox dedup + +## Problem + +The codex-fleet TUI is functional but has eight measurable gaps that compound throughput loss. (1) The supervisor's asking/blocked/working classifier in scripts/codex-fleet/supervisor.sh has no replayable fixtures and no documented Opus 4.7 + Sonnet tiering thresholds, so regressions in classification land silently; the 3-strike loop guard is also opaque. (2) cap-swap-daemon.sh hands a 429'd pane off to a fallback worker without an explicit contract for Colony claim transfer, worktree preservation, or env carry-over, so swapped panes sometimes orphan their claim. (3) Plan publication is unguarded — there is no validator that enforces the parallel-first rule (flat depends_on, disjoint file_scope), so bad plans deadlock workers on task_claim_file. (4) scripts/codex-fleet/auto-reviewer.sh is referenced by the dispatch protocol and the codex-fleet-dispatch skill but does not actually exist on disk — end-of-plan review is therefore manual. (5) There is no per-pane health surface — operators tail individual logs to diagnose a stuck pane; pane-health (last activity, claim state, cap-status) should be a first-class crate. (6) The supervisor metrics TSV (when written) has no live viewer, only post-hoc grep. (7) The dashboard chrome (iOS page headers in fleet-waves, fleet-state, etc) is rendered ad-hoc per crate; a shared renderer-polish layer would give consistent corner radii / hairlines / iOS-blue accent across every dashboard binary. (8) Colony attention_inbox returns duplicate-near handoffs (same task, slightly different timestamps or rationales); a dedup helper would let the orchestrator show the operator a clean list. All 12 lanes are flat-parallel — every lane edits exactly one disjoint file path (or one new disjoint set), depends_on=[] on all of them, so a fleet of 12 workers can claim and ship in parallel without task_claim_file contention. New rust crates use the workspace's fleet-* glob, so no shared rust/Cargo.toml edit is required. Soft references (Lane 5 calls Lane 4's validator at a known path; Lane 6's auto-reviewer reads Lane 7's rubric at a known path) tolerate either landing order — the consumer no-ops or warns until the producer ships. + +## Acceptance criteria + +- All 12 sub-tasks land independently as 12 separate PRs against main with depends_on=[] honored; no two PRs touch the same file path. +- After Lane 0 ships, scripts/codex-fleet/supervisor.sh contains: an explicit classifier prompt with labeled categories (working / asking / blocked / done), a documented Opus 4.7 escalation threshold, prompt-cache markers around the static system prompt, and a comment block describing the 3-strike loop guard with the exact metric that trips it. shellcheck exits 0. +- After Lane 1 ships, scripts/codex-fleet/test/classifier-fixtures/ contains at least 20 captured pane snapshots (.txt files) with sibling .label files marking the expected category. scripts/codex-fleet/test/run-classifier-replay.sh iterates the fixtures, invokes the classifier, and prints a confusion matrix; exits non-zero if accuracy < 0.85 on the captured set. +- After Lane 2 ships, cap-swap-daemon.sh has a top-of-file CONTRACT section enumerating every field that must transfer on hand-off (Colony task_id, branch, worktree path, CODEX_HOME, account email, last claim timestamp) and a smoke-test stanza that simulates a 429 against a fixture pane and asserts the claim is released cleanly. No orphaned worktrees after the simulated swap. +- After Lane 3 ships, scripts/codex-fleet/claude-spawn.sh is idempotent (re-running on a live pane is a no-op + 0 exit), accepts an inherited CODEX_FLEET_TASK_ID env var so a cap-swapped pane resumes the same Colony claim, and refuses to spawn into a pane whose @panel does not match the expected worker pattern (defensive guard). +- After Lane 4 ships, scripts/codex-fleet/lib/plan-validator.sh exists, is executable, and validates a plan.json file at a given path against three rules: (a) every sub-task's depends_on is empty unless --allow-waves is passed, (b) no two sub-tasks share a file path in file_scope, (c) acceptance_criteria is a non-empty array of strings each ≥ 40 chars. Exit codes: 0 ok, 2 warnings, 3 hard errors. +- After Lane 5 ships, plan-watcher.sh invokes plan-validator.sh on every tick against the currently-active plan and surfaces warnings/errors in /tmp/plan-watcher.log with a stable prefix ('PLAN-VALIDATE:'). Hard errors do NOT crash the watcher but DO skip dispatch for that tick. shellcheck exits 0. +- After Lane 6 ships, scripts/codex-fleet/auto-reviewer.sh exists, is executable, and on invocation reads .codex-fleet/active-plan, gathers all PRs merged for that plan slug via gh pr list, builds a review prompt using the rubric (Lane 7) and the prepass diff (Lane 7), invokes the local claude CLI in --print mode, and writes the output to /tmp/claude-viz/plan-review-.md. Supports --dry-run for offline test. +- After Lane 7 ships, scripts/codex-fleet/lib/review-rubric.md exists and documents the explicit review checklist (regression risk, scope creep against plan acceptance_criteria, anti-pattern flags, blast radius); scripts/codex-fleet/lib/review-prepass.sh exists and emits a single markdown blob with the plan's stated scope + the actual diff for every PR, ready to be piped to a model. +- After Lane 8 ships, rust/fleet-pane-health/ is a new workspace crate that builds (cargo check -p fleet-pane-health) and renders a per-pane health row (pane id, last activity age, current Colony claim if any, cap-probe cache state) using ratatui + the shared fleet-ui chrome helpers. It reads from /tmp/claude-viz/cap-probe-cache/*.json and tmux capture-pane output. No edits to existing crates. +- After Lane 9 ships, rust/fleet-metrics-viewer/ is a new workspace crate that tails a TSV path passed via --path (default /tmp/claude-viz/supervisor-metrics.tsv when present, else --no-op) and renders the last N rows as a live dashboard with iOS-style chrome. cargo check -p fleet-metrics-viewer succeeds. No edits to existing crates. +- After Lane 10 ships, rust/fleet-renderer-polish/ is a new workspace crate exposing a small library of ratatui chrome primitives (rounded_corner_block, hairline_divider, ios_status_chip, page_header_with_accent) factored from the patterns already in fleet-waves/fleet-state. cargo check -p fleet-renderer-polish succeeds; it does NOT yet replace any existing crate's chrome — adoption is a follow-up. No edits to existing crates. +- After Lane 11 ships, scripts/codex-fleet/lib/inbox-dedup.sh exists and reads JSONL from stdin (Colony attention_inbox export), groups near-duplicates by (task_id, kind, content-hash with whitespace normalized), and prints a deduped JSONL to stdout. Exit 0 always; idempotent on already-deduped input. +- No regression in existing dashboards: cargo check --workspace from rust/ still passes after all 12 lanes land. +- Every PR's final note records: branch, files changed, command + output evidence (shellcheck, cargo check, fixture replay where applicable), PR URL, MERGED state, and sandbox cleanup proof per the Guardex completion contract. + +## Sub-tasks + +### Sub-task 0: Supervisor classifier prompt + Opus/Sonnet tiering + 3-strike loop guard documentation + +Audit and rewrite scripts/codex-fleet/supervisor.sh's classifier section. Required: (1) Extract the classifier prompt (the one sent to Claude that decides working/asking/blocked/done) into a clearly delimited heredoc at the top of the script with explicit labeled categories and one example per category. (2) Add prompt-cache markers (the static system prompt portion should be inside a cache_control: ephemeral block when invoking claude --print, document the cache hit expectation in a comment). (3) Document Opus 4.7 escalation: by default route to Sonnet 4.6; escalate to Opus only when (a) the classifier itself returns 'uncertain' or (b) a pane has been flagged 'blocked' for ≥ 3 consecutive ticks. Add an env var CODEX_FLEET_FORCE_OPUS=1 override for debugging. (4) 3-strike loop guard: document the existing or add a new counter — after 3 consecutive identical classifier outputs on the same pane, the supervisor must escalate to a different action (poke pane, post Colony note, or page operator) rather than re-running the classifier. Add a top-of-file comment block describing the loop guard with the exact metric (pane id + classification + timestamp) that trips it. (5) shellcheck must remain clean. (6) No behavior change to existing daemons that source this script; only the classifier section is rewritten. file_scope: exactly scripts/codex-fleet/supervisor.sh — do NOT add fixtures (Lane 1 owns them) and do NOT touch plan-watcher.sh (Lane 5 owns it). + +File scope: scripts/codex-fleet/supervisor.sh + +### Sub-task 1: Classifier replay fixtures + harness (new test dir) + +Create scripts/codex-fleet/test/classifier-fixtures/ with at least 20 real captured pane snapshots covering each classifier category. Required: (1) Run tmux capture-pane against a variety of pane states during normal fleet operation (or use the existing pane logs under /tmp/claude-viz/*-worker-*.log) and save each snapshot as a .txt file named after the expected category (e.g. working-001.txt, asking-001.txt, blocked-001.txt, done-001.txt). (2) For each .txt, write a sibling .label file containing the single-line expected classification. (3) Cover edge cases: long log tails, ANSI-heavy output, codex CLI prompts mid-stream, plan-mode 'paste your answer' prompts, 429 rate-limit messages. (4) Write scripts/codex-fleet/test/run-classifier-replay.sh which iterates the fixtures, invokes the classifier from scripts/codex-fleet/supervisor.sh (source it and call the classifier function, or shell out to a minimal wrapper), collects the predicted vs expected label, and prints a confusion matrix + accuracy. Exit non-zero if accuracy < 0.85. (5) Make the harness deterministic — set CODEX_FLEET_FORCE_MODEL=sonnet-4-6 or similar so replays don't burn Opus. (6) shellcheck clean. file_scope: exactly the two new paths below — do NOT modify supervisor.sh (Lane 0 owns it). + +File scope: scripts/codex-fleet/test/classifier-fixtures/, scripts/codex-fleet/test/run-classifier-replay.sh + +### Sub-task 2: Cap-swap hand-off contract + worktree/claim preservation + +Harden scripts/codex-fleet/cap-swap-daemon.sh so a 429'd codex pane hands off cleanly to a fallback worker (Kiro or Claude). Required: (1) Add a top-of-file CONTRACT comment block enumerating every field that must transfer: Colony task_id, agent/* branch, worktree path, CODEX_HOME path, account email, last claim timestamp, accumulated lane context (last Colony task_post note). (2) Before triggering the swap, the daemon MUST: (a) call task_note_working or task_post with a 'swapping due to 429' marker, (b) NOT release the Colony claim — the new worker re-claims by inheriting CODEX_FLEET_TASK_ID, (c) preserve the agent/* worktree (the new worker `cd`'s into it). (3) Add a smoke-test stanza near the top of the script (commented) that simulates a 429: against a fixture pane, set CODEX_FLEET_SIMULATE_429=1, run one tick, assert the claim is preserved and the new worker starts in the same worktree. (4) Defensive: if any required env var is missing on the fallback side, the daemon must log + skip the swap rather than fire a broken worker. (5) shellcheck clean. (6) No edits to claude-spawn.sh (Lane 3 owns it). file_scope: exactly scripts/codex-fleet/cap-swap-daemon.sh. + +File scope: scripts/codex-fleet/cap-swap-daemon.sh + +### Sub-task 3: Claude fallback worker spawn polish — idempotent, claim-aware + +Polish scripts/codex-fleet/claude-spawn.sh so it cleanly handles the cap-swap inheritance case. Required: (1) Idempotent — re-running on a pane that already has a live claude worker is a 0-exit no-op (detect via tmux capture-pane checking for the claude prompt or a process check). (2) Accept CODEX_FLEET_TASK_ID env: when set, the spawned claude worker is told to immediately resume that Colony task (insert it into the prompt or the initial message). (3) Refuse to spawn into a pane whose @panel does not match an expected worker pattern (e.g. starts with [codex- or [kiro- or [claude-). Log + exit 1 cleanly on mismatch. (4) Inherit CODEX_HOME, ACCOUNT_EMAIL from caller env when present; otherwise log + fall back to defaults. (5) Add a top-of-file comment documenting the cap-swap inheritance contract (mirror of Lane 2's contract section). (6) shellcheck clean. (7) No edits to cap-swap-daemon.sh (Lane 2 owns it) or claude-worker.sh (out of scope). file_scope: exactly scripts/codex-fleet/claude-spawn.sh. + +File scope: scripts/codex-fleet/claude-spawn.sh + +### Sub-task 4: Plan flat-parallelism validator (new lib script) + +Create scripts/codex-fleet/lib/plan-validator.sh — a standalone validator for plan.json files. Required: (1) Usage: plan-validator.sh [--allow-waves]. (2) Validate three rules: (a) every sub-task's depends_on is empty UNLESS --allow-waves is passed, (b) no two sub-tasks share any file path in file_scope (note: a sub-task scope that lists a directory like 'foo/bar/' counts as overlapping with any file path under that directory), (c) acceptance_criteria is a non-empty array of strings each ≥ 40 chars. (3) Output: human-readable findings on stderr; one JSON summary on stdout with shape {ok, warnings: [...], errors: [...]}. (4) Exit codes: 0 ok, 2 warnings only, 3 hard errors. (5) Use jq for JSON parsing (jq is already a project dependency). (6) Add a self-test stanza near the top: a small inline plan.json fixture validates ok, another fails on overlapping file_scope. (7) shellcheck clean, executable bit set. (8) file_scope: exactly scripts/codex-fleet/lib/plan-validator.sh — do NOT wire it into plan-watcher.sh (Lane 5 owns that). + +File scope: scripts/codex-fleet/lib/plan-validator.sh + +### Sub-task 5: Wire plan-validator into plan-watcher.sh on every tick + +Edit scripts/codex-fleet/plan-watcher.sh so each tick (when looping with --loop) invokes the plan validator against the currently-pinned plan. Required: (1) Read .codex-fleet/active-plan to get the slug; resolve plan.json at openspec/plans//plan.json. (2) Invoke scripts/codex-fleet/lib/plan-validator.sh on that path. If the validator script is missing (Lane 4 not yet shipped), log 'PLAN-VALIDATE: skipped (validator missing)' and continue — never crash. (3) On exit code 0: log 'PLAN-VALIDATE: ok' once per tick at INFO. (4) On exit code 2 (warnings): log 'PLAN-VALIDATE: WARN ' with the JSON summary on the next line; continue dispatching. (5) On exit code 3 (hard errors): log 'PLAN-VALIDATE: ERROR ' with the JSON summary, SKIP dispatch for that tick, continue the loop. (6) All log lines go to /tmp/plan-watcher.log with the stable 'PLAN-VALIDATE:' prefix so a grep can extract them. (7) shellcheck clean. (8) Smoke test: run one tick locally against the current openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.json — should be ok. (9) file_scope: exactly scripts/codex-fleet/plan-watcher.sh. + +File scope: scripts/codex-fleet/plan-watcher.sh + +### Sub-task 6: Auto-reviewer daemon scaffold (file is currently MISSING) + +Create scripts/codex-fleet/auto-reviewer.sh — the end-of-plan auto-reviewer that the codex-fleet-dispatch protocol references but does not currently exist on disk. Required: (1) On invocation, read .codex-fleet/active-plan to get the slug. (2) Use gh pr list --search 'head:agent/* ' or similar to find every PR linked to this plan (or read openspec/plans//plan.json and harvest PR URLs from completed_summary fields). (3) For each PR, fetch the diff (gh pr diff ). (4) Build a review prompt using the rubric at scripts/codex-fleet/lib/review-rubric.md (Lane 7) and the prepass output from scripts/codex-fleet/lib/review-prepass.sh (Lane 7) — if either is missing, fall back to a built-in minimal rubric and inline diff dump, and log a warning. (5) Invoke claude --print --permission-mode bypassPermissions with the assembled prompt; capture stdout. (6) Write the review to /tmp/claude-viz/plan-review-.md (mkdir -p the parent). (7) Support --dry-run (do everything except the claude invocation; print the prompt that would be sent). (8) Support --plan-slug override for ad-hoc runs. (9) shellcheck clean, executable bit set. (10) file_scope: exactly scripts/codex-fleet/auto-reviewer.sh — do NOT touch the rubric or prepass (Lane 7 owns them). + +File scope: scripts/codex-fleet/auto-reviewer.sh + +### Sub-task 7: Review rubric + diff prepass (two new lib files) + +Create the two artifacts the auto-reviewer (Lane 6) consumes. Required: (1) scripts/codex-fleet/lib/review-rubric.md — a markdown checklist with four sections: REGRESSION RISK (does the diff change behavior beyond what the plan promised?), SCOPE CREEP (does any sub-task touch files outside its declared file_scope?), ANTI-PATTERN FLAGS (CLAUDE.md violations: backwards-compat shims, dead comments, premature abstractions, error-handling for impossible states), BLAST RADIUS (config/CI/migration/db touches; shared helper edits). Each section gets 3-5 bullets the reviewer model can answer yes/no/n-a against. Keep total length under 2k chars so it caches well. (2) scripts/codex-fleet/lib/review-prepass.sh — usage: review-prepass.sh . Output: a single markdown blob on stdout with sections: ## Plan acceptance criteria (verbatim from plan.json), ## Sub-task scope claims (per-lane file_scope), ## PR diffs (one fenced block per PR, fetched via gh pr diff). Limit each diff to 200 lines (head -200) to keep the prompt bounded. shellcheck clean. (3) Both files executable bit set where applicable (.md no, .sh yes). (4) file_scope: exactly the two new lib paths below — do NOT touch auto-reviewer.sh (Lane 6 owns it). + +File scope: scripts/codex-fleet/lib/review-rubric.md, scripts/codex-fleet/lib/review-prepass.sh + +### Sub-task 8: Pane health crate (new rust workspace crate) + +Create rust/fleet-pane-health/ as a new workspace crate (auto-picked-up by the fleet-* glob in rust/Cargo.toml). Required: (1) Cargo.toml: name 'fleet-pane-health', version 0.0.1, edition 2021, ratatui = '0.30', crossterm = '0.29', fleet-ui = { path = '../fleet-ui' } for shared chrome, fleet-data = { path = '../fleet-data' } if needed, [[bin]] name 'fleet-pane-health' path 'src/main.rs'. (2) src/main.rs: a ratatui app that polls every 1s and renders a vertical list of per-pane health rows. Each row: pane id (e.g. '%337'), pane @panel label, last-activity age (now - mtime of /tmp/claude-viz/{kiro,claude,codex}-worker-.log), current Colony claim state (parsed from a JSON dump at /tmp/claude-viz/colony-claims.json if present, else 'unknown'), cap-probe state (read /tmp/claude-viz/cap-probe-cache/.json mtime + ok/429). (3) Use the existing fleet-ui chrome (page header, hairline dividers, iOS-blue accent). (4) Quit on q or Esc. (5) cargo check -p fleet-pane-health succeeds from rust/. (6) Read-only — no writes to /tmp. (7) file_scope: rust/fleet-pane-health/Cargo.toml and rust/fleet-pane-health/src/main.rs — do NOT edit any existing crate or rust/Cargo.toml (the glob picks it up). + +File scope: rust/fleet-pane-health/Cargo.toml, rust/fleet-pane-health/src/main.rs + +### Sub-task 9: Metrics TSV viewer crate (new rust workspace crate) + +Create rust/fleet-metrics-viewer/ as a new workspace crate. Required: (1) Cargo.toml: name 'fleet-metrics-viewer', version 0.0.1, edition 2021, ratatui = '0.30', crossterm = '0.29', fleet-ui = { path = '../fleet-ui' }, [[bin]] name 'fleet-metrics-viewer' path 'src/main.rs'. (2) src/main.rs: a ratatui live tail of a TSV file. CLI: --path (default /tmp/claude-viz/supervisor-metrics.tsv if present, else exit 0 with an 'idle (no metrics file yet)' message). (3) Render the last 30 rows in a scrollable table with iOS-style chrome. Auto-refresh every 500ms via crossterm event poll + file mtime check. (4) Column headers parsed from the TSV's first line. (5) Use the existing fleet-ui chrome helpers for headers and dividers. (6) Quit on q or Esc; PgUp/PgDn to scroll. (7) cargo check -p fleet-metrics-viewer succeeds. (8) file_scope: rust/fleet-metrics-viewer/Cargo.toml and rust/fleet-metrics-viewer/src/main.rs — do NOT edit any existing crate. + +File scope: rust/fleet-metrics-viewer/Cargo.toml, rust/fleet-metrics-viewer/src/main.rs + +### Sub-task 10: Renderer polish crate (shared chrome primitives library) + +Create rust/fleet-renderer-polish/ as a new workspace crate exposing a small library of ratatui chrome primitives factored from patterns already present in fleet-waves/fleet-state. Required: (1) Cargo.toml: name 'fleet-renderer-polish', version 0.0.1, edition 2021, ratatui = '0.30', [lib] path 'src/lib.rs'. (2) src/lib.rs: pub fn rounded_corner_block(title: &str) -> Block — returns a ratatui Block with rounded corners and a one-cell padding; pub fn hairline_divider(width: u16) -> Line — a single line of '─' in fg=#3A3A3C; pub fn ios_status_chip(label: &str, color: IosColor) -> Span — a small chip like ' LIVE ' in fg-only ANSI matching the project's iOS palette (enum IosColor { Green, Blue, Yellow, Red, Gray }); pub fn page_header_with_accent(title: &str, accent: IosColor) -> Vec — a two-line iOS page header (bold title + accent underline). (3) Each fn has a doc comment with one usage example. (4) cargo check -p fleet-renderer-polish succeeds. (5) Library only — no main.rs, no binary. (6) Do NOT touch any existing crate; adoption is a separate follow-up. (7) file_scope: rust/fleet-renderer-polish/Cargo.toml and rust/fleet-renderer-polish/src/lib.rs. + +File scope: rust/fleet-renderer-polish/Cargo.toml, rust/fleet-renderer-polish/src/lib.rs + +### Sub-task 11: Attention inbox dedup helper (new lib script) + +Create scripts/codex-fleet/lib/inbox-dedup.sh — a stdin-to-stdout filter that dedupes Colony attention_inbox output. Required: (1) Reads JSONL on stdin (one JSON object per line; Colony's attention_inbox export shape: task_id, kind, content, timestamp, agent). (2) Groups near-duplicates by a composite key: (task_id, kind, content-hash-with-whitespace-normalized). The content hash normalizes by lowercasing, collapsing runs of whitespace to single spaces, and stripping leading/trailing whitespace before hashing (sha1 of normalized content). (3) For each group, emit only the latest (largest timestamp) entry on stdout. (4) Idempotent: running it twice yields the same output. (5) Pure bash + jq + sha1sum — no python. (6) Add a self-test stanza near the top: pipe an inline JSONL fixture with three duplicates through the script, assert the output count is correct. (7) shellcheck clean, executable bit set. (8) file_scope: exactly scripts/codex-fleet/lib/inbox-dedup.sh. + +File scope: scripts/codex-fleet/lib/inbox-dedup.sh + + +## §S delta +op|target|row +-|-|- + +## §T tasks +id|status|task|cites +-|-|-|- + +## §B bugs +id|status|task|cites +-|-|-|- diff --git a/openspec/changes/fleet-tui-ratatui-port-2026-05-14/design.md b/openspec/changes/fleet-tui-ratatui-port-2026-05-14/design.md index 1f7b7ac..c29e956 100644 --- a/openspec/changes/fleet-tui-ratatui-port-2026-05-14/design.md +++ b/openspec/changes/fleet-tui-ratatui-port-2026-05-14/design.md @@ -8,7 +8,7 @@ The fleet has two layers and only one moves. |----------------|--------------------------------------------------|----------------| | Orchestration | `full-bringup.sh`, `cap-swap-daemon.sh`, `force-claim.sh`, `cap-probe.sh`, `claim-release-supervisor.sh`, `style-tabs.sh` | **stays bash** | | Rendering | `watcher-board.sh`, `fleet-state-anim.sh`, `plan-tree-anim.sh`, `waves-anim*.sh`, `fleet-tick.sh` (rendering half) | **becomes Rust (ratatui)** | -| Data plumbing | `plan.json` parsers, `codex-auth list` parsers, tmux pane introspection | **becomes Rust (typed)** | +| Data plumbing | `plan.json` parsers, `agent-auth list` parsers, tmux pane introspection | **becomes Rust (typed)** | `style-tabs.sh` *renders* (it sets tmux options + bindings) but it operates on the tmux server, not on a frame buffer. It stays bash. @@ -49,7 +49,7 @@ rust/ │ └── overlay.rs centered_overlay(area, w, h); Clear + bordered popup ├── fleet-data/ library crate — typed data layer │ ├── plan.rs serde structs for openspec/plans/*/plan.json -│ ├── accounts.rs codex-auth list parser → Account { email, 5h%, weekly%, … } +│ ├── accounts.rs agent-auth list parser → Account { email, 5h%, weekly%, … } │ └── panes.rs tmux introspection, PaneState enum ├── fleet-watcher/ bin replacing watcher-board.sh ├── fleet-state/ bin replacing fleet-state-anim.sh + fleet-tick.sh (render half) @@ -90,7 +90,7 @@ Each module ships with `insta` snapshot tests so the existing ### Phase 2 — `fleet-data` typed data layer -`plan.rs` (`plan.json` deser), `accounts.rs` (`codex-auth list` +`plan.rs` (`plan.json` deser), `accounts.rs` (`agent-auth list` parser), `panes.rs` (tmux introspection + `PaneState` enum). First port: keep scraping `tmux capture-pane` for pane classification. A follow-up plan replaces scraping with a real signal (Colony presence diff --git a/openspec/changes/fleet-tui-ratatui-port-2026-05-14/proposal.md b/openspec/changes/fleet-tui-ratatui-port-2026-05-14/proposal.md index 4d515dd..9244793 100644 --- a/openspec/changes/fleet-tui-ratatui-port-2026-05-14/proposal.md +++ b/openspec/changes/fleet-tui-ratatui-port-2026-05-14/proposal.md @@ -36,7 +36,7 @@ boundary is: anything that *renders a frame* moves to Rust; anything that widgets with section headers, right-aligned keybind hints, and a selected-row accent — surfaces that are clumsy to build in tmux. 4. **Typed data layer.** Every dashboard currently re-parses - `plan.json`, `codex-auth list`, and tmux scrollback with scripts. + `plan.json`, `agent-auth list`, and tmux scrollback with scripts. Centralising those into `serde` structs eliminates duplicated regex. ## Out of scope diff --git a/openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md b/openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md index fe661e4..06059a8 100644 --- a/openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md +++ b/openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md @@ -33,7 +33,7 @@ Once all three boxes are ticked by the operator, Phase 1 is unblocked. - [ ] Scaffold `rust/fleet-data/` library crate, register in workspace `Cargo.toml` - [ ] `plan.rs` — serde structs for `openspec/plans/*/plan.json`; `load(path)` + `newest_plan(repo_root)` helpers; fixture-based test -- [ ] `accounts.rs` — `codex-auth list` parser → `Account` struct; fixture-based test +- [ ] `accounts.rs` — `agent-auth list` parser → `Account` struct; fixture-based test - [ ] `panes.rs` — tmux pane introspection + `PaneState` enum; classification test against captured scrollback fixtures ## Phase 3 — `fleet-watcher` (proves the framework) diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/README.md new file mode 100644 index 0000000..0fbc735 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/README.md @@ -0,0 +1,30 @@ +# Plan Workspace: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 + +This folder stores durable planning artifacts before implementation changes. + +## Shared files +- `summary.md` +- `checkpoints.md` +- `phases.md` +- `open-questions.md` +- `coordinator-prompt.md` +- `kickoff-prompts.md` + +## Role folders +- `planner/` +- `architect/` +- `critic/` +- `executor/` +- `writer/` +- `verifier/` + +When Codex or Claude hits an unresolved question that should survive chat, add it to `open-questions.md` as an unchecked `- [ ]` item. + +Each role folder contains OpenSpec-style artifacts: +- `.openspec.yaml` +- `prompt.md` (copy/paste role prompt) +- `proposal.md` +- `tasks.md` (Spec / Tests / Implementation / Checkpoints checklists) +- `specs//spec.md` +Planner also gets `plan.md`; executor also gets `checkpoints.md`. +Planner plans should follow `openspec/plan/PLANS.md`. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/.openspec.yaml b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/.openspec.yaml new file mode 100644 index 0000000..36a31ee --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/.openspec.yaml @@ -0,0 +1,9 @@ +schema: 1 +plan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 +role: architect +status: draft +artifacts: + prompt: prompt.md + proposal: proposal.md + tasks: tasks.md + spec: specs/architect/spec.md diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/README.md new file mode 100644 index 0000000..1e1c275 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/README.md @@ -0,0 +1,12 @@ +# architect + +Role workspace for `architect`. + +Default artifacts: +- `.openspec.yaml` +- `prompt.md` +- `proposal.md` +- `tasks.md` +- `specs//spec.md` + +Use this folder for role notes, artifacts, and status updates. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/prompt.md new file mode 100644 index 0000000..dd794b5 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/prompt.md @@ -0,0 +1,34 @@ +# architect Prompt + +You are the `architect` role for OpenSpec plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Complete only this role's assigned checklist and leave compact evidence for the coordinator. + +## Source of truth + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/tasks.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/proposal.md` + +## Before edits + +1. Confirm branch/worktree with `git status --short --branch`. +2. Claim every touched file before editing: + - Prefer Colony `task_claim_file` when an active task exists. + - Otherwise run `gx locks claim --branch `. +3. Stay inside assigned files/modules; coordinate before touching shared paths. + +## Working rules + +- Update `architect/tasks.md` as each item completes. +- Record durable unresolved questions in `open-questions.md`. +- Keep handoffs short: files changed, behavior touched, verification, risks. +- Do not revert another agent's edits. + +## Cleanup + +Only the owner/finalizer lane runs `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. If blocked, append `BLOCKED:` with branch, task, blocker, next, evidence. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/proposal.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/proposal.md new file mode 100644 index 0000000..7e25166 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/proposal.md @@ -0,0 +1,15 @@ +# Proposal: architect (agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00) + +## Why + +Summarize why this role's work is required for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## What Changes + +- [ ] List the planned role-specific changes + +## Impact + +- Scope: +- Risks: +- Dependencies: diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/specs/architect/spec.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/specs/architect/spec.md new file mode 100644 index 0000000..fac7cab --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/specs/architect/spec.md @@ -0,0 +1,10 @@ +# Capability Spec: architect + +## ADDED Requirements + +### Requirement: architect responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +This role MUST define and deliver its scoped outputs with evidence. + +#### Scenario: Role executes assigned scope +- **WHEN** the role begins execution for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- **THEN** it follows `tasks.md` and records evidence for completion diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/tasks.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/tasks.md new file mode 100644 index 0000000..d913617 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/architect/tasks.md @@ -0,0 +1,33 @@ +# architect tasks + +## 1. Spec + +- [ ] 1.1 Define ownership boundaries, interfaces, and artifact responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- [ ] 1.2 Validate architecture constraints and non-functional requirements coverage + +## 2. Tests + +- [ ] 2.1 Define architectural verification checkpoints (integration boundaries, failure modes, compatibility) +- [ ] 2.2 Validate that acceptance criteria map to concrete architecture decisions + +## 3. Implementation + +- [ ] 3.1 Review plan for strongest antithesis/tradeoff tensions +- [ ] 3.2 Propose synthesis path and guardrails for implementation teams +- [ ] 3.3 Record architecture sign-off notes for downstream execution + +## 4. Checkpoints + +- [ ] [A1] READY - Architecture review checkpoint + +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark `N/A` when solo. +- [ ] 5.3 Record unresolved plan questions in `../open-questions.md`, or mark `N/A` when none. + +## 6. Cleanup + +- [ ] 6.1 If this lane owns finalization, run `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. +- [ ] 6.2 Record PR URL + final `MERGED` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or append `BLOCKED:` and stop. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md new file mode 100644 index 0000000..05157be --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md @@ -0,0 +1,4 @@ +# Plan Checkpoints: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 + +Chronological checkpoint log for all roles. + diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/coordinator-prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/coordinator-prompt.md new file mode 100644 index 0000000..bea2f21 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/coordinator-prompt.md @@ -0,0 +1,41 @@ +# Master Coordinator Prompt + +You are the coordinator for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Drive this plan from draft to execution-ready status with strict checkpoint discipline and no scope drift. + +## Source-of-truth artifacts + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/plan.md` +- role `prompt.md` files for copy/paste helper startup +- role `tasks.md` files for planner/architect/critic/executor/writer/verifier + +## Coordinator responsibilities + +1. Keep checkpoints current in each role `tasks.md` and root `checkpoints.md`. +2. Route unresolved questions and branching decisions into `open-questions.md`. +3. Ensure each role has explicit acceptance criteria and verification evidence. +4. Prevent implementation from starting before planning gates are complete. +5. Keep handoffs concise: files changed, behavior touched, verification output, risks. + +## Wave-splitting decision (optional) + +Create wave prompts in `kickoff-prompts.md` only when at least one applies: + +- 3+ independent implementation lanes can run in parallel. +- Runtime cutover/rollback sequencing needs explicit lane ownership. +- Risk is high enough that bounded execution packets reduce coordination mistakes. + +If wave splitting is not needed, keep execution under a single owner with normal role checkpoints. + +## Exit criteria + +- All role checkpoints required for planning are done. +- Execution lanes (if any) have clear ownership boundaries. +- `open-questions.md` captures unresolved decisions that still need answers. +- Verification plan and rollback expectations are explicit and testable. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/.openspec.yaml b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/.openspec.yaml new file mode 100644 index 0000000..428eb40 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/.openspec.yaml @@ -0,0 +1,9 @@ +schema: 1 +plan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 +role: critic +status: draft +artifacts: + prompt: prompt.md + proposal: proposal.md + tasks: tasks.md + spec: specs/critic/spec.md diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/README.md new file mode 100644 index 0000000..5b5c877 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/README.md @@ -0,0 +1,12 @@ +# critic + +Role workspace for `critic`. + +Default artifacts: +- `.openspec.yaml` +- `prompt.md` +- `proposal.md` +- `tasks.md` +- `specs//spec.md` + +Use this folder for role notes, artifacts, and status updates. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/prompt.md new file mode 100644 index 0000000..04e1342 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/prompt.md @@ -0,0 +1,34 @@ +# critic Prompt + +You are the `critic` role for OpenSpec plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Complete only this role's assigned checklist and leave compact evidence for the coordinator. + +## Source of truth + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/tasks.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/proposal.md` + +## Before edits + +1. Confirm branch/worktree with `git status --short --branch`. +2. Claim every touched file before editing: + - Prefer Colony `task_claim_file` when an active task exists. + - Otherwise run `gx locks claim --branch `. +3. Stay inside assigned files/modules; coordinate before touching shared paths. + +## Working rules + +- Update `critic/tasks.md` as each item completes. +- Record durable unresolved questions in `open-questions.md`. +- Keep handoffs short: files changed, behavior touched, verification, risks. +- Do not revert another agent's edits. + +## Cleanup + +Only the owner/finalizer lane runs `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. If blocked, append `BLOCKED:` with branch, task, blocker, next, evidence. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/proposal.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/proposal.md new file mode 100644 index 0000000..4e57e6c --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/proposal.md @@ -0,0 +1,15 @@ +# Proposal: critic (agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00) + +## Why + +Summarize why this role's work is required for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## What Changes + +- [ ] List the planned role-specific changes + +## Impact + +- Scope: +- Risks: +- Dependencies: diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/specs/critic/spec.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/specs/critic/spec.md new file mode 100644 index 0000000..895f49e --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/specs/critic/spec.md @@ -0,0 +1,10 @@ +# Capability Spec: critic + +## ADDED Requirements + +### Requirement: critic responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +This role MUST define and deliver its scoped outputs with evidence. + +#### Scenario: Role executes assigned scope +- **WHEN** the role begins execution for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- **THEN** it follows `tasks.md` and records evidence for completion diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/tasks.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/tasks.md new file mode 100644 index 0000000..6b455a2 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/critic/tasks.md @@ -0,0 +1,33 @@ +# critic tasks + +## 1. Spec + +- [ ] 1.1 Validate principle-driver-option consistency across the plan +- [ ] 1.2 Validate risks, consequences, and mitigation clarity (including idempotency expectations) + +## 2. Tests + +- [ ] 2.1 Validate testability and measurability of all acceptance criteria +- [ ] 2.2 Validate verification steps are concrete and reproducible + +## 3. Implementation + +- [ ] 3.1 Produce verdict (APPROVE / ITERATE / REJECT) with actionable feedback +- [ ] 3.2 Confirm revised drafts resolve prior findings before approval +- [ ] 3.3 Publish final quality/risk sign-off notes + +## 4. Checkpoints + +- [ ] [C1] READY - Quality gate checkpoint + +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark `N/A` when solo. +- [ ] 5.3 Record unresolved plan questions in `../open-questions.md`, or mark `N/A` when none. + +## 6. Cleanup + +- [ ] 6.1 If this lane owns finalization, run `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. +- [ ] 6.2 Record PR URL + final `MERGED` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or append `BLOCKED:` and stop. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/.openspec.yaml b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/.openspec.yaml new file mode 100644 index 0000000..68c7c0a --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/.openspec.yaml @@ -0,0 +1,9 @@ +schema: 1 +plan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 +role: executor +status: draft +artifacts: + prompt: prompt.md + proposal: proposal.md + tasks: tasks.md + spec: specs/executor/spec.md diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/README.md new file mode 100644 index 0000000..62b95ee --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/README.md @@ -0,0 +1,12 @@ +# executor + +Role workspace for `executor`. + +Default artifacts: +- `.openspec.yaml` +- `prompt.md` +- `proposal.md` +- `tasks.md` +- `specs//spec.md` + +Use this folder for role notes, artifacts, and status updates. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/checkpoints.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/checkpoints.md new file mode 100644 index 0000000..93d7c6b --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/checkpoints.md @@ -0,0 +1,4 @@ +# executor checkpoints + +Timestamped execution checkpoints for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/prompt.md new file mode 100644 index 0000000..30d0f13 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/prompt.md @@ -0,0 +1,34 @@ +# executor Prompt + +You are the `executor` role for OpenSpec plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Complete only this role's assigned checklist and leave compact evidence for the coordinator. + +## Source of truth + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/tasks.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/proposal.md` + +## Before edits + +1. Confirm branch/worktree with `git status --short --branch`. +2. Claim every touched file before editing: + - Prefer Colony `task_claim_file` when an active task exists. + - Otherwise run `gx locks claim --branch `. +3. Stay inside assigned files/modules; coordinate before touching shared paths. + +## Working rules + +- Update `executor/tasks.md` as each item completes. +- Record durable unresolved questions in `open-questions.md`. +- Keep handoffs short: files changed, behavior touched, verification, risks. +- Do not revert another agent's edits. + +## Cleanup + +Only the owner/finalizer lane runs `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. If blocked, append `BLOCKED:` with branch, task, blocker, next, evidence. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/proposal.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/proposal.md new file mode 100644 index 0000000..72d1a1c --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/proposal.md @@ -0,0 +1,15 @@ +# Proposal: executor (agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00) + +## Why + +Summarize why this role's work is required for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## What Changes + +- [ ] List the planned role-specific changes + +## Impact + +- Scope: +- Risks: +- Dependencies: diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/specs/executor/spec.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/specs/executor/spec.md new file mode 100644 index 0000000..7f62027 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/specs/executor/spec.md @@ -0,0 +1,10 @@ +# Capability Spec: executor + +## ADDED Requirements + +### Requirement: executor responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +This role MUST define and deliver its scoped outputs with evidence. + +#### Scenario: Role executes assigned scope +- **WHEN** the role begins execution for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- **THEN** it follows `tasks.md` and records evidence for completion diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/tasks.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/tasks.md new file mode 100644 index 0000000..062ff29 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/executor/tasks.md @@ -0,0 +1,33 @@ +# executor tasks + +## 1. Spec + +- [ ] 1.1 Map approved plan requirements to concrete implementation work items +- [ ] 1.2 Validate touched components/files are explicitly listed before coding starts + +## 2. Tests + +- [ ] 2.1 Define test additions/updates required to lock intended behavior +- [ ] 2.2 Validate regression and smoke verification commands for delivery + +## 3. Implementation + +- [ ] 3.1 Execute implementation tasks in approved order +- [ ] 3.2 Keep progress and evidence linked back to plan checkpoints +- [ ] 3.3 Complete final verification bundle for handoff + +## 4. Checkpoints + +- [ ] [E1] READY - Execution start checkpoint + +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark `N/A` when solo. +- [ ] 5.3 Record unresolved plan questions in `../open-questions.md`, or mark `N/A` when none. + +## 6. Cleanup + +- [ ] 6.1 If this lane owns finalization, run `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. +- [ ] 6.2 Record PR URL + final `MERGED` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or append `BLOCKED:` and stop. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/kickoff-prompts.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/kickoff-prompts.md new file mode 100644 index 0000000..c7f8661 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/kickoff-prompts.md @@ -0,0 +1,108 @@ +# Kickoff Prompts (Copy/Paste) + +Use these only when the coordinator decides wave-splitting is needed. + +## Prompt A — Wave A (Primary lane) + +```text +You own Wave-A for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-A scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +``` + +## Prompt B — Wave B (Secondary lane) + +```text +You own Wave-B for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-B scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +``` + +## Prompt C — Wave C (Secondary lane) + +```text +You own Wave-C for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` in /home/deadpool/Documents/codex-lb. + +Goal: +Implement the assigned Wave-C scope and return verification evidence. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Stay in your owned files/modules only. +- Record explicit handoff notes for integration. + +Owned scope: +- + +Verification: +- + +Handoff format: +- Files changed +- Behavior touched +- Verification outputs +- Risks/follow-ups +``` + +## Prompt D — Integrator lane + +```text +You are the integrator for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` in /home/deadpool/Documents/codex-lb. + +Goal: +Integrate completed waves, resolve conflicts, run final verification, and prepare rollout/cutover notes. + +Hard constraints: +- You are not alone in the codebase; do not revert others' work. +- Preserve safety-critical behavior unless explicitly planned and tested. +- Keep final output evidence-first. + +Owned scope: +- integration glue and shared touchpoints +- final validation + handoff summary + +Verification: +- + +Final report: +- Files changed +- Integration decisions +- Verification outputs +- Remaining risks +``` diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md new file mode 100644 index 0000000..7bfaf4d --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md @@ -0,0 +1,6 @@ +# Open Questions: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 + +Capture unresolved plan questions here as unchecked checklist items. +Keep each item concrete, decision-shaped, and easy to close with evidence. + +- [ ] Add the next unresolved question here. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/phases.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/phases.md new file mode 100644 index 0000000..0584d23 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/phases.md @@ -0,0 +1,15 @@ +# Plan Phases: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 + +One entry per phase. Checkbox marks map to: `x` = completed, `>` = in progress, space = pending. +Indented sub-bullets are optional metadata consumed by the Plans UI: + +- `session`: which agent kind runs the phase (`codex` / `claude`). +- `checkpoints`: comma-separated role checkpoint ids delivered within the phase. +- `summary`: one short sentence rendered under the phase title. + +One phase is intended to fit into a single Codex or Claude session task. + +- [ ] [PH01] First milestone title goes here + - session: codex + - checkpoints: P1, A1 + - summary: Describe the single session outcome expected for this phase. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/.openspec.yaml b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/.openspec.yaml new file mode 100644 index 0000000..a9af3d3 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/.openspec.yaml @@ -0,0 +1,9 @@ +schema: 1 +plan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 +role: planner +status: draft +artifacts: + prompt: prompt.md + proposal: proposal.md + tasks: tasks.md + spec: specs/planner/spec.md diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/README.md new file mode 100644 index 0000000..1b0ad5d --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/README.md @@ -0,0 +1,12 @@ +# planner + +Role workspace for `planner`. + +Default artifacts: +- `.openspec.yaml` +- `prompt.md` +- `proposal.md` +- `tasks.md` +- `specs//spec.md` + +Use this folder for role notes, artifacts, and status updates. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/plan.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/plan.md new file mode 100644 index 0000000..04add51 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/plan.md @@ -0,0 +1,65 @@ +# ExecPlan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 + +This ExecPlan is a living document. Keep `Progress`, `Surprises & Discoveries`, `Decision Log`, and `Outcomes & Retrospective` current as work proceeds. + +Follow repository guidance in `openspec/plan/PLANS.md`. + +## Purpose / Big Picture + +Describe what becomes possible after this plan is executed and how a user/operator can observe it working. + +## Progress + +- [ ] (YYYY-MM-DD HH:MMZ) Capture initial scope and acceptance criteria. +- [ ] (YYYY-MM-DD HH:MMZ) Draft architecture/tradeoff plan and verification strategy. +- [ ] (YYYY-MM-DD HH:MMZ) Finalize execution-ready handoff. + +## Surprises & Discoveries + +- Observation: _none yet_ + Evidence: _n/a_ + +## Decision Log + +- Decision: Use OpenSpec plan workspace as source of truth for this planning cycle. + Rationale: Keeps planning artifacts in-repo and reviewable. + Date/Author: YYYY-MM-DD / planner + +## Outcomes & Retrospective + +Summarize outcomes, gaps, and lessons learned when a milestone or the full plan is completed. + +## Context and Orientation + +Describe relevant modules, files, constraints, and assumptions for a newcomer. Use repository-relative paths. + +## Plan of Work + +Describe the sequence of edits and deliverables in prose. Name target files and expected effects. + +## Concrete Steps + +List exact commands with working directory and short expected outcomes. + + cd /home/deadpool/Documents/codex-lb + openspec validate --specs + +## Validation and Acceptance + +State observable behavior and verification evidence required before execution handoff. + +## Idempotence and Recovery + +Document safe re-run behavior, rollback strategy, and failure recovery notes. + +## Artifacts and Notes + +Capture concise command output snippets, evidence pointers, and references. + +## Interfaces and Dependencies + +Name concrete interfaces/modules/dependencies and any required signatures/contracts. + +## Revision Note + +- YYYY-MM-DD HH:MMZ: Initial scaffold generated by `scripts/openspec/init-plan-workspace.sh`. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/prompt.md new file mode 100644 index 0000000..6f19cb7 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/prompt.md @@ -0,0 +1,34 @@ +# planner Prompt + +You are the `planner` role for OpenSpec plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Complete only this role's assigned checklist and leave compact evidence for the coordinator. + +## Source of truth + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/tasks.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/proposal.md` + +## Before edits + +1. Confirm branch/worktree with `git status --short --branch`. +2. Claim every touched file before editing: + - Prefer Colony `task_claim_file` when an active task exists. + - Otherwise run `gx locks claim --branch `. +3. Stay inside assigned files/modules; coordinate before touching shared paths. + +## Working rules + +- Update `planner/tasks.md` as each item completes. +- Record durable unresolved questions in `open-questions.md`. +- Keep handoffs short: files changed, behavior touched, verification, risks. +- Do not revert another agent's edits. + +## Cleanup + +Only the owner/finalizer lane runs `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. If blocked, append `BLOCKED:` with branch, task, blocker, next, evidence. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/proposal.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/proposal.md new file mode 100644 index 0000000..11f7c0c --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/proposal.md @@ -0,0 +1,15 @@ +# Proposal: planner (agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00) + +## Why + +Summarize why this role's work is required for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## What Changes + +- [ ] List the planned role-specific changes + +## Impact + +- Scope: +- Risks: +- Dependencies: diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/specs/planner/spec.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/specs/planner/spec.md new file mode 100644 index 0000000..47e1edf --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/specs/planner/spec.md @@ -0,0 +1,10 @@ +# Capability Spec: planner + +## ADDED Requirements + +### Requirement: planner responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +This role MUST define and deliver its scoped outputs with evidence. + +#### Scenario: Role executes assigned scope +- **WHEN** the role begins execution for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- **THEN** it follows `tasks.md` and records evidence for completion diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/tasks.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/tasks.md new file mode 100644 index 0000000..90cf2af --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/planner/tasks.md @@ -0,0 +1,33 @@ +# planner tasks + +## 1. Spec + +- [ ] 1.1 Define planning principles, decision drivers, and viable options for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- [ ] 1.2 Validate that scope, constraints, and acceptance criteria are captured in `summary.md` + +## 2. Tests + +- [ ] 2.1 Define verification approach for plan quality (traceability, testability, evidence expectations) +- [ ] 2.2 Validate OpenSpec consistency checkpoints (including `openspec validate --specs` when applicable) + +## 3. Implementation + +- [ ] 3.1 Produce the initial RALPLAN-DR plan draft +- [ ] 3.2 Integrate Architect/Critic feedback into revised plan iterations +- [ ] 3.3 Publish final planning handoff with explicit execution lanes + +## 4. Checkpoints + +- [ ] [P1] READY - Initial planning draft checkpoint + +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark `N/A` when solo. +- [ ] 5.3 Record unresolved plan questions in `../open-questions.md`, or mark `N/A` when none. + +## 6. Cleanup + +- [ ] 6.1 If this lane owns finalization, run `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. +- [ ] 6.2 Record PR URL + final `MERGED` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or append `BLOCKED:` and stop. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md new file mode 100644 index 0000000..7e8c359 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md @@ -0,0 +1,8 @@ +# Plan Summary: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 + +- **Mode:** ralplan +- **Status:** draft + +## Context + +Describe the planning context, constraints, and desired outcomes. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/.openspec.yaml b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/.openspec.yaml new file mode 100644 index 0000000..83f067f --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/.openspec.yaml @@ -0,0 +1,9 @@ +schema: 1 +plan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 +role: verifier +status: draft +artifacts: + prompt: prompt.md + proposal: proposal.md + tasks: tasks.md + spec: specs/verifier/spec.md diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/README.md new file mode 100644 index 0000000..1daa373 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/README.md @@ -0,0 +1,12 @@ +# verifier + +Role workspace for `verifier`. + +Default artifacts: +- `.openspec.yaml` +- `prompt.md` +- `proposal.md` +- `tasks.md` +- `specs//spec.md` + +Use this folder for role notes, artifacts, and status updates. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/prompt.md new file mode 100644 index 0000000..682ebc4 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/prompt.md @@ -0,0 +1,34 @@ +# verifier Prompt + +You are the `verifier` role for OpenSpec plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Complete only this role's assigned checklist and leave compact evidence for the coordinator. + +## Source of truth + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/tasks.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/proposal.md` + +## Before edits + +1. Confirm branch/worktree with `git status --short --branch`. +2. Claim every touched file before editing: + - Prefer Colony `task_claim_file` when an active task exists. + - Otherwise run `gx locks claim --branch `. +3. Stay inside assigned files/modules; coordinate before touching shared paths. + +## Working rules + +- Update `verifier/tasks.md` as each item completes. +- Record durable unresolved questions in `open-questions.md`. +- Keep handoffs short: files changed, behavior touched, verification, risks. +- Do not revert another agent's edits. + +## Cleanup + +Only the owner/finalizer lane runs `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. If blocked, append `BLOCKED:` with branch, task, blocker, next, evidence. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/proposal.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/proposal.md new file mode 100644 index 0000000..44ff47b --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/proposal.md @@ -0,0 +1,15 @@ +# Proposal: verifier (agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00) + +## Why + +Summarize why this role's work is required for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## What Changes + +- [ ] List the planned role-specific changes + +## Impact + +- Scope: +- Risks: +- Dependencies: diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/specs/verifier/spec.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/specs/verifier/spec.md new file mode 100644 index 0000000..084f47f --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/specs/verifier/spec.md @@ -0,0 +1,10 @@ +# Capability Spec: verifier + +## ADDED Requirements + +### Requirement: verifier responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +This role MUST define and deliver its scoped outputs with evidence. + +#### Scenario: Role executes assigned scope +- **WHEN** the role begins execution for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- **THEN** it follows `tasks.md` and records evidence for completion diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/tasks.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/tasks.md new file mode 100644 index 0000000..400fba6 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/verifier/tasks.md @@ -0,0 +1,33 @@ +# verifier tasks + +## 1. Spec + +- [ ] 1.1 Define end-to-end validation matrix for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- [ ] 1.2 Validate success/failure conditions and evidence requirements + +## 2. Tests + +- [ ] 2.1 Execute verification commands and collect outputs +- [ ] 2.2 Validate idempotency/re-run behavior and error-path handling + +## 3. Implementation + +- [ ] 3.1 Verify completed work against acceptance criteria +- [ ] 3.2 Produce pass/fail findings with concrete evidence links +- [ ] 3.3 Publish final verification sign-off (or blocker report) + +## 4. Checkpoints + +- [ ] [V1] READY - Verification checkpoint + +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark `N/A` when solo. +- [ ] 5.3 Record unresolved plan questions in `../open-questions.md`, or mark `N/A` when none. + +## 6. Cleanup + +- [ ] 6.1 If this lane owns finalization, run `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. +- [ ] 6.2 Record PR URL + final `MERGED` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or append `BLOCKED:` and stop. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/.openspec.yaml b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/.openspec.yaml new file mode 100644 index 0000000..83b0575 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/.openspec.yaml @@ -0,0 +1,9 @@ +schema: 1 +plan: agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00 +role: writer +status: draft +artifacts: + prompt: prompt.md + proposal: proposal.md + tasks: tasks.md + spec: specs/writer/spec.md diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/README.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/README.md new file mode 100644 index 0000000..757c824 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/README.md @@ -0,0 +1,12 @@ +# writer + +Role workspace for `writer`. + +Default artifacts: +- `.openspec.yaml` +- `prompt.md` +- `proposal.md` +- `tasks.md` +- `specs//spec.md` + +Use this folder for role notes, artifacts, and status updates. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/prompt.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/prompt.md new file mode 100644 index 0000000..9c09f0e --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/prompt.md @@ -0,0 +1,34 @@ +# writer Prompt + +You are the `writer` role for OpenSpec plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## Objective + +Complete only this role's assigned checklist and leave compact evidence for the coordinator. + +## Source of truth + +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/summary.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/checkpoints.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/open-questions.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/tasks.md` +- `openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/proposal.md` + +## Before edits + +1. Confirm branch/worktree with `git status --short --branch`. +2. Claim every touched file before editing: + - Prefer Colony `task_claim_file` when an active task exists. + - Otherwise run `gx locks claim --branch `. +3. Stay inside assigned files/modules; coordinate before touching shared paths. + +## Working rules + +- Update `writer/tasks.md` as each item completes. +- Record durable unresolved questions in `open-questions.md`. +- Keep handoffs short: files changed, behavior touched, verification, risks. +- Do not revert another agent's edits. + +## Cleanup + +Only the owner/finalizer lane runs `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. If blocked, append `BLOCKED:` with branch, task, blocker, next, evidence. diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/proposal.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/proposal.md new file mode 100644 index 0000000..d177557 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/proposal.md @@ -0,0 +1,15 @@ +# Proposal: writer (agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00) + +## Why + +Summarize why this role's work is required for plan `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00`. + +## What Changes + +- [ ] List the planned role-specific changes + +## Impact + +- Scope: +- Risks: +- Dependencies: diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/specs/writer/spec.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/specs/writer/spec.md new file mode 100644 index 0000000..8f36b3e --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/specs/writer/spec.md @@ -0,0 +1,10 @@ +# Capability Spec: writer + +## ADDED Requirements + +### Requirement: writer responsibilities for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +This role MUST define and deliver its scoped outputs with evidence. + +#### Scenario: Role executes assigned scope +- **WHEN** the role begins execution for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- **THEN** it follows `tasks.md` and records evidence for completion diff --git a/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/tasks.md b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/tasks.md new file mode 100644 index 0000000..dd1c6d5 --- /dev/null +++ b/openspec/plan/agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00/writer/tasks.md @@ -0,0 +1,33 @@ +# writer tasks + +## 1. Spec + +- [ ] 1.1 Validate documentation scope and audience for `agent-claude-masterplan-wip-pre-dispatch-sync-2026-05-16-00-00` +- [ ] 1.2 Validate consistency between plan terminology and OpenSpec artifacts + +## 2. Tests + +- [ ] 2.1 Define documentation verification checklist (accuracy, completeness, command correctness) +- [ ] 2.2 Validate command/help text examples against current workflow behavior + +## 3. Implementation + +- [ ] 3.1 Update workflow docs and command guidance for approved plan behavior +- [ ] 3.2 Add or refine examples for operator usage and handoff clarity +- [ ] 3.3 Publish final docs change summary with references + +## 4. Checkpoints + +- [ ] [W1] READY - Docs update checkpoint + +## 5. Collaboration + +- [ ] 5.1 Owner recorded this lane before edits. +- [ ] 5.2 Record joined agents / handoffs, or mark `N/A` when solo. +- [ ] 5.3 Record unresolved plan questions in `../open-questions.md`, or mark `N/A` when none. + +## 6. Cleanup + +- [ ] 6.1 If this lane owns finalization, run `gx branch finish --branch --base dev --via-pr --wait-for-merge --cleanup`. +- [ ] 6.2 Record PR URL + final `MERGED` state in the handoff. +- [ ] 6.3 Confirm sandbox cleanup (`git worktree list`, `git branch -a`) or append `BLOCKED:` and stop. diff --git a/openspec/plans/codex-fleet-design-speed-18way-2026-05-15/plan.json b/openspec/plans/codex-fleet-design-speed-18way-2026-05-15/plan.json new file mode 100644 index 0000000..6bd62f9 --- /dev/null +++ b/openspec/plans/codex-fleet-design-speed-18way-2026-05-15/plan.json @@ -0,0 +1,292 @@ +{ + "schema_version": 1, + "plan_slug": "codex-fleet-design-speed-18way-2026-05-15", + "title": "18-way parallel iOS-design polish + render-speed pass across the fleet TUI", + "problem": "The codex-fleet TUI has 10 reference iOS-style design surfaces captured as static PNG + HTML mocks in /home/deadpool/Documents/codex-fleetui/images/ (Designs A–J: Context menu, Spotlight, Action sheet, Session switcher, Glass dock, ⌘K jump grid, Fleet worker list, Plan wave tree, Waves spawn timeline, Review approval queue). The live fleet renders functional but unstyled equivalents — flat colors, no card shadows, full redraws per tick, blocking IO during state polling, and no frame budget. This plan opens 18 fully-parallel lanes (10 design surfaces + 8 render-speed lanes) that each land their work in a NEW module file inside their target crate. File scopes are disjoint so all 18 panes can claim+edit concurrently with zero serialization on overlay.rs or main.rs. Wiring the new modules into their respective main.rs binaries is intentionally OUT OF SCOPE here — it ships in a follow-up integration plan once these 18 land. Reference images live at /home/deadpool/Documents/codex-fleetui/images/{A..J}_*.png (open the .html sibling for hover/animation behavior).", + "acceptance_criteria": [ + "All 18 tasks have depends_on=[] and disjoint file_scope; no two tasks list the same file.", + "Each task lands a single NEW .rs module file under its target crate; no edits to existing main.rs / lib.rs / overlay.rs in this plan.", + "Each Design lane (sub-0..sub-9) implements a ratatui Widget whose snapshot output matches the reference at /home/deadpool/Documents/codex-fleetui/images/_*.png within reasonable TUI fidelity (color palette, padding, card shadow, separator weight).", + "Each Speed lane (sub-10..sub-17) lands a self-contained struct with a public API plus unit tests proving its perf claim (frame budget, debounce window, cache hit, diff coverage).", + "Each new module compiles standalone via `cargo check -p ` even though it is not yet wired into the binary.", + "Each task includes one `cargo test -p ` invocation as its verifier evidence." + ], + "roles": [ + "planner", + "architect", + "executor", + "verifier" + ], + "tasks": [ + { + "subtask_index": 0, + "title": "Design A — iOS Context menu widget (pinned-to-pane)", + "description": "Create rust/fleet-ui/src/overlay/context_menu_ios.rs implementing an iOS-styled ContextMenu ratatui Widget. Reference: /home/deadpool/Documents/codex-fleetui/images/A _ Context menu _ pinned to active pane.png and its sibling .html for hover/active states. Match: rounded card, two-tone separator, SF-Pro-like uppercase first letter of each item, destructive-red last row. Expose `IosContextMenu { items: Vec, anchor: Rect }` and one inline `#[cfg(test)]` snapshot test using insta. Do NOT modify overlay.rs in this plan.", + "file_scope": [ + "rust/fleet-ui/src/overlay/context_menu_ios.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 1, + "title": "Design B — iOS Spotlight search palette", + "description": "Create rust/fleet-ui/src/overlay/spotlight_ios.rs implementing a search-first command palette modeled on /home/deadpool/Documents/codex-fleetui/images/B _ Spotlight _ search-first palette.png. Match: blurred backdrop sentinel, top-pinned text input with leading magnifier glyph, result rows with subtitle + right-aligned hotkey chip. Public struct `IosSpotlight { query: String, results: Vec }` plus an insta snapshot test for the empty-query and populated-results states. Do not touch overlay.rs.", + "file_scope": [ + "rust/fleet-ui/src/overlay/spotlight_ios.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 2, + "title": "Design C — iOS grouped Action sheet (Cancel)", + "description": "Create rust/fleet-ui/src/overlay/action_sheet_ios.rs implementing a bottom-anchored grouped action sheet matching /home/deadpool/Documents/codex-fleetui/images/C _ Action sheet _ grouped _ Cancel.png. Match: two visually-separated cards (action group + Cancel), 1px hairline separators, larger destructive-red row, full-width Cancel pill. Public `IosActionSheet { groups: Vec, cancel_label: &'static str }` plus snapshot test. Do not touch overlay.rs.", + "file_scope": [ + "rust/fleet-ui/src/overlay/action_sheet_ios.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 3, + "title": "Design D — iOS Session switcher card stack", + "description": "Create rust/fleet-ui/src/overlay/session_switcher_ios.rs implementing a card-stack session switcher modeled on /home/deadpool/Documents/codex-fleetui/images/D _ Session switcher _ card stack.png. Match: peeking card stack, active card lifted with stronger shadow, session name + last-activity timestamp, swipe-up-to-dismiss chrome row. Public `IosSessionSwitcher { sessions: Vec, active: usize }` plus snapshot test. Do not touch overlay.rs.", + "file_scope": [ + "rust/fleet-ui/src/overlay/session_switcher_ios.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 4, + "title": "Design E — Glass dock floating top nav", + "description": "Create rust/fleet-ui/src/glass_dock.rs implementing a floating top navigation dock with a glass/blur backdrop, modeled on /home/deadpool/Documents/codex-fleetui/images/E _ Glass dock _ floating top nav.png. Match: pill-shaped container, leading session badge, trailing icon cluster, subtle inner highlight to fake glass. Public `GlassDock { tabs: Vec, active: usize }` plus snapshot test. Do not edit lib.rs in this plan.", + "file_scope": [ + "rust/fleet-ui/src/glass_dock.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 5, + "title": "Design F — ⌘K jump grid section menu", + "description": "Create rust/fleet-ui/src/overlay/jump_grid.rs implementing a ⌘K-style 3-column section jump grid modeled on /home/deadpool/Documents/codex-fleetui/images/F _ Section menu _ _K jump grid.png. Match: square tile per section, glyph + label, focused tile with thick rounded border, footer help-row showing ↵ to open / ⌘K to dismiss. Public `JumpGrid { sections: Vec, cursor: (usize, usize) }` plus snapshot test. Do not touch overlay.rs.", + "file_scope": [ + "rust/fleet-ui/src/overlay/jump_grid.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 6, + "title": "Design G — Fleet worker list with live status", + "description": "Create rust/fleet-state/src/worker_table.rs implementing a 5-column worker table widget modeled on /home/deadpool/Documents/codex-fleetui/images/G _ Fleet _ worker list _ live status.png. Columns: agent · status pill · current-task summary · file-claim count · last-tick age. Match: zebra rows, status pill colors (idle=cool gray, working=accent blue, blocked=warning amber, done=success green), monospace timestamps. Public `WorkerTable { rows: Vec }` plus a snapshot test. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-state/src/worker_table.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 7, + "title": "Design H — Plan wave tree (topo levels)", + "description": "Create rust/fleet-plan-tree/src/topo_tree.rs implementing a topologically-leveled wave tree modeled on /home/deadpool/Documents/codex-fleetui/images/H _ Plan _ wave tree_ topo levels.png. Match: horizontal rails per topo level, dotted dependency arrows, claimed-vs-available chip per node, current-wave highlight. Public `TopoTree { levels: Vec>, edges: Vec<(usize,usize)>, current_wave: usize }` plus snapshot test. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-plan-tree/src/topo_tree.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 8, + "title": "Design I — Waves spawn timeline", + "description": "Create rust/fleet-waves/src/spawn_timeline.rs implementing a horizontal-scroll spawn-timeline widget modeled on /home/deadpool/Documents/codex-fleetui/images/I _ Waves _ spawn timeline.png. Match: one row per worker, colored span per spawn segment, vertical now-cursor, hover-tooltip ghost row at bottom. Public `SpawnTimeline { rows: Vec, now: Instant, viewport: Range }` plus snapshot test. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-waves/src/spawn_timeline.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 9, + "title": "Design J — Review approval queue", + "description": "Create rust/fleet-ui/src/review_queue.rs implementing the review approval queue modeled on /home/deadpool/Documents/codex-fleetui/images/J _ Review _ approval queue.png. Match: stacked review cards with diff stat chips, approve/needs-changes/reject buttons in iOS pill row, top filter segmented control (Open / Mine / Resolved). Public `ReviewQueue { cards: Vec, filter: ReviewFilter }` plus snapshot test. Do not touch lib.rs.", + "file_scope": [ + "rust/fleet-ui/src/review_queue.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_ui", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 10, + "title": "Speed — diff-based plan-tree redraw", + "description": "Create rust/fleet-plan-tree/src/diff_redraw.rs exposing a `DiffRedraw` engine that compares the previous frame's plan-tree model to the next and emits only the dirty Rects. Goal: skip full redraws when only one node's status changes. Include a unit test that proves a single status flip produces ≤ 1 dirty Rect (not the whole frame). Do not touch main.rs.", + "file_scope": [ + "rust/fleet-plan-tree/src/diff_redraw.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 11, + "title": "Speed — cached wave snapshot", + "description": "Create rust/fleet-waves/src/snapshot_cache.rs exposing a `SnapshotCache` keyed by (plan_slug, mtime_ns) that memoizes the parsed-and-laid-out wave timeline. Goal: avoid re-parsing plan.json + recomputing topo layers when the file hasn't changed. Unit test: 2nd call with same mtime returns the cached `Arc` (pointer-equal) and does NOT re-read the file. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-waves/src/snapshot_cache.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 12, + "title": "Speed — frame-budget loop for fleet-tui-poc", + "description": "Create rust/fleet-tui-poc/src/frame_budget.rs exposing `FrameBudget::tick()` that caps the render loop at 30fps with a soft 33ms slice and yields early when nothing is dirty. Public API: `FrameBudget::new(target_fps: u32)` + `should_render(&mut self, dirty: bool) -> bool`. Unit test: at 30fps with continuous dirty=true, exactly 30 renders happen across a simulated 1s window. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-tui-poc/src/frame_budget.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 13, + "title": "Speed — lazy off-screen tab render", + "description": "Create rust/fleet-tab-strip/src/lazy_render.rs exposing a `LazyTabRenderer` that only invokes a tab's render fn when the tab is the active one or is within an N-tab look-ahead window. Public API: `LazyTabRenderer::new(lookahead: usize)` + `render(&mut self, tabs: &[Tab], active: usize, frame: &mut Frame)`. Unit test: with 6 tabs, lookahead=1, active=2 → tabs 1,2,3 render; tabs 0,4,5 are skipped. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-tab-strip/src/lazy_render.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 14, + "title": "Speed — async file-claim fetch in fleet-state", + "description": "Create rust/fleet-state/src/claim_fetch.rs exposing `ClaimFetcher` that spawns Colony `task_list_account_claims` calls on a background thread and returns a non-blocking `try_latest() -> Option`. Goal: stop the render loop blocking on the MCP roundtrip. Public API: `ClaimFetcher::new(poll: Duration)` + `try_latest()` + `Drop` that joins cleanly. Unit test: a mocked fetcher with a 200ms latency lets the render thread call `try_latest()` 100x in under 50ms with the cached value. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-state/src/claim_fetch.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 15, + "title": "Speed — watcher event debounce", + "description": "Create rust/fleet-watcher/src/debounce.rs exposing a `Debouncer` that coalesces a burst of events within a configurable window (default 50ms) into one emitted event. Public API: `Debouncer::new(window: Duration)` + `push(event: E)` + `drain() -> Vec` (one per coalesce key). Unit test: 100 events pushed within 10ms with the same key coalesce to a single drained event; events with different keys remain distinct. Do not touch main.rs.", + "file_scope": [ + "rust/fleet-watcher/src/debounce.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 16, + "title": "Speed — layout cache for fleet-layout", + "description": "Create rust/fleet-layout/src/cache.rs exposing a `LayoutCache` that memoizes `Layout::split(Rect)` results keyed by (preset_id, rect). Goal: avoid recomputing identical splits across ticks. Public API: `LayoutCache::default()` + `split(&mut self, preset: &Preset, rect: Rect) -> &[Rect]`. Unit test: 1000 identical (preset, rect) calls perform the underlying split exactly once and return slice-equal results. Do not touch lib.rs or preset.rs.", + "file_scope": [ + "rust/fleet-layout/src/cache.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 17, + "title": "Speed — input event coalescing in fleet-input", + "description": "Create rust/fleet-input/src/coalesce.rs exposing `InputCoalescer` that merges repeated arrow-key / mouse-drag events arriving within one frame into a single Action carrying the net delta. Public API: `InputCoalescer::new()` + `push(action: Action)` + `flush() -> Vec`. Unit test: 8 consecutive `Action::MoveCursor { dy: 1 }` events flush to one `MoveCursor { dy: 8 }`; mixed-direction events do not merge. Do not touch lib.rs, action.rs, keymap.rs, modal.rs, or context.rs.", + "file_scope": [ + "rust/fleet-input/src/coalesce.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "rust_perf", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + } + ] +} diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/architect.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/architect.md new file mode 100644 index 0000000..f739057 --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/architect.md @@ -0,0 +1,13 @@ +# Architect + +Plan: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Responsibility + +Check boundaries, data flow, interfaces, and rollback shape. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/checkpoints.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/checkpoints.md new file mode 100644 index 0000000..0f360b0 --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/checkpoints.md @@ -0,0 +1,25 @@ +# Checkpoints + +## Rollup + +- available: 8 +- claimed: 0 +- completed: 0 +- blocked: 0 + +## Subtasks + +- [ ] sub-0 Glass pane action menu — transparent chrome, fg-only ANSI, iOS-blue focus underline [available] +- [ ] sub-1 Glass help popup — same transparent treatment as the action menu [available] +- [ ] sub-2 Drop fleet-tab-strip pane spawn from overview-header.sh [available] +- [ ] sub-3 Drop fleet-tab-strip references from full-bringup.sh [available] +- [ ] sub-4 Drop the tab-strip-panel exclusion in plan-watcher.sh [available] +- [ ] sub-5 Delete the standalone fleet-tab-strip rust crate [available] +- [ ] sub-6 Clean up style-tabs.sh comments + branding post-tab-strip-removal [available] +- [ ] sub-7 Remove orphaned fleet_ui::tab_strip module [available] + +## Completion Gate + +- [ ] All subtasks complete. +- [ ] Spec change archived or explicitly marked not applicable. +- [ ] Verification evidence recorded. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/critic.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/critic.md new file mode 100644 index 0000000..f6db8a4 --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/critic.md @@ -0,0 +1,13 @@ +# Critic + +Plan: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Responsibility + +Challenge weak assumptions, hidden risks, and missing tests. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/executor.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/executor.md new file mode 100644 index 0000000..569198d --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/executor.md @@ -0,0 +1,13 @@ +# Executor + +Plan: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Responsibility + +Implement claimed subtasks inside declared file scope. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/plan.json b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/plan.json new file mode 100644 index 0000000..f71a9ea --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/plan.json @@ -0,0 +1,155 @@ +{ + "schema_version": 1, + "plan_slug": "codex-fleet-glass-menu-drop-tabstrip-2026-05-15", + "title": "Glass/transparent pane menu + drop the codex-fleet tab strip + overall design pass", + "problem": "The operator wants two visible design changes plus a polish pass. (1) The right-click pane action menu currently renders as a solid two-tone card (#1C1C1E inner / #2C2C2E border) that sits opaquely on top of the underlying pane. The operator wants it transparent / glassmorphic — the terminal's background (kitty supports background_opacity) should bleed through, with only hairline strokes, fg-only text, and a subtle iOS-blue underline on the focused row. (2) The 5-tab strip rendered at the top of the overview window by the standalone `rust/fleet-tab-strip` binary (spawned via `scripts/codex-fleet/overview-header.sh` and `scripts/codex-fleet/full-bringup.sh`) is to be removed entirely — including the binary, its workspace member, the spawn sites, and the downstream tmux pane-iteration excludes in `plan-watcher.sh` and `full-bringup.sh` that assume a `[codex-fleet-tab-strip]` panel exists. The dashboards already render their own iOS-chrome page headers (per the ios_page_design.rs modules merged in the previous plan), so the tab pane is now redundant. (3) An accompanying design pass: same transparent treatment for `help-popup.sh`, comment cleanup in `style-tabs.sh`, and removal of the now-orphaned `fleet_ui::tab_strip` module. The 8 lanes are flat-parallel — every lane edits exactly one disjoint file path (or one new disjoint set), depends_on=[] on all of them, so any fleet of 8 workers can claim and ship in parallel without `task_claim_file` contention. No shared helpers are added; each lane inlines the small bit of ANSI/transparency logic it needs.", + "acceptance_criteria": [ + "All 8 sub-tasks land independently as 8 separate PRs against main with depends_on=[] honored; no two PRs touch the same file path.", + "After Lane 0 ships, right-click on any codex-fleet pane renders the action menu with NO solid card background — the underlying pane's text shows through under the menu chrome (verified by sending Esc-prefixed paste of a known visible character before opening the menu). Hairline borders, title row, items, and shortcut chips all use fg-only ANSI; the focused row uses an iOS-blue underline rather than a fill.", + "After Lane 1 ships, the help popup (prefix+Ctrl+H) renders with the same transparent treatment as Lane 0: hairline section dividers in #3A3A3C, section headers in iOS-blue fg, no solid card bg.", + "After Lanes 2-5 ship, `bash scripts/codex-fleet/full-bringup.sh --n 4 --no-attach` brings up the overview window with NO `[codex-fleet-tab-strip]` pane at the top — the 4 workers occupy the full window. `tmux list-panes -t codex-fleet:0 -F '#{@panel}'` does not list the tab-strip panel. `plan-watcher.sh` no longer references it. `rust/Cargo.toml`'s `fleet-*` workspace glob no longer pulls in `fleet-tab-strip` because that directory is gone, and `cargo check --workspace` from `rust/` succeeds.", + "After Lane 6 ships, `style-tabs.sh` no longer contains the 'in-binary tab strip is the navigation surface' branding in its echo / comments — the comments accurately describe the post-removal world (tmux status off by default, glass right-click menu is the canonical chrome layer).", + "After Lane 7 ships, `rust/fleet-ui/src/lib.rs` no longer exports `pub mod tab_strip;`, `rust/fleet-ui/src/tab_strip.rs` is deleted, and `cargo check -p fleet-ui` succeeds.", + "No regression in the existing dashboards: each `cargo check -p ` for fleet-state / fleet-plan-tree / fleet-waves / fleet-watcher still passes after their respective lanes (none of those crates' main.rs are edited by this plan, so this should be a no-op verification).", + "Every PR's final note records: branch, files changed, command + output evidence (cargo check / shellcheck / bringup smoke), PR URL, MERGED state, and sandbox cleanup proof per the Guardex completion contract." + ], + "roles": [ + "planner", + "architect", + "critic", + "executor", + "writer", + "verifier" + ], + "tasks": [ + { + "subtask_index": 0, + "title": "Glass pane action menu — transparent chrome, fg-only ANSI, iOS-blue focus underline", + "description": "Rewrite scripts/codex-fleet/bin/pane-context-menu.sh so the right-click action menu renders as a transparent / glassmorphic surface. Required changes: (1) Stop emitting solid bg SGR escapes — change the chrome helpers (draw_top / draw_bottom / draw_hairline / draw_blank / draw_header / draw_item) so every cell uses ONLY a 38;2;R;G;B foreground escape with NO 48;2;R;G;B background. Inline this directly inside the script — DO NOT modify scripts/codex-fleet/lib/ios-menu.sh. (2) Hairline borders (top, bottom, section dividers) use fg=#3A3A3C (iOS separator gray). (3) Item rows use fg=#FFFFFF for label, fg=#8E8E93 for icon column, fg=#AEAEB2 for shortcut chip text. The bracketing '[ K ]' chip becomes plain '· K' or 'K' in dim gray since there is no longer a card surface to contrast against. (4) Header row: fg=#FFFFFF bold for 'pane N · %ID', fg=#34C759 for the leading dot, fg=#34C759 bold for ' LIVE ' (no bg). (5) Focus indicator: the script today only reads ONE keystroke and dispatches — there is no live focus loop — so the 'focus row' is the row whose hotkey was just pressed. Add a brief 80ms 'feedback flash' where the chosen row briefly underlines (fg sequence: \\033[4m … \\033[24m) in iOS-blue before dispatching, then clears the popup. (6) Danger row (Kill pane) keeps fg=#FF3B30. Disabled rows use fg=#48484A. (7) Update the bottom hint line to 'press a hotkey · ? for help · esc cancels' in fg=#8E8E93. (8) Add a top-of-file comment describing the transparency model and a smoke-test stanza: `printf 'hello-bg\\nhello-bg\\nhello-bg' && CODEX_FLEET_MENU_LINE=demo bash scripts/codex-fleet/bin/pane-context-menu.sh '%0' < /dev/null` and capture the rendered output via `script` or terminal recording to attach as evidence in the PR. file_scope is exactly this one file — do not touch ios-menu.sh, help-popup.sh, or any other file.", + "file_scope": [ + "scripts/codex-fleet/bin/pane-context-menu.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 1, + "title": "Glass help popup — same transparent treatment as the action menu", + "description": "Rewrite scripts/codex-fleet/bin/help-popup.sh to match Lane 0's transparency model. Required: (1) Drop every 48;2;R;G;B bg SGR — chrome helpers (draw_top / draw_bottom / draw_hairline / draw_section / any item draw) emit fg only. (2) Section headers (e.g. 'TMUX', 'CONTEXT MENU', 'SPOTLIGHT', etc.) render in fg=#007AFF bold with NO bg. (3) Keybinding rows: left column (the keystroke) in fg=#FFCC00 bold (iOS yellow), right column (the description) in fg=#FFFFFF, separator dot in fg=#8E8E93. (4) Section dividers use fg=#3A3A3C hairlines. (5) Outer corner glyphs (╭ ╮ ╰ ╯) and edge bars (│ ─) also fg-only in #3A3A3C. (6) Bottom hint: 'any key closes · esc/q exits' in fg=#8E8E93. (7) Keep all currently listed bindings verbatim — this lane is purely visual. (8) Add a self-contained smoke test stanza at the top of the script (commented) showing how to invoke it standalone: `bash scripts/codex-fleet/bin/help-popup.sh < /dev/null` with a 1-byte stdin to dismiss. (9) file_scope is exactly this one file.", + "file_scope": [ + "scripts/codex-fleet/bin/help-popup.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 2, + "title": "Drop fleet-tab-strip pane spawn from overview-header.sh", + "description": "Make scripts/codex-fleet/overview-header.sh a backwards-compatible no-op. Required: (1) Keep the file in place (other scripts source it / call it by path) but the body should now: log 'overview-header: tab strip removed (see plan codex-fleet-glass-menu-drop-tabstrip-2026-05-15)', skip the binary location lookup, skip the split-window / select-pane / set-option calls, and exit 0. (2) Remove the BIN= lookup at lines 64-69, the warn at line 69, the split-window/select-pane block, and the `tmux set-option -p ... '@panel' '[codex-fleet-tab-strip]'` at line 91. Keep the `tmux list-panes -t \"$target\" -F '#{@panel}' | grep -qFx '[codex-fleet-tab-strip]'` idempotence guard as a comment + skip path (so re-run on an OLD session with the strip pane still alive doesn't double-add). (3) Add a top-of-file comment block explaining the removal and pointing to the plan slug. (4) shellcheck must remain clean: `shellcheck scripts/codex-fleet/overview-header.sh` exits 0. (5) file_scope is exactly this one file — DO NOT touch full-bringup.sh, plan-watcher.sh, or rust/fleet-tab-strip in this lane (other lanes own those files).", + "file_scope": [ + "scripts/codex-fleet/overview-header.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 3, + "title": "Drop fleet-tab-strip references from full-bringup.sh", + "description": "Edit scripts/codex-fleet/full-bringup.sh to fully remove every reference to the tab-strip pane. Required: (1) Delete lines 458-468 (STRIP_BIN=… block, the if-exists guard, HEADER_CMD= path, the warn line). Whatever currently consumes HEADER_CMD afterwards must be removed too — trace the variable forward and drop the spawn site cleanly. (2) Delete line 516 (`awk -F'|' '$1 == \"[codex-fleet-tab-strip]\" { print $2; exit }'`) and update the surrounding logic so it no longer needs to identify a 'header pane' — the worker grid simply occupies all panes in the window. (3) Delete line 527's awk filter (`'$1 != \"[codex-fleet-tab-strip]\"'`) — replace with a pass-through that lists all panes. (4) Add an inline comment near each removal pointing at the plan slug. (5) Smoke test: `bash -n scripts/codex-fleet/full-bringup.sh` parses clean, and `shellcheck` exits 0. (6) A live smoke run on a clean repo (`tmux -L test kill-server 2>/dev/null; CODEX_FLEET_TMUX_SOCKET=test bash scripts/codex-fleet/full-bringup.sh --n 2 --no-attach`) must succeed and `tmux -L test list-panes -t codex-fleet:0 -F '#{@panel}'` must NOT contain '[codex-fleet-tab-strip]'. Capture that exact command + its stdout/stderr into the PR description. (7) file_scope is exactly this one file.", + "file_scope": [ + "scripts/codex-fleet/full-bringup.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 4, + "title": "Drop the tab-strip-panel exclusion in plan-watcher.sh", + "description": "Edit scripts/codex-fleet/plan-watcher.sh: at line 134 (and any nearby lines that participate in the same loop) remove the `[ \"$panel\" = \"[codex-fleet-tab-strip]\" ] && continue` skip. Required: (1) Remove the conditional cleanly without breaking the surrounding while-read loop indentation. (2) Update the comment block at lines 127-130 ('the fleet-tab-strip header pane (panel == [codex-fleet-tab-strip])') to remove the bullet about excluding the header pane. (3) Verify with `bash -n scripts/codex-fleet/plan-watcher.sh` and `shellcheck scripts/codex-fleet/plan-watcher.sh`. (4) Run a 1-tick dry-run on the current session if any is up — but DO NOT start a long-running daemon. (5) file_scope is exactly this one file.", + "file_scope": [ + "scripts/codex-fleet/plan-watcher.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 5, + "title": "Delete the standalone fleet-tab-strip rust crate", + "description": "Delete the entire `rust/fleet-tab-strip/` Cargo crate. Required: (1) Remove rust/fleet-tab-strip/Cargo.toml and rust/fleet-tab-strip/src/main.rs (`git rm` both). (2) The workspace `rust/Cargo.toml` uses a `\"fleet-*\"` glob, so no edit there is strictly required — but VERIFY by running `cargo metadata --no-deps --manifest-path rust/Cargo.toml | jq '.packages[].name'` before and after, and confirm `fleet-tab-strip` is gone post-delete and that no other crate failed to resolve (the binary's `use fleet_ui::tab_strip::{Tab, TabHit, TabStrip}` is the only consumer of that import path; with the binary gone, the orphaned `fleet_ui::tab_strip` module is handled by Lane 7). (3) Run `cargo check --workspace --manifest-path rust/Cargo.toml` and capture the output as PR evidence — expected: success. (4) Update `rust/Cargo.lock` only if cargo writes to it as part of the check (let cargo handle it; DO NOT hand-edit the lockfile beyond what cargo produces). (5) file_scope is exactly these two source files — DO NOT touch rust/Cargo.toml in this lane (the glob keeps it stable; if cargo absolutely requires an edit, propose a follow-up PR rather than expanding scope).", + "file_scope": [ + "rust/fleet-tab-strip/Cargo.toml", + "rust/fleet-tab-strip/src/main.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 6, + "title": "Clean up style-tabs.sh comments + branding post-tab-strip-removal", + "description": "Edit scripts/codex-fleet/style-tabs.sh to remove dead branding about the in-binary tab strip. Required: (1) The current echo near the bottom contains 'in-binary tab strip is the navigation surface' as the default `status_state` description — update it to 'tmux status hidden — pane chrome is the navigation surface' (or similar accurate phrasing). (2) Find the long header docstring's reference to '`rust/fleet-ui::tab_strip`' as the in-binary tab strip and replace it with a note that the tab strip was removed in plan codex-fleet-glass-menu-drop-tabstrip-2026-05-15 and `CODEX_FLEET_TMUX_STATUS=on` re-enables the iOS-pill status bar for users who explicitly want chrome. (3) All tmux pill/format options stay in place — `style-tabs.sh` still configures status-style / window-status-current-format / etc. so the bar looks correct WHEN re-enabled. (4) `bash -n` and `shellcheck` must remain clean. (5) file_scope is exactly this one file — DO NOT touch overview-header.sh, full-bringup.sh, plan-watcher.sh, or any rust/ file.", + "file_scope": [ + "scripts/codex-fleet/style-tabs.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 7, + "title": "Remove orphaned fleet_ui::tab_strip module", + "description": "Delete the now-orphaned tab_strip module from the fleet-ui crate. Required: (1) Remove the `pub mod tab_strip;` declaration from rust/fleet-ui/src/lib.rs (line 14 per current grep). (2) Delete rust/fleet-ui/src/tab_strip.rs with `git rm`. (3) Run `cargo check -p fleet-ui --manifest-path rust/Cargo.toml` and capture the output as PR evidence (expected: success — Lane 5 already removed the only consumer at rust/fleet-tab-strip/src/main.rs). (4) Run `cargo check --workspace --manifest-path rust/Cargo.toml` as a regression smoke (expected: success). (5) Do NOT touch any other file in rust/fleet-ui/ (the chip / card / overlay / spotlight_filter modules remain intact). (6) file_scope is exactly these two files — do NOT touch any binary crate's main.rs, scripts/, or workspace manifest in this lane.", + "file_scope": [ + "rust/fleet-ui/src/lib.rs", + "rust/fleet-ui/src/tab_strip.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + } + ], + "published": { + "spec_task_id": 727, + "spec_change_path": "/home/deadpool/Documents/codex-fleet/openspec/changes/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/CHANGE.md", + "auto_archive": true + }, + "created_at": "2026-05-15T20:36:03.703Z", + "updated_at": "2026-05-15T20:36:03.703Z" +} diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/plan.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/plan.md new file mode 100644 index 0000000..dfe1229 --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/plan.md @@ -0,0 +1,34 @@ +# Glass/transparent pane menu + drop the codex-fleet tab strip + overall design pass + +Plan slug: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Problem + +The operator wants two visible design changes plus a polish pass. (1) The right-click pane action menu currently renders as a solid two-tone card (#1C1C1E inner / #2C2C2E border) that sits opaquely on top of the underlying pane. The operator wants it transparent / glassmorphic — the terminal's background (kitty supports background_opacity) should bleed through, with only hairline strokes, fg-only text, and a subtle iOS-blue underline on the focused row. (2) The 5-tab strip rendered at the top of the overview window by the standalone `rust/fleet-tab-strip` binary (spawned via `scripts/codex-fleet/overview-header.sh` and `scripts/codex-fleet/full-bringup.sh`) is to be removed entirely — including the binary, its workspace member, the spawn sites, and the downstream tmux pane-iteration excludes in `plan-watcher.sh` and `full-bringup.sh` that assume a `[codex-fleet-tab-strip]` panel exists. The dashboards already render their own iOS-chrome page headers (per the ios_page_design.rs modules merged in the previous plan), so the tab pane is now redundant. (3) An accompanying design pass: same transparent treatment for `help-popup.sh`, comment cleanup in `style-tabs.sh`, and removal of the now-orphaned `fleet_ui::tab_strip` module. The 8 lanes are flat-parallel — every lane edits exactly one disjoint file path (or one new disjoint set), depends_on=[] on all of them, so any fleet of 8 workers can claim and ship in parallel without `task_claim_file` contention. No shared helpers are added; each lane inlines the small bit of ANSI/transparency logic it needs. + +## Acceptance Criteria + +- All 8 sub-tasks land independently as 8 separate PRs against main with depends_on=[] honored; no two PRs touch the same file path. +- After Lane 0 ships, right-click on any codex-fleet pane renders the action menu with NO solid card background — the underlying pane's text shows through under the menu chrome (verified by sending Esc-prefixed paste of a known visible character before opening the menu). Hairline borders, title row, items, and shortcut chips all use fg-only ANSI; the focused row uses an iOS-blue underline rather than a fill. +- After Lane 1 ships, the help popup (prefix+Ctrl+H) renders with the same transparent treatment as Lane 0: hairline section dividers in #3A3A3C, section headers in iOS-blue fg, no solid card bg. +- After Lanes 2-5 ship, `bash scripts/codex-fleet/full-bringup.sh --n 4 --no-attach` brings up the overview window with NO `[codex-fleet-tab-strip]` pane at the top — the 4 workers occupy the full window. `tmux list-panes -t codex-fleet:0 -F '#{@panel}'` does not list the tab-strip panel. `plan-watcher.sh` no longer references it. `rust/Cargo.toml`'s `fleet-*` workspace glob no longer pulls in `fleet-tab-strip` because that directory is gone, and `cargo check --workspace` from `rust/` succeeds. +- After Lane 6 ships, `style-tabs.sh` no longer contains the 'in-binary tab strip is the navigation surface' branding in its echo / comments — the comments accurately describe the post-removal world (tmux status off by default, glass right-click menu is the canonical chrome layer). +- After Lane 7 ships, `rust/fleet-ui/src/lib.rs` no longer exports `pub mod tab_strip;`, `rust/fleet-ui/src/tab_strip.rs` is deleted, and `cargo check -p fleet-ui` succeeds. +- No regression in the existing dashboards: each `cargo check -p ` for fleet-state / fleet-plan-tree / fleet-waves / fleet-watcher still passes after their respective lanes (none of those crates' main.rs are edited by this plan, so this should be a no-op verification). +- Every PR's final note records: branch, files changed, command + output evidence (cargo check / shellcheck / bringup smoke), PR URL, MERGED state, and sandbox cleanup proof per the Guardex completion contract. + +## Roles + +- [planner](./planner.md) +- [architect](./architect.md) +- [critic](./critic.md) +- [executor](./executor.md) +- [writer](./writer.md) +- [verifier](./verifier.md) + +## Operator Flow + +1. Refine this workspace until scope, risks, and tasks are explicit. +2. Publish the plan with `colony plan publish codex-fleet-glass-menu-drop-tabstrip-2026-05-15` or the `task_plan_publish` MCP tool. +3. Claim subtasks through Colony plan tools before editing files. +4. Close only when all subtasks are complete and `checkpoints.md` records final evidence. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/planner.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/planner.md new file mode 100644 index 0000000..1095c75 --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/planner.md @@ -0,0 +1,13 @@ +# Planner + +Plan: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Responsibility + +Clarify scope, sequencing, dependencies, and acceptance criteria. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/tasks.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/tasks.md new file mode 100644 index 0000000..df8910f --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/tasks.md @@ -0,0 +1,12 @@ +# Tasks + +| # | Status | Title | Files | Depends on | Capability | Spec row | Owner | +| - | - | - | - | - | - | - | - | +0|available|Glass pane action menu — transparent chrome, fg-only ANSI, iOS-blue focus underline|`scripts/codex-fleet/bin/pane-context-menu.sh`|-|ui_work|-|- +1|available|Glass help popup — same transparent treatment as the action menu|`scripts/codex-fleet/bin/help-popup.sh`|-|ui_work|-|- +2|available|Drop fleet-tab-strip pane spawn from overview-header.sh|`scripts/codex-fleet/overview-header.sh`|-|infra_work|-|- +3|available|Drop fleet-tab-strip references from full-bringup.sh|`scripts/codex-fleet/full-bringup.sh`|-|infra_work|-|- +4|available|Drop the tab-strip-panel exclusion in plan-watcher.sh|`scripts/codex-fleet/plan-watcher.sh`|-|infra_work|-|- +5|available|Delete the standalone fleet-tab-strip rust crate|`rust/fleet-tab-strip/Cargo.toml`
`rust/fleet-tab-strip/src/main.rs`|-|infra_work|-|- +6|available|Clean up style-tabs.sh comments + branding post-tab-strip-removal|`scripts/codex-fleet/style-tabs.sh`|-|infra_work|-|- +7|available|Remove orphaned fleet_ui::tab_strip module|`rust/fleet-ui/src/lib.rs`
`rust/fleet-ui/src/tab_strip.rs`|-|infra_work|-|- diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/verifier.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/verifier.md new file mode 100644 index 0000000..5af8110 --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/verifier.md @@ -0,0 +1,13 @@ +# Verifier + +Plan: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Responsibility + +Prove completion with focused tests and explicit evidence. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/writer.md b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/writer.md new file mode 100644 index 0000000..9cc92db --- /dev/null +++ b/openspec/plans/codex-fleet-glass-menu-drop-tabstrip-2026-05-15/writer.md @@ -0,0 +1,13 @@ +# Writer + +Plan: `codex-fleet-glass-menu-drop-tabstrip-2026-05-15` + +## Responsibility + +Keep docs, operator notes, and final handoff language accurate. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/architect.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/architect.md new file mode 100644 index 0000000..f4862e5 --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/architect.md @@ -0,0 +1,13 @@ +# Architect + +Plan: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Responsibility + +Check boundaries, data flow, interfaces, and rollback shape. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/checkpoints.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/checkpoints.md new file mode 100644 index 0000000..d14d471 --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/checkpoints.md @@ -0,0 +1,22 @@ +# Checkpoints + +## Rollup + +- available: 5 +- claimed: 0 +- completed: 0 +- blocked: 0 + +## Subtasks + +- [ ] sub-0 fleet page · iOS bg + width-fill + live indicator [available] +- [ ] sub-1 waves page · iOS bg + spawn-timeline polish + live indicator [available] +- [ ] sub-2 review page · iOS bg + approval queue polish + live indicator [available] +- [ ] sub-3 watcher page · iOS bg + cap-pool polish + live indicator [available] +- [ ] sub-4 plan page · iOS bg + active-now + wave-strip + recent-merges polish + live indicator [available] + +## Completion Gate + +- [ ] All subtasks complete. +- [ ] Spec change archived or explicitly marked not applicable. +- [ ] Verification evidence recorded. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/critic.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/critic.md new file mode 100644 index 0000000..061126b --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/critic.md @@ -0,0 +1,13 @@ +# Critic + +Plan: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Responsibility + +Challenge weak assumptions, hidden risks, and missing tests. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/executor.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/executor.md new file mode 100644 index 0000000..c10bc68 --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/executor.md @@ -0,0 +1,13 @@ +# Executor + +Plan: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Responsibility + +Implement claimed subtasks inside declared file scope. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/plan.json b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/plan.json new file mode 100644 index 0000000..ed9462f --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/plan.json @@ -0,0 +1,106 @@ +{ + "schema_version": 1, + "plan_slug": "codex-fleet-ios-pages-design-pass-2026-05-15", + "title": "iOS background chrome + design polish + live indicators across all 5 fleet pages", + "problem": "All 5 fleet pages (fleet/waves/review/watcher/plan) already partially use the iOS palette (#007AFF · #34C759 · #FF3B30 · #FF9500) in their pills, chips, and status badges — but the PAGE-LEVEL chrome is still plain-black with no rounded card background, inconsistent header treatment, no live indicators that visually signal the data is fresh, and (on fleet) huge unused right-side space because ACTIVE/RESERVE stack vertically inside a fixed ~85-col card. The 'iOS palette · rounded cards' note in the watcher footer hints at the intent but the page bodies haven't been wrapped in iOS card chrome. This plan opens 5 parallel lanes — one per page — each adding a new _ios_design.rs ratatui module that delivers (a) an iOS-styled outer page card with palette gradient + 1px rounded border, (b) a consistent header strip matching the watcher footer palette stripe, (c) refined inner hierarchy and column-fill so no pane wastes width, and (d) an animated LiveIndicator sub-widget that pulses on tick. Wiring each new module into its crate's main.rs is intentionally OUT OF SCOPE here — that ships in a follow-up integration plan once all 5 land, so the 5 lanes have zero file_scope contention.", + "acceptance_criteria": [ + "All 5 tasks have depends_on=[] and file_scope disjoint — no two tasks list the same file.", + "Each task lands a single NEW .rs module file inside its target crate; no edits to existing main.rs / lib.rs / shared helpers in this plan.", + "Each module exports a public IosPageDesign ratatui Widget whose render(frame, area, state) consistently uses the iOS palette (#007AFF accent, #34C759 success, #FF3B30 destructive, #FF9500 warning) for status pills, headings, and dividers.", + "Each module embeds a public LiveIndicator sub-widget that takes a tick counter / Instant and renders an animated state — pulsing dot when fresh (<2s since last update), steady when idle, fade/dim when stale (>10s).", + "Each new module compiles standalone via cargo check -p and ships one insta snapshot test for the fresh-tick state and one for the stale-tick state.", + "Each subtask description points at the matching reference screenshot so the agent can match palette/spacing/hierarchy intent." + ], + "roles": [ + "planner", + "architect", + "critic", + "executor", + "writer", + "verifier" + ], + "tasks": [ + { + "subtask_index": 0, + "title": "fleet page · iOS bg + width-fill + live indicator", + "description": "Create rust/fleet-state/src/ios_page_design.rs implementing the full iOS-styled fleet cockpit page. Match the existing fleet cockpit content (ACTIVE / RESERVE / FOOTER sections currently rendered by scripts/codex-fleet/fleet-tick.sh into /tmp/claude-viz/live-fleet-state.txt) but: (1) wrap the page in a rounded iOS outer card with the palette gradient header, (2) lay out ACTIVE | RESERVE as two SIDE-BY-SIDE cards at panel width >= 180 cols (vertical fallback below 180) so the cockpit fills the pane instead of leaving the right ~60% black, (3) fix the white-bar artifact in the WORKING ON column by computing it from the actual claimed-task text, not a fixed-width sentinel, (4) add a LiveIndicator pulsing dot at the header that ticks every 1s. Snapshot tests: wide layout (200 cols), narrow layout (90 cols), fresh tick, stale tick. Do NOT touch fleet-state/main.rs or scripts/codex-fleet/fleet-tick.sh in this plan.", + "file_scope": [ + "rust/fleet-state/src/ios_page_design.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 1, + "title": "waves page · iOS bg + spawn-timeline polish + live indicator", + "description": "Create rust/fleet-waves/src/ios_page_design.rs implementing the iOS-styled waves spawn-timeline page. Match Image #22's content (W1..Wn wave cards each showing N tasks, done|partial|waiting state, progress rails) but wrap the whole page in a rounded iOS outer card with a header strip showing plan slug + 'parallel execution · live' badge + LiveIndicator. Wave cards become consistent iOS rounded cards with palette-mapped status: done=#34C759, partial=#FF9500, waiting=#FF3B30 outline, ready=#007AFF. Inner progress rails use the iOS green-fill style. Add a MAX PARALLEL / claimed / done / available counters strip in a single rounded sub-card. Snapshot tests: 8-wave layout, fresh+stale ticks. Do NOT touch fleet-waves/main.rs or scripts/codex-fleet/waves-anim-generic.sh.", + "file_scope": [ + "rust/fleet-waves/src/ios_page_design.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 2, + "title": "review page · iOS bg + approval queue polish + live indicator", + "description": "Create rust/fleet-ui/src/review_ios_page_design.rs implementing the iOS-styled review approval queue page. Match Image #24's content (REV-xxx card with risk/auth pills, AUTO-REVIEWER RATIONALE block, FILES TOUCHED list, A/V/D action row, Recent decisions sidebar) but wrap in rounded iOS outer card with palette stripe. The risk pill colors must map: low=#34C759, medium=#FF9500, high=#FF3B30; auth pill uses #007AFF for high, #34C759 for low. Recent-decisions chips use the same mapping. Add a LiveIndicator pulsing at the queue header showing 'auto-reviewer on · last '. Snapshot tests: pending REV card present, empty queue, fresh+stale ticks. Do NOT touch fleet-ui/lib.rs or any existing fleet-ui review code in this plan.", + "file_scope": [ + "rust/fleet-ui/src/review_ios_page_design.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 3, + "title": "watcher page · iOS bg + cap-pool polish + live indicator", + "description": "Create rust/fleet-watcher/src/ios_page_design.rs implementing the iOS-styled fleet-watcher page. Match Image #25's content exactly (FLEET WATCHER header, PANES/CAPPED/SWAPPED/RANKED 4-up summary cards, ACCOUNT POOL healthy/capped pills, FLEET PANES table, CAP POOL burned-accounts table with reset ETA, RECENT ACTIVITY log) but wrap in rounded iOS outer card with the palette footer stripe already mentioned in the bottom of Image #25 ('iOS palette · #007AFF / #34C759 / #FF3B30 / #FF9500 · rounded cards'). All status pills use the canonical palette: working=#007AFF, idle=gray, approval=#FF9500, capped/exhausted=#FF3B30. Add a LiveIndicator near 'last sweep · next in ' that pulses on each sweep. Snapshot tests: idle fleet, with-capped, fresh+stale ticks. Do NOT touch fleet-watcher/main.rs or scripts/codex-fleet/watcher-board.sh.", + "file_scope": [ + "rust/fleet-watcher/src/ios_page_design.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 4, + "title": "plan page · iOS bg + active-now + wave-strip + recent-merges polish + live indicator", + "description": "Create rust/fleet-plan-tree/src/ios_page_design.rs implementing the iOS-styled plan-tree page. Match Image #21's content (PLAN TREE header showing plan slug + N done/claimed/available, ACTIVE NOW agents-on-Colony-tasks list, WAVES W1->Wn strip with working/done/idle pills, RECENT MERGES git-log-oneline list at bottom) but wrap in rounded iOS outer card. ACTIVE NOW rows become palette-mapped: working=#007AFF dot, idle=gray, done=#34C759. WAVES strip pills follow waves page palette. RECENT MERGES list gets a subtle iOS-style left border accent (#007AFF). Add a LiveIndicator near the PLAN TREE header pulsing every 1s when fleet-data refresh is live. Snapshot tests: small plan (3 tasks), large plan (18 tasks), fresh+stale ticks. Do NOT touch fleet-plan-tree/main.rs or scripts/codex-fleet/plan-tree-anim.sh.", + "file_scope": [ + "rust/fleet-plan-tree/src/ios_page_design.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + } + ], + "published": { + "spec_task_id": 736, + "spec_change_path": "/home/deadpool/Documents/codex-fleet/openspec/changes/codex-fleet-ios-pages-design-pass-2026-05-15/CHANGE.md", + "auto_archive": false + }, + "created_at": "2026-05-15T20:36:03.818Z", + "updated_at": "2026-05-15T20:36:03.818Z" +} diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/plan.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/plan.md new file mode 100644 index 0000000..e2f1ddf --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/plan.md @@ -0,0 +1,32 @@ +# iOS background chrome + design polish + live indicators across all 5 fleet pages + +Plan slug: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Problem + +All 5 fleet pages (fleet/waves/review/watcher/plan) already partially use the iOS palette (#007AFF · #34C759 · #FF3B30 · #FF9500) in their pills, chips, and status badges — but the PAGE-LEVEL chrome is still plain-black with no rounded card background, inconsistent header treatment, no live indicators that visually signal the data is fresh, and (on fleet) huge unused right-side space because ACTIVE/RESERVE stack vertically inside a fixed ~85-col card. The 'iOS palette · rounded cards' note in the watcher footer hints at the intent but the page bodies haven't been wrapped in iOS card chrome. This plan opens 5 parallel lanes — one per page — each adding a new _ios_design.rs ratatui module that delivers (a) an iOS-styled outer page card with palette gradient + 1px rounded border, (b) a consistent header strip matching the watcher footer palette stripe, (c) refined inner hierarchy and column-fill so no pane wastes width, and (d) an animated LiveIndicator sub-widget that pulses on tick. Wiring each new module into its crate's main.rs is intentionally OUT OF SCOPE here — that ships in a follow-up integration plan once all 5 land, so the 5 lanes have zero file_scope contention. + +## Acceptance Criteria + +- All 5 tasks have depends_on=[] and file_scope disjoint — no two tasks list the same file. +- Each task lands a single NEW .rs module file inside its target crate; no edits to existing main.rs / lib.rs / shared helpers in this plan. +- Each module exports a public IosPageDesign ratatui Widget whose render(frame, area, state) consistently uses the iOS palette (#007AFF accent, #34C759 success, #FF3B30 destructive, #FF9500 warning) for status pills, headings, and dividers. +- Each module embeds a public LiveIndicator sub-widget that takes a tick counter / Instant and renders an animated state — pulsing dot when fresh (<2s since last update), steady when idle, fade/dim when stale (>10s). +- Each new module compiles standalone via cargo check -p and ships one insta snapshot test for the fresh-tick state and one for the stale-tick state. +- Each subtask description points at the matching reference screenshot so the agent can match palette/spacing/hierarchy intent. + +## Roles + +- [planner](./planner.md) +- [architect](./architect.md) +- [critic](./critic.md) +- [executor](./executor.md) +- [writer](./writer.md) +- [verifier](./verifier.md) + +## Operator Flow + +1. Refine this workspace until scope, risks, and tasks are explicit. +2. Publish the plan with `colony plan publish codex-fleet-ios-pages-design-pass-2026-05-15` or the `task_plan_publish` MCP tool. +3. Claim subtasks through Colony plan tools before editing files. +4. Close only when all subtasks are complete and `checkpoints.md` records final evidence. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/planner.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/planner.md new file mode 100644 index 0000000..f730eaa --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/planner.md @@ -0,0 +1,13 @@ +# Planner + +Plan: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Responsibility + +Clarify scope, sequencing, dependencies, and acceptance criteria. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/tasks.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/tasks.md new file mode 100644 index 0000000..64eb854 --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/tasks.md @@ -0,0 +1,9 @@ +# Tasks + +| # | Status | Title | Files | Depends on | Capability | Spec row | Owner | +| - | - | - | - | - | - | - | - | +0|available|fleet page · iOS bg + width-fill + live indicator|`rust/fleet-state/src/ios_page_design.rs`|-|ui_work|-|- +1|available|waves page · iOS bg + spawn-timeline polish + live indicator|`rust/fleet-waves/src/ios_page_design.rs`|-|ui_work|-|- +2|available|review page · iOS bg + approval queue polish + live indicator|`rust/fleet-ui/src/review_ios_page_design.rs`|-|ui_work|-|- +3|available|watcher page · iOS bg + cap-pool polish + live indicator|`rust/fleet-watcher/src/ios_page_design.rs`|-|ui_work|-|- +4|available|plan page · iOS bg + active-now + wave-strip + recent-merges polish + live indicator|`rust/fleet-plan-tree/src/ios_page_design.rs`|-|ui_work|-|- diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/verifier.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/verifier.md new file mode 100644 index 0000000..6534245 --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/verifier.md @@ -0,0 +1,13 @@ +# Verifier + +Plan: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Responsibility + +Prove completion with focused tests and explicit evidence. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/writer.md b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/writer.md new file mode 100644 index 0000000..59b8493 --- /dev/null +++ b/openspec/plans/codex-fleet-ios-pages-design-pass-2026-05-15/writer.md @@ -0,0 +1,13 @@ +# Writer + +Plan: `codex-fleet-ios-pages-design-pass-2026-05-15` + +## Responsibility + +Keep docs, operator notes, and final handoff language accurate. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-overlay-modulesplit-2026-05-14/plan.json b/openspec/plans/codex-fleet-overlay-modulesplit-2026-05-14/plan.json index 0512c01..3bcaff0 100644 --- a/openspec/plans/codex-fleet-overlay-modulesplit-2026-05-14/plan.json +++ b/openspec/plans/codex-fleet-overlay-modulesplit-2026-05-14/plan.json @@ -111,6 +111,6 @@ "spec_change_path": "/home/deadpool/Documents/codex-fleet/openspec/changes/codex-fleet-overlay-modulesplit-2026-05-14/CHANGE.md", "auto_archive": false }, - "created_at": "2026-05-14T18:04:27.883Z", - "updated_at": "2026-05-14T18:04:27.883Z" + "created_at": "2026-05-15T20:36:04.257Z", + "updated_at": "2026-05-15T20:36:04.257Z" } diff --git a/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/checkpoints.md b/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/checkpoints.md index 9cf7e5c..912379b 100644 --- a/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/checkpoints.md +++ b/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/checkpoints.md @@ -2,19 +2,19 @@ ## Rollup -- available: 6 +- available: 4 - claimed: 0 -- completed: 0 +- completed: 2 - blocked: 0 ## Subtasks -- [ ] sub-0 fleet-ui::overlay::ContextMenu widget — port from POC [available] -- [ ] sub-1 fleet-ui::overlay::Spotlight widget — port from POC with interactive state [available] +- [x] sub-0 fleet-ui::overlay::ContextMenu widget — port from POC [completed] +- [x] sub-1 fleet-ui::overlay::Spotlight widget — port from POC with interactive state [completed] - PR #117 Add fleet-ui spotlight overlay widget - [ ] sub-2 fleet-ui::overlay::ActionSheet + SessionSwitcher widgets — port from POC [available] - [ ] sub-3 Wire Spotlight + ContextMenu keybindings into fleet-watcher [available] - [ ] sub-4 Wire same keybindings into fleet-state + fleet-plan-tree + fleet-waves [available] -- [ ] sub-5 Soak test all four binaries against the live fleet + tick the openspec checkboxes [available] +- [ ] sub-5 Soak test all four binaries against the live fleet + tick the openspec checklist [available] ## Completion Gate diff --git a/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/plan.json b/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/plan.json index 3bef92d..6e47bff 100644 --- a/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/plan.json +++ b/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/plan.json @@ -23,7 +23,7 @@ { "subtask_index": 0, "title": "fleet-ui::overlay::ContextMenu widget — port from POC", - "description": "In rust/fleet-ui/src/overlay.rs, add a `ContextMenu` struct + impl. Inputs: sections (`Vec
` where each Section is a list of MenuItem { icon, label, shortcut, destructive }), title, status_dot (Color), badge (Option<(text, fg, bg)>). The render method should reproduce the POC visuals exactly: rounded 48-wide glass card on IOS_BG_GLASS, drop shadow (use the helper from fleet-tui-poc's card_shadow — port it too), title row with status dot + pane label + right-aligned LIVE pill, hairline below title, sections separated by hairline rows, items rendered as ` [icon] label [shortcut]` with destructive items in IOS_DESTRUCTIVE red. Source: rust/fleet-tui-poc/src/main.rs lines around `fn render_context_menu` (~lines 630-770). Add an insta snapshot test at 80x40 with the same 5 sections the POC uses.", + "description": "In rust/fleet-ui/src/overlay.rs, add a ContextMenu struct with sections, title, status_dot, badge. Render the 48-wide glass card with drop shadow, title row, hairline-separated sections, and destructive red items. Add an insta snapshot test at 80x40 with the POC's 5 sections.", "file_scope": [ "rust/fleet-ui/src/overlay.rs", "rust/fleet-ui/tests/overlay_context_menu.rs", @@ -32,7 +32,7 @@ "depends_on": [], "spec_row_id": null, "capability_hint": "ui_work", - "status": "available", + "status": "completed", "claimed_by_session_id": null, "claimed_by_agent": null, "completed_summary": null @@ -40,7 +40,7 @@ { "subtask_index": 1, "title": "fleet-ui::overlay::Spotlight widget — port from POC with interactive state", - "description": "In rust/fleet-ui/src/overlay.rs, add a `Spotlight` widget. Public state struct: `SpotlightState { pub query: String, pub selected: usize, pub tick: u64 }`. Public item type: `SpotlightItem { pub group: &'static str, pub icon: &'static str, pub title: &'static str, pub sub: &'static str, pub kbd: &'static str }`. Public filter fn: `pub fn filter<'a>(items: &'a [SpotlightItem], query: &str) -> Vec<&'a SpotlightItem>`. Render method takes (frame, area, state, items). Reproduce POC visuals: 78x42 glass card with drop shadow, search bar with ⌕ + query + blinking caret driven off `state.tick`, hairline, TOP HIT label, 3-row top-hit pill (systemBlue with darker icon chip + right-aligned `tmux · KBD` badge + chevron, subtitle on row 2), grouped remaining results with `IOS_CARD_BG` background per group, 2-row items (icon+title+kbd row, then subtitle row), selected row tinted `IOS_TINT_DARK` with white fg + IOS_TINT_SUB sub. Empty-state 'no matches' centered when filter returns empty. Footer hint row: `↵ open · ⌥↵ all panes · esc cancel · ✦ N items`. Source: rust/fleet-tui-poc/src/main.rs ~lines 760-1050. Insta snapshot test at 100x40 with the POC's default 9-item catalogue and query=`split`.", + "description": "Add Spotlight widget + SpotlightState (query, selected, tick) to fleet-ui/src/overlay.rs. Reproduce POC visuals: 78x42 glass card, search bar with blinking caret, top-hit pill, grouped results with selection tint, footer hint, empty-state. Insta snapshot at 100x40 with query='split'.", "file_scope": [ "rust/fleet-ui/src/overlay.rs", "rust/fleet-ui/tests/overlay_spotlight.rs", @@ -51,15 +51,15 @@ ], "spec_row_id": null, "capability_hint": "ui_work", - "status": "available", + "status": "completed", "claimed_by_session_id": null, "claimed_by_agent": null, - "completed_summary": null + "completed_summary": "PR #117 Add fleet-ui spotlight overlay widget" }, { "subtask_index": 2, "title": "fleet-ui::overlay::ActionSheet + SessionSwitcher widgets — port from POC", - "description": "Add two more reusable widgets to rust/fleet-ui/src/overlay.rs. (a) `ActionSheet`: bottom-anchored 64-wide glass card with separate Cancel button below; takes groups (title + optional caption + items). 2-row tall items with 3x2 icon-chip bg, colored chip bg per item state (destructive=red-tint, warning=orange-tint, default=icon-chip-gray). Drop shadow on both the card and the Cancel pill. Source: POC main.rs ~lines 1055-1245. (b) `SessionSwitcher`: full-screen card stack — header (CODEX-FLEET · SESSION SWITCHER + worker count + awaiting-review count), top-right 'New worker' pill, horizontally-scrolling 30-wide tinted cards per session with active card highlighted (systemBlue border + LIVE green pill), MODEL/CONTEXT/RUNTIME rows, action button row (Focus / Queue / Pause / Kill), badge routing (LIVE=green, ⚠ REVIEW=orange, other=chip-gray). Source: POC main.rs ~lines 1247-1640. Insta snapshots at 80x40 and 140x40 respectively.", + "description": "Port ActionSheet (modal bottom card with destructive option) and SessionSwitcher (full-screen iOS surface with clickable session cards) into fleet-ui/src/overlay.rs with insta snapshots.", "file_scope": [ "rust/fleet-ui/src/overlay.rs", "rust/fleet-ui/tests/overlay_action_sheet.rs", @@ -79,7 +79,7 @@ { "subtask_index": 3, "title": "Wire Spotlight + ContextMenu keybindings into fleet-watcher", - "description": "In rust/fleet-watcher/src/main.rs, add overlay state (`overlay: Option`, where OverlayKind in { Spotlight(SpotlightState), ContextMenu }) to the binary's App struct. Key handler: when no overlay is active, `?` or `/` opens Spotlight (initial SpotlightState empty), `m` opens ContextMenu for the active pane (resolve via tmux env `$TMUX_PANE` or pass `--pane` at startup). When Spotlight is open: route printable keys to query, Up/Down to selected, Esc/q to close, Enter to dispatch the selected action via context_menu_tmux_args / direct std::process::Command. When ContextMenu is open: shortcut letters (h, v, z, u, d, s, m, R, X) dispatch the same tmux subcommands as the POC, Esc/q to close. While an overlay is open, skip the dashboard tick repaint so the overlay doesn't flicker; resume tick on dismiss. Render order: dashboard first, then overlay on top via fleet_ui::overlay widgets.", + "description": "Add ? / / for Spotlight, m for ContextMenu, Esc/q for dismiss in fleet-watcher's main loop. Pause dashboard ticks while overlay is open.", "file_scope": [ "rust/fleet-watcher/src/main.rs", "rust/fleet-watcher/Cargo.toml" @@ -98,7 +98,7 @@ { "subtask_index": 4, "title": "Wire same keybindings into fleet-state + fleet-plan-tree + fleet-waves", - "description": "Replicate the overlay wiring from fleet-watcher (subtask 3) into the other three view binaries: rust/fleet-state/src/main.rs, rust/fleet-plan-tree/src/main.rs, rust/fleet-waves/src/main.rs. Key behavior identical: `?` / `/` opens Spotlight, `m` opens ContextMenu, `Esc` / `q` dismisses, dashboard tick pauses while overlay is up. To avoid four-way duplication, consider lifting the overlay-state + key handler into a small helper in fleet-ui (e.g. `fleet_ui::overlay::OverlayController` with `handle_key(&mut self, k: KeyEvent) -> OverlayOutcome` and `render(&mut self, frame, area)`) and call it from each binary's event loop. If the helper proves over-engineered, just duplicate cleanly — three small repetitions are better than a premature abstraction.", + "description": "Mirror the fleet-watcher overlay wiring into the other three Rust dashboard binaries. Share the keybinding helpers via fleet-ui where possible.", "file_scope": [ "rust/fleet-state/src/main.rs", "rust/fleet-plan-tree/src/main.rs", @@ -117,8 +117,8 @@ }, { "subtask_index": 5, - "title": "Soak test all four binaries against the live fleet + tick the openspec checkboxes", - "description": "In a real codex-fleet tmux session, run each of the four view binaries in turn. For each: (a) confirm `?` opens Spotlight, type a filter, select an item, confirm the dispatched tmux command runs against the active pane, (b) confirm `m` opens the ContextMenu for the active pane, press a shortcut, confirm dispatch, (c) confirm `Esc` dismisses without dispatch. Capture before/after screenshots side-by-side with the bash dashboards to confirm visual parity holds when overlays are dismissed. Tick the three Phase 5 checkboxes in openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md: 'Context-menu overlay (bordered list popup)', 'Spotlight palette overlay …', 'Trigger keybindings wired in each view binary'. Include PR links in the bullet annotations. Once Phase 5 is done, leave a short note in the tasks.md hand-off block that Phase 6 (retire bash) is now unblocked.", + "title": "Soak test all four binaries against the live fleet + tick the openspec checklist", + "description": "Run all four Rust binaries in the live tmux fleet, exercise Spotlight + ContextMenu in each, and tick the Phase 5 checkboxes in openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md with PR links.", "file_scope": [ "openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md" ], @@ -138,6 +138,6 @@ "spec_change_path": "/home/deadpool/Documents/codex-fleet/openspec/changes/codex-fleet-overlays-phase5-2026-05-14/CHANGE.md", "auto_archive": false }, - "created_at": "2026-05-14T17:34:07.483Z", - "updated_at": "2026-05-14T17:34:07.483Z" + "created_at": "2026-05-15T20:36:04.135Z", + "updated_at": "2026-05-15T20:46:00.869Z" } diff --git a/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/tasks.md b/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/tasks.md index 5272b25..87c4392 100644 --- a/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/tasks.md +++ b/openspec/plans/codex-fleet-overlays-phase5-2026-05-14/tasks.md @@ -2,9 +2,9 @@ | # | Status | Title | Files | Depends on | Capability | Spec row | Owner | | - | - | - | - | - | - | - | - | -0|available|fleet-ui::overlay::ContextMenu widget — port from POC|`rust/fleet-ui/src/overlay.rs`
`rust/fleet-ui/tests/overlay_context_menu.rs`
`rust/fleet-ui/src/lib.rs`|-|ui_work|-|- -1|available|fleet-ui::overlay::Spotlight widget — port from POC with interactive state|`rust/fleet-ui/src/overlay.rs`
`rust/fleet-ui/tests/overlay_spotlight.rs`
`rust/fleet-ui/src/lib.rs`|0|ui_work|-|- +0|completed|fleet-ui::overlay::ContextMenu widget — port from POC|`rust/fleet-ui/src/overlay.rs`
`rust/fleet-ui/tests/overlay_context_menu.rs`
`rust/fleet-ui/src/lib.rs`|-|ui_work|-|- +1|completed|fleet-ui::overlay::Spotlight widget — port from POC with interactive state|`rust/fleet-ui/src/overlay.rs`
`rust/fleet-ui/tests/overlay_spotlight.rs`
`rust/fleet-ui/src/lib.rs`|0|ui_work|-|- 2|available|fleet-ui::overlay::ActionSheet + SessionSwitcher widgets — port from POC|`rust/fleet-ui/src/overlay.rs`
`rust/fleet-ui/tests/overlay_action_sheet.rs`
`rust/fleet-ui/tests/overlay_session_switcher.rs`
`rust/fleet-ui/src/lib.rs`|1|ui_work|-|- 3|available|Wire Spotlight + ContextMenu keybindings into fleet-watcher|`rust/fleet-watcher/src/main.rs`
`rust/fleet-watcher/Cargo.toml`|1, 2|ui_work|-|- 4|available|Wire same keybindings into fleet-state + fleet-plan-tree + fleet-waves|`rust/fleet-state/src/main.rs`
`rust/fleet-plan-tree/src/main.rs`
`rust/fleet-waves/src/main.rs`
`rust/fleet-ui/src/overlay.rs`|3|ui_work|-|- -5|available|Soak test all four binaries against the live fleet + tick the openspec checkboxes|`openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md`|4|test_work|-|- +5|available|Soak test all four binaries against the live fleet + tick the openspec checklist|`openspec/changes/fleet-tui-ratatui-port-2026-05-14/tasks.md`|4|test_work|-|- diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/architect.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/architect.md new file mode 100644 index 0000000..0cd36e3 --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/architect.md @@ -0,0 +1,13 @@ +# Architect + +Plan: `codex-fleet-tui-improvements-2026-05-15` + +## Responsibility + +Check boundaries, data flow, interfaces, and rollback shape. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/checkpoints.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/checkpoints.md new file mode 100644 index 0000000..203b5d6 --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/checkpoints.md @@ -0,0 +1,29 @@ +# Checkpoints + +## Rollup + +- available: 12 +- claimed: 0 +- completed: 0 +- blocked: 0 + +## Subtasks + +- [ ] sub-0 Supervisor classifier prompt + Opus/Sonnet tiering + 3-strike loop guard documentation [available] +- [ ] sub-1 Classifier replay fixtures + harness (new test dir) [available] +- [ ] sub-2 Cap-swap hand-off contract + worktree/claim preservation [available] +- [ ] sub-3 Claude fallback worker spawn polish — idempotent, claim-aware [available] +- [ ] sub-4 Plan flat-parallelism validator (new lib script) [available] +- [ ] sub-5 Wire plan-validator into plan-watcher.sh on every tick [available] +- [ ] sub-6 Auto-reviewer daemon scaffold (file is currently MISSING) [available] +- [ ] sub-7 Review rubric + diff prepass (two new lib files) [available] +- [ ] sub-8 Pane health crate (new rust workspace crate) [available] +- [ ] sub-9 Metrics TSV viewer crate (new rust workspace crate) [available] +- [ ] sub-10 Renderer polish crate (shared chrome primitives library) [available] +- [ ] sub-11 Attention inbox dedup helper (new lib script) [available] + +## Completion Gate + +- [ ] All subtasks complete. +- [ ] Spec change archived or explicitly marked not applicable. +- [ ] Verification evidence recorded. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/critic.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/critic.md new file mode 100644 index 0000000..f843db1 --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/critic.md @@ -0,0 +1,13 @@ +# Critic + +Plan: `codex-fleet-tui-improvements-2026-05-15` + +## Responsibility + +Challenge weak assumptions, hidden risks, and missing tests. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/executor.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/executor.md new file mode 100644 index 0000000..7ab2405 --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/executor.md @@ -0,0 +1,13 @@ +# Executor + +Plan: `codex-fleet-tui-improvements-2026-05-15` + +## Responsibility + +Implement claimed subtasks inside declared file scope. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.json b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.json new file mode 100644 index 0000000..a539f48 --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.json @@ -0,0 +1,225 @@ +{ + "schema_version": 1, + "plan_slug": "codex-fleet-tui-improvements-2026-05-15", + "title": "codex-fleet TUI improvements: supervisor classifier, cap-swap hand-off, plan validation, auto-reviewer, pane health, metrics viewer, renderer polish, inbox dedup", + "problem": "The codex-fleet TUI is functional but has eight measurable gaps that compound throughput loss. (1) The supervisor's asking/blocked/working classifier in scripts/codex-fleet/supervisor.sh has no replayable fixtures and no documented Opus 4.7 + Sonnet tiering thresholds, so regressions in classification land silently; the 3-strike loop guard is also opaque. (2) cap-swap-daemon.sh hands a 429'd pane off to a fallback worker without an explicit contract for Colony claim transfer, worktree preservation, or env carry-over, so swapped panes sometimes orphan their claim. (3) Plan publication is unguarded — there is no validator that enforces the parallel-first rule (flat depends_on, disjoint file_scope), so bad plans deadlock workers on task_claim_file. (4) scripts/codex-fleet/auto-reviewer.sh is referenced by the dispatch protocol and the codex-fleet-dispatch skill but does not actually exist on disk — end-of-plan review is therefore manual. (5) There is no per-pane health surface — operators tail individual logs to diagnose a stuck pane; pane-health (last activity, claim state, cap-status) should be a first-class crate. (6) The supervisor metrics TSV (when written) has no live viewer, only post-hoc grep. (7) The dashboard chrome (iOS page headers in fleet-waves, fleet-state, etc) is rendered ad-hoc per crate; a shared renderer-polish layer would give consistent corner radii / hairlines / iOS-blue accent across every dashboard binary. (8) Colony attention_inbox returns duplicate-near handoffs (same task, slightly different timestamps or rationales); a dedup helper would let the orchestrator show the operator a clean list. All 12 lanes are flat-parallel — every lane edits exactly one disjoint file path (or one new disjoint set), depends_on=[] on all of them, so a fleet of 12 workers can claim and ship in parallel without task_claim_file contention. New rust crates use the workspace's fleet-* glob, so no shared rust/Cargo.toml edit is required. Soft references (Lane 5 calls Lane 4's validator at a known path; Lane 6's auto-reviewer reads Lane 7's rubric at a known path) tolerate either landing order — the consumer no-ops or warns until the producer ships.", + "acceptance_criteria": [ + "All 12 sub-tasks land independently as 12 separate PRs against main with depends_on=[] honored; no two PRs touch the same file path.", + "After Lane 0 ships, scripts/codex-fleet/supervisor.sh contains: an explicit classifier prompt with labeled categories (working / asking / blocked / done), a documented Opus 4.7 escalation threshold, prompt-cache markers around the static system prompt, and a comment block describing the 3-strike loop guard with the exact metric that trips it. shellcheck exits 0.", + "After Lane 1 ships, scripts/codex-fleet/test/classifier-fixtures/ contains at least 20 captured pane snapshots (.txt files) with sibling .label files marking the expected category. scripts/codex-fleet/test/run-classifier-replay.sh iterates the fixtures, invokes the classifier, and prints a confusion matrix; exits non-zero if accuracy < 0.85 on the captured set.", + "After Lane 2 ships, cap-swap-daemon.sh has a top-of-file CONTRACT section enumerating every field that must transfer on hand-off (Colony task_id, branch, worktree path, CODEX_HOME, account email, last claim timestamp) and a smoke-test stanza that simulates a 429 against a fixture pane and asserts the claim is released cleanly. No orphaned worktrees after the simulated swap.", + "After Lane 3 ships, scripts/codex-fleet/claude-spawn.sh is idempotent (re-running on a live pane is a no-op + 0 exit), accepts an inherited CODEX_FLEET_TASK_ID env var so a cap-swapped pane resumes the same Colony claim, and refuses to spawn into a pane whose @panel does not match the expected worker pattern (defensive guard).", + "After Lane 4 ships, scripts/codex-fleet/lib/plan-validator.sh exists, is executable, and validates a plan.json file at a given path against three rules: (a) every sub-task's depends_on is empty unless --allow-waves is passed, (b) no two sub-tasks share a file path in file_scope, (c) acceptance_criteria is a non-empty array of strings each ≥ 40 chars. Exit codes: 0 ok, 2 warnings, 3 hard errors.", + "After Lane 5 ships, plan-watcher.sh invokes plan-validator.sh on every tick against the currently-active plan and surfaces warnings/errors in /tmp/plan-watcher.log with a stable prefix ('PLAN-VALIDATE:'). Hard errors do NOT crash the watcher but DO skip dispatch for that tick. shellcheck exits 0.", + "After Lane 6 ships, scripts/codex-fleet/auto-reviewer.sh exists, is executable, and on invocation reads .codex-fleet/active-plan, gathers all PRs merged for that plan slug via gh pr list, builds a review prompt using the rubric (Lane 7) and the prepass diff (Lane 7), invokes the local claude CLI in --print mode, and writes the output to /tmp/claude-viz/plan-review-.md. Supports --dry-run for offline test.", + "After Lane 7 ships, scripts/codex-fleet/lib/review-rubric.md exists and documents the explicit review checklist (regression risk, scope creep against plan acceptance_criteria, anti-pattern flags, blast radius); scripts/codex-fleet/lib/review-prepass.sh exists and emits a single markdown blob with the plan's stated scope + the actual diff for every PR, ready to be piped to a model.", + "After Lane 8 ships, rust/fleet-pane-health/ is a new workspace crate that builds (cargo check -p fleet-pane-health) and renders a per-pane health row (pane id, last activity age, current Colony claim if any, cap-probe cache state) using ratatui + the shared fleet-ui chrome helpers. It reads from /tmp/claude-viz/cap-probe-cache/*.json and tmux capture-pane output. No edits to existing crates.", + "After Lane 9 ships, rust/fleet-metrics-viewer/ is a new workspace crate that tails a TSV path passed via --path (default /tmp/claude-viz/supervisor-metrics.tsv when present, else --no-op) and renders the last N rows as a live dashboard with iOS-style chrome. cargo check -p fleet-metrics-viewer succeeds. No edits to existing crates.", + "After Lane 10 ships, rust/fleet-renderer-polish/ is a new workspace crate exposing a small library of ratatui chrome primitives (rounded_corner_block, hairline_divider, ios_status_chip, page_header_with_accent) factored from the patterns already in fleet-waves/fleet-state. cargo check -p fleet-renderer-polish succeeds; it does NOT yet replace any existing crate's chrome — adoption is a follow-up. No edits to existing crates.", + "After Lane 11 ships, scripts/codex-fleet/lib/inbox-dedup.sh exists and reads JSONL from stdin (Colony attention_inbox export), groups near-duplicates by (task_id, kind, content-hash with whitespace normalized), and prints a deduped JSONL to stdout. Exit 0 always; idempotent on already-deduped input.", + "No regression in existing dashboards: cargo check --workspace from rust/ still passes after all 12 lanes land.", + "Every PR's final note records: branch, files changed, command + output evidence (shellcheck, cargo check, fixture replay where applicable), PR URL, MERGED state, and sandbox cleanup proof per the Guardex completion contract." + ], + "roles": [ + "planner", + "architect", + "critic", + "executor", + "writer", + "verifier" + ], + "tasks": [ + { + "subtask_index": 0, + "title": "Supervisor classifier prompt + Opus/Sonnet tiering + 3-strike loop guard documentation", + "description": "Audit and rewrite scripts/codex-fleet/supervisor.sh's classifier section. Required: (1) Extract the classifier prompt (the one sent to Claude that decides working/asking/blocked/done) into a clearly delimited heredoc at the top of the script with explicit labeled categories and one example per category. (2) Add prompt-cache markers (the static system prompt portion should be inside a cache_control: ephemeral block when invoking claude --print, document the cache hit expectation in a comment). (3) Document Opus 4.7 escalation: by default route to Sonnet 4.6; escalate to Opus only when (a) the classifier itself returns 'uncertain' or (b) a pane has been flagged 'blocked' for ≥ 3 consecutive ticks. Add an env var CODEX_FLEET_FORCE_OPUS=1 override for debugging. (4) 3-strike loop guard: document the existing or add a new counter — after 3 consecutive identical classifier outputs on the same pane, the supervisor must escalate to a different action (poke pane, post Colony note, or page operator) rather than re-running the classifier. Add a top-of-file comment block describing the loop guard with the exact metric (pane id + classification + timestamp) that trips it. (5) shellcheck must remain clean. (6) No behavior change to existing daemons that source this script; only the classifier section is rewritten. file_scope: exactly scripts/codex-fleet/supervisor.sh — do NOT add fixtures (Lane 1 owns them) and do NOT touch plan-watcher.sh (Lane 5 owns it).", + "file_scope": [ + "scripts/codex-fleet/supervisor.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 1, + "title": "Classifier replay fixtures + harness (new test dir)", + "description": "Create scripts/codex-fleet/test/classifier-fixtures/ with at least 20 real captured pane snapshots covering each classifier category. Required: (1) Run tmux capture-pane against a variety of pane states during normal fleet operation (or use the existing pane logs under /tmp/claude-viz/*-worker-*.log) and save each snapshot as a .txt file named after the expected category (e.g. working-001.txt, asking-001.txt, blocked-001.txt, done-001.txt). (2) For each .txt, write a sibling .label file containing the single-line expected classification. (3) Cover edge cases: long log tails, ANSI-heavy output, codex CLI prompts mid-stream, plan-mode 'paste your answer' prompts, 429 rate-limit messages. (4) Write scripts/codex-fleet/test/run-classifier-replay.sh which iterates the fixtures, invokes the classifier from scripts/codex-fleet/supervisor.sh (source it and call the classifier function, or shell out to a minimal wrapper), collects the predicted vs expected label, and prints a confusion matrix + accuracy. Exit non-zero if accuracy < 0.85. (5) Make the harness deterministic — set CODEX_FLEET_FORCE_MODEL=sonnet-4-6 or similar so replays don't burn Opus. (6) shellcheck clean. file_scope: exactly the two new paths below — do NOT modify supervisor.sh (Lane 0 owns it).", + "file_scope": [ + "scripts/codex-fleet/test/classifier-fixtures/", + "scripts/codex-fleet/test/run-classifier-replay.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 2, + "title": "Cap-swap hand-off contract + worktree/claim preservation", + "description": "Harden scripts/codex-fleet/cap-swap-daemon.sh so a 429'd codex pane hands off cleanly to a fallback worker (Kiro or Claude). Required: (1) Add a top-of-file CONTRACT comment block enumerating every field that must transfer: Colony task_id, agent/* branch, worktree path, CODEX_HOME path, account email, last claim timestamp, accumulated lane context (last Colony task_post note). (2) Before triggering the swap, the daemon MUST: (a) call task_note_working or task_post with a 'swapping due to 429' marker, (b) NOT release the Colony claim — the new worker re-claims by inheriting CODEX_FLEET_TASK_ID, (c) preserve the agent/* worktree (the new worker `cd`'s into it). (3) Add a smoke-test stanza near the top of the script (commented) that simulates a 429: against a fixture pane, set CODEX_FLEET_SIMULATE_429=1, run one tick, assert the claim is preserved and the new worker starts in the same worktree. (4) Defensive: if any required env var is missing on the fallback side, the daemon must log + skip the swap rather than fire a broken worker. (5) shellcheck clean. (6) No edits to claude-spawn.sh (Lane 3 owns it). file_scope: exactly scripts/codex-fleet/cap-swap-daemon.sh.", + "file_scope": [ + "scripts/codex-fleet/cap-swap-daemon.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 3, + "title": "Claude fallback worker spawn polish — idempotent, claim-aware", + "description": "Polish scripts/codex-fleet/claude-spawn.sh so it cleanly handles the cap-swap inheritance case. Required: (1) Idempotent — re-running on a pane that already has a live claude worker is a 0-exit no-op (detect via tmux capture-pane checking for the claude prompt or a process check). (2) Accept CODEX_FLEET_TASK_ID env: when set, the spawned claude worker is told to immediately resume that Colony task (insert it into the prompt or the initial message). (3) Refuse to spawn into a pane whose @panel does not match an expected worker pattern (e.g. starts with [codex- or [kiro- or [claude-). Log + exit 1 cleanly on mismatch. (4) Inherit CODEX_HOME, ACCOUNT_EMAIL from caller env when present; otherwise log + fall back to defaults. (5) Add a top-of-file comment documenting the cap-swap inheritance contract (mirror of Lane 2's contract section). (6) shellcheck clean. (7) No edits to cap-swap-daemon.sh (Lane 2 owns it) or claude-worker.sh (out of scope). file_scope: exactly scripts/codex-fleet/claude-spawn.sh.", + "file_scope": [ + "scripts/codex-fleet/claude-spawn.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 4, + "title": "Plan flat-parallelism validator (new lib script)", + "description": "Create scripts/codex-fleet/lib/plan-validator.sh — a standalone validator for plan.json files. Required: (1) Usage: plan-validator.sh [--allow-waves]. (2) Validate three rules: (a) every sub-task's depends_on is empty UNLESS --allow-waves is passed, (b) no two sub-tasks share any file path in file_scope (note: a sub-task scope that lists a directory like 'foo/bar/' counts as overlapping with any file path under that directory), (c) acceptance_criteria is a non-empty array of strings each ≥ 40 chars. (3) Output: human-readable findings on stderr; one JSON summary on stdout with shape {ok, warnings: [...], errors: [...]}. (4) Exit codes: 0 ok, 2 warnings only, 3 hard errors. (5) Use jq for JSON parsing (jq is already a project dependency). (6) Add a self-test stanza near the top: a small inline plan.json fixture validates ok, another fails on overlapping file_scope. (7) shellcheck clean, executable bit set. (8) file_scope: exactly scripts/codex-fleet/lib/plan-validator.sh — do NOT wire it into plan-watcher.sh (Lane 5 owns that).", + "file_scope": [ + "scripts/codex-fleet/lib/plan-validator.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 5, + "title": "Wire plan-validator into plan-watcher.sh on every tick", + "description": "Edit scripts/codex-fleet/plan-watcher.sh so each tick (when looping with --loop) invokes the plan validator against the currently-pinned plan. Required: (1) Read .codex-fleet/active-plan to get the slug; resolve plan.json at openspec/plans//plan.json. (2) Invoke scripts/codex-fleet/lib/plan-validator.sh on that path. If the validator script is missing (Lane 4 not yet shipped), log 'PLAN-VALIDATE: skipped (validator missing)' and continue — never crash. (3) On exit code 0: log 'PLAN-VALIDATE: ok' once per tick at INFO. (4) On exit code 2 (warnings): log 'PLAN-VALIDATE: WARN ' with the JSON summary on the next line; continue dispatching. (5) On exit code 3 (hard errors): log 'PLAN-VALIDATE: ERROR ' with the JSON summary, SKIP dispatch for that tick, continue the loop. (6) All log lines go to /tmp/plan-watcher.log with the stable 'PLAN-VALIDATE:' prefix so a grep can extract them. (7) shellcheck clean. (8) Smoke test: run one tick locally against the current openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.json — should be ok. (9) file_scope: exactly scripts/codex-fleet/plan-watcher.sh.", + "file_scope": [ + "scripts/codex-fleet/plan-watcher.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 6, + "title": "Auto-reviewer daemon scaffold (file is currently MISSING)", + "description": "Create scripts/codex-fleet/auto-reviewer.sh — the end-of-plan auto-reviewer that the codex-fleet-dispatch protocol references but does not currently exist on disk. Required: (1) On invocation, read .codex-fleet/active-plan to get the slug. (2) Use gh pr list --search 'head:agent/* ' or similar to find every PR linked to this plan (or read openspec/plans//plan.json and harvest PR URLs from completed_summary fields). (3) For each PR, fetch the diff (gh pr diff ). (4) Build a review prompt using the rubric at scripts/codex-fleet/lib/review-rubric.md (Lane 7) and the prepass output from scripts/codex-fleet/lib/review-prepass.sh (Lane 7) — if either is missing, fall back to a built-in minimal rubric and inline diff dump, and log a warning. (5) Invoke claude --print --permission-mode bypassPermissions with the assembled prompt; capture stdout. (6) Write the review to /tmp/claude-viz/plan-review-.md (mkdir -p the parent). (7) Support --dry-run (do everything except the claude invocation; print the prompt that would be sent). (8) Support --plan-slug override for ad-hoc runs. (9) shellcheck clean, executable bit set. (10) file_scope: exactly scripts/codex-fleet/auto-reviewer.sh — do NOT touch the rubric or prepass (Lane 7 owns them).", + "file_scope": [ + "scripts/codex-fleet/auto-reviewer.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 7, + "title": "Review rubric + diff prepass (two new lib files)", + "description": "Create the two artifacts the auto-reviewer (Lane 6) consumes. Required: (1) scripts/codex-fleet/lib/review-rubric.md — a markdown checklist with four sections: REGRESSION RISK (does the diff change behavior beyond what the plan promised?), SCOPE CREEP (does any sub-task touch files outside its declared file_scope?), ANTI-PATTERN FLAGS (CLAUDE.md violations: backwards-compat shims, dead comments, premature abstractions, error-handling for impossible states), BLAST RADIUS (config/CI/migration/db touches; shared helper edits). Each section gets 3-5 bullets the reviewer model can answer yes/no/n-a against. Keep total length under 2k chars so it caches well. (2) scripts/codex-fleet/lib/review-prepass.sh — usage: review-prepass.sh . Output: a single markdown blob on stdout with sections: ## Plan acceptance criteria (verbatim from plan.json), ## Sub-task scope claims (per-lane file_scope), ## PR diffs (one fenced block per PR, fetched via gh pr diff). Limit each diff to 200 lines (head -200) to keep the prompt bounded. shellcheck clean. (3) Both files executable bit set where applicable (.md no, .sh yes). (4) file_scope: exactly the two new lib paths below — do NOT touch auto-reviewer.sh (Lane 6 owns it).", + "file_scope": [ + "scripts/codex-fleet/lib/review-rubric.md", + "scripts/codex-fleet/lib/review-prepass.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 8, + "title": "Pane health crate (new rust workspace crate)", + "description": "Create rust/fleet-pane-health/ as a new workspace crate (auto-picked-up by the fleet-* glob in rust/Cargo.toml). Required: (1) Cargo.toml: name 'fleet-pane-health', version 0.0.1, edition 2021, ratatui = '0.30', crossterm = '0.29', fleet-ui = { path = '../fleet-ui' } for shared chrome, fleet-data = { path = '../fleet-data' } if needed, [[bin]] name 'fleet-pane-health' path 'src/main.rs'. (2) src/main.rs: a ratatui app that polls every 1s and renders a vertical list of per-pane health rows. Each row: pane id (e.g. '%337'), pane @panel label, last-activity age (now - mtime of /tmp/claude-viz/{kiro,claude,codex}-worker-.log), current Colony claim state (parsed from a JSON dump at /tmp/claude-viz/colony-claims.json if present, else 'unknown'), cap-probe state (read /tmp/claude-viz/cap-probe-cache/.json mtime + ok/429). (3) Use the existing fleet-ui chrome (page header, hairline dividers, iOS-blue accent). (4) Quit on q or Esc. (5) cargo check -p fleet-pane-health succeeds from rust/. (6) Read-only — no writes to /tmp. (7) file_scope: rust/fleet-pane-health/Cargo.toml and rust/fleet-pane-health/src/main.rs — do NOT edit any existing crate or rust/Cargo.toml (the glob picks it up).", + "file_scope": [ + "rust/fleet-pane-health/Cargo.toml", + "rust/fleet-pane-health/src/main.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 9, + "title": "Metrics TSV viewer crate (new rust workspace crate)", + "description": "Create rust/fleet-metrics-viewer/ as a new workspace crate. Required: (1) Cargo.toml: name 'fleet-metrics-viewer', version 0.0.1, edition 2021, ratatui = '0.30', crossterm = '0.29', fleet-ui = { path = '../fleet-ui' }, [[bin]] name 'fleet-metrics-viewer' path 'src/main.rs'. (2) src/main.rs: a ratatui live tail of a TSV file. CLI: --path (default /tmp/claude-viz/supervisor-metrics.tsv if present, else exit 0 with an 'idle (no metrics file yet)' message). (3) Render the last 30 rows in a scrollable table with iOS-style chrome. Auto-refresh every 500ms via crossterm event poll + file mtime check. (4) Column headers parsed from the TSV's first line. (5) Use the existing fleet-ui chrome helpers for headers and dividers. (6) Quit on q or Esc; PgUp/PgDn to scroll. (7) cargo check -p fleet-metrics-viewer succeeds. (8) file_scope: rust/fleet-metrics-viewer/Cargo.toml and rust/fleet-metrics-viewer/src/main.rs — do NOT edit any existing crate.", + "file_scope": [ + "rust/fleet-metrics-viewer/Cargo.toml", + "rust/fleet-metrics-viewer/src/main.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 10, + "title": "Renderer polish crate (shared chrome primitives library)", + "description": "Create rust/fleet-renderer-polish/ as a new workspace crate exposing a small library of ratatui chrome primitives factored from patterns already present in fleet-waves/fleet-state. Required: (1) Cargo.toml: name 'fleet-renderer-polish', version 0.0.1, edition 2021, ratatui = '0.30', [lib] path 'src/lib.rs'. (2) src/lib.rs: pub fn rounded_corner_block(title: &str) -> Block — returns a ratatui Block with rounded corners and a one-cell padding; pub fn hairline_divider(width: u16) -> Line — a single line of '─' in fg=#3A3A3C; pub fn ios_status_chip(label: &str, color: IosColor) -> Span — a small chip like ' LIVE ' in fg-only ANSI matching the project's iOS palette (enum IosColor { Green, Blue, Yellow, Red, Gray }); pub fn page_header_with_accent(title: &str, accent: IosColor) -> Vec — a two-line iOS page header (bold title + accent underline). (3) Each fn has a doc comment with one usage example. (4) cargo check -p fleet-renderer-polish succeeds. (5) Library only — no main.rs, no binary. (6) Do NOT touch any existing crate; adoption is a separate follow-up. (7) file_scope: rust/fleet-renderer-polish/Cargo.toml and rust/fleet-renderer-polish/src/lib.rs.", + "file_scope": [ + "rust/fleet-renderer-polish/Cargo.toml", + "rust/fleet-renderer-polish/src/lib.rs" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "ui_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + }, + { + "subtask_index": 11, + "title": "Attention inbox dedup helper (new lib script)", + "description": "Create scripts/codex-fleet/lib/inbox-dedup.sh — a stdin-to-stdout filter that dedupes Colony attention_inbox output. Required: (1) Reads JSONL on stdin (one JSON object per line; Colony's attention_inbox export shape: task_id, kind, content, timestamp, agent). (2) Groups near-duplicates by a composite key: (task_id, kind, content-hash-with-whitespace-normalized). The content hash normalizes by lowercasing, collapsing runs of whitespace to single spaces, and stripping leading/trailing whitespace before hashing (sha1 of normalized content). (3) For each group, emit only the latest (largest timestamp) entry on stdout. (4) Idempotent: running it twice yields the same output. (5) Pure bash + jq + sha1sum — no python. (6) Add a self-test stanza near the top: pipe an inline JSONL fixture with three duplicates through the script, assert the output count is correct. (7) shellcheck clean, executable bit set. (8) file_scope: exactly scripts/codex-fleet/lib/inbox-dedup.sh.", + "file_scope": [ + "scripts/codex-fleet/lib/inbox-dedup.sh" + ], + "depends_on": [], + "spec_row_id": null, + "capability_hint": "infra_work", + "status": "available", + "claimed_by_session_id": null, + "claimed_by_agent": null, + "completed_summary": null + } + ], + "published": { + "spec_task_id": 714, + "spec_change_path": "/home/deadpool/Documents/codex-fleet/openspec/changes/codex-fleet-tui-improvements-2026-05-15/CHANGE.md", + "auto_archive": true + }, + "created_at": "2026-05-15T20:36:03.571Z", + "updated_at": "2026-05-15T20:36:03.571Z" +} diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.md new file mode 100644 index 0000000..b83660c --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/plan.md @@ -0,0 +1,41 @@ +# codex-fleet TUI improvements: supervisor classifier, cap-swap hand-off, plan validation, auto-reviewer, pane health, metrics viewer, renderer polish, inbox dedup + +Plan slug: `codex-fleet-tui-improvements-2026-05-15` + +## Problem + +The codex-fleet TUI is functional but has eight measurable gaps that compound throughput loss. (1) The supervisor's asking/blocked/working classifier in scripts/codex-fleet/supervisor.sh has no replayable fixtures and no documented Opus 4.7 + Sonnet tiering thresholds, so regressions in classification land silently; the 3-strike loop guard is also opaque. (2) cap-swap-daemon.sh hands a 429'd pane off to a fallback worker without an explicit contract for Colony claim transfer, worktree preservation, or env carry-over, so swapped panes sometimes orphan their claim. (3) Plan publication is unguarded — there is no validator that enforces the parallel-first rule (flat depends_on, disjoint file_scope), so bad plans deadlock workers on task_claim_file. (4) scripts/codex-fleet/auto-reviewer.sh is referenced by the dispatch protocol and the codex-fleet-dispatch skill but does not actually exist on disk — end-of-plan review is therefore manual. (5) There is no per-pane health surface — operators tail individual logs to diagnose a stuck pane; pane-health (last activity, claim state, cap-status) should be a first-class crate. (6) The supervisor metrics TSV (when written) has no live viewer, only post-hoc grep. (7) The dashboard chrome (iOS page headers in fleet-waves, fleet-state, etc) is rendered ad-hoc per crate; a shared renderer-polish layer would give consistent corner radii / hairlines / iOS-blue accent across every dashboard binary. (8) Colony attention_inbox returns duplicate-near handoffs (same task, slightly different timestamps or rationales); a dedup helper would let the orchestrator show the operator a clean list. All 12 lanes are flat-parallel — every lane edits exactly one disjoint file path (or one new disjoint set), depends_on=[] on all of them, so a fleet of 12 workers can claim and ship in parallel without task_claim_file contention. New rust crates use the workspace's fleet-* glob, so no shared rust/Cargo.toml edit is required. Soft references (Lane 5 calls Lane 4's validator at a known path; Lane 6's auto-reviewer reads Lane 7's rubric at a known path) tolerate either landing order — the consumer no-ops or warns until the producer ships. + +## Acceptance Criteria + +- All 12 sub-tasks land independently as 12 separate PRs against main with depends_on=[] honored; no two PRs touch the same file path. +- After Lane 0 ships, scripts/codex-fleet/supervisor.sh contains: an explicit classifier prompt with labeled categories (working / asking / blocked / done), a documented Opus 4.7 escalation threshold, prompt-cache markers around the static system prompt, and a comment block describing the 3-strike loop guard with the exact metric that trips it. shellcheck exits 0. +- After Lane 1 ships, scripts/codex-fleet/test/classifier-fixtures/ contains at least 20 captured pane snapshots (.txt files) with sibling .label files marking the expected category. scripts/codex-fleet/test/run-classifier-replay.sh iterates the fixtures, invokes the classifier, and prints a confusion matrix; exits non-zero if accuracy < 0.85 on the captured set. +- After Lane 2 ships, cap-swap-daemon.sh has a top-of-file CONTRACT section enumerating every field that must transfer on hand-off (Colony task_id, branch, worktree path, CODEX_HOME, account email, last claim timestamp) and a smoke-test stanza that simulates a 429 against a fixture pane and asserts the claim is released cleanly. No orphaned worktrees after the simulated swap. +- After Lane 3 ships, scripts/codex-fleet/claude-spawn.sh is idempotent (re-running on a live pane is a no-op + 0 exit), accepts an inherited CODEX_FLEET_TASK_ID env var so a cap-swapped pane resumes the same Colony claim, and refuses to spawn into a pane whose @panel does not match the expected worker pattern (defensive guard). +- After Lane 4 ships, scripts/codex-fleet/lib/plan-validator.sh exists, is executable, and validates a plan.json file at a given path against three rules: (a) every sub-task's depends_on is empty unless --allow-waves is passed, (b) no two sub-tasks share a file path in file_scope, (c) acceptance_criteria is a non-empty array of strings each ≥ 40 chars. Exit codes: 0 ok, 2 warnings, 3 hard errors. +- After Lane 5 ships, plan-watcher.sh invokes plan-validator.sh on every tick against the currently-active plan and surfaces warnings/errors in /tmp/plan-watcher.log with a stable prefix ('PLAN-VALIDATE:'). Hard errors do NOT crash the watcher but DO skip dispatch for that tick. shellcheck exits 0. +- After Lane 6 ships, scripts/codex-fleet/auto-reviewer.sh exists, is executable, and on invocation reads .codex-fleet/active-plan, gathers all PRs merged for that plan slug via gh pr list, builds a review prompt using the rubric (Lane 7) and the prepass diff (Lane 7), invokes the local claude CLI in --print mode, and writes the output to /tmp/claude-viz/plan-review-.md. Supports --dry-run for offline test. +- After Lane 7 ships, scripts/codex-fleet/lib/review-rubric.md exists and documents the explicit review checklist (regression risk, scope creep against plan acceptance_criteria, anti-pattern flags, blast radius); scripts/codex-fleet/lib/review-prepass.sh exists and emits a single markdown blob with the plan's stated scope + the actual diff for every PR, ready to be piped to a model. +- After Lane 8 ships, rust/fleet-pane-health/ is a new workspace crate that builds (cargo check -p fleet-pane-health) and renders a per-pane health row (pane id, last activity age, current Colony claim if any, cap-probe cache state) using ratatui + the shared fleet-ui chrome helpers. It reads from /tmp/claude-viz/cap-probe-cache/*.json and tmux capture-pane output. No edits to existing crates. +- After Lane 9 ships, rust/fleet-metrics-viewer/ is a new workspace crate that tails a TSV path passed via --path (default /tmp/claude-viz/supervisor-metrics.tsv when present, else --no-op) and renders the last N rows as a live dashboard with iOS-style chrome. cargo check -p fleet-metrics-viewer succeeds. No edits to existing crates. +- After Lane 10 ships, rust/fleet-renderer-polish/ is a new workspace crate exposing a small library of ratatui chrome primitives (rounded_corner_block, hairline_divider, ios_status_chip, page_header_with_accent) factored from the patterns already in fleet-waves/fleet-state. cargo check -p fleet-renderer-polish succeeds; it does NOT yet replace any existing crate's chrome — adoption is a follow-up. No edits to existing crates. +- After Lane 11 ships, scripts/codex-fleet/lib/inbox-dedup.sh exists and reads JSONL from stdin (Colony attention_inbox export), groups near-duplicates by (task_id, kind, content-hash with whitespace normalized), and prints a deduped JSONL to stdout. Exit 0 always; idempotent on already-deduped input. +- No regression in existing dashboards: cargo check --workspace from rust/ still passes after all 12 lanes land. +- Every PR's final note records: branch, files changed, command + output evidence (shellcheck, cargo check, fixture replay where applicable), PR URL, MERGED state, and sandbox cleanup proof per the Guardex completion contract. + +## Roles + +- [planner](./planner.md) +- [architect](./architect.md) +- [critic](./critic.md) +- [executor](./executor.md) +- [writer](./writer.md) +- [verifier](./verifier.md) + +## Operator Flow + +1. Refine this workspace until scope, risks, and tasks are explicit. +2. Publish the plan with `colony plan publish codex-fleet-tui-improvements-2026-05-15` or the `task_plan_publish` MCP tool. +3. Claim subtasks through Colony plan tools before editing files. +4. Close only when all subtasks are complete and `checkpoints.md` records final evidence. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/planner.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/planner.md new file mode 100644 index 0000000..3caedce --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/planner.md @@ -0,0 +1,13 @@ +# Planner + +Plan: `codex-fleet-tui-improvements-2026-05-15` + +## Responsibility + +Clarify scope, sequencing, dependencies, and acceptance criteria. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/tasks.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/tasks.md new file mode 100644 index 0000000..6dc17fd --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/tasks.md @@ -0,0 +1,16 @@ +# Tasks + +| # | Status | Title | Files | Depends on | Capability | Spec row | Owner | +| - | - | - | - | - | - | - | - | +0|available|Supervisor classifier prompt + Opus/Sonnet tiering + 3-strike loop guard documentation|`scripts/codex-fleet/supervisor.sh`|-|infra_work|-|- +1|available|Classifier replay fixtures + harness (new test dir)|`scripts/codex-fleet/test/classifier-fixtures/`
`scripts/codex-fleet/test/run-classifier-replay.sh`|-|infra_work|-|- +2|available|Cap-swap hand-off contract + worktree/claim preservation|`scripts/codex-fleet/cap-swap-daemon.sh`|-|infra_work|-|- +3|available|Claude fallback worker spawn polish — idempotent, claim-aware|`scripts/codex-fleet/claude-spawn.sh`|-|infra_work|-|- +4|available|Plan flat-parallelism validator (new lib script)|`scripts/codex-fleet/lib/plan-validator.sh`|-|infra_work|-|- +5|available|Wire plan-validator into plan-watcher.sh on every tick|`scripts/codex-fleet/plan-watcher.sh`|-|infra_work|-|- +6|available|Auto-reviewer daemon scaffold (file is currently MISSING)|`scripts/codex-fleet/auto-reviewer.sh`|-|infra_work|-|- +7|available|Review rubric + diff prepass (two new lib files)|`scripts/codex-fleet/lib/review-rubric.md`
`scripts/codex-fleet/lib/review-prepass.sh`|-|infra_work|-|- +8|available|Pane health crate (new rust workspace crate)|`rust/fleet-pane-health/Cargo.toml`
`rust/fleet-pane-health/src/main.rs`|-|ui_work|-|- +9|available|Metrics TSV viewer crate (new rust workspace crate)|`rust/fleet-metrics-viewer/Cargo.toml`
`rust/fleet-metrics-viewer/src/main.rs`|-|ui_work|-|- +10|available|Renderer polish crate (shared chrome primitives library)|`rust/fleet-renderer-polish/Cargo.toml`
`rust/fleet-renderer-polish/src/lib.rs`|-|ui_work|-|- +11|available|Attention inbox dedup helper (new lib script)|`scripts/codex-fleet/lib/inbox-dedup.sh`|-|infra_work|-|- diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/verifier.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/verifier.md new file mode 100644 index 0000000..71b773a --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/verifier.md @@ -0,0 +1,13 @@ +# Verifier + +Plan: `codex-fleet-tui-improvements-2026-05-15` + +## Responsibility + +Prove completion with focused tests and explicit evidence. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/openspec/plans/codex-fleet-tui-improvements-2026-05-15/writer.md b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/writer.md new file mode 100644 index 0000000..e3f77e9 --- /dev/null +++ b/openspec/plans/codex-fleet-tui-improvements-2026-05-15/writer.md @@ -0,0 +1,13 @@ +# Writer + +Plan: `codex-fleet-tui-improvements-2026-05-15` + +## Responsibility + +Keep docs, operator notes, and final handoff language accurate. + +## Checkpoints + +- [ ] Read `plan.md`, `tasks.md`, and `checkpoints.md`. +- [ ] Record decisions or blockers in the plan workspace before handoff. +- [ ] Keep task-thread status aligned with local files. diff --git a/rust/fleet-data/src/accounts.rs b/rust/fleet-data/src/accounts.rs index 8086fbf..8d21a96 100644 --- a/rust/fleet-data/src/accounts.rs +++ b/rust/fleet-data/src/accounts.rs @@ -1,4 +1,4 @@ -//! Typed parser for `codex-auth list` output. +//! Typed parser for `agent-auth list` output. //! //! Replaces the awk/sed regex scattered across `cap-probe.sh`, //! `cap-swap-daemon.sh`, and `fleet-tick.sh`'s account-discovery block. @@ -21,7 +21,7 @@ pub struct Account { pub is_current: bool, } -/// Parse the entire stdout of `codex-auth list` into a vector of [`Account`]. +/// Parse the entire stdout of `agent-auth list` into a vector of [`Account`]. /// /// Lines that don't match the expected shape are silently skipped (matches /// the bash `awk` lenience). Each returned account has both `5h=` and @@ -86,11 +86,11 @@ fn extract_percent(s: &str, key: &str) -> Option { digits.parse().ok() } -/// Convenience runner: shells out to `codex-auth list`, parses stdout. The +/// Convenience runner: shells out to `agent-auth list`, parses stdout. The /// dashboards keep calling this on a tick; the parse cost is negligible /// next to the subprocess spawn. pub fn load_live() -> std::io::Result> { - let output = std::process::Command::new("codex-auth").arg("list").output()?; + let output = std::process::Command::new("agent-auth").arg("list").output()?; Ok(parse(&String::from_utf8_lossy(&output.stdout))) } @@ -101,7 +101,7 @@ fn cache() -> &'static crate::cache::TtlCache> { } /// Cached variant of [`load_live`]. Dashboards on a 250 ms tick should call -/// this instead — the `codex-auth list` subprocess is the most expensive +/// this instead — the `agent-auth list` subprocess is the most expensive /// part of a tick (account list shifts on the order of seconds, not frames), /// so a 5 s TTL keeps the UI responsive without burning a fork per frame. /// diff --git a/rust/fleet-data/src/cache.rs b/rust/fleet-data/src/cache.rs index f3b7089..1582a0d 100644 --- a/rust/fleet-data/src/cache.rs +++ b/rust/fleet-data/src/cache.rs @@ -3,7 +3,7 @@ //! The fleet has four separate dashboard binaries (`fleet-state`, //! `fleet-watcher`, `fleet-ui`, `fleet-tui-poc`) that each poll account / //! pane state on a ~250 ms tick. Without a cache, every loader call shells -//! out — `codex-auth list` is hundreds of ms, and `tmux capture-pane` +//! out — `agent-auth list` is hundreds of ms, and `tmux capture-pane` //! adds one fork per pane. With a small in-process TTL this collapses //! to one real call per TTL window, regardless of how many widgets in the //! same binary ask for the data. diff --git a/rust/fleet-data/src/fleet.rs b/rust/fleet-data/src/fleet.rs index 342f842..d38fbab 100644 --- a/rust/fleet-data/src/fleet.rs +++ b/rust/fleet-data/src/fleet.rs @@ -4,7 +4,7 @@ //! can reuse: it stitches together the three independent data sources that //! already live in this crate — //! -//! * [`crate::accounts`] — `codex-auth list` percents per account email. +//! * [`crate::accounts`] — `agent-auth list` percents per account email. //! * [`crate::panes`] — tmux pane scrollback + [`PaneState`] classifier. //! * the `@panel` label — `[codex-]`, the join key between the two. //! @@ -33,9 +33,9 @@ pub struct WorkerRow { /// Dim model label under the email, e.g. `gpt-5.5 xhigh`. `None` when the /// pane scrollback didn't surface a model line. pub model_label: Option, - /// `weekly=` percent from `codex-auth list` — the `WEEKLY · 5H` rail. + /// `weekly=` percent from `agent-auth list` — the `WEEKLY · 5H` rail. pub weekly_pct: u8, - /// `5h=` percent from `codex-auth list` — the `WORKER · 5H` rail. + /// `5h=` percent from `agent-auth list` — the `WORKER · 5H` rail. pub five_h_pct: u8, /// Classified pane state — drives the `STATUS` chip. `None` when the /// account has no live pane (reserve account; renders as a blank/idle row @@ -50,7 +50,7 @@ pub struct WorkerRow { /// tmux pane id (`%47`) — the `PANE` column's `#N >` affordance. `None` /// for reserve accounts. pub pane_id: Option, - /// `true` when this account is the one `codex-auth` marks current (`*`). + /// `true` when this account is the one `agent-auth` marks current (`*`). /// The artboard stars it; also useful for sort stability. pub is_current: bool, /// Advisory quality score for this agent's most recently merged PR, @@ -231,7 +231,7 @@ fn scrape_activity(tail: &str) -> PaneActivity { /// Fleet table's rows. /// /// `accounts` is the authoritative row set — one [`WorkerRow`] per account, -/// in the order `codex-auth list` returned them. Each account is matched to a +/// in the order `agent-auth list` returned them. Each account is matched to a /// pane by `derive_agent_id(account.email) == agent_id_from_panel(pane.@panel)`. /// An account with no matching pane is a reserve account: `state`, `pane_id`, /// `working_on` stay empty. A pane with no matching account is dropped (it's @@ -302,7 +302,7 @@ pub fn join( .collect() } -/// Live runner: shell out to `codex-auth list` + `tmux` and join the results. +/// Live runner: shell out to `agent-auth list` + `tmux` and join the results. /// /// `session` / `window` are the tmux target for [`crate::panes::list_panes`] /// (`"codex-fleet"`, `Some("overview")` for the standard fleet). Mirrors diff --git a/scripts/codex-fleet/add-workers.sh b/scripts/codex-fleet/add-workers.sh index 4f491e2..f484be9 100755 --- a/scripts/codex-fleet/add-workers.sh +++ b/scripts/codex-fleet/add-workers.sh @@ -4,7 +4,7 @@ # pick up ready sub-tasks. Use when the plan board has `available` subs but # the existing panes are dead, capped, or stuck idle. # -# Picks N healthy accounts (cap-probe if present, else codex-auth list with +# Picks N healthy accounts (cap-probe if present, else agent-auth list with # the canonical 5h<100% / weekly<90% / not-already-active filter), then # defaults to respawning dead/idle panes in the running tmux fleet's # `overview` window. Falls back to kitty windows when no fleet session @@ -132,7 +132,7 @@ log "plan=$PLAN_SLUG N=$N active-file=$ACTIVE_FILE" # gap with zero manual upkeep. # 2. cap-probe.sh — same emails but pre-filtered through the 5h/weekly # cap budget. Use when present so we don't pick a capped account. -# 3. codex-auth list — legacy fallback for hosts without cap-probe. +# 3. agent-auth list — legacy fallback for hosts without cap-probe. # # Each path emits TSV: `\t` lines. Accounts already in # $ACTIVE_FILE are filtered out at every layer. @@ -197,17 +197,17 @@ print(m.group(1) if m else '') return fi fi - # Fallback: parse `codex-auth list` directly. - if ! command -v codex-auth >/dev/null 2>&1; then + # Fallback: parse `agent-auth list` directly. + if ! command -v agent-auth >/dev/null 2>&1; then return fi - # NB: cannot use `codex-auth list | python3 - <<'PY' ...` — the `-` tells + # NB: cannot use `agent-auth list | python3 - <<'PY' ...` — the `-` tells # python to read its script from stdin, which collides with the pipe. - # Capture codex-auth output to a tempfile and pass it as a positional arg. + # Capture agent-auth output to a tempfile and pass it as a positional arg. local auth_tmp auth_tmp="$(mktemp)" trap "rm -f '$auth_tmp'" RETURN - codex-auth list >"$auth_tmp" 2>/dev/null || return + agent-auth list >"$auth_tmp" 2>/dev/null || return python3 - "$need" "$ACTIVE_FILE" "$SCRIPT_DIR/accounts.yml" "$auth_tmp" <<'PY' import re, sys, os need = int(sys.argv[1]) @@ -248,7 +248,7 @@ PICKED_N="${#PICKED[@]}" if [ "$PICKED_N" -lt "$N" ]; then warn "only $PICKED_N healthy unallocated accounts available (wanted $N)" fi -[ "$PICKED_N" -gt 0 ] || die "no healthy accounts available — check codex-auth list / accounts.yml" +[ "$PICKED_N" -gt 0 ] || die "no healthy accounts available — check agent-auth list / accounts.yml" # Render worker prompt with plan slug pre-pinned so each new pane goes # straight to the right plan instead of re-deriving via openspec scan. diff --git a/scripts/codex-fleet/bin/pane-menu-clip-dual.sh b/scripts/codex-fleet/bin/pane-menu-clip-dual.sh new file mode 100755 index 0000000..9705afe --- /dev/null +++ b/scripts/codex-fleet/bin/pane-menu-clip-dual.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# pane-menu-clip-dual.sh — read stdin once and write it to BOTH the system +# clipboard and the X11 primary selection. Wired into tmux as the target of +# `copy-pipe-and-cancel` so any drag / double-click / triple-click / +# Enter / `y` lands in both selections at once. Why both: +# - Clipboard (Ctrl+Shift+V, right-click→Paste, paste-buffer) ← explicit +# - Primary (middle-click, Shift+Insert in xterm/gnome-term) ← implicit +# Matches the convention every "normal Linux terminal" follows. +# +# Implemented by buffering stdin into a variable so we don't have to juggle +# tee's process-substitution race conditions in /bin/sh; the worst case is +# a multi-MB capture-pane, which fits comfortably in shell-var memory. +set -eo pipefail + +data="$(cat)" +if command -v wl-copy >/dev/null 2>&1; then + printf '%s' "$data" | wl-copy + printf '%s' "$data" | wl-copy --primary 2>/dev/null || true +elif command -v xclip >/dev/null 2>&1; then + printf '%s' "$data" | xclip -selection clipboard -in + printf '%s' "$data" | xclip -selection primary -in +elif command -v xsel >/dev/null 2>&1; then + printf '%s' "$data" | xsel --clipboard --input + printf '%s' "$data" | xsel --primary --input +fi diff --git a/scripts/codex-fleet/bin/pane-menu-copy-line.sh b/scripts/codex-fleet/bin/pane-menu-copy-line.sh new file mode 100755 index 0000000..efe658e --- /dev/null +++ b/scripts/codex-fleet/bin/pane-menu-copy-line.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# pane-menu-copy-line.sh — copy CODEX_FLEET_MENU_LINE to the system clipboard +# and flash a tmux toast. Used by the MouseDown3Pane display-menu in +# style-tabs.sh — broken out into its own file because the alternative is +# embedding shell escapes inside a tmux `display-menu` item command, where +# tmux's own backslash/dollar handling silently eats the `\$` indirection +# (verified: `\$CODEX_FLEET_MENU_LINE` becomes an empty literal after parse). +# +# Routes the tmux call through scripts/codex-fleet/lib/_tmux.sh so the helper +# honors CODEX_FLEET_TMUX_SOCKET when set. +set -eo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../lib/_tmux.sh" + +line="${CODEX_FLEET_MENU_LINE:-}" +printf '%s' "$line" | wl-copy +tmux display-message -d 1200 '─ line copied' diff --git a/scripts/codex-fleet/cap-swap-daemon.sh b/scripts/codex-fleet/cap-swap-daemon.sh index 0682475..49fe137 100755 --- a/scripts/codex-fleet/cap-swap-daemon.sh +++ b/scripts/codex-fleet/cap-swap-daemon.sh @@ -3,7 +3,7 @@ # codex fleet. Every INTERVAL seconds: # 1. Scans every pane in $SESSION:overview. # 2. If a pane's scrollback contains the cap banner, picks a fresh -# account via cap-probe.sh (LIVE codex exec probe, not codex-auth +# account via cap-probe.sh (LIVE codex exec probe, not agent-auth # meter) and respawns the pane with that account. # 3. Writes a human-readable status snapshot to STATUS_FILE so the # operator can watch what the watcher is doing. @@ -143,10 +143,10 @@ current_emails() { | sort -u } -# Rank candidates by codex-auth score, exclude those currently in fleet +# Rank candidates by agent-auth score, exclude those currently in fleet rank_candidates() { local in_use; in_use=$(current_emails | tr '\n' '|'); in_use="${in_use%|}" - codex-auth list 2>/dev/null \ + agent-auth list 2>/dev/null \ | MIN5="$MIN_5H" MINW="$MIN_WK" INUSE="$in_use" python3 -c ' import os, sys, re min5=int(os.environ["MIN5"]); minw=int(os.environ["MINW"]) diff --git a/scripts/codex-fleet/claude-wake-prompt.md b/scripts/codex-fleet/claude-wake-prompt.md new file mode 100644 index 0000000..906ff69 --- /dev/null +++ b/scripts/codex-fleet/claude-wake-prompt.md @@ -0,0 +1,125 @@ +# claude-fleet worker loop + +You are pane `$CLAUDE_FLEET_AGENT_NAME` (Colony agent id) under the +shared Anthropic subscription tagged `$CLAUDE_FLEET_ACCOUNT_LABEL`. The +orchestrator is the host Claude session plus the `force-claim` + +`claim-release-supervisor` daemons. Your job: pull → preflight → +execute → report. Do not propose tasks. Do not chat. + +This wake-prompt is the Claude-Code variant of `worker-prompt.md`. Same +Colony loop, same Guardex completion contract; env refs renamed +`$CODEX_*` → `$CLAUDE_FLEET_*` and the codex-login / `CODEX_HOME` +sections removed (Claude auth lives in the host shell's +`~/.claude/`, shared across all panes). + +## Token discipline + +- Less word, same proof. No commentary, no narration of your reasoning. +- Tool calls only when state changes. Skip "let me check…" prose. +- One Colony observation per real state change. Nothing else. +- Drop filler tokens (`I will`, `Now`, `Let me`). Imperative + result. + +## Boot (once) + +1. `mcp__colony__hivemind_context` — confirm Colony reachable. If it + fails, stop the loop and echo "colony unreachable" then exit. Do not + retry indefinitely. + +## Loop + +``` +2. ready = mcp__colony__task_ready_for_agent({ agent: $CLAUDE_FLEET_AGENT_NAME, limit: 1 }) +3. if ready.ready is empty: + if ready.next_action contains "rescue" or ready.next_tool == "rescue_stranded_scan": + sleep 60 # claim-release-supervisor daemon owns rescue; do not loop on it + else: + sleep 60 + goto 2 +4. task = ready.ready[0] +``` + +Then preflight, claim, work, report. Sequence below. + +### Tier + specialty gate (REQUIRED before preflight) + +Read once at boot: `tier=$CLAUDE_FLEET_TIER` (default `high`), +`spec=$CLAUDE_FLEET_SPECIALTY` (default empty, comma/space separated). +Let `d = task.metadata.difficulty` (default `standard`). +- Capacity: `high`={hard,standard,trivial}, `medium`={standard,trivial}, `low`={trivial}. +- If `d` not in capacity: `task_post(kind:'note', content:'tier-skip: difficulty= tier=; releasing for stronger pane')`, `task_hand_off(to_agent:'any')`, `sleep 60`, `goto 2`. +- If `spec` non-empty AND no prefix in `spec` is a prefix of `task.plan_slug`: `task_post(kind:'note', content:'specialty-skip: plan= spec=')`, `task_hand_off(to_agent:'any')`, `sleep 60`, `goto 2`. +- Empty `spec` = generalist; do not skip. + +### Preflight (REQUIRED before any edit) + +Reject the claim early if the work is unreachable. + +- **Writable-root check.** For every path in `task.touches_files`, verify + it falls under one of: this pane's `--add-dir` roots + (`/home/deadpool/Documents/recodee`, `/home/deadpool/Documents/codex-fleet`), + `/tmp`, or `$HOME/.claude`. If any path is outside: + - `task_post(kind: 'blocker', content: 'BLOCKED preflight=writable-root; \ + plan=/sub-; path=; need=add-dir or plan retarget')` + - `task_hand_off(to_agent: 'orchestrator')` and `sleep 60`, then `goto 2`. + +- **Dep-already-claimed check.** If `task.depends_on` has any entry + whose status is `claimed` (not `done`) AND the claim is older than + 30 minutes, treat as stranded. Post a tight blocker referencing the + dep's task id and skip to `goto 2` after `sleep 60`. The + `claim-release-supervisor` daemon will reap it. + +### Claim + work + +5. `task_claim_file` for each path in `touches_files` you will edit. +6. `task_note_working({ agent, plan_slug, sub_idx })`. +7. Start the agent worktree: + ``` + gx branch start "" "$CLAUDE_FLEET_AGENT_NAME" + cd "" + ``` +8. Edit. Stay inside `touches_files`. Adjacent test files OK. +9. Verify with the narrowest meaningful command from the project's + AGENTS.md verification gates (e.g. `cargo check -p `, + `pytest -k `, `tsc --noEmit`). +10. Finish (do NOT wait for merge — a supervisor finalizes): + ``` + gx branch finish --branch "" --via-pr --cleanup + ``` + Then immediately: `task_post(kind: 'pending-merge', content: 'PR=; plan=/sub-')`. +11. `task_plan_complete_subtask({ plan_slug, sub_idx, completed_summary: "PR # " })`. +12. `task_post(kind: 'note', content: 'branch=
; plan=/sub-; \ + parent=; blocker=none; next=; state=pending-merge; pr=')`. +13. `goto 2`. + +### Blocker (real, not preflight) + +If verification fails, build breaks, spec ambiguous, or a dep artifact +is missing: +- `task_post(kind: 'blocker', content: 'BLOCKED branch=
; plan=/sub-; reason=; need=')` +- `task_hand_off(to_agent: 'any')` +- Release file claims so another pane can retry. +- `goto 2`. + +## Rate limits (429 / quota) + +The Anthropic subscription is **shared across every claude-fleet pane**. +A 429 on one pane usually means every pane will see it. Single response, +then back off: +1. `task_post(kind: 'blocker', content: 'rate-limit subscription=$CLAUDE_FLEET_ACCOUNT_LABEL; releasing claim')` +2. Release file claims via `task_claim_file` with the released flag (or + `task_hand_off released_files=[...]`). +3. `sleep 300`. Then `goto 2`. The wrapper script also detects the + banner in scrollback and applies its own backoff on relaunch — your + in-prompt sleep is the fast path; the wrapper is the safety net. + +## Don't + +- Don't run `claude logout` / re-auth flows. Auth is shared host config. +- Don't edit `~/.claude/` (other panes share it). +- Don't commit on `main` / `dev`. Always agent-branch worktree. +- Don't call `rescue_stranded_scan` directly — the supervisor daemon owns it. +- Don't poll faster than 60s on empty queues. +- Don't propose new tasks. Don't invent scope. Don't widen `touches_files`. +- Don't narrate. Don't summarize. The orchestrator reads Colony, not pane text. + +Now: step 1, once. Then loop from step 2. diff --git a/scripts/codex-fleet/claude-worker.sh b/scripts/codex-fleet/claude-worker.sh new file mode 100755 index 0000000..5d36513 --- /dev/null +++ b/scripts/codex-fleet/claude-worker.sh @@ -0,0 +1,159 @@ +#!/usr/bin/env bash +# +# claude-worker.sh — persistent Claude Code worker wrapper for the fleet. +# +# Spawns `claude` (Claude Code CLI) with the fleet wake-prompt, in a loop +# with rate-limit-aware backoff. Mirrors codex/kiro worker behaviour: +# self-claims tasks from Colony's `task_ready_for_agent`, produces PRs +# via the Guardex `gx branch finish` flow. +# +# Quota model: ALL claude-fleet panes share the same Anthropic +# subscription on this host (`~/.claude/`). Spawn small (1–2 panes) +# unless multiple ANTHROPIC_API_KEY values are staged per pane via +# CLAUDE_FLEET_API_KEY. +# +# Required env: +# CLAUDE_FLEET_AGENT_NAME Colony agent id (e.g. claude-fleet-1) +# +# Optional env: +# CLAUDE_FLEET_ACCOUNT_LABEL Free-form tag surfaced in blocker posts +# (default: "shared") +# CLAUDE_FLEET_TIER high|medium|low (default: high) +# CLAUDE_FLEET_SPECIALTY comma/space-separated plan_slug prefixes +# (default: empty = generalist) +# CLAUDE_FLEET_MODEL model alias (default: sonnet) +# CLAUDE_FLEET_CONFIG_DIR exported as CLAUDE_CONFIG_DIR for this pane. +# Lets each pane use its own ~/.claude/ login +# (no API key needed). Default: host ~/.claude/ +# (every pane shares one subscription). +# CLAUDE_FLEET_API_KEY if set, exported as ANTHROPIC_API_KEY for +# this pane only. Mutually exclusive with +# CLAUDE_FLEET_CONFIG_DIR — pick one. +# CLAUDE_FLEET_ADD_DIRS extra --add-dir roots (space-separated) +# CLAUDE_FLEET_LOG_DIR log dir (default /tmp/claude-viz) +# RESTART_DELAY_SEC normal exit backoff (default 30) +# RATE_LIMIT_DELAY_SEC 429/quota backoff (default 300) +# STOP_FILE touch this path to break the loop +# (default: $LOG_DIR/claude-worker-.stop) + +set -u + +AGENT="${CLAUDE_FLEET_AGENT_NAME:-}" +if [ -z "$AGENT" ]; then + echo "[claude-worker] fatal: CLAUDE_FLEET_AGENT_NAME unset" >&2 + exit 2 +fi + +LABEL="${CLAUDE_FLEET_ACCOUNT_LABEL:-shared}" +TIER="${CLAUDE_FLEET_TIER:-high}" +SPECIALTY="${CLAUDE_FLEET_SPECIALTY:-}" +MODEL="${CLAUDE_FLEET_MODEL:-sonnet}" +LOG_DIR="${CLAUDE_FLEET_LOG_DIR:-/tmp/claude-viz}" +RESTART_DELAY_SEC="${RESTART_DELAY_SEC:-30}" +RATE_LIMIT_DELAY_SEC="${RATE_LIMIT_DELAY_SEC:-300}" + +mkdir -p "$LOG_DIR" +LOG_FILE="$LOG_DIR/claude-worker-$AGENT.log" +STOP_FILE="${STOP_FILE:-$LOG_DIR/claude-worker-$AGENT.stop}" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WAKE="$SCRIPT_DIR/claude-wake-prompt.md" +if [ ! -f "$WAKE" ]; then + echo "[claude-worker] fatal: wake-prompt missing at $WAKE" >&2 + exit 2 +fi + +ADD_DIR_FLAGS=( + --add-dir "/home/deadpool/Documents/recodee" + --add-dir "/home/deadpool/Documents/codex-fleet" + --add-dir "/tmp" +) +if [ -n "${CLAUDE_FLEET_ADD_DIRS:-}" ]; then + for d in $CLAUDE_FLEET_ADD_DIRS; do + ADD_DIR_FLAGS+=( --add-dir "$d" ) + done +fi + +# Auth path selection. CLAUDE_FLEET_CONFIG_DIR (per-pane subscription) wins +# over CLAUDE_FLEET_API_KEY; default is host ~/.claude/. +if [ -n "${CLAUDE_FLEET_CONFIG_DIR:-}" ]; then + mkdir -p "$CLAUDE_FLEET_CONFIG_DIR" + export CLAUDE_CONFIG_DIR="$CLAUDE_FLEET_CONFIG_DIR" + # Refuse to run if this config dir has no auth.json — the pane would + # otherwise sit forever asking the user to log in. + if [ ! -f "$CLAUDE_CONFIG_DIR/auth.json" ] && [ ! -f "$CLAUDE_CONFIG_DIR/credentials.json" ]; then + printf '[claude-worker] fatal: CLAUDE_FLEET_CONFIG_DIR=%s has no auth — run:\n' "$CLAUDE_CONFIG_DIR" >&2 + printf ' CLAUDE_CONFIG_DIR=%s claude /login\n' "$CLAUDE_CONFIG_DIR" >&2 + exit 2 + fi +elif [ -n "${CLAUDE_FLEET_API_KEY:-}" ]; then + export ANTHROPIC_API_KEY="$CLAUDE_FLEET_API_KEY" +fi + +# Banner the operator can grep from a `tmux capture-pane`. +{ + printf '\n========== claude-worker boot ==========\n' + printf 'agent=%s label=%s tier=%s spec=%s model=%s\n' \ + "$AGENT" "$LABEL" "$TIER" "$SPECIALTY" "$MODEL" + printf 'wake=%s log=%s\n' "$WAKE" "$LOG_FILE" + printf 'stop=%s (touch this to break the loop)\n' "$STOP_FILE" + printf 'add-dir: %s\n' "${ADD_DIR_FLAGS[*]}" + printf '========================================\n\n' +} | tee -a "$LOG_FILE" + +# Detect rate-limit-shaped exits in scrollback. The Claude CLI emits +# different banner shapes than codex (429 / usage limit / quota / overload). +rate_limited_in() { + local f="$1" + [ -f "$f" ] || return 1 + # Pull the last ~120 lines so we don't false-positive on ancient hits. + tail -n 120 "$f" 2>/dev/null \ + | grep -qiE 'rate.?limit|usage.?limit|quota.?exceeded|429|overloaded|too many requests' +} + +run_once() { + local turn_log + turn_log="$LOG_DIR/claude-worker-$AGENT.last-turn.log" + : > "$turn_log" + + # The wake-prompt is fed via the positional `prompt` argument; the + # worker then loops inside the Claude session by issuing tool calls + # against Colony. We use the interactive mode (no --print) so the + # agent can iterate. --dangerously-skip-permissions is required for + # autonomous worktree edits and `gx branch finish` calls. + env \ + CLAUDE_FLEET_AGENT_NAME="$AGENT" \ + CLAUDE_FLEET_ACCOUNT_LABEL="$LABEL" \ + CLAUDE_FLEET_TIER="$TIER" \ + CLAUDE_FLEET_SPECIALTY="$SPECIALTY" \ + claude \ + --model "$MODEL" \ + --permission-mode bypassPermissions \ + --dangerously-skip-permissions \ + "${ADD_DIR_FLAGS[@]}" \ + "$(cat "$WAKE")" \ + 2>&1 | tee -a "$LOG_FILE" "$turn_log" + + rate_limited_in "$turn_log" && return 42 + return 0 +} + +while true; do + if [ -f "$STOP_FILE" ]; then + printf '[claude-worker] stop file present (%s); exiting\n' "$STOP_FILE" | tee -a "$LOG_FILE" + exit 0 + fi + + run_once + rc=$? + + if [ "$rc" -eq 42 ]; then + printf '[claude-worker] rate-limit detected; sleeping %ss\n' "$RATE_LIMIT_DELAY_SEC" \ + | tee -a "$LOG_FILE" + sleep "$RATE_LIMIT_DELAY_SEC" + else + printf '[claude-worker] exit rc=%s; relaunch in %ss\n' "$rc" "$RESTART_DELAY_SEC" \ + | tee -a "$LOG_FILE" + sleep "$RESTART_DELAY_SEC" + fi +done diff --git a/scripts/codex-fleet/codex-fleet-2.sh b/scripts/codex-fleet/codex-fleet-2.sh index b86ce9d..612851a 100755 --- a/scripts/codex-fleet/codex-fleet-2.sh +++ b/scripts/codex-fleet/codex-fleet-2.sh @@ -1,12 +1,17 @@ #!/usr/bin/env bash # -# codex-fleet-2 — open a second, read-only fleet dashboard in a kitty window. +# codex-fleet-2 — open a second fleet kitty window with its own overview + +# visualization tabs. # # Lets you compare a candidate plan/fleet/waves rendering against the live # `codex-fleet` session without touching it. Spawns a sibling tmux session -# `codex-fleet-2` whose tabs run only the visualization scripts (no codex -# workers, no force-claim, no cap-swap). Safe to start while the live fleet -# is running. +# `codex-fleet-2` whose tab 0 is an 8-pane tiled overview — each pane is a +# bash shell pre-configured for a distinct reserve codex account (CODEX_HOME +# set, CODEX_GUARD_BYPASS=1 set so codex-guard.sh defers to the real codex). +# Just type `codex` in a pane to launch that agent. Remaining tabs run the +# visualization scripts (fleet/waves/review/watcher/plan). No force-claim, +# no cap-swap. Safe to start while the live fleet is running — reserve +# accounts are disjoint from codex-fleet:overview's active set. # # Usage: # bash scripts/codex-fleet/codex-fleet-2.sh # auto-pick newest plan @@ -123,10 +128,40 @@ add_window() { fi } +# Plan-tree-anim script must exist (used by the plan window below). PLAN_SCRIPT="$(resolve_script plan-tree-anim.sh)" [[ -z "$PLAN_SCRIPT" ]] && { echo "fatal: plan-tree-anim.sh missing in $REPO and $FALLBACK_REPO" >&2; exit 2; } -tmux new-session -d -s "$SESSION" -n plan \ - "PLAN_TREE_ANIM_PIN_FILE=$PIN_FILE bash $PLAN_SCRIPT" + +# Tab 0: overview with 8 tiled worker panes, each pre-configured for a +# different reserve codex account (CODEX_HOME set, codex-guard.sh bypassed). +# Run `codex` in any pane to launch that agent without the +# "Recodee-instrumented … missing" warning and the stdout-not-a-terminal +# fallback. Account list is reserve-only — accounts already in use by +# codex-fleet:overview are intentionally NOT listed here to avoid CODEX_HOME +# auth conflicts. +RESERVE_ACCOUNTS=( + admin-kollarrobert admin-mite bia-zazrifka fico-magnolia + koncita-pipacs mesi-lebenyse recodee-mite ricsi-zazrifka +) +worker_cmd_for() { + local acct="$1" + # Launch codex directly as the pane command (matches codex-fleet:overview's + # pattern in scripts/codex-fleet/full-bringup.sh). codex inherits the pane's + # TTY cleanly because we skip the bash-lc indirection. The guard wrapper + # (codex-guard.sh) sees CODEX_GUARD_BYPASS=1 and execs the real codex. + printf 'env CODEX_GUARD_BYPASS=1 CODEX_HOME=/tmp/codex-fleet/%s CODEX_FLEET_AGENT_NAME=codex-fleet-2-%s CODEX_FLEET_ACCOUNT=%s CODEX_FLEET_SESSION=%s codex --dangerously-bypass-approvals-and-sandbox --add-dir /home/deadpool/Documents/codex-fleet --add-dir /home/deadpool/Documents/codex-fleetui' \ + "$acct" "$acct" "$acct" "$SESSION" +} +# Force a generous virtual size so 8 worker splits have room before the +# kitty client attaches. tmux resizes to the client on attach anyway. +tmux new-session -d -s "$SESSION" -x 274 -y 78 -n overview \ + "$(worker_cmd_for "${RESERVE_ACCOUNTS[0]}")" +for i in 1 2 3 4 5 6 7; do + acct="${RESERVE_ACCOUNTS[$i]}" + tmux split-window -t "$SESSION:overview" "$(worker_cmd_for "$acct")" >/dev/null 2>&1 || true + tmux select-layout -t "$SESSION:overview" tiled >/dev/null +done + add_window fleet fleet-state-anim.sh # Prefer waves-anim-generic.sh (newer) when present; fall back to the # committed waves-anim.sh otherwise. @@ -143,19 +178,52 @@ else add_window review review-board.sh fi add_window watcher watcher-board.sh +add_window plan plan-tree-anim.sh "PLAN_TREE_ANIM_PIN_FILE=$PIN_FILE " tmux set-option -w -t "$SESSION:plan" remain-on-exit on tmux set-option -w -t "$SESSION:waves" remain-on-exit on -tmux select-window -t "$SESSION:plan" +tmux select-window -t "$SESSION:overview" + +# Mirror the codex-fleet socket setup (scripts/codex-fleet/tmux/up.sh) so the +# secondary session has a working mouse layer. Without `mouse on` the wheel +# never enters scroll/copy-mode (no chat scroll inside codex panes) and the +# `MouseDown3Pane` binding installed by style-tabs.sh below never fires +# (no iOS right-click context menu). codex-fleet-2.sh runs on whatever socket +# the operator launches it from (default = the user's normal tmux server), +# so scope these to $SESSION instead of `-g` to avoid silently flipping +# mouse on for unrelated sessions on that server. +tmux set-option -t "$SESSION" mouse on >/dev/null 2>&1 || true +tmux set-option -t "$SESSION" history-limit 50000 >/dev/null 2>&1 || true +# The right-click popup + prefix-m / prefix-Tab / prefix-C-h bindings expand +# `${CODEX_FLEET_REPO_ROOT}` from the tmux server env at fire time. Push it +# in so display-popup's spawned bash can find pane-context-menu-chooser.sh / +# menu-action-sheet.sh / section-jump-chooser.sh / help-popup.sh. +tmux set-environment -g CODEX_FLEET_REPO_ROOT "$REPO" >/dev/null 2>&1 || true # Apply the canonical iOS-palette tab chrome (style-tabs.sh) — the second # session no longer ships a custom orange-tinted status. Per-session distinction # now comes from the `#S` token rendered inside style-tabs.sh's session badge # pill (e.g. `◖ ◆ codex-fleet-2 ◗`), so both sessions read as one fleet visual # language and pre-iOS overrides don't shadow the global palette. +# style-tabs.sh installs the sticky MouseDown3Pane (right-click iOS menu), +# WheelUpPane / WheelDownPane (alt-screen aware scroll routing), and +# MouseDown1Status (tab click) bindings — those need `mouse on` (set above) +# to actually receive events. if [[ -x "$SCRIPT_DIR/style-tabs.sh" ]]; then CODEX_FLEET_SESSION="$SESSION" bash "$SCRIPT_DIR/style-tabs.sh" >/dev/null 2>&1 || true fi +# Source the prefix-m action sheet, prefix-Tab section jumper, and prefix-C-h +# help popup. Done after style-tabs.sh so its binding pass can't shadow these. +# Mirrors scripts/codex-fleet/tmux/up.sh step 5. +if [[ -f "$SCRIPT_DIR/tmux-bindings.conf" ]]; then + tmux source-file "$SCRIPT_DIR/tmux-bindings.conf" >/dev/null 2>&1 || true +fi +# style-tabs.sh sets status=off in favor of the in-binary fleet-tab-strip +# header pane. codex-fleet-2 deliberately does NOT install that header pane +# (it complicated the 3×3 worker layout), so re-enable the tmux-native top +# status bar — that becomes the menubar showing the window tab labels. +tmux set-option -t "$SESSION" status on >/dev/null 2>&1 || true +tmux set-option -t "$SESSION" status-position top >/dev/null 2>&1 || true if (( USE_KITTY == 1 )) && command -v kitty >/dev/null 2>&1; then # Detached kitty window so this script returns immediately. diff --git a/scripts/codex-fleet/dispatch-plan.sh b/scripts/codex-fleet/dispatch-plan.sh new file mode 100644 index 0000000..96b17c1 --- /dev/null +++ b/scripts/codex-fleet/dispatch-plan.sh @@ -0,0 +1,132 @@ +#!/usr/bin/env bash +# +# dispatch-plan.sh — send claim+implement prompts to codex panes for every +# sub-task of a published Colony plan, one pane per sub-task. +# +# This is the "phase 4" automation step of the codex-fleet AUTO-DISPATCH +# PROTOCOL (see skills/codex-fleet/SKILL.md). It assumes: +# +# 1. The plan is on disk at openspec/plans//plan.json +# 2. The plan is already published to Colony (task_plan_publish has been +# called — `colony plan list` shows it as registered, not "unpublished") +# 3. A tmux session named via $CODEX_FLEET_SESSION (default codex-fleet-2) +# exists with an `overview` window whose pane indexes 0..N-1 are each +# running a codex CLI with CODEX_GUARD_BYPASS=1 set. +# +# What it does: +# - Reads plan.json sub-tasks in subtask_index order. +# - For each i in [0, min(num_subtasks, num_panes)): +# * Generates a claim+implement prompt referencing sub-task i. +# * Sends the prompt to pane i via `tmux send-keys -l` (literal). +# * Sends Enter to submit. +# * Does NOT send Escape (that clears the input box; learned the hard +# way 2026-05-15). +# - After all dispatches, waits 4s and verifies each pane shows +# `• Working` in its capture. Panes still showing "Create a plan?" +# dialog get a Shift+Tab (BTab) press to enter plan mode and start +# processing. Panes showing "usage limit" get logged for the operator. +# +# Usage: +# bash scripts/codex-fleet/dispatch-plan.sh +# bash scripts/codex-fleet/dispatch-plan.sh --session codex-fleet +# bash scripts/codex-fleet/dispatch-plan.sh --max-panes 5 +# bash scripts/codex-fleet/dispatch-plan.sh --plan-mode # send BTab after Enter +# +set -eo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO="$(cd "$SCRIPT_DIR/../.." && pwd)" + +# Route every tmux call through lib/_tmux.sh (socket support). +source "$SCRIPT_DIR/lib/_tmux.sh" + +PLAN_SLUG="" +SESSION="${CODEX_FLEET_SESSION:-codex-fleet-2}" +MAX_PANES="" +PLAN_MODE=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --session) SESSION="$2"; shift 2 ;; + --max-panes) MAX_PANES="$2"; shift 2 ;; + --plan-mode) PLAN_MODE=1; shift ;; + -h|--help) sed -n '2,42p' "$0"; exit 0 ;; + -*) echo "fatal: unknown flag $1" >&2; exit 2 ;; + *) PLAN_SLUG="$1"; shift ;; + esac +done + +[[ -n "$PLAN_SLUG" ]] || { echo "fatal: plan-slug required" >&2; exit 2; } +PLAN_JSON="$REPO/openspec/plans/$PLAN_SLUG/plan.json" +[[ -f "$PLAN_JSON" ]] || { echo "fatal: plan not on disk: $PLAN_JSON" >&2; exit 2; } +tmux has-session -t "$SESSION" 2>/dev/null || { echo "fatal: tmux session $SESSION not running" >&2; exit 2; } +tmux list-windows -t "$SESSION" 2>/dev/null | grep -q ': overview' || \ + { echo "fatal: $SESSION has no 'overview' window" >&2; exit 2; } + +# Pane count. +N_PANES=$(tmux list-panes -t "$SESSION:overview" -F '#{pane_index}' | wc -l) +echo "[dispatch-plan] session=$SESSION overview-panes=$N_PANES plan=$PLAN_SLUG" + +# Per-subtask dispatch. +PY_OUT="$(python3 - "$PLAN_JSON" "$N_PANES" "${MAX_PANES:-$N_PANES}" <<'PY' +import json, sys +plan = json.load(open(sys.argv[1])) +n_panes = int(sys.argv[2]) +max_panes = int(sys.argv[3]) +limit = min(n_panes, max_panes, len(plan["tasks"])) +for i, t in enumerate(plan["tasks"][:limit]): + title = t.get("title","").replace("\n"," ").replace("|","-") + file_scope = " ".join(t.get("file_scope",[])) + crate = "" + for f in t.get("file_scope",[]): + if f.startswith("rust/"): + parts = f.split("/") + if len(parts) >= 2: + crate = parts[1] + break + print(f"{i}|{t['subtask_index']}|{crate}|{file_scope}|{title}") +PY +)" + +if [[ -z "$PY_OUT" ]]; then + echo "fatal: no sub-tasks found in plan" >&2 + exit 2 +fi + +DISPATCHED=() +while IFS='|' read -r pane_i sub_i crate files title; do + [[ -z "$pane_i" ]] && continue + prompt="Claim sub-task ${sub_i} of plan ${PLAN_SLUG} via colony task_plan_claim_subtask. Agent slug = env CODEX_FLEET_AGENT_NAME (read \$CODEX_FLEET_AGENT_NAME). session_id = fresh UUID. Title: ${title}. Implement on a new agent worktree per ${REPO}/AGENTS.md: gx branch start \"${PLAN_SLUG}-sub-${sub_i}\" \"\$CODEX_FLEET_AGENT_NAME\". Deliverable: ${files} (per the sub-task description in plan.json — do NOT edit main.rs / lib.rs / any existing file unless plan.json explicitly lists it). Run cargo check -p ${crate} and cargo test -p ${crate}. Ship via gx branch finish --via-pr --wait-for-merge --cleanup. Then task_post evidence (branch, PR URL, MERGED state) and task_plan_complete_subtask." + echo " → pane $pane_i sub-$sub_i crate=$crate" + tmux send-keys -t "$SESSION:overview.$pane_i" -l "$prompt" + tmux send-keys -t "$SESSION:overview.$pane_i" Enter + DISPATCHED+=("$pane_i:sub-$sub_i:$crate") +done <<< "$PY_OUT" + +echo "[dispatch-plan] dispatched ${#DISPATCHED[@]} prompts. settling 4s …" +sleep 4 + +# Verify each pane and recover stuck ones. +echo "[dispatch-plan] status:" +for entry in "${DISPATCHED[@]}"; do + pane_i="${entry%%:*}" + rest="${entry#*:}" + cap="$(tmux capture-pane -t "$SESSION:overview.$pane_i" -p | tail -10)" + if grep -q "Working" <<<"$cap"; then + echo " ✓ pane $pane_i ($rest) — Working" + elif grep -q "Create a plan?" <<<"$cap"; then + if (( PLAN_MODE == 1 )); then + echo " ⤷ pane $pane_i ($rest) — Plan-mode dialog open; sending BTab (enter plan mode)" + tmux send-keys -t "$SESSION:overview.$pane_i" BTab + else + echo " ! pane $pane_i ($rest) — Plan-mode dialog open. Press Esc in pane (clears input), or re-run with --plan-mode." + fi + elif grep -q "usage limit" <<<"$cap"; then + acct="$(tmux show-environment -t "$SESSION" 2>/dev/null | grep CODEX_HOME || true)" + echo " ⚠ pane $pane_i ($rest) — usage limit hit. Account needs swap. Detail: $(grep -oE 'try again at [^.]*' <<<"$cap" | head -1)" + else + echo " ? pane $pane_i ($rest) — no Working indicator yet; bottom snippet: $(echo "$cap" | tail -2 | tr '\n' ' ' | sed 's/ */ /g' | cut -c1-120)" + fi +done + +echo "[dispatch-plan] done." diff --git a/scripts/codex-fleet/fleet-tick.sh b/scripts/codex-fleet/fleet-tick.sh index 2f352c2..d11402b 100755 --- a/scripts/codex-fleet/fleet-tick.sh +++ b/scripts/codex-fleet/fleet-tick.sh @@ -27,7 +27,7 @@ if [[ "${FLEET_TICK_SOURCE_ONLY:-0}" != "1" ]]; then fi # AID, SHORT, FLEET_EMAILS, IS_CURRENT are populated every tick by the -# discovery block in the main loop, sourced from `codex-auth list` so any +# discovery block in the main loop, sourced from `agent-auth list` so any # account the cap-swap-daemon swaps in (or the operator newly logs in) shows # up automatically. declare -A AID @@ -388,8 +388,8 @@ fi while true; do ts=$(date '+%H:%M:%S') - # ── 1. Discover accounts + usage from codex-auth list ───────────────────── - # codex-auth list output: + # ── 1. Discover accounts + usage from agent-auth list ───────────────────── + # agent-auth list output: # * zeus@kollarrobert.sk type=ChatGPT seat (Business) 5h=100% weekly=36% # The leading "*" marks the currently-authenticated CLI account. Every email # in the output becomes part of the live fleet view; no more hardcoded list. @@ -414,7 +414,7 @@ while true; do fi local_part="${email%%@*}" SHORT_LOCAL_COUNT[$local_part]=$(( ${SHORT_LOCAL_COUNT[$local_part]:-0} + 1 )) - done < <(codex-auth list 2>/dev/null || true) + done < <(agent-auth list 2>/dev/null || true) # Populate AID + SHORT now that we know the full email set (so SHORT can # disambiguate collisions like admin@mite.hu vs admin@pipacsclub.hu with a @@ -481,10 +481,10 @@ while true; do h5=${pair%% *}; wk=${pair##* } aid=${AID[$email]} st=${ALIVE[$aid]:-} - # Display raw USED-% from codex-auth list. Operator request: color + # Display raw USED-% from agent-auth list. Operator request: color # the value/bar on the `available` (battery) axis so 100% reads # green and 0% reads red regardless of what the number means. - # The displayed value still matches `codex-auth list` exactly; only + # The displayed value still matches `agent-auth list` exactly; only # the color gradient changed direction. wk_num=${wk%\%}; h5_num=${h5%\%} [[ "$wk_num" =~ ^[0-9]+$ ]] || wk_num=0 @@ -630,7 +630,7 @@ while true; do render_fleet_section "RESERVE" "reserve" echo # Footer counts: live = panes actually running codex (regardless of cap), - # capped = those marked EXHAUSTED at 5h=100%, accounts = full codex-auth set. + # capped = those marked EXHAUSTED at 5h=100%, accounts = full agent-auth set. n_panes=${#PANE_FOR_AID[@]} n_capped=${#EXHAUSTED[@]} if (( n_panes >= 5 )); then awc=$GRAD6 diff --git a/scripts/codex-fleet/full-bringup.sh b/scripts/codex-fleet/full-bringup.sh index 27118a9..0aae79a 100755 --- a/scripts/codex-fleet/full-bringup.sh +++ b/scripts/codex-fleet/full-bringup.sh @@ -263,14 +263,14 @@ if [ ! -f "$WAKE" ]; then fi # 6. Pick candidate accounts. Two-stage filter: -# (a) Score by codex-auth's 5h% * weekly% (fast, but unreliable for codex +# (a) Score by agent-auth's 5h% * weekly% (fast, but unreliable for codex # CLI's own rolling cap). # (b) Probe each candidate with `codex exec` to detect the *real* cap # state. Take top 3N candidates so we can skip up to 2N capped # accounts and still end up with N healthy ones. TOP=$((N_PANES * 3)) log "picking $TOP candidate accounts (will probe + filter down to $N_PANES healthy)" -CANDIDATES=$(codex-auth list 2>/dev/null | N="$TOP" python3 -c ' +CANDIDATES=$(agent-auth list 2>/dev/null | N="$TOP" python3 -c ' import os, sys, re n = int(os.environ["N"]) rows = [] @@ -287,9 +287,9 @@ rows.sort(reverse=True) for _, email in rows[:n]: print(email) ') -[ -n "$CANDIDATES" ] || die "no candidate accounts found (need 5h>=40%, wk>=25% in codex-auth list)" +[ -n "$CANDIDATES" ] || die "no candidate accounts found (need 5h>=40%, wk>=25% in agent-auth list)" CAND_N=$(printf "%s\n" "$CANDIDATES" | wc -l) -log "ranked $CAND_N candidates by codex-auth score; running live probe..." +log "ranked $CAND_N candidates by agent-auth score; running live probe..." # (b) Live probe — keep only candidates whose codex CLI is actually usable. # 5-min cache short-circuits back-to-back bringups (each probe spawns N codex @@ -542,13 +542,14 @@ while IFS='|' read -r id email tier specialty; do # Runtime selection (CODEX_FLEET_RUNTIME, default codex). spawn-fleet.sh # exposes this via `--runtime claude` for the fallback case where the # codex account pool is exhausted (every account capped). The claude - # branch uses claude's --print + --permission-mode bypassPermissions so - # it operates non-interactively with the same wake-prompt the codex - # workers consume — the worker-prompt template is runtime-agnostic. + # branch hands off to claude-worker.sh which loops `claude` with the + # Claude-tailored wake-prompt and applies rate-limit-aware backoff — + # one-shot `claude --print` would exit after a single task instead of + # pulling more from Colony. case "${CODEX_FLEET_RUNTIME:-codex}" in claude) tmux respawn-pane -k -t "$pid" \ - "env CODEX_FLEET_AGENT_NAME=codex-$id CODEX_FLEET_ACCOUNT_EMAIL=$email CODEX_FLEET_TIER=${tier:-high} CODEX_FLEET_SPECIALTY=\"$specialty\" claude --print --permission-mode bypassPermissions \"\$(cat $WAKE)\"" + "env CLAUDE_FLEET_AGENT_NAME=claude-fleet-$id CLAUDE_FLEET_ACCOUNT_LABEL=$email CLAUDE_FLEET_TIER=${tier:-high} CLAUDE_FLEET_SPECIALTY=\"$specialty\" bash $REPO/scripts/codex-fleet/claude-worker.sh" ;; *) tmux respawn-pane -k -t "$pid" \ diff --git a/scripts/codex-fleet/lib/ios-menu.sh b/scripts/codex-fleet/lib/ios-menu.sh index 9b31987..9ab768d 100644 --- a/scripts/codex-fleet/lib/ios-menu.sh +++ b/scripts/codex-fleet/lib/ios-menu.sh @@ -69,6 +69,17 @@ _ios_sgr() { } _ios_reset() { printf '\033[0m'; } +# Internal: print $2 copies of glyph $1 with no newline. Used by the +# context menu to draw the rounded card's top/bottom/hairline rules +# inside the active SGR. Implemented via printf so it stays cheap and +# avoids forking $(seq …) per call. `printf '%s' "$g$g$g..."` is +# faster than a bash for-loop for the tiny widths we hand it (~52). +_ios_repeat() { + local glyph="$1" count="${2:-0}" out="" + while (( count-- > 0 )); do out+="$glyph"; done + printf '%s' "$out" +} + # ── ios_segmented_control "A|B|C" active_idx ──────────────────────────────── # Renders one line: rounded outer ends, inactive=gray on bg2, active=white on # blue with bold weight. Each segment padded with one space on each side. diff --git a/scripts/codex-fleet/style-tabs.sh b/scripts/codex-fleet/style-tabs.sh index b504bb0..c4af53b 100755 --- a/scripts/codex-fleet/style-tabs.sh +++ b/scripts/codex-fleet/style-tabs.sh @@ -236,10 +236,12 @@ fi # ── iOS-style menu styling ─────────────────────────────────────────────────── # Sheet-style card on tertiarySystemBackground, rounded border, iOS-blue -# selection row — mirrors a UIKit context menu on dark mode. +# selection row — mirrors a UIKit context menu on dark mode. The border fg +# nudges up to #3A3A3C so the rounded outline reads on a black background +# (the prior #2C2C2E was nearly invisible against the pane chrome). tx_set menu-style "fg=#FFFFFF,bg=#1C1C1E" tx_set menu-selected-style "fg=#FFFFFF,bg=#007AFF,bold" -tx_set menu-border-style "fg=#2C2C2E" +tx_set menu-border-style "fg=#3A3A3C,bg=#1C1C1E" tx_set menu-border-lines "rounded" # ── sticky right-click menu ────────────────────────────────────────────────── @@ -280,17 +282,61 @@ trap 'rm -f "$sticky_menu_conf"' EXIT # whole `VAR:-default` as one variable name and rejects it with "invalid # environment variable"). Resolve the fallback in bash first, then push it # into tmux's env so the binding sees a plain ${CODEX_FLEET_REPO_ROOT}. -_repo_root="${CODEX_FLEET_REPO_ROOT:-$HOME/Documents/recodee}" +_repo_root="${CODEX_FLEET_REPO_ROOT:-$HOME/Documents/codex-fleet}" tmux set-environment -g CODEX_FLEET_REPO_ROOT "$_repo_root" 2>/dev/null || true cat >"$sticky_menu_conf" <<'TMUX_CONF' +# ── Right-click context menu ───────────────────────────────────────────────── +# Plain right-click opens a native `display-menu` styled with the iOS palette +# (rounded chrome from menu-border-lines, accents from menu-style). This is +# faster than the bash/ratatui popup, feels like a regular terminal context +# menu, and keeps tmux as the single source of truth for the keystroke loop. +# +# Shift+Right-click opens the richer popup card (pane-context-menu-chooser.sh) +# for operators who want the live LIVE chip header + chip-shaped key hints. +# +# The if-shell gate is unchanged: TUI panes that hold mouse_any_flag get the +# mouse event passed through; copy-mode panes also get it through; otherwise +# we open the menu. unbind-key -T root MouseDown3Pane -# Right-click context menu — runs the ratatui-rendered iOS menu when its -# binary exists, otherwise falls back to the bash renderer. -# The chooser shell script keeps the conditional out of tmux's substitution -# layer (tmux eats `$FB`-style shell vars before the popup spawns). -bind-key -T root MouseDown3Pane if-shell -F -t = "#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}" { select-pane -t = ; send-keys -M } { set-environment -g CODEX_FLEET_MENU_LINE "#{q:mouse_line}" ; display-popup -E -B -w 60 -h 28 -x M -y M -t = "bash ${CODEX_FLEET_REPO_ROOT}/scripts/codex-fleet/bin/pane-context-menu-chooser.sh '#{pane_id}'" } +unbind-key -T root S-MouseDown3Pane +bind-key -T root MouseDown3Pane \ + if-shell -F -t = "#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}" \ + { select-pane -t = ; send-keys -M } \ + { set-environment -g CODEX_FLEET_MENU_LINE "#{q:mouse_line}" ; \ + select-pane -t = ; \ + display-menu -O -x M -y M \ + -T "#[align=centre,bold,fg=#FFFFFF,bg=#1C1C1E] pane #{pane_index} · #{pane_id} " \ + "#[fg=#AEAEB2]▣ #[fg=#FFFFFF]Copy whole pane" C "run-shell \"tmux capture-pane -t '#{pane_id}' -p -S - -E - | bash ${CODEX_FLEET_REPO_ROOT}/scripts/codex-fleet/bin/pane-menu-clip-dual.sh && tmux display-message -d 1200 '▣ pane history copied'\"" \ + "#[fg=#AEAEB2]▢ #[fg=#FFFFFF]Copy visible" c "run-shell \"tmux capture-pane -t '#{pane_id}' -p | bash ${CODEX_FLEET_REPO_ROOT}/scripts/codex-fleet/bin/pane-menu-clip-dual.sh && tmux display-message -d 1200 '▢ visible area copied'\"" \ + "#[fg=#AEAEB2]─ #[fg=#FFFFFF]Copy this line" l "run-shell \"bash ${CODEX_FLEET_REPO_ROOT}/scripts/codex-fleet/bin/pane-menu-copy-line.sh\"" \ + "#[fg=#34C759]↳ #[fg=#FFFFFF]Paste clipboard" p "run-shell \"wl-paste --no-newline | tmux load-buffer - && tmux paste-buffer -d -p -t '#{pane_id}'\"" \ + "" \ + "#[fg=#AEAEB2]↟ #[fg=#FFFFFF]Scroll to top" "<" "copy-mode -t '#{pane_id}' ; send-keys -X -t '#{pane_id}' history-top" \ + "#[fg=#AEAEB2]↡ #[fg=#FFFFFF]Scroll to bottom" ">" "copy-mode -t '#{pane_id}' ; send-keys -X -t '#{pane_id}' history-bottom" \ + "" \ + "#[fg=#AEAEB2]⊟ #[fg=#FFFFFF]Split right" h "split-window -h -t '#{pane_id}'" \ + "#[fg=#AEAEB2]⊞ #[fg=#FFFFFF]Split down" v "split-window -v -t '#{pane_id}'" \ + "#{?#{>:#{window_panes},1},,-}#[fg=#AEAEB2]⤢ #[fg=#FFFFFF]#{?window_zoomed_flag,Unzoom pane,Zoom pane}" z "resize-pane -Z -t '#{pane_id}'" \ + "" \ + "#{?#{>:#{window_panes},1},,-}#[fg=#AEAEB2]↥ #[fg=#FFFFFF]Swap up" u "swap-pane -U -t '#{pane_id}'" \ + "#{?#{>:#{window_panes},1},,-}#[fg=#AEAEB2]↧ #[fg=#FFFFFF]Swap down" d "swap-pane -D -t '#{pane_id}'" \ + "#{?pane_marked_set,,-}#[fg=#AEAEB2]⇄ #[fg=#FFFFFF]Swap with marked" s "swap-pane -t '#{pane_id}'" \ + "#[fg=#FFCC00]★ #[fg=#FFFFFF]#{?pane_marked,Unmark pane,Mark pane}" m "select-pane -m -t '#{pane_id}'" \ + "" \ + "#[fg=#FF9500]↻ #[fg=#FFFFFF]Respawn pane" R "respawn-pane -k -t '#{pane_id}'" \ + "#[fg=#FF3B30]✕ #[fg=#FF3B30,bold]Kill pane" X "confirm-before -p '#[fg=#FF3B30,bold] Kill pane #{pane_id}? (y/n) ' 'kill-pane -t \"#{pane_id}\"'" \ + "" \ + "#[fg=#8E8E93]? Keyboard help…" "?" "display-popup -E -B -w 60 -h 28 -x M -y M -t = \"bash ${CODEX_FLEET_REPO_ROOT}/scripts/codex-fleet/bin/help-popup.sh\"" } + +# Shift+Right-click → rich popup card (live LIVE chip + chip-shaped key hints). +bind-key -T root S-MouseDown3Pane \ + if-shell -F -t = "#{||:#{mouse_any_flag},#{&&:#{pane_in_mode},#{?#{m/r:(copy|view)-mode,#{pane_mode}},0,1}}}" \ + { select-pane -t = ; send-keys -M } \ + { set-environment -g CODEX_FLEET_MENU_LINE "#{q:mouse_line}" ; \ + display-popup -E -B -w 60 -h 28 -x M -y M -t = \ + "bash ${CODEX_FLEET_REPO_ROOT}/scripts/codex-fleet/bin/pane-context-menu-chooser.sh '#{pane_id}'" } -# Mouse-wheel routing — narrowed gate (alt-screen only). +# Mouse-wheel routing — narrowed gate (alt-screen OR codex CLI inline mode). # # Old behavior: wheel always entered copy-mode unless the pane held # mouse_any_flag. That made every plain shell pane (codex-bia-zazrifka @@ -298,15 +344,20 @@ bind-key -T root MouseDown3Pane if-shell -F -t = "#{||:#{mouse_any_flag},#{&&: # from there parked tmux's "(search down)" prompt across the status bar. # # New gate (in dispatch order): -# 1. pane already in copy-mode → send-keys -M (scrolls inside copy-mode) -# 2. pane holds mouse_any_flag → send-keys -M (codex CLI / TUI handles it) -# 3. pane is in alt-screen → copy-mode -e (override: anim dashboards -# set \033[?1049h but don't grab mouse, so -# tmux's default would silently drop the -# wheel — entering copy-mode is the only -# way to scroll their rendered output) -# 4. otherwise (plain shell) → send-keys -M (no accidental copy-mode; -# use prefix+[ for shell backlog instead) +# 1. pane already in copy-mode → send-keys -M (scrolls inside copy-mode) +# 2. pane holds mouse_any_flag → send-keys -M (TUI handles it) +# 3. pane is in alt-screen → copy-mode -e (anim dashboards set +# \033[?1049h but don't grab mouse, so +# tmux's default would silently drop the +# wheel — copy-mode is the only way to +# scroll their rendered output) +# 4. pane runs codex CLI (`node`) → copy-mode -e (codex >=v0.5 renders +# inline, never enters alt-screen at the +# idle prompt, and ignores forwarded +# wheel events. Without this case, scroll +# silently does nothing in chat panes.) +# 5. otherwise (plain shell) → send-keys -M (no accidental copy-mode; +# use prefix+[ for shell backlog instead) # # Why alternate_on instead of a window-name allowlist: full-bringup.sh has # six viz windows (fleet, plan, waves, review, watcher, design) and two @@ -317,10 +368,10 @@ unbind-key -T root WheelUpPane unbind-key -T root WheelDownPane bind-key -T root WheelUpPane if-shell -F "#{||:#{pane_in_mode},#{mouse_any_flag}}" \ "send-keys -M" \ - "if-shell -F '#{alternate_on}' 'copy-mode -e' 'send-keys -M'" + "if-shell -F '#{||:#{alternate_on},#{m/r:^node$,#{pane_current_command}}}' 'copy-mode -e' 'send-keys -M'" bind-key -T root WheelDownPane if-shell -F "#{||:#{pane_in_mode},#{mouse_any_flag}}" \ "send-keys -M" \ - "if-shell -F '#{alternate_on}' 'copy-mode -e' 'send-keys -M'" + "if-shell -F '#{||:#{alternate_on},#{m/r:^node$,#{pane_current_command}}}' 'copy-mode -e' 'send-keys -M'" # Close ONLY the focused pane on `prefix + w` (operator's habit). # @@ -348,6 +399,69 @@ bind-key -T root MouseDown1Status select-window -t= TMUX_CONF tmux source-file "$sticky_menu_conf" >/dev/null 2>&1 || echo "[style-tabs] WARN: sticky menu rebind failed (see $sticky_menu_conf)" +# ── system-clipboard piping for mouse selection ───────────────────────────── +# tmux's default copy-pipe-and-cancel writes the selection to a tmux paste +# buffer only — operators expect drag/double/triple-click to land in the OS +# clipboard so they can paste into the browser. Wire up the right command for +# the host's display server. +# +# Detection order (first available wins): +# wl-copy — Wayland (sway, GNOME, KDE Plasma 6) +# xclip -selection clipboard — Xorg / XWayland fallback +# xsel --clipboard --input — older Xorg setups +# +# When none is found we leave the bindings alone (selection still lives in +# the tmux buffer; `prefix + ]` pastes it). The codex-fleet bin/* scripts +# already hard-depend on wl-copy, so on this rig the first branch wins. +# Use the dual-clip helper so every selection lands in BOTH the system +# clipboard and the X11 primary selection at once. Primary feeds Shift+Insert +# / middle-click paste the way a normal Linux terminal does; clipboard feeds +# Ctrl+Shift+V / paste-buffer. +_dual_clip="bash ${CODEX_FLEET_REPO_ROOT:-$HOME/Documents/codex-fleet}/scripts/codex-fleet/bin/pane-menu-clip-dual.sh" +_clip_cmd="" +if command -v wl-copy >/dev/null 2>&1 || command -v xclip >/dev/null 2>&1 || command -v xsel >/dev/null 2>&1; then + _clip_cmd="$_dual_clip" +fi +if [[ -n "$_clip_cmd" ]]; then + # Drag-end fires inside copy-mode-vi (MouseDrag1Pane enters copy-mode -M + # for non-mouse-grabbing panes). Pipe the selection through the clipboard + # tool then cancel copy-mode so the user is back at the prompt. + tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "$_clip_cmd" 2>/dev/null || true + # `Enter` and `y` (vi yank) — also pipe through clipboard. + tmux bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "$_clip_cmd" 2>/dev/null || true + tmux bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "$_clip_cmd" 2>/dev/null || true + # Double / triple click in copy-mode (word / line selection). + tmux bind-key -T copy-mode-vi DoubleClick1Pane "select-pane ; send-keys -X select-word ; run-shell -d 0.3 ; send-keys -X copy-pipe-and-cancel '$_clip_cmd'" 2>/dev/null || true + tmux bind-key -T copy-mode-vi TripleClick1Pane "select-pane ; send-keys -X select-line ; run-shell -d 0.3 ; send-keys -X copy-pipe-and-cancel '$_clip_cmd'" 2>/dev/null || true + # Root-table double/triple click — the version that fires when the user + # isn't already in copy-mode. tmux's default jumps into copy-mode -H, makes + # the selection, and `copy-pipe-and-cancel` drops back. Same wiring through + # the clipboard. + tmux bind-key -T root DoubleClick1Pane "select-pane -t = ; if-shell -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send-keys -M } { copy-mode -H ; send-keys -X select-word ; run-shell -d 0.3 ; send-keys -X copy-pipe-and-cancel '$_clip_cmd' }" 2>/dev/null || true + tmux bind-key -T root TripleClick1Pane "select-pane -t = ; if-shell -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send-keys -M } { copy-mode -H ; send-keys -X select-line ; run-shell -d 0.3 ; send-keys -X copy-pipe-and-cancel '$_clip_cmd' }" 2>/dev/null || true + + # Middle-click → paste PRIMARY selection (the X11 "last selection" buffer + # that's filled by every drag/double/triple-click). Shift+Insert mirrors + # this so keyboard-driven primary paste works too. Both gestures match + # xterm / gnome-terminal / kitty defaults — the symmetric half of the + # "feels like a normal terminal" copy/paste loop. + # + # For an explicit clipboard paste (the Ctrl+Shift+V semantic), use the + # Paste row in the right-click menu or `prefix + ]`. + _primary_cmd="" + if command -v wl-paste >/dev/null 2>&1; then + _primary_cmd="wl-paste --no-newline --primary" + elif command -v xclip >/dev/null 2>&1; then + _primary_cmd="xclip -selection primary -o" + elif command -v xsel >/dev/null 2>&1; then + _primary_cmd="xsel --primary --output" + fi + if [[ -n "$_primary_cmd" ]]; then + tmux bind-key -T root MouseDown2Pane "select-pane -t = ; if-shell -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send-keys -M } { run-shell '$_primary_cmd | tmux load-buffer - && tmux paste-buffer -d -p' }" 2>/dev/null || true + tmux bind-key -T root S-IC "if-shell -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send-keys S-IC } { run-shell '$_primary_cmd | tmux load-buffer - && tmux paste-buffer -d -p' }" 2>/dev/null || true + fi +fi + # Default UX: hide the tmux status bar entirely. The canonical navigation # surface is now the in-binary tab strip rendered by `rust/fleet-ui::tab_strip` # at the top of every ratatui dashboard (fleet-state / fleet-plan-tree / diff --git a/scripts/codex-fleet/supervisor.sh b/scripts/codex-fleet/supervisor.sh index 79236a8..b550d89 100755 --- a/scripts/codex-fleet/supervisor.sh +++ b/scripts/codex-fleet/supervisor.sh @@ -287,8 +287,8 @@ usage_lines() { cat "$USAGE_FILE" return 0 fi - if command -v codex-auth >/dev/null 2>&1; then - codex-auth list 2>/dev/null || true + if command -v agent-auth >/dev/null 2>&1; then + agent-auth list 2>/dev/null || true fi } diff --git a/scripts/codex-fleet/test/test-status-chips.sh b/scripts/codex-fleet/test/test-status-chips.sh index 743c4f7..26e9c03 100644 --- a/scripts/codex-fleet/test/test-status-chips.sh +++ b/scripts/codex-fleet/test/test-status-chips.sh @@ -9,13 +9,13 @@ mkdir -p "$TMP" mkdir -p "$TMP/bin" printf '{"tasks":[]}\n' > "$TMP/plan.json" : > "$TMP/active.txt" -cat > "$TMP/bin/codex-auth" <<'SH' +cat > "$TMP/bin/agent-auth" <<'SH' #!/usr/bin/env bash if [[ "${1:-}" == "list" ]]; then printf ' chip@example.com type=ChatGPT seat (Business) 5h=0%% weekly=10%%\n' fi SH -chmod +x "$TMP/bin/codex-auth" +chmod +x "$TMP/bin/agent-auth" export PATH="$TMP/bin:$PATH" export FLEET_TICK_SOURCE_ONLY=1 diff --git a/scripts/codex-fleet/token-meter.sh b/scripts/codex-fleet/token-meter.sh index 98151a8..852e9e9 100755 --- a/scripts/codex-fleet/token-meter.sh +++ b/scripts/codex-fleet/token-meter.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # token-meter.sh — per-pane spend snapshot for codex-fleet tmux. -# pane /proc env + codex-auth list + tmux capture-pane → sorted table/JSON. +# pane /proc env + agent-auth list + tmux capture-pane → sorted table/JSON. set -u; LC_ALL=C @@ -42,9 +42,9 @@ if [ "$USE_COLOR" = "1" ]; then c_red=$'\033[31m'; c_dim=$'\033[2m'; c_bold=$'\033[1m'; c_reset=$'\033[0m' fi -# pull `codex-auth list` once; cache as email\t5h\twk per line +# pull `agent-auth list` once; cache as email\t5h\twk per line fetch_auth() { - codex-auth list 2>/dev/null \ + agent-auth list 2>/dev/null \ | awk '/type=ChatGPT/ { email=""; fh="n/a"; wk="n/a"; for (i=1;i<=NF;i++) { @@ -104,7 +104,7 @@ pct_num() { # "62%" → 62; "n/a" → -1 } is_hot() { - # codex-auth's 5h% / weekly% report REMAINING quota; codex's ctx% reports + # agent-auth's 5h% / weekly% report REMAINING quota; codex's ctx% reports # REMAINING context. Low values = about to wedge → red. (Earlier draft had # these inverted because the design brief used "spend %" semantics.) local fh wk ctx diff --git a/scripts/codex-fleet/watcher-board.sh b/scripts/codex-fleet/watcher-board.sh index 6caba0b..60c62de 100644 --- a/scripts/codex-fleet/watcher-board.sh +++ b/scripts/codex-fleet/watcher-board.sh @@ -144,7 +144,7 @@ for line in sh("tmux", "list-panes", "-t", f"{SESSION}:overview", "-F", # ── 4. Quotas ───────────────────────────────────────────────────────── quotas = {} -for line in sh("codex-auth", "list").splitlines(): +for line in sh("agent-auth", "list").splitlines(): em = re.search(r"([\w.+-]+@[\w.-]+\.[a-z]+)", line) if not em: continue h5 = re.search(r"5h=(\d+)%", line); wk = re.search(r"weekly=(\d+)%", line) @@ -153,7 +153,7 @@ for line in sh("codex-auth", "list").splitlines(): # ── 5. Cap pool + healthy pool + per-email probe map ───────────────── # probe_map: {email -> (verdict, eta_str_or_None)} — used by FLEET PANES card -# below as the live "5h" signal, since codex-auth list's 5h column reports the +# below as the live "5h" signal, since agent-auth list's 5h column reports the # API meter (often 100% used while the rolling cap is still fine) and is # misleading. cap-probe's verdict comes from an actual `codex exec` round-trip. cap_pool = [] @@ -330,7 +330,7 @@ hdr = (f"{D}PANE AGENT STATE " f"5h-LIVE WK-USED ACCOUNT{R}") out.append(card_row(hdr)) # 5h column shows the live cap-probe verdict (healthy/capped/unknown) instead -# of codex-auth's API-meter percentage. WK-USED matches the value `codex-auth +# of agent-auth's API-meter percentage. WK-USED matches the value `agent-auth # list` prints for `weekly=`, so the watcher reads identically to the shell. for p in panes: bg, icon, label = state_meta.get(p["state"], (BG_GRAY, "◇", p["state"])) diff --git a/skills/codex-fleet/SKILL.md b/skills/codex-fleet/SKILL.md index c6ffa82..e90c397 100644 --- a/skills/codex-fleet/SKILL.md +++ b/skills/codex-fleet/SKILL.md @@ -41,7 +41,7 @@ bash scripts/codex-fleet/full-bringup.sh # default: newest plan, 8 wor bash scripts/codex-fleet/full-bringup.sh --plan-slug --n 8 --no-attach ``` -`full-bringup.sh` atomically: prunes stale `refs/remotes/origin/` → picks newest plan → `colony plan publish ` (idempotent) → ranks 3N candidates by `codex-auth list` → runs `cap-probe.sh` to verify each candidate live → stages CODEX_HOMEs → creates `codex-fleet` session with FIVE windows in this order: `0 watcher` / `1 overview` / `2 fleet` / `3 plan` / `4 waves` → creates sibling `fleet-ticker` session with `ticker` + `cap-swap` + `state-pump` → attaches. Refuses to start if a `codex-fleet` session already exists. +`full-bringup.sh` atomically: prunes stale `refs/remotes/origin/` → picks newest plan → `colony plan publish ` (idempotent) → ranks 3N candidates by `agent-auth list` → runs `cap-probe.sh` to verify each candidate live → stages CODEX_HOMEs → creates `codex-fleet` session with FIVE windows in this order: `0 watcher` / `1 overview` / `2 fleet` / `3 plan` / `4 waves` → creates sibling `fleet-ticker` session with `ticker` + `cap-swap` + `state-pump` → attaches. Refuses to start if a `codex-fleet` session already exists. ## Canonical visual design (lock this in) @@ -96,7 +96,7 @@ The bash `*-anim.sh` scripts stay one release as the `FLEET_DASHBOARD_RENDERER=b 1. Every codex spawn line includes `CODEX_GUARD_BYPASS=1` to avoid the codex-guard branch-collision storm when N panes spawn within the same second. 2. Pre-spawn `git remote prune origin && git fetch --prune origin` to clear stale `refs/remotes/origin/`. 3. Plan publish (`colony plan publish `) is non-negotiable — workers can only claim from registered plans. -4. Account selection runs through `cap-probe.sh` (live `codex exec` probe), not raw `codex-auth list` percentages — codex CLI's rolling cap is separate from the API meter. +4. Account selection runs through `cap-probe.sh` (live `codex exec` probe), not raw `agent-auth list` percentages — codex CLI's rolling cap is separate from the API meter. 5. Capped accounts are remembered with their reset epoch at `/tmp/claude-viz/cap-probe-cache/.json`; cache lookups skip re-probing for the duration (could be hours, days, or weeks). 6. The cap-swap daemon runs in `fleet-ticker:cap-swap` as the autonomous global watcher — never spawn a separate Claude session to "watch the fleet". @@ -187,8 +187,8 @@ When the user reports "i can't click tabs", "menu doesn't work", The watcher's `FLEET PANES` card has two quota-related columns: -- `5h-LIVE` — verdict from the cap-probe cache (`/tmp/claude-viz/cap-probe-cache/.json`), set by an actual `codex exec` round-trip during the sweep. `✓ OK` green if healthy, `✕ ` red if capped (eta is time until reset, e.g. `6d`), `? ??` gray if unknown. This is the authoritative "is this account usable right now" signal — codex-auth's `5h=` column is the API meter and reads 100% even when the rolling cap is fine, so the watcher does **not** display that value directly. -- `WK-USED` — raw `weekly=N%` value parsed from `codex-auth list`, no inversion. Green ≤40%, yellow ≤75%, red above. Reads identically to what the operator sees in their shell. +- `5h-LIVE` — verdict from the cap-probe cache (`/tmp/claude-viz/cap-probe-cache/.json`), set by an actual `codex exec` round-trip during the sweep. `✓ OK` green if healthy, `✕ ` red if capped (eta is time until reset, e.g. `6d`), `? ??` gray if unknown. This is the authoritative "is this account usable right now" signal — agent-auth's `5h=` column is the API meter and reads 100% even when the rolling cap is fine, so the watcher does **not** display that value directly. +- `WK-USED` — raw `weekly=N%` value parsed from `agent-auth list`, no inversion. Green ≤40%, yellow ≤75%, red above. Reads identically to what the operator sees in their shell. ### `down` — tear it down