feat(cms): add, replace, remove and reorder blocks by key with blockEdits - #897
Open
kmonsoe wants to merge 1 commit into
Open
feat(cms): add, replace, remove and reorder blocks by key with blockEdits#897kmonsoe wants to merge 1 commit into
kmonsoe wants to merge 1 commit into
Conversation
…dits cms_update_entry takes blockEdits — ordered, all-or-nothing set/delete/move operations addressing blocks of a blocks field by their stable key, placed with before/after/position — so changing which blocks exist no longer means resending the array. set replaces a block outright or inserts a new one, minting a key when none is given. Unknown and duplicate keys fail with cms_block_not_found and cms_block_ambiguous, writing nothing. Block edits run before text replacements when a call carries both, and asset rewiring runs on the result so an inserted figure is covered by the delete guard. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJjhaB9bMU1agbqVKTwbB1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #895 — merge that first, then retarget this PR to
mainbefore merging it. Independent of #896 (KB), which is stacked on the same parent.Why
#895 made it possible to reword a block without regenerating the article, but changing which blocks exist still meant sending the whole array through
data. On a real journal entry that array is ~20 blocks and most of the payload, so adding one callout re-transmits the entire post and risks the same drift the text replacements were introduced to avoid.The live
journal-blocksentries already carry authored, stable keys (lead,premise,takeaways,close), so key addressing works on existing content without a migration.What
cms_update_entrygainsblockEdits— an ordered, all-or-nothing list of operations on ablocksfield.setdeletemovebefore/after/positionbeforeandaftername another block's key;positionisstartorend. At most one of the three per edit.setcarries the whole block (typeplus every prop) and replaces the old one outright rather than merging, which keeps the operation idempotent. Omittingkeymints one, so a block can be appended without inventing an identifier.cms_block_not_foundfor an unknown target or anchor,cms_block_ambiguouswhen two blocks share the addressed key,cms_block_invalidfor a malformed edit.blockEditsandtextReplacementscompose on the same field, block edits first.dataremains exclusive with both./v1/cms/drafts/:idPATCH accepts the same field.Design notes
The
openum sits inside the array elements, not on the tool input, so the schema stays a flat object with an enum — nooneOf, which is the shape strict-validation hosts have rejected. This mirrors Sanity'spatch_documents, where one call carries a heterogeneous array ofset/unset/insertoperations.setdeliberately upserts rather than splitting into separate create and update ops: it is the one place the repo'sconfigure_*precedent applies cleanly, since the key is the identity and a re-call is unambiguous.Skills
author-with-blocksgains an operations section, andrevise-entrynow frames the two surgical inputs together: replacements change what a block says, block edits change which blocks exist. Fixtures regenerated.Tests
cms.fields.test.ts: 11 cases over the pure helper — in-place replace, append, before/after/start/end placement, minted keys, replace-and-reposition, ordered edits, empty and non-list values, and each failure code.cms.service.test.ts: insert/replace/move/delete through the service, minted key shape, atomic failure leaving the entry untouched, block-type validation of the result, non-blocks and unknown fields,dataoverlap, and block-edits-before-replacements ordering.cms.integration.test.ts: the surface through/mcp, assertingcms_list_asset_usagepicks up an inserted figure andcms_delete_assetthen refuses.37 files / 589 tests pass across the CMS, MCP, control-plane and common suites; workspace typecheck clean.
🤖 Generated with Claude Code
https://claude.ai/code/session_01VJjhaB9bMU1agbqVKTwbB1