Skip to content

mcpx: a promise and a behaviour that disagree — every declared surface needs a guard that walks it (tracker) #1893

Open

Description

@dezren39

Relocated from dezren39/darwin-nix#177 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

Purpose

Six open issues are filed separately and are the same bug six times: something mcpx
declares does not do what the declaration says.
A doc promises a capability the binary
does not have (#102, #159). A flag is accepted and is inert (#108). A function is built,
tested and never called (#116). An env var is honoured and declared nowhere (#172). A
concept — "a script file" — is resolved one way locally and another way remotely (#106).

Every one of them was found by a human, by hand, after shipping: reading --help, reading
a flag definition, trying a documented example. None was found by a test, because no test
was watching the seam. That is the argument for treating them as one item: fixing the six
instances leaves the seam unwatched and the seventh arrives on schedule.

Done looks like: each instance fixed, and — the part that matters — every surface in
mcpx that declares a set of things has a test that walks that declaration and proves each
member does something observable. The inventory below is the checklist for the second half.

The class, stated

A promise-and-behaviour disagreement is any place where mcpx publishes a set — commands,
flags, routes, tools, settings, environment variables, documented capabilities — and a
member of that set does not do what publishing it implies. The failure mode is specific and
nasty: it is indistinguishable from success. A flag that does nothing parses cleanly and
exits 0. A documented feature that does not exist reads exactly like one that does. An
unread setting appears in mcpx settings. The user's evidence and the code's behaviour are
both silent, so the bug survives until somebody tries the thing for an unrelated reason.

This is distinct from a plain defect, where something is attempted and produces a wrong
answer. Here nothing is attempted at all, and the surface reports that everything is fine.

Instances

Added to this tracker in the 2026-09-30 issues pass, after the bodies above were written. Each is
the same shape; none changes the thesis.

Precedent (closed)

Each of these was the same class, each was fixed as a one-off, and each was found by a
person noticing rather than by a test failing.

  • Bump checkmarx/ast-github-action from 2.0.19 to 2.0.20 #39 (merged) — mcpx declared MCP sampling and the passthrough from fix(deps): update rust crate serde to 1.0.188 - autoclosed #31 was unreachable: the handler was installed after the handshake, so the capability was announced and never offered. Found while answering "what was the decision for sampling?", not by a test — the tests called the passthrough directly, which is how it passed.
  • Update Rust crate bimap to 0.6.3 #66 (merged) — mcpx exec --typecheck=on accepted the flag and ignored it, because opts.TypeCheck was assigned inside the else branch of the inline/file split. Found by asking "does a typo'd namespace fail validation or partially run?" It partially ran. Two further faults were stacked underneath it and each hid the next.
  • Update Rust crate petgraph to 0.6.4 - autoclosed #74 (closed) — --launcher and --allow-repeat accepted by mcpx exec and silently dropped, because writeLauncher was guarded by if opts.File != "". Filed with the observation that this was already "the third instance of the same shape", and the proposal that a test should walk the command table.
  • Update Rust crate proc-macro2 to 1.0.81 - autoclosed #75 (merged) — the fix. Auditing the one flag found five: --launcher, --no-launcher, --export, --allow-repeat, --no-capture-console, all defined for exec, all in its help, all read only when a file was given. It shipped TestEveryExecFlagChangesSomething, and its closing note is the thesis of this tracker: "This fault has now shipped three times … and each was found by accident, because a flag that does nothing looks exactly like a flag that worked."

Four closed instances, six open ones, ten total, zero found by a test written to find them.

The systemic fix: guard tests

The repo has already invented the answer three times without generalising it. A guard test
takes a declared set and asserts that every member of it does something observable.

Existing guard file:line Declared set it walks How it proves the member works
TestEveryDeclaredRouteAnswersOverTheSocket internal/e2e/v1ops_test.go:287 api.Ops() real request over the daemon socket
TestEveryExecFlagChangesSomething internal/e2e/e2e_test.go:2743 hand table of 4 flags runs the same source with and without the flag and requires the outcome to differ
TestNoPackageRedeclaresADefault internal/defaults/guard_test.go:92 defaults.json regex source scan for constants declared elsewhere
TestEverySettingIsReadSomewhere internal/settings/consumed_test.go:73 the settings registry (149 paths at 05c78b2) the path must appear as the argument to an accessor on a resolved Set, outside internal/settings
TestNoHandRolledSettingEnv internal/settings/consumed_test.go:145 same, facing outward no os.Getenv of a variable the registry owns
TestThePluginReadsNoUndeclaredSetting internal/settings/consumed_test.go:209 plugin TypeScript env reads every honoured variable resolves via sch.ByEnv

consumed_test.go is the most developed of the four and worth reading before writing the
next one, for two reasons stated in its own header comment. First, it rejects the obvious
design — a ReadBy: "daemon" field on the declaration — because "that note sits in the same
struct literal as the declaration, gets written in the same keystroke by someone who believes
both halves, and nothing checks the second."
A guard must ask the code, not the author.
Second, it narrows the question from "does this string appear anywhere" to "is it handed to
an accessor on a resolved Set", because pool.max was honoured from a config file and
ignored from its variable and its flag — half-read, which a grep calls live. It found 54
dead settings of 149 (#171).

The generalisation: for every surface that declares a set, there is a test that walks the
declaration and proves each entry does something.
Where no declaration exists, the first
task is to create one — an undeclared set cannot be guarded, only audited by hand, which is
what got us here.

Surface inventory — guarded vs unguarded

Counts and line numbers checked on 8001f23.

Surface Declaration lives in Guard test Status
Settings registry (149 at 05c78b2) internal/settings/registry.go, exec.go, proto.go, plugin.go, consumer.go registry_test.go:27,41,287; consumed_test.go:73,145,209; docs_test.go:19 guarded, both directions — the model for the rest
/v1 routes ↔ ops table (190 op names) internal/api/ops*.go, Ops() at ops.go:140 internal/api/parity_test.go:54,73; internal/e2e/v1ops_test.go:287 guarded — but route discovery is a regex over internal/daemon/*.go and the e2e probe asserts only "not 404/5xx" (see #129)
MCP tools from the ops table internal/api/ops*.go internal/api/parity_test.go:87 guarded (non-streaming ops only)
Package defaults internal/defaults/defaults.json internal/defaults/guard_test.go:92 guarded, leaking — regex scan, and an outOfScope allowlist exempting eight whole packages that nothing shrinks
Plugin options ← registry internal/settings/plugin.go consumed_test.go:209 guarded one way — the reverse (13 options in plugin/opencode/README.md vs 9 registered) is unguarded, #159 item 9
exec/run flags internal/cli/commands.go:434-481 — 23 hand-declared, plus whatever parseFlags binds from the registry e2e_test.go:2743 covers 4 effectively unguarded — the table is hand-maintained with a comment saying "add a row when you add a flag"; three flags #75 itself fixed have no row
All other per-command flags ~118 hand-rolled fs.String/Bool/Int/Duration/Var calls across internal/cli/*.go none unguarded — the exact shape of #74/#75 on every command except exec
CLI commands Commands() at internal/cli/manual.go:33 (32 entries) vs the dispatch map at cmd/mcpx/main.go:119-161 (42 keys) none unguarded — serve, openapi, adapter, registry, api, man, completion and the logs alias are dispatched and undeclared, so they are absent from mcpx help <cmd>, the man page and completion (#159 item 1)
MCP tools from Extra (adapters, OpenAPI specs, /v1 proxies) internal/cli/serve.go:346,391; internal/mcpserver/server.go:106-194 none unguarded — computed once at server construction, invisible to internal/codegen, so tools/list and the generated client disagree by construction (#102)
Generated TS client ↔ tools/list internal/codegen vs internal/mcpserver none unguarded — the parity test #102 proposes; this is the mechanical half of "every documented capability exists"
MCPX_* inbound, unregistered nowhere — 44 of 64 referenced names none possible today unguarded, and undeclarable — TestNoHandRolledSettingEnv cannot see them precisely because the registry does not own them (#172)
MCPX_* outbound (script contract) nowhere — set by internal/runner/internal/execsvc none unguarded — needs a declared table before a guard can exist (#172 approach C)
diagnose.CallError and any other built-and-uncalled export internal/diagnose/diagnose.go:483 none unguarded — no linter runs on mcpx in CI at all, so an unreferenced export is invisible; #116 asks for a targeted test, the class asks for a dead-export check
Script-file resolution two implementations: internal/cli/scripts.go:254 and internal/execsvc/execsvc.go:326 → internal/runner/runner.go:293 none unguarded — one concept, two behaviours, no test comparing them (#106, class half)
docs/parity.md (69 table lines) hand-written none unguarded — no test reads the file; the parity test checks routes/ops/tools and never the document
OpenAPI documents (three: mcpx openapi, mcpx schema --format openapi, GET /v1/openapi.json) internal/api/openapi.go + hand-written none unguarded — they describe different things and one describes a server that was removed (#159 items 3, 4)
Docs code fences (374 across docs/*.md) the prose none unguarded — nothing executes them; docs_test.go:19 checks only that docs/configuration.md lists every setting
/v1 op ↔ CLI command parity api.Ops() vs Commands() none unguarded — #76's table exists as prose, not as a test

Eleven unguarded surfaces, four guarded, two guarded in one direction only. Every open
instance in this tracker sits on an unguarded row.

Division of labour with #129

#129 (mcpx testing: guard tests that close a whole bug class, under #99 under #91) and this
tracker are the two halves of one subject and must not be merged or duplicated.

This tracker #129
Owns the bugs — the six open instances, and the inventory of which surfaces are unguarded the policy and mechanics — how a guard is written, when a bug counts as a class, where exemption lists live
Deliverable each instance fixed; each fix names the surface it leaves unguarded the rule (enumerate → completeness → probe → ratchet → negative test), and the guard implementations
Answers which surfaces need a guard, and what promise each is currently breaking how each guard is built, and how to keep it from decaying
Does not own the shape of the test, the exemption-list ratchet, the no-network and no-leaked-process guards, the AST-vs-regex choice the specific broken promises, or the priority order of fixing them

Concretely: the surface inventory table above is this tracker's output and #129's input.
When #129 picks its next guard, it picks a row from that table. When a fix here closes an
instance, it reports back which row moved from unguarded to guarded. #129's mechanics
sections (approaches A/B/C for writing guards, the no-network sub-choice, the exemption
ratchet, the negative-test requirement) are not restated here and should not be.

Overlap to watch: #129's candidate list already names "every exec/run flag has a row",
"every command's flags", "every /v1 op has a CLI command", and the #102/#106 parity
tests. Those are #129's to build. This tracker's job is to make sure the list is complete
and that the underlying bug is actually fixed, not merely guarded against recurring.

Proposed order

  1. Bump build/buck/preludes/buck2-prelude from d956689 to cb5dc60 #108 — one line, --experimental-strip-types → --experimental-transform-types, plus a test that a file containing enum runs under --runtime node. Ease S, high impact, no dependencies. Ship it first because it is the cheapest possible demonstration that the pattern pays: the fix and its guard are both smaller than this paragraph.
  2. chore(deps): update github.com/developing-today-forks/charm digest to 15e844d - autoclosed #116 — wire diagnose.CallError at the daemon's call boundary. Ease S for the wiring. Second because it is also small, and because a function that has been tested-but-uncalled for months is the clearest illustration of the class to anyone who has not seen it.
  3. Bump build/buck/preludes/buck2-prelude from d956689 to f12c8d1 #102 (doc half) — delete the false sentence from docs/story.md now. There is no reason to keep shipping a known-false claim while the capability is designed. Minutes.
  4. Phase 2: membership, delegation, groups, and server config #172 (inbound half) — move the inbound MCPX_* variables into the registry. Mechanical, 44 decisions, and each one converts a source-only knob into four surfaces at once. Do this before the generated reference (Bump golang.org/x/crypto from 0.16.0 to 0.17.0 in /sources/import #96/🎨 Palette: Improve accessibility of editor search panel #144/⚡ Bolt: Optimize cursor color generation and position grouping #145) is built, or the reference is generated from an incomplete source.
  5. Bump h2 from 0.3.19 to 0.3.24 in /sources/pavex/examples/realworld #106 (class half only) — one script-resolution rule for CLI and daemon. Larger, and it unblocks the harness-free plugin (Update Rust crate anyhow to 1.0.75 #48, Bump rustls-webpki from 0.100.1 to 0.100.2 in /sources/pavex/examples/realworld #44), which has a socket and no binary and therefore cannot resolve a name locally.
  6. Bump build/buck/preludes/buck2-prelude from d956689 to f12c8d1 #102 (capability half) — extras as a real tool source, via chore(deps): bump build/buck/preludes/buck2-prelude from d956689 to 36464cf #83, with the tools/list ↔ generated-client parity test.
  7. Phase 2: membership, delegation, groups, and server config #172 (outbound half) — declare the script environment contract, then guard it.
  8. Root flake check fails on nixosConfigurations due to missing clan-core.clanModules #159 — under Bump golang.org/x/crypto from 0.16.0 to 0.17.0 in /sources/import #96, on its own schedule; sequence it so the doc fixes land before anything is generated from those sources.

Added in the 2026-09-30 pass, slotted by cost rather than appended:

Throughout: each fix names the surface row it sat on and hands it to #129. A fix that closes
an instance without identifying its row has not finished.

Ease / impact

Pulled verbatim from each instance's own footer.

Issue Ease Impact Note
#102 S (doc fix + test) / M (if the capability lands here rather than #83) med "the documented feature is a headline example in docs/story.md"
#106 M (dispatch and cwd policy) / L (shared script resolution across CLI and daemon) high "it turns exec from 'run TypeScript' into 'run a script', and it closes a real CLI-vs-/v1 divergence of the kind #76 tracks" — only the resolution half is this tracker's
#108 S for the flag (one line + a test asserting a non-erasable file runs under --runtime node), M for the probe and messaging high "silently restricts the language on any machine without deno or bun"
#116 S for the wiring, M with the structured field decided med-high "turns an opaque protocol error into the specific reason, on every surface at once"
#172 M (mechanical, but 44 call sites and a decision per variable) med-high "every inbound one is a user-facing option missing from four surfaces at once"
#159 M (items are small; C's single-sourcing is the bulk) high "blocks an accurate reference" — native sub-issue of #96
#178 S (a handful of lines each; the presence test is the bulk) med "nothing is broken for a user today; everything here is a prerequisite that gets more expensive the longer #158 waits on it"
#179 S low–med two small defects, and the guard-test hole that is this tracker's most important finding
#180 S med editing, not engineering — and one of its corrections stops a wrong fix being made
#183 S low–med "no user-visible bug, but it misdescribes the mechanism a reader most needs to trust when debugging which daemon answered"
#188 S med duplicated pools and unstable keys, intermittently — the expensive kind of wrongness
#189 S (the three fixes) / M (round-trip test) / M–L (generated types) high the documented way to call a tool from the plugin passes neither the arguments nor the session
#190 M (the fix is small; the decision and cross-platform verification are the work) med one extra server process per wrong-case spelling, silently, with no wrong answers
#191 S low–med a diagnostic that reports the opposite of what happened, at the moment someone is debugging isolation
#192 S (B) / M (C) med-high "remote exec is the path the ssh and browser surfaces (#174) build on"
#193 S (A, B) / M (C, with #6's gap contract) med silent loss on the one path documented as lossless

Warnings

  1. A guard that cannot be enumerated is a reminder, not a guard. TestEveryExecFlagChangesSomething is the cautionary example in this repo: it was written as the fix for Update Rust crate petgraph to 0.6.4 - autoclosed #74/Update Rust crate proc-macro2 to 1.0.81 - autoclosed #75 and it has four rows against 23 hand-declared flags plus every exec-scoped setting the registry binds, including three flags Update Rust crate proc-macro2 to 1.0.81 - autoclosed #75 itself repaired. Its comment says "Add a row when you add a flag" — which is the memory the guard was created to replace. Any new guard that starts from a hand table inherits this failure on day one.

  2. Acceptance is not effect, and Bump build/buck/preludes/buck2-prelude from d956689 to cb5dc60 #108 is the proof. Node 24 accepts --experimental-strip-types and exits 0. A guard asserting "every flag we pass to a subprocess is a flag that subprocess accepts" passes cleanly on the exact bug in this tracker. Guards must observe a difference in outcome (the Update Rust crate proc-macro2 to 1.0.81 - autoclosed #75 with-and-without pattern), never the absence of an error.

  3. Fixing all six without adding guards is the failure mode this tracker exists to prevent. Bump checkmarx/ast-github-action from 2.0.19 to 2.0.20 #39, Update Rust crate bimap to 0.6.3 #66, Update Rust crate petgraph to 0.6.4 - autoclosed #74 and Update Rust crate proc-macro2 to 1.0.81 - autoclosed #75 were each fixed individually and correctly, and the class arrived four more times. If the fix PRs land and the inventory table above is still eleven rows of "unguarded", nothing has been learned — record that plainly in the closing comment rather than closing quietly.

  4. A guard with an allowlist decays into a no-op unless something shrinks it. TestNoPackageRedeclaresADefault exempts eight whole packages via outOfScope "owned by work happening in parallel", and that parallel work has since landed. consumed_test.go's unreadAllowed has exactly one entry with a paragraph of justification — that is the standard to copy, and Add omasnap upstream repository to flake inputs #129 owns the ratchet that enforces it.

  5. Regex source scans pass silently when they are wrong. PR chore(deps): bump rustix from 0.37.19 to 0.37.25 in /sources/pavex/examples/realworld #56: the defaults guard matched "5 * time.Minute" while gofmt writes 5*time.Minute in call arguments, so nine live constants were invisible and the test reported green. Two of the six guards in the table above are regex scans. Prefer walking a registry; use go/ast when there is no registry; never regex when a declaration exists to enumerate.

  6. Do not run the full test suite to check any of this. go test ./... is ~135 s with internal/e2e at ~101 s. The four-hour daemon leak is fixed — Phase 5: tag event bodies must travel with the event #182 closed chore(deps): bump build/buck/preludes/buck2-prelude from d956689 to e7457f6 #52 by having cleanup call stop --all through the daemon-<key>.json info files and setting MCPX_AUTOSTART_IDLE_EXIT=60s in every test environment (internal/e2e/e2e_test.go:68-83) — so the reason is now time, not hygiene. What is still true is Update dependency htmx.org to v1.9.12 #138: the suite inherits the caller's environment, so a run can reach a developer's real daemon. Run the specific package.

  7. Root flake check fails on nixosConfigurations due to missing clan-core.clanModules #159 and Bump h2 from 0.3.19 to 0.3.24 in /sources/pavex/examples/realworld #106 must not be re-parented. Root flake check fails on nixosConfigurations due to missing clan-core.clanModules #159 is a native sub-issue of Bump golang.org/x/crypto from 0.16.0 to 0.17.0 in /sources/import #96, Bump h2 from 0.3.19 to 0.3.24 in /sources/pavex/examples/realworld #106 of fix(id): make Nix E2E check reproducible #175, and GitHub permits one parent. Adopting either here would silently remove it from the tracker where the work is actually scheduled. Native sub-issues of this tracker at 05c78b2 are Bump build/buck/preludes/buck2-prelude from d956689 to f12c8d1 #102, Bump build/buck/preludes/buck2-prelude from d956689 to cb5dc60 #108, chore(deps): update github.com/developing-today-forks/charm digest to 15e844d - autoclosed #116, Phase 2: membership, delegation, groups, and server config #172, Phase 3: range read_flight buffers frames with no cap while more is set #178, Phase 3: /id-sync/1 is used by both range and LogSync handshakes #179, Phase 3: sync data phase batches are bounded by count, not bytes #180, Phase 5: persisted incremental tag index #183, Phase 3: test_an_interrupted_session_restarts_without_duplicates flakes under full-suite load #188, Phase 4: joiner misses an update made without knowing its concurrent add #189, Serve stalls before printing node in test_world_module_shared_over_iroh_and_web_presentations #190, Phase 4: groups, encryption, and history #191, Phase 4 fix: a joiner fetches the epoch it missed #192 and id: lib does not build with --no-default-features #193; Bump h2 from 0.3.19 to 0.3.24 in /sources/pavex/examples/realworld #106 and Root flake check fails on nixosConfigurations due to missing clan-core.clanModules #159 are members of the class listed in the task list above and nothing more.

Related

Parent: #181

Related: #129 (the testing-side half — guard mechanics and policy; read it before writing any
guard), #99 (its tracker), #91 (the strategy above both), #49 (CI for every package — a guard
that does not run in CI is a guard nobody runs), #52 (closed, fixed in #182 — the leak is gone;
#138 still owns the environment-inheritance half), #159 (member of this class, tracked natively under #96), #175 (runtimes tracker, which owns #106), #171 (the merged settings
audit that produced consumed_test.go and found 54 dead settings of 149), #83 (one tool-source
interface, which #102's capability half belongs to), #76 (CLI ↔ /v1 parity, an unguarded row),
#96 / #144 / #145 (the generated reference, which reads several of these declarations and will
publish whatever they contain).

Closed precedent: #39, #66, #74, #75.

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


    @dezren39 · 2026-09-30T12:25:19Z

    Issues pass (2026-09-30, at 05c78b2). Brought current; the class argument and the surface
    inventory are unchanged, because both are still right.


    @dezren39 · 2026-09-30T12:26:14Z

    Issues pass (2026-09-30, at 05c78b2) -- for whoever lands this. This issue is in flight, so its body was not edited. These came out of re-checking every other issue against current main; each is verified at 05c78b2 unless marked.


    @dezren39 · 2026-09-30T12:28:08Z

    Follow-up: the task-list bullet in my previous comment was overtaken by the 12:25 revision a minute earlier -- #183 and #188-#193 are now in the body. The other bullets stand.


    @dezren39 · 2026-09-30T12:32:58Z

    Correction to the pass comment above: the settings registry declares 149 paths at 05c78b2, not 151. 104 across registry.go/exec.go/proto.go/plugin.go/consumer.go plus 45 more in wire.go (the autostart.* family and others), with no overlap; a naive grep over internal/settings/*.go reaches 151 only by counting two test-only paths in registry_test.go twice over. The body is corrected. #181's evidence section had it right.


    @dezren39 · 2026-09-30T19:35:44Z

    SURFACES pass (2026-09-30). Instances of this class found and fixed while shipping the SURFACES list, each with a test that fails without the fix. Rows of the surface inventory that moved from unguarded to guarded are marked → guarded.

    instance where it was declared fixed in guard
    Commands() declared 34 names, main dispatched 42 (serve openapi adapter registry api man completion + logs) internal/cli/manual.go vs cmd/mcpx/main.go #244 TestEveryDispatchedCommandIsDeclared → guarded (CLI commands row)
    27 of 60 operations had no CLI command, no parity row ops table #244 (generated commands) TestEveryOperationIsReachableFromTheCLI, TestEveryGeneratedCommandReachesItsRoute → guarded (/v1 ↔ CLI row)
    docs/parity.md 33 rows / 60 ops hand-written doc #244 (generated) TestParityDocumentIsCurrent → guarded
    plugin DaemonClient.call() sent arguments/sessionId; /v1/call reads args/session -- every tool called with no arguments plugin/opencode/mcpx/daemon.ts #244 fake + live-daemon bun tests, now run from go test (TestThePluginSuiteRunsAgainstARealDaemon)
    mcpx_artifact_put stored {} as every artifact's content generated MCP tool #244 (Param.Raw) TestMCPArtifactPutStoresTheContent
    mcpx init wrote "mode", which the loader drops starterConfig #234 TestStarterConfigMeansWhatItSays; unknown keys in the mcpx block are now refused by name
    elicit.confirmDestructive failed open on a cold schema cache -- the destructive call ran unasked internal/daemon/consumer.go #262 TestConfirmDestructiveHoldsOnAColdDaemon
    recipes / intents / /v1/diagnose used an empty catalog on a cold daemon same #262 TestARecipeRunOnAColdDaemonSeesItsServers, TestDiagnoseOverV1OnAColdDaemonSeesItsServers
    /v1 served cross-origin requests on loopback TCP (a web page could POST /v1/exec) while /mcp refused them internal/daemon/server.go #267 TestAWebPageCannotRunCodeThroughTheDaemon, TestV1AndMCPAgreeOnOrigins
    prompt.mode (and six other call-scoped consumer settings) ignored from env, flag and PUT /v1/settings, which answered applied: true; an unknown value silently meant the default internal/daemon/consumer.go #266 (renamed prompt.autonomy, decision 0002) TestTheCallersPromptAutonomyReachesTheDaemon, TestAPromptAutonomySetOverTheAPIIsHonoured, TestAnUnknownAutonomyIsRefused
    mcpx exec --before/--on-success/--on-error accepted and dropped internal/cli/commands.go #265 TestASnippetRunsItsBeforeAndOnSuccessPhases
    a top-level throw skipped onError and suffix launcher template #265 TestAThrowingSnippetRunsOnError, TestAFileThatThrowsAtTopLevelRunsOnErrorAndSuffix
    mcpx exec --remote lost its output internal/cli/exec.go #265 TestARemoteExecPrintsItsOutput
    bus kinds call.started, task.updated declared, never published internal/events #265 (removed) --
    script.permissions strict ran with full authority on node/bun internal/runner #274 TestAStrictScriptCannotReadFilesOnARuntimeWithoutPermissions + unit
    restart claimed MCP idempotentHint ops table formula #274 TestIdempotentHintIsTrue
    every restriction: enforced-with-a-refusal-test or advisory-with-an-issue new api.Boundaries() #274 (decision 0003) TestEveryEnforcedBoundaryNamesItsRefusal → guarded (declared-vs-enforced row)

    Merged earlier from the same list: #230 (#116, diagnose.CallError wired), #237 (#172, MCPX_* declared, script env contract; acronyms in derived names), #243 (#179), #227 (#183), #248 (openapi, #102 guard).

    Still unguarded from the inventory: per-command hand-written flags other than exec (~118), script-file resolution local vs remote (#106), docs code fences. Flakes seen while verifying, filed: #270 (TestAStreamConsumerCanCancelAfterTheResult), and already-filed #238, #272.

  3. added
    bugSomething isn't working
    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 · picked up

  6. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    Triage verdict — task 2801 (lane D)

    Verdict: NOT a duplicate. Scope confirmed against current pkgs/mcpx main. Every instance in the body is now accounted for: nine were fixed in the nix repo before relocation (never moved — nothing is owed for them), six were relocated and are open here with their own queued triages, and one (the re-verification artefact) was closed today. The guard half — the part this tracker says matters — is partially landed on main, and its remainder is already owned by queued testing issues (#1971, #1909, #1969). No new packet is enqueued for #1893 itself; that would duplicate those owners.

    Instance mapping (nix numbers in the body are historical)

    Fixed before relocation — closed in dezren39/nix with the fix PR named on the original; do not re-file:

    nix Fix evidence
    #102 adapted binary not callable from a script fixed in nix PR #301 (merged 3ea44c2); doc sentence corrected earlier in #248
    #108 --runtime node strip-types flag closed in nix; native code equivalent #263 is also closed
    #116 diagnose.CallError never called closed by nix PR #230 (now called from Registry.Call, all six surfaces)
    #172 44 undeclared MCPX_* variables closed by nix PR #237 (registry setting or ScriptEnv() contract for every one; shrink-only allowlist; generated docs/environment.md with drift test)
    #179 registry.pageSize unreachable / nextCursor dropped closed by nix PR #243
    #183 ForConfig comment describes removed keying closed by nix PR #227
    #188 Resolved.PoolID hashes Headers in map order marked done in the body ([x]); no relocated counterpart exists or is owed
    #191 degraded-scope log line says 'per-call' fixed via nix PR #396 (merged 84b30a5); native code pair #280/#281 is also closed
    #192 remote exec accepts and drops most exec flags fixed in nix PR #301 (merged 3ea44c2)

    Relocated — open here, each with its own queued triage (per the 2026-10-28 placement-audit move lists):

    nix code Triage task
    #106 exec shebang / file-script resolution #1919 queued
    #159 incomplete generation sources / false docs #1883 2776
    #178 man page / completions / version unverified #1895 triaged today (task 2789); fix follow-up 3140 enqueued
    #189 plugin sends field names the daemon does not read #1910 2805
    #190 wrong-case cwd keys separately #1912 2807
    #193 /v1/events replay drops past 256 silently #1914 2809

    Relocated and now closed: #180 → #1897, triaged and closed today (task 2791, lane C): most findings fixed/moot at current main, live remainders owned by #1883/#1895.

    Per the body's own warning 7, #159 and #106 are members of this class only — they stay parented/tracked under #1903's tree and #1889 respectively; nothing here re-parents them.

    Scope confirmation vs current main — the guard half

    Checked at main = 8124cc0b7005 (2026-10-29T05:56:32Z):

    Verification commands for the follow-ups (per the triage packet)

    Outcome

    #1893 stays open as the class tracker. This triage task completes; follow-ups are the instances' and guard issues' existing queue tasks named above.

    🤖 Agent note · done

  7. 14 remaining items

  8. dezren39 commented on Nov 3, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: triaged (coverage pass)
    Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/none). If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
    Found via: coverage pass 2026-11-03

  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: picked_up
    task: 8716 (triage, repo-health-code-pilot; repo-worker-code; OpenChamber scheduled lane aea12c82-c5af-4e5a-9b66-f8e360f87177)
    state: claimed; fresh GitHub state: #1893 is OPEN with no hard-stop labels. The tracker remains live: guard remainder #1971 is OPEN and already routed through task 8158 (claimed, execution lane opencode); related tracker #1909 remains OPEN; #1969 is CLOSED after merged PR #5055. Prior triage found this is not a duplicate and that no new #1893-specific implementation packet should duplicate the owned children.
    next: post triage verdict with fresh evidence and complete task 8716 as triaged, referencing existing follow-up task 8158.

  10. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  11. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    Triage verdict — task 8716

    Verdict: still live; keep #1893 open. The tracker is not a duplicate. Its remaining purpose is the class-wide guard coverage; do not enqueue another implementation packet that duplicates the existing child owners.

    Fresh state (2026-11-04)

    The previous instance-by-instance triage (task 2801, re-confirmed by task 7772) remains consistent with this state: the guard remainder stays with #1971 and the separately tracked children; #1893 remains a coordination tracker until that work lands. No code or PR changes were made in this triage.

    Route: continue task 8158 for #1971; keep #1893 open and do not create a duplicate follow-up.

    Evidence: #1971 #1971 · #1909 #1909 · #1969 #1969 · PR #5055 #5055

  12. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    event: done
    task: 8716 (triage, repo-health-code-pilot; repo-worker-code; OpenChamber scheduled lane aea12c82-c5af-4e5a-9b66-f8e360f87177)
    state: triaged; queue task completed. Issue #1893 remains OPEN and is not a duplicate. Existing guard remainder task 8158 owns #1971; no duplicate follow-up task was created. Fresh route evidence and the verdict are in the triage comment above.
    labels: queue/claimed, status/in-progress, and work/assigned removed; non-flight labels retained.
    links: task 8158 / #1971 · merged PR #5055

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingsource/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions