Skip to content

mcpx: small correctness problems in daemon state and caches #1866

Closed

Description

@dezren39

Relocated from dezren39/darwin-nix#78 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).

Parent: #181

Small correctness problems reported during #53, #58, #61. Each verified or marked.

  • Two digests, one name (verified). daemon-<key>.json is named for the daemon key (FingerprintConfig, the set of config files), but its configHash field is a different digest (HashConfig, a schema-cache hash). Observed: file daemon-f10059c89ad1.json, field configHash: 7c2204994f77cc6f. Anyone reading the file will assume they match. Rename the field (e.g. schemaHash) and add the key.
    • Still true at 05c78b2. Info.ConfigHash (internal/daemon/paths.go:274) is written from s.reg.ConfigHash() (internal/daemon/server.go:231, the HashConfig digest, paths.go:312). Worse than the report: GET /v1/resolve returns a field with the same name holding the key (Resolution.ConfigHash, internal/daemon/routes_resolve.go:30-37), so one JSON name means two things on two surfaces. Both the resolver (routes_resolve.go:25-29) and the plugin (plugin/opencode/mcpx/daemon.ts:771-775, which reads the key from the file name and ignores the field) already code around it, so renaming the info-file field breaks no in-repo reader. docs/plugin-discovery.md:66-76 records the collision and defers the rename to this issue.
  • A daemon started with MCPX_SOCKET answers /v1/resolve with that socket for every directory (reported by the plugin work, not re-verified). socketPath honours the env before the key, so the answer is right for the daemon itself and wrong for every other directory it is asked about.
  • The schema cache is not invalidated when an entry gains a field (reported, one instance fixed). Adding Annotations parsed cleanly against an old cache and left it empty, so the destructive-call policy never fired. chore(deps): bump rustix from 0.38.3 to 0.38.21 in /build/nix/setup #58 bumped cacheVersion; the trap remains for the next additive field. Derive the version from the cached type's shape, or fail closed on a missing field.
  • mcpx status does not autostart a daemon (reported). Possibly intended -- status should not change what it reports -- but tests had to run ls first to get a socket. Decide and document.
    • Still true at 05c78b2, still undocumented. CmdStatus pings and prints daemon: not running ({"running": false} with --json) without calling EnsureDaemon (internal/cli/commands.go:1107-1119). Note it dials the recomputed socket, so "not running" can also be chore(deps): bump build/buck/preludes/buck2-prelude from d956689 to fd4ce63 #88's false negative. Recommendation: keep it non-starting (a status query that starts what it reports on is a Heisenberg bug) and say so in mcpx status --help and docs/.

(Reported earlier and no longer reproducible: mcpx --json status exiting non-zero with no daemon. It exits 0.)

No real choice on any item: each has one fix, stated with it. The exec-workdir rework in #69/#70/#73 did not touch any of them (workdirs are evicted by count in pruneWorkDirs, internal/runner/runner.go:808; their future is #187's).

Ease · Impact · Related

Ease S (three independent small fixes) · Impact low-med -- none is user-visible on its own; each misleads the next person debugging which daemon answered, or lets a cache silently hide a field.

Related: #88 (socket resolution; owns the MCPX_SOCKET item, collision 8), #187 (cache mechanism, collision 12), #183 (in flight: the ForConfig comment in the same paths.go describes keying that #56 removed -- the same "which digest is which" confusion as item 1), #103 #104 #107 (the new caches #187 governs).

