@runfusion/fusion 0.33.0 → 0.34.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.
Files changed (54) hide show
  1. package/dist/bin.js +1256 -936
  2. package/dist/client/.vite/manifest.json +60 -59
  3. package/dist/client/assets/{AgentDetailView-BACu9GYE.js → AgentDetailView-CzqwIIpv.js} +1 -1
  4. package/dist/client/assets/{AgentPermissionPolicyEditor-tNNlcCDk.js → AgentPermissionPolicyEditor-2eoM2XQH.js} +1 -1
  5. package/dist/client/assets/{AgentsView-CPpHwjn3.js → AgentsView-BrtAvhJl.js} +5 -5
  6. package/dist/client/assets/ChatView-BuIe4MhL.js +6 -0
  7. package/dist/client/assets/{DevServerView-BlxSS8Uu.js → DevServerView-CF6FPLRb.js} +1 -1
  8. package/dist/client/assets/{DirectoryPicker-ioTzF36r.js → DirectoryPicker-BpvHQxhu.js} +1 -1
  9. package/dist/client/assets/{DocumentsView-CsDb8dPw.js → DocumentsView-RMWZBJ-y.js} +1 -1
  10. package/dist/client/assets/{EvalsView-I0GhxVhm.js → EvalsView-DtVxpc4T.js} +1 -1
  11. package/dist/client/assets/{ExperimentalAgentOnboardingModal-Cr6g_jok.js → ExperimentalAgentOnboardingModal-fzJmb-yG.js} +1 -1
  12. package/dist/client/assets/{GoalsView-DXJxe6D4.js → GoalsView-BAchggxo.js} +1 -1
  13. package/dist/client/assets/{InsightsView-BaIhzpvX.js → InsightsView-B8892IbG.js} +1 -1
  14. package/dist/client/assets/{MemoryView-DlmcI0ca.js → MemoryView-Cfp1WmAm.js} +1 -1
  15. package/dist/client/assets/{NodesView-vc4T0uCy.js → NodesView-Dt26DSEQ.js} +1 -1
  16. package/dist/client/assets/{PiExtensionsManager-C0ljxGbt.js → PiExtensionsManager-xHU56SMh.js} +1 -1
  17. package/dist/client/assets/{PluginManager-D27abRF-.js → PluginManager-37WUEOmp.js} +1 -1
  18. package/dist/client/assets/{ResearchView-BSpDz8YN.js → ResearchView-pu88M5xL.js} +1 -1
  19. package/dist/client/assets/{SecretsView-BmCemEu8.js → SecretsView-BT7ofJLN.js} +1 -1
  20. package/dist/client/assets/SettingsModal-Cz9MHNGg.js +31 -0
  21. package/dist/client/assets/{SettingsModal-DvmwpEUE.js → SettingsModal-DxYXsn08.js} +1 -1
  22. package/dist/client/assets/{SetupWizardModal-CDfZpkB7.js → SetupWizardModal-yWTk3Cac.js} +1 -1
  23. package/dist/client/assets/{SkillsView-BCpa_vud.js → SkillsView-CWNfKNTs.js} +1 -1
  24. package/dist/client/assets/{StashRecoveryView-BYLja93K.js → StashRecoveryView-D0t4IIX-.js} +1 -1
  25. package/dist/client/assets/{TodoView-lbnG-8cZ.js → TodoView-B4W1Lhy6.js} +1 -1
  26. package/dist/client/assets/{dashboard-view-CY6MGQbI.js → dashboard-view-4OCJIthP.js} +1 -1
  27. package/dist/client/assets/{folder-open-CZghG0dv.js → folder-open-BTdhwFQ5.js} +1 -1
  28. package/dist/client/assets/index-D4nQgFjo.js +742 -0
  29. package/dist/client/assets/index-k4s0JWir.css +1 -0
  30. package/dist/client/assets/{upload-L7aDk8Xn.js → upload-kESyjow_.js} +1 -1
  31. package/dist/client/assets/{users-DoWKt94F.js → users-DNXMrdcp.js} +1 -1
  32. package/dist/client/index.html +2 -2
  33. package/dist/client/version.json +1 -1
  34. package/dist/droid-cli/package.json +1 -1
  35. package/dist/extension.js +860 -614
  36. package/dist/pi-claude-cli/package.json +1 -1
  37. package/dist/plugins/fusion-plugin-cli-printing-press/package.json +1 -1
  38. package/dist/plugins/fusion-plugin-cursor-runtime/package.json +1 -1
  39. package/dist/plugins/fusion-plugin-dependency-graph/package.json +1 -1
  40. package/dist/plugins/fusion-plugin-droid-runtime/package.json +1 -1
  41. package/dist/plugins/fusion-plugin-hermes-runtime/package.json +1 -1
  42. package/dist/plugins/fusion-plugin-openclaw-runtime/package.json +1 -1
  43. package/dist/plugins/fusion-plugin-paperclip-runtime/package.json +1 -1
  44. package/dist/plugins/fusion-plugin-reports/package.json +1 -1
  45. package/dist/plugins/fusion-plugin-reports/src/dashboard/__tests__/ReportsView.test.tsx +15 -0
  46. package/dist/plugins/fusion-plugin-reports/src/dashboard/test-setup.ts +9 -1
  47. package/dist/plugins/fusion-plugin-roadmap/package.json +1 -1
  48. package/dist/plugins/fusion-plugin-whatsapp-chat/package.json +1 -1
  49. package/package.json +1 -1
  50. package/skill/fusion/references/extension-tools.md +2 -0
  51. package/dist/client/assets/ChatView-CCAUA7HB.js +0 -6
  52. package/dist/client/assets/SettingsModal-m3KMs_uS.js +0 -31
  53. package/dist/client/assets/index-lDPXOH7J.css +0 -1
  54. package/dist/client/assets/index-tJzhtiGM.js +0 -742
