# Managing projects — the PO runbooks These are the flows the project-orchestrator (the AI in `prompts/orchestrator.md`, or a human operator) follows. The PO is **AI-driven, not contract-bound**: for any harness it doesn't already know, it *reads that harness's docs* and works out how to drive it. The helper scripts here cover the common `agent-orchestrator` case; treat them as conveniences, not a rigid interface. The one invariant across every flow: **knowledge is one-directional (PO → project)**. Nothing about the PO or the fleet is ever written into a project repo. --- ## Create a project **Goal:** a new, self-contained project repo — the chosen harness vendored as `engine/` at a pinned ref, a harness config scaffolded by that harness, and **no** PO/fleet metadata — plus (separately) a `fleet.toml` entry on the PO side. ```bash scripts/create-project.sh \ [--dir ] # where to create it (default: ./projects) [--engine-url ] # harness repo (default: the agent-orchestrator repo) [--ref ] # harness ref to pin (default: v0.1.0) [--prefix ] # tmux namespace in the config (default: -) [--register] # also append a [[project]] entry to fleet.toml ``` What it does, step by step (so the PO can also do it by hand for a non-default harness): 1. `git init -b main /`. 2. Vendor the harness: `git submodule add engine`, then `git -C engine checkout `. The submodule pin **is** the recorded harness version inside the project (no other metadata). 3. Scaffold the harness config with the harness's own initializer (`python3 engine/agents.py init .`), and stamp a unique `session_prefix`. This writes `agents.toml` + `prompts/` — **harness config only**. 4. Add a `.gitignore` for runtime state (`.ao-state/`), and an initial commit. 5. **Separately** (only with `--register`, or by hand): append a `[[project]]` block to the PO's `fleet.toml`. This is PO-side; it never lands in the project. Verify the new project standalone — it must work with no knowledge of any PO: ```bash ( cd / && python3 engine/agents.py status ) ``` And confirm isolation — the project must contain **no** PO/fleet metadata: ```bash cd / grep -ril -e 'fleet' -e 'project-orchestrator' -e 'project orchestrator' . --exclude-dir=engine --exclude-dir=.git || echo "clean: no PO/fleet metadata" ``` (Exclude `engine/` — that's the upstream harness, whose own docs legitimately *describe* being driven by a PO; that is the harness documenting a consumer, not this project knowing about a fleet.) --- ## Start / stop a project Drive the project's harness. For an `agent-orchestrator` project: ```bash scripts/start-project.sh [agent...] # → engine/agents.py up (in the project dir) scripts/stop-project.sh [agent...] # → engine/agents.py down ``` Both resolve `` → `location` via `fleet.toml`. For a remote-only `location`, clone it locally first. For a non-`agent-orchestrator` harness, the wrapper bows out — read that harness's docs and drive it directly. --- ## Update a project's harness Bumping the engine is **per-project and opt-in** — it touches only that project's repo; every other project keeps its own pin, so one bump can't break another. ```bash scripts/update-project.sh # checkout new ref in the project's engine/ + commit ``` Then update the project's `ref` in `fleet.toml` and `python3 scripts/fleet.py validate`. --- ## List / status the fleet ```bash python3 scripts/fleet.py list # one line per project: name, enabled, harness@ref, location python3 scripts/fleet.py status # + a total/enabled/disabled summary ``` This reads only `fleet.toml`. To also check live state, drive each enabled project's harness (`engine/agents.py status --config /agents.toml`). The PO does this **on request** — there is no periodic fleet sweep; this repo manages projects when asked, it does not watch them live.