docs(plans): fill Step 13's Status row and correct the Step 13 and 15 entries
Fill Step 13's Status row in docs/plans/2026-07-30-container-remote.md, and take
the plan-file edits that were riding on !1785 (merged). Guardrail 4 keeps both off step MRs.
What changes
The Status row (b325e903b). Step 13's row gains its two MRs, !1784 (merged) (part 1,
container remote refusals and outcome mapping) and !1785 (merged) (part 2, operations glue
and health sweep). The paragraph above the table gains a note saying why one row
carries two MRs, since every other multi-MR step is listed one row per MR. That
paragraph's closing count changes from 29 MRs across 19 steps to
29 rows across 19 steps: Step 13's row is the first to carry two MRs, so the MR
phrasing undercounts from here on, and 29 is the row count a step MR title written
now derives as its denominator. Guardrail 4 derives that number when the title is
written rather than copying an earlier MR's, so the S16 titles merged before the
table grew to 29 today (in 4268c681f) still quote 26.
The Step 13 entry corrections (be4b24cb2), moved off !1785 (merged). Research that
came out of implementing part 2: the third body-size bound
remote.FetchOptions.MaxBodyBytes imposes, the health-sweep aggregate's real home
in cmd/artifact-registry/wire_remote.go rather than wire_jobs.go, the resolver
taking no seam from this step, the wrapper completion this step owes Step 8, and
the Files and Tests bullets the implemented shape changed.
One of those paragraphs lands in Step 15's entry, not Step 13's: what
deferring remote.SingleFlight costs beyond the coalescing. Step 15's Gated
bullet is where that deferral is documented, so the finding is recorded against
its subject rather than against the step that turned it up, and it is tracked by
#752.
Review fixes, round 1 (5576e927c, 8e6c1719d). Seven claims across the two
commits above that did not survive checking against the tree, including the
rationale in Why the row is not split below.
Review fixes, round 2 (a2a5fbb06, 06b1bb3d2, 11c630810, f3b97ffb8).
#752 now reads as the tracker behind coalescing criteria 20 and 23 everywhere the
plan names them, replacing four sentences saying nothing tracked them. The Step 15
deferral paragraph points at the Fetch coalescing bullet under Dependencies,
which owns that decision, instead of restating it against the wrong seam. The
!1762 (merged) pointer is dropped, since !1762 (merged) is in this branch's base. And the
rejected-constant paragraph calls body_size_cap_metadata one input to a
resolved minimum rather than an independent bound. #752's own Scope carries the
seam correction and the request-builder gap, which is the other home for it.
Why the row is not split into 13a and 13b
The row follows the entry, and this entry describes one MR. Step 16 is the contrast rather than the counterexample: it was authored as one MR too, but each of its four parts needs its own Files list and its own account of what it takes from the part before, so its entry was amended into a per-MR table and earned four rows. Step 13's two parts take one Scope, one Files list, and one Acceptance bullet between them, so there is no per-MR table for rows to follow.
The cut runs along a composition seam, and only one way: !1784 (merged) carries the HTTP-free decision vocabulary with no caller, !1785 (merged) composes over it, and !1784 (merged) merged on its own.
Why this is its own MR
Guardrail 4 in the project CLAUDE.md routes every plan-file edit off step MRs,
Status-table fills included, because parallel step MRs editing adjacent rows
collide and a split step keeps consecutive rows in flight together.
The fill was first written on !1784 (merged) and moved off it in 1485325c, after the conflict between that guardrail and shipped practice was escalated and settled: the guardrail stands as written, and commit 728aa91b (Step 11 part 1, which edited this plan file from a step MR) is a violation that shipped rather than a precedent to follow. !1785 (merged)'s plan hunk moved here for the same reason.