@sideboard-ai/core 0.1.60 → 0.1.62

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 (35) hide show
  1. package/dist/{agents-EADRAAPG.js → agents-KF3J3C53.js} +2 -2
  2. package/dist/{agents-B2723EOF.js → agents-QLSFIQAO.js} +2 -2
  3. package/dist/{app-settings-TBHTJWLQ.js → app-settings-HK4KAM4R.js} +3 -1
  4. package/dist/{app-settings-YBNZ4XSR.js → app-settings-LTSFG7QJ.js} +3 -1
  5. package/dist/{chunk-XWPKLRB3.js → chunk-27MAWNKY.js} +2 -2
  6. package/dist/{chunk-CHGOMFTA.js → chunk-2FEA4LDA.js} +4 -4
  7. package/dist/{chunk-MX7UH5AT.js → chunk-2MCNURQV.js} +2 -2
  8. package/dist/{chunk-MFGGIRUA.js → chunk-3KKNTHUC.js} +1 -1
  9. package/dist/{chunk-2P2UK7E7.js → chunk-46KMKHSD.js} +2 -2
  10. package/dist/{chunk-75QR74KM.js → chunk-6CUJQKTJ.js} +10 -0
  11. package/dist/{chunk-HLEX5AQ6.js → chunk-7FD7COKE.js} +4 -0
  12. package/dist/{chunk-QJBC4BRK.js → chunk-A6FOKNOU.js} +2 -2
  13. package/dist/{chunk-FGNBTFRD.js → chunk-DDN3UF4R.js} +10 -0
  14. package/dist/{chunk-MLAST5BB.js → chunk-DXTGDXO2.js} +4 -4
  15. package/dist/{chunk-TSRXOSVD.js → chunk-FWJYLBO6.js} +4 -0
  16. package/dist/{chunk-NTYRBRE7.js → chunk-NVU7EC2E.js} +2 -2
  17. package/dist/{chunk-P7EQUFB6.js → chunk-UGXSSBFJ.js} +1 -1
  18. package/dist/{chunk-ZXDOI6IH.js → chunk-ZF5YJCXO.js} +2 -2
  19. package/dist/{coordinator-prompt-4P23VVFC.js → coordinator-prompt-LKG3SHMI.js} +4 -4
  20. package/dist/{coordinator-prompt-LNWHZ64D.js → coordinator-prompt-N2R6FGZK.js} +4 -4
  21. package/dist/{global-workspace-TMMAVRVW.js → global-workspace-LALWQWRJ.js} +5 -5
  22. package/dist/{global-workspace-BHT4XUAA.js → global-workspace-YOAUQCMA.js} +5 -5
  23. package/dist/index.cjs +124 -18
  24. package/dist/index.d.cts +26 -2
  25. package/dist/index.d.ts +26 -2
  26. package/dist/index.js +131 -39
  27. package/dist/mcp/run-stdio.cjs +122 -18
  28. package/dist/mcp/run-stdio.js +127 -37
  29. package/dist/{thread-store-GHOADGL2.js → thread-store-BUBR24YA.js} +1 -1
  30. package/dist/{thread-store-UJIGMI5J.js → thread-store-XTPFCJAI.js} +1 -1
  31. package/dist/{workspaces-GFPGDGCS.js → workspaces-E75POJXP.js} +6 -6
  32. package/dist/{workspaces-3GO3EDQG.js → workspaces-VCAIHVIE.js} +6 -6
  33. package/dist/{worktree-3L2G6PCM.js → worktree-LZEGVQSN.js} +2 -2
  34. package/dist/{worktree-GBLHEFHR.js → worktree-MV4WRW6G.js} +2 -2
  35. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  listWorkspaces,
5
5
  removeWorkspace,
6
6
  syncWorkspacesFromThreads
