From 4b26eae3b2f189223b06fa04d5f945789cd0c2b0 Mon Sep 17 00:00:00 2001 From: Xiangzhe Date: Fri, 14 Aug 2026 13:21:17 -0300 Subject: [PATCH] fix(cli): remove orphaned resolveOpencodeConfigDir re-export (base-red #9985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `check:dead-code` reports 410 dead symbols against a 409 baseline on the pristine `release/v3.8.50` tip, so every PR on the branch is born red on that gate (#10386, #10393, #10390, #10388, #10382 all fail it). Isolated the +1 by diffing knip 6.32 reports between the rebaseline commit 97aac6ac6c (409) and the tip (410): `resolveOpencodeConfigDir` in `src/shared/services/cliRuntime.ts`. #10246 moved the canonical resolvers into `opencodeConfigPath.ts` and left this wrapper behind; the same commit removed its last consumer. The wrapper was not just unused, it was divergent: it returned `path.dirname()` of the canonical value — `~/.config` rather than `~/.config/opencode` — so any future caller reaching for it by name would have written the OpenCode config one directory too high. Removed the wrapper and its now-unused import. A new test pins the canonical resolver's contract and asserts the divergent re-export stays gone; the guard was mutation-validated (re-adding the wrapper fails it). check:dead-code: 409 = baseline, PASS. cliRuntime/opencode suites: 51 pass, 0 fail. New guard: 3 pass, 0 fail. lint / typecheck:core / file-size / complexity-ratchets / test-discovery: green. --- .../basered-deadcode-opencode-config-dir.md | 1 + src/shared/services/cliRuntime.ts | 18 +----- .../opencode-config-dir-single-source.test.ts | 57 +++++++++++++++++++ 3 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 changelog.d/fixes/basered-deadcode-opencode-config-dir.md create mode 100644 tests/unit/opencode-config-dir-single-source.test.ts diff --git a/changelog.d/fixes/basered-deadcode-opencode-config-dir.md b/changelog.d/fixes/basered-deadcode-opencode-config-dir.md new file mode 100644 index 0000000000..0055420d4f --- /dev/null +++ b/changelog.d/fixes/basered-deadcode-opencode-config-dir.md @@ -0,0 +1 @@ +- fix(cli): drop the orphaned `resolveOpencodeConfigDir` re-export from `cliRuntime` — it lost its last consumer in #10246 and diverged from the canonical resolver by one directory level (#9985) diff --git a/src/shared/services/cliRuntime.ts b/src/shared/services/cliRuntime.ts index bf148aa87c..bee2577555 100644 --- a/src/shared/services/cliRuntime.ts +++ b/src/shared/services/cliRuntime.ts @@ -9,10 +9,7 @@ import { withSettingsFallback } from "./cliInstallFallback"; import { GROK_BUILD_RUNTIME_ENTRY, AMP_RUNTIME_ENTRY } from "./cliRuntimeGrokBuild"; import { isLocationTrusted, findKnownPathMatch } from "./cliRuntimeKnownPath"; import { buildHealthcheckPath } from "./cliRuntimeHealthcheckPath"; -import { - resolveOpencodeConfigDir as resolveOpenCodeConfigDir, - resolveOpencodeConfigPath as resolveOpenCodeConfigPath, -} from "./opencodeConfigPath"; +import { resolveOpencodeConfigPath as resolveOpenCodeConfigPath } from "./opencodeConfigPath"; const VALID_RUNTIME_MODES = new Set(["auto", "host", "container"]); const FALSE_VALUES = new Set(["0", "false", "no", "off"]); @@ -973,19 +970,6 @@ export const getCliConfigHome = () => { return normalized; }; -export const resolveOpencodeConfigDir = ( - _platform = process.platform, - env: NodeJS.ProcessEnv = process.env, - homeDir = os.homedir() -) => { - // #3330: OpenCode reads its config from XDG `~/.config/opencode/` on ALL - // platforms — including Windows, where it uses `%USERPROFILE%\.config`, NOT - // `%APPDATA%`. Writing to %APPDATA% on Windows put the file where OpenCode - // never looks, so dashboard-saved config silently had no effect. `_platform` - // is kept in the signature for call-site/test compatibility. - return path.dirname(resolveOpenCodeConfigDir(env, homeDir)); -}; - export const resolveOpencodeConfigPath = ( _platform = process.platform, env: NodeJS.ProcessEnv = process.env, diff --git a/tests/unit/opencode-config-dir-single-source.test.ts b/tests/unit/opencode-config-dir-single-source.test.ts new file mode 100644 index 0000000000..e7e1000432 --- /dev/null +++ b/tests/unit/opencode-config-dir-single-source.test.ts @@ -0,0 +1,57 @@ +// Regression guard for the #10246 follow-up: `resolveOpencodeConfigDir` has exactly ONE +// implementation, in `src/shared/services/opencodeConfigPath.ts`. +// +// #10246 moved the canonical resolvers into `opencodeConfigPath.ts` and left a thin wrapper +// `resolveOpencodeConfigDir` behind in `cliRuntime.ts`. That wrapper lost its last consumer in +// the same commit and became a dead export — which is what pushed the `check:dead-code` ratchet +// to 410 (baseline 409) and made every PR on `release/v3.8.50` born red on that gate. +// +// Worse than the ratchet: the wrapper returned `path.dirname()` of the canonical value, i.e. +// `~/.config` instead of `~/.config/opencode`. Two same-named exports with DIFFERENT return +// values is a live foot-gun — a future caller importing from `cliRuntime` instead of +// `opencodeConfigPath` would silently write the OpenCode config one directory too high. +// +// This test pins both halves: the canonical resolver's contract, and the absence of the +// divergent re-export. + +import test from "node:test"; +import assert from "node:assert/strict"; +import path from "node:path"; + +import { resolveOpencodeConfigDir } from "@/shared/services/opencodeConfigPath"; +import * as cliRuntime from "@/shared/services/cliRuntime"; + +test("#10246 canonical resolveOpencodeConfigDir returns the XDG opencode directory", () => { + assert.equal( + resolveOpencodeConfigDir({ XDG_CONFIG_HOME: "/xdg" }, "/home/u"), + path.join("/xdg", "opencode") + ); + // No XDG_CONFIG_HOME → `/.config/opencode` on every platform (#3330: OpenCode reads + // XDG even on Windows, where it uses %USERPROFILE%\.config and never %APPDATA%). + assert.equal( + resolveOpencodeConfigDir({}, "/home/u"), + path.join("/home/u", ".config", "opencode") + ); + // A blank/whitespace XDG_CONFIG_HOME must fall back, not produce a relative path. + assert.equal( + resolveOpencodeConfigDir({ XDG_CONFIG_HOME: " " }, "/home/u"), + path.join("/home/u", ".config", "opencode") + ); +}); + +test("#10246 cliRuntime does NOT re-export a divergent resolveOpencodeConfigDir", () => { + assert.equal( + (cliRuntime as Record).resolveOpencodeConfigDir, + undefined, + "cliRuntime must not re-export resolveOpencodeConfigDir — the wrapper returned the PARENT " + + "directory (path.dirname of the canonical value), so importing it by name would write the " + + "OpenCode config one level too high. Import it from opencodeConfigPath instead." + ); +}); + +test("#10246 cliRuntime still exposes the config PATH helpers it owns", () => { + // The path helpers legitimately stay on cliRuntime (they have live consumers) — this guard + // must not be read as "cliRuntime should stop exporting OpenCode helpers entirely". + assert.equal(typeof cliRuntime.resolveOpencodeConfigPath, "function"); + assert.equal(typeof cliRuntime.getOpenCodeConfigPath, "function"); +});