@adhdev/daemon-core 0.9.82-rc.457 → 0.9.82-rc.459

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 (30) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +677 -189
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +676 -190
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/logging/debug-config.d.ts +16 -0
  7. package/dist/mesh/mesh-queue-assignment.d.ts +28 -0
  8. package/dist/mesh/mesh-reconcile-loop.d.ts +1 -0
  9. package/dist/mesh/worktree-bootstrap-config.d.ts +45 -0
  10. package/dist/providers/chat-message-normalization.d.ts +26 -0
  11. package/dist/providers/cli-provider-instance.d.ts +7 -0
  12. package/dist/providers/native-history/antigravity-claim-registry.d.ts +28 -0
  13. package/dist/providers/native-history/antigravity-cli-transcript.d.ts +11 -0
  14. package/dist/providers/native-history/dispatcher.d.ts +4 -0
  15. package/package.json +3 -3
  16. package/src/index.ts +2 -0
  17. package/src/logging/debug-config.ts +25 -0
  18. package/src/logging/debug-trace.ts +7 -2
  19. package/src/mesh/coordinator-prompt.ts +1 -1
  20. package/src/mesh/mesh-events-stale.ts +55 -4
  21. package/src/mesh/mesh-fast-forward.ts +22 -9
  22. package/src/mesh/mesh-queue-assignment.ts +220 -3
  23. package/src/mesh/mesh-reconcile-loop.ts +83 -10
  24. package/src/mesh/mesh-refine-gates.ts +22 -9
  25. package/src/mesh/worktree-bootstrap-config.ts +130 -0
  26. package/src/providers/chat-message-normalization.ts +44 -10
  27. package/src/providers/cli-provider-instance.ts +46 -0
  28. package/src/providers/native-history/antigravity-claim-registry.ts +131 -0
  29. package/src/providers/native-history/antigravity-cli-transcript.ts +154 -4
  30. package/src/providers/native-history/dispatcher.ts +150 -20
package/dist/index.mjs CHANGED
@@ -404,10 +404,10 @@ function readInjected(value) {
404
404
  }
405
405
  function getDaemonBuildInfo() {
406
406
  if (cached) return cached;
407
- const commit = readInjected(true ? "29441f596e5efe1972b874e0fb5b3d380c9d9bda" : void 0) ?? "unknown";
408
- const commitShort = readInjected(true ? "29441f59" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
409
- const version = readInjected(true ? "0.9.82-rc.457" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
410
- const builtAt = readInjected(true ? "2026-07-04T08:51:27.287Z" : void 0);
407
+ const commit = readInjected(true ? "7f95d1c8a5f682abdc7de49343d5bee688a9f16f" : void 0) ?? "unknown";
408
+ const commitShort = readInjected(true ? "7f95d1c8" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
409
+ const version = readInjected(true ? "0.9.82-rc.459" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
410
+ const builtAt = readInjected(true ? "2026-07-04T13:20:51.551Z" : void 0);
411
411
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
412
412
  return cached;
413
413
  }
@@ -3701,7 +3701,7 @@ function buildRulesSection(coordinatorCliType) {
3701
3701
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
3702
3702
  - **Limit parallelism.** Start with 1\u20132 tasks; scale only on success. Never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. This caps *concurrent* load \u2014 it does not mean serialize independent work: when a new, independent request arrives and there is headroom under \`maxParallelTasks\`, dispatch it right away rather than waiting for an in-flight task or a user nudge (read-only diagnosis especially, since it has no merge cost).
3703
3703
  - **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
3704
- - **Sequence shared-base-moving merges.** Parallel dispatch is encouraged, but merging one worktree can advance another in-flight worktree's base \u2014 especially the oss submodule pointer \u2014 turning a clean fast-forward into a diverged rebase (patch-equivalence correctly blocks this). Before merging an in-flight worktree while siblings are also in flight, land in an intentional order, re-clone long-running worktrees from the advanced base, or expect to manually rebase + ff-only the laggards; merging an independent fix mid-flight can strand siblings into a rebase.
3704
+ - **Sequence shared-base-moving merges.** Parallel dispatch is encouraged, but merging one worktree can advance another in-flight worktree's base \u2014 especially a shared submodule pointer \u2014 turning a clean fast-forward into a diverged rebase (patch-equivalence correctly blocks this). Before merging an in-flight worktree while siblings are also in flight, land in an intentional order, re-clone long-running worktrees from the advanced base, or expect to manually rebase + ff-only the laggards; merging an independent fix mid-flight can strand siblings into a rebase.
3705
3705
  - **Converge branches.** After worktree tasks: refine/fast-forward, or classify as \`pushed_feature_branch_needs_merge\` / \`blocked_review\` / \`cleanup_candidate\` / \`not_mergeable\`. Clean up with \`mesh_remove_node\`.
3706
3706
  - **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
3707
3707
  - **Submodule reachability = publish-needed.** \`submodule_reachability_failed\` \u2192 classify as \`blocked_review\`, request user approval to push to submodule main, then rerun \`mesh_refine_node\`.
@@ -8924,12 +8924,15 @@ var worktree_bootstrap_config_exports = {};
8924
8924
  __export(worktree_bootstrap_config_exports, {
8925
8925
  MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS,
8926
8926
  MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA: () => MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA,
8927
+ SUBMODULE_DEFAULT_BRANCH_FALLBACK: () => SUBMODULE_DEFAULT_BRANCH_FALLBACK,
8927
8928
  WORKTREE_BOOTSTRAP_STALE_RUNNING_MS: () => WORKTREE_BOOTSTRAP_STALE_RUNNING_MS,
8928
8929
  computeStaleInputsDigest: () => computeStaleInputsDigest,
8929
8930
  evaluateWorktreeBootstrapState: () => evaluateWorktreeBootstrapState,
8930
8931
  getRegisteredSubmodulePaths: () => getRegisteredSubmodulePaths,
8932
+ getSubmoduleConfiguredBranches: () => getSubmoduleConfiguredBranches,
8931
8933
  isWorktreeBootstrapStaleRunning: () => isWorktreeBootstrapStaleRunning,
8932
8934
  loadMeshWorktreeBootstrapConfig: () => loadMeshWorktreeBootstrapConfig,
8935
+ resolveSubmoduleDefaultBranch: () => resolveSubmoduleDefaultBranch,
8933
8936
  runMeshWorktreeBootstrap: () => runMeshWorktreeBootstrap,
8934
8937
  shouldDeferDispatchForBootstrap: () => shouldDeferDispatchForBootstrap,
8935
8938
  validateMeshWorktreeBootstrapConfig: () => validateMeshWorktreeBootstrapConfig
@@ -8960,6 +8963,81 @@ function getRegisteredSubmodulePaths(workspace) {
8960
8963
  }
8961
8964
  return paths;
8962
8965
  }
8966
+ function getSubmoduleConfiguredBranches(workspace) {
8967
+ const branchesByPath = /* @__PURE__ */ new Map();
8968
+ try {
8969
+ const out = execFileSync2(
8970
+ resolveWin32Executable("git"),
8971
+ ["config", "--file", ".gitmodules", "--list"],
8972
+ { cwd: workspace, encoding: "utf8", timeout: 1e4, windowsHide: true }
8973
+ );
8974
+ const pathByName = /* @__PURE__ */ new Map();
8975
+ const branchByName = /* @__PURE__ */ new Map();
8976
+ for (const line of String(out).split(/\r?\n/)) {
8977
+ const trimmed = line.trim();
8978
+ if (!trimmed) continue;
8979
+ const eq = trimmed.indexOf("=");
8980
+ if (eq < 0) continue;
8981
+ const key2 = trimmed.slice(0, eq);
8982
+ const value = trimmed.slice(eq + 1).trim();
8983
+ const match = /^submodule\.(.+)\.(path|branch)$/.exec(key2);
8984
+ if (!match) continue;
8985
+ const name = match[1];
8986
+ if (match[2] === "path") {
8987
+ const norm = value.replace(/\\/g, "/").replace(/\/+$/, "");
8988
+ if (norm) pathByName.set(name, norm);
8989
+ } else if (value) {
8990
+ branchByName.set(name, value);
8991
+ }
8992
+ }
8993
+ for (const [name, submodulePath] of pathByName) {
8994
+ const branch = branchByName.get(name);
8995
+ if (branch && branch !== ".") branchesByPath.set(submodulePath, branch);
8996
+ }
8997
+ } catch {
8998
+ }
8999
+ return branchesByPath;
9000
+ }
9001
+ function isPlausibleBranchName(name) {
9002
+ return typeof name === "string" && name.length > 0 && !/\s/.test(name) && name !== "HEAD";
9003
+ }
9004
+ async function resolveSubmoduleDefaultBranch(opts) {
9005
+ const remote = opts.remote?.trim() || "origin";
9006
+ const localTimeout = opts.timeoutMs ?? 1e4;
9007
+ const git = resolveWin32Executable("git");
9008
+ const execFileAsync4 = promisify3(execFile3);
9009
+ if (opts.superprojectWorkspace && opts.submodulePath) {
9010
+ try {
9011
+ const normalized = opts.submodulePath.replace(/\\/g, "/").replace(/\/+$/, "");
9012
+ const configured = getSubmoduleConfiguredBranches(opts.superprojectWorkspace).get(normalized);
9013
+ if (isPlausibleBranchName(configured)) return configured;
9014
+ } catch {
9015
+ }
9016
+ }
9017
+ try {
9018
+ const { stdout } = await execFileAsync4(
9019
+ git,
9020
+ ["symbolic-ref", "--short", `refs/remotes/${remote}/HEAD`],
9021
+ { cwd: opts.submoduleRepoPath, encoding: "utf8", timeout: localTimeout, windowsHide: true }
9022
+ );
9023
+ const short = String(stdout || "").trim();
9024
+ const prefix = `${remote}/`;
9025
+ const branch = short.startsWith(prefix) ? short.slice(prefix.length) : short;
9026
+ if (isPlausibleBranchName(branch)) return branch;
9027
+ } catch {
9028
+ }
9029
+ try {
9030
+ const { stdout } = await execFileAsync4(
9031
+ git,
9032
+ ["ls-remote", "--symref", remote, "HEAD"],
9033
+ { cwd: opts.submoduleRepoPath, encoding: "utf8", timeout: Math.max(localTimeout, 3e4), windowsHide: true }
9034
+ );
9035
+ const match = /^ref:\s+refs\/heads\/(\S+)\s+HEAD/m.exec(String(stdout || ""));
9036
+ if (match && isPlausibleBranchName(match[1])) return match[1];
9037
+ } catch {
9038
+ }
9039
+ return SUBMODULE_DEFAULT_BRANCH_FALLBACK;
9040
+ }
8963
9041
  function isCleanIgnoringSubmoduleGitlinks(porcelain, submodulePaths) {
8964
9042
  const lines = porcelain.split(/\r?\n/).filter((line) => line.length > 0);
8965
9043
  for (const line of lines) {
@@ -9202,13 +9280,14 @@ async function runMeshWorktreeBootstrap(mesh, workspace) {
9202
9280
  }
9203
9281
  return state;
9204
9282
  }
9205
- var WORKTREE_BOOTSTRAP_STALE_RUNNING_MS, MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS, MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA, DEFAULT_TIMEOUT_MS2, DEFAULT_OUTPUT_LIMIT_BYTES, OUTPUT_SUMMARY_CHARS;
9283
+ var WORKTREE_BOOTSTRAP_STALE_RUNNING_MS, SUBMODULE_DEFAULT_BRANCH_FALLBACK, MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS, MESH_WORKTREE_BOOTSTRAP_CONFIG_SCHEMA, DEFAULT_TIMEOUT_MS2, DEFAULT_OUTPUT_LIMIT_BYTES, OUTPUT_SUMMARY_CHARS;
9206
9284
  var init_worktree_bootstrap_config = __esm({
9207
9285
  "src/mesh/worktree-bootstrap-config.ts"() {
9208
9286
  "use strict";
9209
9287
  init_resolve_executable();
9210
9288
  init_refine_config();
9211
9289
  WORKTREE_BOOTSTRAP_STALE_RUNNING_MS = 10 * 60 * 1e3;
9290
+ SUBMODULE_DEFAULT_BRANCH_FALLBACK = "main";
9212
9291
  MESH_WORKTREE_BOOTSTRAP_CONFIG_LOCATIONS = [
9213
9292
  ".adhdev/worktree_bootstrap.json",
9214
9293
  ".adhdev/worktree_bootstrap.yaml",
@@ -9825,15 +9904,24 @@ async function resolveSubmodulePushes(status, options, execute, timeoutMs) {
9825
9904
  results.push({ ...base, code: "submodule_status_incomplete" });
9826
9905
  continue;
9827
9906
  }
9907
+ const remoteBranch = await resolveSubmoduleDefaultBranch({
9908
+ submoduleRepoPath: repoPath,
9909
+ superprojectWorkspace: status.repoRoot ?? status.workspace,
9910
+ submodulePath: submodule.path,
9911
+ timeoutMs
9912
+ });
9913
+ base.remoteBranch = remoteBranch;
9914
+ const remoteRef = `refs/remotes/origin/${remoteBranch}`;
9915
+ const fetchRefspec = `refs/heads/${remoteBranch}:${remoteRef}`;
9828
9916
  try {
9829
- await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
9917
+ await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", fetchRefspec], { timeoutMs: timeoutMs ?? 3e4 });
9830
9918
  } catch (error) {
9831
9919
  results.push({ ...base, code: "submodule_fetch_failed", error: formatGitError2(error) });
9832
9920
  continue;
9833
9921
  }
9834
9922
  let alreadyReachable = false;
9835
9923
  try {
9836
- await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
9924
+ await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, remoteRef], { timeoutMs: timeoutMs ?? 15e3 });
9837
9925
  alreadyReachable = true;
9838
9926
  } catch {
9839
9927
  }
@@ -9842,20 +9930,20 @@ async function resolveSubmodulePushes(status, options, execute, timeoutMs) {
9842
9930
  continue;
9843
9931
  }
9844
9932
  try {
9845
- await runGit(repoPath, ["merge-base", "--is-ancestor", "refs/remotes/origin/main", submodule.commit], { timeoutMs: timeoutMs ?? 15e3 });
9933
+ await runGit(repoPath, ["merge-base", "--is-ancestor", remoteRef, submodule.commit], { timeoutMs: timeoutMs ?? 15e3 });
9846
9934
  } catch (error) {
9847
9935
  results.push({ ...base, pushed: false, skipped: false, code: "submodule_non_fast_forward", error: formatGitError2(error) });
9848
9936
  continue;
9849
9937
  }
9850
- const refspec = `${submodule.commit}:refs/heads/main`;
9938
+ const refspec = `${submodule.commit}:refs/heads/${remoteBranch}`;
9851
9939
  if (!execute) {
9852
9940
  results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_available", refspec });
9853
9941
  continue;
9854
9942
  }
9855
9943
  try {
9856
9944
  await runGit(repoPath, ["push", "origin", refspec], { timeoutMs: timeoutMs ?? 3e4 });
9857
- await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", "refs/heads/main:refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 3e4 });
9858
- await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, "refs/remotes/origin/main"], { timeoutMs: timeoutMs ?? 15e3 });
9945
+ await runGit(repoPath, ["-c", "protocol.file.allow=always", "fetch", "origin", fetchRefspec], { timeoutMs: timeoutMs ?? 3e4 });
9946
+ await runGit(repoPath, ["merge-base", "--is-ancestor", submodule.commit, remoteRef], { timeoutMs: timeoutMs ?? 15e3 });
9859
9947
  results.push({ ...base, pushed: true, skipped: false, code: "submodule_pushed", refspec });
9860
9948
  } catch (error) {
9861
9949
  results.push({ ...base, pushed: false, skipped: false, code: "submodule_push_failed", refspec, error: formatGitError2(error) });
@@ -10123,6 +10211,7 @@ var init_mesh_fast_forward = __esm({
10123
10211
  "use strict";
10124
10212
  init_git_status();
10125
10213
  init_git_executor();
10214
+ init_worktree_bootstrap_config();
10126
10215
  STATUS_OPTIONS = { refreshUpstream: true, includeSubmodules: true, timeoutMs: 15e3, forceFresh: true };
10127
10216
  }
10128
10217
  });
@@ -11447,7 +11536,154 @@ var init_mesh_events_pending = __esm({
11447
11536
  }
11448
11537
  });
11449
11538
 
11539
+ // src/logging/debug-config.ts
11540
+ function isAlwaysOnTraceCategory(category) {
11541
+ return !!category && ALWAYS_ON_TRACE_CATEGORIES.includes(category);
11542
+ }
11543
+ function normalizeCategories(categories) {
11544
+ if (!Array.isArray(categories)) return [];
11545
+ return categories.map((category) => String(category || "").trim()).filter(Boolean);
11546
+ }
11547
+ function resolveDebugRuntimeConfig(options = {}) {
11548
+ const dev = options.dev === true;
11549
+ return {
11550
+ logLevel: options.logLevel || (dev ? "debug" : DEFAULT_CONFIG2.logLevel),
11551
+ collectDebugTrace: typeof options.trace === "boolean" ? options.trace : dev,
11552
+ traceContent: options.traceContent === true,
11553
+ traceBufferSize: Number.isFinite(options.traceBufferSize) ? Math.max(10, Math.floor(options.traceBufferSize)) : dev ? DEV_TRACE_BUFFER_SIZE : DEFAULT_CONFIG2.traceBufferSize,
11554
+ traceCategories: normalizeCategories(options.traceCategories)
11555
+ };
11556
+ }
11557
+ function setDebugRuntimeConfig(config) {
11558
+ currentConfig = {
11559
+ ...config,
11560
+ traceCategories: normalizeCategories(config.traceCategories),
11561
+ traceBufferSize: Math.max(10, Math.floor(config.traceBufferSize || DEFAULT_CONFIG2.traceBufferSize))
11562
+ };
11563
+ }
11564
+ function getDebugRuntimeConfig() {
11565
+ return { ...currentConfig, traceCategories: [...currentConfig.traceCategories] };
11566
+ }
11567
+ function resetDebugRuntimeConfig() {
11568
+ currentConfig = { ...DEFAULT_CONFIG2 };
11569
+ }
11570
+ function shouldCollectTraceCategory(category) {
11571
+ const config = currentConfig;
11572
+ if (isAlwaysOnTraceCategory(category)) return true;
11573
+ if (!config.collectDebugTrace) return false;
11574
+ if (!category) return true;
11575
+ if (config.traceCategories.length === 0) return true;
11576
+ return config.traceCategories.includes(category);
11577
+ }
11578
+ var NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, ALWAYS_ON_TRACE_CATEGORIES, DEFAULT_CONFIG2, currentConfig;
11579
+ var init_debug_config = __esm({
11580
+ "src/logging/debug-config.ts"() {
11581
+ "use strict";
11582
+ NORMAL_TRACE_BUFFER_SIZE = 200;
11583
+ DEV_TRACE_BUFFER_SIZE = 1e3;
11584
+ ALWAYS_ON_TRACE_CATEGORIES = ["completion-gate", "fsm-transition"];
11585
+ DEFAULT_CONFIG2 = {
11586
+ logLevel: "info",
11587
+ collectDebugTrace: false,
11588
+ traceContent: false,
11589
+ traceBufferSize: NORMAL_TRACE_BUFFER_SIZE,
11590
+ traceCategories: []
11591
+ };
11592
+ currentConfig = { ...DEFAULT_CONFIG2 };
11593
+ }
11594
+ });
11595
+
11596
+ // src/logging/debug-trace.ts
11597
+ function summarizeString(value) {
11598
+ return `[${value.length} chars]`;
11599
+ }
11600
+ function sanitizeTraceValue(value, traceContent) {
11601
+ if (traceContent) {
11602
+ if (Array.isArray(value)) return value.map((entry) => sanitizeTraceValue(entry, traceContent));
11603
+ if (value && typeof value === "object") {
11604
+ return Object.fromEntries(
11605
+ Object.entries(value).map(([key2, nested]) => [key2, sanitizeTraceValue(nested, traceContent)])
11606
+ );
11607
+ }
11608
+ return value;
11609
+ }
11610
+ if (typeof value === "string") return summarizeString(value);
11611
+ if (Array.isArray(value)) return value.map((entry) => sanitizeTraceValue(entry, traceContent));
11612
+ if (value && typeof value === "object") {
11613
+ return Object.fromEntries(
11614
+ Object.entries(value).map(([key2, nested]) => [key2, sanitizeTraceValue(nested, traceContent)])
11615
+ );
11616
+ }
11617
+ return value;
11618
+ }
11619
+ function sanitizeTracePayload(payload) {
11620
+ if (!payload) return {};
11621
+ const { traceContent } = getDebugRuntimeConfig();
11622
+ return sanitizeTraceValue(payload, traceContent);
11623
+ }
11624
+ function createEntry(event) {
11625
+ return {
11626
+ id: `trace_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
11627
+ ts: Date.now(),
11628
+ ...event,
11629
+ payload: sanitizeTracePayload(event.payload)
11630
+ };
11631
+ }
11632
+ function createDebugTraceStore(options) {
11633
+ const entries = [];
11634
+ const capacity = Math.max(1, Math.floor(options.capacity || 100));
11635
+ return {
11636
+ record(event) {
11637
+ if (!options.enabled && !isAlwaysOnTraceCategory(event.category)) return null;
11638
+ const entry = createEntry(event);
11639
+ entries.push(entry);
11640
+ if (entries.length > capacity) {
11641
+ entries.splice(0, entries.length - capacity);
11642
+ }
11643
+ return entry;
11644
+ },
11645
+ list(query = {}) {
11646
+ const limit = Math.max(1, Math.floor(query.limit || 100));
11647
+ return entries.filter((entry) => !query.interactionId || entry.interactionId === query.interactionId).filter((entry) => !query.category || entry.category === query.category).slice(-limit).map((entry) => ({ ...entry, payload: entry.payload ? { ...entry.payload } : {} }));
11648
+ },
11649
+ clear() {
11650
+ entries.splice(0, entries.length);
11651
+ }
11652
+ };
11653
+ }
11654
+ function configureDebugTraceStore() {
11655
+ const config = getDebugRuntimeConfig();
11656
+ globalStore = createDebugTraceStore({
11657
+ enabled: config.collectDebugTrace,
11658
+ capacity: config.traceBufferSize
11659
+ });
11660
+ }
11661
+ function recordDebugTrace(event) {
11662
+ if (!shouldCollectTraceCategory(event.category)) return null;
11663
+ return globalStore.record(event);
11664
+ }
11665
+ function getRecentDebugTrace(query = {}) {
11666
+ return globalStore.list(query);
11667
+ }
11668
+ function clearDebugTrace() {
11669
+ globalStore.clear();
11670
+ }
11671
+ function createInteractionId(prefix = "ix") {
11672
+ return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
11673
+ }
11674
+ var globalStore;
11675
+ var init_debug_trace = __esm({
11676
+ "src/logging/debug-trace.ts"() {
11677
+ "use strict";
11678
+ init_debug_config();
11679
+ globalStore = createDebugTraceStore({ enabled: false, capacity: getDebugRuntimeConfig().traceBufferSize });
11680
+ }
11681
+ });
11682
+
11450
11683
  // src/mesh/mesh-events-stale.ts
11684
+ function recordSynthCompletionGateTrace(stage, payload) {
11685
+ recordDebugTrace({ category: "completion-gate", stage, level: "debug", payload });
11686
+ }
11451
11687
  function findRecentTerminalLedgerEvidence(args) {
11452
11688
  if (!args.sessionId && !args.nodeId) return null;
11453
11689
  const entries = readLedgerEntries(args.meshId, { tail: 200 });
@@ -11581,6 +11817,7 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
11581
11817
  completedAt
11582
11818
  });
11583
11819
  const workerResult = evidence.workerResult;
11820
+ const selfAttributing = workerResult.source === "final_summary_json";
11584
11821
  const dispatchTime = dispatch?.timestamp ? new Date(dispatch.timestamp).getTime() : Number.NaN;
11585
11822
  const transcriptTime = args.transcriptMessageAt ? new Date(args.transcriptMessageAt).getTime() : Number.NaN;
11586
11823
  const transcriptAfterDispatch = Number.isFinite(dispatchTime) && Number.isFinite(transcriptTime) && transcriptTime >= dispatchTime;
@@ -11613,7 +11850,9 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
11613
11850
  dispatchEntryId: dispatch?.id,
11614
11851
  dispatchTimestamp: dispatch?.timestamp,
11615
11852
  transcriptMessageAt: readNonEmptyString2(args.transcriptMessageAt),
11616
- transcriptFinalAssistantPresent: true
11853
+ // Honestly reflect self-attribution: a plain-text tail did NOT prove a turn-final
11854
+ // assistant message (only a self-attributing final_summary_json did).
11855
+ transcriptFinalAssistantPresent: selfAttributing
11617
11856
  },
11618
11857
  evidence
11619
11858
  }
