Skip to content

A request the helper can never decode leaves the pending set, instead of stopping the line forever - #10707

Merged
briansrls merged 2 commits into
mainfrom
publication-poison
Sep 7, 2026
Merged

briansrls merged 2 commits into
mainfrom
publication-poison

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

What was measured

srv1, 2026-09-06: gunbc-roadmap-publication.service failed on every tick for a day. Two requests in the spool were written under roadmap-publication-request/v1; the deployed helper reads /v2. It refused both, exited 1, and re-read the same two bytes on the next tick.

The refusal is correct. Decoding is a pure function of the request bytes, so no run in that population could have ended differently. The defect is that the refusal retained the request.

Every other terminal outcome consumes its request — the answer is written, then the request is deleted — so the next run sees a spool holding only open questions. The unreadable arm was the exception, so one bad document re-stopped the line every tick, with every request queued behind it waiting, and nothing could ever restart it.

The repair

Stopping the line and consuming the request are two decisions. The stop makes the deficit loud; the retirement makes it stop once per bad document rather than once per tick. A new undecodable request stops the line again — that is the intended signal, and it is preserved.

The judgment is pure; the retirement is the effect. publication_request_admission decides from the entry name and bytes alone. publication_helper_retire_request performs the move and returns the caller's refusal unchanged on success, so retiring a request can never rename why it was refused.

An earlier revision fused them. That put a filesystem move on the decision path and turned two existing witnesses into route gaps — and the available repair there was to add a mock_response to shell.Move.File, which would have passed them against a fabricated move. The judgment moved instead.

A third door was open and is closed here too: HelperSubjectOutsideCapability is equally terminal (the capability is this repository, a constant) and also retained its request. Fixing only the two doors I had found would have left the same permanent stall reachable through the third.

The refusals stay three. They share one remedy — leave the pending set — and nothing else. A document that does not parse, one naming a repository this principal may not act on, and one whose name lies about its own subject are three different findings for whoever reads the stopped line, and the second is the anti-forgery arm.

HelperRequestUnreadable is split from HelperRequestRefused for the same reason: a failed READ is transient and its request stays pending; a failed DECODE is terminal and its request leaves. Collapsing them is exactly how the terminal class inherited the transient class's remedy.

The quarantine is not an answer and cannot be addressed as one. An undecodable request has no decoded subject, so no answer address exists for it; writing one at the caller's entry name is the forgery the request/answer permission split makes unwritable. The bytes go to a third directory the publication principal holds, where they stay readable for the analysis the stopped line demands.

Evidence

24/24 witnesses pass (claim_batch --hermetic), including three new controls: the terminal/transient split is named apart, a failed quarantine is its own outcome and stops the line, and the_three_terminal_refusals_are_distinguished_rather_than_collapsed reds if a later author collapses them.

Not claimed

Production was repaired by hand ahead of this branch — I moved the two documents into requests-refused/, preserving the bytes. That is a one-time operational action, not a fix; if srv1 is rebuilt before this merges, the stall returns.

The helper's ~1 min 53 s CPU per tick is not addressed here and is not caused by this defect — a successful run costs the same, on a 60 s cadence. That is the per-tick closure re-resolve, tracked separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_019iXPtAqzPaNBZbaaM5rxrY

… of stopping the line on the same bytes forever

Measured on srv1 (2026-09-06): two publication requests written under a superseded request schema
stopped the helper on every tick for a day. The refusal was correct -- the document does not decode,
and decoding is a pure function of its bytes, so no run in that population could have ended
differently. The defect was that the refusal RETAINED the request.

Every other terminal outcome consumes its request: the answer is written, then the request is
deleted, so the next run sees a spool holding only open questions. The unreadable arm was the
exception, so one bad document re-stopped the line every tick at a full run's cost, with every
request queued behind it waiting, and no analysis could ever restart it.

STOPPING THE LINE AND CONSUMING THE REQUEST ARE TWO DECISIONS. The stop is what makes the deficit
loud; the retirement is what makes it stop ONCE per bad document rather than once per tick. A new
undecodable request stops the line again, which is the intended signal.

The judgment is pure and the retirement is the effect. publication_request_admission decides from the
entry name and the request bytes alone; publication_helper_retire_request performs the move and
returns the caller's refusal unchanged on success, so retiring never renames why a request was
refused. An earlier revision of this repair fused them, which put a filesystem move on the decision
path and turned two existing witnesses into route gaps -- the available repair there was to mock the
move, which would have passed them against a fabricated success.

A THIRD DOOR WAS OPEN and is closed here too: HelperSubjectOutsideCapability is equally terminal --
the capability is this repository, a constant -- and it also retained its request.

The refusals stay three rather than collapsing into one `terminally refused`. They share a remedy and
nothing else: a document that does not parse, one that names a repository this principal may not act
on, and one whose name lies about its own subject are three different findings for whoever reads the
stopped line, and the second is the anti-forgery arm.

HelperRequestUnreadable is split from HelperRequestRefused for the same reason: a failed READ is
transient and its request stays pending, a failed DECODE is terminal and its request leaves. The
collapse is how the terminal class inherited the transient class's remedy.

The quarantine is not an answer and cannot be addressed as one -- an undecodable request has no
decoded subject, so no answer address exists for it, and writing one at the caller's entry name is
the forgery the request/answer permission split makes unwritable. The deploy creates the third
directory owned by the publication principal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019iXPtAqzPaNBZbaaM5rxrY
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@briansrls
briansrls merged commit d9d6872 into main Sep 7, 2026
4 checks passed
@briansrls
briansrls deleted the publication-poison branch September 7, 2026 02:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant