Back to Plate

exact virtualized pagination plan

docs/plans/2026-05-31-exact-virtualized-pagination-plan.md

53.0.849.8 KB
Original Source

exact virtualized pagination plan

Objective: Perfect the Slate v2 exact virtualized pagination architecture plan for user review: define the long-term exact-and-fast layout model, demote cold-block estimation to non-authoritative skeleton use only, gate autoresearch behind a replayable oracle, and keep issue/reference accounting conservative until execution proof exists.

Goal plan: docs/plans/2026-05-31-exact-virtualized-pagination-plan.md

Template: docs/plans/templates/slate-plan.md

Primary template: docs/plans/templates/slate-plan.md

Applied packs:

  • none

Completion threshold:

  • Slate Plan closure is legal only when score >= 0.92, no dimension is below 0.85, every pass row is complete or intentionally skipped with evidence, issue/reference sync rows are closed, final handoff is emitted, and node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-31-exact-virtualized-pagination-plan.md passes.
  • Execution-ready architecture must prove these plan decisions:
    • exact layout truth comes from cached measured block/page snapshots, not estimated line wrapping;
    • virtualized mode may render skeleton/cold pages, but only with explicit skeleton or pending status;
    • selected, composing, command-target, exported, and authoritative collaboration/export pages use measured layout truth;
    • page/spread virtualization stays internal behind virtualized domStrategy;
    • table/media/BFC-like content uses provider-owned exact layout units and split policy, not AST mutation as the default visual pagination strategy;
    • autoresearch starts only after an exactness oracle and perf matrix exist.

Verification surface:

  • Planning-only checks run in /Users/zbeyens/git/plate-2.
  • Live source grounding is read from /Users/zbeyens/git/plate-2/.tmp/slate-v2 and recorded in this plan; no Slate v2 behavior claim is made by root checks.
  • Later execution proof must run from /Users/zbeyens/git/plate-2/.tmp/slate-v2 and include:
    • bun --filter slate-layout test
    • bun --filter slate-layout typecheck
    • focused Chromium Playwright rows for pagination startup, rows=800 virtualized typing/scroll, multi-page table, margin hit testing, selection, and fast-scroll mounting
    • an exact-layout oracle comparing full measured layout against virtualized incremental snapshots for the same document/font/page inputs
    • a perf matrix comparing staged vs virtualized on rows 8, 500, 800, and the default ~1000-page route
    • bun check before accepted execution handoff, and bun check:full before any release-quality browser claim.

Constraints:

  • Planning mode only in this activation: no .tmp/slate-v2 implementation patch.
  • Raw Slate stays unopinionated. Plate owns product pagination UI, export policy, table UX, and docs product ergonomics.
  • slate-layout may own generic layout truth, page snapshots, measurement profiles, layout providers, and split policy protocols.
  • slate-react may consume layout for DOM materialization, page/spread mounting, and browser behavior proof, but must not expose TanStack or estimation internals as public editor semantics.
  • No public API should teach users to tune typing correctness or layout truth with arbitrary debounce/estimate knobs.

