brigade · git:20261016.c2c17cf · 2026-10-16 · sha256 21e222c2734d4257

brigade git:20261016.c2c17cfA

Immutable. This exact content never changes and is served at /api/v1/blob/21e222c2734d4257.

---
name: brigade
description: "Give a project or a focus area its own standing head chef. It is one long-lived T3 thread that holds a purpose, takes incoming work, delegates it to pstack playbooks, reviews every result against the purpose with another model family, and reports what landed. Use for 'brigade', 'open a restaurant', 'head chef for X', 'chief of staff for this project', 'a standing coordinator for this goal', or running one of those threads. For an executive admin over the coordinators on one repository, use brigade-admin. For one finite program with a done predicate, use poteto-mode's Orchestrate playbook."
---

# Brigade

Brigade copies the setup Lauren Tan runs with Cursor Projects. The user is the executive chef. Each restaurant is one project, or one focus area inside a project. Each restaurant has one head chef: a pinned top-level thread that never writes code. It delegates, reviews, and drives the work forward toward the restaurant's purpose. The user moves between restaurants and reviews what landed.

Every mechanism here comes from pstack. Delegation, roles, isolation, scheduling, and history follow [the runtime](../pstack-runtime/SKILL.md). Workers run poteto-mode playbooks.

A thread that is an executive admin, or that is asked to open, recover, or retire one, starts from the [brigade-admin skill](../brigade-admin/SKILL.md).

## Terms

| Term | Meaning |
| --- | --- |
| Restaurant | One project or focus area, with a store directory. A project may hold several. |
| Head chef | The restaurant's coordinator thread. |
| Menu | `menu.md`: purpose, what good looks like, what is off the menu, budget. |
| House rules | `house-rules.md`: numbered standing orders pasted into every brief. |
| Ticket | One incoming request on the rail (`rail.tsv`). |
| Dish | Related tickets grouped into one unit of work for one station (`dishes.tsv`). |
| Station | A worker running one poteto-mode playbook in its own worktree thread. |
| Pass | The review of a dish against its tickets and the menu (`pass.tsv`). |
| 86 | A decision only the user can make (`86.tsv`). |

These words name files, commands, and steps. They never appear in speech. Replies, reports, briefs, commits, and PRs use plain engineering prose: "merged", "blocked", "needs your decision". Never "plated", "86'd", "heard", or "chef".

## Operating stance

- Run to the next real blocker. "Should I continue" is never a question. Reply as Run a service step 9 says for this restaurant's reporting level.
- A real decision is a product or preference call no evidence settles, an irreversible action the menu does not authorize, or a contradiction between the menu and reality. Park it with `86 add`, give a default, route other work around it, and keep going. An item decision (`--dish`) uses as its default the option that keeps the item parked, and only another listed option closes it.
- Raise a decision once, in the reply where you park it. After that it appears only in reports, where `close` lists every open decision. Never repeat it as "still open" in other replies.
- Delete only what this restaurant created: its dish branches, its worktrees, and the queue's `landing/e<n>` branches, including a leftover `landing/q<n>`. Ask before deleting any other branch, even one fully merged.
- Never write code yourself. Grouping tickets, claiming leases, writing briefs, reviewing evidence, and submitting to the landing queue are your work. Code changes and conflict fixes are dishes.
- Work lands only through the repository's landing queue, per the [landing skill](../landing/SKILL.md). Several restaurants can share one repository. The queue and its leases keep them off each other.
- `handoff.md` is `<restaurant dir>/handoff.md`. Rewrite handoff.md at a quiet point before compaction. After any compaction, read handoff.md, house-rules.md, and the memory index before acting.

## The script

`<skills>/brigade/scripts/brigade.py`, where `<skills>` is the directory holding this skill. Every command but `open` and `walk` takes `--at <restaurant dir>` or `BRIGADE_DIR`. It prints one line or a short block, in plain prose.

