Skip to content

fix(release): restore 1.x publication after the v1.9.0 collision #162

Description

@zoeyrose

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Fields

Priority

None yet

Effort

None yet

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions