fix(mxc): agent tools fail in Windows workspace subdirectories - #115399
Conversation
|
Codex review: needs maintainer review before merge. Reviewed August 5, 2026, 8:47 PM ET / August 6, 2026, 00:47 UTC. ClawSweeper reviewWhat this changesThis PR makes the MXC sandbox validate agent-selected work directories and moves filesystem-bridge initialization into the constructor to prevent provisioning crashes under the plugin source loader. Regression provenancePossible regression — probable (reproduction; reviewed change). No predecessor PR is attributed. Merge readinessKeep open: current main still contains both MXC failure paths, while this focused owner-local repair uses the existing backend validation contract and has discriminating exact-head Windows/jiti runtime proof. Priority: P1 Review scores
Verification
How this fits togetherMXC is the sandbox plugin used by agent tools. Tool-selected directories and sandbox configuration flow through its backend and filesystem bridge before an agent command is launched. flowchart LR
A[Agent tool request] --> B[MXC backend]
B --> C[Workdir validation]
C --> D[Sandbox setup]
D --> E[Filesystem bridge]
E --> F[Tool execution]
Before merge
Agent review detailsSecurityNone. PR surfaceSource +26, Tests +23. Total +49 across 3 files. View PR surface stats
Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Preserve the MXC-local repair, refresh it against current main, and merge after exact-head checks remain green. Do we have a high-confidence way to reproduce the issue? Yes. The exact-head Windows runtime probe discriminates fixed from pre-fix bridge behavior, and current main retains the same source-loader path and hazardous initializers. Is this the best way to solve the issue? Yes. MXC owns its workspace mapping, so using the established backend validator avoids changing generic Docker, SSH, or core behavior for plugin-specific path semantics. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against a1064adb6861. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (25 earlier review cycles; latest 8 shown)
|
69a8aee to
7f09404
Compare
7f09404 to
c167d38
Compare
b5ca3a4 to
39f8e43
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: fc20c06c-e8c0-4649-9efd-ad87fac71a4f
validateWorkdir declares that unusable workdirs return null, but only ENOENT was classified as missing. A workdir nested under a file raises ENOTDIR on Linux, which escaped as a raw filesystem error instead of the normal unavailable-workdir result. The same ENOENT-only classification appeared at three sibling sites in this file, so the shared isMissingPathError guard fixes the whole class rather than the single reported path. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d7253887-71c9-4083-a591-91979c981e39
MxcFsBridge initialized three fields from this.sandbox, but sandbox is a constructor parameter property. Plugin sources load through jiti, which evaluates field initializers before assigning parameter properties, so this.sandbox was still undefined and every MXC sandbox provisioning failed with SandboxProvisioningError: Cannot read properties of undefined (reading 'containerWorkdir'). Assign the derived fields in the constructor body from the sandbox parameter instead. The repo tsconfig sets useDefineForClassFields=false, so tsgo and Vitest (esbuild) both apply legacy ordering and could not observe the failure; only the jiti-loaded runtime path did. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: d7253887-71c9-4083-a591-91979c981e39
|
@RomneyDa - can you take a look? |
What Problem This Solves
Two failures on the MXC sandbox backend.
Agent tools could not run from Windows workspace subdirectories. A valid
child of the agent workspace written with slash-normalized Windows path
semantics was rejected. Invalid workdirs also failed inconsistently:
validateWorkdiris contracted to returnnullwhen a workdir is unusable,but only
ENOENTcounted as "missing", so a workdir nested under a file raisedENOTDIRon Linux and escaped as a raw filesystem error.Every MXC sandbox provisioning attempt crashed. Building the filesystem
bridge threw before any tool could run:
Why This Change Was Made
MXC now owns validation of agent-selected workdirs by opting into the
backend-owned
workdirValidationcontract, reusing its existing workspaceresolver for canonicalization, containment, existence, and directory checks
before execution. Generic Docker and SSH path behavior is unchanged.
The
ENOENT-only classification appeared at three sibling sites in the samefile, so a shared
isMissingPathErrorguard fixes the class rather than theone reported path.
The provisioning crash was a class-field initialization-order bug.
MxcFsBridgeinitialized three fields fromthis.sandbox, butsandboxis aconstructor parameter property. Plugin sources load through jiti, which
evaluates field initializers before assigning parameter properties, so
this.sandboxwasundefined. Those fields are now assigned in theconstructor body from the parameter.
User Impact
Agents configured with the MXC backend can provision a sandbox at all, and can
execute tools from valid Windows workspace subdirectories. Invalid, missing,
out-of-workspace, and nested-under-a-file directories are rejected before MXC
launches and surface as a normal unavailable-workdir result rather than a raw
filesystem error.
Evidence
Exact head and base
88ce07175543df5400d0122d2a55d12e41ec73c8e69c3df2361b38285917c29b0c90867c75b8ebe9(currentmainat rebase)extensions/mxc/src/mxc-backend.ts,extensions/mxc/src/fs-bridge.ts,extensions/mxc/test/mxc-backend.test.ts(+56 / -7)Local checks
node scripts/run-vitest.mjs extensions/mxc/test/mxc-backend.test.ts— 49/49pnpm tsgo— cleanoxfmt --checkon all three changed files — cleanReal Windows proof
Fresh Hyper-V desktop guest hydrated from this exact head via
.github/workflows/crabbox-hydrate.yml(hydrate-windows-daemon):88ce07175543df5400d0122d2a55d12e41ec73c8v24.19.0, pnpm11.15.1, Windows 11pnpm buildon the guest — exit 001-vitest-49.mp4
Runtime proof of the provisioning fix
The test suite cannot cover the provisioning crash.
tsconfig.jsonsetsuseDefineForClassFields: false, sotsgoand Vitest both apply legacy fieldordering and the buggy code passes them — it passed 49/49 while the Gateway was
crashing. The bug only appears under the jiti loader the Gateway uses for
plugin sources.
So this is proved separately, on the same guest, at the same head. The proof
loads the real plugin registry from the built
dist/plugins/loader.js— thesame module the Gateway uses — with
mxcenabled. The loader resolves theplugin to TypeScript source and evaluates it through jiti, then the real
MxcFsBridgeis constructed through the realcreateMxcFsBridgeusing theproduction alias map and production jiti options taken verbatim from
dist.No synthetic class, no stand-in, no hand-rolled loader.
02-provisioning-proof-PASS.mp4
The proof discriminates
A proof that only ever passes proves nothing. On the same guest, only
extensions/mxc/src/fs-bridge.tswas reverted to its pre-fix parent(
ae7d52b57aea419db2074abf8d552e1e1ee0d355) and the identical proof re-run:Character-for-character the error reported from the live Gateway. The file was
then restored to head and the guest tree verified clean.
03-provisioning-proof-PREFIX-FAIL.mp4
Please read the 49/49 as covering the workdir-validation behavior, not the
provisioning crash. The discrimination pair above is what covers the crash.
Recordings capture the runs as they execute rather than a still of an
already-finished prompt, and the guest taskbar clock in each screenshot matches
the capture timestamp in its
metadata.json, confirming live frames rather thana stale framebuffer.
Maintainer verification
Verified locally by the author on the Windows setup that originally hit the
provisioning crash.
Structured review
Both re-run against this rebased head:
gpt-5.6-sol, branch mode against the base above):TruffleHog clean, zero accepted/actionable findings,
verdict "patch is correct (0.99)".
decision=keep_open, confidence high,overall "patch is correct (0.86)", zero review findings, no merge-risk
labels, security review cleared.
An earlier ClawSweeper pass flagged the
ENOTDIRgap as an availability risk.That finding was verified against the source, fixed across all three sibling
sites, and covered by a new regression test; re-reviews since have returned no
merge-risk labels.
Known unrelated failure
src/agents/bash-tools.exec-workdir.test.tshas 3 Windows-only failures(
containerCwdslash direction). Re-confirmed after this rebase: they reproduceidentically on base
e69c3df2361with this PR's changes absent, so they arepre-existing and out of scope here.
Follow-up
The class-field ordering divergence between the repo tsconfig and the jiti
plugin loader is a latent hazard for any plugin, not just MXC — a scan found
exactly one instance, fixed here. Filed as #119014 with a proposed guard.