```bash
B="python3 <skills>/brigade/scripts/brigade.py --at <restaurant dir> --owner <thread>@<generation>"   # the token from status
$B next [--failure fixable|stuck] [--unsent <kind>] [report-back <dish> | review <dish> --verdict pass|send-back|blocked|pass-with-edits | checks <dish> --result pass|fail | merge <dish> | liveness | intake | morning | evening | user [--question] | admin <request>]   # steps this wake owes and reply
$B status                                    # thread <id> or thread not recorded, the counts, reports to <thread> when set, and owner <thread>@<generation> when a generation is recorded
$B set --thread <id> [--replace] --schedule <name>=<id>
$B set --reporting every-turn|milestones|digest
$B set --schedule <name>=                    # drops that name from restaurant.json
$B set --intake github,<feed>                # the intake sources this restaurant owns
$B set --workers <n>                         # dishes in progress or in review at once
$B set --autofire off|urgent|normal|low      # the lowest ticket priority startable lists as startable
$B set --reports-to <thread>                 # the executive admin this restaurant reports through
$B set --mode light|full                     # this restaurant's mode from the next brief
$B set --build-command "<command>" --check-command "<command>"   # the two commands edits verify runs
$B set --cap KIND=N[,KIND=N]                 # the cap on items of that kind holding a worker slot
$B set --review KIND=full|light[,KIND=MODE]   # the default mode for a new item of that kind
$B ticket add --summary "<request>" --kind feature|fix|polish|upkeep|study [--goal G<n>] --source user|github|<feed> [--ref <ref>] [--request A<n>] [--again] [--priority urgent|normal|low] [--paths src/a,src/b] [--decision]   # prints T<n>. --request refuses a second ticket for that request
$B ticket add --from-report reports/D2.md [--dry-run]   # one waiting ticket per follow-up in that report. It prints a `not filed` line for prose it does not take as a follow-up, and a `skipped` line for follow-up text already on the rail
$B ticket list [--state waiting|assigned|moved|done|dropped]
$B ticket set T3 [--state dropped] [--priority urgent|normal|low] [--paths src/a,src/b] [--decision | --no-decision]   # at least one flag
$B ticket set T3 --kind fix [--goal G1 | --no-goal]   # changes a waiting ticket
$B ticket move T3 --to <sibling>             # hands a waiting ticket to a sibling. Prints the thread to tell
$B ticket take                               # files every ticket a sibling handed to this restaurant
$B ticket paths [--dry-run]                  # on each waiting ticket that records no paths, records the tracked paths its summary quotes in backticks
$B startable                                 # the workers line, then a count line and each waiting ticket in start order with why it can or cannot start now, or no waiting tickets. It starts nothing
$B inbox take                                # ticket take, then prints each request from the executive admin as A<n>: <line>
$B inbox done A<n>                           # records the request as acted on and deletes its file
$B goal add --name "<name>" --purpose "<why>" --done "<test>" [--share <n>]   # prints G<n>
$B goal set G1 --state open|paused|done|dropped [--evidence "<one line>"]   # a move to done or dropped needs --evidence
$B goal set G<n> --state paused   # no ticket of that goal starts, not even as a ride-along
$B goal set G<n> --share N   # a ceiling of N worker slots holding that goal's items
$B goal list [--all]   # each open or paused goal, and each done or dropped goal that still has a waiting ticket, an item in flight, or a ticket riding along, with its state, name, counts, purpose, and done test, then the counts of unassigned work
$B fire --tickets T1,T3 --station bug-fix --summary "<outcome>" --paths src/a,src/b [--timebox 60] [--mode full --reason "<one line>"] [--kind <kind>] [--ride-along T3] [--doc-item]   # claims the lease, prints D<n>
$B brief D2 --fields <path>                 # JSON file, or --fields - for stdin. Writes briefs/D2.md
$B brief D2 --goal '...' --acceptance '...' [--acceptance ...] --contract '...' --verify '...' --base main [--context ...]   # same brief. Single-quote every field
$B contract D2                               # prints the contract the last brief of D2 stored
$B watch                                     # a line for every open dish; renews each live lease. A dish that owes its round decision gets <n> send-backs, decision pending
$B hang D1 --provider <provider> --minutes <n> [--attempt <n>]   # one open run after report-back, once per attempt
$B model skip <provider/model> --cause rate-limit|failed   # records that seat as skipped
$B model clear <provider/model>   # records a passing smoke test on that seat and clears its skip
$B thread <dish> --role "panel member" --thread <id> --seat <provider/model>   # records one thread an item used, for a role no other command writes
$B dish D2 --state dropped [--stopped <run id>|idle]   # releases the dish's lease and returns its tickets to waiting
$B dish D2 --state in-progress|in-review|queued|merged [--thread <id>] [--task <id>] [--pr <url>] [--sha <head>] [--timebox <m>] [--reported] [--lease <id>] [--paths <paths>] [--branch <name>]   # --thread writes the open worker row of threads.tsv for the current attempt
$B dish D2 --mode full --reason "<one line>"   # records the item's move to full once
$B dish D1 --worker-ended "<reason>"   # records that this attempt's worker ended or failed and wrote no report
$B pass record D2 --sha <head> --verdict pass|send-back|blocked|pass-with-edits --author <provider/model> --verifier <provider/model> [--pr <url>] [--note "..."] [--same-family] [--report <file>] [--edits <file>] [--reviewer-thread <id>] [--member | --late]   # --reviewer-thread writes the reviewer row of threads.tsv for this attempt. Once the dish owes its round decision, each send-back it counts ends its line with <n> send-backs, decision pending
$B pass check D2 --sha <head> [--json]       # exits 1 unless that SHA passed. --json prints verdict, author, verifier, note, and crossFamily
$B edits verify D2 --from <reviewed sha> --to <head>   # exits 1 when a compared path differs or the build or check command fails
$B 86 add --question "..." --options "a, b" --default "a" [--dish D2]   # prints Q<n>
$B 86 add --dish D2 --round-budget           # the decision D2 owes at three send-backs. prints Q<n>
$B 86 answer Q1 --answer "..." ; $B 86 list
$B close [--dry-run | --to-file]             # report of what changed since the last one. --to-file prints only the written file's path
python3 <skills>/brigade/scripts/brigade.py walk [--repo <project root>]
L="python3 <skills>/landing/scripts/land.py --repo <project root>"   # leases and the landing queue
```

Read [script.md](script.md) when a `$B` command refuses, prints a line this skill does not name, or needs a flag the block above does not show. `$B <command> --help` prints every flag.

