The Turn Ends Before the Work Does
The Chief delegates a todo, or starts an upload, or asks for a service restart. The result will exist in ten minutes or an hour. Her turn ends now. That leaves two bad options, and Master Chief makes both of them worse than usual.
Poll in the foreground. Keep the turn open and check a status every so often. In an ordinary chat that wastes tokens. In Master Chief it holds the room: one turn at a time, in order, so every doorway Dad might use waits behind a model watching a status field. This is the desk-leaving from the last lessons in a new costume.
Say “I'll let you know.” A promise with nobody behind it. When the turn ends, the model has no clock, no memory of the promise and no way to wake itself up. The sentence is true only if something durable was written before it was said.
The answer is the followup family tool, born on 2026-10-07 (commit c2dee4c4) next to the coop tool and offered to every vessel the same way. Before a turn that started deferred work returns, it arms a durable, read-only check.
The Rule Is Written Twice
The instruction to arm reaches the model from two places. The tool's own description says: Arm BEFORE ending the turn, state the returned wake_plan, and keep the work's stable key on retries. And the shared environment header that every Pippa system prompt carries has a block titled Deferred work — arm, then return, which ends with the line that keeps the promise honest: If arming fails, say the check is not armed and resolve that blocker; never promise a later notification without a durable receipt. Two placements, on purpose: the description travels with the tool, and the header travels with every turn, including the ones where the tool is far from the model's mind.
What Gets Armed
An arm call takes exactly seven fields, and arm() refuses anything else:
key, a stable name for the operation. The check's id is the SHA-256 of the conversation id and this key, so arming twice with the same key and the same contract returns the same watch. The same key with a different contract is refused: This key already names a different wake contract; inspect it before choosing a new key.inspect, in words: what evidence to read.probe, the machine check,cooporhttp.success_messageandblocked_message, one line each, in Dad's language. A newline is refused: Notifications must be one line.interval_seconds(default 30) andtimeout_seconds(default 3,600), integers of at least 5, the deadline no shorter than the interval.
The source must be a saved turn of one of Dad's own Pippa conversations: the tool reuses the coop tool's source_context word for word, so Sidekicks, Council and scheduled turns cannot arm anything. What comes back is the saved record with its wake_plan spelled out, which the model is told to state to Dad. It is four sentences, verbatim from the code:
- pending: Recheck quietly; busy/idle or a queued receipt is not completion.
- succeeded: Post success_message once to Chief for Dad's next turn; no external alert.
- blocked: Alert Dad immediately with blocked_message and the worker's for_dad lines, record it in Chief, and keep checking until the deadline.
- deadline: Stop checking and report that completion could not be verified; never repeat the work.
Two Probes, Both Read-Only
A coop probe names work by work_kind and item_id and reads it through Coop's show. Only a done or closed item is success. A blocked, abandoned or released report, or a failed, cancelled or expired assignment while nobody holds the work, is blocked. Busy, idle, a queue receipt or a stale disconnected status is pending. Adding message_id waits instead for that one reply's applied or not_applied answer.
An http probe GETs a credential-free JSON status URL: no user or password in it, no redirects followed, no proxy from the environment. A success predicate is required, dotted JSON keys mapped to exact scalar values, and even the type must match; a blocked predicate is optional. A 401 or 403 is a blocker, since waiting will not fix authorization; any other failure is a transient pending. For a restart or a deploy, the predicate pins the identity you expect, a build hash or a version, because a healthy old process is not success. The sketch below was checked against the real validator: an engine still answering ready on the old build does not match.
Arming Is Not Doing
The check never launches, repeats, approves or cancels the underlying work. cancel withdraws the check, never the work. And arming is not a claim that anything completed: the tool returns a contract, not a result. Short waits can be read again with status in the same turn. Long waits belong to the scheduler, and nothing new is scheduled for them. At startup Pippa registers one interval job, followup-checks, every 5 seconds, on the heartbeat service's existing APScheduler, which runs only in the process holding the cross-process scheduler lease. Each tick lists the checks that are due, leases each row for two minutes, starts its probe as a separate task and returns. The records live in their own SQLite file beside the conversation database and survive restarts. No cron entry, no launchd job, no model call per check. The Coop Quest's Track 7 ends with this same tool seen from Coop's side, probe verdict by probe verdict.