Give the hook a path that outlives the release it was installed from - #696
Merged
Conversation
commitlore.bin recorded <data-root>/v<version>/dist/commitlore.mjs, so an upgrade left every repository validating commits with the build it was installed from. Measured on the first machine to upgrade: three repositories pinned to 0.8.2 and 0.8.0 while the CLI was 1.0.1 -- this repository among them, through two releases. doctor said so on every run and stopped nothing. install.sh now maintains <data-root>/current beside the versioned checkouts, and hooks record that. It stays an absolute path to a .mjs, so the recorded interpreter launches it and the hook remains independent of PATH -- the two properties the versioned path was chosen for. The bin wrapper cannot serve here and that is not a guess: #694 recorded it and hooks failed under the restricted PATH a hook actually runs in, because a shell script cannot be launched with a recorded interpreter. Two things deliberately narrow. The link is only recorded when it resolves to the running bundle -- a current belonging to another install would send the hook to code this one never verified, which is worse than a version pin. And a host where the symlink cannot be made still installs: hooks there keep recording the versioned path, and `commitlore hooks install` after an upgrade remains the repair doctor already names. The path is derived from the layout rather than from the directory being called commitlore, after the first attempt matched on that name and failed anywhere the data root is named otherwise. Existing pins still need `commitlore hooks install` re-run. This changes what is recorded from now on. Limit: a hook records a path that does not name a release Blast: system Undo: easy Certainty: firm Provenance: authored Record-Id: r-693curr
CommitLore — record lintTrailers: clean — 2 commits in Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR. |
The test asserting a foreign current is refused passed for the wrong reason: the fixture pointed current at a path with no bundle, so realpathSync threw and the fallback happened because the link was broken. The identity comparison never ran, and removing it left the test green. The other installation is now a working one. Only the comparison can reject it. Two mutations, two different failures: removing the derivation -> the version-free case fails removing the identity check -> the foreign-current case fails Before this, one mutation covered both and the second layer was unpinned. Caught in review by asking which mutation each assertion answers -- a question the passing suite could not answer for itself. Limit: a rejection test names what does the rejecting Blast: local Undo: easy Certainty: firm Provenance: authored Record-Id: r-693mut2
This was referenced Aug 16, 2026
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.
Closes #693.
commitlore.binrecorded<data-root>/v<version>/dist/commitlore.mjs, so anupgrade left every repository validating commits with the build it was installed
from. Measured on the first machine to upgrade:
This repository was validating its own commits with v0.8.2 while v1.0.0 and
v1.0.1 were released from it.
doctorreported it on every run and stoppednothing.
What changed
install.shmaintains<data-root>/currentbeside the versioned checkouts, andhooks record that. It stays an absolute path to a
.mjs, so the recordedinterpreter launches it and the hook remains independent of
PATH— the twoproperties the versioned path was chosen for.
The
binwrapper cannot serve here, and that is measured rather than assumed:#694 recorded it and hooks failed under the restricted
PATHa hook actuallyruns in, because a shell script cannot be launched with a recorded interpreter.
Two deliberate limits
currentbelonging toanother install would send the hook to code this one never verified — worse
than a version pin.
versioned path, and
commitlore hooks installafter an upgrade remains therepair
doctoralready names. Not fatal, and logged.The path is derived from the layout, not from the directory being called
commitlore— the first attempt matched that name and failed wherever the dataroot is called something else.
Scope
Changes what is recorded from now on. Existing pins still need
commitlore hooks installre-run; #695 documents that.Verified by removing the derivation: the
currentcase fails. 72 tests passingacross
hooksand the new file. Canonical artifact997d93d4.