Skip to content

promote FableLoom intent transitions to per-edge sub-resource routes - #4802

Merged
atomantic merged 1 commit into
mainfrom
claim/issue-4786
Aug 22, 2026
Merged

promote FableLoom intent transitions to per-edge sub-resource routes#4802
atomantic merged 1 commit into
mainfrom
claim/issue-4786

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

  • Intent transitions are now sub-resources under their scene node, so any writer adds or edits one edge per call instead of replaying the whole array off a snapshot another writer has already moved past:
    • POST /api/fableloom/:id/episodes/:episodeId/nodes/:nodeId/transitions{ loom, transition } (server mints the tr-* id)
    • PATCH …/transitions/:transitionId → the loom
    • DELETE …/transitions/:transitionId → the loom
  • Back-compat is intact: the whole-array transitions key on the node PATCH is unchanged, so a client or federated peer from before these routes keeps working. No on-disk shape change, so no migration and no sync-payload version bump.
  • The scene editor saves rows individually. A path is created server-side first, so every row the panel holds already carries its id — syncTransitionsFrom, the re-sync that pushed server-minted ids back into locally-added rows after each save, is gone. Blur-saves, the target select, and remove each touch exactly one edge.
  • Supporting cleanups rolled in: runSave collapses the pending-save / error-toast plumbing shared by every write in the panel; a failed delete restores the row from the record instead of leaving a path that only looks gone; a blurred row with no matching record row now saves rather than silently dropping the edit (absent ≠ unchanged).
  • Schemas (transitionCreateSchema / transitionPatchSchema) derive their caps from LOOM_LIMITS, and addNodeTransition refuses to exceed TRANSITIONS_MAX with 400 LIMIT_REACHED.

Closes #4786

Test plan

  • server: full Vitest suite green (1563 files). New coverage in server/services/fableLoom/records.test.js (mint + read back the row, siblings untouched on add/delete, partial patch keeps the id and unlisted fields, 404 on an unknown id, the cap) and server/routes/fableLoom.test.js (dispatch args for all three routes, id in a POST body is stripped rather than honored, and the whole-array node PATCH still forwards untouched).
  • client: full Vitest suite green (727 files). New client/src/components/fableloom/LoomNodeEditor.test.jsx asserts the add path goes through addLoomTransition and never updateLoomNode, a blurred edit PATCHes one row by id, an unchanged blur skips the round-trip, and remove DELETEs by id. apiFableLoom.test.js covers path building and segment encoding.
  • node scripts/run-ci-lint.js clean.
  • Manual: in the scene editor, add a path, retarget it, edit its intent and trigger phrasings, and remove it — each action is a single request against the one edge.

…ther (#4786)

Adding one intent transition meant PATCHing the node with the whole
`transitions` array, so a second writer working from a stale snapshot dropped
every row it had never seen — and the editor had to reconcile server-minted
ids back into its locally-added rows after each save.

Transitions are now sub-resources under their scene, mirroring the node routes:
POST mints the `tr-*` id and answers `{ loom, transition }`, PATCH and DELETE
address one edge by id and answer with the loom. The whole-array key on the
node PATCH keeps working unchanged, so a client or peer from before these
routes is unaffected.

The scene editor creates a path server-side first, so every row it holds
already carries its id; blur-saves, the target select, and remove each touch
exactly one edge, and the id re-sync workaround is gone.
@atomantic
atomantic merged commit af4fae9 into main Aug 22, 2026
7 checks passed
@atomantic
atomantic deleted the claim/issue-4786 branch August 22, 2026 02:05
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.

promote FableLoom intent transitions to sub-resource routes

1 participant