mirror of
https://github.com/home-assistant/core.git
synced 2026-09-26 09:23:17 -04:00
sandbox: add PLAN_RUNNER.md — the per-plan sub-session workflow
Documents the loop used to build this batch: write a brief to a tempfile, spawn a fresh Claude in a screen window via single-line file-handoff, watch for a STATUS marker, verify independently, push, kill the window. Captures the gotchas that bit (single-line stdin, prompt-submit confirmation, prefix-match window names, orchestrator-only push). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
16a3c17397
commit
83763c94b3
@@ -0,0 +1,105 @@
|
||||
# Plan runner
|
||||
|
||||
How an orchestrator session builds one plan: spawn a fresh Claude in a
|
||||
`screen` window, hand it a brief, wait for a STATUS marker, verify, push, kill
|
||||
the window. One plan per session, sequentially.
|
||||
|
||||
## Why this shape
|
||||
|
||||
- **Fresh context per plan.** Each sub-session reads only its plan + the files
|
||||
it needs — no drift from the orchestrator's long history.
|
||||
- **The orchestrator stays the integrator.** Sub-sessions build and commit;
|
||||
the orchestrator independently verifies (tests, greps, `git status`) and is
|
||||
the only one that pushes.
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Write a brief to a tempfile
|
||||
|
||||
The brief is the sub-session's whole instruction set: which plan to read, the
|
||||
locked decisions, hard rules, build steps, the exact tests/greps to run, and —
|
||||
critically — to **write a STATUS marker file LAST**.
|
||||
|
||||
```
|
||||
/tmp/<name>-brief.md
|
||||
```
|
||||
|
||||
Hard rules every brief repeats:
|
||||
- Do **not** modify the plan file.
|
||||
- Do **not** push. Commit each logical step; the orchestrator pushes.
|
||||
- No `--no-verify`; pre-commit must pass.
|
||||
- Write `sandbox/STATUS-<plan>.md` **last** (after the final commit) — its
|
||||
appearance is the "done" signal.
|
||||
|
||||
### 2. Spawn the session
|
||||
|
||||
Multi-line text piped to `claude-screen` does **not** land reliably (the TUI
|
||||
submits mid-paste). Always pipe a **single line** pointing at the brief:
|
||||
|
||||
```bash
|
||||
echo "Read /tmp/<name>-brief.md and follow every instruction in it exactly." \
|
||||
| ~/dev/claude-screen <name> /home/paulus/dev/hass/core
|
||||
```
|
||||
|
||||
Use an **unambiguous full `<name>`** — `screen -p` matches by prefix, so a
|
||||
later `kill` on a short name can hit the wrong window.
|
||||
|
||||
After ~12s, confirm the prompt was submitted (not just sitting in the input
|
||||
box — an onboarding banner can eat the auto-submit):
|
||||
|
||||
```bash
|
||||
screen -X -S claude -p <name> hardcopy /tmp/<name>-launch.dump && tail -20 /tmp/<name>-launch.dump
|
||||
```
|
||||
|
||||
If it's idle with the prompt unsent, nudge it:
|
||||
|
||||
```bash
|
||||
screen -X -S claude -p <name> stuff $'\r'
|
||||
```
|
||||
|
||||
### 3. Monitor for the STATUS marker
|
||||
|
||||
Arm a background watcher for the marker file, plus a long fallback in case the
|
||||
session hangs without writing it:
|
||||
|
||||
- **Monitor** (persistent, until-loop):
|
||||
`until test -f sandbox/STATUS-<plan>.md; do sleep 30; done; echo done`
|
||||
- **ScheduleWakeup** fallback (~40 min): on fire, peek at the window with
|
||||
`hardcopy` and `tail` to see if it's stuck.
|
||||
|
||||
### 4. Verify independently
|
||||
|
||||
Don't trust the self-report. When STATUS appears, read it, then re-run the
|
||||
load-bearing checks yourself:
|
||||
|
||||
```bash
|
||||
uv run pytest tests/components/sandbox/ --no-cov -q
|
||||
uv run pytest sandbox/hass_client/ -q
|
||||
# plus the plan's specific greps / hassfest / drift guard
|
||||
```
|
||||
|
||||
Common gotcha: a sub-session sometimes lands the code commit but **forgets the
|
||||
docs/STATUS second commit** — check `git status`, and commit any leftover the
|
||||
brief intended.
|
||||
|
||||
### 5. Push and kill
|
||||
|
||||
```bash
|
||||
git push origin sandbox
|
||||
screen -X -S claude -p <name> kill
|
||||
```
|
||||
|
||||
Then advance to the next plan.
|
||||
|
||||
## Gotchas (all bit at least once)
|
||||
|
||||
- **Single-line file-handoff only** — multi-line stdin to `claude-screen` is
|
||||
unreliable.
|
||||
- **Confirm the prompt submitted** — a first-run banner can swallow it; send
|
||||
`$'\r'` to nudge.
|
||||
- **`screen -p` is prefix-match** — use full, distinct window names.
|
||||
- **STATUS is written last** — its presence means done; nothing earlier does.
|
||||
- **Avoid git ops in the repo while a sub-session is mid-write** — index
|
||||
contention. (`prek` stash/restore usually saves you, but don't rely on it.)
|
||||
- **The orchestrator is the only pusher** — keeps one integration point and
|
||||
one verification gate.
|
||||
Reference in New Issue
Block a user