@adhdev/daemon-standalone 0.9.82-rc.294 → 0.9.82-rc.296

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 ? "6ee0e52b0b7347870577ebe598054d87127078fe" : void 0) ?? "unknown";
29987
- const commitShort = readInjected(true ? "6ee0e52b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
29988
- const version2 = readInjected(true ? "0.9.82-rc.294" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
29989
- const builtAt = readInjected(true ? "2026-06-16T12:16:10.838Z" : void 0);
29986
+ const commit = readInjected(true ? "473dc8f049daf72ff7977b90e35ddde4e54f1c2f" : void 0) ?? "unknown";
29987
+ const commitShort = readInjected(true ? "473dc8f0" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
29988
+ const version2 = readInjected(true ? "0.9.82-rc.296" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
29989
+ const builtAt = readInjected(true ? "2026-06-16T14:24:57.627Z" : void 0);
29990
29990
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
29991
29991
  return cached2;
29992
29992
  }
@@ -45411,10 +45411,12 @@ ${lastSnapshot}`;
45411
45411
  if (/Space to (?:select|toggle)|toggle selection|select multiple|select all that apply/i.test(screenText)) {
45412
45412
  return true;
45413
45413
  }
45414
- 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`);
45415
45417
  for (const line of screenText.split(/\r?\n/)) {
45416
45418
  if (line.includes("\u2714 Submit")) continue;
45417
- if (optionCheckbox.test(line)) return true;
45419
+ if (beforeNumber.test(line) || afterNumber.test(line)) return true;
45418
45420
  }
45419
45421
  return false;
45420
45422
  }
@@ -45554,6 +45556,16 @@ ${lastSnapshot}`;
45554
45556
  ...allowFreeform ? { allowFreeform: true } : {}
45555
45557
  };
45556
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
+ }
45557
45569
  function detectClaudeAskUserQuestionPromptFromTuiPages(pages, options) {
45558
45570
  if (pages.length === 0) return null;
45559
45571
  const headers = claudeTuiQuestionHeaders(pages[0].screenText);
@@ -45577,7 +45589,8 @@ ${lastSnapshot}`;
45577
45589
  const answer = response.answers[question.questionId];
45578
45590
  if (!answer) throw new Error(`Missing answer for ${question.questionId}`);
45579
45591
  const freeformText = answer.freeformText?.trim() ?? "";
45580
- if (question.multiSelect) {
45592
+ const treatAsMultiSelect = question.multiSelect || answer.selectedLabels.length > 1;
45593
+ if (treatAsMultiSelect) {
45581
45594
  const labels = answer.selectedLabels;
45582
45595
  if (labels.length === 0) {
45583
45596
  throw new Error(`Expected at least one selected label for ${question.questionId}`);
@@ -61736,6 +61749,15 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61736
61749
  * spirit as the approval FSM's `approvalCooldown` modal-lost hysteresis.
61737
61750
  */
61738
61751
  static INTERACTIVE_PROMPT_LOST_GRACE_MS = 1500;
61752
+ /**
61753
+ * Multi-question TUI capture: after Tabbing to a page, re-snapshot at this
61754
+ * interval until its checkbox glyph column has settled, up to the timeout.
61755
+ * The interval matches the legacy single fixed wait (120ms); the timeout
61756
+ * bounds total capture time so a single-select page (which never shows
61757
+ * glyphs) doesn't stall the capture indefinitely.
61758
+ */
61759
+ static CLAUDE_TUI_PAGE_POLL_INTERVAL_MS = 120;
61760
+ static CLAUDE_TUI_PAGE_SETTLE_TIMEOUT_MS = 600;
61739
61761
  /**
61740
61762
  * Clear a held interactive prompt once the user has resolved it directly
61741
61763
  * in the terminal (the choice picker leaves the screen without going
@@ -61803,12 +61825,20 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61803
61825
  * question to multi-select and re-emit status. Promotion is one-way
61804
61826
  * (false→true only) — once a question is known multi-select we never demote
61805
61827
  * it, since the glyph column can scroll out of view on later frames.
61828
+ *
61829
+ * For MULTI-question prompts the per-page Tab capture is the actual source
61830
+ * of the bug: pages 2..N are snapshotted ~120ms after the Tab keypress,
61831
+ * before their option-row glyph column has redrawn, so those questions
61832
+ * freeze as single-select while page 1 (already settled) is correct. We
61833
+ * cannot upgrade blindly — the live snapshot shows only ONE focused page —
61834
+ * but we CAN read that page's question text/header and upgrade the matching
61835
+ * question. As the user navigates the picker (or it settles), each page is
61836
+ * eventually re-read and repaired.
61806
61837
  */
61807
61838
  maybeUpgradeClaudeTuiMultiSelect() {
61808
61839
  if (this.cliType !== "claude-cli" || this.interactivePromptTransport !== "tui" || !this.activeInteractivePrompt) return;
61809
61840
  const questions = this.activeInteractivePrompt.questions;
61810
- if (questions.length !== 1) return;
61811
- if (questions[0].multiSelect) return;
61841
+ if (questions.every((q) => q.multiSelect)) return;
61812
61842
  let screenText = "";
61813
61843
  try {
61814
61844
  screenText = this.driver.snapshot();
@@ -61816,8 +61846,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61816
61846
  return;
61817
61847
  }
61818
61848
  if (!screenText.includes("Enter to select")) return;
61819
- if (!detectClaudeTuiMultiSelect(screenText)) return;
61820
- questions[0].multiSelect = true;
61849
+ if (questions.length === 1) {
61850
+ if (questions[0].multiSelect) return;
61851
+ if (!detectClaudeTuiMultiSelect(screenText)) return;
61852
+ questions[0].multiSelect = true;
61853
+ this.statusCallback?.();
61854
+ return;
61855
+ }
61856
+ const focused = readFocusedClaudeTuiQuestion(screenText);
61857
+ if (!focused || !focused.multiSelect) return;
61858
+ const match = questions.find((q) => focused.header && q.header && q.header === focused.header || q.question === focused.question);
61859
+ if (!match || match.multiSelect) return;
61860
+ match.multiSelect = true;
61821
61861
  this.statusCallback?.();
61822
61862
  }
61823
61863
  readClaudeTuiHeaders(screenText) {
@@ -61830,16 +61870,43 @@ ${formatManifestValidationIssues2(validation.issues)}`,
61830
61870
  }
61831
61871
  return headers;
61832
61872
  }
61873
+ /**
61874
+ * Snapshot the currently-focused claude TUI page, polling until its
61875
+ * option-row checkbox glyph column has settled (or a bounded timeout).
61876
+ *
61877
+ * Why poll: right after a Tab keypress the newly-focused page's glyph
61878
+ * column has not redrawn yet, so an immediate snapshot shows the question +
61879
+ * option labels but NO per-option checkbox markers — freezing that page as
61880
+ * single-select. A fixed delay either races (too short) or is wasteful (too
61881
+ * long). Instead we re-snapshot at a fixed interval and stop as soon as the
61882
+ * frame shows multi-select glyphs, falling back to the last frame at the
61883
+ * timeout. Single-select pages never show glyphs, so they always poll to the
61884
+ * timeout — bounded small to keep capture snappy.
61885
+ */
61886
+ async snapshotSettledClaudeTuiPage() {
61887
+ let screenText = this.driver.snapshot();
61888
+ const deadline = Date.now() + _SpecCliAdapter.CLAUDE_TUI_PAGE_SETTLE_TIMEOUT_MS;
61889
+ while (!detectClaudeTuiMultiSelect(screenText) && Date.now() < deadline) {
61890
+ await new Promise((resolve24) => setTimeout(resolve24, _SpecCliAdapter.CLAUDE_TUI_PAGE_POLL_INTERVAL_MS));
61891
+ screenText = this.driver.snapshot();
61892
+ }
61893
+ return screenText;
61894
+ }
61833
61895
  async captureClaudeTuiPrompt(firstScreen, headers) {
61834
61896
  const pages = [{ screenText: firstScreen, header: headers[0] }];
61835
61897
  for (let index = 1; index < headers.length; index += 1) {
61836
61898
  this.driver.dispatch({ kind: "pty_write", data: " " });
61837
- await new Promise((resolve24) => setTimeout(resolve24, 120));
61838
- pages.push({ screenText: this.driver.snapshot(), header: headers[index] });
61899
+ await new Promise((resolve24) => setTimeout(resolve24, _SpecCliAdapter.CLAUDE_TUI_PAGE_POLL_INTERVAL_MS));
61900
+ pages.push({ screenText: await this.snapshotSettledClaudeTuiPage(), header: headers[index] });
61839
61901
  }
61840
61902
  for (let index = headers.length - 1; index > 0; index -= 1) {
61841
61903
  this.driver.dispatch({ kind: "pty_write", data: "\x1B[Z" });
61842
- await new Promise((resolve24) => setTimeout(resolve24, 80));
61904
+ await new Promise((resolve24) => setTimeout(resolve24, _SpecCliAdapter.CLAUDE_TUI_PAGE_POLL_INTERVAL_MS));
61905
+ const reread = await this.snapshotSettledClaudeTuiPage();
61906
+ const landed = pages[index - 1];
61907
+ if (landed && !detectClaudeTuiMultiSelect(landed.screenText) && detectClaudeTuiMultiSelect(reread)) {
61908
+ landed.screenText = reread;
61909
+ }
61843
61910
  }
61844
61911
  const prompt = detectClaudeAskUserQuestionPromptFromTuiPages(pages, {
61845
61912
  promptId: `ask-user-${this.providerSessionId || "claude"}-${Date.now()}`,