docs/plans/2026-05-21-slate-v2-pagination-architecture-dx-ralplan.md
slate-layout..tmp/slate-v2/site/examples/ts/pagination.tsx owns
buildPaginationProjection, path-keyed element boxes, per-text-span line
decorations, hitWidth, and hitHeight..tmp/slate-v2/packages/slate-layout/src/index.ts owns
getSlatePageLayoutGeometry, getSlatePageLayoutProjection, pagination
fragments, root-aware projectRange, and layout snapshots..tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx currently covers
only small block-start shortcuts for headings, block quotes, and lists..tmp/slate-v2/site/examples/ts/tables.tsx is explicitly a basic rendering
example; table editing is local and minimal, with no table map, row/column
commands, header/alignment model, selection grid, or pagination geometry..tmp/slate-v2/site/examples/ts/custom-types.d.ts defines table, row, and
cell example types, but these are site example types, not a Slate layout or
Markdown schema contract..tmp/slate-v2/packages/slate-layout/src/react.tsx keeps PagedEditable
focused on fixed page surfaces plus one editable overlay..tmp/slate-v2/playwright/integration/examples/pagination.test.ts proves
blank-tail clicks, paragraph-gap clicks, leading empty paragraphs, caret
containment, and Backspace behavior in Chromium.../premirror/packages/react/src/index.tsx has the right shape: page
viewport, geometry, single editor overlay, projected selection.../premirror/packages/core/src/index.ts models StyledRun, PlacedRun, and
per-line run ranges instead of reducing a block to one string/style pair.../premirror/apps/demo/src/App.tsx still keeps paragraph/run decoration
construction in the demo. That is acceptable for a prototype but not the best
Slate v2 API target.../pretext/src/rich-inline.ts exposes rich inline items, fragments, and line
ranges. Slate should use that substrate for mixed leaf styles instead of
measuring every block with the first text leaf.docs/research/concepts/markdown-native-editing-authority.md says Markdown
editing authority is not just parser correctness; it includes paragraph
creation, line-break handling, links/images, shorthand expansion, and keyboard
ownership.docs/research/sources/typora/code-math-table-and-task-surfaces.md says code,
math, table, and task surfaces own local editing behavior; tables need
row/column insert/delete, resize, alignment, movement, and menu-level
operations.docs/research/sources/lexical/markdown-package-and-shortcuts-doc-patterns.md
supports grouping import/export, shortcuts, and transformers, but that package
shape belongs in Plate for Slate's ecosystem boundary.docs/research/sources/tiptap/input-rules-and-extension-doc-patterns.md
supports a dedicated input-rule concept with extension-local rule authoring.Intent: decide whether the current pagination/layout direction can become the clean architecture for full Markdown-standard rich text, including tables.
Desired outcome: a Slate-close API where Plate/app-owned Markdown import/export, input rules, rich inline layout, tables, and pagination compose without examples owning private geometry or parser glue.
In scope:
PagedEditable, Editable, and page chrome.Non-goals:
slate-react.Decision boundaries:
PagedEditable should stay a thin page-stack renderer.slate-layout owns page geometry, projected block/line/table rectangles, and
layout-space hit-target policy.Principles:
Drivers:
text string and one textStyle per
block, while Slate documents are leaf/run based.hitWidth and hitHeight are real concepts, not demo styling.PagedEditable split is good and should not absorb selection
policy.Options:
PagedEditable.
Target support is not "a few Markdown shortcuts". It is a rich document model that round-trips Markdown syntax while editing as Slate nodes:
Raw Slate should not expose a Markdown package. The Slate-level API should stay layout/substrate-shaped:
const editor = createEditor({
extensions: [
pageLayout({ engine: pretextPageLayoutEngine() }),
],
})
Framework authors should build Markdown parse/serialize/input rules in Plate or
app packages over Slate's schema, transform, clipboard/input, and layout
primitives. Do not put Markdown behavior into slate-layout, slate-react, or
PagedEditable.
The current model:
type SlatePageLayoutBlock = {
text: string
textStyle: SlatePageLayoutTextStyle
}
This is too weak for Slate. The replacement target is leaf/run based for inline content, and block/table-box based for structured content:
type SlatePageLayoutRun = {
id: string
path: Path
range: {
end: number
start: number
}
text: string
textStyle: SlatePageLayoutTextStyle
}
type SlatePageLayoutBlock = {
element: Element
kind: 'flow' | 'box' | 'table'
lineHeight: number
path: Path
runs: readonly SlatePageLayoutRun[]
boxes?: readonly SlatePageLayoutBox[]
spacingAfter: number
}
Box layout target:
type SlatePageLayoutBox = {
kind: 'block' | 'code-line' | 'image' | 'thematic-break' | 'table' | 'table-cell'
path: Path
rect: SlatePageRect
split?: 'avoid' | 'page' | 'row' | 'line'
}
Line output should preserve placed runs:
type SlatePageLayoutPlacedRun = SlatePageLayoutRun & {
left: number
width: number
}
type SlatePageLayoutProjectedLine = {
blockIndex: number
hitRect: SlatePageRect
lineIndex: number
pageIndex: number
path: Path
runs: readonly SlatePageLayoutPlacedRun[]
textRect: SlatePageRect
}
This matches Premirror's StyledRun/PlacedRun split and maps directly to
Pretext rich-inline fragments. It also creates a place for tables and atomic
Markdown blocks that are not text-flow runs.
Tables need their own model. The current example renders nested Slate elements and prevents some destructive actions at cell boundaries, but that is not a Markdown-rich table architecture.
Owner boundary: table editing belongs in Plate/app feature packages. Raw Slate should expose enough generic structure for those packages to provide header rows, alignment, cell-grid selection, row splitting, and repeated headers without importing a raw Slate table package.
Core data model:
type TableElement = {
type: 'table'
align?: Array<'left' | 'center' | 'right' | null>
children: TableRowElement[]
}
type TableCellElement = {
type: 'table-cell'
header?: boolean
colspan?: number
rowspan?: number
children: Descendant[]
}
Product-package responsibilities:
Raw Slate substrate:
Rejected shortcut: treating tables as paragraphs with pipes. That is fine for a source editor, not a rich Markdown editor.
| System | Source | Mechanism | Avoids | Steal | Reject | Slate target | Verdict |
|---|---|---|---|---|---|---|---|
| Premirror | ../premirror/packages/core/src/index.ts, ../premirror/packages/react/src/index.tsx | snapshot -> measured runs -> composed pages -> single editor overlay | page chrome growing with content, duplicated text layer | run model, page geometry, single overlay, projected selection | ProseMirror position model as public API | Slate path/root based run and box projection | agree |
| Pretext | ../pretext/src/rich-inline.ts | rich inline items produce fragment ranges and line stats | block-string measurement lying for mixed styles | rich-inline range walking and prepared measurement cache | editor ownership inside text layout engine | layout engine adapter consumes Slate runs and returns placed runs | agree |
| Typora | docs/research/sources/typora/code-math-table-and-task-surfaces.md | Markdown surfaces own local editing behavior | parser-only Markdown that feels fake while editing | table/task/code/math behavior as UX authority | full Typora product clone | Plate/app packages over Slate substrate | partial |
| Lexical | docs/research/sources/lexical/markdown-package-and-shortcuts-doc-patterns.md | Markdown package groups import/export, shortcuts, transformers | scattering Markdown features across examples | transformer inventory and explicit conversion layer | Lexical node/update model and raw-Slate Markdown package | Plate Markdown package over Slate substrate | diverge |
| Tiptap | docs/research/sources/tiptap/input-rules-and-extension-doc-patterns.md | dedicated input rules concept plus extension-local authoring | hidden editor-global autoformat magic | explicit input-rule API and extension hook | regex-heavy docs as first DX | Plate/app input-rule packages over Slate hooks | agree |
| Current Slate v2 | .tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx, .tmp/slate-v2/site/examples/ts/tables.tsx | example-local transforms and renderers | none; this is the current gap | keep examples as proof fixtures | shipping example-local logic as best practice | substrate-owned layout, feature-owned Markdown/table | gap |
Layering:
slate: document model, operations, schema/specs, transactions, history,
state fields, deterministic normalization.slate-layout: page geometry, run projection, box projection, hit targets,
range projection, and layout invalidation.slate-layout-pretext: measurement engine adapter for inline rich text and
line geometry.slate-react: editable runtime, DOM bridge, browser selection, rendering
strategy, and subscriptions.Public DX should read like this:
const editor = useSlateEditor({
extensions: [
pageLayout({ engine: pretextPageLayoutEngine() }),
],
initialValue,
})
return (
<Slate editor={editor}>
<PagedEditable
layout={layout}
renderElement={renderElement}
renderLeaf={renderLeaf}
/>
</Slate>
)
No example should need to know how to map leaf spans to measured line fragments, how to stretch native hit targets, or how table cells paginate.
Runtime invalidation:
Budgets:
Degradation policy:
text/textStyle with runsslate-layout-pretext to prepareRichInlinegetSlatePageLayoutDecorationstextRect and hitRectPlanning-only gate:
# cwd: /Users/zbeyens/git/plate-2
node tooling/scripts/completion-check.mjs --id 019e46be-4ec4-7d11-bc6e-9fcf033a8803
Implementation gates after Ralph changes .tmp/slate-v2:
# cwd: /Users/zbeyens/git/plate-2/.tmp/slate-v2
bun --filter slate-layout test
bun --filter slate-layout-pretext test
bun --filter slate-layout typecheck
bun --filter slate-layout-pretext typecheck
bun typecheck:site
PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun run playwright playwright/integration/examples/pagination.test.ts --project=chromium
PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun run playwright playwright/integration/examples/markdown-rich-text.test.ts --project=chromium
bun lint:fix
bun check
Markdown/table package gates belong in Plate/app package work, not raw Slate pagination gates.
Keep the existing geometry/projection entry point, but make it run-aware and box-aware, and return both visual and native-hit rectangles:
const projection = getSlatePageLayoutProjection(snapshot, {
geometry,
hitTesting: {
blockGap: { max: 48, target: 'previous-line-end' },
inlineInset: 2,
},
})
Target projection data:
type SlatePageLayoutProjectedLine = {
blockIndex: number
fragmentId: string
lineIndex: number
pageIndex: number
path: Path
range: {
end: number
start: number
}
textRect: SlatePageRect
hitRect: SlatePageRect
}
Table projection:
const projection = getSlatePageLayoutProjection(snapshot, { geometry })
projection.tables.get(pathKey)?.rows[0]?.cells[2].rect
Add one decoration bridge so examples do not reimplement text-span mapping:
const projectedDecorations = getSlatePageLayoutDecorations(projection, {
data: ({ line, run }) => ({ paginationLine: { line, run } }),
})
const decorate: EditableDecorate<PaginationLineDecorationData> = ([node, path]) =>
NodeApi.isText(node) ? projectedDecorations.get(path) : []
Then the example stays focused on actual rendering:
const renderElement = ({ attributes, children }) => {
const block = projection.blocks.get(attributes['data-slate-path'])
return (
<div {...attributes} style={blockStyle(block)}>
{children}
</div>
)
}
const renderLeaf = ({ attributes, children, segment }) => {
const line = getProjectedLine(segment)
return (
<span {...attributes} style={lineStyle(line)}>
{children}
</span>
)
}
This cuts the dirty part: examples no longer compute text spans, next-block gaps, line hit widths, table boxes, or decoration ranges.
Rewrite:
buildPaginationProjection should move out of the example.site/examples/ts/tables.tsx into a
table extension with map-aware commands and tests.site/examples/ts/markdown-shortcuts.tsx
into a Markdown input-rule package.hitWidth/hitHeight should become hitRect on projected lines.Do not rewrite:
PagedEditable page-surface/editor-overlay ownership.pageSettings as an editor state field.Unit tests in slate-layout:
Plate/app Markdown package tests:
Plate/app table package tests:
Browser tests in the pagination example:
insertBreak creates visible editable empty paragraphs.Performance/stress tests:
Non-claims to preserve:
ClawSweeper status: skipped for this pass. Reason: this activation changes a planning target only and makes no new implementation, browser behavior, issue fix, or PR auto-close claim. Existing issue-ledger evidence was still read for the related surface.
Current issue mapping:
| Issue | Cluster | Claim | Why | Proof route | V2 sync ledger | PR line |
|---|---|---|---|---|---|---|
#6034 | table DOM selection | Existing fixed claim, unchanged | Current plan uses the table boundary as architectural pressure for generic selection/layout substrate, but adds no new implementation proof. | Existing coverage matrix and PR reference fixed claim. | unchanged | unchanged |
#5945 | large paste performance | Related, not claimed | Markdown paste/import must be benchmarked against large-paste pressure in Plate/app package work, but this plan adds no paste implementation. | future Plate/app parse/paste benchmark. | unchanged | related matrix only when implemented |
#5131 | selection subscription breadth | Related, not claimed | Table/cell selection and pagination projections must avoid broad subscriptions, but no React runtime code changes here. | future React render benchmark/browser proof. | unchanged | related matrix only when implemented |
#5216 | selection latency | Related, not claimed | Paged/table selection needs browser latency proof before any claim. | future browser stress row. | unchanged | related matrix only when implemented |
Fixed issue claims added: none.
Improved issue claims added: none.
PR description update: unchanged. Reason: this is a planning-only Ralplan update
with no new fixed/improved issue count, no .tmp/slate-v2 implementation proof,
and no current PR-body claim to change. The implementation phase must update
docs/slate-v2/references/pr-description.md when layout projection APIs or
generic substrate APIs actually land.
| Change | Strong objection | Steelman antithesis | Tradeoff tension | Rejected alternative | Migration answer | Proof required | Verdict |
|---|---|---|---|---|---|---|---|
| Add raw Slate Markdown package | Markdown is product policy; raw Slate should not become Typora. | Keep Markdown examples only and let product layers own everything. | Plate/app packages need a clean substrate, not a bundled raw Slate parser. | Example-local shortcuts are too weak as product guidance, but fine as proof fixtures. | Plate owns package API; raw Slate owns schema/operation/input substrate. | Plate package corpus, input-rule browser rows, paste benchmark. | cut from raw Slate |
| Add raw Slate table package | Tables are endless scope; raw Slate historically keeps examples minimal. | Leave tables to Plate. | Table map/cell selection adds real complexity. | Example-only table guards are insufficient for product docs, but acceptable as raw Slate proof. | Plate owns feature package; raw Slate owns selection/layout/normalization substrate. | Plate table map tests, cell nav browser tests, GFM serialization tests. | cut from raw Slate |
Make slate-layout run-aware | Block-string layout is simpler and already powers the demo. | Delay until mixed-style pagination actually breaks. | More measurement data and cache invalidation. | First-leaf text style: lies for bold/italic/code/link-rich content. | Existing text/textStyle can be internal migration only; public examples use projection helper. | mixed-mark layout tests, Pretext rich-inline adapter tests. | keep |
Make slate-layout box-aware for tables/atoms | Layout is becoming a document engine. | Keep pagination text-only until page layout matures. | Box layout must define split/fallback policy. | Treat tables/images/hr as fake text runs: corrupts geometry and selection. | Structured nodes expose boxes through layout adapters; React remains renderer. | table row/cell projection tests, image/hr atomic box tests, browser debug overlay. | keep |
Add hitRect separate from textRect | Native hit policy is browser quirk, not layout data. | Keep hit width/height in the example. | More projection data to document. | CSS-only example hacks: hard to test and copy-paste dirty. | Helper defaults can be conservative and optional. | blank-tail/gap unit tests plus Chromium rows. | keep |
Trigger: public package/API architecture, table data model, Markdown parse/serialize behavior, browser selection, and layout runtime performance.
Blast radius:
slate, slate-react, slate-layout,
slate-layout-pretext, future Plate Markdown/table packagesPre-mortem:
Rollback/remediation:
PagedEditable stays thin, so layout experiments do not poison core React
renderer contracts.| Lens | Status | Findings | Plan delta |
|---|---|---|---|
vercel-react-best-practices | applied | Avoid broad subscriptions; keep Markdown/table rules in transactions; React consumes projection snapshots. | Added performance architecture and budgets. |
performance-oracle | applied | Hot paths are paste, table-map recompute, run measurement, and page projection. | Added 10k-block, 1k-row table, 1MB paste, and p95 budgets. |
performance | applied | Repeated-unit budgets and degradation policy are required before any production pagination claim. | Added explicit budgets and oversized table/wide table policies. |
tdd | applied | Behavior must be proven through package APIs and browser rows, not implementation internals. | Added package, browser, and stress test matrix. |
build-web-apps:shadcn | skipped | No UI component implementation in this pass. | none |
react-useeffect | skipped | No new effect code in this pass. | none |
Plate:
slate-yjs/collab:
PagedEditable thin; move hit target and decoration mapping
into slate-layout.Overall: 0.75 current, 0.92 target.
Do not call the current shape absolute best. It is a strong experimental implementation with the right page/editor ownership, but it is not enough for a Markdown-rich editor. The API is still dirty because reusable layout law is sitting in the example, and the layout model is still missing run-aware inline content plus box-aware tables/atoms.
The best next architecture move is not only hit-target cleanup. First keep
Markdown and table product packages out of raw Slate, then make slate-layout
run-aware and box-aware using Pretext rich-inline ranges plus table/atomic block
boxes, then promote projection hit targets and decoration mapping into
slate-layout, then simplify examples to show only API call sites and rendering
callbacks.
Changed files:
.tmp/slate-v2/config/typescript/tsconfig.jsondocs/slate-v2/references/pr-description.mdWhat changed:
Next owner:
slate-layout run-aware layout: replace block string-only projection with
placed runs and leaf-path mapping.slate-layout Run-Aware Contract TracerChanged files:
.tmp/slate-v2/packages/slate-layout/src/index.ts.tmp/slate-v2/packages/slate-layout/test/page-layout-contract.test.ts.tmp/slate-v2/packages/slate-layout/dist/index.js.tmp/slate-v2/packages/slate-layout/dist/index.d.ts.tmp/slate-v2/packages/slate-layout/dist/index.d.ts.map.tmp/slate-v2/packages/slate-layout/dist/src-DIexvwjR.js.tmp/slate-v2/packages/slate-layout/dist/src-DIexvwjR.js.map.tmp/slate-v2/packages/slate-layout-pretext/dist/index.js.tmp/slate-v2/packages/slate-layout-pretext/dist/index.js.mapdocs/slate-v2/references/pr-description.mdWhat landed:
SlatePageLayoutRun and SlatePageLayoutPlacedRun.text and textStyle stay in place as compatibility fallback.Verification:
bun --filter slate-layout test failed because
block.runs was missing.bun --filter slate-layout test: pass, 9 tests, 37 assertions.bun --filter slate-layout typecheck: pass.bunx biome check packages/slate-layout --fix: pass.bun --filter slate-layout build: pass.bun --filter slate-layout-pretext test: pass, 2 tests, 8 assertions.bun --filter slate-layout-pretext typecheck: pass.bun --filter slate-layout-pretext build: pass.Reference docs:
docs/slate-v2/references/pr-description.md updated to record the run-aware
layout surface.Next owner:
slate-layout box-aware layout: atomic block, code line, image, thematic
break, and table/cell boxes.slate-layout Box-Aware Contract TracerChanged files:
.tmp/slate-v2/packages/slate-layout/src/index.ts.tmp/slate-v2/packages/slate-layout/test/page-layout-contract.test.ts.tmp/slate-v2/packages/slate-layout/dist/index.js.tmp/slate-v2/packages/slate-layout/dist/index.d.ts.tmp/slate-v2/packages/slate-layout/dist/index.d.ts.map.tmp/slate-v2/packages/slate-layout/dist/src-DIexvwjR.js.tmp/slate-v2/packages/slate-layout/dist/src-DIexvwjR.js.map.tmp/slate-v2/packages/slate-layout-pretext/dist/index.js.tmp/slate-v2/packages/slate-layout-pretext/dist/index.js.mapdocs/slate-v2/references/pr-description.mdWhat landed:
SlatePageLayoutBox, SlatePageLayoutBoxKind, and
SlatePageLayoutBoxSplit.code-block,
thematic-break, image, table, and table-cell nodes.Verification:
bun --filter slate-layout test failed because no
block.boxes existed.bun --filter slate-layout test: pass, 10 tests, 38 assertions.bun --filter slate-layout typecheck: pass.bunx biome check packages/slate-layout --fix: pass.bun --filter slate-layout build: pass.bun --filter slate-layout-pretext test: pass, 2 tests, 8 assertions.bun --filter slate-layout-pretext typecheck: pass.bun --filter slate-layout-pretext build: pass.Reference docs:
docs/slate-v2/references/pr-description.md updated to record the box-aware
layout surface.Next owner:
slate-layout Projection DX TracerChanged files:
.tmp/slate-v2/packages/slate-layout/src/index.ts.tmp/slate-v2/packages/slate-layout/test/page-layout-contract.test.ts.tmp/slate-v2/packages/slate-layout/dist/index.js.tmp/slate-v2/packages/slate-layout/dist/index.d.ts.tmp/slate-v2/packages/slate-layout/dist/index.d.ts.map.tmp/slate-v2/packages/slate-layout/dist/src-DIexvwjR.js.tmp/slate-v2/packages/slate-layout/dist/src-DIexvwjR.js.map.tmp/slate-v2/packages/slate-layout-pretext/dist/index.js.tmp/slate-v2/packages/slate-layout-pretext/dist/index.js.map.tmp/slate-v2/site/examples/ts/pagination.tsxWhat landed:
textRect and hitRect to projected layout lines.hitTesting.inlineInset plus block-gap hit extension policy to
getSlatePageLayoutProjection.getSlatePageLayoutDecorations, block/page rect spaces, and exported
getSlatePageLayoutPathKey.leafRange, so decoration ranges map to Slate text
offsets without example-local text-span walking.Verification:
bun --filter slate-layout test failed because
getSlatePageLayoutDecorations was not exported.bun --filter slate-layout test: pass, 12 tests, 42 assertions.bun --filter slate-layout typecheck: pass.bun typecheck:site: pass.bunx biome check packages/slate-layout site/examples/ts/pagination.tsx --fix:
pass.bun --filter slate-layout build: pass.bun --filter slate-layout-pretext test: pass, 2 tests, 8 assertions.bun --filter slate-layout-pretext typecheck: pass.bun --filter slate-layout-pretext build: pass.bun run lint:fix: pass.PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun run playwright playwright/integration/examples/pagination.test.ts --project=chromium:
pass, 3 tests.http://localhost:3101/examples/pagination;
reload was blocked by Browser URL policy, so no Browser screenshot claim is
made for this slice.Reference docs:
Next owner:
Changed files:
.tmp/slate-v2/site/examples/ts/custom-types.d.ts.tmp/slate-v2/site/examples/ts/pagination.tsx.tmp/slate-v2/playwright/integration/examples/pagination.test.tsdocs/slate-v2/references/pr-description.mdWhat landed:
docs/slate-v2/references/pr-description.md with the current
pagination proof files and accepted API shape.Verification:
bun --filter slate-layout test: pass, 12 tests, 42 assertions.bun --filter slate-layout typecheck: pass.bun typecheck:site: pass.bun run lint:fix: pass.bun --filter slate-layout build: pass.bun --filter slate-layout-pretext test: pass, 2 tests, 8 assertions.bun --filter slate-layout-pretext typecheck: pass.bun --filter slate-layout-pretext build: pass.PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun run playwright playwright/integration/examples/pagination.test.ts --project=chromium:
pass, 4 tests.Reference docs:
docs/slate-v2/references/pr-description.md updated for package/example
proof accounting.Next owner:
Changed files:
.tmp/slate-v2/packages/slate-layout/src/index.ts.tmp/slate-v2/packages/slate-layout/test/page-layout-contract.test.ts.tmp/slate-v2/site/examples/ts/pagination.tsx.tmp/slate-v2/playwright/integration/examples/pagination.test.ts.tmp/slate-v2/.changeset/slate-layout-avoid-split-boxes.mddocs/plans/2026-05-21-slate-v2-pagination-page-flow-fix.mdWhat landed:
split: 'avoid' layout boxes move whole to the next page when the
block fits on a fresh page but not the current page remainder.code-block root boxes as avoid-split while keeping individual
code-line boxes line-aware for oversized blocks.Verification:
bun --filter slate-layout test: pass, 13 tests.PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun run playwright playwright/integration/examples/pagination.test.ts --project=chromium:
pass, 6 tests.http://localhost:3100/examples/pagination: the third
paragraph is followed directly by the fourth paragraph, codeBlockInsideFrame: true, noHorizontalScroll: true.Next owner:
Changed files:
.tmp/slate-v2/packages/slate/src/transforms-text/delete-text.ts.tmp/slate-v2/packages/slate/test/delete-contract.ts.tmp/slate-v2/playwright/integration/examples/pagination.test.ts.tmp/slate-v2/.changeset/slate-delete-leading-breaks.mdWhat landed:
insertBreak, space insertion,
insertBreak, then Backspace.Enter, Space, Enter,
and Backspace.Verification:
bun test ./packages/slate/test/delete-contract.ts --bail 1: pass, 15 tests.bun test ./packages/slate/test --bail 1: pass, 975 tests.PLAYWRIGHT_RETRIES=0 PLAYWRIGHT_WORKERS=1 bun run playwright playwright/integration/examples/pagination.test.ts --project=chromium:
pass, 7 tests.http://localhost:3100/examples/pagination: after
native Enter x4, Space, Enter, Backspace, the first blocks remain four
empty paragraphs followed by the merged space-prefixed paragraph.| Pass | Status | Evidence added | Plan delta | Open issues | Next owner |
|---|---|---|---|---|---|
| current-state-read | complete | live pagination, markdown-shortcuts, tables, custom types, layout, Premirror, Pretext, Typora/Lexical/Tiptap research | expanded scope from pagination-only to rich Markdown plus table/layout architecture | issue-ledger and ClawSweeper pass still pending | Slate Ralplan |
| rich-markdown-architecture-decision-brief | complete | principles, drivers, options, rejected alternatives, Markdown/table architecture | chose Plate/app ownership for Markdown/table packages plus run/box-aware layout in Slate | none | done |
| issue-ledger-accounting | complete | existing coverage matrix, v2 sync ledger, PR reference | no new fixed/improved claims; related issue pressure recorded | implementation must update ledgers when code lands | Ralph implementation |
| ecosystem-synthesis | complete | Premirror, Pretext, Typora, Lexical, Tiptap | mapped what to steal/reject | none | done |
| maintainer-objection-ledger | complete | five objection rows | accepted keep/reject choices with proof gates | none | done |
| high-risk-deliberate-pass | complete | blast radius, pre-mortem, rollback | added phase and proof requirements | none | done |
| closure-score-final-gates | complete | scorecard, proof plan, fast gates, final handoff outline | Ralplan ready for user review; implementation now started through Ralph | remaining implementation and verification stay in Ralph execution | Ralph |
| ralph-execution-slice-1 | complete | raw Markdown/table package hard cut, config cleanup, PR reference sync | removed package tracers and reset ownership to Plate/app layer | layout integration and browser proof still pending | slate-layout run-aware layout |
| ralph-execution-slice-2 | complete | superseded by hard cut | package-tracer slice removed from raw Slate scope | run-aware layout, box-aware layout, projection DX, browser proof still pending | slate-layout run-aware layout |
| ralph-execution-slice-3 | complete | slate-layout run-aware contract, tests, typecheck, scoped lint, dependent pretext gates | third implementation phase started with a public layout tracer | box-aware layout, projection DX, browser proof still pending | slate-layout box-aware layout |
| ralph-execution-slice-4 | complete | slate-layout box-aware contract, tests, typecheck, scoped lint, dependent pretext gates | fourth implementation phase started with a public layout tracer | projection DX and browser proof still pending | slate-layout projection DX |
| ralph-execution-slice-5 | complete | slate-layout projection helpers, text/hit rects, decorations, simplified pagination example, focused package/site/browser gates | fifth implementation phase moved example-local hit/decorations math into layout | rich Markdown route and broader browser proof still pending | pagination browser proof |
| ralph-execution-slice-6 | complete | mixed Markdown pagination fixture, render branches, Chromium scroll/frame proof, PR reference sync | first browser proof tracer covers tables/code/image/hr/debug frame inside pagination | full Markdown corpus, browser parity, production pagination, mobile/IME, cross-page copy remain non-claims | closure review |
| ralph-execution-slice-7 | complete | run-scoped decoration rect contract, Chromium mixed-inline overlap proof, in-app Browser screenshot | per-run decoration data now carries per-run text rects and final-run hit tails instead of line-wide rects | pretext still needs true rich-inline measurement before production pagination claims | rich-inline measurement lane |
| ralph-execution-slice-8 | complete | Pretext measured run positions, visual gap regression, clean screenshot proof | slate-layout-pretext now emits measured per-run widths from each run font instead of letting slate-layout estimate them | production pagination still needs richer line breaking for mixed fonts, but the example no longer teaches broken spacing | rich-inline line-break lane |