Skip to content

docs(releases): split the v17 page per minor, and draft the missing 17.4.0 section - #17105

Merged
huangyiirene merged 5 commits into
mainfrom
claude/lane-task-status-stats-ig1o32
Sep 9, 2026
Merged

docs(releases): split the v17 page per minor, and draft the missing 17.4.0 section#17105
huangyiirene merged 5 commits into
mainfrom
claude/lane-task-status-stats-ig1o32

Conversation

@huangyiirene

@huangyiirene huangyiirene commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Docs-only restructure, on the maintainer's direct instruction (「v18 起按新结构建,v17 回填。同意,现在就处理,包括刚发布了 17.4」). ⛔ Not a rider on a code change — content/docs/releases/** is edited here and nowhere else, per the content/docs/releases/ guardrail.

Governed-surface check. Today's register, printed rather than recalled — docs/adr/** · .claude/** · skills/** · AGENTS.md · CLAUDE.md. This PR's 14-file list hits none of them (content/docs/** and scripts/** are not on the register), so Prime Directive #14 does not apply and the merge queue is the landing path (AGENTS.md §7).

Why

content/docs/releases/v17.mdx had reached 5,611 lines / 369 KB — 5.7× the finished v16 page (1,052 lines), at 17.3.0, with 17.4.0 still to land. At roughly 90k tokens that is two thirds of the budget this project advertises for an entire application, in one release-notes file.

And the reader's question is per-minor, while the page answered it in three places up to 1,200 lines apart: What's new in 17.2.0 (line 4042), Breaking changes & migration in 17.2.0 (4059), and 17.2.0 under a separate Upgrade checklist heading (5284).

What changed

v17.mdx becomes v17/, one self-contained page per minor — what it changed, what breaks, and its own upgrade checklist:

page lines
v17/index.mdx 199
v17/17-0.mdx 1,919
v17/17-1.mdx 720
v17/17-2.mdx 377
v17/17-3.mdx 783
v17/17-4.mdx 449

Sidebar: Releases > v17 > [v17, 17.4.0, 17.3.0, 17.2.0, 17.1.0, 17.0.0].

The filenames are dotless on purpose. They first landed as 17.0.mdx17.4.mdx and "Check Documentation Links" went red with 20 File not found errors, all of them /docs/releases/v17/17.N. Reproduced against the pinned lychee 0.24.2 with the workflow's own argv and isolated in a three-link fixture:

/docs/t/17.3   (17.3.mdx exists)  -> ERROR  File not found
/docs/t/17-3   (17-3.mdx exists)  -> OK
/docs/t/plain  (plain.mdx exists) -> OK

--fallback-extensions mdx,md does not fire when the last path segment already contains a dot — lychee reads .3 as the extension and never tries .mdx. It is the filename shape, not the split, that the checker cannot follow, so the slug drops the dot. Frontmatter titles are untouched, so the sidebar still reads 17.0.017.4.0 and the slug is invisible to readers.

Content is conserved. Every line of the old body appears in exactly one new file, verified by set difference — that check caught the ## Upgrade checklist section intro (22 lines, including the callout recording that only the 17.3.0 list was written against a measured upgrade) being dropped; it now lives on index.mdx, linked from each minor. The ### 17.x.0 checklist headings are kept verbatim, so their #1730-style anchors survive the move.

The rc.0 … rc.6 archive is deleted — 1,688 lines, 30% of the old page, describing changes between release candidates of a version that shipped 2026-08-14, all of it contained in the shipped 17.0.0. "When did X change during the rc train" is a changelog question; 17.0.0's page now says so where the archive used to be linked.

17.4.0 — published with no section anywhere

17.4.0 went out 2026-09-09 and releases/index.mdx already named it the current series, but no page carried it.

v17/17-4.mdx is a machine draft and says so at the top. It was built by de-duplicating the 396 changesets that make up 17.4.0 across all 61 package CHANGELOG.md files — a changeset that bumps six packages appears once, not six times — split into 35 carrying a breaking marker, 140 other minor entries, and 221 patch entries reported as counts rather than enumerated.

It carries the same section shape as its siblings so a reader lands where they expect, but only the shape is finished. The two sections no mechanical pass can produce say so where they stand rather than being filled with a guess:

  • Highlights — a judgement about audience, not a transformation of the entries.
  • Upgrade checklist — a walked route; nobody has walked 17.3.0 → 17.4.0.

The Console section names the pin endpoints it can measure (00d3f09c500c53ded82bf7a4, bumped by 30b09907) and states plainly that the intermediate bumps are not enumerated, because this checkout's .objectui-sha history does not carry them.

⛔ Deciding what is user-facing is the maintainer's judgement at release time. This page is raw material for that pass, not a substitute for it.

Three gates learn the second layout — none is weakened

check-release-notes (owns page existence) and check-release-page-status (owns what the page says) now accept either v<major>.mdx or v<major>/index.mdx. Neither layout is deprecated, and no baseline and no exception list is introduced — v16 and earlier stay flat and keep passing unchanged.

check-release-section-coverage is the third, and it is the one this PR would otherwise have quietly blinded. It looked only for a flat page, so after the split it printed (v17: … skipped) and then reported "2 GA major(s) in scope (v16, v17); every one has a heading on its major's release page" — naming v17 as covered while asserting nothing about it. Its source justifies that skip explicitly by the two sibling gates going red on the same fact, and this PR taught both of those the folder layout, so the justification was gone. It now reads either layout, taking the folder as one corpus: "some heading names this minor" is a property of the major's prose wherever it is written, and moving ## What's new in 17.1.0 from line 3475 of one file to line 5 of another is not a coverage change.

Proven to measure rather than merely to stop printing "skipped": with every heading naming the 17.4 series mutated away, the gate reports the finding against content/docs/releases/v17/ and exits 0 advisory / 1 --strict. Its 50-case self-test is unchanged and still passes. (A first mutation attempt on 17.2 wrongly passed — 17-3.mdx carries a heading that mentions 17.2.0 in passing. That looseness is pre-existing: the old flat page contained the same heading.)

Two generated artifacts follow their files

scripts/docs-audit/handwritten-docs.json is generated output — the audit scope, derived as content/docs/**/*.mdx minus the generated references, with hand-editing rejected by the gate whatever the contents. check:docs-audit-scope went red naming both directions of the drift (one listed path gone, six real pages unlisted); regenerated with the gate's own --write, and the diff is exactly those six for that one. Left unfixed, a "FULL audit" would have called itself full while skipping every v17 page, and an agent pointed at the dead path would report "0 fixes" — indistinguishable in the summary from a page read and found accurate.

role-word-baseline.json records a pure relocation: one row, path only, content/docs/releases/v17.mdx: 2v17/17-0.mdx: 2. Count unchanged, nothing else re-baselined in the same stroke. One reserved word appearing in a changeset's own headline is elided in 17-4.mdx with the elision stated inline, rather than silently rewriting a verbatim quote.

upgrading.mdx follows the checklist links to their new pages and gains a 17.4.0 row that says plainly its checklist is not written.

Verification

gate result
Check Documentation Links (pinned lychee 0.24.2, workflow argv) 2,152 links, 0 errors — was 20
check-docs-audit-scope exit 0
check-release-notes · check-release-page-status exit 0 — both GA majors in scope
check-release-section-coverage (live + 50-case self-test) exit 0, and observed going red under mutation
check-role-word · check-doc-anchors · check-docs-single-h1 exit 0
check-doc-authoring · check-docs-image-tag · check-docs-redirects exit 0
check-release-index-currency-sync · check-quick-reference-counts exit 0
check-corpus-claim-drift · check-published-readme-links · check-org-identifier exit 0

Content conservation was verified by comm over the sorted old body against the sorted new files; the only line that does not appear verbatim is the one intra-page anchor deliberately rewritten to point across files. An anchor audit over the split files reported 0 broken intra-page links.

skip-changeset: the diff publishes nothing from any released package (content/docs/** and four files under scripts/).

🤖 Generated with Claude Code

https://claude.ai/code/session_016M1gHPfToXY4sUdzsD2CHa

…7.4.0 section

`content/docs/releases/v17.mdx` had reached 5,611 lines / 369 KB — 5.7x the
finished v16 page, at 17.3.0, with 17.4.0 still to land. At roughly 90k tokens
it is two thirds of the budget this project advertises for an entire
application, in one release-notes file.

It is now a folder, one self-contained page per minor:

  v17/index.mdx            major landing: intro, release status, the
                           cross-release upgrade-checklist guidance, References
  v17/17.0.mdx    1,917    highlights + detail + its own upgrade checklist
  v17/17.0-prerelease.mdx  1,688  archive: the rc.0 … rc.6 train, 30% of the
                           old page and read by nobody upgrading between
                           shipped versions
  v17/17.1 .. 17.3.mdx     the same shape, 375-783 lines each
  v17/17.4.mdx             NEW — see below

A reader's question is per-minor, and the old page answered it in three places
1,200 lines apart: "What's new in 17.2.0", "Breaking changes & migration in
17.2.0", and "17.2.0" under a separate "Upgrade checklist" heading. Each minor
page now carries all three.

Content is conserved: every line of the old body appears in exactly one new
file, verified by set difference. The `### 17.x.0` checklist headings are kept
verbatim, so their `#1730`-style anchors survive the move.

17.4.0 was published on 2026-09-09 — the releases index already named it the
current series — and had no section on any page. `v17/17.4.mdx` is a MACHINE
DRAFT and says so at the top: 396 changesets de-duplicated by hash across all
61 package changelogs (a changeset that bumps six packages appears once), split
into 35 carrying a breaking marker, 140 other minor entries, and 221 patch
entries reported as counts rather than enumerated. No editorial pass has been
made, the Highlights section is deliberately absent rather than guessed, and
the upgrade checklist is not written because nobody has walked 17.3.0 → 17.4.0.
Deciding what is user-facing is the maintainer's judgement at release time.

Two gates learn the second layout rather than being weakened. `check-release-notes`
(page existence) and `check-release-page-status` (what the page says) now accept
either `v<major>.mdx` or `v<major>/index.mdx`; neither layout is deprecated and
no baseline or exception list is introduced. Both pass, as does
`check-release-section-coverage`, which skips v17 and names its own reason.

`role-word-baseline.json` records a pure relocation: the single row
`content/docs/releases/v17.mdx: 2` becomes `v17/17.0.mdx: 2`. Nothing else in
the baseline moved — the sum is unchanged and no other file was re-baselined in
the same stroke. One reserved word in a changeset's own headline is elided in
17.4.mdx with the elision stated inline, rather than silently rewritten.

`upgrading.mdx` follows the checklist links to their new pages and gains a
17.4.0 row that says plainly that its checklist is not written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016M1gHPfToXY4sUdzsD2CHa
…e 17.4.0 the sibling section shape

Two corrections to the split.

The rc.0 … rc.6 archive sat at the top level of `v17/`, so the sidebar listed it
as a peer of the five real releases. It is not a release — it is 17.0.0's own
pre-history — so 17.0.0 becomes a folder and the archive moves inside it:

  v17/17.0/index.mdx       the release
  v17/17.0/prerelease.mdx  the train that preceded it
  v17/17.0/meta.json

The archive is now one level down, reachable by expanding 17.0.0 rather than
sitting beside it, and its URL says the same thing:
`/docs/releases/v17/17.0/prerelease`. Its title is now "Pre-release train
(rc.0 … rc.6)" so the nav entry reads as an archive without opening it. The
minors that have no sub-pages stay flat files; a minor becomes a folder only
when it has something to nest.

17.4.0 now carries the same section shape as 17.1.0 through 17.3.0 —
"Highlights — 17.4.0", "What's new in 17.4.0" with "Breaking changes &
migration", "New capabilities", "Fixes" and "New in Console (Studio)" beneath
it, then "Upgrade checklist" — so a reader crossing releases lands where they
expect. Only the shape is finished. The two sections no mechanical pass can
produce say so where they stand instead of being filled with a guess:
Highlights is a judgement about audience, and the upgrade checklist is a walked
route nobody has walked for 17.3.0 → 17.4.0.

The Console section names the pin endpoints it can measure — `00d3f09c500c`
(the last of 17.3.0's four moves, per that page) to `53ded82bf7a4` (the value
of `.objectui-sha` on this tree, bumped by 30b0990) — and states plainly that
the intermediate bumps are NOT enumerated, because this checkout's history for
that file does not carry them. Naming the gap beats guessing the chain.

`role-word-baseline.json` follows the move: one row, path only,
`v17/17.0.mdx: 2` to `v17/17.0/index.mdx: 2`. Count unchanged, nothing else
re-baselined.

check-release-notes, check-release-page-status, check-role-word,
check-doc-anchors (337 fragment links, all resolving) and check-docs-single-h1
all pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016M1gHPfToXY4sUdzsD2CHa
…ing it

The rc.0 … rc.6 archive was 1,688 lines — 30% of the old monolithic v17 page —
describing changes BETWEEN release candidates of a version that shipped on
2026-08-14. The train it records ended 2026-08-10. Everything it carried is
contained in the shipped 17.0.0.

It had no good home. Flat inside `v17/` it sat in the sidebar as a peer of the
five real releases, which it is not. Nested under `17.0/` it forced a folder and
a fourth path segment into existence for one archive page, and made 17.0.0 the
only minor that expands. Both placements were wrong for the same reason: the
page does not earn a place in the reading path, so any place given to it is one
too many.

Deleted. `17.0` goes back to a flat file, the folder and its `meta.json` go with
it, and the sidebar loses the nesting level entirely:

  Releases > v17 > [v17, 17.4.0, 17.3.0, 17.2.0, 17.1.0, 17.0.0]

Nothing is lost that a reader can reach for. "When exactly did X change during
the rc train" is a changelog question, not a documentation-site one, and it is
answered by the `CHANGELOG.md` files inside the published npm tarballs and by
this repository's history. 17.0.0's own page now says that in place of the
archive link, rather than pointing at a page that is gone.

The two links into the archive — both written earlier in this same branch — go
with it. `role-word-baseline.json` follows the file back to the flat path:
`v17/17.0/index.mdx: 2` returns to `v17/17.0.mdx: 2`, count unchanged, nothing
else re-baselined.

check-release-notes, check-release-page-status, check-role-word,
check-doc-anchors and check-docs-single-h1 all pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016M1gHPfToXY4sUdzsD2CHa
@huangyiirene huangyiirene added documentation Improvements or additions to documentation skip-changeset PR has no user-facing published change; bypasses the changeset gate domain:devx labels Sep 9, 2026 — with Claude
…ng resolves them

The v17 split landed the per-minor pages as `17.0.mdx` … `17.4.mdx`, and
"Check Documentation Links" went red with 20 `File not found` errors, all of
them `/docs/releases/v17/17.N`.

Root cause, reproduced against the pinned lychee 0.24.2 with the workflow's own
argv and isolated in a three-link fixture:

    /docs/t/17.3   (17.3.mdx exists)  -> ERROR  File not found
    /docs/t/17-3   (17-3.mdx exists)  -> OK
    /docs/t/plain  (plain.mdx exists) -> OK

`--fallback-extensions mdx,md` does not fire when the last path segment already
contains a dot — lychee reads `.3` as the extension and never tries `.mdx`. It
is the filename shape, not the split, that the checker cannot follow.

So the slugs lose the dot. Nothing else moves:

  * `git mv` 17.N.mdx -> 17-N.mdx, contents untouched;
  * every `/docs/releases/v17/17.N` link rewritten to `17-N`;
  * `v17/meta.json` pages renamed to match;
  * the role-word baseline key follows the file (count stays 2 — pure
    relocation, the one path that gate documents as legitimate).

Frontmatter titles are unchanged, so the sidebar still reads 17.0.0 … 17.4.0 —
the slug is invisible to readers.

Verified locally with the workflow's exact command line: 2152 links, 0 errors
(was 20). check-release-notes, check-release-page-status, check-doc-anchors,
check-docs-single-h1 and check-role-word all pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016M1gHPfToXY4sUdzsD2CHa
…erage gate skipping v17

Two consequences of the v17 split that CI found and the local run had not.

1. `scripts/docs-audit/handwritten-docs.json` is GENERATED output — the audit
   scope, derived as `content/docs/**/*.mdx` minus the generated references, with
   hand-editing rejected outright. The split moved six pages under it, so
   `check:docs-audit-scope` went red naming both directions of the drift: one
   listed path gone, six real pages unlisted. Regenerated with the gate's own
   `--write`; the diff is exactly those six for that one, nothing else moved.

   Left unfixed this is not cosmetic: a FULL audit would have called itself full
   while silently skipping every v17 page, and an agent pointed at the dead path
   would report "0 fixes" — indistinguishable in the summary from a page that was
   read and found accurate.

2. `check-release-section-coverage` looked only for a flat `v<major>.mdx`, so
   after the split it printed "(v17: … skipped)" and then reported "2 GA major(s)
   in scope (v16, v17); every one has a heading on its major's release page".
   It was asserting nothing about v17 while naming it as covered.

   The skip is explicitly justified in the source by the two sibling gates going
   red on the same fact — and this PR taught both of them the folder layout, so
   that justification had gone. It now reads either layout, the folder as one
   corpus, because "some heading names this minor" is a property of the major's
   prose wherever it is written; the split moved `## What's new in 17.1.0` from
   line 3475 of one file to line 5 of another, which is not a coverage change.

   Proven to measure rather than merely stop printing "skipped": with every
   heading naming the 17.4 series mutated away, the gate reports the finding
   against `content/docs/releases/v17/` and exits 0 advisory / 1 --strict. Its
   50-case self-test is unchanged and still passes.

No gate is weakened and no baseline or exception list is added: one generated
artifact regenerated by its own generator, and one lookup taught the second
layout its two siblings already accept.

check:docs-audit-scope, doc-anchors, doc-authoring, docs-redirects,
docs-single-h1, release-notes, release-page-status, release-index-currency-sync,
role-word, quick-reference-counts, corpus-claim-drift, published-readme-links,
org-identifier and docs-image-tag all pass; lychee reports 2152 links, 0 errors.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016M1gHPfToXY4sUdzsD2CHa
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json f6b7c53db7b65bbfb019750efb4e545470b0c2b7packageMentionDocs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation domain:devx size/xl skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants