@miraland-labs/conduit-bridge 0.16.189 → 0.16.190

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/execution.js CHANGED
@@ -35,7 +35,7 @@ import { boundedTail, captureVerificationFailure, DeliveryReportDefectError, det
35
35
  import { ensureChangeEvidence } from "./ensure-change-evidence.js";
36
36
  import { ensureDemonstrationEvidence } from "./ensure-demonstration-evidence.js";
37
37
  import { ensureNormativeEvidence } from "./ensure-normative-evidence.js";
38
- import { changedPathsSince, compareWorktreeState, diffStatSince, worktreeStateFingerprint, worktreeWrittenPaths } from "./git-witness.js";
38
+ import { changedPathsSince, compareWorktreeState, diffStatSince, mergeBaseWithDefaultBranch, trackedDefaultBranchRef, worktreeStateFingerprint, worktreeWrittenPaths } from "./git-witness.js";
39
39
  import { assertNormativeRefsMaterialized, checkNormativeMarkers, materializeNormativeRefs, NORMATIVE_MARKER_PREFIX, NORMATIVE_REF_PREFIX, parseNormativeRefs, } from "./normative-refs.js";
40
40
  import { checkIntegrationObligations, INTEGRATION_OBLIGATION_PREFIX, parseIntegrationObligations, } from "./integration-obligations.js";
41
41
  /** Keep a Mac awake only while an assignment is active; display sleep remains allowed. */
@@ -431,8 +431,9 @@ const executionContractSchema = z.object({
431
431
  repository_fingerprint: z.string().nullable().optional().default(null),
432
432
  requested_base_commit: z.string().nullable().optional().default(null),
433
433
  claimed_head: z.string().nullable().optional().default(null),
434
- // For a rework, the control plane carries the first revision's resolved attempt start. Older
435
- // contracts omit it and use the T136 worktree-start fallback below.
434
+ // The control plane may carry the first revision's resolved attempt start. Rework and resume
435
+ // measure from the default-branch fork point; this field is the fallback when that fork
436
+ // point cannot be computed.
436
437
  delivery_base_commit: z.string().nullable().optional().default(null),
437
438
  source_attempt_id: z.string().uuid().nullable().optional().default(null),
438
439
  // The change request and head commit the returned delivery left behind. A rework that keeps the
@@ -1231,21 +1232,30 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
1231
1232
  await removeAttemptWorktree(workspace, attemptWorkspace).catch(() => undefined);
1232
1233
  }
1233
1234
  };
1234
- // T136: a first revision's witness starts at the commit the attempt worktree actually checked
1235
- // out. When main has moved past the requested base, that resolved start is the claimed head;
1236
- // diffing from the requested base would report commits that predate the agent as its work.
1237
- // T138: a rework carries the first revision's resolved start, because its worktree starts at the
1238
- // previous delivery's head. That lets a prose-only rework witness the original pack while still
1239
- // including any new rework changes. A conflict rework is different: it is pinned to the live base
1240
- // tip and starts fresh there, so the control plane sends no carried base and the requested base --
1241
- // the pinned tip -- is the delivery base. Diffing from the first revision's start would report
1242
- // every commit the base gained in between as the agent's own work. Older contracts fall back to
1243
- // the T136 rule.
1244
- const rework = task.delivery_state === "changes_requested" || Boolean(executionContract.prior_head_commit);
1245
- const deliveryBaseCommit = executionContract.delivery_base_commit
1246
- ?? (rework
1247
- ? (executionContract.requested_base_commit ?? spec.repository?.base_commit ?? worktreeStart)
1248
- : worktreeStart);
1235
+ // T136: a fresh attempt witnesses from the commit the worktree checked out. When main has
1236
+ // moved past the requested base, that resolved start is the claimed head; diffing from the
1237
+ // requested base would report commits that predate the agent as its work.
1238
+ // A rework or a resumed delivery measures from the merge-base of HEAD with origin/<branch>,
1239
+ // where <branch> is the branch the source checkout has checked out — the branch ensureCheckout
1240
+ // tracks. fetch updates that ref. fetch does not update origin/HEAD. Contract
1241
+ // delivery_base_commit and requested_base_commit apply only when that merge-base cannot be
1242
+ // computed. A contract base from the first attempt's start counts later default-branch commits
1243
+ // as the agent's writes (2026-10-23, task eff1253c). Diagnosis uses the same rule.
1244
+ const reworkOrResume = isReworkOrResumeDelivery({
1245
+ deliveryState: task.delivery_state,
1246
+ priorHeadCommit: executionContract.prior_head_commit,
1247
+ resumeFromAttemptId: executionContract.resume_from_attempt_id,
1248
+ });
1249
+ const deliveryBaseCommit = await resolveDeliveryBaseCommit({
1250
+ worktree: attemptWorkspace,
1251
+ sourceWorkspace: workspace,
1252
+ reworkOrResume,
1253
+ worktreeStart,
1254
+ taskId,
1255
+ deliveryBaseCommit: executionContract.delivery_base_commit,
1256
+ requestedBaseCommit: executionContract.requested_base_commit,
1257
+ repositoryBaseCommit: spec.repository?.base_commit,
1258
+ });
1249
1259
  // Only when the worktree really stands at the timed-out run's head: a computer that cannot reach
1250
1260
  // that commit starts at the base (resolveAttemptStartCommit), and the agent must not be told the
1251
1261
  // work is there.
@@ -3008,6 +3018,37 @@ function referenceKind(kind) {
3008
3018
  * Implemented in git-witness.ts; re-exported for control-plane test pins and investigation.
3009
3019
  */
3010
3020
  export { changedPathsSince } from "./git-witness.js";
3021
+ /**
3022
+ * A rework or a resumed delivery, from the signals the attempt contract carries.
3023
+ *
3024
+ * Diagnosis is not a separate case: the same three signals select the base.
3025
+ */
3026
+ export function isReworkOrResumeDelivery(input) {
3027
+ return input.deliveryState === "changes_requested"
3028
+ || Boolean(input.priorHeadCommit)
3029
+ || Boolean(input.resumeFromAttemptId);
3030
+ }
3031
+ /**
3032
+ * Commit that changedPathsSince, diffStatSince, and the land checks measure from.
3033
+ *
3034
+ * A fresh attempt keeps the worktree start. A rework or a resumed delivery uses the merge-base
3035
+ * of HEAD with `origin/<branch>` on the source checkout. Contract bases apply only when that
3036
+ * merge-base cannot be computed. One log line names the base this attempt used.
3037
+ */
3038
+ export async function resolveDeliveryBaseCommit(input) {
3039
+ const ref = input.reworkOrResume ? await trackedDefaultBranchRef(input.sourceWorkspace) : null;
3040
+ const fork = ref ? await mergeBaseWithDefaultBranch(input.worktree, ref) : null;
3041
+ const base = !input.reworkOrResume
3042
+ ? input.worktreeStart
3043
+ : fork
3044
+ ?? input.deliveryBaseCommit
3045
+ ?? input.requestedBaseCommit
3046
+ ?? input.repositoryBaseCommit
3047
+ ?? input.worktreeStart;
3048
+ const via = fork && ref ? ` (merge-base with ${ref})` : "";
3049
+ console.log(`Assignment ${input.taskId} delivery base ${base}${via}`);
3050
+ return base;
3051
+ }
3011
3052
  /**
3012
3053
  * Does this attempt earn a verification dry run?
3013
3054
  *
@@ -21,6 +21,44 @@ async function gitFields(worktree, args) {
21
21
  return null;
22
22
  }
23
23
  }
24
+ /**
25
+ * Fork point of HEAD with the fetched default-branch ref.
26
+ *
27
+ * Null when the ref is missing or the two histories do not meet. Callers then use the
28
+ * contract base. A merge of that ref into the attempt branch moves this commit forward,
29
+ * so the diff still names only the branch's own files.
30
+ */
31
+ export async function mergeBaseWithDefaultBranch(worktree, defaultBranchRef) {
32
+ try {
33
+ const { stdout } = await execFileAsync("git", ["-C", worktree, "merge-base", "HEAD", defaultBranchRef], { timeout: 30_000, maxBuffer: 1_000_000 });
34
+ const sha = stdout.trim().toLowerCase();
35
+ return /^[0-9a-f]{7,64}$/.test(sha) ? sha : null;
36
+ }
37
+ catch {
38
+ return null;
39
+ }
40
+ }
41
+ /**
42
+ * `origin/<branch>` for the branch this checkout has checked out.
43
+ *
44
+ * `ensureCheckout` leaves that branch checked out. `fetchOrigin` and `refreshSourceWorkspace`
45
+ * update `origin/<branch>`. They do not update `origin/HEAD`, so this function never reads it.
46
+ * Null when HEAD is detached or `origin/<branch>` is absent; callers then use the contract base.
47
+ */
48
+ export async function trackedDefaultBranchRef(workspace) {
49
+ try {
50
+ const { stdout } = await execFileAsync("git", ["-C", workspace, "rev-parse", "--abbrev-ref", "HEAD"], { timeout: 30_000, maxBuffer: 1_000_000 });
51
+ const branch = stdout.trim();
52
+ if (!branch || branch === "HEAD")
53
+ return null;
54
+ const ref = `origin/${branch}`;
55
+ await execFileAsync("git", ["-C", workspace, "rev-parse", "--verify", "--quiet", `${ref}^{commit}`], { timeout: 30_000, maxBuffer: 1_000_000 });
56
+ return ref;
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ }
24
62
  /**
25
63
  * Paths changed on the attempt branch since `startCommit`, including uncommitted work.
26
64
  * Null when git cannot answer — callers must not treat null as failure.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miraland-labs/conduit-bridge",
3
- "version": "0.16.189",
3
+ "version": "0.16.190",
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": {