Skip to content

fix: delete auto-resolve validation repairs in favor of engine normalization - #3247

Merged
christianhg merged 1 commit into
emit-repair-patches-immediatelyfrom
delete-auto-resolve-repairs
Sep 8, 2026
Merged

fix: delete auto-resolve validation repairs in favor of engine normalization#3247
christianhg merged 1 commit into
emit-repair-patches-immediatelyfrom
delete-auto-resolve-repairs

Conversation

@christianhg

Copy link
Copy Markdown
Member

With #3246, the editor emits its structural repair patches the moment a value settles. That left validateValue's autoResolve resolutions as a second repairer running ahead of the engine: four rules (missing block _key, missing or empty children, orphaned markDefs, missing child _key) repaired blocks before ingestion and reported through the sync actor's out-of-band patch channel, with their own patch shapes and their own addressing quirks.

This PR deletes them and makes engine normalization the sole repairer. Validation passes mechanically fixable shapes through untouched; the engine repairs them on intake and its patches emit in engine shapes: a keyless block gets a minimal set on its minted _key (previously a whole-block set), an empty text block gets its placeholder span as an insert before children[0]. The sync actor's patch channel and its reporting machinery go with the rules. The invalid-value flow is untouched for defects that genuinely need a human, and its remaining resolutions now resolve their block anchors through nodeSegment, so a keyless block with a non-mechanical defect is addressed by its numeric index instead of a {_key: undefined} segment that keyed matching would resolve to the first keyless sibling (pinned red-on-old).

Raw input reaches updateBlock for the first time, so it gains a wholesale-set fallback: children arrays with keyless members, or a raw empty children replacing populated children, are set wholesale and normalization mints the keys; no {_key: undefined} segment is ever applied (pinned by unit tests asserting the full applied-operation streams).

Two deliberate deltas. Orphaned markDefs are no longer pruned at intake: the engine's prune is local-only by design, so orphans go when a local edit next dirties the block, emitted as a set of the filtered array (a read-only editor never prunes them). And sync insert operations now carry the raw block, with normalization repairs following as their own operations. InvalidValueResolution.autoResolve is deprecated rather than removed, never set.

One caveat: the empty-block placeholder span now travels as insert ... before children[0] where the deleted rule used insert ... after children[0]; both anchor index 0 of an empty array, and whether Content Lake treats the two anchors identically on an empty array is not verifiable from this repo. Client-side application (applyAll) is pinned equivalent.

Stacked on #3246 and merges after it; the base branch is emit-repair-patches-immediately.

…ization

`validateValue` carried four `autoResolve` resolutions (missing block
`_key`, missing or empty `children`, orphaned `markDefs`, missing
child `_key`) that repaired synced blocks before ingestion and
reported the patches through the sync actor's out-of-band `patch`
channel. Engine normalization repairs the same structural defects on
intake and its patches emit, so the pre-ingestion repairs were a
second repairer running ahead of the real one, with its own patch
shapes and its own addressing bugs.

The four resolutions are deleted; validation passes those shapes
through and the engine repairs them, emitting engine-shaped patches
(minimal `set` on the minted `_key`, placeholder-span `insert` before
`children[0]`). With them go `reportAutoResolution`,
`applyAutoResolution`, `rebaseBlockPatchPath`, and the sync actor's
`patch` channel end to end. `updateBlock` gains the wholesale-set
fallback for raw input: children arrays containing keyless children,
or replacing a raw empty `children`, are set wholesale instead of
reconciled per child, so no `{_key: undefined}` path segment is ever
applied; normalization then mints the keys. Remaining block-anchored
resolutions resolve their paths through `nodeSegment`, so a keyless
block with a non-mechanical defect addresses its resolution at the
block's numeric index instead of `{_key: undefined}` (which keyed
matching would resolve to the first keyless sibling).

Deliberate deltas: orphaned `markDefs` are no longer pruned at
intake (the engine's prune is local-only by the two-class model);
they go when a local edit next dirties the block, as a `set` of the
filtered array. Sync `insert` operations carry the raw block, and
normalization repairs follow as their own operations.
`InvalidValueResolution.autoResolve` is deprecated, never set.
@changeset-bot

changeset-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 918ffda

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@portabletext/editor Patch
@portabletext/plugin-character-pair-decorator Patch
@portabletext/plugin-dnd Patch
@portabletext/plugin-emoji-picker Patch
@portabletext/plugin-input-rule Patch
@portabletext/plugin-list-index Patch
@portabletext/plugin-markdown-shortcuts Patch
@portabletext/plugin-one-line Patch
@portabletext/plugin-paste-link Patch
@portabletext/plugin-sdk-value Patch
@portabletext/plugin-table Patch
@portabletext/plugin-typeahead-picker Patch
@portabletext/plugin-typography Patch
@portabletext/toolbar Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
portable-text-editor-documentation Ready Ready Preview Sep 8, 2026 2:22pm UTC
portable-text-example-basic Ready Ready Preview Sep 8, 2026 2:22pm UTC
portable-text-playground Ready Ready Preview Sep 8, 2026 2:22pm UTC

Request Review

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Bundle Stats

✅ No significant changes.

All scenario measurements (7)

🗺️ @portabletext/editor / @portabletext/editor · @portabletext/editor / @portabletext/editor/behaviors · @portabletext/editor / @portabletext/editor/plugins · @portabletext/editor / @portabletext/editor/selectors · @portabletext/editor / @portabletext/editor/traversal · @portabletext/editor / @portabletext/editor/utils · @portabletext/markdown / @portabletext/markdown · Artifacts

Scenario Kind Bundle (raw / gzip) Gzip change Import time Import change
⚪ @portabletext/editor / @portabletext/editor export 1.09 MB / 252.9 KB -1.1 KB, -0.4% 68 ms +0 ms, +0.6%
⚪ @portabletext/editor / @portabletext/editor/behaviors export 4.0 KB / 1.4 KB None 2 ms +0 ms, +1.9%
⚪ @portabletext/editor / @portabletext/editor/plugins export 5.1 KB / 1.8 KB None 7 ms +0 ms, +0.8%
⚪ @portabletext/editor / @portabletext/editor/selectors export 94.7 KB / 21.7 KB None 8 ms +0 ms, +0.3%
⚪ @portabletext/editor / @portabletext/editor/traversal export 42.8 KB / 11.2 KB None 6 ms +0 ms, +2.1%
⚪ @portabletext/editor / @portabletext/editor/utils export 33.8 KB / 9.1 KB None 6 ms +0 ms, +0.9%
⚪ @portabletext/markdown / @portabletext/markdown export 312.3 KB / 90.7 KB None 41 ms +1 ms, +1.4%

Significant means at least 1.0 KB and 1% gzip, or at least 5 ms and 10% import time.

@christianhg

Copy link
Copy Markdown
Member Author

Folded into #3246 as its third commit; one PR, same commits.

@christianhg
christianhg merged commit 918ffda into emit-repair-patches-immediately Sep 8, 2026
17 checks passed
@christianhg
christianhg deleted the delete-auto-resolve-repairs branch September 8, 2026 15:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant