docs(plans): correct the S11 provenance plan against waves 1 and 2
Why
The merged plan states facts the wave-1 and wave-2 builds falsified. Guardrail 4 bars a step MR from fixing them in place, so each divergence sits in its own MR description, where the next step's author will not look. This folds them back.
Five would misdirect a later step. Step 10's RouteTable() pin is off by one
against main, Step 4's truncation contract is wrong three ways, Step 5 asks
for a suppression guardrail 25 forbids, Step 2's Tests: field names a file
that cannot reach the symbols it must cover, and Step 8 rests its chore type
on a claim that the answers a client sees do not change.
What
| Step | Correction | Build |
|---|---|---|
| Approach, Over-ceiling | Five more steps were forecast under the ceiling and landed over it | the five below |
| 2 | The Tests: file reaches neither new symbol, so the unit cases get their own |
refactor(npm): split the publish charge into a ... (!2803 - merged) • Hayley Swimelar • 19.5 |
| 3 | Two files outside the list: the fuzz:npm target with its 10m to 15m bump, and the corpus index |
chore(npm): parse and shape-check an attestatio... (!2806 - closed) • Hayley Swimelar • 19.5 |
| 4 | The truncation contract, and the FuzzJSONStringReaderBounds registration lands here |
chore(npm): bounded JSON string reader for stre... (!2805 - closed) • Hayley Swimelar • 19.5 |
| 5 | No file-level squawk header, one statement-level ban-drop-column, and a different timeout precedent |
chore(datastore): add npm_versions.attestation_... (!2813 - closed) • Hayley Swimelar • 19.5 |
| 6 | wire_npm_authz_test.go and the S09 row join the list, "two modified test files" is three, and route_disagreements.md stayed untouched |
chore(npm): attestations route grammar and auth... (!2807 - closed) • Hayley Swimelar • 19.5 |
| 7 | Step 3's fixture builder needed no extension | chore(npm): verify a bundle's subject against t... (!2812 - closed) • Hayley Swimelar • 19.5 |
| 8 | Five classes of client-visible answer move, all spec-ordered, none a regression | chore(npm): apply the _attachments key rules at... (!2814 - closed) • Hayley Swimelar • 19.5 |
| 10 | The pin moves 15 to 16, the oracle and census rows land here, and guardrail 20's order goes on Depends on | chore(npm): mount the attestations route on an ... (!2811 - closed) • Hayley Swimelar • 19.5 |
| 11 | Position 3's key needs a bound, the value drains into a pre-sized buffer, Limits.validate() gains its arm, and the cause names the limit |
chore(npm): bounded JSON string reader for stre... (!2805 - closed) • Hayley Swimelar • 19.5 |
| 14 | Why the mux cannot supply package_name, and who consumes the stamp |
chore(npm): mount the attestations route on an ... (!2811 - closed) • Hayley Swimelar • 19.5 |
| 16 | The version capture is validated before any use of it | chore(npm): attestations route grammar and auth... (!2807 - closed) • Hayley Swimelar • 19.5 |
| 18 | npm_command stays audit, with the grouping reason |
chore(npm): mount the attestations route on an ... (!2811 - closed) • Hayley Swimelar • 19.5 |
| 20 | blobSizeDeltas keeps its parameter order, and the asymmetric rows are extended rather than relaxed |
refactor(npm): split the publish charge into a ... (!2803 - merged) • Hayley Swimelar • 19.5 |
Three things a reviewer would otherwise ask:
- The
## Statustable is byte-identical tomain. It belongs to docs(plans): record the open step MRs in the S1... (!2810 - closed) • Hayley Swimelar • 19.5, and no hunk here goes near it. The last command below is the check. - Rules over digits. The over-ceiling correction states the pattern the five builds share, the overshoot sitting on the test side, rather than five counts that go stale on the next push.
- The 2026-09-21 S11 rulings are not folded in. Keyed entries, bounds,
UTF-8, and digest case wait for the
docs(specs)MR that settles them, with a second corrections batch behind it.
Test plan
mise exec -- npx markdownlint-cli2@0.18.1 docs/plans/2026-09-11-npm-provenance-attestations.md docs/plans/README.md
mise exec -- vale --minAlertLevel=error docs/plans/2026-09-11-npm-provenance-attestations.md docs/plans/README.md
mise run lint:links
diff <(git show origin/main:docs/plans/2026-09-11-npm-provenance-attestations.md | sed -n '/^## Status$/,$p') <(sed -n '/^## Status$/,$p' docs/plans/2026-09-11-npm-provenance-attestations.md)markdownlint and the diff print nothing. Vale reports 0 errors, and its 5 new
warnings are all the spelling of mux, a word the plan already uses. lychee is
clean over 3,013 unique links with fragments on, which covers the one anchor
this MR adds.
Guardrails
- 12. No
docs/testing/scenario is added or affected: this MR changes plan prose alone, and no service behavior moves with it. - 24. No
docs/user/page is affected for the same reason, anddocs/plans/does not publish to docs.gitlab.com.
Context for LLM agents
Rationale
- Restating each correction as "the plan said X, the build did Y" in the step
text. Rejected: a plan states what is true, and the narration belongs in this
description. The one exception is Step 10's pin, where
mainreading 15 rather than 14 is itself the fact a later step checks against. - Folding the five over-ceiling line counts into the plan. Rejected: a count written into a plan is stale at the next push, and the pattern the five share is what a later step acts on. The counts stay in the five MR descriptions.
- Correcting Step 8's five answer classes inside the Scope field. Rejected: Scope says what the step does, and the moved answers are a separate contract a reviewer checks against the spec, so they get their own Answers that move field.
- Chosen: correct each step in place, one field at a time, and leave every untouched claim alone.
Non-goals
- Filling the Status table. docs(plans): record the open step MRs in the S1... (!2810 - closed) • Hayley Swimelar • 19.5 owns it, and a second writer is what guardrail 4's single-writer rule exists to stop.
- The 2026-09-21 S11 rulings on keyed entries, bounds, UTF-8, and digest case. Each needs a spec amendment first, and folding a ruling into plan text ahead of its spec would make the plan the authority.
- Four more Files-list gaps of the same class, each recorded in its own MR
description: Step 2's
docs/dev/storage-accounting.md, Step 5'smigrations_checksum_test.goandnpm_schema_integration_test.go, Step 8'sstreampub_test.go, and Step 10'sobserve_test.goandwire_npm_observability_integration_test.go. Steps 3, 6, and 10 got the treatment here because they carry a correction this MR was scoped to; closing the rest belongs with the second batch, in one pass, rather than four at a time. Step 10's Tests field accordingly names the three files its corrected Files list carries. - Re-running the plan's LOC estimates. They are forecasts, and the Over-ceiling section now says how to read them.
Related to #1273