docs(plans): record the step MRs and fold !2075's plan corrections
What
The standing Status-table MR for the npm remote observability plan. It records the step MRs as they open, which AGENTS.md guardrail 4 keeps out of the step MRs themselves, and it is the plan file's single writer while the workstream has steps in flight.
Two rounds now, in two commits:
- The step MRs and step 1's split (
9f6e459) — the reason this MR opened. - Four plan corrections from !2075 (merged)'s review round (
d41849f) — added after the fact; see Why the corrections land here below.
Round 1: the step MRs
- Step 3 → !2071 (merged), which is what this MR opened for.
- Step 1 split into
1aand1b, recorded as !2075 (merged) and !2076 (merged).
Why step 1 split
Its combined diff ran to 1899 reviewable LOC against the 500 docs/dev/development-model.md asks for. The split falls on the seam rather than on size alone: 1a is remote.StandaloneOptions' ReadObserver and the npm observer behind it, which no route installs and which emits no series; 1b is the two routes' wiring, the cache fill, and the catalog edits. 1b builds on 1a and merges after it.
Three edits that had to move together
The table gains the rows, but two other sentences in the same file are downstream of the row count and go stale on their own:
- The marker sentence's denominator goes from
<step>/4to<step>/5, because it counts the Status table's rows. Left alone, the sentence and the table disagree and a step MR title copying either one is wrong against the other. - Step 1's entry gains a
Splitbullet naming which files each half carries, so1aand1btrace back to the entry they came from instead of appearing only in the table. - The merge-order sentence said steps 1, 2 and 3 may merge in either order. That stays true of the steps and was never true inside step 1, where
1bbuilds on1a.
How round 1 was found
A review of !2075 (merged) caught it: the MR had opened with a title claiming 1a/5 against a four-row table containing no 1a, and the plan's own marker sentence still said /4. The marker exists so a list of MRs shows how far through a plan the work is without opening any of them, which a denominator pointing at a table that does not exist defeats.
Round 2: four corrections from !2075 (merged)'s review
Why the corrections land here
!2075 (merged)'s review round produced four findings that target the plan file rather than 1a's code. All four target text that exists only on this branch: on main the Status table is still steps 1 to 4, with no 1a/1b and no Split bullet, so a docs(plans) MR off main cannot implement them. Guardrail 4 bars the step MR from editing the plan, and this MR is the plan file's single writer, so they land here. This MR is unapproved, so folding them in resets no approval.
The four
- Two premise sites were unnamed. The inventory of sites asserting that a metadata route resolves no cache verdict and reports no flight missed
emitRemoteProxyEvent's own doc block, which restates thecoalescedhalf for a reader of the emitter rather than of the struct, and it cited thenpm_remote_proxycatalog row by a line that has since moved (:237at1b4b8c3e4,:238atb0a19460a). Both are now named by the sentence they assert as well as by line, so a row added above one of them no longer strands the reference, and step 1's Files entries reach both. (note) - A fallback serve can follow a miss.
CacheFallbackissues its ownstore.Lookup(internal/remote/lookup.go:54) rather than reusing the read's, so only a miss on that second call reportsErrUpstreamUnavailable, and a read whose first lookup missed can still find a row a concurrent leader committed in between. The derivation table gains that shape as row 8, bookinghit_staleto match row 3, with the competingmissreading named and declined. The code is right; only the plan was wrong. (note) - The observer's
coalesced()stamp timing is recorded as1b's design call. It is read from a deferred call whileObserveLookupbooks its verdict early, so one type carries one panic-resilient field and one that is not. The fix is1b's because its shape is a property of the call site1bwrites, and the accepted inaccuracy is now named in the plan rather than left for1b's reviewer to discover. (note) 1bgains a-raceacceptance criterion.newRemoteDocumentObserver()is a free function, so a wiring that hoists one observer onto a handler struct compiles and passes every test1aships while producing a Go race and cross-request verdict bleed. AGENTS.md's shared-instance-seam rule requires the composition test. (note)
What moved with them
Row 8 is a count the plan states in four other places, so seven becomes eight at each: the declined-alternative sentence in Approach, the table-test sentence beside it, step 1's remote_document_observe_test.go Tests bullet, and Testing Strategy's derivation-table bullet. The paragraph above the table also said "The last two rows", which a row appended below it silently re-points, so it now names rows 6 and 7. Its framing sentence said "Two shapes the table does not admit" and now says one.
The Split bullet's 1a file list also gains the two in-package documents !2075 (merged) edits, internal/format/npm/remote_document_serve.md and internal/format/npm/metrics.md, with metrics.md's two halves noted as disjoint: 1a documents the observer, 1b drops the catalog rows.
Two cross-references were added so the new text is not orphaned: the latch rationale under remote_document_serve.go points at the stamp-timing Note, and the row-7 test bullet says it is the subtest to re-read if 1b moves the stamp site.
Checks
markdownlint, Vale, lychee, gitlint and the rest of the pre-commit chain pass on both commits.
Related to #800 (closed)