@@ -11630,6 +11869,11 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
11630
11869
  finalSummary,
11631
11870
  taskId: args.taskId,
11632
11871
  workerResult,
11872
+ // EARLYNOTIFY-GATEBYPASS (c): mark a non-self-attributing synth WEAK so its pending
11873
+ // fingerprint is `…::weak` (isWeakCompletionMetadata reads evidenceLevel), never claiming
11874
+ // the genuine dedup slot. evidenceLevel:'weak' is deliberately NOT a false-idle marker
11875
+ // (the transcript tail existed) — it keeps the completion superseable, not suppressed.
11876
+ ...selfAttributing ? {} : { evidenceLevel: "weak" },
11633
11877
  completionDiagnostic: {
11634
11878
  reason: "direct_task_transcript_reconciliation",
11635
11879
  terminalLedgerKind: kind,
@@ -11648,6 +11892,14 @@ function reconcileDirectDispatchCompletionFromTranscript(args) {
11648
11892
  ...readNonEmptyString2(args.targetCoordinatorDaemonId) ? { targetCoordinatorDaemonId: readNonEmptyString2(args.targetCoordinatorDaemonId) } : {},
11649
11893
  ...targetCoordinatorSessionId ? { targetCoordinatorSessionId } : {}
11650
11894
  });
11895
+ recordSynthCompletionGateTrace("synth-fire", {
11896
+ producer: "transcript_reconcile",
11897
+ source: args.source || "direct_task_transcript_reconciliation",
11898
+ taskId: args.taskId,
11899
+ kind,
11900
+ selfAttributing,
11901
+ evidenceLevel: selfAttributing ? "sufficient" : "weak"
11902
+ });
11651
11903
  return { reconciled: true, kind, workerResult, ledgerEntryId: entry.id };
11652
11904
  }
11653
11905
  function buildNoProgressCompletionReconciliation(args) {
@@ -11659,10 +11911,20 @@ function buildNoProgressCompletionReconciliation(args) {
11659
11911
  const completionDiagnostic = readRecord5(args.metadataEvent.completionDiagnostic);
11660
11912
  const finalSummary = readNonEmptyString2(args.metadataEvent.finalSummary);
11661
11913
  const status = readNonEmptyString2(args.metadataEvent.status).toLowerCase();
11914
+ const noProgressSelfAttributing = Boolean(
11915
+ finalSummary || workerResult || completionDiagnostic?.finalAssistantPresent === true
11916
+ );
11662
11917
  const explicitCompletionEvidence = Boolean(
11663
- finalSummary || workerResult || completionDiagnostic?.finalAssistantPresent === true || status === "idle" || status === "ready" || status === "completed"
11918
+ noProgressSelfAttributing || status === "idle" || status === "ready" || status === "completed"
11664
11919
  );
11665
11920
  if (explicitCompletionEvidence) {
11921
+ recordSynthCompletionGateTrace("synth-fire", {
11922
+ producer: "no_progress_reconcile",
11923
+ source: "no_progress_reconciliation",
11924
+ taskId: readNonEmptyString2(args.metadataEvent.taskId),
11925
+ selfAttributing: noProgressSelfAttributing,
11926
+ evidenceLevel: noProgressSelfAttributing ? "sufficient" : "weak"
11927
+ });
11666
11928
  return {
11667
11929
  ...args.metadataEvent,
11668
11930
  targetSessionId: sessionId,
@@ -11672,6 +11934,7 @@ function buildNoProgressCompletionReconciliation(args) {
11672
11934
  source: "no_progress_reconciliation",
11673
11935
  reconciledFromEvent: "monitor:no_progress",
11674
11936
  timestamp: args.metadataEvent.timestamp ?? Date.now(),
11937
+ ...noProgressSelfAttributing ? {} : { evidenceLevel: "weak" },
11675
11938
  completionDiagnostic: {
11676
11939
  ...completionDiagnostic || {},
11677
11940
  reconciliationReason: "provider_completion_evidence"
@@ -11700,6 +11963,7 @@ var init_mesh_events_stale = __esm({
11700
11963
  init_mesh_delivery_policy();
11701
11964
  init_mesh_events_pending();
11702
11965
  init_mesh_events_utils();
11966
+ init_debug_trace();
11703
11967
  init_dist();
11704
11968
  DIRECT_DISPATCH_RECONCILE_GRACE_MS = 6e4;
11705
11969
  DIRECT_DISPATCH_IDLE_SESSION_RECONCILE_GRACE_MS = 12e4;
@@ -12749,6 +13013,32 @@ function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType)
12749
13013
  );
12750
13014
  return true;
12751
13015
  }
13016
+ function awaitClaimWindowMs(cycles) {
13017
+ return AUTO_LAUNCH_AWAIT_CLAIM_MS * Math.pow(2, Math.min(cycles, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES));
13018
+ }
13019
+ function remoteSessionAppearsLive(meshId, sessionId) {
13020
+ if (!sessionId) return false;
13021
+ try {
13022
+ return MeshRuntimeStore.getInstance().getRemoteIdleSessions(meshId).some((s2) => sessionIdsEquivalent(s2.sessionId, sessionId));
13023
+ } catch {
13024
+ return false;
13025
+ }
13026
+ }
13027
+ function inWindowAutoLaunchSessionIdsForNode(meshId, nodeId) {
13028
+ const nowMs = Date.now();
13029
+ const out = [];
13030
+ for (const task of getQueue(meshId, { status: ["pending"] })) {
13031
+ const al = task.autoLaunch;
13032
+ const sid = al ? readNonEmptyString2(al.sessionId) : "";
13033
+ if (!al || al.status !== "started" && al.status !== "completed" || !sid) continue;
13034
+ if (!daemonIdsEquivalent(al.nodeId, nodeId)) continue;
13035
+ const launchedAtMs = Date.parse(al.updatedAt);
13036
+ const inBaseWindow = Number.isFinite(launchedAtMs) && nowMs - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS;
13037
+ const inBackoff = autoLaunchAwaitClaimBackoff.has(`${meshId}::${task.id}`);
13038
+ if (inBaseWindow || inBackoff) out.push(sid);
13039
+ }
13040
+ return out;
13041
+ }
12752
13042
  function isActionableSkipReason(reason) {
12753
13043
  if (!reason) return false;
12754
13044
  return ACTIONABLE_SKIP_REASON_PREFIXES.some((prefix) => reason === prefix || reason.startsWith(prefix));
@@ -12988,8 +13278,24 @@ function isSessionActivelyGenerating(components, sessionId) {
12988
13278
  if (!state) return false;
12989
13279
  return sessionStateLooksActive(state);
12990
13280
  }
13281
+ function resolveSessionBusyVerdict(components, sessionId) {
13282
+ if (!sessionId) return "UNKNOWN";
13283
+ try {
13284
+ const instances = components.instanceManager?.getByCategory?.("cli") || [];
13285
+ const inst = instances.find((i) => {
13286
+ const sid = readNonEmptyString2(i?.getState?.().instanceId);
13287
+ return sid && sessionIdsEquivalent(sid, sessionId);
13288
+ });
13289
+ if (!inst) return "UNKNOWN";
13290
+ const state = inst.getState?.();
13291
+ if (!state) return "UNKNOWN";
13292
+ return sessionStateLooksActive(state) ? "GENERATING" : "IDLE_CONFIRMED";
13293
+ } catch {
13294
+ return "UNKNOWN";
13295
+ }
13296
+ }
12991
13297
  function liveSessionCountForNode(components, meshId, nodeId) {
12992
- return components.instanceManager.getByCategory("cli").filter((inst) => {
13298
+ const localInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
12993
13299
  const state = inst.getState();
12994
13300
  const settings = state.settings || {};
12995
13301
  if (readNonEmptyString2(settings.meshNodeFor) !== meshId) return false;
@@ -12997,9 +13303,16 @@ function liveSessionCountForNode(components, meshId, nodeId) {
12997
13303
  if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
12998
13304
  const status = readNonEmptyString2(state.status).toLowerCase();
12999
13305
  return !isTerminalSessionStatus(status);
13000
- }).length;
13306
+ });
13307
+ let count = localInstances.length;
13308
+ const localSessionIds = localInstances.map((inst) => readNonEmptyString2(inst.getState().instanceId)).filter(Boolean);
13309
+ for (const sid of inWindowAutoLaunchSessionIdsForNode(meshId, nodeId)) {
13310
+ if (!localSessionIds.some((local) => sessionIdsEquivalent(local, sid))) count += 1;
13311
+ }
13312
+ return count;
13001
13313
  }
13002
13314
  function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
13315
+ if (inWindowAutoLaunchSessionIdsForNode(meshId, nodeId).length > 0) return true;
13003
13316
  const busySessionIds = new Set(
13004
13317
  getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId)).map((task) => readNonEmptyString2(task.assignedSessionId)).filter(Boolean)
13005
13318
  );
@@ -13110,10 +13423,54 @@ async function resolveUsableProvider(components, nodeId, node, requiredTags) {
13110
13423
  function readMeshNodeId(node) {
13111
13424
  return normalizeMeshNodeId(node) ?? "";
13112
13425
  }
13426
+ function driveExpiredAwaitClaim(components, meshId, task, ctx) {
13427
+ const { sessionId, nodeId, providerType } = ctx;
13428
+ const backoffKey = `${meshId}::${task.id}`;
13429
+ const nowMs = Date.now();
13430
+ const state = autoLaunchAwaitClaimBackoff.get(backoffKey) || { cycles: 0, nextAttemptAtMs: 0 };
13431
+ if (state.nextAttemptAtMs && nowMs < state.nextAttemptAtMs) return "backoff";
13432
+ const atCap = state.cycles >= AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES;
13433
+ const live = remoteSessionAppearsLive(meshId, sessionId);
13434
+ if ((live || atCap) && nodeId && providerType) {
13435
+ try {
13436
+ MeshRuntimeStore.getInstance().setRemoteIdleSession(meshId, nodeId, sessionId, providerType, nowMs + AUTO_LAUNCH_REMOTE_IDLE_TTL_MS);
13437
+ } catch {
13438
+ }
13439
+ const assigned = tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
13440
+ if (assigned) {
13441
+ autoLaunchAwaitClaimBackoff.delete(backoffKey);
13442
+ const isFallback = atCap && !live;
13443
+ recordAutoLaunchEvent(meshId, {
13444
+ phase: "completed",
13445
+ taskId: task.id,
13446
+ reason: isFallback ? "await_claim_direct_dispatch_fallback" : "await_claim_redriven",
13447
+ nodeId,
13448
+ sessionId
13449
+ });
13450
+ LOG.info("MeshQueue", `Auto-launch await-claim ${isFallback ? "direct-dispatch fallback" : "re-drive"} claimed task ${task.id} into existing session ${sessionId} on node ${nodeId} (mesh ${meshId})`);
13451
+ return isFallback ? "fallback" : "claimed";
13452
+ }
13453
+ if (atCap) {
13454
+ autoLaunchAwaitClaimBackoff.delete(backoffKey);
13455
+ return "respawn";
13456
+ }
13457
+ }
13458
+ const cycles = Math.min(state.cycles + 1, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES);
13459
+ autoLaunchAwaitClaimBackoff.set(backoffKey, { cycles, nextAttemptAtMs: nowMs + awaitClaimWindowMs(cycles) });
13460
+ recordAutoLaunchEvent(meshId, { phase: "skipped", taskId: task.id, reason: "awaiting_launched_session_claim_backoff", nodeId, sessionId });
13461
+ return "backoff";
13462
+ }
13113
13463
  async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
13114
13464
  const queue = getQueue(meshId);
13115
13465
  const statusById = new Map(queue.map((task) => [task.id, task.status]));
13116
13466
  const pending = queue.filter((task) => task.status === "pending");
13467
+ {
13468
+ const pendingIds = new Set(pending.map((t) => t.id));
13469
+ const prefix = `${meshId}::`;
13470
+ for (const key2 of [...autoLaunchAwaitClaimBackoff.keys()]) {
13471
+ if (key2.startsWith(prefix) && !pendingIds.has(key2.slice(prefix.length))) autoLaunchAwaitClaimBackoff.delete(key2);
13472
+ }
13473
+ }
13117
13474
  if (!pending.length) return false;
13118
13475
  const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
13119
13476
  const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks);
@@ -13138,10 +13495,18 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
13138
13495
  }
13139
13496
  if (task.autoLaunch?.status === "completed" && task.autoLaunch.sessionId) {
13140
13497
  const launchedAtMs = Date.parse(task.autoLaunch.updatedAt);
13498
+ const alSessionId = readNonEmptyString2(task.autoLaunch.sessionId);
13499
+ const alNodeId = readNonEmptyString2(task.autoLaunch.nodeId);
13500
+ const alProvider = readNonEmptyString2(task.autoLaunch.providerType);
13141
13501
  if (Number.isFinite(launchedAtMs) && Date.now() - launchedAtMs < AUTO_LAUNCH_AWAIT_CLAIM_MS) {
13142
- recordAutoLaunchEvent(meshId, { phase: "skipped", taskId: task.id, reason: "awaiting_launched_session_claim", nodeId: task.autoLaunch.nodeId, sessionId: task.autoLaunch.sessionId });
13502
+ recordAutoLaunchEvent(meshId, { phase: "skipped", taskId: task.id, reason: "awaiting_launched_session_claim", nodeId: alNodeId, sessionId: alSessionId });
13143
13503
  continue;
13144
13504
  }
13505
+ if (Number.isFinite(launchedAtMs) && alSessionId && alNodeId) {
13506
+ const outcome = driveExpiredAwaitClaim(components, meshId, task, { sessionId: alSessionId, nodeId: alNodeId, providerType: alProvider });
13507
+ if (outcome === "claimed" || outcome === "fallback") return true;
13508
+ if (outcome === "backoff") continue;
13509
+ }
13145
13510
  }
13146
13511
  const candidateNodes = Array.isArray(mesh?.nodes) ? mesh.nodes.filter((node) => {
13147
13512
  if (task.targetNodeId && !meshNodeIdMatches(node, task.targetNodeId)) return false;
@@ -13527,7 +13892,7 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
13527
13892
  });
13528
13893
  });
13529
13894
  }