Security/auth deferred; see tracker.

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#78 (verbatim, oldest first):


    @dezren39 · 2026-09-30T07:28:12Z

    Integration pass -- cross-theme collision. Surfaced only when the themes were put side by side; the authors of these issues could not see each other's work. Recorded at the root in #181.

    #88 cannot be finished while #78 is open

    MCPX_SOCKET overrides both the computed path and the info file, so #88's rule that "the record is authoritative" is not true until #78 decides how the override interacts with it. #85 and #86 then build on the hole.

    Also on: #88. Nobody currently owns this.


    @dezren39 · 2026-09-30T07:28:26Z

    Integration pass -- cross-theme collision. Surfaced only when the themes were put side by side; the authors of these issues could not see each other's work. Recorded at the root in #181.

    Three new content-addressed caches, one cache design needed

    #103, #104 and #107 each introduce a content-addressed cache, sized for node_modules trees and Nix closures -- orders of magnitude larger than what pruneWorkDirs/defaults.ExecWorkDirs was sized for. Without one design across the three, #78 gets a fourth instance of the same problem.

    Also on: #103 #104 #107. Nobody currently owns this.


    @dezren39 · 2026-09-30T07:28:48Z

    Integration pass. This issue has no category tracker -- it predates the build-out and is a dependency of several parts of it. Placed in the proposed order at #181.


    @dezren39 · 2026-09-30T11:05:41Z

    Collision ownership (issues pass, 2026-09-30, at 05c78b2). #181 listed these cross-theme collisions with no owner. Each now has one:

    #181 row Collision Owner What the owner decides
    8 MCPX_SOCKET overrides both the computed path and the info file #88 The precedence of MCPX_SOCKET versus the info file is socket resolution, so #88 decides it; #78 drops it from its own list and links #88. Note #182 already made test cleanup resolve through the info files (stop --all).
    12 three new content-addressed caches (#103, #104, #107) #187 (new) One cache mechanism (layout, keys, byte/age eviction, leases, nix GC roots) under #175; the three issues own only what they put in it.

    Where this issue is the owner, the decision is made here; where it is not, it adopts the owner's decision rather than making its own.


    @dezren39 · 2026-09-30T12:12:05Z

    Issues pass (2026-09-30, at 05c78b2).


    @dezren39 · 2026-10-28T20:53:34Z

    Triage verdict (lane A, task 2053, 2026-10-28): all three remaining items CONFIRMED at current HEAD — small, decided fixes, routed code-side; kept open under #181.

    Evidence (owning repo developing-today/code @ 528886e; the mcpx source left dezren39/nix on 2026-10-19, #468):

    1. Two digests, one name — still true. The daemon info file's configHash field (internal/daemon/paths.go:428, Info.ConfigHash) is written from s.reg.ConfigHash() (internal/daemon/server.go:296) — the schema-cache hash — while GET /v1/resolve's configHash (internal/daemon/routes_resolve.go:34, set at :108) is FingerprintConfig(...), the daemon key that also names the info file. Same JSON name, two different digests, on two surfaces.
    2. Schema-cache version still hand-bumped. internal/daemon/registry.go:124-128: the comment still reads "cacheVersion is bumped whenever a cached entry gains a field" and the constant is now 5, compared on load at :256. The trap the issue describes is intact — the next additive field silently parses against a stale cache unless a human remembers the bump.
    3. mcpx status autostart — still undecided in code. CmdStatus (internal/cli/commands.go:1311) still pings, prints daemon: not running ({"running": false} with --json), and never calls EnsureDaemon. The issue's recommendation (keep it non-starting; document it) has not been taken or documented.
      (The fourth item was already moved to chore(deps): bump build/buck/preludes/buck2-prelude from d956689 to fd4ce63 #88 and is not counted here.)

    Routing: no nix follow-up packet — each fix is small and fully specified in this issue (rename the info-file field to schemaHash; derive the cache version from the cached type's shape or fail closed; keep status non-starting and say so in --help/docs/), but the code lives in developing-today/code and re-homing is tracked by #309 (OPEN). No counterpart for #78 exists there yet, so #78 stays open under tracker #181 with this verification as its current-state record.

  3. added
    bugSomething isn't working
    queue/queuedHas a queued task in the Supabase agent queue
    on Oct 28, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

    • Agent: queue worker (repo-worker-code), Lane A shift
    • Session / ID: queue task 2758, shift 2026-10-28 23:04 CDT
    • Found via: queue claim
    • Task: Triage relocated issue (was mcpx: small correctness problems in daemon state and caches dezren39/darwin-nix#78): verify each listed correctness item against current pkgs/mcpx main, dedupe, enqueue follow-up(s) — no implementation in this task
    • Expectation: effort s; done = per-item verdict posted, follow-up(s) enqueued or items closed with reasons, labels truthful
  5. 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
  6. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Triage verdict — CONFIRMED (all three remaining items), not a duplicate (queue task 2758)

    Verified against current main at 42796be5 (2026-10-29). The struck-through MCPX_SOCKET item stays out of scope (moved to the socket-resolution owner, as the issue records).

    1. Two digests, one name — still true. Info.ConfigHash (internal/daemon/paths.go:428, JSON configHash) is written from s.reg.ConfigHash() (internal/daemon/server.go:296, the schema-cache HashConfig digest), while Resolution.ConfigHash (internal/daemon/routes_resolve.go:34, same JSON name) holds the daemon key (FingerprintConfig, assigned at routes_resolve.go:108). One JSON name, two digests, two surfaces — exactly as reported.
    2. Schema cache version is still hand-bumped — trap intact. cacheVersion = 6 (internal/daemon/registry.go:136, comment at :132 admits the failure mode: an added field "parses cleanly against an old file and leaves it empty"), compared on load at registry.go:264. It has been bumped by hand since the report (4 → 6); nothing derives it from the cached type's shape and nothing fails closed on a missing field.
    3. mcpx status still does not autostart, still undocumented. CmdStatus (internal/cli/commands.go:1311) pings and prints daemon: not running ({"running": false} with --json) with no EnsureDaemon call. The issue's recommendation stands: keep it non-starting (a status query that starts what it reports on is a Heisenberg bug) and document that in mcpx status --help and the docs.

    Dedupe: searches for the configHash rename, cache-version derivation, and status-autostart found no other code issue covering any item. (Numbers cited in the original body — #88, #187, #183 — are historical dezren39/nix numbering, not code-repo issues.)

    Follow-up: one small_fix packet enqueued for the set (three independent one-fix items, Ease S as the issue rates them): rename the info-file field to schemaHash + include the daemon key, derive/fail-closed the schema cache version, and document status's non-starting behavior. Verification: cd pkgs/mcpx && go test ./... via CI.

    🤖 Agent note · done (triage)

    • Agent: queue worker (repo-worker-code), Lane A shift
    • Session / ID: queue task 2758
    • Task: Triage complete — verdict above; follow-up enqueued; no implementation in this task, per packet
  7. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Follow-up from the triage above: enqueued as queue task 3085 (small_fix) — the three confirmed items as one set. Labels updated to mirror that queued follow-up.

  8. 12 remaining items

  9. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  10. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  11. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Oct 30, 2026
  12. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions