diff --git a/dist/commands/hooks.js b/dist/commands/hooks.js index 69f43fe0..620b0672 100644 --- a/dist/commands/hooks.js +++ b/dist/commands/hooks.js @@ -21,7 +21,7 @@ */ import { randomBytes } from 'node:crypto'; import { chmodSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync, } from 'node:fs'; -import { join, resolve } from 'node:path'; +import { basename, dirname, join, resolve } from 'node:path'; import { execGit } from '../core/git.js'; import { describeRecordedHookTarget, recordedHookIdentity, readRecordedHookTarget, } from '../core/hook-target.js'; import { PACKAGE_ROOT } from '../core/paths.js'; @@ -157,10 +157,46 @@ export const resolveEntryForRecord = (entry, cwd) => { } return null; }; +/** + * The same bundle reached through a path that does not name a release (#693). + * + * `process.argv[1]` under a normal install is + * `/v/dist/commitlore.mjs`, and recording it pins the + * repository to that release: an upgrade leaves the hook validating commits + * with the old build while the CLI reports the new one. Three repositories on + * the first machine to upgrade were doing exactly that, this one among them, + * throughout two releases. + * + * `install.sh` maintains `/current` beside the versioned checkouts. + * It is still an absolute path to a `.mjs`, so the recorded interpreter can + * launch it and the hook stays independent of PATH — the properties the + * versioned path was chosen for. The `bin` wrapper cannot serve here: it is a + * shell script, and a hook runs where PATH may carry no node at all. + * + * Only accepted when it resolves to the bundle that is running. A `current` + * pointing elsewhere belongs to another install, and sending a hook to code + * this one never verified is worse than pinning a version. + */ +const versionFreeEntryFor = (bundle) => { + // Derived from the layout, not from a directory name: /v/dist/. + // Matching on the literal "commitlore" would have made this depend on what the + // data root happens to be called. + const versionDir = dirname(dirname(bundle)); + if (!/^v\d/.test(basename(versionDir))) + return null; + const candidate = join(dirname(versionDir), 'current', 'dist', 'commitlore.mjs'); + try { + return realpathSync(candidate) === realpathSync(bundle) ? candidate : null; + } + catch { + return null; + } +}; const recordBinPath = (cwd) => { - const resolvedEntry = resolveEntryForRecord(process.argv[1], cwd); - if (resolvedEntry === null) + const running = resolveEntryForRecord(process.argv[1], cwd); + if (running === null) return; + const resolvedEntry = versionFreeEntryFor(running) ?? running; execGit(['config', '--local', 'commitlore.bin', resolvedEntry], { cwd }); // The interpreter as well: the branch that reads these back runs in a hook // whose PATH may not carry node, which is the whole reason it exists. For a diff --git a/dist/commands/hooks.js.map b/dist/commands/hooks.js.map index 6113619f..723e1083 100644 --- a/dist/commands/hooks.js.map +++ b/dist/commands/hooks.js.map @@ -1 +1 @@ -{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/commands/hooks.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commitlore.mjs b/dist/commitlore.mjs index 789dd2b8..8208fc75 100755 --- a/dist/commitlore.mjs +++ b/dist/commitlore.mjs @@ -17792,7 +17792,7 @@ var register3 = (program3) => { import { execFileSync } from "node:child_process"; import { mkdtempSync, rmSync as rmSync5, writeFileSync as writeFileSync13, mkdirSync as mkdirSync9 } from "node:fs"; import { tmpdir } from "node:os"; -import { dirname as dirname9, join as join14, resolve as resolve17 } from "node:path"; +import { dirname as dirname10, join as join14, resolve as resolve17 } from "node:path"; // src/demo/fixture.ts var targetPath = "src/pricing.ts"; @@ -21788,7 +21788,7 @@ import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync11 } from "node:fs"; -import { join as join12, resolve as resolve15 } from "node:path"; +import { basename as basename2, dirname as dirname8, join as join12, resolve as resolve15 } from "node:path"; // src/hooks/post-commit.ts import { createHash as createHash7, randomBytes as randomBytes5 } from "node:crypto"; @@ -22452,9 +22452,20 @@ var resolveEntryForRecord = (entry, cwd) => { } return null; }; +var versionFreeEntryFor = (bundle) => { + const versionDir = dirname8(dirname8(bundle)); + if (!/^v\d/.test(basename2(versionDir))) return null; + const candidate = join12(dirname8(versionDir), "current", "dist", "commitlore.mjs"); + try { + return realpathSync4(candidate) === realpathSync4(bundle) ? candidate : null; + } catch { + return null; + } +}; var recordBinPath = (cwd) => { - const resolvedEntry = resolveEntryForRecord(process.argv[1], cwd); - if (resolvedEntry === null) return; + const running = resolveEntryForRecord(process.argv[1], cwd); + if (running === null) return; + const resolvedEntry = versionFreeEntryFor(running) ?? running; execGit(["config", "--local", "commitlore.bin", resolvedEntry], { cwd }); execGit(["config", "--local", "commitlore.node", process.execPath], { cwd }); try { @@ -22624,15 +22635,15 @@ var register9 = (program3) => { // src/core/agents-guidance.ts import { existsSync as existsSync19, readFileSync as readFileSync19, renameSync as renameSync8, rmSync as rmSync4, statSync as statSync8, writeFileSync as writeFileSync12 } from "node:fs"; -import { basename as basename2, dirname as dirname8, join as join13, resolve as resolve16 } from "node:path"; +import { basename as basename3, dirname as dirname9, join as join13, resolve as resolve16 } from "node:path"; import { fileURLToPath as fileURLToPath2 } from "node:url"; var AGENTS_SECTION_BEGIN = ""; var AGENTS_SECTION_END = ""; var messageOf6 = (error2) => error2 instanceof Error ? error2.message : String(error2); var shippedAgentsPath = () => { const source = fileURLToPath2(import.meta.url); - const here = dirname8(source); - return basename2(here) === "dist" ? resolve16(here, "..", "AGENTS.md") : resolve16(here, "..", "..", "AGENTS.md"); + const here = dirname9(source); + return basename3(here) === "dist" ? resolve16(here, "..", "AGENTS.md") : resolve16(here, "..", "..", "AGENTS.md"); }; var readCommitloreAgentsSection = () => { const contents = readFileSync19(shippedAgentsPath(), "utf8"); @@ -23193,12 +23204,12 @@ var runDemo = async (opts = {}) => { if (tmpResolved === userCwd || tmpResolved.startsWith(userCwd + "/") || userCwd.startsWith(tmpResolved + "/")) { throw new Error("demo: temporary directory overlaps with user repository \u2014 aborting"); } - git(["init", "--quiet", "--template=", "--initial-branch=main", tmpDir], dirname9(tmpDir)); + git(["init", "--quiet", "--template=", "--initial-branch=main", tmpDir], dirname10(tmpDir)); git(["config", "user.name", "CommitLore Demo"], tmpDir); git(["config", "user.email", "demo@commitlore.example"], tmpDir); git(["config", "commit.gpgsign", "false"], tmpDir); const targetFullPath = join14(tmpDir, targetPath); - mkdirSync9(dirname9(targetFullPath), { recursive: true }); + mkdirSync9(dirname10(targetFullPath), { recursive: true }); writeFileSync13(targetFullPath, "export const calculatePrice = () => {};\n"); git(["add", "."], tmpDir); git(["commit", "-m", predecessorCommitMessage], tmpDir); @@ -23666,7 +23677,7 @@ var register14 = (program3) => { import { spawnSync as spawnSync6 } from "node:child_process"; import { copyFileSync, existsSync as existsSync21, mkdirSync as mkdirSync10, readFileSync as readFileSync23, renameSync as renameSync9, statSync as statSync9, writeFileSync as writeFileSync16 } from "node:fs"; import { homedir } from "node:os"; -import { basename as basename3, dirname as dirname10, join as join15, resolve as resolve19 } from "node:path"; +import { basename as basename4, dirname as dirname11, join as join15, resolve as resolve19 } from "node:path"; // src/core/hermes-config.ts import { relative as relative2, resolve as resolve18, sep as sep3 } from "node:path"; @@ -23947,7 +23958,7 @@ var backupPathFor = (configPath) => { } }; var atomicallyWrite = (path2, contents, mode) => { - const temporary = join15(dirname10(path2), `.${basename3(path2)}.commitlore-${process.pid}.tmp`); + const temporary = join15(dirname11(path2), `.${basename4(path2)}.commitlore-${process.pid}.tmp`); try { if (mode === void 0) writeFileSync16(temporary, contents, "utf8"); else writeFileSync16(temporary, contents, { encoding: "utf8", mode }); @@ -23993,7 +24004,7 @@ var runHermesInstall = (options = {}) => { const dataRoot = options.dataRoot ?? join15(dataHome, "commitlore"); const versionedSkills = join15(dataRoot, `v${runtimeIdentity().version}`, "hermes", "skills"); const skillsDir = options.skillsDir ?? (existsSync21(versionedSkills) ? versionedSkills : installedPath("hermes", "skills")); - const detected = options.detected ?? (existsSync21(dirname10(configPath)) || commandExists("hermes")); + const detected = options.detected ?? (existsSync21(dirname11(configPath)) || commandExists("hermes")); const report = []; const verified = []; if (!detected) { @@ -24025,7 +24036,7 @@ var runHermesInstall = (options = {}) => { } if (edit.added.length > 0) { try { - mkdirSync10(dirname10(configPath), { recursive: true }); + mkdirSync10(dirname11(configPath), { recursive: true }); if (existsSync21(configPath)) { const backup = backupPathFor(configPath); copyFileSync(configPath, backup); @@ -24165,7 +24176,7 @@ var register16 = (program3) => { // src/commands/inject.ts import { readFileSync as readFileSync24, realpathSync as realpathSync5 } from "node:fs"; -import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute3, join as join16, relative as relative3, resolve as resolve20, sep as sep4 } from "node:path"; +import { basename as basename5, dirname as dirname12, isAbsolute as isAbsolute3, join as join16, relative as relative3, resolve as resolve20, sep as sep4 } from "node:path"; // src/core/inject.ts import { createHash as createHash9 } from "node:crypto"; @@ -24569,9 +24580,9 @@ var canonical = (target) => { const real = realpathSync5(current); return tail.length === 0 ? real : join16(real, ...tail); } catch { - const parent = dirname11(current); + const parent = dirname12(current); if (parent === current) return absolute; - tail.unshift(basename4(current)); + tail.unshift(basename5(current)); current = parent; } } @@ -24731,7 +24742,7 @@ var register17 = (program3) => { // src/commands/installer-hosts.ts import { existsSync as existsSync22, mkdirSync as mkdirSync11, renameSync as renameSync10, statSync as statSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync17, readFileSync as readFileSync25 } from "node:fs"; -import { delimiter as delimiter2, dirname as dirname12, join as join17 } from "node:path"; +import { delimiter as delimiter2, dirname as dirname13, join as join17 } from "node:path"; import { randomUUID } from "node:crypto"; import { spawnSync as spawnSync7 } from "node:child_process"; var INSTALLER_HOSTS_SCHEMA = "commitlore_installer_hosts.v1"; @@ -24755,8 +24766,8 @@ var commandOf = (format, entry) => { }; var entryFor = (format, wrapper) => format === "json-mcp" ? { type: "local", command: [wrapper, "mcp"], enabled: true } : { command: wrapper, args: ["mcp"] }; var atomicJsonWrite = (path2, value) => { - mkdirSync11(dirname12(path2), { recursive: true }); - const temporary = join17(dirname12(path2), `.${String(path2.split("/").pop())}.commitlore-${process.pid}-${randomUUID()}.tmp`); + mkdirSync11(dirname13(path2), { recursive: true }); + const temporary = join17(dirname13(path2), `.${String(path2.split("/").pop())}.commitlore-${process.pid}-${randomUUID()}.tmp`); try { writeFileSync17(temporary, `${JSON.stringify(value, null, 2)} `, { encoding: "utf8", mode: 384 }); @@ -24845,8 +24856,8 @@ command = ${escaped} args = ["mcp"] `; try { - mkdirSync11(dirname12(path2), { recursive: true }); - const temporary = join17(dirname12(path2), `.${String(path2.split("/").pop())}.commitlore-${process.pid}-${randomUUID()}.tmp`); + mkdirSync11(dirname13(path2), { recursive: true }); + const temporary = join17(dirname13(path2), `.${String(path2.split("/").pop())}.commitlore-${process.pid}-${randomUUID()}.tmp`); try { writeFileSync17(temporary, next, { encoding: "utf8", mode: 384 }); if (process.env.COMMITLORE_INSTALLER_TEST_INTERRUPT_WRITE === "1") throw new Error("interrupted before atomic rename"); diff --git a/install.sh b/install.sh index b6e157c0..ba0dac30 100755 --- a/install.sh +++ b/install.sh @@ -626,6 +626,34 @@ if ! mv "$dest_tmp" "$dest"; then fi dest_tmp="" +# A version-free path to the bundle, maintained beside the versioned checkouts +# (#693). +# +# `commitlore hooks install` records an absolute path to the bundle so a hook is +# independent of PATH and of any node_modules/.bin/commitlore above the +# repository. Recording the versioned checkout pins that repository to one +# release: three repositories on the first machine to upgrade were still +# validating commits with 0.8.2 and 0.8.0, and this repository was one of them. +# +# The wrapper cannot stand in for it -- that was tried and fails, because a hook +# runs where PATH may carry no node and a shell script cannot be launched with +# the recorded interpreter. A symlink to the checkout keeps both properties: an +# absolute path to a .mjs, and one that does not name a release. +# +# Symlink, then rename: an existing `current` cannot be replaced in place while +# something is reading through it. +current_link="$data_root/current" +current_tmp="$current_link.commitlore-install.$$" +if ln -sfn "$candidate" "$current_tmp" 2>/dev/null && mv -f "$current_tmp" "$current_link" 2>/dev/null; then + log "current -> $(basename "$candidate")" +else + rm -f "$current_tmp" 2>/dev/null || true + # Not fatal. A host without symlinks still has a working install; hooks there + # keep recording the versioned path and `commitlore hooks install` after an + # upgrade remains the repair, which `doctor` already names. + log "note: could not maintain $current_link -- hooks will record a versioned path" +fi + log "installed to $dest" printf '%s\n' "$verified_version" diff --git a/installer/canonical-artifact.json b/installer/canonical-artifact.json index 574e1b5d..0c156b45 100644 --- a/installer/canonical-artifact.json +++ b/installer/canonical-artifact.json @@ -15,10 +15,10 @@ "tsconfig.json", "src" ], - "sha256": "064b3810c7c371bfa1cc838fbc3c2e8db8c856f22c0d07e8b2a4e61d3a660c11" + "sha256": "1d11f0bdafe983a545bf070830f32f1afcf6b437a7d154e6413f73651293fb75" }, "artifact": { - "sha256": "c312755d70a4d15b2743f95b9999694ef0fbc433f9ee645acc903c5275ef5a5d", + "sha256": "997d93d4667f50c81db815da8f0a0858cd5f63752d1cd1bbb9e3a2464fffc433", "files": [ { "path": "dist/cli.d.ts", @@ -422,11 +422,11 @@ }, { "path": "dist/commands/hooks.js", - "sha256": "f6c02cae9c88838b3ee7eb99670593e4b99c6dc416908141712708f009482f32" + "sha256": "33d6ebc8e69684983b258b3253423eef7085a49ce44e7579116bed4f7644c5e2" }, { "path": "dist/commands/hooks.js.map", - "sha256": "fd48593e755a6c4efd0350219595cb62de56366d0aefc4ad91c0c7ecd2f22513" + "sha256": "21f2746932ed945e5260d4d688b5da6ee6d591ee95a5472fd17d3098681c8958" }, { "path": "dist/commands/index-cmd.d.ts", @@ -586,7 +586,7 @@ }, { "path": "dist/commitlore.mjs", - "sha256": "136348243607bca3c8f3130825d458a862444c440307d396f1977b34ea6da910" + "sha256": "7dc734bebd046ff5e30277d17807673107fba5254637113772ab834dd9d98b15" }, { "path": "dist/core/agent-configs.d.ts", diff --git a/src/commands/hooks.ts b/src/commands/hooks.ts index 3830f183..e60d34ad 100644 --- a/src/commands/hooks.ts +++ b/src/commands/hooks.ts @@ -32,7 +32,7 @@ import { unlinkSync, writeFileSync, } from 'node:fs'; -import { join, resolve } from 'node:path'; +import { basename, dirname, join, resolve } from 'node:path'; import type { Command } from 'commander'; @@ -234,9 +234,44 @@ export const resolveEntryForRecord = (entry: string | undefined, cwd: string): s return null; }; +/** + * The same bundle reached through a path that does not name a release (#693). + * + * `process.argv[1]` under a normal install is + * `/v/dist/commitlore.mjs`, and recording it pins the + * repository to that release: an upgrade leaves the hook validating commits + * with the old build while the CLI reports the new one. Three repositories on + * the first machine to upgrade were doing exactly that, this one among them, + * throughout two releases. + * + * `install.sh` maintains `/current` beside the versioned checkouts. + * It is still an absolute path to a `.mjs`, so the recorded interpreter can + * launch it and the hook stays independent of PATH — the properties the + * versioned path was chosen for. The `bin` wrapper cannot serve here: it is a + * shell script, and a hook runs where PATH may carry no node at all. + * + * Only accepted when it resolves to the bundle that is running. A `current` + * pointing elsewhere belongs to another install, and sending a hook to code + * this one never verified is worse than pinning a version. + */ +const versionFreeEntryFor = (bundle: string): string | null => { + // Derived from the layout, not from a directory name: /v/dist/. + // Matching on the literal "commitlore" would have made this depend on what the + // data root happens to be called. + const versionDir = dirname(dirname(bundle)); + if (!/^v\d/.test(basename(versionDir))) return null; + const candidate = join(dirname(versionDir), 'current', 'dist', 'commitlore.mjs'); + try { + return realpathSync(candidate) === realpathSync(bundle) ? candidate : null; + } catch { + return null; + } +}; + const recordBinPath = (cwd: string): void => { - const resolvedEntry = resolveEntryForRecord(process.argv[1], cwd); - if (resolvedEntry === null) return; + const running = resolveEntryForRecord(process.argv[1], cwd); + if (running === null) return; + const resolvedEntry = versionFreeEntryFor(running) ?? running; execGit(['config', '--local', 'commitlore.bin', resolvedEntry], { cwd }); // The interpreter as well: the branch that reads these back runs in a hook // whose PATH may not carry node, which is the whole reason it exists. For a diff --git a/test/hook-version-free-pin.test.ts b/test/hook-version-free-pin.test.ts new file mode 100644 index 00000000..34795613 --- /dev/null +++ b/test/hook-version-free-pin.test.ts @@ -0,0 +1,98 @@ +/** + * #693: the hook records a path that survives an upgrade. + * + * `commitlore.bin` held `/v0.8.2/dist/commitlore.mjs`, so an upgrade + * left the repository validating commits with the old build. Three repositories + * on the first machine to upgrade were in that state — this one among them, + * through two releases — and `doctor` said so on every run without stopping + * anything. + * + * `install.sh` now maintains `/current`. Recording that keeps what + * the versioned path was chosen for: an absolute path to a `.mjs`, launchable by + * the recorded interpreter, independent of PATH. The `bin` wrapper cannot serve + * here — it is a shell script, and a hook runs where PATH may carry no node. + * That was measured, not assumed: #694 tried it and hooks failed under the + * restricted PATH. + */ + +import { execFileSync } from 'node:child_process'; +import { cpSync, mkdtempSync, realpathSync, rmSync, symlinkSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +import { afterAll, describe, expect, it } from 'vitest'; + +const REPO_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); +const scratch: string[] = []; + +afterAll(() => { + for (const dir of scratch) rmSync(dir, { recursive: true, force: true }); +}); + +/** A data root with one versioned checkout, and `current` aimed wherever asked. */ +const installation = (currentTarget?: string): { bundle: string; dataRoot: string } => { + const dataRoot = mkdtempSync(join(tmpdir(), 'cl-vfree-')); + scratch.push(dataRoot); + const versioned = join(dataRoot, 'v1.0.1'); + cpSync(join(REPO_ROOT, 'dist'), join(versioned, 'dist'), { recursive: true }); + cpSync(join(REPO_ROOT, 'spec'), join(versioned, 'spec'), { recursive: true }); + cpSync(join(REPO_ROOT, 'package.json'), join(versioned, 'package.json')); + symlinkSync(currentTarget ?? versioned, join(dataRoot, 'current')); + return { bundle: join(versioned, 'dist', 'commitlore.mjs'), dataRoot }; +}; + +const repo = (): string => { + const dir = mkdtempSync(join(tmpdir(), 'cl-vfree-repo-')); + scratch.push(dir); + const run = (args: string[]): void => { + execFileSync('git', args, { cwd: dir, stdio: ['pipe', 'pipe', 'pipe'] }); + }; + run(['init', '-q']); + run(['config', 'user.email', 'a@b']); + run(['config', 'user.name', 'a']); + return dir; +}; + +const recordedPin = (cwd: string, bundle: string): string => { + execFileSync(process.execPath, [bundle, 'hooks', 'install'], { + cwd, + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'], + }); + return execFileSync('git', ['config', '--local', '--get', 'commitlore.bin'], { + cwd, + encoding: 'utf8', + }).trim(); +}; + +describe('#693 what the hook pins itself to', () => { + it('records the version-free path when it resolves to this bundle', () => { + const { bundle, dataRoot } = installation(); + + const pin = recordedPin(repo(), bundle); + + // Compared by realpath: macOS resolves /var to /private/var, and the + // recorded value is the resolved form. + expect(pin, 'the upgrade-surviving path').toBe( + join(dataRoot, 'current', 'dist', 'commitlore.mjs'), + ); + expect(pin, 'and it names no release').not.toMatch(/\/v\d+\.\d+\.\d+\//); + expect(pin, 'still a .mjs, so the recorded interpreter can launch it').toMatch(/\.mjs$/); + }); + + // A `current` belonging to another installation would send the hook to code + // this one never verified — worse than pinning a version. + it('keeps the versioned path when current points at a different install', () => { + // A *working* other installation, not a broken link. If the file simply + // did not exist, realpathSync would throw and the fallback would happen for + // that reason — the identity comparison would never run, and this case + // would pass while proving nothing. It did, until this fixture was fixed. + const elsewhere = mkdtempSync(join(tmpdir(), 'cl-vfree-other-')); + scratch.push(elsewhere); + cpSync(join(REPO_ROOT, 'dist'), join(elsewhere, 'dist'), { recursive: true }); + const { bundle } = installation(elsewhere); + + expect(recordedPin(repo(), bundle), 'an unrelated current is not trusted').toBe(bundle); + }); +});