7
- } from "./chunk-2P2UK7E7.js";
7
+ } from "./chunk-46KMKHSD.js";
8
8
  import {
9
9
  CLOUD_COORDINATOR_BUSY_REPLY,
10
10
  CLOUD_COORDINATOR_STOPPED_REPLY,
@@ -24,7 +24,7 @@ import {
24
24
  orchestratorSessionPoisonedByBuiltins,
25
25
  parseForceStopMessage,
26
26
  takenTeamSlugsForOrchestration
27
- } from "./chunk-MLAST5BB.js";
27
+ } from "./chunk-DXTGDXO2.js";
28
28
  import {
29
29
  BRIGHTSY_MCP_ALLOWED_TOOLS,
30
30
  CLAUDE_MODEL_CATALOG,
@@ -70,7 +70,7 @@ import {
70
70
  resolveQuotaFallbackAgent,
71
71
  sanitizeMcpServerName,
72
72
  writeInjectedMcpConfig
73
- } from "./chunk-ZXDOI6IH.js";
73
+ } from "./chunk-ZF5YJCXO.js";
74
74
  import {
75
75
  ORCHESTRATOR_AGENT_KINDS,
76
76
  assertOrchestratorCapableAgent,
@@ -118,11 +118,12 @@ import {
118
118
  enrichWorkspacesWithGithub,
119
119
  ensureGlobalCoordinatorCwd,
120
120
  formatWorkspaceInventory
121
- } from "./chunk-XWPKLRB3.js";
121
+ } from "./chunk-27MAWNKY.js";
122
122
  import {
123
123
  HARNESS_ENV_KEYS,
124
124
  appSettingsPath,
125
125
  applyAppEnvironment,
126
+ autoArchiveOnMergeEnabled,
126
127
  autoCleanupOrphansEnabled,
127
128
  autoRenameBranchEnabled,
128
129
  autoRunAfterSetupEnabled,
@@ -157,7 +158,7 @@ import {
157
158
  updateClaudeSettings,
158
159
  updateDefaultsSettings,
159
160
  updateIntegrationsSettings
160
- } from "./chunk-75QR74KM.js";
161
+ } from "./chunk-6CUJQKTJ.js";
161
162
  import {
162
163
  FAMOUS_SOCCER_TEAMS,
163
164
  addPrStackLayer,
@@ -220,7 +221,7 @@ import {
220
221
  worktreeDisplayLabel,
221
222
  worktreeDisplayLabelForGroup,
222
223
  worktreeNameFromPath
223
- } from "./chunk-P7EQUFB6.js";
224
+ } from "./chunk-UGXSSBFJ.js";
224
225
  import {
225
226
  ATTACHMENTS_DIR,
226
227
  LEGACY_ATTACHMENTS_DIR,
@@ -240,7 +241,7 @@ import {
240
241
  updateThread,
241
242
  withThreadLock,
242
243
  writeThread
243
- } from "./chunk-TSRXOSVD.js";
244
+ } from "./chunk-FWJYLBO6.js";
244
245
  import {
245
246
  THINKING_EFFORTS,
246
247
  isThinkingEffort,
@@ -706,9 +707,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
706
707
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
707
708
  );
708
709
  }
709
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-TMMAVRVW.js");
710
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-LALWQWRJ.js");
710
711
  if (isGlobalThread2(thread)) {
711
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-LNWHZ64D.js");
712
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-N2R6FGZK.js");
712
713
  ensureGlobalCoordinatorCwd2(
713
714
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
714
715
  );
@@ -2978,7 +2979,7 @@ async function createThread(input, _onSetupLine) {
2978
2979
  return readThread(thread.id) ?? thread;
2979
2980
  }
2980
2981
  async function listLinearIssues(agent, repoPath) {
2981
- const { getAdapter: getAdapter2 } = await import("./agents-B2723EOF.js");
2982
+ const { getAdapter: getAdapter2 } = await import("./agents-QLSFIQAO.js");
2982
2983
  await requireAgent(agent, { requireLinear: true });
2983
2984
  const adapter = getAdapter2(agent);
2984
2985
  if (!adapter.listLinearIssues) {
@@ -3022,6 +3023,8 @@ function worktreeBindingFrom(from) {
3022
3023
  parentThreadId: from.parentThreadId,
3023
3024
  prUrl: from.prUrl,
3024
3025
  prTitle: from.prTitle,
3026
+ prState: from.prState,
3027
+ skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
3025
3028
  stackId: from.stackId,
3026
3029
  stackLayer: from.stackLayer
3027
3030
  };
@@ -3519,7 +3522,7 @@ async function adoptThread(input) {
3519
3522
  messages: input.messages ?? []
3520
3523
  });
3521
3524
  writeThread(thread);
3522
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-3GO3EDQG.js");
3525
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-VCAIHVIE.js");
3523
3526
  await ensureWorkspace2(repoPath);
3524
3527
  return thread;
3525
3528
  }
@@ -3721,6 +3724,20 @@ async function importConductorWorkspaceAsync(workspaceId) {
3721
3724
  import { EventEmitter } from "events";
3722
3725
  import { existsSync as existsSync13 } from "fs";
3723
3726
 
3727
+ // src/git/pr-merge-archive.ts
3728
+ function normalizePrState(state) {
3729
+ return (state ?? "").trim().toUpperCase();
3730
+ }
3731
+ function shouldAutoArchiveOnPrMerge(opts) {
3732
+ if (!opts.autoArchiveEnabled) return false;
3733
+ if (opts.isGlobal) return false;
3734
+ if (opts.skipAutoArchiveOnMerge) return false;
3735
+ if (opts.threadStatus === "archived") return false;
3736
+ const next = normalizePrState(opts.nextPrState);
3737
+ if (next !== "MERGED") return false;
3738
+ return normalizePrState(opts.previousPrState) !== "MERGED";
3739
+ }
3740
+
3724
3741
  // src/git/orphan-cleanup.ts
3725
3742
  import { existsSync as existsSync10, readdirSync as readdirSync4, statSync as statSync5 } from "fs";
3726
3743
  import { join as join8 } from "path";
@@ -4456,7 +4473,7 @@ var Orchestrator = class {
4456
4473
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
4457
4474
  });
4458
4475
  }
4459
- const { autoCleanupOrphansEnabled: autoCleanupOrphansEnabled2 } = await import("./app-settings-TBHTJWLQ.js");
4476
+ const { autoCleanupOrphansEnabled: autoCleanupOrphansEnabled2 } = await import("./app-settings-HK4KAM4R.js");
4460
4477
  if (autoCleanupOrphansEnabled2() && shouldRunWorktreeCleanup() && orphans.length > 0) {
4461
4478
  await cleanupOrphanWorktrees({ repoPaths });
4462
4479
  }
@@ -4613,7 +4630,7 @@ var Orchestrator = class {
4613
4630
  }
4614
4631
  async finishCreateThread(threadId, prompt) {
4615
4632
  await this.runSetupAfterCreate(threadId);
4616
- const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await import("./app-settings-TBHTJWLQ.js");
4633
+ const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await import("./app-settings-HK4KAM4R.js");
4617
4634
  if (autoRunAfterSetupEnabled2()) {
4618
4635
  try {
4619
4636
  await this.startDev(threadId);
@@ -4884,7 +4901,7 @@ var Orchestrator = class {
4884
4901
  });
4885
4902
  const artifactDirective = isBrightsy ? null : formatArtifactDirective();
4886
4903
  const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
4887
- const { autoRenameBranchEnabled: autoRenameBranchEnabled2 } = await import("./app-settings-TBHTJWLQ.js");
4904
+ const { autoRenameBranchEnabled: autoRenameBranchEnabled2 } = await import("./app-settings-HK4KAM4R.js");
4888
4905
  const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
4889
4906
  customPrompt: settings?.prompts?.renameBranch
4890
4907
  }) : null;
@@ -5520,10 +5537,19 @@ var Orchestrator = class {
5520
5537
  this.assertNotGlobal(thread, "Merge PR");
5521
5538
  if (!selector) throw new Error("No pull request linked to this thread");
5522
5539
  const result = await mergePr(cwd, selector);
5523
- if (result.url && result.url !== thread.prUrl) {
5524
- updateThread(thread.id, { prUrl: result.url });
5525
- }
5526
- return result;
5540
+ const state = normalizePrState(result.state) || "MERGED";
5541
+ const metaLike = {
5542
+ number: 0,
5543
+ title: thread.prTitle ?? thread.title,
5544
+ url: result.url || thread.prUrl || "",
5545
+ state,
5546
+ isDraft: false,
5547
+ reviewDecision: null,
5548
+ baseRefName: "",
5549
+ headRefName: ""
5550
+ };
5551
+ await this.persistPrMetaAndMaybeArchive(thread, metaLike);
5552
+ return { url: metaLike.url, state };
5527
5553
  }
5528
5554
  /** Resolve PR selector and optionally persist `prUrl` when found. */
