mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-10-20 05:15:31 +00:00
docs: upstream alignment playbook — forkless invariant, shim ledger, upgrade contract
Maintainer signals (native yoga next release, 2x layout, opencode's 100-cap was a legacy perf workaround): what changes for us (WASM ratchet dies), what doesn't (the 65k handle table still makes windowing load-bearing at 3000 rows), the boundary/ shim ledger with delete-on-upstream-fix criteria, and the per-release upgrade playbook that uses the bench suite as the acceptance contract.
This commit is contained in:
parent
6f5f7457fe
commit
44c896a5e2
1 changed files with 73 additions and 0 deletions
73
docs/opentui-upstream-alignment.md
Normal file
73
docs/opentui-upstream-alignment.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Upstream alignment — how we inherit OpenTUI's performance work for free
|
||||
|
||||
Context (maintainer, 2026-06-11): opencode's 100-message cap was a November-era
|
||||
performance workaround, since obsoleted; the **next OpenTUI version ships
|
||||
native yoga** (≥2× layout performance, more improvements building on it);
|
||||
opencode does not use virtualization.
|
||||
|
||||
## The invariant that makes alignment free
|
||||
|
||||
**We are forkless and public-API-only.** The windowing layer (S1+S2) drives the
|
||||
STOCK `<scrollbox>` through documented surface only — `onSizeChange`,
|
||||
`setFrameCallback`, `scrollTop`/`viewport`/`scrollHeight`, Solid `<Show>`
|
||||
mount/unmount. Zero patches to `@opentui/core`. Every upstream release
|
||||
therefore drops in by bumping three pinned versions in `ui-opentui/package.json`
|
||||
(`@opentui/{core,keymap,solid}`, currently 0.4.0). Keep it that way: any new
|
||||
code that needs core behavior goes through a `boundary/` wrapper, never a
|
||||
patched dependency.
|
||||
|
||||
## What native yoga changes for us (and what it doesn't)
|
||||
|
||||
- **Kills the WASM ratchet** (grow-only linear memory → freeable native
|
||||
allocations). This retro-justifies S2 less, but S2's append-time windowing
|
||||
remains correct: transient mounted peaks still cost handles and RSS.
|
||||
- **Does NOT obsolete windowing.** The binding constraint is the 65,535-slot
|
||||
native handle table: ~47 handles/row × 3,000 stored rows ≈ 141k handles —
|
||||
over the table at ANY layout speed. Windowing is what makes the 3,000-row
|
||||
scrollback possible; yoga's backend is irrelevant to that math.
|
||||
- **Makes windowing feel even better**: 2× layout = cheaper margin remounts =
|
||||
smaller window margins viable and less exposure for the one accepted limit
|
||||
(estimate-height snap under scrollbar jumps). After the bump, re-tune margin/
|
||||
hysteresis against the scroll cell.
|
||||
|
||||
## The shim ledger (delete-on-upstream-fix; all in `ui-opentui/src/boundary/`)
|
||||
|
||||
| shim | what it papers over | delete when |
|
||||
|---|---|---|
|
||||
| `ffiSafe.ts` | u32 draw coords go negative under Node FFI (Bun silently wraps) — ERR_INVALID_ARG_VALUE loop | upstream clamps, or Node FFI path is officially supported |
|
||||
| `nativeHandles.ts` | SyntaxStyle exhaustion crashes mid-mount; degrade-to-unstyled | handle table widened (INDEX_BITS>16) or per-kind tables |
|
||||
| `renderer.ts` exit-signal guard | core 0.4.0 treats SIGPIPE (clipboard spawn) as an exit signal; its own uncaughtException handler allocates a handle and dies (exit-7 masking) | both fixed upstream |
|
||||
| `clipboard.ts` hardening | same SIGPIPE incident class | with the above |
|
||||
|
||||
Each is (a) isolated, (b) inert if upstream fixes the behavior, (c) worth
|
||||
reporting upstream — four concrete, reproduced, root-caused issues. Filing them
|
||||
is the cheapest alignment lever we have: it converts our workarounds into
|
||||
upstream regression tests. (Needs glitch's go-ahead — public repo activity.)
|
||||
|
||||
## The upgrade playbook (per upstream release)
|
||||
|
||||
1. Branch `chore/opentui-X.Y.Z`, bump the three pins, `npm ci`.
|
||||
2. `npm run check` (648 tests; the windowing invariants — identical
|
||||
scrollHeight ON/OFF, byte-stable frames across corrections — are literal
|
||||
assertions and will catch behavioral drift).
|
||||
3. Bench acceptance, sequential: `--cell gate` (determinism digest; EXPECT a
|
||||
new digest if upstream changed rendering — eyeball the frame, re-bless),
|
||||
`--cell mem3000 --msgs 2000` + `--cell scroll --msgs 3000` vs current
|
||||
numbers (300–375MB / p99 6–8ms), `--cell pipeline` (frame pacing ≥22fps).
|
||||
4. Shim audit: try each boundary shim OFF; delete the ones upstream fixed.
|
||||
5. Live tmux smoke (scroll sweep / resize / selection-copy), screenshots.
|
||||
6. Windowing re-tune if layout got faster: margins up or hysteresis down,
|
||||
re-run scroll cell, keep p99 ≤ 17ms gate.
|
||||
|
||||
The bench suite IS the upgrade contract — it's exactly the harness that lets
|
||||
us take every upstream improvement within a day of release, with proof.
|
||||
|
||||
## Questions worth relaying to the maintainer
|
||||
|
||||
1. Any plan to widen the 16-bit native handle table (or split per-kind)?
|
||||
That's our hard ceiling, independent of yoga.
|
||||
2. Is the Node `--experimental-ffi` path on their support radar, or Bun-only?
|
||||
(Native yoga adds new FFI surface; we run Node.)
|
||||
3. Would they take the windowing layer's core-agnostic pieces (exact-height
|
||||
spacer pattern, correction-legality rule) as a documented recipe or
|
||||
framework-level utility? We have it production-shaped with tests.
|
||||
Loading…
Add table
Add a link
Reference in a new issue