@miraland-labs/conduit-bridge 0.16.196 → 0.16.198

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/cli.js CHANGED
@@ -623,6 +623,14 @@ async function runner() {
623
623
  : null;
624
624
  if (rehearsalPlan)
625
625
  reportedGateRehearsals = rehearsalPlan.reports;
626
+ const rehearsalWaiting = Boolean(workspace && onlineDriverIds(config).length && rehearsalPlan?.due
627
+ && running.size === 0 && Object.keys(config.activeAttempts).length === 0 && !attemptsActiveOnComputer());
628
+ const waitingForRehearsalLock = rehearsalWaiting && gateRehearsalLockHeld();
629
+ rehearsalLockWaiting = waitingForRehearsalLock;
630
+ if (waitingForRehearsalLock && !reportedRehearsalLockWait) {
631
+ console.log(`Claim deferred for gate rehearsal in ${rehearsalPlan?.due?.workspace}: waiting for another runner's computer lock`);
632
+ }
633
+ reportedRehearsalLockWait = waitingForRehearsalLock;
626
634
  const preflight = workspace
627
635
  ? await cachedBridgePreflight({ config, workspace, managedRoot, brief: currentBrief ?? undefined, refresh, agentTimeoutMs: timeoutMs })
628
636
  : unavailableWorkspacePreflight({ config, managedRoot, agentTimeoutMs: timeoutMs });
@@ -739,6 +747,9 @@ async function runner() {
739
747
  }
740
748
  /** True while the gate rehearsal runs in the background. Waiting assignments do not interrupt it. */
741
749
  let gateRehearsalRunning = false;
750
+ let claimsPaused;
751
+ let rehearsalLockWaiting = false;
752
+ let reportedRehearsalLockWait = false;
742
753
  let gateRehearsalAbort = null;
743
754
  let gateRehearsalDone = Promise.resolve();
744
755
  /** An observation fingerprints the source checkout; a fast-forward under it reads as the observer writing. */
@@ -844,6 +855,13 @@ async function reportedRefresh(workspace, options = {}) {
844
855
  }
845
856
  return refresh;
846
857
  }
