Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,10 @@ produces `1.0.0-rc.1.2`. A minor or major change advances the candidate number:
`1.0.0-rc.1.2` becomes `1.0.0-rc.2`. Packages already on stable 1.x versions,
including `@tanstack/query-db-collection` and
`@tanstack/offline-transactions`, continue to use normal semantic versioning
and publish under npm's `latest` tag.
and publish under npm's `latest` tag. Release candidates also publish under
`latest`, per the maintainer's 2026-10-29 decision. Existing versions are not
republished to move a tag: use `npm dist-tag add <package>@<version> latest`.
This preserves any existing `rc` alias.

## Pull requests

Expand Down
17 changes: 17 additions & 0 deletions docs/contributing/oracle-coverage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Oracle coverage and closeout

## RC npm tag policy, 2026-10-29

The maintainer directed RC versions to npm's `latest` tag on 2026-10-29.
`CONTRIBUTING.md` records this policy. The release-history model and command/HTTP
receivers now expect `latest` for candidate and stable uploads. Exact-version
membership still decides whether an upload is needed; an existing version is
never republished to move a tag. Existing `rc` aliases are preserved by the
separate `npm dist-tag add <package>@<version> latest` operation.

Historical campaign records below retain the former `rc`-only authority and
its P01 findings. They are not current tag-policy evidence. The existing
histories, comparisons, reach declarations, and run budgets remain intact.
The maintainer explicitly stopped local tests during this release. No RED,
GREEN, or mutant campaign was run for this policy change; execution evidence
is pending CI. The command/HTTP owners do not cover manual tag promotion,
production npm credentials, or Actions authentication.

## RC scope partition, 2026-10-29

The [deferred oracle record](oracle-reviews/2026-10-29-pr-2171-deferred-oracles.md)
Expand Down
10 changes: 5 additions & 5 deletions scripts/publish-history-oracle.property.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Candidates must reach rc and stable versions must reach latest, independent
* of registry history. CONTRIBUTING.md supplies this policy; stable minors are
* the maintainer's deliberate policy. The shared model states the independent
* Candidates and stable versions must reach latest, independent of registry
* history (maintainer decision 2026-10-29, recorded in CONTRIBUTING.md).
* Stable minors are the maintainer's deliberate policy. The shared model states the independent
* version/tag law. A registry ledger is controlled input, not a tag classifier.
*
* The receiver invokes production publishDuringRc with its default command.
Expand Down Expand Up @@ -150,7 +150,7 @@ test.each(['duplicate', 'omission', 'tag', 'version', 'registry', 'access'])(
'release publish judgment rejects wrong %s observation',
(fault) => {
const expected = [
{ name: packageNames.db, version: '1.0.0-rc.1.10', tag: 'rc' },
{ name: packageNames.db, version: '1.0.0-rc.1.10', tag: 'latest' },
]
const correct = [
{
Expand All @@ -168,7 +168,7 @@ test.each(['duplicate', 'omission', 'tag', 'version', 'registry', 'access'])(
else
wrong[0][fault] =
fault === 'tag'
? 'latest'
? 'rc'
: fault === 'version'
? '1.0.0-rc.1.9'
: fault === 'registry'
Expand Down
9 changes: 5 additions & 4 deletions scripts/publish-http-oracle.property.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Candidate releases reach rc; stable releases reach latest exactly once.
* Authority: CONTRIBUTING.md Changesets/Releases and the accepted RC policy.
* Candidate and stable releases reach latest exactly once.
* Authority: CONTRIBUTING.md Changesets/Releases, maintainer decision 2026-10-29.
* The existing release ledger supplies the independent version/tag judgment.
* This receiver crosses the real npm11/pnpm11/Changesets HTTP boundary, with
* the default production publish command and real package-manager archives.
Expand All @@ -9,8 +9,9 @@
* The bounded shared grammar retains the original metadata/failure histories
* and varies exact-version presence independently of tags. Current candidates
* can have only latest, no tags, or rc pointing to an older present version.
* The exact wrong-tag aftermath keeps old rc alongside latest=current. A
* separate stable-phase neighbor removes stable latest while versions remain.
* A historical old-policy wrong-tag aftermath keeps old rc alongside
* latest=current. A separate stable-phase neighbor removes stable latest
* while versions remain.
* Missing targets also have a no-tags neighbor. Two different candidate
* versions vary which package is already current and reverse their assignment.
* A later-candidate fault follows an actual successful candidate upload, in
Expand Down
6 changes: 4 additions & 2 deletions scripts/publish-packages.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ async function publishWithHiddenPackages(
/**
* Publish stable versions first, then candidates, grouped by exact version.
* npm reads that exact version even when dist-tags are missing or stale.
* Explicit upload tags are independent of the metadata selector.
* Uploads use latest under the maintainer's RC policy (CONTRIBUTING.md),
* independently of the exact-version metadata selector. Existing versions
* are skipped; promoting their tags requires a separate npm dist-tag command.
*/
export async function publishDuringRc(
rootDirectory = root,
Expand Down Expand Up @@ -91,7 +93,7 @@ export async function publishDuringRc(
publicPackages.filter(
({ packageJson }) => packageJson.version !== version,
),
{ version, tag: stableVersion.test(version) ? 'latest' : 'rc' },
{ version, tag: 'latest' },
publishCommand,
)
}
Expand Down
7 changes: 4 additions & 3 deletions scripts/publish-packages.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function packageState(root) {
)
}

test('RC publishing gives candidate and stable packages their own npm tags', async (t) => {
test('RC publishing uses latest while isolating candidate and stable versions', async (t) => {
const root = createWorkspace()
t.after(() => rmSync(root, { recursive: true, force: true }))
const before = packageState(root)
Expand Down Expand Up @@ -82,7 +82,7 @@ test('RC publishing gives candidate and stable packages their own npm tags', asy
publicNames: ['@tanstack/db'],
preMode: false,
version: '1.0.0-rc.2',
tag: 'rc',
tag: 'latest',
},
])
assert.deepEqual(packageState(root), before)
Expand All @@ -98,7 +98,8 @@ test('failed candidate publishing restores package manifests and prerelease stat
await assert.rejects(
publishDuringRc(root, (_, publication) => {
phase++
if (publication.tag === 'rc') throw new Error('publish failed')
if (publication.version.startsWith('1.0.0-rc.'))
throw new Error('publish failed')
}),
/publish failed/,
)
Expand Down
9 changes: 3 additions & 6 deletions scripts/release-history-oracle.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* Release laws come from CONTRIBUTING.md's Changesets and Releases sections:
* candidates start at 1.0.0-rc.1, patches extend the current candidate, and a
* minor or major starts the next candidate. Stable packages use ordinary semver
* and latest; candidates use rc. Versioning consumes each changeset once.
* and latest. Candidates also use latest (maintainer decision 2026-10-29,
* recorded in CONTRIBUTING.md). Versioning consumes each changeset once.
* Exit promotes candidates to 1.0.0 and applies only still-pending work.
*
* This independent model uses numeric tuples and an authored changeset ledger.
Expand Down Expand Up @@ -318,11 +319,7 @@ export function expectedPublishes(manifests, registry) {
.map((manifest) => ({
name: manifest.name,
version: manifest.version,
tag:
manifest.name === packageNames.db ||
manifest.name === packageNames.react
? 'rc'
: 'latest',
tag: 'latest',
}))
}

Expand Down
Loading