You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The docs site publishes a /next/ section that is meant to show unreleased documentation. Under the current trunk-based auto-publish model it cannot do that, and today it does something worse: it shows already-released documentation that /latest/ is missing.
This proposes gating breaking changes behind a next prerelease branch, which would make /next/ genuinely mean "not yet released" and remove the need to hand-sequence a major release.
Raising for discussion rather than acting — this changes contributor workflow and needs a repo settings change.
The problem
/next/ cannot diverge under auto-publish
release.yml runs on every push to main, and semantic-release releases from main. So:
A releasable commit (feat / fix / perf / refactor / revert / breaking) publishes the moment it merges. If its docs ride in the same PR — as they should — next and latest converge at merge time. The divergence window is the length of the release run.
The only genuine divergence is doc-only commits (docs:, chore:, test:, ci:), which by definition describe already-released behaviour. That is "corrections to current", not "next".
The case that would justify /next/ — writing docs ahead of a feature — is impossible, because merging the feature releases it.
/next/ only makes sense with a release train: accumulate changes, release deliberately. That is the develop → master model this repo deliberately dropped in #114.
What /next/ contains today
docs/next and docs/v2 differ in 7 files. The divergence is documentation for fluent chaining (called.once().withArg(...)), which shipped in v2.2.0 and is live on npm now.
$ diff -rq docs/next docs/v2
Files docs/next/ai/canonical-examples.md and docs/v2/ai/canonical-examples.md differ
Files docs/next/ai/common-mistakes.md and docs/v2/ai/common-mistakes.md differ
Files docs/next/ai/decision-tree.md and docs/v2/ai/decision-tree.md differ
Files docs/next/api/index.md and docs/v2/api/index.md differ
Files docs/next/api/types.md and docs/v2/api/types.md differ
Files docs/next/guide/expectations.md and docs/v2/guide/expectations.md differ
Files docs/next/guide/typescript.md and docs/v2/guide/typescript.md differ
Both directories were last touched by the same commit (75bd576, 2026-04-25). docs/v2 was snapshotted from a state predating the v2.1/v2.2 feature docs, and the release-time snapshot step has never worked (see #132).
Net effect: /latest/ — where the site root redirects every visitor — is missing documentation for features released four months ago, and the fix is filed under a heading that says "unreleased".
Why it matters now
#135 is a breaking change (feat!) sitting green against main. Merging it publishes v3.0.0 immediately, because release.yml fires on every push to main. There is no gap in which to prepare docs, README, or the version switcher — the merge is the release.
That is workable with careful sequencing, but it means every future major carries the same one-shot risk.
Auto-publish on main is unchanged — non-breaking changes keep shipping on merge. Breaking changes never touch main, so they cannot trigger a major before we intend it.
Day-to-day
Change
Target
Result
fix: / feat: / perf:
main
auto-publishes 2.x, exactly as today
feat!: / BREAKING CHANGE:
next
publishes 3.0.0-next.N on the next tag
Ship the major
PR next → main
cuts 3.0.0 stable
next can be ephemeral
semantic-release/lib/branches/expand.js intersects the configured branches with the branches that actually exist on the remote, so a configured-but-missing branch produces no entries rather than an error. The config can stay in .releaserc.json permanently while the branch only exists when a breaking change is in flight, then gets deleted after the major ships.
That matters here — deride has had 3 majors in its life (v0, v1, v2), so a permanently-maintained parallel branch would be idle almost all the time.
npm authentication is unaffected
The trusted publisher configured for #134 is pinned to org / repo / workflow filename / environment — not to a branch. Prereleases from next authenticate over the same OIDC path with no registry-side change.
Docs wiring
A Pages deploy replaces the whole site, and a build on one branch cannot see the other's docs. So main owns the deploy and pulls the prerelease docs at build time:
# docs.ymlon:
push:
branches: [main, next]paths: ['docs/**', '.github/workflows/docs.yml', 'package.json', 'pnpm-lock.yaml', 'brand/**']steps:
- uses: actions/checkout@v6with: { ref: main, fetch-depth: 0 }
- name: Overlay in-development docs from the next branchrun: | if git ls-remote --exit-code --heads origin next >/dev/null; then git fetch origin next --depth=1 git checkout FETCH_HEAD -- docs/v3 fi # absent -> no prerelease section, cleanly
- run: pnpm docs:build
config.ts would list whichever docs/v* directories exist, so the switcher gains and loses the prerelease entry automatically. hasNextVersion becomes a real signal instead of the always-true comparison it is today.
Suggested naming: use /v3/, not /next/. A version-pinned URL works from day one, survives the stable release without changing, and means /v2/ and /v3/ are both available throughout. Label it "v3 (prerelease)" in the switcher. /next/ could remain as a redirect to the current in-development major if a stable "show me unreleased" link is wanted.
Blocker — repo merge settings
The repository currently allows squash merges only:
Promoting next → main by squash collapses every conventional commit into one, so semantic-release sees a single message and the release is wrong or no-ops.
CLAUDE.md already states:
Do NOT squash-merge release PRs. … Merge with "Create a merge commit" or "Rebase and merge" — preserves the individual conventional-commit messages.
That instruction is currently impossible to follow, because squash is the only method enabled. This is worth fixing regardless of whether this proposal is adopted.
Costs
Two branches to keep in sync; docs and README are the likeliest conflict sites.
A repo settings change (enable merge commits) that is not optional.
Contributors need to know which branch to target — requires a CONTRIBUTING / CLAUDE.md rule.
More CI minutes, and npm accumulates prerelease versions (normal, but visible on the versions page).
Roughly three workflow/config files plus the docs overlay logic.
Worth it if a major is something we want to develop and dogfood over days or weeks. Overkill if a major is a single PR merged the same afternoon.
Alternative — drop /next/ instead
If the answer is "majors are rare and land in one go", the honest move is to delete /next/ rather than fix it:
docs/v2/ — the v2 line, frozen when v3 ships
docs/v3/ — the live tree for the current major
docs/latest — symlink to the current major
No prerelease branch, no overlay, no release-time git writes. Version-pinned URLs still work. This is less machinery and removes the same class of bug, but gives up the ability to publish and dogfood an unreleased major.
Decisions needed
Do we want a prerelease channel at all, or is "majors land in one PR" the accepted model? This is the fork in the road; everything else follows.
Enable merge commits? Needed for this proposal, and needed for CLAUDE.md's existing guidance to be followable either way.
Summary
The docs site publishes a
/next/section that is meant to show unreleased documentation. Under the current trunk-based auto-publish model it cannot do that, and today it does something worse: it shows already-released documentation that/latest/is missing.This proposes gating breaking changes behind a
nextprerelease branch, which would make/next/genuinely mean "not yet released" and remove the need to hand-sequence a major release.Raising for discussion rather than acting — this changes contributor workflow and needs a repo settings change.
The problem
/next/cannot diverge under auto-publishrelease.ymlruns on every push tomain, and semantic-release releases frommain. So:feat/fix/perf/refactor/revert/ breaking) publishes the moment it merges. If its docs ride in the same PR — as they should —nextandlatestconverge at merge time. The divergence window is the length of the release run.docs:,chore:,test:,ci:), which by definition describe already-released behaviour. That is "corrections to current", not "next"./next/— writing docs ahead of a feature — is impossible, because merging the feature releases it./next/only makes sense with a release train: accumulate changes, release deliberately. That is thedevelop→mastermodel this repo deliberately dropped in #114.What
/next/contains todaydocs/nextanddocs/v2differ in 7 files. The divergence is documentation for fluent chaining (called.once().withArg(...)), which shipped in v2.2.0 and is live on npm now.Both directories were last touched by the same commit (
75bd576, 2026-04-25).docs/v2was snapshotted from a state predating the v2.1/v2.2 feature docs, and the release-time snapshot step has never worked (see #132).Net effect:
/latest/— where the site root redirects every visitor — is missing documentation for features released four months ago, and the fix is filed under a heading that says "unreleased".Why it matters now
#135 is a breaking change (
feat!) sitting green againstmain. Merging it publishes v3.0.0 immediately, becauserelease.ymlfires on every push tomain. There is no gap in which to prepare docs, README, or the version switcher — the merge is the release.That is workable with careful sequencing, but it means every future major carries the same one-shot risk.
Proposal
Use semantic-release's prerelease branch support.
main2.3.0,2.2.1latestnpm i deridenext3.0.0-next.1,.2…nextnpm i deride@nextAuto-publish on
mainis unchanged — non-breaking changes keep shipping on merge. Breaking changes never touchmain, so they cannot trigger a major before we intend it.Day-to-day
fix:/feat:/perf:mainfeat!:/BREAKING CHANGE:next3.0.0-next.Non thenexttagnext→main3.0.0stablenextcan be ephemeralsemantic-release/lib/branches/expand.jsintersects the configured branches with the branches that actually exist on the remote, so a configured-but-missing branch produces no entries rather than an error. The config can stay in.releaserc.jsonpermanently while the branch only exists when a breaking change is in flight, then gets deleted after the major ships.That matters here — deride has had 3 majors in its life (v0, v1, v2), so a permanently-maintained parallel branch would be idle almost all the time.
npm authentication is unaffected
The trusted publisher configured for #134 is pinned to org / repo / workflow filename / environment — not to a branch. Prereleases from
nextauthenticate over the same OIDC path with no registry-side change.Docs wiring
A Pages deploy replaces the whole site, and a build on one branch cannot see the other's docs. So
mainowns the deploy and pulls the prerelease docs at build time:config.tswould list whicheverdocs/v*directories exist, so the switcher gains and loses the prerelease entry automatically.hasNextVersionbecomes a real signal instead of the always-true comparison it is today.Suggested naming: use
/v3/, not/next/. A version-pinned URL works from day one, survives the stable release without changing, and means/v2/and/v3/are both available throughout. Label it "v3 (prerelease)" in the switcher./next/could remain as a redirect to the current in-development major if a stable "show me unreleased" link is wanted.Blocker — repo merge settings
The repository currently allows squash merges only:
Promoting
next→mainby squash collapses every conventional commit into one, so semantic-release sees a single message and the release is wrong or no-ops.CLAUDE.md already states:
That instruction is currently impossible to follow, because squash is the only method enabled. This is worth fixing regardless of whether this proposal is adopted.
Costs
Worth it if a major is something we want to develop and dogfood over days or weeks. Overkill if a major is a single PR merged the same afternoon.
Alternative — drop
/next/insteadIf the answer is "majors are rare and land in one go", the honest move is to delete
/next/rather than fix it:docs/v2/— the v2 line, frozen when v3 shipsdocs/v3/— the live tree for the current majordocs/latest— symlink to the current majorNo prerelease branch, no overlay, no release-time git writes. Version-pinned URLs still work. This is less machinery and removes the same class of bug, but gives up the ability to publish and dogfood an unreleased major.
Decisions needed
/v3/or/next/as the prerelease URL.nextand ships as3.0.0-next.1first. Under the alternative it merges tomainand cuts v3.0.0 directly.Verified vs still to verify
Verified while writing this:
expand.jsdrops configured branches that do not exist on the remote — sonextcan be ephemerallib/definitions/branches.jsdocs/next↔docs/v2divergence is v2.2.0 fluent-chaining docs, not unreleased contentNot yet verified, and worth a throwaway branch before committing to this:
nextis behindmainlatestsymlinkRelated
main, which is what made/next/unworkable.