0017 — The Operator is fed; it does not poll

The decision

Watching is a scheduled process's job. Judging is the Operator's. They are different rungs and they integrate by a FILE, not by a call.

  1. A scheduled deriver reads the fleet's surfaces and writes one digest. PR state, required contexts with their durations, real review verdicts, main's CI, and the decision queue. The Operator reads that file at the wakes it already has and does not re-derive any of it.
  2. The puller never acts. It does not merge, resolve a decision, approve, label, drop hold-for-review, toggle draft→ready, re-trigger a review, write to production, or write task.json / STATE.md / any registry. One writer per artifact (ADR-0003); the only artifacts it writes are its own. A puller that acts is a second Operator, and two Operators on one board is the failure that let a PR merge out from under the first one on the night this was written.
  3. It is not a wake source and not a nudge watcher. It writes to disk and exits. The operator skill caps judgement at roughly 30 firings per task rather than 400, on purpose; a puller that messaged on every delta would rebuild that cost one layer up. And a second looper beside the Operator's watcher is ordered killed on sight — correctly — so this must be distinguishable from one: launchd, no loop, no GATE, never in the nudge roster.
  4. Deltas, not state, and the first digest is a declared BASELINE. Restating everything makes the Operator re-read what it already knows, which is the entire cost this removes. A first run has nothing to diff against, and a baseline silently rendered as "no changes" is a green that means nothing.
  5. Every source carries exactly one of changed / unchanged / UNREAD(<why>), and UNREAD is never folded into unchanged. This is ADR-0009 applied per source rather than per system: not proving a thing must never look like proving it. All four classes print every time, empties printed as empty — an absent section and an empty section are different claims, and only one of them means nobody looked.
  6. The puller MAY route a decision to the ladder. It may NOT resolve one. An open block with no ruling is handed to fable-decide. A RESOLVED receipt is reported as apply it, addressed to the Operator. Reading a ruling and executing it are different acts, and the second belongs to the rung that holds the acceptance criterion.
  7. A rung that was REACHED and DECLINED is never re-asked — by the puller either. ADR-0016 forbids laundering a refusal into a ruling inside the ladder; this extends the same rule to the thing that feeds the ladder, because a scheduled job that re-asks a declined question every five minutes would launder it by attrition. NEEDS HUMAN is terminal in the puller's ledger, forever. Only ERROR / WALLED — could-not-be-reached — are re-askable, and only after the receipt's retry_after.
  8. Provenance travels with the answer. The digest names the rung that answered, the model, and the receipt id. A receipt carrying neither field renders provenance UNKNOWN, never "Fable".

Why

The Operator polled by hand. Every wake, it swept PR states, check conclusions, review verdicts and the decision queue one at a time, mostly to learn that nothing had changed. On 2026-09-10 that shape cost three measurable things in one evening: a PR merged out from under the Operator, a regenerating alarm it was losing to one withdrawal at a time, and twice Gera noticed a problem before the Operator did. The last one is the tell. A coordinator that a human has to correct about the state of its own board is not coordinating.

The obvious fix — a live agent that watches — is the wrong shape and would be more expensive than the disease. Watching is mostly the production of "nothing changed", and a full-price model context producing that sentence on a loop is exactly the per-session polling the fleet already retired once when it moved the nudge loop off every worker and onto one Operator per task. The fleet already has the right shape working twice: derive-live-work and decision-ladder-canary both read on a clock, call no model, and write a file somebody else reads.

Why the decision queue belongs to the same rung

It was two separate hand-jobs, and they failed the same way. On the night this was written, two questions sat on the founder's decisions page over rulings Astra had already made, at high effort, with the rulings sitting in the block's own recommendation field. Nothing was broken; nobody had looked. The thing that reads the board every five minutes is the thing that should have noticed, and it is the only actor in the loop whose noticing is free.

So the flow is: the puller sees an open decision → the puller routes it through the ladder → only what the ladder genuinely cannot settle reaches the human. That closes the waste in both directions: a question nobody asked gets asked, and a question already answered stops being presented as though it were waiting on a person.

Why "may route" and "may not resolve" is a real line and not ceremony

They look like one act and they are two. Routing produces evidence — a receipt, with a model's name on it. Resolving spends that evidence against a goal, and it needs the acceptance criterion, which the puller does not hold and cannot hold: it is a stateless process with no memory of what the task is for. Doctrine already says a model-RESOLVED question is APPLIED by the operator and cannot even be re-raised; a watcher that self-applied would be a third path to the same act, with the least context of the three.

Why the traps had to be encoded rather than trusted

A digest that repeats a lying instrument is worse than no digest, because it launders a bad reading into something the Operator was explicitly told not to re-derive. Every one of these was measured on 2026-09-10:

The rule that generalises past this list: any required context whose duration is zero is UNKNOWN, in either direction. Not green, not red. A stamp is not a run.

Consequences