Skip to content

[finding] check:release-page-status guards the release-status blockquote but not section coverage — a published minor with no section on its per-major page fails nothing #10268

Description

@os-zhuang

Filed unassigned while discharging #10232 (authoring the missing 17.1.0 section). This is item 4 of that card's suggested shape, which #10232's triage explicitly deferred: "Item 4 (mechanising 'published version has no section') is out of scope here — if wanted it should be a separate finding after 1–3 land." 1–3 have landed, so here it is.

The gap, stated precisely

scripts/check-release-page-status.mjs (from #8892) already mechanises half of the detectable surface, and it works — it caught a stale wording during #10232's own implementation, red on a novel phrasing no phrase list had seen:

• content/docs/releases/v17.mdx: the release-status blockquote never states that a 17.x
version is released. @objectstack/spec 17.x is GA, so the page must say so in a form a
reader and this gate can both find …

What it checks is keyed on the major: releasedAssertionRe(major) matches \b<major>\.\d+\.\d+ … (?:is|was|has been) (?:released|published|…). That predicate is satisfied by any17.x.y claim on the page. So:

  • ✅ caught: a v17 page that still describes the series as a pre-release, or that asserts no release at all.
  • not caught: a v17 page whose blockquote says 17.0.0 is released while latest has been 17.1.0 for six days, with no 17.1.0 section anywhere on the page.

That second state is exactly what #10232 measured, and the index-entry arm has the same shape — it flags a parenthetical naming a prerelease, but not one naming a superseded stable version (current series: 17.0.0 while latest is 17.1.0 passes today).

This is now the third occurrence of the class

check:docs-image-tag's header states the repo's own threshold:

Two occurrences of an identical drift is where a mechanical guard beats fixing the third one by hand.

What is and is not generatable

⚠️ Worth stating explicitly, because it is the reason item 4 was deferred rather than bundled: curated release prose cannot be generated from changesets without losing the thing that makes it curated. #10232's section took a full read of 69 CHANGELOG.md sections (314 distinct entries) and a lot of judgement about what is user-facing.

But the absence is mechanically detectable without writing a word of prose. Two candidate assertions, both computable from artifacts already in the tree:

  1. Section coverage — for every <major>.<minor>.0 with a ## <version> section in packages/spec/CHANGELOG.md (the instrument check-release-page-status.mjs already reads and already trusts for its GA predicate), content/docs/releases/v<major>.mdx must carry a heading naming that minor. The v16 and v17 pages both use # What's new in <version> plus ### <version> in the upgrade checklist, so the shape is already conventional.
  2. Index currency — the (current series: <version>, …) parenthetical must name the newest released version of that major, not merely a non-prerelease one.

Both are shrink-only ratchets in the same style as the existing gate, and both would have gone red on 2026-08-20 without anyone reading the page.

Not claimed

  • I have not written either check, and I have not measured what an older page (v9–v15) would do under assertion 1 — the existing gate deliberately floors at v16 under a maintainer ruling (「只负责 v16 以后的」), and any new assertion should almost certainly inherit that same floor rather than invent its own.
  • Whether assertion 1 should be an error or an advisory is a real question: a minor published minutes ago has legitimately not been documented yet, so the useful form may be a grace window or a latest-tag-only trigger rather than a hard fail on every PR. I have no recommendation with evidence behind it.
  • I have not checked whether docs/releases-maintenance.md already prescribes a release-notes step that was simply skipped — [finding] 17.1.0 published on 2026-08-20 with a 69-package train and no release notes — the v17 page and the releases index both still end at 17.0.0 #10232 flagged that as unexamined and I did not open it either.

Cross-links: #10232 (this release's manual fix), #8892 (the existing gate), #8917 (the v16 occurrence), #8882 / #8886 (the GA-cut occurrences).

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions