Skip to content

docs(protocol): the backward-compatibility page states the 17.x launch-window rule and the v18 prerelease regime - #22988

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-22964-backward-compat-regime
Oct 12, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-22964-backward-compat-regime

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #22964
Clause-②: no

A docs-only PR on a hand-written page, content/docs/protocol/backward-compatibility.mdx, which is not release-owned. It changes one file by +18 / -16 lines (34 changed lines). It edits no gate script, takes no release action, and changes nothing under content/docs/releases/**. The new wording matches the releases index's "Versioning policy" section as PR #22963 left it on main (246edf5b3).

What was false

On main at 19805d895 (this PR's base), the page said four things that were not true:

  • the launch-window rule ("a breaking change ships as a MINOR release") "is in force today", and it overrides the tables;
  • scripts/check-changeset-no-major.mjs "fails any pull request that declares a major bump";
  • "The current release, 17.2.0, is a MINOR";
  • the launch-window section "is the operative rule wherever any part of this page disagrees".

The seat listed the line numbers on da9c2bf2f. They are the same on 19805d895: the last commit to touch the file is 165587ee6.

The main facts each change rests on

  • F1. .changeset/pre.json reads {"mode": "pre", "tag": "next"}.
  • F2. In scripts/check-changeset-no-major.mjs, judge() at :673 reads if (pre?.mode === 'pre') return { verdict: 'exempt', ... }, and the RC EXEMPTION paragraph is at :105. Outside pre mode, :674 returns enforce. The header also documents an allow-major label escape hatch outside pre mode, so the past-tense sentences say the guard failed "a" pull request, not "any".
  • F3. release.yml triggers only on a push to main (:177-:180). The v18 page (content/docs/releases/v18/index.mdx) says every release cut from main is the next 18.0.0-next.N, and that latest stays on 17.x (:6-:8, :27-:29).
  • F4. npm view @objectstack/spec dist-tags, read 2026-10-12, shows latest: 17.7.0 and rc: 17.0.0-rc.6, and no next tag. No 18.0.0-next.N has been published yet. The new sentences say what a cut from main produces. None of them says a cut has happened.
  • F5. packages/spec/package.json is 17.7.0, and the CHANGELOG's newest heading is ## 17.7.0, so "17.2.0" was not the current release. The v17 page's banner calls 17.1.0 through 17.7.0 "minors by version number, not by blast radius". It also says 17.0.0 was cut from an rc train after changeset pre exit.
  • F6. .changeset/config.json's fixed[0] has 70 members. Both sentences that check:lockstep-package-count anchors on are kept word for word.

Each changed sentence: before, after, and the fact it rests on

  1. Top callout, lead (:18)
  2. Top callout, override clause (:18)
    • Before: "This rule is in force today and overrides the MAJOR/MINOR mapping in the tables below wherever they disagree; read [Launch Window] ... before you plan an upgrade."
    • After: "read [Launch Window] ... before you upgrade across 17.x."
    • Rests on: F1 and F2. The rule is not what governs a cut from main today. The tables now label their 17.x mapping (see 11), so there is nothing left to override.
  3. Top callout, the v18 regime (new paragraph)
  4. Versioning Strategy, intro (:21)
  5. SemVer table, MINOR row (:26)
    • Before: "New features — and, during the launch window, breaking changes"
    • After: "New features — and, in the 17.x minors, breaking changes"
    • Rests on: F5.
  6. SemVer Guarantees, Zod schemas bullet (:31)
    • Before: "which during the launch window also ships in a MINOR release."
    • After: "which the 17.x minors also shipped in a MINOR release."
    • Rests on: F5.
  7. Phase 3 heading (:66)
    • Before: "Phase 3: Removal (MINOR release, during the launch window)"
    • After: "Phase 3: Removal (MINOR release in 17.x, the next 18.0.0-next.N on the v18 line)"
    • Rests on: F3 and F5. The heading's slug changes. git grep 'backward-compatibility#' finds exactly one inbound fragment link to this page, releases/index.mdx:79, and it targets the launch-window anchor. In ../objectui the same grep finds nothing.
  8. Timeline mermaid, node C (:80)
    • Before: "(MINOR release, during the launch window)"
    • After: "(MINOR release in 17.x, the next 18.0.0-next.N on the v18 line)"
    • Rests on: F3 and F5.
  9. "No minimum survival window" callout (:84)
    • Before: "during the launch window that removal itself lands in a MINOR release, so a MINOR bump is where you should expect a removal to arrive."
    • After: "in the 17.x minors that removal itself landed in a MINOR release, so a MINOR bump was where to expect a removal to arrive. On the v18 line it lands in the next 18.0.0-next.N."
    • Rests on: F3 and F5.
  10. What Constitutes a Breaking Change, lead (:93)
    • Before: "during the launch window every row below — breaking or not — ships in a MINOR or PATCH release, so the bump size does not tell you whether you have work to do."
    • After: "in the 17.x minors every row below — breaking or not — shipped in a MINOR or PATCH release, and on the v18 line every row ships in the next 18.0.0-next.N, so on neither line does the bump size tell you whether you have work to do."
    • Rests on: F3 and F5.
  11. Change-type table, column header (:95)
    • Before: "Version Impact (launch window)"
    • After: "Version Impact (17.x minors)"
    • Rests on: F5. The cells are unchanged, and so is the table's shape.
  12. Breaking Change Process, step 4 (:115)
    • Before: "During the launch window the breaking change ships in the next MINOR version ... scripts/check-changeset-no-major.mjs fails any pull request that declares a major bump, because under lockstep one major would promote all 70 published packages."
    • After: the same sentence in the past tense ("In the 17.x minors ... shipped ... failed a pull request that declared"). Then: "On the v18 line it ships in the next 18.0.0-next.N: the guard stands aside in pre mode, so a pull request may declare a major bump." Then the v18 link.
    • Rests on: F1 to F3 and F6. The lockstep anchor would promote all 70 published packages. is kept word for word.
  13. Export Stability bullet (:174)
    • Before: "during the launch window it ships in a MINOR release"
    • After: "the 17.x minors shipped it in a MINOR release, and on the v18 line it ships in the next 18.0.0-next.N"
    • Rests on: F3 and F5.
  14. Launch Window callout (:188)
    • Before: "This exception overrides the MAJOR/MINOR mapping above — read it before you plan an upgrade. ... while the launch window is open a breaking change ships as a MINOR ... The current release, 17.2.0, is a MINOR and it contains a documented breaking change."
    • After: "The 17.x minors ran under this exception — read it before you upgrade across them. ... in the 17.x minors a breaking change shipped as a MINOR release rather than burning a MAJOR, so those minors contain documented breaking changes. The v18 line is a major in prerelease: every release cut from main is the next 18.0.0-next.N on npm's next tag, while latest stays on 17.x." Then the v18 link.
    • Rests on: F3 to F5. The hard-coded current-release number is dropped rather than replaced, so it cannot go stale again. Readers who arrive from the releases index's anchor link land on this callout.
  15. Which surfaces this covers (:193; tense only)
    • Before: "This is not scoped ... No published surface is exempt."
    • After: "It was not scoped ... No published surface was exempt."
    • The lockstep sentence and the all **70** packages published from this repository anchor are unchanged (F6).
  16. The guard paragraph (:195)
    • Before: "The convention is enforced ... scripts/check-changeset-no-major.mjs fails any pull request that introduces a major bump ..."
    • After: the same sentence in the past tense, then "Changesets is now in pre mode with the tag next, and the guard stands aside in pre mode, so a pull request on the v18 line may declare a major bump."
    • Rests on: F1 and F2.
  17. The MAJOR paragraph (:203)
    • Before: "MAJOR releases do still happen — 17.0.0 was cut ... — but an individual breaking change does not, on its own, force one."
    • After: "MAJOR releases do still happen — 17.0.0 was cut ..., and the v18 line is a major in prerelease — but in the 17.x minors an individual breaking change did not, on its own, force one."
    • Rests on: F1 and F5.
  18. When it stops applying (:207). The override clause is rewritten, not removed (H3).
    • Before: "The tables and deprecation timeline above now state this rule directly, so the page no longer contradicts itself. ... Until it closes, this section is the operative rule wherever any part of this page disagrees."
    • After: "The tables and deprecation timeline above state this rule for the 17.x minors directly, beside what the v18 line does. ... For the 17.x minors, this section was the operative rule wherever any part of this page disagreed. For the 18.0.0-next.N prereleases, the operative rule is how a breaking stage lands on the v18 line."
    • Why rewritten: the page still carries guarantees scoped to "within a MAJOR version" (:33-:36, :179-:181). One example is "Enum values are append-only within a MAJOR version. Existing values are never removed or renamed in MINOR/PATCH releases". The 17.x minors did not keep those guarantees: the change-type table's own 17.x column marks "Removing an enum value | Yes | MINOR". The clause is what reconciled the two. Removing it would leave those guarantees unqualified against 17.x history, so it now speaks in the past tense for the 17.x minors and sends 18.0.0-next.N readers to the v18 section.

Where this departs from the card's direction, or stops short of it

  • Anchor. The heading text "Launch Window: MINOR Releases Can Contain Breaking Changes" is unchanged, so #launch-window-minor-releases-can-contain-breaking-changes still resolves, and releases/index.mdx:79 is not edited. The heading stays true: the 17.x minors are MINOR releases that contain breaking changes (F5).
  • Not written: "breaking changes land as major changesets". The card rules it out. The v18 sentences say only what the guard admits and what a cut from main publishes.
  • Kept word for word: "the window closes at GA, and strict SemVer resumes from that point". It does not state the current regime. It restates the guard header's END CONDITION ("at GA ... the group returns to STRICT SEMVER"). The page says nothing new about what happens when pre mode exits.
  • Kept as history: :75's shipped examples (17.2.0, 15.1.0).
  • No date, and no version beyond 18.0.0-next.N.
  • H5: one file, 34 changed lines.

Tests (all at e8e1525ed, the HEAD of this branch)

  • Gate derivation. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 41 commands at e8e1525ed. That is the same set as the dispatch's lead list. I ran all 41 and captured each exit code before any pipe.
  • Reconciliation. --ran printed: "41 derived famil(ies) accounted for — 41 run, 0 NOT-MEASURED (a DERIVED zero — all 41 recorded an exit code and none of them is 3)."
  • Prerequisite refusals. Five gates first refused on missing build output: check:doc-formula-expressions (3), check:doc-security-posture (3), check:docs (1, "Generate it first: gen:schema"), check:skill-examples (3) and check:docs-transcript-drift (3). These were refusals, not findings.
  • Builds. I built @objectstack/lint... (4 tasks) and then @objectstack/client-react... (35 tasks) under the verify lock. Both printed VERDICT command-exit 0. Re-run after the builds, all five exit 0.
  • Verdict lines:
    • check:doc-anchors: "489 internal #fragment link(s) across 419 source file(s) all resolve to a real heading".
    • check:lockstep-package-count: "all 3 occurrence(s) agree with the true count (70)".
    • check:docs: "226 generated files in sync with packages/spec".
    • check:skill-examples: "262 prose examples type-check across 3 surface(s)".
    • check:nul-bytes: "OK (scanned 10999 text file(s) ... no raw ASCII control bytes)".
  • MDX syntax. The page body compiles with the workspace's @mdx-js/mdx 3.1.1. Negative control: an unclosed Callout is refused ("Expected a closing tag for Callout").
  • Lint, a proven narrowing rather than a skipped run:
    • The population comes from eslint's own config. Every files glob in eslint.config.mjs is a {ts,tsx,mts,cts,js,jsx,mjs,cjs} spelling or narrower. None of them matches .mdx.
    • npx eslint --no-inline-config --format json on the page returned 1 file, 0 errors and 1 warning: "File ignored because no matching configuration was supplied."
    • The config never enables type-aware linting (eslint.config.mjs :328), and the diff changes only a file no config object matches, so no linted file's verdict can move.
  • Not run locally. No package is touched, so no package test or typecheck is owed. Build Docs and Test Core belong to CI and were not measured here.
  • skip-changeset. I read 70 non-private tracked manifests, and no files[] entry names content/docs. In @objectstack/spec's shipped paths (dist, llms.txt, prompts, README.md), "launch-window-minor-releases" and "This rule is in force today" match 0 files. Positive control: "defineStack" matches 87.

Acceptance notes

  • Untouched, outside the regime sentences: the "Support Windows" table (:153-:157). It promises patches to the current and previous MAJOR. release.yml publishes only from main (F3), which is in pre mode, and npm shows no 16.x after 16.1.0 (2026-07-22), although 17.0.0 shipped on 2026-08-14. No lane exists to publish a maintenance patch for a line other than the one main is on. I did not file this; it is reported to the seat.
  • Untouched: the within-a-MAJOR guarantee sentences (:33-:36, :179-:181). The rewritten clause in 18 reconciles them with the 17.x history.

Generated by Claude Code

…h-window rule and the v18 prerelease regime

The page said the launch-window rule (a breaking change ships as a MINOR)
is in force today, that check-changeset-no-major.mjs fails any pull
request declaring a major, and that the current release is 17.2.0. On
main, Changesets is in pre mode with the tag `next`, the guard stands
aside in pre mode, and every release cut from main is the next
18.0.0-next.N. The launch-window sentences now describe the 17.x minors
in the past tense, the v18 line is stated beside them with a link to the
v18 page's breaking-stage section, the hard-coded current-release number
is dropped, and the section's override clause is scoped to the 17.x
minors. The launch-window heading text, and so its anchor, is unchanged.

Claude-Session: https://claude.ai/code/session_012yK1ddAdAqfzwigRHZq3r2
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Oct 12, 2026
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 12, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 12, 2026 08:07
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 12, 2026 08:08
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 12, 2026
Merged via the queue into main with commit 0524c16 Oct 12, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22964-backward-compat-regime branch October 12, 2026 08:36
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 size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants