@sideboard-ai/core 0.1.212 → 0.1.214

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 (31) hide show
  1. package/dist/{agents-GQANI7M5.js → agents-HETHRRZJ.js} +4 -4
  2. package/dist/{agents-A2U3K7VK.js → agents-WBDDLRBY.js} +4 -4
  3. package/dist/{chunk-JJ3ONQ4Q.js → chunk-3IMSQNTS.js} +12 -2
  4. package/dist/{chunk-IA5IPGZI.js → chunk-7MTVRNP4.js} +3 -3
  5. package/dist/{chunk-DINKOGEU.js → chunk-C32SBNA3.js} +187 -84
  6. package/dist/{chunk-MS6HGW2H.js → chunk-D2IKXMF3.js} +185 -83
  7. package/dist/{chunk-IRCAWYTN.js → chunk-DFTVZEZY.js} +3 -3
  8. package/dist/{chunk-2PE6SZCM.js → chunk-FNGXKY5W.js} +2 -2
  9. package/dist/{chunk-GHKFSBES.js → chunk-HY2GFZ5S.js} +12 -2
  10. package/dist/{chunk-WNVQJZ7P.js → chunk-KFD2OXCE.js} +2 -2
  11. package/dist/{chunk-NRKDRQM3.js → chunk-NI243N27.js} +1 -1
  12. package/dist/{chunk-VPQXJYIW.js → chunk-XYKVRRC2.js} +1 -1
  13. package/dist/{coordinator-prompt-LMTMWCPN.js → coordinator-prompt-FQX6ALAI.js} +3 -3
  14. package/dist/{coordinator-prompt-EHRDZ2ZU.js → coordinator-prompt-LE2GQZ2X.js} +3 -3
  15. package/dist/{global-workspace-NG2TBUI5.js → global-workspace-6P236KKG.js} +3 -3
  16. package/dist/{global-workspace-RHABXQWB.js → global-workspace-KT3FRHZL.js} +3 -3
  17. package/dist/index.cjs +199 -75
  18. package/dist/index.d.cts +59 -3
  19. package/dist/index.d.ts +59 -3
  20. package/dist/index.js +11 -5
  21. package/dist/mcp/run-stdio.cjs +193 -75
  22. package/dist/mcp/run-stdio.js +5 -5
  23. package/dist/{orchestrator-DW4HDWLA.js → orchestrator-MI7A5DQZ.js} +7 -5
  24. package/dist/{orchestrator-333M3JAU.js → orchestrator-WVZPTHBV.js} +7 -5
  25. package/dist/{thread-store-MSMBQ3V4.js → thread-store-KDPPXJJ3.js} +3 -1
  26. package/dist/{thread-store-4M6WETL6.js → thread-store-N6WQIWZ4.js} +3 -1
  27. package/dist/{workspaces-VIUUE4RT.js → workspaces-KM7KTLVO.js} +3 -3
  28. package/dist/{workspaces-FRR6Y4BY.js → workspaces-R5LJCJRB.js} +3 -3
  29. package/dist/{worktree-GKUOHXXB.js → worktree-MDMTCAHX.js} +2 -2
  30. package/dist/{worktree-3MEG62KB.js → worktree-VXRI7LYM.js} +2 -2
  31. package/package.json +1 -1
@@ -44,9 +44,9 @@ import {
44
44
  resolveLoginCommand,
45
45
  resolveQuotaFallbackAgent,
46
46
  whichOnPath
47
- } from "./chunk-IRCAWYTN.js";
48
- import "./chunk-2PE6SZCM.js";
49
- import "./chunk-NRKDRQM3.js";
47
+ } from "./chunk-DFTVZEZY.js";
48
+ import "./chunk-FNGXKY5W.js";
49
+ import "./chunk-NI243N27.js";
50
50
  import "./chunk-6K64FJDD.js";
51
51
  import "./chunk-QQKDGPUI.js";
52
52
  import "./chunk-SALM35KD.js";
