@adhdev/daemon-core 0.9.82-rc.449 → 0.9.82-rc.450

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
@@ -409,10 +409,10 @@ function readInjected(value) {
409
409
  }
410
410
  function getDaemonBuildInfo() {
411
411
  if (cached) return cached;
412
- const commit = readInjected(true ? "fe0e4d2aa03aea2793c2379e5ffc89abef5143d6" : void 0) ?? "unknown";
413
- const commitShort = readInjected(true ? "fe0e4d2a" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
- const version = readInjected(true ? "0.9.82-rc.449" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
- const builtAt = readInjected(true ? "2026-07-03T01:58:07.610Z" : void 0);
412
+ const commit = readInjected(true ? "4d9f330890bc663a858fde1c84931144b825f8b2" : void 0) ?? "unknown";
413
+ const commitShort = readInjected(true ? "4d9f3308" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
414
+ const version = readInjected(true ? "0.9.82-rc.450" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
415
+ const builtAt = readInjected(true ? "2026-07-03T08:51:21.732Z" : void 0);
416
416
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
417
417
  return cached;
418
418
  }
@@ -19275,6 +19275,15 @@ function validateCondition(c, sectionIds, path44) {
19275
19275
  }
19276
19276
  if ("stable_ms" in w) {
19277
19277
  if (typeof w.stable_ms !== "number") errs.push(`${path44}.stable_ms must be a number`);
19278
+ if (w.section && !sectionIds.has(w.section)) errs.push(`${path44}.section "${w.section}" unknown`);
19279
+ if (w.ignore_lines !== void 0) {
19280
+ if (typeof w.ignore_lines !== "string") errs.push(`${path44}.ignore_lines must be a string`);
19281
+ else try {
19282
+ new RegExp(w.ignore_lines, "m");
19283
+ } catch (e) {
19284
+ errs.push(`${path44}.ignore_lines invalid regex: ${e.message}`);
19285
+ }
19286
+ }
19278
19287
  return errs;
19279
19288
  }
19280
19289
  errs.push(`${path44} is not a recognized condition`);
@@ -19577,10 +19586,13 @@ var init_evaluator = __esm({
19577
19586
  var fsm_evaluator_exports = {};
19578
19587
  __export(fsm_evaluator_exports, {
19579
19588
  evaluateConditionPreview: () => evaluateConditionPreview,
19580
- evaluateFsm: () => evaluateFsm
19589
+ evaluateFsm: () => evaluateFsm,
19590
+ stableRegionKey: () => stableRegionKey
19581
19591
  });
19582
- function regionKey(cursorAbove) {
19583
- return cursorAbove && cursorAbove > 0 ? cursorAbove : WHOLE_SCREEN;
19592
+ function stableRegionKey(cond) {
19593
+ const region = cond.section ? `section:${cond.section}` : cond.cursor_above && cond.cursor_above > 0 ? cond.cursor_above : WHOLE_SCREEN;
19594
+ if (!cond.ignore_lines) return region;
19595
+ return `${region}#ignore:${cond.ignore_lines}`;
19584
19596
  }
19585
19597
  function isRegex(c) {
19586
19598
  return "matches" in c;
@@ -19628,13 +19640,14 @@ function evalCond(cond, sections, fullScreen, cursor, prevLines, clock, legacyTr
19628
19640
  return { kind: "elapsed", result, detail: `elapsed ${age}ms / ${cond.elapsed_ms}ms`, remainingMs };
19629
19641
  }
19630
19642
  if (isStable(cond)) {
19631
- const key2 = regionKey(cond.cursor_above);
19643
+ const key2 = stableRegionKey(cond);
19632
19644
  const lastChanged = clock.regionLastChangedAt.get(key2) ?? clock.stateEnteredAt;
19633
19645
  const stableFor = clock.now - lastChanged;
19634
19646
  const result = stableFor >= cond.stable_ms;
19635
19647
  const remainingMs = result ? 0 : cond.stable_ms - stableFor;
19636
- const where = key2 === WHOLE_SCREEN ? "screen" : `cursor_above=${cond.cursor_above}`;
19637
- return { kind: "stable", result, detail: `stable ${where} ${stableFor}ms / ${cond.stable_ms}ms`, remainingMs };
19648
+ const where = cond.section ? `section=${cond.section}` : cond.cursor_above && cond.cursor_above > 0 ? `cursor_above=${cond.cursor_above}` : "screen";
19649
+ const ign = cond.ignore_lines ? " (ignore_lines)" : "";
19650
+ return { kind: "stable", result, detail: `stable ${where}${ign} ${stableFor}ms / ${cond.stable_ms}ms`, remainingMs };
19638
19651
  }
19639
19652
  if (isRegex(cond) || isChanged(cond)) {
19640
19653
  const result = evaluateCondition(cond, sections, fullScreen, cursor, prevLines, legacyTrace, stateId);
@@ -38201,8 +38214,10 @@ var FsmDriver = class {
38201
38214
  // ── Clock bookkeeping for time conditions.
38202
38215
  startedAtMs = 0;
38203
38216
  prevScreenLines = [];
38204
- /** Per cursor_above region (key: cursor_above, -1 = whole screen) last
38205
- * time that region's content changed. Drives stable_ms conditions. */
38217
+ /** Per stable region last time that region's content changed. Drives
38218
+ * stable_ms conditions. Key = stableRegionKey(cond): numeric cursor_above
38219
+ * (−1 = whole screen), or a `section:<id>` / `<region>#ignore:<pat>` string
38220
+ * when the clause scopes to a section or declares an ignore_lines filter. */
38206
38221
  regionLastChangedAt = /* @__PURE__ */ new Map();
38207
38222
  /** Timer that re-runs evaluate() when a time-condition would flip true
38208
38223
  * with no PTY frame to trigger it. */
@@ -38628,36 +38643,55 @@ var FsmDriver = class {
38628
38643
  }
38629
38644
  return out;
38630
38645
  }
38631
- /** Track which cursor_above regions changed since the previous frame so
38632
- * stable_ms conditions can measure quiet time. We record every region
38633
- * size referenced by a stable_ms condition in the spec, plus the whole
38634
- * screen (-1). */
38646
+ /** Track which stable regions changed since the previous frame so
38647
+ * stable_ms conditions can measure quiet time. We record every distinct
38648
+ * stable region referenced in the current state (numeric cursor_above /
38649
+ * whole-screen -1, and named `section:<id>` regions) plus, for each, the
38650
+ * optional `ignore_lines` filter that folds into its key.
38651
+ *
38652
+ * `ignore_lines` is the content-aware fix for the busy→idle wedge: lines
38653
+ * matching it are stripped from BOTH frames before the comparison, so a
38654
+ * benign residual ticker (bare token counter / elapsed timer that repaints
38655
+ * every frame post-generation) no longer resets the clock — while an active
38656
+ * spinner line, which does NOT match the benign pattern, still does (the
38657
+ * FALSEIDLE2 / FALSEBUSY-B whole-screen invariant is preserved). */
38635
38658
  trackRegionChanges(currentLines, cursor, now) {
38636
38659
  if (this.prevScreenLines.length === 0) return;
38637
- const sizes = this.stableRegionSizes();
38638
- for (const size of sizes) {
38639
- let cur;
38640
- let prev;
38641
- if (size < 0) {
38642
- cur = currentLines.join("\n");
38643
- prev = this.prevScreenLines.join("\n");
38660
+ const descs = this.stableRegionDescriptors();
38661
+ const needsSections = descs.some((d) => !!d.section);
38662
+ const curSections = needsSections ? resolveSections(this.spec.sections ?? {}, currentLines) : [];
38663
+ const prevSections = needsSections ? resolveSections(this.spec.sections ?? {}, this.prevScreenLines) : [];
38664
+ for (const d of descs) {
38665
+ let curLines;
38666
+ let prevLines;
38667
+ if (d.section) {
38668
+ curLines = sliceSectionLines(currentLines, curSections, d.section);
38669
+ prevLines = sliceSectionLines(this.prevScreenLines, prevSections, d.section);
38670
+ } else if (!d.cursor_above || d.cursor_above <= 0) {
38671
+ curLines = currentLines;
38672
+ prevLines = this.prevScreenLines;
38644
38673
  } else {
38645
- const start = Math.max(0, cursor.row - size);
38646
- cur = currentLines.slice(start, cursor.row).join("\n");
38647
- prev = this.prevScreenLines.slice(start, cursor.row).join("\n");
38648
- }
38649
- if (cur !== prev) this.regionLastChangedAt.set(size, now);
38650
- }
38651
- }
38652
- /** All cursor_above region sizes referenced by stable_ms conditions in the
38653
- * current state's outgoing transitions, plus whole-screen. Cached lazily
38654
- * per spec load would be nicer but the set is tiny. */
38655
- stableRegionSizes() {
38656
- const sizes = /* @__PURE__ */ new Set([-1]);
38674
+ const start = Math.max(0, cursor.row - d.cursor_above);
38675
+ curLines = currentLines.slice(start, cursor.row);
38676
+ prevLines = this.prevScreenLines.slice(start, cursor.row);
38677
+ }
38678
+ const cur = filterIgnoredLines(curLines, d.ignoreRe).join("\n");
38679
+ const prev = filterIgnoredLines(prevLines, d.ignoreRe).join("\n");
38680
+ if (cur !== prev) this.regionLastChangedAt.set(d.key, now);
38681
+ }
38682
+ }
38683
+ /** Every distinct stable-region descriptor referenced by stable_ms
38684
+ * conditions in the current state's outgoing transitions, plus the plain
38685
+ * whole-screen key (-1) that other machinery (stall watchdog) reads.
38686
+ * De-duplicated by key. Cached lazily per spec load would be nicer but the
38687
+ * set is tiny. */
38688
+ stableRegionDescriptors() {
38689
+ const byKey = /* @__PURE__ */ new Map();
38690
+ byKey.set(-1, { key: -1 });
38657
38691
  for (const t of outgoingTransitions(this.spec, this.currentStateId)) {
38658
- collectStableSizes(t.when, sizes);
38692
+ collectStableDescriptors(t.when, byKey);
38659
38693
  }
38660
- return sizes;
38694
+ return [...byKey.values()];
38661
38695
  }
38662
38696
  /** Schedule a re-evaluation for the soonest pending time-condition on any
38663
38697
  * outgoing transition (elapsed_ms / stable_ms / min_hold_ms). Without
@@ -39154,26 +39188,45 @@ function findStable(c) {
39154
39188
  }
39155
39189
  return null;
39156
39190
  }
39157
- function collectStableSizes(when, sizes) {
39191
+ function collectStableDescriptors(when, byKey) {
39158
39192
  if (!when) return;
39159
39193
  const w = when;
39160
39194
  if ("stable_ms" in w) {
39161
- sizes.add(w.cursor_above && w.cursor_above > 0 ? w.cursor_above : -1);
39195
+ const key2 = stableRegionKey(w);
39196
+ if (!byKey.has(key2)) {
39197
+ let ignoreRe;
39198
+ if (w.ignore_lines) {
39199
+ try {
39200
+ ignoreRe = new RegExp(w.ignore_lines, "m");
39201
+ } catch {
39202
+ }
39203
+ }
39204
+ byKey.set(key2, { key: key2, section: w.section, cursor_above: w.cursor_above, ignoreRe });
39205
+ }
39162
39206
  return;
39163
39207
  }
39164
39208
  if ("all" in w) {
39165
- for (const c of w.all) collectStableSizes(c, sizes);
39209
+ for (const c of w.all) collectStableDescriptors(c, byKey);
39166
39210
  return;
39167
39211
  }
39168
39212
  if ("any" in w) {
39169
- for (const c of w.any) collectStableSizes(c, sizes);
39213
+ for (const c of w.any) collectStableDescriptors(c, byKey);
39170
39214
  return;
39171
39215
  }
39172
39216
  if ("not" in w) {
39173
- collectStableSizes(w.not, sizes);
39217
+ collectStableDescriptors(w.not, byKey);
39174
39218
  return;
39175
39219
  }
39176
39220
  }
39221
+ function sliceSectionLines(lines, sections, id) {
39222
+ const sec = sections.find((s2) => s2.id === id);
39223
+ if (!sec) return [];
39224
+ return lines.slice(sec.fromLine, sec.toLine);
39225
+ }
39226
+ function filterIgnoredLines(lines, ignoreRe) {
39227
+ if (!ignoreRe) return lines;
39228
+ return lines.filter((l) => !ignoreRe.test(l));
39229
+ }
39177
39230
 
39178
39231
  // src/providers/spec/cli-adapter.ts
39179
39232
  init_evaluator();