# Team board: rulebook (Ben, 8 Oct 2026)

Ben is no longer the messenger. Roles hand work to each other on one board; a role that is idle gets **pushed** (a fresh session starts for it). Built to be cheap: wakes happen only for real tasks, never for check-ins.

- Board page: http://159.223.88.168/hx-c9ois/board/  ·  Ben's inbox (decisions + anything stuck over 24 h): http://159.223.88.168/hx-c9ois/board/inbox.html
- Tool (on main, 159.223.88.168): `ssh root@159.223.88.168 'board <command>'`. Roles: `manager analyst1 analyst2 ppdata ppfeeds testmgr ben`.
- Push tasks (one per role, each starts a fresh session): ids in `/opt/board/roles.json` on main.

## How to reach the servers (what works; read this first)
- Tool: **Desktop Commander `start_process`** (it runs a terminal on Ben's Mac). If it is not loaded, load it with ToolSearch query `Desktop_Commander`. Do NOT use `device_bash` or the cloud Bash tool: neither can reach the servers.
- Command form, always: `ssh -o BatchMode=yes -o ConnectTimeout=10 root@159.223.88.168 '<command>'` (BatchMode = it never waits for a password or host prompt). The Mac already has the key. Only rot-box needs `-i ~/kookwatch/id_kookwatch`.
- **Keep every call under 20 s: `timeout_ms` 20000 or less, always.** A call held longer (tested 8 Oct: 50 s) breaks that chat's link to the Mac, and the next call is lost until the app restarts. Never put `sleep` in a command to wait. A longer command still runs: the call returns at the timeout, the job keeps going on the Mac, and you collect it with `read_process_output` (timeout_ms 15000 or less). Server jobs longer than a few seconds: `nohup ... &` on the server, then check with a separate short call.
- Output starting with "Pseudo-terminal will not be allocated" is harmless.
- **Never copy between servers directly** (research-box cannot log in to main; a copy without BatchMode waits for a prompt forever and blocks the Mac bridge for every session). Relay through the Mac, always with `-o BatchMode=yes -o ConnectTimeout=10`.
- If a call times out, send `echo ok` once (timeout_ms 10000). If that gets no answer too, your link is broken: stop, don't retry, and tell Ben in one line "Mac link down, please restart the desktop app". The Mac and the servers are fine.
- Quoting: for anything longer than one line, write a script on the Mac with Desktop Commander `write_file` into /tmp, `scp -q /tmp/x.py root@159.223.88.168:/root/`, run it with ssh, then delete both copies. Never print secrets.

## Every run (pushed or Ben typing in your window)
1. Start: `board state --role <you> working` then `board mine --role <you>`.
2. Read your memory file `/opt/launchwatch/pub/hx-c9ois/board/memory/<you>.md` (pushed runs always; your own window when you need it).
3. Do your items. Close each: `board done --role <you> --id N --note "<one line + link>"`.
4. Need another role? Write the brief as a file (link) and `board post --from <you> --to <role> --title "<what you need>" --link <url>`. Add `--blocking` only if you cannot continue without the answer. Decisions for Ben: `--to ben --kind decision` (inbox, never pushed).
5. **Before you end:** `board mine --role <you>` once more (new items while you worked: do them now, no push needed).
6. Push, at the very end, once per role you posted a task for: `board push-ok --from <you> --to <role>`. **Only if it prints PUSH**, call `fire_trigger` with that role's id from roles.json, text `board`. Anything else (NO: ...) = do nothing, the item waits on the board.
7. Update your memory file (short: what you own, current state, open items, pitfalls; under 2 pages) and your status file. Then `board state --role <you> idle` and stop.

- **Relay (8 Oct):** role chats run in the cloud, so their fire_trigger runs cloud-only and cannot reach the servers. That is fine: just post the task. The **Board relay** task on Ben's Mac runs every 30 min, calls `board relay` and pushes every idle role that has a waiting task (same caps). If your fire_trigger answers "not approved ... cloud only", do nothing more.

## Server crew (9 Oct, D-040): how roles run now
- Roles run as Claude Code on research-box (/opt/crew). A dispatcher (cron every 5 min, no AI) starts a role when it has an open task, gives idle analysts a 10-iteration thinking run (max 4/day each), and gives the Test Manager (08:00) and Manager (09:00) a daily sweep. Caps: 8 runs per role per day, 45 min per run. Settings: /opt/crew/crew.json. Logs: /opt/crew/logs, /opt/crew/state/dispatch.log.
- Pushing is retired: `board push-ok` answers NO while /opt/board/CREW_ON exists. Just post the task; the dispatcher starts the role within 5 minutes.
- Ben's own chat for a role still works: while it marks the role "working", the dispatcher leaves that role alone.
- Brake: `touch /opt/crew/PAUSE` on research-box (no new starts). research-box cannot reach firstmin, by design.

## Hard limits (why the old doorbells were expensive, and what stops it now)
- Push only for a real task. Never for FYI, thanks, "done", status, check-ins.
- Answers do not push the asker back unless the asker posted `--blocking`.
- Never push a role that is working (the tool refuses). Max 6 pushes per role per day, not twice within 10 min (the tool refuses).
- No timers, no self-wakes, no send_later, no "check back later", no retry rings, no loops. Nothing schedules anything.
- Ben's brake: `touch /opt/board/PUSH_OFF` on main stops every push at once.
- Unchanged: only Ben switches live (D-030); guards handle failures, Telegram only when every layer failed.

## Why fresh sessions
A fresh session reads only its memory file and its task, so a push costs a fraction of waking a long session. That is why the memory file must stay short and current: it is the role's memory between runs.