@@ -67,7 +67,7 @@ import {
67
67
  import "./chunk-4TR3HZFT.js";
68
68
  import "./chunk-WDRMZKVB.js";
69
69
  import "./chunk-JT7R45JB.js";
70
- import "./chunk-JJ3ONQ4Q.js";
70
+ import "./chunk-3IMSQNTS.js";
71
71
  import "./chunk-7J72QJOM.js";
72
72
  import "./chunk-77WWLBCI.js";
73
73
  import "./chunk-WFUDY6PC.js";
@@ -50,14 +50,14 @@ import {
50
50
  resolveQuotaFallbackAgent,
51
51
  turnCostUsdFromCursorUsage,
52
52
  whichOnPath
53
- } from "./chunk-IA5IPGZI.js";
54
- import "./chunk-WNVQJZ7P.js";
53
+ } from "./chunk-7MTVRNP4.js";
54
+ import "./chunk-KFD2OXCE.js";
55
55
  import "./chunk-3OHR73VK.js";
56
56
  import "./chunk-Y4MIXGPA.js";
57
57
  import "./chunk-VKQGAWHY.js";
58
- import "./chunk-VPQXJYIW.js";
58
+ import "./chunk-XYKVRRC2.js";
59
59
  import "./chunk-D6JWYJ4P.js";
60
- import "./chunk-GHKFSBES.js";
60
+ import "./chunk-HY2GFZ5S.js";
61
61
  import "./chunk-X5B3OS5I.js";
62
62
  import "./chunk-SYFVUF2C.js";
