From 8d9b017afa0a361f476e667fa44e776c697b8f5d Mon Sep 17 00:00:00 2001 From: Lihua <1017343802@qq.com> Date: Sat, 7 Nov 2026 20:36:59 -0800 Subject: [PATCH 1/2] test(usage): anchor persistent fixtures to a classified-persistent base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two persistent-route tests built their fixtures under a CWD-relative .local directory. From a checkout or worktree under a temporary root — a legitimate contributor layout, and on macOS /tmp resolves to /private/tmp — the production classifier correctly calls that fixture temporary, because it also weighs the running module's own location (fileURLToPath(import.meta.url) is one of its candidates): a LoopX running from a throwaway checkout suppresses usage ping everywhere. The tests then failed deterministically and read as main regressions. The fixtures now anchor to a base the classifier itself calls persistent (homedir first, then the checkout), and skip with that stated reason when no candidate qualifies — which is exactly the case of a temp-root checkout, where the persistent-route behavior genuinely cannot be constructed. Verified from both layouts: 3/3 pass from a persistent checkout (unchanged), 1 pass + 2 reasoned skips from a /private/tmp worktree where 2 hard failures stood before. Signed-off-by: Lihua <1017343802@qq.com> --- .../usage_statistics_environment.test.ts | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/tests/control_plane_ts/usage_statistics_environment.test.ts b/tests/control_plane_ts/usage_statistics_environment.test.ts index e6f4e961db..a1873a7ad9 100644 --- a/tests/control_plane_ts/usage_statistics_environment.test.ts +++ b/tests/control_plane_ts/usage_statistics_environment.test.ts @@ -1,13 +1,29 @@ import assert from "node:assert/strict"; import { createServer } from "node:http"; import { mkdir, mkdtemp, readFile, rm, symlink } from "node:fs/promises"; -import { platform, tmpdir } from "node:os"; +import { homedir, platform, tmpdir } from "node:os"; import { join, resolve } from "node:path"; import test from "node:test"; import { configure, inspect, observe } from "../../loopx/control_plane/runtime/usage_statistics.ts"; import type { Context } from "../../loopx/control_plane/runtime/usage_statistics.ts"; import { temporaryUsageEnvironment } from "../../loopx/control_plane/runtime/usage_statistics_environment.ts"; +/** + * A fixture base the production classifier itself calls persistent. A checkout + * (or git worktree) under a temporary root is a legitimate contributor layout, + * and there the classifier is right to call a CWD-relative ".local" fixture + * temporary; anchoring the persistent fixtures to a classified-persistent base + * keeps these tests about relative eligibility, not about where the checkout + * lives. When no candidate base classifies as persistent the tests skip with + * that stated reason instead of failing. + */ +const persistentFixtureBase = (): string => { + for (const base of [homedir(), resolve(".")]) { + if (!temporaryUsageEnvironment(join(base, "usage-ping.json"), {HOME: base})) return base; + } + return ""; +}; + test("temporary machine routes suppress every HTTP channel even with enabled/copied state", async t => { const requests: Array<{ path: string; schema: string }> = []; const server = createServer(async (request, response) => { @@ -54,8 +70,9 @@ test("temporary machine routes suppress every HTTP channel even with enabled/cop }); test("persistent machine routes retain notice-before-default-on without an enable flag", async t => { - await mkdir(resolve(".local"), { recursive: true }); - const root = await mkdtemp(join(resolve(".local"), "usage-persistent-")); + const base = persistentFixtureBase(); + if (!base) return t.skip("no candidate base classifies as persistent on this host"); + const root = await mkdtemp(join(base, "loopx-usage-persistent-")); t.after(() => rm(root, { recursive: true, force: true })); const path = join(root, "usage-ping.json"); const ctx: Context = { env: { HOME: root, LOOPX_USAGE_PING_ENDPOINT: "http://127.0.0.1:1/v1/ping" }, @@ -76,9 +93,11 @@ test("persistent machine routes retain notice-before-default-on without an enabl }); test("temporary roots, filesystem aliases and path-component boundaries are local eligibility facts", async t => { + const base = persistentFixtureBase(); + if (!base) return t.skip("no candidate base classifies as persistent on this host"); const root = await mkdtemp(join(tmpdir(), "loopx-usage-paths-")); t.after(() => rm(root, { recursive: true, force: true })); - const persistent = resolve(".local", "usage-policy-persistent"); + const persistent = join(base, "usage-policy-persistent"); for (const key of ["HOME", "USERPROFILE", "CODEX_HOME", "XDG_STATE_HOME", "XDG_DATA_HOME", "XDG_CONFIG_HOME"]) { assert.equal(temporaryUsageEnvironment(join(persistent, "usage-ping.json"), { HOME: persistent, [key]: join(root, "home") }), true, key); } @@ -89,8 +108,7 @@ test("temporary roots, filesystem aliases and path-component boundaries are loca } assert.equal(temporaryUsageEnvironment(join(persistent, "tests", "usage-ping.json"), { HOME: persistent }), false, "a test-like name or a normal process temp directory must not suppress a persistent installation"); - await mkdir(resolve(".local"), { recursive: true }); - const links = await mkdtemp(join(resolve(".local"), "usage-alias-")); + const links = await mkdtemp(join(base, "loopx-usage-alias-")); t.after(() => rm(links, { recursive: true, force: true })); await mkdir(join(root, "physical")); const alias = join(links, "alias"); From 1aa8eb73fab7500274609ffd7c9a858feb16e162 Mon Sep 17 00:00:00 2001 From: Lihua <1017343802@qq.com> Date: Sat, 7 Nov 2026 23:03:34 -0800 Subject: [PATCH 2/2] test(usage): select the fixture base by an independent path oracle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review follow-up: choosing the fixture base with the classifier under test made the oracle self-referential — a regressed classifier that rejects every path would turn both scenarios into silent skips instead of the failed assertions that catch the regression. The base selection now restates the documented temporary-root rules independently (including the classifier's own module-location dimension, for which the test file stands in), so: a persistent checkout proceeds and a classifier regression fails the assertions; a temp-root checkout skips with the documented reason, where the all-temporary answer is the correct behavior. Verified three ways on this head: persistent checkout 3/3 pass; a /private/tmp worktree 1 pass + 2 reasoned skips; and a mutation probe that forces the classifier to always report temporary now yields 1 pass + 2 FAILED (previously masked as skips). Signed-off-by: Lihua <1017343802@qq.com> --- .../usage_statistics_environment.test.ts | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/tests/control_plane_ts/usage_statistics_environment.test.ts b/tests/control_plane_ts/usage_statistics_environment.test.ts index a1873a7ad9..682b6dad0a 100644 --- a/tests/control_plane_ts/usage_statistics_environment.test.ts +++ b/tests/control_plane_ts/usage_statistics_environment.test.ts @@ -1,27 +1,64 @@ import assert from "node:assert/strict"; import { createServer } from "node:http"; import { mkdir, mkdtemp, readFile, rm, symlink } from "node:fs/promises"; +import { realpathSync } from "node:fs"; import { homedir, platform, tmpdir } from "node:os"; -import { join, resolve } from "node:path"; +import { dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path"; +import { fileURLToPath } from "node:url"; import test from "node:test"; import { configure, inspect, observe } from "../../loopx/control_plane/runtime/usage_statistics.ts"; import type { Context } from "../../loopx/control_plane/runtime/usage_statistics.ts"; import { temporaryUsageEnvironment } from "../../loopx/control_plane/runtime/usage_statistics_environment.ts"; /** - * A fixture base the production classifier itself calls persistent. A checkout - * (or git worktree) under a temporary root is a legitimate contributor layout, - * and there the classifier is right to call a CWD-relative ".local" fixture - * temporary; anchoring the persistent fixtures to a classified-persistent base - * keeps these tests about relative eligibility, not about where the checkout - * lives. When no candidate base classifies as persistent the tests skip with - * that stated reason instead of failing. + * A fixture base that an INDEPENDENTLY written path rule — the documented + * temporary-root list, restated here on purpose — calls persistent. The rule + * must not consult the classifier under test: a regressed classifier that + * rejects every path would otherwise turn these scenarios into silent skips + * instead of the failed assertions that catch the regression. When no + * candidate base passes the independent rule (a checkout or worktree under a + * temporary root is a legitimate contributor layout) the tests skip with that + * stated reason — and there the classifier's all-temporary answer is the + * correct behavior, because it also weighs its own module location. */ +const independentlyTemporary = (value: string): boolean => { + const windows = platform() === "win32"; + const home = homedir(); + const roots = [tmpdir(), process.env.TMPDIR, process.env.TEMP, process.env.TMP, + ...(windows ? [join(process.env.SystemRoot || process.env.WINDIR || "C:\\Windows", "Temp"), + join(process.env.LOCALAPPDATA || join(home, "AppData", "Local"), "Temp")] + : ["/tmp", "/var/tmp", "/private/tmp", "/private/var/tmp", + ...(platform() === "darwin" ? ["/var/folders", "/private/var/folders"] : [])])]; + const physical = (path: string): string => { + let parent = resolve(path); + const missing: string[] = []; + while (true) { + try { return join(realpathSync(parent), ...missing); } + catch { missing.unshift(parent.slice(dirname(parent).length).replace(/^[/\\]+/, "")); + const next = dirname(parent); + if (next === parent) return resolve(path); + parent = next; } + } + }; + const normalize = (path: string) => windows ? path.toLowerCase() : path; + const directories = [...new Set(roots.filter(root => !!root && isAbsolute(root)) + .map(physical).filter(root => root !== parse(root).root).map(normalize))]; + const candidate = normalize(physical(value)); + return directories.some(root => { + const child = relative(root, candidate); + return child === "" || (!isAbsolute(child) && child !== ".." && !child.startsWith(".." + sep)); + }); +}; + const persistentFixtureBase = (): string => { - for (const base of [homedir(), resolve(".")]) { - if (!temporaryUsageEnvironment(join(base, "usage-ping.json"), {HOME: base})) return base; - } - return ""; + // The classifier also weighs its own module location: a LoopX running from + // a throwaway checkout suppresses everywhere, so no persistent-route + // scenario can be constructed there. That dimension is encoded here with + // the same independent rule (the test file stands in for the module), so a + // temp-root checkout skips for the documented reason while a classifier + // regression on a persistent checkout still fails the assertions. + if (independentlyTemporary(fileURLToPath(import.meta.url))) return ""; + return [homedir(), resolve(".")].find(base => !independentlyTemporary(join(base, "usage-ping.json"))) ?? ""; }; test("temporary machine routes suppress every HTTP channel even with enabled/copied state", async t => {