@miraland-labs/conduit-bridge 0.16.172 → 0.16.174

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.
@@ -12,6 +12,20 @@ const execFileAsync = promisify(execFile);
12
12
  export function attemptWorktreePath(sourceWorkspace, attemptId) {
13
13
  return join(sourceWorkspace, ".conduit", "attempts", attemptId);
14
14
  }
15
+ export function rehearsalWorktreePath(sourceWorkspace) {
16
+ return join(sourceWorkspace, ".conduit", "rehearsal");
17
+ }
18
+ export async function createRehearsalWorktree(sourceWorkspace, commit) {
19
+ await ensureConduitExclude(sourceWorkspace);
20
+ const path = rehearsalWorktreePath(sourceWorkspace);
21
+ await removeAttemptWorktree(sourceWorkspace, path);
22
+ await mkdir(join(sourceWorkspace, ".conduit"), { recursive: true });
23
+ await execFileAsync("git", ["-C", sourceWorkspace, "worktree", "add", "--detach", path, commit], {
24
+ timeout: 60_000,
25
+ maxBuffer: 2_000_000,
26
+ });
27
+ return path;
28
+ }
15
29
  /**
16
30
  * The branch each attempt works on. Named by attempt id, which is globally unique, so concurrent slots
17
31
  * (F-07 multi-slot) never collide in the shared ref namespace and a retry never clashes with a prior
package/dist/cli.js CHANGED
@@ -20,7 +20,8 @@ import { BOOTSTRAP_RESULTS, buildSovereignExecutionFacts, workspaceIsClean } fro
20
20
  import { ensureCheckout } from "./checkout.js";
21
21
  import { buildOnShiftIntentProof, managedWorkspacePath, maybeApplyOnShiftIntent } from "./on-shift-apply.js";
22
22
  import { expandOpsValue, loadOpsEnv, OPS_VERBS, runOps } from "./ops.js";
23
- import { discardWorktreeWrites, pumpExecutionSlots, renewLeases } from "./execution.js";
23
+ import { pumpExecutionSlots, renewLeases } from "./execution.js";
24
+ import { createRehearsalWorktree, rehearsalWorktreePath, removeAttemptWorktree } from "./attempt-worktree.js";
24
25
  import { applyRunnerToolPath, installRunnerService, uninstallRunnerService } from "./service.js";
25
26
  import { BRIDGE_PROTOCOL_VERSION, cachedBridgePreflight, gateRehearsalLockHeld, planGateRehearsals, PREFLIGHT_CACHE_TTL_MS, runGateRehearsal, unavailableWorkspacePreflight } from "./preflight.js";
26
27
  import { refreshSourceWorkspace } from "./workspace-refresh.js";
@@ -760,20 +761,21 @@ async function rehearsalCheckouts(workspace, brief, refresh) {
760
761
  return checkouts;
761
762
  }
762
763
  /**
763
- * Run one on-shift repository's gate once in its checkout, off the loop: a ten-minute gate
764
- * must not stop the heartbeat, or the computer reads offline while it measures. The workspace was
765
- * clean when it started, so whatever is written there afterwards is the gate's and is discarded.
764
+ * Run one on-shift repository's gate in a detached worktree at its HEAD, nested under .conduit/ as
765
+ * an attempt's is, and remove only that worktree afterwards. Run off the loop: a ten-minute gate
766
+ * must not stop the heartbeat, or the computer reads offline while it measures.
766
767
  */
767
768
  function startGateRehearsal(workspace, plan) {
768
769
  gateRehearsalRunning = true;
770
+ const rehearsalPath = rehearsalWorktreePath(workspace);
769
771
  console.log(`Rehearsing the gate in ${workspace}: ${plan.commands.join(", ")}`);
770
- void runGateRehearsal(workspace, plan)
772
+ void createRehearsalWorktree(workspace, plan.commit)
773
+ .then((path) => runGateRehearsal(path, plan))
771
774
  .then((rehearsal) => { if (rehearsal === "busy")
772
775
  console.log("Gate rehearsal deferred: another runner on this computer is rehearsing"); })
773
776
  .catch((error) => console.error(`Gate rehearsal failed: ${redactSecrets(error instanceof Error ? error.message : "unknown error")}`))
774
777
  .finally(async () => {
775
- if (!await workspaceIsClean(workspace))
776
- await discardWorktreeWrites(workspace);
778
+ await removeAttemptWorktree(workspace, rehearsalPath);
777
779
  gateRehearsalRunning = false;
778
780
  });
779
781
  }
@@ -744,6 +744,8 @@ export async function ensureTestEvidence(input) {
744
744
  witnessed.push({
745
745
  kind: "test",
746
746
  name: command,
747
+ command,
748
+ exit_code: result.code,
747
749
  details,
748
750
  acceptance_criteria: criteriaForTestEvidence(input.report, command, acceptance),
749
751
  witness: "bridge",
package/dist/execution.js CHANGED
@@ -2823,6 +2823,8 @@ async function prepareDelivery(client, attemptId, taskId, report) {
2823
2823
  details: item.details,
2824
2824
  acceptance_criteria: item.acceptance_criteria,
2825
2825
  ...(item.witness ? { witness: item.witness } : {}),
2826
+ ...(item.command !== undefined ? { command: item.command } : {}),
2827
+ ...(item.exit_code !== undefined ? { exit_code: item.exit_code } : {}),
2826
2828
  },
2827
2829
  idempotency_key: `bridge:artifact:${attemptId}:${index + 1}`,
2828
2830
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miraland-labs/conduit-bridge",
3
- "version": "0.16.172",
3
+ "version": "0.16.174",
4
4
  "description": "Conduit Bridge CLI \u2014 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": {