What Workers Actually Say
The previous two lessons describe what a worker should end with. Here is what workers often end with: shipped, pushed, tests green. Plain prose, no JSON, no binding id. Sometimes the worker forgot the format. Sometimes it is mid-task and just finished a turn. Sometimes a person was talking to it and it answered them.
A strict system has two bad options here. It can ignore the final because it is not a report, which throws away exactly the sentence Dad would have read before deciding the work was finished. Or it can try to infer an outcome from the prose, which turns a model's casual phrasing into a ledger transition nobody authorized. Coop takes neither. Since commit 4a99306 (2026-09-30, the day the chief became Dad's proxy), a final without a structured report becomes a note.
The Note
In Coordinator.observe_work, each completed final from the exact native session is checked for a report. If it carries none and the envelope still has active bindings, the adapter calls Engine.note with the final's text. The comment beside that call is the whole rationale: the worker's own words are the chief's evidence when no structured report came, because shipped and pushed in prose is what Dad would read before closing.
A note is deliberately small. The engine keeps text.strip()[:NOTE_LIMIT], and NOTE_LIMIT is 4,000 characters. The schema calls the table a bounded excerpt per native message, never a transcript. Notes are not canonical state: they stay out of the change feed and are pruned after thirty days. They are keyed by the native message id with INSERT OR IGNORE, so seeing the same final twice stores it once.
Who reads them? The chief. When it reviews an obligation, its context includes the six most recent notes on that dispatch next to the reports, deliveries and events. It reads them the way Dad would read the chat. Notes also decide whether there is anything to review at all: when a worker goes idle on an obligation the chief has already reviewed, the engine pulls it forward only if a note newer than that review exists. An idle worker that said nothing new is not news.
A Rejected Report Is Also a Note
The second use arrived with commit 4e78f1e (2026-10-05). Before it, if Engine.report refused a report (a done with an unanswered reply, a stale revision), the exception escaped the observation pass before the cursor moved. On the next pass the adapter read the same final, tried the same report, and failed the same way. Forever. The worker could send a corrected report in its next turn and the adapter would never reach it, because it was stuck replaying the old one. A poison message, in queue terms.
Now the adapter catches the refusal and records a note instead: Report rejected: followed by the engine's reason and the final's text. Then it moves on. The rejection is evidence the chief can read, the obligation is still owed, and the worker's next report gets its turn. The architecture puts it in one line: rejected native reports remain notes for review; they never hide a later corrected report.
Read that line as a promise about what the engine refuses, because that is all the catch covers. Two checks run in the adapter before the engine is ever asked, outside the try: an entry in coop_reports that is not a JSON object raises Invalid work report, and a second report for the same binding, or one carrying a key outside REPORT_FIELDS, raises Duplicate or malformed per-item report. Those escape the pass exactly the way engine refusals used to. The cursor stays where it was, the next pass reads the same final and fails the same way, and the worker's corrected report waits behind it. The poison message is cured for engine refusals and still alive for malformed entries.
The Cursor Moves Last
All of this rests on an ordering rule that is older than notes (commit 2f9c779, 2026-09-28): the adapter persists its transcript cursor only after every effect from that page of finals has committed. If the host crashes halfway, the next pass starts from the old cursor and replays finals it already handled. That is safe because every effect is keyed: a report is an engine command with an idempotency key built from the envelope, the native message id and the binding, and a note is unique per native message. Replay is idempotent; skipping is impossible.
Reverse the order and you get the opposite failure. Advance the cursor first, crash before the effect, and that final is never read again. A lost report is far worse than a repeated one, because nothing downstream even knows to look for it.
Three Facts, Not One
Watch how many different things observe_work records. The native harness acknowledging that the work envelope arrived is a delivery receipt. A completed assistant turn is a final, and becomes a note or a report. A committed done, released or abandoned is a terminal work report. The architecture insists these are three separate facts. Receiving the task is not starting it, finishing a turn is not finishing the work, and an ordinary final or a blocked report leaves observation running for the next turn.