Pass brief fields as a JSON file with `--fields <path>`, or from stdin with `--fields -`. Put every flag value in single quotes so the shell does not expand it. Before you write brief fields, read [Brief fields](script.md#brief-fields).

Each intake source has one owner. `set --intake`, and `open --intake` when it creates a restaurant, refuse a source a sibling already lists, with `brigade: <sibling> already owns intake from <source>; move tickets to it instead`. On an existing one it changes nothing. `set --intake` refuses to drop a source while a `waiting` or `assigned` ticket came from it. `ticket add --ref` refuses a ref that is already live here or in a sibling, with `brigade: <ref> is already T1 (waiting); nothing added`. The ref stays unchanged through every `ticket move` and `ticket take`. Before you file or update a ticket, change intake, or fix a malformed table line, read [Intake and refs](script.md#intake-and-refs).

The cap counts dishes in progress or in review. `fire` refuses before it claims a lease when the count is already there. A refused `fire` leaves the tickets waiting and logs why. When the cap is full, `dish --state in-progress` or `in-review` refuses when that dish is not already one of those states. Moving between those states, or replacing the worker, does not. `dish --lease` and `dish --paths` record a lease claimed again, and refuse a merged or dropped dish. When `fire` cannot release a lease it claimed and then could not keep, it warns with the lease id and the landing queue's diagnostic. `open` warns when `workers` is at or above the repository cap and a sibling exists. `watch` prints `waiting on L<n> (<holder>)`, `waiting for room in the repository (<n> of <n> changes in flight)`, `waiting for a worker (<running> of <cap> running)`, or `unblocked` with a shell-quoted `fire` command. Run that command as printed. Before you run `open --workers` or `fire` or change a dish's lease, paths, or branch, read [Worker cap](script.md#worker-cap). When `watch` or `ticket list` prints a worker, lease, or repository block, or `walk` prints a blocked count, read that section before acting on the block.

Every ticket has a priority. `urgent` is work that is broken, unsafe, or blocking, such as data loss, a broken install, a red trunk, a privacy or security hole, or an upstream sync. `normal` is wrong or missing behavior, a false statement in docs people follow, or a feature the user asked for. `low` is polish, a refactor, or an optional pointer. Set it at triage with `ticket add --priority`. Change it with `ticket set T<n> --priority` when the user says so or the facts change.

`status` prints `owner <thread>@<generation>`. Every write in a store with a generation needs `--owner <thread>@<generation>`, except `set --thread`, which `--replace` fences. The check runs under the store lock, and the lock is held through the write. A token that does not match exits 1 with `brigade: owner <token> is stale; this store is owned by <thread>@<generation>` and changes nothing. `set --thread --replace` first raises the landing floor for `<restaurant>/` with `land.py owner`, so `land.py` also refuses the replaced thread's `--owner <restaurant>/@<old generation>`. Before you run `set --thread`, read [Owner](script.md#owner).

On a dish that holds a lease and records a worker thread, `dish --state dropped` refuses without `--stopped`, with `brigade: D3 holds L4 and its worker may still be running; wait for its run with t3_thread_wait, then pass --stopped <run id>`. The lease stays active, so no sibling claims its paths early. Before you run `dish --state dropped`, read [Dropping a dish](script.md#dropping-a-dish).

`dish --state queued` and `--state merged` fail unless the dish has a `pass` verdict at its head SHA. `pass record` refuses a verifier from the author's model family unless you pass `--same-family`, which you use only when `orchestrator_capabilities` shows no other runnable family. `--report <file>` refuses a path or file outside `<restaurant dir>/reports/` or a missing or bad review file. The round budget stops another fix round. A dish's round count is its send-backs written after the later of its last passing verdict and its last answered round decision. A dish owes a round decision while that count is three or more and its state is `in-progress`, `in-review`, `sent-back`, or `blocked`. While a dish owes it, `watch` prints `D<n>: <count> send-backs, decision pending` in place of the dish's state or progress line, and `pass record` ends the line of each send-back it counts with `; <count> send-backs, decision pending`. `dish --state in-progress`, `dish --thread` or `--task` with an id the dish does not already record, and a `brief` whose fields parse exit 1 with `brigade: D<n> has <count> send-backs; no fix round until its decision is answered; run 86 add --dish D<n> --round-budget`. `fire` exits 1 on a ticket of that dish with `brigade: T<n> is D<n>'s ticket;` and the same words. The budget refuses nothing else. `$B 86 add --dish <id> --round-budget` writes the decision with the options `known limits`, `redesign`, `drop`, and `keep parked`, and marks the row `round-budget` in `86.tsv`. While another decision holds the dish it exits 1 with `brigade: D<n> is held by Q<n>; answer it, then run 86 add --dish D<n> --round-budget`. Only `known limits`, `redesign`, or `drop` closes it. No other decision's answer restarts the count. `ROUND_BUDGET` in `brigade.py` sets the number. Before you write report instructions for a worker or verifier, run `pass record` or `dish --reported`, or act on a review-report warning from `close`, read [Pass and round budget](script.md#pass-and-round-budget).

Each item runs in full or light mode per [the runtime's Modes section](../pstack-runtime/SKILL.md#modes). When the store changes meanwhile, `brief` resolves again, and after three changes it exits 1 with `brigade: D<n> changed while resolving its mode; run brief again`. `dish --mode full` refuses a queued, merged, or dropped dish. `--mode light` on an item exits 1. Before you run `brief` or pass `--mode` to `open`, `set`, `fire`, or `dish`, read [Mode](script.md#mode).

## Open a restaurant

To open a restaurant, read [opening.md](opening.md#open-a-restaurant) and run its steps in order.

## First service

A head chef's first wake runs [First service](opening.md#first-service) in opening.md, then Run a service.

   - While this restaurant has dishes queued, keep a landing drain schedule per the [landing skill](../landing/SKILL.md#keep-the-queue-moving), and delete it when none are. Name the reporting level in that prompt, and say to follow Run a service step 9. After the queue opens a PR, that section has this thread call `watch_pull_request` and run `land` on each wake. Other restaurants' drains on the same repository are harmless. The queue lock runs one at a time. When you delete that schedule, run `$B set --schedule drain=`.
   - While `$B watch` prints anything other than "no work in progress", and on the first refused `fire`, keep a liveness schedule. `watch` renews every live lease, so this schedule is what keeps a lease from expiring. At `every-turn` and `milestones` use `{"type": "interval", "everyMs": 600000}`, every 10 minutes. At `digest` use `{"type": "interval", "everyMs": 1800000}`, every 30 minutes, because worker report-backs and pull request watches are the primary wakes. The prompt is "Use the brigade skill. You are the head chef for the restaurant at `<restaurant dir>`. Reporting level: `<level>`. Follow Run a service step 9. Run the liveness check." Delete it when `$B watch` prints "no work in progress". When you delete that schedule, run `$B set --schedule liveness=`. After `$B set --reporting` moves the level to or from `digest`, delete the running liveness schedule, create it again at the new interval, and record the new id with `$B set --schedule liveness=<id>`.
   - Record each ID with `$B set --schedule <name>=<id>`. When the landing drain schedule is recreated, record the new id with `$B set --schedule drain=<id>`. Report schedules only in a reply Run a service step 9 already allows. At `digest`, creating, recreating, or deleting a schedule is not a reply occasion. The IDs stay in `restaurant.json`, and `list_scheduled_tasks` shows each cadence and `nextRunAt`. A first service started by opening the restaurant, and a reply to a user's level change, may name the schedules within Digest messages. This overrides the runtime's "Report the returned cadence and `nextRunAt`" for a head chef at `digest`.

## Filing tracker work

Coordinators and the executive admin follow this section before each `ticket add` for a user request or a supplier finding. The tracker is the one AGENTS.md names. Read its open items with the commands AGENTS.md names. Run `gh issue list` only when AGENTS.md names no other tracker. The rail records the work a restaurant runs. It is not the project's tracker.

1. **Match.** A ref the request names is its ref. Otherwise read the open items and find the one item that is the same work as the request, by its summary. Pass that item's ref as `--ref` and create nothing. When more than one item could be the same work, create nothing and add the ticket with no `--ref`. A scope that forbids tracker writes still passes an existing item's ref.
2. **File.** When no item matches, follow AGENTS.md's filing rules. Create an item only when those rules call for one and the user or the house rules allow that write. Pass the ref the tracker prints for it. When the rules or the permission do not allow the write, create nothing and add the ticket with no `--ref`.
3. **Unavailable.** When the tracker cannot be read, report it and fetch nothing in its place. A user request is still filed. Pass the ref it names as `--ref`, and omit `--ref` only when it names none. A supplier finding with no ref adds no ticket.
4. **Refusals.** A refused `ticket add` is not an error to work around. Four of its refusals are about the request. A live ticket here or in a sibling has the ref. A ticket of this restaurant already carries the `--request` id. The source is not `user`, and a sibling lists it or this restaurant's intake does not. The add is from `user` with no `--ref`, and a `waiting` or `assigned` ticket of this restaurant has the same summary. Case, leading and trailing whitespace, and the length of a whitespace run do not count in that comparison. That last refusal prints `brigade: same text as T<n> (<state>); nothing added; pass --again to file a second ticket`. The request is already on the rail, so answer with the ticket the line names. Pass `--again` only when the request is separate work in the same words. `--again` lifts no other refusal. A replay looks the work up again and finds the same ref, including an item the first run created, so its add is refused. The summary check does not cover an add in other words, a summary that only a `done`, `dropped`, or `moved` ticket or a sibling's ticket has, or an add from another source. So read `$B ticket list` before you file a no-ref request again.

## Run a service

Every wake runs this: a user message, a worker's report-back, a verifier's completion, a schedule, or a `watch_pull_request` wake.

0. **Next.** Run `$B next` first. Pass `user` for a user message. Pass `report-back <dish>` for a worker report. Pass `review <dish> --verdict <verdict>` for a verifier completion. Pass `liveness`, `intake`, `morning`, or `evening` for the matching schedule. Leave the wake off for the landing drain schedule and follow [First service](#first-service). Pass `checks <dish> --result pass|fail` when a `watch_pull_request` wake reports failed checks or passed required checks. For other PR-watch events, leave the wake off, read the PR event, and follow [First service](#first-service). Pass `merge <dish>` when land may have landed the dish. Leave the wake off when its cause is unknown. Pass `--failure` for a known failure. Pass `--unsent` for an unsent admin line. Its output names the steps this wake owes and whether it is a reply.

1. **Read.** `menu.md`, `house-rules.md`, `$B status`, `$B 86 list`. Re-read the menu every service. It is the purpose every decision answers to. `$B status` prints `thread <id>` first and `owner <thread>@<generation>` last. When it names another thread, end the turn with no further command. Otherwise set `$B` to `brigade.py --at <restaurant dir> --owner <thread>@<generation>`, and pass `--owner <restaurant>/@<generation>` on every `$L lease claim`, `lease renew`, `lease release`, and `submit`. When `status` prints no owner line and `restaurant.json` records this thread, run `$B set --thread <this thread>` once and read `status` again. A write refused with `is stale` means another thread replaced this one. End the service with no further command.
2. **Take tickets.** Start with `$B inbox take`. It files each ticket a sibling or the executive admin handed to this restaurant, then prints each request from the admin as `A<n>: <line>`. Act on each request per [Reporting to an executive admin](#reporting-to-an-executive-admin), then run `$B inbox done A<n>`. Each user request or supplier finding becomes `$B ticket add`, with `--source user` or the intake name of the source it came from, such as the tracker AGENTS.md names, and with `--kind`, and the `--ref` that [Filing tracker work](#filing-tracker-work) gives it. Fetch only the sources in this restaurant's intake. A ticket that is a sibling's work goes to it with `$B ticket move <id> --to <sibling>`. Then call `t3_thread_send` to the thread it prints, with mode `"auto"`, the line `ticket <sibling>: run ticket take`, and the handoff id as `clientRequestId`. The handoff id is this restaurant's store path, the last two parts of `<restaurant dir>`, then the ticket, such as `app/engine/T6`. Fetch supplier sources only when the house rules name them and this restaurant owns them. Read backlog from the tracker that [Filing tracker work](#filing-tracker-work) names. Read pull requests with `gh pr list` only when the house rules name pull requests and this restaurant owns that source. Read notifications only when the house rules name them and this restaurant owns that source. Drop a ticket that is off the menu with `$B ticket set <id> --state dropped` and say why in the next report. At `digest` a dropped ticket is not a reply occasion.
3. **Group before firing.** Read the waiting tickets together. Several reports of one cause are one dish. Fire a ticket alone only when it is urgent or unrelated to the rest. A ticket that is a whole program with a done predicate runs as one dish whose station is poteto-mode's Orchestrate playbook.
4. **Fire.** Pick the station: the poteto-mode playbook that matches (bug fix, feature, refactoring, perf issue, investigation). Then:
   1. `$B fire --tickets ... --station <playbook> --summary "<outcome>" --timebox <minutes> --paths <files and directories the dish will change> [--branch <name>]`. Pass `--mode full --reason "<one line>"` when the tickets name a lock, a lease, a race, a migration, or history rewriting. `fire` is refused when the first ticket has no kind, no `--kind` is passed, and the station is not `bug-fix`, `perf-issue`, or `investigation`. It claims a landing lease on those paths plus the generated copies and doc pages the build layout maps from them when the project has one, for holder `<restaurant>/<dish>` before it records anything. `fire` refuses when this restaurant's running workers are already at `--workers`. A refused claim names the holder and fires nothing. A refused `fire` leaves the tickets waiting. Fire refuses a lease holding README.md, docs/guide.md, t3/runtime.md, t3/setup.md, or a SKILL.md under t3/added/, t3/overrides/, or skills/ when timebox is over 90 or tickets are more than one, unless --doc-item. On the first refusal, create the liveness schedule from [First service step 3](#first-service) if `restaurant.json` has no `liveness` id. Fold the tickets into the holder's dish when it is this restaurant's, or leave them waiting until that lease is released. Never pass `.` for a dish that touches a few files. Size the timebox to the work, 30 to 90 minutes. The timebox follows [Deadlines](../pstack-runtime/SKILL.md#deadlines).
   2. `$B brief <dish> --fields <path>`. The file is the JSON object [Brief fields](script.md#brief-fields) describes. `--fields -` reads it from stdin. Single-quote every flag value per [The script](#the-script). Read [Brief fields](script.md#brief-fields) before you write brief fields. It assembles the brief from the menu, the tickets, the house rules, and the landing rules, names the dish branch, adds the exclusive-slot rule for measuring stations, and writes `briefs/<dish>.md`. The brief carries the item's `Mode:` lines and `Gate: brigade`. Read its `Mode:` value for steps 4.3 and 6. The report section first tells the worker never to end its turn while a child task it delegated is open, per [the runtime's Delegation section](../pstack-runtime/SKILL.md#delegation). It gives a thread the worker launched the same bounded wait, except a long-lived owner its playbook supervises, which follows [the runtime's Top-level threads section](../pstack-runtime/SKILL.md#top-level-threads). It then tells the worker to call `t3_thread_send` on the coordinator thread after the report file is written. It refuses when a field is missing, and when no coordinator thread is recorded. Run `$B set --thread` first. Fix the field. Never hand-write a brief.
   3. Launch the worker with `t3_thread_launch`: title `<restaurant> <dish>: <summary>`, `workspaceStrategy: {"type": "worktree", "baseRef": "<trunk>", "branch": "<dish branch from the brief>", "startFromOrigin": true}` (local landing mode: `baseRef` `refs/landing/<trunk>` and `startFromOrigin` false), and the brief file's contents as `message`. Resolve the station's seat with `roles.py show --brief-mode <the Mode: value in briefs/<dish>.md>` and no other mode flag, per [the runtime's Roles section](../pstack-runtime/SKILL.md#roles), so an item moved to full gets full seats. Build `modelSelection` from that seat per [the runtime's Top-level threads section](../pstack-runtime/SKILL.md#top-level-threads). Omit `modelSelection` for an `inherit` seat. Confirm the applied options per [the runtime's Delegation section](../pstack-runtime/SKILL.md#delegation) before step 4.4. Step 4.4 records the thread only after the readback matches. On a mismatch, stop the thread per the runtime, record nothing, and park the dish per [Seat mismatch](recovery.md#seat-mismatch).
   When `watch`, `pass record`, or a worker's report prints a line this section does not name, find that line in [recovery.md](recovery.md) and follow its step.
   4. `$B dish <dish> --thread <threadId>` only after the readback in step 4.3 matches.

   **Refill.** The worker cap is a target, not only a ceiling. After every merge, every passed review, every dropped dish, every liveness check, and every intake run, run `$B startable` in the same turn, before ending it. Take the first ticket line that says `startable`. Fire one dish per steps 3 and 4 with that ticket, every ticket printed as `rides with` it, and `--paths` set to the paths on its line. Run `$B startable` again and repeat until no ticket line says `startable` or a `fire` is refused. Fire nothing that prints `below auto-start`, `decision for the owner`, or `held back` unless the user says so. For a ticket printed as `unknown, no paths recorded`, run `$B ticket paths` once, or record its files with `$B ticket set T<n> --paths <comma-separated files and directories>`, then read `$B startable` again.
5. **End the turn** while dishes run. A worker's report-back message wakes the coordinator, which marks the dish reported with `$B dish <id> --reported` and reviews it per step 6. The liveness schedule, every 10 minutes or every 30 at `digest`, stays as the backstop for a worker that hangs or never sends the message.
6. **Review.** A held item gets no verifier and no review, including on a late worker report-back. When a worker is done, read its report. When it says `Contested: <reason>` under its status line, follow **Contested** below instead of the rest of this step. Otherwise read its diff yourself. A worker's "done" is a claim. The timebox follows [Deadlines](../pstack-runtime/SKILL.md#deadlines). The coordinator checks that the report names what remains. An unexplained skip in the report's deviations is a send-back. A skip cited to the timebox is a send-back. A step the brief's `Waived by mode:` line names is not a skip. `t3_thread_read` on the worker thread returns its `worktreePath` and branch. Run `$B dish <id> --state in-review --sha <head>`. Spawn one verifier with `delegate_task`, `mode: "async"`, from the `verifiers` role, resolved with `roles.py show --brief-mode <the item's Mode: value>`, on a model family other than the author's. Its `target` is that seat unchanged. Right after the spawn, confirm its options with `t3_thread_configuration` on the returned `childThreadId` before the verdict counts, per [the runtime's Delegation section](../pstack-runtime/SKILL.md#delegation). On a mismatch, call `task_cancel`, record no verdict, and park the dish and record the user's answer the same way step 4.3 does. Its read-only brief: the tickets, the menu, the worktree path and the diff at that SHA, two questions (does it work on the real surface, and does it serve the menu without scope the tickets did not ask for), and "write your findings to `<restaurant dir>/reports/<dish>-review-<k>.md`". When the brief says `Mode: light`, write the verifier's brief per [the runtime's Gate review](../pstack-runtime/SKILL.md#gate-review) step 2, with the comment rules, the gate contract, the chosen design, and the decision trail when they apply. Then add this step's tickets, menu, and two questions below the contract. The contract forbids file edits, so write the report the verifier returns to `<restaurant dir>/reports/<dish>-review-<k>.md` yourself. In both modes, include [verdict-protocol.md](verdict-protocol.md) in the verifier brief for the worth-a-fix-round test, the `Rare:` mark, and the `## Edits` shape. Copy the `scratchDir` value from `restaurant.json` into the verifier brief as the `mktemp -d -p` parent, and say so in the brief when none is set. In both modes, the verifier's brief also carries the output of `$B contract <dish>`, unchanged, under the heading `Item contract`. Below it the brief says "A bullet under `changes/` fails this review only when it states something false. A true bullet that omits a condition is a note." The brief also says "Never change git configuration, and never export GIT_DIR or GIT_WORK_TREE. For a scratch copy, run git worktree add --detach <a new directory outside the checkout> <sha>, or run git clone <the worktree path> <a new directory> and git checkout <sha> in the clone." For each new or changed test, ask the reviewer which change to the code makes that test fail and nothing else fail. A test with no answer is a follow-up unless it hides a defect. Record every round, pass or fail, with `$B pass record` at the reviewed SHA and `--report <that file>`.

   **Contested.** When a worker reports `Contested: <reason>` under its status line, do not mark the dish in review and spawn no verifier. Follow [Contested](recovery.md#contested).
   When `watch`, `pass record`, or a worker's report prints a line this section does not name, find that line in [recovery.md](recovery.md) and follow its step.
7. **Act on the verdict.** A held item gets no send-back worker and no bounce worker.
   - `pass`: first run `$B ticket add --from-report reports/<dish>.md`. It files follow-ups as waiting tickets and skips text already on the rail. It prints `not filed` for a list lead-in. It prints `not filed` for prose after a section's last list item. It prints `not filed` for text after the word on a follow-ups heading line. It prints `not filed` for a deeper heading that does not start with follow-ups, with that heading's text when it has any. It prints `not filed` for a block whose whole text is `None`, `None required`, `None needed`, `Nothing`, `Nothing needed`, `N/A`, `Not applicable`, or `No follow-ups`, in any letter case, with or without list markers, a final period, and `*`, `_`, or backtick marks around it. Read each `not filed` line and file each real follow-up with `$B ticket add --summary "..." --kind <kind>`. Drop a ticket that is not worth an item with `$B ticket set <id> --state dropped`, or fire it with related tickets as one dish per step 3. When the dish depends on another coordinator's item that has not landed and `$B status` prints `reports to <thread>`, never hold it outside the queue. Follow [Contests](admin-reporting.md#contests) before you submit. Then submit as below. Write the PR title and body (what changed, the measured effect, how it was verified) to `<restaurant dir>/prs/<dish>.md`, then `$L submit --holder <restaurant>/<dish> --branch <b> --sha <head> --lease L<n> --reviewer <provider/model> --title "..." --body-file <restaurant dir>/prs/<dish>.md`, then `$B dish <id> --state queued`, then `$L land`. When it lands, `$B dish <id> --state merged`. In `merge` and `human` mode it opens a PR first. Record it with `$B dish <id> --pr <url>`, link it with `link_pull_request`, and call `watch_pull_request` on it per [Pull request watching](../pstack-runtime/SKILL.md#pull-request-watching). This head chef thread owns the PR. On each wake, run `$L land`. Keep the watch while the dish is queued or awaiting merge. A reply, or a wake with no reply, keeps the watch. Call `unwatch_pull_request` only when this thread stops driving that PR. Driving stops when the dish is dropped, when its PR closes, when the queue bounces it and leaves the PR open, or when the restaurant closes. If this thread is settled, call `t3_thread_organize` with `action: "unsettle"` (no `threadId`, acting on the caller on purpose) before the next `watch_pull_request`. This thread is pinned, so a merge does not auto-settle it. Mark the dish merged when a later `land` reports it landed.
   - Bounced by the queue: the lease is active again. Call `unwatch_pull_request` on the PR the bounce left open. Finish with the old worker per [Git and PR housekeeping](#git-and-pr-housekeeping). Then run `$B dish <id> --state in-progress`, because `brief` refuses a queued dish. That command clears the recorded worker thread. Rerun `$B brief` with `--context` naming the bounce reason and current trunk. Launch a fresh worker per steps 4.3 and 4.4, unless the item is held. A conflict or a changed rebase needs a new review.
   - When `pass record` or `watch` prints `<n> send-backs, decision pending`, stop patching. Launch no fix worker. Follow [Decision pending](recovery.md#decision-pending) in place of the `send-back` bullet below.
   - `pass with edits`, when the review report says `Verdict: pass with edits`, do not record a `pass-with-edits` verdict with `--report`. Follow [Pass with edits](recovery.md#pass-with-edits) before recording this round at the reviewed SHA.
   - `send-back`: finish with the old worker per [Git and PR housekeeping](#git-and-pr-housekeeping). Then `$B dish <id> --state in-progress`, which clears the recorded worker thread. Rerun `$B brief` with `--base <the old branch head>`. It adds the verifier's findings file and the `Attempt: fix` lines, per [the runtime's Modes section](../pstack-runtime/SKILL.md#modes). Every send-back launches a fresh worker per steps 4.3 and 4.4, on a new branch from the old branch's head, however small the fix, unless the item is held. Never call `t3_thread_send` on the old worker.
   - Drop a dish in three steps. A requested interrupt is not a stop. `t3_thread_interrupt` can return `status: "interrupt_requested"` while the worker's run goes on.
     1. Call `t3_thread_interrupt` on its worker thread.
     2. Call `t3_thread_wait` on the run id it returned, or on the thread when it returned none. When the wait returns `timedOut: true`, leave the dish in its state. `watch` keeps its lease renewing. Wait again on the next service.
     3. When the wait reports a terminal state, run `$B dish <id> --state dropped --stopped <run id>`, or `--stopped idle` when the wait reported an idle thread. That releases its lease.
   - After a dish merges or is dropped, clean up per [Git and PR housekeeping](#git-and-pr-housekeeping). A send-back or a bounce follows that same finish above, and does not enter in progress while the old worker's run is still open or its child work is still pending. After a send-back, delete the old branch per that section once the fresh worker is launched.
   - `blocked`: `86 add` if only the user can unblock it. Otherwise fix the environment and run the pass again.
   - Usage limit: when a provider in the `verifiers` role or a station's role hits its usage limit, launch no replacement before following [Usage limit](recovery.md#usage-limit). For a worker, run steps 1 and 2 of the three drop steps in step 7 without step 3 and wait for a terminal state before any replacement. Do not change the mode on your own.
   When `watch`, `pass record`, or a worker's report prints a line this section does not name, find that line in [recovery.md](recovery.md) and follow its step.
8. **Fix the recipe.** When two dishes repeat the same mistake, fire a dish that runs the **correct** skill to make it impossible (lint, type, test, or skill). Run the **reflect** skill over this restaurant's threads once a week. Skip it while `roles.py mode --cwd <project root>`, with `--coordinator-mode` set to the `restaurant.json` mode when one is recorded, prints `Mode: light`, per [the runtime's Modes section](../pstack-runtime/SKILL.md#modes).
9. **Report.** When `$B status` prints `reports to <thread>`, this restaurant reports through the executive admin, and this paragraph replaces the rest of this step, levels included. Follow [admin-reporting.md](admin-reporting.md#step-9) in place of the rest of this step. Without a `reports to` line, read `reporting` from `restaurant.json`. A missing field means `milestones`. Send the scheduled evening report at every level. The 09:00 morning service is not a report. A batch has drained when `$B status` omits `in progress`, `in review`, `passed review`, and `waiting to land`. Status omits a count of zero, so a missing label is a count of zero. `waiting to land` is work queued to land, including a pull request that awaits merge. Send the drain summary on the wake that first finds the batch drained. A later wake that still sees the batch drained does not send that summary again. A service the user started is a turn begun by a user message. A worker report, a verifier completion, a schedule, or a pull-request wake is not a service the user started. A message from the user gets at least a one-line acknowledgment at every level. A direct question gets an answer. Each level below adds the replies it names. It does not drop the evening report, the user message, or the direct question.
   - `every-turn`. Send a short reply after every wake. Run `$B close` on the scheduled evening report, a reply that raises a decision for the user, the end of a service the user started, and closing the restaurant.
   - `milestones`. Reply when work merges, when a review sends work back or blocks it, when a decision needs the user, when something fails or the queue pauses, or when the user sends a message. A routine wake ends with no reply, or with a single line when the host requires text. A liveness check with nothing new, a liveness check while a review is pending, a review starting, and a worker launching are routine wakes. Run `$B close` on the scheduled evening report, a reply that raises a decision for the user, the end of a service the user started, and closing the restaurant.
   - `digest`. Reply only on these five wakes:
     1. A decision the user must make. A blocked verdict that needs the user is a decision.
     2. A failure, or a paused queue, that this thread cannot fix itself. A send-back is not a failure. A queue bounce this thread hands to a fresh worker is not a failure.
     3. One summary when a batch drains.
     4. The scheduled evening report.
     5. A message from the user.
     Every other wake ends the turn with no reply text at all. Those wakes include a worker's report-back, a verifier's completion, a send-back, a queue bounce, a worker launching or being replaced, a timebox raised, a review starting, a merge that does not drain the batch, a `watch_pull_request` wake, a landing drain run that neither drains the batch nor pauses the queue, a liveness check, intake with nothing new or only dropped tickets, a fix dish fired by step 8 or the liveness check, logging a hang for a run left open after its report-back, and creating, recreating, or deleting a schedule. A status line is still a reply. Do not send one on those wakes, even a single line. Every digest reply runs `$B close --to-file` once, including a failure reply and closing the restaurant. Write each reply per Digest messages below.
   At `milestones` and `digest`, a delegated child's question is not a reply occasion by itself. Answer it with `t3_pending_request_respond` only from facts and decisions the user already gave, per [the runtime's Pending requests section](../pstack-runtime/SKILL.md#pending-requests). When the question is a real decision, per [Operating stance](#operating-stance), park it with `86 add`, and reply as this level replies to a decision. The `every-turn` level sends a short reply after every wake, so a question wake gets that reply there.
   On T3 Code 0.0.46-nightly.20261014.3132 or later, the native Claude adapter shows a non-empty thinking block from Claude 5.1 or later as reply text when it immediately precedes a tool call and directly follows another non-empty thinking block in the same message. A lone thinking block stays reasoning. On a wake that sends no reply, write no progress update between tool calls. Earlier builds and older thread history follow the version bounds in [History notes](../pstack-runtime/host.md#history-notes), the section [History](../pstack-runtime/SKILL.md#history) points to. Keep the no-reply rule and do not write an extra status to explain those paragraphs.
   Run `$B close` only on the replies named for that level above, including closing the restaurant. At `digest` that command is `$B close --to-file`. When one wake qualifies for more than one of those replies, send one reply and run `$B close` once. Close runs once per reply. On a reply that runs `$B close`, answer a direct question first. That answer sits outside the three-sentence cap. At `every-turn` and `milestones`, keep the rest to at most three sentences on what the changes mean for the menu, then the `close` output verbatim. It lists each ticket and dish once, under its latest state since the last report, with PR links. Write no other report file. At those two levels every other reply is plain and does not run `$B close`.

### Digest messages

At `digest`, write every reply for a person who has not followed the work. Use a few plain sentences: what got done and what it means for the menu, what is next, and anything the user must decide with its default. Describe each change by what it does for the user, not by how it was built.

- Leave out dish, ticket, and decision IDs (`D<n>`, `T<n>`, `Q<n>`), SHAs, file paths, branch names, review-round counts, verdicts, and tool or command names.
- Merged pull requests may follow as a short list, one line each, a plain title linked to its PR URL.
- `$B close --to-file` writes the full report under `<restaurant dir>/closeouts/` and prints its path. End the message with one line that names that path, such as "Full report: <path>". That line is the only path in the message. Never paste the `close` output.
- Name the mode only in the first reply after `set --mode` changes it.
- Put commits, IDs, and other engineering detail in the store, not the message. A paused queue's two commits, which the [landing skill](../landing/SKILL.md#when-the-queue-pauses) asks for, go in the `$B 86 add --question` text, and the full report carries them.

A drain summary reads like this:

> Startup is about twice as fast, and the settings page no longer freezes when it opens. Both changes are merged. Next I start on the slow search results you reported this morning. Nothing needs your decision.
>
> - [Faster app startup](https://github.com/acme/app/pull/41)
> - [Fix the settings page freeze](https://github.com/acme/app/pull/42)
>
> Full report: ~/.local/state/pstack-t3/brigade/app/perf/closeouts/2026-10-06T230012.481207.md

## Git and PR housekeeping

The head chef owns every git and PR chore its work creates. In `merge` and `push` mode the user has no step. In `human` mode the user merges each PR. In `local` mode the user merges `refs/landing/<trunk>` into a branch.

- Write each PR's title and body through `submit`, and link every PR with `link_pull_request`.
- Keep the landing drain schedule while anything is queued or awaiting merge, per the [landing skill](../landing/SKILL.md#keep-the-queue-moving). After the queue opens a PR, also watch it as that section says. Keep that watch across reports while the entry is queued or awaiting merge. When you delete the schedule, run `$B set --schedule drain=`. Call `unwatch_pull_request` only when this thread stops driving that PR.
- Finish with the old worker when a dish merges, is dropped, is sent back, bounces, or is replaced after a contested report. The old worker is the thread the dish row names before any `$B dish <id> --thread` records a replacement. Name that thread id in every call below, so the replacement's open run is never touched. Read it with `t3_thread_read`. If its run is still open after the report-back, call `t3_thread_interrupt`, then `$B hang <id> --provider <provider> --minutes <n>` with the provider and the minutes that read showed. After `t3_thread_interrupt`, call `t3_thread_wait` on the returned run id, or on the thread when it returned none, and read the worker's activity again. Archive with `t3_thread_organize`, `action: "archive"`, and that `threadId` only after the worker's run is terminal and its child work is no longer pending. When the wait times out or child work remains, keep the thread and finish cleanup on a later service. A worker that an earlier attempt launched counts too. Check each attempt's thread, and for a run a replaced attempt left open, add `--attempt <n>`, counting attempts from 1 in launch order. If the run has already closed, archive it only when its child work is no longer pending. When that child work remains, keep the thread and finish cleanup on a later service. On a send-back or a bounce, finish before `$B dish <id> --state in-progress`. Entering in progress starts a new attempt, and `hang` then refuses with `brigade: no report-back on this attempt`. At `digest` reading, interrupting, logging a hang, and archiving send no reply of their own. A merge that drains the batch still sends the drain summary.
- After a dish merges, is dropped, is sent back, or is replaced after a contested report, remove the old worker's worktree, delete its branch locally and on the remote, and delete the queue's `landing/e<n>` branch, including a leftover `landing/q<n>`, once its PR merged or closed. After a send-back or a contested replacement, delete the old branch only once the fresh worker is launched, because its branch starts from the old head.
- After a landing, when the user's checkout at the project root is clean and on trunk, fast-forward it with `git merge --ff-only`. Otherwise leave it alone.
- A bounce or a conflict is a dish for a fresh worker, never a manual rebase.
- Never force-push trunk, rewrite published history, change branch protection, or delete a branch this restaurant did not create.

## Liveness check

Run on the liveness schedule, and at the start of any service while work is in progress.

1. `$B watch`. It prints one line per dish in progress, one line for each other dish not `merged` or `dropped`, one line per ticket moved to a sibling that has not filed it yet, and `handed to you: <n>; run ticket take` while siblings' handoffs wait in this restaurant's inbox. On `handed to you`, run `$B ticket take`. On `not delivered`, run the `ticket move` command the line prints, then message the sibling per Run a service step 2. `waiting for ticket take` needs nothing until the sibling's next service. For a waiting ticket whose latest log row is `blocked`, it prints `waiting for a worker (<running> of <cap> running)`, `waiting on L<n> (<holder>)`, or `waiting for room in the repository (<n> of <n> changes in flight)`, the first that holds now. An `unblocked` line names a shell-quoted `fire` command. Run it as printed. That is the `fire` in steps 3 and 4 of Run a service for those tickets. When `$B status` prints `reports to <thread>` and a ticket's first `blocked` row in `log.tsv` is more than an hour old, read [Liveness](admin-reporting.md#liveness) before you send the `blocked` line.
   `watch` renews the lease of every dish in progress, in review, passed, sent back, or parked, and prints nothing for a live one. It updates `lastActivityAt` after a pass that renewed every live lease, so `walk` marks a restaurant whose leases stopped renewing. A submitted lease is the queue's. Act on these lines.
   - `D3: lease L4 expired; stop its worker, then run lease renew L4`. Run steps 1 and 2 of the three drop steps in step 7 without step 3 and wait for a terminal state before any renew. Follow [Lease lines](recovery.md#lease-lines).
   - `D3: lease L4 was released; claim again before submitting`. Claim the paths and record the lease before any submit. Follow [Lease lines](recovery.md#lease-lines).
   - `D3: could not renew L4: <error>`. Fix the landing store cause. Follow [Lease lines](recovery.md#lease-lines).
   - `D2: in review`, `D3: passed, not submitted`, `D4: parked`, and `D5: sent back` keep the liveness schedule alive. Act on them per Run a service steps 6 and 7.
   - `D1: 3 send-backs, decision pending`. Launch no fix worker. Follow the decision-pending bullet in Run a service step 7.
   - `D1: open decision Q1: <question>; launch no worker or verifier until 86 answer Q1`. Launch nothing and spawn nothing. Read no worker thread and send it no nudge. Skip Liveness steps 2 to 5 for that item. Act on a lease line printed under it. After `$B 86 answer` prints `Q<n> answered`, the ordinary line returns.
   - `D1: in progress with no worker thread; launch a fresh worker`. Launch a fresh worker per steps 4.3 and 4.4. Never call `t3_thread_send` on an earlier attempt's thread.
   - `D1: worker ended with no report; the recorded reason is <text>`. Never call `t3_thread_send` on the dead thread. Run the four steps the line prints, in order. Follow [Worker ended](recovery.md#worker-ended).
   - `skipped <provider/model> (<cause>); run model clear <provider/model> after a smoke test passes`. Launch no worker, verifier, or code delegate on that seat while the line prints. Follow [Skipped seat](recovery.md#skipped-seat).
   - For a passed or queued dish, `watch` reads `land.py status --holder <restaurant>/<dish> --sha <dish sha>` and takes the highest entry at exactly the dish's SHA. `D1: landed as E1 (<commit>); mark it merged`: run `$B dish D1 --state merged`. `D2: E3 awaiting merge <pr url>; watch that PR`: call `watch_pull_request` on that PR, because this thread owns it even when a sibling's `land` opened it. `D4: E4 bounced: <reason>`: follow the bounce step in Run a service step 7. `D5: E6 already submitted; mark it queued`: run `$B dish D5 --state queued`. That recovers a crash between `submit` and `dish --state queued`. `D6: E7 queued` needs nothing until the queue moves.
   When `watch`, `pass record`, or a worker's report prints a line this section does not name, find that line in [recovery.md](recovery.md) and follow its step.
2. "report written, no report-back" is a defect. Read the worker thread and find why the message never arrived. Follow [Report written, no report-back](recovery.md#report-written-no-report-back).
3. A "report written" line that does not say "no report-back", and a line `D<n>: reported Nm ago, not in review; read the thread (thread <id>)`, mean the worker reported back and its review has not started. Read the worker thread with `t3_thread_read`. If its run is still open, call `t3_thread_interrupt`, then `$B hang <id> --provider <provider> --minutes <n>` with the provider and the minutes that read showed. Then review per Run a service step 6. At `digest` this is a routine wake with no reply.
4. "over its timebox": `t3_thread_read` the thread with `view: "activity"` and `afterPosition`. When it made progress in the last 10 minutes, raise the timebox once with `$B dish <id> --timebox <m>`. Otherwise run steps 1 and 2 of the three drop steps in step 7 without step 3, then launch a fresh worker per steps 4.3 and 4.4 with a smaller scope, or park the dish with `86 add` when only the user can unblock it. Step 4.4 records that thread, and recording it starts the attempt while the dish stays in progress. The previous report and report-back mark belong to the worker you replaced. `$B watch` compares the report file to this new start.
5. `D<n>: running Nm of Tm (thread <id>)`: `t3_thread_read` the worker thread. When `activeRunId` is null and the latest run in `recentRuns` completed more than 10 minutes ago, the worker is idle with its timebox still open and no report for the current attempt. The `running` line already means that, even when an earlier attempt's report file remains, because `watch` compares the report to this attempt's start. `brigade.py` reads only the store, the clock, and the landing queue, so this check needs the thread read. Send the worker one nudge with `t3_thread_send`, mode `"auto"`, `clientRequestId` `nudge-<dish>-<that run id>`, and the line `Your thread has been idle since <completedAt> with no report. Check each open child with task_status, handle a stalled one per the runtime's Delegation step 5, then finish the brief.` A worker idle again after that nudge goes to step 4 as if over its timebox. Otherwise the line means nothing new. Reply per Run a service step 9. When `$B status` prints `reports to <thread>`, follow [Liveness](admin-reporting.md#liveness) and end the turn with no assistant text. Otherwise, at `milestones` this is a routine wake, so end with no reply, or with a single line when the host requires text. At `digest`, end the turn with no reply text at all. At `every-turn`, send a short reply. A dish in `in-review` or `passed` is not this line.
6. When `$B watch` prints "no work in progress", delete the liveness schedule with `delete_scheduled_task`, then run `$B set --schedule liveness=`. Delete it only on that line. A blocked ticket is not that line, so the schedule stays while one is waiting. Do not treat that line as a drained batch. A batch has drained when step 9 says it has. The drain summary is sent on the wake that first finds the batch drained. A review still pending means the batch has not drained. Do not send the drain summary while a review is pending. Reply per step 9.

## Agent activity

When the user asks what the agents are doing, or asks for activity or status as a picture, follow [Agent activity](views.md#agent-activity) in views.md.

## Executive chef's view

`$B status` prints the reporting level, the landing mode as `lands by <mode>` or `no landing contract`, then the counts. A `restaurant.json` with no `reporting` field reads as `milestones`. `$B status` prints `mode <m>` when `restaurant.json` records one. Before you run `brigade.py walk` to show the owner view, read [Executive chef's view](views.md#executive-chefs-view) in views.md. That view lives in views.md.

## Close a restaurant

To close a restaurant, follow [Close a restaurant](opening.md#close-a-restaurant) in opening.md.

## Reporting to an executive admin

While `$B status` prints `reports to <thread>`, read [admin-reporting.md](admin-reporting.md) before you act on an admin request or send that thread anything, and follow it in place of step 9's levels. Also read it when `$B inbox take` prints an admin request, even without a `reports to` line. An executive admin following a link here reads [admin-reporting.md](admin-reporting.md) for the coordinator's event lines, request formats, and ruling responses. What the admin does, and its limits, are in the [brigade-admin skill](../brigade-admin/SKILL.md). Work a `from-user` request asks for becomes `$B ticket add --summary "..." --kind <kind> --request A<n>`, which refuses a second ticket for that id.