@adhdev/daemon-standalone 0.9.82-rc.293 → 0.9.82-rc.295

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
@@ -29983,10 +29983,10 @@ var require_dist3 = __commonJS({
29983
29983
  }
29984
29984
  function getDaemonBuildInfo() {
29985
29985
  if (cached2) return cached2;
29986
- const commit = readInjected(true ? "88f97abcc85d83fe5d5313b229d32a7d76b1208a" : void 0) ?? "unknown";
29987
- const commitShort = readInjected(true ? "88f97abc" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
29988
- const version2 = readInjected(true ? "0.9.82-rc.293" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
29989
- const builtAt = readInjected(true ? "2026-06-16T11:14:20.929Z" : void 0);
29986
+ const commit = readInjected(true ? "dc26917ced80beb84689897738b6edb82208c146" : void 0) ?? "unknown";
29987
+ const commitShort = readInjected(true ? "dc26917c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
29988
+ const version2 = readInjected(true ? "0.9.82-rc.295" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
29989
+ const builtAt = readInjected(true ? "2026-06-16T13:44:55.274Z" : void 0);
29990
29990
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
29991
29991
  return cached2;
29992
29992
  }
@@ -31725,6 +31725,7 @@ ${rules.join("\n")}`;
31725
31725
  - **Verify via git, not source.** Use \`mesh_git_status\` to confirm side effects. Treat agent summaries as self-reports, not verification.
31726
31726
  - **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).
31727
31727
  - **Check history first.** Call \`mesh_task_history\` at session start to avoid duplicate work and inform recovery. On failure, read task history before retrying.
31728
+ - **Sequence shared-base-moving merges.** Parallel dispatch is encouraged, but merging one worktree can advance another in-flight worktree's base \u2014 especially the oss submodule pointer \u2014 turning a clean fast-forward into a diverged rebase (patch-equivalence correctly blocks this). Before merging an in-flight worktree while siblings are also in flight, land in an intentional order, re-clone long-running worktrees from the advanced base, or expect to manually rebase + ff-only the laggards; merging an independent fix mid-flight can strand siblings into a rebase.
31728
31729
  - **Converge branches.** After worktree tasks: refine/fast-forward, or classify as \`pushed_feature_branch_needs_merge\` / \`blocked_review\` / \`cleanup_candidate\` / \`not_mergeable\`. Clean up with \`mesh_remove_node\`.
31729
31730
  - **Refinery is config-driven.** \`mesh_refine_node\` must run validation from \`.adhdev/refine.{json,yaml,yml}\` or \`repo-mesh.refine.*\`. Heuristics are scaffolding only.
31730
31731
  - **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\`.
@@ -45410,10 +45411,12 @@ ${lastSnapshot}`;
45410
45411
  if (/Space to (?:select|toggle)|toggle selection|select multiple|select all that apply/i.test(screenText)) {
45411
45412
  return true;
45412
45413
  }
45413
- const optionCheckbox = /^\s*(?:[❯›>]\s*)?(?:\[[ xX]\]|[☐☒◻◼])\s*\d+\.\s+\S/;
45414
+ const optionCheckbox = `(?:\\[[ xX]\\]|[\u2610\u2612\u25FB\u25FC])`;
45415
+ const beforeNumber = new RegExp(`^\\s*(?:[\u276F\u203A>]\\s*)?${optionCheckbox}\\s*\\d+\\.\\s+\\S`);
45416
+ const afterNumber = new RegExp(`^\\s*(?:[\u276F\u203A>]\\s*)?\\d+\\.\\s*${optionCheckbox}\\s+\\S`);
45414
45417
  for (const line of screenText.split(/\r?\n/)) {
45415
45418
  if (line.includes("\u2714 Submit")) continue;
45416
- if (optionCheckbox.test(line)) return true;
45419
+ if (beforeNumber.test(line) || afterNumber.test(line)) return true;
45417
45420
  }
45418
45421
  return false;
45419
45422
  }
@@ -45553,6 +45556,16 @@ ${lastSnapshot}`;
45553
45556
  ...allowFreeform ? { allowFreeform: true } : {}
45554
45557
  };
45555
45558
  }
45559
+ function readFocusedClaudeTuiQuestion(screenText) {
45560
+ if (!screenText.includes("Enter to select")) return null;
45561
+ const parsed = parseClaudeInteractiveTuiQuestion({ screenText }, 0);
45562
+ if (!parsed) return null;
45563
+ return {
45564
+ question: parsed.question,
45565
+ ...parsed.header ? { header: parsed.header } : {},
45566
+ multiSelect: parsed.multiSelect
45567
+ };
45568
+ }
45556
45569
  function detectClaudeAskUserQuestionPromptFromTuiPages(pages, options) {
45557
45570
  if (pages.length === 0) return null;
45558
45571
  const headers = claudeTuiQuestionHeaders(pages[0].screenText);
@@ -51597,22 +51610,160 @@ ${cleanBody}`;
51597
51610
  if (!Number.isFinite(numericOffset) || !Number.isFinite(numericExclude)) return false;
51598
51611
  return true;
51599
51612
  }
51613
+ var REVERSE_TAIL_SMALL_FILE_BYTES = 64 * 1024;
51614
+ var REVERSE_TAIL_CHUNK_BYTES = 64 * 1024;
51615
+ var TAIL_LINES_RETAINED = BOUNDED_TAIL_MAX_LIMIT + 2 * BOUNDED_TAIL_SLACK;
51616
+ var INCREMENTAL_TAIL_CACHE_MAX_ENTRIES = 64;
51617
+ var incrementalTailCache = /* @__PURE__ */ new Map();
51618
+ function evictIncrementalTailCache() {
51619
+ while (incrementalTailCache.size > INCREMENTAL_TAIL_CACHE_MAX_ENTRIES) {
51620
+ const oldest = incrementalTailCache.keys().next().value;
51621
+ if (oldest === void 0) break;
51622
+ incrementalTailCache.delete(oldest);
51623
+ }
51624
+ }
51625
+ function splitBufferLines(buf) {
51626
+ const lines = [];
51627
+ let lineEnd = buf.length;
51628
+ let firstNewline = -1;
51629
+ for (let i = buf.length - 1; i >= 0; i--) {
51630
+ if (buf[i] !== 10) continue;
51631
+ if (i + 1 < lineEnd) {
51632
+ lines.push(buf.toString("utf-8", i + 1, lineEnd));
51633
+ }
51634
+ lineEnd = i;
51635
+ firstNewline = i;
51636
+ }
51637
+ lines.reverse();
51638
+ const head = firstNewline >= 0 ? buf.subarray(0, firstNewline) : buf;
51639
+ return { head, lines };
51640
+ }
51641
+ function readReverseTailLines(filePath, needed) {
51642
+ const fd = fs52.openSync(filePath, "r");
51643
+ try {
51644
+ const stat2 = fs52.fstatSync(fd);
51645
+ const size = stat2.size;
51646
+ let position = size;
51647
+ let carry = Buffer.alloc(0);
51648
+ const collected = [];
51649
+ while (position > 0 && collected.length < needed) {
51650
+ const chunkSize = Math.min(REVERSE_TAIL_CHUNK_BYTES, position);
51651
+ position -= chunkSize;
51652
+ const chunk = Buffer.alloc(chunkSize);
51653
+ fs52.readSync(fd, chunk, 0, chunkSize, position);
51654
+ const combined = carry.length ? Buffer.concat([chunk, carry]) : chunk;
51655
+ const { head, lines } = splitBufferLines(combined);
51656
+ carry = head;
51657
+ for (let i = lines.length - 1; i >= 0; i--) {
51658
+ collected.push(lines[i]);
51659
+ }
51660
+ }
51661
+ const reachedStart = position <= 0;
51662
+ if (reachedStart && carry.length) {
51663
+ collected.push(carry.toString("utf-8"));
51664
+ }
51665
+ collected.reverse();
51666
+ return { lines: collected, coversWholeFile: reachedStart, size, mtimeMs: stat2.mtimeMs };
51667
+ } finally {
51668
+ fs52.closeSync(fd);
51669
+ }
51670
+ }
51671
+ function readFileTailLines(filePath, needed) {
51672
+ let stat2;
51673
+ try {
51674
+ stat2 = fs52.statSync(filePath);
51675
+ } catch {
51676
+ return { lines: [], coversWholeFile: true };
51677
+ }
51678
+ const size = stat2.size;
51679
+ const mtimeMs = stat2.mtimeMs;
51680
+ if (size === 0) {
51681
+ incrementalTailCache.delete(filePath);
51682
+ return { lines: [], coversWholeFile: true };
51683
+ }
51684
+ const cached22 = incrementalTailCache.get(filePath);
51685
+ if (cached22) {
51686
+ if (cached22.size === size && cached22.mtimeMs === mtimeMs) {
51687
+ incrementalTailCache.delete(filePath);
51688
+ incrementalTailCache.set(filePath, cached22);
51689
+ if (cached22.coversWholeFile || cached22.lines.length >= needed) {
51690
+ return { lines: cached22.lines, coversWholeFile: cached22.coversWholeFile };
51691
+ }
51692
+ } else if (size > cached22.size) {
51693
+ const incremental = tryIncrementalTailGrowth(filePath, cached22, size, mtimeMs, needed);
51694
+ if (incremental) return { lines: incremental.lines, coversWholeFile: incremental.coversWholeFile };
51695
+ }
51696
+ incrementalTailCache.delete(filePath);
51697
+ }
51698
+ if (size <= REVERSE_TAIL_SMALL_FILE_BYTES) {
51699
+ let content;
51700
+ try {
51701
+ content = fs52.readFileSync(filePath, "utf-8");
51702
+ } catch {
51703
+ return { lines: [], coversWholeFile: true };
51704
+ }
51705
+ const lines = content.split("\n");
51706
+ if (lines.length && lines[lines.length - 1] === "") lines.pop();
51707
+ storeIncrementalTailCache(filePath, size, mtimeMs, lines, true);
51708
+ return { lines, coversWholeFile: true };
51709
+ }
51710
+ let result;
51711
+ try {
51712
+ result = readReverseTailLines(filePath, needed);
51713
+ } catch {
51714
+ return { lines: [], coversWholeFile: true };
51715
+ }
51716
+ storeIncrementalTailCache(filePath, result.size, result.mtimeMs, result.lines, result.coversWholeFile);
51717
+ return { lines: result.lines, coversWholeFile: result.coversWholeFile };
51718
+ }
51719
+ function tryIncrementalTailGrowth(filePath, cached22, size, mtimeMs, needed) {
51720
+ const fd = fs52.openSync(filePath, "r");
51721
+ try {
51722
+ if (cached22.size > 0) {
51723
+ const boundary = Buffer.alloc(1);
51724
+ fs52.readSync(fd, boundary, 0, 1, cached22.size - 1);
51725
+ if (boundary[0] !== 10) return null;
51726
+ }
51727
+ const appendedLength = size - cached22.size;
51728
+ const appended = Buffer.alloc(appendedLength);
51729
+ fs52.readSync(fd, appended, 0, appendedLength, cached22.size);
51730
+ const newLines = appended.toString("utf-8").split("\n");
51731
+ if (newLines.length && newLines[newLines.length - 1] === "") newLines.pop();
51732
+ const merged = cached22.lines.concat(newLines);
51733
+ const trimmed = merged.length > TAIL_LINES_RETAINED ? merged.slice(merged.length - TAIL_LINES_RETAINED) : merged;
51734
+ const coversWholeFile = cached22.coversWholeFile && trimmed.length === merged.length;
51735
+ storeIncrementalTailCache(filePath, size, mtimeMs, trimmed, coversWholeFile);
51736
+ if (coversWholeFile || trimmed.length >= needed) {
51737
+ return { lines: trimmed, coversWholeFile };
51738
+ }
51739
+ return { lines: trimmed, coversWholeFile };
51740
+ } catch {
51741
+ return null;
51742
+ } finally {
51743
+ fs52.closeSync(fd);
51744
+ }
51745
+ }
51746
+ function storeIncrementalTailCache(filePath, size, mtimeMs, lines, coversWholeFile) {
51747
+ const retained = lines.length > TAIL_LINES_RETAINED ? lines.slice(lines.length - TAIL_LINES_RETAINED) : lines;
51748
+ const covers = coversWholeFile && retained.length === lines.length;
51749
+ incrementalTailCache.delete(filePath);
51750
+ incrementalTailCache.set(filePath, { size, mtimeMs, lines: retained, coversWholeFile: covers });
51751
+ evictIncrementalTailCache();
51752
+ }
51600
51753
  function readBoundedTailRecords(agentType, dir, files, needed) {
51601
51754
  const collected = [];
51602
51755
  const seen = /* @__PURE__ */ new Set();
51603
51756
  let readAllFiles = true;
51604
51757
  for (let f = 0; f < files.length; f++) {
51605
51758
  const filePath = path12.join(dir, files[f]);
51606
- let content;
51607
- try {
51608
- content = fs52.readFileSync(filePath, "utf-8");
51609
- } catch {
51610
- continue;
51611
- }
51612
- const lines = content.trim().split("\n").filter(Boolean);
51759
+ const remaining = Math.max(0, needed - collected.length);
51760
+ const perFileNeeded = Math.min(needed, remaining + BOUNDED_TAIL_SLACK);
51761
+ const { lines, coversWholeFile } = readFileTailLines(filePath, perFileNeeded);
51613
51762
  for (let i = lines.length - 1; i >= 0; i--) {
51763
+ const line = lines[i];
51764
+ if (!line) continue;
51614
51765
  try {
51615
- const parsed = JSON.parse(lines[i]);
51766
+ const parsed = JSON.parse(line);
51616
51767
  const sanitizedMessage = sanitizeHistoryMessage(agentType, parsed);
51617
51768
  if (!sanitizedMessage) continue;
51618
51769
  const hash2 = buildHistoryMessageHash(agentType, sanitizedMessage);
@@ -51622,6 +51773,10 @@ ${cleanBody}`;
51622
51773
  } catch {
51623
51774
  }
51624
51775
  }
51776
+ if (!coversWholeFile) {
51777
+ readAllFiles = false;
51778
+ break;
51779
+ }
51625
51780
  if (collected.length >= needed && f < files.length - 1) {
51626
51781
  readAllFiles = false;
51627
51782
  break;
@@ -61492,12 +61647,14 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61492
61647
  }
61493
61648
  this.maybeClearResolvedClaudeTuiPrompt();
61494
61649
  this.maybeCaptureClaudeTuiPrompt();
61650
+ this.maybeUpgradeClaudeTuiMultiSelect();
61495
61651
  this.statusCallback?.();
61496
61652
  return;
61497
61653
  case "pty_data":
61498
61654
  this.detectInteractivePromptFromPtyChunk(ev.chunk);
61499
61655
  this.maybeClearResolvedClaudeTuiPrompt();
61500
61656
  this.maybeCaptureClaudeTuiPrompt();
61657
+ this.maybeUpgradeClaudeTuiMultiSelect();
61501
61658
  try {
61502
61659
  this.ptyDataCallback?.(ev.chunk);
61503
61660
  } catch {
@@ -61646,6 +61803,53 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61646
61803
  this.claudeTuiPromptCaptureInFlight = false;
61647
61804
  });
61648
61805
  }
61806
+ /**
61807
+ * The TUI prompt is captured on the FIRST frame that renders the
61808
+ * "Enter to select" footer. At that instant the option rows' checkbox
61809
+ * column may not have drawn yet, so `detectClaudeTuiMultiSelect` returns
61810
+ * false and the prompt is frozen as single-select — the dashboard then
61811
+ * renders radio buttons even though the picker is multi-select.
61812
+ *
61813
+ * While the same TUI prompt is still on screen, re-check the live snapshot:
61814
+ * if checkbox glyphs have since appeared, promote any single-select
61815
+ * question to multi-select and re-emit status. Promotion is one-way
61816
+ * (false→true only) — once a question is known multi-select we never demote
61817
+ * it, since the glyph column can scroll out of view on later frames.
61818
+ *
61819
+ * For MULTI-question prompts the per-page Tab capture is the actual source
61820
+ * of the bug: pages 2..N are snapshotted ~120ms after the Tab keypress,
61821
+ * before their option-row glyph column has redrawn, so those questions
61822
+ * freeze as single-select while page 1 (already settled) is correct. We
61823
+ * cannot upgrade blindly — the live snapshot shows only ONE focused page —
61824
+ * but we CAN read that page's question text/header and upgrade the matching
61825
+ * question. As the user navigates the picker (or it settles), each page is
61826
+ * eventually re-read and repaired.
61827
+ */
61828
+ maybeUpgradeClaudeTuiMultiSelect() {
61829
+ if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
61830
+ const questions = this.activeInteractivePrompt.questions;
61831
+ if (questions.every((q) => q.multiSelect)) return;
61832
+ let screenText = "";
61833
+ try {
61834
+ screenText = this.driver.snapshot();
61835
+ } catch {
61836
+ return;
61837
+ }
61838
+ if (!screenText.includes("Enter to select")) return;
61839
+ if (questions.length === 1) {
61840
+ if (questions[0].multiSelect) return;
61841
+ if (!detectClaudeTuiMultiSelect(screenText)) return;
61842
+ questions[0].multiSelect = true;
61843
+ this.statusCallback?.();
61844
+ return;
61845
+ }
61846
+ const focused = readFocusedClaudeTuiQuestion(screenText);
61847
+ if (!focused || !focused.multiSelect) return;
61848
+ const match = questions.find((q) => focused.header && q.header && q.header === focused.header || q.question === focused.question);
61849
+ if (!match || match.multiSelect) return;
61850
+ match.multiSelect = true;
61851
+ this.statusCallback?.();
61852
+ }
61649
61853
  readClaudeTuiHeaders(screenText) {
61650
61854
  const navLine = screenText.split(/\r?\n/).find((line) => line.includes("\u2714 Submit") && /[☐☒]/.test(line));
61651
61855
  if (!navLine) return [];
@@ -61787,6 +61991,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61787
61991
  }
61788
61992
  return normalizedId;
61789
61993
  }
61994
+ var STATUS_HYDRATION_TAIL_LIMIT = 200;
61790
61995
  function isIdleStatus(value) {
61791
61996
  const status = typeof value === "string" ? value.trim().toLowerCase() : "";
61792
61997
  return !status || status === "idle" || status === "ready";
@@ -63449,12 +63654,14 @@ ${effect.notification.body || ""}`.trim();
63449
63654
  const newestMessageAt = parsedMessages.reduce((newest, message) => Math.max(newest, getMessageTime(message)), 0);
63450
63655
  return newestMessageAt === 0;
63451
63656
  }
63452
- syncCanonicalSavedHistoryIfNeeded() {
63657
+ syncCanonicalSavedHistoryIfNeeded(options = {}) {
63453
63658
  if (!this.providerSessionId) return false;
63454
63659
  const canonicalHistory = this.provider.nativeHistory;
63455
63660
  if (!canonicalHistory) return false;
63661
+ const limit = options.full ? Number.MAX_SAFE_INTEGER : STATUS_HYDRATION_TAIL_LIMIT;
63662
+ const windowTag = options.full ? "full" : `tail:${STATUS_HYDRATION_TAIL_LIMIT}`;
63456
63663
  if (isNativeSourceCanonicalHistory(canonicalHistory)) {
63457
- const cacheKey = [this.type, this.providerSessionId, this.workingDir].join("\0");
63664
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, windowTag].join("\0");
63458
63665
  const now = Date.now();
63459
63666
  if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
63460
63667
  return true;
@@ -63466,7 +63673,7 @@ ${effect.notification.body || ""}`.trim();
63466
63673
  historySessionId: this.providerSessionId,
63467
63674
  workspace: this.workingDir,
63468
63675
  offset: 0,
63469
- limit: Number.MAX_SAFE_INTEGER,
63676
+ limit,
63470
63677
  historyBehavior: this.provider.historyBehavior,
63471
63678
  scripts: this.provider.scripts
63472
63679
  });
@@ -63482,7 +63689,7 @@ ${effect.notification.body || ""}`.trim();
63482
63689
  return true;
63483
63690
  }
63484
63691
  try {
63485
- const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror"].join("\0");
63692
+ const cacheKey = [this.type, this.providerSessionId, this.workingDir, canonicalHistory.mode || "materialized-mirror", windowTag].join("\0");
63486
63693
  const now = Date.now();
63487
63694
  if (cacheKey === this.lastNativeSourceCanonicalCacheKey && now - this.lastNativeSourceCanonicalCheckAt < 2e3) {
63488
63695
  return true;
@@ -63492,7 +63699,7 @@ ${effect.notification.body || ""}`.trim();
63492
63699
  if (!materializeProviderNativeHistory(this.type, canonicalHistory, this.providerSessionId, this.workingDir, this.provider.scripts)) {
63493
63700
  return false;
63494
63701
  }
63495
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
63702
+ const restoredHistory = readChatHistory(this.type, 0, limit, this.providerSessionId, 0, this.provider.historyBehavior);
63496
63703
  this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
63497
63704
  role: message.role,
63498
63705
  content: message.content,
@@ -63507,7 +63714,7 @@ ${effect.notification.body || ""}`.trim();
63507
63714
  }
63508
63715
  restorePersistedHistoryFromCurrentSession() {
63509
63716
  if (!this.providerSessionId) return;
63510
- this.syncCanonicalSavedHistoryIfNeeded();
63717
+ this.syncCanonicalSavedHistoryIfNeeded({ full: true });
63511
63718
  const restoredHistory = isNativeSourceCanonicalHistory(this.provider.nativeHistory) ? readProviderChatHistory(this.type, {
63512
63719
  canonicalHistory: this.provider.nativeHistory,
63513
63720
  historySessionId: this.providerSessionId,