@shipers-dev/multi 0.41.0 → 0.43.0

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/index.js CHANGED
@@ -17109,7 +17109,7 @@ function setWorktreeIndexEntry(workingDir, key, issueId) {
17109
17109
  idx[key] = issueId;
17110
17110
  writeIndex(workingDir, idx);
17111
17111
  }
17112
- async function ensureWorktree(workingDir, issueKey, issueId) {
17112
+ async function ensureWorktree(workingDir, issueKey, issueId, opts) {
17113
17113
  if (!await isGitRepo(workingDir)) {
17114
17114
  return { path: workingDir, branch: "", created: false };
17115
17115
  }
@@ -17126,8 +17126,19 @@ async function ensureWorktree(workingDir, issueKey, issueId) {
17126
17126
  try {
17127
17127
  mkdirSync3(wtDir, { recursive: true });
17128
17128
  } catch {}
17129
+ let baseRef = "HEAD";
17130
+ if (opts?.parentBranch) {
17131
+ const localOk = await branchExists(workingDir, opts.parentBranch);
17132
+ if (localOk) {
17133
+ baseRef = opts.parentBranch;
17134
+ } else {
17135
+ const fetched = await run3(workingDir, "git", ["fetch", "origin", `${opts.parentBranch}:${opts.parentBranch}`]);
17136
+ if (fetched.code === 0)
17137
+ baseRef = opts.parentBranch;
17138
+ }
17139
+ }
17129
17140
  const exists4 = await branchExists(workingDir, branch);
17130
- const args2 = exists4 ? ["worktree", "add", wtPath, branch] : ["worktree", "add", "-b", branch, wtPath, "HEAD"];
17141
+ const args2 = exists4 ? ["worktree", "add", wtPath, branch] : ["worktree", "add", "-b", branch, wtPath, baseRef];
17131
17142
  const r = await run3(workingDir, "git", args2);
17132
17143
  if (r.code !== 0) {
17133
17144
  throw new Error(`git worktree add failed: ${r.stderr || r.stdout}`);
@@ -17219,6 +17230,48 @@ async function removeWorktree(workingDir, issueKey, opts = {}) {
17219
17230
  removeWorktreeIndexEntry(workingDir, key);
17220
17231
  return result;
17221
17232
  }
17233
+ async function squashMergeChild(wtPath, childBranch, childKey) {
17234
+ const result = { childKey, branch: childBranch, ok: false, empty: false, conflicts: [], message: "" };
17235
+ await run3(wtPath, "git", ["fetch", "origin", `${childBranch}:${childBranch}`]).catch(() => null);
17236
+ const haveLocal = await branchExists(wtPath, childBranch);
17237
+ if (!haveLocal) {
17238
+ result.message = `branch ${childBranch} not resolvable locally or via origin`;
17239
+ return result;
17240
+ }
17241
+ const ahead = await run3(wtPath, "git", ["rev-list", "--count", `HEAD..${childBranch}`]);
17242
+ if (ahead.code === 0 && Number((ahead.stdout || "0").trim()) === 0) {
17243
+ result.ok = true;
17244
+ result.empty = true;
17245
+ result.message = `${childKey} had no commits ahead of parent — nothing to merge`;
17246
+ return result;
17247
+ }
17248
+ const merge9 = await run3(wtPath, "git", ["merge", "--squash", "--no-commit", childBranch]);
17249
+ const conflicted = await run3(wtPath, "git", ["diff", "--name-only", "--diff-filter=U"]);
17250
+ const conflictPaths = (conflicted.stdout || "").split(`
17251
+ `).map((l) => l.trim()).filter(Boolean);
17252
+ if (merge9.code !== 0 || conflictPaths.length > 0) {
17253
+ result.conflicts = conflictPaths;
17254
+ result.message = `${childKey} had ${conflictPaths.length} conflicting path(s); worktree left dirty for parent to resolve`;
17255
+ return result;
17256
+ }
17257
+ const staged = await run3(wtPath, "git", ["diff", "--cached", "--name-only"]);
17258
+ const stagedFiles = (staged.stdout || "").split(`
17259
+ `).map((l) => l.trim()).filter(Boolean);
17260
+ if (stagedFiles.length === 0) {
17261
+ result.ok = true;
17262
+ result.empty = true;
17263
+ result.message = `${childKey} produced no staged changes — nothing to commit`;
17264
+ return result;
17265
+ }
17266
+ const commit = await run3(wtPath, "git", ["commit", "-m", `squash: ${childKey} (${childBranch})`]);
17267
+ if (commit.code !== 0) {
17268
+ result.message = `${childKey} commit failed: ${commit.stderr || commit.stdout}`;
17269
+ return result;
17270
+ }
17271
+ result.ok = true;
17272
+ result.message = `${childKey} squash-merged (${stagedFiles.length} file${stagedFiles.length === 1 ? "" : "s"})`;
17273
+ return result;
17274
+ }
17222
17275
  var init_worktree = () => {};
17223
17276
 
17224
17277
  // ../../node_modules/zod/v4/core/core.js
@@ -34357,7 +34410,7 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
34357
34410
  let worktreeBranch = "";
34358
34411
  if (baseWorkingDir) {
34359
34412
  try {
34360
- const wt = await ensureWorktree(baseWorkingDir, task.key || issueId, issueId);
34413
+ const wt = await ensureWorktree(baseWorkingDir, task.key || issueId, issueId, { parentBranch: task.parent_branch ?? undefined });
34361
34414
  workingDir = wt.path;
34362
34415
  worktreeBranch = wt.branch;
34363
34416
  await postStream(apiUrl, issueId, "worktree_created", { path: wt.path, branch: wt.branch, reused: !wt.created });
@@ -34372,6 +34425,44 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
34372
34425
  await postStream(apiUrl, issueId, "worktree_error", { message: fmtError(e) });
34373
34426
  }
34374
34427
  }
34428
+ let mergeReportLines = [];
34429
+ let mergeHadConflicts = false;
34430
+ const mergeTargets = Array.isArray(task.merge_targets) ? task.merge_targets : [];
34431
+ if (workingDir && mergeTargets.length) {
34432
+ for (const t of mergeTargets) {
34433
+ if (!t?.branch || !t?.child_key)
34434
+ continue;
34435
+ try {
34436
+ const r = await squashMergeChild(workingDir, String(t.branch), String(t.child_key));
34437
+ if (r.ok && r.empty) {
34438
+ mergeReportLines.push(`- _empty_ ${t.child_key} → no changes`);
34439
+ } else if (r.ok) {
34440
+ mergeReportLines.push(`- ✅ ${t.child_key} squashed into ${worktreeBranch || "(parent)"}`);
34441
+ } else if (r.conflicts.length) {
34442
+ mergeHadConflicts = true;
34443
+ mergeReportLines.push(`- ⚠ ${t.child_key} CONFLICT in: ${r.conflicts.join(", ")}`);
34444
+ } else {
34445
+ mergeReportLines.push(`- ✗ ${t.child_key} ${r.message}`);
34446
+ }
34447
+ await postStream(apiUrl, issueId, "child_merge", {
34448
+ child_key: t.child_key,
34449
+ branch: t.branch,
34450
+ ok: r.ok,
34451
+ empty: r.empty,
34452
+ conflicts: r.conflicts,
34453
+ message: r.message
34454
+ });
34455
+ } catch (e) {
34456
+ mergeReportLines.push(`- ✗ ${t.child_key} merge threw: ${fmtError(e)}`);
34457
+ }
34458
+ }
34459
+ if (mergeReportLines.length) {
34460
+ const header = mergeHadConflicts ? "## ⚠ Squash-merge results — conflicts to resolve in your worktree" : "## Squash-merge results";
34461
+ const block = [header, ...mergeReportLines, "", "---", ""].join(`
34462
+ `);
34463
+ task.followup = block + (task.followup || "");
34464
+ }
34465
+ }
34375
34466
  log3(`▶ run_task ${task.key}: ${isFollowup ? "(follow-up) " : ""}${task.title}${workingDir ? ` [cwd: ${workingDir}${worktreeBranch ? ` @${worktreeBranch}` : ""}]` : ""}`);
34376
34467
  if (tenantWsId)
34377
34468
  await patchIssueStatus(apiUrl, tenantWsId, issueId, "in_progress");
@@ -35030,7 +35121,8 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
35030
35121
  priority: a.priority,
35031
35122
  assignee_type: a.assignee_type,
35032
35123
  assignee_id: a.assignee_id,
35033
- parent_id: a.parent_id || parentId
35124
+ parent_id: a.parent_id || parentId,
35125
+ await_children: a.await_children
35034
35126
  };
35035
35127
  const res = await apiClient.post(mutateUrl, body, { headers });
35036
35128
  if (!res.success) {
@@ -36197,7 +36289,8 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
36197
36289
  priority: a.priority,
36198
36290
  assignee_type: a.assignee_type,
36199
36291
  assignee_id: a.assignee_id,
36200
- parent_id: a.parent_id
36292
+ parent_id: a.parent_id,
36293
+ await_children: a.await_children
36201
36294
  };
36202
36295
  const res = await apiClient.post(mutateUrl, body, { headers });
36203
36296
  if (!res.success) {
@@ -37403,7 +37496,7 @@ import { parseArgs } from "util";
37403
37496
  // package.json
37404
37497
  var package_default = {
37405
37498
  name: "@shipers-dev/multi",
37406
- version: "0.41.0",
37499
+ version: "0.43.0",
37407
37500
  type: "module",
37408
37501
  bin: {
37409
37502
  "multi-agent": "./dist/index.js"
@@ -37688,8 +37781,8 @@ init_errors();
37688
37781
 
37689
37782
  class Worktree extends exports_Effect.Service()("cli/Worktree", {
37690
37783
  succeed: {
37691
- ensure: (workingDir, issueKey, issueId) => exports_Effect.tryPromise({
37692
- try: () => ensureWorktree(workingDir, issueKey, issueId),
37784
+ ensure: (workingDir, issueKey, issueId, opts) => exports_Effect.tryPromise({
37785
+ try: () => ensureWorktree(workingDir, issueKey, issueId, opts),
37693
37786
  catch: (cause3) => new WorktreeError({ message: `ensureWorktree failed`, cause: cause3 })
37694
37787
  }),
37695
37788
  isGitRepo: (dir) => exports_Effect.tryPromise({
@@ -38415,8 +38508,8 @@ init_errors();
38415
38508
 
38416
38509
  class Worktree2 extends exports_Effect.Service()("cli/Worktree", {
38417
38510
  succeed: {
38418
- ensure: (workingDir, issueKey, issueId) => exports_Effect.tryPromise({
38419
- try: () => ensureWorktree(workingDir, issueKey, issueId),
38511
+ ensure: (workingDir, issueKey, issueId, opts) => exports_Effect.tryPromise({
38512
+ try: () => ensureWorktree(workingDir, issueKey, issueId, opts),
38420
38513
  catch: (cause3) => new WorktreeError({ message: `ensureWorktree failed`, cause: cause3 })
38421
38514
  }),
38422
38515
  isGitRepo: (dir) => exports_Effect.tryPromise({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipers-dev/multi",
3
- "version": "0.41.0",
3
+ "version": "0.43.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "multi-agent": "./dist/index.js"
Binary file
Binary file
Binary file