diff --git a/skills/batch/SKILL.md b/skills/batch/SKILL.md index 8f76a38..f16c4e8 100644 --- a/skills/batch/SKILL.md +++ b/skills/batch/SKILL.md @@ -5,18 +5,13 @@ description: Compose the next unattended batch through the PyAutoBrain Batch Age # Batch -Read [`../../agents/conductors/batch/AGENTS.md`](../../agents/conductors/batch/AGENTS.md) -completely, then run `bin/pyauto-brain batch plan` in the documented mode. +Read [`batch.md`](batch.md) in this directory — the authoritative body for the +slot door: how to propose a batch, how to compose one from what the human +pasted or described, how to dispatch it, and how to work through what came +back. Then read +[`../../agents/conductors/batch/AGENTS.md`](../../agents/conductors/batch/AGENTS.md) +for the constraints and why each exists. -Return the **BatchDecision** as written — members, the review-minutes it spends, -and what it rejected with reasons. Do not re-rank it, do not quietly add a -member the planner excluded, and do not present it as a schedule: it is a -proposal, and the human approving it in their slot is what launches the batch -([`../../AUTONOMY.md`](../../AUTONOMY.md), "What a batch launch is"). A -scheduler may carry the timing; it never carries the authority. - -Two parts of the output are the point and must survive into your reply: the -**review-minute total** (the budget is the human's hour, not a task count), and -the **other lane's ready count** when the session cannot plan it — *"4 local-dev -tasks are ready, run this from the laptop"*. An empty batch at the backpressure -cap is a finding, not a deadlock; say which. +The one rule that outranks convenience: **the human's go in the conversation is +what launches a batch** (`../../AUTONOMY.md`, "What a batch launch is"). A +schedule may carry the timing; it never carries the authority. diff --git a/skills/batch/batch.md b/skills/batch/batch.md new file mode 100644 index 0000000..8c6a2a6 --- /dev/null +++ b/skills/batch/batch.md @@ -0,0 +1,102 @@ +# Batch — the slot door + +The front door for the two-slot workflow: **what runs unattended, and what came +back**. Drive it from a chat; nothing here needs a terminal. + +Read [`../../agents/conductors/batch/AGENTS.md`](../../agents/conductors/batch/AGENTS.md) +before acting — it holds the constraints, why each exists, and the full slot +procedure. This page is how to *converse* with it. + +## The three things a human says + +**1. "What should I run?"** — `/batch`, or any ask for the next batch. + +Run `bin/pyauto-brain batch plan` and return the **BatchDecision as written**. +Do not re-rank it. Do not quietly add a member it rejected. Two parts must +survive into your reply because they are the point of the whole surface: + +- the **review-minute total** — the budget is the human's hour, not a task count; +- the **other lane's ready count**, when this session cannot plan it: *"4 + local-dev tasks are ready — run this from the laptop."* + +An empty batch at the backpressure cap is a **finding, not a deadlock**: nothing +in the backlog costs zero review-minutes. Say which it is. + +**2. "Here are the ones I want."** — a paste of paths from the Mind dashboard, +or a description ("something on the numba path", "the next euclid slice"). + +Resolve what they gave you to prompt paths, then run the planner's constraints +over exactly that set — do not silently substitute your own picks. Report, per +task they named: + +- **taken** — with its tier and review-minutes; +- **rejected, and why** — in the planner's own words. The reasons that come up + most: `autonomy supervised — would park at ship` (it will stop at the ship + checkpoint and come back as a question, which is the failure this workflow + exists to remove), `Status: says the work is already done`, `epic phase + N is not next`, ` already claimed this shift`, `would exceed the budget`. + +If everything they named is rejected, **say so plainly and offer the planner's +own proposal instead** — never hand back a batch they did not ask for as though +it were what they wanted. + +The human may overrule any rejection except two: a `Blocked-by:` that is still +open, and `Unattended: never`. Those are not preferences. + +**3. "Go."** — the dispatch. This is the launch, and it is the human's act +(`AUTONOMY.md`, "What a batch launch is"): membership fixed at approval, the +grant expiring with the shift. Never dispatch on your own initiative, on a +schedule, or because a batch looks ready. + +In order: + +1. Consult vitals (`bin/pyauto-brain vitals`). If Heart is YELLOW, **ask the + human to acknowledge the reason set for this shift** and record it verbatim. + You may not acknowledge it for them, and a set carried from an earlier batch + is void. +2. Write `PyAutoMind/batches/-.md` from the schema in that + folder's `AGENTS.md` — members, planned review-minutes, the reason set — + **before** any session starts. That file is what makes the launch auditable. +3. Start one session per member, each carrying exactly + `/start_dev --auto`. Spawn them if this harness can; otherwise hand + the human the lines to paste. **One session per member, never shared**: a + shared session serialises them and carries one member's context into the + next. +4. Confirm what was dispatched, and stop. Do not follow the runs. + +## When they come back + +Read the PRs. Order: **failures first, then anything labelled `decision-taken`, +then clean.** For each, offer three things and do the one they pick: + +- **merge** — `/prm `; +- **tweak** — they say one line; *you* draft the follow-up prompt and put it at + the top of `queue.md`. They should never have to write a prompt file. +- **reject** — route it to `condemned.md`. + +Then append the outcome to the batch record: `delivered:` (see below) and +**`review-minutes-actual:`**. That second number is the only calibration the +estimate will ever get, so ask for it if the human does not volunteer it. + +**Before reading any PR from a batch, the independent adversary leg must have +run** (`AUTONOMY.md` leg 5): `bin/pyauto-brain review --task --witness +"" --adversary`, **in a session using a different model +from the one that wrote the branch**. A self-run adversary leg is an absent leg, +not a weak one, and recording it as run is a false ledger row. If it has not +run, say so rather than reviewing as though it had. + +**`delivered:` is not "green".** A cloud session's green status means it exited +without an infrastructure error — not that the task succeeded. A member counts +as delivered only with a PR that has a non-empty diff and checks that ran. A +member that ended green with no PR is reported **not delivered**, loudly, at the +top. + +## Never + +- Dispatch without an explicit go from the human in this conversation. +- Acknowledge a Heart YELLOW or RED on their behalf, or reuse a previous + shift's reason set. +- Add a member the planner rejected without saying which rejection you are + overruling and why. +- Present the proposal as a schedule. The schedule may carry the timing; it + never carries the authority.