Two Ways Into One Room
Everything that reaches Master Chief arrives in one of two shapes. A turn is Dad saying something through a doorway and a brain answering: the engine admits it through the turn lock, replays the conversation, runs the model and stores both rows. A report is a line the engine appends on someone's behalf: no model runs, no replay is paid for, nothing waits for an answer. A turn occupies the room. A report leaves a note in it.
The whole family of sibling apps runs jobs on schedules: briefs, scans, triage passes, nightly checks. Every one of them is something Dad might want to know about, and almost none of them is Dad speaking. Get that distinction wrong and an endless conversation fills with work that was never a conversation. This track is about the machinery that keeps it right, and it starts with the two mistakes that showed why it was needed.
The Morning the Brief Moved In
Tidings, the family's news engine, sends a scheduled daily brief to Pippa through the older Ask door, with source: tidings. To the admission gate that looked exactly like Dad speaking from inside Tidings, so the brief ran inside the Chief every morning: the job prompt landed as a user row in Dad's room, followed by a 26,000-token reply. Track 2 walks the gate itself. What matters here is the fix (7252f738, 2026-10-08): a payload marked 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 one addressed to the Chief gets a 409. The job had to declare what it was, because the door it used was Dad's door.
That fix keeps a job out. It says nothing about how the job's outcome gets in. That part has its own history.
From Every Result to Only the Ones That Need Dad
An earlier change had made cron results that notify Dad also post into the Chief, whole. Two things went wrong in quick succession. First, the gate read job.get('notify', 'telegram') != 'none'. The Soul Stream Wake jobs carry notify: null, and a default in get() only covers a missing key, so None sailed through and every hourly wake skip landed in the Chief (fixed in f2f1b14b: missing or null now means no notification). Second, even with that fixed, jobs that legitimately notify Dad were copying their full bodies into the room, "inbox is empty" included. Dad ruled on it (coop #345): the Chief receives only outcomes that need him, as one-line summaries that link to the job's own conversation. That ruling became d0eaaf16 (2026-10-08).
The Receipt, Not the Prose
How does the engine know whether a run needs Dad? It does not read the report and guess. A shared scheduler prompt asks every eligible worker to end with one final line, CRON_OUTCOME: {"status": ..., "summary": ...}, using one of eight statuses. Four are actionable: approval_required, failed, blocked, question. The other four (success, noop, skipped, empty) stay quiet. The parser reads only that terminal line; a missing or malformed receipt is unknown and puts nothing in the Chief (unless an owning engine's snapshot, below, says otherwise), and an actionable status with an empty summary is rejected as malformed. A valid receipt stays in the worker's transcript and is stripped before the job's own Telegram or email notification sees the body. A malformed one is left in place: the parser only reads, so the job's own notification, which follows the job's own policy, can still carry that broken line to the phone.
Two refinements keep it honest. Where an owning engine knows the truth better than the worker (the Herald and Journal approval queues), the engine snapshots the pending drafts before and after the run: new or revised drafts waiting for Dad count as approval_required, an unchanged backlog does not, and an unavailable snapshot is treated as unknown, never as an empty queue. And when the run itself crashes, the engine types the failure directly instead of asking a failed worker to write JSON.
The Gate and the Line
Before any of that, eligible() decides whether a job may report at all: it must be a Pippa job, its notify must be set to something other than missing, blank, null or none (that opt-out wins even over a push flag), and its chief_report must be actionable, the default (the only other legal value is never). Then one_line() builds what Dad sees: the job name, cut to 80 characters, a colon, the summary, cut to 200, and a link to the job's conversation. Brackets, parentheses, backticks and the other Markdown characters are stripped from both, so a job name cannot inject a second link or a code block into Dad's room. The full result never moves; it stays where the job ran.