13530
- var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
13895
+ var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
13531
13896
  var init_mesh_queue_assignment = __esm({
13532
13897
  "src/mesh/mesh-queue-assignment.ts"() {
13533
13898
  "use strict";
@@ -13562,6 +13927,9 @@ var init_mesh_queue_assignment = __esm({
13562
13927
  autoLaunchCooldownUntil = /* @__PURE__ */ new Map();
13563
13928
  AUTO_LAUNCH_COOLDOWN_MS = 5e3;
13564
13929
  AUTO_LAUNCH_AWAIT_CLAIM_MS = 9e4;
13930
+ AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES = 2;
13931
+ AUTO_LAUNCH_REMOTE_IDLE_TTL_MS = 5 * 60 * 1e3;
13932
+ autoLaunchAwaitClaimBackoff = /* @__PURE__ */ new Map();
13565
13933
  lastAutoLaunchLedgerKey = /* @__PURE__ */ new Map();
13566
13934
  AUTO_LAUNCH_LEDGER_DEDUP_MAX = 2e3;
13567
13935
  ACTIONABLE_SKIP_REASON_PREFIXES = [
@@ -14589,22 +14957,26 @@ function extractFinalSummaryFromMessagesAfter(messages, minTimestampMs, maxChars
14589
14957
  return "";
14590
14958
  }
14591
14959
  function extractFinalAssistantSummaryEvidence(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
14592
- if (!Array.isArray(messages) || messages.length === 0) return { finalSummary: "" };
14960
+ const turnEnd = selectFinalAssistantTurnEndMessage(messages);
14961
+ if (!turnEnd) return { finalSummary: "" };
14962
+ return {
14963
+ finalSummary: flattenContent(turnEnd.content).trim().slice(0, maxChars),
14964
+ transcriptMessageAt: readChatMessageTimestampIso(turnEnd)
14965
+ };
14966
+ }
14967
+ function selectFinalAssistantTurnEndMessage(messages) {
14968
+ if (!Array.isArray(messages) || messages.length === 0) return null;
14593
14969
  for (let i = messages.length - 1; i >= 0; i--) {
14594
14970
  const msg = messages[i];
14595
14971
  if (!msg) continue;
14596
14972
  const classification = classifyChatMessageVisibility(msg);
14597
- if (classification.isUserFacing && (msg.role === "assistant" || msg.role === "model")) {
14598
- const text = flattenContent(msg.content).trim();
14599
- if (text) {
14600
- return {
14601
- finalSummary: text.slice(0, maxChars),
14602
- transcriptMessageAt: readChatMessageTimestampIso(msg)
14603
- };
14604
- }
14973
+ if (!classification.isUserFacing) continue;
14974
+ if (msg.role === "assistant" || msg.role === "model") {
14975
+ return flattenContent(msg.content).trim() ? msg : null;
14605
14976
  }
14977
+ return null;
14606
14978
  }
14607
- return { finalSummary: "" };
14979
+ return null;
14608
14980
  }
14609
14981
  function canonicalizeKindHint(value) {
14610
14982
  return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
@@ -17598,6 +17970,11 @@ function recoverStrandedAssignedDispatches(components, meshId, store) {
17598
17970
  const assigned = getQueue(meshId, { status: ["assigned"] });
17599
17971
  if (!assigned.length) return;
17600
17972
  const nowMs = Date.now();
17973
+ const assignedKeys = new Set(assigned.map((r) => `${meshId}::${r.id}`));
17974
+ const meshKeyPrefix = `${meshId}::`;
17975
+ for (const key2 of [...deliveredNoTurnUnknownStreak.keys()]) {
17976
+ if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) deliveredNoTurnUnknownStreak.delete(key2);
17977
+ }
17601
17978
  for (const row of assigned) {
17602
17979
  const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
17603
17980
  if (!Number.isFinite(dispatchedAtMs)) continue;
@@ -17621,20 +17998,45 @@ function recoverStrandedAssignedDispatches(components, meshId, store) {
17621
17998
  }
17622
17999
  if (store.taskHasConfirmedDelivery(meshId, row.id)) {
17623
18000
  if (nowMs - dispatchedAtMs < DELIVERED_NO_TURN_DEADLINE_MS) continue;
17624
- if (row.assignedSessionId && isSessionActivelyGenerating(components, row.assignedSessionId)) continue;
18001
+ const streakKey = `${meshId}::${row.id}`;
18002
+ const verdict = row.assignedSessionId ? resolveSessionBusyVerdict(components, row.assignedSessionId) : "IDLE_CONFIRMED";
18003
+ if (verdict === "GENERATING") {
18004
+ deliveredNoTurnUnknownStreak.delete(streakKey);
18005
+ continue;
18006
+ }
18007
+ let reclaimReason;
18008
+ if (verdict === "IDLE_CONFIRMED") {
18009
+ deliveredNoTurnUnknownStreak.delete(streakKey);
18010
+ reclaimReason = "delivered_no_turn_deadline";
18011
+ } else {
18012
+ const streak = (deliveredNoTurnUnknownStreak.get(streakKey) ?? 0) + 1;
18013
+ deliveredNoTurnUnknownStreak.set(streakKey, streak);
18014
+ if (streak < RECLAIM_UNKNOWN_GRACE_TICKS) {
18015
+ traceMeshEventDrop("reclaim_deferred_unknown_verdict", {
18016
+ taskId: row.id,
18017
+ sessionId: row.assignedSessionId,
18018
+ nodeId: row.assignedNodeId,
18019
+ meshId,
18020
+ event: "agent:generating_completed"
18021
+ }, `unknown ${streak}/${RECLAIM_UNKNOWN_GRACE_TICKS}`);
18022
+ continue;
18023
+ }
18024
+ reclaimReason = "reclaim_after_unknown_grace";
18025
+ }
17625
18026
  const reclaimedLost = reclaimStrandedAssignedTask(meshId, row.id, {
17626
- reason: "delivered_no_turn_deadline",
18027
+ reason: reclaimReason,
17627
18028
  ageMs: nowMs - dispatchedAtMs
17628
18029
  });
17629
18030
  if (reclaimedLost) {
17630
- LOG.warn("MeshReconcile", `Reclaimed delivered-but-lost task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, delivered but no completion in ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s, session non-generating \u2192 ${reclaimedLost.status})`);
18031
+ deliveredNoTurnUnknownStreak.delete(streakKey);
18032
+ LOG.warn("MeshReconcile", `Reclaimed delivered-but-lost task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, delivered but no completion in ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s, verdict ${verdict} \u2192 ${reclaimReason} \u2192 ${reclaimedLost.status})`);
17631
18033
  traceMeshEventDrop("assigned_stranded_delivered_no_turn", {
17632
18034
  taskId: row.id,
17633
18035
  sessionId: row.assignedSessionId,
17634
18036
  nodeId: row.assignedNodeId,
17635
18037
  meshId,
17636
18038
  event: "agent:generating_completed"
17637
- }, `delivered ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s \u2192 ${reclaimedLost.status}`);
18039
+ }, `delivered ${Math.round((nowMs - dispatchedAtMs) / 1e3)}s ${reclaimReason} \u2192 ${reclaimedLost.status}`);
17638
18040
  }
17639
18041
  continue;
17640
18042
  }
@@ -18337,7 +18739,7 @@ function setupMeshReconcileLoop(components) {
18337
18739
  }
18338
18740
  };
18339
18741
  }
18340
- var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
18742
+ var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, DEFAULT_PENDING_HELD_DRAIN_ESCALATE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
18341
18743
  var init_mesh_reconcile_loop = __esm({
18342
18744
  "src/mesh/mesh-reconcile-loop.ts"() {
18343
18745
  "use strict";
@@ -18368,6 +18770,8 @@ var init_mesh_reconcile_loop = __esm({
18368
18770
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
18369
18771
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
18370
18772
  DELIVERED_NO_TURN_DEADLINE_MS = 15 * 6e4;
18773
+ RECLAIM_UNKNOWN_GRACE_TICKS = 3;
18774
+ deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
18371
18775
  STRICT_SESSION_MATCH_TTL_MS = 6e4;
18372
18776
  unresolvedForwardRejectionCounts = /* @__PURE__ */ new Map();
18373
18777
  MAX_FORWARD_REJECTIONS = 5;
@@ -18497,58 +18901,6 @@ var init_approval_utils = __esm({
18497
18901
  }
18498
18902
  });
18499
18903
 
18500
- // src/logging/debug-config.ts
18501
- function normalizeCategories(categories) {
18502
- if (!Array.isArray(categories)) return [];
18503
- return categories.map((category) => String(category || "").trim()).filter(Boolean);
18504
- }
18505
- function resolveDebugRuntimeConfig(options = {}) {
18506
- const dev = options.dev === true;
18507
- return {
18508
- logLevel: options.logLevel || (dev ? "debug" : DEFAULT_CONFIG2.logLevel),
18509
- collectDebugTrace: typeof options.trace === "boolean" ? options.trace : dev,
18510
- traceContent: options.traceContent === true,
18511
- traceBufferSize: Number.isFinite(options.traceBufferSize) ? Math.max(10, Math.floor(options.traceBufferSize)) : dev ? DEV_TRACE_BUFFER_SIZE : DEFAULT_CONFIG2.traceBufferSize,
18512
- traceCategories: normalizeCategories(options.traceCategories)
18513
- };
18514
- }
18515
- function setDebugRuntimeConfig(config) {
18516
- currentConfig = {
18517
- ...config,
18518
- traceCategories: normalizeCategories(config.traceCategories),
18519
- traceBufferSize: Math.max(10, Math.floor(config.traceBufferSize || DEFAULT_CONFIG2.traceBufferSize))
18520
- };
18521
- }
18522
- function getDebugRuntimeConfig() {
18523
- return { ...currentConfig, traceCategories: [...currentConfig.traceCategories] };
18524
- }
18525
- function resetDebugRuntimeConfig() {
18526
- currentConfig = { ...DEFAULT_CONFIG2 };
18527
- }
18528
- function shouldCollectTraceCategory(category) {
18529
- const config = currentConfig;
18530
- if (!config.collectDebugTrace) return false;
18531
- if (!category) return true;
18532
- if (config.traceCategories.length === 0) return true;
18533
- return config.traceCategories.includes(category);
18534
- }
18535
- var NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, DEFAULT_CONFIG2, currentConfig;
18536
- var init_debug_config = __esm({
18537
- "src/logging/debug-config.ts"() {
18538
- "use strict";
18539
- NORMAL_TRACE_BUFFER_SIZE = 200;
18540
- DEV_TRACE_BUFFER_SIZE = 1e3;
18541
- DEFAULT_CONFIG2 = {
18542
- logLevel: "info",
18543
- collectDebugTrace: false,
18544
- traceContent: false,
18545
- traceBufferSize: NORMAL_TRACE_BUFFER_SIZE,
18546
- traceCategories: []
18547
- };
18548
- currentConfig = { ...DEFAULT_CONFIG2 };
18549
- }
18550
- });
18551
-
18552
18904
  // src/providers/sdk/v1/schemas/cli/provider.schema.json
18553
18905
  var provider_schema_default;
18554
18906
  var init_provider_schema = __esm({
@@ -30582,97 +30934,18 @@ function resolveTargetSessionActualWorkspace(h, targetSessionId) {
30582
30934
 
30583
30935
  // src/commands/chat-commands-debug-bundle.ts
30584
30936
  init_logger();
30937
+ init_debug_trace();
30585
30938
  import * as fs7 from "fs";
30586
30939
  import * as os10 from "os";
30587
30940
  import * as path17 from "path";
30588
30941
  import { randomUUID as randomUUID11 } from "crypto";
30589
30942
 
30590
- // src/logging/debug-trace.ts
30591
- init_debug_config();
30592
- function summarizeString(value) {
30593
- return `[${value.length} chars]`;
30594
- }
30595
- function sanitizeTraceValue(value, traceContent) {
30596
- if (traceContent) {
30597
- if (Array.isArray(value)) return value.map((entry) => sanitizeTraceValue(entry, traceContent));
30598
- if (value && typeof value === "object") {
30599
- return Object.fromEntries(
30600
- Object.entries(value).map(([key2, nested]) => [key2, sanitizeTraceValue(nested, traceContent)])
30601
- );
30602
- }
30603
- return value;
30604
- }
30605
- if (typeof value === "string") return summarizeString(value);
30606
- if (Array.isArray(value)) return value.map((entry) => sanitizeTraceValue(entry, traceContent));
30607
- if (value && typeof value === "object") {
30608
- return Object.fromEntries(
30609
- Object.entries(value).map(([key2, nested]) => [key2, sanitizeTraceValue(nested, traceContent)])
30610
- );
30611
- }
30612
- return value;
30613
- }
30614
- function sanitizeTracePayload(payload) {
30615
- if (!payload) return {};
30616
- const { traceContent } = getDebugRuntimeConfig();
30617
- return sanitizeTraceValue(payload, traceContent);
30618
- }
30619
- function createEntry(event) {
30620
- return {
30621
- id: `trace_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
30622
- ts: Date.now(),
30623
- ...event,
30624
- payload: sanitizeTracePayload(event.payload)
30625
- };
30626
- }
30627
- function createDebugTraceStore(options) {
30628
- const entries = [];
30629
- const capacity = Math.max(1, Math.floor(options.capacity || 100));
30630
- return {
30631
- record(event) {
30632
- if (!options.enabled) return null;
30633
- const entry = createEntry(event);
30634
- entries.push(entry);
30635
- if (entries.length > capacity) {
30636
- entries.splice(0, entries.length - capacity);
30637
- }
30638
- return entry;
30639
- },
30640
- list(query = {}) {
30641
- const limit = Math.max(1, Math.floor(query.limit || 100));
30642
- return entries.filter((entry) => !query.interactionId || entry.interactionId === query.interactionId).filter((entry) => !query.category || entry.category === query.category).slice(-limit).map((entry) => ({ ...entry, payload: entry.payload ? { ...entry.payload } : {} }));
30643
- },
30644
- clear() {
30645
- entries.splice(0, entries.length);
30646
- }
30647
- };
30648
- }
30649
- var globalStore = createDebugTraceStore({ enabled: false, capacity: getDebugRuntimeConfig().traceBufferSize });
30650
- function configureDebugTraceStore() {
30651
- const config = getDebugRuntimeConfig();
30652
- globalStore = createDebugTraceStore({
30653
- enabled: config.collectDebugTrace,
30654
- capacity: config.traceBufferSize
30655
- });
30656
- }
30657
- function recordDebugTrace(event) {
30658
- if (!shouldCollectTraceCategory(event.category)) return null;
30659
- return globalStore.record(event);
30660
- }
30661
- function getRecentDebugTrace(query = {}) {
30662
- return globalStore.list(query);
30663
- }
30664
- function clearDebugTrace() {
30665
- globalStore.clear();
30666
- }
30667
- function createInteractionId(prefix = "ix") {
30668
- return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
30669
- }
30670
-
30671
30943
  // src/commands/chat-commands-read.ts
30672
30944
  init_contracts();
30673
30945
  import * as path16 from "path";
30674
30946
  init_coordinator_registry();
30675
30947
  init_logger();
30948
+ init_debug_trace();
30676
30949
 
30677
30950
  // src/chat/source-machine.ts
30678
30951
  var INITIAL_CHAT_SOURCE_STATE = Object.freeze({
@@ -35907,6 +36180,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
35907
36180
  };
35908
36181
 
35909
36182
  // src/commands/low-family/session-host.ts
36183
+ init_debug_trace();
35910
36184
  function toHostedCliRuntimeDescriptor(record) {
35911
36185
  if (!record || typeof record !== "object") return null;
35912
36186
  const runtimeId = typeof record.sessionId === "string" ? record.sessionId : "";
@@ -36398,6 +36672,7 @@ var refineConfigHandlers = {
36398
36672
 
36399
36673
  // src/commands/low-family/diagnostics.ts
36400
36674
  init_logger();
36675
+ init_debug_trace();
36401
36676
  import * as fs11 from "fs";
36402
36677
  var diagnosticsHandlers = {
36403
36678
  get_logs: async (_ctx, args) => {
@@ -37910,6 +38185,7 @@ function applyPreLaunchTrust(trust, workingDir) {
37910
38185
 
37911
38186
  // src/providers/spec/fsm-driver.ts
37912
38187
  init_logger();
38188
+ init_debug_trace();
37913
38189
  init_debug_config();
37914
38190
  init_pty_write_chunking();
37915
38191
  function countNewlines(s2) {
@@ -40765,6 +41041,7 @@ function createCliAdapter(provider, workingDir, cliArgs, extraEnv, transportFact
40765
41041
 
40766
41042
  // src/providers/cli-provider-instance.ts
40767
41043
  init_logger();
41044
+ init_debug_trace();
40768
41045
  init_debug_config();
40769
41046
  init_mesh_event_trace();
40770
41047
  init_control_effects();
@@ -40788,6 +41065,46 @@ function normalizeProviderSessionId(provider, providerSessionId) {
40788
41065
  return normalizedId;
40789
41066
  }
40790
41067
 
41068
+ // src/providers/native-history/antigravity-claim-registry.ts
41069
+ var claimsByUuid = /* @__PURE__ */ new Map();
41070
+ var CLAIM_STALE_MS = 10 * 60 * 1e3;
41071
+ function normalizeUuid(uuid) {
41072
+ return String(uuid || "").trim().toLowerCase();
41073
+ }
41074
+ function antigravityOwnerToken(workspace, sessionStartedAtMs, instanceId) {
41075
+ const iid = typeof instanceId === "string" ? instanceId.trim() : "";
41076
+ if (iid) return `iid:${iid}`;
41077
+ if (typeof sessionStartedAtMs === "number" && sessionStartedAtMs > 0) {
41078
+ const ws = String(workspace || "").trim().toLowerCase();
41079
+ return `spawn:${ws}:${sessionStartedAtMs}`;
41080
+ }
41081
+ return "";
41082
+ }
41083
+ function claimAntigravityConversation(uuid, owner, now = Date.now()) {
41084
+ const key2 = normalizeUuid(uuid);
41085
+ if (!key2 || !owner) return false;
41086
+ const existing = claimsByUuid.get(key2);
41087
+ if (existing && existing.owner !== owner && now - existing.refreshedAtMs < CLAIM_STALE_MS) {
41088
+ return false;
41089
+ }
41090
+ claimsByUuid.set(key2, { owner, refreshedAtMs: now });
41091
+ return true;
41092
+ }
41093
+ function isAntigravityConversationClaimedByOther(uuid, owner, now = Date.now()) {
41094
+ const key2 = normalizeUuid(uuid);
41095
+ if (!key2) return false;
41096
+ const existing = claimsByUuid.get(key2);
41097
+ if (!existing) return false;
41098
+ if (existing.owner === owner) return false;
41099
+ return now - existing.refreshedAtMs < CLAIM_STALE_MS;
41100
+ }
41101
+ function releaseAntigravityOwner(owner) {
41102
+ if (!owner) return;
41103
+ for (const [key2, claim] of claimsByUuid) {
41104
+ if (claim.owner === owner) claimsByUuid.delete(key2);
41105
+ }
41106
+ }
41107
+
40791
41108
  // src/providers/cli-provider-instance.ts
40792
41109
  init_chat_message_normalization();
40793
41110
 
@@ -41720,7 +42037,20 @@ var CliProviderInstance = class _CliProviderInstance {
41720
42037
  if (now - at > USER_INPUT_ACK_DEDUP_WINDOW_MS) this.recentUserInputAcks.delete(key2);
41721
42038
  }
41722
42039
  }
42040
+ /**
42041
+ * Owner token for this session in the antigravity conversation-claim
42042
+ * registry. Derived identically to the dispatcher's read-side token
42043
+ * (workspace + spawn time) so the claims the dispatcher records under this
42044
+ * session are the ones dispose() releases.
42045
+ */
42046
+ antigravityClaimOwner() {
42047
+ return antigravityOwnerToken(this.workingDir, this.startedAt);
42048
+ }
41723
42049
  dispose() {
42050
+ if (this.type === "antigravity-cli") {
42051
+ const owner = this.antigravityClaimOwner();
42052
+ if (owner) releaseAntigravityOwner(owner);
42053
+ }
41724
42054
  this.adapter.shutdown();
41725
42055
  this.monitor.reset();
41726
42056
  if (this.autoApproveSettleTimer) {
@@ -42475,12 +42805,21 @@ var CliProviderInstance = class _CliProviderInstance {
42475
42805
  if (this.isMeshWorkerSession()) {
42476
42806
  traceMeshEventStage("fired", this.meshTraceCtx(), `${reason} (source=${fcEvidenceSource})`);
42477
42807
  }
42808
+ if (this.completionTraceOn()) this.recordCompletionGateTrace("synth-fire", {
42809
+ path: "startup_grace_fast_collapse",
42810
+ reason,
42811
+ evidenceSource: fcEvidenceSource,
42812
+ hadFinalSummary: !!fcFinalSummary,
42813
+ missingEvidence,
42814
+ evidenceLevel: "weak"
42815
+ });
42478
42816
  this.pushEvent({
42479
42817
  event: "agent:generating_completed",
42480
42818
  chatTitle,
42481
42819
  duration: 0,
42482
42820
  timestamp: now,
42483
42821
  finalSummary: fcFinalSummary,
42822
+ evidenceLevel: "weak",
42484
42823
  completionDiagnostic: {
42485
42824
  reason,
42486
42825
  finalAssistantEvidenceSource: fcEvidenceSource,
@@ -43207,6 +43546,10 @@ ${effect.notification.body || ""}`.trim();
43207
43546
  const previousHistorySessionId = this.providerSessionId || this.instanceId;
43208
43547
  const previousProviderSessionId = this.providerSessionId;
43209
43548
  this.providerSessionId = nextSessionId;
43549
+ if (this.type === "antigravity-cli") {
43550
+ const owner = this.antigravityClaimOwner();
43551
+ if (owner) claimAntigravityConversation(nextSessionId, owner);
43552
+ }
43210
43553
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
43211
43554
  this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
43212
43555
  if (this.shouldHydrateExistingProviderHistory()) {
@@ -47083,6 +47426,51 @@ function extractUserPrompt(payload) {
47083
47426
  if (!text) return "";
47084
47427
  return extractUserRequestContent(text);
47085
47428
  }
47429
+ function extractModelReasoning(payload) {
47430
+ const inner = firstLenField(payload, 20);
47431
+ if (!inner) return "";
47432
+ const reasoning = firstLenField(inner, 3);
47433
+ if (!reasoning || !looksLikeText(reasoning)) return "";
47434
+ return reasoning.toString("utf-8").trim();
47435
+ }
47436
+ function topLevelFieldNumbers(payload) {
47437
+ return decodeProtoFields(payload).map((f) => f.field);
47438
+ }
47439
+ var MIN_RECOVERED_MESSAGE_CHARS = 12;
47440
+ function extractUtf8TextRuns(buf) {
47441
+ if (buf.length === 0) return [];
47442
+ const decoded = buf.toString("utf-8");
47443
+ const parts = decoded.split(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F\uFFFD]+/);
47444
+ const runs = [];
47445
+ for (const part of parts) {
47446
+ const trimmed = part.trim();
47447
+ if (trimmed.length >= MIN_PRINTABLE_RUN) runs.push(trimmed);
47448
+ }
47449
+ return runs;
47450
+ }
47451
+ function isPlausibleMessageText(s2) {
47452
+ if (s2.length < MIN_RECOVERED_MESSAGE_CHARS) return false;
47453
+ if (!/[A-Za-zÀ-￿]/.test(s2)) return false;
47454
+ if (/^(file:\/\/|[A-Za-z]:[\\/]|\/[A-Za-z0-9._-]+\/)/.test(s2)) return false;
47455
+ if ((s2.match(/ /g) ?? []).length < 2) return false;
47456
+ if (/[[{]\s*"/.test(s2)) return false;
47457
+ const structural = (s2.match(/[{}[\]":\\]/g) ?? []).length;
47458
+ if (structural / s2.length > 0.12) return false;
47459
+ return true;
47460
+ }
47461
+ function recoverMessageText(payload, excludeTexts) {
47462
+ const exclusions = excludeTexts.map((t) => t.trim()).filter(Boolean);
47463
+ let best = "";
47464
+ for (const run of extractUtf8TextRuns(payload)) {
47465
+ const candidate = stripAnswerMarker(run).trim();
47466
+ if (!isPlausibleMessageText(candidate)) continue;
47467
+ if (exclusions.some((e) => e === candidate || e.includes(candidate) || candidate.includes(e))) {
47468
+ continue;
47469
+ }
47470
+ if (candidate.length > best.length) best = candidate;
47471
+ }
47472
+ return best;
47473
+ }
47086
47474
  function isSqliteBusyError(err) {
47087
47475
  if (!err) return false;
47088
47476
  const code = err.code;
@@ -47161,8 +47549,23 @@ function parseConversationDb(filePath, sessionId, workspace) {
47161
47549
  if (!payload || !Buffer.isBuffer(payload) || payload.length === 0) continue;
47162
47550
  const receivedAt = baseTs + messages.length;
47163
47551
  if (row.step_type === AGY_STEP_TYPE_USER) {
47164
- const content = extractUserPrompt(payload);
47165
- if (!content) continue;
47552
+ let content = extractUserPrompt(payload);
47553
+ if (!content) {
47554
+ const recovered = extractUserRequestContent(recoverMessageText(payload, []));
47555
+ if (recovered) {
47556
+ content = recovered;
47557
+ LOG.debug(
47558
+ "NativeHistory",
47559
+ `antigravity .db ${path31.basename(filePath)} step ${row.idx} (type ${row.step_type}): user prompt absent at field 19; recovered ${content.length} chars via printable-run fallback \u2014 possible step_payload schema drift`
47560
+ );
47561
+ } else {
47562
+ LOG.debug(
47563
+ "NativeHistory",
47564
+ `antigravity .db ${path31.basename(filePath)} step ${row.idx} (type ${row.step_type}) dropped: no user prompt text (payload ${payload.length}B, top-level fields [${topLevelFieldNumbers(payload).join(",")}])`
47565
+ );
47566
+ continue;
47567
+ }
47568
+ }
47166
47569
  const msg = {
47167
47570
  ts: new Date(receivedAt).toISOString(),
47168
47571
  receivedAt,
@@ -47175,8 +47578,24 @@ function parseConversationDb(filePath, sessionId, workspace) {
47175
47578
  if (normalizedWorkspace) msg.workspace = normalizedWorkspace;
47176
47579
  messages.push(msg);
47177
47580
  } else if (row.step_type === AGY_STEP_TYPE_MODEL) {
47178
- const content = extractModelAnswer(payload);
47179
- if (!content) continue;
47581
+ let content = extractModelAnswer(payload);
47582
+ if (!content) {
47583
+ const reasoning = extractModelReasoning(payload);
47584
+ const recovered = recoverMessageText(payload, reasoning ? [reasoning] : []);
47585
+ if (recovered) {
47586
+ content = recovered;
47587
+ LOG.debug(
47588
+ "NativeHistory",
47589
+ `antigravity .db ${path31.basename(filePath)} step ${row.idx} (type ${row.step_type}): answer absent at field 20; recovered ${content.length} chars via printable-run fallback \u2014 possible step_payload schema drift`
47590
+ );
47591
+ } else {
47592
+ LOG.debug(
47593
+ "NativeHistory",
47594
+ `antigravity .db ${path31.basename(filePath)} step ${row.idx} (type ${row.step_type}) dropped: no answer text (payload ${payload.length}B, top-level fields [${topLevelFieldNumbers(payload).join(",")}], reasoningOnly=${reasoning ? "yes" : "no"})`
47595
+ );
47596
+ continue;
47597
+ }
47598
+ }
47180
47599
  const msg = {
47181
47600
  ts: new Date(receivedAt).toISOString(),
47182
47601
  receivedAt,
@@ -47422,7 +47841,8 @@ function createNativeHistoryDispatcher(reader) {
47422
47841
  const sessionId = input.sessionId || input.historySessionId || "";
47423
47842
  const requestedProviderSid = input.providerSessionId || "";
47424
47843
  const sessionStartedAtMs = typeof input.sessionStartedAtMs === "number" ? input.sessionStartedAtMs : typeof input.args?.sessionStartedAtMs === "number" ? input.args.sessionStartedAtMs : 0;
47425
- const sourcePath = resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs);
47844
+ const instanceId = typeof input.instanceId === "string" ? input.instanceId : typeof input.args?.instanceId === "string" ? input.args.instanceId : "";
47845
+ const sourcePath = resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs, instanceId);
47426
47846
  if (!sourcePath) return null;
47427
47847
  if (input.forceRefresh === true || input.args?.forceRefresh === true) {
47428
47848
  try {
@@ -47450,14 +47870,14 @@ function createNativeHistoryDispatcher(reader) {
47450
47870
  };
47451
47871
  };
47452
47872
  }
47453
- function resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs) {
47873
+ function resolveSourcePath(reader, workspace, sessionId, sessionStartedAtMs, instanceId) {
47454
47874
  switch (reader) {
47455
47875
  case "claude-cli":
47456
47876
  return resolveClaudePath(workspace, sessionId);
47457
47877
  case "codex-cli":
47458
47878
  return resolveCodexPath(workspace, sessionId, sessionStartedAtMs);
47459
47879
  case "antigravity-cli":
47460
- return resolveAntigravityPath(workspace, sessionId);
47880
+ return resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instanceId);
47461
47881
  case "hermes-cli":
47462
47882
  return resolveHermesPath(workspace, sessionId);
47463
47883
  }
@@ -47572,27 +47992,73 @@ function resolveRealPath(value) {
47572
47992
  return value;
47573
47993
  }
47574
47994
  }
47575
- function resolveAntigravityPath(workspace, sessionId) {
47576
- void workspace;
47995
+ var AGY_SPAWN_CLAIM_GRACE_MS = 2e3;
47996
+ function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instanceId) {
47577
47997
  const agyRoot = path33.join(os24.homedir(), ".gemini", "antigravity-cli");
47998
+ const owner = antigravityOwnerToken(workspace, sessionStartedAtMs, instanceId);
47578
47999
  if (sessionId && isUuidLikeSessionId2(sessionId)) {
47579
48000
  const dbPath = path33.join(agyRoot, "conversations", `${sessionId}.db`);
47580
- if (fs24.existsSync(dbPath)) return dbPath;
48001
+ if (fs24.existsSync(dbPath)) {
48002
+ if (owner) claimAntigravityConversation(sessionId, owner);
48003
+ return dbPath;
48004
+ }
47581
48005
  }
47582
48006
  const brainRoot2 = path33.join(agyRoot, "brain");
47583
48007
  if (fs24.existsSync(brainRoot2)) {
47584
- const cutoff = Date.now() - RECENT_WINDOW_MS;
47585
- const entries = fs24.readdirSync(brainRoot2, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => ({ p: path33.join(brainRoot2, e.name), mtime: safeMtime(path33.join(brainRoot2, e.name)) })).filter((e) => e.mtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
48008
+ const cutoff = spawnAwareCutoff(sessionStartedAtMs);
48009
+ const entries = fs24.readdirSync(brainRoot2, { withFileTypes: true }).filter((e) => e.isDirectory() && isUuidLikeSessionId2(e.name)).filter((e) => !isAntigravityConversationClaimedByOther(e.name, owner)).map((e) => ({ uuid: e.name, p: path33.join(brainRoot2, e.name), mtime: safeMtime(path33.join(brainRoot2, e.name)) })).filter((e) => e.mtime >= cutoff).sort((a, b) => b.mtime - a.mtime);
47586
48010
  for (const e of entries) {
47587
48011
  const t = path33.join(e.p, ".system_generated", "logs", "transcript.jsonl");
47588
- if (fs24.existsSync(t) && safeSize(t) > 0) return t;
48012
+ if (fs24.existsSync(t) && safeSize(t) > 0) {
48013
+ if (owner) claimAntigravityConversation(e.uuid, owner);
48014
+ return t;
48015
+ }
47589
48016
  }
47590
48017
  }
47591
48018
  const convRoot = path33.join(agyRoot, "conversations");
47592
- const newestDb = newestRecentFile2(convRoot, /^[0-9a-f-]+\.db$/i);
47593
- if (newestDb) return newestDb;
48019
+ const picked = pickUnboundConversationDb(convRoot, sessionStartedAtMs, owner);
48020
+ if (picked) {
48021
+ if (owner) claimAntigravityConversation(picked.uuid, owner);
48022
+ return picked.path;
48023
+ }
47594
48024
  return null;
47595
48025
  }
48026
+ function pickUnboundConversationDb(convRoot, sessionFloorMs, owner) {
48027
+ let entries = [];
48028
+ try {
48029
+ entries = fs24.readdirSync(convRoot, { withFileTypes: true });
48030
+ } catch {
48031
+ return null;
48032
+ }
48033
+ const recencyCutoff = Date.now() - RECENT_WINDOW_MS;
48034
+ const candidates = [];
48035
+ for (const entry of entries) {
48036
+ if (!entry.isFile()) continue;
48037
+ const match = /^([0-9a-f-]+)\.db$/i.exec(entry.name);
48038
+ if (!match || !isUuidLikeSessionId2(match[1])) continue;
48039
+ const uuid = match[1];
48040
+ if (isAntigravityConversationClaimedByOther(uuid, owner)) continue;
48041
+ const p = path33.join(convRoot, entry.name);
48042
+ const mtime = safeMtime(p);
48043
+ if (mtime < recencyCutoff) continue;
48044
+ candidates.push({ path: p, uuid, mtime, birth: safeBirthtime(p) });
48045
+ }
48046
+ if (candidates.length === 0) return null;
48047
+ if (sessionFloorMs > 0) {
48048
+ const floor = sessionFloorMs - AGY_SPAWN_CLAIM_GRACE_MS;
48049
+ const own = candidates.filter((c) => (c.birth > 0 ? c.birth : c.mtime) >= floor);
48050
+ if (own.length === 0) return null;
48051
+ own.sort((a, b) => (a.birth || a.mtime) - (b.birth || b.mtime));
48052
+ return { path: own[0].path, uuid: own[0].uuid };
48053
+ }
48054
+ candidates.sort((a, b) => b.mtime - a.mtime);
48055
+ return { path: candidates[0].path, uuid: candidates[0].uuid };
48056
+ }
48057
+ function spawnAwareCutoff(sessionStartedAtMs) {
48058
+ const recency = Date.now() - RECENT_WINDOW_MS;
48059
+ if (sessionStartedAtMs > 0) return Math.max(recency, sessionStartedAtMs - AGY_SPAWN_CLAIM_GRACE_MS);
48060
+ return recency;
48061
+ }
47596
48062
  function resolveHermesPath(workspace, sessionId) {
47597
48063
  void workspace;
47598
48064
  void sessionId;
@@ -47649,6 +48115,15 @@ function safeMtime(p) {
47649
48115
  return 0;
47650
48116
  }
47651
48117
  }
48118
+ function safeBirthtime(p) {
48119
+ try {
48120
+ const st = fs24.statSync(p);
48121
+ const birth = Math.floor(st.birthtimeMs);
48122
+ return birth > 0 ? birth : Math.floor(st.mtimeMs);
48123
+ } catch {
48124
+ return 0;
48125
+ }
48126
+ }
47652
48127
  function safeSize(p) {
47653
48128
  try {
47654
48129
  return fs24.statSync(p).size;
@@ -53184,6 +53659,7 @@ function getRecentCommands(count = 50) {
53184
53659
  cleanOldFiles();
53185
53660
 
53186
53661
  // src/commands/router.ts
53662
+ init_debug_trace();
53187
53663
  init_mesh_host_ownership();
53188
53664
  init_mesh_work_queue();
53189
53665
  import * as fs33 from "fs";
@@ -54476,9 +54952,10 @@ async function resolveProviderTypeFromPriority(args) {
54476
54952
 
54477
54953
  // src/commands/router-refine.ts
54478
54954
  init_logger();
54479
- import { execFileSync as execFileSync8 } from "child_process";
54955
+ init_debug_trace();
54480
54956
  init_dist();
54481
54957
  init_mesh_events();
54958
+ import { execFileSync as execFileSync8 } from "child_process";
54482
54959
 
54483
54960
  // src/mesh/mesh-refine-batch.ts
54484
54961
  init_resolve_executable();
@@ -55262,6 +55739,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
55262
55739
  commit: gitlink.commit,
55263
55740
  reachable: false
55264
55741
  };
55742
+ let submoduleDefaultBranch = "main";
55265
55743
  try {
55266
55744
  if (!fs30.existsSync(submodulePath)) {
55267
55745
  entry.error = `Submodule checkout missing at ${gitlink.path}`;
@@ -55314,9 +55792,14 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
55314
55792
  entries.push(entry);
55315
55793
  continue;
55316
55794
  }
55317
- entry.remoteMainBranch = "main";
55795
+ submoduleDefaultBranch = await resolveSubmoduleDefaultBranch({
55796
+ submoduleRepoPath: submodulePath,
55797
+ superprojectWorkspace: repoRoot,
55798
+ submodulePath: gitlink.path
55799
+ });
55800
+ entry.remoteMainBranch = submoduleDefaultBranch;
55318
55801
  try {
55319
- await verifyRemoteMainContainsCommit(submodulePath, gitlink.commit, "main");
55802
+ await verifyRemoteMainContainsCommit(submodulePath, gitlink.commit, submoduleDefaultBranch);
55320
55803
  entry.fetchedFromOrigin = true;
55321
55804
  entry.remoteReachable = true;
55322
55805
  entry.remoteMainReachable = true;
@@ -55326,17 +55809,17 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
55326
55809
  entry.remoteMainReachable = false;
55327
55810
  entry.publishRequired = true;
55328
55811
  const details = truncateValidationOutput(e?.stderr || e?.message || String(e));
55329
- entry.error = `Submodule remote main reachability check failed for origin/main: ${details}`;
55812
+ entry.error = `Submodule remote main reachability check failed for origin/${submoduleDefaultBranch}: ${details}`;
55330
55813
  if (options.allowAutoPublishSubmoduleMainCommits === true && entry.localReachable === true) {
55331
55814
  entry.autoPublishAllowed = true;
55332
55815
  entry.autoPublishAttempted = true;
55333
55816
  try {
55334
- const publish = await publishCommitToRemoteMain(submodulePath, gitlink.commit, "main");
55817
+ const publish = await publishCommitToRemoteMain(submodulePath, gitlink.commit, submoduleDefaultBranch);
55335
55818
  entry.autoPublishRefspec = publish.refspec;
55336
55819
  entry.publishStdout = truncateValidationOutput(publish.stdout);
55337
55820
  entry.publishStderr = truncateValidationOutput(publish.stderr);
55338
55821
  entry.autoPublishSucceeded = true;
55339
- await verifyRemoteMainContainsCommit(submodulePath, gitlink.commit, "main");
55822
+ await verifyRemoteMainContainsCommit(submodulePath, gitlink.commit, submoduleDefaultBranch);
55340
55823
  entry.fetchedFromOrigin = true;
55341
55824
  entry.remoteReachable = true;
55342
55825
  entry.remoteMainReachable = true;
@@ -55348,12 +55831,12 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
55348
55831
  entry.autoPublishSucceeded = false;
55349
55832
  entry.autoPublishVerified = false;
55350
55833
  const publishDetails = truncateValidationOutput(publishError?.stderr || publishError?.message || String(publishError));
55351
- entry.error = `Submodule auto-publish to origin/main failed or could not be verified: ${publishDetails}`;
55834
+ entry.error = `Submodule auto-publish to origin/${submoduleDefaultBranch} failed or could not be verified: ${publishDetails}`;
55352
55835
  }
55353
55836
  } else if (options.allowAutoPublishSubmoduleMainCommits === true) {
55354
55837
  entry.autoPublishAllowed = true;
55355
55838
  entry.autoPublishAttempted = false;
55356
- entry.autoPublishSkippedReason = entry.autoPublishSkippedReason || "candidate commit is not reachable in the source checkout or worktree submodule, so Refinery cannot push it to origin/main";
55839
+ entry.autoPublishSkippedReason = entry.autoPublishSkippedReason || `candidate commit is not reachable in the source checkout or worktree submodule, so Refinery cannot push it to origin/${submoduleDefaultBranch}`;
55357
55840
  }
55358
55841
  }
55359
55842
  } catch (e) {
@@ -55361,7 +55844,7 @@ async function runMeshRefineSubmoduleReachabilityGate(repoRoot, mergedTree, opti
55361
55844
  entry.remoteMainReachable = false;
55362
55845
  entry.publishRequired = true;
55363
55846
  const details = truncateValidationOutput(e?.stderr || e?.message || String(e));
55364
- entry.error = `Submodule remote main reachability check failed for origin/main: ${details}`;
55847
+ entry.error = `Submodule remote main reachability check failed for origin/${submoduleDefaultBranch}: ${details}`;
55365
55848
  }
55366
55849
  } catch (e) {
55367
55850
  entry.error = truncateValidationOutput(e?.message || String(e));
@@ -58696,6 +59179,7 @@ init_build_info();
58696
59179
  init_normalize();
58697
59180
  init_logger();
58698
59181
  init_debug_config();
59182
+ init_debug_trace();
58699
59183
 
58700
59184
  // src/ipc-protocol.ts
58701
59185
  var DEFAULT_DAEMON_PORT = 19222;
@@ -66660,6 +67144,7 @@ var V1_ALL_PRIMITIVES = Object.freeze(
66660
67144
  );
66661
67145
  var V1_CONTRACT_VERSION = "1.0.0";
66662
67146
  export {
67147
+ ALWAYS_ON_TRACE_CATEGORIES,
66663
67148
  AcpProviderInstance,
66664
67149
  AgentStreamPoller,
66665
67150
  BUILTIN_CHAT_MESSAGE_KINDS,
@@ -66891,6 +67376,7 @@ export {
66891
67376
  installGlobalInterceptor,
66892
67377
  interactivePromptFromClaudeAskUserQuestion,
66893
67378
  isActivityChatMessage,
67379
+ isAlwaysOnTraceCategory,
66894
67380
  isBuiltinChatMessageKind,
66895
67381
  isCdpConnected,
66896
67382
  isExtensionInstalled,