docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.md
Do not pivot to a different editor.
Pivot harder into the final Slate v2 architecture and close the remaining escape hatches:
Slate model + operations
Lexical-style editor.read / editor.update lifecycle
ProseMirror-style transaction and DOM-selection authority
Tiptap-style extension DX
React 19.2 live-read / dirty-commit runtime
Selection/Caret Conformance Kernel
Generated browser gauntlets as release gates
The current architecture direction is right. The remaining work is to remove legacy mental models, make kernel authority impossible to bypass, broaden the proof from scoped green to battle-tested, and close the exact platform/perf caveats that still block an "absolute best" claim.
The previous conformance-kernel lane is closed for its scoped Batch A-F target. It proved a lot:
That is real progress. It is not the same thing as final battle-tested architecture.
Remaining blockers from the harsh review:
Transforms.* still exists as a primary-looking API in examples/docs/tests
unless hard-cut everywhereeditor.updatePrimary public API:
editor.read(() => {
editor.getSelection();
editor.getChildren();
editor.getMarks();
});
editor.update(() => {
editor.unwrapNodes({ match: isList });
editor.setNodes({ type: "list-item" });
editor.wrapNodes({ type: "bulleted-list", children: [] });
});
Rules:
editor.update(fn) is the only blessed write boundary.editor.read(fn) is the blessed coherent read boundary.at is omitted.at never import DOM selection.tx.resolveTarget() remains internal.editor.update.editor.update.EditorCommit remains local runtime truthEvery browser path reduces to:
event
-> event frame / epoch
-> intent
-> selection source
-> target resolution
-> editor.update / transaction
-> operations
-> EditorCommit
-> repair decision
-> trace
Exactly one owner decides that sequence: EditableConformanceKernel.
Controllers are workers:
InputRouter classifies raw events onlySelectionReconciler imports/exports model and DOM selection onlyCaretEngine computes movement onlyMutationController executes model changes through editor.update onlyDOMRepairQueue executes kernel-scheduled repairs onlyBrowserHandle is semantic proof transport onlyCut from primary runtime, docs, examples, tests, and blessed extension patterns:
editor.selectioneditor.childreneditor.markseditor.operationsTransforms.* as primary mutation APIeditor.apply as an extension pointeditor.onChange as an extension pointeditor.updateReactEditor.runCommandfocus().chain().run() ceremonyeditor.extenddecorate as primary overlay architectureCompat may remain only as explicitly internal or scheduled deletion. Compat must forward into the new runtime; it must not preserve an alternate write or selection authority.
This plan is complete only when all seven batches are closed or deferred with exact rationale:
editor.updatebun test:integration-local, relevant package build/type/lint, and React/core
perf gates passactive goal state is updated only when this becomes the active
implementation laneGoal: remove stale-state API pressure from primary usage.
Work:
editor.selectioneditor.childreneditor.markseditor.operationsTransforms.*editor.applyeditor.onChangeeditor.readeditor.updateTransforms.* from primary docs/examples.Transforms.* imports or direct UI-command reads of public mutable fields.Acceptance:
Transforms.*Transforms.* for user commandseditor.selection directlyeditor.update or internal runtime pathsDo not:
Goal: prove editor.update is the only local write boundary.
Work:
selectsetNodeswrapNodesunwrapNodesinsertNodesremoveNodessplitNodesmergeNodesmoveNodesinsertTextdeleteinsertFragmentinsertBreakat is omittedat is providedEditorCommiteditor.update
where safe.Acceptance:
editor.update fails in dev/test or is classified as
internal compat with forwardingDo not:
tx.resolveTarget() to plugin authorsGoal: keep Slate/Plate extension power without letting random method replacement be the architecture.
Work:
editor.extend({ name, methods, normalizers, schema, capabilities, handlers, commitListeners }).editor.update.Acceptance:
editor.read / editor.update and commit
metadata without reaching for mutable fieldsDo not:
Goal: prove the conformance kernel is the only browser authority.
Work:
slate-react event paths for direct decisions around:
EditableConformanceKernel results.selectionchange classification.Acceptance:
selectionchange cannot re-import as user intentDo not:
EditableGoal: stop relying on hand-authored bug rows.
Work:
slate-browser primitive.Acceptance:
Do not:
Goal: close or honestly scope native mobile keyboard, clipboard, and IME.
Work:
Acceptance:
Do not:
Goal: resolve the remaining huge-doc middle-block caveat without reviving the old chunk-count architecture.
Work:
Acceptance:
Do not:
Goal: make the public story match the real architecture and proof.
Work:
editor.readeditor.updateTransforms.*editor.apply / editor.onChange as extension pointsAcceptance:
active goal state is done only after all active implementation
targets are closedDo not:
Core:
bun test ./packages/slate/test/read-update-contract.ts --bail 1
bun test ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1
bun test ./packages/slate/test/transaction-target-runtime-contract.ts --bail 1
bun test ./packages/slate/test/commit-metadata-contract.ts --bail 1
bun test ./packages/slate/test/bookmark-contract.ts --bail 1
bun test ./packages/slate-history --bail 1
bunx turbo build --filter=./packages/slate --filter=./packages/slate-history --force
bunx turbo typecheck --filter=./packages/slate --filter=./packages/slate-history --force
React/browser:
bun test ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts --bail 1
bun test ./packages/slate-react/test/target-runtime-contract.tsx --bail 1
bun test ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1
bunx turbo build --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --force
bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --force
Browser release proof:
bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0
bunx playwright test ./playwright/integration/examples/inlines.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --workers=4 --retries=0
bunx playwright test ./playwright/integration/examples/editable-voids.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --workers=4 --retries=0
bunx playwright test ./playwright/integration/examples/shadow-dom.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --workers=4 --retries=0
bunx playwright test ./playwright/integration/examples/paste-html.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --workers=4 --retries=0
bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --workers=4 --retries=0
bun test:integration-local
Perf:
bun run bench:react:rerender-breadth:local
REACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:local
bun run bench:core:observation:compare:local
bun run bench:core:huge-document:compare:local
Always after code changes:
bun run lint:fix
bun run lint
active goal state to pending
before code work startsactive goal state to done until all active completion
targets are met or exactly deferredStop only when:
A pivot is not stop. A replan is not stop. A red browser lane is not stop.
Start with Batch 1:
Transforms.*, editor.apply, and
editor.onChange usage in .tmp/slate-v2Actions:
active goal state to status: pendingCommands:
sed -n '1,260p' docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdsed -n '260,620p' docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdsed -n '1,160p' active goal statesed -n '1,220p' package.jsonArtifacts:
docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdactive goal stateEvidence:
Hypothesis:
Transforms.* and public mutable fieldsDecision:
Owner classification:
Changed files:
docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdactive goal stateRejected tactics:
Next action:
/Users/zbeyens/git/slate-v2Actions:
site/examples/ts/richtext.tsx and site/examples/js/richtext.jsxsite/examples/js/richtext.jsxTransforms.*, raw editor.selection,
and onKeyDown hotkey mutation to editor methods, editor.getSelection(),
editor.getMarks(), and onKeyCommandCommands:
bun test ./packages/slate/test/public-surface-contract.ts --bail 1sed -n '1,260p' site/examples/js/richtext.jsxsed -n '1,260p' site/examples/ts/richtext.tsxsed -n '260,520p' site/examples/ts/richtext.tsxbun test ./packages/slate/test/public-field-hard-cut-contract.ts --bail 1bun test ./packages/slate/test/read-update-contract.ts --bail 1bun test ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1Artifacts:
.tmp/slate-v2/packages/slate/test/public-surface-contract.ts.tmp/slate-v2/site/examples/js/richtext.jsxEvidence:
/\bTransforms\./ in
site/examples/js/richtext.jsxbun test ./packages/slate/test/public-surface-contract.ts --bail 1
passed with 2 testsbun test ./packages/slate/test/public-field-hard-cut-contract.ts --bail 1
passed with 2 testsbun test ./packages/slate/test/read-update-contract.ts --bail 1
passed with 2 testsbun test ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1
passed with 18 testsFailed probes:
bun test ./packages/slate/test/public-surface-contract.ts --bail 1
initially failed because the JS richtext example still taught
Transforms.*Owner classification:
Rejected tactics:
Transforms.* fixture under packages/slate/test
in this slice; transform fixtures are compatibility/internal proof until
the public surface is cleanNext action:
Actions:
Transforms.* to editor primitives and update
grouping where the action is one user intenteditor.selection and editor.childrendeleteBackward, markdown-shortcuts insertText /
deleteBackward, and huge-document editor.applypackages/slate/package.json export-map typing by adding explicit
types and import conditions for TypeScript bundler resolutionCommands:
rg -n "\bTransforms\.|\beditor\.(selection|children|marks|operations)\b|\beditor\.(apply|onChange)\s*=" site/examples docs --glob '!site/out/**' --glob '!site/.next/**'bun test ./packages/slate/test/public-surface-contract.ts --bail 1bun test ./packages/slate/test/public-field-hard-cut-contract.ts --bail 1bun test ./packages/slate/test/read-update-contract.ts --bail 1bun test ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1bun installbunx turbo build --filter=./packages/slate --forcebunx turbo typecheck --filter=./packages/slate --forcebun run typecheck:sitebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/forced-layout.test.ts ./playwright/integration/examples/editable-voids.test.ts ./playwright/integration/examples/paste-html.test.ts ./playwright/integration/examples/check-lists.test.ts ./playwright/integration/examples/embeds.test.ts ./playwright/integration/examples/images.test.ts ./playwright/integration/examples/code-highlighting.test.ts ./playwright/integration/examples/inlines.test.ts ./playwright/integration/examples/mentions.test.ts ./playwright/integration/examples/markdown-shortcuts.test.ts ./playwright/integration/examples/review-comments.test.ts ./playwright/integration/examples/persistent-annotation-anchors.test.ts ./playwright/integration/examples/large-document-runtime.test.ts ./playwright/integration/examples/huge-document.test.ts --project=chromium --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate/test/public-surface-contract.ts.tmp/slate-v2/packages/slate/package.json.tmp/slate-v2/site/examples/ts/richtext.tsx.tmp/slate-v2/site/examples/js/richtext.jsx.tmp/slate-v2/site/examples/ts/forced-layout.tsx.tmp/slate-v2/site/examples/js/forced-layout.jsx.tmp/slate-v2/site/examples/ts/editable-voids.tsx.tmp/slate-v2/site/examples/js/editable-voids.jsx.tmp/slate-v2/site/examples/ts/paste-html.tsx.tmp/slate-v2/site/examples/js/paste-html.jsx.tmp/slate-v2/site/examples/ts/check-lists.tsx.tmp/slate-v2/site/examples/js/check-lists.jsx.tmp/slate-v2/site/examples/ts/embeds.tsx.tmp/slate-v2/site/examples/js/embeds.jsx.tmp/slate-v2/site/examples/ts/images.tsx.tmp/slate-v2/site/examples/js/images.jsx.tmp/slate-v2/site/examples/ts/code-highlighting.tsx.tmp/slate-v2/site/examples/js/code-highlighting.jsx.tmp/slate-v2/site/examples/ts/inlines.tsx.tmp/slate-v2/site/examples/js/inlines.jsx.tmp/slate-v2/site/examples/ts/mentions.tsx.tmp/slate-v2/site/examples/js/mentions.jsx.tmp/slate-v2/site/examples/ts/markdown-shortcuts.tsx.tmp/slate-v2/site/examples/js/markdown-shortcuts.jsx.tmp/slate-v2/site/examples/ts/large-document-runtime.tsx.tmp/slate-v2/site/examples/ts/review-comments.tsx.tmp/slate-v2/site/examples/ts/persistent-annotation-anchors.tsx.tmp/slate-v2/site/examples/js/huge-document.jsxEvidence:
site/examples returned no hitsdocs/general/changelog.md, classified as
historical changelog text rather than current docs/examplesFailed probes:
bun run typecheck:site initially failed because TypeScript bundler
resolution could not resolve package slate through the package export mapbun run lint:fix initially failed on a real syntax error in the JS
markdown-shortcuts migration; the error was fixed and lint reran greenOwner classification:
docs/general/changelog.md, deferred until
Batch 8 docs cleanup or changelog deletion decisionRejected tactics:
editor.update where neededNext action:
Actions:
editor.update proof that two primitive writes publish
one commit with operation list, operation class, selection before/after, and
dirty metadataeditor.update as
compatibility auto-transactions that forward into the same transaction
runtime, not a separate write architectureCommands:
sed -n '1,260p' packages/slate/test/primitive-method-runtime-contract.tssed -n '1,260p' packages/slate/test/transaction-target-runtime-contract.tssed -n '1,260p' packages/slate/test/commit-metadata-contract.tssed -n '1,220p' packages/slate/test/write-boundary-contract.tsbun test ./packages/slate/test/transaction-target-runtime-contract.ts --bail 1bun test ./packages/slate/test/commit-metadata-contract.ts --bail 1bun test ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1bun test ./packages/slate/test/write-boundary-contract.ts ./packages/slate/test/transaction-target-runtime-contract.ts ./packages/slate/test/commit-metadata-contract.ts ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1bunx turbo build --filter=./packages/slate --forcebunx turbo typecheck --filter=./packages/slate --forcebun run lint:fixbun run lintArtifacts:
.tmp/slate-v2/packages/slate/test/transaction-target-runtime-contract.ts.tmp/slate-v2/packages/slate/test/commit-metadata-contract.tsEvidence:
Failed probes:
Owner classification:
editor.update; current runtime keeps them as compatibility auto-transactions
until public docs/type surface hard cut is completeRejected tactics:
tx.resolveTarget() publiclyeditor.updateNext action:
editor.extend, extension method registration, duplicate method
handling, commit listeners, and existing method monkeypatch surfacesActions:
editor.extend, extension method registration, duplicate method
handling, and public example method replacement patternsisVoid, isInline,
insertData, normalizeNode, insertBreak, and getChunkSizedefineEditorExtension plus editor.extendonKeyCommand
boundary handlingTransforms.* and mutable public-field guards active while adding the
extension monkeypatch guardCommands:
bun test ./packages/slate/test/public-surface-contract.ts --bail 1rg -n "\beditor\.(isVoid|isInline|isElementReadOnly|isSelectable|markableVoid|insertData|insertText|deleteBackward|deleteForward|insertBreak|normalizeNode|getChunkSize)\s*=" site/examples/ts site/examples/js --glob '!site/out/**' --glob '!site/.next/**'bun test ./packages/slate/test/public-surface-contract.ts ./packages/slate/test/extension-methods-contract.ts ./packages/slate/test/extension-contract.ts --bail 1bun run typecheck:sitebunx turbo build --filter=./packages/slate --forcebunx turbo typecheck --filter=./packages/slate --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/editable-voids.test.ts ./playwright/integration/examples/embeds.test.ts ./playwright/integration/examples/paste-html.test.ts ./playwright/integration/examples/images.test.ts ./playwright/integration/examples/inlines.test.ts ./playwright/integration/examples/mentions.test.ts ./playwright/integration/examples/forced-layout.test.ts ./playwright/integration/examples/large-document-runtime.test.ts ./playwright/integration/examples/tables.test.ts ./playwright/integration/examples/huge-document.test.ts --project=chromium --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate/src/core/editor-extension.ts.tmp/slate-v2/packages/slate/test/extension-methods-contract.ts.tmp/slate-v2/packages/slate/test/public-surface-contract.ts.tmp/slate-v2/site/examples/ts/editable-voids.tsx.tmp/slate-v2/site/examples/js/editable-voids.jsx.tmp/slate-v2/site/examples/ts/embeds.tsx.tmp/slate-v2/site/examples/js/embeds.jsx.tmp/slate-v2/site/examples/ts/paste-html.tsx.tmp/slate-v2/site/examples/js/paste-html.jsx.tmp/slate-v2/site/examples/ts/images.tsx.tmp/slate-v2/site/examples/js/images.jsx.tmp/slate-v2/site/examples/ts/inlines.tsx.tmp/slate-v2/site/examples/js/inlines.jsx.tmp/slate-v2/site/examples/ts/mentions.tsx.tmp/slate-v2/site/examples/js/mentions.jsx.tmp/slate-v2/site/examples/ts/forced-layout.tsx.tmp/slate-v2/site/examples/js/forced-layout.jsx.tmp/slate-v2/site/examples/ts/large-document-runtime.tsx.tmp/slate-v2/site/examples/js/tables.jsx.tmp/slate-v2/site/examples/js/huge-document.jsxEvidence:
insertData
callback as DataTransferFailed probes:
js/tables was added before
migrating its direct deleteBackward / deleteForward / insertBreak
replacementbun run typecheck:site failed once because the typed images extension
callback left data.files iteration as unknownbun run lint:fix failed once on dead node bindings in forced-layout
extension callbacksOwner classification:
Rejected tactics:
ReactEditor.runCommand or command policy objects the extension
migration pathNext action:
Actions:
selectionchange handling to begin an editable event frame before
importing or preserving DOM selectionselectionchange traces that try to re-import as native intentrepairDOMInput so delayed input repair
cancels before mutating selection or text if a newer event frame superseded itEditable so paste, cut, and drop
open their event frame before executing mutation workers, then record the
command/trace after the worker returnsCommands:
bun test ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts --bail 1bunx turbo build --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts ./playwright/integration/examples/paste-html.test.ts ./playwright/integration/examples/inlines.test.ts --project=chromium --grep "selectionchange|repair|paste|drop|cut|toolbar mark|warm toolbar|plain text paste" --workers=4 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts ./playwright/integration/examples/paste-html.test.ts ./playwright/integration/examples/inlines.test.ts --project=firefox --project=webkit --project=mobile --grep "selectionchange|repair|paste|drop|cut|toolbar mark|warm toolbar|plain text paste" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/editable/editing-kernel.ts.tmp/slate-v2/packages/slate-react/src/editable/dom-repair-queue.ts.tmp/slate-v2/packages/slate-react/test/editing-kernel-contract.tsEvidence:
Failed probes:
domRepairQueue before that hook is created; the repair queue
cancellation path was moved through a refOwner classification:
Rejected tactics:
Next action:
Actions:
syncEditorSelectionFromDOM, syncEditableDOMSelectionToEditor, and direct
selection transformsCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts --bail 1bunx turbo build --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-react --forcebun run lint:fixbun run lintArtifacts:
.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
Failed probes:
Owner classification:
Rejected tactics:
Next action:
model-input-strategy, keyboard-input-strategy, and
clipboard-input-strategy should return kernel/worker results where possible
instead of scheduling repair or mutating directlyActions:
applyModelOwnedBeforeInputOperation from a worker that mutates
and schedules repair to a worker that mutates and returns an
EditableRepairRequestEditable event owner via
requestEditableRepair(repair)domRepairQueue and
preferModelSelectionForInputRef inputs from the beforeinput model workermodel-input-strategy
repair authority dropped from 7 direct repair call sites to 3Commands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/editable/model-input-strategy.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
model-input-strategyFailed probes:
model-input-strategy repair count, proving the guard catches authority
inventory changesOwner classification:
keyboard-input-strategy and clipboard-input-strategy
still carry direct repair/mutation authority that should be reduced or
explicitly classifiedRejected tactics:
requestRepair inside every model worker as an easy callbackNext action:
keyboard-input-strategy:
return repair requests for key-command/caret/select-all paths where possible
while preserving current browser behavior and trace gatesActions:
applyEditableKeyDown from a boolean-returning worker into a
worker-result API with { handled, repair }Editable event owner via
requestEditableRepair(repair)requestRepair(...) call from
keyboard-input-strategyrequestRepair callback only for caret movement paths
that still need a narrower extraction/classification passkeyboard-input-strategy repair scheduling dropped from one direct repair
call site to zeroCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bun run lint:fixbun run lintbunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/editable/keyboard-input-strategy.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
keyboard-input-strategy stopped scheduling repair directlyFailed probes:
Owner classification:
Rejected tactics:
Next action:
clipboard-input-strategy: extract a worker-result
shape for mutation/repair/trace where possible, or explicitly classify why a
remaining clipboard-owned operation must stay inside the strategyCheckpoint:
clipboard-input-strategy authority by returning a
result to the event owner where possible, with audit-driven red/green proofActions:
EditableClipboardResult with command, optional repair, and optional
shell-backed selection state changesEditable event owner for
cut selection deletion, shell-backed paste, plain paste fallback, and external
drop focus repairEditable event ownerclipboard-input-strategy repair scheduling dropped from six direct repair
call sites to zeroCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/editable/clipboard-input-strategy.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
clipboard-input-strategy repair count was six and the new count is zeroFailed probes:
Owner classification:
Rejected tactics:
Next action:
Checkpoint:
Actions:
kernel-authority-audit-contract.ts from raw count snapshots to
count-plus-rationale inventoriesburn-down
instead of treating it as silently acceptedEditable, MutationController,
SelectionController, CaretEngine, and DOMRepairQueue as explicit
central owners or bridgesCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun run lint:fixbun run lintbun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1Artifacts:
.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
Failed probes:
Owner classification:
burn-down inventory entries need extraction,
narrowing, or explicit acceptance before Batch 4 can closeRejected tactics:
burn-down entries as accepted debtNext action:
input-router repair/mutation callback is smaller and safer than clipboard
mutation extraction, so remove or classify that router-owned authority nextCheckpoint:
burn-down entries are still real debtburn-down entry without changing browser behaviorinput-router mutation/repair authority before
attempting the broader clipboard mutation moveburn-down entries
remainActions:
Editor.insertText mutation from
useEditableReactBeforeInputHandlerapplyModelOwnedBeforeInputOperation model-owned path in Editableinput-router, but reclassified it as an
explicit bridge because the actual repair policy/execution is owned by the
Editable callback and DOMRepairQueueinput-router mutation count dropped from
one to zeroCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/editable/input-router.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
input-router mutation count was one and the new count is zeroFailed probes:
Owner classification:
burn-down entries are now concentrated in
clipboard-input-strategy, keyboard-input-strategy, model-input-strategy,
and caret-engineRejected tactics:
Next action:
keyboard-input-strategy and model-input-strategy remaining
mutation/selection burn-down entries; pick the smaller extraction before
tackling clipboard mutationCheckpoint:
burn-down countburn-down entriesActions:
applyEditableCommand({ kind: 'select-all' })select-all through its existing
Transforms.select call pathapplyEditableCommand({ kind: 'insert-text' })Transforms import from keyboard-input-strategykeyboard-input-strategy dropped out of
the direct selection-transform and direct mutation inventoriesCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/editable/keyboard-input-strategy.ts.tmp/slate-v2/packages/slate-react/src/editable/mutation-controller.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
Failed probes:
Owner classification:
applyEditableInput still schedules repair directly;
model-input-strategy still owns native DOM text reconciliation selection and
text mutation; clipboard remains the broad mutation/selection ownerRejected tactics:
Next action:
applyEditableInput to return repair requests to Editable instead
of calling requestRepair directly, preserving native DOM text
reconciliation behaviorCheckpoint:
model-input-strategy direct repair countapplyEditableInput return repair intent and apply it in
EditableActions:
applyEditableInput to return EditableInputResult with repair
requests instead of calling requestRepair directlyEditable event ownermodel-input-strategy dropped out of the
direct repair scheduling inventoryCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/editable/model-input-strategy.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
model-input-strategy repair count was three and the new count is zeroFailed probes:
Owner classification:
Rejected tactics:
Next action:
Transforms.select and Editor.insertText calls
through applyEditableCommand so mutation-controller owns those primitive
operationsCheckpoint:
Editable, focused contracts are green, and
browser proof stayed greenActions:
applyEditableCommand({ kind: 'select' })applyEditableCommand({ kind: 'insert-text' })Transforms import from
model-input-strategymodel-input-strategy dropped out of the
direct selection-transform and direct mutation inventoriesCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/editable/model-input-strategy.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
model-input-strategy selection-transform count was one and the new count is
zeroFailed probes:
Owner classification:
Rejected tactics:
Next action:
applyEditableCaretMovement to return repair intent instead of
calling requestRepair, then let keyboard apply that repair through its
existing result pathCheckpoint:
Actions:
applyEditableCaretMovement from boolean-plus-callback behavior to
EditableCaretMovementResultsync-selection repair intent instead of calling
requestRepairCaretEngine; those are
classified as central movement authority, not worker leakagecaret-engine dropped out of the direct
repair scheduling inventoryCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0rg -n "next: 'burn-down'" packages/slate-react/test/kernel-authority-audit-contract.tsArtifacts:
.tmp/slate-v2/packages/slate-react/src/editable/caret-engine.ts.tmp/slate-v2/packages/slate-react/src/editable/keyboard-input-strategy.ts.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
burn-down entries are concentrated in clipboard selection
and clipboard mutation inventoryFailed probes:
Owner classification:
Rejected tactics:
burn-down ownerNext action:
select and insert-data operations through applyEditableCommand, then
decide whether the remaining cut/drop structural edits are legitimate
clipboard-worker ownership or need a mutation-controller commandCheckpoint:
burn-down owner is clipboard; there
is nowhere else to hide nowselect/insert-data calls without changing paste/drop
rowsActions:
select operations through
applyEditableCommand({ kind: 'select' })insert-data operations through
applyEditableCommand({ kind: 'insert-data' })delete-fragment through applyEditableCommandclipboard-input-strategy audited direct mutation count from seven
to threeclipboard-input-strategy from the direct selection-transform
inventoryEditablenext: 'burn-down' entries left in the
authority auditCommands:
bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcerg -n "next: 'burn-down'" packages/slate-react/test/kernel-authority-audit-contract.tsbun run lint:fixbun run lintbun test ./packages/slate-react/test/kernel-authority-audit-contract.ts ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-react/src/editable/clipboard-input-strategy.ts.tmp/slate-v2/packages/slate-react/test/kernel-authority-audit-contract.tsEvidence:
delete-fragment
through the command executorrg -n "next: 'burn-down'" ... returned only the audit union type, no
runtime authority entriesFailed probes:
Owner classification:
Rejected tactics:
Next action:
Checkpoint:
Actions:
Commands:
bun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/packages/slate-browser/test/core/scenario.test.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.tsEvidence:
Failed probes:
Owner classification:
Rejected tactics:
stepLabelsNext action:
Checkpoint:
Actions:
Commands:
bun run --cwd packages/slate-browser test:core --bail 1bun run --cwd packages/slate-browser test:core --bail 1bun run --cwd packages/slate-browser test:core --bail 1 for warm
toolbar replayabilitybun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0Artifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/packages/slate-browser/test/core/scenario.test.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.tsEvidence:
replaycreateScenarioReplayreplay.replayable was falseFailed probes:
Owner classification:
Rejected tactics:
custom callbacks
when a typed action can express the same user-path stepNext action:
Checkpoint:
Actions:
custom callbacks where
a typed action existsCommands:
bun run --cwd packages/slate-browser test:core --bail 1bun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0rg -n "kind: 'custom'|kind: \"custom\"" packages/slate-browser/src/playwright/index.ts playwright/integration/examples/richtext.test.ts packages/slate-browser/test/core/scenario.test.tsrg -n "createSlateBrowser.*Gauntlet|replay\\.replayable|reductionCandidates" playwright/integration/examples/richtext.test.ts packages/slate-browser/test/core/scenario.test.tsArtifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/packages/slate-browser/test/core/scenario.test.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.tsEvidence:
rg shows generated helper code no longer emits custom; remaining custom
usage is the explicit custom step type, core tests that prove non-replayable
custom handling, and hand-authored one-off richtext scenariosFailed probes:
Owner classification:
Rejected tactics:
Next action:
custom scenario rows and
convert any cursor/caret release-claim row into typed replayable actions or a
generated helperCheckpoint:
rg custom inventory plus targeted richtext replay
assertions on converted rowsActions:
assertLastCommit scenario actionCommands:
bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "native word selection toolbar mark" --workers=1 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "native word selection toolbar mark" --workers=1 --retries=0bun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0rg -n "kind: 'custom'|kind: \"custom\"" playwright/integration/examples/richtext.test.ts packages/slate-browser/src/playwright/index.ts packages/slate-browser/test/core/scenario.test.tsArtifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.tsEvidence:
result.replay.replayable falseFailed probes:
Owner classification:
Rejected tactics:
Next action:
Checkpoint:
Actions:
rootClick, assertSelectionLocation, assertModelText, and
native undo supporttypeThenUndo, preserving the old
timing discipline while keeping the artifact replayableCommands:
bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "navigation and mutation chained" --workers=1 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "navigation and mutation chained" --workers=1 --retries=0 after splitting undo into separate steps; native undo no longer fired after trace snapshotsbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "navigation and mutation chained" --workers=1 --retries=0bun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fix on duplicate inline Mac regexbun run lint:fixbun run lintbun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0rg -n "kind: 'custom'|kind: \"custom\"" playwright/integration/examples/richtext.test.ts packages/slate-browser/src/playwright/index.ts packages/slate-browser/test/core/scenario.test.tsArtifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.tsEvidence:
typeThenUndo made the timing constraint
explicit and replayablenavigator.userAgent.includes('Mac OS X')Failed probes:
type, assert, undo, and
follow-up assert steps failed because the scenario trace snapshot changed the
browser undo timingpage.evaluateOwner classification:
Rejected tactics:
custom; use typed atomic steps when browser timing demands
an atomic replay unitNext action:
Checkpoint:
Actions:
custom callbacks to typed replayable stepscustom scenario rows; the remaining
custom hits are the custom step type and core tests that prove custom steps
are honestly non-replayablewaitForHandleSelection so a missing handle is not success; the harness
now keeps waiting or fails instead of proceeding with fake model selectionCommands:
bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "records core command metadata|records selectionchange and repair" --workers=1 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "records core command metadata|records selectionchange and repair" --workers=1 --retries=0rg -n "kind: 'custom'|kind: \"custom\"" packages/slate-browser/src/playwright/index.ts playwright/integration/examples/richtext.test.ts packages/slate-browser/test/core/scenario.test.tsbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "generated navigation and typing|generated mixed editing|Backspace at selected text end" --workers=1 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "generated navigation and typing|generated mixed editing|Backspace at selected text end" --workers=4 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --grep "generated navigation and typing|generated mixed editing|Backspace at selected text end" --workers=4 --retries=0bunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0bun run --cwd packages/slate-browser test:core --bail 1bunx turbo build --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintArtifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.tsEvidence:
rg custom inventory now returns only:
packages/slate-browser/src/playwright/index.ts custom step typepackages/slate-browser/test/core/scenario.test.ts non-replayable custom
fixturesplaywright/integration/examples/richtext.test.ts custom rowsnull model selection after select and one Chromium
Backspace row timing out waiting for a DOM rangewaitForHandleSelection treated a missing handle as
success; that was a false wait success under full-gate loadFailed probes:
null selection failures and one Backspace DOM-range timeoutOwner classification:
Rejected tactics:
Next action:
Checkpoint:
Actions:
DataTransfer drop rows stay
synthetic-datatransfer proof instead of being upgraded to generic mobile
viewport proof[0] to text path [0, 0]Commands:
bun run --cwd packages/slate-browser test:core --bail 1claim fieldbunx turbo build --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=mobile --grep "generated navigation and typing|generated mixed editing|mobile semantic editing|generated mark typing|navigation and mutation chained" --workers=2 --retries=0bunx playwright test ./playwright/integration/examples/paste-html.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "generated clipboard paste|generated drop data" --workers=4 --retries=0bunx playwright test ./playwright/integration/examples/paste-html.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "generated clipboard paste|generated drop data" --workers=4 --retries=0bunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "generated composition" --workers=4 --retries=0bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0rg -n "appium|android|ios|safari|mobile native|native mobile|real device|imeSetComposition|composition|clipboard|native-keyboard|native.*mobile" packages playwright docs config site scripts --glob '!**/dist/**' --glob '!**/node_modules/**'src pathArtifacts:
.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts.tmp/slate-v2/packages/slate-browser/test/core/scenario.test.ts.tmp/slate-v2/playwright/integration/examples/richtext.test.ts.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts.tmp/slate-v2/playwright/integration/examples/large-document-runtime.test.tsEvidence:
Failed probes:
claim; this re-confirms build-before-browser-proof for
slate-browser subpath consumerssrc, which polluted the
probe with an rg path error; subsequent inventory should target existing
repo roots onlyOwner classification:
Rejected tactics:
slate-browserNext action:
Checkpoint:
mobile
project namepackages/slate-browser/src/transports/** descriptors and decide whether
Batch 6 closes by adding one runnable raw-device gate or by narrowing the
release claim with exact unsupported transport rowsActions:
classifyBrowserMobileTransportProof(...) and
getBrowserMobileTransportProofMatrix() to slate-browser/transportsslate-browser READMECommands:
bun run --cwd packages/slate-browser test:core --bail 1bun run --cwd packages/slate-browser test:core --bail 1bunx turbo build --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbun run --cwd packages/slate-browser test:core --bail 1bunx turbo typecheck --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forceArtifacts:
.tmp/slate-v2/packages/slate-browser/src/transports/contracts.ts.tmp/slate-v2/packages/slate-browser/test/core/proof.test.ts.tmp/slate-v2/packages/slate-browser/README.mdEvidence:
Failed probes:
classifyBrowserMobileTransportProof, which was the intended RED contractOwner classification:
Rejected tactics:
mobile Playwright project imply Android/iOS native transportNext action:
Checkpoint:
Actions:
React import in EditableDOMRoot to a type-only importReadOnlyContext.Provider
creation use the runtime React.createElement(...) bindingReact is not definedactiveRadius: 0
so the durable artifact matches the current accepted corridoractiveRadius: 0 as the default and rejected radius-1 as a default
pivotCommands:
bun run bench:react:rerender-breadth:local before this slice with
ReferenceError: React is not definedbun run lint:fix && bun run lint once on a redundant fragment after
the first React.createElement(...) patchbun run lint:fix && bun run lintbun run bench:react:rerender-breadth:localbunx turbo build --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate-dom --filter=./packages/slate-react --forceREACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:localbun test ./packages/slate-react/test/large-doc-and-scroll.tsx --bail 1Artifacts:
.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/tmp/react-rerender-breadth-local.json.tmp/slate-v2/packages/slate-react/tmp/huge-document-legacy-compare-local.jsonEvidence:
React import00000activeRadius: 0, blocks: 5000,
iterations: 5, and typeOps: 1010.67ms vs legacy chunk-on 347.05ms5.22ms vs legacy chunk-on 36.29ms1.02ms vs legacy chunk-on 35.20ms49.04ms vs legacy chunk-on 31.73ms46.49ms vs legacy chunk-on
31.77ms9.53ms vs legacy chunk-on
33.22ms19.88ms vs legacy chunk-on 118.77ms20.32ms vs legacy chunk-on
105.68msFailed probes:
React.createElement(...) patch because it wrapped a
single provider child in an unnecessary fragmentREACT_HUGE_COMPARE_ACTIVE_RADIUS=1 evidence did not justify a
default switch; radius 1 narrowed one direct middle-block path in one run, but
the current plan intentionally uses active radius 0 and activation/promotion
as the user corridorOwner classification:
Rejected tactics:
Next action:
editor.read/editor.update,
extension-method runtime, kernel authority, generated gauntlets, scoped mobile
proof, and the accepted huge-doc perf caveatCheckpoint:
bun test:integration-local plus package build/type/lint/perf guardrailsTransforms.*, mutable editor fields, or child-count chunking in docsActions:
docs/slate-v2 front door to read that claim firstTransforms.*, decorate, and child-count
chunking are not presented as primary public surfaceseditor.read, editor.update, primitive editor methods,
extension methods, and commit subscribers instead of the older retrofit APICommands:
sed -n '492,560p' docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdsed -n '1,260p' docs/slate-v2/overview.mdsed -n '1,280p' docs/slate-v2/master-roadmap.mdsed -n '1,260p' docs/slate-v2/release-readiness-decision.mdsed -n '1,260p' docs/slate-v2/replacement-gates-scoreboard.mdsed -n '1,260p' docs/slate-v2/final-api-hard-cuts-status.mdsed -n '1,300p' docs/slate-v2/references/architecture-contract.mdsed -n '1,320p' docs/slate-v2/true-slate-rc-proof-ledger.mdrg -n "Transforms\\.|editor\\.(selection|children|marks|operations)|editor\\.apply|editor\\.onChange" docs/slate-v2/overview.md docs/slate-v2/absolute-architecture-release-claim.md docs/slate-v2/release-readiness-decision.md docs/slate-v2/replacement-gates-scoreboard.md docs/slate-v2/final-api-hard-cuts-status.md docs/slate-v2/references/architecture-contract.md docs/slate-v2/true-slate-rc-proof-ledger.mdrg -n "compatibility mirrors kept through RC|editor\\.children survives|editor\\.selection survives|Editor\\.apply\\(editor|first shelled-block activation|same-path open rows|mixed rows still include|proved in Chromium|Chromium-only closure" docs/slate-v2 docs/research/decisions docs/research/systems --glob '!**/ledgers/**'Artifacts:
docs/slate-v2/absolute-architecture-release-claim.mddocs/slate-v2/overview.mddocs/slate-v2/master-roadmap.mddocs/slate-v2/release-readiness-decision.mddocs/slate-v2/replacement-gates-scoreboard.mddocs/slate-v2/final-api-hard-cuts-status.mddocs/slate-v2/true-slate-rc-proof-ledger.mddocs/slate-v2/references/architecture-contract.mddocs/slate-v2/slate-react-perf-loop-context.mdEvidence:
editor.read / editor.updateEditorCommitFailed probes:
Owner classification:
docs/slate-v2 and docs/research surfaces outside ledger archivesRejected tactics:
Next action:
active goal state to done only if every required gate passes or to
blocked only with exact missing evidenceCheckpoint:
bun test:integration-local can still expose browser/example
drift; docs cannot paper over thatbun test:integration-local, focused core/React/browser
contract suites, package build/typecheck, lint, and React/core perf guardrailsbun completion-check while status is pending, and do not downgrade
failures into prose unless they are explicitly accepted/deferredActions:
typecheck depend on dependent package builds through ^buildcode-highlighting example matcher type so Next/Turbopack can
typecheck the example under TypeScript 6page.goto timeouts because the full suite passed with retries and the exact
rows passed with --retries=0 in a focused one-worker runCommands:
bun test ./packages/slate/test/read-update-contract.ts ./packages/slate/test/primitive-method-runtime-contract.ts ./packages/slate/test/transaction-target-runtime-contract.ts ./packages/slate/test/commit-metadata-contract.ts ./packages/slate/test/bookmark-contract.ts --bail 1bun test ./packages/slate-history --bail 1bun test ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bun run --cwd packages/slate-browser test:core --bail 1bunx turbo build --filter=./packages/slate --filter=./packages/slate-history --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebunx turbo typecheck --filter=./packages/slate --filter=./packages/slate-history --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --force before the Turbo dependency-order fixbun run build once on the code-highlighting implicit any matcherbun run buildbunx turbo typecheck --filter=./packages/slate --filter=./packages/slate-history --filter=./packages/slate-browser --filter=./packages/slate-dom --filter=./packages/slate-react --forcebun run lint:fixbun run lintbun test:integration-localbunx playwright test ./playwright/integration/examples/large-document-runtime.test.ts --project=firefox --grep "commits IME composition|preserves Slate fragment paste over shell-backed selection|selects void content" --workers=1 --retries=0bun run bench:react:rerender-breadth:localREACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:localbun run bench:core:observation:compare:localbun run bench:core:huge-document:compare:localArtifacts:
.tmp/slate-v2/turbo.json.tmp/slate-v2/site/examples/ts/code-highlighting.tsx.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-browser/src/transports/contracts.ts.tmp/slate-v2/packages/slate-browser/test/core/proof.test.ts.tmp/slate-v2/packages/slate-browser/README.md.tmp/slate-v2/packages/slate-react/tmp/**.tmp/slate-v2/test-results/**Evidence:
bun test:integration-local passed with 525 passed and 3 flaky Firefox
large-document rows; the flakes were initial page.goto timeouts under full
parallel load and all passed on retryactiveRadius: 0; v2
middleBlockPromoteThenTypeMs mean was 9.53ms vs legacy chunk-on
33.22msreadChildrenLengthAfterEachMs at +0.36msFailed probes:
slate-history started while
slate/dist was empty; root cause was typecheck.dependsOn missing
^buildsite/examples/ts/code-highlighting.tsxOwner classification:
Rejected tactics:
Next action:
active goal state to done and run bun completion-checkCheckpoint:
bun completion-check after the completion file flips to
doneActions:
children, selection, marks, and operations from the
Slate BaseEditor type and from createEditor() runtime initializationcore/public-state.ts; internal
state is seeded directly and read through accessor methodsEditor.getChildren(editor) instead of root .children.children / .selection mirrorsTransforms.* and editor.childrenCommands:
bun test ./packages/slate/test/public-surface-contract.ts ./packages/slate/test/public-field-hard-cut-contract.ts ./packages/slate/test/escape-hatch-inventory-contract.ts ./packages/slate/test/write-boundary-contract.ts ./packages/slate/test/surface-contract.ts ./packages/slate/test/snapshot-contract.ts ./packages/slate/test/interfaces-contract.ts ./packages/slate/test/clipboard-contract.ts ./packages/slate/test/accessor-transaction.test.ts ./packages/slate/test/read-update-contract.ts ./packages/slate/test/primitive-method-runtime-contract.ts ./packages/slate/test/transaction-target-runtime-contract.ts ./packages/slate/test/commit-metadata-contract.ts ./packages/slate/test/bookmark-contract.ts --bail 1bun test ./packages/slate/test --bail 1bunx turbo build --filter=./packages/slate --forcebunx turbo typecheck --filter=./packages/slate --forcebun run lint:fixbun run lintrg -n "editor\\.(selection|children|marks|operations)" packages/slate/src packages/slate/test --glob '!**/dist/**'rg -n "\\bTransforms\\.|\\beditor\\.(selection|children|marks|operations)\\b|\\beditor\\.(apply|onChange)\\s*=" site/examples docs --glob '!site/out/**' --glob '!site/.next/**'Evidence:
packages/slate build passedpackages/slate typecheck passededitor.children, editor.selection, editor.marks,
and editor.operations returned no matches in packages/slate/src and
packages/slate/testTransforms.*, public mutable fields, and direct
editor.apply / editor.onChange extension points returned no matchesHypothesis:
Decision:
EditorOwner classification:
Changed files:
.tmp/slate-v2/packages/slate/src/interfaces/editor.ts.tmp/slate-v2/packages/slate/src/create-editor.ts.tmp/slate-v2/packages/slate/src/core/public-state.ts.tmp/slate-v2/packages/slate/src/editor/is-editor.ts.tmp/slate-v2/packages/slate/src/editor/next.ts.tmp/slate-v2/packages/slate/src/editor/previous.ts.tmp/slate-v2/packages/slate/src/interfaces/node.ts.tmp/slate-v2/packages/slate/src/interfaces/transforms/general.ts.tmp/slate-v2/packages/slate/src/transforms-node/insert-nodes.ts.tmp/slate-v2/packages/slate/src/transforms-node/lift-nodes.ts.tmp/slate-v2/packages/slate/src/transforms-node/merge-nodes.ts.tmp/slate-v2/packages/slate/src/transforms-node/move-nodes.ts.tmp/slate-v2/packages/slate/src/transforms-node/unwrap-nodes.ts.tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts.tmp/slate-v2/packages/slate/src/core/get-fragment.ts.tmp/slate-v2/packages/slate/src/utils/modify.ts.tmp/slate-v2/packages/slate/test/**.tmp/slate-v2/docs/general/changelog.mdactive goal statedocs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdRejected tactics:
Next action:
bun completion-checkCheckpoint:
bun completion-checkeditor.children, editor.selection,
editor.marks, or editor.operations as public compatibility fieldsActions:
onChange from the core BaseEditor runtime/type surfaceeditor.apply so plugins/tests cannot replace it as an
extension pointeditor.applyOperations(...) as the explicit operation import/replay
APIeditor.extend(...) so DOM
runtime operation interception composes through the extension registry instead
of monkeypatching editor.applyslate-dom operation interception from direct apply replacement
to operation middleware<Slate onChange> prop dispatch onto snapshot/commit
subscription instead of editor.onChangeeditor.selection / editor.marks mirrorsapply, absent onChange,
applyOperations, and subscriber/commit-listener orderingCommands:
bun test ./packages/slate/test/apply-onchange-hard-cut-contract.ts --bail 1bun test ./packages/slate/test/apply-onchange-hard-cut-contract.ts ./packages/slate/test/extension-contract.ts ./packages/slate/test/surface-contract.ts ./packages/slate/test/snapshot-contract.ts ./packages/slate/test/transaction-contract.ts ./packages/slate/test/escape-hatch-inventory-contract.ts --bail 1bun test ./packages/slate/test --bail 1bun test ./packages/slate-history --bail 1bun test ./packages/slate-history/test/history-contract.ts ./packages/slate-history/test/integrity-contract.ts --bail 1bun test ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts --bail 1bunx turbo build --filter=./packages/slate --filter=./packages/slate-dom --filter=./packages/slate-react --filter=./packages/slate-history --forcebunx turbo typecheck --filter=./packages/slate --filter=./packages/slate-dom --filter=./packages/slate-react --filter=./packages/slate-history --forcebun run lint:fixbun run lintbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0rg -n "editor\\.onChange\\b|\\.onChange\\s*=|editor\\.apply\\s*=" packages/slate packages/slate-dom packages/slate-react packages/slate-history --glob '!**/dist/**' --glob '!**/CHANGELOG.md'Evidence:
slate, slate-dom, slate-react, and slate-historyslate, slate-dom, slate-react, and
slate-historylint:fix formatted 5 files, then lint passed with no fixes appliededitor.onChange assignment or
editor.apply = replacement outside the hard-cut contractHypothesis:
editor.apply and editor.onChange are no longer viable extension points,
so plugin/runtime interception has one explicit path: operation middleware
plus commit subscribersDecision:
Editor.apply / readonly instance editor.apply as low-level operation
machinery, but never as the extension mechanismeditor.applyOperations(...) for explicit operation replay/importeditor.extend({ operationMiddlewares }) for operation interceptionEditor.subscribe / Editor.registerCommitListener for observationOwner classification:
editor.apply / editor.onChange hard cutChanged files:
.tmp/slate-v2/packages/slate/src/interfaces/editor.ts.tmp/slate-v2/packages/slate/src/create-editor.ts.tmp/slate-v2/packages/slate/src/core/editor-extension.ts.tmp/slate-v2/packages/slate/src/core/extension-registry.ts.tmp/slate-v2/packages/slate/src/core/public-state.ts.tmp/slate-v2/packages/slate/src/editor/is-editor.ts.tmp/slate-v2/packages/slate/test/apply-onchange-hard-cut-contract.ts.tmp/slate-v2/packages/slate/test/escape-hatch-inventory-contract.ts.tmp/slate-v2/packages/slate/test/extension-contract.ts.tmp/slate-v2/packages/slate/test/snapshot-contract.ts.tmp/slate-v2/packages/slate/test/surface-contract.ts.tmp/slate-v2/packages/slate/test/transaction-contract.ts.tmp/slate-v2/packages/slate-dom/src/plugin/dom-editor.ts.tmp/slate-v2/packages/slate-dom/src/plugin/with-dom.ts.tmp/slate-v2/packages/slate-dom/src/utils/range-list.ts.tmp/slate-v2/packages/slate-dom/src/utils/weak-maps.ts.tmp/slate-v2/packages/slate-dom/src/index.ts.tmp/slate-v2/packages/slate-history/src/with-history.ts.tmp/slate-v2/packages/slate-history/test/index.spec.ts.tmp/slate-v2/packages/slate-history/test/integrity-contract.ts.tmp/slate-v2/packages/slate-react/src/components/editable.tsx.tmp/slate-v2/packages/slate-react/src/components/slate.tsx.tmp/slate-v2/packages/slate-react/src/editable/clipboard-input-strategy.ts.tmp/slate-v2/packages/slate-react/src/editable/composition-state.ts.tmp/slate-v2/packages/slate-react/src/editable/selection-reconciler.ts.tmp/slate-v2/packages/slate-react/src/hooks/android-input-manager/android-input-manager.tsdocs/solutions/developer-experience/2026-04-19-slate-public-single-op-writes-should-use-editor-apply-and-keep-onchange-behind-subscribers.mdactive goal statedocs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdRejected tactics:
editor.onChange compatibility shimeditor.applyrunCommand ceremonyeditor.selection / editor.marks mirrors to fix
React falloutNext action:
bun completion-checkCheckpoint:
editor.apply/onChange as extension points were legacy
footguns; keeping them replaceable would undermine the update/commit runtimeeditor.apply(...) still exists as readonly low-level
machinery; future batches should continue moving tests and docs toward
editor.update(...) and editor.applyOperations(...)bun completion-checkeditor.onChange, writable
editor.apply, or method monkeypatching as compatibility escape hatchesActions:
Transforms.* hard cutactive goal state back to status: pendingTransforms.* look like a first-class
APICommands:
sed -n '1,240p' docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdsed -n '1,220p' active goal staterg -n "Transforms|transform namespace|editor\\.update|Public API|Hard Cut|mutable|completion" docs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.md docs/research/decisions/slate-v2-read-update-runtime-architecture.md docs/research/systems/slate-v2-perfect-plan-steal-reject-defer-map.md active goal staterg -n "title:.*(transform|slate|api)|tags:.*(transform|slate|api)|module:.*(slate|editor)" docs/solutions --glob '*.md' -iEvidence:
active goal state is pending for this active ownerTransforms.* was only reduced in
selected paths, not fully cuteditor.update / primitive-method public
runtime targetHypothesis:
Decision:
Owner classification:
Transforms.* namespace hard cut.tmp/slate-v2/packages/slate/**.tmp/slate-v2/packages/slate-history/**,
.tmp/slate-v2/packages/slate-react/**, and legacy fixtures that import from
slateChanged files:
active goal statedocs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdRejected tactics:
toggleList just to avoid
primitive compositiontx.resolveTarget() or command policy objectNext action:
Transforms, then remove the export and migrate the runtime/test falloutCheckpoint:
Transforms.* surviving in contracts and fixtures keeps the old
API alive even if docs are clean; that is zombie architecture, not hard cuteditor.update are the chosen public runtime, so
free-function mutation namespaces should not remain publicTransforms as a compat shim, and do not
delete transform implementation internals before the editor primitive path is
greenClosure actions:
slate must not export
Transforms, GeneralTransforms, NodeTransforms, SelectionTransforms, or
TextTransformsinterfaces/index.tsOperationTransformMethods, NodeMutationMethods,
SelectionMutationMethods, and TextMutationMethodsTransforms.* calls
to editor primitive methods or editor.applyOperations(...)GeneralTransforms.applyBatch(...) and
GeneralTransforms.transform(...) contract coverage with editor operation
replay coverageapplyInsertText as an implementation-local helper so semantic
editor.insertText(...) no longer recurses through itself after the namespace
cutat insert semantics so explicit target insertion does not
consume active marks, and read-only/void collapsed targets are ignored before
opening a transactionTransformsTransforms namespaceCommands:
bun test ./packages/slate/test/public-surface-contract.ts --bail 1bun test ./packages/slate/test/public-surface-contract.ts ./packages/slate/test/surface-contract.ts ./packages/slate/test/escape-hatch-inventory-contract.ts --bail 1bun test ./packages/slate/test/transaction-contract.ts ./packages/slate/test/accessor-transaction.test.ts ./packages/slate/test/snapshot-contract.ts --bail 1SLATE_FIXTURE_FILTER='transforms/insertText/voids-false/read-only-inline' bun test ./packages/slate/test/index.spec.ts --bail 1bun test ./packages/slate/test --bail 1bun test ./packages/slate-history --bail 1bun test ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts ./packages/slate-react/test/target-runtime-contract.tsx ./packages/slate-react/test/dom-text-sync-contract.ts ./packages/slate-react/test/kernel-authority-audit-contract.ts --bail 1bunx turbo build --filter=./packages/slate --filter=./packages/slate-dom --filter=./packages/slate-react --filter=./packages/slate-history --forcebunx turbo typecheck --filter=./packages/slate --filter=./packages/slate-dom --filter=./packages/slate-react --filter=./packages/slate-history --forcebun run lint:fixbun run lintrg -n "\\bTransforms\\." packages site docs playwright --glob '!**/dist/**' --glob '!**/CHANGELOG.md' --glob '!site/out/**' --glob '!site/.next/**' --glob '!docs/general/changelog.md'rg -n "\\bTransforms\\b|\\b(GeneralTransforms|NodeTransforms|SelectionTransforms|TextTransforms)\\b" packages/slate/src packages/slate/test packages/slate-history packages/slate-react packages/slate-dom site/examples docs --glob '!**/dist/**' --glob '!**/CHANGELOG.md' --glob '!site/out/**' --glob '!site/.next/**' --glob '!docs/general/changelog.md'bun completion-checkEvidence:
Transforms was
still exportedslate, slate-dom, slate-react, and slate-historyslate, slate-dom, slate-react, and
slate-historylint:fixTransforms.* call-site grep is clean outside excluded generated/changelog
outputpackages/slate/test/public-surface-contract.tsbun completion-check passes for active goal stateHypothesis:
editor.update write boundary; transform implementation modules may remain as
private organization, but the free-function namespace is no longer a public or
test-facing APIDecision:
Transforms.* as compatibility scaffoldingeditor.applyOperations(...)
in tests that need exact operation coverageOwner classification:
Transforms.* namespace hard cuteditor.update enforcement, browser gauntlets, mobile/IME
proof, and core perf cleanupChanged files:
.tmp/slate-v2/.changeset/remove-transforms-namespace.md.tmp/slate-v2/docs/Summary.md.tmp/slate-v2/docs/walkthroughs/03-defining-custom-elements.md.tmp/slate-v2/docs/walkthroughs/07-enabling-collaborative-editing.md.tmp/slate-v2/packages/slate/src/core/apply.ts.tmp/slate-v2/packages/slate/src/editor/insert-text.ts.tmp/slate-v2/packages/slate/src/interfaces/editor.ts.tmp/slate-v2/packages/slate/src/interfaces/index.ts.tmp/slate-v2/packages/slate/src/interfaces/transforms/general.ts.tmp/slate-v2/packages/slate/src/interfaces/transforms/index.ts.tmp/slate-v2/packages/slate/src/interfaces/transforms/node.ts.tmp/slate-v2/packages/slate/src/interfaces/transforms/selection.ts.tmp/slate-v2/packages/slate/src/interfaces/transforms/text.ts.tmp/slate-v2/packages/slate/src/transforms-text/insert-text.ts.tmp/slate-v2/packages/slate/test/public-surface-contract.ts.tmp/slate-v2/packages/slate/test/surface-contract.ts.tmp/slate-v2/packages/slate/test/escape-hatch-inventory-contract.tsTransforms.* to editor primitivesdocs/solutions/developer-experience/2026-04-09-slate-transform-namespaces-should-stay-thin-sugar-over-the-current-engine.mdactive goal statedocs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdRejected tactics:
Transformstx.resolveTarget() to replace
transformstoggleList just to avoid
primitive compositiontransformsNext action:
active goal state done for this slice and run
bun completion-checkCheckpoint:
Transforms.* in fixtures and contracts was not harmless;
it taught contributors the old runtime even after docs moved ontransforms, and private
implementation files still live under transform folders; that is acceptable
only as implementation organization, not API directionbun completion-checkTransforms, do not add broad semantic method
bloat, and do not use test-only transform wrappers as migration scaffoldingActions:
active goal state back to status: pendingeditor.update(...) is the write boundary, Lexical state helpers error
outside update/read, and only named command dispatch opens an implicit updateCommands:
rg -n "slate-v2|read/update|editor.update|completion-check|hard cut" /Users/zbeyens/.codex/memories/MEMORY.mdrg -n "auto.?transaction|compatibility auto|write boundary|editor\\.update|read-update" docs/solutions docs/plans docs/research active goal state --glob '*.md'rg -n "auto.?transaction|compatibility auto|write boundary|editor\\.update|withTransaction|applyOperations" .tmp/slate-v2/packages/slate/src .tmp/slate-v2/packages/slate/test .tmp/slate-v2/docs --glob '!**/dist/**'sed -n '1,220p' .tmp/slate-v2/packages/slate/test/write-boundary-contract.tssed -n '1,1240p' .tmp/slate-v2/packages/slate/src/core/public-state.tsEvidence:
.tmp/slate-v2/packages/slate/test/write-boundary-contract.ts still has a
contract named keeps direct primitive calls as compatibility auto-transactions.tmp/slate-v2/packages/slate/src/core/public-state.ts only rejects direct
primitive writes from inside editor.read, not from ordinary userlandeditor.update(...), so the remaining gap is
runtime enforcement and fixture/test migrationHypothesis:
Decision:
editor.update(...) should throweditor.applyOperations(...) remains the explicit import/replay writerOwner classification:
.tmp/slate-v2/packages/slate/src/core/public-state.tsRejected tactics:
Next action:
write-boundary-contract.ts RED so direct primitive calls outside
editor.update(...) must throw, then enforce the runtime guardCheckpoint:
editor.updatebun test ./packages/slate/test/write-boundary-contract.ts --bail 1tx.resolveTarget() to userlandActions:
editor.update(...) as the only public primitive write boundaryeditor.applyOperations(...) as the explicit import/replay writerTransforms.*Slate.Transforms only as a dynamic fallback inside legacy cross-repo
benchmark runnersCommands:
bun test ./packages/slate/test/write-boundary-contract.ts ./packages/slate/test/read-update-contract.ts ./packages/slate/test/primitive-method-runtime-contract.ts --bail 1bun test ./packages/slate/test/public-surface-contract.ts ./packages/slate/test/escape-hatch-inventory-contract.ts --bail 1bun test ./packages/slate-react/test/editing-kernel-contract.ts ./packages/slate-react/test/selection-controller-contract.ts ./packages/slate-react/test/dom-repair-policy-contract.ts --bail 1bunx turbo build --filter=./packages/slate --filter=./packages/slate-dom --filter=./packages/slate-react --filter=./packages/slate-history --forcebunx turbo typecheck --filter=./packages/slate --filter=./packages/slate-dom --filter=./packages/slate-react --filter=./packages/slate-history --forcebun run lint:fixbun run lintbun run bench:core:huge-document:compare:localbun run bench:core:observation:compare:localbun run bench:core:normalization:compare:localbun run bench:core:text-selection:localbun run bench:core:transaction:localbun run bench:core:editor-store:localbun run bench:core:normalization:localbun run bench:core:query-ref-observation:localbun run bench:core:node-transforms:localbun run bench:core:refs-projection:localbun run bench:react:rerender-breadth:localREACT_HUGE_DOC_BLOCKS=200 REACT_HUGE_DOC_BENCH_ITERATIONS=2 bun run bench:react:huge-document-overlays:localREACT_HUGE_COMPARE_BLOCKS=5000 REACT_HUGE_COMPARE_ITERATIONS=5 REACT_HUGE_COMPARE_TYPE_OPS=10 bun run bench:react:huge-document:legacy-compare:localbunx playwright test ./playwright/integration/examples/richtext.test.ts --project=chromium --project=firefox --project=webkit --project=mobile --grep "selection|caret|toolbar|bold|heading|arrow|backspace|delete|warm|generated" --workers=4 --retries=0bun test:integration-localEvidence:
editor.update(...) throweditor.update(...) still compose through commitseditor.applyOperations(...) remains the explicit operation replay pathTransforms.* has no remaining public/docs/examples/runtime benchmark usageHypothesis:
Decision:
Slate.Transforms only to compare
against ../slateOwner classification:
Rejected tactics:
tx.resolveTarget()executeCommand auto-update fallbackTransforms as a public namespaceNext action:
bun completion-checkCheckpoint:
editor.update(...) architecturebun completion-checkTransforms, and do not treat legacy benchmark fallbacks as user-facing APIActions:
slate-browser release-proof artifact helpers for raw mobile/device,
persistent-browser soak, and ongoing release-discipline claimsslate-browser proof tests that reject semantic/proxy mobile
evidence for raw device claimsslate-browser scenario stepscheck:full to run release-proof gates and persistent-browser soak
before bun test:integration-localsite/examples TS/TSX
and JS/JSX file is scanned, not only a handpicked subseteditor.selection to editor.getSelection().agents/AGENTS.md and synced root AGENTS.md so future agents do
not use Playwright mobile viewport or semantic handles as raw-device proofCommands:
command -v adbcommand -v appiumcommand -v xcrunadb devicesxcrun simctl list devices bootedxcrun simctl list devices availableappium driver list --installedpnpm installbun --filter slate-browser test:proofbun test:release-disciplinebun test:mobile-device-proofbun test:release-proofSLATE_BROWSER_SOAK_ITERATIONS=2 bun test:persistent-soakbunx turbo build --filter=./packages/slate-browser --forcebunx turbo typecheck --filter=./packages/slate-browser --forcebun run lint:fixbun run lintEvidence:
bun test:release-proof passed:
slate-browser release/scenario proof: 17 passed, 37 expectsSLATE_BROWSER_SOAK_ITERATIONS=2 bun test:persistent-soak passed and wrote
.tmp/slate-v2/test-results/release-proof/persistent-browser-soak.jsonbunx turbo build --filter=./packages/slate-browser --force passedbunx turbo typecheck --filter=./packages/slate-browser --force passedbun run lint:fix and bun run lint passedadb, appium, and xcrun, but no attached Android
device and no booted iOS simulator/device during this sliceHypothesis:
Decision:
check:fulltest:mobile-device-proof:raw is an explicit device-lab gate, not part of
ordinary local check:full, because machines without raw devices would fail
honestlyOwner classification:
Changed files:
.tmp/slate-v2/package.json.tmp/slate-v2/packages/slate-browser/package.json.tmp/slate-v2/packages/slate-browser/src/core/index.ts.tmp/slate-v2/packages/slate-browser/src/core/release-proof.ts.tmp/slate-v2/packages/slate-browser/test/core/release-proof.test.ts.tmp/slate-v2/packages/slate/test/public-surface-contract.ts.tmp/slate-v2/scripts/proof/mobile-device-proof.mjs.tmp/slate-v2/scripts/proof/persistent-browser-soak.mjs.tmp/slate-v2/site/examples/js/hovering-toolbar.jsx.tmp/slate-v2/site/examples/ts/hovering-toolbar.tsx.tmp/slate-v2/site/examples/ts/tables.tsx.agents/AGENTS.mdAGENTS.mdactive goal statedocs/plans/2026-04-24-slate-v2-absolute-architecture-closure-plan.mdRejected tactics:
check:fullNext action:
active goal state done for this release-proof slice and run
bun completion-checkCheckpoint:
bun completion-checkcheck:full, and do not let primary examples reintroduce
mutable fields or Transforms.*