858
+ function pausedClaimsPreflight() {
859
+ const reason = gateRehearsalRunning ? "gate_rehearsal" : rehearsalLockWaiting ? "gate_rehearsal_lock" : undefined;
860
+ claimsPaused = reason
861
+ ? claimsPaused?.reason === reason ? claimsPaused : { reason, since: new Date().toISOString() }
862
+ : undefined;
863
+ return claimsPaused ? { claims_paused: claimsPaused } : {};
864
+ }
847
865
  async function heartbeat(client, config, workspacePath, brief, preflight, intentProof, bootstrapResult) {
848
866
  const online = onlineDriverIds(config);
849
867
  const status = heartbeatStatusForDrivers(online);
@@ -867,6 +885,7 @@ async function heartbeat(client, config, workspacePath, brief, preflight, intent
867
885
  ...(assignmentPollBehindServer() ? { runner_behind_server: true } : {}),
868
886
  ...(process.env.CONDUIT_RUNNER_SERVICE === "container" ? { runner_service: "container" } : {}),
869
887
  ...(workspacePath && reportedGateRehearsals.length ? { gate_rehearsals: reportedGateRehearsals } : {}),
888
+ ...pausedClaimsPreflight(),
870
889
  };
871
890
  const response = await client.request("/runner/v1/heartbeat", { method: "POST", body: JSON.stringify({
872
891
  status,
@@ -156,16 +156,20 @@ export function buildInvestigationPrompt(assignment, commit, context) {
156
156
  * verdict per criterion is the product; prose without verdicts is an unusable brief.
157
157
  */
158
158
  export function buildDeliveryVerificationPrompt(assignment, commit, context) {
159
- // The lane's shell holds only the registered commands, so it cannot run git itself. Bridge ran the
160
- // stat; the lane reads the named files at the pinned commit.
159
+ // Bridge supplies the stat; OS-sandboxed lanes can also read through their read-only shell.
160
+ const osSandbox = context.boundedBy === "os_sandbox";
161
+ const readFiles = osSandbox
162
+ ? `Read the tree with read-only shell commands such as cat, sed, ls, grep, and git show ${commit}:<path> at the pinned commit.`
163
+ : "Read the changed files that matter to each criterion at the pinned commit; you cannot run git.";
161
164
  const stat = context.diffStat?.trim() ?? "";
162
165
  const cut = stat.length > DIFF_STAT_MAX_CHARS;
163
166
  const diff = stat
164
- ? `CHANGE SUMMARY (git diff --stat ${assignment.base_commit ?? "base"}..${commit}, computed by Bridge)\n${cut ? `${stat.slice(0, DIFF_STAT_MAX_CHARS)}\n[cut at ${DIFF_STAT_MAX_CHARS} characters]` : stat}\nRead the changed files that matter to each criterion at the pinned commit; you cannot run git.`
165
- : "No change summary is available: read the files each criterion names at the pinned commit; you cannot run git.";
167
+ ? `CHANGE SUMMARY (git diff --stat ${assignment.base_commit ?? "base"}..${commit}, computed by Bridge)\n${cut ? `${stat.slice(0, DIFF_STAT_MAX_CHARS)}\n[cut at ${DIFF_STAT_MAX_CHARS} characters]` : stat}\n${readFiles}`
168
+ : osSandbox ? `No change summary is available: read the files each criterion names at the pinned commit. ${readFiles}`
169
+ : "No change summary is available: read the files each criterion names at the pinned commit; you cannot run git.";
166
170
  const commands = context.verificationCommands.length
167
- ? `REGISTERED COMMANDS (the only commands your shell accepts)\n${context.verificationCommands.map((command) => `- ${command}`).join("\n")}`
168
- : "REGISTERED COMMANDS\n- none: this repository registers no verification command, so judge from the files only";
171
+ ? `${osSandbox ? "REGISTERED COMMANDS (the only gate commands)" : "REGISTERED COMMANDS (the only commands your shell accepts)"}\n${context.verificationCommands.map((command) => `- ${command}`).join("\n")}`
172
+ : `${osSandbox ? "REGISTERED COMMANDS (the only gate commands)" : "REGISTERED COMMANDS"}\n- none: this repository registers no verification command, so judge from the files only`;
169
173
  const keys = (assignment.brief_keys ?? []).map((key) => key.trim()).filter(Boolean);
170
174
  const briefKeysBlock = keys.length ? `BRIEF KEYS\n${keys.join("\n")}` : "";
171
175
  const returns = (assignment.owner_returns ?? []).map((text) => text.trim()).filter(Boolean);
@@ -178,7 +182,9 @@ export function buildDeliveryVerificationPrompt(assignment, commit, context) {
178
182
  "You have repo_read and test_run only. Do not edit, create, delete, format, commit, branch, push, install, or change any file.",
179
183
  diff,
180
184
  formatGatesRunBlock(context.gatesRun ?? []),
181
- "Bridge already ran the gates at this commit. The GATES RUN block is the only gate fact — use those exit codes and output tails; do not choose which commands count as gates. You may still run a REGISTERED COMMAND to read more. Run nothing that is not registered. Never start a server, deploy, or call a production system.",
185
+ osSandbox
186
+ ? "Bridge already ran the gates at this commit. The GATES RUN block is the only gate fact — use those exit codes and output tails; do not choose which commands count as gates. A registered-command rerun that fails on the read-only tree is not evidence against the delivery and is not a new gate. Never start a server, deploy, or call a production system."
187
+ : "Bridge already ran the gates at this commit. The GATES RUN block is the only gate fact — use those exit codes and output tails; do not choose which commands count as gates. You may still run a REGISTERED COMMAND to read more. Run nothing that is not registered. Never start a server, deploy, or call a production system.",
182
188
  // T132: three verifications ended at the time limit with no brief. Order the work so the brief
183
189
  // exists before the budget does not.
184
190
  "Order of work: read the GATES RUN facts first, then the changed files that matter, then write the brief. You may run a registered command to read more, one at a time and never two at once (a test suite that rewrites a source file and restores it races against itself when run concurrently, and a changed tree voids your run). Your time is limited: a brief with `unclear` verdicts for what you did not reach is the required outcome; a run that ends without a brief settles nothing.",
@@ -868,6 +874,7 @@ export async function executeNextInvestigation(client, config, workspace, brief,
868
874
  })
869
875
  : [];
870
876
  const context = {
877
+ boundedBy: boundedByForDriver(driverId),
871
878
  verificationCommands,
872
879
  diffStat: assignment.base_commit ? await diffStatSince(attemptWorkspace, assignment.base_commit) : null,
873
880
  gatesRun,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miraland-labs/conduit-bridge",
3
- "version": "0.16.196",
3
+ "version": "0.16.198",
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": {