# The delegation silenced two channels it depends on (daily audit, 2026-10-08)

On 2026-10-07 the owner stepped back: `config/fleet.yaml`
`notifications.email: weekly_digest_only` made the Friday fleet digest the
only email the system sends, and `ops/STEWARD.md` handed both human gates —
queue approval and PR merge — to an agent that reads the withheld alerts in
his place. The change was built carefully: every sender gated at one Python
chokepoint, every stdlib mirror lockstep-tested, every gate mutation-tested.

Within one day it had two holes, and they share a shape worth naming. Both
are cases where **narrowing the channel to one weekly email left a producer
with no reader at all** — not because a gate failed, but because the new
topology has a timing edge and a coverage edge that nothing was checking.

This note records both, and the one general lesson.

## 1. Every Friday steward report was invisible, forever

`_gather_steward_week` (`src/thales/execution/fleet_digest.py`) admitted a
report iff `lo < d <= today`, with `lo = today - 7 days` — a strict `<` on the
lower edge.

The steward writes `research/steward/YYYY-MM-DD.md` at **23:00Z**. Every
Friday digest gathers **hours earlier** — nominally 15:50Z, and ~20:50Z as
GitHub actually delivered it on 10-08. So Friday's report does not exist at
Friday's own digest, and the strict lower edge then excluded that exact date
from the next Friday's window. Each Friday report fell between two digests.

Measured against the live function, with reports for Fri 10-09 and
Mon-Fri 10-12..10-16 on disk:

```
_gather_steward_week(2026-10-16) -> 10-12, 10-13, 10-14, 10-15, 10-16
                                    (2026-10-09 absent)
_gather_steward_week(2026-10-23) -> []
```

Every `NEEDS-OWNER:` line in a Friday report — the decisions `STEWARD.md` §0
reserves to the owner — therefore reached nobody. In the one channel the
delegation created.

Found by research panel run 37 (#227), which verified it three times
statically and handed it to the steward. **Fixed in PR #228**: the lower edge
is inclusive, so each report lands in exactly one Friday digest (the previous
Friday's in this week's email, this Friday's in next week's). The function had
shipped with no tests; four were added in the observability tier, with two
negative controls (restoring the strict edge reds all four and nothing else;
dropping the bound entirely reds the chain test and the over-widening guard).

**Why the daily audit wrote the fix rather than the steward**, which is the
part that generalises: the steward is authorized to author observability
fixes, but it cannot merge what its own session wrote — that is why #225
needed the owner on 10-07 — and the owner now reads only the Friday digest.
A steward-authored fix to the Friday digest is stuck behind the defect it
fixes. **Author and merger must be different agents.** Any single-agent
delegation has this shape somewhere; it is worth looking for the others.

## 2. The tbx-win cutover lost its only reader

The scripted cutover that moves trading off GitHub Actions and onto the
Windows box runs from a launchd agent on the Mac each weekday at 18:00 PT,
retries on failure, and **removes itself on Friday 2026-10-16** whether or not
it ever switched. Its entire reporting surface is email: a "postponed" message
on a failed gate, a success message at the switch.

`cutover.sh` is one of the senders the 10-07 change gated. So from 10-07
onward its mail is withheld — correctly, by the policy as written. But its
fallback is not what the schedule paragraph in `CLAUDE.md` claims for the
withheld classes ("RECORDED — run annotations, outbox branches, logs,
committed ledgers"). The cutover runs on the Mac; its record is a local log
no routine can read. Its deadline is a launchd agent nothing in the repository
knows about.

The evidence that this is live, not theoretical:

- 10-06's 18:00 PT attempt mailed its postponement (gate 1 returned an SSH
  transport error, `Connection timed out during banner exchange`).
- 10-07's attempt, ~1 h after the policy landed, mailed **nothing** — yet it
  demonstrably ran and failed, because #226 had just rewritten the same
  `CLAUDE.md` paragraph the go-live PR (#206) rewrites, making #206 conflict,
  and the cutover gates on #206 being mergeable. The conflict was resolved by
  a `merge main into the go-live PR` commit at 03:27Z on 10-08.
- 10-08's trading was dispatched by the **Mac**, not the box: the three
  `workflow_dispatch` runs fired at 14:35:08 / :11 / :14Z in the order
  momentum, meanrev, vrp — the argument order in
  `ops/launchd/com.thales.dispatch-trading.plist`. The box's sequence is
  vrp, momentum, meanrev, and after the switch it runs the day locally and
  pushes state rather than dispatching workflows at all. So the cutover has
  not happened.

That last item is the useful by-product: **dispatch-order is a repo-side
discriminator for which machine dispatched a session**, available from the
Actions API without touching either host. It is strictly better than the
remedy an earlier audit proposed for the same question (`launchctl list` on
the Mac), which a 2026-10-07 correction had already shown would mislead.

## The lesson

Both holes are the same failure with different clocks: a channel was narrowed,
and nobody enumerated the producers on the far side of it. The 10-07 change
enumerated **senders** exhaustively and gated every one. What it did not
enumerate was **readers** — who now sees each withheld class, and whether the
"RECORDED" fallback actually exists for that producer. For the digest's own
steward section the reader existed but the window excluded it; for the cutover
the fallback does not exist at all.

A useful standing check for any future narrowing of the alarm layer: for each
class now withheld, name the reader, name the artifact they read, and verify
by reading it. Three of the four alarm channels this platform has lost in the
last month were lost silently, and each was found by a routine looking at
something else.

## Carried

- The cutover's give-up date, **Friday 2026-10-16**, is unobserved by anything
  in the repository. #206 open and `main` carrying the Mac's dispatch is the
  observable proxy.
- `research/steward/*.md` is inside `publish_set`, so steward reports publish
  to the journal. Nothing wrong with that, but it means the reports are
  subject to the publish gate that froze the site on 10-07.
