Let a release candidate install beside the release - #21
Merged
Conversation
Gear Lever holds one entry per app identity, and a candidate presents the same one as the release: same productName, same desktopName. Only one can be integrated at a time. Records the build-time overrides that give a candidate its own identity, the finding that userData comes from package.json name rather than productName (so shared settings are the default, not something to arrange), and the first-launch backup that makes sharing them safe. Also records dropping the Windows executable from what a release publishes, including the copy of it inside SpinUI-Manual.zip and the quality gate assertions that currently require it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Two pull requests: the candidate identity and its first-launch backup, then dropping the Windows executable from what a release publishes. Records the parts that have to move together -- the workflow literals the quality gate asserts on cannot be edited in a separate commit from the gate, or the tree is red in between -- and the shell quoting the artifactName override needs, which bash would otherwise expand to nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…masking A partial copy left mkdirSync's target directory behind, and that same directory doubled as the already-backed-up marker, so a crashed attempt permanently masked the fact the real snapshot never completed. Stage copies in a sibling <version>.partial directory and rename it into place only once every file has copied.
…out it The round-1 regression tests both passed against the pre-fix code, so neither proved anything: one never triggered a copy failure at all, and the other forced mkdirSync to throw before any directory could exist. Add a test that makes the second of four source files a directory so copyFileSync throws EISDIR after one file has already copied, then assert the marker directory does not exist and a repaired retry succeeds. Verified by temporarily reverting rc-backup.ts to its pre-fix state and confirming this test fails there.
The RC backup only covered four Electron-owned JSON files, but the Python engine writes weekly_boss_kills.json and adventure_journal.sqlite3 into the same shared userData directory -- irreplaceable raid progress and kill history that a release candidate could silently corrupt with zero protection. Extend RC_BACKUP_FILES to also cover the journal's WAL/SHM sidecars, since the engine runs in WAL mode and the bare .sqlite3 file can miss the tail of an unclean shutdown. Also close two smaller gaps found in the same review: - Scope the staging directory by pid so two simultaneous launches (this runs before requestSingleInstanceLock) can no longer interleave and produce a snapshot that's missing a file but reported as complete. - Use statSync().isDirectory() instead of existsSync() for the already-backed-up marker, so a stray file left at that path can't permanently suppress the backup. Document all of this in RELEASING.md so whoever cuts a release knows a candidate shares live data and how to recover if it goes wrong. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gear Lever holds one entry per app identity, and a candidate presented the same one as the live release: same
productName, samedesktopName. Only one could be integrated at a time.A candidate now builds as Loremaster RC with its own desktop entry, application id, executable name and AppImage filename. These are build-time
-c.overrides only —package.jsonis untouched, so local builds and full releases are byte-identical to before.Shared settings, on purpose
userDatacomes frompackage.jsonname, notproductName, so a candidate shares the live settings directory by default. That is deliberate: bugs surface against real data.To make that safe, an RC snapshots the shared state once per candidate to
spins-loremaster-rc-backups/<version>/before anything can write, and never blocks startup if that fails. The snapshot covers the Electron settings and the engine-owned progress data —weekly_boss_kills.jsonandadventure_journal.sqlite3with its WAL sidecars — which the Python engine writes into that same shared directory. Those are the genuinely irreplaceable files; review caught that the original design missed them.Note for future edits: overriding
extraMetadata.nameorextraMetadata.productNamewould moveuserDataand silently split the config. The spec and plan both record this constraint.Verified against a real build
A local
electron-builder --linuxrun with the RC flags producedLoremaster-RC-0.4.0-rc.1-x86_64.AppImagecontainingloremaster-rc.desktopwithName=Loremaster RCandStartupWMClass=loremaster-rc, againstloremaster.desktop/Name=Loremasterin the live build. The packagedpackage.jsoninside the asar confirmsnameis stillspins-loremasterandproductNameis absent — so the settings directory is genuinely shared.Quality gate ALL PASS. Desktop suite passes (
test:updatesis Windows-only and fails on Linux on every commit; CI runs it only in the windows-latest job).Spec:
docs/superpowers/specs/2026-08-14-rc-identity-and-windows-exe-removal-design.mdPlan:
docs/superpowers/plans/2026-08-14-rc-identity-and-windows-exe-removal.md🤖 Generated with Claude Code