package/dist/extension.js CHANGED
@@ -4642,7 +4642,7 @@ var init_db = __esm({
4642
4642
  DEFAULT_SQLITE_BUSY_TIMEOUT_MS = 5e3;
4643
4643
  DEFAULT_SQLITE_LOCK_RECOVERY_WINDOW_MS = 1e3;
4644
4644
  DEFAULT_SQLITE_LOCK_RECOVERY_DELAY_MS = 50;
4645
- SCHEMA_VERSION = 90;
4645
+ SCHEMA_VERSION = 91;
4646
4646
  SCHEMA_SQL = `
4647
4647
  -- Tasks table with JSON columns for nested data
4648
4648
  CREATE TABLE IF NOT EXISTS tasks (
@@ -5189,6 +5189,7 @@ CREATE TABLE IF NOT EXISTS missions (
5189
5189
  description TEXT,
5190
5190
  status TEXT NOT NULL,
5191
5191
  interviewState TEXT NOT NULL,
5192
+ baseBranch TEXT,
5192
5193
  autoAdvance INTEGER DEFAULT 0,
5193
5194
  createdAt TEXT NOT NULL,
5194
5195
  updatedAt TEXT NOT NULL
@@ -7501,6 +7502,11 @@ This means a caller passed a .fusion directory where a project root was expected
7501
7502
  this.addColumnIfMissing("tasks", "scopeAutoWiden", "TEXT DEFAULT '[]'");
7502
7503
  });
7503
7504
  }
7505
+ if (version < 91) {
7506
+ this.applyMigration(91, () => {
7507
+ this.addColumnIfMissing("missions", "baseBranch", "TEXT");
7508
+ });
7509
+ }
7504
7510
  }
7505
7511
  /**
7506
7512
  * Run a single migration step inside a transaction and bump the version.
@@ -7643,7 +7649,7 @@ This means a caller passed a .fusion directory where a project root was expected
7643
7649
  );
7644
7650
  }
7645
7651
  _Database.sharedIntegrityChecks.delete(this.dbPath);
7646
- }, 3e3);
7652
+ }, 6e4);
7647
7653
  _Database.sharedIntegrityChecks.set(this.dbPath, shared);
7648
7654
  }
7649
7655
  /**
@@ -12547,6 +12553,7 @@ var init_mission_store = __esm({
12547
12553
  description: row.description || void 0,
12548
12554
  status: row.status,
12549
12555
  interviewState: row.interviewState,
12556
+ baseBranch: row.baseBranch || void 0,
12550
12557
  autoAdvance: Boolean(row.autoAdvance),
12551
12558
  autopilotEnabled: Boolean(row.autopilotEnabled),
12552
12559
  autopilotState: row.autopilotState || "inactive",
@@ -12724,6 +12731,7 @@ var init_mission_store = __esm({
12724
12731
  description: input.description,
12725
12732
  status: "planning",
12726
12733
  interviewState: "not_started",
12734
+ baseBranch: input.baseBranch,
12727
12735
  autoAdvance: false,
12728
12736
  autopilotEnabled: input.autopilotEnabled ?? false,
12729
12737
  autopilotState: "inactive",
@@ -12731,14 +12739,15 @@ var init_mission_store = __esm({
12731
12739
  updatedAt: now
12732
12740
  };
12733
12741
  this.db.prepare(`
12734
- INSERT INTO missions (id, title, description, status, interviewState, autoAdvance, autopilotEnabled, autopilotState, createdAt, updatedAt)
12735
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
12742
+ INSERT INTO missions (id, title, description, status, interviewState, baseBranch, autoAdvance, autopilotEnabled, autopilotState, createdAt, updatedAt)
12743
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
12736
12744
  `).run(
12737
12745
  mission.id,
12738
12746
  mission.title,
12739
12747
  mission.description ?? null,
12740
12748
  mission.status,
12741
12749
  mission.interviewState,
12750
+ mission.baseBranch ?? null,
12742
12751
  mission.autoAdvance ? 1 : 0,
12743
12752
  mission.autopilotEnabled ? 1 : 0,
12744
12753
  mission.autopilotState ?? "inactive",
@@ -13204,6 +13213,7 @@ var init_mission_store = __esm({
13204
13213
  description = ?,
13205
13214
  status = ?,
13206
13215
  interviewState = ?,
13216
+ baseBranch = ?,
13207
13217
  autoAdvance = ?,
13208
13218
  autopilotEnabled = ?,
13209
13219
  autopilotState = ?,
@@ -13215,6 +13225,7 @@ var init_mission_store = __esm({
13215
13225
  updated.description ?? null,
13216
13226
  updated.status,
13217
13227
  updated.interviewState,
13228
+ updated.baseBranch ?? null,
13218
13229
  updated.autoAdvance ? 1 : 0,
13219
13230
  updated.autopilotEnabled ? 1 : 0,
13220
13231
  updated.autopilotState ?? "inactive",
@@ -14883,6 +14894,8 @@ ${feature.acceptanceCriteria}`);
14883
14894
  const slice = this.getSlice(feature.sliceId);
14884
14895
  const milestone = slice ? this.getMilestone(slice.milestoneId) : void 0;
14885
14896
  const missionId = milestone?.missionId;
14897
+ const mission = missionId ? this.getMission(missionId) : void 0;
14898
+ const resolvedBaseBranch = branchOptions?.baseBranch ?? mission?.baseBranch;
14886
14899
  const lockScope = missionId ? `mission:${missionId}` : `mission-store:${this.taskStore.getRootDir()}`;
14887
14900
  const guard = await runDeterministicDuplicateGuard(this.taskStore, {
14888
14901
  title: taskTitle || feature.title,
@@ -14897,13 +14910,13 @@ ${feature.acceptanceCriteria}`);
14897
14910
  title: taskTitle || feature.title,
14898
14911
  description,
14899
14912
  branch: branchOptions?.branch,
14900
- baseBranch: branchOptions?.baseBranch,
14913
+ baseBranch: resolvedBaseBranch,
14901
14914
  ...missionId ? {
14902
14915
  branchContext: {
14903
14916
  groupId: `mission:${missionId}`,
14904
14917
  source: "mission",
14905
14918
  assignmentMode: branchOptions?.assignmentMode ?? "shared",
14906
- inheritedBaseBranch: branchOptions?.baseBranch
14919
+ inheritedBaseBranch: resolvedBaseBranch
14907
14920
  }
14908
14921
  } : {}
14909
14922
  });
@@ -14945,12 +14958,16 @@ ${feature.acceptanceCriteria}`);
14945
14958
  }
14946
14959
  const features = this.listFeatures(sliceId);
14947
14960
  const definedFeatures = features.filter((f2) => f2.status === "defined");
14961
+ const milestone = this.getMilestone(slice.milestoneId);
14962
+ const mission = milestone ? this.getMission(milestone.missionId) : void 0;
14963
+ const resolvedBaseBranch = branchOptions?.baseBranch ?? mission?.baseBranch;
14948
14964
  const triaged = [];
14949
14965
  for (const feature of definedFeatures) {
14950
14966
  const branch = branchOptions?.assignmentMode === "per-task-derived" ? branchOptions?.branch ? `${branchOptions.branch}/${feature.id.toLowerCase()}` : void 0 : branchOptions?.branch;
14951
14967
  const updated = await this.triageFeature(feature.id, void 0, void 0, {
14952
14968
  ...branchOptions,
14953
- branch
14969
+ branch,
14970
+ baseBranch: resolvedBaseBranch
14954
14971
  });
14955
14972
  triaged.push(updated);
14956
14973
  }
@@ -25329,8 +25346,8 @@ var init_central_core = __esm({
25329
25346
  async generateProjectName(projectPath) {
25330
25347
  try {
25331
25348
  const { execFile: execFile18 } = await import("node:child_process");
25332
- const { promisify: promisify49 } = await import("node:util");
25333
- const execFileAsync14 = promisify49(execFile18);
25349
+ const { promisify: promisify50 } = await import("node:util");
25350
+ const execFileAsync14 = promisify50(execFile18);
25334
25351
  const { stdout } = await execFileAsync14(
25335
25352
  "git",
25336
25353
  ["remote", "get-url", "origin"],
@@ -26036,8 +26053,8 @@ var init_migration = __esm({
26036
26053
  }
26037
26054
  try {
26038
26055
  const { execFile: execFile18 } = await import("node:child_process");
26039
- const { promisify: promisify49 } = await import("node:util");
26040
- const execFileAsync14 = promisify49(execFile18);
26056
+ const { promisify: promisify50 } = await import("node:util");
26057
+ const execFileAsync14 = promisify50(execFile18);
26041
26058
  const { stdout } = await execFileAsync14(
26042
26059
  "git",
26043
26060
  ["remote", "get-url", "origin"],
@@ -37787,8 +37804,8 @@ async function searchWithQmd(rootDir, options) {
37787
37804
  const limit = Math.max(1, Math.min(options.limit ?? 5, 20));
37788
37805
  try {
37789
37806
  const { execFile: execFile18 } = await import("node:child_process");
37790
- const { promisify: promisify49 } = await import("node:util");
37791
- const execFileAsync14 = promisify49(execFile18);
37807
+ const { promisify: promisify50 } = await import("node:util");
37808
+ const execFileAsync14 = promisify50(execFile18);
37792
37809
  await ensureQmdProjectMemoryCollection(rootDir, execFileAsync14);
37793
37810
  scheduleQmdProjectMemoryRefresh(rootDir);
37794
37811
  const args = buildQmdSearchArgs(rootDir, options);
@@ -37839,8 +37856,8 @@ ${stderr}`)) {
37839
37856
  }
37840
37857
  async function getDefaultExecFileAsync() {
37841
37858
  const { execFile: execFile18 } = await import("node:child_process");
37842
- const { promisify: promisify49 } = await import("node:util");
37843
- return promisify49(execFile18);
37859
+ const { promisify: promisify50 } = await import("node:util");
37860
+ return promisify50(execFile18);
37844
37861
  }
37845
37862
  async function refreshQmdProjectMemoryIndex(rootDir, options) {
37846
37863
  const key = resolve8(rootDir);
@@ -49012,27 +49029,43 @@ function normalizeRunGhOptions(opts) {
49012
49029
  if (typeof opts === "string") return { cwd: opts };
49013
49030
  return opts ?? {};
49014
49031
  }
49032
+ function resetGhAvailabilityCache() {
49033
+ cachedAvailable = void 0;
49034
+ cachedAuthenticated = void 0;
49035
+ }
49015
49036
  function isGhAvailable() {
49037
+ if (cachedAvailable && Date.now() - cachedAvailable.at < GH_CHECK_TTL_MS) {
49038
+ return cachedAvailable.value;
49039
+ }
49040
+ let value = false;
49016
49041
  try {
49017
49042
  execFileSync("gh", ["--version"], {
49018
49043
  encoding: "utf-8",
49019
49044
  stdio: ["pipe", "pipe", "ignore"]
49020
49045
  });
49021
- return true;
49046
+ value = true;
49022
49047
  } catch {
49023
- return false;
49048
+ value = false;
49024
49049
  }
49050
+ cachedAvailable = { value, at: Date.now() };
49051
+ return value;
49025
49052
  }
49026
49053
  function isGhAuthenticated() {
49054
+ if (cachedAuthenticated && Date.now() - cachedAuthenticated.at < GH_CHECK_TTL_MS) {
49055
+ return cachedAuthenticated.value;
49056
+ }
49057
+ let value = false;
49027
49058
  try {
49028
49059
  const result = execFileSync("gh", ["auth", "status"], {
49029
49060
  encoding: "utf-8",
49030
49061
  stdio: ["pipe", "pipe", "ignore"]
49031
49062
  });
49032
- return result.includes("Logged in") || result.includes("Authenticated");
49063
+ value = result.includes("Logged in") || result.includes("Authenticated");
49033
49064
  } catch {
49034
- return false;
49065
+ value = false;
49035
49066
  }
49067
+ cachedAuthenticated = { value, at: Date.now() };
49068
+ return value;
49036
49069
  }
49037
49070
  function runGh(args, cwd) {
49038
49071
  try {
@@ -49300,11 +49333,12 @@ function getCurrentRepo(cwd) {
49300
49333
  return null;
49301
49334
  }
49302
49335
  }
49303
- var DEFAULT_GH_TIMEOUT_MS;
49336
+ var DEFAULT_GH_TIMEOUT_MS, GH_CHECK_TTL_MS, cachedAvailable, cachedAuthenticated;
49304
49337
  var init_gh_cli = __esm({
49305
49338
  "../core/src/gh-cli.ts"() {
49306
49339
  "use strict";
49307
49340
  DEFAULT_GH_TIMEOUT_MS = 3e4;
49341
+ GH_CHECK_TTL_MS = 6e4;
49308
49342
  }
49309
49343
  });
49310
49344
 
@@ -57102,11 +57136,11 @@ var require_extract_zip = __commonJS({
57102
57136
  var { createWriteStream, promises: fs6 } = __require("fs");
57103
57137
  var getStream = require_get_stream();
57104
57138
  var path6 = __require("path");
57105
- var { promisify: promisify49 } = __require("util");
57139
+ var { promisify: promisify50 } = __require("util");
57106
57140
  var stream = __require("stream");
57107
57141
  var yauzl = require_yauzl();
57108
- var openZip = promisify49(yauzl.open);
57109
- var pipeline = promisify49(stream.pipeline);
57142
+ var openZip = promisify50(yauzl.open);
57143
+ var pipeline = promisify50(stream.pipeline);
57110
57144
  var Extractor = class {
57111
57145
  constructor(zipPath, opts) {
57112
57146
  this.zipPath = zipPath;
@@ -57188,7 +57222,7 @@ var require_extract_zip = __commonJS({
57188
57222
  await fs6.mkdir(destDir, mkdirOptions);
57189
57223
  if (isDir) return;
57190
57224
  debug("opening read stream", dest);
57191
- const readStream = await promisify49(this.zipfile.openReadStream.bind(this.zipfile))(entry);
57225
+ const readStream = await promisify50(this.zipfile.openReadStream.bind(this.zipfile))(entry);
57192
57226
  if (symlink) {
57193
57227
  const link = await getStream(readStream);
57194
57228
  debug("creating symlink", link, dest);
@@ -69845,6 +69879,7 @@ __export(src_exports, {
69845
69879
  renderMemoryAuditMarkdown: () => renderMemoryAuditMarkdown,
69846
69880
  replicationCollisionError: () => replicationCollisionError,
69847
69881
  requiresWorktrunkInstallVerification: () => requiresWorktrunkInstallVerification,
69882
+ resetGhAvailabilityCache: () => resetGhAvailabilityCache,
69848
69883
  resolveAgentMemoryInclusionMode: () => resolveAgentMemoryInclusionMode,
69849
69884
  resolveAgentPermissionPolicyPreset: () => resolveAgentPermissionPolicyPreset,
69850
69885
  resolveAgentPrompt: () => resolveAgentPrompt,
@@ -71437,7 +71472,7 @@ var init_github_provider = __esm({
71437
71472
  "repos",
71438
71473
  query,
71439
71474
  "--json",
71440
- "fullName,description,htmlUrl,stargazersCount,language,updatedAt",
71475
+ "fullName,description,url,stargazersCount,language,updatedAt",
71441
71476
  "--limit",
71442
71477
  String(maxResults)
71443
71478
  ],
@@ -71445,9 +71480,9 @@ var init_github_provider = __esm({
71445
71480
  );
71446
71481
  sources.push(
71447
71482
  ...repos.slice(0, maxResults).map((repo, idx) => ({
71448
- id: `github-repo-${idx}-${repo.htmlUrl}`,
71483
+ id: `github-repo-${idx}-${repo.url}`,
71449
71484
  type: "github",
71450
- reference: repo.htmlUrl,
71485
+ reference: repo.url,
71451
71486
  title: repo.fullName,
71452
71487
  excerpt: repo.description ?? "",
71453
71488
  status: "completed",
@@ -71468,7 +71503,7 @@ var init_github_provider = __esm({
71468
71503
  "issues",
71469
71504
  query,
71470
71505
  "--json",
71471
- "title,body,htmlUrl,state,labels",
71506
+ "title,body,url,state,labels",
71472
71507
  "--limit",
71473
71508
  String(maxResults)
71474
71509
  ],
@@ -71476,9 +71511,9 @@ var init_github_provider = __esm({
71476
71511
  );
71477
71512
  sources.push(
71478
71513
  ...issues.slice(0, maxResults).map((issue, idx) => ({
71479
- id: `github-issue-${idx}-${issue.htmlUrl}`,
71514
+ id: `github-issue-${idx}-${issue.url}`,
71480
71515
  type: "github",
71481
- reference: issue.htmlUrl,
71516
+ reference: issue.url,
71482
71517
  title: issue.title,
71483
71518
  excerpt: issue.body?.slice(0, 280) ?? "",
71484
71519
  status: "completed",
@@ -72479,6 +72514,16 @@ async function promptSessionAndCheck(session, prompt, options) {
72479
72514
  }
72480
72515
  }
72481
72516
  async function promptWithFallback(session, prompt, options) {
72517
+ const sessionWithDispatch = session;
72518
+ if (typeof sessionWithDispatch.promptWithFallback === "function" && !promptWithFallbackInFlight.has(session)) {
72519
+ promptWithFallbackInFlight.add(session);
72520
+ try {
72521
+ await sessionWithDispatch.promptWithFallback(prompt, options);
72522
+ return;
72523
+ } finally {
72524
+ promptWithFallbackInFlight.delete(session);
72525
+ }
72526
+ }
72482
72527
  piLog.log(`promptWithFallback: calling session.prompt (prompt length=${prompt.length})`);
72483
72528
  try {
72484
72529
  await promptSessionAndCheck(session, prompt, options);
@@ -73773,7 +73818,7 @@ async function createFnAgent2(options) {
73773
73818
  });
73774
73819
  return { session: promptableSession, sessionFile: promptableSession.sessionFile };
73775
73820
  }
73776
- var execAsync, hostExtensionPaths, FN_MEMORY_APPEND_TOOL_NAME, FUSION_SHUTDOWN_WRAP_FLAG, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS, MAX_COMPACTED_SUBTASK_GUIDANCE_CHARS, MAX_COMPACTED_ATTACHMENTS_CHARS, MAX_COMPACTED_EXISTING_SPEC_CHARS, MAX_COMPACTED_TASK_PROMPT_CHARS, MAX_COMPACTED_USER_COMMENTS_CHARS, GATE_BYPASS_TOOL_NAMES;
73821
+ var execAsync, hostExtensionPaths, FN_MEMORY_APPEND_TOOL_NAME, FUSION_SHUTDOWN_WRAP_FLAG, promptWithFallbackInFlight, COMPACTION_FALLBACK_INSTRUCTIONS, MAX_COMPACTED_PROMPT_MEMORY_CHARS, MAX_COMPACTED_SUBTASK_GUIDANCE_CHARS, MAX_COMPACTED_ATTACHMENTS_CHARS, MAX_COMPACTED_EXISTING_SPEC_CHARS, MAX_COMPACTED_TASK_PROMPT_CHARS, MAX_COMPACTED_USER_COMMENTS_CHARS, GATE_BYPASS_TOOL_NAMES;
73777
73822
  var init_pi = __esm({
73778
73823
  "../engine/src/pi.ts"() {
73779
73824
  "use strict";
@@ -73790,6 +73835,7 @@ var init_pi = __esm({
73790
73835
  hostExtensionPaths = [];
73791
73836
  FN_MEMORY_APPEND_TOOL_NAME = "fn_memory_append";
73792
73837
  FUSION_SHUTDOWN_WRAP_FLAG = "__fusionSessionShutdownDisposeWrapped";
73838
+ promptWithFallbackInFlight = /* @__PURE__ */ new WeakSet();
73793
73839
  COMPACTION_FALLBACK_INSTRUCTIONS = [
73794
73840
  "Summarize all completed steps concisely.",
73795
73841
  "Preserve the current step number and any in-progress work details.",
@@ -75390,8 +75436,8 @@ async function refreshAgentMemoryQmdIndex(rootDir, agentMemory) {
75390
75436
  }
75391
75437
  const promise = (async () => {
75392
75438
  const { execFile: execFile18 } = await import("node:child_process");
75393
- const { promisify: promisify49 } = await import("node:util");
75394
- const execFileAsync14 = promisify49(execFile18);
75439
+ const { promisify: promisify50 } = await import("node:util");
75440
+ const execFileAsync14 = promisify50(execFile18);
75395
75441
  try {
75396
75442
  await execFileAsync14("qmd", buildQmdAgentMemoryCollectionAddArgs(rootDir, agentMemory.agentId), {
75397
75443
  cwd: rootDir,
@@ -75463,8 +75509,8 @@ async function searchAgentMemoryWithQmd(rootDir, agentMemory, query, limit) {
75463
75509
  try {
75464
75510
  await refreshAgentMemoryQmdIndex(rootDir, agentMemory);
75465
75511
  const { execFile: execFile18 } = await import("node:child_process");
75466
- const { promisify: promisify49 } = await import("node:util");
75467
- const execFileAsync14 = promisify49(execFile18);
75512
+ const { promisify: promisify50 } = await import("node:util");
75513
+ const execFileAsync14 = promisify50(execFile18);
75468
75514
  const { stdout } = await execFileAsync14("qmd", buildQmdAgentMemorySearchArgs(rootDir, agentMemory.agentId, query, limit), {
75469
75515
  cwd: rootDir,
75470
75516
  timeout: 4e3,
@@ -85918,6 +85964,7 @@ var init_triage_preflight = __esm({
85918
85964
  });
85919
85965
 
85920
85966
  // ../engine/src/restart-recovery-coordinator.ts
85967
+ import { setImmediate as setImmediateCb } from "node:timers";
85921
85968
  function hasStepProgress(task) {
85922
85969
  const steps = Array.isArray(task.steps) ? task.steps : [];
85923
85970
  return steps.some((step) => step.status === "done" || step.status === "in-progress" || step.status === "skipped");
@@ -85960,12 +86007,13 @@ function isRecoverableMissingWorktreeReviewFailureWithProgress(task) {
85960
86007
  function isRecoverableMissingWorktreeReviewFailureNoProgress(task) {
85961
86008
  return task.column === "in-review" && !task.paused && task.status === "failed" && isMissingWorktreeSessionStartFailure(task.error) && !hasStepProgress(task);
85962
86009
  }
85963
- var log15, MISSING_WORKTREE_SESSION_PREFIXES, RestartRecoveryCoordinator;
86010
+ var log15, yieldEventLoop, MISSING_WORKTREE_SESSION_PREFIXES, RestartRecoveryCoordinator;
85964
86011
  var init_restart_recovery_coordinator = __esm({
85965
86012
  "../engine/src/restart-recovery-coordinator.ts"() {
85966
86013
  "use strict";
85967
86014
  init_logger2();
85968
86015
  log15 = createLogger2("restart-recovery");
86016
+ yieldEventLoop = () => new Promise((resolve32) => setImmediateCb(resolve32));
85969
86017
  MISSING_WORKTREE_SESSION_PREFIXES = [
85970
86018
  "Refusing to start coding agent in missing worktree:",
85971
86019
  "Refusing to start coding agent in incomplete worktree:",
@@ -85985,6 +86033,7 @@ var init_restart_recovery_coordinator = __esm({
85985
86033
  if (!this.mustSafeRetry(task)) continue;
85986
86034
  await this.safeRequeue(task);
85987
86035
  requeued++;
86036
+ await yieldEventLoop();
85988
86037
  }
85989
86038
  if (requeued > 0) {
85990
86039
  log15.log(`Restart recovery requeued ${requeued} interrupted task(s) for safe retry`);
@@ -86323,10 +86372,57 @@ var init_already_merged_detector = __esm({
86323
86372
  }
86324
86373
  });
86325
86374
 
86326
- // ../engine/src/recovery/foreign-only-contamination.ts
86375
+ // ../engine/src/merger-bare-subject.ts
86327
86376
  import { exec as exec14 } from "node:child_process";
86328
- import { existsSync as existsSync33 } from "node:fs";
86329
86377
  import { promisify as promisify15 } from "node:util";
86378
+ function quoteArg(value) {
86379
+ return `'${value.replace(/'/g, "'\\''")}'`;
86380
+ }
86381
+ async function regenerateBareMergeSubject(params) {
86382
+ const { subject, commitSha, branch, taskId, rootDir, settings } = params;
86383
+ if (!subject || !BARE_MERGE_SUBJECT_RE.test(subject)) return subject;
86384
+ if (!settings.useAiMergeCommitSummary) return subject;
86385
+ if (!commitSha) return subject;
86386
+ try {
86387
+ const { stdout: diffStat } = await execAsync13(
86388
+ `git show ${quoteArg(commitSha)} --stat --format=`,
86389
+ { cwd: rootDir, encoding: "utf-8" }
86390
+ );
86391
+ const trimmedStat = diffStat.trim();
86392
+ if (trimmedStat.length === 0) return subject;
86393
+ const resolved = resolveTitleSummarizerSettingsModel(settings);
86394
+ const regenerated = await summarizeCommitSubject(
86395
+ trimmedStat,
86396
+ rootDir,
86397
+ resolved.provider,
86398
+ resolved.modelId,
86399
+ { branch, taskId }
86400
+ );
86401
+ if (!regenerated) return subject;
86402
+ const prefixMatch = subject.match(/^([a-z]+(?:\([^)]+\))?!?:)/i);
86403
+ const prefix = prefixMatch ? prefixMatch[1] : `feat(${taskId}):`;
86404
+ return `${prefix} ${regenerated}`;
86405
+ } catch (err) {
86406
+ const message = err instanceof Error ? err.message : String(err);
86407
+ mergerLog.warn(`${taskId}: bare-merge-subject regeneration failed (${message})`);
86408
+ return subject;
86409
+ }
86410
+ }
86411
+ var execAsync13, BARE_MERGE_SUBJECT_RE;
86412
+ var init_merger_bare_subject = __esm({
86413
+ "../engine/src/merger-bare-subject.ts"() {
86414
+ "use strict";
86415
+ init_src();
86416
+ init_logger2();
86417
+ execAsync13 = promisify15(exec14);
86418
+ BARE_MERGE_SUBJECT_RE = /^[a-z]+(?:\([^)]+\))?!?:\s*merge\s+\S+\s*$/i;
86419
+ }
86420
+ });
86421
+
86422
+ // ../engine/src/recovery/foreign-only-contamination.ts
86423
+ import { exec as exec15 } from "node:child_process";
86424
+ import { existsSync as existsSync33 } from "node:fs";
86425
+ import { promisify as promisify16 } from "node:util";
86330
86426
  function quote2(value) {
86331
86427
  return `'${value.replace(/'/g, `'\\''`)}'`;
86332
86428
  }
@@ -86391,8 +86487,8 @@ async function recoverForeignOnlyContamination(task, deps) {
86391
86487
  });
86392
86488
  return { recovered: false, reason: "active-session" };
86393
86489
  }
86394
- await execAsync13("git worktree prune", { cwd: deps.repoDir, timeout: GIT_TIMEOUT_MS4, maxBuffer: GIT_MAX_BUFFER2 }).catch(() => void 0);
86395
- await execAsync13(`git branch -D ${quote2(task.branch)}`, { cwd: deps.repoDir, timeout: GIT_TIMEOUT_MS4, maxBuffer: GIT_MAX_BUFFER2 }).catch(() => void 0);
86490
+ await execAsync14("git worktree prune", { cwd: deps.repoDir, timeout: GIT_TIMEOUT_MS4, maxBuffer: GIT_MAX_BUFFER2 }).catch(() => void 0);
86491
+ await execAsync14(`git branch -D ${quote2(task.branch)}`, { cwd: deps.repoDir, timeout: GIT_TIMEOUT_MS4, maxBuffer: GIT_MAX_BUFFER2 }).catch(() => void 0);
86396
86492
  await deps.taskStore.moveTask(task.id, "todo", {
86397
86493
  moveSource: "engine",
86398
86494
  preserveResumeState: true,
@@ -86422,14 +86518,14 @@ async function recoverForeignOnlyContamination(task, deps) {
86422
86518
  });
86423
86519
  return { recovered: true, subtype: "branch-discard" };
86424
86520
  }
86425
- var execAsync13, GIT_TIMEOUT_MS4, GIT_MAX_BUFFER2;
86521
+ var execAsync14, GIT_TIMEOUT_MS4, GIT_MAX_BUFFER2;
86426
86522
  var init_foreign_only_contamination = __esm({
86427
86523
  "../engine/src/recovery/foreign-only-contamination.ts"() {
86428
86524
  "use strict";
86429
86525
  init_active_session_registry();
86430
86526
  init_branch_conflicts();
86431
86527
  init_worktree_pool();
86432
- execAsync13 = promisify15(exec14);
86528
+ execAsync14 = promisify16(exec15);
86433
86529
  GIT_TIMEOUT_MS4 = 3e4;
86434
86530
  GIT_MAX_BUFFER2 = 10 * 1024 * 1024;
86435
86531
  }
@@ -86561,8 +86657,8 @@ var init_dependency_blocked_todo_reporter = __esm({
86561
86657
  });
86562
86658
 
86563
86659
  // ../engine/src/sandbox/bubblewrap-detect.ts
86564
- import { exec as exec15 } from "node:child_process";
86565
- import { promisify as promisify16 } from "node:util";
86660
+ import { exec as exec16 } from "node:child_process";
86661
+ import { promisify as promisify17 } from "node:util";
86566
86662
  function parseVersion(raw) {
86567
86663
  const match = raw.match(/(\d+\.\d+(?:\.\d+)?)/);
86568
86664
  return match?.[1];
@@ -86572,7 +86668,7 @@ async function detectBwrapUncached() {
86572
86668
  return { available: false, reason: "not-linux" };
86573
86669
  }
86574
86670
  try {
86575
- const { stdout, stderr } = await execAsync14("command -v bwrap && bwrap --version", {
86671
+ const { stdout, stderr } = await execAsync15("command -v bwrap && bwrap --version", {
86576
86672
  timeout: 5e3,
86577
86673
  maxBuffer: 256 * 1024,
86578
86674
  encoding: "utf-8",
@@ -86602,11 +86698,11 @@ async function detectBwrap() {
86602
86698
  }
86603
86699
  return detectPromise;
86604
86700
  }
86605
- var execAsync14, detectPromise;
86701
+ var execAsync15, detectPromise;
86606
86702
  var init_bubblewrap_detect = __esm({
86607
86703
  "../engine/src/sandbox/bubblewrap-detect.ts"() {
86608
86704
  "use strict";
86609
- execAsync14 = promisify16(exec15);
86705
+ execAsync15 = promisify17(exec16);
86610
86706
  detectPromise = null;
86611
86707
  }
86612
86708
  });
@@ -86693,14 +86789,14 @@ var init_bubblewrap_policy = __esm({
86693
86789
  });
86694
86790
 
86695
86791
  // ../engine/src/sandbox/native.ts
86696
- import { exec as exec16 } from "node:child_process";
86697
- import { promisify as promisify17 } from "node:util";
86698
- var execAsync15, NativeSandboxBackend;
86792
+ import { exec as exec17 } from "node:child_process";
86793
+ import { promisify as promisify18 } from "node:util";
86794
+ var execAsync16, NativeSandboxBackend;
86699
86795
  var init_native = __esm({
86700
86796
  "../engine/src/sandbox/native.ts"() {
86701
86797
  "use strict";
86702
86798
  init_src();
86703
- execAsync15 = promisify17(exec16);
86799
+ execAsync16 = promisify18(exec17);
86704
86800
  NativeSandboxBackend = class {
86705
86801
  capabilities() {
86706
86802
  return {
@@ -86725,7 +86821,7 @@ var init_native = __esm({
86725
86821
  ...options.env !== void 0 && { env: options.env },
86726
86822
  ...options.signal !== void 0 && { signal: options.signal }
86727
86823
  };
86728
- const { stdout, stderr } = await execAsync15(command, execOptions);
86824
+ const { stdout, stderr } = await execAsync16(command, execOptions);
86729
86825
  return {
86730
86826
  stdout: stdout?.toString?.() ?? "",
86731
86827
  stderr: stderr?.toString?.() ?? "",
@@ -86865,16 +86961,16 @@ var init_native = __esm({
86865
86961
  });
86866
86962
 
86867
86963
  // ../engine/src/sandbox/bubblewrap-backend.ts
86868
- import { exec as exec17, spawn as spawn3 } from "node:child_process";
86869
- import { promisify as promisify18 } from "node:util";
86870
- var execAsync16, SandboxUnavailableError, BubblewrapBackend;
86964
+ import { exec as exec18, spawn as spawn3 } from "node:child_process";
86965
+ import { promisify as promisify19 } from "node:util";
86966
+ var execAsync17, SandboxUnavailableError, BubblewrapBackend;
86871
86967
  var init_bubblewrap_backend = __esm({
86872
86968
  "../engine/src/sandbox/bubblewrap-backend.ts"() {
86873
86969
  "use strict";
86874
86970
  init_bubblewrap_detect();
86875
86971
  init_bubblewrap_policy();
86876
86972
  init_native();
86877
- execAsync16 = promisify18(exec17);
86973
+ execAsync17 = promisify19(exec18);
86878
86974
  SandboxUnavailableError = class extends Error {
86879
86975
  constructor(message) {
86880
86976
  super(message);
@@ -86949,7 +87045,7 @@ var init_bubblewrap_backend = __esm({
86949
87045
  if (cached) return cached;
86950
87046
  let resolved = `${process.env.HOME ?? ""}/.local/share/pnpm`;
86951
87047
  try {
86952
- const { stdout } = await execAsync16("pnpm store path --silent", {
87048
+ const { stdout } = await execAsync17("pnpm store path --silent", {
86953
87049
  cwd,
86954
87050
  timeout: 1e4,
86955
87051
  maxBuffer: 256 * 1024,
@@ -87058,12 +87154,12 @@ var init_container_argv = __esm({
87058
87154
 
87059
87155
  // ../engine/src/sandbox/container.ts
87060
87156
  import * as childProcess from "node:child_process";
87061
- import { promisify as promisify19 } from "node:util";
87157
+ import { promisify as promisify20 } from "node:util";
87062
87158
  function getExecAsync() {
87063
- return promisify19(childProcess.exec);
87159
+ return promisify20(childProcess.exec);
87064
87160
  }
87065
87161
  function getExecFileAsync() {
87066
- return promisify19(childProcess.execFile);
87162
+ return promisify20(childProcess.execFile);
87067
87163
  }
87068
87164
  var ContainerSandboxBackend;
87069
87165
  var init_container = __esm({
@@ -87270,14 +87366,14 @@ var init_container = __esm({
87270
87366
  });
87271
87367
 
87272
87368
  // ../engine/src/sandbox/sandbox-exec-detect.ts
87273
- import { exec as exec19 } from "node:child_process";
87274
- import { promisify as promisify20 } from "node:util";
87369
+ import { exec as exec20 } from "node:child_process";
87370
+ import { promisify as promisify21 } from "node:util";
87275
87371
  async function detectSandboxExecUncached() {
87276
87372
  if (process.platform !== "darwin") {
87277
87373
  return { available: false, reason: "not-darwin" };
87278
87374
  }
87279
87375
  try {
87280
- const { stdout } = await execAsync17("command -v sandbox-exec && sandbox-exec -p '(version 1)(allow default)' /usr/bin/true", {
87376
+ const { stdout } = await execAsync18("command -v sandbox-exec && sandbox-exec -p '(version 1)(allow default)' /usr/bin/true", {
87281
87377
  timeout: 5e3,
87282
87378
  maxBuffer: 256 * 1024,
87283
87379
  encoding: "utf-8",
@@ -87302,11 +87398,11 @@ async function detectSandboxExec() {
87302
87398
  }
87303
87399
  return detectPromise2;
87304
87400
  }
87305
- var execAsync17, detectPromise2;
87401
+ var execAsync18, detectPromise2;
87306
87402
  var init_sandbox_exec_detect = __esm({
87307
87403
  "../engine/src/sandbox/sandbox-exec-detect.ts"() {
87308
87404
  "use strict";
87309
- execAsync17 = promisify20(exec19);
87405
+ execAsync18 = promisify21(exec20);
87310
87406
  detectPromise2 = null;
87311
87407
  }
87312
87408
  });
@@ -87428,14 +87524,14 @@ var init_sandbox_exec_policy = __esm({
87428
87524
  });
87429
87525
 
87430
87526
  // ../engine/src/sandbox/sandbox-exec-backend.ts
87431
- import { exec as exec20 } from "node:child_process";
87527
+ import { exec as exec21 } from "node:child_process";
87432
87528
  import os4 from "node:os";
87433
87529
  import path3 from "node:path";
87434
- import { promisify as promisify21 } from "node:util";
87530
+ import { promisify as promisify22 } from "node:util";
87435
87531
  function shEscape(value) {
87436
87532
  return `'${value.replace(/'/g, `'\\''`)}'`;
87437
87533
  }
87438
- var execAsync18, log16, SandboxUnavailableError2, SandboxExecBackend;
87534
+ var execAsync19, log16, SandboxUnavailableError2, SandboxExecBackend;
87439
87535
  var init_sandbox_exec_backend = __esm({
87440
87536
  "../engine/src/sandbox/sandbox-exec-backend.ts"() {
87441
87537
  "use strict";
@@ -87443,7 +87539,7 @@ var init_sandbox_exec_backend = __esm({
87443
87539
  init_sandbox_exec_policy();
87444
87540
  init_native();
87445
87541
  init_logger2();
87446
- execAsync18 = promisify21(exec20);
87542
+ execAsync19 = promisify22(exec21);
87447
87543
  log16 = createLogger2("sandbox-exec");
87448
87544
  SandboxUnavailableError2 = class extends Error {
87449
87545
  constructor(message) {
@@ -87495,7 +87591,7 @@ var init_sandbox_exec_backend = __esm({
87495
87591
  const repoRootPath = process.cwd();
87496
87592
  let pnpmStorePath = path3.join(os4.homedir(), "Library/pnpm/store");
87497
87593
  try {
87498
- const { stdout } = await execAsync18("pnpm store path --silent", {
87594
+ const { stdout } = await execAsync19("pnpm store path --silent", {
87499
87595
  cwd: worktreePath,
87500
87596
  timeout: 1e4,
87501
87597
  maxBuffer: 256 * 1024,
@@ -87543,7 +87639,7 @@ var init_sandbox_exec_backend = __esm({
87543
87639
  ...options.encoding !== void 0 && { encoding: options.encoding },
87544
87640
  ...typeof options.shell === "string" && { shell: options.shell }
87545
87641
  };
87546
- const { stdout, stderr } = await execAsync18(wrappedCommand, execOptions);
87642
+ const { stdout, stderr } = await execAsync19(wrappedCommand, execOptions);
87547
87643
  const result = {
87548
87644
  stdout: stdout?.toString?.() ?? "",
87549
87645
  stderr: stderr?.toString?.() ?? "",
@@ -88034,8 +88130,8 @@ var init_verification_utils = __esm({
88034
88130
  });
88035
88131
 
88036
88132
  // ../engine/src/branch-attribution.ts
88037
- import { exec as exec21 } from "node:child_process";
88038
- import { promisify as promisify22 } from "node:util";
88133
+ import { exec as exec22 } from "node:child_process";
88134
+ import { promisify as promisify23 } from "node:util";
88039
88135
  function quoteShellArg4(value) {
88040
88136
  return `'${value.replace(/'/g, `'\\''`)}'`;
88041
88137
  }
@@ -88073,7 +88169,7 @@ function taskIdsMatch(a, b2) {
88073
88169
  return a.toUpperCase() === b2.toUpperCase();
88074
88170
  }
88075
88171
  async function collectOwnTaskCommitsForRange(opts) {
88076
- const execImpl = opts.execAsyncImpl ?? execAsync19;
88172
+ const execImpl = opts.execAsyncImpl ?? execAsync20;
88077
88173
  let logOutput;
88078
88174
  try {
88079
88175
  const result = await execImpl(
@@ -88114,7 +88210,7 @@ async function collectOwnTaskCommitsForRange(opts) {
88114
88210
  return { ownCommitCount: ownCommitShas.length, ownCommitShas };
88115
88211
  }
88116
88212
  async function filterFilesToOwnTaskCommits(opts) {
88117
- const execImpl = opts.execAsyncImpl ?? execAsync19;
88213
+ const execImpl = opts.execAsyncImpl ?? execAsync20;
88118
88214
  const runGit8 = async (command) => {
88119
88215
  try {
88120
88216
  const { stdout } = await execImpl(command, {
@@ -88180,11 +88276,11 @@ async function filterFilesToOwnTaskCommits(opts) {
88180
88276
  commitAttributions
88181
88277
  };
88182
88278
  }
88183
- var execAsync19, GIT_TIMEOUT_MS5, GIT_MAX_BUFFER3, BranchAttributionError, SilentNoOpAttributionMismatchError;
88279
+ var execAsync20, GIT_TIMEOUT_MS5, GIT_MAX_BUFFER3, BranchAttributionError, SilentNoOpAttributionMismatchError;
88184
88280
  var init_branch_attribution = __esm({
88185
88281
  "../engine/src/branch-attribution.ts"() {
88186
88282
  "use strict";
88187
- execAsync19 = promisify22(exec21);
88283
+ execAsync20 = promisify23(exec22);
88188
88284
  GIT_TIMEOUT_MS5 = 3e4;
88189
88285
  GIT_MAX_BUFFER3 = 10 * 1024 * 1024;
88190
88286
  BranchAttributionError = class extends Error {
@@ -88303,7 +88399,7 @@ var init_session_token_usage = __esm({
88303
88399
 
88304
88400
  // ../engine/src/merger-squash-audit.ts
88305
88401
  import { execFile as execFile5 } from "node:child_process";
88306
- import { promisify as promisify23 } from "node:util";
88402
+ import { promisify as promisify24 } from "node:util";
88307
88403
  async function auditSquashMerge(input) {
88308
88404
  const normalizedLookback = normalizeMergeOverlapLookback(input.lookback);
88309
88405
  if (input.strategy === "rebase") {
@@ -88458,7 +88554,7 @@ var execFileAsync, MERGER_MAIN_OVERLAP_LOOKBACK_COMMITS, GIT_OUTPUT_MAX_BUFFER;
88458
88554
  var init_merger_squash_audit = __esm({
88459
88555
  "../engine/src/merger-squash-audit.ts"() {
88460
88556
  "use strict";
88461
- execFileAsync = promisify23(execFile5);
88557
+ execFileAsync = promisify24(execFile5);
88462
88558
  MERGER_MAIN_OVERLAP_LOOKBACK_COMMITS = 30;
88463
88559
  GIT_OUTPUT_MAX_BUFFER = 10 * 1024 * 1024;
88464
88560
  }
@@ -88466,7 +88562,7 @@ var init_merger_squash_audit = __esm({
88466
88562
 
88467
88563
  // ../engine/src/merger-overlap-guard.ts
88468
88564
  import { execFile as execFile6 } from "node:child_process";
88469
- import { promisify as promisify24 } from "node:util";
88565
+ import { promisify as promisify25 } from "node:util";
88470
88566
  async function getBranchTouchedFiles({
88471
88567
  rootDir,
88472
88568
  branch,
@@ -88591,14 +88687,14 @@ var init_merger_overlap_guard = __esm({
88591
88687
  "use strict";
88592
88688
  init_logger2();
88593
88689
  init_merger_squash_audit();
88594
- execFileAsync2 = promisify24(execFile6);
88690
+ execFileAsync2 = promisify25(execFile6);
88595
88691
  GIT_OUTPUT_MAX_BUFFER2 = 10 * 1024 * 1024;
88596
88692
  }
88597
88693
  });
88598
88694
 
88599
88695
  // ../engine/src/merger-diff-volume-gate.ts
88600
88696
  import { execFile as execFile7 } from "node:child_process";
88601
- import { promisify as promisify25 } from "node:util";
88697
+ import { promisify as promisify26 } from "node:util";
88602
88698
  function buildMessage(findings) {
88603
88699
  const details = findings.map((finding) => `${finding.file} (branch_net=${finding.branchNet}, staged=${finding.staged}, ratio=${finding.ratio.toFixed(3)})`).join(", ");
88604
88700
  return `Per-file diff-volume regression detected: ${details}`;
@@ -88659,7 +88755,7 @@ var init_merger_diff_volume_gate = __esm({
88659
88755
  "../engine/src/merger-diff-volume-gate.ts"() {
88660
88756
  "use strict";
88661
88757
  init_merger();
88662
- execFileAsync3 = promisify25(execFile7);
88758
+ execFileAsync3 = promisify26(execFile7);
88663
88759
  DiffVolumeRegressionError = class extends Error {
88664
88760
  constructor(findings) {
88665
88761
  super(buildMessage(findings));
@@ -88671,19 +88767,19 @@ var init_merger_diff_volume_gate = __esm({
88671
88767
  });
88672
88768
 
88673
88769
  // ../engine/src/merger-auto-prerebase.ts
88674
- import { exec as exec22 } from "node:child_process";
88675
- import { promisify as promisify26 } from "node:util";
88770
+ import { exec as exec23 } from "node:child_process";
88771
+ import { promisify as promisify27 } from "node:util";
88676
88772
  async function probeDivergence(opts) {
88677
88773
  const mainRef = opts.mainRef ?? "HEAD";
88678
88774
  const range = `${opts.baseCommitSha}..${mainRef}`;
88679
88775
  const [{ stdout: countOut }, { stdout: diffOut }] = await Promise.all([
88680
- execAsync20(`git rev-list --count ${range}`, {
88776
+ execAsync21(`git rev-list --count ${range}`, {
88681
88777
  cwd: opts.rootDir,
88682
88778
  encoding: "utf-8",
88683
88779
  timeout: 6e4,
88684
88780
  maxBuffer: 10 * 1024 * 1024
88685
88781
  }),
88686
- execAsync20(`git diff --name-only ${range}`, {
88782
+ execAsync21(`git diff --name-only ${range}`, {
88687
88783
  cwd: opts.rootDir,
88688
88784
  encoding: "utf-8",
88689
88785
  timeout: 6e4,
@@ -88721,14 +88817,14 @@ function decideAutoPrerebase(input) {
88721
88817
  return { fire: false, reason: "no-divergence", commitsBehind, hotMatches: [] };
88722
88818
  }
88723
88819
  async function runAutoPrerebase(deps) {
88724
- const mainHead = deps.mainHead?.trim() || (await execAsync20("git rev-parse HEAD", {
88820
+ const mainHead = deps.mainHead?.trim() || (await execAsync21("git rev-parse HEAD", {
88725
88821
  cwd: deps.rootDir,
88726
88822
  encoding: "utf-8",
88727
88823
  timeout: 6e4,
88728
88824
  maxBuffer: 10 * 1024 * 1024
88729
88825
  })).stdout.trim();
88730
88826
  try {
88731
- await execAsync20(`git rebase "${mainHead}"`, {
88827
+ await execAsync21(`git rebase "${mainHead}"`, {
88732
88828
  cwd: deps.worktreePath,
88733
88829
  encoding: "utf-8",
88734
88830
  timeout: 6e4,
@@ -88740,7 +88836,7 @@ async function runAutoPrerebase(deps) {
88740
88836
  const message = error instanceof Error ? error.message : String(error);
88741
88837
  deps.logger.warn(`${deps.taskId}: auto-prerebase failed (${message}) \u2014 aborting`);
88742
88838
  try {
88743
- await execAsync20("git rebase --abort", {
88839
+ await execAsync21("git rebase --abort", {
88744
88840
  cwd: deps.worktreePath,
88745
88841
  encoding: "utf-8",
88746
88842
  timeout: 6e4,
@@ -88752,23 +88848,23 @@ async function runAutoPrerebase(deps) {
88752
88848
  return { ok: false, mainHead, error: message };
88753
88849
  }
88754
88850
  }
88755
- var execAsync20;
88851
+ var execAsync21;
88756
88852
  var init_merger_auto_prerebase = __esm({
88757
88853
  "../engine/src/merger-auto-prerebase.ts"() {
88758
88854
  "use strict";
88759
- execAsync20 = promisify26(exec22);
88855
+ execAsync21 = promisify27(exec23);
88760
88856
  }
88761
88857
  });
88762
88858
 
88763
88859
  // ../engine/src/branch-autocorrect.ts
88764
- import { exec as exec23 } from "node:child_process";
88765
- import { promisify as promisify27 } from "node:util";
88860
+ import { exec as exec24 } from "node:child_process";
88861
+ import { promisify as promisify28 } from "node:util";
88766
88862
  function quoteShellArg5(value) {
88767
88863
  return `'${value.replace(/'/g, `'\\''`)}'`;
88768
88864
  }
88769
88865
  async function runGit2(command, worktreePath) {
88770
88866
  try {
88771
- const { stdout } = await execAsync21(command, {
88867
+ const { stdout } = await execAsync22(command, {
88772
88868
  cwd: worktreePath,
88773
88869
  timeout: GIT_TIMEOUT_MS6,
88774
88870
  maxBuffer: GIT_MAX_BUFFER4
@@ -88827,11 +88923,11 @@ async function attemptBranchAutocorrect({
88827
88923
  }
88828
88924
  return { status: "failed", reason: checkout.reason };
88829
88925
  }
88830
- var execAsync21, GIT_TIMEOUT_MS6, GIT_MAX_BUFFER4;
88926
+ var execAsync22, GIT_TIMEOUT_MS6, GIT_MAX_BUFFER4;
88831
88927
  var init_branch_autocorrect = __esm({
88832
88928
  "../engine/src/branch-autocorrect.ts"() {
88833
88929
  "use strict";
88834
- execAsync21 = promisify27(exec23);
88930
+ execAsync22 = promisify28(exec24);
88835
88931
  GIT_TIMEOUT_MS6 = 1e4;
88836
88932
  GIT_MAX_BUFFER4 = 1024 * 1024;
88837
88933
  }
@@ -89320,8 +89416,8 @@ var init_mesh_lease_manager = __esm({
89320
89416
 
89321
89417
  // ../engine/src/merger-integration-worktree.ts
89322
89418
  import { createHash as createHash10 } from "node:crypto";
89323
- import { exec as exec24, execFile as execFile8 } from "node:child_process";
89324
- import { promisify as promisify28 } from "node:util";
89419
+ import { exec as exec25, execFile as execFile8 } from "node:child_process";
89420
+ import { promisify as promisify29 } from "node:util";
89325
89421
  function quoteAutostashArg(value) {
89326
89422
  return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
89327
89423
  }
@@ -89343,7 +89439,7 @@ async function resolveIntegrationRemote(input) {
89343
89439
  return configured;
89344
89440
  }
89345
89441
  try {
89346
- const { stdout } = await execAsync22(
89442
+ const { stdout } = await execAsync23(
89347
89443
  `git config --get branch.${input.integrationBranch}.remote`,
89348
89444
  { cwd: input.rootDir, encoding: "utf-8" }
89349
89445
  );
@@ -89354,7 +89450,7 @@ async function resolveIntegrationRemote(input) {
89354
89450
  } catch {
89355
89451
  }
89356
89452
  try {
89357
- const { stdout } = await execAsync22("git remote", {
89453
+ const { stdout } = await execAsync23("git remote", {
89358
89454
  cwd: input.rootDir,
89359
89455
  encoding: "utf-8"
89360
89456
  });
@@ -89488,26 +89584,26 @@ async function acquireReuseHandoff(input) {
89488
89584
  let stashSha = null;
89489
89585
  let stashError = null;
89490
89586
  try {
89491
- await execAsync22("git add -A", { cwd: worktreePath });
89492
- const { stdout: createOut } = await execAsync22("git stash create", {
89587
+ await execAsync23("git add -A", { cwd: worktreePath });
89588
+ const { stdout: createOut } = await execAsync23("git stash create", {
89493
89589
  cwd: worktreePath,
89494
89590
  encoding: "utf-8"
89495
89591
  });
89496
89592
  stashSha = String(createOut).trim() || null;
89497
89593
  if (stashSha) {
89498
- await execAsync22(
89594
+ await execAsync23(
89499
89595
  `git stash store -m ${quoteAutostashArg(stashLabel)} ${stashSha}`,
89500
89596
  { cwd: worktreePath }
89501
89597
  );
89502
- await execAsync22("git reset --hard HEAD", { cwd: worktreePath });
89503
- await execAsync22("git clean -fd", { cwd: worktreePath });
89598
+ await execAsync23("git reset --hard HEAD", { cwd: worktreePath });
89599
+ await execAsync23("git clean -fd", { cwd: worktreePath });
89504
89600
  }
89505
89601
  } catch (err) {
89506
89602
  stashError = err instanceof Error ? err.message : String(err);
89507
89603
  }
89508
89604
  if (!stashSha || stashError) {
89509
89605
  try {
89510
- await execAsync22("git reset", { cwd: worktreePath });
89606
+ await execAsync23("git reset", { cwd: worktreePath });
89511
89607
  } catch {
89512
89608
  }
89513
89609
  throw new MergeHandoffRefusedError("working-tree-dirty", "dirty-worktree-autostash-failed", {
@@ -89532,7 +89628,7 @@ async function acquireReuseHandoff(input) {
89532
89628
  }
89533
89629
  });
89534
89630
  }
89535
- const { stdout: headStdout } = await execAsync22("git rev-parse --abbrev-ref HEAD", {
89631
+ const { stdout: headStdout } = await execAsync23("git rev-parse --abbrev-ref HEAD", {
89536
89632
  cwd: worktreePath,
89537
89633
  encoding: "utf-8",
89538
89634
  timeout: 1e4,
@@ -89558,7 +89654,7 @@ async function acquireReuseHandoff(input) {
89558
89654
  mode: autocorrectResult.status
89559
89655
  }
89560
89656
  });
89561
- const { stdout: correctedHead } = await execAsync22("git rev-parse --abbrev-ref HEAD", {
89657
+ const { stdout: correctedHead } = await execAsync23("git rev-parse --abbrev-ref HEAD", {
89562
89658
  cwd: worktreePath,
89563
89659
  encoding: "utf-8",
89564
89660
  timeout: 1e4,
@@ -89574,7 +89670,7 @@ async function acquireReuseHandoff(input) {
89574
89670
  input.task.id
89575
89671
  );
89576
89672
  if (authority.ok) {
89577
- const reattach = await execAsync22(`git checkout ${expectedBranch}`, {
89673
+ const reattach = await execAsync23(`git checkout ${expectedBranch}`, {
89578
89674
  cwd: worktreePath,
89579
89675
  encoding: "utf-8",
89580
89676
  timeout: 3e4,
@@ -89584,7 +89680,7 @@ async function acquireReuseHandoff(input) {
89584
89680
  (err) => ({ ok: false, reason: err instanceof Error ? err.message : String(err) })
89585
89681
  );
89586
89682
  if (reattach.ok) {
89587
- const { stdout: reattachedHead } = await execAsync22("git rev-parse --abbrev-ref HEAD", {
89683
+ const { stdout: reattachedHead } = await execAsync23("git rev-parse --abbrev-ref HEAD", {
89588
89684
  cwd: worktreePath,
89589
89685
  encoding: "utf-8",
89590
89686
  timeout: 1e4,
@@ -89787,7 +89883,7 @@ async function releaseReuseHandoff(input) {
89787
89883
  }
89788
89884
  });
89789
89885
  }
89790
- var execAsync22, execFileAsync4, MERGE_HANDOFF_WORKER_ID, MergeHandoffRefusedError;
89886
+ var execAsync23, execFileAsync4, MERGE_HANDOFF_WORKER_ID, MergeHandoffRefusedError;
89791
89887
  var init_merger_integration_worktree = __esm({
89792
89888
  "../engine/src/merger-integration-worktree.ts"() {
89793
89889
  "use strict";
@@ -89798,8 +89894,8 @@ var init_merger_integration_worktree = __esm({
89798
89894
  init_mesh_lease_manager();
89799
89895
  init_worktree_pool();
89800
89896
  init_worktree_names();
89801
- execAsync22 = promisify28(exec24);
89802
- execFileAsync4 = promisify28(execFile8);
89897
+ execAsync23 = promisify29(exec25);
89898
+ execFileAsync4 = promisify29(execFile8);
89803
89899
  MERGE_HANDOFF_WORKER_ID = "merger-reuse-handoff";
89804
89900
  MergeHandoffRefusedError = class extends Error {
89805
89901
  reason;
@@ -90068,8 +90164,8 @@ var init_worktrunk_failure_handler = __esm({
90068
90164
 
90069
90165
  // ../engine/src/worktree-acquisition.ts
90070
90166
  import { existsSync as existsSync35 } from "node:fs";
90071
- import { exec as exec25 } from "node:child_process";
90072
- import { promisify as promisify29 } from "node:util";
90167
+ import { exec as exec26 } from "node:child_process";
90168
+ import { promisify as promisify30 } from "node:util";
90073
90169
  function configuredCommandErrorMessage(result) {
90074
90170
  if (result.spawnError) return `Failed to start command: ${result.spawnError}`;
90075
90171
  if (result.timedOut) return "Command timed out";
@@ -90101,8 +90197,8 @@ async function maybeWarnForeignTaskStartPoint(input) {
90101
90197
  const { baseBranch, rootDir, worktreePath, taskId, logger: logger3, store, runContext } = input;
90102
90198
  if (!baseBranch || !/^fusion\/fn-\d+$/i.test(baseBranch)) return;
90103
90199
  try {
90104
- const tipSha = (await execAsync23(`git rev-parse --verify ${JSON.stringify(`${baseBranch}^{commit}`)}`, { cwd: rootDir, encoding: "utf-8" })).stdout.trim();
90105
- const details = (await execAsync23(`git log -1 --format=%s%x1f%b ${JSON.stringify(tipSha)}`, { cwd: worktreePath, encoding: "utf-8" })).stdout.trim();
90200
+ const tipSha = (await execAsync24(`git rev-parse --verify ${JSON.stringify(`${baseBranch}^{commit}`)}`, { cwd: rootDir, encoding: "utf-8" })).stdout.trim();
90201
+ const details = (await execAsync24(`git log -1 --format=%s%x1f%b ${JSON.stringify(tipSha)}`, { cwd: worktreePath, encoding: "utf-8" })).stdout.trim();
90106
90202
  const [subject = "", body = ""] = details.split("");
90107
90203
  const subjectMatch = subject.match(/^(?:feat|fix|test|chore|docs|refactor|perf|build)\((FN-\d+)\):/i);
90108
90204
  const trailerMatch = body.match(/(?:^|\n)Fusion-Task-Id:\s*(FN-\d+)\s*(?:\n|$)/i);
@@ -90440,7 +90536,7 @@ async function verifyResumeBranchNotMisbound(input) {
90440
90536
  const { worktreePath, branchName, taskId, rootDir, store, audit, logger: logger3, runContext } = input;
90441
90537
  let baseSha = "";
90442
90538
  try {
90443
- const { stdout } = await execAsync23(
90539
+ const { stdout } = await execAsync24(
90444
90540
  "git merge-base HEAD main 2>/dev/null || git merge-base HEAD origin/main",
90445
90541
  { cwd: worktreePath, encoding: "utf-8" }
90446
90542
  );
@@ -90491,7 +90587,7 @@ async function verifyResumeBranchNotMisbound(input) {
90491
90587
  logger3?.warn?.(`${taskId}: resume re-anchor failed (continuing \u2014 executor preflight will handle): ${formatError(err)}`);
90492
90588
  }
90493
90589
  }
90494
- var execAsync23, INIT_OUTCOME_MAX_CHARS;
90590
+ var execAsync24, INIT_OUTCOME_MAX_CHARS;
90495
90591
  var init_worktree_acquisition = __esm({
90496
90592
  "../engine/src/worktree-acquisition.ts"() {
90497
90593
  "use strict";
@@ -90506,14 +90602,14 @@ var init_worktree_acquisition = __esm({
90506
90602
  init_worktrunk_failure_handler();
90507
90603
  init_secrets_env_writer();
90508
90604
  init_worktree_desktop_artifacts();
90509
- execAsync23 = promisify29(exec25);
90605
+ execAsync24 = promisify30(exec26);
90510
90606
  INIT_OUTCOME_MAX_CHARS = 2e3;
90511
90607
  }
90512
90608
  });
90513
90609
 
90514
90610
  // ../engine/src/merger-ref-update-advance.ts
90515
90611
  import { execFile as execFile9 } from "node:child_process";
90516
- import { promisify as promisify30 } from "node:util";
90612
+ import { promisify as promisify31 } from "node:util";
90517
90613
  async function runGit3(args, cwd) {
90518
90614
  return await execFileAsync5("git", args, {
90519
90615
  cwd,
@@ -90656,7 +90752,7 @@ var execFileAsync5, testHooks, IntegrationBranchConcurrentAdvanceError;
90656
90752
  var init_merger_ref_update_advance = __esm({
90657
90753
  "../engine/src/merger-ref-update-advance.ts"() {
90658
90754
  "use strict";
90659
- execFileAsync5 = promisify30(execFile9);
90755
+ execFileAsync5 = promisify31(execFile9);
90660
90756
  testHooks = {
90661
90757
  runGit: runGit3
90662
90758
  };
@@ -90684,7 +90780,7 @@ var init_merger_ref_update_advance = __esm({
90684
90780
 
90685
90781
  // ../engine/src/worktree-ref-sync.ts
90686
90782
  import { execFile as execFile10, spawn as spawn5 } from "node:child_process";
90687
- import { promisify as promisify31 } from "node:util";
90783
+ import { promisify as promisify32 } from "node:util";
90688
90784
  import { copyFileSync, existsSync as existsSync36, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync2, readFileSync as readFileSync11, rmSync as rmSync3, writeFileSync as writeFileSync2 } from "node:fs";
90689
90785
  import { dirname as dirname17, join as join40 } from "node:path";
90690
90786
  import { tmpdir as tmpdir4 } from "node:os";
@@ -90927,16 +91023,16 @@ var execFileAsync6;
90927
91023
  var init_worktree_ref_sync = __esm({
90928
91024
  "../engine/src/worktree-ref-sync.ts"() {
90929
91025
  "use strict";
90930
- execFileAsync6 = promisify31(execFile10);
91026
+ execFileAsync6 = promisify32(execFile10);
90931
91027
  }
90932
91028
  });
90933
91029
 
90934
91030
  // ../engine/src/merger-scope-auto-widen.ts
90935
- import { exec as exec26 } from "node:child_process";
91031
+ import { exec as exec27 } from "node:child_process";
90936
91032
  import { readFile as readFile20, writeFile as writeFile15 } from "node:fs/promises";
90937
91033
  import { join as join41 } from "node:path";
90938
- import { promisify as promisify32 } from "node:util";
90939
- function quoteArg(value) {
91034
+ import { promisify as promisify33 } from "node:util";
91035
+ function quoteArg2(value) {
90940
91036
  return `'${value.replace(/'/g, `'\\''`)}'`;
90941
91037
  }
90942
91038
  function attributedBySubjectPrefix(subject, taskToken) {
@@ -90968,7 +91064,7 @@ function classifyCommitAttribution(subject, body, taskToken) {
90968
91064
  }
90969
91065
  async function isGitIgnored(file, rootDir, execImpl) {
90970
91066
  try {
90971
- await execImpl(`git check-ignore -- ${quoteArg(file)}`, {
91067
+ await execImpl(`git check-ignore -- ${quoteArg2(file)}`, {
90972
91068
  cwd: rootDir,
90973
91069
  encoding: "utf-8",
90974
91070
  maxBuffer: GIT_MAX_BUFFER5
@@ -90987,7 +91083,7 @@ function scopeContainsPath(scope, file) {
90987
91083
  }
90988
91084
  async function evaluateScopeAutoWiden(params) {
90989
91085
  const { store, task, taskId, rootDir, branch, baseRef, candidateFiles } = params;
90990
- const execImpl = params.execAsyncImpl ?? execAsync24;
91086
+ const execImpl = params.execAsyncImpl ?? execAsync25;
90991
91087
  const widened = [];
90992
91088
  const refused = [];
90993
91089
  const taskToken = toTaskToken(task.id || taskId);
@@ -91016,7 +91112,7 @@ async function evaluateScopeAutoWiden(params) {
91016
91112
  }
91017
91113
  if (claimed) continue;
91018
91114
  const { stdout } = await execImpl(
91019
- `git log ${quoteArg(`${baseRef}..${branch}`)} --format=%H%x00%s%x00%B%x1e -- ${quoteArg(file)}`,
91115
+ `git log ${quoteArg2(`${baseRef}..${branch}`)} --format=%H%x00%s%x00%B%x1e -- ${quoteArg2(file)}`,
91020
91116
  {
91021
91117
  cwd: rootDir,
91022
91118
  encoding: "utf-8",
@@ -91090,12 +91186,12 @@ ${insertion}
91090
91186
  await writeFile15(promptPath, `${before}${normalizedSection}${after}`, "utf-8");
91091
91187
  return toAdd;
91092
91188
  }
91093
- var execAsync24, GIT_MAX_BUFFER5, ScopeAutoWidenPersistError;
91189
+ var execAsync25, GIT_MAX_BUFFER5, ScopeAutoWidenPersistError;
91094
91190
  var init_merger_scope_auto_widen = __esm({
91095
91191
  "../engine/src/merger-scope-auto-widen.ts"() {
91096
91192
  "use strict";
91097
91193
  init_merger();
91098
- execAsync24 = promisify32(exec26);
91194
+ execAsync25 = promisify33(exec27);
91099
91195
  GIT_MAX_BUFFER5 = 10 * 1024 * 1024;
91100
91196
  ScopeAutoWidenPersistError = class extends Error {
91101
91197
  constructor(message) {
@@ -91110,6 +91206,7 @@ var init_merger_scope_auto_widen = __esm({
91110
91206
  var merger_exports = {};
91111
91207
  __export(merger_exports, {
91112
91208
  AutostashCreationFailedError: () => AutostashCreationFailedError,
91209
+ BARE_MERGE_SUBJECT_RE: () => BARE_MERGE_SUBJECT_RE,
91113
91210
  DiffVolumeRegressionError: () => DiffVolumeRegressionError,
91114
91211
  FUSION_TASK_ID_TRAILER_KEY: () => FUSION_TASK_ID_TRAILER_KEY2,
91115
91212
  FileScopeViolationError: () => FileScopeViolationError,
@@ -91174,6 +91271,7 @@ __export(merger_exports, {
91174
91271
  partitionConflictsByFileScope: () => partitionConflictsByFileScope,
91175
91272
  pushToRemoteAfterMerge: () => pushToRemoteAfterMerge,
91176
91273
  readActiveMergerStatus: () => readActiveMergerStatus,
91274
+ regenerateBareMergeSubject: () => regenerateBareMergeSubject,
91177
91275
  resolveConflicts: () => resolveConflicts,
91178
91276
  resolvePostMergeAuditAction: () => resolvePostMergeAuditAction,
91179
91277
  resolvePostMergeAuditInvocation: () => resolvePostMergeAuditInvocation,
@@ -91196,8 +91294,8 @@ __export(merger_exports, {
91196
91294
  tryFastForwardFromOrigin: () => tryFastForwardFromOrigin,
91197
91295
  validateDiffScope: () => validateDiffScope
91198
91296
  });
91199
- import { execSync as execSync4, exec as exec27, execFile as execFile11 } from "node:child_process";
91200
- import { promisify as promisify33 } from "node:util";
91297
+ import { execSync as execSync4, exec as exec28, execFile as execFile11 } from "node:child_process";
91298
+ import { promisify as promisify34 } from "node:util";
91201
91299
  import { existsSync as existsSync37, readFileSync as readFileSync12, readdirSync as readdirSync5, writeFileSync as writeFileSync3, unlinkSync, renameSync as renameSync2 } from "node:fs";
91202
91300
  import { createHash as createHash11 } from "node:crypto";
91203
91301
  import { join as join42 } from "node:path";
@@ -91352,11 +91450,11 @@ function formatDiffVolumeFindings(findings) {
91352
91450
  return findings.map((finding) => `${finding.file} (branchNet=${finding.branchNet}, staged=${finding.staged}, ratio=${finding.ratio.toFixed(3)})`).join("\n");
91353
91451
  }
91354
91452
  async function resetToIntegrationTarget(rootDir, integrationTargetSha) {
91355
- await execAsync25(`git reset --hard ${quoteArg2(integrationTargetSha)}`, {
91453
+ await execAsync26(`git reset --hard ${quoteArg3(integrationTargetSha)}`, {
91356
91454
  cwd: rootDir,
91357
91455
  encoding: "utf-8"
91358
91456
  });
91359
- await execAsync25("git clean -fd", {
91457
+ await execAsync26("git clean -fd", {
91360
91458
  cwd: rootDir,
91361
91459
  encoding: "utf-8"
91362
91460
  });
@@ -91391,7 +91489,7 @@ async function runDiffVolumeGate(params) {
91391
91489
  }
91392
91490
  async function getStagedFiles(cwd) {
91393
91491
  try {
91394
- const { stdout } = await execAsync25("git diff --cached --name-only", {
91492
+ const { stdout } = await execAsync26("git diff --cached --name-only", {
91395
91493
  cwd,
91396
91494
  encoding: "utf-8"
91397
91495
  });
@@ -91462,7 +91560,7 @@ async function syncDependenciesForMerge(store, rootDir, taskId, signal) {
91462
91560
  mergerLog.log(`${taskId}: syncing dependencies before merge verification`);
91463
91561
  await store.logEntry(taskId, `Syncing dependencies before merge verification: ${installCommand}`);
91464
91562
  try {
91465
- await execAsync25(installCommand, {
91563
+ await execAsync26(installCommand, {
91466
91564
  cwd: rootDir,
91467
91565
  encoding: "utf-8",
91468
91566
  maxBuffer: 10 * 1024 * 1024,
@@ -91805,7 +91903,7 @@ function deriveScopedPnpmTestCommand(rootDir, baseBranch, branch) {
91805
91903
  let changedFilesOutput;
91806
91904
  try {
91807
91905
  changedFilesOutput = execSync4(
91808
- `git diff --name-only ${quoteArg2(baseBranch)}...${quoteArg2(branch)}`,
91906
+ `git diff --name-only ${quoteArg3(baseBranch)}...${quoteArg3(branch)}`,
91809
91907
  { cwd: rootDir, stdio: "pipe", encoding: "utf-8" }
91810
91908
  ).toString();
91811
91909
  } catch {
@@ -91817,7 +91915,7 @@ function deriveScopedPnpmTestCommand(rootDir, baseBranch, branch) {
91817
91915
  if (packageNames.length === 0) {
91818
91916
  return null;
91819
91917
  }
91820
- const filters = packageNames.map((name) => `--filter ${quoteArg2(`${name}...^`)}`).join(" ");
91918
+ const filters = packageNames.map((name) => `--filter ${quoteArg3(`${name}...^`)}`).join(" ");
91821
91919
  return `pnpm ${filters} test`;
91822
91920
  }
91823
91921
  function inferDefaultTestCommand(rootDir, explicitTestCommand, explicitBuildCommand, baseBranch, branch) {
@@ -91886,8 +91984,8 @@ function parseFailingFilesFromOutput(output) {
91886
91984
  }
91887
91985
  function getBranchChangedFiles(rootDir, baseBranch, branch) {
91888
91986
  try {
91889
- const baseRef = quoteArg2(baseBranch);
91890
- const headRef = branch === "HEAD" ? "HEAD" : quoteArg2(branch);
91987
+ const baseRef = quoteArg3(baseBranch);
91988
+ const headRef = branch === "HEAD" ? "HEAD" : quoteArg3(branch);
91891
91989
  const output = execSync4(
91892
91990
  `git diff --name-only ${baseRef}...${headRef}`,
91893
91991
  { cwd: rootDir, stdio: "pipe", encoding: "utf-8" }
@@ -92022,7 +92120,7 @@ async function runDeterministicVerification(store, rootDir, taskId, testCommand,
92022
92120
  await store.appendAgentLog(taskId, "[verification:bootstrap] running bootstrap preamble", "tool", bootstrapCommand, "merger");
92023
92121
  try {
92024
92122
  throwIfAborted(signal, taskId);
92025
- await execAsync25(bootstrapCommand, {
92123
+ await execAsync26(bootstrapCommand, {
92026
92124
  cwd: rootDir,
92027
92125
  timeout: 3e5,
92028
92126
  maxBuffer: 10 * 1024 * 1024,
@@ -92083,7 +92181,7 @@ async function runDeterministicVerification(store, rootDir, taskId, testCommand,
92083
92181
  await store.appendAgentLog(taskId, "[verification:retry] bootstrap-built", "tool", rebuildCommand, "merger");
92084
92182
  try {
92085
92183
  throwIfAborted(signal, taskId);
92086
- await execAsync25(rebuildCommand, {
92184
+ await execAsync26(rebuildCommand, {
92087
92185
  cwd: rootDir,
92088
92186
  timeout: 3e5,
92089
92187
  maxBuffer: 10 * 1024 * 1024,
@@ -92447,8 +92545,8 @@ function resetMergeWithWarn(rootDir, taskId, label) {
92447
92545
  async function listStashChangedPaths(rootDir, stashSha) {
92448
92546
  const out = /* @__PURE__ */ new Set();
92449
92547
  try {
92450
- const { stdout } = await execAsync25(
92451
- `git stash show -z --name-only ${quoteArg2(stashSha)}`,
92548
+ const { stdout } = await execAsync26(
92549
+ `git stash show -z --name-only ${quoteArg3(stashSha)}`,
92452
92550
  { cwd: rootDir, encoding: "utf-8" }
92453
92551
  );
92454
92552
  for (const entry of stdout.split("\0")) {
@@ -92462,8 +92560,8 @@ async function listStashChangedPaths(rootDir, stashSha) {
92462
92560
  async function stashTreesEqual(rootDir, aSha, bSha) {
92463
92561
  try {
92464
92562
  const [a, b2] = await Promise.all([
92465
- execAsync25(`git rev-parse ${quoteArg2(aSha)}^{tree}`, { cwd: rootDir, encoding: "utf-8" }),
92466
- execAsync25(`git rev-parse ${quoteArg2(bSha)}^{tree}`, { cwd: rootDir, encoding: "utf-8" })
92563
+ execAsync26(`git rev-parse ${quoteArg3(aSha)}^{tree}`, { cwd: rootDir, encoding: "utf-8" }),
92564
+ execAsync26(`git rev-parse ${quoteArg3(bSha)}^{tree}`, { cwd: rootDir, encoding: "utf-8" })
92467
92565
  ]);
92468
92566
  return a.stdout.trim() === b2.stdout.trim();
92469
92567
  } catch {
@@ -92556,7 +92654,7 @@ function parsePorcelainZ(raw) {
92556
92654
  }
92557
92655
  async function listOrphanedAutostashes(rootDir) {
92558
92656
  try {
92559
- const { stdout } = await execAsync25(
92657
+ const { stdout } = await execAsync26(
92560
92658
  `git stash list --format="%H %gd %s"`,
92561
92659
  { cwd: rootDir, encoding: "utf-8" }
92562
92660
  );
@@ -92599,9 +92697,9 @@ async function classifyAutostashOrphan(rootDir, sha) {
92599
92697
  try {
92600
92698
  const stashFiles = await listStashChangedPaths(rootDir, sha);
92601
92699
  if (stashFiles.size === 0) return "subsumed";
92602
- const pathsArg = [...stashFiles].map(quoteArg2).join(" ");
92603
- const { stdout: pathDiffOut } = await execAsync25(
92604
- `git diff --name-only HEAD ${quoteArg2(sha)} -- ${pathsArg}`,
92700
+ const pathsArg = [...stashFiles].map(quoteArg3).join(" ");
92701
+ const { stdout: pathDiffOut } = await execAsync26(
92702
+ `git diff --name-only HEAD ${quoteArg3(sha)} -- ${pathsArg}`,
92605
92703
  { cwd: rootDir, encoding: "utf-8" }
92606
92704
  );
92607
92705
  return pathDiffOut.trim() === "" ? "subsumed" : "live";
@@ -92641,7 +92739,7 @@ async function notifyAutostashOrphans(store, rootDir, options) {
92641
92739
  }
92642
92740
  async function applyAutostashBySha(rootDir, sha) {
92643
92741
  try {
92644
- await execAsync25(`git stash apply ${quoteArg2(sha)}`, { cwd: rootDir, encoding: "utf-8" });
92742
+ await execAsync26(`git stash apply ${quoteArg3(sha)}`, { cwd: rootDir, encoding: "utf-8" });
92645
92743
  return { ok: true };
92646
92744
  } catch (err) {
92647
92745
  const stderr = err && typeof err === "object" && "stderr" in err ? String(err.stderr ?? "") : "";
@@ -92658,7 +92756,7 @@ ${message}`;
92658
92756
  }
92659
92757
  async function getAutostashDiff(rootDir, sha) {
92660
92758
  const maxBytes = 64 * 1024;
92661
- const { stdout } = await execAsync25(`git stash show -p ${quoteArg2(sha)}`, {
92759
+ const { stdout } = await execAsync26(`git stash show -p ${quoteArg3(sha)}`, {
92662
92760
  cwd: rootDir,
92663
92761
  encoding: "utf-8",
92664
92762
  maxBuffer: 5 * 1024 * 1024
@@ -92690,9 +92788,9 @@ async function sweepAutostashOrphans(rootDir, taskId, store) {
92690
92788
  subsumed.push(orphan);
92691
92789
  continue;
92692
92790
  }
92693
- const pathsArg = [...stashFiles].map(quoteArg2).join(" ");
92694
- const { stdout: pathDiffOut } = await execAsync25(
92695
- `git diff --name-only HEAD ${quoteArg2(orphan.sha)} -- ${pathsArg}`,
92791
+ const pathsArg = [...stashFiles].map(quoteArg3).join(" ");
92792
+ const { stdout: pathDiffOut } = await execAsync26(
92793
+ `git diff --name-only HEAD ${quoteArg3(orphan.sha)} -- ${pathsArg}`,
92696
92794
  { cwd: rootDir, encoding: "utf-8" }
92697
92795
  );
92698
92796
  const isPathSubsumed = pathDiffOut.trim() === "";
@@ -92717,8 +92815,8 @@ async function sweepAutostashOrphans(rootDir, taskId, store) {
92717
92815
  continue;
92718
92816
  }
92719
92817
  try {
92720
- const { stdout: netDiffOut } = await execAsync25(
92721
- `git diff HEAD ${quoteArg2(orphan.sha)}`,
92818
+ const { stdout: netDiffOut } = await execAsync26(
92819
+ `git diff HEAD ${quoteArg3(orphan.sha)}`,
92722
92820
  { cwd: rootDir, encoding: "utf-8" }
92723
92821
  );
92724
92822
  if (netDiffOut.trim() === "") {
@@ -92802,18 +92900,18 @@ async function stashUnrelatedRootDirChanges(rootDir, taskId) {
92802
92900
  const dirty = await snapshotDirtyFiles(rootDir);
92803
92901
  if (dirty.size === 0) return null;
92804
92902
  const label = `${AUTOSTASH_LABEL_PREFIX}${taskId}:${Date.now()}`;
92805
- await execAsync25("git add -A", { cwd: rootDir });
92806
- const { stdout: createOut } = await execAsync25("git stash create", {
92903
+ await execAsync26("git add -A", { cwd: rootDir });
92904
+ const { stdout: createOut } = await execAsync26("git stash create", {
92807
92905
  cwd: rootDir,
92808
92906
  encoding: "utf-8"
92809
92907
  });
92810
92908
  const sha = String(createOut).trim();
92811
92909
  if (!sha) {
92812
- await execAsync25("git reset", { cwd: rootDir }).catch(() => void 0);
92910
+ await execAsync26("git reset", { cwd: rootDir }).catch(() => void 0);
92813
92911
  return null;
92814
92912
  }
92815
- await execAsync25(
92816
- `git stash store -m ${quoteArg2(label)} ${sha}`,
92913
+ await execAsync26(
92914
+ `git stash store -m ${quoteArg3(label)} ${sha}`,
92817
92915
  { cwd: rootDir }
92818
92916
  );
92819
92917
  const primaryStashPaths = await listStashChangedPaths(rootDir, sha);
@@ -92823,9 +92921,9 @@ async function stashUnrelatedRootDirChanges(rootDir, taskId) {
92823
92921
  const newlyDirty = [...currentDirty].filter((p2) => !primaryStashPaths.has(p2));
92824
92922
  if (newlyDirty.length === 0) break;
92825
92923
  const rescueLabel = `${AUTOSTASH_LABEL_PREFIX}${taskId}:race-rescue-${attempt}:${Date.now()}`;
92826
- await execAsync25("git reset", { cwd: rootDir }).catch(() => void 0);
92827
- await execAsync25("git add -A", { cwd: rootDir });
92828
- const { stdout: rescueOut } = await execAsync25("git stash create", {
92924
+ await execAsync26("git reset", { cwd: rootDir }).catch(() => void 0);
92925
+ await execAsync26("git add -A", { cwd: rootDir });
92926
+ const { stdout: rescueOut } = await execAsync26("git stash create", {
92829
92927
  cwd: rootDir,
92830
92928
  encoding: "utf-8"
92831
92929
  });
@@ -92833,8 +92931,8 @@ async function stashUnrelatedRootDirChanges(rootDir, taskId) {
92833
92931
  if (!rescueSha) break;
92834
92932
  const rescueTreeSame = await stashTreesEqual(rootDir, sha, rescueSha);
92835
92933
  if (rescueTreeSame) break;
92836
- await execAsync25(
92837
- `git stash store -m ${quoteArg2(rescueLabel)} ${rescueSha}`,
92934
+ await execAsync26(
92935
+ `git stash store -m ${quoteArg3(rescueLabel)} ${rescueSha}`,
92838
92936
  { cwd: rootDir }
92839
92937
  );
92840
92938
  rescueShas.push({ sha: rescueSha, label: rescueLabel });
@@ -92843,8 +92941,8 @@ async function stashUnrelatedRootDirChanges(rootDir, taskId) {
92843
92941
  );
92844
92942
  for (const p2 of newlyDirty) primaryStashPaths.add(p2);
92845
92943
  }
92846
- await execAsync25("git reset --hard HEAD", { cwd: rootDir });
92847
- await execAsync25("git clean -fd", { cwd: rootDir });
92944
+ await execAsync26("git reset --hard HEAD", { cwd: rootDir });
92945
+ await execAsync26("git clean -fd", { cwd: rootDir });
92848
92946
  const rescueSuffix = rescueShas.length > 0 ? ` + ${rescueShas.length} race-rescue stash(es): ${rescueShas.map((r) => r.sha.slice(0, 7)).join(", ")}` : "";
92849
92947
  mergerLog.log(
92850
92948
  `${taskId}: stashed ${dirty.size} unrelated dirty path(s) in rootDir as ${sha.slice(0, 7)} (${label})${rescueSuffix}`
@@ -92853,7 +92951,7 @@ async function stashUnrelatedRootDirChanges(rootDir, taskId) {
92853
92951
  } catch (err) {
92854
92952
  const msg = err instanceof Error ? err.message : String(err);
92855
92953
  try {
92856
- await execAsync25("git reset", { cwd: rootDir });
92954
+ await execAsync26("git reset", { cwd: rootDir });
92857
92955
  } catch {
92858
92956
  }
92859
92957
  mergerLog.warn(
@@ -92864,7 +92962,7 @@ async function stashUnrelatedRootDirChanges(rootDir, taskId) {
92864
92962
  }
92865
92963
  async function findStashRefBySha(rootDir, sha) {
92866
92964
  try {
92867
- const { stdout } = await execAsync25(
92965
+ const { stdout } = await execAsync26(
92868
92966
  `git stash list --format="%H %gd"`,
92869
92967
  { cwd: rootDir, encoding: "utf-8" }
92870
92968
  );
@@ -92888,7 +92986,7 @@ async function dropAutostashBySha(rootDir, taskId, sha) {
92888
92986
  }
92889
92987
  let refSha = "";
92890
92988
  try {
92891
- const { stdout } = await execAsync25(`git rev-parse ${ref}`, { cwd: rootDir, encoding: "utf-8" });
92989
+ const { stdout } = await execAsync26(`git rev-parse ${ref}`, { cwd: rootDir, encoding: "utf-8" });
92892
92990
  refSha = String(stdout).trim();
92893
92991
  } catch (err) {
92894
92992
  const msg = err instanceof Error ? err.message : String(err);
@@ -92900,7 +92998,7 @@ async function dropAutostashBySha(rootDir, taskId, sha) {
92900
92998
  continue;
92901
92999
  }
92902
93000
  try {
92903
- await execAsync25(`git stash drop ${ref}`, { cwd: rootDir });
93001
+ await execAsync26(`git stash drop ${ref}`, { cwd: rootDir });
92904
93002
  return { dropped: true };
92905
93003
  } catch (err) {
92906
93004
  const msg = err instanceof Error ? err.message : String(err);
@@ -92917,9 +93015,9 @@ async function isAutostashLive(rootDir, sha) {
92917
93015
  try {
92918
93016
  const stashFiles = await listStashChangedPaths(rootDir, sha);
92919
93017
  if (stashFiles.size === 0) return false;
92920
- const pathsArg = [...stashFiles].map(quoteArg2).join(" ");
92921
- const { stdout: pathDiffOut } = await execAsync25(
92922
- `git diff --name-only HEAD ${quoteArg2(sha)} -- ${pathsArg}`,
93018
+ const pathsArg = [...stashFiles].map(quoteArg3).join(" ");
93019
+ const { stdout: pathDiffOut } = await execAsync26(
93020
+ `git diff --name-only HEAD ${quoteArg3(sha)} -- ${pathsArg}`,
92923
93021
  { cwd: rootDir, encoding: "utf-8" }
92924
93022
  );
92925
93023
  return pathDiffOut.trim().length > 0;
@@ -93098,8 +93196,8 @@ async function findFilesWithConflictMarkers(rootDir, files) {
93098
93196
  try {
93099
93197
  const fullPath = join42(rootDir, file);
93100
93198
  if (!existsSync37(fullPath)) continue;
93101
- const { stdout } = await execAsync25(
93102
- `git grep -l -e "^<<<<<<< " -e "^=======$" -e "^>>>>>>> " --no-index -- ${quoteArg2(fullPath)}`,
93199
+ const { stdout } = await execAsync26(
93200
+ `git grep -l -e "^<<<<<<< " -e "^=======$" -e "^>>>>>>> " --no-index -- ${quoteArg3(fullPath)}`,
93103
93201
  { cwd: rootDir, encoding: "utf-8" }
93104
93202
  ).catch(() => ({ stdout: "" }));
93105
93203
  if (String(stdout).trim()) stillConflicted.push(file);
@@ -93115,7 +93213,7 @@ async function tryRecoverHardFailApply(params) {
93115
93213
  let threeWayConflicted = [];
93116
93214
  let threeWayApplied = false;
93117
93215
  try {
93118
- const { stdout: patchOut } = await execAsync25(
93216
+ const { stdout: patchOut } = await execAsync26(
93119
93217
  `git stash show -p --binary ${sha}`,
93120
93218
  { cwd: rootDir, encoding: "utf-8", maxBuffer: 32 * 1024 * 1024 }
93121
93219
  );
@@ -93126,7 +93224,7 @@ async function tryRecoverHardFailApply(params) {
93126
93224
  const patchPath = join42(rootDir, ".git", `fusion-autostash-${sha.slice(0, 7)}.patch`);
93127
93225
  writeFileSync3(patchPath, patchText, "utf-8");
93128
93226
  try {
93129
- await execAsync25(`git apply --3way --whitespace=nowarn ${quoteArg2(patchPath)}`, { cwd: rootDir });
93227
+ await execAsync26(`git apply --3way --whitespace=nowarn ${quoteArg3(patchPath)}`, { cwd: rootDir });
93130
93228
  threeWayApplied = true;
93131
93229
  mergerLog.log(`${taskId}: autostash ${sha.slice(0, 7)} recovered via git apply --3way`);
93132
93230
  } catch (threeWayErr) {
@@ -93432,7 +93530,7 @@ async function restoreRescueAutostashes(rootDir, taskId, handle, ctx) {
93432
93530
  let unresolvedCount = 0;
93433
93531
  for (const rescue of rescueShas) {
93434
93532
  try {
93435
- await execAsync25(`git stash apply ${rescue.sha}`, { cwd: rootDir });
93533
+ await execAsync26(`git stash apply ${rescue.sha}`, { cwd: rootDir });
93436
93534
  const dropResult = await dropAutostashBySha(rootDir, taskId, rescue.sha);
93437
93535
  if (dropResult.dropped) {
93438
93536
  mergerLog.log(`${taskId}: restored and dropped race-rescue autostash ${rescue.sha.slice(0, 7)} (${rescue.label})`);
@@ -93459,7 +93557,7 @@ async function restoreUnrelatedRootDirChanges(rootDir, taskId, handle, ctx) {
93459
93557
  let applyStderr = "";
93460
93558
  let applyErrorMsg = "";
93461
93559
  try {
93462
- await execAsync25(`git stash apply ${sha}`, { cwd: rootDir });
93560
+ await execAsync26(`git stash apply ${sha}`, { cwd: rootDir });
93463
93561
  } catch (err) {
93464
93562
  const errAsRecord = err;
93465
93563
  applyErrorMsg = err instanceof Error ? err.message : String(err);
@@ -93641,6 +93739,35 @@ async function generateAiMergeSubject(commitLog, diffStat, settings, rootDir, br
93641
93739
  return null;
93642
93740
  }
93643
93741
  }
93742
+ async function recordCommitAssociationFromHead(store, rootDir, taskId, lineageId) {
93743
+ let sha = "";
93744
+ let subject = "";
93745
+ let authoredAt = "";
93746
+ try {
93747
+ sha = (await execAsync26("git rev-parse HEAD", { cwd: rootDir })).stdout.trim();
93748
+ subject = (await execAsync26("git log -1 --format=%s HEAD", { cwd: rootDir })).stdout.trim();
93749
+ authoredAt = (await execAsync26("git log -1 --format=%aI HEAD", { cwd: rootDir })).stdout.trim();
93750
+ } catch (err) {
93751
+ const message = err instanceof Error ? err.message : String(err);
93752
+ mergerLog.warn(`${taskId}: skipped commit-association write \u2014 git inspection failed (${message})`);
93753
+ return;
93754
+ }
93755
+ if (!sha || !subject || !authoredAt) {
93756
+ mergerLog.warn(
93757
+ `${taskId}: skipped commit-association write \u2014 empty git output (sha=${sha.length}, subject=${subject.length}, authoredAt=${authoredAt.length})`
93758
+ );
93759
+ return;
93760
+ }
93761
+ await store.upsertTaskCommitAssociation({
93762
+ taskLineageId: lineageId,
93763
+ taskIdSnapshot: taskId,
93764
+ commitSha: sha,
93765
+ commitSubject: subject,
93766
+ authoredAt,
93767
+ matchedBy: "canonical-lineage-trailer",
93768
+ confidence: "canonical"
93769
+ });
93770
+ }
93644
93771
  function deriveDeterministicSubjectSummary(commitLog) {
93645
93772
  const lines = commitLog.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0);
93646
93773
  if (lines.length === 0) return null;
@@ -93689,16 +93816,16 @@ async function persistFinalizeResetLeftovers(rootDir, taskId, store) {
93689
93816
  try {
93690
93817
  const dirtyPaths = [...await snapshotDirtyFiles(rootDir)];
93691
93818
  if (dirtyPaths.length === 0) return;
93692
- await execAsync25("git add -A", { cwd: rootDir });
93693
- const { stdout: createOut } = await execAsync25("git stash create", { cwd: rootDir, encoding: "utf-8" });
93819
+ await execAsync26("git add -A", { cwd: rootDir });
93820
+ const { stdout: createOut } = await execAsync26("git stash create", { cwd: rootDir, encoding: "utf-8" });
93694
93821
  const sha = String(createOut).trim();
93695
93822
  if (!sha) {
93696
- await execAsync25("git reset", { cwd: rootDir }).catch(() => void 0);
93823
+ await execAsync26("git reset", { cwd: rootDir }).catch(() => void 0);
93697
93824
  return;
93698
93825
  }
93699
93826
  const label = `${AUTOSTASH_LABEL_PREFIX}${taskId}:finalize-reset:${Date.now()}`;
93700
- await execAsync25(`git stash store -m ${quoteArg2(label)} ${sha}`, { cwd: rootDir });
93701
- await execAsync25("git reset", { cwd: rootDir }).catch(() => void 0);
93827
+ await execAsync26(`git stash store -m ${quoteArg3(label)} ${sha}`, { cwd: rootDir });
93828
+ await execAsync26("git reset", { cwd: rootDir }).catch(() => void 0);
93702
93829
  mergerLog.warn(
93703
93830
  `${taskId}: persisted ${dirtyPaths.length} dirty rootDir path(s) before finalize reset as ${sha.slice(0, 7)} (${label})`
93704
93831
  );
@@ -93792,12 +93919,12 @@ async function filterStagedGitignoredPaths(rootDir, taskId) {
93792
93919
  }
93793
93920
  async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, includeTaskId, preAttemptHeadSha, authorArg, diffStat, settings, signal, aiSummary, aiSubject, fixModifiedFiles = /* @__PURE__ */ new Set(), store, auditor) {
93794
93921
  try {
93795
- const { stdout: squashStagedOut } = await execAsync25("git diff --cached --name-only", {
93922
+ const { stdout: squashStagedOut } = await execAsync26("git diff --cached --name-only", {
93796
93923
  cwd: rootDir,
93797
93924
  encoding: "utf-8"
93798
93925
  });
93799
93926
  const squashStaged = new Set(squashStagedOut.split("\n").map((l) => l.trim()).filter(Boolean));
93800
- const { stdout: unstagedOut } = await execAsync25("git diff --name-only", {
93927
+ const { stdout: unstagedOut } = await execAsync26("git diff --name-only", {
93801
93928
  cwd: rootDir,
93802
93929
  encoding: "utf-8"
93803
93930
  });
@@ -93842,7 +93969,7 @@ async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, i
93842
93969
  mergerLog.log(
93843
93970
  `${taskId}: staging allowlist \u2014 squash: [${cap([...squashStaged])}], fixModified: [${cap([...fixModifiedFiles])}]`
93844
93971
  );
93845
- const { stdout: staged } = await execAsync25("git diff --cached --raw", {
93972
+ const { stdout: staged } = await execAsync26("git diff --cached --raw", {
93846
93973
  cwd: rootDir,
93847
93974
  encoding: "utf-8"
93848
93975
  });
@@ -93852,53 +93979,53 @@ async function commitOrAmendMergeWithFixes(rootDir, taskId, branch, commitLog, i
93852
93979
  const path6 = match[1];
93853
93980
  mergerLog.warn(`${taskId}: refusing to stage gitlink "${path6}" (project uses no submodules \u2014 likely a nested worktree). Unstaging.`);
93854
93981
  try {
93855
- await execAsync25(`git reset HEAD -- "${path6}"`, { cwd: rootDir });
93982
+ await execAsync26(`git reset HEAD -- "${path6}"`, { cwd: rootDir });
93856
93983
  } catch (err) {
93857
93984
  const msg = err instanceof Error ? err.message : String(err);
93858
93985
  mergerLog.warn(`${taskId}: failed to unstage gitlink "${path6}": ${msg}`);
93859
93986
  }
93860
93987
  }
93861
93988
  await filterStagedGitignoredPaths(rootDir, taskId);
93862
- const { stdout: finalStaged } = await execAsync25("git diff --cached --name-only", {
93989
+ const { stdout: finalStaged } = await execAsync26("git diff --cached --name-only", {
93863
93990
  cwd: rootDir,
93864
93991
  encoding: "utf-8"
93865
93992
  });
93866
93993
  const hasStaged = finalStaged.trim().length > 0;
93867
- const { stdout: currentHeadOut } = await execAsync25("git rev-parse HEAD", {
93994
+ const { stdout: currentHeadOut } = await execAsync26("git rev-parse HEAD", {
93868
93995
  cwd: rootDir,
93869
93996
  encoding: "utf-8"
93870
93997
  });
93871
93998
  const currentHead = currentHeadOut.trim();
93872
93999
  const headMoved = currentHead !== preAttemptHeadSha;
93873
94000
  if (!hasStaged && !headMoved) {
93874
- const { stdout: branchTipOut } = await execAsync25(`git rev-parse ${quoteArg2(branch)}`, {
94001
+ const { stdout: branchTipOut } = await execAsync26(`git rev-parse ${quoteArg3(branch)}`, {
93875
94002
  cwd: rootDir,
93876
94003
  encoding: "utf-8"
93877
94004
  });
93878
94005
  const branchTip = branchTipOut.trim();
93879
94006
  const trailerOnHead = await headCarriesTaskIdTrailer(rootDir, taskId);
93880
- const { stdout: mergeBaseOut } = await execAsync25(
93881
- `git merge-base ${quoteArg2(branchTip)} ${quoteArg2(preAttemptHeadSha)}`,
94007
+ const { stdout: mergeBaseOut } = await execAsync26(
94008
+ `git merge-base ${quoteArg3(branchTip)} ${quoteArg3(preAttemptHeadSha)}`,
93882
94009
  {
93883
94010
  cwd: rootDir,
93884
94011
  encoding: "utf-8"
93885
94012
  }
93886
94013
  );
93887
94014
  const mergeBase = mergeBaseOut.trim();
93888
- const { stdout: diffStatOut } = await execAsync25(`git diff --stat ${preAttemptHeadSha}..${branch}`, {
94015
+ const { stdout: diffStatOut } = await execAsync26(`git diff --stat ${preAttemptHeadSha}..${branch}`, {
93889
94016
  cwd: rootDir,
93890
94017
  encoding: "utf-8"
93891
94018
  });
93892
94019
  const diffStatSummary = diffStatOut.split("\n").slice(0, 20).join("\n");
93893
- const { stdout: stagedCountOut } = await execAsync25("git diff --cached --name-only", {
94020
+ const { stdout: stagedCountOut } = await execAsync26("git diff --cached --name-only", {
93894
94021
  cwd: rootDir,
93895
94022
  encoding: "utf-8"
93896
94023
  });
93897
- const { stdout: unstagedCountOut } = await execAsync25("git diff --name-only", {
94024
+ const { stdout: unstagedCountOut } = await execAsync26("git diff --name-only", {
93898
94025
  cwd: rootDir,
93899
94026
  encoding: "utf-8"
93900
94027
  });
93901
- const { stdout: untrackedCountOut } = await execAsync25("git ls-files --others --exclude-standard", {
94028
+ const { stdout: untrackedCountOut } = await execAsync26("git ls-files --others --exclude-standard", {
93902
94029
  cwd: rootDir,
93903
94030
  encoding: "utf-8"
93904
94031
  });
@@ -93927,8 +94054,8 @@ ${diffStatSummary || " <empty>"}`;
93927
94054
  const branchTipCarriesTaskTrailer = await commitCarriesTaskIdTrailer(rootDir, taskId, branchTip);
93928
94055
  let branchAlreadyOnIntegrationTarget = false;
93929
94056
  try {
93930
- await execAsync25(
93931
- `git merge-base --is-ancestor ${quoteArg2(branchTip)} ${quoteArg2(preAttemptHeadSha)}`,
94057
+ await execAsync26(
94058
+ `git merge-base --is-ancestor ${quoteArg3(branchTip)} ${quoteArg3(preAttemptHeadSha)}`,
93932
94059
  {
93933
94060
  cwd: rootDir,
93934
94061
  encoding: "utf-8",
@@ -93950,8 +94077,8 @@ ${diffStatSummary || " <empty>"}`;
93950
94077
  return { ok: true, reason: "branch-already-merged" };
93951
94078
  }
93952
94079
  try {
93953
- const { stdout: mergeBaseForPatchOut } = await execAsync25(
93954
- `git merge-base ${quoteArg2(branchTip)} ${quoteArg2(preAttemptHeadSha)}`,
94080
+ const { stdout: mergeBaseForPatchOut } = await execAsync26(
94081
+ `git merge-base ${quoteArg3(branchTip)} ${quoteArg3(preAttemptHeadSha)}`,
93955
94082
  {
93956
94083
  cwd: rootDir,
93957
94084
  encoding: "utf-8",
@@ -93960,8 +94087,8 @@ ${diffStatSummary || " <empty>"}`;
93960
94087
  );
93961
94088
  const mergeBaseForPatch = mergeBaseForPatchOut.trim();
93962
94089
  if (mergeBaseForPatch) {
93963
- const { stdout: branchPatchIdOut } = await execAsync25(
93964
- `git diff ${quoteArg2(mergeBaseForPatch)}..${quoteArg2(branchTip)} | git patch-id --stable`,
94090
+ const { stdout: branchPatchIdOut } = await execAsync26(
94091
+ `git diff ${quoteArg3(mergeBaseForPatch)}..${quoteArg3(branchTip)} | git patch-id --stable`,
93965
94092
  {
93966
94093
  cwd: rootDir,
93967
94094
  encoding: "utf-8",
@@ -93970,8 +94097,8 @@ ${diffStatSummary || " <empty>"}`;
93970
94097
  );
93971
94098
  const branchPatchId = branchPatchIdOut.trim().split(/\s+/)[0] || "";
93972
94099
  if (branchPatchId && branchTipCarriesTaskTrailer) {
93973
- const { stdout: recentShaOut } = await execAsync25(
93974
- `git log ${quoteArg2(preAttemptHeadSha)} -n 20 --format=%H`,
94100
+ const { stdout: recentShaOut } = await execAsync26(
94101
+ `git log ${quoteArg3(preAttemptHeadSha)} -n 20 --format=%H`,
93975
94102
  {
93976
94103
  cwd: rootDir,
93977
94104
  encoding: "utf-8",
@@ -93999,15 +94126,15 @@ ${diffStatSummary || " <empty>"}`;
93999
94126
  let squashRestoreReportedUpToDate = false;
94000
94127
  try {
94001
94128
  await persistFinalizeResetLeftovers(rootDir, taskId, store);
94002
- await execAsync25(`git reset --hard ${preAttemptHeadSha}`, {
94129
+ await execAsync26(`git reset --hard ${preAttemptHeadSha}`, {
94003
94130
  cwd: rootDir,
94004
94131
  encoding: "utf-8"
94005
94132
  });
94006
- await execAsync25("git clean -fd", {
94133
+ await execAsync26("git clean -fd", {
94007
94134
  cwd: rootDir,
94008
94135
  encoding: "utf-8"
94009
94136
  });
94010
- const { stdout: squashRestoreOut, stderr: squashRestoreErr } = await execAsync25(`git merge --squash ${branch}`, {
94137
+ const { stdout: squashRestoreOut, stderr: squashRestoreErr } = await execAsync26(`git merge --squash ${branch}`, {
94011
94138
  cwd: rootDir,
94012
94139
  encoding: "utf-8"
94013
94140
  });
@@ -94028,7 +94155,7 @@ ${msg}`;
94028
94155
  mergerLog.warn(`${taskId}: failed to restore squash state before finalize: ${msg}; stderr=${stderr.trim() || "<empty>"}`);
94029
94156
  }
94030
94157
  await filterStagedGitignoredPaths(rootDir, taskId);
94031
- const { stdout: restoredStagedOut } = await execAsync25("git diff --cached --name-only", {
94158
+ const { stdout: restoredStagedOut } = await execAsync26("git diff --cached --name-only", {
94032
94159
  cwd: rootDir,
94033
94160
  encoding: "utf-8"
94034
94161
  });
@@ -94117,23 +94244,12 @@ ${msg}`;
94117
94244
  settings,
94118
94245
  store
94119
94246
  });
94120
- await execAsync25(
94247
+ await execAsync26(
94121
94248
  `git commit ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
94122
94249
  { cwd: rootDir, env: mergerCommitEnv() }
94123
94250
  );
94124
94251
  if (store && lineageId) {
94125
- const sha = (await execAsync25("git rev-parse HEAD", { cwd: rootDir })).stdout.trim();
94126
- const subject = (await execAsync25("git log -1 --format=%s HEAD", { cwd: rootDir })).stdout.trim();
94127
- const authoredAt = (await execAsync25("git log -1 --format=%aI HEAD", { cwd: rootDir })).stdout.trim();
94128
- await store.upsertTaskCommitAssociation({
94129
- taskLineageId: lineageId,
94130
- taskIdSnapshot: taskId,
94131
- commitSha: sha,
94132
- commitSubject: subject,
94133
- authoredAt,
94134
- matchedBy: "canonical-lineage-trailer",
94135
- confidence: "canonical"
94136
- });
94252
+ await recordCommitAssociationFromHead(store, rootDir, taskId, lineageId);
94137
94253
  }
94138
94254
  mergerLog.log(`${taskId}: created fresh merge commit after verification fix (no prior commit to amend)`);
94139
94255
  return { ok: true, reason: "committed" };
@@ -94156,23 +94272,12 @@ ${msg}`;
94156
94272
  settings,
94157
94273
  store
94158
94274
  });
94159
- await execAsync25(
94275
+ await execAsync26(
94160
94276
  `git commit --amend ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
94161
94277
  { cwd: rootDir, env: mergerCommitEnv() }
94162
94278
  );
94163
94279
  if (store && lineageId) {
94164
- const sha = (await execAsync25("git rev-parse HEAD", { cwd: rootDir })).stdout.trim();
94165
- const subject = (await execAsync25("git log -1 --format=%s HEAD", { cwd: rootDir })).stdout.trim();
94166
- const authoredAt = (await execAsync25("git log -1 --format=%aI HEAD", { cwd: rootDir })).stdout.trim();
94167
- await store.upsertTaskCommitAssociation({
94168
- taskLineageId: lineageId,
94169
- taskIdSnapshot: taskId,
94170
- commitSha: sha,
94171
- commitSubject: subject,
94172
- authoredAt,
94173
- matchedBy: "canonical-lineage-trailer",
94174
- confidence: "canonical"
94175
- });
94280
+ await recordCommitAssociationFromHead(store, rootDir, taskId, lineageId);
94176
94281
  }
94177
94282
  mergerLog.log(`${taskId}: amended merge commit with verification fixes (deterministic message)`);
94178
94283
  return { ok: true, reason: "committed" };
@@ -94187,8 +94292,8 @@ ${msg}`;
94187
94292
  );
94188
94293
  if (authority.ok) {
94189
94294
  try {
94190
- await execAsync25(`git reset --hard ${preAttemptHeadSha}`, { cwd: rootDir, encoding: "utf-8" });
94191
- await execAsync25("git clean -fd", { cwd: rootDir, encoding: "utf-8" });
94295
+ await execAsync26(`git reset --hard ${preAttemptHeadSha}`, { cwd: rootDir, encoding: "utf-8" });
94296
+ await execAsync26("git clean -fd", { cwd: rootDir, encoding: "utf-8" });
94192
94297
  mergerLog.warn(
94193
94298
  `${taskId}: finalize threw but branch ref is authoritative (tip carries Fusion-Task-Id, no foreign commits since base) \u2014 reset HEAD to ${preAttemptHeadSha.slice(0, 8)} for clean retry`
94194
94299
  );
@@ -94356,9 +94461,9 @@ async function applyLayer3ConflictScopePartition(params) {
94356
94461
  const { inScope } = partitionConflictsByFileScope({ conflictFiles, declaredScope: effectiveDeclaredScope });
94357
94462
  for (const file of outOfScope) {
94358
94463
  await resolveWithOurs(file, rootDir);
94359
- await execAsync25(`git reset HEAD -- ${quoteArg2(file)}`, { cwd: rootDir });
94464
+ await execAsync26(`git reset HEAD -- ${quoteArg3(file)}`, { cwd: rootDir });
94360
94465
  }
94361
- const { stdout: stagedOut } = await execAsync25("git diff --cached --name-only", { cwd: rootDir, encoding: "utf-8" });
94466
+ const { stdout: stagedOut } = await execAsync26("git diff --cached --name-only", { cwd: rootDir, encoding: "utf-8" });
94362
94467
  const stagedAfterPartition = stagedOut.split("\n").map((line) => line.trim()).filter(Boolean);
94363
94468
  const outOfScopeStillStaged = stagedAfterPartition.filter((file) => outOfScope.includes(file));
94364
94469
  if (outOfScopeStillStaged.length > 0) {
@@ -94406,7 +94511,7 @@ async function assertSquashOverlapsFileScope(params) {
94406
94511
  if (declaredScope.length === 0) {
94407
94512
  return;
94408
94513
  }
94409
- const { stdout } = await execAsync25("git diff --cached --name-only", {
94514
+ const { stdout } = await execAsync26("git diff --cached --name-only", {
94410
94515
  cwd: rootDir,
94411
94516
  encoding: "utf-8"
94412
94517
  });
@@ -94513,12 +94618,12 @@ async function resolveTaskDiffBaseRef({
94513
94618
  const fallbackBranch = integrationBranchFallback?.trim() || void 0;
94514
94619
  const fallbackRemote = integrationRemoteFallback?.trim() || void 0;
94515
94620
  const resolvedBaseBranch = baseBranch?.trim() || (baseCommitSha ? void 0 : fallbackBranch);
94516
- const quotedHeadRef = quoteArg2(headRef);
94621
+ const quotedHeadRef = quoteArg3(headRef);
94517
94622
  let mergeBase;
94518
94623
  if (resolvedBaseBranch) {
94519
94624
  try {
94520
94625
  try {
94521
- const { stdout } = await execAsync25(`git merge-base ${quotedHeadRef} ${quoteArg2(resolvedBaseBranch)}`, {
94626
+ const { stdout } = await execAsync26(`git merge-base ${quotedHeadRef} ${quoteArg3(resolvedBaseBranch)}`, {
94522
94627
  cwd,
94523
94628
  encoding: "utf-8"
94524
94629
  });
@@ -94527,7 +94632,7 @@ async function resolveTaskDiffBaseRef({
94527
94632
  if (!fallbackRemote) {
94528
94633
  throw new Error("missing integration remote fallback");
94529
94634
  }
94530
- const { stdout } = await execAsync25(`git merge-base ${quotedHeadRef} ${quoteArg2(`${fallbackRemote}/${resolvedBaseBranch}`)}`, {
94635
+ const { stdout } = await execAsync26(`git merge-base ${quotedHeadRef} ${quoteArg3(`${fallbackRemote}/${resolvedBaseBranch}`)}`, {
94531
94636
  cwd,
94532
94637
  encoding: "utf-8"
94533
94638
  });
@@ -94538,7 +94643,7 @@ async function resolveTaskDiffBaseRef({
94538
94643
  }
94539
94644
  if (mergeBase) {
94540
94645
  try {
94541
- const { stdout } = await execAsync25(`git rev-parse ${quotedHeadRef}`, {
94646
+ const { stdout } = await execAsync26(`git rev-parse ${quotedHeadRef}`, {
94542
94647
  cwd,
94543
94648
  encoding: "utf-8"
94544
94649
  });
@@ -94551,7 +94656,7 @@ async function resolveTaskDiffBaseRef({
94551
94656
  let recoveredBase;
94552
94657
  if (!baseBranch?.trim() && fallbackBranch) {
94553
94658
  try {
94554
- const { stdout } = await execAsync25(`git merge-base ${quotedHeadRef} ${quoteArg2(fallbackBranch)}`, {
94659
+ const { stdout } = await execAsync26(`git merge-base ${quotedHeadRef} ${quoteArg3(fallbackBranch)}`, {
94555
94660
  cwd,
94556
94661
  encoding: "utf-8"
94557
94662
  });
@@ -94559,7 +94664,7 @@ async function resolveTaskDiffBaseRef({
94559
94664
  } catch {
94560
94665
  if (fallbackRemote) {
94561
94666
  try {
94562
- const { stdout } = await execAsync25(`git merge-base ${quotedHeadRef} ${quoteArg2(`${fallbackRemote}/${fallbackBranch}`)}`, {
94667
+ const { stdout } = await execAsync26(`git merge-base ${quotedHeadRef} ${quoteArg3(`${fallbackRemote}/${fallbackBranch}`)}`, {
94563
94668
  cwd,
94564
94669
  encoding: "utf-8"
94565
94670
  });
@@ -94571,13 +94676,13 @@ async function resolveTaskDiffBaseRef({
94571
94676
  }
94572
94677
  if (baseCommitSha) {
94573
94678
  try {
94574
- await execAsync25(`git merge-base --is-ancestor ${quoteArg2(baseCommitSha)} ${quotedHeadRef}`, {
94679
+ await execAsync26(`git merge-base --is-ancestor ${quoteArg3(baseCommitSha)} ${quotedHeadRef}`, {
94575
94680
  cwd,
94576
94681
  encoding: "utf-8"
94577
94682
  });
94578
94683
  if (recoveredBase && recoveredBase !== baseCommitSha) {
94579
94684
  try {
94580
- await execAsync25(`git merge-base --is-ancestor ${quoteArg2(baseCommitSha)} ${quoteArg2(recoveredBase)}`, {
94685
+ await execAsync26(`git merge-base --is-ancestor ${quoteArg3(baseCommitSha)} ${quoteArg3(recoveredBase)}`, {
94581
94686
  cwd,
94582
94687
  encoding: "utf-8"
94583
94688
  });
@@ -94591,7 +94696,7 @@ async function resolveTaskDiffBaseRef({
94591
94696
  }
94592
94697
  if (recoveredBase) return recoveredBase;
94593
94698
  try {
94594
- const { stdout } = await execAsync25(`git rev-parse ${quoteArg2(`${headRef}~1`)}`, {
94699
+ const { stdout } = await execAsync26(`git rev-parse ${quoteArg3(`${headRef}~1`)}`, {
94595
94700
  cwd,
94596
94701
  encoding: "utf-8"
94597
94702
  });
@@ -94602,7 +94707,7 @@ async function resolveTaskDiffBaseRef({
94602
94707
  }
94603
94708
  async function getConflictedFiles(cwd) {
94604
94709
  try {
94605
- const { stdout } = await execAsync25("git diff --name-only --diff-filter=U", {
94710
+ const { stdout } = await execAsync26("git diff --name-only --diff-filter=U", {
94606
94711
  cwd,
94607
94712
  encoding: "utf-8"
94608
94713
  });
@@ -94615,7 +94720,7 @@ async function getConflictedFiles(cwd) {
94615
94720
  }
94616
94721
  async function isTrivialWhitespaceConflict(filePath, cwd) {
94617
94722
  try {
94618
- const { stdout } = await execAsync25(
94723
+ const { stdout } = await execAsync26(
94619
94724
  `git diff-tree -p -w -- :2:"${filePath}" :3:"${filePath}"`,
94620
94725
  { cwd, encoding: "utf-8" }
94621
94726
  );
@@ -94720,7 +94825,7 @@ function buildTaskTrailerArgs(taskId, lineageId) {
94720
94825
  }
94721
94826
  async function commitCarriesTaskIdTrailer(rootDir, taskId, commitish) {
94722
94827
  try {
94723
- const { stdout } = await execAsync25(`git log -1 --pretty=%B ${quoteArg2(commitish)}`, {
94828
+ const { stdout } = await execAsync26(`git log -1 --pretty=%B ${quoteArg3(commitish)}`, {
94724
94829
  cwd: rootDir,
94725
94830
  encoding: "utf-8"
94726
94831
  });
@@ -94736,7 +94841,7 @@ async function headCarriesTaskIdTrailer(rootDir, taskId) {
94736
94841
  }
94737
94842
  async function ensureTaskTrailersOnHead(rootDir, task) {
94738
94843
  try {
94739
- const { stdout: existingMessage } = await execAsync25("git log -1 --pretty=%B", {
94844
+ const { stdout: existingMessage } = await execAsync26("git log -1 --pretty=%B", {
94740
94845
  cwd: rootDir,
94741
94846
  encoding: "utf-8"
94742
94847
  });
@@ -94752,7 +94857,7 @@ async function ensureTaskTrailersOnHead(rootDir, task) {
94752
94857
  for (const trailer of trailersToAdd) {
94753
94858
  amendCommand += ` --trailer "${trailer}"`;
94754
94859
  }
94755
- await execAsync25(amendCommand, { cwd: rootDir, env: mergerCommitEnv() });
94860
+ await execAsync26(amendCommand, { cwd: rootDir, env: mergerCommitEnv() });
94756
94861
  } catch (err) {
94757
94862
  const msg = err instanceof Error ? err.message : String(err);
94758
94863
  mergerLog.warn(`${task.id}: failed to add merge trailers to HEAD (${msg}) \u2014 relying on fallback ownership signals`);
@@ -94760,21 +94865,21 @@ async function ensureTaskTrailersOnHead(rootDir, task) {
94760
94865
  }
94761
94866
  async function runCherryPickWithEmptySkip(rootDir, args) {
94762
94867
  try {
94763
- await execAsync25(`git cherry-pick ${args}`, { cwd: rootDir });
94868
+ await execAsync26(`git cherry-pick ${args}`, { cwd: rootDir });
94764
94869
  return { kind: "landed" };
94765
94870
  } catch (error) {
94766
94871
  if (!isEmptyCherryPickError(error)) {
94767
94872
  throw error;
94768
94873
  }
94769
94874
  try {
94770
- await execAsync25("git cherry-pick --skip", { cwd: rootDir });
94875
+ await execAsync26("git cherry-pick --skip", { cwd: rootDir });
94771
94876
  return { kind: "empty", recovery: "skip" };
94772
94877
  } catch {
94773
94878
  try {
94774
- await execAsync25("git cherry-pick --abort", { cwd: rootDir });
94879
+ await execAsync26("git cherry-pick --abort", { cwd: rootDir });
94775
94880
  } catch {
94776
94881
  }
94777
- await execAsync25("git reset --hard HEAD", { cwd: rootDir });
94882
+ await execAsync26("git reset --hard HEAD", { cwd: rootDir });
94778
94883
  return { kind: "empty", recovery: "abort-reset" };
94779
94884
  }
94780
94885
  }
@@ -94792,13 +94897,13 @@ ${message}`;
94792
94897
  }
94793
94898
  async function isCherryPickInProgress(rootDir) {
94794
94899
  try {
94795
- const { stdout: cherryPickHeadPathOut } = await execAsync25("git rev-parse --git-path CHERRY_PICK_HEAD", {
94900
+ const { stdout: cherryPickHeadPathOut } = await execAsync26("git rev-parse --git-path CHERRY_PICK_HEAD", {
94796
94901
  cwd: rootDir,
94797
94902
  encoding: "utf-8"
94798
94903
  });
94799
94904
  const cherryPickHeadPath = join42(rootDir, cherryPickHeadPathOut.trim());
94800
94905
  if (existsSync37(cherryPickHeadPath)) return true;
94801
- const { stdout: sequencerPathOut } = await execAsync25("git rev-parse --git-path sequencer", {
94906
+ const { stdout: sequencerPathOut } = await execAsync26("git rev-parse --git-path sequencer", {
94802
94907
  cwd: rootDir,
94803
94908
  encoding: "utf-8"
94804
94909
  });
@@ -94810,7 +94915,7 @@ async function isCherryPickInProgress(rootDir) {
94810
94915
  }
94811
94916
  async function cherryPickCommitPreservingTaskTrailers(rootDir, commitSha, task, mergeConflictStrategy, smartConflictResolution, result) {
94812
94917
  try {
94813
- const initialPick = await runCherryPickWithEmptySkip(rootDir, quoteArg2(commitSha));
94918
+ const initialPick = await runCherryPickWithEmptySkip(rootDir, quoteArg3(commitSha));
94814
94919
  if (initialPick.kind === "empty") {
94815
94920
  return { landed: false, reason: "empty" };
94816
94921
  }
@@ -94837,22 +94942,22 @@ async function cherryPickCommitPreservingTaskTrailers(rootDir, commitSha, task,
94837
94942
  }
94838
94943
  }
94839
94944
  if (unresolvedComplex === 0) {
94840
- await execAsync25("git cherry-pick --continue", { cwd: rootDir });
94945
+ await execAsync26("git cherry-pick --continue", { cwd: rootDir });
94841
94946
  await ensureTaskTrailersOnHead(rootDir, task);
94842
94947
  return { landed: true };
94843
94948
  }
94844
94949
  }
94845
94950
  try {
94846
- await execAsync25("git cherry-pick --abort", { cwd: rootDir });
94951
+ await execAsync26("git cherry-pick --abort", { cwd: rootDir });
94847
94952
  } catch {
94848
94953
  }
94849
94954
  if (mergeConflictStrategy === "smart-prefer-main") {
94850
- const fallbackPick = await runCherryPickWithEmptySkip(rootDir, `-X ours ${quoteArg2(commitSha)}`);
94955
+ const fallbackPick = await runCherryPickWithEmptySkip(rootDir, `-X ours ${quoteArg3(commitSha)}`);
94851
94956
  if (fallbackPick.kind === "empty") {
94852
94957
  return { landed: false, reason: "empty" };
94853
94958
  }
94854
94959
  } else if (mergeConflictStrategy === "smart-prefer-branch") {
94855
- const fallbackPick = await runCherryPickWithEmptySkip(rootDir, `-X theirs ${quoteArg2(commitSha)}`);
94960
+ const fallbackPick = await runCherryPickWithEmptySkip(rootDir, `-X theirs ${quoteArg3(commitSha)}`);
94856
94961
  if (fallbackPick.kind === "empty") {
94857
94962
  return { landed: false, reason: "empty" };
94858
94963
  }
@@ -94865,11 +94970,11 @@ async function cherryPickCommitPreservingTaskTrailers(rootDir, commitSha, task,
94865
94970
  }
94866
94971
  async function applyBranchCommitsPreservingHistory(params) {
94867
94972
  const { rootDir, baseRef, branch, task, taskId, store, mergeConflictStrategy, smartConflictResolution, result, testCommand, buildCommand: buildCommand2, testSource, buildSource, signal } = params;
94868
- const { stdout: baseShaStdout } = await execAsync25(`git rev-parse ${quoteArg2(baseRef)}`, { cwd: rootDir, encoding: "utf-8" });
94973
+ const { stdout: baseShaStdout } = await execAsync26(`git rev-parse ${quoteArg3(baseRef)}`, { cwd: rootDir, encoding: "utf-8" });
94869
94974
  const baseSha = baseShaStdout.trim();
94870
- const { stdout: originalBranchShaOut } = await execAsync25("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
94975
+ const { stdout: originalBranchShaOut } = await execAsync26("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
94871
94976
  const originalBranchSha = originalBranchShaOut.trim();
94872
- const { stdout: commitStdout } = await execAsync25(`git rev-list --reverse ${quoteArg2(`${baseSha}..${branch}`)}`, {
94977
+ const { stdout: commitStdout } = await execAsync26(`git rev-list --reverse ${quoteArg3(`${baseSha}..${branch}`)}`, {
94873
94978
  cwd: rootDir,
94874
94979
  encoding: "utf-8"
94875
94980
  });
@@ -94890,7 +94995,7 @@ async function applyBranchCommitsPreservingHistory(params) {
94890
94995
  skippedEmptyCount += 1;
94891
94996
  continue;
94892
94997
  }
94893
- const { stdout: landedShaOut } = await execAsync25("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
94998
+ const { stdout: landedShaOut } = await execAsync26("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
94894
94999
  landedCommitShas.push(landedShaOut.trim());
94895
95000
  }
94896
95001
  const fullySubsumedByMain = landedCommitShas.length === 0 && skippedEmptyCount === commitShas.length && commitShas.length > 0;
@@ -94900,26 +95005,26 @@ async function applyBranchCommitsPreservingHistory(params) {
94900
95005
  await store.logEntry(taskId, `Auto-merge skipped ${skippedEmptyCount} empty cherry-pick(s); proceeded with ${landedCommitShas.length} non-empty commit(s)`);
94901
95006
  }
94902
95007
  try {
94903
- const { stdout: statusOut } = await execAsync25("git status --porcelain", { cwd: rootDir, encoding: "utf-8" });
95008
+ const { stdout: statusOut } = await execAsync26("git status --porcelain", { cwd: rootDir, encoding: "utf-8" });
94904
95009
  const statusClean = statusOut.trim().length === 0;
94905
95010
  const cherryPickActive = await isCherryPickInProgress(rootDir);
94906
95011
  if (!statusClean || cherryPickActive) {
94907
95012
  mergerLog.warn(`${taskId}: cherry-pick cleanup invariant violated (statusClean=${statusClean}, cherryPickActive=${cherryPickActive}); attempting defensive recovery`);
94908
95013
  try {
94909
- await execAsync25("git cherry-pick --abort", { cwd: rootDir });
95014
+ await execAsync26("git cherry-pick --abort", { cwd: rootDir });
94910
95015
  } catch {
94911
95016
  }
94912
- await execAsync25(`git reset --hard ${quoteArg2(originalBranchSha)}`, { cwd: rootDir });
95017
+ await execAsync26(`git reset --hard ${quoteArg3(originalBranchSha)}`, { cwd: rootDir });
94913
95018
  }
94914
95019
  } catch (error) {
94915
95020
  const message = error instanceof Error ? error.message : String(error);
94916
95021
  mergerLog.warn(`${taskId}: failed while validating cherry-pick cleanup invariant (${message}); attempting defensive recovery`);
94917
95022
  try {
94918
- await execAsync25("git cherry-pick --abort", { cwd: rootDir });
95023
+ await execAsync26("git cherry-pick --abort", { cwd: rootDir });
94919
95024
  } catch {
94920
95025
  }
94921
95026
  try {
94922
- await execAsync25(`git reset --hard ${quoteArg2(originalBranchSha)}`, { cwd: rootDir });
95027
+ await execAsync26(`git reset --hard ${quoteArg3(originalBranchSha)}`, { cwd: rootDir });
94923
95028
  } catch {
94924
95029
  }
94925
95030
  }
@@ -95084,7 +95189,7 @@ async function findWorktreeUser(store, worktreePath, excludeTaskId) {
95084
95189
  }
95085
95190
  return null;
95086
95191
  }
95087
- function quoteArg2(value) {
95192
+ function quoteArg3(value) {
95088
95193
  return `"${value.replace(/(["\\$`])/g, "\\$1")}"`;
95089
95194
  }
95090
95195
  function parseShortstatSummary(statsOutput) {
@@ -95102,7 +95207,7 @@ async function sumShortstatsForCommits(rootDir, ownCommitShas) {
95102
95207
  let insertions = 0;
95103
95208
  let deletions = 0;
95104
95209
  for (const sha of ownCommitShas) {
95105
- const { stdout } = await execAsync25(`git show --shortstat --format= ${quoteArg2(sha)}`, {
95210
+ const { stdout } = await execAsync26(`git show --shortstat --format= ${quoteArg3(sha)}`, {
95106
95211
  cwd: rootDir,
95107
95212
  encoding: "utf-8",
95108
95213
  maxBuffer: 2 * 1024 * 1024
@@ -95184,12 +95289,12 @@ async function captureRebaseLandedFilesForTask(params) {
95184
95289
  if (onAttributionFailure) {
95185
95290
  await onAttributionFailure(message);
95186
95291
  }
95187
- const { stdout: landedFilesOutput } = await execAsync25(
95188
- `git diff --name-only ${quoteArg2(`${rebaseMergeBaseSha}..${recordedSha}`)}`,
95292
+ const { stdout: landedFilesOutput } = await execAsync26(
95293
+ `git diff --name-only ${quoteArg3(`${rebaseMergeBaseSha}..${recordedSha}`)}`,
95189
95294
  { cwd: rootDir, encoding: "utf-8", maxBuffer: 2 * 1024 * 1024 }
95190
95295
  );
95191
95296
  const landedFiles = landedFilesOutput.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
95192
- const { stdout: statsOutput } = await execAsync25(`git diff --shortstat ${quoteArg2(`${rebaseMergeBaseSha}..HEAD`)}`, {
95297
+ const { stdout: statsOutput } = await execAsync26(`git diff --shortstat ${quoteArg3(`${rebaseMergeBaseSha}..HEAD`)}`, {
95193
95298
  cwd: rootDir,
95194
95299
  encoding: "utf-8"
95195
95300
  });
@@ -95228,7 +95333,7 @@ function isNonSubstantiveCommitChange(change) {
95228
95333
  return isGeneratedOnlyPath(change.filePath);
95229
95334
  }
95230
95335
  async function classifyBranchCommitsForDirectMerge(rootDir, baseRef, branch) {
95231
- const { stdout: commitStdout } = await execAsync25(`git rev-list --reverse ${quoteArg2(`${baseRef}..${branch}`)}`, {
95336
+ const { stdout: commitStdout } = await execAsync26(`git rev-list --reverse ${quoteArg3(`${baseRef}..${branch}`)}`, {
95232
95337
  cwd: rootDir,
95233
95338
  encoding: "utf-8"
95234
95339
  });
@@ -95237,7 +95342,7 @@ async function classifyBranchCommitsForDirectMerge(rootDir, baseRef, branch) {
95237
95342
  for (const sha of commitShas) {
95238
95343
  let subject = sha;
95239
95344
  try {
95240
- const { stdout } = await execAsync25(`git log -1 --format=%s ${quoteArg2(sha)}`, {
95345
+ const { stdout } = await execAsync26(`git log -1 --format=%s ${quoteArg3(sha)}`, {
95241
95346
  cwd: rootDir,
95242
95347
  encoding: "utf-8"
95243
95348
  });
@@ -95246,7 +95351,7 @@ async function classifyBranchCommitsForDirectMerge(rootDir, baseRef, branch) {
95246
95351
  }
95247
95352
  let substantive = true;
95248
95353
  try {
95249
- const { stdout } = await execAsync25(`git diff-tree --root --no-commit-id --name-status -r ${quoteArg2(sha)}`, {
95354
+ const { stdout } = await execAsync26(`git diff-tree --root --no-commit-id --name-status -r ${quoteArg3(sha)}`, {
95250
95355
  cwd: rootDir,
95251
95356
  encoding: "utf-8"
95252
95357
  });
@@ -95278,7 +95383,7 @@ async function resolveAuditRangeBaseCandidate(opts) {
95278
95383
  const candidateRef = opts.candidateRef.trim();
95279
95384
  if (!candidateRef) return void 0;
95280
95385
  try {
95281
- const { stdout: resolvedOut } = await execAsync25(`git rev-parse --verify ${quoteArg2(`${candidateRef}^{commit}`)}`, {
95386
+ const { stdout: resolvedOut } = await execAsync26(`git rev-parse --verify ${quoteArg3(`${candidateRef}^{commit}`)}`, {
95282
95387
  cwd: opts.rootDir,
95283
95388
  encoding: "utf-8"
95284
95389
  });
@@ -95286,7 +95391,7 @@ async function resolveAuditRangeBaseCandidate(opts) {
95286
95391
  if (!resolvedSha || resolvedSha === opts.auditSha) {
95287
95392
  return void 0;
95288
95393
  }
95289
- await execAsync25(`git merge-base --is-ancestor ${quoteArg2(resolvedSha)} ${quoteArg2(opts.auditSha)}`, {
95394
+ await execAsync26(`git merge-base --is-ancestor ${quoteArg3(resolvedSha)} ${quoteArg3(opts.auditSha)}`, {
95290
95395
  cwd: opts.rootDir,
95291
95396
  encoding: "utf-8"
95292
95397
  });
@@ -95335,7 +95440,7 @@ async function resolvePostMergeAuditInvocation(opts) {
95335
95440
  }
95336
95441
  let mergeBaseSha;
95337
95442
  try {
95338
- const { stdout } = await execAsync25(`git merge-base ${quoteArg2(opts.auditSha)} ${quoteArg2(opts.mergeTargetBranch)}`, {
95443
+ const { stdout } = await execAsync26(`git merge-base ${quoteArg3(opts.auditSha)} ${quoteArg3(opts.mergeTargetBranch)}`, {
95339
95444
  cwd: opts.rootDir,
95340
95445
  encoding: "utf-8"
95341
95446
  });
@@ -95489,8 +95594,8 @@ ${cleanStat}`;
95489
95594
  }
95490
95595
  async function commitPatchId(rootDir, sha) {
95491
95596
  try {
95492
- const { stdout } = await execAsync25(
95493
- `git diff-tree -p ${quoteArg2(sha)} | git patch-id --stable`,
95597
+ const { stdout } = await execAsync26(
95598
+ `git diff-tree -p ${quoteArg3(sha)} | git patch-id --stable`,
95494
95599
  { cwd: rootDir, encoding: "utf-8" }
95495
95600
  );
95496
95601
  const line = stdout.trim();
@@ -95504,8 +95609,8 @@ async function commitPatchId(rootDir, sha) {
95504
95609
  async function collectPatchIds(rootDir, target, windowSize) {
95505
95610
  const ids = /* @__PURE__ */ new Set();
95506
95611
  try {
95507
- const { stdout } = await execAsync25(
95508
- `git log -n ${Math.max(1, windowSize)} --format=%H ${quoteArg2(target)}`,
95612
+ const { stdout } = await execAsync26(
95613
+ `git log -n ${Math.max(1, windowSize)} --format=%H ${quoteArg3(target)}`,
95509
95614
  { cwd: rootDir, encoding: "utf-8" }
95510
95615
  );
95511
95616
  const shas = stdout.trim().split("\n").filter(Boolean);
@@ -95519,16 +95624,16 @@ async function collectPatchIds(rootDir, target, windowSize) {
95519
95624
  }
95520
95625
  async function computeActualMergeCommitContext(params) {
95521
95626
  const { rootDir, integrationTargetSha, branch } = params;
95522
- const targetArg = quoteArg2(integrationTargetSha);
95627
+ const targetArg = quoteArg3(integrationTargetSha);
95523
95628
  let diffStat = "";
95524
95629
  try {
95525
- const { stdout: stagedStat } = await execAsync25(
95630
+ const { stdout: stagedStat } = await execAsync26(
95526
95631
  `git diff --cached ${targetArg} --stat`,
95527
95632
  { cwd: rootDir, encoding: "utf-8" }
95528
95633
  );
95529
95634
  diffStat = stagedStat.trim();
95530
95635
  if (diffStat.length === 0) {
95531
- const { stdout: headStat } = await execAsync25(
95636
+ const { stdout: headStat } = await execAsync26(
95532
95637
  `git diff ${targetArg} HEAD --stat`,
95533
95638
  { cwd: rootDir, encoding: "utf-8" }
95534
95639
  );
@@ -95539,8 +95644,8 @@ async function computeActualMergeCommitContext(params) {
95539
95644
  let commitLog = "";
95540
95645
  try {
95541
95646
  const targetPatchIds = await collectPatchIds(rootDir, integrationTargetSha, 200);
95542
- const { stdout: branchShas } = await execAsync25(
95543
- `git log ${targetArg}..${quoteArg2(branch)} --format=%H`,
95647
+ const { stdout: branchShas } = await execAsync26(
95648
+ `git log ${targetArg}..${quoteArg3(branch)} --format=%H`,
95544
95649
  { cwd: rootDir, encoding: "utf-8" }
95545
95650
  );
95546
95651
  const shas = branchShas.trim().split("\n").filter(Boolean);
@@ -95549,8 +95654,8 @@ async function computeActualMergeCommitContext(params) {
95549
95654
  const pid = await commitPatchId(rootDir, sha);
95550
95655
  if (pid && targetPatchIds.has(pid)) continue;
95551
95656
  try {
95552
- const { stdout: subj } = await execAsync25(
95553
- `git log -1 ${quoteArg2(sha)} --format=%s`,
95657
+ const { stdout: subj } = await execAsync26(
95658
+ `git log -1 ${quoteArg3(sha)} --format=%s`,
95554
95659
  { cwd: rootDir, encoding: "utf-8" }
95555
95660
  );
95556
95661
  const s3 = subj.trim();
@@ -95565,8 +95670,8 @@ async function computeActualMergeCommitContext(params) {
95565
95670
  }
95566
95671
  async function listBranchCommits(rootDir, target, branch) {
95567
95672
  try {
95568
- const { stdout } = await execAsync25(
95569
- `git log --reverse --format=%H ${quoteArg2(target)}..${quoteArg2(branch)}`,
95673
+ const { stdout } = await execAsync26(
95674
+ `git log --reverse --format=%H ${quoteArg3(target)}..${quoteArg3(branch)}`,
95570
95675
  { cwd: rootDir, encoding: "utf-8" }
95571
95676
  );
95572
95677
  return stdout.trim().split("\n").filter(Boolean);
@@ -95728,10 +95833,10 @@ async function resolveRebaseConflictSet(store, rootDir, taskId, settings, option
95728
95833
  }
95729
95834
  }
95730
95835
  async function pullWithRebaseAndResolveConflicts(store, rootDir, taskId, settings, remote, branch, options) {
95731
- const pullCommand = `git pull --rebase ${quoteArg2(remote)} ${quoteArg2(branch)}`;
95836
+ const pullCommand = `git pull --rebase ${quoteArg3(remote)} ${quoteArg3(branch)}`;
95732
95837
  try {
95733
95838
  throwIfAborted(options?.signal, taskId);
95734
- await execAsync25(pullCommand, {
95839
+ await execAsync26(pullCommand, {
95735
95840
  cwd: rootDir,
95736
95841
  timeout: PULL_REBASE_TIMEOUT_MS,
95737
95842
  maxBuffer: VERIFICATION_COMMAND_MAX_BUFFER,
@@ -95757,7 +95862,7 @@ async function pullWithRebaseAndResolveConflicts(store, rootDir, taskId, setting
95757
95862
  }
95758
95863
  try {
95759
95864
  throwIfAborted(options?.signal, taskId);
95760
- await execAsync25("GIT_EDITOR=true git rebase --continue", {
95865
+ await execAsync26("GIT_EDITOR=true git rebase --continue", {
95761
95866
  cwd: rootDir,
95762
95867
  timeout: PULL_REBASE_TIMEOUT_MS,
95763
95868
  maxBuffer: VERIFICATION_COMMAND_MAX_BUFFER,
@@ -95784,7 +95889,7 @@ async function pullWithRebaseAndResolveConflicts(store, rootDir, taskId, setting
95784
95889
  } catch (resolutionError) {
95785
95890
  if (isRebaseInProgress(rootDir)) {
95786
95891
  try {
95787
- await execAsync25("git rebase --abort", {
95892
+ await execAsync26("git rebase --abort", {
95788
95893
  cwd: rootDir,
95789
95894
  timeout: PUSH_TIMEOUT_MS,
95790
95895
  maxBuffer: VERIFICATION_COMMAND_MAX_BUFFER,
@@ -95822,10 +95927,10 @@ async function pushToRemoteAfterMerge(store, rootDir, taskId, settings, options)
95822
95927
  mergerLog.error(`${taskId}: pull --rebase before push failed: ${message}`);
95823
95928
  return { pushed: false, error: message };
95824
95929
  }
95825
- const pushCommand = `git push ${quoteArg2(remote)} ${quoteArg2(branch)}`;
95930
+ const pushCommand = `git push ${quoteArg3(remote)} ${quoteArg3(branch)}`;
95826
95931
  try {
95827
95932
  throwIfAborted(options?.signal, taskId);
95828
- await execAsync25(pushCommand, {
95933
+ await execAsync26(pushCommand, {
95829
95934
  cwd: rootDir,
95830
95935
  timeout: PUSH_TIMEOUT_MS,
95831
95936
  maxBuffer: VERIFICATION_COMMAND_MAX_BUFFER,
@@ -95844,7 +95949,7 @@ async function pushToRemoteAfterMerge(store, rootDir, taskId, settings, options)
95844
95949
  throwIfAborted(options?.signal, taskId);
95845
95950
  await pullWithRebaseAndResolveConflicts(store, rootDir, taskId, settings, remote, branch, options);
95846
95951
  throwIfAborted(options?.signal, taskId);
95847
- await execAsync25(pushCommand, {
95952
+ await execAsync26(pushCommand, {
95848
95953
  cwd: rootDir,
95849
95954
  timeout: PUSH_TIMEOUT_MS,
95850
95955
  maxBuffer: VERIFICATION_COMMAND_MAX_BUFFER,
@@ -95864,7 +95969,7 @@ async function createPostMergeWorktree(rootDir, taskId, settings) {
95864
95969
  const randomSuffix = Math.random().toString(36).slice(2, 10);
95865
95970
  const postMergeWorktree = resolveTaskWorktreePath(rootDir, settings, `post-merge-${taskId}-${randomSuffix}`);
95866
95971
  try {
95867
- await execAsync25(`git worktree add ${quoteArg2(postMergeWorktree)} HEAD`, { cwd: rootDir });
95972
+ await execAsync26(`git worktree add ${quoteArg3(postMergeWorktree)} HEAD`, { cwd: rootDir });
95868
95973
  return postMergeWorktree;
95869
95974
  } catch (err) {
95870
95975
  mergerLog.warn(`${taskId}: failed to create post-merge worktree: ${getCommandErrorMessage(err)}`);
@@ -95888,8 +95993,8 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
95888
95993
  const { task, taskId, store, audit, log: log25, projectRootDir, mergeTargetBranch } = input;
95889
95994
  const branch = task.branch || canonicalFusionBranchName(taskId);
95890
95995
  try {
95891
- await execAsync25(
95892
- `git show-ref --verify --quiet ${quoteArg2(`refs/heads/${branch}`)}`,
95996
+ await execAsync26(
95997
+ `git show-ref --verify --quiet ${quoteArg3(`refs/heads/${branch}`)}`,
95893
95998
  { cwd: projectRootDir, timeout: 3e4 }
95894
95999
  );
95895
96000
  } catch {
@@ -95897,8 +96002,8 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
95897
96002
  }
95898
96003
  let aheadCount;
95899
96004
  try {
95900
- const { stdout } = await execAsync25(
95901
- `git rev-list --count ${quoteArg2(`${mergeTargetBranch}..${branch}`)}`,
96005
+ const { stdout } = await execAsync26(
96006
+ `git rev-list --count ${quoteArg3(`${mergeTargetBranch}..${branch}`)}`,
95902
96007
  { cwd: projectRootDir, encoding: "utf-8", timeout: 3e4 }
95903
96008
  );
95904
96009
  const parsed = Number.parseInt(stdout.trim(), 10);
@@ -95909,8 +96014,8 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
95909
96014
  }
95910
96015
  let mergeBase;
95911
96016
  try {
95912
- const { stdout } = await execAsync25(
95913
- `git merge-base ${quoteArg2(mergeTargetBranch)} ${quoteArg2(branch)}`,
96017
+ const { stdout } = await execAsync26(
96018
+ `git merge-base ${quoteArg3(mergeTargetBranch)} ${quoteArg3(branch)}`,
95914
96019
  { cwd: projectRootDir, encoding: "utf-8", timeout: 3e4 }
95915
96020
  );
95916
96021
  mergeBase = stdout.trim();
@@ -95919,8 +96024,8 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
95919
96024
  return null;
95920
96025
  }
95921
96026
  try {
95922
- await execAsync25(
95923
- `git diff --quiet ${quoteArg2(`${mergeBase}..${branch}`)}`,
96027
+ await execAsync26(
96028
+ `git diff --quiet ${quoteArg3(`${mergeBase}..${branch}`)}`,
95924
96029
  { cwd: projectRootDir, timeout: 3e4 }
95925
96030
  );
95926
96031
  } catch {
@@ -95975,7 +96080,7 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
95975
96080
  let dirty = false;
95976
96081
  let dirtyDiagnostic;
95977
96082
  try {
95978
- const { stdout } = await execAsync25(
96083
+ const { stdout } = await execAsync26(
95979
96084
  `git status --porcelain --untracked-files=no`,
95980
96085
  { cwd: stranded, encoding: "utf-8", timeout: 15e3 }
95981
96086
  );
@@ -95996,8 +96101,8 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
95996
96101
  );
95997
96102
  } else {
95998
96103
  try {
95999
- await execAsync25(
96000
- `git worktree remove --force ${quoteArg2(stranded)}`,
96104
+ await execAsync26(
96105
+ `git worktree remove --force ${quoteArg3(stranded)}`,
96001
96106
  { cwd: projectRootDir, timeout: 3e4 }
96002
96107
  );
96003
96108
  worktreeRemoved = true;
@@ -96011,8 +96116,8 @@ async function tryEarlyEmptyOwnDiffFinalize(input) {
96011
96116
  }
96012
96117
  if (ownedBranchOnEntry) {
96013
96118
  try {
96014
- await execAsync25(
96015
- `git branch -D ${quoteArg2(ownedBranchOnEntry)}`,
96119
+ await execAsync26(
96120
+ `git branch -D ${quoteArg3(ownedBranchOnEntry)}`,
96016
96121
  { cwd: projectRootDir, timeout: 3e4 }
96017
96122
  );
96018
96123
  branchDeleted = true;
@@ -96166,7 +96271,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96166
96271
  const directReuseEligible = !(options.pool && settings.recycleWorktrees);
96167
96272
  if (directReuseEligible) {
96168
96273
  try {
96169
- const { stdout: porcelain } = await execAsync25(
96274
+ const { stdout: porcelain } = await execAsync26(
96170
96275
  `git worktree list --porcelain`,
96171
96276
  { cwd: projectRootDir, encoding: "utf-8", timeout: 3e4 }
96172
96277
  );
@@ -96212,7 +96317,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96212
96317
  }
96213
96318
  if (prunedAnyStaleRegistration) {
96214
96319
  try {
96215
- await execAsync25(`git worktree prune`, { cwd: projectRootDir, encoding: "utf-8", timeout: 3e4 });
96320
+ await execAsync26(`git worktree prune`, { cwd: projectRootDir, encoding: "utf-8", timeout: 3e4 });
96216
96321
  await emitReuseHandoffAuditEvent(
96217
96322
  "merge:reuse-fallback-pruned-stale-registration",
96218
96323
  {
@@ -96302,7 +96407,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96302
96407
  runContext: engineRunContext,
96303
96408
  runInitCommand: false,
96304
96409
  createWorktree: async (branch2, path6, _taskId, _startPoint, _allowSiblingBranchRename) => {
96305
- await execAsync25(`git worktree add -f ${quoteArg2(path6)} ${quoteArg2(branch2)}`, {
96410
+ await execAsync26(`git worktree add -f ${quoteArg3(path6)} ${quoteArg3(branch2)}`, {
96306
96411
  cwd: projectRootDir,
96307
96412
  encoding: "utf-8",
96308
96413
  timeout: 12e4,
@@ -96513,28 +96618,28 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96513
96618
  };
96514
96619
  const resolveAheadCount = async () => {
96515
96620
  try {
96516
- await execAsync25(`git rev-parse --verify ${quoteArg2(branch)}`, { cwd: rootDir, timeout: 3e4 });
96621
+ await execAsync26(`git rev-parse --verify ${quoteArg3(branch)}`, { cwd: rootDir, timeout: 3e4 });
96517
96622
  } catch {
96518
96623
  return null;
96519
96624
  }
96520
96625
  let baseRef = requestedBaseRef;
96521
96626
  try {
96522
- await execAsync25(`git rev-parse --verify ${quoteArg2(baseRef)}`, { cwd: rootDir, timeout: 3e4 });
96627
+ await execAsync26(`git rev-parse --verify ${quoteArg3(baseRef)}`, { cwd: rootDir, timeout: 3e4 });
96523
96628
  } catch {
96524
96629
  if (!integrationRemote) {
96525
96630
  return null;
96526
96631
  }
96527
96632
  const remoteRef = `${integrationRemote}/${requestedBaseRef}`;
96528
96633
  try {
96529
- await execAsync25(`git rev-parse --verify ${quoteArg2(remoteRef)}`, { cwd: rootDir, timeout: 3e4 });
96634
+ await execAsync26(`git rev-parse --verify ${quoteArg3(remoteRef)}`, { cwd: rootDir, timeout: 3e4 });
96530
96635
  baseRef = remoteRef;
96531
96636
  } catch {
96532
96637
  return null;
96533
96638
  }
96534
96639
  }
96535
96640
  try {
96536
- const { stdout } = await execAsync25(
96537
- `git rev-list --count ${quoteArg2(baseRef)}..${quoteArg2(branch)}`,
96641
+ const { stdout } = await execAsync26(
96642
+ `git rev-list --count ${quoteArg3(baseRef)}..${quoteArg3(branch)}`,
96538
96643
  { cwd: rootDir, timeout: 3e4 }
96539
96644
  );
96540
96645
  const aheadCount = Number.parseInt(stdout.trim(), 10);
@@ -96550,13 +96655,21 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96550
96655
  if (aheadInfo?.aheadCount === 0) {
96551
96656
  const classification = await classifyOwnedLandedEvidence(rootDir, task, { mergeTargetBranch: aheadInfo.baseRef });
96552
96657
  if (classification.kind === "owned-commit") {
96658
+ const mergeCommitMessage = await regenerateBareMergeSubject({
96659
+ subject: classification.commit.subject,
96660
+ commitSha: classification.commit.sha,
96661
+ branch,
96662
+ taskId,
96663
+ rootDir,
96664
+ settings
96665
+ });
96553
96666
  const mergeDetails = {
96554
96667
  ...task.mergeDetails || {},
96555
96668
  commitSha: classification.commit.sha,
96556
96669
  filesChanged: classification.commit.filesChanged,
96557
96670
  insertions: classification.commit.insertions,
96558
96671
  deletions: classification.commit.deletions,
96559
- mergeCommitMessage: classification.commit.subject,
96672
+ mergeCommitMessage,
96560
96673
  mergeConfirmed: true,
96561
96674
  mergedAt: (/* @__PURE__ */ new Date()).toISOString(),
96562
96675
  prNumber: task.prInfo?.number,
@@ -96755,13 +96868,21 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96755
96868
  }
96756
96869
  if (classification.kind === "owned-commit") {
96757
96870
  const mergedAt = (/* @__PURE__ */ new Date()).toISOString();
96871
+ const mergeCommitMessage = await regenerateBareMergeSubject({
96872
+ subject: classification.commit.subject,
96873
+ commitSha: classification.commit.sha,
96874
+ branch,
96875
+ taskId,
96876
+ rootDir,
96877
+ settings
96878
+ });
96758
96879
  await store.updateTask(taskId, {
96759
96880
  mergeDetails: {
96760
96881
  commitSha: classification.commit.sha,
96761
96882
  filesChanged: classification.commit.filesChanged,
96762
96883
  insertions: classification.commit.insertions,
96763
96884
  deletions: classification.commit.deletions,
96764
- mergeCommitMessage: classification.commit.subject,
96885
+ mergeCommitMessage,
96765
96886
  mergedAt,
96766
96887
  mergeConfirmed: true,
96767
96888
  prNumber: task.prInfo?.number,
@@ -96775,7 +96896,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96775
96896
  result.filesChanged = classification.commit.filesChanged;
96776
96897
  result.insertions = classification.commit.insertions;
96777
96898
  result.deletions = classification.commit.deletions;
96778
- result.mergeCommitMessage = classification.commit.subject;
96899
+ result.mergeCommitMessage = mergeCommitMessage;
96779
96900
  result.mergedAt = mergedAt;
96780
96901
  result.mergeTargetBranch = mergeTarget.branch;
96781
96902
  result.mergeTargetSource = mergeTarget.source;
@@ -96822,13 +96943,13 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96822
96943
  mergerLog.log(
96823
96944
  `${taskId}: reusing task worktree \u2014 detaching HEAD at '${mergeTarget.branch}' before merge (${mergeTarget.source})`
96824
96945
  );
96825
- await execAsync25(`git checkout --detach "${mergeTarget.branch}"`, {
96946
+ await execAsync26(`git checkout --detach "${mergeTarget.branch}"`, {
96826
96947
  cwd: rootDir
96827
96948
  });
96828
96949
  await audit.git({ type: "branch:checkout", target: mergeTarget.branch });
96829
96950
  } else if (currentBranch2 !== mergeTarget.branch) {
96830
96951
  mergerLog.log(`${taskId}: rootDir on '${currentBranch2}', checking out '${mergeTarget.branch}' before merge (${mergeTarget.source})`);
96831
- await execAsync25(`git checkout "${mergeTarget.branch}"`, {
96952
+ await execAsync26(`git checkout "${mergeTarget.branch}"`, {
96832
96953
  cwd: rootDir
96833
96954
  });
96834
96955
  await audit.git({ type: "branch:checkout", target: mergeTarget.branch });
@@ -96843,7 +96964,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96843
96964
  try {
96844
96965
  throwIfAborted(options.signal, taskId);
96845
96966
  const refName = `refs/heads/${mergeTarget.branch}`;
96846
- const { stdout: mainHeadOut } = await execAsync25(
96967
+ const { stdout: mainHeadOut } = await execAsync26(
96847
96968
  `git rev-parse --verify ${refName}`,
96848
96969
  { cwd: rootDir, encoding: "utf-8" }
96849
96970
  );
@@ -96938,7 +97059,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96938
97059
  async function runLocalBaseRebase(label) {
96939
97060
  if (!worktreePath) return;
96940
97061
  try {
96941
- const { stdout: localHeadOut } = await execAsync25("git rev-parse HEAD", {
97062
+ const { stdout: localHeadOut } = await execAsync26("git rev-parse HEAD", {
96942
97063
  cwd: rootDir,
96943
97064
  encoding: "utf-8"
96944
97065
  });
@@ -96946,7 +97067,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96946
97067
  if (!localHead) return;
96947
97068
  let alreadyContains = false;
96948
97069
  try {
96949
- await execAsync25(`git merge-base --is-ancestor "${localHead}" HEAD`, { cwd: worktreePath });
97070
+ await execAsync26(`git merge-base --is-ancestor "${localHead}" HEAD`, { cwd: worktreePath });
96950
97071
  alreadyContains = true;
96951
97072
  } catch {
96952
97073
  }
@@ -96955,7 +97076,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96955
97076
  return;
96956
97077
  }
96957
97078
  throwIfAborted(options.signal, taskId);
96958
- await execAsync25(`git rebase "${localHead}"`, { cwd: worktreePath });
97079
+ await execAsync26(`git rebase "${localHead}"`, { cwd: worktreePath });
96959
97080
  rebaseHappened = true;
96960
97081
  mergerLog.log(`${taskId}: rebased ${branch} onto local HEAD ${localHead.slice(0, 8)}${label ? ` (${label})` : ""}`);
96961
97082
  await store.appendAgentLog(
@@ -96970,7 +97091,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96970
97091
  const lmsg = localRebaseErr instanceof Error ? localRebaseErr.message : String(localRebaseErr);
96971
97092
  mergerLog.warn(`${taskId}: pre-merge rebase onto local HEAD failed (${lmsg}) \u2014 aborting and falling through`);
96972
97093
  try {
96973
- await execAsync25("git rebase --abort", { cwd: worktreePath });
97094
+ await execAsync26("git rebase --abort", { cwd: worktreePath });
96974
97095
  } catch (abortError) {
96975
97096
  mergerLog.warn(`${taskId}: failed to abort local-HEAD rebase: ${getCommandErrorMessage(abortError)}`);
96976
97097
  }
@@ -96988,11 +97109,11 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
96988
97109
  } else {
96989
97110
  throwIfAborted(options.signal, taskId);
96990
97111
  mergerLog.log(`${taskId}: fetching ${integrationRemote} before merge`);
96991
- await execAsync25(`git fetch ${quoteArg2(integrationRemote)}`, { cwd: rootDir });
97112
+ await execAsync26(`git fetch ${quoteArg3(integrationRemote)}`, { cwd: rootDir });
96992
97113
  try {
96993
97114
  const remoteRef = `${integrationRemote}/${mergeTarget.branch}`;
96994
97115
  throwIfAborted(options.signal, taskId);
96995
- await execAsync25(`git rebase ${quoteArg2(remoteRef)}`, { cwd: worktreePath });
97116
+ await execAsync26(`git rebase ${quoteArg3(remoteRef)}`, { cwd: worktreePath });
96996
97117
  rebaseHappened = true;
96997
97118
  mergerLog.log(`${taskId}: rebased ${branch} onto ${remoteRef}`);
96998
97119
  await store.appendAgentLog(
@@ -97008,7 +97129,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97008
97129
  mergerLog.warn(`${taskId}: pre-merge rebase failed (${msg}) \u2014 aborting rebase and falling through`);
97009
97130
  if (worktreePath) {
97010
97131
  try {
97011
- await execAsync25("git rebase --abort", { cwd: worktreePath });
97132
+ await execAsync26("git rebase --abort", { cwd: worktreePath });
97012
97133
  } catch (abortError) {
97013
97134
  mergerLog.warn(`${taskId}: failed to abort pre-merge rebase: ${getCommandErrorMessage(abortError)}`);
97014
97135
  }
@@ -97033,7 +97154,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97033
97154
  if (preferMainRebaseFailureMessage && worktreePath) {
97034
97155
  let rebaseTarget = "";
97035
97156
  try {
97036
- const { stdout } = await execAsync25("git rev-parse HEAD", {
97157
+ const { stdout } = await execAsync26("git rev-parse HEAD", {
97037
97158
  cwd: rootDir,
97038
97159
  encoding: "utf-8"
97039
97160
  });
@@ -97044,7 +97165,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97044
97165
  if (rebaseTarget && task.executionStartBranch && task.executionStartBranch !== mergeTarget.branch) {
97045
97166
  let depTip;
97046
97167
  try {
97047
- const { stdout } = await execAsync25(
97168
+ const { stdout } = await execAsync26(
97048
97169
  `git rev-parse --verify "${task.executionStartBranch}^{commit}"`,
97049
97170
  { cwd: rootDir, encoding: "utf-8" }
97050
97171
  );
@@ -97054,7 +97175,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97054
97175
  }
97055
97176
  if (!depTip && task.baseCommitSha) {
97056
97177
  try {
97057
- const { stdout } = await execAsync25(
97178
+ const { stdout } = await execAsync26(
97058
97179
  `git rev-parse --verify "${task.baseCommitSha}^{commit}"`,
97059
97180
  { cwd: rootDir, encoding: "utf-8" }
97060
97181
  );
@@ -97066,10 +97187,10 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97066
97187
  if (depTip && depTip !== rebaseTarget) {
97067
97188
  try {
97068
97189
  throwIfAborted(options.signal, taskId);
97069
- await execAsync25("git rebase --abort", { cwd: worktreePath }).catch(
97190
+ await execAsync26("git rebase --abort", { cwd: worktreePath }).catch(
97070
97191
  () => void 0
97071
97192
  );
97072
- await execAsync25(
97193
+ await execAsync26(
97073
97194
  `git rebase --onto "${rebaseTarget}" "${depTip}" "${branch}"`,
97074
97195
  { cwd: worktreePath }
97075
97196
  );
@@ -97087,7 +97208,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97087
97208
  mergerLog.warn(
97088
97209
  `${taskId}: Layer 1 (dep-drop) recovery failed: ${layer1Err instanceof Error ? layer1Err.message : String(layer1Err)}`
97089
97210
  );
97090
- await execAsync25("git rebase --abort", { cwd: worktreePath }).catch(
97211
+ await execAsync26("git rebase --abort", { cwd: worktreePath }).catch(
97091
97212
  () => void 0
97092
97213
  );
97093
97214
  }
@@ -97117,7 +97238,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97117
97238
  } else if (dropped > 0) {
97118
97239
  let originalBranchSha = "";
97119
97240
  try {
97120
- const { stdout } = await execAsync25(
97241
+ const { stdout } = await execAsync26(
97121
97242
  `git rev-parse --verify "${branch}^{commit}"`,
97122
97243
  { cwd: worktreePath, encoding: "utf-8" }
97123
97244
  );
@@ -97127,33 +97248,33 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97127
97248
  }
97128
97249
  const restoreOriginalBranch = async () => {
97129
97250
  if (!originalBranchSha) return;
97130
- await execAsync25(`git reset --hard "${originalBranchSha}"`, {
97251
+ await execAsync26(`git reset --hard "${originalBranchSha}"`, {
97131
97252
  cwd: worktreePath
97132
97253
  }).catch(() => void 0);
97133
- await execAsync25(`git checkout -f "${branch}"`, { cwd: worktreePath }).catch(
97254
+ await execAsync26(`git checkout -f "${branch}"`, { cwd: worktreePath }).catch(
97134
97255
  () => void 0
97135
97256
  );
97136
- await execAsync25(`git reset --hard "${originalBranchSha}"`, {
97257
+ await execAsync26(`git reset --hard "${originalBranchSha}"`, {
97137
97258
  cwd: worktreePath
97138
97259
  }).catch(() => void 0);
97139
97260
  };
97140
97261
  try {
97141
- await execAsync25("git rebase --abort", { cwd: worktreePath }).catch(
97262
+ await execAsync26("git rebase --abort", { cwd: worktreePath }).catch(
97142
97263
  () => void 0
97143
97264
  );
97144
- await execAsync25(`git checkout "${branch}"`, { cwd: worktreePath });
97145
- await execAsync25(`git reset --hard "${rebaseTarget}"`, {
97265
+ await execAsync26(`git checkout "${branch}"`, { cwd: worktreePath });
97266
+ await execAsync26(`git reset --hard "${rebaseTarget}"`, {
97146
97267
  cwd: worktreePath
97147
97268
  });
97148
97269
  for (const sha of surviving) {
97149
97270
  throwIfAborted(options.signal, taskId);
97150
97271
  try {
97151
- await execAsync25(`git cherry-pick --allow-empty "${sha}"`, {
97272
+ await execAsync26(`git cherry-pick --allow-empty "${sha}"`, {
97152
97273
  cwd: worktreePath
97153
97274
  });
97154
97275
  } catch (pickErr) {
97155
97276
  rethrowIfMergeAborted(pickErr);
97156
- await execAsync25("git cherry-pick --abort", { cwd: worktreePath }).catch(
97277
+ await execAsync26("git cherry-pick --abort", { cwd: worktreePath }).catch(
97157
97278
  () => void 0
97158
97279
  );
97159
97280
  await restoreOriginalBranch();
@@ -97247,7 +97368,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97247
97368
  let commitLog = "";
97248
97369
  let diffStat = "";
97249
97370
  try {
97250
- const { stdout: logOutput } = await execAsync25(`git log ${contextDiffRange} --format="- %s"`, {
97371
+ const { stdout: logOutput } = await execAsync26(`git log ${contextDiffRange} --format="- %s"`, {
97251
97372
  cwd: rootDir,
97252
97373
  encoding: "utf-8"
97253
97374
  });
@@ -97256,7 +97377,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97256
97377
  commitLog = "(unable to read commit log)";
97257
97378
  }
97258
97379
  try {
97259
- const { stdout: diffOutput } = await execAsync25(`git diff ${contextDiffRange} --stat`, {
97380
+ const { stdout: diffOutput } = await execAsync26(`git diff ${contextDiffRange} --stat`, {
97260
97381
  cwd: rootDir,
97261
97382
  encoding: "utf-8"
97262
97383
  });
@@ -97348,7 +97469,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97348
97469
  });
97349
97470
  let preAttemptHeadSha = "";
97350
97471
  try {
97351
- const { stdout } = await execAsync25("git rev-parse HEAD", {
97472
+ const { stdout } = await execAsync26("git rev-parse HEAD", {
97352
97473
  cwd: rootDir,
97353
97474
  encoding: "utf-8"
97354
97475
  });
@@ -97509,7 +97630,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97509
97630
  }
97510
97631
  if (fixSuccess) {
97511
97632
  const authorArg = getCommitAuthorArg(settings);
97512
- const { stdout: finalizeHeadOut } = await execAsync25("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97633
+ const { stdout: finalizeHeadOut } = await execAsync26("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97513
97634
  mergerLog.log(`${taskId}: in-merge fix entering with preAttemptHeadSha=${preAttemptHeadSha}, currentHead=${finalizeHeadOut.trim()}`);
97514
97635
  const finalized = await commitOrAmendMergeWithFixes(
97515
97636
  rootDir,
@@ -97548,8 +97669,8 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97548
97669
  mergeWasEmpty = true;
97549
97670
  return true;
97550
97671
  }
97551
- const { stdout: currentHeadOut } = await execAsync25("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97552
- const { stdout: branchTipOut } = await execAsync25(`git rev-parse ${branch}`, { cwd: rootDir, encoding: "utf-8" });
97672
+ const { stdout: currentHeadOut } = await execAsync26("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97673
+ const { stdout: branchTipOut } = await execAsync26(`git rev-parse ${branch}`, { cwd: rootDir, encoding: "utf-8" });
97553
97674
  resetMergeWithWarn(rootDir, taskId, "verification-fix finalize");
97554
97675
  const classification = finalized.reason === "fix-produced-no-content" ? "fix produced no content" : finalized.reason === "branch-ref-ahead-reset" ? "branch-ref ahead of integration target (reset for retry)" : "unknown phantom";
97555
97676
  const originalErrorSuffix = finalized.originalError ? ` originalError="${finalized.originalError}";` : "";
@@ -97640,7 +97761,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97640
97761
  }
97641
97762
  if (fixSuccess) {
97642
97763
  const authorArg = getCommitAuthorArg(settings);
97643
- const { stdout: finalizeHeadOut } = await execAsync25("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97764
+ const { stdout: finalizeHeadOut } = await execAsync26("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97644
97765
  mergerLog.log(`${taskId}: in-merge fix entering with preAttemptHeadSha=${preAttemptHeadSha}, currentHead=${finalizeHeadOut.trim()}`);
97645
97766
  const finalized = await commitOrAmendMergeWithFixes(
97646
97767
  rootDir,
@@ -97679,8 +97800,8 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97679
97800
  mergeWasEmpty = true;
97680
97801
  return true;
97681
97802
  }
97682
- const { stdout: currentHeadOut } = await execAsync25("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97683
- const { stdout: branchTipOut } = await execAsync25(`git rev-parse ${branch}`, { cwd: rootDir, encoding: "utf-8" });
97803
+ const { stdout: currentHeadOut } = await execAsync26("git rev-parse HEAD", { cwd: rootDir, encoding: "utf-8" });
97804
+ const { stdout: branchTipOut } = await execAsync26(`git rev-parse ${branch}`, { cwd: rootDir, encoding: "utf-8" });
97684
97805
  resetMergeWithWarn(rootDir, taskId, "build-verification fix finalize");
97685
97806
  const classification = finalized.reason === "fix-produced-no-content" ? "fix produced no content" : finalized.reason === "branch-ref-ahead-reset" ? "branch-ref ahead of integration target (reset for retry)" : "unknown phantom";
97686
97807
  const originalErrorSuffix = finalized.originalError ? ` originalError="${finalized.originalError}";` : "";
@@ -97800,7 +97921,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97800
97921
  let landedFiles;
97801
97922
  try {
97802
97923
  if (!rebaseMergeBaseSha) {
97803
- const { stdout: statsOutput } = await execAsync25("git show --shortstat --format= HEAD", {
97924
+ const { stdout: statsOutput } = await execAsync26("git show --shortstat --format= HEAD", {
97804
97925
  cwd: rootDir,
97805
97926
  encoding: "utf-8"
97806
97927
  });
@@ -97836,7 +97957,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97836
97957
  const verificationCandidateRefs = [auditSha, task.branch].filter((ref) => Boolean(ref));
97837
97958
  for (const candidateRef of verificationCandidateRefs) {
97838
97959
  try {
97839
- const { stdout: treeOut } = await execAsync25(`git rev-parse ${quoteArg2(candidateRef)}^{tree}`, {
97960
+ const { stdout: treeOut } = await execAsync26(`git rev-parse ${quoteArg3(candidateRef)}^{tree}`, {
97840
97961
  cwd: rootDir,
97841
97962
  encoding: "utf-8"
97842
97963
  });
@@ -97926,7 +98047,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
97926
98047
  mergerLog.log(`${taskId}: rebase-strategy landed-files capture: zero own commits \u2014 verified-short-circuit`);
97927
98048
  }
97928
98049
  } else {
97929
- const { stdout: landedFilesOutput } = await execAsync25(`git show --name-only --format= ${quoteArg2(recordedSha)}`, {
98050
+ const { stdout: landedFilesOutput } = await execAsync26(`git show --name-only --format= ${quoteArg3(recordedSha)}`, {
97930
98051
  cwd: rootDir,
97931
98052
  encoding: "utf-8",
97932
98053
  maxBuffer: 2 * 1024 * 1024
@@ -98041,7 +98162,7 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
98041
98162
  }).trim();
98042
98163
  if (worktreeHeadSha) {
98043
98164
  const integrationBranch2 = mergeTarget.branch || await resolveIntegrationBranch(projectRootDir, settings);
98044
- const expectedCurrentSha = execSyncText(`git rev-parse --verify ${quoteArg2(`refs/heads/${integrationBranch2}`)}`, {
98165
+ const expectedCurrentSha = execSyncText(`git rev-parse --verify ${quoteArg3(`refs/heads/${integrationBranch2}`)}`, {
98045
98166
  cwd: rootDir,
98046
98167
  stdio: "pipe",
98047
98168
  encoding: "utf-8"
@@ -98100,12 +98221,12 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
98100
98221
  }
98101
98222
  }
98102
98223
  try {
98103
- await execAsync25(`git branch -d "${branch}"`, { cwd: rootDir });
98224
+ await execAsync26(`git branch -d "${branch}"`, { cwd: rootDir });
98104
98225
  result.branchDeleted = true;
98105
98226
  await audit.git({ type: "branch:delete", target: branch });
98106
98227
  } catch {
98107
98228
  try {
98108
- await execAsync25(`git branch -D "${branch}"`, { cwd: rootDir });
98229
+ await execAsync26(`git branch -D "${branch}"`, { cwd: rootDir });
98109
98230
  result.branchDeleted = true;
98110
98231
  await audit.git({ type: "branch:delete", target: branch, metadata: { force: true } });
98111
98232
  } catch {
@@ -98160,9 +98281,9 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
98160
98281
  result.worktreeRemoved = false;
98161
98282
  } else {
98162
98283
  try {
98163
- const onBranch = await execAsync25("git symbolic-ref --quiet HEAD", { cwd: worktreePath, timeout: 5e3, encoding: "utf-8" }).then(() => true).catch(() => false);
98284
+ const onBranch = await execAsync26("git symbolic-ref --quiet HEAD", { cwd: worktreePath, timeout: 5e3, encoding: "utf-8" }).then(() => true).catch(() => false);
98164
98285
  if (onBranch) {
98165
- await execAsync25("git checkout --detach HEAD", { cwd: worktreePath, timeout: 1e4, encoding: "utf-8" });
98286
+ await execAsync26("git checkout --detach HEAD", { cwd: worktreePath, timeout: 1e4, encoding: "utf-8" });
98166
98287
  }
98167
98288
  } catch (err) {
98168
98289
  const msg = err instanceof Error ? err.message : String(err);
@@ -98243,8 +98364,8 @@ async function aiMergeTask(store, rootDir, taskId, options = {}) {
98243
98364
  deletions: existingDetails.deletions
98244
98365
  };
98245
98366
  try {
98246
- const { stdout: postPushStatsOutput } = await execAsync25(
98247
- `git show --shortstat --format= ${quoteArg2(postPushSha)}`,
98367
+ const { stdout: postPushStatsOutput } = await execAsync26(
98368
+ `git show --shortstat --format= ${quoteArg3(postPushSha)}`,
98248
98369
  { cwd: pushRootDir, encoding: "utf-8" }
98249
98370
  );
98250
98371
  const normalized = postPushStatsOutput.trim().replace(/\n/g, " ");
@@ -98361,7 +98482,7 @@ async function tryFastForwardFromOrigin(rootDir, taskId, integrationBranch, inte
98361
98482
  const remote = integrationRemote?.trim();
98362
98483
  if (!currentBranch2 || !remote) return;
98363
98484
  try {
98364
- await execAsync25(`git fetch ${quoteArg2(remote)} ${quoteArg2(currentBranch2)}`, { cwd: rootDir });
98485
+ await execAsync26(`git fetch ${quoteArg3(remote)} ${quoteArg3(currentBranch2)}`, { cwd: rootDir });
98365
98486
  } catch (err) {
98366
98487
  mergerLog.log(`${taskId}: pre-merge fetch failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
98367
98488
  return;
@@ -98370,7 +98491,7 @@ async function tryFastForwardFromOrigin(rootDir, taskId, integrationBranch, inte
98370
98491
  let ahead = 0;
98371
98492
  const remoteRef = `${remote}/${currentBranch2}`;
98372
98493
  try {
98373
- const counts = execSyncText(`git rev-list --left-right --count ${quoteArg2(`${remoteRef}...HEAD`)}`, {
98494
+ const counts = execSyncText(`git rev-list --left-right --count ${quoteArg3(`${remoteRef}...HEAD`)}`, {
98374
98495
  cwd: rootDir,
98375
98496
  encoding: "utf-8",
98376
98497
  stdio: "pipe"
@@ -98387,7 +98508,7 @@ async function tryFastForwardFromOrigin(rootDir, taskId, integrationBranch, inte
98387
98508
  return;
98388
98509
  }
98389
98510
  try {
98390
- await execAsync25(`git merge --ff-only ${quoteArg2(remoteRef)}`, { cwd: rootDir });
98511
+ await execAsync26(`git merge --ff-only ${quoteArg3(remoteRef)}`, { cwd: rootDir });
98391
98512
  mergerLog.log(`${taskId}: fast-forwarded ${currentBranch2} by ${behind} commit(s) from ${remote}`);
98392
98513
  } catch (err) {
98393
98514
  mergerLog.log(`${taskId}: fast-forward failed (continuing): ${err instanceof Error ? err.message : String(err)}`);
@@ -98465,7 +98586,7 @@ async function executeMergeAttempt(params, aiTracker) {
98465
98586
  if (attemptNum === 2 && smartConflictResolution) {
98466
98587
  let mergeError;
98467
98588
  try {
98468
- await execAsync25(`git merge --squash "${branch}"`, {
98589
+ await execAsync26(`git merge --squash "${branch}"`, {
98469
98590
  cwd: rootDir
98470
98591
  });
98471
98592
  throwIfAborted(options.signal, taskId);
@@ -98569,7 +98690,7 @@ async function executeMergeAttempt(params, aiTracker) {
98569
98690
  settings,
98570
98691
  store
98571
98692
  });
98572
- await execAsync25(
98693
+ await execAsync26(
98573
98694
  `git commit ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
98574
98695
  { cwd: rootDir, env: mergerCommitEnv() }
98575
98696
  );
@@ -98618,7 +98739,7 @@ async function executeMergeAttempt(params, aiTracker) {
98618
98739
  }
98619
98740
  }
98620
98741
  } else {
98621
- await execAsync25(`git merge --squash "${branch}"`, {
98742
+ await execAsync26(`git merge --squash "${branch}"`, {
98622
98743
  cwd: rootDir
98623
98744
  });
98624
98745
  throwIfAborted(options.signal, taskId);
@@ -98725,7 +98846,7 @@ async function executeMergeAttempt(params, aiTracker) {
98725
98846
  const authorArg = getCommitAuthorArg(params.settings);
98726
98847
  let integrationTargetSha;
98727
98848
  try {
98728
- const { stdout } = await execAsync25("git rev-parse HEAD~1", {
98849
+ const { stdout } = await execAsync26("git rev-parse HEAD~1", {
98729
98850
  cwd: rootDir,
98730
98851
  encoding: "utf-8"
98731
98852
  });
@@ -98747,7 +98868,7 @@ async function executeMergeAttempt(params, aiTracker) {
98747
98868
  aiSubject
98748
98869
  });
98749
98870
  const trailerArg = buildTaskTrailerArgs(taskId);
98750
- await execAsync25(
98871
+ await execAsync26(
98751
98872
  `git commit --amend ${subjectArg} ${bodyArg}${trailerArg}${authorArg}`,
98752
98873
  { cwd: rootDir, env: mergerCommitEnv() }
98753
98874
  );
@@ -98785,7 +98906,7 @@ async function attemptWithSideStrategy(params, side = "theirs", aiTracker) {
98785
98906
  mergerLog.log(`${taskId}: attempting merge with -X ${side} strategy`);
98786
98907
  try {
98787
98908
  throwIfAborted(params.options.signal, taskId);
98788
- await execAsync25(`git merge -X ${side} --squash "${branch}"`, {
98909
+ await execAsync26(`git merge -X ${side} --squash "${branch}"`, {
98789
98910
  cwd: rootDir
98790
98911
  });
98791
98912
  const conflictedOutput = execSyncText("git diff --name-only --diff-filter=U", {
@@ -98812,7 +98933,7 @@ async function attemptWithMixedSideStrategy(params, strategy, aiTracker) {
98812
98933
  );
98813
98934
  try {
98814
98935
  throwIfAborted(params.options.signal, taskId);
98815
- await execAsync25(`git merge -X ${strategy.defaultSide} --squash "${branch}"`, {
98936
+ await execAsync26(`git merge -X ${strategy.defaultSide} --squash "${branch}"`, {
98816
98937
  cwd: rootDir
98817
98938
  });
98818
98939
  const conflictedOutput = execSyncText("git diff --name-only --diff-filter=U", {
@@ -98898,7 +99019,7 @@ async function finalizeSideStrategyAttempt(params, side, aiTracker) {
98898
99019
  settings,
98899
99020
  store
98900
99021
  });
98901
- await execAsync25(
99022
+ await execAsync26(
98902
99023
  `git commit ${subjectArg} ${bodyArg}${issueRefBodyArg}${trailerArg}${authorArg}`,
98903
99024
  { cwd: rootDir, env: mergerCommitEnv() }
98904
99025
  );
@@ -99169,7 +99290,7 @@ async function runAiAgentForCommit(params) {
99169
99290
  settings,
99170
99291
  store
99171
99292
  });
99172
- await execAsync25(
99293
+ await execAsync26(
99173
99294
  `git commit ${subjectArg} ${bodyArg}${issueRefBodyArg}${trailerArg}${authorArg2}`,
99174
99295
  { cwd: rootDir, env: mergerCommitEnv() }
99175
99296
  );
@@ -99568,7 +99689,7 @@ async function completeTask(store, taskId, result) {
99568
99689
  result.task = task;
99569
99690
  store.emit("task:merged", result);
99570
99691
  }
99571
- var execAsync25, execFileAsync7, LOCKFILE_PATTERNS, GENERATED_PATTERNS, DEPENDENCY_SYNC_TRIGGER_PATTERNS, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS, PULL_REBASE_TIMEOUT_MS, PUSH_TIMEOUT_MS, MERGE_COMMIT_LOG_MAX_CHARS, MERGE_DIFF_STAT_MAX_CHARS, summarizeVerificationOutputLocal, INSTALL_MARKER_RELPATH, LOCKFILE_CANDIDATES, VerificationError, MergeAbortedError, OutOfScopeVerificationError, SquashAuditError, VERIFICATION_EXTRA_ENV, AUTOSTASH_LABEL_PREFIX, AUTOSTASH_TIMESTAMP_RE, ACTIVE_MERGER_STATUS_FILENAME, __test__, AutostashCreationFailedError, NUL, FileScopeViolationError, FUSION_TASK_ID_TRAILER_KEY2, mergerTestHooks;
99692
+ var execAsync26, execFileAsync7, LOCKFILE_PATTERNS, GENERATED_PATTERNS, DEPENDENCY_SYNC_TRIGGER_PATTERNS, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS, PULL_REBASE_TIMEOUT_MS, PUSH_TIMEOUT_MS, MERGE_COMMIT_LOG_MAX_CHARS, MERGE_DIFF_STAT_MAX_CHARS, summarizeVerificationOutputLocal, INSTALL_MARKER_RELPATH, LOCKFILE_CANDIDATES, VerificationError, MergeAbortedError, OutOfScopeVerificationError, SquashAuditError, VERIFICATION_EXTRA_ENV, AUTOSTASH_LABEL_PREFIX, AUTOSTASH_TIMESTAMP_RE, ACTIVE_MERGER_STATUS_FILENAME, __test__, AutostashCreationFailedError, NUL, FileScopeViolationError, FUSION_TASK_ID_TRAILER_KEY2, mergerTestHooks;
99572
99693
  var init_merger = __esm({
99573
99694
  "../engine/src/merger.ts"() {
99574
99695
  "use strict";
@@ -99590,6 +99711,8 @@ var init_merger = __esm({
99590
99711
  init_active_session_registry();
99591
99712
  init_agent_logger();
99592
99713
  init_logger2();
99714
+ init_merger_bare_subject();
99715
+ init_merger_bare_subject();
99593
99716
  init_usage_limit_detector();
99594
99717
  init_context_limit_detector();
99595
99718
  init_rate_limit_retry();
@@ -99610,8 +99733,8 @@ var init_merger = __esm({
99610
99733
  init_merger_scope_auto_widen();
99611
99734
  init_merger_diff_volume_gate();
99612
99735
  init_merger_ref_update_advance();
99613
- execAsync25 = promisify33(exec27);
99614
- execFileAsync7 = promisify33(execFile11);
99736
+ execAsync26 = promisify34(exec28);
99737
+ execFileAsync7 = promisify34(execFile11);
99615
99738
  LOCKFILE_PATTERNS = [
99616
99739
  "package-lock.json",
99617
99740
  "pnpm-lock.yaml",
@@ -99740,8 +99863,9 @@ var init_merger = __esm({
99740
99863
  });
99741
99864
 
99742
99865
  // ../engine/src/self-healing.ts
99743
- import { exec as exec28, execSync as execSync5 } from "node:child_process";
99744
- import { promisify as promisify34 } from "node:util";
99866
+ import { exec as exec29, execSync as execSync5 } from "node:child_process";
99867
+ import { promisify as promisify35 } from "node:util";
99868
+ import { setImmediate as setImmediateCb2 } from "node:timers";
99745
99869
  import { existsSync as existsSync38, mkdirSync as mkdirSync9, readdirSync as readdirSync6, readFileSync as readFileSync13, realpathSync as realpathSync5, rmSync as rmSync4, statSync as statSync6, writeFileSync as writeFileSync4 } from "node:fs";
99746
99870
  import { isAbsolute as isAbsolute12, join as join43, relative as relative10, resolve as resolve27 } from "node:path";
99747
99871
  async function archiveAsGhostBug(store, taskId, taskTitle, decision) {
@@ -99772,11 +99896,11 @@ function formatRecoveryTimestamp(date = /* @__PURE__ */ new Date()) {
99772
99896
  }
99773
99897
  async function preserveWorktreeChanges(repoDir, worktreePath, taskId) {
99774
99898
  try {
99775
- const status = (await execAsync26("git status --porcelain", { cwd: worktreePath, encoding: "utf-8" })).stdout.trim();
99899
+ const status = (await execAsync27("git status --porcelain", { cwd: worktreePath, encoding: "utf-8" })).stdout.trim();
99776
99900
  if (!status) {
99777
99901
  return null;
99778
99902
  }
99779
- const diff = (await execAsync26("git diff HEAD --binary", { cwd: worktreePath, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 })).stdout;
99903
+ const diff = (await execAsync27("git diff HEAD --binary", { cwd: worktreePath, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 })).stdout;
99780
99904
  const recoveryDir = join43(repoDir, ".fusion", "recovery");
99781
99905
  mkdirSync9(recoveryDir, { recursive: true });
99782
99906
  const patchPath = join43(recoveryDir, `${taskId.toLowerCase()}-${formatRecoveryTimestamp()}.patch`);
@@ -99901,7 +100025,7 @@ function shellQuote2(value) {
99901
100025
  async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
99902
100026
  const branchName = task.branch || canonicalFusionBranchName(task.id);
99903
100027
  try {
99904
- await execAsync26(`git rev-parse --verify ${shellQuote2(branchName)}`, {
100028
+ await execAsync27(`git rev-parse --verify ${shellQuote2(branchName)}`, {
99905
100029
  cwd: rootDir,
99906
100030
  timeout: 3e4
99907
100031
  });
@@ -99911,14 +100035,14 @@ async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
99911
100035
  const requestedBaseRef = preferredBaseRef || task.mergeDetails?.mergeTargetBranch || await resolveIntegrationBranch(rootDir, void 0);
99912
100036
  let resolvedBaseRef = requestedBaseRef;
99913
100037
  try {
99914
- await execAsync26(`git rev-parse --verify ${shellQuote2(requestedBaseRef)}`, {
100038
+ await execAsync27(`git rev-parse --verify ${shellQuote2(requestedBaseRef)}`, {
99915
100039
  cwd: rootDir,
99916
100040
  timeout: 3e4
99917
100041
  });
99918
100042
  } catch {
99919
100043
  const remoteRef = `origin/${requestedBaseRef}`;
99920
100044
  try {
99921
- await execAsync26(`git rev-parse --verify ${shellQuote2(remoteRef)}`, {
100045
+ await execAsync27(`git rev-parse --verify ${shellQuote2(remoteRef)}`, {
99922
100046
  cwd: rootDir,
99923
100047
  timeout: 3e4
99924
100048
  });
@@ -99928,7 +100052,7 @@ async function isBranchAheadOfBase(task, rootDir, preferredBaseRef) {
99928
100052
  }
99929
100053
  }
99930
100054
  try {
99931
- const { stdout } = await execAsync26(
100055
+ const { stdout } = await execAsync27(
99932
100056
  `git rev-list --count ${shellQuote2(resolvedBaseRef)}..${shellQuote2(branchName)}`,
99933
100057
  { cwd: rootDir, timeout: 3e4 }
99934
100058
  );
@@ -99980,7 +100104,7 @@ function isNoTaskDoneFailure2(task) {
99980
100104
  function hasStepProgress2(task) {
99981
100105
  return task.steps.some((step) => step.status !== "pending");
99982
100106
  }
99983
- var log20, worktreeMetadataReconcileLog, execAsync26, DONE_TASK_INTEGRITY_SWEEP_LIMIT, BOARD_STALL_NOTIFICATION_COOLDOWN_MS, DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS, STALE_ACTIVE_BRANCH_EXECUTION_GRACE_MS, COMPLETION_HANDOFF_LIMBO_GRACE_MS, MAX_COMPLETION_HANDOFF_LIMBO_RECOVERIES, APPROVED_TRIAGE_RECOVERY_GRACE_MS, STARVED_REFINEMENT_RECOVERY_GRACE_MS, STARVED_PEER_PROGRESS_THRESHOLD, STARVED_REFINEMENT_ESCALATION_COOLDOWN_MS, ORPHANED_EXECUTION_RECOVERY_GRACE_MS, ACTIVE_MERGE_STATUSES2, NON_TERMINAL_STEP_STATUSES2, STRANDED_COMPLETED_TODO_ACTIVE_STATUSES, GHOST_REVIEW_PRESERVED_STATUSES, ORPHANED_WITH_WORKTREE_GRACE_MS, MAX_TASK_DONE_RETRIES, MAX_WORKTREE_SESSION_RETRIES, MAX_AUTO_MERGE_RETRIES, MAX_STARVATION_DROPS, DEADLOCK_RECOVERY_COOLDOWN_MS, DEFAULT_STALE_MERGING_STATUS_MIN_AGE_MS, DEFAULT_STALE_MERGING_FANOUT_MIN_AGE_MS, DEFAULT_UNBACKED_MERGING_FANOUT_GRACE_MS, DURABLE_ERROR_RECOVERY_MAX_RETRIES, DURABLE_ERROR_RECOVERY_BASE_COOLDOWN_MS, DURABLE_ERROR_RECOVERY_MAX_COOLDOWN_MS, RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS, SelfHealingManager;
100107
+ var log20, worktreeMetadataReconcileLog, execAsync27, yieldEventLoop2, DONE_TASK_INTEGRITY_SWEEP_LIMIT, BOARD_STALL_NOTIFICATION_COOLDOWN_MS, DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS, STALE_ACTIVE_BRANCH_EXECUTION_GRACE_MS, COMPLETION_HANDOFF_LIMBO_GRACE_MS, MAX_COMPLETION_HANDOFF_LIMBO_RECOVERIES, APPROVED_TRIAGE_RECOVERY_GRACE_MS, STARVED_REFINEMENT_RECOVERY_GRACE_MS, STARVED_PEER_PROGRESS_THRESHOLD, STARVED_REFINEMENT_ESCALATION_COOLDOWN_MS, ORPHANED_EXECUTION_RECOVERY_GRACE_MS, ACTIVE_MERGE_STATUSES2, NON_TERMINAL_STEP_STATUSES2, STRANDED_COMPLETED_TODO_ACTIVE_STATUSES, GHOST_REVIEW_PRESERVED_STATUSES, ORPHANED_WITH_WORKTREE_GRACE_MS, MAX_TASK_DONE_RETRIES, MAX_WORKTREE_SESSION_RETRIES, MAX_AUTO_MERGE_RETRIES, MAX_STARVATION_DROPS, DEADLOCK_RECOVERY_COOLDOWN_MS, DEFAULT_STALE_MERGING_STATUS_MIN_AGE_MS, DEFAULT_STALE_MERGING_FANOUT_MIN_AGE_MS, DEFAULT_UNBACKED_MERGING_FANOUT_GRACE_MS, DURABLE_ERROR_RECOVERY_MAX_RETRIES, DURABLE_ERROR_RECOVERY_BASE_COOLDOWN_MS, DURABLE_ERROR_RECOVERY_MAX_COOLDOWN_MS, RUNNING_ON_INACTIVE_TASK_STALE_RUN_MS, SelfHealingManager;
99984
100108
  var init_self_healing = __esm({
99985
100109
  "../engine/src/self-healing.ts"() {
99986
100110
  "use strict";
@@ -99997,12 +100121,14 @@ var init_self_healing = __esm({
99997
100121
  init_worktree_paths();
99998
100122
  init_worktree_names();
99999
100123
  init_integration_branch();
100124
+ init_merger_bare_subject();
100000
100125
  init_foreign_only_contamination();
100001
100126
  init_notifier();
100002
100127
  init_dependency_blocked_todo_reporter();
100003
100128
  log20 = createLogger2("self-healing");
100004
100129
  worktreeMetadataReconcileLog = createLogger2("worktree-metadata-reconcile");
100005
- execAsync26 = promisify34(exec28);
100130
+ execAsync27 = promisify35(exec29);
100131
+ yieldEventLoop2 = () => new Promise((resolve32) => setImmediateCb2(resolve32));
100006
100132
  DONE_TASK_INTEGRITY_SWEEP_LIMIT = 50;
100007
100133
  BOARD_STALL_NOTIFICATION_COOLDOWN_MS = 60 * 6e4;
100008
100134
  DB_CORRUPTION_NOTIFICATION_COOLDOWN_MS = 60 * 60 * 1e3;
@@ -100281,6 +100407,7 @@ var init_self_healing = __esm({
100281
100407
  const stepErrMessage = stepErr instanceof Error ? stepErr.message : String(stepErr);
100282
100408
  log20.error(`Startup recovery step "${step.name}" failed: ${stepErrMessage} \u2014 continuing with remaining steps`);
100283
100409
  }
100410
+ await yieldEventLoop2();
100284
100411
  }
100285
100412
  }
100286
100413
  stop() {
@@ -100476,12 +100603,12 @@ var init_self_healing = __esm({
100476
100603
  if (completedSteps.length === 0) return;
100477
100604
  const branchName = task.branch || canonicalFusionBranchName(task.id);
100478
100605
  try {
100479
- const { stdout: mergeBaseOut } = await execAsync26(
100606
+ const { stdout: mergeBaseOut } = await execAsync27(
100480
100607
  `git merge-base "${branchName}" HEAD`,
100481
100608
  { cwd: this.options.rootDir, encoding: "utf-8", timeout: 3e4 }
100482
100609
  );
100483
100610
  const mergeBase = mergeBaseOut.trim();
100484
- const { stdout: branchHeadOut } = await execAsync26(
100611
+ const { stdout: branchHeadOut } = await execAsync27(
100485
100612
  `git rev-parse "${branchName}"`,
100486
100613
  { cwd: this.options.rootDir, encoding: "utf-8", timeout: 3e4 }
100487
100614
  );
@@ -100530,11 +100657,11 @@ var init_self_healing = __esm({
100530
100657
  const storedSha = task.mergeDetails?.commitSha;
100531
100658
  if (storedSha) {
100532
100659
  try {
100533
- await execAsync26(
100660
+ await execAsync27(
100534
100661
  `git merge-base --is-ancestor ${shellQuote2(storedSha)} HEAD`,
100535
100662
  { cwd: this.options.rootDir }
100536
100663
  );
100537
- const { stdout: stdout2 } = await execAsync26(
100664
+ const { stdout: stdout2 } = await execAsync27(
100538
100665
  `git log -1 --format=%H%x1f%s%x1f%b ${shellQuote2(storedSha)}`,
100539
100666
  { cwd: this.options.rootDir, maxBuffer: 1024 * 1024 }
100540
100667
  );
@@ -100563,7 +100690,7 @@ var init_self_healing = __esm({
100563
100690
  `--grep=${grepArg}`,
100564
100691
  shellQuote2(range)
100565
100692
  ].join(" ");
100566
- return execAsync26(command, {
100693
+ return execAsync27(command, {
100567
100694
  cwd: this.options.rootDir,
100568
100695
  maxBuffer: 1024 * 1024
100569
100696
  });
@@ -100611,7 +100738,7 @@ var init_self_healing = __esm({
100611
100738
  const [candidateSha, candidateSubject = ""] = line.split("");
100612
100739
  if (!candidateSha) continue;
100613
100740
  try {
100614
- const { stdout: bodyOut } = await execAsync26(
100741
+ const { stdout: bodyOut } = await execAsync27(
100615
100742
  `git log -1 --format=%b ${shellQuote2(candidateSha)}`,
100616
100743
  { cwd: this.options.rootDir, maxBuffer: 1024 * 1024 }
100617
100744
  );
@@ -100680,7 +100807,7 @@ var init_self_healing = __esm({
100680
100807
  }
100681
100808
  const branch = task.branch || canonicalFusionBranchName(task.id);
100682
100809
  try {
100683
- await execAsync26(`git branch -D ${shellQuote2(branch)}`, {
100810
+ await execAsync27(`git branch -D ${shellQuote2(branch)}`, {
100684
100811
  cwd: this.options.rootDir,
100685
100812
  timeout: 12e4
100686
100813
  });
@@ -100748,6 +100875,7 @@ var init_self_healing = __esm({
100748
100875
  } catch (stepErr) {
100749
100876
  log20.error(`Maintenance batch 1 step "${fn2.name}" failed: ${stepErr instanceof Error ? stepErr.message : String(stepErr)}`);
100750
100877
  }
100878
+ await yieldEventLoop2();
100751
100879
  }
100752
100880
  const recoverySettings = await this.store.getSettings();
100753
100881
  if (recoverySettings.globalPause || recoverySettings.enginePaused) {
@@ -100817,6 +100945,7 @@ var init_self_healing = __esm({
100817
100945
  } catch (stepErr) {
100818
100946
  log20.error(`Maintenance batch 2 step "${fn2.name}" failed: ${stepErr instanceof Error ? stepErr.message : String(stepErr)}`);
100819
100947
  }
100948
+ await yieldEventLoop2();
100820
100949
  }
100821
100950
  }
100822
100951
  const batch3Fns = [
@@ -100829,6 +100958,7 @@ var init_self_healing = __esm({
100829
100958
  } catch (stepErr) {
100830
100959
  log20.error(`Maintenance batch 3 step "${fn2.name}" failed: ${stepErr instanceof Error ? stepErr.message : String(stepErr)}`);
100831
100960
  }
100961
+ await yieldEventLoop2();
100832
100962
  }
100833
100963
  const elapsedMs = Date.now() - startMs;
100834
100964
  log20.log(`Maintenance cycle completed in ${elapsedMs}ms`);
@@ -101132,8 +101262,8 @@ var init_self_healing = __esm({
101132
101262
  const canAutoReclaimLiveZero = branchOwnerTaskId !== null && branchOwnerTaskId === taskIdUpper && !ownedByOtherInProgressTask;
101133
101263
  if (canAutoReclaimLiveZero) {
101134
101264
  await removeWorktree({ rootDir: this.options.rootDir, worktreePath: inspection.livePath, settings, taskId: task.id, reason: RemovalReason.SelfHealingBranchConflict });
101135
- await execAsync26("git worktree prune", { cwd: this.options.rootDir, timeout: 12e4, maxBuffer: 10 * 1024 * 1024 });
101136
- await execAsync26(`git branch -D ${JSON.stringify(task.branch)}`, { cwd: this.options.rootDir, timeout: 12e4, maxBuffer: 10 * 1024 * 1024 });
101265
+ await execAsync27("git worktree prune", { cwd: this.options.rootDir, timeout: 12e4, maxBuffer: 10 * 1024 * 1024 });
101266
+ await execAsync27(`git branch -D ${JSON.stringify(task.branch)}`, { cwd: this.options.rootDir, timeout: 12e4, maxBuffer: 10 * 1024 * 1024 });
101137
101267
  await this.store.updateTask(task.id, { worktree: null, branch: null, paused: false, pausedReason: void 0, status: null, error: null });
101138
101268
  await auditor.database({ type: "task:pr-conflict-reclaim", target: task.id, metadata: { outcome: "reclaimed", mode: "fully-subsumed", recoveredFromPaused: wasPausedBranchConflict } });
101139
101269
  return withPerPr({ outcome: "reclaimed" });
@@ -101357,12 +101487,12 @@ var init_self_healing = __esm({
101357
101487
  reason: RemovalReason.SelfHealingBranchConflict
101358
101488
  });
101359
101489
  }
101360
- await execAsync26("git worktree prune", {
101490
+ await execAsync27("git worktree prune", {
101361
101491
  cwd: this.options.rootDir,
101362
101492
  timeout: 12e4,
101363
101493
  maxBuffer: 10 * 1024 * 1024
101364
101494
  });
101365
- await execAsync26(`git branch -D ${JSON.stringify(branchName)}`, {
101495
+ await execAsync27(`git branch -D ${JSON.stringify(branchName)}`, {
101366
101496
  cwd: this.options.rootDir,
101367
101497
  timeout: 12e4,
101368
101498
  maxBuffer: 10 * 1024 * 1024
@@ -101446,12 +101576,12 @@ var init_self_healing = __esm({
101446
101576
  taskId: task.id,
101447
101577
  reason: RemovalReason.SelfHealingBranchConflict
101448
101578
  });
101449
- await execAsync26("git worktree prune", {
101579
+ await execAsync27("git worktree prune", {
101450
101580
  cwd: this.options.rootDir,
101451
101581
  timeout: 12e4,
101452
101582
  maxBuffer: 10 * 1024 * 1024
101453
101583
  });
101454
- await execAsync26(`git branch -D ${JSON.stringify(task.branch)}`, {
101584
+ await execAsync27(`git branch -D ${JSON.stringify(task.branch)}`, {
101455
101585
  cwd: this.options.rootDir,
101456
101586
  timeout: 12e4,
101457
101587
  maxBuffer: 10 * 1024 * 1024
@@ -101724,7 +101854,7 @@ var init_self_healing = __esm({
101724
101854
  if (task.worktree && existsSync38(task.worktree)) {
101725
101855
  try {
101726
101856
  if (statSync6(task.worktree).isDirectory()) {
101727
- const { stdout } = await execAsync26(`git -C ${JSON.stringify(task.worktree)} status --porcelain`, {
101857
+ const { stdout } = await execAsync27(`git -C ${JSON.stringify(task.worktree)} status --porcelain`, {
101728
101858
  cwd: this.options.rootDir,
101729
101859
  timeout: 3e4,
101730
101860
  maxBuffer: 10 * 1024 * 1024
@@ -101745,12 +101875,12 @@ var init_self_healing = __esm({
101745
101875
  log20.warn(`[recovery] stale-active-branch-rescue-needed ${task.id} branch=${branch} unique=${inspection.uniqueCommitCount} tip=${inspection.tipSha.slice(0, 12)}`);
101746
101876
  continue;
101747
101877
  }
101748
- await execAsync26(`git branch -D ${JSON.stringify(branch)}`, {
101878
+ await execAsync27(`git branch -D ${JSON.stringify(branch)}`, {
101749
101879
  cwd: this.options.rootDir,
101750
101880
  timeout: 12e4,
101751
101881
  maxBuffer: 10 * 1024 * 1024
101752
101882
  });
101753
- await execAsync26("git worktree prune", {
101883
+ await execAsync27("git worktree prune", {
101754
101884
  cwd: this.options.rootDir,
101755
101885
  timeout: 12e4,
101756
101886
  maxBuffer: 10 * 1024 * 1024
@@ -101817,7 +101947,7 @@ var init_self_healing = __esm({
101817
101947
  */
101818
101948
  async findWorktreePathForBranch(branchName) {
101819
101949
  try {
101820
- const { stdout } = await execAsync26("git worktree list --porcelain", {
101950
+ const { stdout } = await execAsync27("git worktree list --porcelain", {
101821
101951
  cwd: this.options.rootDir,
101822
101952
  timeout: 3e4
101823
101953
  });
@@ -101850,7 +101980,7 @@ var init_self_healing = __esm({
101850
101980
  }
101851
101981
  async clearCompletionBranchIfSubsumed(task, branchName) {
101852
101982
  try {
101853
- await execAsync26(`git rev-parse --verify ${shellQuote2(branchName)}`, {
101983
+ await execAsync27(`git rev-parse --verify ${shellQuote2(branchName)}`, {
101854
101984
  cwd: this.options.rootDir,
101855
101985
  timeout: 3e4
101856
101986
  });
@@ -101866,7 +101996,7 @@ var init_self_healing = __esm({
101866
101996
  return false;
101867
101997
  }
101868
101998
  try {
101869
- await execAsync26(`git branch -D ${shellQuote2(branchName)}`, {
101999
+ await execAsync27(`git branch -D ${shellQuote2(branchName)}`, {
101870
102000
  cwd: this.options.rootDir,
101871
102001
  timeout: 3e4
101872
102002
  });
@@ -102063,7 +102193,7 @@ var init_self_healing = __esm({
102063
102193
  if (settings.globalPause || settings.enginePaused) return result;
102064
102194
  const allTasks = await this.store.listTasks({ slim: true, includeArchived: false });
102065
102195
  const tasks = allTasks.filter((task) => task.column === "in-review");
102066
- const fusionRefOutput = await execAsync26("git for-each-ref --format='%(refname:short)' refs/heads/fusion/", {
102196
+ const fusionRefOutput = await execAsync27("git for-each-ref --format='%(refname:short)' refs/heads/fusion/", {
102067
102197
  cwd: this.options.rootDir,
102068
102198
  timeout: 3e4
102069
102199
  }).catch(() => ({ stdout: "" }));
@@ -102073,7 +102203,7 @@ var init_self_healing = __esm({
102073
102203
  const existingBinding = task.branch;
102074
102204
  if (existingBinding) {
102075
102205
  try {
102076
- await execAsync26(`git show-ref --verify --quiet ${shellQuote2(`refs/heads/${existingBinding}`)}`, {
102206
+ await execAsync27(`git show-ref --verify --quiet ${shellQuote2(`refs/heads/${existingBinding}`)}`, {
102077
102207
  cwd: this.options.rootDir,
102078
102208
  timeout: 3e4
102079
102209
  });
@@ -102089,50 +102219,52 @@ var init_self_healing = __esm({
102089
102219
  if (stem.toLowerCase() === normalizedId) candidates.add(branch);
102090
102220
  }
102091
102221
  const integrationBase = task.baseBranch || await resolveIntegrationBranch(this.options.rootDir, void 0);
102092
- const existingCandidatesByRef = /* @__PURE__ */ new Map();
102222
+ const candidateByRefSha = /* @__PURE__ */ new Map();
102223
+ const normalizedCandidate = canonicalFusionBranchName(task.id);
102093
102224
  for (const branch of candidates) {
102225
+ let branchSha;
102094
102226
  try {
102095
- await execAsync26(`git show-ref --verify --quiet ${shellQuote2(`refs/heads/${branch}`)}`, {
102227
+ const { stdout } = await execAsync27(`git rev-parse --verify ${shellQuote2(`refs/heads/${branch}`)}`, {
102096
102228
  cwd: this.options.rootDir,
102097
102229
  timeout: 3e4
102098
102230
  });
102231
+ branchSha = stdout.trim();
102099
102232
  } catch {
102100
102233
  continue;
102101
102234
  }
102235
+ if (!branchSha) continue;
102102
102236
  let comparisonBase = integrationBase;
102103
102237
  try {
102104
- await execAsync26(`git rev-parse --verify ${shellQuote2(comparisonBase)}`, {
102238
+ await execAsync27(`git rev-parse --verify ${shellQuote2(comparisonBase)}`, {
102105
102239
  cwd: this.options.rootDir,
102106
102240
  timeout: 3e4
102107
102241
  });
102108
102242
  } catch {
102109
102243
  const originBase = `origin/${comparisonBase}`;
102110
- await execAsync26(`git rev-parse --verify ${shellQuote2(originBase)}`, {
102244
+ await execAsync27(`git rev-parse --verify ${shellQuote2(originBase)}`, {
102111
102245
  cwd: this.options.rootDir,
102112
102246
  timeout: 3e4
102113
102247
  });
102114
102248
  comparisonBase = originBase;
102115
102249
  }
102116
- const mergeBase = (await execAsync26(`git merge-base ${shellQuote2(comparisonBase)} ${shellQuote2(branch)}`, {
102250
+ const mergeBase = (await execAsync27(`git merge-base ${shellQuote2(comparisonBase)} ${shellQuote2(branch)}`, {
102117
102251
  cwd: this.options.rootDir,
102118
102252
  timeout: 3e4
102119
102253
  })).stdout.trim();
102120
- const aheadCountRaw = await execAsync26(`git rev-list --count ${shellQuote2(mergeBase)}..${shellQuote2(branch)}`, {
102254
+ const aheadCountRaw = await execAsync27(`git rev-list --count ${shellQuote2(mergeBase)}..${shellQuote2(branch)}`, {
102121
102255
  cwd: this.options.rootDir,
102122
102256
  timeout: 3e4
102123
102257
  });
102124
102258
  const aheadCount = Number.parseInt(aheadCountRaw.stdout.trim(), 10);
102125
- const normalizedBranchRef = branch.toLowerCase();
102126
- const existingCandidate = existingCandidatesByRef.get(normalizedBranchRef);
102127
- const normalizedCandidate = canonicalFusionBranchName(task.id);
102128
- if (!existingCandidate || branch === normalizedCandidate) {
102129
- existingCandidatesByRef.set(normalizedBranchRef, {
102259
+ const existing = candidateByRefSha.get(branchSha);
102260
+ if (!existing || branch === normalizedCandidate) {
102261
+ candidateByRefSha.set(branchSha, {
102130
102262
  branch,
102131
102263
  aheadCount: Number.isFinite(aheadCount) ? aheadCount : 0
102132
102264
  });
102133
102265
  }
102134
102266
  }
102135
- const existingCandidates = [...existingCandidatesByRef.values()];
102267
+ const existingCandidates = [...candidateByRefSha.values()];
102136
102268
  if (existingCandidates.length === 0) {
102137
102269
  await this.emitBranchRebindAuditEvent({
102138
102270
  taskId: task.id,
@@ -102147,7 +102279,7 @@ var init_self_healing = __esm({
102147
102279
  const selected = withUniqueWork[0];
102148
102280
  const patch = { branch: selected.branch, worktree: null };
102149
102281
  if (!task.baseCommitSha) {
102150
- const derivedBaseCommit = (await execAsync26(
102282
+ const derivedBaseCommit = (await execAsync27(
102151
102283
  `git merge-base ${shellQuote2(integrationBase)} ${shellQuote2(selected.branch)}`,
102152
102284
  { cwd: this.options.rootDir, timeout: 3e4 }
102153
102285
  )).stdout.trim();
@@ -103166,13 +103298,21 @@ var init_self_healing = __esm({
103166
103298
  }
103167
103299
  const mergedAt = (/* @__PURE__ */ new Date()).toISOString();
103168
103300
  if (classification.kind === "owned-commit") {
103301
+ const mergeCommitMessage = await regenerateBareMergeSubject({
103302
+ subject: classification.commit.subject,
103303
+ commitSha: classification.commit.sha,
103304
+ branch: task.branch ?? "",
103305
+ taskId: task.id,
103306
+ rootDir: this.options.rootDir,
103307
+ settings
103308
+ });
103169
103309
  const mergeDetails = {
103170
103310
  ...task.mergeDetails || {},
103171
103311
  commitSha: classification.commit.sha,
103172
103312
  filesChanged: classification.commit.filesChanged,
103173
103313
  insertions: classification.commit.insertions,
103174
103314
  deletions: classification.commit.deletions,
103175
- mergeCommitMessage: classification.commit.subject,
103315
+ mergeCommitMessage,
103176
103316
  mergeConfirmed: true,
103177
103317
  mergedAt,
103178
103318
  mergeTargetBranch: ahead.baseRef
@@ -103243,6 +103383,14 @@ var init_self_healing = __esm({
103243
103383
  for (const task of candidates) {
103244
103384
  const classification = await classifyOwnedLandedEvidenceForSelfHealing(this.options.rootDir, task, mergeTargetBranch);
103245
103385
  if (classification.kind === "owned-commit") {
103386
+ const mergeCommitMessage = await regenerateBareMergeSubject({
103387
+ subject: classification.commit.subject,
103388
+ commitSha: classification.commit.sha,
103389
+ branch: task.branch ?? "",
103390
+ taskId: task.id,
103391
+ rootDir: this.options.rootDir,
103392
+ settings
103393
+ });
103246
103394
  await this.store.updateTask(task.id, {
103247
103395
  mergeDetails: {
103248
103396
  ...task.mergeDetails || {},
@@ -103250,7 +103398,7 @@ var init_self_healing = __esm({
103250
103398
  filesChanged: classification.commit.filesChanged,
103251
103399
  insertions: classification.commit.insertions,
103252
103400
  deletions: classification.commit.deletions,
103253
- mergeCommitMessage: classification.commit.subject
103401
+ mergeCommitMessage
103254
103402
  }
103255
103403
  });
103256
103404
  await this.recordIntegrityAudit(task.id, "task:integrity-reconcile-modified-files", {
@@ -103931,13 +104079,21 @@ var init_self_healing = __esm({
103931
104079
  try {
103932
104080
  const landedCommit = await this.findLandedTaskCommit(task);
103933
104081
  if (landedCommit) {
104082
+ const mergeCommitMessage = await regenerateBareMergeSubject({
104083
+ subject: landedCommit.subject,
104084
+ commitSha: landedCommit.sha,
104085
+ branch: task.branch ?? "",
104086
+ taskId: task.id,
104087
+ rootDir: this.options.rootDir,
104088
+ settings
104089
+ });
103934
104090
  const mergeDetails = {
103935
104091
  commitSha: landedCommit.sha,
103936
104092
  rebaseBaseSha: landedCommit.rebaseBaseSha,
103937
104093
  filesChanged: landedCommit.filesChanged,
103938
104094
  insertions: landedCommit.insertions,
103939
104095
  deletions: landedCommit.deletions,
103940
- mergeCommitMessage: landedCommit.subject,
104096
+ mergeCommitMessage,
103941
104097
  mergedAt: (/* @__PURE__ */ new Date()).toISOString(),
103942
104098
  mergeConfirmed: true,
103943
104099
  prNumber: getPrimaryPrInfo(task)?.number
@@ -103991,7 +104147,7 @@ var init_self_healing = __esm({
103991
104147
  async readShortstatForSha(sha, rebaseBaseSha) {
103992
104148
  try {
103993
104149
  const command = rebaseBaseSha ? `git diff --shortstat ${shellQuote2(`${rebaseBaseSha}..${sha}`)}` : `git show --shortstat --format= ${shellQuote2(sha)}`;
103994
- const stats = await execAsync26(command, {
104150
+ const stats = await execAsync27(command, {
103995
104151
  cwd: this.options.rootDir,
103996
104152
  maxBuffer: 1024 * 1024
103997
104153
  });
@@ -104008,7 +104164,7 @@ var init_self_healing = __esm({
104008
104164
  async readLandedFilesForSha(sha, rebaseBaseSha) {
104009
104165
  try {
104010
104166
  const command = rebaseBaseSha ? `git diff --name-only ${shellQuote2(`${rebaseBaseSha}..${sha}`)}` : `git show --name-only --format= ${shellQuote2(sha)}`;
104011
- const result = await execAsync26(command, {
104167
+ const result = await execAsync27(command, {
104012
104168
  cwd: this.options.rootDir,
104013
104169
  maxBuffer: 1024 * 1024
104014
104170
  });
@@ -104263,13 +104419,21 @@ var init_self_healing = __esm({
104263
104419
  try {
104264
104420
  const landedCommit = await this.findLandedTaskCommit(task);
104265
104421
  if (landedCommit) {
104422
+ const mergeCommitMessage = await regenerateBareMergeSubject({
104423
+ subject: landedCommit.subject,
104424
+ commitSha: landedCommit.sha,
104425
+ branch: task.branch ?? "",
104426
+ taskId: task.id,
104427
+ rootDir: this.options.rootDir,
104428
+ settings
104429
+ });
104266
104430
  const mergeDetails = {
104267
104431
  commitSha: landedCommit.sha,
104268
104432
  rebaseBaseSha: landedCommit.rebaseBaseSha,
104269
104433
  filesChanged: landedCommit.filesChanged,
104270
104434
  insertions: landedCommit.insertions,
104271
104435
  deletions: landedCommit.deletions,
104272
- mergeCommitMessage: landedCommit.subject,
104436
+ mergeCommitMessage,
104273
104437
  mergedAt: (/* @__PURE__ */ new Date()).toISOString(),
104274
104438
  mergeConfirmed: true,
104275
104439
  prNumber: getPrimaryPrInfo(task)?.number
@@ -104685,7 +104849,7 @@ var init_self_healing = __esm({
104685
104849
  }
104686
104850
  async isBranchTipMisboundToTask(input) {
104687
104851
  const { branch, taskId, lineageId, baseBranch } = input;
104688
- const { stdout: bodyOut } = await execAsync26(`git log -1 --format=%B ${shellQuote2(branch)}`, {
104852
+ const { stdout: bodyOut } = await execAsync27(`git log -1 --format=%B ${shellQuote2(branch)}`, {
104689
104853
  cwd: this.options.rootDir,
104690
104854
  timeout: 3e4,
104691
104855
  maxBuffer: 1024 * 1024
@@ -104693,7 +104857,7 @@ var init_self_healing = __esm({
104693
104857
  const body = bodyOut;
104694
104858
  const hasTaskId = body.includes(`Fusion-Task-Id: ${taskId}`);
104695
104859
  const hasLineage = lineageId ? body.includes(`Fusion-Task-Lineage: ${lineageId}`) : false;
104696
- const { stdout: tipOut } = await execAsync26(`git rev-parse ${shellQuote2(branch)}`, {
104860
+ const { stdout: tipOut } = await execAsync27(`git rev-parse ${shellQuote2(branch)}`, {
104697
104861
  cwd: this.options.rootDir,
104698
104862
  timeout: 3e4,
104699
104863
  maxBuffer: 1024 * 1024
@@ -105659,7 +105823,7 @@ var init_self_healing = __esm({
105659
105823
  async hasRecoverableGitWork(task) {
105660
105824
  if (task.worktree && existsSync38(task.worktree)) {
105661
105825
  try {
105662
- const { stdout: status } = await execAsync26("git status --porcelain", {
105826
+ const { stdout: status } = await execAsync27("git status --porcelain", {
105663
105827
  cwd: task.worktree,
105664
105828
  timeout: 3e4
105665
105829
  });
@@ -105674,7 +105838,7 @@ var init_self_healing = __esm({
105674
105838
  }
105675
105839
  const branchName = task.branch || canonicalFusionBranchName(task.id);
105676
105840
  try {
105677
- await execAsync26(`git rev-parse --verify "${branchName}"`, {
105841
+ await execAsync27(`git rev-parse --verify "${branchName}"`, {
105678
105842
  cwd: this.options.rootDir,
105679
105843
  timeout: 3e4
105680
105844
  });
@@ -105682,7 +105846,7 @@ var init_self_healing = __esm({
105682
105846
  return false;
105683
105847
  }
105684
105848
  try {
105685
- const { stdout: uniqueCommits } = await execAsync26(
105849
+ const { stdout: uniqueCommits } = await execAsync27(
105686
105850
  `git rev-list --count HEAD.."${branchName}"`,
105687
105851
  { cwd: this.options.rootDir, timeout: 3e4 }
105688
105852
  );
@@ -105955,7 +106119,7 @@ var init_self_healing = __esm({
105955
106119
  }
105956
106120
  }
105957
106121
  }
105958
- await execAsync26("git worktree prune", {
106122
+ await execAsync27("git worktree prune", {
105959
106123
  cwd: this.options.rootDir,
105960
106124
  timeout: 3e4
105961
106125
  });
@@ -106199,10 +106363,10 @@ var init_self_healing = __esm({
106199
106363
 
106200
106364
  // ../engine/src/triage.ts
106201
106365
  import { Type as Type3 } from "@mariozechner/pi-ai";
106202
- import { exec as exec29 } from "node:child_process";
106366
+ import { exec as exec30 } from "node:child_process";
106203
106367
  import { readFile as readFile21 } from "node:fs/promises";
106204
106368
  import { join as join44 } from "node:path";
106205
- import { promisify as promisify35 } from "node:util";
106369
+ import { promisify as promisify36 } from "node:util";
106206
106370
  function parseFileScopeFromPrompt(text) {
106207
106371
  const match = text.match(/^##\s+File Scope\s*\n([\s\S]*?)(?=^##\s+|$)/m);
106208
106372
  if (!match) return [];
@@ -108462,7 +108626,7 @@ Take a completely different approach to writing this specification. Do NOT repea
108462
108626
  written,
108463
108627
  {
108464
108628
  cwd: this.rootDir,
108465
- exec: promisify35(exec29)
108629
+ exec: promisify36(exec30)
108466
108630
  }
108467
108631
  ),
108468
108632
  new Promise((resolve32) => setTimeout(() => resolve32(null), 15e3))
@@ -108619,7 +108783,7 @@ Take a completely different approach to writing this specification. Do NOT repea
108619
108783
 
108620
108784
  // ../engine/src/merger-orphan-rehome.ts
108621
108785
  import { execFile as execFile12 } from "node:child_process";
108622
- import { promisify as promisify36 } from "node:util";
108786
+ import { promisify as promisify37 } from "node:util";
108623
108787
  async function runGit5(args, cwd) {
108624
108788
  const { stdout } = await execFileAsync8("git", args, {
108625
108789
  cwd,
@@ -108724,7 +108888,7 @@ var init_merger_orphan_rehome = __esm({
108724
108888
  "../engine/src/merger-orphan-rehome.ts"() {
108725
108889
  "use strict";
108726
108890
  init_merger_ref_update_advance();
108727
- execFileAsync8 = promisify36(execFile12);
108891
+ execFileAsync8 = promisify37(execFile12);
108728
108892
  }
108729
108893
  });
108730
108894
 
@@ -108773,10 +108937,10 @@ var init_token_cap_detector = __esm({
108773
108937
  });
108774
108938
 
108775
108939
  // ../engine/src/auto-recovery-handlers/branch-worktree.ts
108776
- import { exec as exec30 } from "node:child_process";
108940
+ import { exec as exec31 } from "node:child_process";
108777
108941
  import { existsSync as existsSync39 } from "node:fs";
108778
- import { promisify as promisify37 } from "node:util";
108779
- var execAsync27, baseLog2, GIT_TIMEOUT_MS7, GIT_MAX_BUFFER6, BranchWorktreeAutoRecoveryHandler;
108942
+ import { promisify as promisify38 } from "node:util";
108943
+ var execAsync28, baseLog2, GIT_TIMEOUT_MS7, GIT_MAX_BUFFER6, BranchWorktreeAutoRecoveryHandler;
108780
108944
  var init_branch_worktree = __esm({
108781
108945
  "../engine/src/auto-recovery-handlers/branch-worktree.ts"() {
108782
108946
  "use strict";
@@ -108784,7 +108948,7 @@ var init_branch_worktree = __esm({
108784
108948
  init_active_session_registry();
108785
108949
  init_integration_branch();
108786
108950
  init_logger2();
108787
- execAsync27 = promisify37(exec30);
108951
+ execAsync28 = promisify38(exec31);
108788
108952
  baseLog2 = createLogger2("auto-recovery:branch-worktree");
108789
108953
  GIT_TIMEOUT_MS7 = 3e4;
108790
108954
  GIT_MAX_BUFFER6 = 10 * 1024 * 1024;
@@ -108796,7 +108960,7 @@ var init_branch_worktree = __esm({
108796
108960
  return this.deps.logger ?? baseLog2;
108797
108961
  }
108798
108962
  async runGit(repoDir, command) {
108799
- const { stdout } = await execAsync27(command, {
108963
+ const { stdout } = await execAsync28(command, {
108800
108964
  cwd: repoDir,
108801
108965
  timeout: GIT_TIMEOUT_MS7,
108802
108966
  maxBuffer: GIT_MAX_BUFFER6,
@@ -108994,7 +109158,7 @@ var init_branch_worktree = __esm({
108994
109158
  if (!isLiveOwned) {
108995
109159
  if (existsSync39(conflictingWorktreePath)) {
108996
109160
  try {
108997
- await execAsync27(`git worktree remove --force ${this.quote(conflictingWorktreePath)}`, {
109161
+ await execAsync28(`git worktree remove --force ${this.quote(conflictingWorktreePath)}`, {
108998
109162
  cwd: repoDir,
108999
109163
  timeout: GIT_TIMEOUT_MS7,
109000
109164
  maxBuffer: GIT_MAX_BUFFER6
@@ -109005,7 +109169,7 @@ var init_branch_worktree = __esm({
109005
109169
  }
109006
109170
  }
109007
109171
  try {
109008
- await execAsync27("git worktree prune", {
109172
+ await execAsync28("git worktree prune", {
109009
109173
  cwd: repoDir,
109010
109174
  timeout: GIT_TIMEOUT_MS7,
109011
109175
  maxBuffer: GIT_MAX_BUFFER6
@@ -109013,7 +109177,7 @@ var init_branch_worktree = __esm({
109013
109177
  } catch {
109014
109178
  }
109015
109179
  try {
109016
- await execAsync27(`git branch -D ${this.quote(branchName)}`, {
109180
+ await execAsync28(`git branch -D ${this.quote(branchName)}`, {
109017
109181
  cwd: repoDir,
109018
109182
  timeout: GIT_TIMEOUT_MS7,
109019
109183
  maxBuffer: GIT_MAX_BUFFER6
@@ -109187,19 +109351,19 @@ var init_contamination = __esm({
109187
109351
  });
109188
109352
 
109189
109353
  // ../engine/src/auto-recovery-handlers/file-scope.ts
109190
- import { exec as exec31 } from "node:child_process";
109191
- import { promisify as promisify38 } from "node:util";
109354
+ import { exec as exec32 } from "node:child_process";
109355
+ import { promisify as promisify39 } from "node:util";
109192
109356
  function createFileScopeAutoRecoveryHandler(deps) {
109193
109357
  return new FileScopeAutoRecoveryHandler({
109194
109358
  ...deps,
109195
- exec: deps.exec ?? execAsync28
109359
+ exec: deps.exec ?? execAsync29
109196
109360
  });
109197
109361
  }
109198
- var execAsync28, FileScopeAutoRecoveryHandler;
109362
+ var execAsync29, FileScopeAutoRecoveryHandler;
109199
109363
  var init_file_scope = __esm({
109200
109364
  "../engine/src/auto-recovery-handlers/file-scope.ts"() {
109201
109365
  "use strict";
109202
- execAsync28 = promisify38(exec31);
109366
+ execAsync29 = promisify39(exec32);
109203
109367
  FileScopeAutoRecoveryHandler = class {
109204
109368
  constructor(deps) {
109205
109369
  this.deps = deps;
@@ -109592,13 +109756,23 @@ var init_run_verification_tool = __esm({
109592
109756
  });
109593
109757
 
109594
109758
  // ../engine/src/executor.ts
109595
- import { exec as exec32, execSync as execSync6 } from "node:child_process";
109596
- import { promisify as promisify39 } from "node:util";
109759
+ import { exec as exec33, execSync as execSync6 } from "node:child_process";
109760
+ import { promisify as promisify40 } from "node:util";
109761
+ import { setImmediate as setImmediateCb3 } from "node:timers";
109597
109762
  import { delimiter, isAbsolute as isAbsolute14, join as join47, relative as relative11, resolve as resolvePath } from "node:path";
109598
109763
  import { existsSync as existsSync41, realpathSync as realpathSync6 } from "node:fs";
109599
109764
  import { readFile as readFile22, rm as rm5, writeFile as writeFile16 } from "node:fs/promises";
109600
109765
  import { Type as Type5 } from "@mariozechner/pi-ai";
109601
109766
  import { ModelRegistry as ModelRegistry2, SessionManager as SessionManager2 } from "@mariozechner/pi-coding-agent";
109767
+ function getResumeOrphanDelayMs() {
109768
+ const raw = process.env.FUSION_RESUME_ORPHAN_DELAY_MS;
109769
+ if (raw !== void 0) {
109770
+ const parsed = Number.parseInt(raw, 10);
109771
+ if (Number.isFinite(parsed) && parsed >= 0) return parsed;
109772
+ }
109773
+ if (process.env.VITEST || process.env.NODE_ENV === "test") return 0;
109774
+ return 3e4;
109775
+ }
109602
109776
  function canonicalizePath2(path6) {
109603
109777
  try {
109604
109778
  return realpathSync6(path6);
@@ -110141,7 +110315,7 @@ function detectReviewHandoffIntent(commentText) {
110141
110315
  ];
110142
110316
  return handoffPhrases.some((phrase) => text.includes(phrase));
110143
110317
  }
110144
- var execAsync29, tokenCacheMetricsLog, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, COMPLETED_TASK_WATCHDOG_MS, WORKFLOW_RERUN_WATCHDOG_MS, TASK_DONE_REFUSAL_SUFFIX, DISSENT_PATTERNS, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, WORKFLOW_FEEDBACK_PATH_REGEX, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, WORKFLOW_STEP_VERDICTS, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
110318
+ var execAsync30, yieldEventLoop3, tokenCacheMetricsLog, STEP_STATUSES, MAX_WORKFLOW_STEP_RETRIES, MAX_TASK_DONE_SESSION_RETRIES, MAX_TASK_DONE_REQUEUE_RETRIES, COMPLETED_TASK_WATCHDOG_MS, WORKFLOW_RERUN_WATCHDOG_MS, TASK_DONE_REFUSAL_SUFFIX, DISSENT_PATTERNS, WORKFLOW_SCRIPT_OUTPUT_MAX_CHARS2, WORKFLOW_FEEDBACK_PATH_REGEX, NonRetryableWorktreeError, taskUpdateParams, taskAddDepParams, spawnAgentParams, WORKFLOW_STEP_VERDICTS, reviewStepParams, EXECUTOR_SYSTEM_PROMPT, TaskExecutor;
110145
110319
  var init_executor = __esm({
110146
110320
  "../engine/src/executor.ts"() {
110147
110321
  "use strict";
@@ -110199,7 +110373,8 @@ var init_executor = __esm({
110199
110373
  init_retry_burned_logger();
110200
110374
  init_agent_logger();
110201
110375
  init_agent_tools();
110202
- execAsync29 = promisify39(exec32);
110376
+ execAsync30 = promisify40(exec33);
110377
+ yieldEventLoop3 = () => new Promise((resolve32) => setImmediateCb3(resolve32));
110203
110378
  tokenCacheMetricsLog = createLogger2("token-cache-metrics");
110204
110379
  STEP_STATUSES = ["pending", "in-progress", "done", "skipped"];
110205
110380
  MAX_WORKFLOW_STEP_RETRIES = 3;
@@ -110225,7 +110400,10 @@ var init_executor = __esm({
110225
110400
  status: Type5.Union(
110226
110401
  STEP_STATUSES.map((s3) => Type5.Literal(s3)),
110227
110402
  { description: "New status: pending, in-progress, done, or skipped" }
110228
- )
110403
+ ),
110404
+ dependencies: Type5.Optional(Type5.Array(Type5.String(), {
110405
+ description: "Optional task dependency array. Replaces existing dependencies. Pass ['FN-001', 'FN-002'] to set dependencies. Pass [] to clear all dependencies. Omit parameter to preserve existing dependencies."
110406
+ }))
110229
110407
  });
110230
110408
  taskAddDepParams = Type5.Object({
110231
110409
  task_id: Type5.String({ description: 'The ID of the task to depend on (e.g. "KB-001")' }),
@@ -111956,7 +112134,21 @@ The tool prevents your session from being killed by the inactivity watchdog duri
111956
112134
  );
111957
112135
  if (inProgress.length === 0) return;
111958
112136
  executorLog.log(`Found ${inProgress.length} orphaned in-progress task(s)`);
112137
+ const resumeDelayMs = getResumeOrphanDelayMs();
112138
+ if (resumeDelayMs > 0) {
112139
+ executorLog.log(
112140
+ `Deferring orphan task resumption for ${resumeDelayMs}ms to keep dashboard responsive during cold start`
112141
+ );
112142
+ }
112143
+ const scheduleResume = resumeDelayMs > 0 ? (fn2) => {
112144
+ setTimeout(fn2, resumeDelayMs);
112145
+ } : (fn2) => {
112146
+ fn2();
112147
+ };
112148
+ let yieldNext = false;
111959
112149
  for (const task of inProgress) {
112150
+ if (yieldNext) await yieldEventLoop3();
112151
+ yieldNext = true;
111960
112152
  if (this.isTaskWorkComplete(task) && !task.mergeDetails) {
111961
112153
  if (this.recoveringCompleted.has(task.id)) {
111962
112154
  executorLog.log(`${task.id} completed-task recovery already running - skipping duplicate startup recovery`);
@@ -111964,10 +112156,12 @@ The tool prevents your session from being killed by the inactivity watchdog duri
111964
112156
  }
111965
112157
  executorLog.log(`${task.id} is already complete \u2014 fast-pathing to in-review`);
111966
112158
  this.recoveringCompleted.add(task.id);
111967
- void this.recoverCompletedTask(task).catch(
111968
- (err) => executorLog.error(`Failed to recover completed orphan ${task.id}:`, err)
111969
- ).finally(() => {
111970
- this.recoveringCompleted.delete(task.id);
112159
+ scheduleResume(() => {
112160
+ void this.recoverCompletedTask(task).catch(
112161
+ (err) => executorLog.error(`Failed to recover completed orphan ${task.id}:`, err)
112162
+ ).finally(() => {
112163
+ this.recoveringCompleted.delete(task.id);
112164
+ });
111971
112165
  });
111972
112166
  continue;
111973
112167
  }
@@ -111983,9 +112177,11 @@ The tool prevents your session from being killed by the inactivity watchdog duri
111983
112177
  } catch (err) {
111984
112178
  executorLog.error(`Failed to write resume log for ${task.id}:`, err);
111985
112179
  }
111986
- this.execute(task).catch(
111987
- (err) => executorLog.error(`Failed to resume ${task.id}:`, err)
111988
- );
112180
+ scheduleResume(() => {
112181
+ this.execute(task).catch(
112182
+ (err) => executorLog.error(`Failed to resume ${task.id}:`, err)
112183
+ );
112184
+ });
111989
112185
  }
111990
112186
  }
111991
112187
  /**
@@ -113681,7 +113877,7 @@ ${summary}`,
113681
113877
  repoDir: this.rootDir,
113682
113878
  sha: commit.sha,
113683
113879
  commitSubject: commit.subject,
113684
- commitBody: await execAsync29(`git log -1 --format=%b ${commit.sha}`, { cwd: this.rootDir, encoding: "utf-8" }).then((r) => r.stdout).catch(() => ""),
113880
+ commitBody: await execAsync30(`git log -1 --format=%b ${commit.sha}`, { cwd: this.rootDir, encoding: "utf-8" }).then((r) => r.stdout).catch(() => ""),
113685
113881
  currentTaskId: task.id
113686
113882
  });
113687
113883
  if (misroutedResult.misrouted && misroutedResult.foreignTaskId) {
@@ -113694,7 +113890,7 @@ ${summary}`,
113694
113890
  const genuinelyUnique = [];
113695
113891
  const integrationBranchForOrphan = task.mergeDetails?.mergeTargetBranch ?? task.baseBranch ?? "main";
113696
113892
  for (const commit of preOrphanUnique) {
113697
- const orphanBody = await execAsync29(`git log -1 --format=%b ${commit.sha}`, { cwd: this.rootDir, encoding: "utf-8" }).then((r) => r.stdout).catch(() => "");
113893
+ const orphanBody = await execAsync30(`git log -1 --format=%b ${commit.sha}`, { cwd: this.rootDir, encoding: "utf-8" }).then((r) => r.stdout).catch(() => "");
113698
113894
  const orphanClass = await classifyOrphanOurAdvance({
113699
113895
  repoDir: this.rootDir,
113700
113896
  taskStore: this.store,
@@ -114076,10 +114272,10 @@ ${summary}`,
114076
114272
  return {
114077
114273
  name: "fn_task_update",
114078
114274
  label: "Update Step",
114079
- description: "Update a step's status. Call before starting a step (in-progress), after completing it (done), or to skip it (skipped). The board updates in real-time.",
114275
+ description: "Update a step's status. Call before starting a step (in-progress), after completing it (done), or to skip it (skipped). Optionally update task dependencies by passing a dependencies array. The board updates in real-time.",
114080
114276
  parameters: taskUpdateParams,
114081
114277
  execute: async (_id, params) => {
114082
- const { step, status } = params;
114278
+ const { step, status, dependencies } = params;
114083
114279
  if (status === "in-progress" || status === "done" || status === "skipped") {
114084
114280
  stuckDetector?.recordProgress(taskId);
114085
114281
  }
@@ -114117,6 +114313,35 @@ ${summary}`,
114117
114313
  details: {}
114118
114314
  };
114119
114315
  }
114316
+ if (dependencies !== void 0) {
114317
+ if (dependencies.includes(taskId)) {
114318
+ return {
114319
+ content: [{
114320
+ type: "text",
114321
+ text: `Cannot add self-dependency: ${taskId} cannot depend on itself.`
114322
+ }],
114323
+ details: {}
114324
+ };
114325
+ }
114326
+ const invalidIds = [];
114327
+ for (const depId of dependencies) {
114328
+ try {
114329
+ await store.getTask(depId);
114330
+ } catch {
114331
+ invalidIds.push(depId);
114332
+ }
114333
+ }
114334
+ if (invalidIds.length > 0) {
114335
+ return {
114336
+ content: [{
114337
+ type: "text",
114338
+ text: `Cannot set dependencies \u2014 the following task(s) do not exist: ${invalidIds.join(", ")}`
114339
+ }],
114340
+ details: {}
114341
+ };
114342
+ }
114343
+ await store.updateTask(taskId, { dependencies });
114344
+ }
114120
114345
  const task = await store.updateStep(taskId, stepIndex, status);
114121
114346
  const stepInfo = task.steps[stepIndex];
114122
114347
  if (!stepInfo) {
@@ -114300,8 +114525,14 @@ ${summary}`,
114300
114525
  expected: `resolvable task worktree under ${resolveWorktreesDir(this.rootDir, settings)}/*`
114301
114526
  };
114302
114527
  }
114528
+ if (!existsSync41(worktreePath)) {
114529
+ executorLog.log(
114530
+ `${task.id}: worktree directory not found at ${worktreePath} \u2014 skipping git validation for task completion`
114531
+ );
114532
+ return { ok: true };
114533
+ }
114303
114534
  try {
114304
- const { stdout } = await execAsync29("git rev-parse --show-toplevel", {
114535
+ const { stdout } = await execAsync30("git rev-parse --show-toplevel", {
114305
114536
  cwd: worktreePath,
114306
114537
  encoding: "utf-8",
114307
114538
  timeout: 1e4,
@@ -114328,7 +114559,7 @@ ${summary}`,
114328
114559
  };
114329
114560
  }
114330
114561
  try {
114331
- const { stdout } = await execAsync29("git rev-parse --abbrev-ref HEAD", {
114562
+ const { stdout } = await execAsync30("git rev-parse --abbrev-ref HEAD", {
114332
114563
  cwd: worktreePath,
114333
114564
  encoding: "utf-8",
114334
114565
  timeout: 1e4,
@@ -114386,7 +114617,7 @@ ${summary}`,
114386
114617
  return { ok: true };
114387
114618
  }
114388
114619
  try {
114389
- const { stdout } = await execAsync29(`git rev-list --count ${baseRef}..HEAD`, {
114620
+ const { stdout } = await execAsync30(`git rev-list --count ${baseRef}..HEAD`, {
114390
114621
  cwd: worktreePath,
114391
114622
  encoding: "utf-8",
114392
114623
  timeout: 1e4,
@@ -114849,7 +115080,7 @@ ${result.review}`;
114849
115080
  case "RETHINK": {
114850
115081
  if (reviewType === "code" && baseline) {
114851
115082
  try {
114852
- await execAsync29(`git reset --hard ${baseline}`, { cwd: worktreePath });
115083
+ await execAsync30(`git reset --hard ${baseline}`, { cwd: worktreePath });
114853
115084
  executorLog.log(`${taskId}: RETHINK \u2014 git reset --hard ${baseline}`);
114854
115085
  } catch (gitErr) {
114855
115086
  const gitErrMessage = gitErr instanceof Error ? gitErr.message : String(gitErr);
@@ -114971,7 +115202,7 @@ Take a different approach. Do NOT repeat the rejected strategy. Re-read the step
114971
115202
  const branch = task.branch || canonicalFusionBranchName(taskId);
114972
115203
  let branchDeleted = false;
114973
115204
  try {
114974
- await execAsync29(`git branch -D "${branch}"`, { cwd: this.rootDir });
115205
+ await execAsync30(`git branch -D "${branch}"`, { cwd: this.rootDir });
114975
115206
  branchDeleted = true;
114976
115207
  } catch (err) {
114977
115208
  const msg = err instanceof Error ? err.message : String(err);
@@ -115524,7 +115755,7 @@ ${failureFeedback}
115524
115755
  }
115525
115756
  let baseCommitSha;
115526
115757
  try {
115527
- const { stdout } = await execAsync29(
115758
+ const { stdout } = await execAsync30(
115528
115759
  "git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main",
115529
115760
  { cwd: worktreePath, encoding: "utf-8" }
115530
115761
  );
@@ -115534,7 +115765,7 @@ ${failureFeedback}
115534
115765
  executorLog.warn(`${task.id}: merge-base failed, falling back to HEAD: ${errorMessage}`);
115535
115766
  }
115536
115767
  if (!baseCommitSha) {
115537
- const { stdout } = await execAsync29("git rev-parse HEAD", {
115768
+ const { stdout } = await execAsync30("git rev-parse HEAD", {
115538
115769
  cwd: worktreePath,
115539
115770
  encoding: "utf-8"
115540
115771
  });
@@ -115563,7 +115794,7 @@ ${failureFeedback}
115563
115794
  */
115564
115795
  async resolveContaminationBaseRef(worktreePath) {
115565
115796
  try {
115566
- const { stdout } = await execAsync29(
115797
+ const { stdout } = await execAsync30(
115567
115798
  "git merge-base HEAD main 2>/dev/null || git merge-base HEAD origin/main",
115568
115799
  { cwd: worktreePath, encoding: "utf-8" }
115569
115800
  );
@@ -115583,7 +115814,7 @@ ${failureFeedback}
115583
115814
  async resolveDiffBaseRef(worktreePath, baseCommitSha) {
115584
115815
  if (baseCommitSha) return baseCommitSha;
115585
115816
  try {
115586
- const { stdout } = await execAsync29(
115817
+ const { stdout } = await execAsync30(
115587
115818
  "git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main",
115588
115819
  { cwd: worktreePath, encoding: "utf-8" }
115589
115820
  );
@@ -115594,7 +115825,7 @@ ${failureFeedback}
115594
115825
  executorLog.warn(`Failed merge-base lookup for diff base in ${worktreePath}, trying HEAD~1 fallback: ${mergeBaseMsg}`);
115595
115826
  }
115596
115827
  try {
115597
- const { stdout } = await execAsync29("git rev-parse HEAD~1", {
115828
+ const { stdout } = await execAsync30("git rev-parse HEAD~1", {
115598
115829
  cwd: worktreePath,
115599
115830
  encoding: "utf-8"
115600
115831
  });
@@ -115637,7 +115868,7 @@ ${failureFeedback}
115637
115868
  } catch (error) {
115638
115869
  if (error instanceof BranchAttributionError) {
115639
115870
  executorLog.warn(`${taskId}: branch-attribution failed (${error.message}); falling back to raw diff`);
115640
- const { stdout } = await execAsync29(`git diff --name-only ${baseRef}..HEAD`, {
115871
+ const { stdout } = await execAsync30(`git diff --name-only ${baseRef}..HEAD`, {
115641
115872
  cwd: worktreePath,
115642
115873
  encoding: "utf-8"
115643
115874
  });
@@ -115655,8 +115886,8 @@ ${failureFeedback}
115655
115886
  async captureUncommittedModifiedFiles(worktreePath) {
115656
115887
  try {
115657
115888
  const [unstaged, staged] = await Promise.all([
115658
- execAsync29("git diff --name-only", { cwd: worktreePath, encoding: "utf-8" }),
115659
- execAsync29("git diff --name-only --cached", { cwd: worktreePath, encoding: "utf-8" })
115889
+ execAsync30("git diff --name-only", { cwd: worktreePath, encoding: "utf-8" }),
115890
+ execAsync30("git diff --name-only --cached", { cwd: worktreePath, encoding: "utf-8" })
115660
115891
  ]);
115661
115892
  const files = [...unstaged.stdout.split("\n"), ...staged.stdout.split("\n")].map((entry) => entry.trim()).filter(Boolean);
115662
115893
  return [...new Set(files)];
@@ -116067,7 +116298,7 @@ ${failureFeedback}
116067
116298
  try {
116068
116299
  const baseRef = await this.resolveDiffBaseRef(worktreePath, task.baseCommitSha);
116069
116300
  if (baseRef) {
116070
- const { stdout } = await execAsync29(`git diff --shortstat ${baseRef}..HEAD`, {
116301
+ const { stdout } = await execAsync30(`git diff --shortstat ${baseRef}..HEAD`, {
116071
116302
  cwd: worktreePath,
116072
116303
  encoding: "utf-8"
116073
116304
  });
@@ -116460,7 +116691,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116460
116691
  await this.cleanupConflictingWorktree(inspection.livePath, error.branchName, task.id);
116461
116692
  }
116462
116693
  try {
116463
- await execAsync29("git worktree prune", {
116694
+ await execAsync30("git worktree prune", {
116464
116695
  cwd: this.rootDir,
116465
116696
  timeout: 12e4,
116466
116697
  maxBuffer: 10 * 1024 * 1024
@@ -116468,7 +116699,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116468
116699
  } catch {
116469
116700
  }
116470
116701
  try {
116471
- await execAsync29(`git branch -D ${JSON.stringify(error.branchName)}`, {
116702
+ await execAsync30(`git branch -D ${JSON.stringify(error.branchName)}`, {
116472
116703
  cwd: this.rootDir,
116473
116704
  timeout: 12e4,
116474
116705
  maxBuffer: 10 * 1024 * 1024
@@ -116493,13 +116724,13 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116493
116724
  const cleanupSuccess = await this.cleanupConflictingWorktree(inspection.livePath, error.branchName, task.id);
116494
116725
  if (cleanupSuccess) {
116495
116726
  try {
116496
- await execAsync29("git worktree prune", { cwd: this.rootDir });
116727
+ await execAsync30("git worktree prune", { cwd: this.rootDir });
116497
116728
  } catch {
116498
116729
  }
116499
116730
  try {
116500
116731
  const worktreeMap = await this.getWorktreeBranchMap();
116501
116732
  if (!worktreeMap.has(error.branchName)) {
116502
- await execAsync29(`git branch -D "${error.branchName}"`, { cwd: this.rootDir });
116733
+ await execAsync30(`git branch -D "${error.branchName}"`, { cwd: this.rootDir });
116503
116734
  }
116504
116735
  } catch {
116505
116736
  }
@@ -116635,7 +116866,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116635
116866
  let remote = settings.worktreeRebaseRemote?.trim() || "";
116636
116867
  if (!remote) {
116637
116868
  try {
116638
- const { stdout } = await execAsync29("git remote", { cwd: this.rootDir });
116869
+ const { stdout } = await execAsync30("git remote", { cwd: this.rootDir });
116639
116870
  const remotes = stdout.split("\n").map((s3) => s3.trim()).filter(Boolean);
116640
116871
  if (remotes.includes("origin")) remote = "origin";
116641
116872
  else if (remotes.length === 1) remote = remotes[0];
@@ -116645,7 +116876,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116645
116876
  if (remote) {
116646
116877
  let defaultBranch = "";
116647
116878
  try {
116648
- const { stdout } = await execAsync29(
116879
+ const { stdout } = await execAsync30(
116649
116880
  `git rev-parse --abbrev-ref ${this.quoteShellArg(remote)}/HEAD`,
116650
116881
  { cwd: this.rootDir }
116651
116882
  );
@@ -116653,12 +116884,12 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116653
116884
  } catch {
116654
116885
  }
116655
116886
  if (defaultBranch && defaultBranch !== "HEAD") {
116656
- await execAsync29(
116887
+ await execAsync30(
116657
116888
  `git fetch ${this.quoteShellArg(remote)} ${this.quoteShellArg(defaultBranch)}`,
116658
116889
  { cwd: this.rootDir }
116659
116890
  ).catch(() => void 0);
116660
116891
  try {
116661
- const { stdout } = await execAsync29(
116892
+ const { stdout } = await execAsync30(
116662
116893
  `git rev-parse --verify "${remote}/${defaultBranch}^{commit}"`,
116663
116894
  { cwd: this.rootDir, encoding: "utf-8" }
116664
116895
  );
@@ -116670,7 +116901,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116670
116901
  }
116671
116902
  if (!mainBase) {
116672
116903
  try {
116673
- const { stdout } = await execAsync29("git rev-parse HEAD", {
116904
+ const { stdout } = await execAsync30("git rev-parse HEAD", {
116674
116905
  cwd: this.rootDir,
116675
116906
  encoding: "utf-8"
116676
116907
  });
@@ -116681,7 +116912,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116681
116912
  }
116682
116913
  if (!mainBase) return null;
116683
116914
  try {
116684
- await execAsync29(
116915
+ await execAsync30(
116685
116916
  `git merge-base --is-ancestor ${this.quoteShellArg(depTip)} ${this.quoteShellArg(mainBase)}`,
116686
116917
  { cwd: this.rootDir }
116687
116918
  );
@@ -116701,7 +116932,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116701
116932
  */
116702
116933
  async squashImportDepIntoWorktree(worktreePath, taskId, depTip, label) {
116703
116934
  try {
116704
- await execAsync29(
116935
+ await execAsync30(
116705
116936
  `git merge-base --is-ancestor ${this.quoteShellArg(depTip)} HEAD`,
116706
116937
  { cwd: worktreePath }
116707
116938
  );
@@ -116709,30 +116940,30 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116709
116940
  } catch {
116710
116941
  }
116711
116942
  try {
116712
- await execAsync29(
116943
+ await execAsync30(
116713
116944
  `git merge --squash --allow-unrelated-histories ${this.quoteShellArg(depTip)}`,
116714
116945
  { cwd: worktreePath }
116715
116946
  );
116716
116947
  } catch (err) {
116717
- await execAsync29("git reset --hard HEAD", { cwd: worktreePath }).catch(
116948
+ await execAsync30("git reset --hard HEAD", { cwd: worktreePath }).catch(
116718
116949
  () => void 0
116719
116950
  );
116720
116951
  throw err;
116721
116952
  }
116722
116953
  try {
116723
- await execAsync29("git diff --cached --quiet", { cwd: worktreePath });
116954
+ await execAsync30("git diff --cached --quiet", { cwd: worktreePath });
116724
116955
  return;
116725
116956
  } catch {
116726
116957
  }
116727
116958
  const subject = `chore(${taskId}): import dependency content from ${label}`;
116728
116959
  const body = `Squash-imported the working tree of ${label} as a single commit so this branch carries the dep's content without inheriting its individual commits. If the dep is later squash-merged to main, this commit's patch-id should match the merge and rebase cleanly.`;
116729
116960
  try {
116730
- await execAsync29(
116961
+ await execAsync30(
116731
116962
  `git commit -m ${this.quoteShellArg(subject)} -m ${this.quoteShellArg(body)}`,
116732
116963
  { cwd: worktreePath }
116733
116964
  );
116734
116965
  } catch (commitErr) {
116735
- await execAsync29("git reset --hard HEAD", { cwd: worktreePath }).catch(
116966
+ await execAsync30("git reset --hard HEAD", { cwd: worktreePath }).catch(
116736
116967
  () => void 0
116737
116968
  );
116738
116969
  throw commitErr;
@@ -116764,7 +116995,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116764
116995
  let remote = settings.worktreeRebaseRemote?.trim() || "";
116765
116996
  if (!remote) {
116766
116997
  try {
116767
- const { stdout } = await execAsync29("git remote", { cwd: this.rootDir });
116998
+ const { stdout } = await execAsync30("git remote", { cwd: this.rootDir });
116768
116999
  const remotes = stdout.split("\n").map((s3) => s3.trim()).filter(Boolean);
116769
117000
  if (remotes.includes("origin")) remote = "origin";
116770
117001
  else if (remotes.length === 1) remote = remotes[0];
@@ -116774,13 +117005,13 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116774
117005
  if (!remote) return;
116775
117006
  let defaultBranch = "";
116776
117007
  try {
116777
- const { stdout } = await execAsync29(`git rev-parse --abbrev-ref ${remote}/HEAD`, { cwd: this.rootDir });
117008
+ const { stdout } = await execAsync30(`git rev-parse --abbrev-ref ${remote}/HEAD`, { cwd: this.rootDir });
116778
117009
  defaultBranch = stdout.trim().replace(new RegExp(`^${remote}/`), "");
116779
117010
  } catch {
116780
117011
  }
116781
117012
  if (!defaultBranch) {
116782
117013
  try {
116783
- const { stdout } = await execAsync29("git rev-parse --abbrev-ref HEAD", { cwd: this.rootDir });
117014
+ const { stdout } = await execAsync30("git rev-parse --abbrev-ref HEAD", { cwd: this.rootDir });
116784
117015
  defaultBranch = stdout.trim();
116785
117016
  } catch {
116786
117017
  return;
@@ -116789,7 +117020,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116789
117020
  if (!defaultBranch || defaultBranch === "HEAD") return;
116790
117021
  const remoteRef = `${remote}/${defaultBranch}`;
116791
117022
  try {
116792
- await execAsync29(`git fetch ${this.quoteShellArg(remote)} ${this.quoteShellArg(defaultBranch)}`, { cwd: this.rootDir });
117023
+ await execAsync30(`git fetch ${this.quoteShellArg(remote)} ${this.quoteShellArg(defaultBranch)}`, { cwd: this.rootDir });
116793
117024
  } catch (err) {
116794
117025
  executorLog.warn(
116795
117026
  `Worktree rebase: fetch ${remote} ${defaultBranch} failed for ${taskId}: ${err instanceof Error ? err.message : String(err)}`
@@ -116797,7 +117028,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116797
117028
  return;
116798
117029
  }
116799
117030
  try {
116800
- await execAsync29(`git rebase ${this.quoteShellArg(remoteRef)}`, { cwd: worktreePath });
117031
+ await execAsync30(`git rebase ${this.quoteShellArg(remoteRef)}`, { cwd: worktreePath });
116801
117032
  await this.store.logEntry(
116802
117033
  taskId,
116803
117034
  `Rebased new worktree branch ${branch} onto ${remoteRef}`
@@ -116808,7 +117039,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116808
117039
  `Worktree rebase: rebase onto ${remoteRef} failed for ${taskId} \u2014 aborting and leaving local base intact: ${msg}`
116809
117040
  );
116810
117041
  try {
116811
- await execAsync29("git rebase --abort", { cwd: worktreePath });
117042
+ await execAsync30("git rebase --abort", { cwd: worktreePath });
116812
117043
  } catch {
116813
117044
  }
116814
117045
  await this.store.logEntry(
@@ -116828,7 +117059,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
116828
117059
  async resolveWorktreeStartPoint(startPoint, taskId) {
116829
117060
  const command = isAbsolute14(startPoint) && existsSync41(startPoint) ? `git -C "${startPoint}" rev-parse --verify HEAD^{commit}` : `git rev-parse --verify "${startPoint}^{commit}"`;
116830
117061
  try {
116831
- const { stdout } = await execAsync29(command, { cwd: this.rootDir });
117062
+ const { stdout } = await execAsync30(command, { cwd: this.rootDir });
116832
117063
  return stdout.trim() || startPoint;
116833
117064
  } catch (error) {
116834
117065
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -117031,7 +117262,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117031
117262
  const createWithBranch = async (branchToCreate) => {
117032
117263
  const cmd = startPoint ? `git worktree add -b "${branchToCreate}" "${path6}" "${startPoint}"` : `git worktree add -b "${branchToCreate}" "${path6}"`;
117033
117264
  try {
117034
- await execAsync29(cmd, { cwd: this.rootDir });
117265
+ await execAsync30(cmd, { cwd: this.rootDir });
117035
117266
  } catch (err) {
117036
117267
  try {
117037
117268
  await rm5(path6, { recursive: true, force: true });
@@ -117043,7 +117274,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117043
117274
  };
117044
117275
  const createFromExistingBranch = async () => {
117045
117276
  try {
117046
- await execAsync29(`git worktree add "${path6}" "${branch}"`, { cwd: this.rootDir });
117277
+ await execAsync30(`git worktree add "${path6}" "${branch}"`, { cwd: this.rootDir });
117047
117278
  } catch (err) {
117048
117279
  try {
117049
117280
  await rm5(path6, { recursive: true, force: true });
@@ -117316,7 +117547,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117316
117547
  * Returns true if the conflicting worktree is used by an active task.
117317
117548
  */
117318
117549
  async getWorktreeBranchMap() {
117319
- const { stdout } = await execAsync29("git worktree list --porcelain", { cwd: this.rootDir, encoding: "utf-8" });
117550
+ const { stdout } = await execAsync30("git worktree list --porcelain", { cwd: this.rootDir, encoding: "utf-8" });
117320
117551
  const map = /* @__PURE__ */ new Map();
117321
117552
  let currentWorktree = null;
117322
117553
  for (const line of stdout.split("\n")) {
@@ -117479,7 +117710,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117479
117710
  }
117480
117711
  try {
117481
117712
  try {
117482
- await execAsync29(`git worktree unlock "${worktreePath}"`, {
117713
+ await execAsync30(`git worktree unlock "${worktreePath}"`, {
117483
117714
  cwd: this.rootDir
117484
117715
  });
117485
117716
  await this.store.logEntry(taskId, `Unlocked worktree`, worktreePath);
@@ -117496,7 +117727,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117496
117727
  });
117497
117728
  await this.store.logEntry(taskId, `Removed conflicting worktree`, worktreePath);
117498
117729
  try {
117499
- await execAsync29(`git branch -D "${branch}"`, {
117730
+ await execAsync30(`git branch -D "${branch}"`, {
117500
117731
  cwd: this.rootDir
117501
117732
  });
117502
117733
  await this.store.logEntry(taskId, `Deleted branch`, branch);
@@ -117510,7 +117741,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117510
117741
  const errorMessage = error instanceof Error ? error.message : String(error);
117511
117742
  if (/validation failed, cannot remove working tree/i.test(errorMessage)) {
117512
117743
  try {
117513
- await execAsync29("git worktree prune", {
117744
+ await execAsync30("git worktree prune", {
117514
117745
  cwd: this.rootDir,
117515
117746
  timeout: 3e4,
117516
117747
  maxBuffer: 10 * 1024 * 1024
@@ -117520,7 +117751,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117520
117751
  executorLog.warn(`${taskId}: git worktree prune failed during stale-path cleanup of ${worktreePath}: ${pruneMsg}`);
117521
117752
  }
117522
117753
  try {
117523
- await execAsync29(`git branch -D "${branch}"`, { cwd: this.rootDir });
117754
+ await execAsync30(`git branch -D "${branch}"`, { cwd: this.rootDir });
117524
117755
  this.store.clearStaleExecutionStartBranchReferences([branch], taskId);
117525
117756
  } catch {
117526
117757
  }
@@ -117554,12 +117785,12 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117554
117785
  */
117555
117786
  async cleanupStaleBranch(branch, taskId) {
117556
117787
  try {
117557
- await execAsync29("git worktree prune", { cwd: this.rootDir });
117788
+ await execAsync30("git worktree prune", { cwd: this.rootDir });
117558
117789
  await this.store.logEntry(taskId, `Pruned stale worktree metadata`, branch);
117559
117790
  } catch {
117560
117791
  }
117561
117792
  try {
117562
- await execAsync29(`git branch -D "${branch}"`, {
117793
+ await execAsync30(`git branch -D "${branch}"`, {
117563
117794
  cwd: this.rootDir
117564
117795
  });
117565
117796
  await this.store.logEntry(taskId, `Removed stale branch`, branch);
@@ -117578,7 +117809,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117578
117809
  }
117579
117810
  try {
117580
117811
  const refPath = `refs/heads/${branch}`;
117581
- await execAsync29(`git update-ref -d "${refPath}"`, {
117812
+ await execAsync30(`git update-ref -d "${refPath}"`, {
117582
117813
  cwd: this.rootDir
117583
117814
  });
117584
117815
  await this.store.logEntry(taskId, `Force-removed stale branch reference via update-ref`, refPath);
@@ -117751,7 +117982,7 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117751
117982
  if (pendingOrInProgressSteps.length === 0) return;
117752
117983
  let logOutput;
117753
117984
  try {
117754
- const { stdout } = await execAsync29(
117985
+ const { stdout } = await execAsync30(
117755
117986
  `git log "${baseCommitSha}..HEAD" --oneline`,
117756
117987
  { cwd: worktreePath }
117757
117988
  );
@@ -117809,11 +118040,11 @@ Review the work done in this worktree and evaluate it against the criteria in yo
117809
118040
  if (completedSteps.length === 0) return;
117810
118041
  const branchName = task.branch || canonicalFusionBranchName(task.id);
117811
118042
  try {
117812
- const { stdout: mergeBaseStdout } = await execAsync29(
118043
+ const { stdout: mergeBaseStdout } = await execAsync30(
117813
118044
  `git merge-base "${branchName}" HEAD 2>/dev/null`,
117814
118045
  { cwd: this.rootDir, encoding: "utf-8" }
117815
118046
  );
117816
- const { stdout: branchHeadStdout } = await execAsync29(
118047
+ const { stdout: branchHeadStdout } = await execAsync30(
117817
118048
  `git rev-parse "${branchName}" 2>/dev/null`,
117818
118049
  { cwd: this.rootDir, encoding: "utf-8" }
117819
118050
  );
@@ -121565,7 +121796,7 @@ ${taskContext}` : ""}`;
121565
121796
 
121566
121797
  // ../engine/src/smart-pull.ts
121567
121798
  import { execFile as execFile13 } from "node:child_process";
121568
- import { promisify as promisify40 } from "node:util";
121799
+ import { promisify as promisify41 } from "node:util";
121569
121800
  async function runGit6(args, cwd, timeoutMs) {
121570
121801
  const result = await execFileAsync9("git", args, {
121571
121802
  cwd,
@@ -121722,7 +121953,7 @@ var execFileAsync9;
121722
121953
  var init_smart_pull = __esm({
121723
121954
  "../engine/src/smart-pull.ts"() {
121724
121955
  "use strict";
121725
- execFileAsync9 = promisify40(execFile13);
121956
+ execFileAsync9 = promisify41(execFile13);
121726
121957
  }
121727
121958
  });
121728
121959
 
@@ -126197,12 +126428,12 @@ var init_finalize_types = __esm({
126197
126428
  });
126198
126429
 
126199
126430
  // ../engine/src/experiment/git-ops.ts
126200
- import { exec as exec33 } from "node:child_process";
126201
- import { promisify as promisify41 } from "node:util";
126431
+ import { exec as exec34 } from "node:child_process";
126432
+ import { promisify as promisify42 } from "node:util";
126202
126433
  async function runGit7(cwd, args) {
126203
126434
  const command = `git ${args.join(" ")}`;
126204
126435
  try {
126205
- const { stdout } = await execAsync30(command, {
126436
+ const { stdout } = await execAsync31(command, {
126206
126437
  cwd,
126207
126438
  timeout: GIT_TIMEOUT_MS8,
126208
126439
  maxBuffer: GIT_MAX_BUFFER7
@@ -126299,12 +126530,12 @@ function defaultGitOps(cwd) {
126299
126530
  }
126300
126531
  };
126301
126532
  }
126302
- var execAsync30, GIT_TIMEOUT_MS8, GIT_MAX_BUFFER7;
126533
+ var execAsync31, GIT_TIMEOUT_MS8, GIT_MAX_BUFFER7;
126303
126534
  var init_git_ops = __esm({
126304
126535
  "../engine/src/experiment/git-ops.ts"() {
126305
126536
  "use strict";
126306
126537
  init_finalize_types();
126307
- execAsync30 = promisify41(exec33);
126538
+ execAsync31 = promisify42(exec34);
126308
126539
  GIT_TIMEOUT_MS8 = 3e4;
126309
126540
  GIT_MAX_BUFFER7 = 10 * 1024 * 1024;
126310
126541
  }
@@ -128036,10 +128267,10 @@ var init_evaluator = __esm({
128036
128267
  });
128037
128268
 
128038
128269
  // ../engine/src/cron-runner.ts
128039
- import { exec as exec34 } from "node:child_process";
128270
+ import { exec as exec35 } from "node:child_process";
128040
128271
  function execCommand(command, options) {
128041
128272
  return new Promise((resolve32, reject) => {
128042
- exec34(command, options, (error, stdout, stderr) => {
128273
+ exec35(command, options, (error, stdout, stderr) => {
128043
128274
  const stdoutText = typeof stdout === "string" ? stdout : String(stdout ?? "");
128044
128275
  const stderrText = typeof stderr === "string" ? stderr : String(stderr ?? "");
128045
128276
  if (error) {
@@ -130954,7 +131185,8 @@ var init_task_agent_sync = __esm({
130954
131185
 
130955
131186
  // ../engine/src/runtimes/in-process-runtime.ts
130956
131187
  import { EventEmitter as EventEmitter19 } from "node:events";
130957
- var InProcessRuntime;
131188
+ import { setImmediate as setImmediateCb4 } from "node:timers";
131189
+ var yieldEventLoop4, InProcessRuntime;
130958
131190
  var init_in_process_runtime = __esm({
130959
131191
  "../engine/src/runtimes/in-process-runtime.ts"() {
130960
131192
  "use strict";
@@ -130981,6 +131213,7 @@ var init_in_process_runtime = __esm({
130981
131213
  init_node_dispatch_validation();
130982
131214
  init_task_agent_sync();
130983
131215
  init_run_audit();
131216
+ yieldEventLoop4 = () => new Promise((resolve32) => setImmediateCb4(resolve32));
130984
131217
  InProcessRuntime = class extends EventEmitter19 {
130985
131218
  /**
130986
131219
  * @param config - Runtime configuration
@@ -131073,6 +131306,7 @@ var init_in_process_runtime = __esm({
131073
131306
  runtimeLog.log(`TaskStore initialized for project ${this.config.projectId}`);
131074
131307
  }
131075
131308
  this.messageStore = new MessageStoreClass(this.taskStore.getDatabase());
131309
+ await yieldEventLoop4();
131076
131310
  this.pluginStore = new PluginStoreClass(this.config.workingDirectory);
131077
131311
  await this.pluginStore.init();
131078
131312
  this.pluginLoader = new PluginLoaderClass({
@@ -131087,6 +131321,7 @@ var init_in_process_runtime = __esm({
131087
131321
  });
131088
131322
  await this.pluginRunner.init();
131089
131323
  runtimeLog.log(`PluginRunner initialized`);
131324
+ await yieldEventLoop4();
131090
131325
  const { reapOrphanWorktrees: reapOrphanWorktrees2, scanIdleWorktrees: scanIdleWorktrees2 } = await Promise.resolve().then(() => (init_worktree_pool(), worktree_pool_exports));
131091
131326
  const settings = await this.taskStore.getSettings();
131092
131327
  try {
@@ -131115,6 +131350,7 @@ var init_in_process_runtime = __esm({
131115
131350
  `Rehydrated worktree pool with ${idleWorktrees.length} idle worktrees`
131116
131351
  );
131117
131352
  }
131353
+ await yieldEventLoop4();
131118
131354
  if (this.config.globalSemaphore) {
131119
131355
  this.globalSemaphore = this.config.globalSemaphore;
131120
131356
  } else {
@@ -131128,6 +131364,7 @@ var init_in_process_runtime = __esm({
131128
131364
  this.centralCore.on("concurrency:changed", this.concurrencyChangedListener);
131129
131365
  }
131130
131366
  }
131367
+ await yieldEventLoop4();
131131
131368
  let agentStoreForReflection;
131132
131369
  try {
131133
131370
  const { AgentStore: AgentStoreClass } = await Promise.resolve().then(() => (init_src(), src_exports));
@@ -131138,6 +131375,7 @@ var init_in_process_runtime = __esm({
131138
131375
  runtimeLog.warn(`AgentStore initialization failed (reflection service will be unavailable):`, agentErr instanceof Error ? agentErr.message : agentErr);
131139
131376
  }
131140
131377
  this.agentStore = agentStoreForReflection;
131378
+ await yieldEventLoop4();
131141
131379
  const missionStore = this.taskStore.getMissionStore();
131142
131380
  this.missionAutopilot = missionStore ? new MissionAutopilot(this.taskStore, missionStore) : void 0;
131143
131381
  const missionAutopilot = this.missionAutopilot;
@@ -131198,6 +131436,7 @@ var init_in_process_runtime = __esm({
131198
131436
  },
131199
131437
  snapshotManager: autoClaimSnapshotManager
131200
131438
  });
131439
+ await yieldEventLoop4();
131201
131440
  this.stuckTaskDetector = new StuckTaskDetector(this.taskStore, {
131202
131441
  beforeRequeue: (taskId, reason, event) => this.selfHealingManager?.checkStuckBudget(taskId, reason, event) ?? Promise.resolve(true),
131203
131442
  onLoopDetected: (event) => this.executor?.handleLoopDetected(event) ?? Promise.resolve(false),
@@ -131320,6 +131559,7 @@ var init_in_process_runtime = __esm({
131320
131559
  }
131321
131560
  })();
131322
131561
  });
131562
+ await yieldEventLoop4();
131323
131563
  if (this.heartbeatMonitor) {
131324
131564
  }
131325
131565
  if (!this.heartbeatMonitor && this.agentStore) {
@@ -131389,7 +131629,9 @@ var init_in_process_runtime = __esm({
131389
131629
  }
131390
131630
  if (this.workerManager) {
131391
131631
  this.workerManager.attachStateChangeListener();
131392
- await this.workerManager.reconcileOrphaned();
131632
+ void this.workerManager.reconcileOrphaned().catch((err) => {
131633
+ runtimeLog.warn(`Deferred workerManager.reconcileOrphaned failed: ${err instanceof Error ? err.message : String(err)}`);
131634
+ });
131393
131635
  }
131394
131636
  try {
131395
131637
  const agents = await this.agentStore.listAgents();
@@ -131470,6 +131712,7 @@ var init_in_process_runtime = __esm({
131470
131712
  } catch (routineErr) {
131471
131713
  runtimeLog.warn("RoutineScheduler initialization skipped:", routineErr instanceof Error ? routineErr.message : routineErr);
131472
131714
  }
131715
+ await yieldEventLoop4();
131473
131716
  this.chatStore ??= new ChatStore(this.taskStore.getFusionDir(), this.taskStore.getDatabase());
131474
131717
  this.selfHealingManager = new SelfHealingManager(this.taskStore, {
131475
131718
  rootDir: this.config.workingDirectory,
@@ -131528,7 +131771,9 @@ var init_in_process_runtime = __esm({
131528
131771
  );
131529
131772
  } else {
131530
131773
  this.startupRecoveryDeferred = false;
131531
- await this.resumeStartupRecoverySequence();
131774
+ void this.resumeStartupRecoverySequence().catch((err) => {
131775
+ runtimeLog.error("Deferred startup recovery sequence failed:", err);
131776
+ });
131532
131777
  }
131533
131778
  this.scheduler.start();
131534
131779
  this.triageProcessor?.start();
@@ -133988,8 +134233,8 @@ var init_provider_adapters = __esm({
133988
134233
 
133989
134234
  // ../engine/src/remote-access/tunnel-process-manager.ts
133990
134235
  import { EventEmitter as EventEmitter24 } from "node:events";
133991
- import { exec as exec35, execFile as execFile14, spawn as spawn8 } from "node:child_process";
133992
- import { promisify as promisify42 } from "node:util";
134236
+ import { exec as exec36, execFile as execFile14, spawn as spawn8 } from "node:child_process";
134237
+ import { promisify as promisify43 } from "node:util";
133993
134238
  function nowIso2() {
133994
134239
  return (/* @__PURE__ */ new Date()).toISOString();
133995
134240
  }
@@ -134029,7 +134274,7 @@ function toStateError(code, err) {
134029
134274
  at: nowIso2()
134030
134275
  };
134031
134276
  }
134032
- var DEFAULT_MAX_LOG_ENTRIES, DEFAULT_STOP_TIMEOUT_MS2, execFileAsync10, execAsync31, LineBuffer, TunnelProcessManager;
134277
+ var DEFAULT_MAX_LOG_ENTRIES, DEFAULT_STOP_TIMEOUT_MS2, execFileAsync10, execAsync32, LineBuffer, TunnelProcessManager;
134033
134278
  var init_tunnel_process_manager = __esm({
134034
134279
  "../engine/src/remote-access/tunnel-process-manager.ts"() {
134035
134280
  "use strict";
@@ -134038,8 +134283,8 @@ var init_tunnel_process_manager = __esm({
134038
134283
  init_provider_adapters();
134039
134284
  DEFAULT_MAX_LOG_ENTRIES = 400;
134040
134285
  DEFAULT_STOP_TIMEOUT_MS2 = 5e3;
134041
- execFileAsync10 = promisify42(execFile14);
134042
- execAsync31 = promisify42(exec35);
134286
+ execFileAsync10 = promisify43(execFile14);
134287
+ execAsync32 = promisify43(exec36);
134043
134288
  LineBuffer = class {
134044
134289
  pending = "";
134045
134290
  push(chunk) {
@@ -134145,7 +134390,7 @@ var init_tunnel_process_manager = __esm({
134145
134390
  }
134146
134391
  }
134147
134392
  try {
134148
- const { stdout } = await execAsync31('pgrep -f "tailscale funnel"', { timeout: 5e3 });
134393
+ const { stdout } = await execAsync32('pgrep -f "tailscale funnel"', { timeout: 5e3 });
134149
134394
  const pids = stdout.split(/\s+/).map((value) => Number(value.trim())).filter((value) => Number.isInteger(value) && value > 0);
134150
134395
  await Promise.all(pids.map(async (pid) => {
134151
134396
  try {
@@ -134441,7 +134686,7 @@ var init_tunnel_process_manager = __esm({
134441
134686
 
134442
134687
  // ../engine/src/project-engine.ts
134443
134688
  import { execFile as execFile15 } from "node:child_process";
134444
- import { promisify as promisify43 } from "node:util";
134689
+ import { promisify as promisify44 } from "node:util";
134445
134690
  function formatErrorDetails(error) {
134446
134691
  if (error instanceof Error) {
134447
134692
  return {
@@ -134488,7 +134733,7 @@ var init_project_engine = __esm({
134488
134733
  init_run_audit();
134489
134734
  init_verification_followup_dedup();
134490
134735
  init_tunnel_process_manager();
134491
- execFileAsync11 = promisify43(execFile15);
134736
+ execFileAsync11 = promisify44(execFile15);
134492
134737
  MERGE_HANDOFF_GRACE_MS = 300;
134493
134738
  isRemoteActive = (ra) => ra?.activeProvider != null && (ra.providers[ra.activeProvider]?.enabled ?? false);
134494
134739
  ProjectEngine = class _ProjectEngine {
@@ -139095,12 +139340,7 @@ async function shouldUseHybridExecutor(centralCore) {
139095
139340
  if (nodes.length > 1) {
139096
139341
  return { enabled: true, reason: "multi-node" };
139097
139342
  }
139098
- const projects = await centralCore.listProjects();
139099
- const liveProjects = projects.filter((project) => project.status === "active" || project.status === "initializing");
139100
- if (liveProjects.length > 1) {
139101
- return { enabled: true, reason: "multi-project" };
139102
- }
139103
- return { enabled: false, reason: "single-project-local-only" };
139343
+ return { enabled: false, reason: "single-node-local-only" };
139104
139344
  } catch {
139105
139345
  return { enabled: false, reason: "central-unavailable" };
139106
139346
  }
@@ -142701,11 +142941,11 @@ var init_context = __esm({
142701
142941
  });
142702
142942
 
142703
142943
  // ../dashboard/src/github.ts
142704
- import { exec as exec36 } from "node:child_process";
142944
+ import { exec as exec37 } from "node:child_process";
142705
142945
  import { mkdtemp as mkdtemp2, rm as rm6 } from "node:fs/promises";
142706
142946
  import { tmpdir as tmpdir7 } from "node:os";
142707
142947
  import { join as join53 } from "node:path";
142708
- import { promisify as promisify44 } from "node:util";
142948
+ import { promisify as promisify45 } from "node:util";
142709
142949
  function quoteGitArg(value) {
142710
142950
  return `'${value.replaceAll("'", "'\\''")}'`;
142711
142951
  }
@@ -142958,12 +143198,12 @@ function mapGraphQlBatchIssueStateReason(stateReason) {
142958
143198
  return void 0;
142959
143199
  }
142960
143200
  }
142961
- var execAsync32, PR_REVIEW_PAGE_SIZE, MAX_PR_REVIEW_PAGES, MAX_BADGE_BATCH_SIZE, BATCH_RETRY_DELAY_MS, MAX_BATCH_RETRIES, GitHubClient;
143201
+ var execAsync33, PR_REVIEW_PAGE_SIZE, MAX_PR_REVIEW_PAGES, MAX_BADGE_BATCH_SIZE, BATCH_RETRY_DELAY_MS, MAX_BATCH_RETRIES, GitHubClient;
142962
143202
  var init_github = __esm({
142963
143203
  "../dashboard/src/github.ts"() {
142964
143204
  "use strict";
142965
143205
  init_src();
142966
- execAsync32 = promisify44(exec36);
143206
+ execAsync33 = promisify45(exec37);
142967
143207
  PR_REVIEW_PAGE_SIZE = 100;
142968
143208
  MAX_PR_REVIEW_PAGES = 10;
142969
143209
  MAX_BADGE_BATCH_SIZE = 100;
@@ -143616,17 +143856,17 @@ var init_github = __esm({
143616
143856
  let usedFallbackFiles = false;
143617
143857
  if (opts.repoRoot) {
143618
143858
  try {
143619
- await execAsync32(`git -C ${quoteGitArg(opts.repoRoot)} rev-parse --git-dir`, {
143859
+ await execAsync33(`git -C ${quoteGitArg(opts.repoRoot)} rev-parse --git-dir`, {
143620
143860
  timeout: 3e4,
143621
143861
  maxBuffer: 10 * 1024 * 1024
143622
143862
  });
143623
143863
  const baseRef = `origin/${opts.baseBranch}`;
143624
143864
  const headRef = `origin/${opts.headBranch}`;
143625
- await execAsync32(`git -C ${quoteGitArg(opts.repoRoot)} fetch --no-tags --quiet origin ${quoteGitArg(opts.baseBranch)} ${quoteGitArg(opts.headBranch)}`, {
143865
+ await execAsync33(`git -C ${quoteGitArg(opts.repoRoot)} fetch --no-tags --quiet origin ${quoteGitArg(opts.baseBranch)} ${quoteGitArg(opts.headBranch)}`, {
143626
143866
  timeout: 3e4,
143627
143867
  maxBuffer: 10 * 1024 * 1024
143628
143868
  }).catch(() => void 0);
143629
- const { stdout: mergeBaseStdout } = await execAsync32(
143869
+ const { stdout: mergeBaseStdout } = await execAsync33(
143630
143870
  `git -C ${quoteGitArg(opts.repoRoot)} merge-base ${quoteGitArg(baseRef)} ${quoteGitArg(headRef)}`,
143631
143871
  { timeout: 3e4, maxBuffer: 10 * 1024 * 1024 }
143632
143872
  );
@@ -143635,12 +143875,12 @@ var init_github = __esm({
143635
143875
  const indexPath = join53(indexDir, "index");
143636
143876
  const gitEnv = { ...process.env, GIT_INDEX_FILE: indexPath };
143637
143877
  try {
143638
- await execAsync32(`git -C ${quoteGitArg(opts.repoRoot)} read-tree -m ${quoteGitArg(mergeBase)} ${quoteGitArg(baseRef)} ${quoteGitArg(headRef)}`, {
143878
+ await execAsync33(`git -C ${quoteGitArg(opts.repoRoot)} read-tree -m ${quoteGitArg(mergeBase)} ${quoteGitArg(baseRef)} ${quoteGitArg(headRef)}`, {
143639
143879
  timeout: 3e4,
143640
143880
  maxBuffer: 10 * 1024 * 1024,
143641
143881
  env: gitEnv
143642
143882
  }).catch(() => void 0);
143643
- const { stdout } = await execAsync32(`git -C ${quoteGitArg(opts.repoRoot)} ls-files --unmerged`, {
143883
+ const { stdout } = await execAsync33(`git -C ${quoteGitArg(opts.repoRoot)} ls-files --unmerged`, {
143644
143884
  timeout: 3e4,
143645
143885
  maxBuffer: 10 * 1024 * 1024,
143646
143886
  env: gitEnv
@@ -145975,7 +146215,7 @@ var init_github_poll = __esm({
145975
146215
  });
145976
146216
 
145977
146217
  // ../dashboard/src/pr-metadata-generator.ts
145978
- import { promisify as promisify45 } from "node:util";
146218
+ import { promisify as promisify46 } from "node:util";
145979
146219
  import { exec as execCb } from "node:child_process";
145980
146220
  import { access as access8, readFile as readFile26 } from "node:fs/promises";
145981
146221
  import { join as join54 } from "node:path";
@@ -146083,7 +146323,7 @@ Closes ${taskId}`.trim()]
146083
146323
  return out.join("\n");
146084
146324
  }
146085
146325
  async function runCommand(command, cwd) {
146086
- const { stdout } = await execAsync33(command, {
146326
+ const { stdout } = await execAsync34(command, {
146087
146327
  cwd,
146088
146328
  timeout: 15e3,
146089
146329
  maxBuffer: 10 * 1024 * 1024
@@ -146169,31 +146409,31 @@ async function generatePrMetadata(input) {
146169
146409
  templateUsed: templateExists
146170
146410
  };
146171
146411
  }
146172
- var execAsync33;
146412
+ var execAsync34;
146173
146413
  var init_pr_metadata_generator = __esm({
146174
146414
  "../dashboard/src/pr-metadata-generator.ts"() {
146175
146415
  "use strict";
146176
146416
  init_src();
146177
146417
  init_src2();
146178
- execAsync33 = promisify45(execCb);
146418
+ execAsync34 = promisify46(execCb);
146179
146419
  }
146180
146420
  });
146181
146421
 
146182
146422
  // ../dashboard/src/routes/resolve-diff-base.ts
146183
146423
  import { execFile as execFile16 } from "node:child_process";
146184
- import { promisify as promisify46 } from "node:util";
146424
+ import { promisify as promisify47 } from "node:util";
146185
146425
  var execFileAsync12;
146186
146426
  var init_resolve_diff_base = __esm({
146187
146427
  "../dashboard/src/routes/resolve-diff-base.ts"() {
146188
146428
  "use strict";
146189
- execFileAsync12 = promisify46(execFile16);
146429
+ execFileAsync12 = promisify47(execFile16);
146190
146430
  }
146191
146431
  });
146192
146432
 
146193
146433
  // ../dashboard/src/routes/register-git-github.ts
146194
146434
  import { exec as execCb2, spawn as spawn12 } from "node:child_process";
146195
- import { promisify as promisify47 } from "node:util";
146196
- var execAsync34, PR_ROUTE_MAX_BUFFER_BYTES;
146435
+ import { promisify as promisify48 } from "node:util";
146436
+ var execAsync35, PR_ROUTE_MAX_BUFFER_BYTES;
146197
146437
  var init_register_git_github = __esm({
146198
146438
  "../dashboard/src/routes/register-git-github.ts"() {
146199
146439
  "use strict";
@@ -146210,7 +146450,7 @@ var init_register_git_github = __esm({
146210
146450
  init_pr_metadata_generator();
146211
146451
  init_github_webhooks();
146212
146452
  init_resolve_diff_base();
146213
- execAsync34 = promisify47(execCb2);
146453
+ execAsync35 = promisify48(execCb2);
146214
146454
  PR_ROUTE_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
146215
146455
  }
146216
146456
  });
@@ -146248,34 +146488,6 @@ var init_register_planning_subtask_routes = __esm({
146248
146488
  }
146249
146489
  });
146250
146490
 
146251
- // ../dashboard/src/routes/chat-attachment-config.ts
146252
- var CHAT_MAX_ATTACHMENT_SIZE;
146253
- var init_chat_attachment_config = __esm({
146254
- "../dashboard/src/routes/chat-attachment-config.ts"() {
146255
- "use strict";
146256
- CHAT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024;
146257
- }
146258
- });
146259
-
146260
- // ../dashboard/src/rate-limit.ts
146261
- var init_rate_limit = __esm({
146262
- "../dashboard/src/rate-limit.ts"() {
146263
- "use strict";
146264
- init_api_error();
146265
- }
146266
- });
146267
-
146268
- // ../dashboard/src/routes/register-chat-routes.ts
146269
- var init_register_chat_routes = __esm({
146270
- "../dashboard/src/routes/register-chat-routes.ts"() {
146271
- "use strict";
146272
- init_api_error();
146273
- init_chat_attachment_config();
146274
- init_rate_limit();
146275
- init_sse_buffer();
146276
- }
146277
- });
146278
-
146279
146491
  // ../dashboard/src/chat.ts
146280
146492
  import { EventEmitter as EventEmitter31 } from "node:events";
146281
146493
  import { SessionManager as SessionManager3 } from "@mariozechner/pi-coding-agent";
@@ -146426,6 +146638,36 @@ var init_chat_project_services = __esm({
146426
146638
  "use strict";
146427
146639
  init_src();
146428
146640
  init_chat();
146641
+ }
146642
+ });
146643
+
146644
+ // ../dashboard/src/routes/chat-attachment-config.ts
146645
+ var CHAT_MAX_ATTACHMENT_SIZE;
146646
+ var init_chat_attachment_config = __esm({
146647
+ "../dashboard/src/routes/chat-attachment-config.ts"() {
146648
+ "use strict";
146649
+ CHAT_MAX_ATTACHMENT_SIZE = 5 * 1024 * 1024;
146650
+ }
146651
+ });
146652
+
146653
+ // ../dashboard/src/rate-limit.ts
146654
+ var init_rate_limit = __esm({
146655
+ "../dashboard/src/rate-limit.ts"() {
146656
+ "use strict";
146657
+ init_api_error();
146658
+ }
146659
+ });
146660
+
146661
+ // ../dashboard/src/routes/register-chat-routes.ts
146662
+ var init_register_chat_routes = __esm({
146663
+ "../dashboard/src/routes/register-chat-routes.ts"() {
146664
+ "use strict";
146665
+ init_api_error();
146666
+ init_chat_project_services();
146667
+ init_chat_attachment_config();
146668
+ init_rate_limit();
146669
+ init_sse_buffer();
146670
+ init_chat_project_services();
146429
146671
  init_project_store_resolver();
146430
146672
  }
146431
146673
  });
@@ -151421,12 +151663,12 @@ var init_register_agents_projects_nodes = __esm({
151421
151663
 
151422
151664
  // ../dashboard/src/exec-file.ts
151423
151665
  import { execFile as execFile17 } from "node:child_process";
151424
- import { promisify as promisify48 } from "node:util";
151666
+ import { promisify as promisify49 } from "node:util";
151425
151667
  var execFileAsync13;
151426
151668
  var init_exec_file = __esm({
151427
151669
  "../dashboard/src/exec-file.ts"() {
151428
151670
  "use strict";
151429
- execFileAsync13 = promisify48(execFile17);
151671
+ execFileAsync13 = promisify49(execFile17);
151430
151672
  }
151431
151673
  });
151432
151674
 
@@ -160157,7 +160399,7 @@ function wrapText(text, width) {
160157
160399
  }
160158
160400
  return lines;
160159
160401
  }
160160
- async function runTaskPlan(initialPlanArg, yesFlag = false, projectName) {
160402
+ async function runTaskPlan(initialPlanArg, yesFlag = false, projectName, baseBranch) {
160161
160403
  let initialPlan = initialPlanArg;
160162
160404
  if (!initialPlan) {
160163
160405
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
@@ -160273,6 +160515,7 @@ async function runTaskPlan(initialPlanArg, yesFlag = false, projectName) {
160273
160515
  description: result.data.description,
160274
160516
  column: "triage",
160275
160517
  dependencies: result.data.suggestedDependencies,
160518
+ baseBranch: baseBranch?.trim() || void 0,
160276
160519
  source: { sourceType: "cli" }
160277
160520
  });
160278
160521
  console.log();
@@ -161602,7 +161845,8 @@ ${sourceUrl}`
161602
161845
  Type8.String({
161603
161846
  description: "Initial plan description (optional) \u2014 the AI will ask clarifying questions if not provided"
161604
161847
  })
161605
- )
161848
+ ),
161849
+ baseBranch: Type8.Optional(Type8.String({ description: "Optional base branch for the task created from this planning session" }))
161606
161850
  }),
161607
161851
  async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
161608
161852
  const { runTaskPlan: runTaskPlan2 } = await Promise.resolve().then(() => (init_task(), task_exports));
@@ -161621,7 +161865,7 @@ ${sourceUrl}`
161621
161865
  };
161622
161866
  let taskId;
161623
161867
  try {
161624
- taskId = await runTaskPlan2(params.description, true);
161868
+ taskId = await runTaskPlan2(params.description, true, void 0, params.baseBranch);
161625
161869
  } catch (err) {
161626
161870
  console.error = originalError;
161627
161871
  console.log = originalLog;
@@ -162272,14 +162516,16 @@ Planning session completed. Task ${taskId} is now in planning and will be auto-p
162272
162516
  ),
162273
162517
  autoAdvance: Type8.Optional(
162274
162518
  Type8.Boolean({ description: "Automatically activate the next pending slice when the current slice completes" })
162275
- )
162519
+ ),
162520
+ baseBranch: Type8.Optional(Type8.String({ description: "Optional integration base branch for tasks triaged from this mission" }))
162276
162521
  }),
162277
162522
  async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
162278
162523
  const store = await getStore2(ctx.cwd);
162279
162524
  const missionStore = store.getMissionStore();
162280
162525
  const mission = missionStore.createMission({
162281
162526
  title: params.title.trim(),
162282
- description: params.description?.trim()
162527
+ description: params.description?.trim(),
162528
+ baseBranch: params.baseBranch?.trim() || void 0
162283
162529
  });
162284
162530
  if (params.autoAdvance !== void 0) {
162285
162531
  missionStore.updateMission(mission.id, { autoAdvance: params.autoAdvance });