Skip to content

mcpx daemon tests fail when the temp tree sits under the real $HOME (config walk leaks ~/.config/mcpx/config.json) #1959

Closed

Description

@dezren39

Relocated from dezren39/darwin-nix#259 on 2026-10-28 (placement audit): mcpx's single source lives in developing-today/code (pkgs/mcpx); re-home tracked at #309. Original body below; issue references inside it are historical (dezren39/nix numbering).

Repro

On pristine origin/main 408bc2b, with a real ~/.config/mcpx/config.json present and TMPDIR pointing under $HOME (my case: TMPDIR on a btrfs volume at ~/tmp because /tmp is a 512M tmpfs):

cd pkgs/mcpx
TMPDIR=$HOME/tmp go test ./internal/daemon/

5 failures, e.g.:

--- FAIL: TestResolveNamesTheDaemonKeyedToTheNearestConfig (0.00s)
    routes_resolve_test.go:55: configHash = "70618a007427", want "ffec5674504f"
--- FAIL: TestResolveOverHTTPAnswersForTheAskingDaemonItself (0.00s)
    routes_resolve_test.go:199: sources = [.../003/.mcpx.json /home/hatch/.config/mcpx/config.json], want [.../003/.mcpx.json]
--- FAIL: TestResolveForADirectoryWithNoConfigNamesTheDefaultDaemon (0.00s)
    routes_resolve_test.go:227: configHash = "dc56d4a7680a", want empty: nothing contributed

Root cause

Same class as #196/#221 (fixed there for internal/config): SearchPathFrom checks $dir/.config/mcpx/config.json at every ancestor level during the upward walk. The test's isolate() set HOME/XDG_CONFIG_HOME to a t.TempDir, but the temp tree itself lived under the real $HOME, so the walk passed through the real home directory and picked up the developer's own config — changing the daemon key in FingerprintConfig and breaking socket resolution (the leaked hash dc56d4a7680a is the same default-daemon hash from #196).

Two Go gotchas made the obvious fix wrong:

  • testing.TempDir reads GOTMPDIR, not TMPDIR (go1.26 testing/testing.go:1460), and caches one parent dir per test — setting TMPDIR after the first t.TempDir has no effect.
  • So the fake home itself must be created outside the real $HOME tree.

Fix

In PR #221 (commit 995fb9a on branch mcpx-test-home-isolation): isolate() now creates the fake home with os.MkdirTemp("/tmp", ...) and points GOTMPDIR+TMPDIR+HOME at it before any t.TempDir call. Full internal/daemon package green with the fix; the 5 failures reproduce on pristine 408bc2b.

Acceptance criteria

  • go test ./internal/daemon/ passes with TMPDIR under the real $HOME and a real ~/.config/mcpx/config.json present.
  • The daemon tests are hermetic: config discovery in tests cannot read the operator's real config (test-scoped HOME or config-dir override).
  • No production behavior changes beyond what test hermeticity requires.

Activity

  1. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  2. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    History carried over from dezren39/darwin-nix#259 (verbatim, oldest first):


    @dezren39 · 2026-10-15T09:23:28Z

    Verified fixed on current origin/main (fe3038f).

    Reproduced the exact issue preconditions: real ~/.config/mcpx/config.json present, TMPDIR=/home/hatch/tmp (under the real $HOME), GOTMPDIR unset, then go test -count=1 ./internal/daemon/ in pkgs/mcpx — 30/30 PASS, no failures.

    The fix is the isolate() rework from PR #221 (commit 995fb9a, merged 2026-09-30 as 0e38804): the fake home is created with os.MkdirTemp("/tmp", ...) (outside the real $HOME tree) with GOTMPDIR+TMPDIR+HOME pointed at it before any t.TempDir call, so the upward config walk can never leak the developers own config.

    No further work needed from this side; closing is yours to call.


    @dezren39 · 2026-10-27T15:35:09Z

    Intake review

    Fleet monitor intake pass, 2026-10-27 (repo-fleet-monitor).

    Related: the 2026-09-30 mcpx conformance set — parent analysis #252, siblings #253, #254, #255, #256, #257, #258, #259 (filed together from docs/spec/conformance-matrix.md in dezren39/nix). Treat the set as one body of work; do not re-file per-gap issues.

    Notes: Unlike the rest of the set this one is reproduced on pristine main (408bc2b) with an exact repro and 5 named failures — the config walk leaking the real ~/.config/mcpx/config.json into daemon tests. Priority normal and effort m (monitor judgment): it poisons the test signal for every other mcpx change, including the rest of this set.

    Risks: A test-only fix that masks a real config-precedence bug — the repro test (TestResolveNamesTheDaemonKeyedToTheNearestConfig) suggests nearest-config resolution is the mechanism, so verify the production precedence is intended before walling it off in tests.

    Suggested approach: reproduce first, then decide whether the leak is a test-isolation gap or a genuine resolution bug; fix at that layer.

  3. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    priority/normalOrdinary priority (the default)
    effort/mMedium: expected under 1 day of work
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 28, 2026
  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 29, 2026
  5. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

    Triage verdict (task 2859, 2026-10-29): already fixed on current main — closing

    The fix this issue asks for is already present in developing-today/code. Verified read-only against current main today:

    pkgs/mcpx/internal/daemon/routes_resolve_test.go, isolate() (lines 28–50):

    • fake home created with os.MkdirTemp("/tmp", "mcpx-test-home-") — outside the real $HOME tree, exactly the PR feat(id): add bounded pure Roc JSON library #221 approach this issue prescribes;
    • HOME, XDG_CONFIG_HOME, GOTMPDIR and TMPDIR all pointed at the fake home inside isolate(), before any t.TempDir call in the tests that use it;
    • plus a later refinement the nix version did not have: the fake home is passed through filepath.EvalSymlinks so path comparisons also hold on macOS (/tmp → /private/tmp).

    That matches the carried-over verification in this issue's own history (dezren39, 2026-10-15: exact repro preconditions — real ~/.config/mcpx/config.json present, TMPDIR under the real $HOME — go test -count=1 ./internal/daemon/ 30/30 PASS on the nix tree's main at fe3038f, fix = PR #221 commit 995fb9a, merged 2026-09-30 as 0e38804). The re-home carried both the fix and that verification into this repo; the acceptance criteria (daemon tests pass with TMPDIR under real $HOME; tests hermetic; no production behavior change) are met by test-only code already on main.

    Dedupe pass: searches for "mcpx daemon tests HOME config walk hermetic" and the conformance-set siblings return no other code issue covering this subject — #1988 (mcpx Go tests fail on macOS) is a different failure set (internal/config path tests), not this one. No follow-up packet enqueued: there is nothing left to implement.

    Closing as completed (already fixed upstream, inherited via the #309 re-home).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workkind/bugSomething isn't working (prefixed form of the classic bug label)meta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)status:done

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions