@adhdev/daemon-standalone 1.0.41 → 1.0.42-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31423,9 +31423,9 @@ var require_streamx = __commonJS({
31423
31423
  }
31424
31424
  });
31425
31425
 
31426
- // ../daemon-core/node_modules/b4a/index.js
31426
+ // ../../node_modules/tar-stream/node_modules/b4a/index.js
31427
31427
  var require_b4a2 = __commonJS({
31428
- "../daemon-core/node_modules/b4a/index.js"(exports2, module2) {
31428
+ "../../node_modules/tar-stream/node_modules/b4a/index.js"(exports2, module2) {
31429
31429
  "use strict";
31430
31430
  function isBuffer(value) {
31431
31431
  return Buffer.isBuffer(value) || value instanceof Uint8Array;
@@ -31581,9 +31581,9 @@ var require_b4a2 = __commonJS({
31581
31581
  }
31582
31582
  });
31583
31583
 
31584
- // ../daemon-core/node_modules/tar-stream/headers.js
31584
+ // ../../node_modules/tar-stream/headers.js
31585
31585
  var require_headers = __commonJS({
31586
- "../daemon-core/node_modules/tar-stream/headers.js"(exports2) {
31586
+ "../../node_modules/tar-stream/headers.js"(exports2) {
31587
31587
  "use strict";
31588
31588
  var b4a = require_b4a2();
31589
31589
  var ZEROS = "0000000000000000000";
@@ -31844,9 +31844,9 @@ var require_headers = __commonJS({
31844
31844
  }
31845
31845
  });
31846
31846
 
31847
- // ../daemon-core/node_modules/tar-stream/extract.js
31847
+ // ../../node_modules/tar-stream/extract.js
31848
31848
  var require_extract = __commonJS({
31849
- "../daemon-core/node_modules/tar-stream/extract.js"(exports2, module2) {
31849
+ "../../node_modules/tar-stream/extract.js"(exports2, module2) {
31850
31850
  "use strict";
31851
31851
  var { Writable, Readable, getStreamError } = require_streamx();
31852
31852
  var FIFO = require_fast_fifo();
@@ -32189,9 +32189,9 @@ var require_extract = __commonJS({
32189
32189
  }
32190
32190
  });
32191
32191
 
32192
- // ../daemon-core/node_modules/tar-stream/constants.js
32192
+ // ../../node_modules/tar-stream/constants.js
32193
32193
  var require_constants = __commonJS({
32194
- "../daemon-core/node_modules/tar-stream/constants.js"(exports2, module2) {
32194
+ "../../node_modules/tar-stream/constants.js"(exports2, module2) {
32195
32195
  "use strict";
32196
32196
  var constants = {
32197
32197
  // just for envs without fs
@@ -32210,9 +32210,9 @@ var require_constants = __commonJS({
32210
32210
  }
32211
32211
  });
32212
32212
 
32213
- // ../daemon-core/node_modules/tar-stream/pack.js
32213
+ // ../../node_modules/tar-stream/pack.js
32214
32214
  var require_pack = __commonJS({
32215
- "../daemon-core/node_modules/tar-stream/pack.js"(exports2, module2) {
32215
+ "../../node_modules/tar-stream/pack.js"(exports2, module2) {
32216
32216
  "use strict";
32217
32217
  var { Readable, Writable, getStreamError } = require_streamx();
32218
32218
  var b4a = require_b4a2();
@@ -32445,9 +32445,9 @@ var require_pack = __commonJS({
32445
32445
  }
32446
32446
  });
32447
32447
 
32448
- // ../daemon-core/node_modules/tar-stream/index.js
32448
+ // ../../node_modules/tar-stream/index.js
32449
32449
  var require_tar_stream = __commonJS({
32450
- "../daemon-core/node_modules/tar-stream/index.js"(exports2) {
32450
+ "../../node_modules/tar-stream/index.js"(exports2) {
32451
32451
  "use strict";
32452
32452
  exports2.extract = require_extract();
32453
32453
  exports2.pack = require_pack();
@@ -32690,9 +32690,9 @@ var require_pump = __commonJS({
32690
32690
  }
32691
32691
  });
32692
32692
 
32693
- // ../daemon-core/node_modules/tar-fs/index.js
32693
+ // ../../node_modules/tar-fs/index.js
32694
32694
  var require_tar_fs = __commonJS({
32695
- "../daemon-core/node_modules/tar-fs/index.js"(exports2) {
32695
+ "../../node_modules/tar-fs/index.js"(exports2) {
32696
32696
  "use strict";
32697
32697
  var tar = require_tar_stream();
32698
32698
  var pump = require_pump();
@@ -36556,10 +36556,10 @@ var require_dist3 = __commonJS({
36556
36556
  }
36557
36557
  function getDaemonBuildInfo() {
36558
36558
  if (cached2) return cached2;
36559
- const commit = readInjected(true ? "dc9692fede78fb48fa51439a40fe9436b0b08df0" : void 0) ?? "unknown";
36560
- const commitShort = readInjected(true ? "dc9692f" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36561
- const version2 = readInjected(true ? "1.0.41" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36562
- const builtAt = readInjected(true ? "2026-08-10T07:09:00.605Z" : void 0);
36559
+ const commit = readInjected(true ? "887aef0e08676616ce97395698e7690167982603" : void 0) ?? "unknown";
36560
+ const commitShort = readInjected(true ? "887aef0e" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36561
+ const version2 = readInjected(true ? "1.0.42-rc.2" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36562
+ const builtAt = readInjected(true ? "2026-08-10T17:37:45.509Z" : void 0);
36563
36563
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
36564
36564
  return cached2;
36565
36565
  }
@@ -36826,9 +36826,9 @@ var require_dist3 = __commonJS({
36826
36826
  const effectiveOptions = options.timeoutMs === void 0 ? { ...options, timeoutMs: GIT_STATUS_TIMEOUT_MS } : options;
36827
36827
  const cacheKey = statusCacheKey(workspace, options);
36828
36828
  if (!options.forceFresh) {
36829
- const cached4 = lastKnownGoodStatus.get(cacheKey);
36830
- if (cached4 && lastCheckedAt - cached4.cachedAt < GIT_STATUS_CACHE_TTL_MS) {
36831
- return cached4.status;
36829
+ const cached5 = lastKnownGoodStatus.get(cacheKey);
36830
+ if (cached5 && lastCheckedAt - cached5.cachedAt < GIT_STATUS_CACHE_TTL_MS) {
36831
+ return cached5.status;
36832
36832
  }
36833
36833
  }
36834
36834
  try {
@@ -36839,10 +36839,10 @@ var require_dist3 = __commonJS({
36839
36839
  } catch (error48) {
36840
36840
  const gitError = error48 instanceof GitCommandError ? error48 : new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error48 });
36841
36841
  if (isTransientGitFailure(gitError)) {
36842
- const cached4 = lastKnownGoodStatus.get(cacheKey)?.status;
36843
- if (cached4) {
36842
+ const cached5 = lastKnownGoodStatus.get(cacheKey)?.status;
36843
+ if (cached5) {
36844
36844
  return {
36845
- ...cached4,
36845
+ ...cached5,
36846
36846
  lastCheckedAt,
36847
36847
  upstreamStatus: "unavailable",
36848
36848
  error: gitError.stderr || gitError.message,
@@ -37065,9 +37065,9 @@ var require_dist3 = __commonJS({
37065
37065
  return { config: null, sourceKey: "no-repo-root" };
37066
37066
  }
37067
37067
  const loaded = loadChangeImpactConfig(repoRoot);
37068
- const cached4 = changeImpactConfigCache.get(repoRoot);
37069
- if (cached4 && cached4.sourceKey === loaded.sourceKey) {
37070
- return { config: cached4.config, sourceKey: loaded.sourceKey };
37068
+ const cached5 = changeImpactConfigCache.get(repoRoot);
37069
+ if (cached5 && cached5.sourceKey === loaded.sourceKey) {
37070
+ return { config: cached5.config, sourceKey: loaded.sourceKey };
37071
37071
  }
37072
37072
  const config2 = loaded.sourceType === "repo_file" ? loaded.config ?? null : null;
37073
37073
  changeImpactConfigCache.set(repoRoot, { sourceKey: loaded.sourceKey, config: config2 });
@@ -37817,7 +37817,7 @@ var require_dist3 = __commonJS({
37817
37817
  }
37818
37818
  });
37819
37819
  function resolveBuildTrack(env2 = process.env) {
37820
- const injected = true ? "" : void 0;
37820
+ const injected = true ? "preview" : void 0;
37821
37821
  const stamped = typeof injected === "string" ? injected.trim() : "";
37822
37822
  const raw = (stamped || (env2[BUILD_CHANNEL_ENV_VAR] ?? "").trim()).toLowerCase();
37823
37823
  return raw === "preview" || raw === "next" ? "preview" : "stable";
@@ -51154,8 +51154,8 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
51154
51154
  }
51155
51155
  function getCachedRawEntries(meshId) {
51156
51156
  const now = Date.now();
51157
- const cached4 = ledgerReadCache.get(meshId);
51158
- if (cached4 && now - cached4.cachedAt < LEDGER_CACHE_TTL_MS) return cached4.entries;
51157
+ const cached5 = ledgerReadCache.get(meshId);
51158
+ if (cached5 && now - cached5.cachedAt < LEDGER_CACHE_TTL_MS) return cached5.entries;
51159
51159
  let entries;
51160
51160
  try {
51161
51161
  entries = readLedgerFromStore(meshId);
@@ -55357,13 +55357,13 @@ ${rendered}`, "utf-8");
55357
55357
  nodes
55358
55358
  };
55359
55359
  }
55360
- function reconcileInlineMeshCache(cached4, incoming, removedNodeIds) {
55361
- if (!cached4 || typeof cached4 !== "object" || Array.isArray(cached4)) return incoming;
55362
- if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached4;
55363
- const cachedNodes = Array.isArray(cached4.nodes) ? cached4.nodes : [];
55360
+ function reconcileInlineMeshCache(cached5, incoming, removedNodeIds) {
55361
+ if (!cached5 || typeof cached5 !== "object" || Array.isArray(cached5)) return incoming;
55362
+ if (!incoming || typeof incoming !== "object" || Array.isArray(incoming)) return cached5;
55363
+ const cachedNodes = Array.isArray(cached5.nodes) ? cached5.nodes : [];
55364
55364
  const incomingNodes = Array.isArray(incoming.nodes) ? incoming.nodes : [];
55365
- if (!cachedNodes.length || !incomingNodes.length) return { ...cached4, ...incoming };
55366
- const cachedUpdatedAt = Date.parse(readStringValue(cached4.updatedAt, cached4.updated_at) || "");
55365
+ if (!cachedNodes.length || !incomingNodes.length) return { ...cached5, ...incoming };
55366
+ const cachedUpdatedAt = Date.parse(readStringValue(cached5.updatedAt, cached5.updated_at) || "");
55367
55367
  const incomingUpdatedAt = Date.parse(readStringValue(incoming.updatedAt, incoming.updated_at) || "");
55368
55368
  const cacheFieldsWinOnConflict = Number.isFinite(cachedUpdatedAt) && (!Number.isFinite(incomingUpdatedAt) || cachedUpdatedAt > incomingUpdatedAt);
55369
55369
  const cachedById = /* @__PURE__ */ new Map();
@@ -55393,10 +55393,10 @@ ${rendered}`, "utf-8");
55393
55393
  nodes.push(cachedNode);
55394
55394
  }
55395
55395
  if (droppedNodeIds.length > 0) {
55396
- LOG2.info("Mesh", `[NodeMembershipMerge] mesh=${String(cached4.id || incoming.id || "unknown")} droppedNodeIds=${JSON.stringify(droppedNodeIds)} reason=tombstoned_removal cachedCount=${cachedNodes.length} incomingCount=${incomingNodes.length}`);
55396
+ LOG2.info("Mesh", `[NodeMembershipMerge] mesh=${String(cached5.id || incoming.id || "unknown")} droppedNodeIds=${JSON.stringify(droppedNodeIds)} reason=tombstoned_removal cachedCount=${cachedNodes.length} incomingCount=${incomingNodes.length}`);
55397
55397
  }
55398
55398
  return {
55399
- ...cached4,
55399
+ ...cached5,
55400
55400
  ...incoming,
55401
55401
  nodes
55402
55402
  };
@@ -56332,9 +56332,9 @@ ${rendered}`, "utf-8");
56332
56332
  */
56333
56333
  async probe(daemonId, workspace, probe) {
56334
56334
  const key2 = this.key(daemonId, workspace);
56335
- const cached4 = this.recent.get(key2);
56336
- if (cached4 && this.now() - cached4.at < this.reuseMs) {
56337
- return cached4.value;
56335
+ const cached5 = this.recent.get(key2);
56336
+ if (cached5 && this.now() - cached5.at < this.reuseMs) {
56337
+ return cached5.value;
56338
56338
  }
56339
56339
  const existing = this.inflight.get(key2);
56340
56340
  if (existing) return existing;
@@ -58478,11 +58478,11 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
58478
58478
  return path18.join(getConfigDir2(), "history");
58479
58479
  }
58480
58480
  function readBoundedTailCache(key2, signature) {
58481
- const cached4 = boundedTailReadCache.get(key2);
58482
- if (!cached4 || cached4.signature !== signature) return null;
58481
+ const cached5 = boundedTailReadCache.get(key2);
58482
+ if (!cached5 || cached5.signature !== signature) return null;
58483
58483
  boundedTailReadCache.delete(key2);
58484
- boundedTailReadCache.set(key2, cached4);
58485
- return cached4.result;
58484
+ boundedTailReadCache.set(key2, cached5);
58485
+ return cached5.result;
58486
58486
  }
58487
58487
  function writeBoundedTailCache(key2, signature, result) {
58488
58488
  boundedTailReadCache.delete(key2);
@@ -58966,9 +58966,9 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
58966
58966
  for (const file2 of files.slice().sort()) {
58967
58967
  const filePath = path18.join(dir, file2);
58968
58968
  const signature = fileSignatures.get(file2) || `${file2}:missing`;
58969
- const cached4 = savedHistoryFileSummaryCache.get(filePath);
58969
+ const cached5 = savedHistoryFileSummaryCache.get(filePath);
58970
58970
  const persisted = persistedEntries.get(file2);
58971
- const reusableEntry = cached4?.signature === signature ? cached4 : persisted?.signature === signature ? persisted : null;
58971
+ const reusableEntry = cached5?.signature === signature ? cached5 : persisted?.signature === signature ? persisted : null;
58972
58972
  const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(dir, file2);
58973
58973
  const nextEntry = reusableEntry || {
58974
58974
  signature,
@@ -59118,16 +59118,16 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
59118
59118
  incrementalTailCache.delete(filePath);
59119
59119
  return { lines: [], coversWholeFile: true };
59120
59120
  }
59121
- const cached4 = incrementalTailCache.get(filePath);
59122
- if (cached4) {
59123
- if (cached4.size === size && cached4.mtimeMs === mtimeMs) {
59121
+ const cached5 = incrementalTailCache.get(filePath);
59122
+ if (cached5) {
59123
+ if (cached5.size === size && cached5.mtimeMs === mtimeMs) {
59124
59124
  incrementalTailCache.delete(filePath);
59125
- incrementalTailCache.set(filePath, cached4);
59126
- if (cached4.coversWholeFile || cached4.lines.length >= needed) {
59127
- return { lines: cached4.lines, coversWholeFile: cached4.coversWholeFile };
59125
+ incrementalTailCache.set(filePath, cached5);
59126
+ if (cached5.coversWholeFile || cached5.lines.length >= needed) {
59127
+ return { lines: cached5.lines, coversWholeFile: cached5.coversWholeFile };
59128
59128
  }
59129
- } else if (size > cached4.size) {
59130
- const incremental = tryIncrementalTailGrowth(filePath, cached4, size, mtimeMs, needed);
59129
+ } else if (size > cached5.size) {
59130
+ const incremental = tryIncrementalTailGrowth(filePath, cached5, size, mtimeMs, needed);
59131
59131
  if (incremental) return { lines: incremental.lines, coversWholeFile: incremental.coversWholeFile };
59132
59132
  }
59133
59133
  incrementalTailCache.delete(filePath);
@@ -59153,22 +59153,22 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
59153
59153
  storeIncrementalTailCache(filePath, result.size, result.mtimeMs, result.lines, result.coversWholeFile);
59154
59154
  return { lines: result.lines, coversWholeFile: result.coversWholeFile };
59155
59155
  }
59156
- function tryIncrementalTailGrowth(filePath, cached4, size, mtimeMs, needed) {
59156
+ function tryIncrementalTailGrowth(filePath, cached5, size, mtimeMs, needed) {
59157
59157
  const fd = fs10.openSync(filePath, "r");
59158
59158
  try {
59159
- if (cached4.size > 0) {
59159
+ if (cached5.size > 0) {
59160
59160
  const boundary = Buffer.alloc(1);
59161
- fs10.readSync(fd, boundary, 0, 1, cached4.size - 1);
59161
+ fs10.readSync(fd, boundary, 0, 1, cached5.size - 1);
59162
59162
  if (boundary[0] !== 10) return null;
59163
59163
  }
59164
- const appendedLength = size - cached4.size;
59164
+ const appendedLength = size - cached5.size;
59165
59165
  const appended = Buffer.alloc(appendedLength);
59166
- fs10.readSync(fd, appended, 0, appendedLength, cached4.size);
59166
+ fs10.readSync(fd, appended, 0, appendedLength, cached5.size);
59167
59167
  const newLines = appended.toString("utf-8").split("\n");
59168
59168
  if (newLines.length && newLines[newLines.length - 1] === "") newLines.pop();
59169
- const merged = cached4.lines.concat(newLines);
59169
+ const merged = cached5.lines.concat(newLines);
59170
59170
  const trimmed = merged.length > TAIL_LINES_RETAINED ? merged.slice(merged.length - TAIL_LINES_RETAINED) : merged;
59171
- const coversWholeFile = cached4.coversWholeFile && trimmed.length === merged.length;
59171
+ const coversWholeFile = cached5.coversWholeFile && trimmed.length === merged.length;
59172
59172
  storeIncrementalTailCache(filePath, size, mtimeMs, trimmed, coversWholeFile);
59173
59173
  if (coversWholeFile || trimmed.length >= needed) {
59174
59174
  return { lines: trimmed, coversWholeFile };
@@ -59233,8 +59233,8 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
59233
59233
  const fileSignatures = buildSavedHistoryFileSignatureMap(dir, files);
59234
59234
  const cacheKey = `${sanitized}\0${historySessionId || ""}\0${offset}\0${limit}\0${excludeRecentCount}\0${historyBehavior?.collapseConsecutiveAssistantTurns ? "1" : "0"}`;
59235
59235
  const signature = buildSavedHistoryCacheSignature(files, fileSignatures);
59236
- const cached4 = readBoundedTailCache(cacheKey, signature);
59237
- if (cached4) return cached4;
59236
+ const cached5 = readBoundedTailCache(cacheKey, signature);
59237
+ if (cached5) return cached5;
59238
59238
  const numericLimit = Math.max(1, Number(limit));
59239
59239
  const numericOffset = Math.max(0, Number(offset));
59240
59240
  const numericExclude = Math.max(0, Number(excludeRecentCount));
@@ -59277,23 +59277,23 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
59277
59277
  savedHistorySessionCache.delete(sanitized);
59278
59278
  return { sessions: [], hasMore: false };
59279
59279
  }
59280
- const cached4 = savedHistorySessionCache.get(sanitized);
59280
+ const cached5 = savedHistorySessionCache.get(sanitized);
59281
59281
  const offset = Math.max(0, options.offset || 0);
59282
59282
  const limit = Math.max(1, options.limit || 30);
59283
59283
  const indexSignature = buildSavedHistoryIndexFileSignature(dir);
59284
59284
  let cacheWasInvalidated = false;
59285
- if (cached4) {
59286
- const cacheLooksPersisted = cached4.signature.startsWith("index:");
59287
- const cacheStillValid = cacheLooksPersisted ? cached4.signature === indexSignature : (() => {
59285
+ if (cached5) {
59286
+ const cacheLooksPersisted = cached5.signature.startsWith("index:");
59287
+ const cacheStillValid = cacheLooksPersisted ? cached5.signature === indexSignature : (() => {
59288
59288
  const files2 = listHistoryFiles(dir);
59289
59289
  const fileSignatures2 = buildSavedHistoryFileSignatureMap(dir, files2);
59290
- return cached4.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
59290
+ return cached5.signature === buildSavedHistoryCacheSignature(files2, fileSignatures2);
59291
59291
  })();
59292
59292
  if (cacheStillValid) {
59293
- const sliced2 = cached4.summaries.slice(offset, offset + limit);
59293
+ const sliced2 = cached5.summaries.slice(offset, offset + limit);
59294
59294
  return {
59295
59295
  sessions: sliced2,
59296
- hasMore: cached4.summaries.length > offset + limit
59296
+ hasMore: cached5.summaries.length > offset + limit
59297
59297
  };
59298
59298
  }
59299
59299
  cacheWasInvalidated = true;
@@ -59474,6 +59474,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
59474
59474
  }
59475
59475
  return {
59476
59476
  records,
59477
+ turnTerminalMarkers: Array.isArray(result.turnTerminalMarkers) ? result.turnTerminalMarkers : void 0,
59477
59478
  sourcePath: typeof result.sourcePath === "string" ? result.sourcePath : "",
59478
59479
  sourceMtimeMs: Number(result.sourceMtimeMs) || 0,
59479
59480
  providerSessionId: typeof result.providerSessionId === "string" ? result.providerSessionId.trim() : void 0,
@@ -59541,7 +59542,10 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
59541
59542
  partialReason: nativeResult.partialReason,
59542
59543
  unavailableReason: nativeResult.unavailableReason,
59543
59544
  ownerConfirmed: nativeResult.ownerConfirmed,
59544
- attribution: nativeResult.attribution
59545
+ attribution: nativeResult.attribution,
59546
+ // (NATIVE-TURN-SIGNAL) Terminal markers ride alongside the paged messages —
59547
+ // deliberately NOT paged, since they are turn metadata, not chat content.
59548
+ turnTerminalMarkers: nativeResult.turnTerminalMarkers
59545
59549
  };
59546
59550
  }
59547
59551
  return {
@@ -64363,8 +64367,8 @@ ${cleanBody}`;
64363
64367
  }
64364
64368
  function getCachedMeshByWorkspace(workspace) {
64365
64369
  const now = Date.now();
64366
- const cached4 = meshByWorkspaceCache.get(workspace);
64367
- if (cached4 && now - cached4.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached4.mesh;
64370
+ const cached5 = meshByWorkspaceCache.get(workspace);
64371
+ if (cached5 && now - cached5.cachedAt < MESH_WORKSPACE_CACHE_TTL_MS) return cached5.mesh;
64368
64372
  const mesh = getMeshByRepo(workspace);
64369
64373
  meshByWorkspaceCache.set(workspace, { mesh, cachedAt: now });
64370
64374
  return mesh;
@@ -66022,8 +66026,8 @@ ${cleanBody}`;
66022
66026
  }
66023
66027
  }
66024
66028
  function getHoldState(synthKey, meshId) {
66025
- const cached4 = inFlightAckedHoldState.get(synthKey);
66026
- if (cached4) return cached4;
66029
+ const cached5 = inFlightAckedHoldState.get(synthKey);
66030
+ if (cached5) return cached5;
66027
66031
  const store = holdStore();
66028
66032
  if (!store) return void 0;
66029
66033
  let row;
@@ -66878,9 +66882,9 @@ ${cleanBody}`;
66878
66882
  return;
66879
66883
  }
66880
66884
  try {
66881
- const cached4 = deps.getCachedInlineMesh?.(meshId);
66882
- if (cached4 && deps.removeInlineMeshNode) {
66883
- if (deps.removeInlineMeshNode(meshId, cached4, nodeId)) removed = true;
66885
+ const cached5 = deps.getCachedInlineMesh?.(meshId);
66886
+ if (cached5 && deps.removeInlineMeshNode) {
66887
+ if (deps.removeInlineMeshNode(meshId, cached5, nodeId)) removed = true;
66884
66888
  }
66885
66889
  } catch {
66886
66890
  }
@@ -71204,6 +71208,55 @@ ${cont}` : cont;
71204
71208
  init_provider_cli_shared();
71205
71209
  }
71206
71210
  });
71211
+ function resolveNativeCompletionSignalSpec(nativeHistory) {
71212
+ if (!nativeHistory || typeof nativeHistory !== "object") return null;
71213
+ const declared = nativeHistory.completionSignal;
71214
+ if (!declared || typeof declared !== "object") return null;
71215
+ const spec = declared;
71216
+ const recordType = typeof spec.recordType === "string" ? spec.recordType.trim() : "";
71217
+ if (!recordType) return null;
71218
+ const abortRecordType = typeof spec.abortRecordType === "string" ? spec.abortRecordType.trim() : "";
71219
+ const summaryField = typeof spec.summaryField === "string" ? spec.summaryField.trim() : "";
71220
+ const turnIdField = typeof spec.turnIdField === "string" ? spec.turnIdField.trim() : "";
71221
+ return {
71222
+ recordType,
71223
+ ...abortRecordType ? { abortRecordType } : {},
71224
+ ...summaryField ? { summaryField } : {},
71225
+ ...turnIdField ? { turnIdField } : {}
71226
+ };
71227
+ }
71228
+ function providerHasNativeTurnSignal(provider) {
71229
+ if (!provider) return false;
71230
+ if (resolveNativeCompletionSignalSpec(provider.nativeHistory)) return true;
71231
+ const type2 = typeof provider.type === "string" ? provider.type.trim() : "";
71232
+ return !!type2 && BUILTIN_TURN_SIGNAL_PROVIDER_TYPES.has(type2);
71233
+ }
71234
+ function selectTurnTerminalMarker(markers, scope) {
71235
+ if (!Array.isArray(markers) || markers.length === 0) return null;
71236
+ const wantedTurnId = typeof scope.turnId === "string" && scope.turnId.trim() ? scope.turnId.trim() : "";
71237
+ if (wantedTurnId) {
71238
+ for (let i = markers.length - 1; i >= 0; i--) {
71239
+ const m = markers[i];
71240
+ if (m && m.turnId === wantedTurnId) return m;
71241
+ }
71242
+ return null;
71243
+ }
71244
+ const startedAt = typeof scope.turnStartedAt === "number" && Number.isFinite(scope.turnStartedAt) && scope.turnStartedAt > 0 ? scope.turnStartedAt : 0;
71245
+ if (!startedAt) return null;
71246
+ for (let i = markers.length - 1; i >= 0; i--) {
71247
+ const m = markers[i];
71248
+ if (!m) continue;
71249
+ if (typeof m.receivedAt === "number" && m.receivedAt >= startedAt) return m;
71250
+ }
71251
+ return null;
71252
+ }
71253
+ var BUILTIN_TURN_SIGNAL_PROVIDER_TYPES;
71254
+ var init_native_turn_signal = __esm2({
71255
+ "src/providers/completion/native-turn-signal.ts"() {
71256
+ "use strict";
71257
+ BUILTIN_TURN_SIGNAL_PROVIDER_TYPES = /* @__PURE__ */ new Set(["codex-cli"]);
71258
+ }
71259
+ });
71207
71260
  var SCRIPT_STATUS_DEBOUNCE_MS;
71208
71261
  var MAX_FINISH_RETRIES;
71209
71262
  var FINISH_RETRY_DELAY_MS;
@@ -71213,6 +71266,8 @@ ${cont}` : cont;
71213
71266
  var APPROVAL_RESUME_IDLE_DEFER_CAP_MS;
71214
71267
  var MAX_TRANSCRIPT_FINISH_DEFERS;
71215
71268
  var TRANSCRIPT_FINISH_DEFER_CAP_MS;
71269
+ var TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS;
71270
+ var BLOCKED_FINISH_WATCHDOG_MIN_DELAY_MS;
71216
71271
  var SCREEN_QUIET_IDLE_MS;
71217
71272
  var CliStateEngine;
71218
71273
  var init_cli_state_engine = __esm2({
@@ -71222,6 +71277,7 @@ ${cont}` : cont;
71222
71277
  init_provider_cli_parse();
71223
71278
  init_provider_cli_shared();
71224
71279
  init_transcript_evidence();
71280
+ init_native_turn_signal();
71225
71281
  SCRIPT_STATUS_DEBOUNCE_MS = 3e3;
71226
71282
  MAX_FINISH_RETRIES = 2;
71227
71283
  FINISH_RETRY_DELAY_MS = 300;
@@ -71231,6 +71287,8 @@ ${cont}` : cont;
71231
71287
  APPROVAL_RESUME_IDLE_DEFER_CAP_MS = 18e3;
71232
71288
  MAX_TRANSCRIPT_FINISH_DEFERS = 3;
71233
71289
  TRANSCRIPT_FINISH_DEFER_CAP_MS = 3e4;
71290
+ TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS = 5 * 6e4;
71291
+ BLOCKED_FINISH_WATCHDOG_MIN_DELAY_MS = 1e3;
71234
71292
  SCREEN_QUIET_IDLE_MS = 5e3;
71235
71293
  CliStateEngine = class {
71236
71294
  constructor(provider, runner, transport, callbacks, timeouts) {
@@ -71329,6 +71387,9 @@ ${cont}` : cont;
71329
71387
  // ── Timers ───────────────────────────────────────
71330
71388
  settleTimer = null;
71331
71389
  idleTimeout = null;
71390
+ // (INFINITE-GENERATING) Re-evaluation tick for a BLOCKED transcript finish — the only
71391
+ // thing that keeps the blocked path alive long enough for its hard cap to fire.
71392
+ blockedFinishWatchdogTimer = null;
71332
71393
  finishRetryTimer = null;
71333
71394
  providerErrorRetryTimer = null;
71334
71395
  providerErrorRetryKey = "";
@@ -71575,6 +71636,10 @@ ${cont}` : cont;
71575
71636
  this.pendingIdleFinishTimer = null;
71576
71637
  this.pendingIdleFinishAt = 0;
71577
71638
  }
71639
+ if (this.blockedFinishWatchdogTimer) {
71640
+ clearTimeout(this.blockedFinishWatchdogTimer);
71641
+ this.blockedFinishWatchdogTimer = null;
71642
+ }
71578
71643
  this.providerErrorRetryKey = "";
71579
71644
  }
71580
71645
  resetActiveTurnState() {
@@ -72079,7 +72144,10 @@ ${cont}` : cont;
72079
72144
  return;
72080
72145
  }
72081
72146
  if (this.shouldDeferIdleTimeoutFinish()) return;
72082
- if (!this.hasScreenBeenQuietForIdle(Date.now())) {
72147
+ const hasNativeTurnSignal = providerHasNativeTurnSignal(this.provider);
72148
+ const turnAgeMs = this.currentTurnStartedAt > 0 ? Date.now() - this.currentTurnStartedAt : 0;
72149
+ const keepWaitingOnScreen = hasNativeTurnSignal ? false : turnAgeMs < TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS;
72150
+ if (!this.hasScreenBeenQuietForIdle(Date.now()) && keepWaitingOnScreen) {
72083
72151
  if (this.idleTimeout) clearTimeout(this.idleTimeout);
72084
72152
  this.idleTimeout = setTimeout(() => {
72085
72153
  if (this.isWaitingForResponse) this.evaluateSettled(this.transport.getSnapshot());
@@ -72217,6 +72285,7 @@ ${cont}` : cont;
72217
72285
  this.rescheduleTranscriptFinishCheck(reason);
72218
72286
  return "deferred";
72219
72287
  }
72288
+ this.armBlockedFinishWatchdog(reason);
72220
72289
  if (this.currentStatus !== "generating" || !this.isWaitingForResponse || this.hasActionableApproval()) {
72221
72290
  this.recordTrace("transcript_finish_defer_cap_fail_closed", {
72222
72291
  reason,
@@ -72228,8 +72297,20 @@ ${cont}` : cont;
72228
72297
  });
72229
72298
  return "blocked";
72230
72299
  }
72300
+ const blockedForMs = elapsedMs;
72301
+ const hardCapTripped = blockedForMs >= TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS;
72231
72302
  const snap = this.transport.getSnapshot();
72232
72303
  if (!this.hasScreenBeenQuietForIdle(now) || this.hasRecentInteractiveActivity(snap, now)) {
72304
+ if (hardCapTripped) {
72305
+ this.recordTrace("transcript_finish_blocked_hard_cap_escape", {
72306
+ reason,
72307
+ guard: "screen_active",
72308
+ count: this.transcriptFinishDeferCount,
72309
+ elapsedMs,
72310
+ hardCapMs: TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS
72311
+ });
72312
+ return "proceed";
72313
+ }
72233
72314
  this.recordTrace("transcript_finish_defer_cap_fail_closed", {
72234
72315
  reason,
72235
72316
  guard: "screen_active",
@@ -72247,6 +72328,16 @@ ${cont}` : cont;
72247
72328
  }
72248
72329
  }
72249
72330
  if (!nativeProven) {
72331
+ if (hardCapTripped) {
72332
+ this.recordTrace("transcript_finish_blocked_hard_cap_escape", {
72333
+ reason,
72334
+ guard: "native_proof",
72335
+ count: this.transcriptFinishDeferCount,
72336
+ elapsedMs,
72337
+ hardCapMs: TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS
72338
+ });
72339
+ return "proceed";
72340
+ }
72250
72341
  this.recordTrace("transcript_finish_defer_cap_fail_closed", {
72251
72342
  reason,
72252
72343
  guard: "native_proof",
@@ -72515,6 +72606,36 @@ ${cont}` : cont;
72515
72606
  }, this.timeouts.idleFinishConfirm);
72516
72607
  this.recordTrace("transcript_finish_deferred", { reason });
72517
72608
  }
72609
+ /**
72610
+ * (INFINITE-GENERATING) Keep a BLOCKED transcript finish re-evaluated until the
72611
+ * hard cap can release it.
72612
+ *
72613
+ * rescheduleTranscriptFinishCheck only re-arms on the 'deferred' path. On 'blocked'
72614
+ * nothing re-armed at all, so finishResponse was never re-entered: the FSM went
72615
+ * fully dormant with currentTurnScope still open, and no purely time-based cap could
72616
+ * ever be consulted because no timer would fire to consult it. That is what made the
72617
+ * wedge permanent rather than merely slow.
72618
+ *
72619
+ * Deliberately NOT rescheduleTranscriptFinishCheck: this must not call setStatus or
72620
+ * clearIdleFinishCandidate (the blocked state is already correct and re-asserting it
72621
+ * would churn status history), and it must not touch transcriptFinishDeferCount —
72622
+ * the defer bound stays tripped. It is a bare re-evaluation tick, self-cancelling
72623
+ * once the turn closes.
72624
+ */
72625
+ armBlockedFinishWatchdog(reason) {
72626
+ if (this.blockedFinishWatchdogTimer) return;
72627
+ const epoch = this.responseEpoch;
72628
+ const elapsed = this.transcriptFinishDeferSince > 0 ? Date.now() - this.transcriptFinishDeferSince : 0;
72629
+ const remaining = Math.max(BLOCKED_FINISH_WATCHDOG_MIN_DELAY_MS, TRANSCRIPT_FINISH_BLOCKED_HARD_CAP_MS - elapsed);
72630
+ this.blockedFinishWatchdogTimer = setTimeout(() => {
72631
+ this.blockedFinishWatchdogTimer = null;
72632
+ if (epoch !== this.responseEpoch) return;
72633
+ if (!this.isWaitingForResponse || !this.currentTurnScope) return;
72634
+ if (this.hasActionableApproval()) return;
72635
+ this.finishResponse();
72636
+ }, remaining);
72637
+ this.recordTrace("transcript_finish_blocked_watchdog_armed", { reason, remainingMs: remaining });
72638
+ }
72518
72639
  shouldRetryFinishResponse(snap, commitResult) {
72519
72640
  if (!this.currentTurnScope) return false;
72520
72641
  if (this.hasActionableApproval()) return false;
@@ -73008,6 +73129,7 @@ ${cont}` : cont;
73008
73129
  }
73009
73130
  }
73010
73131
  if (messages.length === 0) return null;
73132
+ const turnTerminalMarkers = extractBuiltinTurnTerminalMarkers(input.agentType, lines);
73011
73133
  return {
73012
73134
  messages,
73013
73135
  providerSessionId,
@@ -73022,9 +73144,45 @@ ${cont}` : cont;
73022
73144
  providerSessionId: providerSessionId || "",
73023
73145
  agent: typeof input.agentType === "string" ? input.agentType : "unknown"
73024
73146
  })
73025
- } : {}
73147
+ } : {},
73148
+ ...turnTerminalMarkers.length > 0 ? { turnTerminalMarkers } : {}
73026
73149
  };
73027
73150
  }
73151
+ function extractBuiltinTurnTerminalMarkers(agentType, lines) {
73152
+ if (agentType !== "codex-cli") return [];
73153
+ const markers = [];
73154
+ for (const rec of lines) {
73155
+ if (String(rec?.type ?? "") !== "event_msg") continue;
73156
+ const payload = rec?.payload;
73157
+ if (!payload || typeof payload !== "object") continue;
73158
+ const payloadType = String(payload.type ?? "").trim();
73159
+ const isComplete = payloadType === "task_complete";
73160
+ const isAbort = payloadType === "turn_aborted";
73161
+ if (!isComplete && !isAbort) continue;
73162
+ const receivedAt = parseTimestamp(rec?.timestamp) ?? Date.now();
73163
+ const summary = flattenJsonlText(payload.last_agent_message);
73164
+ const rawTurnId = payload.turn_id;
73165
+ const turnId = typeof rawTurnId === "string" && rawTurnId.trim() ? rawTurnId.trim() : "";
73166
+ markers.push({
73167
+ receivedAt,
73168
+ outcome: isAbort ? "aborted" : "completed",
73169
+ summary,
73170
+ ...turnId ? { turnId } : {}
73171
+ });
73172
+ }
73173
+ return markers;
73174
+ }
73175
+ function flattenJsonlText(value) {
73176
+ if (typeof value === "string") return value.trim();
73177
+ if (value == null) return "";
73178
+ if (Array.isArray(value)) return value.map(flattenJsonlText).filter(Boolean).join("\n").trim();
73179
+ if (typeof value === "object") {
73180
+ const obj = value;
73181
+ if (typeof obj.text === "string") return obj.text.trim();
73182
+ if (typeof obj.content === "string" || Array.isArray(obj.content)) return flattenJsonlText(obj.content);
73183
+ }
73184
+ return "";
73185
+ }
73028
73186
  function resolveJsonlSourcePath(src, input) {
73029
73187
  return resolveJsonlSourcePathDetailed(src, input).path;
73030
73188
  }
@@ -74745,10 +74903,10 @@ ${lastSnapshot}`;
74745
74903
  return this.accumulatedRawBuffer.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
74746
74904
  }
74747
74905
  getFreshParsedStatusCache() {
74748
- const cached4 = this.parsedStatusCache;
74906
+ const cached5 = this.parsedStatusCache;
74749
74907
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
74750
- if (cached4 && cached4.responseBuffer === this.responseBuffer && cached4.currentTurnScope === this.engine.currentTurnScope && cached4.recentOutputBuffer === this.recentOutputBuffer && cached4.accumulatedBuffer === this.accumulatedBuffer && cached4.accumulatedRawBufferKey === accumulatedRawBufferKey && cached4.screenText === this.lastScreenText && cached4.currentStatus === this.engine.currentStatus && cached4.activeModal === this.engine.activeModal && cached4.cliName === this.cliName) {
74751
- return cached4.result;
74908
+ if (cached5 && cached5.responseBuffer === this.responseBuffer && cached5.currentTurnScope === this.engine.currentTurnScope && cached5.recentOutputBuffer === this.recentOutputBuffer && cached5.accumulatedBuffer === this.accumulatedBuffer && cached5.accumulatedRawBufferKey === accumulatedRawBufferKey && cached5.screenText === this.lastScreenText && cached5.currentStatus === this.engine.currentStatus && cached5.activeModal === this.engine.activeModal && cached5.cliName === this.cliName) {
74909
+ return cached5.result;
74752
74910
  }
74753
74911
  return null;
74754
74912
  }
@@ -75355,10 +75513,10 @@ ${lastSnapshot}`;
75355
75513
  backgroundTaskSupport: bg.support ?? "unknown",
75356
75514
  ...bg.active ? { backgroundTaskActive: true, backgroundTaskCount: bg.count, backgroundTaskIds: bg.ids } : {}
75357
75515
  };
75358
- const cached4 = this.parsedStatusCache;
75516
+ const cached5 = this.parsedStatusCache;
75359
75517
  const accumulatedRawBufferKey = this.getAccumulatedRawBufferCacheKey();
75360
- if (!this.providerOwnsTranscript() && cached4 && cached4.responseBuffer === this.responseBuffer && cached4.currentTurnScope === this.engine.currentTurnScope && cached4.recentOutputBuffer === this.recentOutputBuffer && cached4.accumulatedBuffer === this.accumulatedBuffer && cached4.accumulatedRawBufferKey === accumulatedRawBufferKey && cached4.screenText === parseScreenText && cached4.currentStatus === this.engine.currentStatus && cached4.activeModal === this.engine.activeModal && cached4.cliName === this.cliName) {
75361
- return { ...cached4.result, ...backgroundTaskFields };
75518
+ if (!this.providerOwnsTranscript() && cached5 && cached5.responseBuffer === this.responseBuffer && cached5.currentTurnScope === this.engine.currentTurnScope && cached5.recentOutputBuffer === this.recentOutputBuffer && cached5.accumulatedBuffer === this.accumulatedBuffer && cached5.accumulatedRawBufferKey === accumulatedRawBufferKey && cached5.screenText === parseScreenText && cached5.currentStatus === this.engine.currentStatus && cached5.activeModal === this.engine.activeModal && cached5.cliName === this.cliName) {
75519
+ return { ...cached5.result, ...backgroundTaskFields };
75362
75520
  }
75363
75521
  const parsed = this.runParseSession();
75364
75522
  if (!parsed || !Array.isArray(parsed.messages)) {
@@ -77729,6 +77887,7 @@ ${lastSnapshot}`;
77729
77887
  STALE_MAGI_WINDOW_MS: () => STALE_MAGI_WINDOW_MS,
77730
77888
  STALE_TERMINAL_REFINE_WINDOW_MS: () => STALE_TERMINAL_REFINE_WINDOW_MS,
77731
77889
  STANDALONE_CDP_SCAN_INTERVAL_MS: () => STANDALONE_CDP_SCAN_INTERVAL_MS2,
77890
+ SYM: () => SYM,
77732
77891
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
77733
77892
  StatuslineInstallError: () => StatuslineInstallError2,
77734
77893
  TRACK: () => TRACK,
@@ -77804,6 +77963,7 @@ ${lastSnapshot}`;
77804
77963
  computeProviderTreeDigest: () => computeProviderTreeDigest,
77805
77964
  configureDebugTraceStore: () => configureDebugTraceStore,
77806
77965
  connectCdpManager: () => connectCdpManager,
77966
+ consoleSymbols: () => consoleSymbols,
77807
77967
  coordinatorIdentityFromEmitFields: () => coordinatorIdentityFromEmitFields,
77808
77968
  createDebugTraceStore: () => createDebugTraceStore,
77809
77969
  createDefaultGitCommandServices: () => createDefaultGitCommandServices,
@@ -78052,6 +78212,7 @@ ${lastSnapshot}`;
78052
78212
  requeueTask: () => requeueTask,
78053
78213
  requireMeshHostQueueOwner: () => requireMeshHostQueueOwner,
78054
78214
  resetConfig: () => resetConfig,
78215
+ resetConsoleSymbolsCache: () => resetConsoleSymbolsCache,
78055
78216
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
78056
78217
  resetProcessInstanceContextForTests: () => resetProcessInstanceContextForTests,
78057
78218
  resetState: () => resetState,
@@ -78060,6 +78221,7 @@ ${lastSnapshot}`;
78060
78221
  resolveBackoffMs: () => resolveBackoffMs,
78061
78222
  resolveBuildTrack: () => resolveBuildTrack,
78062
78223
  resolveChatMessageKind: () => resolveChatMessageKind,
78224
+ resolveConsoleSymbols: () => resolveConsoleSymbols,
78063
78225
  resolveConvergeRequiredTags: () => resolveConvergeRequiredTags,
78064
78226
  resolveCurrentGlobalInstallSurface: () => resolveCurrentGlobalInstallSurface,
78065
78227
  resolveDebugRuntimeConfig: () => resolveDebugRuntimeConfig,
@@ -78121,6 +78283,7 @@ ${lastSnapshot}`;
78121
78283
  summarizeMeshMission: () => summarizeMeshMission,
78122
78284
  summarizeMeshUsage: () => summarizeMeshUsage,
78123
78285
  summarizeMissionTasks: () => summarizeMissionTasks,
78286
+ supportsUnicodeSymbols: () => supportsUnicodeSymbols,
78124
78287
  taskDependenciesSatisfied: () => taskDependenciesSatisfied,
78125
78288
  tombstoneOperatingNote: () => tombstoneOperatingNote,
78126
78289
  totalTokens: () => totalTokens,
@@ -80264,9 +80427,9 @@ ${lastSnapshot}`;
80264
80427
  usageFileCache.delete(path54);
80265
80428
  return emptyFile(meshId);
80266
80429
  }
80267
- const cached4 = usageFileCache.get(path54);
80268
- if (cached4 && cached4.mtimeMs === stat2.mtimeMs && cached4.size === stat2.size) {
80269
- return cached4.file;
80430
+ const cached5 = usageFileCache.get(path54);
80431
+ if (cached5 && cached5.mtimeMs === stat2.mtimeMs && cached5.size === stat2.size) {
80432
+ return cached5.file;
80270
80433
  }
80271
80434
  try {
80272
80435
  const parsed = JSON.parse((0, import_fs14.readFileSync)(path54, "utf-8"));
@@ -92599,6 +92762,7 @@ ${marker}`,
92599
92762
  init_provider_input_support();
92600
92763
  init_hash();
92601
92764
  init_transcript_evidence();
92765
+ init_native_turn_signal();
92602
92766
  init_logger();
92603
92767
  var BUSY_LEASE_BOUND_MS = 18e4;
92604
92768
  var DEFAULT_CANARY_PROVIDERS = ["kimi", "codex-cli"];
@@ -92967,6 +93131,13 @@ ${marker}`,
92967
93131
  return n;
92968
93132
  }
92969
93133
  var SUBMIT_DELAY_FLOOR_MS = 200;
93134
+ var SEND_IN_FLIGHT_MAX_MS = 3e4;
93135
+ var DUPLICATE_RESEND_WINDOW_MS = 6e4;
93136
+ function hashSendText(text) {
93137
+ let h = 5381;
93138
+ for (let i = 0; i < text.length; i += 1) h = ((h << 5) + h ^ text.charCodeAt(i)) >>> 0;
93139
+ return `${h.toString(36)}:${text.length}`;
93140
+ }
92970
93141
  var fsmDriverSeq = 0;
92971
93142
  var WIN32_SUBMIT_RESEND_GAP_MS = 350;
92972
93143
  var WIN32_SUBMIT_MAX_RESENDS = 14;
@@ -93073,6 +93244,19 @@ ${marker}`,
93073
93244
  // non-busy ("ready") state — same contract as v3's idleSeenOnce.
93074
93245
  readySeenOnce = false;
93075
93246
  pendingSends = [];
93247
+ /** True while a send is written but the FSM has not yet left idle, i.e. the
93248
+ * composer is mid-submit. Blocks a second send from overwriting the first
93249
+ * before the CLI has consumed it (see handleSendMessage). */
93250
+ sendInFlight = false;
93251
+ /** Wall-clock (ms) the in-flight send was written. Bounds sendInFlight so a
93252
+ * send the CLI never visibly consumed cannot wedge the queue forever. */
93253
+ sendInFlightAt = 0;
93254
+ /** Content hash → wall-clock of the last PTY write, for the pre-write
93255
+ * duplicate gate (see isDuplicateResend). */
93256
+ recentSendHashes = /* @__PURE__ */ new Map();
93257
+ /** Pending queued-send drain timer, tracked so shutdown() can cancel it and
93258
+ * a torn-down driver never writes a queued body into a dead PTY. */
93259
+ pendingSendDrainTimer = null;
93076
93260
  pickerInProgress = null;
93077
93261
  delegateTimers = /* @__PURE__ */ new Map();
93078
93262
  specWatcher = null;
@@ -93225,6 +93409,11 @@ ${marker}`,
93225
93409
  clearTimeout(this.win32ModalConfirmTimer);
93226
93410
  this.win32ModalConfirmTimer = null;
93227
93411
  }
93412
+ if (this.pendingSendDrainTimer) {
93413
+ clearTimeout(this.pendingSendDrainTimer);
93414
+ this.pendingSendDrainTimer = null;
93415
+ }
93416
+ this.pendingSends.length = 0;
93228
93417
  this.specWatcher?.close();
93229
93418
  this.adapter.kill();
93230
93419
  }
@@ -93416,12 +93605,14 @@ ${marker}`,
93416
93605
  this.scheduleWakeForState();
93417
93606
  this.scheduleStallWatchdog();
93418
93607
  this.maybeMarkReady();
93608
+ this.drainPendingSends();
93419
93609
  return;
93420
93610
  }
93421
93611
  this.emitStateChanged(forceEmit);
93422
93612
  this.scheduleWakeForState();
93423
93613
  this.scheduleStallWatchdog();
93424
93614
  this.maybeMarkReady();
93615
+ this.drainPendingSends();
93425
93616
  }
93426
93617
  commitTransition(fired, now, ev) {
93427
93618
  const from = this.currentStateId;
@@ -93691,8 +93882,7 @@ ${marker}`,
93691
93882
  if (!st) return;
93692
93883
  if (!st.initial && statusForState(st) === "idle") {
93693
93884
  this.readySeenOnce = true;
93694
- const queued = this.pendingSends.splice(0);
93695
- for (const text of queued) setTimeout(() => this.actuallySendMessage(text), 50);
93885
+ this.drainPendingSends();
93696
93886
  }
93697
93887
  }
93698
93888
  // ────────────────────────────────────────────────────────────────────
@@ -93730,13 +93920,109 @@ ${marker}`,
93730
93920
  // ────────────────────────────────────────────────────────────────────
93731
93921
  // Dashboard commands (identical semantics to v3)
93732
93922
  // ────────────────────────────────────────────────────────────────────
93923
+ /**
93924
+ * SEND-OVERLAP gate. A send may only go straight to the PTY when the machine
93925
+ * is genuinely able to accept one: it has been ready at least once, it is
93926
+ * sitting at an idle prompt right now, and no earlier send is still in flight.
93927
+ * Anything else is queued and drained by drainPendingSends() when the machine
93928
+ * next returns to idle.
93929
+ *
93930
+ * Before the fix this consulted ONLY `readySeenOnce` — a one-shot latch — so
93931
+ * every send after the first ignored the live FSM state and could be written
93932
+ * on top of a still-generating turn, braiding the two bodies in the composer
93933
+ * (see the SEND-OVERLAP note above the constants).
93934
+ */
93733
93935
  handleSendMessage(text) {
93734
- if (!this.readySeenOnce) {
93936
+ if (this.isDuplicateResend(text)) {
93937
+ LOG2.info("FsmDriver", `[${this.specTag()}] send suppressed \u2014 duplicate resend within ${DUPLICATE_RESEND_WINDOW_MS}ms (len=${text.length})`);
93938
+ return;
93939
+ }
93940
+ if (!this.canSendNow()) {
93735
93941
  this.pendingSends.push(text);
93942
+ LOG2.info(
93943
+ "FsmDriver",
93944
+ `[${this.specTag()}] send queued \u2014 ${this.sendBlockedReason()} (len=${text.length}, queued=${this.pendingSends.length})`
93945
+ );
93736
93946
  return;
93737
93947
  }
93948
+ this.beginSend(text);
93949
+ }
93950
+ /** True when a send can be written to the PTY right now. */
93951
+ canSendNow() {
93952
+ if (!this.readySeenOnce) return false;
93953
+ if (this.isSendInFlight()) return false;
93954
+ return this.currentStatus() === "idle";
93955
+ }
93956
+ /** Human-readable reason a send was queued — logged, never used for control flow. */
93957
+ sendBlockedReason() {
93958
+ if (!this.readySeenOnce) return "machine not ready yet";
93959
+ if (this.isSendInFlight()) return `previous send still in flight (${Date.now() - this.sendInFlightAt}ms)`;
93960
+ return `machine is ${this.currentStatus()}`;
93961
+ }
93962
+ /** In-flight latch with its self-expiry applied, so a send the CLI never
93963
+ * visibly consumed cannot wedge the queue permanently. */
93964
+ isSendInFlight() {
93965
+ if (!this.sendInFlight) return false;
93966
+ if (Date.now() - this.sendInFlightAt > SEND_IN_FLIGHT_MAX_MS) {
93967
+ LOG2.warn("FsmDriver", `[${this.specTag()}] in-flight send latch expired after ${SEND_IN_FLIGHT_MAX_MS}ms \u2014 releasing`);
93968
+ this.sendInFlight = false;
93969
+ return false;
93970
+ }
93971
+ return true;
93972
+ }
93973
+ /**
93974
+ * Pre-write duplicate gate. Suppresses a repeat of text that was written to
93975
+ * the PTY within DUPLICATE_RESEND_WINDOW_MS *while that text is still being
93976
+ * processed* — i.e. a send is in flight or the machine has not returned to
93977
+ * idle. A genuine repeat typed at an idle prompt is NOT suppressed: sending
93978
+ * "continue" twice in a row is ordinary use, and silently swallowing the
93979
+ * second one would be a worse defect than the one being fixed.
93980
+ */
93981
+ isDuplicateResend(text) {
93982
+ const now = Date.now();
93983
+ const key2 = hashSendText(text);
93984
+ for (const [candidate, at] of this.recentSendHashes) {
93985
+ if (now - at > DUPLICATE_RESEND_WINDOW_MS) this.recentSendHashes.delete(candidate);
93986
+ }
93987
+ const previous = this.recentSendHashes.get(key2);
93988
+ if (previous === void 0) return false;
93989
+ if (now - previous > DUPLICATE_RESEND_WINDOW_MS) return false;
93990
+ const stillProcessing = this.isSendInFlight() || this.currentStatus() !== "idle" || this.pendingSends.length > 0;
93991
+ return stillProcessing;
93992
+ }
93993
+ /** Mark a send as in flight, record it for the duplicate gate, and write it. */
93994
+ beginSend(text) {
93995
+ this.sendInFlight = true;
93996
+ this.sendInFlightAt = Date.now();
93997
+ this.recentSendHashes.set(hashSendText(text), this.sendInFlightAt);
93738
93998
  this.actuallySendMessage(text);
93739
93999
  }
94000
+ /**
94001
+ * Release the in-flight latch and write the next queued send, if the machine
94002
+ * can take one. Called from the FSM evaluation loop, so it runs on the same
94003
+ * frame the machine reaches idle — the queue never waits for an extra PTY
94004
+ * frame that a quiet CLI would never produce (the same hazard maybeMarkReady
94005
+ * documents for the very first message).
94006
+ */
94007
+ drainPendingSends() {
94008
+ if (!this.readySeenOnce) return;
94009
+ const status = this.currentStatus();
94010
+ if (this.sendInFlight && status !== "idle") {
94011
+ this.sendInFlight = false;
94012
+ }
94013
+ if (status !== "idle") return;
94014
+ if (this.isSendInFlight()) return;
94015
+ if (this.pendingSends.length === 0) return;
94016
+ const next = this.pendingSends.shift();
94017
+ LOG2.info("FsmDriver", `[${this.specTag()}] draining queued send (len=${next.length}, remaining=${this.pendingSends.length})`);
94018
+ if (this.pendingSendDrainTimer) clearTimeout(this.pendingSendDrainTimer);
94019
+ this.pendingSendDrainTimer = setTimeout(() => {
94020
+ this.pendingSendDrainTimer = null;
94021
+ this.beginSend(next);
94022
+ }, 50);
94023
+ this.sendInFlight = true;
94024
+ this.sendInFlightAt = Date.now();
94025
+ }
93740
94026
  actuallySendMessage(text) {
93741
94027
  const sm = this.spec.send_message;
93742
94028
  const perChar = sm.delay_ms_per_char ?? 0;
@@ -95535,6 +95821,7 @@ ${marker}`,
95535
95821
  var PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS = 1200;
95536
95822
  var ANTIGRAVITY_HOLD_QUIET_DWELL_MS = 3e3;
95537
95823
  var ANTIGRAVITY_HOLD_HARD_CAP_MS = 5 * 6e4;
95824
+ var TERMINAL_BLOCK_HARD_CAP_MS = 10 * 6e4;
95538
95825
  var BACKGROUND_TASK_HOLD_MAX_MS = 5 * 6e4;
95539
95826
  var USER_INPUT_ACK_DEDUP_WINDOW_MS = 6e4;
95540
95827
  var STARTUP_GRACE_IDLE_COLLAPSE_WINDOW_MS = 12e3;
@@ -95593,6 +95880,12 @@ ${marker}`,
95593
95880
  evidencePatch.resolvedFinalEvidenceObservedAt = null;
95594
95881
  }
95595
95882
  if (!evidence.present) {
95883
+ if (evidence.source === "native-signal") {
95884
+ return {
95885
+ block: { reason: "native_signal_adapter_pending", terminal: false, allowTimeout: true },
95886
+ evidencePatch
95887
+ };
95888
+ }
95596
95889
  if (ownsExternal) {
95597
95890
  if (evidence.source === "external-native") {
95598
95891
  const probe = reader.externalNativeTailProbe();
@@ -95625,17 +95918,15 @@ ${marker}`,
95625
95918
  evidencePatch
95626
95919
  };
95627
95920
  }
95628
- if (timing === "floor") {
95629
- return {
95630
- block: {
95631
- reason: "missing_final_assistant",
95632
- terminal: true,
95633
- allowTimeout: allowMissingAssistantTimeout,
95634
- noExternalTranscriptSource: true
95635
- },
95636
- evidencePatch
95637
- };
95638
- }
95921
+ return {
95922
+ block: {
95923
+ reason: "missing_final_assistant",
95924
+ terminal: false,
95925
+ allowTimeout: true,
95926
+ ...timing === "floor" ? { noExternalTranscriptSource: true } : {}
95927
+ },
95928
+ evidencePatch
95929
+ };
95639
95930
  } else {
95640
95931
  return {
95641
95932
  block: {
@@ -95771,7 +96062,7 @@ ${marker}`,
95771
96062
  }
95772
96063
  }
95773
96064
  }
95774
- if (!isTranscriptEvidenceGate && (block2.terminal || waitedMs < policy.finalizationMaxWaitMs)) {
96065
+ if (!isTranscriptEvidenceGate && (block2.terminal ? waitedMs < policy.terminalBlockHardCapMs : waitedMs < policy.finalizationMaxWaitMs)) {
95775
96066
  return hold(block2.reason, {
95776
96067
  terminal: block2.terminal === true,
95777
96068
  holdForTranscript: block2.holdForTranscript === true,
@@ -95789,11 +96080,13 @@ ${marker}`,
95789
96080
  });
95790
96081
  }
95791
96082
  const emittedAfterFinalizationTimeout = waitedMs >= policy.finalizationMaxWaitMs;
96083
+ const releasedByTerminalBlockHardCap = block2.terminal === true && !isTranscriptEvidenceGate && waitedMs >= policy.terminalBlockHardCapMs;
95792
96084
  return {
95793
96085
  kind: "emit-weak",
95794
96086
  block: block2,
95795
96087
  emittedAfterFinalizationTimeout,
95796
96088
  decoupledImmediateEmit: isTranscriptEvidenceGate && !emittedAfterFinalizationTimeout,
96089
+ releasedByTerminalBlockHardCap,
95797
96090
  waitedMs,
95798
96091
  armPatch: basePatch,
95799
96092
  trace: {
@@ -95801,6 +96094,7 @@ ${marker}`,
95801
96094
  latestVisibleStatus: visibleStatus,
95802
96095
  approvalResolvedIdle: arm.previousStatus === "waiting_approval",
95803
96096
  emittedAfterFinalizationTimeout,
96097
+ releasedByTerminalBlockHardCap,
95804
96098
  waitedMs,
95805
96099
  busyEpoch
95806
96100
  }
@@ -96431,7 +96725,17 @@ ${buttons.join("\n")}`;
96431
96725
  instanceId: host.instanceId,
96432
96726
  envOverrides: host.spawnedEnvOverrides(),
96433
96727
  forceRefresh: true
96728
+ // (NATIVE-TURN-SIGNAL audit) excludeInProgressTurn is deliberately NOT passed
96729
+ // here, and that is correct — not the declared-but-ignored field it looks like.
96730
+ // It is a per-CALL display concern, not a manifest policy: read_chat sets it only
96731
+ // for `returnedStatus === 'waiting_approval'` (chat-commands-read.ts) so a paused
96732
+ // turn's half-written tail is hidden from the user. The completion gate needs the
96733
+ // exact opposite — it exists to judge the turn that JUST finished, so excluding the
96734
+ // in-progress turn would hide the very evidence it is looking for and would make
96735
+ // missing_final_assistant strictly more common. Codex's manifest sets
96736
+ // excludeInProgressTurn:true for its own read path; that must not leak here.
96434
96737
  });
96738
+ host.lastNativeTurnTerminalMarkers = Array.isArray(restoredHistory.turnTerminalMarkers) ? restoredHistory.turnTerminalMarkers : null;
96435
96739
  if (restoredHistory.source !== "provider-native") {
96436
96740
  host.lastExternalCompletionProbe = null;
96437
96741
  host.publishTranscriptSignalObservation(null);
@@ -96446,11 +96750,11 @@ ${buttons.join("\n")}`;
96446
96750
  return restoredHistory.messages;
96447
96751
  }
96448
96752
  function cachedInTurnCompletionSummaryContent(host, turnStartedAt) {
96449
- const cached4 = host.lastCompletionSummary;
96450
- const content = typeof cached4?.content === "string" ? cached4.content.trim() : "";
96753
+ const cached5 = host.lastCompletionSummary;
96754
+ const content = typeof cached5?.content === "string" ? cached5.content.trim() : "";
96451
96755
  if (!content) return "";
96452
96756
  const hasBoundary = typeof turnStartedAt === "number" && Number.isFinite(turnStartedAt) && turnStartedAt > 0;
96453
- const ts2 = cached4?.sourceTimestampMs;
96757
+ const ts2 = cached5?.sourceTimestampMs;
96454
96758
  if (hasBoundary && typeof ts2 === "number" && Number.isFinite(ts2) && ts2 < turnStartedAt) {
96455
96759
  return "";
96456
96760
  }
@@ -96458,6 +96762,16 @@ ${buttons.join("\n")}`;
96458
96762
  }
96459
96763
  function completionFinalAssistantEvidence(host, parsedMessages, turnStartedAt) {
96460
96764
  const turnClosed = !host.hasAdapterPendingResponse();
96765
+ const terminalMarker = host.nativeTurnTerminalMarker?.(turnStartedAt);
96766
+ if (terminalMarker) {
96767
+ return {
96768
+ present: turnClosed,
96769
+ messages: Array.isArray(parsedMessages) ? parsedMessages : [],
96770
+ source: "native-signal",
96771
+ nativeSummary: terminalMarker.summary,
96772
+ nativeOutcome: terminalMarker.outcome
96773
+ };
96774
+ }
96461
96775
  const preferNativeOverParsed = host.adapter?.chatMessagesOwnedExternally === true && host.busyLeaseGateEnabled();
96462
96776
  if (!preferNativeOverParsed && host.completionHasFinalAssistantMessage(parsedMessages, turnStartedAt)) {
96463
96777
  return {
@@ -98173,6 +98487,9 @@ ${buttons.join("\n")}`;
98173
98487
  completedDebounceTimer = null;
98174
98488
  completedDebouncePending = null;
98175
98489
  lastExternalCompletionProbe = null;
98490
+ // (NATIVE-TURN-SIGNAL) Terminal markers from the last native transcript read. Refreshed
98491
+ // on every completion probe; null when the provider surfaces none.
98492
+ lastNativeTurnTerminalMarkers = null;
98176
98493
  /** TX-FSM: lazily-created transcript signal normalizer. Fed ONLY by
98177
98494
  * transcript reads this instance already performs — it adds zero I/O.
98178
98495
  * Stage 0: its output was a pure shadow observation for the FSM driver.
@@ -98431,8 +98748,8 @@ ${buttons.join("\n")}`;
98431
98748
  * next turn (see lastCompletionSummary = null on onTurnStarted).
98432
98749
  */
98433
98750
  cachedCompletionSummaryContent() {
98434
- const cached4 = this.lastCompletionSummary;
98435
- const content = typeof cached4?.content === "string" ? cached4.content.trim() : "";
98751
+ const cached5 = this.lastCompletionSummary;
98752
+ const content = typeof cached5?.content === "string" ? cached5.content.trim() : "";
98436
98753
  return content;
98437
98754
  }
98438
98755
  /** See completion/evidence.ts — FALSE-IDLE Defect 1c turn-scoped cache view. */
@@ -98752,6 +99069,28 @@ ${buttons.join("\n")}`;
98752
99069
  return false;
98753
99070
  }
98754
99071
  }
99072
+ /**
99073
+ * (NATIVE-TURN-SIGNAL) This turn's terminal marker from the provider's own transcript,
99074
+ * or null when the provider declares no completion signal / the turn has not ended.
99075
+ *
99076
+ * Turn scoping prefers the provider-native turn id when the adapter knows it, falling
99077
+ * back to the turn-start boundary — see selectTurnTerminalMarker. Any read error fails
99078
+ * CLOSED (null ⇒ shape inference), so a malformed transcript can never manufacture a
99079
+ * completion.
99080
+ */
99081
+ nativeTurnTerminalMarker(turnStartedAt) {
99082
+ try {
99083
+ const markers = this.lastNativeTurnTerminalMarkers;
99084
+ if (!markers || markers.length === 0) return null;
99085
+ const adapterTurnId = typeof this.adapter?.currentProviderTurnId === "string" ? this.adapter.currentProviderTurnId : void 0;
99086
+ return selectTurnTerminalMarker(markers, {
99087
+ ...adapterTurnId ? { turnId: adapterTurnId } : {},
99088
+ ...typeof turnStartedAt === "number" ? { turnStartedAt } : {}
99089
+ });
99090
+ } catch {
99091
+ return null;
99092
+ }
99093
+ }
98755
99094
  /**
98756
99095
  * See completion/stall-rescue.ts — pre-cleanup mesh completion flush
98757
99096
  * (verbatim move; KIMI-MESH-COMPLETION-EMIT axis 2 provenance lives with
@@ -98912,7 +99251,8 @@ ${buttons.join("\n")}`;
98912
99251
  canonCMinElapsedFloorMs: CANON_C_MISSING_ASSISTANT_MIN_ELAPSED_MS,
98913
99252
  transcriptGrowthQuietMs: MISSING_ASSISTANT_TRANSCRIPT_GROWTH_QUIET_MS,
98914
99253
  holdClassHardCapMs: ANTIGRAVITY_HOLD_HARD_CAP_MS,
98915
- ptyParsedFinalAssistantQuietDwellMs: PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS
99254
+ ptyParsedFinalAssistantQuietDwellMs: PTY_PARSED_FINAL_ASSISTANT_QUIET_DWELL_MS,
99255
+ terminalBlockHardCapMs: TERMINAL_BLOCK_HARD_CAP_MS
98916
99256
  };
98917
99257
  }
98918
99258
  /**
@@ -99149,12 +99489,14 @@ ${buttons.join("\n")}`;
99149
99489
  emittedAfterFinalizationTimeout
99150
99490
  });
99151
99491
  completionDiagnostic.decoupledImmediateEmit = decision.decoupledImmediateEmit;
99152
- LOG2.warn("CLI", `[${this.type}] emitting completed event (${decision.decoupledImmediateEmit ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`}) without finalized assistant turn (${blockReason})`);
99492
+ completionDiagnostic.releasedByTerminalBlockHardCap = decision.releasedByTerminalBlockHardCap;
99493
+ const emitCause = decision.releasedByTerminalBlockHardCap ? `terminal block never cleared, released at ${waitedMs}ms hard cap` : decision.decoupledImmediateEmit ? "CANON-C decoupled-immediate, transcript pending" : `after ${waitedMs}ms`;
99494
+ LOG2.warn("CLI", `[${this.type}] emitting completed event (${emitCause}) without finalized assistant turn (${blockReason})`);
99153
99495
  if (this.isMeshWorkerSession()) {
99154
99496
  traceMeshEventStage("fired", this.meshTraceCtx(), `forced after ${waitedMs}ms (${blockReason})`);
99155
99497
  }
99156
99498
  if (this.completionTraceOn()) this.recordCompletionGateTrace("fire", {
99157
- path: decision.decoupledImmediateEmit ? "canon_c_decoupled" : "forced_timeout",
99499
+ path: decision.releasedByTerminalBlockHardCap ? "terminal_block_hard_cap" : decision.decoupledImmediateEmit ? "canon_c_decoupled" : "forced_timeout",
99158
99500
  blockReason,
99159
99501
  latestVisibleStatus,
99160
99502
  approvalResolvedIdle: pending.previousStatus === "waiting_approval",
@@ -99173,7 +99515,7 @@ ${buttons.join("\n")}`;
99173
99515
  taskId: pending.taskId,
99174
99516
  // finalSummary provenance chain unchanged (see snapshotExternalNativeCompletionSummary /
99175
99517
  // completionFinalSummary / cachedInTurnCompletionSummaryContent docs above).
99176
- finalSummary: this.snapshotExternalNativeCompletionSummary(pending) || this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages, pending.turnStartedAt) || this.cachedInTurnCompletionSummaryContent(pending.turnStartedAt) || (blockReason.startsWith("parsed_status:") ? "" : void 0),
99518
+ finalSummary: this.nativeTurnTerminalSummary(pending.turnStartedAt) || this.snapshotExternalNativeCompletionSummary(pending) || this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages, pending.turnStartedAt) || this.cachedInTurnCompletionSummaryContent(pending.turnStartedAt) || (blockReason.startsWith("parsed_status:") ? "" : void 0),
99177
99519
  completionDiagnostic
99178
99520
  });
99179
99521
  this.completedDebouncePending = null;
@@ -99260,6 +99602,21 @@ ${buttons.join("\n")}`;
99260
99602
  cleanCompletionFinalSummary(pending) {
99261
99603
  return cleanCompletionFinalSummary(this, pending);
99262
99604
  }
99605
+ /**
99606
+ * (NATIVE-TURN-SIGNAL) finalSummary straight from the provider's own terminal record.
99607
+ *
99608
+ * Placed at the HEAD of the finalSummary provenance chain so the two sources can never
99609
+ * diverge: when the provider states the turn's final text, that text wins outright and
99610
+ * the reconstruction chain (native snapshot > parsed screen > cached in-turn summary) is
99611
+ * not consulted at all. Returns undefined — not '' — for a terminal record with no text,
99612
+ * so a tool-terminated turn falls through to the existing chain rather than forcing an
99613
+ * empty summary onto a completion that might legitimately have one from elsewhere.
99614
+ */
99615
+ nativeTurnTerminalSummary(turnStartedAt) {
99616
+ const marker = this.nativeTurnTerminalMarker(turnStartedAt);
99617
+ const text = typeof marker?.summary === "string" ? marker.summary.trim() : "";
99618
+ return text || void 0;
99619
+ }
99263
99620
  /** See completion/evidence.ts — KIMI-RC30 forced-emit native snapshot seed. */
99264
99621
  snapshotExternalNativeCompletionSummary(pending) {
99265
99622
  return snapshotExternalNativeCompletionSummary(pending);
@@ -103304,6 +103661,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
103304
103661
  var fs33 = __toESM2(require("fs"));
103305
103662
  var path37 = __toESM2(require("path"));
103306
103663
  init_usage_normalize();
103664
+ init_native_turn_signal();
103665
+ var CODEX_DEFAULT_COMPLETION_SIGNAL = {
103666
+ recordType: "task_complete",
103667
+ abortRecordType: "turn_aborted",
103668
+ summaryField: "last_agent_message",
103669
+ turnIdField: "turn_id"
103670
+ };
103307
103671
  function extractTimestampValue2(value) {
103308
103672
  if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
103309
103673
  if (typeof value === "string") {
@@ -103418,8 +103782,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
103418
103782
  if (!totals || typeof totals !== "object" || Array.isArray(totals)) return null;
103419
103783
  const t = totals;
103420
103784
  const rawInput = Number(t.input_tokens);
103421
- const cached4 = Number(t.cached_input_tokens);
103422
- const uncachedInput = Number.isFinite(rawInput) && Number.isFinite(cached4) ? Math.max(0, rawInput - cached4) : rawInput;
103785
+ const cached5 = Number(t.cached_input_tokens);
103786
+ const uncachedInput = Number.isFinite(rawInput) && Number.isFinite(cached5) ? Math.max(0, rawInput - cached5) : rawInput;
103423
103787
  const usage = makeUsage({
103424
103788
  inputTokens: uncachedInput,
103425
103789
  outputTokens: t.output_tokens,
@@ -103441,16 +103805,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
103441
103805
  return null;
103442
103806
  }
103443
103807
  }
103444
- function parseSessionFile(filePath, sessionId, workspaceFallback) {
103808
+ function parseSessionFile(filePath, sessionId, workspaceFallback, completionSignal = CODEX_DEFAULT_COMPLETION_SIGNAL) {
103445
103809
  let raw;
103446
103810
  try {
103447
103811
  raw = fs33.readFileSync(filePath, "utf-8");
103448
103812
  } catch {
103449
- return { messages: [], usageRecords: [] };
103813
+ return { messages: [], usageRecords: [], turnTerminalMarkers: [] };
103450
103814
  }
103451
103815
  const lines = raw.split("\n").filter(Boolean);
103452
103816
  const records = [];
103453
103817
  const usageRecords = [];
103818
+ const turnTerminalMarkers = [];
103454
103819
  let fallbackTs = Date.now();
103455
103820
  let detectedWorkspace = typeof workspaceFallback === "string" ? workspaceFallback.trim() : "";
103456
103821
  for (const line of lines) {
@@ -103469,7 +103834,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
103469
103834
  if (!payload) continue;
103470
103835
  if (type2 === "session_meta") {
103471
103836
  const metaId = String(payload.id ?? "").trim();
103472
- if (metaId && metaId !== sessionId) return { messages: [], usageRecords: [] };
103837
+ if (metaId && metaId !== sessionId) return { messages: [], usageRecords: [], turnTerminalMarkers: [] };
103473
103838
  const metaWorkspace = String(payload.cwd ?? "").trim();
103474
103839
  if (!detectedWorkspace && metaWorkspace) detectedWorkspace = metaWorkspace;
103475
103840
  if (records.length === 0 && detectedWorkspace) {
@@ -103488,6 +103853,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
103488
103853
  }
103489
103854
  const payloadType = String(payload.type ?? "").trim();
103490
103855
  if (type2 === "event_msg") {
103856
+ if (completionSignal) {
103857
+ const isComplete = payloadType === completionSignal.recordType;
103858
+ const isAbort = !!completionSignal.abortRecordType && payloadType === completionSignal.abortRecordType;
103859
+ if (isComplete || isAbort) {
103860
+ const summary = completionSignal.summaryField ? flattenCodexContent(payload[completionSignal.summaryField]).trim() : "";
103861
+ const rawTurnId = completionSignal.turnIdField ? payload[completionSignal.turnIdField] : void 0;
103862
+ const turnId = typeof rawTurnId === "string" && rawTurnId.trim() ? rawTurnId.trim() : "";
103863
+ turnTerminalMarkers.push({
103864
+ receivedAt,
103865
+ outcome: isAbort ? "aborted" : "completed",
103866
+ summary,
103867
+ ...turnId ? { turnId } : {}
103868
+ });
103869
+ }
103870
+ }
103491
103871
  if (payloadType === "task_complete") {
103492
103872
  pushAssistantStandardMessage(
103493
103873
  records,
@@ -103560,9 +103940,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
103560
103940
  records.push(msg);
103561
103941
  }
103562
103942
  }
103563
- return { messages: records, usageRecords };
103943
+ return { messages: records, usageRecords, turnTerminalMarkers };
103564
103944
  }
103565
- function readSession2(sessionPath) {
103945
+ function readSession2(sessionPath, nativeHistory) {
103566
103946
  if (!sessionPath || !path37.isAbsolute(sessionPath)) return null;
103567
103947
  if (!fs33.existsSync(sessionPath)) return null;
103568
103948
  const meta3 = readSessionMeta(sessionPath);
@@ -103575,7 +103955,13 @@ Run 'adhdev doctor' for detailed diagnostics.`
103575
103955
  if (!sessionId || !isUuidLikeSessionId(sessionId)) return null;
103576
103956
  const workspaceFallback = typeof meta3?.cwd === "string" ? meta3.cwd : void 0;
103577
103957
  const sourceMtimeMs = statMtimeMs2(sessionPath);
103578
- const { messages, usageRecords } = parseSessionFile(sessionPath, sessionId, workspaceFallback);
103958
+ const declaredSignal = resolveNativeCompletionSignalSpec(nativeHistory);
103959
+ const { messages, usageRecords, turnTerminalMarkers } = parseSessionFile(
103960
+ sessionPath,
103961
+ sessionId,
103962
+ workspaceFallback,
103963
+ declaredSignal ?? CODEX_DEFAULT_COMPLETION_SIGNAL
103964
+ );
103579
103965
  if (messages.length === 0) return null;
103580
103966
  const firstSystem = messages.find((m) => m.kind === "session_start");
103581
103967
  const workspace = firstSystem?.workspace || firstSystem?.content || void 0;
@@ -103594,6 +103980,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
103594
103980
  agent: "codex-cli"
103595
103981
  });
103596
103982
  }
103983
+ if (turnTerminalMarkers.length > 0) session.turnTerminalMarkers = turnTerminalMarkers;
103597
103984
  return session;
103598
103985
  }
103599
103986
  var fs34 = __toESM2(require("fs"));
@@ -103805,6 +104192,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
103805
104192
  }
103806
104193
  var AGY_STEP_TYPE_USER = 14;
103807
104194
  var AGY_STEP_TYPE_MODEL = 15;
104195
+ var AGY_STATUS_DONE = 3;
103808
104196
  function readVarint(buf, offset) {
103809
104197
  let result = 0;
103810
104198
  let shift = 0;
@@ -103929,6 +104317,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
103929
104317
  }
103930
104318
  return best;
103931
104319
  }
104320
+ function extractStepCreatedAtMs(metadata) {
104321
+ if (!metadata || !Buffer.isBuffer(metadata) || metadata.length === 0) return null;
104322
+ const stamp = firstLenField(metadata, 1);
104323
+ if (!stamp) return null;
104324
+ let seconds = 0;
104325
+ let nanos = 0;
104326
+ for (const f of decodeProtoFields(stamp)) {
104327
+ if (f.wireType !== 0 || typeof f.varint !== "number") continue;
104328
+ if (f.field === 1) seconds = f.varint;
104329
+ else if (f.field === 2) nanos = f.varint;
104330
+ }
104331
+ if (!(seconds > 15e8 && seconds < 25e8)) return null;
104332
+ const ms = seconds * 1e3 + Math.floor(nanos / 1e6);
104333
+ return Number.isFinite(ms) ? ms : null;
104334
+ }
103932
104335
  function isSqliteBusyError(err) {
103933
104336
  if (!err) return false;
103934
104337
  const code = err.code;
@@ -103965,10 +104368,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
103965
104368
  db.pragma(`busy_timeout = ${AGY_DB_BUSY_TIMEOUT_MS}`);
103966
104369
  } catch {
103967
104370
  }
104371
+ let columns;
104372
+ try {
104373
+ columns = new Set(
104374
+ db.prepare("PRAGMA table_info(steps)").all().map((c) => String(c?.name ?? ""))
104375
+ );
104376
+ } catch {
104377
+ columns = /* @__PURE__ */ new Set();
104378
+ }
104379
+ const hasStatus = columns.has("status");
104380
+ const hasMetadata = columns.has("metadata");
103968
104381
  rows = db.prepare(
103969
- `SELECT idx, step_type, step_payload
104382
+ `SELECT idx, step_type, step_payload${hasMetadata ? ", metadata" : ""}
103970
104383
  FROM steps
103971
104384
  WHERE step_type IN (${AGY_STEP_TYPE_USER}, ${AGY_STEP_TYPE_MODEL})
104385
+ ${hasStatus ? `AND status = ${AGY_STATUS_DONE}` : ""}
103972
104386
  ORDER BY idx ASC`
103973
104387
  ).all();
103974
104388
  break;
@@ -104005,7 +104419,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
104005
104419
  for (const row of rows) {
104006
104420
  const payload = row.step_payload;
104007
104421
  if (!payload || !Buffer.isBuffer(payload) || payload.length === 0) continue;
104008
- const receivedAt = baseTs + messages.length;
104422
+ const realCreatedAt = extractStepCreatedAtMs(row.metadata ?? null);
104423
+ const receivedAt = realCreatedAt ?? baseTs + messages.length;
104009
104424
  if (row.step_type === AGY_STEP_TYPE_USER) {
104010
104425
  let content = extractUserPrompt(payload);
104011
104426
  if (!content) {
@@ -104475,7 +104890,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
104475
104890
  sourcePath: session.sourcePath,
104476
104891
  sourceMtimeMs: session.sourceMtimeMs,
104477
104892
  nativeHistoryCoverage: session.nativeHistoryCoverage || "full",
104478
- ownerConfirmed
104893
+ ownerConfirmed,
104894
+ // (NATIVE-TURN-SIGNAL) Pass the provider's own turn-terminal records through
104895
+ // untouched. Readers that surface none simply omit the field.
104896
+ ...Array.isArray(session.turnTerminalMarkers) && session.turnTerminalMarkers.length > 0 ? { turnTerminalMarkers: session.turnTerminalMarkers } : {}
104479
104897
  };
104480
104898
  };
104481
104899
  }
@@ -107023,8 +107441,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
107023
107441
  return null;
107024
107442
  }
107025
107443
  registerProviderScriptRootSafely(path45.dirname(path45.dirname(providerDir)));
107026
- const cached4 = this.scriptsCache.get(dir);
107027
- if (cached4) return cached4;
107444
+ const cached5 = this.scriptsCache.get(dir);
107445
+ if (cached5) return cached5;
107028
107446
  const scriptsJs = path45.join(dir, "scripts.js");
107029
107447
  if (fs41.existsSync(scriptsJs)) {
107030
107448
  try {
@@ -114912,8 +115330,8 @@ ${e?.stderr || ""}`;
114912
115330
  const repoRootBaseRef = /* @__PURE__ */ new Map();
114913
115331
  const submodulePathsByRepoRoot = /* @__PURE__ */ new Map();
114914
115332
  const resolveBaseRef = async (repoRoot) => {
114915
- const cached4 = repoRootBaseRef.get(repoRoot);
114916
- if (cached4) return cached4;
115333
+ const cached5 = repoRootBaseRef.get(repoRoot);
115334
+ if (cached5) return cached5;
114917
115335
  let baseBranch = "main";
114918
115336
  try {
114919
115337
  const { stdout } = await execFileAsync6("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
@@ -116218,13 +116636,13 @@ ${e?.stderr || ""}`;
116218
116636
  };
116219
116637
  }
116220
116638
  function getCachedAggregateMeshStatus(self, meshId, mesh, options) {
116221
- const cached4 = self.aggregateMeshStatusCache.get(meshId);
116222
- if (!cached4?.snapshot || cached4.snapshot.success !== true || !Array.isArray(cached4.snapshot.nodes)) return null;
116223
- if (cached4.queueRevision !== getMeshQueueRevision(meshId)) return null;
116224
- let snapshot = cloneJsonValue(cached4.snapshot);
116639
+ const cached5 = self.aggregateMeshStatusCache.get(meshId);
116640
+ if (!cached5?.snapshot || cached5.snapshot.success !== true || !Array.isArray(cached5.snapshot.nodes)) return null;
116641
+ if (cached5.queueRevision !== getMeshQueueRevision(meshId)) return null;
116642
+ let snapshot = cloneJsonValue(cached5.snapshot);
116225
116643
  snapshot = hydrateCachedAggregateMeshStatusFromInline(self, snapshot, mesh, options);
116226
116644
  if (!options?.allowStalePending && shouldRefreshStalePendingAggregate(snapshot, options)) return null;
116227
- const ageMs2 = Math.max(0, Date.now() - cached4.builtAt);
116645
+ const ageMs2 = Math.max(0, Date.now() - cached5.builtAt);
116228
116646
  const sourceOfTruth = snapshot.sourceOfTruth && typeof snapshot.sourceOfTruth === "object" ? snapshot.sourceOfTruth : {};
116229
116647
  snapshot.sourceOfTruth = {
116230
116648
  ...sourceOfTruth,
@@ -116235,7 +116653,7 @@ ${e?.stderr || ""}`;
116235
116653
  source: "memory",
116236
116654
  refreshReason: "memory_cache_hit",
116237
116655
  ageMs: ageMs2,
116238
- cachedAt: new Date(cached4.builtAt).toISOString(),
116656
+ cachedAt: new Date(cached5.builtAt).toISOString(),
116239
116657
  returnedAt: (/* @__PURE__ */ new Date()).toISOString()
116240
116658
  }
116241
116659
  };
@@ -116291,8 +116709,8 @@ ${e?.stderr || ""}`;
116291
116709
  }
116292
116710
  function collectMeshSessionOwnerCandidateNodes(self) {
116293
116711
  const nodes = self.getCachedInlineMeshNodes();
116294
- for (const cached4 of self.aggregateMeshStatusCache.values()) {
116295
- const snapshotNodes = cached4?.snapshot?.nodes;
116712
+ for (const cached5 of self.aggregateMeshStatusCache.values()) {
116713
+ const snapshotNodes = cached5?.snapshot?.nodes;
116296
116714
  if (Array.isArray(snapshotNodes)) nodes.push(...snapshotNodes);
116297
116715
  }
116298
116716
  return nodes;
@@ -116613,9 +117031,9 @@ ${e?.stderr || ""}`;
116613
117031
  meshId,
116614
117032
  sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(inlineMesh))
116615
117033
  );
116616
- const cached4 = this.inlineMeshCache.get(meshId);
116617
- if (cached4) {
116618
- const merged = reconcileInlineMeshCache(cached4, sanitizedInlineMesh, this.removedInlineMeshNodeIds.get(meshId));
117034
+ const cached5 = this.inlineMeshCache.get(meshId);
117035
+ if (cached5) {
117036
+ const merged = reconcileInlineMeshCache(cached5, sanitizedInlineMesh, this.removedInlineMeshNodeIds.get(meshId));
116619
117037
  this.inlineMeshCache.set(meshId, merged);
116620
117038
  return merged;
116621
117039
  }
@@ -116625,18 +117043,18 @@ ${e?.stderr || ""}`;
116625
117043
  async getMeshForCommand(meshId, inlineMesh, options) {
116626
117044
  const preferInline = options?.preferInline !== false;
116627
117045
  if (preferInline) {
116628
- const cached5 = this.getCachedInlineMesh(meshId);
116629
- if (cached5) {
117046
+ const cached6 = this.getCachedInlineMesh(meshId);
117047
+ if (cached6) {
116630
117048
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
116631
117049
  const merged = reconcileInlineMeshCache(
116632
- cached5,
117050
+ cached6,
116633
117051
  this.applyInlineMeshNodeTombstones(meshId, inlineMesh),
116634
117052
  this.removedInlineMeshNodeIds.get(meshId)
116635
117053
  );
116636
117054
  this.inlineMeshCache.set(meshId, sanitizeInlineMesh(normalizeInlineMeshNodeIdentity(merged)));
116637
117055
  return { mesh: merged, inline: true, source: "inline_cache" };
116638
117056
  }
116639
- return { mesh: cached5, inline: true, source: "inline_cache" };
117057
+ return { mesh: cached6, inline: true, source: "inline_cache" };
116640
117058
  }
116641
117059
  if (inlineMeshCarriesTransientNodeTruth(inlineMesh)) {
116642
117060
  this.warmInlineMeshCache(meshId, inlineMesh);
@@ -116649,8 +117067,8 @@ ${e?.stderr || ""}`;
116649
117067
  if (mesh) return { mesh, inline: false, source: "local_config" };
116650
117068
  } catch {
116651
117069
  }
116652
- const cached4 = this.getCachedInlineMesh(meshId);
116653
- if (cached4) return { mesh: cached4, inline: true, source: "inline_cache" };
117070
+ const cached5 = this.getCachedInlineMesh(meshId);
117071
+ if (cached5) return { mesh: cached5, inline: true, source: "inline_cache" };
116654
117072
  const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
116655
117073
  return warmedInline ? { mesh: warmedInline, inline: true, source: "inline_bootstrap" } : null;
116656
117074
  }
@@ -116789,13 +117207,13 @@ ${e?.stderr || ""}`;
116789
117207
  };
116790
117208
  let changed = false;
116791
117209
  try {
116792
- const cached4 = this.getCachedInlineMesh(meshId);
116793
- if (cached4 && stamp(cached4)) {
116794
- cached4.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
116795
- this.inlineMeshCache.set(meshId, cached4);
117210
+ const cached5 = this.getCachedInlineMesh(meshId);
117211
+ if (cached5 && stamp(cached5)) {
117212
+ cached5.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
117213
+ this.inlineMeshCache.set(meshId, cached5);
116796
117214
  changed = true;
116797
- } else if (!cached4 || !(Array.isArray(cached4.nodes) && cached4.nodes.some((entry) => meshNodeIdMatches(entry, nodeId)))) {
116798
- const shell = cached4 && typeof cached4 === "object" ? cached4 : { id: meshId, nodes: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
117215
+ } else if (!cached5 || !(Array.isArray(cached5.nodes) && cached5.nodes.some((entry) => meshNodeIdMatches(entry, nodeId)))) {
117216
+ const shell = cached5 && typeof cached5 === "object" ? cached5 : { id: meshId, nodes: [], updatedAt: (/* @__PURE__ */ new Date()).toISOString() };
116799
117217
  if (!Array.isArray(shell.nodes)) shell.nodes = [];
116800
117218
  const hydratedNode = {
116801
117219
  id: nodeId,
@@ -117376,6 +117794,59 @@ ${e?.stderr || ""}`;
117376
117794
  init_track_identity();
117377
117795
  init_normalize();
117378
117796
  init_logger();
117797
+ var UNICODE_SYMBOLS = {
117798
+ ok: "\u2713",
117799
+ fail: "\u2717",
117800
+ warn: "\u26A0",
117801
+ info: "\u2022"
117802
+ };
117803
+ var ASCII_SYMBOLS = {
117804
+ ok: "[OK]",
117805
+ fail: "[X]",
117806
+ warn: "[!]",
117807
+ info: "-"
117808
+ };
117809
+ function supportsUnicodeSymbols(probe) {
117810
+ const forced = probe.env.ADHDEV_ASCII_SYMBOLS;
117811
+ if (forced === "1") return false;
117812
+ if (forced === "0") return true;
117813
+ if (probe.platform !== "win32") return true;
117814
+ if (probe.env.WT_SESSION) return true;
117815
+ if (probe.env.TERM_PROGRAM) return true;
117816
+ const codePageHints = [probe.env.ADHDEV_CONSOLE_CODEPAGE, probe.env.LC_ALL, probe.env.LANG];
117817
+ for (const hint of codePageHints) {
117818
+ if (!hint) continue;
117819
+ if (hint === "65001" || /utf-?8/i.test(hint)) return true;
117820
+ }
117821
+ return false;
117822
+ }
117823
+ function resolveConsoleSymbols(probe) {
117824
+ return supportsUnicodeSymbols(probe) ? UNICODE_SYMBOLS : ASCII_SYMBOLS;
117825
+ }
117826
+ var cached4 = null;
117827
+ function consoleSymbols() {
117828
+ if (!cached4) {
117829
+ cached4 = resolveConsoleSymbols({ platform: process.platform, env: process.env });
117830
+ }
117831
+ return cached4;
117832
+ }
117833
+ function resetConsoleSymbolsCache() {
117834
+ cached4 = null;
117835
+ }
117836
+ var SYM = {
117837
+ get ok() {
117838
+ return consoleSymbols().ok;
117839
+ },
117840
+ get fail() {
117841
+ return consoleSymbols().fail;
117842
+ },
117843
+ get warn() {
117844
+ return consoleSymbols().warn;
117845
+ },
117846
+ get info() {
117847
+ return consoleSymbols().info;
117848
+ }
117849
+ };
117379
117850
  init_debug_config();
117380
117851
  init_debug_trace();
117381
117852
  init_ipc_protocol();