One Gate, Wrapped Around Every Brain
Pippa can think with seven different brains: Claude, Codex, Kimi, Grok, GLM, Gemini and Ollama. Each has its own chat router in the engine, written at different times for different SDKs. If the Chief's admission rules lived inside those handlers, there would be seven copies, and the eighth brain would arrive without one. So the rules live in a FastAPI route class, ChiefChatRoute, and every one of the seven routers is built with APIRouter(route_class=ChiefChatRoute). A test globs the seven chat route files, asserts there are exactly seven, and fails if any lacks the route class. A new brain inherits the gate by construction, not by someone remembering.
The wrapper is deliberately narrow. It touches only POST routes whose path ends in /chat. A body that does not parse, or fails the route's own validation, goes straight to the original handler, so the client gets that route's ordinary error. And a turn that is not bound for the Chief at all (no master_chief flag, not the Chief's row, not a legacy app turn) runs exactly as it did before Master Chief existed.
Refuse Before Anything Is Read
Every refusal happens before the brain reads history, picks a parent message, or selects a provider session. The order is the point. Whatever the handler touched before the gate is something the gate can no longer protect: a private turn's words would already sit in a replay, a persona's prompt would already have shaped a reply, a parent chosen early would already have forked the room. The checks, in the order the route runs them:
| What arrives | What it gets |
|---|---|
A private conversation, a private flag, or an incognito host | 409 "Private turns cannot enter Master Chief" |
| An internal fan-out call carrying another viewer (the Council's self-calls) | 409 "Worker turns cannot enter Master Chief" |
A turn marked automated | 409 "Automated turns cannot enter Master Chief" |
| A conversation that belongs to another soul or another person | 409 "Cannot move another soul or person's conversation" |
Another soul_id, or a system_prompt_override (a Council persona run on the base model) | 409 "Master Chief is not a persona or worker session" |
| An origin thread that is private | 409 "Private context cannot enter Master Chief" |
| An origin thread owned by someone else or another soul | 404 "origin not found" |
Under all of these sits the viewer check in resolve(): when the person at the screen is not Dad, the Chief answers 403 "Master Chief belongs to Dad", with a named variant for Quiet Mode that Track 6 covers. The cold review of 2026-10-08 checked this whole set (non-Dad, private, incognito, worker and other-soul turns all rejected before admission) and listed it as sound.
Why a Job Is Never a Turn
The set was sound, and a hole still ran every morning. The rejection that matters most in practice is the one keyed on automated, and it was not there at first. Tidings, the family's news engine, sends a scheduled daily brief through the Ask door with source: tidings. The legacy-app check saw a Dad-owned Pippa thread bound to Tidings and a matching source, took the job for Dad speaking from Tidings, and ran it inside the Chief: the job prompt landed as a user row in Dad's room, followed by a 26,000-token reply. That contradicted a ruling Dad had already made (coop #345): a scheduled job reaches the Chief only as a one-line report.
The fix (7252f738, 2026-10-08) makes the job say what it is. A payload with automated: true is a sibling's own job: it is never an app turn, it runs in the conversation it names, it leaves no doorway, and if it is addressed to the Chief it gets a 409. Its outcome may still reach Dad, as a report. Track 6 is about exactly that path.
Nothing Foreign Is Projected Into Dad's Room
The Chief is Pippa herself with Dad. Not a persona, not a worker, not someone else's conversation viewed through Dad's screen. So two things can never be projected in, whatever path they take: other people's and other souls' contexts, and anything private or incognito. A private origin is refused even when the turn itself is clean, because the origin is what the turn's host tools refer to. Note the last row of the table, too: an origin owned by someone else does not get a 409 that explains whose it is; it gets the same 404 a missing thread gets.