Land the first-run ENOENT fix on main (PR #11 merged to the wrong branch) - #13
Merged
Conversation
A user's first install died just after "Database created":
Setting up GemDB failed: ENOENT: no such file or directory,
open '/Users/…/GemDB/grail/.gemdb-grail-stamp'
prepareFiles recorded Grail as filed into the database before anything
had created <rootPath>/grail for the record to live in. Python support
was then never staged, and every retry failed the same way.
The same misordering broke upgrades, more quietly. Where the directory
did exist, the stamp was written into the PREVIOUS version's copy;
grailNeedsUpdate then compared the bundled stamp with the bundled stamp,
found them equal, and skipped staging -- so a new version's payload never
reached disk, wearing the new version's label, and writeCliScripts never
re-ran to refresh bin/gemdb. It could not have worked either way, since
stageGrail replaces the directory wholesale and deletes the stamp it was
just handed.
Neither failure reproduces on a machine that has run an earlier version,
which is how both reached a release: every developer machine already had
the directory, and the integration suite calls stageGrail itself rather
than going through prepare.
The order now lives in one named place, stageAndRecordGrail, with the
reasons attached. The condition moved too: createDatabase returns
{created, preloaded} so the stamp follows this call having made the
database from the shipped extent, rather than the extension merely
shipping one. An upgrade finds a database carrying whatever Grail was
filed into it before, and stamping there would claim an install that
never happened; leaving it unstamped is what sends ensureRunning to file
the new Grail in.
src/__tests__/grailStaging.test.ts starts from a root path that does not
exist, which is the condition the existing tests could not express. Two
of its five cases fail with the calls reversed -- one reproducing the
reported ENOENT verbatim -- and database.test.ts pins the new return.
Co-Authored-By: Claude Fable 5 <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.
#11 is marked merged, but its fix is not on
main. This re-lands it, unchanged.What happened
#11 was stacked on
fix/grail-retired-canonical-flagso it could go green while #12 was still open. #12 then merged that branch intomain, but the branch itself survived — precisely because #11 was still pointing at it — and GitHub only auto-retargets a stacked PR when its base branch is deleted. So #11 stayed based on the stale branch and, on merge, wrote into it rather than intomain.Net effect:
mainhas the canonical-flag fix (#12) and not the ENOENT fix (#11).The commit was not lost — it sits on
origin/fix/grail-retired-canonical-flagbehind merge commitcc5bf3b, which is the only reason that branch still needs to exist. My mistake, in setting the stack up that way.What this PR is
add7887cherry-picked ontomain, byte-identical:So it is still the fix for the reported first-run failure: setup dying with
ENOENT … '<root>/grail/.gemdb-grail-stamp'right after "Database created", because Grail was recorded as filed in before anything created the directory that record lives in — and, on upgrades, the same misordering making GemDB skip staging a new payload entirely.Verification
Re-run on top of current
main, not carried over: 114 unit tests, 46 integration against a payload rebuilt from Grail HEAD (dab4588). Lint, format, both typechecks clean.After this merges
fix/grail-retired-canonical-flagbecomes safe to delete — it is currently the only remote copy of this commit.🤖 Generated with Claude Code