@miraland-labs/conduit-bridge 0.16.19 → 0.16.21
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/README.md +1 -1
- package/dist/cli.js +1 -1
- package/dist/driver.js +1 -1
- package/dist/ensure-pull-request.js +4 -2
- package/dist/execution.js +1 -1
- package/dist/ops.js +30 -2
- package/ops/conduit-ops.cmd +1 -1
- package/ops/connect.cmd +1 -1
- package/ops/disconnect.cmd +1 -1
- package/ops/doctor.cmd +1 -1
- package/ops/install.cmd +1 -1
- package/ops/offline.cmd +1 -1
- package/ops/online.cmd +1 -1
- package/ops/status.cmd +1 -1
- package/ops/uninstall.cmd +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Local Bridge CLI for [Conduit](https://github.com/miralandlabs/conduit). Connects a computer to one organization, claims work, and drives a local agent.
|
|
4
4
|
|
|
5
|
-
**Package version:** `0.16.
|
|
5
|
+
**Package version:** `0.16.21` — mutate_repo with `pr_create` opens a pull request even when `change_scope` is empty. `ops disconnect` now asks before it removes the runner service and clears credentials; pass `--yes` to skip the question. `ops.env` is enrollment/bootstrap defaults only: an explicit workspace does not inherit an old repository, and project switches do not rewrite global project state. `ops enroll` exchanges a single-use token, registers the machine, binds project affinity, provisions fuel keys, brings detected drivers online, and starts the runner in one command. On Linux, `ops install` refuses any effective systemd drop-in. A switch intent remains queued until the target runner heartbeat proves Bound. After every Bridge publish, operators must re-run `ops install` (LaunchAgent pins an absolute `cli.js`).
|
|
6
6
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
package/dist/cli.js
CHANGED
|
@@ -371,7 +371,7 @@ async function initOps() {
|
|
|
371
371
|
console.log(`Config file (separate): ${envPath}`);
|
|
372
372
|
console.log("");
|
|
373
373
|
console.log("Works the same on macOS, Linux, and Windows via:");
|
|
374
|
-
console.log(` ${bridgeUsage("ops", "<connect|install|switch|online|offline|status|disconnect|uninstall>")}`);
|
|
374
|
+
console.log(` ${bridgeUsage("ops", "<connect|install|switch|online|offline|status|doctor|disconnect|uninstall>")}`);
|
|
375
375
|
console.log("");
|
|
376
376
|
console.log("1. Set enrollment/bootstrap defaults once:");
|
|
377
377
|
console.log(` Create folder: ${configDir}`);
|
package/dist/driver.js
CHANGED
|
@@ -131,7 +131,7 @@ export function buildAssignmentPrompt(context) {
|
|
|
131
131
|
if (rework)
|
|
132
132
|
lines.push("", `REWORK FEEDBACK — an independent review returned this delivery; address every point\n${rework}`);
|
|
133
133
|
const mustCommit = context.grants.includes("repo_write") && context.grants.includes("branch_create");
|
|
134
|
-
const mustOpenPr = mustCommit && context.grants.includes("pr_create")
|
|
134
|
+
const mustOpenPr = mustCommit && context.grants.includes("pr_create");
|
|
135
135
|
const executionClass = context.executionClass
|
|
136
136
|
?? requireStampedExecutionClass(spec.execution_class);
|
|
137
137
|
// Phase B: control-plane instruction is additive evidence/class prose.
|
|
@@ -29,8 +29,10 @@ export async function commitsAheadOfBase(workspace, base) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
export function needsPullRequest(report, spec, grants) {
|
|
32
|
+
void spec;
|
|
33
|
+
// Empty change_scope is "whole repo", not "no land". Run 7 committed CANARY.md with pr_create
|
|
34
|
+
// granted and never opened a PR because this used to require a non-empty scope.
|
|
32
35
|
return Boolean(grants.includes("pr_create")
|
|
33
|
-
&& (spec.change_scope?.length ?? 0) > 0
|
|
34
36
|
&& report.head_commit
|
|
35
37
|
&& !report.pull_request_url);
|
|
36
38
|
}
|
|
@@ -181,7 +183,7 @@ export async function ensureDeliveryPullRequest(input) {
|
|
|
181
183
|
const push = input.pushOriginHead ?? pushOriginHead;
|
|
182
184
|
const countAhead = input.countCommitsAhead ?? commitsAheadOfBase;
|
|
183
185
|
let report = adoptPullRequestUrlFromEvidence(input.report, input.repositoryFingerprint);
|
|
184
|
-
if ((input.spec.change_scope?.length ?? 0) > 0) {
|
|
186
|
+
if (input.grants.includes("pr_create") || (input.spec.change_scope?.length ?? 0) > 0) {
|
|
185
187
|
const head = await readHead(input.workspace);
|
|
186
188
|
if (report.head_commit && !commitsMatch(report.head_commit, head)) {
|
|
187
189
|
console.error(`Agent head_commit ${report.head_commit} does not match workspace HEAD ${head}; using workspace HEAD`);
|
package/dist/execution.js
CHANGED
|
@@ -1764,8 +1764,8 @@ export function validateDeliveryReport(report, spec, grants = [], actualPaths) {
|
|
|
1764
1764
|
throw new Error("Agent reported repository changes without the repo_write grant");
|
|
1765
1765
|
}
|
|
1766
1766
|
// Merge-on-accept lands GitHub PRs. Local attempt commits without a PR never reach main.
|
|
1767
|
+
// Empty change_scope means whole-repo, not "skip the PR" (Run 7).
|
|
1767
1768
|
if (grants.includes("pr_create")
|
|
1768
|
-
&& (spec.change_scope?.length ?? 0) > 0
|
|
1769
1769
|
&& report.head_commit
|
|
1770
1770
|
&& !report.pull_request_url) {
|
|
1771
1771
|
throw new Error("Repository changes require a pull_request_url when pr_create is granted");
|
package/dist/ops.js
CHANGED
|
@@ -6,6 +6,8 @@ import { spawnSync } from "node:child_process";
|
|
|
6
6
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
9
|
+
import { stdin as input, stdout as output } from "node:process";
|
|
10
|
+
import { createInterface } from "node:readline/promises";
|
|
9
11
|
import { parseArgs } from "node:util";
|
|
10
12
|
import { ConduitClient } from "./client.js";
|
|
11
13
|
import { loadConfig } from "./config.js";
|
|
@@ -51,7 +53,7 @@ export function expandOpsValue(value, home = homedir()) {
|
|
|
51
53
|
}
|
|
52
54
|
next = next.replace(/%USERPROFILE%/gi, home).replace(/%HOME%/gi, home);
|
|
53
55
|
next = next.replace(/\$HOME\b/g, home).replace(/\$\{HOME\}/g, home);
|
|
54
|
-
if (next.startsWith("~/") || next === "~")
|
|
56
|
+
if (next.startsWith("~/") || next.startsWith("~\\") || next === "~")
|
|
55
57
|
next = join(home, next.slice(2));
|
|
56
58
|
return next;
|
|
57
59
|
}
|
|
@@ -67,7 +69,12 @@ export function parseOpsEnvFile(text, home = homedir()) {
|
|
|
67
69
|
const key = line.slice(0, eq).trim();
|
|
68
70
|
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
69
71
|
continue;
|
|
70
|
-
|
|
72
|
+
// Drop a trailing annotation such as `CONDUIT_WORKSPACE=$HOME/repo # laptop`, so it does not
|
|
73
|
+
// become part of the path. A quoted value keeps everything inside its quotes, and a `#` with no
|
|
74
|
+
// space before it stays in the value.
|
|
75
|
+
const rawValue = line.slice(eq + 1).trim();
|
|
76
|
+
const quoted = rawValue.startsWith('"') || rawValue.startsWith("'");
|
|
77
|
+
out[key] = expandOpsValue(quoted ? rawValue : rawValue.replace(/\s+#.*$/, ""), home);
|
|
71
78
|
}
|
|
72
79
|
return out;
|
|
73
80
|
}
|
|
@@ -185,6 +192,20 @@ export function shellQuoteArgs(args) {
|
|
|
185
192
|
return `"${arg.replaceAll('"', '\\"')}"`;
|
|
186
193
|
}).join(" ");
|
|
187
194
|
}
|
|
195
|
+
/** Ask the operator to approve a step that cannot be undone. Non-interactive shells must pass --yes. */
|
|
196
|
+
async function confirmOps(question) {
|
|
197
|
+
if (!input.isTTY || !output.isTTY) {
|
|
198
|
+
throw new Error("This step needs confirmation. Re-run with --yes to approve it without a prompt.");
|
|
199
|
+
}
|
|
200
|
+
const rl = createInterface({ input, output });
|
|
201
|
+
try {
|
|
202
|
+
const answer = (await rl.question(question)).trim().toLowerCase();
|
|
203
|
+
return answer === "y" || answer === "yes";
|
|
204
|
+
}
|
|
205
|
+
finally {
|
|
206
|
+
rl.close();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
188
209
|
function defaultRunBridge(args, options = {}) {
|
|
189
210
|
// Re-enter this package's CLI in a child so ops stays a thin orchestrator.
|
|
190
211
|
const cli = process.argv[1];
|
|
@@ -205,6 +226,13 @@ export async function runOps(verb, argv = [], deps = {}) {
|
|
|
205
226
|
const runBridge = deps.runBridge ?? defaultRunBridge;
|
|
206
227
|
const env = deps.env ?? loadOpsEnv();
|
|
207
228
|
if (verb === "disconnect") {
|
|
229
|
+
// Ask here, not in the child command: this verb also removes the runner service, and the
|
|
230
|
+
// child's own prompt would come too late to stop that.
|
|
231
|
+
const approved = argv.includes("--yes") || argv.includes("-y") || await (deps.confirm ?? confirmOps)("Disengage this computer from the organization, remove the runner service, and clear local credentials? [y/N] ");
|
|
232
|
+
if (!approved) {
|
|
233
|
+
console.log("Cancelled.");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
208
236
|
runBridge(["uninstall-service"], { allowFail: true });
|
|
209
237
|
runBridge(["disconnect", "--yes"]);
|
|
210
238
|
console.log("Disconnected. Run: npx @miraland-labs/conduit-bridge@latest ops connect");
|
package/ops/conduit-ops.cmd
CHANGED
|
@@ -4,5 +4,5 @@ if "%~1"=="" (
|
|
|
4
4
|
echo Usage: %~nx0 ^<connect^|install^|online^|offline^|status^|doctor^|disconnect^|uninstall^> [args…]
|
|
5
5
|
exit /b 1
|
|
6
6
|
)
|
|
7
|
-
npx --yes @miraland-labs/conduit-bridge@latest ops %*
|
|
7
|
+
call npx --yes @miraland-labs/conduit-bridge@latest ops %*
|
|
8
8
|
if errorlevel 1 exit /b %errorlevel%
|
package/ops/connect.cmd
CHANGED
package/ops/disconnect.cmd
CHANGED
package/ops/doctor.cmd
CHANGED
package/ops/install.cmd
CHANGED
package/ops/offline.cmd
CHANGED
package/ops/online.cmd
CHANGED
package/ops/status.cmd
CHANGED
package/ops/uninstall.cmd
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miraland-labs/conduit-bridge",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.21",
|
|
4
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": {
|