5529
5555
  async withPrSelector(threadRef) {
@@ -5545,19 +5571,55 @@ var Orchestrator = class {
5545
5571
  if (!selector) return null;
5546
5572
  const meta = await getPrMeta(cwd, selector);
5547
5573
  if (meta) {
5548
- const patch = {};
5549
- if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
5550
- if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
5551
- if (Object.keys(patch).length > 0) {
5552
- updateThread(thread.id, patch);
5553
- const latest = this.requireThread(thread.id);
5554
- if (!latest.userSetTitle && meta.title && latest.title !== meta.title) {
5555
- updateThread(thread.id, { title: meta.title });
5556
- }
5557
- }
5574
+ await this.persistPrMetaAndMaybeArchive(thread, meta);
5558
5575
  }
5559
5576
  return meta;
5560
5577
  }
5578
+ /**
5579
+ * Persist PR URL/title/state and Conductor-style auto-archive when the PR
5580
+ * first becomes MERGED.
5581
+ */
5582
+ async persistPrMetaAndMaybeArchive(thread, meta) {
5583
+ const prevState = normalizePrState(thread.prState);
5584
+ const nextState = normalizePrState(meta.state);
5585
+ const patch = {};
5586
+ if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
5587
+ if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
5588
+ if (nextState && nextState !== prevState) patch.prState = nextState;
5589
+ if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
5590
+ patch.skipAutoArchiveOnMerge = false;
5591
+ }
5592
+ if (Object.keys(patch).length > 0) {
5593
+ updateThread(thread.id, patch);
5594
+ const latest2 = this.requireThread(thread.id);
5595
+ if (!latest2.userSetTitle && meta.title && latest2.title !== meta.title) {
5596
+ updateThread(thread.id, { title: meta.title });
5597
+ }
5598
+ }
5599
+ const { autoArchiveOnMergeEnabled: autoArchiveOnMergeEnabled2 } = await import("./app-settings-HK4KAM4R.js");
5600
+ const latest = this.requireThread(thread.id);
5601
+ if (!shouldAutoArchiveOnPrMerge({
5602
+ previousPrState: prevState || null,
5603
+ nextPrState: nextState,
5604
+ threadStatus: latest.status,
5605
+ skipAutoArchiveOnMerge: latest.skipAutoArchiveOnMerge,
5606
+ autoArchiveEnabled: autoArchiveOnMergeEnabled2(),
5607
+ isGlobal: isGlobalThread(latest)
5608
+ })) {
5609
+ return;
5610
+ }
5611
+ const siblings = threadsSharingWorktree(latest.worktreePath);
5612
+ for (const t of siblings) {
5613
+ const sibPatch = { prState: "MERGED" };
5614
+ if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
5615
+ if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
5616
+ if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
5617
+ }
5618
+ for (const t of siblings) {
5619
+ if (this.requireThread(t.id).status === "archived") continue;
5620
+ await this.archive(t.id);
5621
+ }
5622
+ }
5561
5623
  async getPrStack(threadRef) {
5562
5624
  const thread = this.requireThread(threadRef);
5563
5625
  if (!thread.worktreePath?.trim()) return null;
@@ -5735,7 +5797,9 @@ var Orchestrator = class {
5735
5797
  const thread = this.requireThread(threadRef);
5736
5798
  this.stop(thread.id);
5737
5799
  if (isGlobalThread(thread)) {
5738
- return setStatus(thread.id, "archived");
5800
+ const archived2 = setStatus(thread.id, "archived");
5801
+ this.emit({ type: "status_changed", threadId: archived2.id, status: "archived" });
5802
+ return archived2;
5739
5803
  }
5740
5804
  const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
5741
5805
  if (siblings.length === 0) {
@@ -5753,9 +5817,10 @@ var Orchestrator = class {
5753
5817
  await removeWorktree(thread.repoPath, thread.worktreePath);
5754
5818
  }
5755
5819
  const archived = setStatus(thread.id, "archived");
5820
+ this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
5756
5821
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
5757
5822
  try {
5758
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-3GO3EDQG.js");
5823
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-VCAIHVIE.js");
5759
5824
  await ensureWorkspace2(thread.repoPath);
5760
5825
  } catch {
5761
5826
  }
@@ -5776,7 +5841,7 @@ var Orchestrator = class {
5776
5841
  await runArchiveScript(thread.repoPath, thread.worktreePath);
5777
5842
  } catch {
5778
5843
  }
5779
- const { deleteBranchOnPurgeEnabled: deleteBranchOnPurgeEnabled2 } = await import("./app-settings-TBHTJWLQ.js");
5844
+ const { deleteBranchOnPurgeEnabled: deleteBranchOnPurgeEnabled2 } = await import("./app-settings-HK4KAM4R.js");
5780
5845
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled2();
5781
5846
  await removeWorktree(thread.repoPath, thread.worktreePath, {
5782
5847
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -5792,10 +5857,12 @@ var Orchestrator = class {
5792
5857
  if (isGlobalThread(thread)) {
5793
5858
  const { globalAgentCwd: globalAgentCwd2 } = await import("./paths-VPH3ITBK.js");
5794
5859
  updateThread(thread.id, { worktreePath: globalAgentCwd2() });
5795
- return setStatus(thread.id, "idle");
5860
+ const restored2 = setStatus(thread.id, "idle");
5861
+ this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
5862
+ return restored2;
5796
5863
  }
5797
5864
  if (!existsSync13(thread.worktreePath)) {
5798
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-GBLHEFHR.js");
5865
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-MV4WRW6G.js");
5799
5866
  const { execa: execa6 } = await import("execa");
5800
5867
  const slug = thread.worktreePath.split("/").pop();
5801
5868
  const dest = thread.worktreePath;
@@ -5805,7 +5872,31 @@ var Orchestrator = class {
5805
5872
  void createThreadWorktree2;
5806
5873
  void slug;
5807
5874
  }
5808
- return setStatus(thread.id, "idle");
5875
+ const restorePatch = {};
5876
+ let alreadyMerged = normalizePrState(thread.prState) === "MERGED";
5877
+ if (!alreadyMerged && thread.prUrl?.trim() && thread.worktreePath?.trim()) {
5878
+ try {
5879
+ const selector = resolvePrSelector(thread);
5880
+ if (selector) {
5881
+ const meta = await getPrMeta(thread.worktreePath, selector);
5882
+ if (meta) {
5883
+ const state = normalizePrState(meta.state);
5884
+ if (meta.url && meta.url !== thread.prUrl) restorePatch.prUrl = meta.url;
5885
+ if (meta.title && meta.title !== thread.prTitle) restorePatch.prTitle = meta.title;
5886
+ if (state) restorePatch.prState = state;
5887
+ if (state === "MERGED") alreadyMerged = true;
5888
+ }
5889
+ }
5890
+ } catch {
5891
+ }
5892
+ }
5893
+ if (alreadyMerged) restorePatch.skipAutoArchiveOnMerge = true;
5894
+ if (Object.keys(restorePatch).length > 0) {
5895
+ updateThread(thread.id, restorePatch);
5896
+ }
5897
+ const restored = setStatus(thread.id, "idle");
5898
+ this.emit({ type: "status_changed", threadId: restored.id, status: restored.status });
5899
+ return restored;
5809
5900
  }
5810
5901
  async attachCommand(threadRef) {
5811
5902
  const thread = this.requireThread(threadRef);
@@ -5880,7 +5971,7 @@ async function startOrchestration(opts) {
5880
5971
  sourceRef: "default",
5881
5972
  ...createOpts
5882
5973
  }).catch(async () => {
5883
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-GBLHEFHR.js");
5974
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-MV4WRW6G.js");
5884
5975
  const repo = await resolveRepoRoot2(repoPath);
5885
5976
  const def = await resolveDefaultBranch2(repo);
5886
5977
  return createThread({
@@ -5890,7 +5981,7 @@ async function startOrchestration(opts) {
5890
5981
  repoPath: repo
5891
5982
  });
5892
5983
  });
5893
- const { updateThread: upd } = await import("./thread-store-UJIGMI5J.js");
5984
+ const { updateThread: upd } = await import("./thread-store-XTPFCJAI.js");
5894
5985
  const updated = upd(thread.id, {
5895
5986
  sourceType: "orchestration",
5896
5987
  sourceRef: goal
@@ -6036,7 +6127,7 @@ function withTimeout(promise, ms, label) {
6036
6127
  async function startMcpServer() {
6037
6128
  const orch = getOrchestrator();
6038
6129
  try {
6039
- const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-TBHTJWLQ.js");
6130
+ const { maxConcurrentAgents: maxConcurrentAgents2 } = await import("./app-settings-HK4KAM4R.js");
6040
6131
  orch.setMaxConcurrent(maxConcurrentAgents2());
6041
6132
  } catch {
6042
6133
  }
@@ -6247,7 +6338,7 @@ async function startMcpServer() {
6247
6338
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
6248
6339
  }
6249
6340
  );
6250
- const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-TBHTJWLQ.js");
6341
+ const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults: resolveThreadDefaults2 } = await import("./app-settings-HK4KAM4R.js");
6251
6342
  const accountDefaults = resolveThreadDefaults2();
6252
6343
  const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
6253
6344
  server.tool(
@@ -6286,7 +6377,7 @@ async function startMcpServer() {
6286
6377
  parent = null;
6287
6378
  }
6288
6379
  if (parentId) {
6289
- const children = orch.getThreads(true).filter((t) => t.parentThreadId === parentId);
6380
+ const children = orch.getThreads(false).filter((t) => t.parentThreadId === parentId);
6290
6381
  if (children.length >= MAX_ORCH_THREADS) {
6291
6382
  return {
6292
6383
  content: [
@@ -7367,6 +7458,7 @@ export {
7367
7458
  attachmentsFromBuffers,
7368
7459
  attachmentsFromWorktreePaths,
7369
7460
  attachmentsGitignoreBody,
7461
+ autoArchiveOnMergeEnabled,
7370
7462
  autoCleanupOrphansEnabled,
7371
7463
  autoRenameBranchEnabled,
7372
7464
  autoRunAfterSetupEnabled,
@@ -486,6 +486,8 @@ function normalizeThread(raw) {
486
486
  agentPid: raw.agentPid ?? null,
487
487
  attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
488
488
  prTitle: raw.prTitle ?? null,
489
+ prState: raw.prState ?? null,
490
+ skipAutoArchiveOnMerge: Boolean(raw.skipAutoArchiveOnMerge),
489
491
  stackId: raw.stackId ?? null,
490
492
  stackLayer: raw.stackLayer ?? null,
491
493
  userSetTitle: Boolean(raw.userSetTitle),
@@ -512,6 +514,8 @@ function createEmptyThread(partial) {
512
514
  activeRuns: partial.activeRuns ?? [],
513
515
  prUrl: partial.prUrl ?? null,
514
516
  prTitle: partial.prTitle ?? null,
517
+ prState: partial.prState ?? null,
518
+ skipAutoArchiveOnMerge: partial.skipAutoArchiveOnMerge ?? false,
515
519
  stackId: partial.stackId ?? null,
516
520
  stackLayer: partial.stackLayer ?? null,
517
521
  userSetTitle: partial.userSetTitle ?? false,
@@ -2987,6 +2991,7 @@ __export(app_settings_exports, {
2987
2991
  HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
2988
2992
  appSettingsPath: () => appSettingsPath,
2989
2993
  applyAppEnvironment: () => applyAppEnvironment,
2994
+ autoArchiveOnMergeEnabled: () => autoArchiveOnMergeEnabled,
2990
2995
  autoCleanupOrphansEnabled: () => autoCleanupOrphansEnabled,
2991
2996
  autoRenameBranchEnabled: () => autoRenameBranchEnabled,
2992
2997
  autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
@@ -3104,6 +3109,9 @@ function normalizeAdvanced(raw) {
3104
3109
  if (typeof source.deleteBranchOnPurge === "boolean") {
3105
3110
  out.deleteBranchOnPurge = source.deleteBranchOnPurge;
3106
3111
  }
3112
+ if (typeof source.autoArchiveOnMerge === "boolean") {
3113
+ out.autoArchiveOnMerge = source.autoArchiveOnMerge;
3114
+ }
3107
3115
  if (typeof source.maxConcurrent === "number" && Number.isFinite(source.maxConcurrent)) {
3108
3116
  out.maxConcurrent = Math.max(1, Math.min(32, Math.floor(source.maxConcurrent)));
3109
3117
  }
@@ -3364,6 +3372,9 @@ function updateAdvancedSettings(patch) {
3364
3372
  if (typeof patch.deleteBranchOnPurge === "boolean") {
3365
3373
  advanced.deleteBranchOnPurge = patch.deleteBranchOnPurge;
3366
3374
  }
3375
+ if (typeof patch.autoArchiveOnMerge === "boolean") {
3376
+ advanced.autoArchiveOnMerge = patch.autoArchiveOnMerge;
3377
+ }
3367
3378
  if (typeof patch.maxConcurrent === "number" && Number.isFinite(patch.maxConcurrent)) {
3368
3379
  advanced.maxConcurrent = Math.max(1, Math.min(32, Math.floor(patch.maxConcurrent)));
3369
3380
  }
@@ -3405,6 +3416,9 @@ function caffeinateWhileCloudConnectEnabled(settings = loadAppSettings()) {
3405
3416
  function deleteBranchOnPurgeEnabled(settings = loadAppSettings()) {
3406
3417
  return Boolean(settings.advanced.deleteBranchOnPurge);
3407
3418
  }
3419
+ function autoArchiveOnMergeEnabled(settings = loadAppSettings()) {
3420
+ return Boolean(settings.advanced.autoArchiveOnMerge);
3421
+ }
3408
3422
  function autoCleanupOrphansEnabled(settings = loadAppSettings()) {
3409
3423
  return Boolean(settings.advanced.autoCleanupOrphans);
3410
3424
  }
@@ -7187,6 +7201,20 @@ init_agents();
7187
7201
  init_worktree();
7188
7202
  init_stack();
7189
7203
 
7204
+ // src/git/pr-merge-archive.ts
7205
+ function normalizePrState(state) {
7206
+ return (state ?? "").trim().toUpperCase();
7207
+ }
7208
+ function shouldAutoArchiveOnPrMerge(opts) {
7209
+ if (!opts.autoArchiveEnabled) return false;
7210
+ if (opts.isGlobal) return false;
7211
+ if (opts.skipAutoArchiveOnMerge) return false;
7212
+ if (opts.threadStatus === "archived") return false;
7213
+ const next = normalizePrState(opts.nextPrState);
7214
+ if (next !== "MERGED") return false;
7215
+ return normalizePrState(opts.previousPrState) !== "MERGED";
7216
+ }
7217
+
7190
7218
  // src/hook/conductor.ts
7191
7219
  var import_node_fs13 = require("fs");
7192
7220
  var import_node_net = require("net");
@@ -8226,6 +8254,8 @@ function worktreeBindingFrom(from) {
8226
8254
  parentThreadId: from.parentThreadId,
8227
8255
  prUrl: from.prUrl,
8228
8256
  prTitle: from.prTitle,
8257
+ prState: from.prState,
8258
+ skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
8229
8259
  stackId: from.stackId,
8230
8260
  stackLayer: from.stackLayer
8231
8261
  };
@@ -11751,10 +11781,19 @@ var Orchestrator = class {
11751
11781
  this.assertNotGlobal(thread, "Merge PR");
11752
11782
  if (!selector) throw new Error("No pull request linked to this thread");
11753
11783
  const result = await mergePr(cwd, selector);
11754
- if (result.url && result.url !== thread.prUrl) {
11755
- updateThread(thread.id, { prUrl: result.url });
11756
- }
11757
- return result;
11784
+ const state = normalizePrState(result.state) || "MERGED";
11785
+ const metaLike = {
11786
+ number: 0,
11787
+ title: thread.prTitle ?? thread.title,
11788
+ url: result.url || thread.prUrl || "",
11789
+ state,
11790
+ isDraft: false,
11791
+ reviewDecision: null,
11792
+ baseRefName: "",
11793
+ headRefName: ""
11794
+ };
11795
+ await this.persistPrMetaAndMaybeArchive(thread, metaLike);
11796
+ return { url: metaLike.url, state };
11758
11797
  }
11759
11798
  /** Resolve PR selector and optionally persist `prUrl` when found. */
11760
11799
  async withPrSelector(threadRef) {
@@ -11776,19 +11815,55 @@ var Orchestrator = class {
11776
11815
  if (!selector) return null;
11777
11816
  const meta = await getPrMeta(cwd, selector);
11778
11817
  if (meta) {
11779
- const patch = {};
11780
- if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
11781
- if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
11782
- if (Object.keys(patch).length > 0) {
11783
- updateThread(thread.id, patch);
11784
- const latest = this.requireThread(thread.id);
11785
- if (!latest.userSetTitle && meta.title && latest.title !== meta.title) {
11786
- updateThread(thread.id, { title: meta.title });
11787
- }
11788
- }
11818
+ await this.persistPrMetaAndMaybeArchive(thread, meta);
11789
11819
  }
11790
11820
  return meta;
11791
11821
  }
11822
+ /**
11823
+ * Persist PR URL/title/state and Conductor-style auto-archive when the PR
11824
+ * first becomes MERGED.
11825
+ */
11826
+ async persistPrMetaAndMaybeArchive(thread, meta) {
11827
+ const prevState = normalizePrState(thread.prState);
11828
+ const nextState = normalizePrState(meta.state);
11829
+ const patch = {};
11830
+ if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
11831
+ if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
11832
+ if (nextState && nextState !== prevState) patch.prState = nextState;
11833
+ if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
11834
+ patch.skipAutoArchiveOnMerge = false;
11835
+ }
11836
+ if (Object.keys(patch).length > 0) {
11837
+ updateThread(thread.id, patch);
11838
+ const latest2 = this.requireThread(thread.id);
11839
+ if (!latest2.userSetTitle && meta.title && latest2.title !== meta.title) {
11840
+ updateThread(thread.id, { title: meta.title });
11841
+ }
11842
+ }
11843
+ const { autoArchiveOnMergeEnabled: autoArchiveOnMergeEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
11844
+ const latest = this.requireThread(thread.id);
11845
+ if (!shouldAutoArchiveOnPrMerge({
11846
+ previousPrState: prevState || null,
11847
+ nextPrState: nextState,
11848
+ threadStatus: latest.status,
11849
+ skipAutoArchiveOnMerge: latest.skipAutoArchiveOnMerge,
11850
+ autoArchiveEnabled: autoArchiveOnMergeEnabled2(),
11851
+ isGlobal: isGlobalThread(latest)
11852
+ })) {
11853
+ return;
11854
+ }
11855
+ const siblings = threadsSharingWorktree(latest.worktreePath);
11856
+ for (const t of siblings) {
11857
+ const sibPatch = { prState: "MERGED" };
11858
+ if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
11859
+ if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
11860
+ if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
11861
+ }
11862
+ for (const t of siblings) {
11863
+ if (this.requireThread(t.id).status === "archived") continue;
11864
+ await this.archive(t.id);
11865
+ }
11866
+ }
11792
11867
  async getPrStack(threadRef) {
11793
11868
  const thread = this.requireThread(threadRef);
11794
11869
  if (!thread.worktreePath?.trim()) return null;
@@ -11966,7 +12041,9 @@ var Orchestrator = class {
11966
12041
  const thread = this.requireThread(threadRef);
11967
12042
  this.stop(thread.id);
11968
12043
  if (isGlobalThread(thread)) {
11969
- return setStatus(thread.id, "archived");
12044
+ const archived2 = setStatus(thread.id, "archived");
12045
+ this.emit({ type: "status_changed", threadId: archived2.id, status: "archived" });
12046
+ return archived2;
11970
12047
  }
11971
12048
  const siblings = threadsSharingWorktree(thread.worktreePath).filter((t) => t.id !== thread.id);
11972
12049
  if (siblings.length === 0) {
@@ -11984,6 +12061,7 @@ var Orchestrator = class {
11984
12061
  await removeWorktree(thread.repoPath, thread.worktreePath);
11985
12062
  }
11986
12063
  const archived = setStatus(thread.id, "archived");
12064
+ this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
11987
12065
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
11988
12066
  try {
11989
12067
  const { ensureWorkspace: ensureWorkspace2 } = await Promise.resolve().then(() => (init_workspaces(), workspaces_exports));
@@ -12023,7 +12101,9 @@ var Orchestrator = class {
12023
12101
  if (isGlobalThread(thread)) {
12024
12102
  const { globalAgentCwd: globalAgentCwd2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
12025
12103
  updateThread(thread.id, { worktreePath: globalAgentCwd2() });
12026
- return setStatus(thread.id, "idle");
12104
+ const restored2 = setStatus(thread.id, "idle");
12105
+ this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
12106
+ return restored2;
12027
12107
  }
12028
12108
  if (!(0, import_node_fs28.existsSync)(thread.worktreePath)) {
12029
12109
  const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
@@ -12036,7 +12116,31 @@ var Orchestrator = class {
12036
12116
  void createThreadWorktree2;
12037
12117
  void slug;
12038
12118
  }
12039
- return setStatus(thread.id, "idle");
12119
+ const restorePatch = {};
12120
+ let alreadyMerged = normalizePrState(thread.prState) === "MERGED";
12121
+ if (!alreadyMerged && thread.prUrl?.trim() && thread.worktreePath?.trim()) {
12122
+ try {
12123
+ const selector = resolvePrSelector(thread);
12124
+ if (selector) {
12125
+ const meta = await getPrMeta(thread.worktreePath, selector);
12126
+ if (meta) {
12127
+ const state = normalizePrState(meta.state);
12128
+ if (meta.url && meta.url !== thread.prUrl) restorePatch.prUrl = meta.url;
12129
+ if (meta.title && meta.title !== thread.prTitle) restorePatch.prTitle = meta.title;
12130
+ if (state) restorePatch.prState = state;
12131
+ if (state === "MERGED") alreadyMerged = true;
12132
+ }
12133
+ }
12134
+ } catch {
12135
+ }
12136
+ }
12137
+ if (alreadyMerged) restorePatch.skipAutoArchiveOnMerge = true;
12138
+ if (Object.keys(restorePatch).length > 0) {
12139
+ updateThread(thread.id, restorePatch);
12140
+ }
12141
+ const restored = setStatus(thread.id, "idle");
12142
+ this.emit({ type: "status_changed", threadId: restored.id, status: restored.status });
12143
+ return restored;
12040
12144
  }
12041
12145
  async attachCommand(threadRef) {
12042
12146
  const thread = this.requireThread(threadRef);
@@ -12482,7 +12586,7 @@ async function startMcpServer() {
12482
12586
  parent = null;
12483
12587
  }
12484
12588
  if (parentId) {
12485
- const children = orch.getThreads(true).filter((t) => t.parentThreadId === parentId);
12589
+ const children = orch.getThreads(false).filter((t) => t.parentThreadId === parentId);
12486
12590
  if (children.length >= MAX_ORCH_THREADS) {
12487
12591
  return {
12488
12592
  content: [