docs/plans/2026-05-07-slate-v2-insert-fragment-at-location-ralplan.md
Date: 2026-05-07
Ready for Ralph.
The next lane is core insertFragment explicit target and caret placement:
#5412 and #5429.
This beats #5080, #3891, and #5129 as the immediate next move:
#5412 is ready-now, core-only, and points at a real transform regression:
explicit insertFragment({ at }) must not ignore the provided target.#5429 is the sibling caret-placement case: inserting into an empty node must
leave selection after the inserted content.#5080 is a clean query-order bug, but it is isolated and does not advance
the fragment/clipboard cluster already carrying open PR debt.#3891 and #5129 are API design requests, not direct red-test targets.Intent: close the next high-confidence core transform regression without turning fragment insertion into a broad paste-policy rewrite.
Desired outcome:
insertFragment(..., { at }) writes at the supplied location even
when current selection points elsewhere;In scope:
.tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts;.tmp/slate-v2/packages/slate/test/;Non-goals:
#5129;#3891;Editor.nodes({ reverse: true }) traversal fix for #5080;#3557/#4542;Decision boundary:
insertFragment target or selection behavior after a
failing package test.Fixes #5412 only after explicit-target package proof lands.Fixes #5429 only after empty-node insertion caret proof
lands.#5089, #4542, #5151, #3557, and #3155 related or improved
unless exact repro proof lands.Principles:
Drivers:
#5412 and #5429 ready-now.tx.resolveTarget({ at: options.at }),
so the likely failure is a narrow target or post-insert selection path.Options:
insertFragment directly after red package tests.
#5412 is a core Transforms.insertFragment(..., { at })
regression.Chosen: option 1, with tests that cover both explicit target insertion and empty-node caret placement.
Current source:
.tmp/slate-v2/packages/slate/src/transforms-text/insert-fragment.ts owns
insertFragment.applyInsertFragment resolves options.at through
tx.resolveTarget({ at: options.at })..tmp/slate-v2/packages/slate/src/core/public-state.ts returns explicit
options.at unchanged from resolveTarget.insert-fragment.ts has several fast replacement paths before the legacy
split/insert path, then only performs final transforms.select(end) when
!options.at..tmp/slate-v2/packages/slate/test/primitive-method-runtime-contract.ts covers
omitted transaction targets for tx.fragment.insert, not the explicit at
issue..tmp/slate-v2/packages/slate/test/clipboard-contract.ts covers many fragment
replacement shapes, including target-block preservation, but not #5412.Live current shape exists. This is not a fake migration from old Slate; it is a current v2 transform contract gap.
Target fixed claims after Ralph proof:
#5412: selected active target. Fixes only after package proof shows
explicit at is honored.#5429: selected active target. Fixes only after package proof shows empty
node insertion places selection after inserted content.Related rows:
#5089: related. Multi-block fragment shape pressure, but exact closure needs
a middle-paragraph multi-block insertion proof.#4542: related. Empty-block paste policy is adjacent, but broad browser
paste behavior is not this lane.#5151: improved by existing target-block preservation proof; exact browser
closure remains unclaimed.#3557: related. Extension method override pressure belongs to clipboard and
extension API design, not this core transform fix.#3155: related. Fragment non-merging policy is broader than explicit target
correctness.Excluded next candidates:
#5080: next possible package lane for Editor.nodes({ reverse: true });
separate query-order owner.#3891: not a direct test candidate; separate API design.#5129: not a direct test candidate; separate replace/rewrap transform API.Live gitcrawl ledger:
docs/slate-issues/gitcrawl-live-open-ledger.md carries generated live issue
fields only. Claim state is synced in this plan,
docs/slate-v2/ledgers/issue-coverage-matrix.md,
docs/slate-v2/ledgers/fork-issue-dossier.md, and
docs/slate-v2/references/pr-description.md.| Dimension | Score | Evidence |
|---|---|---|
| React 19.2 runtime performance | 0.90 | React is out of scope unless browser paste proof becomes necessary. |
| Slate-close unopinionated DX | 0.94 | Existing insertFragment option behavior is the public contract; no new API is proposed. |
| Plate/slate-yjs migration backbone | 0.90 | Operation and transaction proof stay core-owned; no Plate adapter required. |
| Regression-proof testing strategy | 0.95 | #5412 and #5429 are ready-now; package tests can assert model children and selection. |
| Research evidence completeness | 0.91 | Current issue dossiers, candidate maps, and live v2 source were read. External systems are not needed for this local regression. |
| shadcn-style composability | 0.90 | Not a UI lane; minimal public options avoid component/API sprawl. |
Total: 0.92.
No external ecosystem source is used as decisive evidence here. That is intentional. The failure is local to Slate's own transform contract and issue corpus.
Mechanism to keep: transaction-owned core write with deterministic selection.
Mechanism to reject: using browser paste behavior or app override hooks as a substitute for a correct raw core transform.
#5412 package test.
Editor.insertFragment(editor, fragment, { at }) with at pointing
somewhere else.at, not current selection.#5429 package test.
insert-fragment.ts.#5089 and #4542 as related unless the same package proof exactly
covers their repros.Ralph should run:
bun test ./packages/slate/test/clipboard-contract.ts -t "insertFragment"
bun test ./packages/slate/test/primitive-method-runtime-contract.ts -t "insertFragment"
bun --filter slate typecheck
bun lint:fix
If implementation touches browser or DOM clipboard code, add focused DOM/browser proof before any fixed browser claim.
| Pass | Status | Evidence added | Plan delta | Next owner |
|---|---|---|---|---|
| current-state read | complete | Read issue maps, dossiers, coverage rows, PR reference, insert-fragment.ts, public-state.ts, and current tests. | Selected #5412/#5429. | Ralph TDD |
| related issue discovery | complete | Reviewed #5089, #4542, #5151, #3557, #3155, #5080, #3891, #5129. | Kept non-targets bounded. | Ralph TDD |
| closure score | complete | Score 0.92, no dimension below 0.90. | Ready for execution. | Ralph |
| Ralph execution start | complete | .tmp/completion-checks/slate-v2-insert-fragment-at-location-execution.md; active goal state. | Activated TDD pass for #5412 and #5429. | Package tests |
| TDD proof | complete | .tmp/slate-v2/packages/slate/test/clipboard-contract.ts adds exact package proof for explicit insertFragment({ at }) and empty-block caret placement. | Current source already satisfies both issue-shaped contracts; no production patch needed. | Verification sweep |
| Verification sweep | complete | bun test ./packages/slate/test/clipboard-contract.ts -t "insertFragment"; bun test ./packages/slate/test/primitive-method-runtime-contract.ts -t "insertFragment"; bun --filter slate typecheck; bun lint:fix; bun run completion-check. | #5412 and #5429 moved to Fixes; non-target rows remain bounded. | Next slate-ralplan bucket selection |
The lane is ready for Ralph when:
.tmp/completion-checks/slate-v2-insert-fragment-at-location-ralplan.md is
done;bun run completion-check passes.The later execution lane is done only after:
#5412 and #5429 have exact package proof or explicit non-claim evidence;bun --filter slate typecheck passes;bun lint:fix passes;Ralph execution landed exact package proof for both active targets:
#5412: insertFragment(..., { at }) writes at the supplied target instead
of ambient selection.#5429: insertFragment into an empty text block leaves selection after the
inserted content.No implementation patch was needed because current source already satisfied the
two contracts once the issue-shaped tests were added. Keep #5089, #4542,
#5151, #3557, and #3155 related or improved only; this lane does not add
browser paste, method override, or multi-block middle-paragraph paste closure.