@adhdev/daemon-core 0.9.82-rc.407 → 0.9.82-rc.409

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.mjs CHANGED
@@ -394,10 +394,10 @@ function readInjected(value) {
394
394
  }
395
395
  function getDaemonBuildInfo() {
396
396
  if (cached) return cached;
397
- const commit = readInjected(true ? "bfd7d9b1d38a7d1f4709fbad2627c56b5a1ae342" : void 0) ?? "unknown";
398
- const commitShort = readInjected(true ? "bfd7d9b1" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
399
- const version = readInjected(true ? "0.9.82-rc.407" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
400
- const builtAt = readInjected(true ? "2026-06-28T06:12:15.473Z" : void 0);
397
+ const commit = readInjected(true ? "69cd9c459ec9efafe19a05f66899bb791d6e0561" : void 0) ?? "unknown";
398
+ const commitShort = readInjected(true ? "69cd9c45" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
399
+ const version = readInjected(true ? "0.9.82-rc.409" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
400
+ const builtAt = readInjected(true ? "2026-06-28T09:03:15.861Z" : void 0);
401
401
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
402
402
  return cached;
403
403
  }
@@ -650,6 +650,11 @@ var init_change_impact_config = __esm({
650
650
  });
651
651
 
652
652
  // src/git/git-status.ts
653
+ function statusCacheKey(workspace, options) {
654
+ const includeSubmodules = options.includeSubmodules !== false;
655
+ const refreshUpstream = options.refreshUpstream === true;
656
+ return `${workspace}\0sub=${includeSubmodules ? 1 : 0}\0up=${refreshUpstream ? 1 : 0}`;
657
+ }
653
658
  function isTransientGitFailure(error) {
654
659
  return error.reason === "timeout" || error.reason === "git_command_failed";
655
660
  }
@@ -657,15 +662,22 @@ async function getGitRepoStatus(workspace, options = {}) {
657
662
  const lastCheckedAt = Date.now();
658
663
  const includeSubmodules = options.includeSubmodules !== false;
659
664
  const effectiveOptions = options.timeoutMs === void 0 ? { ...options, timeoutMs: GIT_STATUS_TIMEOUT_MS } : options;
665
+ const cacheKey = statusCacheKey(workspace, options);
666
+ if (!options.forceFresh) {
667
+ const cached3 = lastKnownGoodStatus.get(cacheKey);
668
+ if (cached3 && lastCheckedAt - cached3.cachedAt < GIT_STATUS_CACHE_TTL_MS) {
669
+ return cached3.status;
670
+ }
671
+ }
660
672
  try {
661
673
  const repo = await resolveGitRepository(workspace, effectiveOptions);
662
674
  const status = await collectGitRepoStatus(repo, includeSubmodules, lastCheckedAt, effectiveOptions);
663
- lastKnownGoodStatus.set(workspace, status);
675
+ lastKnownGoodStatus.set(cacheKey, { status, cachedAt: lastCheckedAt });
664
676
  return status;
665
677
  } catch (error) {
666
678
  const gitError = error instanceof GitCommandError ? error : new GitCommandError("git_command_failed", "Failed to read Git status", { cause: error });
667
679
  if (isTransientGitFailure(gitError)) {
668
- const cached3 = lastKnownGoodStatus.get(workspace);
680
+ const cached3 = lastKnownGoodStatus.get(cacheKey)?.status;
669
681
  if (cached3) {
670
682
  return {
671
683
  ...cached3,
@@ -684,19 +696,25 @@ async function collectGitRepoStatus(repo, includeSubmodules, lastCheckedAt, opti
684
696
  let upstreamProbe = getInitialUpstreamProbe(parsed);
685
697
  if (options.refreshUpstream) {
686
698
  upstreamProbe = await refreshTrackedUpstream(repo, parsed, options);
687
- if (upstreamProbe.upstreamStatus === "fresh") {
699
+ if (upstreamProbe.upstreamStatus === "fresh" && upstreamProbe.didFetch) {
688
700
  parsed = await readPorcelainStatus(repo, options);
689
701
  }
690
702
  }
691
703
  const head = await readHead(repo, options);
692
704
  const stashCount = await readStashCount(repo, options);
693
705
  let submodules;
706
+ let submoduleHeadOids = /* @__PURE__ */ new Map();
694
707
  if (includeSubmodules) {
695
- submodules = await getSubmoduleStatuses(repo, options);
708
+ const subResult = await getSubmoduleStatuses(repo, options);
709
+ submodules = subResult.submodules;
710
+ submoduleHeadOids = subResult.headOidByPath;
696
711
  }
697
712
  const submoduleDirty = (submodules || []).some((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error);
698
713
  const dirty = parsed.staged + parsed.modified + parsed.untracked + parsed.deleted + parsed.renamed > 0 || parsed.conflictFiles.length > 0 || stashCount > 0 || submoduleDirty;
699
- const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options);
714
+ const daemonBuildBehind = await detectDaemonBuildBehind(repo, submodules, options, {
715
+ rootHeadOid: parsed.headOid,
716
+ submoduleHeadOids
717
+ });
700
718
  return {
701
719
  workspace: repo.workspace,
702
720
  repoRoot: repo.repoRoot,
@@ -799,25 +817,50 @@ function resolveChangeImpactConfigForRepo(repoRoot, options) {
799
817
  changeImpactConfigCache.set(repoRoot, { sourceKey: loaded.sourceKey, config });
800
818
  return { config, sourceKey: loaded.sourceKey };
801
819
  }
802
- async function detectDaemonBuildBehind(repo, submodules, options) {
820
+ async function detectDaemonBuildBehind(repo, submodules, options, headOids = { rootHeadOid: null, submoduleHeadOids: /* @__PURE__ */ new Map() }) {
803
821
  const build = options.daemonBuildInfo ?? getDaemonBuildInfo();
804
822
  if (!build.commit || build.commit === "unknown") return void 0;
805
823
  const { config, sourceKey: configKey } = resolveChangeImpactConfigForRepo(repo.repoRoot, options);
806
824
  const policy = resolveChangeImpactPolicy(config);
807
825
  const scopes = [
808
- { scope: "root", repoPath: repo.repoRoot || repo.workspace }
826
+ { scope: "root", repoPath: repo.repoRoot || repo.workspace, knownHeadOid: headOids.rootHeadOid }
809
827
  ];
810
828
  for (const sub of submodules || []) {
811
- if (sub.repoPath && !sub.error) scopes.push({ scope: sub.path, repoPath: sub.repoPath });
829
+ if (sub.repoPath && !sub.error) {
830
+ scopes.push({ scope: sub.path, repoPath: sub.repoPath, knownHeadOid: headOids.submoduleHeadOids.get(sub.path) ?? null });
831
+ }
812
832
  }
813
- for (const { scope, repoPath } of scopes) {
833
+ for (const { scope, repoPath, knownHeadOid } of scopes) {
814
834
  try {
815
- await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
816
- const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
817
- const head = headResult.stdout.trim();
818
- if (!head || head === build.commit) continue;
819
- await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
835
+ let head = knownHeadOid;
836
+ const ancestryKey = head ? `${repoPath}::${build.commit}::${head}` : null;
837
+ if (ancestryKey) {
838
+ const cachedVerdict = buildBehindAncestryCache.get(ancestryKey);
839
+ if (cachedVerdict === false) continue;
840
+ if (cachedVerdict === void 0) {
841
+ if (head === build.commit) {
842
+ buildBehindAncestryCache.set(ancestryKey, false);
843
+ continue;
844
+ }
845
+ await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
846
+ try {
847
+ await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
848
+ } catch {
849
+ buildBehindAncestryCache.set(ancestryKey, false);
850
+ continue;
851
+ }
852
+ buildBehindAncestryCache.set(ancestryKey, true);
853
+ }
854
+ } else {
855
+ await runGit(repoPath, ["cat-file", "-e", `${build.commit}^{commit}`], options);
856
+ const headResult = await runGit(repoPath, ["rev-parse", "HEAD"], options);
857
+ head = headResult.stdout.trim();
858
+ if (!head || head === build.commit) continue;
859
+ await runGit(repoPath, ["merge-base", "--is-ancestor", build.commit, "HEAD"], options);
860
+ buildBehindAncestryCache.set(`${repoPath}::${build.commit}::${head}`, true);
861
+ }
820
862
  const evalKey = `${repoPath}\0${build.commit}\0${head}\0${configKey}`;
863
+ if (!head) continue;
821
864
  let evaluated = changeImpactEvalCache.get(evalKey);
822
865
  if (!evaluated) {
823
866
  evaluated = await classifyDaemonBuildChange(repoPath, build.commit, options, policy);
@@ -859,6 +902,15 @@ async function refreshTrackedUpstream(repo, parsed, options) {
859
902
  if (!parsed.upstream || !parsed.branch) {
860
903
  return { upstreamStatus: "no_upstream" };
861
904
  }
905
+ const now = Date.now();
906
+ const lastFetch = upstreamFetchedAt.get(repo.workspace);
907
+ if (!options.forceFresh && lastFetch !== void 0 && now - lastFetch < GIT_FETCH_THROTTLE_MS) {
908
+ return {
909
+ upstreamStatus: "fresh",
910
+ upstreamFetchedAt: lastFetch,
911
+ didFetch: false
912
+ };
913
+ }
862
914
  const remoteName = await readBranchRemote(repo, parsed.branch, options) ?? inferRemoteName(parsed.upstream);
863
915
  if (!remoteName) {
864
916
  return {
@@ -868,9 +920,12 @@ async function refreshTrackedUpstream(repo, parsed, options) {
868
920
  }
869
921
  try {
870
922
  await runGit(repo, ["fetch", "--quiet", "--prune", "--no-tags", remoteName], options);
923
+ const fetchedAt = Date.now();
924
+ upstreamFetchedAt.set(repo.workspace, fetchedAt);
871
925
  return {
872
926
  upstreamStatus: "fresh",
873
- upstreamFetchedAt: Date.now()
927
+ upstreamFetchedAt: fetchedAt,
928
+ didFetch: true
874
929
  };
875
930
  } catch (error) {
876
931
  return {
@@ -903,6 +958,7 @@ function formatGitError(error) {
903
958
  function parsePorcelainV2Status(output) {
904
959
  const parsed = {
905
960
  branch: null,
961
+ headOid: null,
906
962
  upstream: null,
907
963
  ahead: 0,
908
964
  behind: 0,
@@ -915,6 +971,11 @@ function parsePorcelainV2Status(output) {
915
971
  };
916
972
  for (const line of output.split("\n")) {
917
973
  if (!line) continue;
974
+ if (line.startsWith("# branch.oid ")) {
975
+ const oid = line.slice("# branch.oid ".length).trim();
976
+ parsed.headOid = oid && oid !== "(initial)" && /^[0-9a-f]{7,64}$/.test(oid) ? oid : null;
977
+ continue;
978
+ }
918
979
  if (line.startsWith("# branch.head ")) {
919
980
  const branch = line.slice("# branch.head ".length).trim();
920
981
  parsed.branch = branch && branch !== "(detached)" ? branch : null;
@@ -1012,25 +1073,27 @@ function emptyStatus(workspace, lastCheckedAt, error) {
1012
1073
  };
1013
1074
  }
1014
1075
  async function getSubmoduleStatuses(repo, options) {
1015
- if (!repo.repoRoot) return [];
1076
+ if (!repo.repoRoot) return { submodules: [], headOidByPath: /* @__PURE__ */ new Map() };
1016
1077
  try {
1017
- const submodules = await deriveSubmoduleGitlinkStatuses(repo, options);
1078
+ const { submodules, headOidByPath } = await deriveSubmoduleGitlinkStatuses(repo, options);
1018
1079
  await Promise.all(submodules.map((submodule) => enrichSubmoduleWorktreeStatus(repo, submodule, options)));
1019
- return submodules;
1080
+ return { submodules, headOidByPath };
1020
1081
  } catch {
1021
- return [];
1082
+ return { submodules: [], headOidByPath: /* @__PURE__ */ new Map() };
1022
1083
  }
1023
1084
  }
1024
1085
  async function deriveSubmoduleGitlinkStatuses(repo, options) {
1025
- if (!repo.repoRoot) return [];
1086
+ if (!repo.repoRoot) return { submodules: [], headOidByPath: /* @__PURE__ */ new Map() };
1026
1087
  const paths = await readSubmodulePaths(repo, options);
1027
1088
  const ignoreSet = new Set(options.submoduleIgnorePaths || []);
1028
1089
  const lastCheckedAt = Date.now();
1090
+ const headOidByPath = /* @__PURE__ */ new Map();
1029
1091
  const entries = await Promise.all(
1030
1092
  paths.filter((path43) => !ignoreSet.has(path43)).map(async (path43) => {
1031
1093
  const repoPath = repo.repoRoot + "/" + path43;
1032
1094
  const expected = await readGitlinkExpectedSha(repo, path43, options);
1033
1095
  const actual = await readSubmoduleHeadSha(repo, repoPath, options);
1096
+ if (actual) headOidByPath.set(path43, actual);
1034
1097
  const outOfSync = actual === null ? true : expected !== null && expected !== actual;
1035
1098
  return {
1036
1099
  path: path43,
@@ -1044,7 +1107,7 @@ async function deriveSubmoduleGitlinkStatuses(repo, options) {
1044
1107
  };
1045
1108
  })
1046
1109
  );
1047
- return entries;
1110
+ return { submodules: entries, headOidByPath };
1048
1111
  }
1049
1112
  async function readSubmodulePaths(repo, options) {
1050
1113
  if (!repo.repoRoot) return [];
@@ -1101,16 +1164,20 @@ async function enrichSubmoduleWorktreeStatus(repo, submodule, options) {
1101
1164
  submodule.error = formatGitError(error);
1102
1165
  }
1103
1166
  }
1104
- var lastKnownGoodStatus, changeImpactEvalCache, changeImpactConfigCache, DEFAULT_DAEMON_RUNTIME_PACKAGES, DEFAULT_WEB_ONLY_PACKAGES, DEFAULT_IMPACT_TARGETS;
1167
+ var GIT_STATUS_CACHE_TTL_MS, lastKnownGoodStatus, changeImpactEvalCache, changeImpactConfigCache, buildBehindAncestryCache, GIT_FETCH_THROTTLE_MS, upstreamFetchedAt, DEFAULT_DAEMON_RUNTIME_PACKAGES, DEFAULT_WEB_ONLY_PACKAGES, DEFAULT_IMPACT_TARGETS;
1105
1168
  var init_git_status = __esm({
1106
1169
  "src/git/git-status.ts"() {
1107
1170
  "use strict";
1108
1171
  init_git_executor();
1109
1172
  init_build_info();
1110
1173
  init_change_impact_config();
1174
+ GIT_STATUS_CACHE_TTL_MS = 1500;
1111
1175
  lastKnownGoodStatus = /* @__PURE__ */ new Map();
1112
1176
  changeImpactEvalCache = /* @__PURE__ */ new Map();
1113
1177
  changeImpactConfigCache = /* @__PURE__ */ new Map();
1178
+ buildBehindAncestryCache = /* @__PURE__ */ new Map();
1179
+ GIT_FETCH_THROTTLE_MS = 3e4;
1180
+ upstreamFetchedAt = /* @__PURE__ */ new Map();
1114
1181
  DEFAULT_DAEMON_RUNTIME_PACKAGES = [
1115
1182
  "daemon-core",
1116
1183
  "daemon-standalone",
@@ -2989,7 +3056,7 @@ function normalizeGitStatus(status, node, options) {
2989
3056
  const repoRoot = readString3(status.repoRoot, status.repo_root, node.repoRoot, node.repo_root, status.workspace, node.workspace) || void 0;
2990
3057
  const submodules = readGitSubmodules(status.submodules, repoRoot);
2991
3058
  const upstreamStatus = readString3(status.upstreamStatus, status.upstream_status);
2992
- const upstreamFetchedAt = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
3059
+ const upstreamFetchedAt2 = readNumber(status.upstreamFetchedAt, status.upstream_fetched_at);
2993
3060
  const upstreamFetchError = readString3(status.upstreamFetchError, status.upstream_fetch_error);
2994
3061
  const error = readString3(status.error);
2995
3062
  const staged = readNumber(status.staged) ?? 0;
@@ -3006,7 +3073,7 @@ function normalizeGitStatus(status, node, options) {
3006
3073
  headMessage: readString3(status.headMessage) ?? null,
3007
3074
  upstream: readString3(status.upstream) ?? null,
3008
3075
  upstreamStatus: upstreamStatus ?? "unchecked",
3009
- ...upstreamFetchedAt !== void 0 ? { upstreamFetchedAt } : {},
3076
+ ...upstreamFetchedAt2 !== void 0 ? { upstreamFetchedAt: upstreamFetchedAt2 } : {},
3010
3077
  ...upstreamFetchError ? { upstreamFetchError } : {},
3011
3078
  ahead: readNumber(status.ahead) ?? 0,
3012
3079
  behind: readNumber(status.behind) ?? 0,
@@ -4678,6 +4745,7 @@ __export(mesh_work_queue_exports, {
4678
4745
  getQueue: () => getQueue,
4679
4746
  hasPendingDependents: () => hasPendingDependents,
4680
4747
  insertDirectDispatch: () => insertDirectDispatch,
4748
+ isTaskReadonly: () => isTaskReadonly,
4681
4749
  markStaleDirectDispatches: () => markStaleDirectDispatches,
4682
4750
  nodeSatisfiesRequiredTags: () => nodeSatisfiesRequiredTags,
4683
4751
  normalizeMeshCapabilityTags: () => normalizeMeshCapabilityTags,
@@ -4694,6 +4762,10 @@ __export(mesh_work_queue_exports, {
4694
4762
  validateMeshTaskModeRequest: () => validateMeshTaskModeRequest
4695
4763
  });
4696
4764
  import { randomUUID as randomUUID6 } from "crypto";
4765
+ function isTaskReadonly(task) {
4766
+ if (!task) return false;
4767
+ return task.readonly === true || task.taskMode === "live_debug_readonly";
4768
+ }
4697
4769
  function hasNegationBefore(text, matchIndex) {
4698
4770
  const before = text.slice(0, matchIndex);
4699
4771
  const clauseStart = Math.max(
@@ -4879,13 +4951,11 @@ function normalizeMeshTaskMode(value) {
4879
4951
  const normalized = value.trim();
4880
4952
  return MESH_TASK_MODES.includes(normalized) ? normalized : void 0;
4881
4953
  }
4882
- function validateMeshTaskModeRequest(mode, message) {
4954
+ function validateMeshTaskModeRequest(mode, message, readonly) {
4883
4955
  const taskMode = normalizeMeshTaskMode(mode);
4884
- if (!taskMode) {
4885
- return { valid: true, violations: [] };
4886
- }
4887
- if (taskMode !== "live_debug_readonly") {
4888
- return { valid: true, taskMode, violations: [] };
4956
+ const isReadonly = isTaskReadonly({ readonly, taskMode });
4957
+ if (!isReadonly) {
4958
+ return taskMode ? { valid: true, taskMode, violations: [] } : { valid: true, violations: [] };
4889
4959
  }
4890
4960
  const text = message || "";
4891
4961
  const violations = LIVE_DEBUG_READONLY_FORBIDDEN.filter((rule) => patternHasRealMutation(rule.pattern, text)).map((rule) => rule.label);
@@ -5012,7 +5082,8 @@ function assertNoDependencyCycle(meshId, newTaskId, dependsOn) {
5012
5082
  }
5013
5083
  function enqueueTask(meshId, message, opts) {
5014
5084
  requireMeshHostQueueOwner(opts);
5015
- const modeValidation = validateMeshTaskModeRequest(opts?.taskMode, message);
5085
+ const readonly = opts?.readonly === true;
5086
+ const modeValidation = validateMeshTaskModeRequest(opts?.taskMode, message, readonly);
5016
5087
  if (!modeValidation.valid) {
5017
5088
  throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
5018
5089
  }
@@ -5036,6 +5107,7 @@ function enqueueTask(meshId, message, opts) {
5036
5107
  message,
5037
5108
  status: "pending",
5038
5109
  taskMode: modeValidation.taskMode,
5110
+ ...readonly ? { readonly: true } : {},
5039
5111
  targetNodeId: opts?.targetNodeId,
5040
5112
  targetSessionId: opts?.targetSessionId,
5041
5113
  requiredTags: resolvedRequiredTags,
@@ -5054,7 +5126,8 @@ function recordDirectDispatchTask(meshId, message, opts) {
5054
5126
  if (!missionId) return null;
5055
5127
  const taskId = typeof opts.id === "string" ? opts.id.trim() : "";
5056
5128
  if (!taskId) return null;
5057
- const modeValidation = validateMeshTaskModeRequest(opts.taskMode, message);
5129
+ const readonly = opts.readonly === true;
5130
+ const modeValidation = validateMeshTaskModeRequest(opts.taskMode, message, readonly);
5058
5131
  if (!modeValidation.valid) {
5059
5132
  throw new Error(`live_debug_readonly_guardrail_violation: forbidden operations (${modeValidation.violations.join(", ")})`);
5060
5133
  }
@@ -5069,6 +5142,7 @@ function recordDirectDispatchTask(meshId, message, opts) {
5069
5142
  message,
5070
5143
  status: "assigned",
5071
5144
  ...modeValidation.taskMode ? { taskMode: modeValidation.taskMode } : {},
5145
+ ...readonly ? { readonly: true } : {},
5072
5146
  missionId,
5073
5147
  ...opts.assignedNodeId ? { targetNodeId: opts.assignedNodeId, assignedNodeId: opts.assignedNodeId } : {},
5074
5148
  ...opts.assignedSessionId ? { targetSessionId: opts.assignedSessionId, assignedSessionId: opts.assignedSessionId } : {},
@@ -6048,7 +6122,7 @@ var init_mesh_runtime_store = __esm({
6048
6122
  return deps.every((depId) => depStatus.get(depId) === "completed");
6049
6123
  };
6050
6124
  const nodeConflictAllows = (candidate) => {
6051
- if (candidate.taskMode === "live_debug_readonly") return true;
6125
+ if (isTaskReadonly(candidate)) return true;
6052
6126
  return !nodeBusy;
6053
6127
  };
6054
6128
  const nodeIsWorktree = opts?.nodeIsWorktree === true;
@@ -9260,7 +9334,7 @@ var init_mesh_fast_forward = __esm({
9260
9334
  "use strict";
9261
9335
  init_git_status();
9262
9336
  init_git_executor();
9263
- STATUS_OPTIONS = { refreshUpstream: true, includeSubmodules: true, timeoutMs: 15e3 };
9337
+ STATUS_OPTIONS = { refreshUpstream: true, includeSubmodules: true, timeoutMs: 15e3, forceFresh: true };
9264
9338
  }
9265
9339
  });
9266
9340
 
@@ -9660,9 +9734,6 @@ var mesh_scheduling_runtime_exports = {};
9660
9734
  __export(mesh_scheduling_runtime_exports, {
9661
9735
  buildMeshSchedulingRuntime: () => buildMeshSchedulingRuntime
9662
9736
  });
9663
- function isReadonly(task) {
9664
- return task.taskMode === "live_debug_readonly";
9665
- }
9666
9737
  function isAssigned(task) {
9667
9738
  return task.status === "assigned";
9668
9739
  }
@@ -9671,8 +9742,8 @@ function buildMeshSchedulingRuntime(mesh, queue) {
9671
9742
  const maxParallelTasks = resolveMaxParallelTasks(mesh?.policy?.maxParallelTasks);
9672
9743
  const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks);
9673
9744
  const assignedTasks = (Array.isArray(queue) ? queue : []).filter(isAssigned);
9674
- const activeWriteAssigned = assignedTasks.filter((t) => !isReadonly(t)).length;
9675
- const activeReadonlyAssigned = assignedTasks.filter(isReadonly).length;
9745
+ const activeWriteAssigned = assignedTasks.filter((t) => !isTaskReadonly(t)).length;
9746
+ const activeReadonlyAssigned = assignedTasks.filter(isTaskReadonly).length;
9676
9747
  const globalWriteCapReached = activeWriteAssigned >= maxParallelTasks;
9677
9748
  const globalReadonlyCapReached = activeReadonlyAssigned >= maxReadonlyParallelTasks;
9678
9749
  const writeAssignedByNode = /* @__PURE__ */ new Map();
@@ -9682,7 +9753,7 @@ function buildMeshSchedulingRuntime(mesh, queue) {
9682
9753
  const nodeId = typeof task.assignedNodeId === "string" ? task.assignedNodeId.trim() : "";
9683
9754
  if (!nodeId) continue;
9684
9755
  assignedByNode.set(nodeId, (assignedByNode.get(nodeId) ?? 0) + 1);
9685
- if (!isReadonly(task)) {
9756
+ if (!isTaskReadonly(task)) {
9686
9757
  writeAssignedByNode.set(nodeId, (writeAssignedByNode.get(nodeId) ?? 0) + 1);
9687
9758
  }
9688
9759
  const provider = typeof task.assignedProviderType === "string" ? task.assignedProviderType : "";
@@ -9755,6 +9826,7 @@ var init_mesh_scheduling_runtime = __esm({
9755
9826
  "use strict";
9756
9827
  init_repo_mesh_types();
9757
9828
  init_dist();
9829
+ init_mesh_work_queue();
9758
9830
  }
9759
9831
  });
9760
9832
 
@@ -12157,10 +12229,10 @@ function resolveAutoLaunchTarget(components, node) {
12157
12229
  return { mode: "remote", daemonId, coordinatorDaemonId };
12158
12230
  }
12159
12231
  function activeWriteAssignedCount(meshId) {
12160
- return getQueue(meshId, { status: ["assigned"] }).filter((task) => task.taskMode !== "live_debug_readonly").length;
12232
+ return getQueue(meshId, { status: ["assigned"] }).filter((task) => !isTaskReadonly(task)).length;
12161
12233
  }
12162
12234
  function activeReadonlyAssignedCount(meshId) {
12163
- return getQueue(meshId, { status: ["assigned"] }).filter((task) => task.taskMode === "live_debug_readonly").length;
12235
+ return getQueue(meshId, { status: ["assigned"] }).filter(isTaskReadonly).length;
12164
12236
  }
12165
12237
  function nodeHasActiveAssignment(meshId, nodeId) {
12166
12238
  return getQueue(meshId, { status: ["assigned"] }).some((task) => task.assignedNodeId === nodeId);
@@ -12336,8 +12408,8 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
12336
12408
  );
12337
12409
  const maxReadonlyParallelTasks = resolveMaxReadonlyParallelTasks(maxParallelTasks, schedulingOverride?.readonlyMultiplier);
12338
12410
  for (const task of pending) {
12339
- const isReadonly2 = task.taskMode === "live_debug_readonly";
12340
- if (isReadonly2) {
12411
+ const isReadonly = isTaskReadonly(task);
12412
+ if (isReadonly) {
12341
12413
  if (activeReadonlyAssignedCount(meshId) >= maxReadonlyParallelTasks) {
12342
12414
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "max_readonly_parallel_tasks_reached" });
12343
12415
  continue;
@@ -12419,7 +12491,7 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
12419
12491
  sweepExpiredCooldowns();
12420
12492
  continue;
12421
12493
  }
12422
- if (task.taskMode !== "live_debug_readonly" && nodeHasActiveAssignment(meshId, nodeId)) {
12494
+ if (!isTaskReadonly(task) && nodeHasActiveAssignment(meshId, nodeId)) {
12423
12495
  markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
12424
12496
  continue;
12425
12497
  }
@@ -13166,6 +13238,9 @@ function isModuleNotFoundError(error, ref) {
13166
13238
  const code = "code" in error ? error.code : void 0;
13167
13239
  return code === "MODULE_NOT_FOUND" && message.includes(ref);
13168
13240
  }
13241
+ function runtimeTriplet() {
13242
+ return `${process.platform}-${process.arch}-node${process.versions.modules}`;
13243
+ }
13169
13244
  function normalizeBinding(mod, ref) {
13170
13245
  const binding = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;
13171
13246
  if (!binding) {
@@ -13200,7 +13275,7 @@ function loadGhosttyVtBinding() {
13200
13275
  }
13201
13276
  cachedBinding = null;
13202
13277
  cachedBindingError = new Error(
13203
- `ghostty-vt binding unavailable (${errors.join("; ") || "no candidates tried"})`
13278
+ `ghostty-vt binding unavailable for runtime ${runtimeTriplet()} (${errors.join("; ") || "no candidates tried"})`
13204
13279
  );
13205
13280
  throw cachedBindingError;
13206
13281
  }
@@ -13750,21 +13825,42 @@ function extractFinalSummaryFromMessages(messages, maxChars = DEFAULT_FINAL_SUMM
13750
13825
  }
13751
13826
  return "";
13752
13827
  }
13753
- function readChatMessageTimestampIso(message) {
13828
+ function readChatMessageTimestampMs(message) {
13754
13829
  if (!message) return void 0;
13755
13830
  const record = message;
13756
- for (const value of [record.timestamp, record.createdAt, record.created_at, record.updatedAt, record.time]) {
13831
+ for (const value of [record.timestamp, record.createdAt, record.created_at, record.updatedAt, record.time, record.receivedAt]) {
13757
13832
  if (typeof value === "number" && Number.isFinite(value)) {
13758
- const ms = value > 1e10 ? value : value * 1e3;
13759
- return new Date(ms).toISOString();
13833
+ return value > 1e10 ? value : value * 1e3;
13760
13834
  }
13761
13835
  if (typeof value === "string" && value.trim()) {
13762
13836
  const ms = new Date(value.trim()).getTime();
13763
- if (Number.isFinite(ms)) return new Date(ms).toISOString();
13837
+ if (Number.isFinite(ms)) return ms;
13764
13838
  }
13765
13839
  }
13766
13840
  return void 0;
13767
13841
  }
13842
+ function readChatMessageTimestampIso(message) {
13843
+ const ms = readChatMessageTimestampMs(message);
13844
+ return typeof ms === "number" ? new Date(ms).toISOString() : void 0;
13845
+ }
13846
+ function extractFinalSummaryFromMessagesAfter(messages, minTimestampMs, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
13847
+ if (!Array.isArray(messages) || messages.length === 0) return "";
13848
+ const hasBoundary = typeof minTimestampMs === "number" && Number.isFinite(minTimestampMs);
13849
+ for (let i = messages.length - 1; i >= 0; i--) {
13850
+ const msg = messages[i];
13851
+ if (!msg) continue;
13852
+ if (hasBoundary) {
13853
+ const ts2 = readChatMessageTimestampMs(msg);
13854
+ if (typeof ts2 === "number" && ts2 < minTimestampMs) continue;
13855
+ }
13856
+ const classification = classifyChatMessageVisibility(msg);
13857
+ if (classification.isUserFacing && (msg.role === "assistant" || msg.role === "model")) {
13858
+ const text = flattenContent(msg.content).trim();
13859
+ if (text) return text.slice(0, maxChars);
13860
+ }
13861
+ }
13862
+ return "";
13863
+ }
13768
13864
  function extractFinalAssistantSummaryEvidence(messages, maxChars = DEFAULT_FINAL_SUMMARY_MAX_CHARS) {
13769
13865
  if (!Array.isArray(messages) || messages.length === 0) return { finalSummary: "" };
13770
13866
  for (let i = messages.length - 1; i >= 0; i--) {
@@ -16374,11 +16470,8 @@ function resolveTunedReconcileMs(envName, def, min, max) {
16374
16470
  }
16375
16471
  return def;
16376
16472
  }
16377
- function resolveMinIdleSettleMs() {
16378
- return resolveTunedReconcileMs("MESH_INFLIGHT_MIN_IDLE_SETTLE_MS", 16e3, 0, 12e4);
16379
- }
16380
- function resolveAckedTurnSettleMs() {
16381
- return resolveTunedReconcileMs("MESH_INFLIGHT_ACKED_TURN_SETTLE_MS", 2e4, 0, 18e4);
16473
+ function resolveAckedDeathDeadlineMs() {
16474
+ return resolveTunedReconcileMs("MESH_INFLIGHT_ACKED_DEATH_DEADLINE_MS", 8 * 6e4, 0, 60 * 6e4);
16382
16475
  }
16383
16476
  function inFlightSynthKey(meshId, taskId) {
16384
16477
  return `${meshId}::${taskId}`;
@@ -16989,9 +17082,9 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
16989
17082
  const activeTaskKeys = new Set(
16990
17083
  dispatches.map((d) => readNonEmptyString2(d.taskId)).filter(Boolean).map((taskId) => inFlightSynthKey(mesh.id, taskId))
16991
17084
  );
16992
- for (const key of inFlightIdleObservationCounts.keys()) {
17085
+ for (const key of inFlightAckedHoldState.keys()) {
16993
17086
  if (key.startsWith(`${mesh.id}::`) && !activeTaskKeys.has(key)) {
16994
- inFlightIdleObservationCounts.delete(key);
17087
+ inFlightAckedHoldState.delete(key);
16995
17088
  }
16996
17089
  }
16997
17090
  const dispatchMeshCommand = components.dispatchMeshCommand;
@@ -17012,49 +17105,61 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
17012
17105
  ...node?.workspace ? { workspace: node.workspace } : {},
17013
17106
  ...providerType ? { agentType: providerType, providerType } : {}
17014
17107
  };
17108
+ const synthKey = inFlightSynthKey(mesh.id, taskId);
17109
+ const isAcked = dispatch.status === "acked";
17015
17110
  let payload = null;
17111
+ let readFailed = false;
17016
17112
  try {
17017
17113
  if (isLocalNode) {
17018
17114
  const result = await components.commandHandler.handle("read_chat", readArgs);
17019
- if (result && result.success === false) continue;
17020
- payload = unwrapReadChatPayload(result);
17115
+ if (result && result.success === false) {
17116
+ readFailed = true;
17117
+ } else {
17118
+ payload = unwrapReadChatPayload(result);
17119
+ }
17021
17120
  } else if (dispatchMeshCommand) {
17022
17121
  const result = await dispatchMeshCommand(nodeDaemonId, "read_chat", readArgs);
17023
17122
  payload = unwrapReadChatPayload(result);
17024
- if (payload && payload.success === false) continue;
17123
+ if (payload && payload.success === false) {
17124
+ payload = null;
17125
+ readFailed = true;
17126
+ }
17025
17127
  } else {
17026
17128
  continue;
17027
17129
  }
17028
17130
  } catch {
17131
+ readFailed = true;
17132
+ }
17133
+ if (!payload && !readFailed) continue;
17134
+ if (readFailed || !payload) {
17135
+ if (isAcked) {
17136
+ const prior = inFlightAckedHoldState.get(synthKey);
17137
+ const failures = (prior?.consecutiveReadFailures ?? 0) + 1;
17138
+ const liveConfirmedSinceAck = prior?.liveConfirmedSinceAck ?? false;
17139
+ inFlightAckedHoldState.set(synthKey, { liveConfirmedSinceAck, consecutiveReadFailures: failures });
17140
+ if (liveConfirmedSinceAck && failures >= ACKED_DEATH_CONSECUTIVE_READ_FAILURES) {
17141
+ LOG.warn("MeshReconcile", `Acked-hold death signal: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read_chat failed ${failures}x consecutively after a live-confirmed ack \u2014 worker session presumed gone mid-turn; releasing the indefinite synth hold to the stranded-reclaim / orphan-prune nets`);
17142
+ }
17143
+ }
17029
17144
  continue;
17030
17145
  }
17031
- if (!payload) continue;
17032
- const synthKey = inFlightSynthKey(mesh.id, taskId);
17146
+ inFlightAckedHoldState.set(synthKey, { liveConfirmedSinceAck: true, consecutiveReadFailures: 0 });
17033
17147
  const nowMs = Date.now();
17034
17148
  if (readChatPayloadStatus(payload) !== "idle") {
17035
- inFlightIdleObservationCounts.delete(synthKey);
17036
17149
  continue;
17037
17150
  }
17038
- if (dispatch.status === "acked") {
17039
- const prior = inFlightIdleObservationCounts.get(synthKey);
17040
- const firstIdleAtMs = prior?.firstIdleAtMs ?? nowMs;
17041
- const idleStreak = (prior?.count ?? 0) + 1;
17042
- inFlightIdleObservationCounts.set(synthKey, { count: idleStreak, firstIdleAtMs });
17043
- const idleSettleMs = nowMs - firstIdleAtMs;
17044
- const minIdleSettleMs = resolveMinIdleSettleMs();
17045
- const ackedTurnSettleMs = resolveAckedTurnSettleMs();
17151
+ if (isAcked) {
17046
17152
  const ackedAtMs = Date.parse(readNonEmptyString2(dispatch.updatedAt));
17047
17153
  const sinceAckMs = Number.isFinite(ackedAtMs) ? nowMs - ackedAtMs : Number.POSITIVE_INFINITY;
17048
- const tickGuardMet = idleStreak >= REQUIRED_CONSECUTIVE_IDLE_TICKS_FOR_INFLIGHT_SYNTH;
17049
- const settleGuardMet = idleSettleMs >= minIdleSettleMs;
17050
- const ackGuardMet = sinceAckMs >= ackedTurnSettleMs;
17051
- if (!tickGuardMet || !settleGuardMet || !ackGuardMet) {
17052
- LOG.info("MeshReconcile", `In-flight synth hold: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) idle ${idleStreak}/${REQUIRED_CONSECUTIVE_IDLE_TICKS_FOR_INFLIGHT_SYNTH} tick(s), settle ${Math.round(idleSettleMs / 1e3)}s/${Math.round(minIdleSettleMs / 1e3)}s, since-ack ${Number.isFinite(sinceAckMs) ? Math.round(sinceAckMs / 1e3) + "s" : "\u221E"}/${Math.round(ackedTurnSettleMs / 1e3)}s \u2014 deferring completion synth until the worker's turn genuinely settles (guards against a mid-turn idle window pre-empting the real completion)`);
17154
+ const deathDeadlineMs = resolveAckedDeathDeadlineMs();
17155
+ if (sinceAckMs < deathDeadlineMs) {
17156
+ LOG.info("MeshReconcile", `Acked-hold: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read idle ${Number.isFinite(sinceAckMs) ? Math.round(sinceAckMs / 1e3) + "s" : "\u221E"} since the generating_started ack \u2014 HOLDING synth indefinitely (worker is alive and will emit; a later real emit is idempotent). Death backstop fires at ${Math.round(deathDeadlineMs / 1e3)}s or on consecutive read failures.`);
17053
17157
  continue;
17054
17158
  }
17159
+ LOG.warn("MeshReconcile", `Acked-hold death deadline reached: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) still idle ${Math.round(sinceAckMs / 1e3)}s after the ack (deadline ${Math.round(deathDeadlineMs / 1e3)}s) \u2014 synthesizing the missing completion as a notification-loss net (a real emit, if it ever lands, no-ops idempotently).`);
17055
17160
  }
17056
17161
  if (realTerminalEmitPendingForTask(mesh.id, taskId)) {
17057
- inFlightIdleObservationCounts.delete(synthKey);
17162
+ inFlightAckedHoldState.delete(synthKey);
17058
17163
  LOG.info("MeshReconcile", `Worker-emit priority: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) has a real terminal completion already queued \u2014 yielding synth to the worker's own emit`);
17059
17164
  continue;
17060
17165
  }
@@ -17076,7 +17181,7 @@ async function reconcileUnterminatedDirectDispatches(components, mesh, selfIds,
17076
17181
  }
17077
17182
  const reprobeStatus = await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
17078
17183
  if (reprobeStatus && reprobeStatus !== "idle") {
17079
- inFlightIdleObservationCounts.delete(synthKey);
17184
+ inFlightAckedHoldState.delete(synthKey);
17080
17185
  LOG.info("MeshReconcile", `Live re-probe defer: task ${taskId} on node ${nodeId} (mesh ${mesh.id}) read '${reprobeStatus}' at synth-commit time \u2014 worker resumed generating; deferring synth to a later tick`);
17081
17186
  continue;
17082
17187
  }
@@ -17218,7 +17323,7 @@ function setupMeshReconcileLoop(components) {
17218
17323
  }
17219
17324
  };
17220
17325
  }
17221
- var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, REQUIRED_CONSECUTIVE_IDLE_TICKS_FOR_INFLIGHT_SYNTH, inFlightIdleObservationCounts, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
17326
+ var DEFAULT_RECONCILE_INTERVAL_MS, DEFAULT_AUTO_PRUNE_MIN_AGE_MS, ACKED_DEATH_CONSECUTIVE_READ_FAILURES, inFlightAckedHoldState, coordinatorModalParkState, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS;
17222
17327
  var init_mesh_reconcile_loop = __esm({
17223
17328
  "src/mesh/mesh-reconcile-loop.ts"() {
17224
17329
  "use strict";
@@ -17240,8 +17345,8 @@ var init_mesh_reconcile_loop = __esm({
17240
17345
  init_chat_message_normalization();
17241
17346
  DEFAULT_RECONCILE_INTERVAL_MS = 4e3;
17242
17347
  DEFAULT_AUTO_PRUNE_MIN_AGE_MS = 24 * 60 * 6e4;
17243
- REQUIRED_CONSECUTIVE_IDLE_TICKS_FOR_INFLIGHT_SYNTH = 2;
17244
- inFlightIdleObservationCounts = /* @__PURE__ */ new Map();
17348
+ ACKED_DEATH_CONSECUTIVE_READ_FAILURES = 3;
17349
+ inFlightAckedHoldState = /* @__PURE__ */ new Map();
17245
17350
  coordinatorModalParkState = /* @__PURE__ */ new Map();
17246
17351
  heldEventLedgerRecorded = /* @__PURE__ */ new Set();
17247
17352
  ASSIGNED_STRANDED_DEADLINE_MS = 5 * 6e4;
@@ -23848,7 +23953,7 @@ function validateMutatingMessage(value) {
23848
23953
  async function gitCheckpoint(workspace, message, includeUntracked) {
23849
23954
  const repo = await resolveGitRepository(workspace);
23850
23955
  const repoRoot = repo.repoRoot;
23851
- const statusResult = await getGitRepoStatus(workspace);
23956
+ const statusResult = await getGitRepoStatus(workspace, { forceFresh: true });
23852
23957
  if (statusResult.hasConflicts) {
23853
23958
  throw new GitCommandError("conflict", "Repository has conflicts \u2014 resolve before checkpointing");
23854
23959
  }
@@ -32330,6 +32435,10 @@ async function handleResolveAction(h, args) {
32330
32435
  const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" || parsedStatus?.status === "waiting_approval" ? "waiting_approval" : status?.status;
32331
32436
  LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} parsedModal=${parsedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
32332
32437
  if (!effectiveModal) {
32438
+ if (typeof adapter.isApprovalRecentlyResolved === "function" && adapter.isApprovalRecentlyResolved()) {
32439
+ LOG.info("Command", `[resolveAction] CLI PTY \u2192 already_resolved (modal gone, resolved within cooldown)`);
32440
+ return { success: true, alreadyResolved: true, status: "already_resolved" };
32441
+ }
32333
32442
  return { success: false, error: "Not in approval state" };
32334
32443
  }
32335
32444
  const buttons = Array.isArray(effectiveModal.buttons) ? effectiveModal.buttons : [];
@@ -40351,14 +40460,14 @@ var CliProviderInstance = class _CliProviderInstance {
40351
40460
  source: "unavailable"
40352
40461
  };
40353
40462
  }
40354
- completionFinalSummary(parsedMessages) {
40463
+ completionFinalSummary(parsedMessages, turnStartedAt) {
40355
40464
  const adapterOwnsMessagesElsewhere = this.adapter?.chatMessagesOwnedExternally === true;
40356
40465
  const parsedSummary = extractFinalSummaryFromMessages(
40357
40466
  this.completionHasFinalAssistantMessage(parsedMessages) ? Array.isArray(parsedMessages) ? parsedMessages : [] : []
40358
40467
  );
40359
40468
  if (adapterOwnsMessagesElsewhere) {
40360
40469
  const externalMessages = this.readExternalCompletionMessages();
40361
- const externalSummary = externalMessages ? extractFinalSummaryFromMessages(externalMessages) : "";
40470
+ const externalSummary = externalMessages ? extractFinalSummaryFromMessagesAfter(externalMessages, turnStartedAt) : "";
40362
40471
  if (externalSummary) return externalSummary;
40363
40472
  return parsedSummary || void 0;
40364
40473
  }
@@ -40645,7 +40754,7 @@ var CliProviderInstance = class _CliProviderInstance {
40645
40754
  // delegated session's inbox preview blank — or, for a LOCAL worktree session,
40646
40755
  // stuck on the dispatched user task. If the parser DID surface assistant text,
40647
40756
  // prefer it; only fall back to '' when no assistant summary can be derived.
40648
- finalSummary: blockReason.startsWith("parsed_status:") ? this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages) ?? "" : this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages),
40757
+ finalSummary: blockReason.startsWith("parsed_status:") ? this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages, pending.turnStartedAt) ?? "" : this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages, pending.turnStartedAt),
40649
40758
  completionDiagnostic
40650
40759
  });
40651
40760
  this.completedDebouncePending = null;
@@ -40665,7 +40774,7 @@ var CliProviderInstance = class _CliProviderInstance {
40665
40774
  timestamp: pending.timestamp,
40666
40775
  // ARCH-REFACTOR R1: attribute to the turn captured at idle-transition.
40667
40776
  ...pending.taskId ? { taskId: pending.taskId } : {},
40668
- finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages)
40777
+ finalSummary: this.completionFinalSummary(this.adapter?.getScriptParsedStatus()?.messages, pending.turnStartedAt)
40669
40778
  });
40670
40779
  this.completedDebouncePending = null;
40671
40780
  this.completedDebounceTimer = null;
@@ -40781,7 +40890,7 @@ var CliProviderInstance = class _CliProviderInstance {
40781
40890
  */
40782
40891
  recheckAutoApproveSettled() {
40783
40892
  try {
40784
- const adapterStatus = this.adapter.getStatus({ allowParse: false });
40893
+ const adapterStatus = this.adapter.getStatus({ allowParse: true });
40785
40894
  this.maybeAutoApproveStatus(adapterStatus, Date.now());
40786
40895
  } catch {
40787
40896
  }
@@ -41012,7 +41121,16 @@ var CliProviderInstance = class _CliProviderInstance {
41012
41121
  // ARCH-REFACTOR R1: snapshot the completing turn's taskId NOW (sync),
41013
41122
  // before any follow-up task's flush can start a new turn and move
41014
41123
  // engine.currentTurnTaskId.
41015
- ...this.completingTurnTaskId() ? { taskId: this.completingTurnTaskId() } : {}
41124
+ ...this.completingTurnTaskId() ? { taskId: this.completingTurnTaskId() } : {},
41125
+ // NOTIF Defect-B: snapshot the producing turn's START instant NOW, for the
41126
+ // same reason as taskId — a follow-up turn moves engine.currentTurnStartedAt.
41127
+ // Prefer the engine's per-turn start (set at onTurnStarted, earliest reliable
41128
+ // anchor) and fall back to generatingStartedAt (when generating was observed).
41129
+ ...(() => {
41130
+ const engineTurnStart = typeof this.adapter?.currentTurnStartedAt === "number" && Number.isFinite(this.adapter.currentTurnStartedAt) ? this.adapter.currentTurnStartedAt : 0;
41131
+ const turnStartedAt = engineTurnStart || this.generatingStartedAt || 0;
41132
+ return turnStartedAt ? { turnStartedAt } : {};
41133
+ })()
41016
41134
  };
41017
41135
  const ownsExternalHistory = !!this.adapter?.chatMessagesOwnedExternally;
41018
41136
  const meshWorkerSession = this.isMeshWorkerSession();
@@ -52649,7 +52767,10 @@ async function alignRefinerySubmodulesAfterMerge(repoRoot, previousBaseHead, cur
52649
52767
  const preStatus = await getGitRepoStatus(repoRoot, {
52650
52768
  includeSubmodules: true,
52651
52769
  submoduleIgnorePaths: options.submoduleIgnorePaths,
52652
- timeoutMs: 15e3
52770
+ timeoutMs: 15e3,
52771
+ // Decision path — the out-of-sync submodule set drives a mutating `submodule
52772
+ // update`. Must not act on a TTL-cached status; bypass the C1 cache.
52773
+ forceFresh: true
52653
52774
  });
52654
52775
  const outOfSyncPaths = (preStatus.submodules || []).filter((submodule) => submodule.dirty || submodule.outOfSync || !!submodule.error).map((submodule) => submodule.path);
52655
52776
  const updatePaths = [.../* @__PURE__ */ new Set([...changedGitlinkPaths, ...outOfSyncPaths])].sort();
@@ -52678,7 +52799,10 @@ async function alignRefinerySubmodulesAfterMerge(repoRoot, previousBaseHead, cur
52678
52799
  const postStatus = await getGitRepoStatus(repoRoot, {
52679
52800
  includeSubmodules: true,
52680
52801
  submoduleIgnorePaths: options.submoduleIgnorePaths,
52681
- timeoutMs: 15e3
52802
+ timeoutMs: 15e3,
52803
+ // Re-read AFTER `submodule update` mutated the tree — MUST be fresh, never the
52804
+ // cached preStatus from moments ago (which would falsely report still-dirty).
52805
+ forceFresh: true
52682
52806
  });
52683
52807
  const remaining = (postStatus.submodules || []).filter((submodule) => updatePaths.includes(submodule.path) && (submodule.dirty || submodule.outOfSync || !!submodule.error));
52684
52808
  return {
@@ -64133,6 +64257,7 @@ export {
64133
64257
  isSessionHostLiveRuntime,
64134
64258
  isSessionHostRecoverySnapshot,
64135
64259
  isSetupComplete,
64260
+ isTaskReadonly,
64136
64261
  isUserFacingChatMessage,
64137
64262
  killIdeProcess,
64138
64263
  launchIDE,