Skip to content

fix(release): carry QUICK_REFERENCE's Current Release block in changeset:version - #5396

Merged
os-support-ai merged 1 commit into
mainfrom
claude/issue-5394-quick-reference-release-drift
Aug 20, 2026
Merged

fix(release): carry QUICK_REFERENCE's Current Release block in changeset:version#5396
os-support-ai merged 1 commit into
mainfrom
claude/issue-5394-quick-reference-release-drift

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#5394

main was red on scripts/__tests__/quick-reference-current-release-4143.test.ts:
manifests at 17.6.0, QUICK_REFERENCE.md still saying 17.5.0. The gate is
untouched
— no skip, no exemption, no loosened assertion. It stays the judge; this PR
adds the thing that keeps the doc true so the gate has nothing to report.

Route chosen: B — carry it in the release, and why A cannot work alone

Measured on origin/main before choosing:

questionmeasurement
who moves the anchor with no human present?changeset version, run by changeset-release.yml as version: pnpm changeset:version
does the release PR's CI catch it?No. Every ci.yml run on branch changeset-release/main has conclusion: "action_required" with created_at == run_started_at — the workflow never executes. A GITHUB_TOKEN-authored PR starts no workflows. PR #4655 (the 17.6.0 release) merged with one check run on its head sha, and that one started 7 seconds after the merge.
so when is the drift first seen?the push build on main — run 32356587040, Test (coverage) failure after 39 min 26 s

That is why main — never a PR — goes red once per release. It also settles A vs B:

  • A (derive the row) does not close the window. Deriving the value changes how the
    row is written, not when. changeset version would still bump 40 manifests with
    nothing re-running the derivation, the doc would still be a version behind, and the
    push build on main would still be the first reader. A alone buys nothing here.
  • The dispatch's other worry about A is real too: the gate asserts the doc against the
    manifests. A block generated wholesale from those same manifests would leave the gate
    comparing generated text with its own generator's input, and the rows' hand-written
    anchor notes — which the gate's header calls out as deliberately rewordable — would
    become script-owned prose.

So this PR runs A's mechanism at B's moment: a derivation that executes inside
changeset:version, rewriting only the version literals and leaving every word of
prose alone. The gate keeps judging the result with its own independent derivation, so a
bug in the writer still goes red.

The change

  • scripts/sync-quick-reference-release.mjs — reads the anchors, rewrites the literals
    of the anchored rows in place. It refuses (non-zero) rather than guessing when a row's
    literal count no longer matches its anchor's, and never touches the unanchored
    TypeScript row.
  • package.jsonchangeset:version is now
    changeset version && node scripts/sync-quick-reference-release.mjs, plus
    quick-reference:sync / quick-reference:check for humans bumping Node, pnpm or the
    spec range by hand.
  • QUICK_REFERENCE.md — the row catches up to 17.6.0, and the block's preamble names
    the new mechanism.
  • scripts/__tests__/sync-quick-reference-release.test.ts — 12 tests. The load-bearing
    ones pin the wiring in both places (package.json, and the workflow's version:
    input, so nobody can bypass the npm script) and pin that the writer and the judge spell
    VERSION_LITERAL identically — two tokenizers would be free to drift into a doc the
    script calls synced and the gate calls stale.

Recurrence proof: a real release bump, no hand edit

Not a simulation of the script — the actual release command, in the worktree:

$ pnpm changeset:version
> changeset version && node scripts/sync-quick-reference-release.mjs
🦋 changeset v3.0.1
All files have been updated. Review them and commit at your leisure
Version: 17.6.0 → 17.7.0
✅ Rewrote QUICK_REFERENCE.md's "Current Release" block from its anchors.
$ grep -m1 '"version"' apps/console/package.json → "version": "17.7.0",
$ grep '^- \*\*Version:\*\*' QUICK_REFERENCE.md → - **Version:** 17.7.0 (…)
$ pnpm exec vitest run scripts/__tests__/quick-reference-current-release-4143.test.ts
Test Files 1 passed (1) Tests 8 passed (8)

81 files modified by that one command, QUICK_REFERENCE.md among them — so the changesets
action commits the doc in the same chore: release packages commit as the manifests.

Control leg (what changeset version alone produces): doc reverted to the pre-bump
literal, manifests left at 17.7.0 — the gate goes red exactly as it did today, one
release into the future:

AssertionError: QUICK_REFERENCE.md must state the workspace version as exactly "17.7.0":
expected [ '17.6.0' ] to deeply equal [ '17.7.0' ]
AssertionError: … block states ["17.6.0"], which no manifest in this tree produced …
Tests 2 failed | 6 passed (8)

The worktree was reset to the committed state afterwards (git status --porcelain empty).

Reverse verification — predicted before running, both legs matched

No build artifact sits between either leg and the tests. The gate reads
QUICK_REFERENCE.md and the manifests off disk with fs; the test imports the .mjs
source directly (tsconfig.scripts.jsonallowJs, types inferred, nothing compiled).
Nothing here has a dist/, so no rebuild leg applies.

legpredictedobserved
A — revert only the changeset:version wiring1 failed test / 1 failed file; gate file green at 8 passed1 failed, 19 passed; Test Files 1 failed / 1 passed — the failure is `changeset:version` invokes the sync script after bumping the manifests
B — revert only QUICK_REFERENCE.md to origin/main7 failed tests / 2 failed files: 2 in the gate, 5 in the sync test (in-sync, rewrites-Version, touches-nothing, pnpm-slot, refusal)7 failed, 13 passed / 2 failed files — those exact seven

Leg A is the one that matters: it is the difference between this card and a one-line edit.
With the wiring gone every other test still passes and the gate is still green — the tree
looks fixed and the next release reddens main again. That single assertion is what makes
the recurrence visible.

Verification (all from the repo root, at 89cb6b0d1)

pnpm exec vitest run scripts/__tests__/ → 58 files, 1549 tests passed
pnpm type-check:scripts → exit 0
pnpm lint:root → 26 warnings, 0 errors
pnpm check:control-bytes → OK (4480 tracked files)
pnpm changeset:check → OK (fixed group, no major)
node scripts/check-changeset-presence.mjs → OK
pnpm docs:check-links → valid across 13 scan roots
pnpm type-check:coverage / lint:coverage → 46/46, exit 0

Plus a manual control-byte scan of the untracked-at-the-time files (the tracked-file gate
could not see them yet): no hits.

pnpm check:published-dist was not run — it exceeded the 10-minute foreground budget
and it is outside this diff's surface (it guards changeset:publish, unchanged here).

Changeset

Empty frontmatter, deliberately. No package src/ is touched, so nothing publishes; per
AGENTS.md that is the legal first-class way to declare "this releases nothing" rather than
leaving it undeclared. Scoring it patch would publish 39 packages for a docs-and-tooling
change.

What this does not cover

The React row states a variable-length list of majors; if that list ever changes length
the script refuses the row and exits non-zero, failing the release loudly instead of
guessing which slot gets which value. Same for a literal wrapped across a line break. Both
land a human on the row — which is the right outcome, and neither has ever happened: the
only rows that have ever drifted are Version (this family) and Spec/Client (#4977,
whose own channel was closed by #4973).

Generated by Claude Code


Generated by Claude Code

…set:version (#5394)
The "Current Release" block fossilised once per release, three times
(#4642, #4977, #5394). Its own preamble assumed a human holds the anchor
when it moves — but the anchor moves inside `changeset version`, run by
`changeset-release.yml` with nobody present, and the release PR is not a
backstop: every `ci.yml` run on `changeset-release/main` is
`conclusion: action_required` with `created_at == run_started_at`,
because a GITHUB_TOKEN-authored PR starts no workflows. The first thing
that reads a release is the push build on `main`, which is why `main` —
never a PR — went red every time.
So the derivation has to RUN where the anchor moves. `changeset:version`
now runs `scripts/sync-quick-reference-release.mjs`, which rewrites only
the version literals of the anchored rows, preserving each row's
hand-written anchor note. It refuses (non-zero) rather than guessing when
a row's literal count no longer matches its anchor, and leaves the
unanchored TypeScript row alone.
`quick-reference-current-release-4143.test.ts` is untouched — it stays the
judge. The new test pins the wiring in both places (`package.json` and the
workflow's `version:` input) and pins that the writer and the judge spell
`VERSION_LITERAL` identically.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

configurationdependenciesdocumentationImprovements or additions to documentationtests

Projects

None yet

2 participants

@os-support-ai@claude