@vincemakes/kiso-tui 0.14.0 → 0.15.0

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.
Files changed (2) hide show
  1. package/dist/compositor.js +68 -38
  2. package/package.json +2 -2
@@ -472,9 +472,6 @@ export class Body {
472
472
  return;
473
473
  }
474
474
  this.#endMd();
475
- const last = this.#cells[this.#cells.length - 1];
476
- if (last !== undefined && last.kind === "text" && !last.done)
477
- last.done = true;
478
475
  this.#mark();
479
476
  }
480
477
  /** W14 — the turn boundary's END: the CLI calls this at the run's
@@ -1688,40 +1685,67 @@ export class Body {
1688
1685
  // content loss).
1689
1686
  if (skip > 0 && !overlay) {
1690
1687
  const leaving = Math.max(0, skip - this.#lastSkip);
1691
- // A8b (the fresh leaving share): a leaving row whose old-screen
1692
- // copy is stalethe committed-this-frame lines (their old rows
1693
- // held the previous live/chrome) is pre-painted at its OLD row
1694
- // so the LF scroll carries it into the scrollback; the frozen
1695
- // leaving rows are already on screen and scroll as-is. The first
1696
- // overflow frame of a batch: the window's top row is the freshly
1697
- // committed line, NEVER on the old screen without the
1698
- // pre-paint the scroll pushes a blank and the line's only paint
1699
- // (the clamped march at row 1) is overwritten by its neighbor.
1700
- if (skip > frozen.length) {
1701
- const fromIdx = Math.max(0, this.#lastSkip - frozen.length);
1702
- const top = Math.min(skip - frozen.length, all.length - frozen.length);
1703
- for (let i = fromIdx; i < top; i += 1) {
1704
- out.push(`\x1b[${Math.max(1, frozen.length + i - this.#lastSkip + 1)};1H\x1b[0K${this.#checked(all[frozen.length + i], W)}`);
1688
+ // TT-1B (finding TUI2-MD-1): a burst taller than the screen can
1689
+ // NOT be staged in one pass rows placed past H are clamped by
1690
+ // the terminal itself (CUP pins to the last row), the pile keeps
1691
+ // only its last member, and the scroll pushes the wreckage: the
1692
+ // short-terminal row loss the finding measured. The transit is
1693
+ // chunked instead: each pass paints <= H leaving rows at rows
1694
+ // 1..chunk and scrolls exactly that many LFs, so every row is ON
1695
+ // the screen when its scroll slot comes up. The <= H path below
1696
+ // keeps its exact pre-round bytes (its staging never exceeds H
1697
+ // position <= skip - lastSkip = leaving).
1698
+ if (leaving > H) {
1699
+ let p = this.#lastSkip;
1700
+ while (p < skip) {
1701
+ const chunk = Math.min(skip - p, H);
1702
+ for (let k = 0; k < chunk; k += 1) {
1703
+ out.push(`\x1b[${k + 1};1H\x1b[0K${this.#checked(all[p + k], W)}`);
1704
+ }
1705
+ if (chunk < H)
1706
+ out.push(`\x1b[${chunk + 1};1H\x1b[0J`);
1707
+ out.push(`\x1b[${H};1H`);
1708
+ for (let k = 0; k < chunk; k += 1)
1709
+ out.push("\n");
1710
+ p += chunk;
1705
1711
  }
1706
1712
  }
1707
- if (leaving < skip)
1708
- out.push(`\x1b[${leaving + 1};1H\x1b[0J`);
1709
- out.push(`\x1b[${H};1H`);
1710
- // TUI2-R2pre scroll the rows that LEFT THE WINDOW SINCE THE
1711
- // LAST FRAME (`leaving`), never `skip`, which is the window's
1712
- // ABSOLUTE top. Scrolling the absolute top re-pushed the whole
1713
- // history's worth of rows on EVERY full redraw and a live-region
1714
- // shrink takes this path, so that was most frames of a real
1715
- // session. The ED above had just blanked everything below row
1716
- // `leaving`, so what those surplus LFs carried into the terminal's
1717
- // scrollback was blank rows: the large blank bands mid-history of
1718
- // the owner's field report. The SCREEN never showed it because the
1719
- // repaint below covers every row 1..H (the V6-1 rule), and the
1720
- // house emulator drops scrolled rows on the floor so no gate
1721
- // could see it either. Measured on the 5-turn 80x24 repro: the
1722
- // scrollback went from 162 blank rows of 168 to 14 of 52.
1723
- for (let i = 0; i < leaving; i += 1)
1724
- out.push("\n");
1713
+ else {
1714
+ // A8b (the fresh leaving share): a leaving row whose old-screen
1715
+ // copy is stale — the committed-this-frame lines (their old rows
1716
+ // held the previous live/chrome) is pre-painted at its OLD row
1717
+ // so the LF scroll carries it into the scrollback; the frozen
1718
+ // leaving rows are already on screen and scroll as-is. The first
1719
+ // overflow frame of a batch: the window's top row is the freshly
1720
+ // committed line, NEVER on the old screen without the
1721
+ // pre-paint the scroll pushes a blank and the line's only paint
1722
+ // (the clamped march at row 1) is overwritten by its neighbor.
1723
+ if (skip > frozen.length) {
1724
+ const fromIdx = Math.max(0, this.#lastSkip - frozen.length);
1725
+ const top = Math.min(skip - frozen.length, all.length - frozen.length);
1726
+ for (let i = fromIdx; i < top; i += 1) {
1727
+ out.push(`\x1b[${Math.max(1, frozen.length + i - this.#lastSkip + 1)};1H\x1b[0K${this.#checked(all[frozen.length + i], W)}`);
1728
+ }
1729
+ }
1730
+ if (leaving < skip)
1731
+ out.push(`\x1b[${leaving + 1};1H\x1b[0J`);
1732
+ out.push(`\x1b[${H};1H`);
1733
+ // TUI2-R2pre ② — scroll the rows that LEFT THE WINDOW SINCE THE
1734
+ // LAST FRAME (`leaving`), never `skip`, which is the window's
1735
+ // ABSOLUTE top. Scrolling the absolute top re-pushed the whole
1736
+ // history's worth of rows on EVERY full redraw — and a live-region
1737
+ // shrink takes this path, so that was most frames of a real
1738
+ // session. The ED above had just blanked everything below row
1739
+ // `leaving`, so what those surplus LFs carried into the terminal's
1740
+ // scrollback was blank rows: the large blank bands mid-history of
1741
+ // the owner's field report. The SCREEN never showed it because the
1742
+ // repaint below covers every row 1..H (the V6-1 rule), and the
1743
+ // house emulator drops scrolled rows on the floor — so no gate
1744
+ // could see it either. Measured on the 5-turn 80x24 repro: the
1745
+ // scrollback went from 162 blank rows of 168 to 14 of 52.
1746
+ for (let i = 0; i < leaving; i += 1)
1747
+ out.push("\n");
1748
+ }
1725
1749
  }
1726
1750
  if (!overlay)
1727
1751
  this.#lastSkip = skip;
@@ -1788,6 +1812,15 @@ export class Body {
1788
1812
  const overlay = this.#overlayFrame;
1789
1813
  const skip = overlay ? this.#lastSkip : Math.max(0, this.#committedLines + liveLines.length + CHROME_ROWS + inputExtra + queueRows.length + menuRows.length - H);
1790
1814
  const leaving = overlay ? 0 : Math.max(0, skip - this.#lastSkip);
1815
+ // TT-1B (finding TUI2-MD-1): the steady staging has the same
1816
+ // past-H clamp as the full path had — a window that moved more than
1817
+ // a screenful in one frame cannot transit on this path at all.
1818
+ // Delegate the oversized frame to #drawFull's chunked emission (the
1819
+ // full path repaints every row, so the hand-off is self-contained).
1820
+ if (leaving > H) {
1821
+ this.#drawFull(out, W, H, liveTop, liveLines, queueRows, menuRows, editor);
1822
+ return;
1823
+ }
1791
1824
  // the jump to the bottom row H, then N real LFs scroll the screen
1792
1825
  // exactly N rows — ONE per committed line (the bookkeeping; the
1793
1826
  // stale 1B anchor jumped to H−1 and the N LFs scrolled only N−1 —
@@ -1999,9 +2032,6 @@ export class Body {
1999
2032
  * tail block closes and its cell becomes commit-eligible. */
2000
2033
  #closeOpenText() {
2001
2034
  this.#endMd();
2002
- const last = this.#cells[this.#cells.length - 1];
2003
- if (last !== undefined && last.kind === "text" && !last.done)
2004
- last.done = true;
2005
2035
  }
2006
2036
  /** Close an open thinking cell when a new cell starts. */
2007
2037
  #closeOpenThinking() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-tui",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "kiso tui — the pure terminal layer (cell renderer, dock, raw editor, diff, palette). Zero runtime dependencies: input is data, output is bytes.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,6 +35,6 @@
35
35
  },
36
36
  "homepage": "https://github.com/vincemakes/kiso/tree/main/packages/tui#readme",
37
37
  "dependencies": {
38
- "@vincemakes/kiso-tui-cells": "0.14.0"
38
+ "@vincemakes/kiso-tui-cells": "0.15.0"
39
39
  }
40
40
  }