From ae4a45ffb6573e187ad5c97cdbb89d66bb944622 Mon Sep 17 00:00:00 2001 From: joaovictor91123 Date: Sun, 12 Jul 2026 17:12:37 +0400 Subject: [PATCH] feat(miner): surface a codex auth-freshness remediation detail in doctor (#5166) checkCodexCliPresent already stats auth.json for readability but reported a generic advisory string regardless of whether codex-cli is actually the configured driver. When MINER_CODING_AGENT_PROVIDER is codex-cli and auth.json is missing or unreadable, the check now surfaces a specific, actionable remediation ("run `codex auth` to authenticate before attempts run") instead of the generic aside. The unconfigured (or differently-configured) case's message is unchanged, and ok stays true either way -- this is a message-quality refinement on top of #5165's gating, not a change to the ok logic itself. --- packages/gittensory-miner/lib/laptop-init.js | 16 +++++-- test/unit/miner-cli-doctor-checks.test.ts | 50 ++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/packages/gittensory-miner/lib/laptop-init.js b/packages/gittensory-miner/lib/laptop-init.js index 3aa729949..051dc7daf 100644 --- a/packages/gittensory-miner/lib/laptop-init.js +++ b/packages/gittensory-miner/lib/laptop-init.js @@ -160,11 +160,17 @@ export function checkCodexCliPresent(options = {}) { } catch { // auth.json missing or unreadable — codex would fail for lack of credentials at call time. } - return { - name: "codex-cli-present", - ok: true, - detail: authed ? `found at ${codexPath} (authenticated)` : `found at ${codexPath} (not authenticated: run \`codex auth\`)`, - }; + if (authed) { + return { name: "codex-cli-present", ok: true, detail: `found at ${codexPath} (authenticated)` }; + } + // codex-cli IS the configured driver but auth.json is missing/expired: a more specific, actionable remediation + // than the generic advisory below, mirroring ORB's codexAuthReadinessProbe/assertCodexAuthConfigured wording + // (#5166). `ok` stays true either way (unchanged by this issue, see #5165) since the CLI itself IS present -- + // only the CLI-absent case is a hard doctor failure. + const detail = codingAgentProviderConfiguredFor(env, "codex-cli") + ? `found at ${codexPath} but auth.json is missing or expired — run \`codex auth\` to authenticate before attempts run` + : `found at ${codexPath} (not authenticated: run \`codex auth\`)`; + return { name: "codex-cli-present", ok: true, detail }; } export function runInit(args = [], env = process.env) { diff --git a/test/unit/miner-cli-doctor-checks.test.ts b/test/unit/miner-cli-doctor-checks.test.ts index 848cac762..514fc0a51 100644 --- a/test/unit/miner-cli-doctor-checks.test.ts +++ b/test/unit/miner-cli-doctor-checks.test.ts @@ -131,6 +131,56 @@ describe("gittensory-miner doctor — coding-agent CLI checks (#4304)", () => { expect(check.detail).toBe("found at /usr/bin/codex (authenticated)"); }); + it("codex: auth-freshness remediation -- names the exact remediation step when codex-cli is configured and auth.json is missing", () => { + const check = checkCodexCliPresent({ + env: { MINER_CODING_AGENT_PROVIDER: "codex-cli" }, + resolveCodexPath: () => "/usr/bin/codex", + resolveCodexAuthPath: () => join(tempRoot(), "does-not-exist.json"), + }); + expect(check.ok).toBe(true); + expect(check.detail).toBe( + "found at /usr/bin/codex but auth.json is missing or expired — run `codex auth` to authenticate before attempts run", + ); + }); + + it("codex: auth-freshness remediation -- no remediation message when codex-cli is configured and auth.json IS present", () => { + const authFile = join(tempRoot(), "auth.json"); + writeFileSync(authFile, "{}"); + const check = checkCodexCliPresent({ + env: { MINER_CODING_AGENT_PROVIDER: "codex-cli" }, + resolveCodexPath: () => "/usr/bin/codex", + resolveCodexAuthPath: () => authFile, + }); + expect(check.detail).toBe("found at /usr/bin/codex (authenticated)"); + expect(check.detail).not.toContain("run `codex auth`"); + }); + + it("codex: auth-freshness remediation -- a DIFFERENT provider configured keeps the generic advisory message unchanged", () => { + const check = checkCodexCliPresent({ + env: { MINER_CODING_AGENT_PROVIDER: "claude-cli" }, + resolveCodexPath: () => "/usr/bin/codex", + resolveCodexAuthPath: () => join(tempRoot(), "does-not-exist.json"), + }); + expect(check.detail).toBe("found at /usr/bin/codex (not authenticated: run `codex auth`)"); + }); + + it("invariant: the unconfigured-provider message shape never changes regardless of auth.json state", () => { + const authMissing = checkCodexCliPresent({ + env: {}, + resolveCodexPath: () => "/usr/bin/codex", + resolveCodexAuthPath: () => join(tempRoot(), "does-not-exist.json"), + }); + const authPresentFile = join(tempRoot(), "auth.json"); + writeFileSync(authPresentFile, "{}"); + const authPresent = checkCodexCliPresent({ + env: {}, + resolveCodexPath: () => "/usr/bin/codex", + resolveCodexAuthPath: () => authPresentFile, + }); + expect(authMissing.detail).toBe("found at /usr/bin/codex (not authenticated: run `codex auth`)"); + expect(authPresent.detail).toBe("found at /usr/bin/codex (authenticated)"); + }); + it("invariant: an unconfigured (or differently-configured) provider's CLI check is never reported as ok: false regardless of CLI presence", () => { const missingUnconfigured = checkClaudeCliPresent({ env: {}, resolveClaudePath: () => null }); const presentUnconfigured = checkClaudeCliPresent({ env: {}, resolveClaudePath: () => "/usr/bin/claude" });