@oh-my-pi/pi-tui 16.3.4 → 16.3.5
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/CHANGELOG.md +6 -0
- package/dist/types/tui.d.ts +0 -6
- package/package.json +3 -3
- package/src/tui.ts +29 -100
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.3.5] - 2026-07-04
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed the modifyOtherKeys keyboard fallback enabling on unknown SSH terminals, avoiding broken Shift input in iOS SSH clients such as Redock ([#4325](https://github.com/can1357/oh-my-pi/issues/4325)).
|
|
10
|
+
|
|
5
11
|
## [16.3.3] - 2026-07-02
|
|
6
12
|
|
|
7
13
|
### Fixed
|
package/dist/types/tui.d.ts
CHANGED
|
@@ -105,11 +105,6 @@ export interface OverlayFocusOwner {
|
|
|
105
105
|
* dropped row or an audit re-anchor spray. Provisional live blocks (collapsing
|
|
106
106
|
* tool/edit previews whose head is a throwaway tail window) omit it. Defaults to
|
|
107
107
|
* `commitSafeEnd ?? liveRegionStart` when absent.
|
|
108
|
-
* `getNativeScrollbackOfferSafeEnd` optionally reports the deepest prefix row
|
|
109
|
-
* that may physically enter native scrollback while still remaining audited.
|
|
110
|
-
* This is for finalized lower siblings under a live block: the rows may scroll
|
|
111
|
-
* off, but a later live-block insertion above them must trigger repair instead
|
|
112
|
-
* of becoming durable audit-exempt history.
|
|
113
108
|
*
|
|
114
109
|
* When several root children report a seam in the same frame, the topmost
|
|
115
110
|
* one (and its commit-safe / snapshot-safe extension) defines the boundary:
|
|
@@ -120,7 +115,6 @@ export interface NativeScrollbackLiveRegion {
|
|
|
120
115
|
getNativeScrollbackLiveRegionStart(): number | undefined;
|
|
121
116
|
getNativeScrollbackCommitSafeEnd?(): number | undefined;
|
|
122
117
|
getNativeScrollbackSnapshotSafeEnd?(): number | undefined;
|
|
123
|
-
getNativeScrollbackOfferSafeEnd?(): number | undefined;
|
|
124
118
|
}
|
|
125
119
|
export interface NativeScrollbackCommittedRows {
|
|
126
120
|
setNativeScrollbackCommittedRows(rows: number): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-tui",
|
|
4
|
-
"version": "16.3.
|
|
4
|
+
"version": "16.3.5",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"fmt": "biome format --write ."
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@oh-my-pi/pi-natives": "16.3.
|
|
41
|
-
"@oh-my-pi/pi-utils": "16.3.
|
|
40
|
+
"@oh-my-pi/pi-natives": "16.3.5",
|
|
41
|
+
"@oh-my-pi/pi-utils": "16.3.5",
|
|
42
42
|
"lru-cache": "11.5.1",
|
|
43
43
|
"marked": "^18.0.5"
|
|
44
44
|
},
|
package/src/tui.ts
CHANGED
|
@@ -212,11 +212,6 @@ export interface OverlayFocusOwner {
|
|
|
212
212
|
* dropped row or an audit re-anchor spray. Provisional live blocks (collapsing
|
|
213
213
|
* tool/edit previews whose head is a throwaway tail window) omit it. Defaults to
|
|
214
214
|
* `commitSafeEnd ?? liveRegionStart` when absent.
|
|
215
|
-
* `getNativeScrollbackOfferSafeEnd` optionally reports the deepest prefix row
|
|
216
|
-
* that may physically enter native scrollback while still remaining audited.
|
|
217
|
-
* This is for finalized lower siblings under a live block: the rows may scroll
|
|
218
|
-
* off, but a later live-block insertion above them must trigger repair instead
|
|
219
|
-
* of becoming durable audit-exempt history.
|
|
220
215
|
*
|
|
221
216
|
* When several root children report a seam in the same frame, the topmost
|
|
222
217
|
* one (and its commit-safe / snapshot-safe extension) defines the boundary:
|
|
@@ -227,7 +222,6 @@ export interface NativeScrollbackLiveRegion {
|
|
|
227
222
|
getNativeScrollbackLiveRegionStart(): number | undefined;
|
|
228
223
|
getNativeScrollbackCommitSafeEnd?(): number | undefined;
|
|
229
224
|
getNativeScrollbackSnapshotSafeEnd?(): number | undefined;
|
|
230
|
-
getNativeScrollbackOfferSafeEnd?(): number | undefined;
|
|
231
225
|
}
|
|
232
226
|
|
|
233
227
|
export interface NativeScrollbackCommittedRows {
|
|
@@ -257,10 +251,6 @@ function getNativeScrollbackSnapshotSafeEnd(component: Component): number | unde
|
|
|
257
251
|
return (component as Component & Partial<NativeScrollbackLiveRegion>).getNativeScrollbackSnapshotSafeEnd?.();
|
|
258
252
|
}
|
|
259
253
|
|
|
260
|
-
function getNativeScrollbackOfferSafeEnd(component: Component): number | undefined {
|
|
261
|
-
return (component as Component & Partial<NativeScrollbackLiveRegion>).getNativeScrollbackOfferSafeEnd?.();
|
|
262
|
-
}
|
|
263
|
-
|
|
264
254
|
/**
|
|
265
255
|
* Opt-in stability report for components that mutate their returned render
|
|
266
256
|
* array in place across frames (instead of returning a fresh array per
|
|
@@ -638,7 +628,6 @@ interface FrameSegment {
|
|
|
638
628
|
liveLocalStart?: number;
|
|
639
629
|
commitLocalEnd?: number;
|
|
640
630
|
snapshotLocalEnd?: number;
|
|
641
|
-
offerLocalEnd?: number;
|
|
642
631
|
}
|
|
643
632
|
|
|
644
633
|
/** Depth-first identity search through `Container`-shaped children. */
|
|
@@ -1020,27 +1009,23 @@ export class TUI extends Container {
|
|
|
1020
1009
|
// #auditCommittedPrefix). Holds references to component-cached strings, so
|
|
1021
1010
|
// the audit is a pointer walk in the common case.
|
|
1022
1011
|
#committedPrefix: string[] = [];
|
|
1023
|
-
// The committed prefix [0, committedRows) splits into
|
|
1024
|
-
// monotone marks auditRows ≤ durableRows ≤
|
|
1012
|
+
// The committed prefix [0, committedRows) splits into three audit zones by
|
|
1013
|
+
// two monotone marks auditRows ≤ durableRows ≤ committedRows:
|
|
1025
1014
|
// [0, auditRows) BYTE-STABLE — audited (re-anchor on any shift).
|
|
1026
1015
|
// [auditRows, durableRows) DURABLE snapshot — exempt: rows may drift in
|
|
1027
1016
|
// place (a streaming table widening) without re-anchoring, so their
|
|
1028
1017
|
// expected drift never sprays duplicate snapshots.
|
|
1029
|
-
// [durableRows,
|
|
1030
|
-
// native scrollback while a live block above could still shift them.
|
|
1031
|
-
// A mismatch here requires a destructive replay, not a duplicate tail.
|
|
1032
|
-
// [offerRows, committedRows) FORCED-overflow — audited: rows committed
|
|
1018
|
+
// [durableRows, committedRows) FORCED-overflow — audited: rows committed
|
|
1033
1019
|
// only because they scrolled above the window under a commit-unstable
|
|
1034
1020
|
// barrier; auditing them re-anchors (duplication, never loss) when the
|
|
1035
1021
|
// barrier later shifts/finalizes/removes, instead of stranding a stale
|
|
1036
1022
|
// prefix that silently drops the rows beneath it.
|
|
1037
|
-
//
|
|
1038
|
-
// otherwise advance per the persistence rules in #updateCommittedAuditRows.
|
|
1023
|
+
// Both marks re-base on a wholesale re-slice (full paint / shrink / geometry)
|
|
1024
|
+
// and otherwise advance per the persistence rules in #updateCommittedAuditRows.
|
|
1039
1025
|
// #auditCommittedPrefix audits [0, committedRows) skipping the exempt window
|
|
1040
1026
|
// [auditRows, durableRows).
|
|
1041
1027
|
#committedPrefixAuditRows = 0;
|
|
1042
1028
|
#committedPrefixDurableRows = 0;
|
|
1043
|
-
#committedPrefixOfferRows = 0;
|
|
1044
1029
|
// Frame row currently mapped to screen row 0. Monotonic between full
|
|
1045
1030
|
// paints: a shrink never re-exposes scrolled-off rows (they cannot be
|
|
1046
1031
|
// un-scrolled without rewriting history); live rows repaint at fixed
|
|
@@ -1051,7 +1036,6 @@ export class TUI extends Container {
|
|
|
1051
1036
|
#nativeScrollbackLiveRegionStart: number | undefined;
|
|
1052
1037
|
#nativeScrollbackCommitSafeEnd: number | undefined;
|
|
1053
1038
|
#nativeScrollbackSnapshotSafeEnd: number | undefined;
|
|
1054
|
-
#nativeScrollbackOfferSafeEnd: number | undefined;
|
|
1055
1039
|
#fullRedrawCount = 0;
|
|
1056
1040
|
// Caps how many inline images render as live graphics; older ones fall back
|
|
1057
1041
|
// to text via a purge + full redraw. Cap is configured by the host app.
|
|
@@ -1171,7 +1155,6 @@ export class TUI extends Container {
|
|
|
1171
1155
|
this.#nativeScrollbackLiveRegionStart = undefined;
|
|
1172
1156
|
this.#nativeScrollbackCommitSafeEnd = undefined;
|
|
1173
1157
|
this.#nativeScrollbackSnapshotSafeEnd = undefined;
|
|
1174
|
-
this.#nativeScrollbackOfferSafeEnd = undefined;
|
|
1175
1158
|
const children = this.children;
|
|
1176
1159
|
const previousSegments = this.#frameSegments;
|
|
1177
1160
|
const segments: FrameSegment[] = new Array(children.length);
|
|
@@ -1194,14 +1177,12 @@ export class TUI extends Container {
|
|
|
1194
1177
|
let liveLocalStart: number | undefined;
|
|
1195
1178
|
let commitLocalEnd: number | undefined;
|
|
1196
1179
|
let snapshotLocalEnd: number | undefined;
|
|
1197
|
-
let offerLocalEnd: number | undefined;
|
|
1198
1180
|
let reported: number | undefined;
|
|
1199
1181
|
if (reuse) {
|
|
1200
1182
|
childLines = previous.lines;
|
|
1201
1183
|
liveLocalStart = previous.liveLocalStart;
|
|
1202
1184
|
commitLocalEnd = previous.commitLocalEnd;
|
|
1203
1185
|
snapshotLocalEnd = previous.snapshotLocalEnd;
|
|
1204
|
-
offerLocalEnd = previous.offerLocalEnd;
|
|
1205
1186
|
} else {
|
|
1206
1187
|
// Feed the engine's committed-row claim (from the previous frame's
|
|
1207
1188
|
// emit) before rendering so the child can skip re-deriving blocks
|
|
@@ -1230,13 +1211,6 @@ export class TUI extends Container {
|
|
|
1230
1211
|
? Math.max(snapshotFloor, Math.min(childLines.length, Math.trunc(snapshotSafeEnd)))
|
|
1231
1212
|
: childLines.length;
|
|
1232
1213
|
}
|
|
1233
|
-
const offerSafeEnd = getNativeScrollbackOfferSafeEnd(child);
|
|
1234
|
-
if (offerSafeEnd !== undefined) {
|
|
1235
|
-
const offerFloor = snapshotLocalEnd ?? commitLocalEnd ?? liveLocalStart;
|
|
1236
|
-
offerLocalEnd = Number.isFinite(offerSafeEnd)
|
|
1237
|
-
? Math.max(offerFloor, Math.min(childLines.length, Math.trunc(offerSafeEnd)))
|
|
1238
|
-
: childLines.length;
|
|
1239
|
-
}
|
|
1240
1214
|
}
|
|
1241
1215
|
// Consume the stability report unconditionally for implementers:
|
|
1242
1216
|
// reading re-bases the component's baseline to the state this
|
|
@@ -1260,9 +1234,6 @@ export class TUI extends Container {
|
|
|
1260
1234
|
if (snapshotLocalEnd !== undefined) {
|
|
1261
1235
|
this.#nativeScrollbackSnapshotSafeEnd = offset + snapshotLocalEnd;
|
|
1262
1236
|
}
|
|
1263
|
-
if (offerLocalEnd !== undefined) {
|
|
1264
|
-
this.#nativeScrollbackOfferSafeEnd = offset + offerLocalEnd;
|
|
1265
|
-
}
|
|
1266
1237
|
}
|
|
1267
1238
|
if (chainStable) {
|
|
1268
1239
|
if (previous !== undefined && previous.component === child && previous.start === offset) {
|
|
@@ -1293,7 +1264,6 @@ export class TUI extends Container {
|
|
|
1293
1264
|
liveLocalStart,
|
|
1294
1265
|
commitLocalEnd,
|
|
1295
1266
|
snapshotLocalEnd,
|
|
1296
|
-
offerLocalEnd,
|
|
1297
1267
|
};
|
|
1298
1268
|
offset += childLines.length;
|
|
1299
1269
|
}
|
|
@@ -2694,7 +2664,6 @@ export class TUI extends Container {
|
|
|
2694
2664
|
const liveRegionStart = this.#nativeScrollbackLiveRegionStart;
|
|
2695
2665
|
const commitSafeEnd = this.#nativeScrollbackCommitSafeEnd;
|
|
2696
2666
|
const snapshotSafeEnd = this.#nativeScrollbackSnapshotSafeEnd;
|
|
2697
|
-
const offerSafeEnd = this.#nativeScrollbackOfferSafeEnd;
|
|
2698
2667
|
|
|
2699
2668
|
// Commit boundaries (also used by the window/commit math in section 3),
|
|
2700
2669
|
// hoisted above the audit gate because the resync needs byteStableBoundary
|
|
@@ -2702,27 +2671,22 @@ export class TUI extends Container {
|
|
|
2702
2671
|
// The commit floor is windowTop in every non-frozen path (see chunkTo), so
|
|
2703
2672
|
// whatever scrolls above the window is committed — never committed nowhere
|
|
2704
2673
|
// AND painted nowhere (the loss bug). The boundaries no longer gate the
|
|
2705
|
-
// commit; they define audit
|
|
2674
|
+
// commit; they define the audit-exempt span. byteStableBoundary: rows below
|
|
2706
2675
|
// it are byte-stable (never re-layout), audited. durableBoundary: rows in
|
|
2707
2676
|
// [byteStableBoundary, durableBoundary) are durable — permanent on scroll-off
|
|
2708
2677
|
// but may drift in place (a streaming table re-aligning), committed
|
|
2709
|
-
// audit-EXEMPT.
|
|
2710
|
-
//
|
|
2711
|
-
// audited
|
|
2712
|
-
//
|
|
2713
|
-
//
|
|
2714
|
-
//
|
|
2715
|
-
// audited, so a later shift/finalize/removal re-anchors (duplication, never
|
|
2716
|
-
// loss) instead of stranding a stale prefix. Built on the finalized prefix
|
|
2717
|
-
// (live-region start); the whole frame when the root reports no seam (shell
|
|
2718
|
-
// semantics: whatever scrolls is final).
|
|
2678
|
+
// audit-EXEMPT. Rows at/beyond durableBoundary committed only because they
|
|
2679
|
+
// scrolled above the window (a commit-unstable barrier over a long tail) are
|
|
2680
|
+
// forced-overflow rows: audited, so a later shift/finalize/removal re-anchors
|
|
2681
|
+
// (duplication, never loss) instead of stranding a stale prefix. Built on the
|
|
2682
|
+
// finalized prefix (live-region start); the whole frame when the root reports
|
|
2683
|
+
// no seam (shell semantics: whatever scrolls is final).
|
|
2719
2684
|
const frameLength = rawFrame.length;
|
|
2720
2685
|
const byteStableBoundary = Math.max(0, Math.min(frameLength, commitSafeEnd ?? liveRegionStart ?? frameLength));
|
|
2721
2686
|
const durableBoundary = Math.max(
|
|
2722
2687
|
byteStableBoundary,
|
|
2723
2688
|
Math.min(frameLength, snapshotSafeEnd ?? byteStableBoundary),
|
|
2724
2689
|
);
|
|
2725
|
-
const offerBoundary = Math.max(durableBoundary, Math.min(frameLength, offerSafeEnd ?? durableBoundary));
|
|
2726
2690
|
|
|
2727
2691
|
// 2. Transition state captured before any emitter runs.
|
|
2728
2692
|
const prevWindowTop = this.#windowTopRow;
|
|
@@ -2755,28 +2719,18 @@ export class TUI extends Container {
|
|
|
2755
2719
|
let committedRowsResynced = false;
|
|
2756
2720
|
// Audit covers [0, auditRows) and the forced suffix [durableRows,
|
|
2757
2721
|
// committedRows); the durable middle [auditRows, durableRows) is exempt
|
|
2758
|
-
// (in-place drift).
|
|
2722
|
+
// (in-place drift). Two reasons to run the audit this frame:
|
|
2759
2723
|
// - the stable prefix does not cover every audited row (auditUpper); or
|
|
2760
2724
|
// - a forced-overflow row this frame became durable/permanent
|
|
2761
|
-
// (committedPrefixDurableRows <
|
|
2762
|
-
//
|
|
2763
|
-
//
|
|
2764
|
-
//
|
|
2765
|
-
//
|
|
2766
|
-
// (committedPrefixOfferRows < min(committed, offerBoundary)): a
|
|
2767
|
-
// finalized sibling under a live block asks for destructive-replay
|
|
2768
|
-
// repair, so a single-row shift there must be caught even if
|
|
2769
|
-
// tail-sample tolerance would otherwise skip it.
|
|
2770
|
-
// The hard scan in findCommittedPrefixResync covers [durableRows,
|
|
2771
|
-
// hardAuditEnd) in full (no tail-sample miss).
|
|
2725
|
+
// (committedPrefixDurableRows < hardAuditEnd): the barrier above it
|
|
2726
|
+
// finalized, so its committed bytes must be re-checked even though the
|
|
2727
|
+
// stable prefix says nothing moved — a stale committed copy there would
|
|
2728
|
+
// silently drop the row. The hard scan in findCommittedPrefixResync
|
|
2729
|
+
// covers [durableRows, hardAuditEnd) in full (no tail-sample miss).
|
|
2772
2730
|
const auditUpper =
|
|
2773
2731
|
this.#committedPrefixDurableRows < this.#committedRows ? this.#committedRows : this.#committedPrefixAuditRows;
|
|
2774
|
-
const
|
|
2775
|
-
const
|
|
2776
|
-
const hardAuditEnd = Math.max(durableHardEnd, offerHardEnd);
|
|
2777
|
-
const needHardAudit =
|
|
2778
|
-
this.#committedPrefixDurableRows < durableHardEnd || this.#committedPrefixOfferRows < offerHardEnd;
|
|
2779
|
-
let repairOfferedScrollback = false;
|
|
2732
|
+
const hardAuditEnd = Math.min(this.#committedRows, durableBoundary);
|
|
2733
|
+
const needHardAudit = this.#committedPrefixDurableRows < hardAuditEnd;
|
|
2780
2734
|
const auditRan =
|
|
2781
2735
|
this.#hasEverRendered &&
|
|
2782
2736
|
!geometryChanged &&
|
|
@@ -2784,21 +2738,14 @@ export class TUI extends Container {
|
|
|
2784
2738
|
(this.#renderStablePrefixRows < auditUpper || needHardAudit);
|
|
2785
2739
|
if (auditRan) {
|
|
2786
2740
|
const committedRowsBeforeAudit = this.#committedRows;
|
|
2787
|
-
|
|
2788
|
-
const durableRowsBeforeAudit = this.#committedPrefixDurableRows;
|
|
2789
|
-
this.#auditCommittedPrefix(rawFrame, hardAuditEnd);
|
|
2741
|
+
this.#auditCommittedPrefix(rawFrame, durableBoundary);
|
|
2790
2742
|
committedRowsResynced = this.#committedRows !== committedRowsBeforeAudit;
|
|
2791
|
-
repairOfferedScrollback =
|
|
2792
|
-
offeredRowsBeforeAudit > durableRowsBeforeAudit &&
|
|
2793
|
-
committedRowsResynced &&
|
|
2794
|
-
this.#committedRows < offeredRowsBeforeAudit;
|
|
2795
2743
|
}
|
|
2796
2744
|
// Committed-prefix state this frame's commit math extends from (post-audit).
|
|
2797
2745
|
// Drives the audit-rows / durable-rows caps recomputed after the emit.
|
|
2798
2746
|
const preCommitRows = this.#committedRows;
|
|
2799
2747
|
const preCommitAuditRows = this.#committedPrefixAuditRows;
|
|
2800
2748
|
const preCommitDurableRows = this.#committedPrefixDurableRows;
|
|
2801
|
-
const preCommitOfferRows = this.#committedPrefixOfferRows;
|
|
2802
2749
|
|
|
2803
2750
|
// 3. Window and commit math (lengths only; content prepared below).
|
|
2804
2751
|
let hasVisibleOverlay = false;
|
|
@@ -2816,7 +2763,7 @@ export class TUI extends Container {
|
|
|
2816
2763
|
// place, because an ED3 rewrap is unsafe (pane scrollback / alt-screen
|
|
2817
2764
|
// feedback loop), so committed history keeps its old wrap.
|
|
2818
2765
|
const firstPaint = !this.#hasEverRendered;
|
|
2819
|
-
const replaceRequested = this.#clearScrollbackOnNextRender
|
|
2766
|
+
const replaceRequested = this.#clearScrollbackOnNextRender;
|
|
2820
2767
|
const geometryRebuild = geometryChanged && !resizeRepaintsInPlace();
|
|
2821
2768
|
const fullPaint = firstPaint || replaceRequested || geometryRebuild;
|
|
2822
2769
|
let windowTop: number;
|
|
@@ -2928,10 +2875,8 @@ export class TUI extends Container {
|
|
|
2928
2875
|
preCommitRows,
|
|
2929
2876
|
preCommitAuditRows,
|
|
2930
2877
|
preCommitDurableRows,
|
|
2931
|
-
preCommitOfferRows,
|
|
2932
2878
|
byteStableBoundary,
|
|
2933
2879
|
durableBoundary,
|
|
2934
|
-
offerBoundary,
|
|
2935
2880
|
false,
|
|
2936
2881
|
);
|
|
2937
2882
|
this.#clearScrollbackOnNextRender = false;
|
|
@@ -2959,10 +2904,8 @@ export class TUI extends Container {
|
|
|
2959
2904
|
preCommitRows,
|
|
2960
2905
|
preCommitAuditRows,
|
|
2961
2906
|
preCommitDurableRows,
|
|
2962
|
-
preCommitOfferRows,
|
|
2963
2907
|
byteStableBoundary,
|
|
2964
2908
|
durableBoundary,
|
|
2965
|
-
offerBoundary,
|
|
2966
2909
|
auditRan,
|
|
2967
2910
|
);
|
|
2968
2911
|
}
|
|
@@ -2989,7 +2932,6 @@ export class TUI extends Container {
|
|
|
2989
2932
|
this.#committedRows = resyncTo;
|
|
2990
2933
|
this.#committedPrefixAuditRows = Math.min(this.#committedPrefixAuditRows, resyncTo);
|
|
2991
2934
|
this.#committedPrefixDurableRows = Math.min(this.#committedPrefixDurableRows, resyncTo);
|
|
2992
|
-
this.#committedPrefixOfferRows = Math.min(this.#committedPrefixOfferRows, resyncTo);
|
|
2993
2935
|
prefix.length = resyncTo;
|
|
2994
2936
|
if ($flag("PI_DEBUG_REDRAW")) {
|
|
2995
2937
|
const msg = `[${new Date().toISOString()}] commit resync: committed prefix diverged at row ${resyncTo}; recommitting\n`;
|
|
@@ -3002,24 +2944,21 @@ export class TUI extends Container {
|
|
|
3002
2944
|
* #committedPrefixAuditRows field doc for the three audit zones).
|
|
3003
2945
|
*
|
|
3004
2946
|
* auditRows tracks the byte-stable boundary; durableRows the durable snapshot
|
|
3005
|
-
* boundary
|
|
3006
|
-
*
|
|
3007
|
-
*
|
|
3008
|
-
*
|
|
3009
|
-
*
|
|
3010
|
-
*
|
|
3011
|
-
*
|
|
3012
|
-
* durableRows.
|
|
2947
|
+
* boundary. A wholesale re-slice (full paint / shrink / geometry) re-bases
|
|
2948
|
+
* each mark from the current frame (min(committed, boundary)). An incremental
|
|
2949
|
+
* extend keeps a mark once a row past it has committed (mark < committed): a
|
|
2950
|
+
* later RISE in a boundary (a table finalizing) must neither pull
|
|
2951
|
+
* already-committed stale snapshots back under the byte-stable cap nor
|
|
2952
|
+
* retroactively exempt forced-overflow rows already audited. durableRows is
|
|
2953
|
+
* floored at auditRows so the exempt window can never invert.
|
|
3013
2954
|
*/
|
|
3014
2955
|
#updateCommittedAuditRows(
|
|
3015
2956
|
resliced: boolean,
|
|
3016
2957
|
preCommittedRows: number,
|
|
3017
2958
|
preAuditRows: number,
|
|
3018
2959
|
preDurableRows: number,
|
|
3019
|
-
preOfferRows: number,
|
|
3020
2960
|
byteStableBoundary: number,
|
|
3021
2961
|
durableBoundary: number,
|
|
3022
|
-
offerBoundary: number,
|
|
3023
2962
|
hardAudited: boolean,
|
|
3024
2963
|
): void {
|
|
3025
2964
|
const committed = this.#committedRows;
|
|
@@ -3036,18 +2975,8 @@ export class TUI extends Container {
|
|
|
3036
2975
|
resliced || preDurableRows >= preCommittedRows || hardAudited
|
|
3037
2976
|
? Math.min(committed, durableBoundary)
|
|
3038
2977
|
: Math.min(preDurableRows, committed);
|
|
3039
|
-
// offerRows may EXTEND to include forced-overflow rows within a
|
|
3040
|
-
// newly-visible offerBoundary — unlike auditRows/durableRows, retroactive
|
|
3041
|
-
// promotion is safe: both offered and forced-overflow zones stay
|
|
3042
|
-
// audited; offered only switches divergence repair from tolerant recommit
|
|
3043
|
-
// to destructive replay (stronger, not weaker). A dropped offerBoundary
|
|
3044
|
-
// still keeps the durability rule via `preOfferRows` (never demote
|
|
3045
|
-
// already-offered rows to forced-overflow).
|
|
3046
|
-
const offerCap = Math.min(committed, offerBoundary);
|
|
3047
|
-
const offerRows = resliced ? offerCap : Math.max(Math.min(preOfferRows, committed), offerCap);
|
|
3048
2978
|
this.#committedPrefixAuditRows = auditRows;
|
|
3049
2979
|
this.#committedPrefixDurableRows = Math.max(auditRows, durableRows);
|
|
3050
|
-
this.#committedPrefixOfferRows = Math.max(this.#committedPrefixDurableRows, offerRows);
|
|
3051
2980
|
}
|
|
3052
2981
|
|
|
3053
2982
|
/**
|