63
63
  import {
@@ -144,6 +144,7 @@ function forgetThread(id) {
144
144
  const cache = cacheForDir();
145
145
  cache.byId.delete(id);
146
146
  cache.mtimeMs.delete(id);
147
+ selfWriteMtimes.delete(id);
147
148
  }
148
149
  function invalidateThreadListCache() {
149
150
  listCache = null;
@@ -167,20 +168,28 @@ function readThread(id) {
167
168
  rememberThread(thread, mtimeMs);
168
169
  return thread;
169
170
  }
171
+ var selfWriteMtimes = /* @__PURE__ */ new Map();
170
172
  function writeThread(thread, opts) {
171
173
  const path = threadFilePath(idPath(thread.id));
172
174
  const tmp = `${path}.${process.pid}.tmp`;
173
175
  const next = opts?.touch === false ? { ...thread } : { ...thread, updatedAt: nowIso() };
174
176
  writeFileSync(tmp, JSON.stringify(next, null, 2), "utf8");
175
177
  renameSync(tmp, path);
176
- rememberThread(next, fileMtimeMs(path) ?? Date.now());
178
+ const mtimeMs = fileMtimeMs(path) ?? Date.now();
179
+ rememberThread(next, mtimeMs);
180
+ selfWriteMtimes.set(thread.id, mtimeMs);
181
+ }
182
+ function isSelfWrittenRecord(id) {
183
+ const ours = selfWriteMtimes.get(id);
184
+ if (ours == null) return false;
185
+ return fileMtimeMs(threadFilePath(id)) === ours;
177
186
  }
178
187
  function idPath(id) {
179
188
  return id;
180
189
  }
181
190
  function isThreadRecordFile(nameOrPath) {
182
191
  const name = basename(nameOrPath);
183
- return name.endsWith(".json") && !name.endsWith(".live.json");
192
+ return name.endsWith(".json") && !name.endsWith(".live.json") && !name.endsWith(".setup.log.json");
184
193
  }
185
194
  function listThreads(opts) {
186
195
  const cache = cacheForDir();
@@ -256,6 +265,7 @@ export {
256
265
  invalidateThreadRecord,
257
266
  readThread,
258
267
  writeThread,
268
+ isSelfWrittenRecord,
259
269
  isThreadRecordFile,
260
270
  listThreads,
261
271
  deleteThreadRecord,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  isOrchestratorThread
5
- } from "./chunk-WNVQJZ7P.js";
5
+ } from "./chunk-KFD2OXCE.js";
6
6
  import {
7
7
  applyConnectedTeamToCli,
8
8
  brightsyMcpServerName,
@@ -20,7 +20,7 @@ import {
20
20
  mergeAgentGitAuthEnv,
21
21
  resolveAgentGitAuthEnv,
22
22
  resolveCodexGitWritableRoots
23
- } from "./chunk-VPQXJYIW.js";
23
+ } from "./chunk-XYKVRRC2.js";
24
24
  import {
25
25
  enrichPathWithNpmGlobalBin,
26
26
  isConductorBundledCli,
@@ -2414,7 +2414,7 @@ var claudeAdapter = {
2414
2414
  );
2415
2415
  }
2416
2416
  const mode = permissionMode(thread);
2417
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-RHABXQWB.js");
2417
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-KT3FRHZL.js");
2418
2418
  const isOrchestrator = isOrchestratorThread2(thread);
2419
2419
  const injectedServers = await buildInjectedMcpServers({
2420
2420
  includeSideboard: true,
@@ -24,7 +24,7 @@ import {
24
24
  resolveQuotaFallbackAgent,
25
25
  stripBrightsyNdjsonNoise,
26
26
  toolDescription
27
- } from "./chunk-IRCAWYTN.js";
27
+ } from "./chunk-DFTVZEZY.js";
28
28
  import {
29
29
  SLACK_REPLY_FORMATTING,
30
30
  addWorkspace,
@@ -47,7 +47,7 @@ import {
47
47
  stageAbsolutePathsAsAttachments,
48
48
  stageBuffersAsAttachments,
49
49
  syncWorkspacesFromThreads
50
- } from "./chunk-2PE6SZCM.js";
50
+ } from "./chunk-FNGXKY5W.js";
51
51
  import {
52
52
  addPrStackLayer,
53
53
  allocateTeamName,
@@ -97,7 +97,7 @@ import {
97
97
  worktreeDisplayLabelForGroup,
98
98
  worktreeNameFromPath,
99
99
  worktreeSlugForTicket
100
- } from "./chunk-NRKDRQM3.js";
100
+ } from "./chunk-NI243N27.js";
101
101
  import {
102
102
  ATTACHMENTS_DIR,
103
103
  DETACHED_JOBS_DIR,
@@ -189,7 +189,7 @@ import {
189
189
  updateThread,
190
190
  withThreadLock,
191
191
  writeThread
192
- } from "./chunk-JJ3ONQ4Q.js";
192
+ } from "./chunk-3IMSQNTS.js";
193
193
  import {
194
194
  appDataDir,
195
195
  findConventionSetup,
@@ -483,7 +483,7 @@ async function continueSourceThread(threadId, prompt) {
483
483
  await continueOnReply(threadId, prompt);
484
484
  return;
485
485
  }
486
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-333M3JAU.js");
486
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-WVZPTHBV.js");
487
487
  await getOrchestrator2().send(threadId, prompt);
488
488
  } catch {
489
489
  }
@@ -817,9 +817,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
817
817
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
818
818
  );
819
819
  }
820
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-NG2TBUI5.js");
820
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-6P236KKG.js");
821
821
  if (isGlobalThread2(thread)) {
822
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-LMTMWCPN.js");
822
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-FQX6ALAI.js");
823
823
  ensureGlobalCoordinatorCwd2(
824
824
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
825
825
  );
@@ -2377,6 +2377,29 @@ ${line}` : line;
2377
2377
  }
2378
2378
  var memory = /* @__PURE__ */ new Map();
2379
2379
  var persistTimers = /* @__PURE__ */ new Map();
2380
+ function fromSnapshot(snap) {
2381
+ return {
2382
+ chunks: snap.output ? [snap.output] : [],
2383
+ length: snap.output.length,
2384
+ running: snap.running,
2385
+ exitCode: snap.exitCode,
2386
+ source: snap.source
2387
+ };
2388
+ }
2389
+ function materialize(mem) {
2390
+ let output = mem.chunks.join("\n");
2391
+ if (output.length > MAX_SETUP_LOG_CHARS) {
2392
+ output = appendSetupOutput("", output);
2393
+ mem.chunks = [output];
2394
+ mem.length = output.length;
2395
+ }
2396
+ return {
2397
+ output,
2398
+ running: mem.running,
2399
+ exitCode: mem.exitCode,
2400
+ source: mem.source
2401
+ };
2402
+ }
2380
2403
  function setupLogPath(threadId) {
2381
2404
  return join7(threadsDir(), `${threadId}.setup.log.json`);
2382
2405
  }
@@ -2395,20 +2418,22 @@ function mergeSetupOutput(prev, incoming) {
2395
2418
  if (incoming.startsWith(prev) || incoming.endsWith(prev)) return incoming;
2396
2419
  return incoming.length >= prev.length ? incoming : prev;
2397
2420
  }
2398
- function clone(snap) {
2399
- return { ...snap };
2400
- }
2421
+ var PERSIST_DEBOUNCE_MS = 500;
2401
2422
  function persistNow(threadId) {
2402
2423
  const timer = persistTimers.get(threadId);
2403
2424
  if (timer) {
2404
2425
  clearTimeout(timer);
2405
2426
  persistTimers.delete(threadId);
2406
2427
  }
2407
- const snap = memory.get(threadId);
2408
- if (!snap) return;
2428
+ const mem = memory.get(threadId);
2429
+ if (!mem) return;
2409
2430
  try {
2410
- writeFileSync2(setupLogPath(threadId), `${JSON.stringify(snap)}
2411
- `, "utf8");
2431
+ writeFileSync2(
2432
+ setupLogPath(threadId),
2433
+ `${JSON.stringify(materialize(mem))}
2434
+ `,
2435
+ "utf8"
2436
+ );
2412
2437
  } catch {
2413
2438
  }
2414
2439
  }
@@ -2419,7 +2444,7 @@ function schedulePersist(threadId) {
2419
2444
  setTimeout(() => {
2420
2445
  persistTimers.delete(threadId);
2421
2446
  persistNow(threadId);
2422
- }, 100)
2447
+ }, PERSIST_DEBOUNCE_MS)
2423
2448
  );
2424
2449
  }
2425
2450
  function loadFromDisk(threadId) {
@@ -2437,49 +2462,50 @@ function loadFromDisk(threadId) {
2437
2462
  return null;
2438
2463
  }
2439
2464
  }
2465
+ function memFor(threadId) {
2466
+ const cached = memory.get(threadId);
2467
+ if (cached) return cached;
2468
+ const mem = fromSnapshot(loadFromDisk(threadId) ?? emptySetupLog());
2469
+ memory.set(threadId, mem);
2470
+ return mem;
2471
+ }
2440
2472
  function readSetupLog(threadId) {
2441
2473
  const cached = memory.get(threadId);
2442
- if (cached) return clone(cached);
2474
+ if (cached) return materialize(cached);
2443
2475
  const disk = loadFromDisk(threadId);
2444
2476
  if (disk) {
2445
- memory.set(threadId, disk);
2446
- return clone(disk);
2477
+ memory.set(threadId, fromSnapshot(disk));
2478
+ return disk;
2447
2479
  }
2448
2480
  return emptySetupLog();
2449
2481
  }
2450
2482
  function beginSetupLog(threadId) {
2451
- const snap = {
2452
- output: "",
2483
+ const mem = {
2484
+ chunks: [],
2485
+ length: 0,
2453
2486
  running: true,
2454
2487
  exitCode: null,
2455
2488
  source: null
2456
2489
  };
2457
- memory.set(threadId, snap);
2490
+ memory.set(threadId, mem);
2458
2491
  persistNow(threadId);
2459
- return clone(snap);
2492
+ return materialize(mem);
2460
2493
  }
2461
2494
  function appendSetupLog(threadId, line) {
2462
- const current = memory.get(threadId) ?? readSetupLog(threadId);
2463
- const snap = {
2464
- ...current,
2465
- output: appendSetupOutput(current.output, line),
2466
- running: true
2467
- };
2468
- memory.set(threadId, snap);
2495
+ const mem = memFor(threadId);
2496
+ mem.chunks.push(line);
2497
+ mem.length += line.length + 1;
2498
+ mem.running = true;
2499
+ if (mem.length > MAX_SETUP_LOG_CHARS * 2) materialize(mem);
2469
2500
  schedulePersist(threadId);
2470
- return clone(snap);
2471
2501
  }
2472
2502
  function finishSetupLog(threadId, exitCode, source) {
2473
- const current = memory.get(threadId) ?? readSetupLog(threadId);
2474
- const snap = {
2475
- ...current,
2476
- running: false,
2477
- exitCode,
2478
- source: source ?? current.source
2479
- };
2480
- memory.set(threadId, snap);
2503
+ const mem = memFor(threadId);
2504
+ mem.running = false;
2505
+ mem.exitCode = exitCode;
2506
+ mem.source = source ?? mem.source;
2481
2507
  persistNow(threadId);
2482
- return clone(snap);
2508
+ return materialize(mem);
2483
2509
  }
2484
2510
 
2485
2511
  // src/git/orphan-cleanup.ts
@@ -4039,7 +4065,7 @@ async function createThread(input, _onSetupLine) {
4039
4065
  return readThread(thread.id) ?? thread;
4040
4066
  }
4041
4067
  async function listLinearIssues(agent, repoPath) {
4042
- const { getAdapter: getAdapter2 } = await import("./agents-GQANI7M5.js");
4068
+ const { getAdapter: getAdapter2 } = await import("./agents-HETHRRZJ.js");
4043
4069
  await requireAgent(agent, { requireLinear: true });
4044
4070
  const adapter = getAdapter2(agent);
4045
4071
  if (!adapter.listLinearIssues) {
@@ -4071,6 +4097,33 @@ function shouldRemoveWorktreeOnTeardown(thread) {
4071
4097
  return !isCowboyThread(thread) && !isPrimaryCheckoutThread(thread);
4072
4098
  }
4073
4099
 
4100
+ // src/util/line-coalescer.ts
4101
+ function createLineCoalescer(onChunk, opts) {
4102
+ const delayMs = opts?.delayMs ?? 50;
4103
+ const maxLines = opts?.maxLines ?? 200;
4104
+ let buffer = [];
4105
+ let timer = null;
4106
+ const flush2 = () => {
4107
+ if (timer) {
4108
+ clearTimeout(timer);
4109
+ timer = null;
4110
+ }
4111
+ if (buffer.length === 0) return;
4112
+ const chunk = buffer.join("\n");
4113
+ buffer = [];
4114
+ onChunk(chunk);
4115
+ };
4116
+ const push = (line) => {
4117
+ buffer.push(line);
4118
+ if (buffer.length >= maxLines) {
4119
+ flush2();
4120
+ return;
4121
+ }
4122
+ if (!timer) timer = setTimeout(flush2, delayMs);
4123
+ };
4124
+ return { push, flush: flush2 };
4125
+ }
4126
+
4074
4127
  // src/store/turn-live.ts
4075
4128
  import {
4076
4129
  existsSync as existsSync11,
@@ -4485,7 +4538,7 @@ async function adoptThread(input) {
4485
4538
  messages: input.messages ?? []
4486
4539
  });
4487
4540
  writeThread(thread);
4488
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-FRR6Y4BY.js");
4541
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-R5LJCJRB.js");
4489
4542
  await ensureWorkspace2(repoPath);
4490
4543
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
4491
4544
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -5705,6 +5758,29 @@ function writeWorktreeFile(worktreePath, relativePath, content) {
5705
5758
  writeFileSync6(abs, content, "utf8");
5706
5759
  return { path: relativePath };
5707
5760
  }
5761
+ async function getWorktreeDirtyStat(worktreePath) {
5762
+ const status = await inspectGitWorktree(worktreePath);
5763
+ if (status !== "ok") {
5764
+ return { additions: 0, deletions: 0, dirty: false };
5765
+ }
5766
+ const head = await git(["rev-parse", "--verify", "HEAD"], worktreePath, {
5767
+ reject: false,
5768
+ timeoutMs: 4e3
5769
+ });
5770
+ if (head.exitCode !== 0) {
5771
+ return { additions: 0, deletions: 0, dirty: await isDirty(worktreePath) };
5772
+ }
5773
+ const [num, dirty] = await Promise.all([
5774
+ gitDiff(["--numstat", "HEAD"], worktreePath, { timeoutMs: 4e3 }),
5775
+ isDirty(worktreePath)
5776
+ ]);
5777
+ const counts = statFromNumstat(num.stdout);
5778
+ return {
5779
+ additions: counts.additions,
5780
+ deletions: counts.deletions,
5781
+ dirty: dirty || counts.additions > 0 || counts.deletions > 0
5782
+ };
5783
+ }
5708
5784
  async function getDiffSummary(worktreePath, repoPath, opts) {
5709
5785
  const full = await getDiff(worktreePath, repoPath, {
5710
5786
  maxHunkChars: opts?.maxHunkChars ?? 2e3,
@@ -7121,7 +7197,7 @@ function formatScheduledPrompt(name, prompt) {
7121
7197
  ${prompt}`;
7122
7198
  }
7123
7199
  async function defaultDeps() {
7124
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-333M3JAU.js");
7200
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-WVZPTHBV.js");
7125
7201
  const orch = getOrchestrator2();
7126
7202
  return {
7127
7203
  findThread: (id) => findThreadByRef(id),
@@ -7252,6 +7328,7 @@ function resolveOrchChildFollowUp(requested) {
7252
7328
  return followUpBehavior();
7253
7329
  }
7254
7330
  var STALE_AGENT_PID_WAIT_MS = 2500;
7331
+ var LIGHT_RECONCILE_THROTTLE_MS = 1e4;
7255
7332
  function writeLiveStatus(threadId, status, lastError) {
7256
7333
  const latest = readThread(threadId);
7257
7334
  if (!latest || latest.status === "archived") return latest;
@@ -7266,6 +7343,8 @@ var Orchestrator = class {
7266
7343
  startingTurns = /* @__PURE__ */ new Set();
7267
7344
  /** Last sync thread-file read for false-stop heal (throttled per thread). */
7268
7345
  lastReconcileHealAt = /* @__PURE__ */ new Map();
7346
+ /** Per-repo timestamp of the last `reconcile(repo, { light: true })`. */
7347
+ lightReconcileAt = /* @__PURE__ */ new Map();
7269
7348
  /**
7270
7349
  * Threads intentionally force-stopped. Prevents runTurn from re-asserting
7271
7350
  * `running` after spawn, and from overwriting `stopped` with idle/error when
@@ -7351,6 +7430,20 @@ var Orchestrator = class {
7351
7430
  async reconcile(repoPath, opts) {
7352
7431
  const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
7353
7432
  const drainQueues = opts?.drainQueues !== false;
7433
+ if (opts?.light && repoPath) {
7434
+ const last = this.lightReconcileAt.get(repoPath) ?? 0;
7435
+ if (Date.now() - last < LIGHT_RECONCILE_THROTTLE_MS) return;
7436
+ this.lightReconcileAt.set(repoPath, Date.now());
7437
+ for (const thread of listThreads()) {
7438
+ if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
7439
+ if (!existsSync19(thread.worktreePath)) {
7440
+ setStatus(thread.id, "broken", "Worktree missing on disk");
7441
+ this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
7442
+ }
7443
+ }
7444
+ await this.reconcileOrphans([repoPath]);
7445
+ return;
7446
+ }
7354
7447
  healOrchestrationSoccerTitles();
7355
7448
  for (const thread of listThreads({ includeArchived: true })) {
7356
7449
  if (thread.status === "archived") continue;
@@ -7383,6 +7476,21 @@ var Orchestrator = class {
7383
7476
  }
7384
7477
  }
7385
7478
  const repoPaths = (repoPath ? [repoPath] : [...new Set(listThreads({ includeArchived: true }).map((t) => t.repoPath))]).filter((p) => !isGlobalRepoPath(p));
7479
+ await this.reconcileOrphans(repoPaths);
7480
+ try {
7481
+ if (shouldRunHistoryCleanup()) {
7482
+ cleanupArchivedHistory();
7483
+ }
7484
+ } catch {
7485
+ }
7486
+ if (drainQueues) {
7487
+ this.adoptPersistedQueues();
7488
+ }
7489
+ this.schedulePendingQuotaResumes();
7490
+ armSchedules();
7491
+ }
7492
+ /** Surface (and, when enabled, clean up) worktrees git knows about but no thread owns. */
7493
+ async reconcileOrphans(repoPaths) {
7386
7494
  try {
7387
7495
  const orphans = await findOrphanWorktrees(repoPaths);
7388
7496
  if (orphans.length) {
@@ -7397,17 +7505,6 @@ var Orchestrator = class {
7397
7505
  }
7398
7506
  } catch {
7399
7507
  }
7400
- try {
7401
- if (shouldRunHistoryCleanup()) {
7402
- cleanupArchivedHistory();
7403
- }
7404
- } catch {
7405
- }
7406
- if (drainQueues) {
7407
- this.adoptPersistedQueues();
7408
- }
7409
- this.schedulePendingQuotaResumes();
7410
- armSchedules();
7411
7508
  }
7412
7509
  /**
7413
7510
  * Adopt queues persisted by another process (MCP stdio / CLI) into this
@@ -7641,7 +7738,7 @@ var Orchestrator = class {
7641
7738
  return listThreads({ includeArchived });
7642
7739
  }
7643
7740
  getThread(idOrRef) {
7644
- return findThreadByRef(idOrRef) ?? readThread(idOrRef);
7741
+ return readThread(idOrRef) ?? findThreadByRef(idOrRef);
7645
7742
  }
7646
7743
  async createThread(input) {
7647
7744
  const prior = new Set(
@@ -8497,17 +8594,18 @@ var Orchestrator = class {
8497
8594
  }
8498
8595
  }
8499
8596
  }
8597
+ const runOutput = createLineCoalescer((chunk) => {
8598
+ this.emit({
8599
+ type: "run_output",
8600
+ threadId: thread.id,
8601
+ scriptName: resolvedName,
8602
+ line: chunk
8603
+ });
8604
+ });
8500
8605
  const handle = await startDevServer(
8501
8606
  thread.repoPath,
8502
8607
  thread.worktreePath,
8503
- (line) => {
8504
- this.emit({
8505
- type: "run_output",
8506
- threadId: thread.id,
8507
- scriptName: resolvedName,
8508
- line
8509
- });
8510
- },
8608
+ runOutput.push,
8511
8609
  { scriptName: resolvedName }
8512
8610
  );
8513
8611
  if (!handle) {
@@ -8553,6 +8651,7 @@ var Orchestrator = class {
8553
8651
  scriptName: resolvedName
8554
8652
  });
8555
8653
  void handle.done.then(() => {
8654
+ runOutput.flush();
8556
8655
  this.processes.delete(runKey);
8557
8656
  if (isDefault) this.processes.delete(worktreeDevProcessKey(thread.worktreePath));
8558
8657
  const latest = mergeWorktreeActiveRuns(threadsSharingWorktree(thread.worktreePath));
@@ -8638,9 +8737,14 @@ var Orchestrator = class {
8638
8737
  (t) => this.processes.has(`${t.id}:setup`)
8639
8738
  );
8640
8739
  }
8641
- writeSetupLog(threadId, worktreePath, fn) {
8740
+ /**
8741
+ * The worktree-keyed log is canonical (`resolveWorktreeSetupLog` prefers it
8742
+ * whenever it has output/running/exitCode); per-chat keys only exist for
8743
+ * records that predate it. Writing one key halves the sync persists during
8744
+ * `pnpm install`.
8745
+ */
8746
+ writeSetupLog(worktreePath, fn) {
8642
8747
  fn(setupLogKeyForWorktree(worktreePath));
8643
- fn(threadId);
8644
8748
  }
8645
8749
  async runSetup(threadRef, opts) {
8646
8750
  const thread = this.requireThread(threadRef);
@@ -8655,14 +8759,18 @@ var Orchestrator = class {
8655
8759
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
8656
8760
  kill: () => abort.abort()
8657
8761
  });
8658
- this.writeSetupLog(thread.id, thread.worktreePath, beginSetupLog);
8762
+ this.writeSetupLog(thread.worktreePath, beginSetupLog);
8659
8763
  this.emit({ type: "setup_started", threadId: thread.id });
8764
+ const output = createLineCoalescer((chunk) => {
8765
+ this.writeSetupLog(thread.worktreePath, (logKey) => appendSetupLog(logKey, chunk));
8766
+ this.emit({ type: "setup_output", threadId: thread.id, line: chunk });
8767
+ });
8660
8768
  let finished = false;
8661
8769
  const finish = (exitCode, source) => {
8662
8770
  if (finished) return;
8663
8771
  finished = true;
8772
+ output.flush();
8664
8773
  this.writeSetupLog(
8665
- thread.id,
8666
8774
  thread.worktreePath,
8667
8775
  (logKey) => finishSetupLog(logKey, exitCode, source)
8668
8776
  );
@@ -8672,24 +8780,12 @@ var Orchestrator = class {
8672
8780
  const setup = await runWorkspaceSetup(
8673
8781
  thread.repoPath,
8674
8782
  thread.worktreePath,
8675
- (line) => {
8676
- this.writeSetupLog(
8677
- thread.id,
8678
- thread.worktreePath,
8679
- (logKey) => appendSetupLog(logKey, line)
8680
- );
8681
- this.emit({ type: "setup_output", threadId: thread.id, line });
8682
- },
8783
+ output.push,
8683
8784
  { signal: abort.signal }
8684
8785
  );
8685
8786
  if (!setup.ran) {
8686
8787
  const line = "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)";
8687
- this.writeSetupLog(
8688
- thread.id,
8689
- thread.worktreePath,
8690
- (logKey) => appendSetupLog(logKey, line)
8691
- );
8692
- this.emit({ type: "setup_output", threadId: thread.id, line });
8788
+ output.push(line);
8693
8789
  finish(null, null);
8694
8790
  throw new Error(line);
8695
8791
  }
@@ -8895,6 +8991,11 @@ var Orchestrator = class {
8895
8991
  lastTurnBase: this.turnBaselines.get(thread.id) ?? null
8896
8992
  });
8897
8993
  }
8994
+ async worktreeDirtyStat(threadRef) {
8995
+ const thread = this.requireThread(threadRef);
8996
+ this.assertNotGlobal(thread, "Diff");
8997
+ return getWorktreeDirtyStat(thread.worktreePath);
8998
+ }
8898
8999
  async diffSummary(threadRef) {
8899
9000
  const thread = this.requireThread(threadRef);
8900
9001
  this.assertNotGlobal(thread, "Diff");
@@ -9343,7 +9444,7 @@ var Orchestrator = class {
9343
9444
  this.enforceHistoryRetention();
9344
9445
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
9345
9446
  try {
9346
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-FRR6Y4BY.js");
9447
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-R5LJCJRB.js");
9347
9448
  await ensureWorkspace2(thread.repoPath);
9348
9449
  } catch {
9349
9450
  }
@@ -9397,7 +9498,7 @@ var Orchestrator = class {
9397
9498
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
9398
9499
  );
9399
9500
  }
9400
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-GKUOHXXB.js");
9501
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-MDMTCAHX.js");
9401
9502
  const slug = thread.worktreePath.split("/").pop();
9402
9503
  const dest = thread.worktreePath;
9403
9504
  await withRepoGitLock(thread.repoPath, async () => {
@@ -9507,7 +9608,7 @@ async function startOrchestration(opts) {
9507
9608
  sourceRef: "default",
9508
9609
  ...createOpts
9509
9610
  }).catch(async () => {
9510
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-GKUOHXXB.js");
9611
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-MDMTCAHX.js");
9511
9612
  const repo = await resolveRepoRoot2(repoPath);
9512
9613
  const def = await resolveDefaultBranch2(repo);
9513
9614
  return orch.createThread({
@@ -9517,7 +9618,7 @@ async function startOrchestration(opts) {
9517
9618
  repoPath: repo
9518
9619
  });
9519
9620
  });
9520
- const { updateThread: upd } = await import("./thread-store-4M6WETL6.js");
9621
+ const { updateThread: upd } = await import("./thread-store-N6WQIWZ4.js");
9521
9622
  const updated = upd(thread.id, {
9522
9623
  sourceType: "orchestration",
9523
9624
  sourceRef: goal
@@ -9723,6 +9824,7 @@ export {
9723
9824
  readWorktreeFileForUpload,
9724
9825
  readWorktreeFile,
9725
9826
  writeWorktreeFile,
9827
+ getWorktreeDirtyStat,
9726
9828
  getDiffSummary,
9727
9829
  previewLand,
9728
9830
  confirmLand,
@@ -9776,6 +9878,7 @@ export {
9776
9878
  waitForPidExit,
9777
9879
  resolveSendFollowUp,
9778
9880
  resolveOrchChildFollowUp,
9881
+ LIGHT_RECONCILE_THROTTLE_MS,
9779
9882
  Orchestrator,
9780
9883
  getOrchestrator,
9781
9884
  startOrchestration,