omnius 1.0.691 → 1.0.692

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
@@ -737988,15 +737988,9 @@ var init_status_bar = __esm({
737988
737988
  }
737989
737989
  /** Force a complete footer redraw (public wrapper for renderFooterAndPositionInput).
737990
737990
  *
737991
- * IMPORTANT: do NOT call `updateFooterHeight()` here. The inner render
737992
- * function captures `oldFooterTop` from the CURRENT `_currentFooterHeight`
737993
- * BEFORE updating it, so it can detect height changes and clear the
737994
- * rows that the old (taller) footer used to occupy. Pre-calling
737995
- * `updateFooterHeight` here would mutate the height to the new value
737996
- * first, leaving the inner render to think nothing changed and skipping
737997
- * the transition-row clear — which is exactly what caused stale prompt
737998
- * text to remain on the input box's top unicode border after submitting
737999
- * a multi-line input. */
737991
+ * `_lastFooterPaintTop`, not `_currentFooterHeight`, is the authority for
737992
+ * what is still present on the physical terminal. Some content-write paths
737993
+ * must precompute the next logical layout before this render runs. */
738000
737994
  redrawFooter() {
738001
737995
  if (!this.active) return;
738002
737996
  this.renderFooterAndPositionInput();
@@ -740714,8 +740708,15 @@ var init_status_bar = __esm({
740714
740708
  if (bufferedContentChanged) self2.scheduleStreamingRepaint();
740715
740709
  }
740716
740710
  if (self2._contentCursorReplayActive && bufferedContentChanged && self2._bufferContent && !isOverlayActive()) {
740717
- self2.clearStreamingRepaintTimer();
740718
- self2.repaintContent();
740711
+ const callback = [...args].reverse().find((arg) => typeof arg === "function");
740712
+ if (callback) {
740713
+ queueMicrotask(() => {
740714
+ try {
740715
+ callback();
740716
+ } catch {
740717
+ }
740718
+ });
740719
+ }
740719
740720
  return true;
740720
740721
  }
740721
740722
  if (typeof chunk === "string") {
@@ -740753,6 +740754,7 @@ ${CONTENT_BG_SEQ}`);
740753
740754
  if (!this.active) return;
740754
740755
  this.writeDepth = Math.max(0, this.writeDepth - 1);
740755
740756
  if (this.writeDepth === 0) {
740757
+ const replayWasActive = this._contentCursorReplayActive;
740756
740758
  this.clearStreamingRepaintTimer();
740757
740759
  if (this._inProgressLine.length > 0) {
740758
740760
  const sanitized = this.sanitizeBufferedContentLine(
@@ -740777,6 +740779,7 @@ ${CONTENT_BG_SEQ}`);
740777
740779
  process.stdout.write = this._origWrite;
740778
740780
  this._origWrite = null;
740779
740781
  }
740782
+ if (replayWasActive) this.repaintContent();
740780
740783
  process.stdout.write(RESET4);
740781
740784
  this._brailleSpinner.setMetrics({ isStreaming: false });
740782
740785
  this.renderFooterAndPositionInput();
@@ -742311,15 +742314,27 @@ ${CONTENT_BG_SEQ}`);
742311
742314
  rememberFooterPaint(top) {
742312
742315
  this._lastFooterPaintTop = top;
742313
742316
  }
742317
+ /** Return the top row of the footer that is actually painted on screen. */
742318
+ paintedFooterTop(rows) {
742319
+ if (this._lastFooterPaintTop > 0) {
742320
+ return Math.max(1, Math.min(rows, this._lastFooterPaintTop));
742321
+ }
742322
+ return Math.max(1, rows - this._currentFooterHeight + 1);
742323
+ }
742314
742324
  renderFooterAndPositionInput(force = false) {
742315
742325
  if (!this.active || this._resizing && !force) return;
742316
742326
  const rows = termRows();
742317
742327
  const w = getTermWidth();
742318
- const oldFooterTop = Math.max(1, rows - this._currentFooterHeight + 1);
742328
+ const oldFooterTop = this.paintedFooterTop(rows);
742319
742329
  const heightChanged = this.updateFooterHeight(w);
742320
742330
  const pos = this.rowPositions(rows);
742321
742331
  this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
742322
- if (heightChanged) {
742332
+ const geometryChanged = heightChanged || oldFooterTop !== pos.inputStartRow;
742333
+ if (geometryChanged) {
742334
+ if (this.writeDepth > 0) {
742335
+ this._contentCursorNeedsReplay = true;
742336
+ this._contentCursorReplayActive = true;
742337
+ }
742323
742338
  this.applyScrollRegion();
742324
742339
  this.clearFooterTransitionRows(oldFooterTop, pos.inputStartRow);
742325
742340
  this.fillContentArea();
@@ -742393,7 +742408,11 @@ ${CONTENT_BG_SEQ}`);
742393
742408
  */
742394
742409
  renderFooterPreserveCursor(force = false) {
742395
742410
  if (!this.active || this._resizing && !force) return;
742396
- if (this.footerHeightChanged()) {
742411
+ const rows = termRows();
742412
+ const oldFooterTop = this.paintedFooterTop(rows);
742413
+ const logicalHeightChanged = this.footerHeightChanged();
742414
+ const footerMoved = !logicalHeightChanged && oldFooterTop !== this.rowPositions(rows).inputStartRow;
742415
+ if (logicalHeightChanged || footerMoved) {
742397
742416
  if (this.writeDepth > 0) {
742398
742417
  this.renderInputRowDuringStream(force);
742399
742418
  } else {
@@ -742402,7 +742421,7 @@ ${CONTENT_BG_SEQ}`);
742402
742421
  return;
742403
742422
  }
742404
742423
  const w = getTermWidth();
742405
- const pos = this.rowPositions(termRows());
742424
+ const pos = this.rowPositions(rows);
742406
742425
  this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
742407
742426
  const inputWrap = this.wrapInput(w);
742408
742427
  let buf = "\x1B7\x1B[?7l";
@@ -742471,114 +742490,60 @@ ${CONTENT_BG_SEQ}`);
742471
742490
  this.renderFooterAndPositionInput(force);
742472
742491
  return;
742473
742492
  }
742474
- const oldFooterHeight = this._currentFooterHeight;
742475
- const oldFooterTop = Math.max(1, rows - oldFooterHeight + 1);
742493
+ const oldFooterTop = this.paintedFooterTop(rows);
742476
742494
  const heightChanged = this.updateFooterHeight(w);
742477
742495
  const pos = this.rowPositions(rows);
742478
742496
  this.rebuildSuggestionHitZones(pos.suggestStartRow, w);
742479
742497
  const inputWrap = this.wrapInput(w);
742480
- if (heightChanged) {
742481
- const heightDelta = this._currentFooterHeight - oldFooterHeight;
742482
- let buf = "\x1B7";
742483
- if (heightDelta > 0) {
742484
- const oldScrollEnd = Math.max(
742485
- rows - oldFooterHeight,
742486
- this.scrollRegionTop + 1
742487
- );
742488
- buf += `\x1B[${oldScrollEnd};1H`;
742489
- for (let i2 = 0; i2 < heightDelta; i2++) buf += "\n";
742490
- buf += `\x1B[${this.scrollRegionTop};${pos.scrollEnd}r`;
742491
- } else {
742492
- const absD = Math.abs(heightDelta);
742493
- buf += `\x1B[${this.scrollRegionTop};${pos.scrollEnd}r`;
742494
- buf += `\x1B[${this.scrollRegionTop};1H`;
742495
- for (let i2 = 0; i2 < absD; i2++) buf += "\x1BM";
742496
- }
742497
- const releasedEnd = pos.inputStartRow - 1;
742498
- if (oldFooterTop <= releasedEnd) {
742499
- for (let row2 = oldFooterTop; row2 <= releasedEnd; row2++) {
742500
- buf += `\x1B[${row2};1H${CONTENT_BG_SEQ}\x1B[2K`;
742501
- }
742502
- }
742503
- buf += "\x1B[?7l";
742504
- buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}`;
742505
- for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
742506
- const row2 = pos.inputStartRow + 1 + i2;
742507
- const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
742508
- const lineContent = `${prefix}${inputWrap.lines[i2]}`;
742509
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
742510
- }
742511
- buf += this.buildEnhanceSegment(
742512
- w,
742513
- pos.inputStartRow + 1,
742514
- inputWrap.lines.length
742515
- );
742516
- if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
742517
- for (let si = 0; si < this._suggestions.length; si++) {
742518
- const row2 = pos.suggestStartRow + si;
742519
- const cmd = this._suggestions[si];
742520
- const isHl = si === this._suggestIndex;
742521
- const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
742522
- const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
742523
- const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
742524
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742525
- buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
742526
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
742527
- }
742528
- }
742529
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
742530
- if (pos.metricsRow > 0) {
742531
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}`;
742532
- }
742533
- buf += "\x1B[?7h";
742534
- buf += "\x1B8";
742535
- if (heightDelta > 0) {
742536
- buf += `\x1B[${heightDelta}A`;
742537
- } else {
742538
- buf += `\x1B[${Math.abs(heightDelta)}B`;
742539
- }
742540
- const w1 = this._origWrite ?? this._trueStdoutWrite;
742541
- w1.call(process.stdout, buf);
742498
+ const geometryChanged = heightChanged || oldFooterTop !== pos.inputStartRow;
742499
+ if (geometryChanged) {
742500
+ this._contentCursorNeedsReplay = true;
742501
+ this._contentCursorReplayActive = true;
742502
+ this.applyScrollRegion();
742503
+ this.clearFooterTransitionRows(oldFooterTop, pos.inputStartRow);
742504
+ this.fillContentArea();
742505
+ this.repaintContent();
742506
+ this.refreshTasksPanelAfterLayoutChange();
742542
742507
  this.rememberFooterPaint(pos.inputStartRow);
742543
- if (heightDelta !== 0) this.refreshTasksPanelAfterLayoutChange();
742544
- } else {
742545
- let buf = "\x1B7\x1B[?25l\x1B[?7l";
742546
- buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}${PANEL_BG_SEQ}`;
742547
- for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
742548
- const row2 = pos.inputStartRow + 1 + i2;
742549
- const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
742550
- const lineContent = `${prefix}${inputWrap.lines[i2]}`;
742551
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K`;
742552
- buf += `${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
742553
- buf += `${PANEL_BG_SEQ}\x1B[K`;
742554
- buf += `\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742555
- }
742556
- buf += this.buildEnhanceSegment(
742557
- w,
742558
- pos.inputStartRow + 1,
742559
- inputWrap.lines.length
742560
- );
742561
- if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
742562
- for (let si = 0; si < this._suggestions.length; si++) {
742563
- const row2 = pos.suggestStartRow + si;
742564
- const cmd = this._suggestions[si];
742565
- const isHl = si === this._suggestIndex;
742566
- const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
742567
- const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
742568
- const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m` : " ";
742569
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742570
- buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
742571
- buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742572
- }
742573
- }
742574
- buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
742575
- if (pos.metricsRow > 0) {
742576
- buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
742508
+ this.renderFooterPreserveCursor(force);
742509
+ return;
742510
+ }
742511
+ let buf = "\x1B7\x1B[?25l\x1B[?7l";
742512
+ buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}${PANEL_BG_SEQ}`;
742513
+ for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
742514
+ const row2 = pos.inputStartRow + 1 + i2;
742515
+ const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
742516
+ const lineContent = `${prefix}${inputWrap.lines[i2]}`;
742517
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K`;
742518
+ buf += `${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
742519
+ buf += `${PANEL_BG_SEQ}\x1B[K`;
742520
+ buf += `\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742521
+ }
742522
+ buf += this.buildEnhanceSegment(
742523
+ w,
742524
+ pos.inputStartRow + 1,
742525
+ inputWrap.lines.length
742526
+ );
742527
+ if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
742528
+ for (let si = 0; si < this._suggestions.length; si++) {
742529
+ const row2 = pos.suggestStartRow + si;
742530
+ const cmd = this._suggestions[si];
742531
+ const isHl = si === this._suggestIndex;
742532
+ const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
742533
+ const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
742534
+ const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
742535
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742536
+ buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
742537
+ buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
742577
742538
  }
742578
- buf += "\x1B[?7h\x1B8\x1B[?25l";
742579
- this.termWrite(buf);
742580
- this.rememberFooterPaint(pos.inputStartRow);
742581
742539
  }
742540
+ buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
742541
+ if (pos.metricsRow > 0) {
742542
+ buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
742543
+ }
742544
+ buf += "\x1B[?7h\x1B8\x1B[?25l";
742545
+ this.termWrite(buf);
742546
+ this.rememberFooterPaint(pos.inputStartRow);
742582
742547
  }
742583
742548
  /**
742584
742549
  * Build the content for the buffer line.
@@ -33864,6 +33864,44 @@
33864
33864
  }
33865
33865
  ]
33866
33866
  },
33867
+ {
33868
+ "id": "guide.work-orders-runtime-health-remediation-wo-22-autocomplete-footer-geometry-uppercase",
33869
+ "kind": "guide",
33870
+ "title": "WO-22: Autocomplete Footer Geometry Integrity",
33871
+ "summary": "Scope: CLI TUI footer, DirectInput redraw scheduling, active content writes",
33872
+ "keywords": [
33873
+ "work",
33874
+ "orders",
33875
+ "runtime",
33876
+ "health",
33877
+ "remediation",
33878
+ "WO",
33879
+ "22",
33880
+ "autocomplete",
33881
+ "footer",
33882
+ "geometry",
33883
+ "md"
33884
+ ],
33885
+ "maturity": "internal",
33886
+ "audiences": [
33887
+ "maintainer",
33888
+ "large-context-agent"
33889
+ ],
33890
+ "layer": "documentation",
33891
+ "interfaces": [
33892
+ {
33893
+ "type": "file",
33894
+ "target": "docs/work-orders/runtime-health-remediation/WO-22-autocomplete-footer-geometry.md"
33895
+ }
33896
+ ],
33897
+ "references": [
33898
+ {
33899
+ "type": "documentation",
33900
+ "target": "docs/work-orders/runtime-health-remediation/WO-22-autocomplete-footer-geometry.md",
33901
+ "relation": "canonical-artifact"
33902
+ }
33903
+ ]
33904
+ },
33867
33905
  {
33868
33906
  "id": "guide.work-orders-telegram-dmn-wo-22-dmn-outreach-and-learning-uppercase",
33869
33907
  "kind": "guide",
package/docs/DISCOVERY.md CHANGED
@@ -560,6 +560,7 @@ Daemon equivalents are `GET /v1/discovery/bootstrap`, `GET /v1/discovery?q=<inte
560
560
  | `guide.work-orders-runtime-health-remediation-wo-19-clean-build-reproducibility-uppercase` | WO-19: Clean Build and Optional-Dependency Reproducibility | Status: deterministic acceptance complete Risk: medium Depends on: WO-00 |
561
561
  | `guide.work-orders-runtime-health-remediation-wo-20-exact-session-continuation-uppercase` | WO-20: Exact session continuation across exit and restart | On 2026-09-03, the telegramtest TUI displayed the latest pentest task during startup, but the first restored model context combined a completed breach.py handoff with an unrelated, older page.tsx todo tree. The user then entered continue, and Omnius continued the stale tree instead of the task that was active before /quit. |
562
562
  | `guide.work-orders-runtime-health-remediation-wo-21-task-convergence-and-todo-scope-uppercase` | WO-21: Task convergence and todo scope | On 2026-09-03, a user reported that Omnius remained at task 2/8 for about 40 turns. The report did not include a screenshot or run artifact, so the exact label remains unverified. Omnius has two similar counters: |
563
+ | `guide.work-orders-runtime-health-remediation-wo-22-autocomplete-footer-geometry-uppercase` | WO-22: Autocomplete Footer Geometry Integrity | Scope: CLI TUI footer, DirectInput redraw scheduling, active content writes |
563
564
  | `guide.work-orders-telegram-dmn-wo-22-dmn-outreach-and-learning-uppercase` | WO-22: DMN outreach, DM sharing, and outcome learning | On 2026-09-03 at 17:07 PDT the bot posted in the OMNIUS group without being addressed. The operator asked whether this was self-induced reflection. |
564
565
  | `guide.work-orders-telegram-dropbear-context-rca-workorder` | Telegram Dropbear Context Engineering RCA Work Order | Observed run: /home/roko/Documents/Projects/Adjacent/telegramtest/.omnius, run id 1782873796963-i5r7mv. |
565
566
  | `guide.work-orders-wo-am-gaps-uppercase` | Associative Memory Gap Work Orders | Generated: 2026-04-13 Source: Deep audit of multimodal associative memory systems Status: READY FOR IMPLEMENTATION |
@@ -320,6 +320,15 @@ deterministically repaired P0 or P1 defect.
320
320
  - [x] Latch an advisory convergence review when the leaf frontier is static.
321
321
  - [x] Make loop, reminder, budget, and workboard progress semantics truthful.
322
322
  - [x] Pass deterministic race, stasis, display, typecheck, and build tests.
323
+ - [x] WO-22 autocomplete footer geometry uses the last painted layout as its
324
+ terminal authority and clears all released rows during idle and active-stream
325
+ contraction.
326
+ - [x] Trace the deferred DirectInput repaint and content-write ordering race.
327
+ - [x] Confirm existing tests do not model final terminal cells in this path.
328
+ - [x] Unify idle and streaming geometry transitions around deterministic
329
+ replay.
330
+ - [x] Cover precommitted multi-match to fewer-match and zero-match contraction.
331
+ - [x] Pass focused footer tests, CLI typecheck, and CLI build.
323
332
  - [x] A recovered pause no longer strands its session. Submitting a new task
324
333
  retires the superseded generation instead of refusing every later prompt,
325
334
  while unreconciled external effects still fence admission.
@@ -0,0 +1,93 @@
1
+ # WO-22: Autocomplete Footer Geometry Integrity
2
+
3
+ **Status:** complete
4
+
5
+ **Observed:** 2026-09-03
6
+
7
+ **Scope:** CLI TUI footer, DirectInput redraw scheduling, active content writes
8
+
9
+ ## Failure
10
+
11
+ When slash-command autocomplete expands and then contracts, rows from the old
12
+ footer can remain visible above the current input box. The captured failure
13
+ occurred while `file_read` content was active. A complete old input box and old
14
+ suggestion rows remained in the content viewport after the live footer moved
15
+ down.
16
+
17
+ ## Root cause
18
+
19
+ DirectInput emits a change and schedules footer painting with `setImmediate`.
20
+ If content output starts before that callback, `beginContentWrite()` recomputes
21
+ and stores the new footer height. The later renderer reconstructs the supposed
22
+ old footer top from that already-mutated height. It therefore observes no
23
+ height change and skips the transition clear.
24
+
25
+ The terminal's last painted geometry and the logical layout are separate
26
+ states. `_lastFooterPaintTop` is the authority for the former. A mutable
27
+ `_currentFooterHeight` cannot be used to infer what remains on screen.
28
+
29
+ The streaming renderer also uses incremental line-feed and reverse-index
30
+ compensation when the footer moves. That path depends on terminal scroll-region
31
+ semantics and does not deterministically rebuild released rows from Omnius's
32
+ scrollback model.
33
+
34
+ ## Invariants
35
+
36
+ - Every footer renderer compares the new top with the last successfully painted
37
+ footer top.
38
+ - A changed logical height or changed painted top is a geometry transition.
39
+ - Geometry transitions update DECSTBM, clear the complete old/new footer union,
40
+ replay content from the virtual scrollback, repaint tasks, and then paint the
41
+ new footer.
42
+ - Active content writes do not use line feed, reverse index, or cursor-offset
43
+ guesses to compensate for footer growth or shrinkage.
44
+ - After a geometry transition, token chunks enter the bounded 33 ms replay
45
+ scheduler. They do not cause synchronous full-viewport repainting per token.
46
+ - Replay-consumed stdout writes preserve callback completion, and stream close
47
+ paints any final coalesced line before returning ownership to the idle footer.
48
+ - Cursor-preserving animation and metrics frames cannot accept a precomputed
49
+ footer position before the transition is cleared.
50
+ - Footer chrome writes bypass the buffered content layer.
51
+ - The native streaming cursor is restored by content replay, while the input
52
+ cursor remains owned by the idle path.
53
+ - Repeated expansion and contraction is idempotent and cannot accumulate rows.
54
+
55
+ ## Work items
56
+
57
+ - [x] Trace DirectInput change ordering and scheduled redraw ownership.
58
+ - [x] Trace `beginContentWrite()` layout mutation and terminal paint ordering.
59
+ - [x] Confirm the idle source-level regression test does not cover active writes.
60
+ - [x] Confirm the PTY helper does not interpret final terminal cells.
61
+ - [x] Make last-painted footer geometry authoritative in the idle renderer.
62
+ - [x] Route active-stream geometry transitions through deterministic replay.
63
+ - [x] Preserve the direct terminal bypass for chrome paints.
64
+ - [x] Add a test for a precommitted logical shrink before idle paint.
65
+ - [x] Add a test for a precommitted logical shrink during active content output.
66
+ - [x] Cover multi-match to fewer-match and multi-match to zero-match transitions.
67
+ - [x] Prove no reverse-index compensation remains in the streaming transition.
68
+ - [x] Run the focused footer and DirectInput suite.
69
+ - [x] Run CLI typecheck and build.
70
+ - [x] Inspect the scoped diff and record acceptance evidence.
71
+
72
+ ## Acceptance evidence
73
+
74
+ - `StatusBar.paintedFooterTop()` uses `_lastFooterPaintTop` as physical screen
75
+ authority, with a logical-height fallback only before the first paint.
76
+ - Both footer render paths treat either a height change or a painted-top change
77
+ as a geometry transition.
78
+ - Active-stream transitions update DECSTBM, clear the old/new footer union, fill
79
+ and replay the viewport, refresh tasks, and repaint the footer. Later chunks
80
+ stay in a coalesced virtual replay until the stream closes.
81
+ - `footer-suggestion-shrink-render.test.ts` executes five-to-one and one-to-zero
82
+ contraction after precommitting the logical height. Its ANSI framebuffer
83
+ confirms that prior suggestion text is absent from final terminal cells.
84
+ - The same test executes the five-to-one race with `writeDepth > 0` and confirms
85
+ the replay path. A following token does not trigger an immediate repaint, its
86
+ write callback completes, and stream close performs the final replay.
87
+ - A cursor-preserving-frame regression proves that a precomputed logical layout
88
+ cannot overwrite the last-painted geometry before cleanup.
89
+ - The focused footer/DirectInput suite passed: 6 files, 44 tests.
90
+ - The complete CLI suite passed: 262 files, 2,446 tests.
91
+ - `pnpm --filter omnius typecheck` passed.
92
+ - `pnpm --filter omnius build` passed.
93
+ - No live inference or CUDA workload was used.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.691",
3
+ "version": "1.0.692",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.691",
9
+ "version": "1.0.692",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.691",
3
+ "version": "1.0.692",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/library.js",