@wrongstack/core 0.268.0 → 0.269.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 (75) hide show
  1. package/dist/{agent-bridge-UhojbpWx.d.ts → agent-bridge-PcHQl_UQ.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-Bvtf1o9K.d.ts → agent-subagent-runner-SHJW7t8q.d.ts} +8 -8
  3. package/dist/{brain-69wzMKp1.d.ts → brain-BYcK__Ym.d.ts} +1 -1
  4. package/dist/{compactor-CBQAJoDc.d.ts → compactor-C2RKEBtC.d.ts} +1 -1
  5. package/dist/{config-VKfOZ-6X.d.ts → config-C_ae2k86.d.ts} +11 -2
  6. package/dist/{context-C0U8B9NF.d.ts → context-Dp87Bcaq.d.ts} +24 -1
  7. package/dist/coordination/index.d.ts +22 -16
  8. package/dist/coordination/index.js +233 -86
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +25 -25
  11. package/dist/defaults/index.js +272 -69
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +15 -15
  14. package/dist/execution/index.js +116 -19
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +1 -1
  17. package/dist/extension/index.d.ts +6 -6
  18. package/dist/{global-mailbox-KByEFFBa.d.ts → global-mailbox-Bvrz1P3f.d.ts} +2 -1
  19. package/dist/{goal-preamble-CrYjmdw4.d.ts → goal-preamble-CA_4yiGQ.d.ts} +9 -9
  20. package/dist/{goal-store-Y_zdLZ3q.d.ts → goal-store-DhuJoUNG.d.ts} +1 -1
  21. package/dist/hq/index.d.ts +15 -6
  22. package/dist/hq/index.js +55 -8
  23. package/dist/hq/index.js.map +1 -1
  24. package/dist/{index-CtQnmkaS.d.ts → index-CZQ6Pwbs.d.ts} +8 -8
  25. package/dist/{index-gCv830d7.d.ts → index-W4VJCzHa.d.ts} +5 -5
  26. package/dist/{index-BfaS-f_m.d.ts → index-whDfTANu.d.ts} +2 -2
  27. package/dist/index.d.ts +41 -41
  28. package/dist/index.js +531 -167
  29. package/dist/index.js.map +1 -1
  30. package/dist/infrastructure/index.d.ts +6 -6
  31. package/dist/infrastructure/index.js +3 -3
  32. package/dist/infrastructure/index.js.map +1 -1
  33. package/dist/kernel/index.d.ts +9 -9
  34. package/dist/{mcp-servers-HT3Fi7Bl.d.ts → mcp-servers-DJdZiRcv.d.ts} +3 -3
  35. package/dist/models/index.d.ts +5 -5
  36. package/dist/models/index.js +1 -1
  37. package/dist/models/index.js.map +1 -1
  38. package/dist/{models-registry-Bvcl3Vaa.d.ts → models-registry-C3a-2-Yd.d.ts} +1 -1
  39. package/dist/{multi-agent-coordinator-BACjsmkC.d.ts → multi-agent-coordinator-CJSpTe5O.d.ts} +1 -1
  40. package/dist/{null-fleet-bus-DA7fvhUg.d.ts → null-fleet-bus-QVshIsDx.d.ts} +6 -6
  41. package/dist/observability/index.d.ts +2 -2
  42. package/dist/{parallel-eternal-engine-Ci71gYu_.d.ts → parallel-eternal-engine-D9y5Pkcc.d.ts} +9 -9
  43. package/dist/{path-resolver-O1IJnmKE.d.ts → path-resolver-CnQ8SIfh.d.ts} +3 -3
  44. package/dist/{permission-Bd-57Lbl.d.ts → permission-CvYQNUqZ.d.ts} +1 -1
  45. package/dist/{permission-policy-uNXC6Kge.d.ts → permission-policy-D5Ss8j4B.d.ts} +2 -2
  46. package/dist/{pipeline-BDNvENyV.d.ts → pipeline-l_zzFRh3.d.ts} +2 -2
  47. package/dist/{plan-templates-EMsalEtN.d.ts → plan-templates-NtPgyeJA.d.ts} +6 -5
  48. package/dist/{provider-model-resolve-CEb9x886.d.ts → provider-model-resolve-d5poT5y0.d.ts} +3 -3
  49. package/dist/{provider-runner-DWJbpo70.d.ts → provider-runner-gkctlQV_.d.ts} +3 -3
  50. package/dist/{retry-policy-C3s_lvdK.d.ts → retry-policy-CtFhfwa8.d.ts} +1 -1
  51. package/dist/sdd/index.d.ts +8 -8
  52. package/dist/sdd/index.js +1 -1
  53. package/dist/sdd/index.js.map +1 -1
  54. package/dist/{secret-vault-Cgduf5xL.d.ts → secret-vault-BLsVmTIK.d.ts} +1 -1
  55. package/dist/security/index.d.ts +5 -5
  56. package/dist/security/index.js.map +1 -1
  57. package/dist/{selector-47LBnBVk.d.ts → selector-CXl2_y9W.d.ts} +1 -1
  58. package/dist/{session-event-bridge-Cw7oqmW2.d.ts → session-event-bridge-Ccud20CC.d.ts} +1 -1
  59. package/dist/{session-reader-DD4v2Obw.d.ts → session-reader-ZeXQmsmE.d.ts} +1 -1
  60. package/dist/skills/index.js.map +1 -1
  61. package/dist/storage/index.d.ts +13 -11
  62. package/dist/storage/index.js +210 -64
  63. package/dist/storage/index.js.map +1 -1
  64. package/dist/tools/index.d.ts +2 -2
  65. package/dist/tools/index.js.map +1 -1
  66. package/dist/types/index.d.ts +21 -21
  67. package/dist/types/index.js +110 -19
  68. package/dist/types/index.js.map +1 -1
  69. package/dist/utils/index.d.ts +2 -2
  70. package/dist/utils/index.js +58 -24
  71. package/dist/utils/index.js.map +1 -1
  72. package/package.json +1 -1
  73. package/skills/chimera/SKILL.md +1 -1
  74. package/skills/typescript-strict/SKILL.md +3 -3
  75. package/skills/typescript-strict/SKILL.save.md +1 -1
