diff --git a/scripts/lib/bootstrap-maintenance.mjs b/scripts/lib/bootstrap-maintenance.mjs index 25f0adab..4be2e021 100644 --- a/scripts/lib/bootstrap-maintenance.mjs +++ b/scripts/lib/bootstrap-maintenance.mjs @@ -1,3 +1,4 @@ +import { readFileSync } from "node:fs"; import { homedir } from "node:os"; import { join, resolve } from "node:path"; import { pathToFileURL } from "node:url"; @@ -30,6 +31,14 @@ function fail(code) { throw new Error(code); } +function currentPackageVersion() { + try { + return String(JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8"))?.version || "").trim() || null; + } catch { + return null; + } +} + function defaultCodexHome() { return resolve(process.env.CODEX_HOME || join(homedir(), ".codex")); } @@ -258,6 +267,9 @@ export async function runBootstrapDoctor({ const readAuthority = dependencies.readInstalledAuthorityHost || readInstalledAuthorityHost; const readReceipt = dependencies.readActivationReceipt || readActivationReceipt; const latestRelease = dependencies.latestRelease || (() => createGitHubReleaseClient().latestRelease()); + const runtimeVersion = typeof dependencies.runtimeVersion === "function" + ? dependencies.runtimeVersion() + : currentPackageVersion(); const environment = checkEnvironment(); const found = discover(target ? { explicitTarget: target } : {}); @@ -269,6 +281,7 @@ export async function runBootstrapDoctor({ const report = { action: "doctor", + runtime: { packageVersion: runtimeVersion, relationToLatest: null }, environment, target: selected?.target || (target ? resolve(target) : null), installations: found, @@ -355,6 +368,7 @@ export async function runBootstrapDoctor({ const match = /^v(\d+\.\d+\.\d+)$/.exec(tag); if (!match) fail("stable_release_tag_invalid"); report.latest.version = match[1]; + if (runtimeVersion) report.runtime.relationToLatest = relation(runtimeVersion, match[1]); if (selected?.version) report.latest.relation = relation(selected.version, match[1]); if ( report.authorityHost.ok && diff --git a/tests/unit/bootstrap-maintenance.test.mjs b/tests/unit/bootstrap-maintenance.test.mjs index e9755610..a6cccc5e 100644 --- a/tests/unit/bootstrap-maintenance.test.mjs +++ b/tests/unit/bootstrap-maintenance.test.mjs @@ -296,6 +296,7 @@ test("doctor is read-only and reports integrity, activation, config, authority h codexHome: CODEX_HOME, dependencies: { checkBootstrapEnvironment: () => ({ ok: true, node: { ok: true }, git: { ok: true }, gh: { ok: true }, ghAuth: { ok: true } }), + runtimeVersion: () => "9.9.9", discoverInstallations: () => validInstallation(), readInstalledManifest: () => manifest, compareInstalledManifest: () => ({ clean: false, modifications: [{ path: "SKILL.md", reason: "changed" }] }), @@ -314,6 +315,7 @@ test("doctor is read-only and reports integrity, activation, config, authority h assert.deepEqual(mutations, []); assert.equal(report.target, TARGET); + assert.deepEqual(report.runtime, { packageVersion: "9.9.9", relationToLatest: "already_ahead" }); assert.equal(report.installed.version, "0.4.0"); assert.equal(report.integrity.clean, false); assert.equal(report.config.ok, true);