fix(ui): monotonic height lock + lineCells debounce to eliminate thinking jitter#989
Conversation
pub fn skipped_count is never dead_code — pub items are always reachable. The #[allow(dead_code)] attribute triggers clippy::useless_attribute in Rust 1.95, which with -D warnings causes CI failure.
FrameCache::default() had prev_raw="" which matched an empty-string
first frame, causing is_new("") to incorrectly return false and the
empty_string_is_valid_frame test to fail.
Add has_prev flag so the first frame always returns true regardless of
content matching the default empty prev_raw.
bool::default() is false, which is exactly what has_prev needs. Manual impl Default triggers clippy::derivable_impls.
|
CI is now green on my fork ✅ The 3 Rust fixes applied:
All changes are in `frame_cache.rs` — the TS side and `main.rs` are unchanged from the original PR. |
|
Solid root-cause analysis and the Rust Blocker 1 — Blocker 2 — Fix: move the timer into Nit (not blocking) — The good parts (keep as-is):
Alternative path if you want to ship faster: split the Rust |
|
All three items addressed: Blocker 1 ✅ — Removed `.github/workflows/ci-rust.yml`. The upstream `ci.yml` (lines 54-75) already covers the Rust pipeline. Blocker 2 ✅ — Rewrote `useIncrementalWrap` debounce: `useState(lineCells)` + `useEffect([lineCells])` with `pendingCellsRef` to avoid the closure-over-state issue. The `setTimeout` callback now calls `setEffectiveCells` which triggers a proper re-render, so an idle resize will pick up the new width correctly. Nit ✅ — Added comment to `isCardSettled` noting that future card kinds whose height shrinks while in-flight need an explicit entry. Verified: `npm run lint` / `npm run typecheck` / `npm test` (201 files, 3020 tests) all green. |
…alWrap debounce, add isCardSettled comment Blocker 1: Remove .github/workflows/ci-rust.yml (duplicates existing CI). Blocker 2: Move setTimeout out of useMemo into useEffect + useState so the debounce commit triggers a proper re-render, fixing the idle-resize bug where the old width persisted indefinitely. Nit: Add comment to isCardSettled about future card kinds.
|
All review items resolved. CI verified on fork first (rust fmt+clippy+test ✅, ts lint+typecheck+test ✅). Changes since last review:
Added `.github/workflows/verify.yml` on the fork for pre-PR validation (runs both Rust and TS jobs). Ready for re-review. |
|
Thanks for the revision — the One residual ask before merge: please drop
Totally fine to keep |
|
Done — dropped `.github/workflows/verify.yml` from this PR. Will keep it on the fork's main branch for pre-PR validation on our side. |
Summary / 概要
Eliminates thinking-process jitter in the CLI TUI by fixing the root cause: Yoga layout oscillation feeding back into the virtual scroll window.
消除 CLI TUI 中思考过程的抖动问题,修复根因:Yoga 布局振荡反馈到虚拟滚动窗口。
Root Cause / 根因
The jitter is caused by a feedback loop across 3 components:
抖动由 3 个组件间的反馈循环引起:
```
streaming token → card re-render → Yoga measures height (may emit transient shrink)
→ MeasuredCard.report → setCardHeight → cardHeights map changes
→ CardStream re-render → inner.height changes → setMaxScroll
→ scrollRows shift → virtual window boundary moves → cards enter/exit
→ new Yoga measurements → cycle repeats
```
Additionally, terminal resize during streaming breaks the incremental wrap's monotonicity, causing expensive full-text re-wraps that compound the problem.
另外,流式输出期间终端宽度变化会打破增量换行的单调性,触发昂贵的全文本重计算,加剧问题。
Changes / 改动
TypeScript (3 files)
Rust (3 files)
Verification / 验证
Expected Impact / 预期效果