@adhdev/daemon-standalone 1.0.39-rc.1 → 1.0.39-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -31423,9 +31423,9 @@ var require_streamx = __commonJS({
31423
31423
  }
31424
31424
  });
31425
31425
 
31426
- // ../daemon-core/node_modules/b4a/index.js
31426
+ // ../../node_modules/tar-stream/node_modules/b4a/index.js
31427
31427
  var require_b4a2 = __commonJS({
31428
- "../daemon-core/node_modules/b4a/index.js"(exports2, module2) {
31428
+ "../../node_modules/tar-stream/node_modules/b4a/index.js"(exports2, module2) {
31429
31429
  "use strict";
31430
31430
  function isBuffer(value) {
31431
31431
  return Buffer.isBuffer(value) || value instanceof Uint8Array;
@@ -31581,9 +31581,9 @@ var require_b4a2 = __commonJS({
31581
31581
  }
31582
31582
  });
31583
31583
 
31584
- // ../daemon-core/node_modules/tar-stream/headers.js
31584
+ // ../../node_modules/tar-stream/headers.js
31585
31585
  var require_headers = __commonJS({
31586
- "../daemon-core/node_modules/tar-stream/headers.js"(exports2) {
31586
+ "../../node_modules/tar-stream/headers.js"(exports2) {
31587
31587
  "use strict";
31588
31588
  var b4a = require_b4a2();
31589
31589
  var ZEROS = "0000000000000000000";
@@ -31844,9 +31844,9 @@ var require_headers = __commonJS({
31844
31844
  }
31845
31845
  });
31846
31846
 
31847
- // ../daemon-core/node_modules/tar-stream/extract.js
31847
+ // ../../node_modules/tar-stream/extract.js
31848
31848
  var require_extract = __commonJS({
31849
- "../daemon-core/node_modules/tar-stream/extract.js"(exports2, module2) {
31849
+ "../../node_modules/tar-stream/extract.js"(exports2, module2) {
31850
31850
  "use strict";
31851
31851
  var { Writable, Readable, getStreamError } = require_streamx();
31852
31852
  var FIFO = require_fast_fifo();
@@ -32189,9 +32189,9 @@ var require_extract = __commonJS({
32189
32189
  }
32190
32190
  });
32191
32191
 
32192
- // ../daemon-core/node_modules/tar-stream/constants.js
32192
+ // ../../node_modules/tar-stream/constants.js
32193
32193
  var require_constants = __commonJS({
32194
- "../daemon-core/node_modules/tar-stream/constants.js"(exports2, module2) {
32194
+ "../../node_modules/tar-stream/constants.js"(exports2, module2) {
32195
32195
  "use strict";
32196
32196
  var constants = {
32197
32197
  // just for envs without fs
@@ -32210,9 +32210,9 @@ var require_constants = __commonJS({
32210
32210
  }
32211
32211
  });
32212
32212
 
32213
- // ../daemon-core/node_modules/tar-stream/pack.js
32213
+ // ../../node_modules/tar-stream/pack.js
32214
32214
  var require_pack = __commonJS({
32215
- "../daemon-core/node_modules/tar-stream/pack.js"(exports2, module2) {
32215
+ "../../node_modules/tar-stream/pack.js"(exports2, module2) {
32216
32216
  "use strict";
32217
32217
  var { Readable, Writable, getStreamError } = require_streamx();
32218
32218
  var b4a = require_b4a2();
@@ -32445,9 +32445,9 @@ var require_pack = __commonJS({
32445
32445
  }
32446
32446
  });
32447
32447
 
32448
- // ../daemon-core/node_modules/tar-stream/index.js
32448
+ // ../../node_modules/tar-stream/index.js
32449
32449
  var require_tar_stream = __commonJS({
32450
- "../daemon-core/node_modules/tar-stream/index.js"(exports2) {
32450
+ "../../node_modules/tar-stream/index.js"(exports2) {
32451
32451
  "use strict";
32452
32452
  exports2.extract = require_extract();
32453
32453
  exports2.pack = require_pack();
@@ -32690,9 +32690,9 @@ var require_pump = __commonJS({
32690
32690
  }
32691
32691
  });
32692
32692
 
32693
- // ../daemon-core/node_modules/tar-fs/index.js
32693
+ // ../../node_modules/tar-fs/index.js
32694
32694
  var require_tar_fs = __commonJS({
32695
- "../daemon-core/node_modules/tar-fs/index.js"(exports2) {
32695
+ "../../node_modules/tar-fs/index.js"(exports2) {
32696
32696
  "use strict";
32697
32697
  var tar = require_tar_stream();
32698
32698
  var pump = require_pump();
@@ -36528,10 +36528,10 @@ var require_dist3 = __commonJS({
36528
36528
  }
36529
36529
  function getDaemonBuildInfo() {
36530
36530
  if (cached2) return cached2;
36531
- const commit = readInjected(true ? "a1082159590bba25809d2f8a65c10055b8d3bc97" : void 0) ?? "unknown";
36532
- const commitShort = readInjected(true ? "a1082159" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36533
- const version2 = readInjected(true ? "1.0.39-rc.1" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36534
- const builtAt = readInjected(true ? "2026-08-07T02:52:22.815Z" : void 0);
36531
+ const commit = readInjected(true ? "e83658a6a9fa9fe9529dd88548adac8581276d02" : void 0) ?? "unknown";
36532
+ const commitShort = readInjected(true ? "e83658a6" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36533
+ const version2 = readInjected(true ? "1.0.39-rc.10" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36534
+ const builtAt = readInjected(true ? "2026-08-08T05:15:16.251Z" : void 0);
36535
36535
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
36536
36536
  return cached2;
36537
36537
  }
@@ -38643,6 +38643,7 @@ child.on('exit', () => process.exit(0));
38643
38643
  });
38644
38644
  var config_exports = {};
38645
38645
  __export2(config_exports, {
38646
+ clearAuthCredentials: () => clearAuthCredentials,
38646
38647
  generateMachineId: () => generateMachineId,
38647
38648
  getConfigDir: () => getConfigDir2,
38648
38649
  getDaemonDataDir: () => getDaemonDataDir,
@@ -38879,6 +38880,13 @@ child.on('exit', () => process.exit(0));
38879
38880
  function resetConfig() {
38880
38881
  saveConfig({ ...DEFAULT_CONFIG });
38881
38882
  }
38883
+ function clearAuthCredentials() {
38884
+ const config2 = loadConfig2();
38885
+ config2.machineSecret = void 0;
38886
+ config2.userEmail = null;
38887
+ config2.userName = null;
38888
+ saveConfig(config2);
38889
+ }
38882
38890
  var import_path4;
38883
38891
  var import_fs3;
38884
38892
  var import_crypto2;
@@ -40714,7 +40722,7 @@ child.on('exit', () => process.exit(0));
40714
40722
  resolveWorktreePath: () => resolveWorktreePath
40715
40723
  });
40716
40724
  function getDefaultWorktreeBaseDir() {
40717
- return path11.join(os52.homedir(), ".adhdev", WORKTREE_DIR_NAME);
40725
+ return path11.join(resolveConfigDir(), WORKTREE_DIR_NAME);
40718
40726
  }
40719
40727
  function resolveWorktreeBaseDir(worktreeBaseDir) {
40720
40728
  const override = typeof worktreeBaseDir === "string" ? worktreeBaseDir.trim() : "";
@@ -41004,7 +41012,6 @@ ${error48.message || ""}`;
41004
41012
  }
41005
41013
  }
41006
41014
  var path11;
41007
- var os52;
41008
41015
  var import_promises3;
41009
41016
  var import_node_fs2;
41010
41017
  var import_node_child_process3;
@@ -41018,11 +41025,11 @@ ${error48.message || ""}`;
41018
41025
  "src/git/git-worktree.ts"() {
41019
41026
  "use strict";
41020
41027
  path11 = __toESM2(require("path"));
41021
- os52 = __toESM2(require("os"));
41022
41028
  import_promises3 = require("fs/promises");
41023
41029
  import_node_fs2 = require("fs");
41024
41030
  import_node_child_process3 = require("child_process");
41025
41031
  import_node_util2 = require("util");
41032
+ init_config_dir();
41026
41033
  execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process3.execFile);
41027
41034
  WORKTREE_DIR_NAME = "worktrees";
41028
41035
  GIT_TIMEOUT_MS = 3e4;
@@ -41033,7 +41040,7 @@ ${error48.message || ""}`;
41033
41040
  function expandPath(p) {
41034
41041
  const t = (p || "").trim();
41035
41042
  if (!t) return "";
41036
- if (t.startsWith("~")) return path13.join(os7.homedir(), t.slice(1).replace(/^\//, ""));
41043
+ if (t.startsWith("~")) return path13.join(os62.homedir(), t.slice(1).replace(/^\//, ""));
41037
41044
  return path13.resolve(t);
41038
41045
  }
41039
41046
  function validateWorkspacePath(absPath) {
@@ -41106,7 +41113,7 @@ ${error48.message || ""}`;
41106
41113
  };
41107
41114
  }
41108
41115
  if (a.useHome === true) {
41109
- return { ok: true, path: os7.homedir(), source: "home" };
41116
+ return { ok: true, path: os62.homedir(), source: "home" };
41110
41117
  }
41111
41118
  return {
41112
41119
  ok: false,
@@ -41190,7 +41197,7 @@ ${error48.message || ""}`;
41190
41197
  return { config: { ...config2, defaultWorkspaceId: id } };
41191
41198
  }
41192
41199
  var fs7;
41193
- var os7;
41200
+ var os62;
41194
41201
  var path13;
41195
41202
  var import_crypto22;
41196
41203
  var MAX_WORKSPACES;
@@ -41198,7 +41205,7 @@ ${error48.message || ""}`;
41198
41205
  "src/config/workspaces.ts"() {
41199
41206
  "use strict";
41200
41207
  fs7 = __toESM2(require("fs"));
41201
- os7 = __toESM2(require("os"));
41208
+ os62 = __toESM2(require("os"));
41202
41209
  path13 = __toESM2(require("path"));
41203
41210
  import_crypto22 = require("crypto");
41204
41211
  MAX_WORKSPACES = 50;
@@ -46795,11 +46802,11 @@ Next step: ${nextStep}`;
46795
46802
  const pinnedProvider = typeof providerType === "string" && providerType.trim() ? providerType.trim() : void 0;
46796
46803
  const providerTags = pinnedProvider ? [pinnedProvider] : readNodeProviderTypes(node?.policy);
46797
46804
  const worktreeBranch = typeof node?.worktreeBranch === "string" && node.worktreeBranch.trim() ? node.worktreeBranch.trim() : null;
46798
- const os30 = readNodeOverride(node, "platform") ?? readNodeReporter(node, "platform") ?? process.platform;
46805
+ const os29 = readNodeOverride(node, "platform") ?? readNodeReporter(node, "platform") ?? process.platform;
46799
46806
  const arch2 = readNodeOverride(node, "arch") ?? readNodeReporter(node, "arch") ?? process.arch;
46800
46807
  return normalizeMeshCapabilityTags([
46801
46808
  ...Array.isArray(node?.capabilities) ? node.capabilities : [],
46802
- `os=${os30}`,
46809
+ `os=${os29}`,
46803
46810
  `arch=${arch2}`,
46804
46811
  ...providerTags.map((p) => `provider=${p}`),
46805
46812
  // Worktree nodes automatically expose a "worktree=<branch>" tag so that
@@ -51163,7 +51170,8 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
51163
51170
  "task_approval_needed",
51164
51171
  "task_question_pending",
51165
51172
  "p2p_dispatch_failed",
51166
- "dispatch_duplicate_rebound"
51173
+ "dispatch_duplicate_rebound",
51174
+ "queue_hold_hard_deadline"
51167
51175
  ]);
51168
51176
  LEDGER_DIR_NAME = "mesh-ledger";
51169
51177
  MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
@@ -51646,7 +51654,8 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
51646
51654
  checkpoint_then_continue: "- Auto-checkpoint dirty nodes before sending tasks"
51647
51655
  }[policy.dirtyWorkspaceBehavior] || "";
51648
51656
  if (dirtyBehavior) rules.push(dirtyBehavior);
51649
- rules.push(`- Maximum **${policy.maxParallelTasks}** tasks running in parallel`);
51657
+ rules.push(`- Maximum **${policy.maxParallelTasks}** concurrent WRITE tasks; **${resolveMaxReadonlyParallelTasks(policy.maxParallelTasks)}** concurrent READ-ONLY tasks (\`live_debug_readonly\`) \u2014 read-only work runs under its own, larger cap`);
51658
+ rules.push("- Write tasks are limited to **one active task per node**, so N parallel write tasks need N nodes (clone worktrees). Read-only tasks are exempt and may stack on a node that is already busy. Both caps are ceilings, not targets");
51650
51659
  if (policy.coordinatorIdlePushPolicy === "auto_silent_on_dispatch") {
51651
51660
  rules.push("- Delegated-worker completions are **auto-silenced**: the routine idle/completion push for a task you dispatch is suppressed once (approval-needed, failure, and long-running alerts still notify the owner normally)");
51652
51661
  }
@@ -51661,14 +51670,14 @@ ${rules.join("\n")}`;
51661
51670
  - **Route, don't implement.** Delegate all code reading, analysis, and execution to node agents. Never read source files or run commands in the coordinator \u2014 keep context lean. See also: **Never use local sub-agents** below.
51662
51671
  - **Never use local sub-agents.** Do NOT spawn your runtime's own sub-agents (e.g. Claude Code's Task/Explore/Agent tools, or any equivalent in-process agent-spawning tool) to read code, investigate, run RCA, or implement. Such sub-agents execute on the coordinator's machine, outside the mesh \u2014 they escape mesh parallelism, the ledger/audit trail, node capability profiles, and worktree isolation, and leave no \`mesh_task_history\` record. ALL code reading, analysis, RCA, and implementation must be delegated to mesh nodes via \`mesh_enqueue_task\` / \`mesh_send_task\` (use \`task_mode: "live_debug_readonly"\` for read-only investigation), or cross-verified via \`mesh_magi_review\` for read-only fan-out. The coordinator's own actions are limited to \`mesh_*\` tool orchestration and synthesizing results.
51663
51672
  - **Front-load task messages.** Include everything the agent needs (files, problem, expected fix) in \`mesh_enqueue_task\` / \`mesh_send_task\`. Append a structured result request at the end: ask the worker to conclude with a JSON block containing \`status\`, \`changedFiles\`, \`gitStatus\`, \`validationResults\`, \`errors\`, \`nextAction\`. The daemon parses this automatically; you can read it from \`mesh_task_history\`.
51664
- - **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start a fresh session only when: (a) branch/worktree isolation is required, (b) the existing session had a dispatch failure or provider mismatch, (c) the transcript/runtime is contaminated or interrupted, or (d) the user explicitly asks for a different provider/session. Continuation of the same issue in an already-idle session is allowed and preferred \u2014 this rule blocks concurrent unrelated work interleaved into a live (still-generating) session, not sequential same-issue follow-ups.
51665
- - **Worktree affinity.** A worktree is a durable per-branch workspace; keep all of a branch's code_change/fix/review work on its worktree node by targeting \`required_tags: ["worktree=<branch>"]\` or \`target_node_id\`. Get the id/branch from the \`mesh_clone_node\` result or a live \`mesh_status\` \u2014 the Configured Nodes snapshot won't list a worktree cloned after launch. Untargeted same-branch follow-ups drift to the base node. Only \`convergence\` (merge/push) runs on the base, never pinned to the worktree.
51673
+ - **Reuse idle sessions.** For follow-up, retry, commit/push, or cleanup on the same issue, send only the delta to the existing idle session. Start a fresh session only when: (a) branch/worktree isolation is required, (b) the existing session had a dispatch failure or provider mismatch, (c) the transcript/runtime is contaminated or interrupted, (d) the user explicitly asks for a different provider/session, or (e) **the delta is a genuinely NEW subject rather than a continuation** \u2014 a new topic appended to an existing session can be dropped or re-run as the previous task, so give it its own task even when a session sits idle. Continuation of the same issue in an already-idle session is allowed and preferred \u2014 this rule blocks concurrent unrelated work interleaved into a live (still-generating) session, not sequential same-issue follow-ups. The test is subject continuity, not timing: carrying an investigation forward into its own fix is the SAME subject and belongs in that session (Workflow 3f), while an unrelated bug is a new subject even if the same session just went idle.
51674
+ - **Worktree affinity.** A worktree is a durable per-branch workspace; keep all of a branch's code_change/fix/review work on its worktree node. Target it with \`required_tags: ["worktree=<branch>"]\` or \`target_node_id\`. Get the id/branch from the \`mesh_clone_node\` result or a live \`mesh_status\` \u2014 the Configured Nodes snapshot won't list a worktree cloned after launch. Untargeted same-branch follow-ups drift to the base node. Only \`convergence\` (merge/push) runs on the base, never pinned to the worktree.
51666
51675
  - **Classify task difficulty to save tokens.** For each task you enqueue, judge its execution difficulty and pass \`difficulty\`: \`easy\` (extraction, renames, doc tweaks, trivial fixes), \`medium\` (ordinary feature/bugfix work), \`difficult\` (architecture, tricky debugging, multi-file refactors, subtle reasoning), or \`freeform\`. The mesh's per-difficulty brain preset then runs easy tasks on a cheaper model at low reasoning effort and hard tasks on a stronger model at high effort \u2014 real token savings on simple work. The current presets are shown in the "Brain presets" section below. You may still pass an explicit \`model\`/\`thinkingLevel\` to override the preset for one task.
51667
51676
  - **Retune node profiles when routing is a poor fit \u2014 but only with approval.** A node's capability slots (its provider/model/thinking + difficulty range + capability tags, seen via \`mesh_node_slots_list\`) are what task\u2192node fitness routing matches against. If you notice a persistent mismatch \u2014 e.g. every \`difficult\` task lands on a node whose only slot is a cheap model, or a capability a node clearly has isn't declared \u2014 you MAY propose a slot change with \`mesh_node_slots_set\` (write=false). That returns current-vs-proposed; present that diff to the user with a one-line reason and apply (write=true) ONLY after they approve. It is a WHOLESALE replacement of the node's slots, so include the slots you want to keep. Never rewrite a node's profile silently or without a clear routing reason.
51668
51677
  - **Bootstrap a node's slots from what's actually installed.** When a node has NO slots configured (routing then falls back to "first available provider"), or CLI agents were newly installed on it, call \`mesh_node_slots_propose({ node_id })\` instead of hand-writing a profile. It detects the node's installed CLI agents and drafts a slot list from them \u2014 read-only, it never writes. Present its \`proposedSlots\` with the \`droppedSlots\` / \`destructive\` fields it reports (a wholesale write would delete any existing hand-tuned slot the draft doesn't reproduce, including providers not currently on PATH), then apply with \`mesh_node_slots_set({ slots: proposedSlots, write: true })\` after approval. It flags \`unknownProvider\` / \`provisional\` slots whose placement is a conservative guess rather than an attested one \u2014 call those out rather than presenting them as settled.
51669
51678
  - **Respect explicit provider requests.** Map: Hermes \u2192 \`hermes-cli\`, Claude/Claude Code \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`, Antigravity \u2192 \`antigravity-cli\`. Never substitute the coordinator's own runtime.
51670
51679
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
51671
- - **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).
51680
+ - **Match concurrency to task kind.** Read-only investigation (\`live_debug_readonly\`) carries no isolation or merge cost and is exempt from the one-write-per-node limit: dispatch every independent read-only task at once, up to the read-only cap shown in Policy \u2014 they need neither a free node nor a worktree. Write tasks (\`code_change\`) are limited to ONE active task per node, so N parallel write tasks need N nodes; clone worktrees rather than queueing them onto one node. Ramp up cautiously only when tasks share a base branch or a submodule pointer, where landing order actually matters. Never launch a second session onto work already in flight for the same issue, and never duplicate a session because \`mesh_read_chat\` shows no final message while tool/terminal activity is ongoing. All of this is about *unrelated* work running side by side; it does not mean splitting one line of work across sessions \u2014 successive stages of the same investigation belong in the session that already has the context (see Workflow 3f).
51672
51681
  - **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
51673
51682
  - **Don't reopen already-done work after a resume.** Before reopening a reported issue after context compaction or session resume, check current git state and recent session context. If another session has already completed the work, continue from the existing diff/commit instead of starting a duplicate investigation.
51674
51683
  - **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.
@@ -51677,6 +51686,7 @@ ${rules.join("\n")}`;
51677
51686
  - **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\`.
51678
51687
  - **Honor per-node instructions.** When a node carries a \u{1F4CC} Node instruction in the nodes section, include the relevant parts of that instruction in the task message you send to that node. Don't paraphrase the instruction into your own words \u2014 quote it verbatim so the worker agent sees exactly what the user wrote.
51679
51688
  - **Mission status does not update itself.** When a mission's tasks are all done or the work is abandoned, explicitly call \`mesh_mission_upsert\` to set status \`completed\` or \`abandoned\`. Never leave a finished mission in \`active\`. All-cancelled tasks with no further work \u2192 \`abandoned\`.
51689
+ - **Promote durable lessons to operating notes \u2014 especially at mission close.** Before calling \`mesh_mission_upsert\` with status \`completed\`/\`abandoned\`, ask whether this mission taught something a future coordinator needs (a provider quirk, a pattern to avoid, a recovery lesson); if so, call \`mesh_record_note\` FIRST \u2014 a mission's goal/history is invisible to the next coordinator once it completes, so an unrecorded lesson is lost at exactly the moment it was learned. Record only when all three hold: (a) a coordinator on another day or another session would act differently knowing it, (b) it cannot be rediscovered from code, config, or \`git log\`, and (c) it is not a one-off detail specific to this single mission. Note that operating notes reach the COORDINATOR prompt only \u2014 they are never injected into delegated worker sessions, so a convention workers must follow belongs in a CI gate or the repo's agent instructions file, not in a note.
51680
51690
  - **Don't spawn a nested coordinator for simple inspection.** Do not spawn a nested coordinator-like agent for simple inspection tasks. If delegation is required, use explicit provider selection and a fully self-contained, bounded task instruction.
51681
51691
  - **Keep internal traffic out of the transcript.** Internal tool calls, status events, control messages, and debug output must not appear as ordinary user-visible chat transcript content unless explicitly marked user-facing by the producing agent.
51682
51692
  - **Never fabricate tool results.** Always call the actual tool.
@@ -51778,11 +51788,12 @@ Before doing any coordinator work, confirm that the actual callable tool list in
51778
51788
  2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist. If \`mesh_task_history\` shows a recent failure for a task, decide whether to retry or reassign. **For multi-task work, create a mission first**: call \`mesh_mission_upsert\` with a title and goal, then attach every enqueued task with \`mission_id\`. Express "B after A" ordering with \`depends_on\` on the queue task instead of waiting and polling \u2014 the system claims dependents automatically when their dependencies complete. When the mission's outcome is decided, update its status (\`completed\`/\`abandoned\`) via \`mesh_mission_upsert\`. If the prompt already shows an **Active Mission**, continue it from its current task state \u2014 do not re-enqueue tasks that already exist.
51779
51789
  3. **Queue / Delegate** \u2014 The Mesh uses an autonomous pull-based Work Queue:
51780
51790
  a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
51781
- b. **Node Preparation**: Reuse an existing idle session on the correct node/provider before launching a new chat/session. Call \`mesh_launch_session\` only when no suitable session exists, when the user explicitly asks for a fresh provider/session, or when branch/worktree isolation requires it. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
51782
- b1. **Keep a branch's work on its worktree (worktree affinity).** A worktree node is a durable per-branch workspace, not a one-task throwaway \u2014 implement, review, and fix for the same branch all belong on the SAME worktree, and it lives until its work is converged (merged/pushed) and it is cleaned up. So once you clone a worktree for a branch, route every subsequent \`code_change\`/\`validation\`/fix task for that branch back to that same node: pass \`required_tags: ["worktree=<branch>"]\` or \`target_node_id: <that worktree node's id>\`. **Where to get the node id / tag:** the \`mesh_clone_node\` result returns the new node's \`id\` and \`worktreeBranch\` directly \u2014 use them immediately. The Configured Nodes list in this prompt is a launch-time snapshot and will NOT list a worktree you cloned after this session started, so do not rely on it for freshly-cloned worktrees; take the id/branch from the \`mesh_clone_node\` result, or call \`mesh_status\` to re-list the live nodes (each worktree there advertises its \`worktree=<branch>\` tag). Do NOT leave same-branch follow-ups untargeted \u2014 an untargeted task is claimed by whichever node polls first (usually the base machine node), which strands the work off the branch's worktree. The ONE exception is a \`convergence\` task (merge/push): that is base-only and must NOT be pinned to the worktree.
51791
+ b. **Node Preparation**: Reuse an existing idle session on the correct node/provider before launching a new chat/session. Call \`mesh_launch_session\` only when no suitable session exists, when the user explicitly asks for a fresh provider/session, or when branch/worktree isolation requires it. **A node is not limited to one live session for read-only work** \u2014 \`readonly\`/\`live_debug_readonly\` tasks are exempt from the one-active-per-node invariant, so the SAME node can auto-launch multiple concurrent read-only sessions with no worktree needed. Cloning a worktree costs roughly 10 seconds, so it is cheap enough to create one whenever write work needs a free node; use it for branch isolation, for parallel write tasks (one active write per node), or when a node's read-only queue is deep enough that a second node would clearly finish faster \u2014 call \`mesh_clone_node\` to create the worktree node first.
51792
+ b1. **Keep a branch's work on its worktree (worktree affinity).** This is about routing a branch's follow-ups back to its OWN worktree \u2014 it is never a reason to avoid creating a NEW worktree for independent work. A worktree node is a durable per-branch workspace, not a one-task throwaway \u2014 implement, review, and fix for the same branch all belong on the SAME worktree, and it lives until its work is converged (merged/pushed) and it is cleaned up. So once you clone a worktree for a branch, route every subsequent \`code_change\`/\`validation\`/fix task for that branch back to that same node: pass \`required_tags: ["worktree=<branch>"]\` or \`target_node_id: <that worktree node's id>\`. **Where to get the node id / tag:** the \`mesh_clone_node\` result returns the new node's \`id\` and \`worktreeBranch\` directly \u2014 use them immediately. The Configured Nodes list in this prompt is a launch-time snapshot and will NOT list a worktree you cloned after this session started, so do not rely on it for freshly-cloned worktrees; take the id/branch from the \`mesh_clone_node\` result, or call \`mesh_status\` to re-list the live nodes (each worktree there advertises its \`worktree=<branch>\` tag). Do NOT leave same-branch follow-ups untargeted \u2014 an untargeted task is claimed by whichever node polls first (usually the base machine node), which strands the work off the branch's worktree. The ONE exception is a \`convergence\` task (merge/push): that is base-only and must NOT be pinned to the worktree.
51783
51793
  c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
51784
51794
  d. For the first dispatch of a new task, provide a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
51785
51795
  e. For a continuation of the same issue in an existing session, send a concise **delta instruction**: current verified state, the exact failed/blocked step, the newly approved action, and final reporting requirements. Do not resend the full original task or open a new chat solely to continue the same work; that wastes coordinator and worker context.
51796
+ f. **Let the investigator apply the fix when the findings settle it \u2014 otherwise split deliberately.** An investigator that has read the source and named the file:line and the fix already holds context a fresh worker must rebuild from scratch, and you would have to restate its findings in the new task message to get there. Task mode is **per task, not per session**: the read-only guardrail is evaluated on each dispatch from that task's own \`readonly\`/\`task_mode\`, so you hand off by sending a follow-up \`mesh_send_task\` to the SAME session WITHOUT the read-only flag (use \`task_mode: "code_change"\`). You do not need a new session or a fresh worktree for the mode to change. **Hand off in-session when** the findings match your hypothesis, the fix stays inside the files just investigated, and no user decision is pending. **Split to a separate task when** the investigation needs a user decision (it surfaced design options, or a cost/risk tradeoff), when it OVERTURNED your hypothesis so the direction itself needs rethinking, or when the fix touches files another in-flight worker owns. **Never convert an investigation whose own conclusion was "do not change this"** \u2014 a correct no-op finding is a completed task, and pushing it into a fix produces an unverified change nobody asked for. Dispatching the investigation as an ordinary report-first task skips the handoff, but drops the guardrail against premature fixes \u2014 keep \`live_debug_readonly\` whenever the point is to find out whether anything is wrong at all.
51786
51797
  4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Do **not** repeatedly call \`mesh_status\` or \`mesh_view_queue\` just to wait for assigned/generating work. After dispatching a direct or queued task, send one progress update with the task/session handle, then stop. Wait for \`pendingCoordinatorEvents\` or another completion/approval/status signal, an explicit user status request, or a real timeout/stall signal before reading status/chat/queue again. Use at most one compact \`mesh_read_chat\` check after a terminal signal. Handle approvals via \`mesh_approve\`. **Proactively parallelize new work.** When the user reports a new bug or asks for new work, start it immediately if it is independent of in-flight tasks and there is headroom under \`maxParallelTasks\` \u2014 do not wait for a current task to finish or for the user to prompt you to parallelize. Read-only diagnosis (\`live_debug_readonly\`) has no isolation or merge cost, so dispatch it in parallel right away. The no-polling / concurrency-limit rules constrain *re-checking or duplicating already-dispatched work*; they are **not** a reason to defer starting a new, independent task.
51787
51798
  5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
51788
51799
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
@@ -53181,14 +53192,14 @@ When the user asks to **set up / configure / onboard** this repo for Repo Mesh (
53181
53192
  }
53182
53193
  function resolveHermesCoordinatorHome(meshId, workspace) {
53183
53194
  const key2 = `${meshId || "mesh"}
53184
- ${(0, import_node_path3.resolve)(workspace || os8.tmpdir())}`;
53195
+ ${(0, import_node_path3.resolve)(workspace || os7.tmpdir())}`;
53185
53196
  const hash2 = shortHash(key2);
53186
- return (0, import_node_path3.join)(os8.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash2}`);
53197
+ return (0, import_node_path3.join)(os7.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash2}`);
53187
53198
  }
53188
53199
  function resolveMcpConfigPath(configPath, workspace) {
53189
53200
  const trimmed = configPath.trim();
53190
- if (trimmed === "~") return os8.homedir();
53191
- if (trimmed.startsWith("~/")) return (0, import_node_path3.join)(os8.homedir(), trimmed.slice(2));
53201
+ if (trimmed === "~") return os7.homedir();
53202
+ if (trimmed.startsWith("~/")) return (0, import_node_path3.join)(os7.homedir(), trimmed.slice(2));
53192
53203
  if ((0, import_node_path3.isAbsolute)(trimmed)) return trimmed;
53193
53204
  return (0, import_node_path3.join)(workspace, trimmed);
53194
53205
  }
@@ -53394,7 +53405,7 @@ ${rendered}`, "utf-8");
53394
53405
  });
53395
53406
  }
53396
53407
  var import_node_fs3;
53397
- var os8;
53408
+ var os7;
53398
53409
  var import_session_host_core32;
53399
53410
  var import_node_path3;
53400
53411
  var DEFAULT_SERVER_NAME;
@@ -53405,7 +53416,7 @@ ${rendered}`, "utf-8");
53405
53416
  "src/commands/mesh-coordinator.ts"() {
53406
53417
  "use strict";
53407
53418
  import_node_fs3 = require("fs");
53408
- os8 = __toESM2(require("os"));
53419
+ os7 = __toESM2(require("os"));
53409
53420
  import_session_host_core32 = require_dist();
53410
53421
  import_node_path3 = require("path");
53411
53422
  init_logger();
@@ -61201,7 +61212,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
61201
61212
  continue;
61202
61213
  }
61203
61214
  if (!isLaunchableNode(node)) {
61204
- markSkip(nodeId, "node_not_launch_ready");
61215
+ markSkip(nodeId, "node_health_not_launchable");
61205
61216
  continue;
61206
61217
  }
61207
61218
  if (!isMeshNodeFreshEnoughToLaunch(node, freshnessGate)) {
@@ -62240,7 +62251,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
62240
62251
  }
62241
62252
  });
62242
62253
  async function updateDarwinMemoryCache() {
62243
- if (os9.platform() !== "darwin") return;
62254
+ if (os8.platform() !== "darwin") return;
62244
62255
  try {
62245
62256
  const { stdout } = await execAsync2("vm_stat", {
62246
62257
  encoding: "utf-8",
@@ -62264,26 +62275,26 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
62264
62275
  const fileBacked = counts["file_backed"] ?? 0;
62265
62276
  const availPages = free + inactive + speculative + purgeable + fileBacked;
62266
62277
  const bytes = availPages * pageSize;
62267
- cachedDarwinAvail = Number.isFinite(bytes) && bytes >= 0 ? Math.min(bytes, os9.totalmem()) : null;
62278
+ cachedDarwinAvail = Number.isFinite(bytes) && bytes >= 0 ? Math.min(bytes, os8.totalmem()) : null;
62268
62279
  } catch {
62269
62280
  }
62270
62281
  }
62271
62282
  function getHostMemorySnapshot() {
62272
- if (os9.platform() === "darwin" && !darwinMemoryInterval) {
62283
+ if (os8.platform() === "darwin" && !darwinMemoryInterval) {
62273
62284
  updateDarwinMemoryCache();
62274
62285
  darwinMemoryInterval = setInterval(updateDarwinMemoryCache, 3e3);
62275
62286
  darwinMemoryInterval.unref();
62276
62287
  }
62277
- const totalMem = os9.totalmem();
62278
- const freeMem = os9.freemem();
62279
- const availableMem = os9.platform() === "darwin" ? cachedDarwinAvail ?? freeMem : freeMem;
62288
+ const totalMem = os8.totalmem();
62289
+ const freeMem = os8.freemem();
62290
+ const availableMem = os8.platform() === "darwin" ? cachedDarwinAvail ?? freeMem : freeMem;
62280
62291
  return {
62281
62292
  totalMem,
62282
62293
  freeMem,
62283
62294
  availableMem
62284
62295
  };
62285
62296
  }
62286
- var os9;
62297
+ var os8;
62287
62298
  var import_child_process4;
62288
62299
  var import_util3;
62289
62300
  var execAsync2;
@@ -62292,7 +62303,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
62292
62303
  var init_host_memory = __esm2({
62293
62304
  "src/system/host-memory.ts"() {
62294
62305
  "use strict";
62295
- os9 = __toESM2(require("os"));
62306
+ os8 = __toESM2(require("os"));
62296
62307
  import_child_process4 = require("child_process");
62297
62308
  import_util3 = require("util");
62298
62309
  execAsync2 = (0, import_util3.promisify)(import_child_process4.exec);
@@ -63431,8 +63442,8 @@ ${cleanBody}`;
63431
63442
  }
63432
63443
  function buildMachineInfo2(profile = "full") {
63433
63444
  const base = {
63434
- hostname: os10.hostname(),
63435
- platform: os10.platform()
63445
+ hostname: os9.hostname(),
63446
+ platform: os9.platform()
63436
63447
  };
63437
63448
  if (profile === "live") {
63438
63449
  return base;
@@ -63441,23 +63452,23 @@ ${cleanBody}`;
63441
63452
  const memSnap2 = getHostMemorySnapshot();
63442
63453
  return {
63443
63454
  ...base,
63444
- arch: os10.arch(),
63445
- cpus: os10.cpus().length,
63455
+ arch: os9.arch(),
63456
+ cpus: os9.cpus().length,
63446
63457
  totalMem: memSnap2.totalMem,
63447
- release: os10.release()
63458
+ release: os9.release()
63448
63459
  };
63449
63460
  }
63450
63461
  const memSnap = getHostMemorySnapshot();
63451
63462
  return {
63452
63463
  ...base,
63453
- arch: os10.arch(),
63454
- cpus: os10.cpus().length,
63464
+ arch: os9.arch(),
63465
+ cpus: os9.cpus().length,
63455
63466
  totalMem: memSnap.totalMem,
63456
63467
  freeMem: memSnap.freeMem,
63457
63468
  availableMem: memSnap.availableMem,
63458
- loadavg: os10.loadavg(),
63459
- uptime: os10.uptime(),
63460
- release: os10.release()
63469
+ loadavg: os9.loadavg(),
63470
+ uptime: os9.uptime(),
63471
+ release: os9.release()
63461
63472
  };
63462
63473
  }
63463
63474
  function parseMessageTime(value) {
@@ -63694,13 +63705,13 @@ ${cleanBody}`;
63694
63705
  }
63695
63706
  };
63696
63707
  }
63697
- var os10;
63708
+ var os9;
63698
63709
  var READ_DEBUG_ENABLED;
63699
63710
  var recentReadDebugSignatureBySession;
63700
63711
  var init_snapshot2 = __esm2({
63701
63712
  "src/status/snapshot.ts"() {
63702
63713
  "use strict";
63703
- os10 = __toESM2(require("os"));
63714
+ os9 = __toESM2(require("os"));
63704
63715
  init_config();
63705
63716
  init_state_store();
63706
63717
  init_recent_activity();
@@ -67344,6 +67355,40 @@ ${cleanBody}`;
67344
67355
  return false;
67345
67356
  }
67346
67357
  }
67358
+ function queueHoldHardDeadlineExceeded(meshId, row, gate, dispatchedAtMs, nowMs, detail) {
67359
+ const heldMs = nowMs - dispatchedAtMs;
67360
+ if (!Number.isFinite(heldMs) || heldMs < QUEUE_HOLD_HARD_DEADLINE_MS) return false;
67361
+ const auditKey = `${meshId}::${row.id}::${gate}`;
67362
+ if (queueHoldHardDeadlineAudited.has(auditKey)) return true;
67363
+ queueHoldHardDeadlineAudited.add(auditKey);
67364
+ const heldMin = Math.round(heldMs / 6e4);
67365
+ LOG2.warn("MeshReconcile", `Queue-hold HARD DEADLINE exceeded for task ${row.id} on mesh ${meshId}: gate '${gate}'${detail ? ` (${detail})` : ""} held the row 'assigned' for ${heldMin}min (> ${Math.round(QUEUE_HOLD_HARD_DEADLINE_MS / 6e4)}min ceiling) on node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"} \u2014 the hold signal is presumed stale (a lost queue-status write), forcing the bounded reclaim so the node can claim again`);
67366
+ try {
67367
+ appendLedgerEntry(meshId, {
67368
+ kind: "queue_hold_hard_deadline",
67369
+ nodeId: row.assignedNodeId,
67370
+ sessionId: row.assignedSessionId,
67371
+ providerType: row.assignedProviderType,
67372
+ payload: {
67373
+ taskId: row.id,
67374
+ reason: "queue_hold_hard_deadline",
67375
+ gate,
67376
+ heldMs,
67377
+ ceilingMs: QUEUE_HOLD_HARD_DEADLINE_MS,
67378
+ ...detail ? { detail } : {}
67379
+ }
67380
+ });
67381
+ } catch {
67382
+ }
67383
+ traceMeshEventStage("queue_hold_hard_deadline", {
67384
+ taskId: row.id,
67385
+ sessionId: row.assignedSessionId,
67386
+ nodeId: row.assignedNodeId,
67387
+ meshId,
67388
+ event: "agent:generating_completed"
67389
+ }, `${gate} held ${heldMin}min > ceiling \u2014 forcing reclaim`);
67390
+ return true;
67391
+ }
67347
67392
  function resolveAssignedTranscriptProfile(components, row) {
67348
67393
  const stamped = row.assignedTranscriptProfile;
67349
67394
  if (stamped && typeof stamped === "object" && typeof stamped.emitsPtyTurnEvents === "boolean") {
@@ -67533,6 +67578,11 @@ ${cleanBody}`;
67533
67578
  for (const key2 of [...assignedIdleFinalAssistantSince.keys()]) {
67534
67579
  if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) assignedIdleFinalAssistantSince.delete(key2);
67535
67580
  }
67581
+ for (const key2 of [...queueHoldHardDeadlineAudited]) {
67582
+ if (!key2.startsWith(meshKeyPrefix)) continue;
67583
+ const taskKey = key2.slice(0, key2.lastIndexOf("::"));
67584
+ if (!assignedKeys.has(taskKey)) queueHoldHardDeadlineAudited.delete(key2);
67585
+ }
67536
67586
  for (const row of assigned) {
67537
67587
  restampReboundMeshWorkerAssignment(components, store, meshId, row);
67538
67588
  const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
@@ -67681,7 +67731,7 @@ ${cleanBody}`;
67681
67731
  }
67682
67732
  if (verdict === "IDLE_CONFIRMED") {
67683
67733
  deliveredUnconsumedUnknownStreak.delete(shortStreakKey);
67684
- } else if (assignedRowLiveStatusIsAwaitingApproval(mesh, row.assignedNodeId, evidenceSessionId)) {
67734
+ } else if (assignedRowLiveStatusIsAwaitingApproval(mesh, row.assignedNodeId, evidenceSessionId) && !queueHoldHardDeadlineExceeded(meshId, row, "live_awaiting_approval", dispatchedAtMs, nowMs, "short_redrive")) {
67685
67735
  traceMeshEventDrop("short_redrive_deferred_awaiting_approval", {
67686
67736
  taskId: row.id,
67687
67737
  sessionId: row.assignedSessionId,
@@ -67713,7 +67763,15 @@ ${cleanBody}`;
67713
67763
  // the bounded UNKNOWN grace just exhausted above
67714
67764
  nowMs
67715
67765
  });
67716
- if (suspensionGate.kind === "recovered" || suspensionGate.kind === "blocked") {
67766
+ const suspensionHoldExpired = suspensionGate.kind === "blocked" && queueHoldHardDeadlineExceeded(
67767
+ meshId,
67768
+ row,
67769
+ "held_suspension",
67770
+ dispatchedAtMs,
67771
+ nowMs,
67772
+ `short_redrive; stages ${suspensionGate.stages.join("/")}`
67773
+ );
67774
+ if (!suspensionHoldExpired && (suspensionGate.kind === "recovered" || suspensionGate.kind === "blocked")) {
67717
67775
  deliveredUnconsumedUnknownStreak.delete(shortStreakKey);
67718
67776
  traceMeshEventDrop(suspensionGate.kind === "recovered" ? "suspension_consumed_recovered" : "redrive_blocked_by_suspension", {
67719
67777
  taskId: row.id,
@@ -67819,7 +67877,7 @@ ${cleanBody}`;
67819
67877
  if (verdict === "IDLE_CONFIRMED") {
67820
67878
  deliveredNoTurnUnknownStreak.delete(streakKey);
67821
67879
  reclaimReason = "delivered_no_turn_deadline";
67822
- } else if (assignedRowLiveStatusIsAwaitingApproval(mesh, row.assignedNodeId, evidenceSessionId)) {
67880
+ } else if (assignedRowLiveStatusIsAwaitingApproval(mesh, row.assignedNodeId, evidenceSessionId) && !queueHoldHardDeadlineExceeded(meshId, row, "live_awaiting_approval", dispatchedAtMs, nowMs, "delivered_no_turn")) {
67823
67881
  traceMeshEventDrop("reclaim_deferred_awaiting_approval", {
67824
67882
  taskId: row.id,
67825
67883
  sessionId: row.assignedSessionId,
@@ -67852,7 +67910,15 @@ ${cleanBody}`;
67852
67910
  // the bounded UNKNOWN grace just exhausted above
67853
67911
  nowMs
67854
67912
  });
67855
- if (suspensionGate.kind === "recovered" || suspensionGate.kind === "blocked") {
67913
+ const suspensionHoldExpired = suspensionGate.kind === "blocked" && queueHoldHardDeadlineExceeded(
67914
+ meshId,
67915
+ row,
67916
+ "held_suspension",
67917
+ dispatchedAtMs,
67918
+ nowMs,
67919
+ `delivered_no_turn; stages ${suspensionGate.stages.join("/")}`
67920
+ );
67921
+ if (!suspensionHoldExpired && (suspensionGate.kind === "recovered" || suspensionGate.kind === "blocked")) {
67856
67922
  deliveredNoTurnUnknownStreak.delete(streakKey);
67857
67923
  traceMeshEventDrop(suspensionGate.kind === "recovered" ? "suspension_consumed_recovered" : "redrive_blocked_by_suspension", {
67858
67924
  taskId: row.id,
@@ -67923,7 +67989,14 @@ ${cleanBody}`;
67923
67989
  }
67924
67990
  })();
67925
67991
  const attemptStage = readNonEmptyString(currentAttempt?.stage);
67926
- if (currentAttempt && !currentAttempt.terminalOutcome && (attemptStage === "generating" || attemptStage === "waiting_approval" || attemptStage === "waiting_choice" || attemptStage === "finalizing")) {
67992
+ if (currentAttempt && !currentAttempt.terminalOutcome && (attemptStage === "generating" || attemptStage === "waiting_approval" || attemptStage === "waiting_choice" || attemptStage === "finalizing") && !queueHoldHardDeadlineExceeded(
67993
+ meshId,
67994
+ row,
67995
+ "active_attempt_stage",
67996
+ dispatchedAtMs,
67997
+ nowMs,
67998
+ `attempt ${currentAttempt.attemptId} stage ${attemptStage}`
67999
+ )) {
67927
68000
  deliveredNoTurnUnknownStreak.delete(streakKey);
67928
68001
  noteRedriveBlocked("active_attempt_stage");
67929
68002
  traceMeshEventDrop("redrive_blocked_active_attempt", {
@@ -68589,6 +68662,8 @@ ${cleanBody}`;
68589
68662
  var NATIVE_SOURCE_ACTIVITY_STALE_MS;
68590
68663
  var ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS;
68591
68664
  var RECLAIM_UNKNOWN_GRACE_TICKS;
68665
+ var QUEUE_HOLD_HARD_DEADLINE_MS;
68666
+ var queueHoldHardDeadlineAudited;
68592
68667
  var deliveredNoTurnUnknownStreak;
68593
68668
  var deliveredUnconsumedUnknownStreak;
68594
68669
  var ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS;
@@ -68642,6 +68717,8 @@ ${cleanBody}`;
68642
68717
  NATIVE_SOURCE_ACTIVITY_STALE_MS = 10 * 6e4;
68643
68718
  ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS = 25e3;
68644
68719
  RECLAIM_UNKNOWN_GRACE_TICKS = 3;
68720
+ QUEUE_HOLD_HARD_DEADLINE_MS = 90 * 6e4;
68721
+ queueHoldHardDeadlineAudited = /* @__PURE__ */ new Set();
68645
68722
  deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
68646
68723
  deliveredUnconsumedUnknownStreak = /* @__PURE__ */ new Map();
68647
68724
  ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS = 8e3;
@@ -70331,14 +70408,14 @@ ${cleanBody}`;
70331
70408
  }
70332
70409
  return cachedPty;
70333
70410
  }
70334
- var os13;
70411
+ var os12;
70335
70412
  var cachedPty;
70336
70413
  var NodePtyRuntimeTransport;
70337
70414
  var NodePtyTransportFactory;
70338
70415
  var init_pty_transport = __esm2({
70339
70416
  "src/cli-adapters/pty-transport.ts"() {
70340
70417
  "use strict";
70341
- os13 = __toESM2(require("os"));
70418
+ os12 = __toESM2(require("os"));
70342
70419
  init_spawn_env();
70343
70420
  init_resolve_executable();
70344
70421
  NodePtyRuntimeTransport = class {
@@ -70378,9 +70455,9 @@ ${cleanBody}`;
70378
70455
  try {
70379
70456
  const fs54 = require("fs");
70380
70457
  const stat2 = fs54.statSync(cwd);
70381
- if (!stat2.isDirectory()) cwd = os13.homedir();
70458
+ if (!stat2.isDirectory()) cwd = os12.homedir();
70382
70459
  } catch {
70383
- cwd = os13.homedir();
70460
+ cwd = os12.homedir();
70384
70461
  }
70385
70462
  }
70386
70463
  const handle = pty.spawn(resolveWin32Executable(command), args, {
@@ -72843,7 +72920,7 @@ ${cont}` : cont;
72843
72920
  function resolveCliSpawnPlanFromParts(options) {
72844
72921
  const { command, baseArgs, shell, baseEnv, workingDir, extraArgs, extraEnv, geometry, diagnosticCliType, diagnosticProviderVersion } = options;
72845
72922
  const binaryPath = findBinary(command);
72846
- const isWin = os14.platform() === "win32";
72923
+ const isWin = os13.platform() === "win32";
72847
72924
  const allArgs = [...baseArgs ?? [], ...extraArgs ?? []].map(
72848
72925
  (arg) => typeof arg === "string" ? arg.replace(/\{\{workingDir\}\}/g, workingDir) : arg
72849
72926
  );
@@ -72931,13 +73008,13 @@ ${cont}` : cont;
72931
73008
  }
72932
73009
  return "";
72933
73010
  }
72934
- var os14;
73011
+ var os13;
72935
73012
  var path27;
72936
73013
  var import_session_host_core7;
72937
73014
  var init_provider_cli_runtime = __esm2({
72938
73015
  "src/cli-adapters/provider-cli-runtime.ts"() {
72939
73016
  "use strict";
72940
- os14 = __toESM2(require("os"));
73017
+ os13 = __toESM2(require("os"));
72941
73018
  path27 = __toESM2(require("path"));
72942
73019
  init_logger();
72943
73020
  import_session_host_core7 = require_dist();
@@ -73081,7 +73158,7 @@ ${cont}` : cont;
73081
73158
  }
73082
73159
  function expandTemplateRootForEnumeration(template, input) {
73083
73160
  if (!template) return "";
73084
- const posixHome = () => toPosixPath(os15.homedir());
73161
+ const posixHome = () => toPosixPath(os14.homedir());
73085
73162
  let out = template;
73086
73163
  if (out === "~") out = posixHome();
73087
73164
  else if (out.startsWith("~/")) out = `${posixHome()}/${out.slice(2)}`;
@@ -73639,13 +73716,13 @@ ${cont}` : cont;
73639
73716
  if (!template) return null;
73640
73717
  let out = template;
73641
73718
  if (out.startsWith("~/") || out === "~") {
73642
- out = path28.join(os15.homedir(), out.slice(2));
73719
+ out = path28.join(os14.homedir(), out.slice(2));
73643
73720
  }
73644
73721
  out = out.replace(/\$\{([A-Z_][A-Z0-9_]*)(?::-(.*?))?\}/g, (_m, name, fallback) => {
73645
73722
  const v = input.envOverrides?.[name] ?? process.env[name];
73646
73723
  return v != null && v !== "" ? v : fallback ?? "";
73647
73724
  });
73648
- if (out.startsWith("~/")) out = path28.join(os15.homedir(), out.slice(2));
73725
+ if (out.startsWith("~/")) out = path28.join(os14.homedir(), out.slice(2));
73649
73726
  const now = /* @__PURE__ */ new Date();
73650
73727
  const workspaceRaw = input.workspace ?? "";
73651
73728
  let workspaceResolved = workspaceRaw;
@@ -73688,7 +73765,7 @@ ${cont}` : cont;
73688
73765
  function scanProjectsRootForSessionFile(template, input, requestedSessionId) {
73689
73766
  if (!requestedSessionId) return null;
73690
73767
  let head = template;
73691
- if (head.startsWith("~/") || head === "~") head = path28.join(os15.homedir(), head.slice(2));
73768
+ if (head.startsWith("~/") || head === "~") head = path28.join(os14.homedir(), head.slice(2));
73692
73769
  const base = staticTemplateBase(head);
73693
73770
  if (!base) return null;
73694
73771
  let baseStat = null;
@@ -73837,13 +73914,13 @@ ${cont}` : cont;
73837
73914
  if (!template) return null;
73838
73915
  let out = template;
73839
73916
  if (out.startsWith("~/") || out === "~") {
73840
- out = path28.join(os15.homedir(), out.slice(2));
73917
+ out = path28.join(os14.homedir(), out.slice(2));
73841
73918
  }
73842
73919
  out = out.replace(/\$\{([A-Z_][A-Z0-9_]*)(?::-(.*?))?\}/g, (_m, name, fallback) => {
73843
73920
  const v = input.envOverrides?.[name] ?? process.env[name];
73844
73921
  return v != null && v !== "" ? v : fallback ?? "";
73845
73922
  });
73846
- if (out.startsWith("~/")) out = path28.join(os15.homedir(), out.slice(2));
73923
+ if (out.startsWith("~/")) out = path28.join(os14.homedir(), out.slice(2));
73847
73924
  const workspaceRaw = input.workspace ?? "";
73848
73925
  let workspaceResolved = workspaceRaw;
73849
73926
  if (workspaceRaw) {
@@ -74302,7 +74379,7 @@ ${cont}` : cont;
74302
74379
  return t.negate ? !result : result;
74303
74380
  }
74304
74381
  var fs222;
74305
- var os15;
74382
+ var os14;
74306
74383
  var path28;
74307
74384
  var UUID_RE;
74308
74385
  var DEFAULT_TOOL_CALL_TYPES;
@@ -74311,7 +74388,7 @@ ${cont}` : cont;
74311
74388
  "src/providers/spec/native-history-executor.ts"() {
74312
74389
  "use strict";
74313
74390
  fs222 = __toESM2(require("fs"));
74314
- os15 = __toESM2(require("os"));
74391
+ os14 = __toESM2(require("os"));
74315
74392
  path28 = __toESM2(require("path"));
74316
74393
  init_logger();
74317
74394
  init_load_better_sqlite3();
@@ -74607,7 +74684,7 @@ ${cont}` : cont;
74607
74684
  missingBackgroundSourceWarned.add(cliType);
74608
74685
  LOG2.warn("CLI", `[${cliType}] background-task tracking declared but nativeHistory.source missing after provider resolve; background detection inactive`);
74609
74686
  }
74610
- var os16;
74687
+ var os15;
74611
74688
  var import_crypto11;
74612
74689
  var import_session_host_core8;
74613
74690
  var missingBackgroundSourceWarned;
@@ -74616,7 +74693,7 @@ ${cont}` : cont;
74616
74693
  var init_provider_cli_adapter = __esm2({
74617
74694
  "src/cli-adapters/provider-cli-adapter.ts"() {
74618
74695
  "use strict";
74619
- os16 = __toESM2(require("os"));
74696
+ os15 = __toESM2(require("os"));
74620
74697
  import_crypto11 = require("crypto");
74621
74698
  init_logger();
74622
74699
  init_debug_config();
@@ -74643,7 +74720,7 @@ ${cont}` : cont;
74643
74720
  this.transportFactory = transportFactory;
74644
74721
  this.cliType = provider.type;
74645
74722
  this.cliName = provider.name;
74646
- this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os16.homedir()) : workingDir;
74723
+ this.workingDir = workingDir.startsWith("~") ? workingDir.replace(/^~/, os15.homedir()) : workingDir;
74647
74724
  const resolvedConfig = resolveCliAdapterConfig(provider);
74648
74725
  this.timeouts = resolvedConfig.timeouts;
74649
74726
  this.approvalKeys = resolvedConfig.approvalKeys;
@@ -77255,6 +77332,7 @@ ${lastSnapshot}`;
77255
77332
  classifyShadowDivergence: () => classifyShadowDivergence,
77256
77333
  classifyStaleDirectForPrune: () => classifyStaleDirectForPrune,
77257
77334
  cleanupTerminalDirectDispatches: () => cleanupTerminalDirectDispatches,
77335
+ clearAuthCredentials: () => clearAuthCredentials,
77258
77336
  clearDebugTrace: () => clearDebugTrace,
77259
77337
  clearPendingMeshCoordinatorEvents: () => clearPendingMeshCoordinatorEvents,
77260
77338
  collectPendingApprovals: () => collectPendingApprovals,
@@ -77537,6 +77615,7 @@ ${lastSnapshot}`;
77537
77615
  resolveMuted: () => resolveMuted,
77538
77616
  resolveNodeSchedulingPriority: () => resolveNodeSchedulingPriority,
77539
77617
  resolveNotBefore: () => resolveNotBefore,
77618
+ resolveNpmPublishedVersion: () => resolveNpmPublishedVersion,
77540
77619
  resolveProviderChannel: () => resolveProviderChannel,
77541
77620
  resolveProviderMaxParallel: () => resolveProviderMaxParallel,
77542
77621
  resolveScopedMeshId: () => resolveScopedMeshId,
@@ -78878,7 +78957,7 @@ ${lastSnapshot}`;
78878
78957
  };
78879
78958
  init_git_worktree();
78880
78959
  init_config();
78881
- var os62 = __toESM2(require("os"));
78960
+ var os52 = __toESM2(require("os"));
78882
78961
  var path12 = __toESM2(require("path"));
78883
78962
  var import_session_host_core22 = require_dist();
78884
78963
  init_config_dir();
@@ -78922,7 +79001,7 @@ ${lastSnapshot}`;
78922
79001
  var cached22 = null;
78923
79002
  function resolveInstanceContext(options = {}) {
78924
79003
  const env2 = options.env ?? process.env;
78925
- const homeDir = options.homeDir ?? os62.homedir();
79004
+ const homeDir = options.homeDir ?? os52.homedir();
78926
79005
  const envDir = typeof env2.ADHDEV_CONFIG_DIR === "string" ? env2.ADHDEV_CONFIG_DIR.trim() : "";
78927
79006
  const explicitDir = typeof options.configDir === "string" ? options.configDir.trim() : "";
78928
79007
  if (explicitDir && envDir && (0, import_session_host_core22.canonicalizeInstancePath)(explicitDir) !== (0, import_session_host_core22.canonicalizeInstancePath)(envDir)) {
@@ -78943,7 +79022,7 @@ ${lastSnapshot}`;
78943
79022
  }
78944
79023
  function getProcessInstanceContext(options = {}) {
78945
79024
  const envDir = typeof process.env.ADHDEV_CONFIG_DIR === "string" ? process.env.ADHDEV_CONFIG_DIR.trim() : "";
78946
- const key2 = `${envDir}|${os62.homedir()}|${options.standalone ? "standalone" : "daemon"}`;
79025
+ const key2 = `${envDir}|${os52.homedir()}|${options.standalone ? "standalone" : "daemon"}`;
78947
79026
  if (!cached22 || cached22.key !== key2) {
78948
79027
  cached22 = { key: key2, context: resolveInstanceContext({ standalone: options.standalone }) };
78949
79028
  }
@@ -80235,17 +80314,17 @@ ${lastSnapshot}`;
80235
80314
  return null;
80236
80315
  }
80237
80316
  async function detectIDEs(providerLoader) {
80238
- const os30 = (0, import_os3.platform)();
80317
+ const os29 = (0, import_os3.platform)();
80239
80318
  const results = [];
80240
80319
  for (const def of getMergedDefinitions()) {
80241
80320
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
80242
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os30] || []) || []);
80321
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os29] || []) || []);
80243
80322
  let resolvedCli = cliPath;
80244
- if (!resolvedCli && appPath && os30 === "darwin") {
80323
+ if (!resolvedCli && appPath && os29 === "darwin") {
80245
80324
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
80246
80325
  if ((0, import_fs18.existsSync)(bundledCli)) resolvedCli = bundledCli;
80247
80326
  }
80248
- if (!resolvedCli && appPath && os30 === "win32") {
80327
+ if (!resolvedCli && appPath && os29 === "win32") {
80249
80328
  const { dirname: dirname22 } = await import("path");
80250
80329
  const appDir = dirname22(appPath);
80251
80330
  const candidates = [
@@ -80262,7 +80341,7 @@ ${lastSnapshot}`;
80262
80341
  }
80263
80342
  }
80264
80343
  }
80265
- const installed = os30 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
80344
+ const installed = os29 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
80266
80345
  const version2 = null;
80267
80346
  results.push({
80268
80347
  id: def.id,
@@ -86970,7 +87049,7 @@ ${effect.notification.body || ""}`.trim();
86970
87049
  }
86971
87050
  var fs15 = __toESM2(require("fs"));
86972
87051
  var path232 = __toESM2(require("path"));
86973
- var os11 = __toESM2(require("os"));
87052
+ var os10 = __toESM2(require("os"));
86974
87053
  var KEY_TO_VK = {
86975
87054
  Backspace: 8,
86976
87055
  Tab: 9,
@@ -87224,7 +87303,7 @@ ${effect.notification.body || ""}`.trim();
87224
87303
  function resolveSafePath(requestedPath) {
87225
87304
  const rawPath = typeof requestedPath === "string" ? requestedPath.trim() : "";
87226
87305
  const inputPath = rawPath || ".";
87227
- const home = os11.homedir();
87306
+ const home = os10.homedir();
87228
87307
  if (inputPath.startsWith("~")) {
87229
87308
  return path232.resolve(path232.join(home, inputPath.slice(1)));
87230
87309
  }
@@ -89838,12 +89917,13 @@ ${formatManifestValidationIssues2(validation.issues)}`,
89838
89917
  var import_child_process8 = require("child_process");
89839
89918
  var import_child_process9 = require("child_process");
89840
89919
  var fs20 = __toESM2(require("fs"));
89841
- var os12 = __toESM2(require("os"));
89920
+ var os11 = __toESM2(require("os"));
89842
89921
  var path26 = __toESM2(require("path"));
89843
89922
  var import_child_process7 = require("child_process");
89844
89923
  var fs19 = __toESM2(require("fs"));
89845
89924
  var http2 = __toESM2(require("http"));
89846
89925
  var path25 = __toESM2(require("path"));
89926
+ init_track_identity();
89847
89927
  var import_child_process6 = require("child_process");
89848
89928
  init_logger();
89849
89929
  function errorText(error48) {
@@ -90040,7 +90120,9 @@ ${formatManifestValidationIssues2(validation.issues)}`,
90040
90120
  }
90041
90121
  var POINTER_NAME = ".adhdev-current";
90042
90122
  var STABLE_FILES = [POINTER_NAME, "adhdev.cmd", "adhdev.ps1", "adhdev"];
90043
- var DEFAULT_HEALTH_PORT = 19222;
90123
+ function resolveDefaultHealthPort(env2 = process.env) {
90124
+ return getTrackIdentity(resolveBuildTrack(env2)).defaultPort;
90125
+ }
90044
90126
  var DEFAULT_HEALTH_TIMEOUT_MS = 12e4;
90045
90127
  function fetchLocalJson(port, pathname) {
90046
90128
  return new Promise((resolve29) => {
@@ -90379,6 +90461,11 @@ exec "${portableNode}" "${cliEntry}" "$@"
90379
90461
  publishStableShimsAndPointer(layout, versionName);
90380
90462
  hooks.log(`Atomically activated ${versionName}`);
90381
90463
  restarted = hooks.restart(portableNode, stagedCliEntry);
90464
+ if (restarted === null) {
90465
+ hooks.log(`Activated ${targetVersion} without restarting a daemon (none was running)`);
90466
+ await hooks.cleanup(layout, stagedPrefix);
90467
+ return { stagedPrefix, stagedCliEntry, daemonPid: null };
90468
+ }
90382
90469
  const daemonPid = restarted.pid;
90383
90470
  if (!daemonPid || !await hooks.waitForHealth(daemonPid, targetVersion)) {
90384
90471
  throw new Error("replacement daemon did not pass the health/version gate");
@@ -90410,7 +90497,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
90410
90497
  }
90411
90498
  }
90412
90499
  function createDefaultWindowsAtomicHooks(options) {
90413
- const healthPort = options.healthPort ?? DEFAULT_HEALTH_PORT;
90500
+ const healthPort = options.healthPort ?? resolveDefaultHealthPort(options.env);
90414
90501
  const healthTimeoutMs = options.healthTimeoutMs ?? DEFAULT_HEALTH_TIMEOUT_MS;
90415
90502
  return {
90416
90503
  install: (stagedPrefix, portableNode) => {
@@ -90442,7 +90529,10 @@ exec "${portableNode}" "${cliEntry}" "$@"
90442
90529
  },
90443
90530
  restart: (portableNode, stagedCliEntry) => {
90444
90531
  const restartArgv = options.restartArgv.map((arg, index) => index === 0 ? stagedCliEntry : arg);
90445
- if (restartArgv.length === 0) throw new Error("replacement daemon restart arguments are missing");
90532
+ if (restartArgv.length === 0) {
90533
+ options.log("No restart arguments provided (daemon was not running); leaving the activated version in place without starting a daemon");
90534
+ return null;
90535
+ }
90446
90536
  const child = (0, import_child_process7.spawn)(portableNode, restartArgv, {
90447
90537
  detached: true,
90448
90538
  stdio: "ignore",
@@ -90543,6 +90633,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
90543
90633
  }
90544
90634
  var import_session_host_core6 = require_dist();
90545
90635
  init_config();
90636
+ init_track_identity();
90546
90637
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
90547
90638
  function resolveInstanceDir(configDir = getConfigDir2()) {
90548
90639
  const base = path26.basename(configDir).trim();
@@ -90649,7 +90740,7 @@ exec "${portableNode}" "${cliEntry}" "$@"
90649
90740
  const packageRoot = findCurrentPackageRoot(options.currentCliPath || process.argv[1], options.packageName);
90650
90741
  const npmInvocation = resolveSiblingNpmInvocation(options.nodeExecutable || process.execPath, options.platform);
90651
90742
  const platform10 = options.platform || process.platform;
90652
- const homeDir = options.homeDir || os12.homedir();
90743
+ const homeDir = options.homeDir || os11.homedir();
90653
90744
  const instanceDir = options.instanceDir || resolveInstanceDir();
90654
90745
  let installPrefix = packageRoot ? resolveInstallPrefixFromPackageRoot(packageRoot, options.packageName) : null;
90655
90746
  if (platform10 === "win32" && isPortableNode22Prefix(installPrefix, homeDir, instanceDir)) {
@@ -90707,6 +90798,27 @@ exec "${portableNode}" "${cliEntry}" "$@"
90707
90798
  }
90708
90799
  );
90709
90800
  }
90801
+ function resolveNpmPublishedVersion(packageName, tagOrVersion, surface, options = {}) {
90802
+ const args = ["view", `${packageName}@${tagOrVersion}`, "version"];
90803
+ const execOptions = {
90804
+ encoding: "utf-8",
90805
+ ..."timeout" in options ? options.timeout === void 0 ? {} : { timeout: options.timeout } : { timeout: 1e4 },
90806
+ ...options.stdio ? { stdio: options.stdio } : {}
90807
+ };
90808
+ if (options.execFileSync) {
90809
+ const runnerOptions = surface?.execOptions || getNpmExecOptions();
90810
+ return String(options.execFileSync(
90811
+ surface?.npmExecutable || "npm",
90812
+ [...surface?.npmArgsPrefix || [], ...args],
90813
+ {
90814
+ ...execOptions,
90815
+ ...runnerOptions,
90816
+ ...process.platform === "win32" ? { windowsHide: true } : {}
90817
+ }
90818
+ )).trim();
90819
+ }
90820
+ return String(execNpmCommandSync(args, execOptions, surface)).trim();
90821
+ }
90710
90822
  function isManagedSessionHostPid(pid) {
90711
90823
  const commandLine = getProcessCommandLine(pid);
90712
90824
  return !!commandLine && /session-host-daemon/i.test(commandLine);
@@ -90807,24 +90919,75 @@ exec "${portableNode}" "${cliEntry}" "$@"
90807
90919
  function buildManualRecoveryCommand(installCommand) {
90808
90920
  return [installCommand.command, ...installCommand.args].map((part) => /\s/.test(part) ? `"${part}"` : part).join(" ");
90809
90921
  }
90810
- function emitUpgradeFailureNotice(lines, configDir = getConfigDir2()) {
90922
+ var UPGRADE_FAILURE_TARGET_MARKER = "adhdev-upgrade-target:";
90923
+ function emitUpgradeFailureNotice(lines, configDir = getConfigDir2(), options = {}) {
90811
90924
  const body = lines.join("\n");
90812
90925
  appendUpgradeLog(`Upgrade blocked \u2014 user action required:
90813
90926
  ${body}`, configDir);
90927
+ const target = typeof options.targetVersion === "string" ? options.targetVersion.trim() : "";
90928
+ const marker = target ? `${UPGRADE_FAILURE_TARGET_MARKER} ${target}
90929
+ ` : "";
90814
90930
  try {
90815
- fs20.writeFileSync(getUpgradeFailureNoticePath(configDir), `[${(/* @__PURE__ */ new Date()).toISOString()}]
90931
+ fs20.writeFileSync(
90932
+ getUpgradeFailureNoticePath(configDir),
90933
+ `[${(/* @__PURE__ */ new Date()).toISOString()}]
90816
90934
  ${body}
90817
- `, "utf8");
90935
+ ${marker}`,
90936
+ "utf8"
90937
+ );
90818
90938
  } catch {
90819
90939
  }
90820
90940
  }
90941
+ function clearUpgradeFailureNotice(configDir = getConfigDir2()) {
90942
+ const noticePath = getUpgradeFailureNoticePath(configDir);
90943
+ try {
90944
+ fs20.unlinkSync(noticePath);
90945
+ } catch (error48) {
90946
+ if (error48?.code === "ENOENT") return;
90947
+ appendUpgradeLog(
90948
+ `Failed to clear stale upgrade-failure notice (${error48?.code || "error"}): ${noticePath} \u2014 ${error48?.message || String(error48)}. Investigate a file lock or permissions: until it is removed, every daemon boot will keep warning about this ALREADY-RESOLVED failure.`,
90949
+ configDir
90950
+ );
90951
+ }
90952
+ }
90953
+ function formatUpgradeNoticeAge(ageMs2) {
90954
+ if (ageMs2 < 0) return "in the future (clock skew?)";
90955
+ const minutes = Math.floor(ageMs2 / 6e4);
90956
+ if (minutes < 1) return "just now";
90957
+ if (minutes < 60) return `${minutes}m ago`;
90958
+ const hours = Math.floor(minutes / 60);
90959
+ if (hours < 24) return `${hours}h ago`;
90960
+ return `${Math.floor(hours / 24)}d ago`;
90961
+ }
90962
+ function parseUpgradeNoticeTimestamp(notice) {
90963
+ const match = /^\[([^\]\n]+)\]/.exec(notice);
90964
+ if (!match) return null;
90965
+ const parsed = Date.parse(match[1]);
90966
+ return Number.isFinite(parsed) ? new Date(parsed).toISOString() : null;
90967
+ }
90968
+ function parseUpgradeNoticeTargetVersion(notice) {
90969
+ const pattern = new RegExp(`^${UPGRADE_FAILURE_TARGET_MARKER}\\s*(.+)$`, "m");
90970
+ const match = pattern.exec(notice);
90971
+ const value = match?.[1]?.trim();
90972
+ return value ? value : null;
90973
+ }
90821
90974
  function readUpgradeFailureNotice(configDir = getConfigDir2()) {
90822
90975
  try {
90823
90976
  const noticePath = getUpgradeFailureNoticePath(configDir);
90824
90977
  if (!fs20.existsSync(noticePath)) return null;
90825
90978
  const notice = fs20.readFileSync(noticePath, "utf8").trim();
90826
90979
  if (!notice) return null;
90827
- return { noticePath, logPath: getUpgradeLogPath(configDir), notice };
90980
+ const recordedAt = parseUpgradeNoticeTimestamp(notice);
90981
+ const ageMs2 = recordedAt ? Date.now() - Date.parse(recordedAt) : null;
90982
+ return {
90983
+ noticePath,
90984
+ logPath: getUpgradeLogPath(configDir),
90985
+ notice,
90986
+ recordedAt,
90987
+ ageMs: ageMs2,
90988
+ ageLabel: ageMs2 === null ? null : formatUpgradeNoticeAge(ageMs2),
90989
+ targetVersion: parseUpgradeNoticeTargetVersion(notice)
90990
+ };
90828
90991
  } catch {
90829
90992
  return null;
90830
90993
  }
@@ -90930,20 +91093,17 @@ ${body}
90930
91093
  if (payload.skipInstall) {
90931
91094
  appendUpgradeLog("Restart-only mode \u2014 package install skipped, re-spawning daemon");
90932
91095
  spawnDetachedDaemonRestart(restartArgv, payload.cwd);
90933
- try {
90934
- fs20.unlinkSync(getUpgradeFailureNoticePath());
90935
- } catch {
90936
- }
91096
+ clearUpgradeFailureNotice();
90937
91097
  return;
90938
91098
  }
90939
91099
  const instanceDir = resolveInstanceDir();
90940
91100
  const windowsInstallerLayout = resolveWindowsInstallerLayout({
90941
- homeDir: os12.homedir(),
91101
+ homeDir: os11.homedir(),
90942
91102
  installPrefix: installCommand.surface.installPrefix,
90943
91103
  instanceDir
90944
91104
  });
90945
91105
  if (windowsInstallerLayout) {
90946
- const portableNode = findPortableNode22(os12.homedir(), process.execPath, instanceDir);
91106
+ const portableNode = findPortableNode22(os11.homedir(), process.execPath, instanceDir);
90947
91107
  if (!portableNode) {
90948
91108
  throw new Error("installer-managed Windows update requires the portable Node.js 22 runtime");
90949
91109
  }
@@ -90965,8 +91125,9 @@ ${body}
90965
91125
  `Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s2) => s2.pid).join(", ")}`
90966
91126
  );
90967
91127
  }
91128
+ let atomicResult;
90968
91129
  try {
90969
- await performWindowsAtomicUpgrade({
91130
+ atomicResult = await performWindowsAtomicUpgrade({
90970
91131
  layout: windowsInstallerLayout,
90971
91132
  packageName: payload.packageName,
90972
91133
  targetVersion: payload.targetVersion,
@@ -90987,14 +91148,17 @@ ${body}
90987
91148
  `adhdev ${payload.packageName}@${payload.targetVersion} upgrade failed and was rolled back: ${error48?.message || String(error48)}`,
90988
91149
  `Previous version preserved (active prefix: ${windowsInstallerLayout.activePrefix}).`,
90989
91150
  "See daemon-upgrade.log for the full install/health trace. The next daemon start will retry."
90990
- ]);
91151
+ ], getConfigDir2(), { targetVersion: payload.targetVersion });
90991
91152
  throw error48;
90992
91153
  }
90993
- try {
90994
- fs20.unlinkSync(getUpgradeFailureNoticePath());
90995
- } catch {
91154
+ clearUpgradeFailureNotice();
91155
+ if (atomicResult.daemonPid === null) {
91156
+ appendUpgradeLog(
91157
+ `Installer-managed Windows atomic upgrade completed (no daemon was running, so none was started \u2014 run \`${IDENTITY.binaryName} daemon\` to start it)`
91158
+ );
91159
+ } else {
91160
+ appendUpgradeLog("Installer-managed Windows atomic upgrade completed");
90996
91161
  }
90997
- appendUpgradeLog("Installer-managed Windows atomic upgrade completed");
90998
91162
  return;
90999
91163
  }
91000
91164
  await stopForeignNativeAddonHolders(installCommand.surface.packageRoot, { parentPid: payload.parentPid });
@@ -91041,7 +91205,7 @@ ${body}
91041
91205
  notice.push("To recover, reinstall manually:");
91042
91206
  }
91043
91207
  notice.push(` ${buildManualRecoveryCommand(installCommand)}`);
91044
- emitUpgradeFailureNotice(notice);
91208
+ emitUpgradeFailureNotice(notice, getConfigDir2(), { targetVersion: payload.targetVersion });
91045
91209
  }
91046
91210
  throw error48;
91047
91211
  }
@@ -91060,7 +91224,7 @@ ${body}
91060
91224
  "so the running daemon was left on its previous version and was NOT restarted.",
91061
91225
  "To recover, reinstall (this forces the shipped prebuild instead of a source rebuild):",
91062
91226
  ` ${buildManualRecoveryCommand(installCommand)}`
91063
- ]);
91227
+ ], getConfigDir2(), { targetVersion: payload.targetVersion });
91064
91228
  throw error48;
91065
91229
  }
91066
91230
  }
@@ -91070,10 +91234,7 @@ ${body}
91070
91234
  appendUpgradeLog("Post-install staging cleanup complete");
91071
91235
  }
91072
91236
  spawnDetachedDaemonRestart(restartArgv, payload.cwd);
91073
- try {
91074
- fs20.unlinkSync(getUpgradeFailureNoticePath());
91075
- } catch {
91076
- }
91237
+ clearUpgradeFailureNotice();
91077
91238
  }
91078
91239
  function spawnDetachedDaemonRestart(restartArgv, cwd) {
91079
91240
  if (restartArgv.length > 0) {
@@ -91435,7 +91596,7 @@ ${body}
91435
91596
  LOG2.info("Upgrade", "Ignoring deprecated channel hint \u2014 upgrade target is the build track");
91436
91597
  }
91437
91598
  const npmTag = IDENTITY.npmTag;
91438
- const latest = String(execNpmCommandSync(["view", `${pkgName}@${npmTag}`, "version"], { encoding: "utf-8", timeout: 1e4 }, npmSurface)).trim();
91599
+ const latest = resolveNpmPublishedVersion(pkgName, npmTag, npmSurface);
91439
91600
  LOG2.info("Upgrade", `Latest ${pkgName}@${npmTag}: v${latest}`);
91440
91601
  let currentInstalled = null;
91441
91602
  try {
@@ -92073,7 +92234,7 @@ ${body}
92073
92234
  })
92074
92235
  );
92075
92236
  init_dist();
92076
- var os21 = __toESM2(require("os"));
92237
+ var os20 = __toESM2(require("os"));
92077
92238
  var path35 = __toESM2(require("path"));
92078
92239
  var crypto6 = __toESM2(require("crypto"));
92079
92240
  var import_fs19 = require("fs");
@@ -92167,7 +92328,7 @@ ${body}
92167
92328
  }
92168
92329
  }
92169
92330
  init_summary_metadata();
92170
- var os20 = __toESM2(require("os"));
92331
+ var os19 = __toESM2(require("os"));
92171
92332
  var crypto5 = __toESM2(require("crypto"));
92172
92333
  var fs29 = __toESM2(require("fs"));
92173
92334
  init_contracts2();
@@ -92305,7 +92466,7 @@ ${body}
92305
92466
  var path31 = __toESM2(require("path"));
92306
92467
  init_provider_cli_adapter();
92307
92468
  var fs25 = __toESM2(require("fs"));
92308
- var os18 = __toESM2(require("os"));
92469
+ var os17 = __toESM2(require("os"));
92309
92470
  var path30 = __toESM2(require("path"));
92310
92471
  init_terminal_screen();
92311
92472
  var import_session_host_core9 = require_dist();
@@ -92484,12 +92645,12 @@ ${body}
92484
92645
  init_fsm_types();
92485
92646
  init_fsm_loader();
92486
92647
  var fs24 = __toESM2(require("fs"));
92487
- var os17 = __toESM2(require("os"));
92648
+ var os16 = __toESM2(require("os"));
92488
92649
  var path29 = __toESM2(require("path"));
92489
92650
  init_logger();
92490
92651
  function expandHome2(p) {
92491
- if (p === "~") return os17.homedir();
92492
- if (p.startsWith("~/")) return path29.join(os17.homedir(), p.slice(2));
92652
+ if (p === "~") return os16.homedir();
92653
+ if (p.startsWith("~/")) return path29.join(os16.homedir(), p.slice(2));
92493
92654
  return p;
92494
92655
  }
92495
92656
  function realWorkspacePath(workingDir) {
@@ -93299,7 +93460,7 @@ ${body}
93299
93460
  }
93300
93461
  fireDelegate(d) {
93301
93462
  const ev = this.currentEval;
93302
- const task = d.task_template.replace(/\{node\}/g, os18.hostname()).replace(/\{state\.label\}/g, ev?.state.label ?? "").replace(/\{state\.title\}/g, ev?.state.title ?? "").replace(/\{duration_ms\}/g, String(d.after_duration_ms ?? 0));
93463
+ const task = d.task_template.replace(/\{node\}/g, os17.hostname()).replace(/\{state\.label\}/g, ev?.state.label ?? "").replace(/\{state\.title\}/g, ev?.state.title ?? "").replace(/\{duration_ms\}/g, String(d.after_duration_ms ?? 0));
93303
93464
  this.emit({ kind: "delegate", id: d.id, task });
93304
93465
  }
93305
93466
  // ────────────────────────────────────────────────────────────────────
@@ -93597,7 +93758,7 @@ ${body}
93597
93758
  const ctl = (this.spec.control_bar ?? []).find((c) => c.action.type === "attach_image");
93598
93759
  if (!ctl || ctl.action.type !== "attach_image") return;
93599
93760
  const ext = guessExt(mime);
93600
- const tmp = path30.join(os18.tmpdir(), `adhdev-attach-${Date.now()}${ext}`);
93761
+ const tmp = path30.join(os17.tmpdir(), `adhdev-attach-${Date.now()}${ext}`);
93601
93762
  try {
93602
93763
  fs25.writeFileSync(tmp, Buffer.from(blob, "base64"));
93603
93764
  } catch {
@@ -94898,7 +95059,7 @@ ${body}
94898
95059
  init_transcript_claim_registry();
94899
95060
  init_chat_message_normalization();
94900
95061
  init_working_dir();
94901
- var os19 = __toESM2(require("os"));
95062
+ var os18 = __toESM2(require("os"));
94902
95063
  var path322 = __toESM2(require("path"));
94903
95064
  var crypto4 = __toESM2(require("crypto"));
94904
95065
  var fs28 = __toESM2(require("fs"));
@@ -94969,7 +95130,7 @@ ${body}
94969
95130
  const promptParts = [];
94970
95131
  const imageRefs = [];
94971
95132
  const resourceRefs = [];
94972
- const materializeDir = options.materializeDir || path322.join(os19.tmpdir(), "adhdev-input-media");
95133
+ const materializeDir = options.materializeDir || path322.join(os18.tmpdir(), "adhdev-input-media");
94973
95134
  input.parts.forEach((part, index) => {
94974
95135
  if (part.type === "text" && part.text.trim()) {
94975
95136
  promptParts.push(part.text.trim());
@@ -95708,7 +95869,7 @@ ${body}
95708
95869
  * Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
95709
95870
  */
95710
95871
  probeSessionIdFromConfig(probe) {
95711
- const resolvedDbPath = probe.dbPath.replace(/^~/, os20.homedir());
95872
+ const resolvedDbPath = probe.dbPath.replace(/^~/, os19.homedir());
95712
95873
  const now = Date.now();
95713
95874
  if (this.cachedSqliteDbMissingUntil > now) return null;
95714
95875
  if (!fs29.existsSync(resolvedDbPath)) {
@@ -100503,7 +100664,7 @@ ${rawInput}` : rawInput;
100503
100664
  }
100504
100665
  function expandExecutable(command) {
100505
100666
  const trimmed = command.trim();
100506
- return trimmed.startsWith("~") ? path35.join(os21.homedir(), trimmed.slice(1)) : trimmed;
100667
+ return trimmed.startsWith("~") ? path35.join(os20.homedir(), trimmed.slice(1)) : trimmed;
100507
100668
  }
100508
100669
  function commandExists(command) {
100509
100670
  const trimmed = command.trim();
@@ -100653,9 +100814,9 @@ ${rawInput}` : rawInput;
100653
100814
  return false;
100654
100815
  }
100655
100816
  function ensureEmptyDelegatedMcpConfig(workspace) {
100656
- const baseDir = path35.join(os21.tmpdir(), "adhdev-delegated-agent-empty-mcp");
100817
+ const baseDir = path35.join(os20.tmpdir(), "adhdev-delegated-agent-empty-mcp");
100657
100818
  (0, import_fs19.mkdirSync)(baseDir, { recursive: true });
100658
- const workspaceHash = shortHash(path35.resolve(workspace || os21.tmpdir()));
100819
+ const workspaceHash = shortHash(path35.resolve(workspace || os20.tmpdir()));
100659
100820
  const filePath = path35.join(baseDir, `${workspaceHash}.json`);
100660
100821
  (0, import_fs19.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
100661
100822
  return filePath;
@@ -101050,7 +101211,7 @@ ${rawInput}` : rawInput;
101050
101211
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
101051
101212
  const trimmed = (workingDir || "").trim();
101052
101213
  if (!trimmed) throw new Error("working directory required");
101053
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os21.homedir()) : path35.resolve(trimmed);
101214
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os20.homedir()) : path35.resolve(trimmed);
101054
101215
  const normalizedType = this.providerLoader.resolveAlias(cliType);
101055
101216
  const rawProvider = this.providerLoader.getByAlias(cliType);
101056
101217
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -102077,11 +102238,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
102077
102238
  };
102078
102239
  var import_child_process12 = require("child_process");
102079
102240
  var net3 = __toESM2(require("net"));
102080
- var os26 = __toESM2(require("os"));
102241
+ var os25 = __toESM2(require("os"));
102081
102242
  var path46 = __toESM2(require("path"));
102082
102243
  var fs39 = __toESM2(require("fs"));
102083
102244
  var path45 = __toESM2(require("path"));
102084
- var os25 = __toESM2(require("os"));
102245
+ var os24 = __toESM2(require("os"));
102085
102246
  var chokidar = __toESM2(require_chokidar());
102086
102247
  init_hash();
102087
102248
  init_logger();
@@ -102556,7 +102717,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
102556
102717
  init_config();
102557
102718
  init_native_history_executor();
102558
102719
  var fs35 = __toESM2(require("fs"));
102559
- var os24 = __toESM2(require("os"));
102720
+ var os23 = __toESM2(require("os"));
102560
102721
  var path40 = __toESM2(require("path"));
102561
102722
  var fs31 = __toESM2(require("fs"));
102562
102723
  var path36 = __toESM2(require("path"));
@@ -103062,7 +103223,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
103062
103223
  }
103063
103224
  var fs33 = __toESM2(require("fs"));
103064
103225
  var path38 = __toESM2(require("path"));
103065
- var os222 = __toESM2(require("os"));
103226
+ var os21 = __toESM2(require("os"));
103066
103227
  init_load_better_sqlite3();
103067
103228
  init_logger();
103068
103229
  function extractTimestampValue3(value) {
@@ -103086,7 +103247,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
103086
103247
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
103087
103248
  }
103088
103249
  function antigravityRoot() {
103089
- return path38.join(os222.homedir(), ".gemini", "antigravity-cli");
103250
+ return path38.join(os21.homedir(), ".gemini", "antigravity-cli");
103090
103251
  }
103091
103252
  function historyJsonlPath() {
103092
103253
  return path38.join(antigravityRoot(), "history.jsonl");
@@ -103673,11 +103834,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
103673
103834
  }
103674
103835
  var fs34 = __toESM2(require("fs"));
103675
103836
  var path39 = __toESM2(require("path"));
103676
- var os23 = __toESM2(require("os"));
103837
+ var os222 = __toESM2(require("os"));
103677
103838
  init_load_better_sqlite3();
103678
103839
  init_usage_normalize();
103679
- var HERMES_STATE_DB = path39.join(os23.homedir(), ".hermes", "state.db");
103680
- var HERMES_LEGACY_SESSIONS_DIR = path39.join(os23.homedir(), ".hermes", "sessions");
103840
+ var HERMES_STATE_DB = path39.join(os222.homedir(), ".hermes", "state.db");
103841
+ var HERMES_LEGACY_SESSIONS_DIR = path39.join(os222.homedir(), ".hermes", "sessions");
103681
103842
  function statMtimeMs4(p) {
103682
103843
  try {
103683
103844
  return Math.floor(fs34.statSync(p).mtimeMs);
@@ -103962,7 +104123,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
103962
104123
  }
103963
104124
  }
103964
104125
  function resolveClaudePath(workspace, sessionId) {
103965
- const dir = path40.join(os24.homedir(), ".claude", "projects", cwdAsDashes(workspace));
104126
+ const dir = path40.join(os23.homedir(), ".claude", "projects", cwdAsDashes(workspace));
103966
104127
  if (!fs35.existsSync(dir)) return null;
103967
104128
  if (sessionId) {
103968
104129
  const candidate = path40.join(dir, `${sessionId}.jsonl`);
@@ -104084,7 +104245,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
104084
104245
  }
104085
104246
  var AGY_SPAWN_CLAIM_GRACE_MS = 2e3;
104086
104247
  function resolveAntigravityPath(workspace, sessionId, sessionStartedAtMs, instanceId) {
104087
- const agyRoot = path40.join(os24.homedir(), ".gemini", "antigravity-cli");
104248
+ const agyRoot = path40.join(os23.homedir(), ".gemini", "antigravity-cli");
104088
104249
  const owner = antigravityOwnerToken(workspace, sessionStartedAtMs, instanceId);
104089
104250
  if (sessionId && isUuidLikeSessionId2(sessionId)) {
104090
104251
  const dbPath = path40.join(agyRoot, "conversations", `${sessionId}.db`);
@@ -104168,9 +104329,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
104168
104329
  function resolveHermesPath(workspace, sessionId) {
104169
104330
  void workspace;
104170
104331
  void sessionId;
104171
- const dbPath = path40.join(os24.homedir(), ".hermes", "state.db");
104332
+ const dbPath = path40.join(os23.homedir(), ".hermes", "state.db");
104172
104333
  if (fs35.existsSync(dbPath)) return dbPath;
104173
- const dir = path40.join(os24.homedir(), ".hermes", "sessions");
104334
+ const dir = path40.join(os23.homedir(), ".hermes", "sessions");
104174
104335
  if (!fs35.existsSync(dir)) return null;
104175
104336
  return newestRecentFile2(dir, /^session_.*\.json$/);
104176
104337
  }
@@ -104196,7 +104357,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
104196
104357
  return cwd.replace(/\//g, "-");
104197
104358
  }
104198
104359
  function codexSessionsRoot() {
104199
- return path40.join(os24.homedir(), ".codex", "sessions");
104360
+ return path40.join(os23.homedir(), ".codex", "sessions");
104200
104361
  }
104201
104362
  function isUuidLikeSessionId2(sessionId) {
104202
104363
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(sessionId);
@@ -106602,8 +106763,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
106602
106763
  return { updated: false };
106603
106764
  }
106604
106765
  this.log("Downloading latest providers from GitHub...");
106605
- const tmpTar = path45.join(os25.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
106606
- const tmpExtract = path45.join(os25.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
106766
+ const tmpTar = path45.join(os24.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
106767
+ const tmpExtract = path45.join(os24.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
106607
106768
  await this.downloadFile(tarballTarget.url, tmpTar);
106608
106769
  fs39.mkdirSync(tmpExtract, { recursive: true });
106609
106770
  await extractTarballGz(tmpTar, tmpExtract);
@@ -107358,7 +107519,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
107358
107519
  });
107359
107520
  }
107360
107521
  async function killIdeProcess(ideId) {
107361
- const plat = os26.platform();
107522
+ const plat = os25.platform();
107362
107523
  const appName = getMacAppIdentifiers()[ideId];
107363
107524
  const winProcesses = getWinProcessNames()[ideId];
107364
107525
  try {
@@ -107419,7 +107580,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
107419
107580
  }
107420
107581
  }
107421
107582
  async function isIdeRunning(ideId) {
107422
- const plat = os26.platform();
107583
+ const plat = os25.platform();
107423
107584
  try {
107424
107585
  if (plat === "darwin") {
107425
107586
  const appName = getMacAppIdentifiers()[ideId];
@@ -107474,7 +107635,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
107474
107635
  }
107475
107636
  }
107476
107637
  async function detectCurrentWorkspace(ideId) {
107477
- const plat = os26.platform();
107638
+ const plat = os25.platform();
107478
107639
  if (plat === "darwin") {
107479
107640
  try {
107480
107641
  const appName = getMacAppIdentifiers()[ideId];
@@ -107494,7 +107655,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
107494
107655
  const appName = appNameMap[ideId];
107495
107656
  if (appName) {
107496
107657
  const storagePath = path46.join(
107497
- process.env.APPDATA || path46.join(os26.homedir(), "AppData", "Roaming"),
107658
+ process.env.APPDATA || path46.join(os25.homedir(), "AppData", "Roaming"),
107498
107659
  appName,
107499
107660
  "storage.json"
107500
107661
  );
@@ -107516,7 +107677,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
107516
107677
  return void 0;
107517
107678
  }
107518
107679
  async function launchWithCdp(options = {}) {
107519
- const platform10 = os26.platform();
107680
+ const platform10 = os25.platform();
107520
107681
  let targetIde;
107521
107682
  const ides = await detectIDEs(getProviderLoader());
107522
107683
  if (options.ideId) {
@@ -108590,6 +108751,7 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
108590
108751
  if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
108591
108752
  }
108592
108753
  let worktreeCleanup;
108754
+ let remoteForwardedResult;
108593
108755
  if (node?.isLocalWorktree) {
108594
108756
  const nodeDaemonId = typeof node.daemonId === "string" ? node.daemonId.trim() : void 0;
108595
108757
  const isRemoteWorktree = nodeDaemonId && !daemonIdsEquivalent(nodeDaemonId, ctx.deps.statusInstanceId) && ctx.deps.dispatchMeshCommand && !args?._meshDirectDispatch;
@@ -108598,7 +108760,11 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
108598
108760
  ...typeof args === "object" && args !== null ? args : {},
108599
108761
  _meshDirectDispatch: true
108600
108762
  });
108601
- return forwarded ?? { success: false, error: "no response from remote node" };
108763
+ const forwardedResult = forwarded ?? { success: false, error: "no response from remote node" };
108764
+ const forwardedRemoved = forwardedResult.success === true && forwardedResult.removed !== false;
108765
+ if (!forwardedRemoved) return forwardedResult;
108766
+ remoteForwardedResult = forwardedResult;
108767
+ worktreeCleanup = forwardedResult.worktreeCleanup !== null && typeof forwardedResult.worktreeCleanup === "object" ? forwardedResult.worktreeCleanup : void 0;
108602
108768
  }
108603
108769
  const cleanupResult = await ctx.cleanupLocalWorktreeNode({ mesh, node, nodeId, force: args?.force === true });
108604
108770
  if (cleanupResult.success === false) {
@@ -108650,6 +108816,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
108650
108816
  nodeId,
108651
108817
  payload: {
108652
108818
  worktree: !!node?.isLocalWorktree,
108819
+ // Distinguish a removal executed by a remote owning daemon
108820
+ // (this entry records only the coordinator-side membership
108821
+ // reconciliation) from a fully local one.
108822
+ ...remoteForwardedResult ? { removedByRemoteDaemon: true } : {},
108653
108823
  sessionCleanupMode,
108654
108824
  workspace: typeof node?.workspace === "string" ? node.workspace : void 0,
108655
108825
  daemonId: typeof node?.daemonId === "string" ? node.daemonId : void 0,
@@ -108670,6 +108840,10 @@ ${formatManifestValidationIssues2(validation2.issues)}`);
108670
108840
  const orphanedSessionsRemaining = skippedLiveSessionIds.length > 0;
108671
108841
  const orphanNextAction = orphanedSessionsRemaining ? `Live session(s) [${skippedLiveSessionIds.join(", ")}] were skipped and still survive this node removal. Run mesh_cleanup_sessions with mode:'stop_and_delete' and sessionIds:[${skippedLiveSessionIds.map((id) => `'${id}'`).join(", ")}] to release them.` : void 0;
108672
108842
  return {
108843
+ // Remote-forwarded removal: start from the owning daemon's own response
108844
+ // so its detail fields survive, then overlay this coordinator's
108845
+ // membership bookkeeping (removed/ledger/cache) computed above.
108846
+ ...remoteForwardedResult ?? {},
108673
108847
  success: true,
108674
108848
  removed,
108675
108849
  ...residueWarning ? { residueWarning } : {},
@@ -115006,6 +115180,7 @@ ${e?.stderr || ""}`;
115006
115180
  return handle;
115007
115181
  }
115008
115182
  var fs44 = __toESM2(require("fs"));
115183
+ var import_node_os2 = require("os");
115009
115184
  var import_path19 = require("path");
115010
115185
  init_logger();
115011
115186
  init_dist();
@@ -115036,6 +115211,19 @@ ${e?.stderr || ""}`;
115036
115211
  const v = mesh?.policy?.worktreeBaseDir;
115037
115212
  return typeof v === "string" && v.trim() ? v.trim() : void 0;
115038
115213
  }
115214
+ var TRACK_CONFIG_DIR_NAMES = [".adhdev", ".adhdev-preview"];
115215
+ function looksLikeCrossTrackWorktreePath(actualPath, normalizePath2) {
115216
+ const home = normalizePath2((0, import_node_os2.homedir)());
115217
+ return TRACK_CONFIG_DIR_NAMES.some((trackDirName) => {
115218
+ const trackWorktreesDir = (0, import_path19.join)(home, trackDirName, "worktrees");
115219
+ return actualPath === normalizePath2(trackWorktreesDir) || actualPath.startsWith(normalizePath2(trackWorktreesDir) + import_path19.sep);
115220
+ });
115221
+ }
115222
+ function unexpectedPathRecoveryHint(actualPath, normalizePath2, suffix) {
115223
+ const base = "Use git worktree list/status to inspect the path. Retry only after confirming the mesh node metadata points to an ADHDev-managed worktree.";
115224
+ const legacyHint = looksLikeCrossTrackWorktreePath(actualPath, normalizePath2) ? " This path matches the layout used before worktree paths became build-track-aware (oss c24ae254) and is likely a legacy worktree from an older daemon version \u2014 mesh_remove_node will not remove it automatically. To clean it up: run `git worktree remove --force '" + actualPath + "'` directly, then retry mesh_remove_node so it can drop the now-missing-path node from the mesh registry." : "";
115225
+ return base + legacyHint + suffix;
115226
+ }
115039
115227
  function sessionMatchesMeshNode(self, record2, node, nodeId, sessionIds) {
115040
115228
  const sessionId = typeof record2?.sessionId === "string" ? record2.sessionId : "";
115041
115229
  if (!sessionId) return false;
@@ -115120,7 +115308,7 @@ ${e?.stderr || ""}`;
115120
115308
  ok: false,
115121
115309
  code: "mesh_worktree_cleanup_unexpected_path",
115122
115310
  error: `Refusing to remove worktree '${workspace}' because it is not at the expected managed path '${expectedPaths[0]}'`,
115123
- recoveryHint: "Use git worktree list/status to inspect the path. Retry only after confirming the mesh node metadata points to an ADHDev-managed worktree." + sessionPreservedNote
115311
+ recoveryHint: unexpectedPathRecoveryHint(actualPath, normalizePath2, sessionPreservedNote)
115124
115312
  };
115125
115313
  }
115126
115314
  const entries = await listWorktrees2(repoRoot);
@@ -115216,7 +115404,7 @@ ${e?.stderr || ""}`;
115216
115404
  success: false,
115217
115405
  code: "mesh_worktree_cleanup_unexpected_path",
115218
115406
  error: `Refusing to remove worktree '${workspace}' because it is not at the expected managed path '${expectedPaths[0]}'`,
115219
- recoveryHint: "Use git worktree list/status to inspect the path. Retry only after confirming the mesh node metadata points to an ADHDev-managed worktree."
115407
+ recoveryHint: unexpectedPathRecoveryHint(actualPath, normalizePath2, "")
115220
115408
  };
115221
115409
  }
115222
115410
  const entries = await listWorktrees2(repoRoot);
@@ -118324,7 +118512,7 @@ ${e?.stderr || ""}`;
118324
118512
  init_chat_message_normalization();
118325
118513
  var fs47 = __toESM2(require("fs"));
118326
118514
  var path48 = __toESM2(require("path"));
118327
- var os27 = __toESM2(require("os"));
118515
+ var os26 = __toESM2(require("os"));
118328
118516
  var import_os6 = require("os");
118329
118517
  init_config();
118330
118518
  var import_child_process13 = require("child_process");
@@ -118449,7 +118637,7 @@ ${e?.stderr || ""}`;
118449
118637
  function checkPathExists2(paths) {
118450
118638
  for (const p of paths) {
118451
118639
  if (p.includes("*")) {
118452
- const home = os27.homedir();
118640
+ const home = os26.homedir();
118453
118641
  const resolved = p.replace(/\*/g, home.split(path48.sep).pop() || "");
118454
118642
  if (fs47.existsSync(resolved)) return resolved;
118455
118643
  } else {
@@ -120846,7 +121034,7 @@ async (params) => {
120846
121034
  }
120847
121035
  var fs50 = __toESM2(require("fs"));
120848
121036
  var path51 = __toESM2(require("path"));
120849
- var os28 = __toESM2(require("os"));
121037
+ var os27 = __toESM2(require("os"));
120850
121038
  var import_session_host_core11 = require_dist();
120851
121039
  function getAutoImplPid(ctx) {
120852
121040
  const pid = ctx.autoImplProcess?.pid;
@@ -121048,7 +121236,7 @@ async (params) => {
121048
121236
  });
121049
121237
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
121050
121238
  const prompt = buildAutoImplPrompt(ctx, type2, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
121051
- const tmpDir = path51.join(os28.tmpdir(), "adhdev-autoimpl");
121239
+ const tmpDir = path51.join(os27.tmpdir(), "adhdev-autoimpl");
121052
121240
  if (!fs50.existsSync(tmpDir)) fs50.mkdirSync(tmpDir, { recursive: true });
121053
121241
  const promptFile = path51.join(tmpDir, `prompt-${type2}-${Date.now()}.md`);
121054
121242
  fs50.writeFileSync(promptFile, prompt, "utf-8");
@@ -121203,7 +121391,7 @@ async (params) => {
121203
121391
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
121204
121392
  const baseArgs = [...spawn7.args || []].filter((a) => !interactiveFlags.includes(a));
121205
121393
  let shellCmd;
121206
- const isWin = os28.platform() === "win32";
121394
+ const isWin = os27.platform() === "win32";
121207
121395
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
121208
121396
  const promptMode = autoImpl?.promptMode ?? "stdin";
121209
121397
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -121242,7 +121430,7 @@ async (params) => {
121242
121430
  try {
121243
121431
  const pty = require("node-pty");
121244
121432
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
121245
- const isWin2 = os28.platform() === "win32";
121433
+ const isWin2 = os27.platform() === "win32";
121246
121434
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
121247
121435
  name: "xterm-256color",
121248
121436
  cols: import_session_host_core11.DEFAULT_SESSION_HOST_COLS,
@@ -123897,7 +124085,7 @@ data: ${JSON.stringify(msg.data)}
123897
124085
  }
123898
124086
  var import_child_process14 = require("child_process");
123899
124087
  var fs52 = __toESM2(require("fs"));
123900
- var os29 = __toESM2(require("os"));
124088
+ var os28 = __toESM2(require("os"));
123901
124089
  var path53 = __toESM2(require("path"));
123902
124090
  var import_session_host_core15 = require_dist();
123903
124091
  init_logger();
@@ -123969,7 +124157,7 @@ data: ${JSON.stringify(msg.data)}
123969
124157
  }
123970
124158
  let portableNode = null;
123971
124159
  try {
123972
- portableNode = findPortableNode22(os29.homedir(), process.execPath, resolveInstanceDir());
124160
+ portableNode = findPortableNode22(os28.homedir(), process.execPath, resolveInstanceDir());
123973
124161
  } catch (error48) {
123974
124162
  LOG2.warn(
123975
124163
  "SessionHost",
@@ -124469,8 +124657,12 @@ data: ${JSON.stringify(msg.data)}
124469
124657
  loadMeshCoordinatorRegistry();
124470
124658
  const upgradeFailureNotice = readUpgradeFailureNotice();
124471
124659
  if (upgradeFailureNotice) {
124472
- LOG2.warn("Upgrade", `Previous daemon upgrade FAILED and was rolled back \u2014 this daemon is running the previous version. Notice (${upgradeFailureNotice.noticePath}):
124473
- ${upgradeFailureNotice.notice}`);
124660
+ const age = upgradeFailureNotice.ageLabel ? `${upgradeFailureNotice.ageLabel}, recorded ${upgradeFailureNotice.recordedAt}` : "recorded at an unknown time";
124661
+ const target = upgradeFailureNotice.targetVersion ? `, attempted target v${upgradeFailureNotice.targetVersion}` : "";
124662
+ const running = (config2.statusVersion || "").trim().replace(/^v/, "");
124663
+ const supersededHint = upgradeFailureNotice.targetVersion && running && upgradeFailureNotice.targetVersion.replace(/^v/, "") !== running ? ` This notice targets a DIFFERENT version than the one now running (v${running}) \u2014 it is most likely a stale record of an earlier attempt, not a report about this boot.` : "";
124664
+ LOG2.warn("Upgrade", `Previous daemon upgrade FAILED and was rolled back \u2014 this daemon is running the previous version. Notice (${age}${target}) at ${upgradeFailureNotice.noticePath}:
124665
+ ${upgradeFailureNotice.notice}${supersededHint}`);
124474
124666
  }
124475
124667
  const appConfig = loadConfig2();
124476
124668
  const providerSourceMode = appConfig.providerSourceMode || "normal";