Skip to content

tower: mailbox delivery race eats leading bytes when the write lands mid-composer-settle #1521

Description

@amrmelsayed

Problem

Mailbox delivery (Spec 1313) can intermittently lose the leading bytes of a delivered message when the write lands while the receiving terminal's composer is still settling after a turn. The render-gate classifies the prompt as clean, then writes — but if the classification races the composer's settling window, the terminal eats the front of the burst.

Observed (2026-08-18, two independent sightings)

  • The owner's dev-approval relay for pir-1494 arrived in the vscode architect's channel with its header truncated: ER via VS Code | 2026-08-18T10:52:43.461Z instead of [USER via VS Code] | …. Witnessed first-hand by the receiving architect.
  • The pir-1494 builder saw the same corruption intermittently while testing the gate-relay message and diagnosed it: not the message formatter (the string is correct at the source and test-pinned), not the vscode: approval gates should relay through the spawning architect instead of invoking porch approve directly #1494 change (it does not touch the write path). The loss happens at delivery.

Why it matters more now

Truncation severity depends on what the leading bytes carry. Until now they were mostly prose. Under the gate-approval relay shipped by #1494, the leading bytes are the [USER via VS Code] header — the marker that tells the receiving agent a human's decision is being relayed. Losing exactly that prefix downgrades an authorization-bearing message into what reads like ordinary agent traffic. The relay path also fires on-demand (button click), which appears to hit the settling window more often than queued sends.

Suspected mechanism

Race between the render-gate's clean-prompt classification and the composer finishing its previous turn: classify-then-write is not atomic, so a write that lands mid-settle loses its head. Intermittent; timing-dependent.

Fix directions (for whoever takes it)

  • Settle-before-write: require the prompt to be stable for a short interval after classification before the burst is written, or re-verify cleanliness immediately before the write.
  • Sacrificial leading byte(s): prefix the burst with expendable bytes (e.g. a newline) so any swallowed head costs nothing meaningful.
  • Either must preserve the mailbox-first contract: persist first, deliver only onto a verified-empty prompt, respond delivered | held.

Out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/towerArea: Tower server / agent farm CLI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions