docs/solutions/logic-errors/2026-04-03-editor-key-protocols-must-cover-expanded-selection-and-repeated-escalation.md
Several keyboard seams looked fine when tested with a single collapsed caret, but broke once selection shape or repeated key ownership entered the picture.
The failures were different on the surface, but the bug pattern was the same: the implementation only handled the first happy-path cursor state.
Enter inside selected heading text created another heading instead of a paragraph.Backspace at the start of a non-empty first code line exploded the code
block into paragraphs.Shift+Tab over multiple selected nested quote blocks only lifted one block.selectAll inside a table stopped at the table forever instead of escalating
on the second invocation.deleteBackward or
insertBreak at a caret.Make the key seams selection-aware and escalation-aware:
splitReset run for same-block expanded selections, not just collapsed
cursorsBackspace local at the first non-empty line and merge empty
inner lines locallyTab, deepest paths firstselectAll from cell -> table -> document instead of stopping
at table selection foreverThe important part was not one specific plugin. It was closing the protocol blind spot across multiple owners.
Keyboard behavior is not defined only by the key and the node type.
It is also defined by:
If tests cover only collapsed selections and single invocations, the protocol looks complete while major real-world paths are still wrong.
deleteFragment as the real seam for expanded ⌫ / ⌦ behavior. Do
not pretend deleteBackward alone covers selection deletion.These checks passed:
bun test packages/core/src/lib/plugins/override/withBreakRules.spec.tsx packages/core/src/lib/plugins/override/withDeleteRules.spec.tsx packages/core/src/lib/plugins/override/withMergeRules.spec.tsx packages/code-block/src/lib/withCodeBlock.spec.tsx packages/table/src/lib/withTable.spec.tsx packages/indent/src/lib/withIndent.spec.tsx packages/list/src/lib/withList.spec.tsx
pnpm turbo build --filter=./packages/core --filter=./packages/basic-nodes --filter=./packages/code-block --filter=./packages/table --filter=./packages/indent --filter=./packages/list
pnpm turbo typecheck --filter=./packages/core --filter=./packages/basic-nodes --filter=./packages/code-block --filter=./packages/table --filter=./packages/indent --filter=./packages/list
pnpm lint:fix
#4898