Problem
The maintained Classic content line can no longer publish releases. The latest successful 1.x release is v1.8.5, but the branch now contains validated Classic changes—including authored colored-light data—that are not present in any published Classic runtime archive.
The latest Semantic Release run found 13 commits after v1.8.5 and selected 1.9.0 because the range includes feat(...) commits. Publication then failed with EINVALIDNEXTVERSION: main already owns immutable tag v1.9.0, so 1.x may publish only >=1.8.5 <1.9.0.
Evidence:
The unreleased range currently contains these feature-classified squash commits reported by Semantic Release:
0eea49ef65f21b7b02defda2fdaaf7f8292c17fd — feat(lighting): author colored light sources (#64)
ead72ef831444c874f65da841498924bab625e99 — feat(maps): persist the Incuna Sam objective (#63)
9d5aa3c88becabd33247418af76b2866376ce92b — feat(lighting): audit effective light-source colors (#67)
ca2ed0f966cc66de40f6e393cc8e93a7c97867f0 — feat(quests): teach the Incuna apartment flow on 1.x (#112)
d2387818a014536da84833d6f8179e9112b9f6c8 — feat(archetypes): make fire fixtures emit light (#115)
7575b438ae985bfa4a2347776a27c37368f5ee0a — feat(maps): transfer crystal light ownership (#116)
Required outcome
Restore automatic 1.x publication without moving, deleting, or reusing an existing tag, and publish a checksum-bound Classic runtime archive containing the current validated 1.x content.
Implementation requirements
- Add a narrowly bounded recovery rule for the already-merged feature commits above so this historical unreleased range produces a patch within
>=1.8.5 <1.9.0.
- Match the exact committed subjects/scopes or another equivalently fail-closed identity.
- Do not add a blanket rule that silently reclassifies every future
feat on every release line.
- Define and enforce the future
1.x commit policy so another minor release cannot accumulate behind the v1.9.0 boundary.
- Reject feature/breaking pull-request titles on
1.x, or replace the version namespace through an explicit reviewed release-contract migration.
- Keep
main behavior unchanged.
- Keep Semantic Release as the sole tag/release publisher; do not create a tag or release manually.
- Preserve the maintenance channel and the immutable history through
v1.8.5.
- Update
.releaserc.cjs, workflow/contract tests, AGENTS.md, and docs/RELEASE_LINES.md together.
- Ensure release failure reporting preserves the original Semantic Release error and does not obscure it with a secondary issue-creation failure.
Acceptance criteria
- A Semantic Release dry run on the exact reviewed
1.x head selects the next available 1.8.x patch, not 1.9.0.
- The normal post-merge workflow publishes that version on the
1.x channel.
- The runtime asset contains
manifest.json schema version 2 with:
source.repository == "atrinik/content";
source.branch == "1.x";
source.commit equal to the release tag commit;
release_line == "1.x";
replacement_ready == false;
replacement_toolkit_package == false;
compatible_classic_releases still covering supported Classic 5.x releases.
SHA256SUMS verifies both published archives.
- The runtime archive contains explicit
light_color fields and the files introduced by the reviewed lighting work.
- Existing tags and releases are unchanged.
- A regression test proves that an ordinary future
feat(...) on 1.x cannot recreate an out-of-range release silently.
Validation
python3 tools/validate.py
- the repository's focused release-guidance and packaging tests
- Semantic Release dry run for
1.x
- build and inspect both release archives and
manifest.json
- verify
SHA256SUMS
git diff --check
Rollback and recovery
If the production release fails before creating a tag, fix the reviewed automation and rerun it. If it creates immutable release state, follow the repository's documented recovery path; never delete or move the tag to retry.
Problem
The maintained Classic content line can no longer publish releases. The latest successful
1.xrelease isv1.8.5, but the branch now contains validated Classic changes—including authored colored-light data—that are not present in any published Classic runtime archive.The latest Semantic Release run found 13 commits after
v1.8.5and selected1.9.0because the range includesfeat(...)commits. Publication then failed withEINVALIDNEXTVERSION:mainalready owns immutable tagv1.9.0, so1.xmay publish only>=1.8.5 <1.9.0.Evidence:
0eea49ef65f21b7b02defda2fdaaf7f8292c17fdcontracts/release-lines/classic-1x.json.releaserc.cjs,AGENTS.md, anddocs/RELEASE_LINES.mdThe unreleased range currently contains these feature-classified squash commits reported by Semantic Release:
0eea49ef65f21b7b02defda2fdaaf7f8292c17fd—feat(lighting): author colored light sources (#64)ead72ef831444c874f65da841498924bab625e99—feat(maps): persist the Incuna Sam objective (#63)9d5aa3c88becabd33247418af76b2866376ce92b—feat(lighting): audit effective light-source colors (#67)ca2ed0f966cc66de40f6e393cc8e93a7c97867f0—feat(quests): teach the Incuna apartment flow on 1.x (#112)d2387818a014536da84833d6f8179e9112b9f6c8—feat(archetypes): make fire fixtures emit light (#115)7575b438ae985bfa4a2347776a27c37368f5ee0a—feat(maps): transfer crystal light ownership (#116)Required outcome
Restore automatic
1.xpublication without moving, deleting, or reusing an existing tag, and publish a checksum-bound Classic runtime archive containing the current validated1.xcontent.Implementation requirements
>=1.8.5 <1.9.0.featon every release line.1.xcommit policy so another minor release cannot accumulate behind thev1.9.0boundary.1.x, or replace the version namespace through an explicit reviewed release-contract migration.mainbehavior unchanged.v1.8.5..releaserc.cjs, workflow/contract tests,AGENTS.md, anddocs/RELEASE_LINES.mdtogether.Acceptance criteria
1.xhead selects the next available1.8.xpatch, not1.9.0.1.xchannel.manifest.jsonschema version 2 with:source.repository == "atrinik/content";source.branch == "1.x";source.commitequal to the release tag commit;release_line == "1.x";replacement_ready == false;replacement_toolkit_package == false;compatible_classic_releasesstill covering supported Classic5.xreleases.SHA256SUMSverifies both published archives.light_colorfields and the files introduced by the reviewed lighting work.feat(...)on1.xcannot recreate an out-of-range release silently.Validation
python3 tools/validate.py1.xmanifest.jsonSHA256SUMSgit diff --checkRollback and recovery
If the production release fails before creating a tag, fix the reviewed automation and rerun it. If it creates immutable release state, follow the repository's documented recovery path; never delete or move the tag to retry.