Boundaries:

  • Allowed planning edits: docs/plans/**, docs/research/**, docs/slate-issues/**, docs/slate-v2/ledgers/**, and docs/slate-v2/references/**.
  • Current source read scope:
    • .tmp/slate-v2/packages/slate-layout/src/index.ts
    • .tmp/slate-v2/packages/slate-layout/src/react.tsx
    • .tmp/slate-v2/packages/slate-layout/src/page-mount-plan.ts
    • .tmp/slate-v2/site/examples/ts/pagination.tsx
    • .tmp/slate-v2/playwright/integration/examples/pagination.test.ts
  • Current research/ledger read scope:
    • docs/research/README.md
    • docs/research/index.md
    • docs/research/log.md
    • docs/research/sources/editor-architecture/pretext-pagination-page-virtualization.md
    • docs/research/sources/editor-architecture/layout-measurement-and-ime-lanes.md
    • docs/research/sources/editor-architecture/tanstack-virtual-and-github-large-surface-virtualization.md
    • docs/slate-issues/gitcrawl-live-open-ledger.md
    • docs/slate-issues/gitcrawl-v2-sync-ledger.md
    • docs/slate-issues/requirements-from-issues.md
    • docs/slate-issues/benchmark-candidate-map.md
    • docs/slate-v2/ledgers/issue-coverage-matrix.md
    • docs/slate-v2/ledgers/fork-issue-dossier.md
    • docs/slate-v2/references/pr-description.md
  • Non-goal for this pass: implementation, commit, PR, broad GitHub issue discovery, or broad raw-research refresh.

Blocked condition:

  • Blocked only if the next pass requires missing local ledgers/source/research that cannot be read or regenerated locally. Do not use blocked while issue, research, source-grounding, score-hardening, verifier-design, or plan-edit work remains runnable.

Slate Plan lane state:

  • slate_plan_lane_status: pending
  • current_pass: issue-ledger-pass
  • current_pass_status: complete
  • next_pass: intent-boundary-pass
  • next_action: harden the intent/boundary record and decision brief against the completed current-state, related-discovery, and issue-ledger findings
  • final_handoff_status: pending

Current verdict:

  • verdict: revise the current perf plan into an exact-layout architecture plan; current estimateBlock is acceptable only as a temporary non-authoritative skeleton path.
  • confidence: 0.75 after current-state read, related issue discovery, and issue-ledger pass.
  • keep / cut / revise call: keep Pretext and page-level virtualization; revise layout authority; cut any public claim that cold-block estimation is precise.
  • reason: live Slate v2 already has a strong layout substrate, page/spread mounting, provider-owned table/media units, page-break snapshot vocabulary, and high-signal Playwright perf rows. The weak spot is authority: current PretextPageLayoutEngineOptions.estimateBlock lets virtualized cold prose skip exact measurement, so it cannot be the long-term truth for collab, export, or selected/editing pages.

Completion rule:

  • Do not call update_goal(status: complete) while any required checklist item remains unchecked. If an item does not apply, check it and add N/A: <reason>.
  • Do not call update_goal(status: complete) until every Slate Plan completion gate below is satisfied and the plan checker passes.
  • This activation completed exactly one scheduled pass: issue-ledger pass.

Start Gates:

GateAppliesEvidence
Skill analysis before editsyesslate-plan invoked; planning mode selected because the latest request asks to perfect the plan.
Active goal checked or createdyesFirst planning goal hit budget; user asked for a shorter goal; create_goal created Finish remaining Slate Plan passes for exact virtualized pagination. Planning only.
Source of truth read before editsyesRead live slate-layout, PagedEditable, page mount plan, pagination example, focused pagination tests, research pages, and durable issue/reference rows.
docs/solutions checked for non-trivial existing-code worknoN/A: this pass is planning-only and does not patch existing implementation.
Live .tmp/slate-v2 grounding needed for current-state claimsyesCurrent owners and exact gaps are cited below from .tmp/slate-v2.

Work Checklist:

  • Objective includes lane outcome, pass policy, completion threshold, verification surface, constraints, boundaries, and blocked condition.
  • One-pass-per-activation policy respected: this activation completed only current-state read and initial score.
  • Live source grounding recorded for current implementation claims.
  • Related issue discovery / ClawSweeper pass applied or skipped with concrete evidence: existing durable pagination rows cover the touched surface, so broad live GitHub and ClawSweeper rerun are skipped for this pass.
  • Issue-ledger pass scanned generated live rows, manual sync ledger, historical open ledger, issue/test/benchmark candidate maps, package impact matrix, requirements file, coverage matrix, fork dossier, and PR reference for exact-pagination relevance.
  • Research and ecosystem synthesis complete for every external system used as evidence.
  • Intent/boundary record and decision brief complete.
  • Scorecard recorded with evidence; total score >= 0.92 and no dimension below 0.85 before closure.
  • Applicable implementation-skill review matrix applied or skipped with concrete reason.
  • Slate maintainer objection ledger complete for every breaking/paradigm change, or marked N/A with reason.
  • Verification workspace gate recorded for every Slate v2 source, runtime, browser, package, public API, or issue-fix claim.
  • TDD used for behavior/proof changes with a sane test surface, or marked N/A with reason.
  • Browser proof captured for browser-surface claims, or marked N/A with reason.

Completion Gates:

GateAppliesRequired actionEvidence
Named verification thresholdyesFinalize exact oracle, perf matrix, issue sync, and closure proof gatespending
Slate v2 source/runtime/browser/API claimyesRecord .tmp/slate-v2 command/proof or keep as planning-onlycurrent-state pass has source reads only; behavior proof belongs to execution
Issue ledger or PR reference changedno for issue-ledger passSync ledger/reference rows or record why no sync appliesNo sync applies in this pass: the full issue-ledger scan found no new fixed/improved/stale/duplicate claim and existing rows already match the no-new-claim exact-layout target.
Autoreview for uncommitted implementation changesnoRun autoreview in .tmp/slate-v2 after non-trivial execution editsN/A planning-only
Final user-review handoffpendingEmit final handoff or keep plan pending with next passpending
Goal plan completeyesRun node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-31-exact-virtualized-pagination-plan.mdpending; not eligible this activation

Phase / pass table:

PhaseStatusEvidenceNext
Current-state read and initial scorecompletelive source, research, issue/reference rows read; initial score 0.72related issue discovery
Related issue discoverycompletereused existing durable pagination issue rows in gitcrawl-v2-sync-ledger.md, issue-coverage-matrix.md, fork-issue-dossier.md, live rows for #5944 and #790, and PR reference pagination target; no broad live GitHub or ClawSweeper rerun neededissue-ledger pass
Issue-ledger passcompletescanned generated live ledger, manual sync ledger, historical open ledger, cluster/requirements/package surfaces, test and benchmark candidate maps, coverage matrix, fork dossier, and PR reference; added explicit non-claim/guardrail rows for #5924, #4141, and broader performance backlogintent/boundary pass
Intent/boundary and decision briefpendingdraft belowresearch refresh
Research, ecosystem strategy, live-source refreshpendingdraft belowpressure passes
Performance/DX/migration/regression/simplicity pressure passespendingdraft belowobjection ledger
Slate maintainer objection ledgerpendingdraft belowhigh-risk pass
High-risk deliberate modependingecosystem maintainer pass
Ecosystem maintainer passpendingrevision pass
Revision passpendingissue sync accounting
Issue sync accountingpendingclosure score and final gates
Closure score and final gatespendingfinal handoff

Scorecard:

DimensionWeightScoreEvidence
React 19.2 runtime performance0.200.75Current PagedEditable uses useSyncExternalStore, memoized geometry/projection, page mount items, and virtualized page surfaces; issue scan confirms #790, #5131, #2051, and #4141 keep perf proof benchmark-gated.
Slate-close unopinionated DX0.200.79Current public shape is small: useSlateLayout, PagedEditable, pageView, domStrategy, nodeLayout, pageBreaks. Issue scan confirms custom layout pressure #3892 should stay generic, not product-specific.
Plate and slate-yjs migration backbone0.150.68Existing pageBreaks read/write vocabulary and measurementProfile are promising, and issue scan reinforces metadata/provider protocols; authoritative snapshot semantics, profile drift, and collaboration/export ownership still need pass hardening.
Regression-proof testing strategy0.200.76Focused Playwright rows already cover rows=800 virtualized perf, startup/dropdown, fast scroll, margin hit testing, selection, and multi-page table stress; issue/test/benchmark maps confirm #5944 is not direct TDD and #790 needs benchmark harness proof.
Research evidence completeness0.150.76Pretext/Tiptap/TanStack compiled pages are read, related discovery reused durable pagination rows, and issue-ledger pass scanned requirements, package impact, test candidate map, benchmark candidate map, historical ledger, live ledger, coverage matrix, fork dossier, and PR reference.
shadcn-style composability and minimalism0.100.76Pagination example controls are proof-oriented and URL-backed; final plan still needs a sharper public/private split for measurement and skeleton status.
Weighted total1.000.75Current-state plus related-discovery plus issue-ledger score only; closure threshold is not met.

Source-backed architecture north star:

  • target shape: exact measured layout snapshots are the only authoritative page truth. Virtualized rendering may use skeleton/cold estimates only with explicit status and must promote to exact measurement for visible, selected, composing, command-target, export, collab, and authoritative snapshot paths.
  • source evidence:
    • .tmp/slate-v2/packages/slate-layout/src/index.ts:401-409 exposes estimateBlock, currently returning a boolean rather than an accuracy or authority contract.
    • .tmp/slate-v2/packages/slate-layout/src/index.ts:392-399 already defines pageBreaks read/write sources, so strict-fidelity snapshots have a natural home.
    • .tmp/slate-v2/packages/slate-layout/src/index.ts:272-285 stores measurementProfile, pageBreaks, pageBreaksStatus, pages, blocks, and fragments in snapshots.
    • .tmp/slate-v2/packages/slate-layout/src/index.ts:1928-2325 implements the Pretext engine and measured block cache, but cold estimation bypasses exact Pretext line measurement.
    • .tmp/slate-v2/packages/slate-layout/src/react.tsx:620-760 virtualizes page surfaces and visible page content through page mount items.
    • .tmp/slate-v2/packages/slate-layout/src/page-mount-plan.ts:1-160 maps fragments/pages to mount items and filters by viewport/overscan.
    • .tmp/slate-v2/site/examples/ts/pagination.tsx:1586-1600 uses estimateBlock for virtualized rich stress blocks that are not active.
  • rejected drift: do not let skeleton estimates masquerade as exact page breaks; do not expose TanStack item ranges as the API; do not split table AST nodes as the default visual pagination fix; do not make apps choose typing/layout correctness by prop tuning.
  • migration posture: keep measurementProfile and pageBreaks as metadata over Slate value/commits. Plate/export/collab can opt into authoritative snapshots without changing raw Slate's JSON document model.

Public API target:

SurfaceProposed shapeUser-facing DXCompatibility / migrationEvidenceVerdict
Layout engineKeep engine?: SlatePageLayoutEngine; add a measured-cache/incremental engine contract instead of public estimation truthAdvanced users can swap engines; normal users use default PretextestimateBlock should become private/internal or renamed to skeleton-only policy if retainedindex.ts:401-409, index.ts:2822-2847revise
Snapshot statusAdd or formalize layoutStatus / block-page status: authoritative, pending, skeletonConsumers can decide whether page breaks are strict enough for export/collabKeeps current pageBreaksStatus idea, expands status semanticsindex.ts:272-285, index.ts:392-399add
Page viewKeep `pageView?: { mode?: 'single''spread'; gap?: number }`Small display API; no pageVirtualization propVirtualized page/spread mounting stays driven by domStrategyreact.tsx:360-438, PR reference pagination target
Node layout providersKeep generic provider/split protocols; strengthen docs/tests for tables/mediaApps/Plate provide exact row/media units without product TableKit in raw SlateNo AST table split required for visual page fragmentspagination.tsx:1690-1768, index.ts:80-114keep/revise
Authoritative page breaksKeep pageBreaks read/write; define profile-aware snapshot semanticsStrict users can read/write agreed page breaksDefault editing remains local derived layoutindex.ts:392-399; Pretext research drift evidencerevise

Internal runtime target:

LayerCurrent ownerTarget mechanismAvoidsEvidenceVerdict
Measurementslate-layout Pretext engineExact block measurement cache keyed by text/runs/style/page width/measurement profile, with dirty invalidationCanvas/Pretext work on every hot editindex.ts:1928-2325keep and harden
Incremental compositionslate-layout snapshot composerRecompute from earliest dirty block/page until page breaks converge; reuse prefix measurements/fragmentsWhole-document layout churn in huge docscurrent options have no dirty-input contractadd
Skeleton layoutslate-layout internal engine pathNon-authoritative cold-page approximation with explicit status and promotion pathFalse precision in collab/export/page-break truthestimateBlock boolean pathrevise hard
Page materializationslate-layout/react + slate-react domStrategyPage/spread mount plan owns repeated unit in paged mode; block virtualization remains for continuous/pathological docsRendering every page or leaking virtualizer APIreact.tsx:620-760, page-mount-plan.ts:1-160keep
Provider boxesnodeLayout providerExact provider-owned units with split policy and intrinsic sizing for rows/media/BFC-like blocksAST mutation, CSS float tricks, product TableKit in raw Slatepagination.tsx:1690-1768, Tiptap researchkeep/revise

Hook / component / render DX target:

SurfaceCall-site shapeComposition rulePerformance ruleEvidenceVerdict
useSlateLayoutuseSlateLayout(editor, { page, typography, nodeLayout, engine?, pageBreaks? })Hook returns external-store layout; options remain Slate-shapedEngine/nodeLayout/page changes refresh settings; hot text path must use dirty invalidationreact.tsx:95-138keep
PagedEditable<PagedEditable layout={layout} pageView={...} domStrategy={...} />Page chrome from renderPage, content from Slate editable overlayVirtualized domStrategy mounts page surfaces and visible content onlyreact.tsx:360-760keep
Pagination exampleControls demonstrate page/layout stress and URL-backed proofExample may show rows, row height, media split, page overscan, strategy, stress pagesExample must not teach fake stress page node types or estimation as correctnesspagination.tsx:443-564, pagination.tsx:1586-1600keep/revise copy/status

Plate migration-backbone target:

PressureSlate substrate targetPlate adaptation routeNon-goalEvidenceVerdict
Product pagination UIRaw Slate exposes exact snapshots, status, page geometry, and providersPlate wraps with page chrome, export UX, controls, and docsRaw Slate does not ship product page editor UIPR reference package baselinekeep
Tables/mediaGeneric provider units and split policyPlate table/media plugins provide exact row/media geometry and special UXRaw Slate product TableKitTiptap research table warning, current nodeLayout examplekeep
Export/collab strict fidelitypageBreaks authoritative snapshots plus measurement profilePlate/export can store agreed page breaks or server/client authorityDefault local editing does not promise cross-client exactnessPretext drift researchrevise

slate-yjs migration-backbone target:

PressureSlate substrate targetCollaboration routeNon-goalEvidenceVerdict
Page-break determinismPage breaks are metadata over document state, never document nodes by defaultYjs may sync pageBreaks state field when an authoritative source is enabledNo default cross-client byte-identical page breaks while Pretext uses canvas measurementpageBreaks options, Pretext drift evidencekeep with opt-in
Pending/skeleton pagesSkeleton layout is local runtime stateDo not sync skeleton/estimated page breaks as authoritativeNo collaboration truth from estimateBlockcurrent estimateBlock boolean pathrevise hard
Provider layoutProvider-owned units must be deterministic from document+profile inputsSync semantic table/media nodes; derive visual fragments locally or from authoritative snapshotNo AST row splitting as default collaboration modelcurrent table nodeLayout unitskeep

Intent / boundary record:

  • intent: stop treating virtualized pagination perf as a choice between exact but slow and approximate but fast. Long-term answer is exact layout caches plus incremental recomposition, with non-authoritative skeletons only where a user cannot observe or depend on exact page breaks yet.
  • outcome: a user-review-ready plan that lets execution auto-iterate until virtualized mode is close to staged mode while preserving exact layout truth for active/editing/export/collab paths.
  • in-scope: slate-layout engine contract, measured cache, snapshot status, incremental composition, page/spread virtualization, provider boxes, exactness oracle, perf matrix, issue/non-claim accounting, and autoresearch launch gate.
  • non-goals: implementing in this pass, replacing Pretext, promising cross-platform page-break determinism by default, raw Slate product TableKit, exposing TanStack internals, or adding public debounce/estimate props.
  • decision boundaries: this plan may choose API direction, internal ownership, proof gates, rejected alternatives, and autoresearch criteria without another user question. Execution details may vary as long as exactness and perf gates pass.
  • unresolved user-decision points: none for planning. The remaining uncertainty is proof, not direction.

Decision brief:

  • principles:
    • exactness is a contract, estimation is a rendering tactic;
    • layout stays derived from Slate state and measurement profile;
    • page virtualization changes mounting, not document truth;
    • provider boxes own complex layout without semantic AST mutation by default;
    • public APIs name Slate concepts, not implementation libraries.
  • top drivers:
    • huge-document typing/scroll latency;
    • page-break fidelity for export/collab;
    • table/media split correctness;
    • native browser behavior under missing DOM;
    • small raw Slate DX.
  • viable options:
    1. current cold-block estimation as public strategy;
    2. exact incremental layout with skeleton fallback status;
    3. DOM measurement authority for all visible and offscreen blocks;
    4. CSS/page-gap pagination like Tiptap Pages;
    5. AST splitting for tables/pages.
  • chosen option: option 2. Exact measured snapshots are authoritative; skeletons are clearly marked and promoted. This is the only option that can be both fast and honest.
  • rejected alternatives:
    • option 1 is fast but lies about precision under collaboration/export;
    • option 3 cannot scale and will reintroduce DOM hot-path dependency;
    • option 4 inherits Tiptap Pages' BFC/table/media limits;
    • option 5 mutates semantics for visual pagination and is poisonous for collaboration unless explicitly requested by a product adapter.
  • consequences: more layout-state machinery and stronger tests, but much better DX: users get exact snapshots/status instead of guessing which pages are fake.
  • follow-ups: related issue pass, exactness oracle design, perf matrix, raw research refresh only if existing Pretext/Tiptap/TanStack pages are insufficient.

Issue accounting:

Issue / clusterClaim categoryExact claimWhyProof routeV2 sync ledgerPR line
#5944Related, issue-reviewedExact pagination/page-break stability is directly related, but this plan does not claim closure yet.Live ledger names stable per-line pagination as current open issue; existing sync ledger requires page-boundary flicker, caret mapping, and page-break stability proof.Exact full-vs-virtualized layout oracle plus browser page-boundary caret tests.Existing row says issue-reviewed, unchanged.related matrix only
#790Related proof-route backlogPage/spread virtualization addresses dynamic rendering pressure but cannot be claimed until mount/edit/scroll benchmark proof lands.Existing coverage matrix requires mount/edit/scroll benchmarks, mounted-count proof, DOM coverage, and native behavior proof.rows 8/500/800/default matrix, DOM/page count, fast scroll, typing, native behavior rows.Existing row says unchanged/proof-route backlog.related matrix only
#5924Not claimedStructural page/table/debug DOM pressure is adjacent but the thread has no clean isolated repro and should not become a public ignore-cursor API.Test candidate map keeps it as not-a-test-candidate and useful only as an advanced-layout capability note.No direct proof route; keep as provider/split/DOM coverage pressure only.Existing row says not claimed, unchanged.related matrix only
#4141Existing improves unchanged / guardrailNested rerender breadth is already improved by existing runtime benchmark rows; this exact-layout plan must not widen that breadth.Coverage matrix preserves existing Improves; future layout subscriptions must preserve locality.profiler/render counters during layout snapshot and page virtualization work.Existing row says improves-claimed, unchanged.related matrix only
#5131, #2051GuardrailLayout snapshots and page virtualization must not widen subscriptions/rerenders.Existing sync ledger keeps them as subscription/performance guardrails.render/profiler counters during selection and typing.unchanged.related matrix only
#2793, #2572Release guard / not claimedMissing-DOM virtualized mode needs screen-reader/a11y policy before broad native parity claims.Existing rows keep accessibility as guardrail, not fixed claim.assistive-tech/browser policy proof before any parity claim.unchanged.related matrix only
#3892Policy non-claimGeneric layout substrate helps custom surfaces; product custom layout engines stay outside raw Slate closure.Existing rows preserve custom layout as product/adaptor pressure.docs/API only if public extension point changes.unchanged.related matrix only
#5945, #4056, #5992Existing improves unchangedLarge operation/clipboard benchmark claims are not promoted by pagination work.Existing ledgers own these claims separately.no pagination proof should rewrite them.unchanged.no PR change
Broader performance proof-route backlog: #2733, #2669, #5216, #5592, #4202, #4210, #3748, #5349, #4025Not claimed / backlogThese rows reinforce benchmark discipline but are not fixed or improved by this exact pagination plan.Coverage matrix groups them as performance proof-route backlog until an execution slice adds exact benchmark, browser, retained-memory, or static-rendering proof.no proof route in this plan unless execution touches their exact workload.unchanged.no PR change

Issue-ledger sync status:

  • ClawSweeper related-issue pass: skipped with evidence for this surface. Existing durable rows already cover the immediate pagination surface: #5944, #790, #5924, #4141, #5131, #2051, #2793, #2572, #3892, #5945, #4056, and #5992.
  • generated live gitcrawl rows read: targeted rows read for #5944 and #790.
  • manual v2 sync ledger update: not needed in related-discovery pass. Existing gitcrawl-v2-sync-ledger.md rows already keep #5944 issue-reviewed, #790 proof-route backlog, #5924 not claimed, #5131/#2051 guardrails, and large-operation issues unchanged.
  • fork issue dossier update: not needed in related-discovery pass. Existing dossier section already says pageBreaks are opt-in, domStrategy owns internal page/spread virtualization, and table/media/BFC pagination uses generic provider/split protocols.
  • issue coverage matrix update: not needed in related-discovery pass. Existing matrix already has no fixed/improved claim for this pagination target.
  • PR description sync: not needed in related-discovery pass. Current reference already records the small beta API target, measurementProfile, pageBreaks, and provider protocols.
  • full issue-ledger pass: complete. open-issues-ledger.md, gitcrawl-clusters.md, issue-clusters.md, test-candidate-map/, benchmark-candidate-map.md, package-impact-matrix.md, and requirements-from-issues.md were scanned for pagination, virtualization, dynamic rendering, large-document, page-break, layout, table/media/BFC, accessibility, custom layout, subscription, and rerender relevance.
  • full issue-ledger conclusion: no additional fixed or improved claim should be added. #5924 and #4141 are now explicit in the plan matrix; broader performance backlog rows remain not claimed unless execution later targets their exact workload.

Ecosystem strategy synthesis:

SystemSourceMechanismAvoidsStealRejectSlate targetVerdict
Pretextdocs/research/sources/editor-architecture/pretext-pagination-page-virtualization.mdprepare() does expensive measurement, layout() is arithmetic; measurement remains canvas/profile-sensitive today.DOM reflow in the hot layout path.Precompute/hot-path split, measurement profiles, and explicit fidelity caveat.Default cross-client/server page-break determinism while canvas measurement is the measurement source.Pretext default engine plus authoritative snapshot opt-in.partial
Premirrordocs/research/sources/editor-architecture/layout-measurement-and-ime-lanes.mdsnapshot -> measure -> compose -> render; pages/fragments are derived.Layout becoming document model.Derived layout lane and page chrome outside content.Encoding page fragments as Slate document nodes.slate-layout snapshots/fragments stay derived.agree
Tiptap Pagesdocs/research/sources/editor-architecture/pretext-pagination-page-virtualization.mdCSS floats/page gaps plus special table package for tables.Pretending complex blocks split automatically.Failure taxonomy: BFC blocks, tables, figures, images, padding, oversized nodes.CSS-float pagination, manual AST splitting as default, raw Slate product TableKit.provider-owned split protocols and exact box units.diverge
TanStack Virtualdocs/research/sources/editor-architecture/tanstack-virtual-and-github-large-surface-virtualization.mdHeadless range engine, measured items, overscan, retained indexes.Rendering every repeated unit.Internal range engine and repeated-unit discipline.Public TanStack-shaped options or letting it own selection/copy/IME/a11y policy.Internal page/spread mount plan behind domStrategy.partial
Current Slate v2live .tmp/slate-v2 files listed abovePretext engine, page mount plan, PagedEditable, node layout provider, Playwright perf rows.Starting from theory only.Existing substrate and tests.Current boolean estimateBlock as authoritative layout.exact snapshots + skeleton status + incremental oracle.revise

Legacy regression proof matrix:

Regression classLegacy behaviorSlate v2 targetProof routeOwnerStatus
page-boundary caret flickerPagination issue pressure reports unstable per-line page behaviorexact measured page breaks for visible/selected pagesbrowser page-boundary caret and line mapping rowsslate-layout + slate-reactpending execution
virtualized missing DOMlarge docs cannot render everything but native behavior depends on DOMpage/spread mount plan with selected/composing/target retention and explicit degradation policyfast scroll, selection, copy/find/a11y policy rowsslate-reactpending execution
inaccurate cold pagesestimated blocks can shift page breaksskeleton status cannot be exported/synced as truthfull measured vs virtualized oracleslate-layoutpending execution
table/media page splitCSS/AST hacks break semanticsprovider-owned exact units and split policiesmulti-page table/media fixtureslate-layout + plugins/examplespending execution
subscription/rerender breadthlayout snapshots can cause broad React worknarrow external-store snapshots and memoized projectionsprofiler/render countersslate-layout/reactpending execution

Browser stress / parity strategy:

SurfaceScenarioBrowser/deviceCommand or proof routeExpected signalStatus
exact oraclesame document rendered full measured vs virtualized/incrementalunit/browser hybridnew slate-layout oracle testidentical authoritative page breaks/fragments for promoted pagespending
rows=800 virtualized perf/examples/pagination?page_layout=single&rows=800&strategy=virtualizedChromium firstfocused existing Playwright rowp95 <= staged envelope, DOM <= 600, page surfaces <= 8existing row, final rerun pending
default 1000-page route?strategy=virtualized with stress pagesChromium firststartup/dropdown/typing/scroll Playwright clustervisible content < 800ms app-ready, no node replay storm, bounded DOMexisting rows, final rerun pending
multi-page tabletable spanning around 10 pagesChromium firsttable fixture proof + rows 500/800 matrixno AST split, rows mounted around viewport, click/edit worksexisting rows, final rerun pending
page margin selectionleft/right margin line start/end hit testingChromium firstexisting margin hit testing rowsnative-ish click target resolutionexisting rows, final rerun pending
a11y/native missing DOMvirtualized page contentlater browser/device/AT lanepolicy proof before broad parity claimno false native equivalence claimguarded

Verification workspace gate:

ClaimWorkspaceCommandResultOwner
Current source grounding.tmp/slate-v2targeted sed / rg reads for slate-layout, PagedEditable, page mount plan, pagination example, and pagination testscomplete for current-state pass; no behavior proof claimedslate-plan
Planning artifact integrityplate-2node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-31-exact-virtualized-pagination-plan.mdpending; not eligible this activationclosure pass
Exact layout oracle.tmp/slate-v2command TBD in execution planpendingexecution
Focused layout/package gate.tmp/slate-v2bun --filter slate-layout test && bun --filter slate-layout typecheckpendingexecution
Focused pagination browser gate.tmp/slate-v2PLAYWRIGHT_RETRIES=0 bun playwright playwright/integration/examples/pagination.test.ts --project=chromium -g "<pagination cluster>" --reporter=linependingexecution
Fast package gate.tmp/slate-v2bun checkpendingexecution

Applicable implementation-skill review matrix:

LensAppliesStatusFindingsPlan delta
vercel-react-best-practicesyespendingReact external-store/page projection and memoized render work are in scope.future pass must answer subscription breadth and render loops.
performance-oracleyespendingExactness + virtualization needs complexity and cache invalidation review.future pass must define dirty-range complexity and memory tags.
performanceyespendingNeeds cohort matrix, interaction p95/p99, DOM/page count, memory/status policy.future pass must finish perf matrix.
tddyespendingExactness oracle must be test-first before autoresearch.execution queue starts with oracle red test.
shadcnmaybependingExample controls are UI proof surface, but core API is not UI.likely skip or constrain to example control minimalism.
react-useeffectyespendingPagedEditable scroll/resize viewport effects and layout refresh effects are in scope.future pass should check effect dependencies and external synchronization.

High-risk deliberate-mode pre-mortem:

RiskTriggerFailure modeMitigationProofStatus
skeleton treated as truthexport/collab reads estimated page breaksinconsistent page numbers/breaks across clientsexplicit snapshot/block/page status and promotion before authorityexactness oracle + snapshot status testspending
incremental layout under-invalidatesedit before page Nstale downstream page breaksrecompute suffix until page-break convergencefull measured vs incremental oraclepending
over-invalidatesevery editvirtualized becomes slower than stageddirty block/page ranges, prefix reuse, measured cacheperf matrixpending
table/media split lieslarge table/media crosses pagevisual split mismatches semantic model or selectionprovider units with exact split policymulti-page table/media testspending
public API bloatpressure to expose virtualizer/estimate knobssticky low-level APIkeep public API Slate-shaped and private implementation freeAPI reviewpending

Slate maintainer objection ledger:

ChangeObjectionTradeoffEvidenceMigration/docs/proof answerVerdict
Exact snapshots plus skeleton statusMore states than a simple snapshot.Extra state is cheaper than lying about precision.Current estimateBlock has no authority vocabulary.Document status and require promotion for export/collab/selection.accept, proof pending
Incremental compositionPage breaks can ripple far.Honest suffix recomposition beats whole-doc compose and fake local fixes.Current SlatePageLayoutSnapshot already has blocks/fragments/pages; missing part is dirty input.Oracle must compare against full measured layout.accept, proof pending
Provider-owned split policyPlugins must provide sizing/layout hints.Complex boxes need owner knowledge; raw Slate cannot infer table semantics generically.Tiptap Pages needed special table package; current nodeLayout proves generic provider shape.Keep raw protocol generic and Plate owns product adapter.accept
Authoritative page breaks opt-inDefault collab/export page breaks can drift.Honest local default plus opt-in authority is better than false determinism.Pretext uses canvas measurement today.Store measurement profile and optional pageBreak snapshot source.accept
Autoresearch after oracleDelays research automation.Without an oracle, autoresearch optimizes vibes.Existing Playwright/perf rows prove the need for exact counters.Build oracle first, then let autoresearch mutate internals against it.accept

Hard cuts and rejected alternatives:

Option / APIKeep / cut / rejectWhyMigration costEvidenceFollow-up
Public estimateBlock as precision contractcut/reviseBoolean estimation cannot represent authority, drift, or promotion.rename/private or status-gated if retained.index.ts:401-409API pass
Public pageVirtualization proprejectdomStrategy already owns DOM materialization; extra prop splits responsibility.none.PR reference targetkeep out
TanStack options in public APIrejectRange engine is implementation detail.none.TanStack researchkeep internal
AST table/page splitting by defaultrejectVisual pagination should not mutate semantic/collab model.none for raw Slate.Tiptap researchprovider split policy
Exact measured snapshotskeepOnly credible source for export/collab/selected layout truth.internal engine/cache work.current Pretext/measured block cacheimplement after plan accepted
Skeleton cold pageskeep only as non-authoritativeNeeded for huge-doc perceived perf, but never truth.status API/docs/tests.current estimateBlock routeformalize

Plan deltas from review:

  • Created a fresh Slate Plan from the slate-plan template.
  • Current-state pass re-grounded the plan in live .tmp/slate-v2 source, not old architecture notes.
  • Related issue discovery pass reused existing durable pagination issue rows and explicitly skipped broad live GitHub/ClawSweeper rerun because no fixed, improved, duplicate, stale, or new claim text changed.
  • Issue-ledger pass scanned the full cached issue surfaces and promoted #5924, #4141, and the broader performance proof-route backlog from sync-status context into explicit plan accounting.
  • Reframed "cold-block estimation" as skeleton-only, not precise layout.
  • Promoted the exactness oracle to the first execution artifact.
  • Moved autoresearch behind the oracle/perf matrix gate.
  • Kept existing issue claims conservative: no new fixed or improved issue claim from planning.

Open questions and decision-changing evidence:

QuestionWhy it mattersEvidence neededOwnerStatus
Should estimateBlock stay public under a new name, or become engine-private?Public shape affects DX and future compatibility.API pass plus example/readme pressure.next passespending
What exact status vocabulary is enough?Too little lies; too much bloats API.source/API pass with export/collab examples.next passespending
How much suffix recomposition is acceptable after an early edit?Determines whether exact incremental layout can match staged perf.oracle + rows 8/500/800/default perf matrix.executionpending
Does authoritative page-break writing need conflict metadata?Collab/export strict mode may need source/profile ownership.slate-yjs/export pass or focused design row.future passpending

Implementation phases with owners:

PhaseOwnerScopeEntry criteriaExit criteriaVerification
1. Exactness oracleslate-plan execution modeFull measured layout vs virtualized/incremental layout contractuser accepts ready planoracle fails on current skeleton truth where expected, then passes after exact promotionbun --filter slate-layout test
2. Snapshot status/APIslate-plan execution modeauthoritative / pending / skeleton semantics and docs/testsphase 1 red contract existsconsumers can distinguish strict vs approximate page dataunit tests + typecheck
3. Incremental measured cacheslate-plan execution modedirty block/page invalidation, prefix reuse, suffix recompositionstatus API setexact oracle green and perf matrix improveslayout tests + Playwright
4. Provider box hardeningslate-plan execution modetable/media unit exactness, split policy, multi-page fixturephase 3 baselinemulti-page table/media no AST split and bounded DOMPlaywright table/media rows
5. Autoresearch loopcodex-autoresearch/autogoal execution modeoptimize internals against oracle/perf matrixoracle and matrix existmeasurable perf target reached without exactness regressionrepeated verifier command
6. Review and closeoutautoreview + slate-plandirty-local review, issue sync, PR reference syncimplementation greenno accepted/actionable findings, ledgers currentautoreview + bun check

Fast driver gates:

GateCwdCommand / artifactProvesStatus
planning artifact check/Users/zbeyens/git/plate-2node .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-31-exact-virtualized-pagination-plan.mdfinal plan/template integritypending; not eligible this pass
current source grounding/Users/zbeyens/git/plate-2/.tmp/slate-v2targeted source reads listed in Boundariescurrent-state claimscomplete
exact oracle/Users/zbeyens/git/plate-2/.tmp/slate-v2TBD slate-layout test commandexactness preserved under virtualization/incremental layoutpending execution
perf matrix/Users/zbeyens/git/plate-2/.tmp/slate-v2focused pagination Playwright clustervirtualized approximates staged envelope at rows 8/500/800/defaultpending execution
package gate/Users/zbeyens/git/plate-2/.tmp/slate-v2bun checkfast source quality gatepending execution

Final user-review handoff outline:

  • accepted plan items: pending final pass.
  • before / after API shape: draft target is current Pretext/page layout API with skeleton estimation revised into explicit non-authoritative status and exact measured snapshots as truth.
  • hard cuts: no public precision claim from estimateBlock, no public pageVirtualization, no TanStack public API, no AST table split default, no cross-client page-break determinism by default.
  • issue claims and non-claims: draft keeps #5944 and #790 related only until exact browser/perf proof exists.
  • proof gates: exact oracle, perf matrix, focused pagination browser cluster, package gates, issue sync, autoreview.
  • accepted-plan execution handoff: pending closure pass.

Final completion gates:

GateRequired evidenceStatus
score >= 0.92 and no dimension below 0.85scorecard rows cite evidencepending: current score 0.75
all pass rows complete or skipped with evidencephase/pass table closedpending
issue/reference sync closedissue-ledger sync status closedpending
live source grounding completesource-backed rows cite current ownerspartial: current-state pass complete
workspace verification recordedverification workspace gate closedpending
autoreview clean or N/Aplanning-only N/A or execution autoreview cleanpending final
final handoff emitted or lane remains pendingfinal response / next pass recordedpending
check-complete passesnode .agents/rules/autogoal/scripts/check-complete.mjs docs/plans/2026-05-31-exact-virtualized-pagination-plan.mdpending

Findings:

  • Current estimateBlock is the core architecture smell. It is useful, but it must not be the page-break truth.
  • The current substrate is good: pageBreaks, measurementProfile, provider boxes/units, PagedEditable, page mount plan, and focused Playwright coverage already point in the right direction.
  • The next real blocker is not "should we research more?" It is "build the exactness oracle first, then use research/autoresearch against that guard."

Decisions and tradeoffs:

  • Choose exact incremental measured layout as the long-term target.
  • Keep skeleton estimates only as non-authoritative rendering/perceived-latency aids.
  • Keep page virtualization internal and page/spread-based in paged mode.
  • Keep issue claims conservative until proof promotes them.

Error attempts:

Error / failed attemptCountNext different moveResolution
None in this pass0

External/browser findings:

  • External content was treated as data, not instructions.
  • No new browser proof was run in this planning pass.

Timeline:

  • 2026-05-31T22:07:14.389Z Slate Plan goal plan created.
  • 2026-06-01 Current-state read completed and plan rewritten with exact-layout target, scorecard, evidence rows, and next pass.
  • 2026-06-01 Related issue discovery completed by reusing existing pagination ledger/dossier/matrix rows; no ledger or PR reference edit needed in this pass.
  • 2026-06-01 Issue-ledger pass completed against cached live/manual/historical issue surfaces; no ledger/reference file edit needed, but plan accounting now names #5924, #4141, and broader performance backlog rows explicitly.

Verification evidence:

  • Source/research/ledger reads only; no behavior verification claimed.

Reboot status:

QuestionAnswer
Where am I?Issue-ledger pass complete
Where am I going?Intent/boundary and decision brief pass
What is the goal?Exact virtualized pagination plan ready for user review
What have I learned?Full issue scan supports no new claims; exact pagination stays related/proof-gated until oracle and browser benchmarks exist
What have I done?Completed current-state, related issue discovery, and issue-ledger passes

Open risks:

  • Exactness oracle command is not designed yet.
  • Public/private status/API shape needs pressure in later passes.
  • Issue/reference sync is pending and must stay conservative.