@miraland-labs/conduit-bridge 0.16.180 → 0.16.182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/driver.js +25 -3
- package/dist/failure-signal.js +17 -0
- package/package.json +2 -2
package/dist/driver.js
CHANGED
|
@@ -2038,7 +2038,8 @@ export function buildUntrustedCodeSpawn(input, host) {
|
|
|
2038
2038
|
...(host.toolchainRead ?? []).flatMap((path) => ["--ro-bind", path, path]),
|
|
2039
2039
|
...(rootWorkspace ? ["--bind", input.cwd, input.cwd] : []),
|
|
2040
2040
|
...(hidden ? ["--tmpfs", hidden] : []),
|
|
2041
|
-
...writable.filter((path) => !rootWorkspace || path !== input.cwd).flatMap((path) => ["--bind", path, path]),
|
|
2041
|
+
...writable.filter((path) => !rootWorkspace || path !== input.cwd).flatMap((path) => ["--bind", path, path]),
|
|
2042
|
+
...(host.ephemeral ?? []).flatMap((path) => ["--tmpfs", path]), "--chdir", input.cwd, "--clearenv",
|
|
2042
2043
|
...Object.entries(input.env).flatMap(([key, value]) => value === undefined ? [] : ["--setenv", key, value]),
|
|
2043
2044
|
"--", input.command, ...input.argv];
|
|
2044
2045
|
return { ...direct, command: host.executable ?? "/usr/bin/bwrap", argv };
|
|
@@ -2060,7 +2061,7 @@ export function buildUntrustedCodeSpawn(input, host) {
|
|
|
2060
2061
|
}
|
|
2061
2062
|
const metadata = [...ancestors].map((path) => `(literal ${JSON.stringify(path)})`).join(" ");
|
|
2062
2063
|
const profile = `(version 1) (allow default) (deny network*) (deny file-write*)
|
|
2063
|
-
(allow file-write* ${subpaths(writable)}) (allow file-write-data (literal "/dev/null"))
|
|
2064
|
+
(allow file-write* ${subpaths([...writable, ...(host.ephemeral ?? [])])}) (allow file-write-data (literal "/dev/null"))
|
|
2064
2065
|
(deny file-read* (subpath ${JSON.stringify(host.home)}) ${hidden ? `(subpath ${JSON.stringify(hidden)})` : ""})
|
|
2065
2066
|
(allow file-read* ${subpaths(readPaths)}) (allow file-read-metadata ${metadata})`;
|
|
2066
2067
|
return { ...direct, command: host.executable ?? "/usr/bin/sandbox-exec", argv: ["-p", profile, "--", input.command, ...input.argv] };
|
|
@@ -2085,6 +2086,26 @@ async function sandboxRepositoryPaths(cwd) {
|
|
|
2085
2086
|
return {};
|
|
2086
2087
|
}
|
|
2087
2088
|
}
|
|
2089
|
+
/**
|
|
2090
|
+
* A worktree resolves Node packages upward into the source repository's install, and vite, babel
|
|
2091
|
+
* and their kin write caches beside those packages (`.vite-temp`, `.cache`). The install stays
|
|
2092
|
+
* read-only; those two directories are tmpfs, so a gate can start and the next attempt never sees
|
|
2093
|
+
* what this one wrote. bwrap mounts tmpfs only on an existing directory, so they are created here.
|
|
2094
|
+
*/
|
|
2095
|
+
async function sandboxNodeScratch(cwd, sourceRepository) {
|
|
2096
|
+
if (!sourceRepository || sourceRepository === cwd)
|
|
2097
|
+
return [];
|
|
2098
|
+
const install = join(sourceRepository, "node_modules");
|
|
2099
|
+
if (!(await stat(install).then((entry) => entry.isDirectory(), () => false)))
|
|
2100
|
+
return [];
|
|
2101
|
+
const scratch = [];
|
|
2102
|
+
for (const name of [".vite-temp", ".cache"]) {
|
|
2103
|
+
const path = join(install, name);
|
|
2104
|
+
await mkdir(path, { recursive: true });
|
|
2105
|
+
scratch.push(await realpath(path));
|
|
2106
|
+
}
|
|
2107
|
+
return scratch;
|
|
2108
|
+
}
|
|
2088
2109
|
/** A delivered instrument's nested runs stay inside its already isolated scratch directory. */
|
|
2089
2110
|
export function untrustedCodeTempRoot(workspace) {
|
|
2090
2111
|
return process.env.HOME && process.env.TMPDIR === join(process.env.HOME, "tmp")
|
|
@@ -2195,8 +2216,9 @@ export async function untrustedCodeSpawn(input) {
|
|
|
2195
2216
|
// Installed toolchains are read like PATH directories; a gate never rewrites rustc for the next attempt.
|
|
2196
2217
|
if (input.env.RUSTUP_HOME && existsSync(input.env.RUSTUP_HOME))
|
|
2197
2218
|
toolchainRead.push(await realpath(input.env.RUSTUP_HOME));
|
|
2219
|
+
const repository = await sandboxRepositoryPaths(cwd);
|
|
2198
2220
|
return buildUntrustedCodeSpawn({ ...input, command, cwd, env, writable }, {
|
|
2199
|
-
...sandbox, home: await realpath(homedir()), toolchainRead, ...await
|
|
2221
|
+
...sandbox, home: await realpath(homedir()), toolchainRead, ...repository, ephemeral: await sandboxNodeScratch(cwd, repository.sourceRepository),
|
|
2200
2222
|
});
|
|
2201
2223
|
}
|
|
2202
2224
|
const sandboxExecFile = promisify(execFile);
|
package/dist/failure-signal.js
CHANGED
|
@@ -372,6 +372,20 @@ export const VERIFICATION_FAILS_ON_BASE = "verification fails on the base commit
|
|
|
372
372
|
* red commit.
|
|
373
373
|
*/
|
|
374
374
|
export const WORKSPACE_DEPENDENCIES_MISSING_PATTERN = /(?:^|\n)\s*(?:\/(?:usr\/)?bin\/)?(?:ba|z|da)?sh:\s*(?:(?:\d+:\s*)?[^:\n]{1,120}:\s*(?:command\s+)?not found|command not found:\s*[^\n]+)\s*(?=\n|$)|(?:^|\n)\s*'[^'\n]+' is not recognized as an internal or external command/im;
|
|
375
|
+
/** A write the toolchain needs that the computer refused before any test ran: the sandbox or disk, not the base commit. */
|
|
376
|
+
export const WORKSPACE_WRITE_REFUSED_PATTERN = /\b(?:EROFS|ENOSPC)\b|read-only file system|no space left on device/i;
|
|
377
|
+
/** CR17e (2026-10-22): vitest could not write its config bundle under the sandboxed install; Bridge held the owner for its own mount. */
|
|
378
|
+
export function workspaceWriteRefusedFailure(detail) {
|
|
379
|
+
return {
|
|
380
|
+
code: "workspace_write_refused",
|
|
381
|
+
class: "environment",
|
|
382
|
+
disposition: "hold",
|
|
383
|
+
responsible_party: "conduit",
|
|
384
|
+
message: "The gate could not start: this computer refused a write the project's toolchain needs.",
|
|
385
|
+
next_action: "Nothing to repair in the base commit — no test ran. Update Bridge on this computer (or free its disk), then press Try again.",
|
|
386
|
+
diagnostic_detail: detail,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
375
389
|
/** The one envelope for a gate whose tool is absent from the checkout, wherever it was noticed. */
|
|
376
390
|
export function workspaceDependenciesMissingFailure(detail) {
|
|
377
391
|
return {
|
|
@@ -602,6 +616,9 @@ export function classifyFailureSignal(signal) {
|
|
|
602
616
|
if (signal.exit_code === 127 || WORKSPACE_DEPENDENCIES_MISSING_PATTERN.test(output)) {
|
|
603
617
|
return workspaceDependenciesMissingFailure([`$ ${command}`, `exit ${signal.exit_code ?? "unknown"}`, output].filter(Boolean).join("\n"));
|
|
604
618
|
}
|
|
619
|
+
if (WORKSPACE_WRITE_REFUSED_PATTERN.test(output)) {
|
|
620
|
+
return workspaceWriteRefusedFailure([`$ ${command}`, `exit ${signal.exit_code ?? "unknown"}`, output].filter(Boolean).join("\n"));
|
|
621
|
+
}
|
|
605
622
|
return {
|
|
606
623
|
code: "verification_red_base",
|
|
607
624
|
class: "contract",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miraland-labs/conduit-bridge",
|
|
3
|
-
"version": "0.16.
|
|
4
|
-
"description": "Conduit Bridge CLI
|
|
3
|
+
"version": "0.16.182",
|
|
4
|
+
"description": "Conduit Bridge CLI — join, connect, disconnect, multi-driver lanes, and run Claude Code / Codex / Cursor / OpenCode / Pi / Kiro / Antigravity / Grok Build agents for a Conduit organization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"conduit": "dist/cli.js"
|