Skip to content

ISS-12135: feat(vibe): Add fleet-orchestrator skill - #318

Merged
shafty023 merged 28 commits into
mainfrom
feat/vibe-fleet-orchestrator
Oct 20, 2026
Merged

shafty023 merged 28 commits into
mainfrom
feat/vibe-fleet-orchestrator

Conversation

@shafty023

@shafty023 shafty023 commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Purpose

Adds a fleet-orchestrator skill to the vibe plugin. It keeps what was learned running a 14-PR, two-machine Codex and Claude program so later sessions start with it. It is for a Claude Code session that orchestrates several Codex and Claude workers on parallel PRs, on one or more machines, for an operator who does QA and merges. It works on anyone's machine: everything machine-specific comes from the orchestration dir's config.env.

  • SKILL.md: rules, each with a one-line reason: roles, state and persistence, monitoring (links to codex-fleet-monitor), Codex sessions (budget, takeover), Claude workers, machines and CPU, quality gates and QA, pushback, lessons loop, reporting. Repo specifics come from the repo's own docs or the team knowledge base; no repo, org, host or account values are hardcoded.
  • references/setup.md: one prerequisite for several machines (ssh key auth, plus codex, node, gh on each), a placeholder config.env and a setup checklist (create the dir, fill config, verify ssh and a login shell that finds node and codex, push a branch to another machine's clone, check the transport). One machine needs no remote keys.
  • references/state.md (dir layout, resume log, lessons ledger), references/templates.md (visual request, worker and takeover preamble, flag approval), references/judgment.md (judgment patterns from past programs).
  • scripts/fleet.sh <orchDir> local|remote session turn|steer|last <name>: drives a Codex session here or on REMOTE_HOST. For a remote session it copies the scripts and the prompt file over ssh and runs them in REMOTE_SHELL. --model and --effort default to CODEX_MODEL and CODEX_EFFORT from config. fleet.sh <orchDir> local|remote slot <lock> <owner> <dir> <command...> runs a command in that machine's slots: HEAVY_SLOTS or REMOTE_HEAVY_SLOTS for heavy, one for any other lock such as a shared e2e stack.
  • scripts/codex-session.mjs: starts a thread bound to a worktree cwd (a new session needs an effort) or resumes the saved one, starts a turn from a prompt file, steers an active turn, and reads the last messages. It reuses the App Server client and timeout exported by codex-fleet-monitor's liveness.mjs (nothing duplicated, no GNU timeout). Approval policy is never because it disconnects once a turn is accepted. Its state file is the one the monitor reads for local|remote <name> lines.
  • scripts/slot-lock.sh [--slots N] <lock> <owner> <command...>: records the owner, reclaims slots whose holder pid died, and frees the slot (stopping the command) on exit, INT or TERM. --status lists holders.
  • scripts/generic.test.mjs: fails if any file in the skill carries a home path, IP, email, ticket id, owner/repo#N reference, or this org's or repo's name.
  • vibe 1.0.59 to 1.0.65 (above the highest open vibe PR, ISS-12135: fix(vibe): encode the open vibe lessons ledger #317 at 1.0.64), README section and CHANGELOG entry.

Limit kept on purpose: like codex-fleet-monitor, config has one remote machine (REMOTE_*), not a list.

Affected files

  • plugins/vibe/skills/fleet-orchestrator/ (SKILL.md, agents/openai.yaml, references/{setup,state,templates,judgment}.md, scripts/{fleet.sh,codex-session.mjs,slot-lock.sh} and their tests, scripts/generic.test.mjs)
  • plugins/vibe/.claude-plugin/plugin.json, plugins/vibe/.codex-plugin/plugin.json, plugins/vibe/README.md, CHANGELOG.md

Commands run

  • node --test on every plugins/**/*.test.{mjs,cjs,js} (the CI step): 458 passed
  • the skill's shell tests again under macOS bash 3.2: pass
  • uv run pytest plugins/vibe: 334 passed; uv run ruff check .: clean; uv run pyright: 0 errors
  • tools/plugin-manifests: npm run typecheck, npm test (6 passed)
  • Live against real App Servers through fleet.sh:
    • locally and on a second machine over ssh, turn on a new session completed after the script disconnected, and last read it back
    • a remote slot heavy ran in the remote dir
    • with codex-session.mjs directly, a second turn resumed the thread, steer changed a running turn's reply, and steer on an idle thread was refused

- Background watcher for a fleet of Codex App Server threads (local
  and one ssh host) plus their pull requests; exits with a diff on the
  first change
- Reads liveness from each thread's last turn and item count, so a
  turn left open by a silent usage limit shows as STALLED
- vibe 1.0.57, README and changelog entries

Testing: pytest plugins/ (2430 passed), ruff, plugin-manifests
typecheck and tests, node --check and zsh -n on the scripts
Risks: None identified, the skill only reads thread and PR state
- Describe when to reach for the skill and why a turn-only watcher misses a usage-limit stall
liveness.mjs no longer imports the app-server-orchestrator skill from
~/.codex/skills. It carries a small App Server client (WebSocket over
codex app-server proxy, initialize, thread/read) in one file so the ssh
copy to a remote host still works. sessions.txt takes
'local|remote <label> <threadId>' as well as the older '<name>' form that
reads a state file. Adds a node:test suite with a fake server.
- ratelimit.mjs reads account/rateLimits/read through the client liveness.mjs
  already exports and prints codex-usage <where> <band>% <state> resets=<n>.
  snapshot.sh runs it locally and on REMOTE_HOST, copying both scripts there.
- Optional REQUESTS_DIR and REMOTE_REQUESTS_DIR print a requests line so the
  watcher wakes when a session drops a delegated-work request.
- watch.sh keeps the previous run's last-snapshot.txt as its base, so a change
  between a watcher exit and its re-arm is still reported.
- PR check counts are only updated once settled; while checks are pending the
  last settled counts show with a (running) suffix.
- SKILL.md documents the new lines and what to do about each.
- Add the fleet-orchestrator skill: rules for running Codex and Claude
  workers on parallel PRs across machines for an operator who does QA
  and merges, with state, template and log formats under references/
- Add codex-session.mjs to start or resume a Codex thread bound to a
  worktree, start and steer turns from prompt files and read the last
  messages, built on the codex-fleet-monitor App Server client
- Add slot-lock.sh for a machine-wide e2e stack slot and an N-slot
  heavy-check cap, with stale pid cleanup and release on exit or signal
- Bump vibe to 1.0.65 and document the skill

Testing: node --test over all vibe test files, uv run pytest
plugins/vibe, ruff, pyright, plugin-manifests tests; one live turn,
resume, steer and last against a real Codex App Server

Risks: None identified; new files only
Base automatically changed from feat/vibe-codex-fleet-monitor to main October 20, 2026 16:47
- Read hosts, paths, model names, effort and slot counts from the
  orchestration dir's config.env through a new fleet.sh, which runs
  sessions and slots locally or over ssh on another machine
- Require an effort for a new Codex session instead of a built in
  default, and create the state dir when saving
- Add a setup reference with prerequisites, a placeholder config and a
  checklist, and replace program specific examples with generic ones
- Add a test that fails on home paths, IPs, emails, ticket ids and
  repo references in the skill

Testing: node --test over the skill scripts under bash 5 and macOS
bash 3.2

Risks: None identified
# Conflicts:
#	CHANGELOG.md
#	plugins/vibe/.claude-plugin/plugin.json
#	plugins/vibe/.codex-plugin/plugin.json
#	plugins/vibe/README.md
- Point repo specifics at the repo's own docs or the team knowledge
  base and name UX precedent generically
- Fail the generic check on this organization's and repository's names
- Add references/judgment.md with the patterns from the brief's
  addendum that SKILL.md did not already carry
- Fold the overlapping ones into their existing SKILL.md rules: usage
  rate, measured QA checks, baseline tracing, precedent rulings
- Name the order each PR moves through before enqueue, and that a
  head change sends it back to the earliest affected step
- Say how to recover Codex threads on a remote machine that rebooted
- Every writer is a vibe session: Codex writers start with a $vibe
  prompt, which codex-session.mjs now requires for a new session, and
  Claude writers invoke vibe:vibe
- Route reviews, handoff, ticket, environment and seed work through
  vibe's own workers and scripts
- Start the worker preamble with invoking vibe, keep a Claude takeover
  inside vibe and log the missing migration as a gap
- One section for moves in both directions between Codex machines or
  accounts and Claude, triggered by MOVE_AT_PERCENT, Codex limit lines
  or Claude limit errors, with the old writer always stopped first
- Add a resume prompt template and the MOVE_AT_PERCENT config key
- List the plugin among the per-machine prerequisites in SKILL.md
- State up front that the operator's attention is the scarcest
  resource and that every worker output gets a sanity check
- Point Roles, Pushback, Reporting and judgment.md at the principles
  instead of restating them
- Add a research section: overlap and collisions before assigning or
  ruling, ticket lineage, callers and importers before a shared change,
  code_tests_for for tests, and tracing a surprising diff to its ticket
- Carry graph-first research in the worker preamble and resume prompt
- List the closedloop-graph server as a prerequisite and check it in
  the setup checklist
- Let the generic check allow the plugin family's own tool names
- Read acceptance criteria and scope, the PRD, human review threads
  including resolved ones, and closedloop-graph before precedent
- Send a conflicting human-sourced line to the operator and record
  every ruling with its source for the writer to cite
- Ask once for machines, writer runtimes, Codex budget and move
  threshold, and the UX precedent product when config.env lacks them,
  with single machine and Claude only as defaults
- Write config.env from the answers, verify, and report; later runs
  ask again only when a verification fails
- Add request-visual.mjs, which files a visual request only when its
  head equals the PR's pushed head and the worktree HEAD, and refuses
  when gh cannot answer; ship it to remote machines with fleet.sh
- Let code_tests_for over the touched files decide which tests run
  after any change, fix or merge, in SKILL.md and both worker prompts
- Keep both changelog entries and vibe at 1.0.65 over main's 1.0.60
- Run a shared e2e stack under vibe's e2e-lock.mjs from main instead
  of a second fleet slot for the same stack
- Send each heavy run to the machine with the lower load per core
- Run human QA in a headless, primed Claude QA-guide session per PR
  that the operator resumes, with a QA guide prompt template
- Drop CODEX_EXPLORER_MODEL from the config example, the first-run
  interview and the resume prompt; keep CODEX_MODEL and CODEX_EFFORT
  for the thread
@shafty023
shafty023 merged commit 7de5bc0 into main Oct 20, 2026
10 checks passed
@shafty023
shafty023 deleted the feat/vibe-fleet-orchestrator branch October 20, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant