Releasing xl3
The reference impl publishes to npm; the spec lives in this repo. This file documents the cut procedure for both.
Versioning model
The npm package version (package.json) and the XTL spec version
(spec/STABILITY.md) move on independent timelines but follow
related rules:
| Bump | Trigger |
|---|---|
xl3 patch (1.0.x) | impl bug fix; no API change; no spec change |
xl3 minor (1.x.0) | new export; spec opt-in addition (e.g., new function added in XTL 1.x) |
xl3 major (2.0.0) | spec breaking change OR impl API breaking change |
| XTL minor (e.g., 1.0 → 1.1) | additive spec change (new function, new directive option) |
| XTL major (e.g., 1.0 → 2.0) | breaking spec change (changes existing semantics) |
A spec minor bump usually drives an xl3 minor bump but not always;
a pure impl refactor can ship as xl3 patch with no spec change.
Pre-release sequence (for any 1.x.0)
-
Land all targeted PRs on
main. -
Verify locally:
npm run typechecknpm test -- --runnpm run buildnpm run conformancenpm run conformance:tznpm run examples:buildnpm run examples:runnpm run benchAll MUST be green. The bench numbers go in
scripts/BENCH.mdif they shifted significantly. -
Confirm
CHANGELOG.md[Unreleased]is comprehensive. -
Bump
package.jsonversion to the rc form (e.g.,1.0.0-rc.1). Do NOT publish a1.0.0directly without an rc cycle for any major / new-spec-minor release. -
Move
[Unreleased]to[1.0.0-rc.1] - YYYY-MM-DDand re-create an empty[Unreleased]section. -
Tag and push:
git tag -a v1.0.0-rc.1 -m "xl3 1.0.0-rc.1"git push origin main --tags -
Publish:
npm publish --tag rcThe
rcdist-tag means hosts opting in (npm install @jinyoung4478/xl3@rc) get the candidate; defaultnpm install @jinyoung4478/xl3keeps the prior stable. -
Create the GitHub Release immediately after
npm publish.npm publishis the easy-to-forget half-step: the package goes live but external installers have no release notes / changelog anchor until this runs.# Extract the just-cut version block into a notes file.awk '/^## \[1\.0\.0-rc\.1\]/{p=1; next} /^## \[/{p=0} p' CHANGELOG.md \> /tmp/release-notes.mdgh release create v1.0.0-rc.1 \--title "xl3 1.0.0-rc.1 — <one-line summary matching CHANGELOG intro>" \--notes-file /tmp/release-notes.md \--prereleaseDrop
--prereleasefor non-rc cuts. The title should mirror the form prior releases used (opengh release list --limit 3to see the established phrasing). -
Post-publish verification — confirm all four artifacts moved together. Any one missing means the release is half-published:
Artifact Check npm latest(orrc)npm view @jinyoung4478/xl3 versionmatches the cutRemote git tag git ls-remote --tags origin | grep v1.0.0-rc.1returns a rowGitHub Release gh release view v1.0.0-rc.1resolves; appears ingh release listCHANGELOG [Unreleased]is empty; the cut version has its own dated sectionIf any row fails, fix that row before announcing the release.
Final 1.0.0 cut
After a minimum 21-day rc soak with no critical issues (ROADMAP G23; extended from 7 days per review feedback):
-
Bump version to
1.0.0. -
Move
[1.0.0-rc.1]→[1.0.0] - YYYY-MM-DDin CHANGELOG (with any rc-only fixes folded in). -
Tag, push, publish:
git tag -a v1.0.0 -m "xl3 1.0.0 — XTL 0.1 final"git push origin main --tagsnpm publishNo
--tag rcthis time; this becomes the newlatest. -
Update IMPLEMENTATIONS.md row for the TS reference impl to show
1.0.0. -
Create the GitHub Release immediately after
npm publish(same step that's been silently skipped in past cuts — see v0.7.0 retrospective). Same shape as the rc step:awk '/^## \[1\.0\.0\]/{p=1; next} /^## \[/{p=0} p' CHANGELOG.md \> /tmp/release-notes.mdgh release create v1.0.0 \--title "xl3 1.0.0 — XTL 0.1 final" \--notes-file /tmp/release-notes.mdNo
--prereleaseflag; this is theLatestrelease on GitHub. -
Run the same Post-publish verification table from the rc sequence (npm version / remote tag / GitHub Release / CHANGELOG). All four MUST be green before announcing.
XTL spec version cut
A spec version cut is independent of the npm release. When the XTL spec moves from 0.1 → 1.0:
-
Update
spec/STABILITY.md"Current state" to read 1.0. -
Tag the conformance corpus snapshot:
git tag -a xtl-1.0 -m "XTL 1.0 conformance corpus baseline"git push origin --tagsThis tag pins the corpus state that any 1.0-claiming implementation must pass.
-
Update fixture
meta.yamlspec_versionfields if any moved from 0.1 to 1.0 (a future operation; no fixtures move at the actual 0.1 → 1.0 cut since 1.0 IS the 0.1 surface frozen).
The XTL 1.0 cut and the xl3 1.0.0 cut SHOULD happen in the same
commit so external porters see a clear baseline.
Things that MUST happen
npm publishandgh release createship as a paired action. The git tag, the npm version, the GitHub Release, and the dated CHANGELOG section all reference the same commit. If you find any one of them missing for a published version, treat it as an incomplete release and finish the others before moving on. (See v0.7.0 retrospective — published to npm but no GitHub Release for ~24 hours, leaving no notes anchor for installers.)- Every cut runs the post-publish verification table.
Things that MUST NOT happen
- A breaking API change in a patch or minor.
- Publishing to npm with a dirty working tree.
- Skipping the rc cycle for a major release.
- Removing a stable export without a 2.0 bump.
- Changing an
xl3/...error code's logical meaning. Adding a new code is fine; renaming or repurposing is breaking. - Changing an English
Error.messagein a way that breaks an existingexpected_errorsubstring assertion. Update the fixture and the message together, or don't touch the message.
Rollback
If a release ships a critical bug:
-
Publish the fix as the next patch (
1.0.0→1.0.1). -
If the fix can't ship within an hour:
npm dist-tag rm @jinyoung4478/xl3 latest # un-recommend the bad versionnpm dist-tag add @jinyoung4478/xl3@<previous> latestHosts that pinned to
@jinyoung4478/xl3keep the old version until they bump. -
Never
npm unpublish— npm policy disallows unpublishing versions used as dependencies after a brief grace window.