Bind the version a caller asked for to the runtime that answers - #566
Merged
Conversation
The installer verified that an existing checkout matched its own manifest and
that `--version` ran. It never asked whether the checkout was the version that
had been requested. A directory named for one release could hold another, and
the install reported success:
place a clean v0.7.1 checkout at .../commitlore/v0.8.0/
install exit=0
wrapper --version -> 0.7.1
A colleague upgrading is told the new release is installed and keeps running the
old one, including every defect the upgrade was for.
Binding is now two-sided, because either side alone can lie. The checkout's own
HEAD must resolve to the requested tag, so a mislabelled directory is caught
before anything is activated; and the runtime that the wrapper will actually
execute must report the requested version, so a tree that passes the tag check
and still ships something else is caught by the smoke test. A checkout that
fails either is refused, never deleted -- destroying a directory because it
failed a version check is a worse answer than declining to use it.
The refusal now carries a way forward. It named the unusable path and stopped,
which left an operator with a message and no next step; it now prints the one
deliberate removal that returns the transaction to a state a rerun can install
into, quoted for a shell and scoped to the checkout alone.
The plugin entry point had the same shape. `scripts/commitlore-run.sh` tried
`commitlore` on PATH before the plugin's own bundle, so a machine carrying both
served every edit from whichever CLI happened to be installed, silently. A
plugin is a versioned release artifact and its hook now runs its own bundle;
outside a plugin invocation, PATH is still the right answer, because there is no
bundle to bind. When the bundle cannot run, the hook fails open rather than
answering with an unrelated installation's context and presenting it as the
plugin's.
`test/plugin-entry-point.test.ts` asserted the old order deliberately, so the
expectation is flipped deliberately, and its comment says why rather than
leaving the reversal to be inferred.
The CI install gate tagged its checkout `v9.9.9` and installed that. Version
binding makes that permanently unsatisfiable -- the tree reports its real
version -- so the gate now tags and installs the version in `package.json` and
asserts the wrapper reports it. Windows gains the wrong-tag refusal and a repair
round trip, because the repair path is only evidence if it is executed.
Limit: this binds the requested tag to the runtime that answers, not the tag to its content -- a tag moved after publication installs whatever it now points at, which is a signing question rather than a version-binding one
Ruled-out: deleting a checkout that fails the version check | a directory the installer cannot identify may not be its own, and refusing costs an operator one command while destroying it may cost them something unrecoverable
Blast: system
Undo: easy
Certainty: firm
Verified: ninety-seven cases pass across install-script, install-ps1, plugin-entry-point, manifest and uninstall; the reproduction at the top now exits 3, activates nothing and leaves the previous wrapper untouched, and following the printed repair verbatim installs and reports the requested version; the plugin route answers from its own bundle while a shadowing PATH entry still wins outside a plugin invocation; both typechecks clean and two builds produce a byte-identical dist
Provenance: drafted
Record-Id: r-vbind001
CommitLore — record lintTrailers: clean — 2 commits in Active constraints for the paths this PR touchesLimits (32)
Ruled out (103)
Warnings (20)
Trailer violations fail this check. Active constraints are informational — they are what the repository already decided, not a verdict on this PR. |
The step meant to prove version binding on Windows tagged the requested version and the wrong version at the same commit. A `--depth 1 --branch <wrong>` clone of that repository therefore carried the requested tag too, pointing at its own HEAD, so binding was satisfied and the install succeeded. The step asserted a refusal, so it failed -- correctly, and for a reason that was the test's rather than the installer's. A name is not a difference. The wrong tag now names a commit built with `commit-tree` over HEAD's own tree: the checkout stays internally valid, so the runtime manifest and the smoke test still pass and cannot be what rejects it, and the only thing left to catch it is the binding under test. Locally, against the shell installer that mirrors this check, that shape exits 3, names the mismatch and activates nothing. The shell installer's own case never had this problem -- its fixture tags a genuinely earlier commit -- which is why the gap showed up only on the side that could not be run before pushing. Limit: PowerShell cannot be run here, so this is reasoned from the shared design and proven against the shell twin; only the windows-latest job is evidence for install.ps1 Blast: local Undo: easy Certainty: firm Verified: the corrected fixture produces a clone whose HEAD differs from the requested tag's commit, and the shell installer refuses it with exit 3, names the mismatch and leaves no wrapper behind; the test tags created for that check were deleted afterwards Provenance: authored Record-Id: r-wrongtag1
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.
Blocking finding 1 of the third production-readiness review, plus the recovery gap it sits next to.
The defect
The installer checked that a checkout matched its own manifest and that
--versionran. It never asked whether it was the version requested. A colleague upgrading is told the new release is installed and keeps running the old one.Binding, two-sided
--version↔ requested versionFailing either is a refusal, never a deletion — a directory the installer cannot identify may not be its own.
The refusal now goes somewhere
It named the unusable path and stopped. It now prints the single deliberate removal that returns the transaction to an installable state, quoted for a shell and scoped to the checkout alone. Verified end to end:
The plugin entry point had the same shape
scripts/commitlore-run.shtriedcommitloreon PATH before the plugin's own bundle, so a machine with both served every edit from whichever CLI was installed — silently.A plugin is a versioned release artifact, so its hook runs its own bundle; outside a plugin invocation PATH is still right, because there is no bundle to bind.
test/plugin-entry-point.test.tsasserted the old order on purpose, so the expectation is flipped on purpose and its comment says why.Why CI changed
The install gate tagged its checkout
v9.9.9and installed that. Version binding makes that permanently unsatisfiable, so the gate now tags and installs the version inpackage.jsonand asserts the wrapper reports it. Windows gains the wrong-tag refusal and a repair round trip — a repair path is only evidence if it is executed.Verification
install-ps1required job is evidence for Windows