@@ -172,8 +172,8 @@ async function atomicWrite(targetPath, content, opts = {}) {
172
172
  }
173
173
  let mode;
174
174
  try {
175
- const stat6 = await fsp6.stat(targetPath);
176
- mode = stat6.mode & 511;
175
+ const stat7 = await fsp6.stat(targetPath);
176
+ mode = stat7.mode & 511;
177
177
  } catch {
178
178
  mode = opts.mode;
179
179
  }
@@ -213,8 +213,8 @@ async function withFileLock(targetPath, fn, opts = {}) {
213
213
  }
214
214
  if (code !== "EEXIST") throw err;
215
215
  try {
216
- const stat6 = await fsp6.stat(lockPath);
217
- if (Date.now() - stat6.mtimeMs > staleMs) {
216
+ const stat7 = await fsp6.stat(lockPath);
217
+ if (Date.now() - stat7.mtimeMs > staleMs) {
218
218
  await fsp6.unlink(lockPath);
219
219
  continue;
220
220
  }
@@ -545,8 +545,8 @@ async function expandGlob(pattern) {
545
545
  for (const e of entries) {
546
546
  const full = `${dir}${SEP}${e}`;
547
547
  try {
548
- const stat6 = await fsp6.stat(full);
549
- if (stat6.isDirectory()) await walk(full, rest);
548
+ const stat7 = await fsp6.stat(full);
549
+ if (stat7.isDirectory()) await walk(full, rest);
550
550
  } catch {
551
551
  }
552
552
  }
@@ -563,8 +563,8 @@ async function expandGlob(pattern) {
563
563
  if (entries.includes(seg)) {
564
564
  const full = `${dir}${SEP}${seg}`;
565
565
  try {
566
- const stat6 = await fsp6.stat(full);
567
- if (stat6.isDirectory()) await walk(full, rest);
566
+ const stat7 = await fsp6.stat(full);
567
+ if (stat7.isDirectory()) await walk(full, rest);
568
568
  } catch {
569
569
  }
570
570
  }
@@ -636,7 +636,7 @@ function hasToolResult(msg) {
636
636
  }
637
637
  function toolUseIds(msg) {
638
638
  const ids = /* @__PURE__ */ new Set();
639
- if (!msg || msg.role !== "assistant") return ids;
639
+ if (msg?.role !== "assistant") return ids;
640
640
  for (const block of contentBlocks(msg)) {
641
641
  if (block.type === "tool_use") ids.add(block.id);
642
642
  }
@@ -644,7 +644,7 @@ function toolUseIds(msg) {
644
644
  }
645
645
  function toolResultIds(msg) {
646
646
  const ids = /* @__PURE__ */ new Set();
647
- if (!msg || msg.role !== "user") return ids;
647
+ if (msg?.role !== "user") return ids;
648
648
  for (const block of contentBlocks(msg)) {
649
649
  if (block.type === "tool_result") ids.add(block.tool_use_id);
650
650
  }
@@ -996,7 +996,7 @@ var CollabSession = class extends EventEmitter {
996
996
  }
997
997
  for (const filePath of allFiles) {
998
998
  try {
999
- const [content, stat6] = await Promise.all([
999
+ const [content, stat7] = await Promise.all([
1000
1000
  fsp6.readFile(filePath, "utf8"),
1001
1001
  fsp6.stat(filePath)
1002
1002
  ]);
@@ -1006,8 +1006,8 @@ var CollabSession = class extends EventEmitter {
1006
1006
  path: filePath,
1007
1007
  content,
1008
1008
  language,
1009
- snapshotMtimeMs: stat6.mtimeMs,
1010
- snapshotSizeBytes: stat6.size
1009
+ snapshotMtimeMs: stat7.mtimeMs,
1010
+ snapshotSizeBytes: stat7.size
1011
1011
  });
1012
1012
  } catch {
1013
1013
  this.snapshot.files.push({ path: filePath, content: "", language: void 0 });
@@ -1420,9 +1420,9 @@ Emit each evaluation immediately. Do not wait until you have read all reports.`;
1420
1420
  for (const file of this.snapshot.files) {
1421
1421
  if (file.snapshotMtimeMs === void 0 && file.snapshotSizeBytes === void 0) continue;
1422
1422
  try {
1423
- const stat6 = await fsp6.stat(file.path);
1424
- const mtimeChanged = file.snapshotMtimeMs !== void 0 && stat6.mtimeMs > file.snapshotMtimeMs + 1;
1425
- const sizeChanged = file.snapshotSizeBytes !== void 0 && stat6.size !== file.snapshotSizeBytes;
1423
+ const stat7 = await fsp6.stat(file.path);
1424
+ const mtimeChanged = file.snapshotMtimeMs !== void 0 && stat7.mtimeMs > file.snapshotMtimeMs + 1;
1425
+ const sizeChanged = file.snapshotSizeBytes !== void 0 && stat7.size !== file.snapshotSizeBytes;
1426
1426
  if (mtimeChanged || sizeChanged) {
1427
1427
  warnings.push(`${file.path} changed after the collab snapshot was captured.`);
1428
1428
  }
@@ -5432,7 +5432,7 @@ var SubagentBudget = class _SubagentBudget {
5432
5432
  */
5433
5433
  _busRequestDecision(entry) {
5434
5434
  const bus = this._events;
5435
- if (!bus || !bus.hasListenerFor("budget.threshold_reached")) {
5435
+ if (!bus?.hasListenerFor("budget.threshold_reached")) {
5436
5436
  return Promise.resolve("stop");
5437
5437
  }
5438
5438
  return new Promise((resolve3) => {
@@ -8763,6 +8763,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
8763
8763
  * processes. When the limit is reached, the oldest entry is evicted.
8764
8764
  */
8765
8765
  _loadCache = /* @__PURE__ */ new Map();
8766
+ _indexCache = null;
8766
8767
  static LOAD_CACHE_MAX_ENTRIES = 50;
8767
8768
  constructor(opts) {
8768
8769
  this.dir = opts.dir;
@@ -8924,15 +8925,10 @@ var DefaultSessionStore = class _DefaultSessionStore {
8924
8925
  let errorMsg;
8925
8926
  let cacheHit = false;
8926
8927
  try {
8927
- let stat6;
8928
- try {
8929
- const s = await fsp6.stat(file);
8930
- stat6 = { mtimeMs: s.mtimeMs, size: s.size };
8931
- } catch (err) {
8932
- throw err;
8933
- }
8928
+ const s = await fsp6.stat(file);
8929
+ const stat7 = { mtimeMs: s.mtimeMs, size: s.size };
8934
8930
  const cached = this._loadCache.get(id);
8935
- if (cached && cached.mtimeMs === stat6.mtimeMs && cached.size === stat6.size) {
8931
+ if (cached && cached.mtimeMs === stat7.mtimeMs && cached.size === stat7.size) {
8936
8932
  cacheHit = true;
8937
8933
  this._loadCache.delete(id);
8938
8934
  this._loadCache.set(id, cached);
@@ -8960,7 +8956,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
8960
8956
  this._loadCache.delete(oldest);
8961
8957
  }
8962
8958
  }
8963
- this._loadCache.set(id, { mtimeMs: stat6.mtimeMs, size: stat6.size, data });
8959
+ this._loadCache.set(id, { mtimeMs: stat7.mtimeMs, size: stat7.size, data });
8964
8960
  return data;
8965
8961
  } catch (err) {
8966
8962
  outcome = "failure";
@@ -9021,6 +9017,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
9021
9017
  await ensureDir(this.dir);
9022
9018
  const line = JSON.stringify(summary) + "\n";
9023
9019
  await fsp6.appendFile(this.indexFile, line, "utf8");
9020
+ this._indexCache = null;
9024
9021
  this.indexAppendCount++;
9025
9022
  if (this.indexAppendCount >= _DefaultSessionStore.COMPACT_EVERY) {
9026
9023
  await this.compactIndex();
@@ -9035,6 +9032,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
9035
9032
  await ensureDir(this.dir);
9036
9033
  const line = JSON.stringify({ action: "delete", id }) + "\n";
9037
9034
  await fsp6.appendFile(this.indexFile, line, "utf8");
9035
+ this._indexCache = null;
9038
9036
  this.indexAppendCount++;
9039
9037
  } catch {
9040
9038
  }
@@ -9054,6 +9052,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
9054
9052
  const lines = entries.map((s) => JSON.stringify(s)).join("\n") + "\n";
9055
9053
  await fsp6.writeFile(tmp, lines, "utf8");
9056
9054
  await fsp6.rename(tmp, this.indexFile);
9055
+ this._indexCache = null;
9057
9056
  } catch (err) {
9058
9057
  outcome = "failure";
9059
9058
  errorMsg = toErrorMessage(err);
@@ -9067,10 +9066,22 @@ var DefaultSessionStore = class _DefaultSessionStore {
9067
9066
  * Returns empty array when the index doesn't exist or is corrupt.
9068
9067
  */
9069
9068
  async readIndex() {
9069
+ let stat7;
9070
+ try {
9071
+ const s = await fsp6.stat(this.indexFile);
9072
+ stat7 = { mtimeMs: s.mtimeMs, size: s.size };
9073
+ } catch {
9074
+ this._indexCache = null;
9075
+ return [];
9076
+ }
9077
+ if (this._indexCache !== null && this._indexCache.mtimeMs === stat7.mtimeMs && this._indexCache.size === stat7.size) {
9078
+ return [...this._indexCache.summaries];
9079
+ }
9070
9080
  let raw;
9071
9081
  try {
9072
9082
  raw = await fsp6.readFile(this.indexFile, "utf8");
9073
9083
  } catch {
9084
+ this._indexCache = null;
9074
9085
  return [];
9075
9086
  }
9076
9087
  const deleted = /* @__PURE__ */ new Set();
@@ -9090,7 +9101,9 @@ var DefaultSessionStore = class _DefaultSessionStore {
9090
9101
  } catch {
9091
9102
  }
9092
9103
  }
9093
- return Array.from(seen.values());
9104
+ const summaries = Array.from(seen.values());
9105
+ this._indexCache = { ...stat7, summaries };
9106
+ return [...summaries];
9094
9107
  }
9095
9108
  /**
9096
9109
  * Rebuild the index from disk by scanning all sessions and writing a
@@ -9104,6 +9117,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
9104
9117
  const lines = valid.map((s) => JSON.stringify(s)).join("\n") + "\n";
9105
9118
  await fsp6.writeFile(tmp, lines, "utf8");
9106
9119
  await fsp6.rename(tmp, this.indexFile);
9120
+ this._indexCache = null;
9107
9121
  return valid.length;
9108
9122
  }
9109
9123
  /** Recursively collect session IDs from date-shard subdirectories.
@@ -9144,8 +9158,8 @@ var DefaultSessionStore = class _DefaultSessionStore {
9144
9158
  return JSON.parse(raw);
9145
9159
  } catch {
9146
9160
  const full = this.sessionPath(id, ".jsonl");
9147
- const stat6 = await fsp6.stat(full);
9148
- const summary = await this.summarize(id, stat6.mtime.toISOString());
9161
+ const stat7 = await fsp6.stat(full);
9162
+ const summary = await this.summarize(id, stat7.mtime.toISOString());
9149
9163
  await atomicWrite(manifest, JSON.stringify(summary), { mode: 384 }).catch((err) => {
9150
9164
  const msg = toErrorMessage(err);
9151
9165
  this.emitError(id, manifest, "summary_fallback", msg, true);
@@ -9227,8 +9241,8 @@ var DefaultSessionStore = class _DefaultSessionStore {
9227
9241
  const pruneFile = async (dir, name, prefix) => {
9228
9242
  const jsonlPath = path5.join(dir, name);
9229
9243
  try {
9230
- const stat6 = await fsp6.stat(jsonlPath);
9231
- if (stat6.mtimeMs >= cutoff) return;
9244
+ const stat7 = await fsp6.stat(jsonlPath);
9245
+ if (stat7.mtimeMs >= cutoff) return;
9232
9246
  } catch {
9233
9247
  return;
9234
9248
  }
@@ -9803,6 +9817,12 @@ var FileSessionWriter = class _FileSessionWriter {
9803
9817
  files
9804
9818
  });
9805
9819
  }
9820
+ /**
9821
+ * Truncate the session file to the checkpoint with the given promptIndex,
9822
+ * removing all events that follow it. Uses a single-pass byte-offset scan
9823
+ * so post-checkpoint content is never read or parsed — O(1) memory instead
9824
+ * of O(N) JSON.parse calls over the full file.
9825
+ */
9806
9826
  async truncateToCheckpoint(targetPromptIndex) {
9807
9827
  if (!this.filePath) return 0;
9808
9828
  if (this.flushTimer) {
@@ -9811,51 +9831,118 @@ var FileSessionWriter = class _FileSessionWriter {
9811
9831
  }
9812
9832
  await this.flushBuffer();
9813
9833
  await this.writeChain;
9814
- const raw = await fsp6.readFile(this.filePath, "utf8");
9815
- const lines = raw.split("\n");
9816
- const kept = [];
9834
+ const CHUNK_SIZE = 65536;
9835
+ let fd;
9836
+ let fileOffset = 0;
9837
+ let lineStartOffset = 0;
9838
+ let checkpointByteOffset = -1;
9817
9839
  let removedCount = 0;
9818
- let targetCheckpointLine = -1;
9819
- let afterTarget = false;
9820
- for (let i = 0; i < lines.length; i++) {
9821
- const line = expectDefined(lines[i]);
9822
- if (!line.trim()) continue;
9823
- let event;
9824
- try {
9825
- event = JSON.parse(line);
9826
- } catch {
9827
- kept.push(line);
9828
- continue;
9829
- }
9830
- if (event.type === "checkpoint") {
9831
- if (event.promptIndex === targetPromptIndex) {
9832
- targetCheckpointLine = kept.length;
9833
- afterTarget = true;
9834
- } else if (event.promptIndex > targetPromptIndex) {
9835
- afterTarget = true;
9840
+ let targetCheckpointSeen = false;
9841
+ try {
9842
+ fd = await fsp6.open(this.filePath, "r", 384);
9843
+ while (true) {
9844
+ const buf = Buffer.alloc(CHUNK_SIZE);
9845
+ const { bytesRead } = await fd.read(buf, 0, CHUNK_SIZE, fileOffset);
9846
+ if (bytesRead === 0) break;
9847
+ let chunkPos = 0;
9848
+ while (chunkPos < bytesRead) {
9849
+ const idx = buf.indexOf("\n", chunkPos);
9850
+ if (idx === -1) {
9851
+ lineStartOffset = fileOffset + chunkPos;
9852
+ break;
9853
+ }
9854
+ if (checkpointByteOffset !== -1) {
9855
+ removedCount++;
9856
+ } else {
9857
+ const lineBytes = buf.subarray(chunkPos, idx);
9858
+ const line = new TextDecoder("utf-8", { fatal: false }).decode(lineBytes);
9859
+ if (line.trim()) {
9860
+ try {
9861
+ const event = JSON.parse(line);
9862
+ if (event.type === "checkpoint") {
9863
+ if (event.promptIndex === targetPromptIndex) {
9864
+ checkpointByteOffset = lineStartOffset;
9865
+ targetCheckpointSeen = true;
9866
+ } else if (event.promptIndex !== void 0 && event.promptIndex > targetPromptIndex) {
9867
+ checkpointByteOffset = lineStartOffset;
9868
+ }
9869
+ } else if (targetCheckpointSeen && event.promptIndex !== void 0 && event.promptIndex > targetPromptIndex) {
9870
+ removedCount++;
9871
+ } else if (targetCheckpointSeen && event.promptIndex === void 0) {
9872
+ removedCount++;
9873
+ } else if (!targetCheckpointSeen && event.promptIndex === void 0) {
9874
+ removedCount++;
9875
+ } else if (!targetCheckpointSeen && event.promptIndex !== void 0 && event.promptIndex > targetPromptIndex) {
9876
+ removedCount++;
9877
+ }
9878
+ } catch {
9879
+ }
9880
+ }
9881
+ }
9882
+ chunkPos = idx + 1;
9883
+ lineStartOffset = fileOffset + chunkPos;
9836
9884
  }
9837
- }
9838
- if (event.promptIndex !== void 0 && event.promptIndex > targetPromptIndex) {
9839
- removedCount++;
9840
- } else if (event.promptIndex === void 0) {
9841
- if (!afterTarget || targetCheckpointLine === -1) {
9842
- kept.push(line);
9843
- } else {
9844
- removedCount++;
9885
+ fileOffset += bytesRead;
9886
+ if (chunkPos >= bytesRead) {
9887
+ lineStartOffset = fileOffset;
9845
9888
  }
9846
- } else {
9847
- kept.push(line);
9848
9889
  }
9890
+ } finally {
9891
+ await fd?.close();
9849
9892
  }
9850
- const truncated = kept.join("\n");
9893
+ if (checkpointByteOffset === -1) return 0;
9894
+ await this.writeChain;
9895
+ await this.handle.close();
9851
9896
  const tmpPath = `${this.filePath}.rewind.tmp`;
9852
- await fsp6.writeFile(tmpPath, truncated + "\n", "utf8");
9897
+ const src = await fsp6.open(this.filePath, "r", 384);
9853
9898
  try {
9854
- await this.handle.close();
9899
+ const statResult = await src.stat();
9900
+ const totalSize = statResult.size;
9901
+ const prefixBytes = checkpointByteOffset;
9902
+ let newlineAfterCheckpoint = prefixBytes;
9903
+ if (prefixBytes < totalSize) {
9904
+ const probeBuf = Buffer.alloc(Math.min(CHUNK_SIZE, totalSize - prefixBytes));
9905
+ const { bytesRead: probeRead } = await src.read(probeBuf, 0, probeBuf.length, prefixBytes);
9906
+ if (probeRead > 0) {
9907
+ const nl = probeBuf.indexOf("\n");
9908
+ newlineAfterCheckpoint = nl !== -1 ? prefixBytes + nl + 1 : totalSize;
9909
+ }
9910
+ } else {
9911
+ newlineAfterCheckpoint = totalSize;
9912
+ }
9913
+ const writeFd = await fsp6.open(tmpPath, "w", 384);
9914
+ try {
9915
+ let copied = 0;
9916
+ let readOffset = 0;
9917
+ while (readOffset < newlineAfterCheckpoint) {
9918
+ const toCopy = Math.min(CHUNK_SIZE, newlineAfterCheckpoint - readOffset);
9919
+ const copyBuf = Buffer.alloc(toCopy);
9920
+ const { bytesRead: r } = await src.read(copyBuf, 0, toCopy, readOffset);
9921
+ if (r === 0) break;
9922
+ await writeFd.write(copyBuf, 0, r);
9923
+ readOffset += r;
9924
+ copied += r;
9925
+ }
9926
+ const raw = await fsp6.readFile(this.filePath);
9927
+ const tail = raw.subarray(newlineAfterCheckpoint).toString("utf8");
9928
+ for (const line of tail.split("\n")) {
9929
+ if (!line.trim()) continue;
9930
+ try {
9931
+ JSON.parse(line);
9932
+ } catch {
9933
+ await writeFd.write(`${line}
9934
+ `, void 0, "utf8");
9935
+ }
9936
+ }
9937
+ } finally {
9938
+ await writeFd.close();
9939
+ }
9940
+ await src.close();
9855
9941
  await fsp6.rename(tmpPath, this.filePath);
9856
9942
  this.handle = await fsp6.open(this.filePath, "a", 384);
9857
9943
  } catch (err) {
9858
9944
  await fsp6.unlink(tmpPath).catch(() => void 0);
9945
+ this.handle = await fsp6.open(this.filePath, "a", 384).catch(() => this.handle);
9859
9946
  throw err;
9860
9947
  }
9861
9948
  await this.append({
@@ -10394,8 +10481,12 @@ function normalizeRecipient(to) {
10394
10481
  // src/coordination/mailbox.ts
10395
10482
  var MAILBOX_FILE = "_mailbox.jsonl";
10396
10483
  var LINE_SEPARATOR = "\n";
10484
+ var MESSAGE_CACHE_MAX_ENTRIES = 1e4;
10397
10485
  var DefaultMailbox = class {
10398
10486
  filePath;
10487
+ _messageCache = null;
10488
+ _messageCacheMtime = -1;
10489
+ _messageCacheSize = -1;
10399
10490
  constructor(sessionDir) {
10400
10491
  this.filePath = path5.join(sessionDir, MAILBOX_FILE);
10401
10492
  }
@@ -10425,12 +10516,13 @@ var DefaultMailbox = class {
10425
10516
  await fsp6.mkdir(path5.dirname(this.filePath), { recursive: true });
10426
10517
  await withFileLock(this.filePath, async () => {
10427
10518
  await fsp6.appendFile(this.filePath, line, "utf8");
10519
+ this._pushToCache(msg);
10428
10520
  });
10429
10521
  return msg;
10430
10522
  }
10431
10523
  // ── Query ─────────────────────────────────────────────────────────────
10432
10524
  async query(q) {
10433
- const all = await this._readAll();
10525
+ const all = await this._readAllCached();
10434
10526
  const limit = q.limit ?? 50;
10435
10527
  const order = q.minPriority !== void 0 ? { low: 0, normal: 1, high: 2 } : null;
10436
10528
  const minPriorityRank = order && q.minPriority !== void 0 ? order[q.minPriority] : 0;
@@ -10485,12 +10577,13 @@ var DefaultMailbox = class {
10485
10577
  const serialized = all.map((m) => JSON.stringify(m)).join(LINE_SEPARATOR) + LINE_SEPARATOR;
10486
10578
  await fsp6.writeFile(this.filePath, serialized, "utf8");
10487
10579
  }
10580
+ this._setMessageCache(all);
10488
10581
  });
10489
10582
  return updated;
10490
10583
  }
10491
10584
  // ── Agent statuses ────────────────────────────────────────────────────
10492
10585
  async getAgentStatuses() {
10493
- const all = await this._readAll();
10586
+ const all = await this._readAllCached();
10494
10587
  const latest = /* @__PURE__ */ new Map();
10495
10588
  for (const m of all) {
10496
10589
  if (m.type !== "status") continue;
@@ -10526,16 +10619,20 @@ var DefaultMailbox = class {
10526
10619
  async heartbeat(_input) {
10527
10620
  }
10528
10621
  async unreadCount(forAgentId) {
10529
- const all = await this._readAll();
10622
+ const all = await this._readAllCached();
10530
10623
  return all.filter(
10531
10624
  (m) => (m.to === forAgentId || m.to === "*") && !(forAgentId in m.readBy) && !m.completed
10532
10625
  ).length;
10533
10626
  }
10534
10627
  async close() {
10628
+ this._messageCache = null;
10629
+ this._messageCacheMtime = -1;
10630
+ this._messageCacheSize = -1;
10535
10631
  }
10536
10632
  async clearAll() {
10537
10633
  await withFileLock(this.filePath, async () => {
10538
10634
  await fsp6.writeFile(this.filePath, "", "utf8");
10635
+ this._setMessageCache([]);
10539
10636
  });
10540
10637
  }
10541
10638
  async purgeStale(opts) {
@@ -10543,13 +10640,14 @@ var DefaultMailbox = class {
10543
10640
  const INCOMPLETE_MAX_AGE_MS = opts?.incompleteMaxAgeMs ?? 6048e5;
10544
10641
  let completedPurged = 0;
10545
10642
  let incompletePurged = 0;
10643
+ let remaining = 0;
10546
10644
  await withFileLock(this.filePath, async () => {
10547
- const all2 = await this._readAll();
10645
+ const all = await this._readAll();
10548
10646
  const now = Date.now();
10549
10647
  const cutoffCompleted = now - COMPLETED_MAX_AGE_MS;
10550
10648
  const cutoffIncomplete = now - INCOMPLETE_MAX_AGE_MS;
10551
10649
  const kept = [];
10552
- for (const msg of all2) {
10650
+ for (const msg of all) {
10553
10651
  const msgTime = new Date(msg.timestamp).getTime();
10554
10652
  const completedTime = msg.completedAt ? new Date(msg.completedAt).getTime() : 0;
10555
10653
  if (msg.completed && completedTime < cutoffCompleted) {
@@ -10562,17 +10660,18 @@ var DefaultMailbox = class {
10562
10660
  }
10563
10661
  kept.push(msg);
10564
10662
  }
10565
- if (kept.length < all2.length) {
10663
+ remaining = kept.length;
10664
+ if (kept.length < all.length) {
10566
10665
  const content = kept.map((m) => JSON.stringify(m)).join(LINE_SEPARATOR) + LINE_SEPARATOR;
10567
10666
  await fsp6.writeFile(this.filePath, content, "utf8");
10568
10667
  }
10668
+ this._setMessageCache(kept);
10569
10669
  });
10570
- const all = await this._readAll();
10571
10670
  return {
10572
10671
  completedPurged,
10573
10672
  incompletePurged,
10574
10673
  totalPurged: completedPurged + incompletePurged,
10575
- remaining: all.length
10674
+ remaining
10576
10675
  };
10577
10676
  }
10578
10677
  // ── Client registry stubs (not applicable per-session) ─────────────────
@@ -10611,6 +10710,52 @@ var DefaultMailbox = class {
10611
10710
  throw err;
10612
10711
  }
10613
10712
  }
10713
+ async _readAllCached() {
10714
+ try {
10715
+ const st = await fsp6.stat(this.filePath);
10716
+ if (this._messageCache !== null && this._messageCacheMtime === st.mtimeMs && this._messageCacheSize === st.size) {
10717
+ return this._messageCache;
10718
+ }
10719
+ const all = await this._readAll();
10720
+ this._setMessageCache(all, st.mtimeMs, st.size);
10721
+ return all;
10722
+ } catch (err) {
10723
+ if (err.code === "ENOENT") {
10724
+ this._setMessageCache([], -1, -1);
10725
+ return [];
10726
+ }
10727
+ throw err;
10728
+ }
10729
+ }
10730
+ _setMessageCache(messages, mtime, size) {
10731
+ if (messages.length > MESSAGE_CACHE_MAX_ENTRIES) {
10732
+ this._messageCache = null;
10733
+ this._messageCacheMtime = -1;
10734
+ this._messageCacheSize = -1;
10735
+ return;
10736
+ }
10737
+ this._messageCache = messages;
10738
+ if (mtime !== void 0 && size !== void 0) {
10739
+ this._messageCacheMtime = mtime;
10740
+ this._messageCacheSize = size;
10741
+ return;
10742
+ }
10743
+ void fsp6.stat(this.filePath).then((st) => {
10744
+ this._messageCacheMtime = st.mtimeMs;
10745
+ this._messageCacheSize = st.size;
10746
+ }).catch(() => {
10747
+ });
10748
+ }
10749
+ _pushToCache(msg) {
10750
+ if (this._messageCache === null) return;
10751
+ if (this._messageCache.length >= MESSAGE_CACHE_MAX_ENTRIES) {
10752
+ this._messageCache = null;
10753
+ this._messageCacheMtime = -1;
10754
+ this._messageCacheSize = -1;
10755
+ return;
10756
+ }
10757
+ this._messageCache.push(msg);
10758
+ }
10614
10759
  };
10615
10760
  var BrainMonitor = class {
10616
10761
  constructor(opts) {
@@ -10751,7 +10896,7 @@ var CLIENT_STALE_MS = 6e4;
10751
10896
  var HEARTBEAT_THROTTLE_MS = 5e3;
10752
10897
  var REGISTRY_CACHE_TTL_MS = 2e3;
10753
10898
  var LINE_SEPARATOR2 = "\n";
10754
- var MESSAGE_CACHE_MAX_ENTRIES = 1e4;
10899
+ var MESSAGE_CACHE_MAX_ENTRIES2 = 1e4;
10755
10900
  function resolveProjectDir(projectRoot, globalRoot) {
10756
10901
  return path5.join(globalRoot, "projects", projectSlug(projectRoot));
10757
10902
  }
@@ -11083,6 +11228,7 @@ var GlobalMailbox = class {
11083
11228
  name: input.name,
11084
11229
  source: input.source
11085
11230
  });
11231
+ this.publishHqMailboxSnapshot();
11086
11232
  }
11087
11233
  async clientHeartbeat(input) {
11088
11234
  const last = this._lastClientHeartbeat.get(input.clientId) ?? 0;
@@ -11104,6 +11250,7 @@ var GlobalMailbox = class {
11104
11250
  this._events?.emitCustom("mailbox.client_heartbeat", {
11105
11251
  clientId: input.clientId
11106
11252
  });
11253
+ this.publishHqMailboxSnapshot();
11107
11254
  }
11108
11255
  async getClientStatuses() {
11109
11256
  await this._ensureClientRegistry();
@@ -11250,7 +11397,7 @@ var GlobalMailbox = class {
11250
11397
  * read or wrote it under the file lock).
11251
11398
  */
11252
11399
  _setMessageCache(messages, mtime, size) {
11253
- if (messages.length > MESSAGE_CACHE_MAX_ENTRIES) {
11400
+ if (messages.length > MESSAGE_CACHE_MAX_ENTRIES2) {
11254
11401
  this._messageCache = null;
11255
11402
  this._messageCacheMtime = -1;
11256
11403
  this._messageCacheSize = -1;
@@ -11276,7 +11423,7 @@ var GlobalMailbox = class {
11276
11423
  */
11277
11424
  _pushToCache(msg) {
11278
11425
  if (this._messageCache === null) return;
11279
- if (this._messageCache.length >= MESSAGE_CACHE_MAX_ENTRIES) {
11426
+ if (this._messageCache.length >= MESSAGE_CACHE_MAX_ENTRIES2) {
11280
11427
  this._messageCache = null;
11281
11428
  this._messageCacheMtime = -1;
11282
11429
  this._messageCacheSize = -1;
@@ -11325,7 +11472,7 @@ var GlobalMailbox = class {
11325
11472
  obj[id] = agent;
11326
11473
  }
11327
11474
  const tmp = `${this.registryPath}.${randomUUID().slice(0, 8)}.tmp`;
11328
- await fsp6.writeFile(tmp, JSON.stringify(obj, null, 2), "utf8");
11475
+ await fsp6.writeFile(tmp, JSON.stringify(obj), "utf8");
11329
11476
  await fsp6.rename(tmp, this.registryPath);
11330
11477
  }
11331
11478
  // ── Client registry internals ───────────────────────────────────────────
@@ -11370,7 +11517,7 @@ var GlobalMailbox = class {
11370
11517
  obj[id] = client;
11371
11518
  }
11372
11519
  const tmp = `${this.clientRegistryPath}.${randomUUID().slice(0, 8)}.tmp`;
11373
- await fsp6.writeFile(tmp, JSON.stringify(obj, null, 2), "utf8");
11520
+ await fsp6.writeFile(tmp, JSON.stringify(obj), "utf8");
11374
11521
  await fsp6.rename(tmp, this.clientRegistryPath);
11375
11522
  }
11376
11523
  };
@@ -12563,7 +12710,7 @@ var TaskDAG = class {
12563
12710
  }
12564
12711
  for (const depId of node.dependents) {
12565
12712
  const dep = this.nodes.get(depId);
12566
- if (dep && dep.deps.every((d) => !this.nodes.has(d) || this.nodes.get(d).status === "done")) {
12713
+ if (dep?.deps.every((d) => !this.nodes.has(d) || this.nodes.get(d).status === "done")) {
12567
12714
  this._transition(depId, "pending", "ready");
12568
12715
  }
12569
12716
  }
@@ -12825,7 +12972,7 @@ var ConsensusProtocol = class {
12825
12972
  */
12826
12973
  async initiateVote(changeId) {
12827
12974
  const change = this.graph.get(changeId);
12828
- if (!change || change.type !== "change") {
12975
+ if (change?.type !== "change") {
12829
12976
  throw new Error(`ConsensusProtocol: no change found with id "${changeId}"`);
12830
12977
  }
12831
12978
  await this.graph.update(changeId, { status: "proposed", votes: [] });
@@ -12838,7 +12985,7 @@ var ConsensusProtocol = class {
12838
12985
  */
12839
12986
  async castVote(changeId, voterId, value, rationale) {
12840
12987
  const change = this.graph.get(changeId);
12841
- if (!change || change.type !== "change") {
12988
+ if (change?.type !== "change") {
12842
12989
  throw new Error(`ConsensusProtocol: no change found for "${changeId}"`);
12843
12990
  }
12844
12991
  const voter = this.voters.get(voterId);
@@ -12892,7 +13039,7 @@ var ConsensusProtocol = class {
12892
13039
  */
12893
13040
  getStatus(changeId) {
12894
13041
  const change = this.graph.get(changeId);
12895
- if (!change || change.type !== "change") return null;
13042
+ if (change?.type !== "change") return null;
12896
13043
  const eligible = this._eligibleVoters(change);
12897
13044
  return this._resolve(changeId, change.votes, eligible);
12898
13045
  }
@@ -13095,7 +13242,7 @@ var ChangeManager = class {
13095
13242
  */
13096
13243
  async submitForReview(changeId) {
13097
13244
  const change = this.graph.get(changeId);
13098
- if (!change || change.type !== "change") {
13245
+ if (change?.type !== "change") {
13099
13246
  throw new Error(`ChangeManager: no change found "${changeId}"`);
13100
13247
  }
13101
13248
  if (change.status !== "proposed") {
@@ -13157,7 +13304,7 @@ var ChangeManager = class {
13157
13304
  */
13158
13305
  async proposeRollback(appliedChangeId, reason) {
13159
13306
  const original = this.graph.get(appliedChangeId);
13160
- if (!original || original.type !== "change") return null;
13307
+ if (original?.type !== "change") return null;
13161
13308
  const rollbackFiles = original.files.map((f) => ({
13162
13309
  path: f.path,
13163
13310
  action: f.action === "create" ? "delete" : f.action === "delete" ? "create" : "modify"
@@ -13711,7 +13858,7 @@ var TaskAuctioneer = class {
13711
13858
  */
13712
13859
  async bid(taskId, agent, rationale) {
13713
13860
  const goal = this.graph.get(taskId);
13714
- if (!goal || goal.type !== "goal") return false;
13861
+ if (goal?.type !== "goal") return false;
13715
13862
  if (goal.status !== "pending") return false;
13716
13863
  const currentCount = this._getAgentTaskCount(agent.agentId);
13717
13864
  if (currentCount >= this.maxTasksPerAgent) return false;
@@ -13760,7 +13907,7 @@ Score: ${score.toFixed(2)}`
13760
13907
  */
13761
13908
  async claim(taskId, agentId, agentName) {
13762
13909
  const goal = this.graph.get(taskId);
13763
- if (!goal || goal.type !== "goal") return false;
13910
+ if (goal?.type !== "goal") return false;
13764
13911
  if (goal.status !== "pending") return false;
13765
13912
  this._cancelBidWindow(taskId);
13766
13913
  await this.graph.update(taskId, {