Canvas Duplicate as new item leaves the copied Task drawing unlinked #1075

Open
opened 2026-10-04 23:01:07 +00:00 by kayg · 4 comments
Owner

Duplicate as new item copies a linked Task drawing but leaves the new drawing unlinked.

Merge-round #867 completed the linked-text authorization, conflict and live refresh checks. Its readonly pointer guard and keyboard Open also passed after the probe waited for the real warm-tooltip exit. The User then opens the original owned Canvas, selects the linked rectangle through its stable element deep link, and activates Duplicate as new item from the real keyboard context menu.

The Notes API returns 200. It contains the original Sticky01 rectangle with its original /t/<id> link, the original bound label, and a new rectangle plus bound label whose links are null. No new rectangle gains a distinct Task link within the existing bounded poll. The exact test assertion remains.

Evidence: artifacts/merge-round-7c2/canvas-text-977-final-success.log at head e92fbdae7. The failing assertion is Duplicate links a new Task. The earlier pointer hit trace confirms CANVAS, excalidraw__canvas interactive, and Edit mode. Both retained and current upstream textarea prohibitions passed.

Relevant code: CanvasView.svelte action duplicate-item, CanvasReact.tsx duplicateLinked and itemLinks, and conversionApi.ts item creation. Determine whether item creation failed or its follow-up could not attach the link. Keep the original Task unchanged. Keep the duplicate accessible and offer recovery if the new item exists. Add a real production regression and distinct-identity checks. This round does not claim an orphaned item or data loss without that evidence.

Duplicate as new item copies a linked Task drawing but leaves the new drawing unlinked. Merge-round #867 completed the linked-text authorization, conflict and live refresh checks. Its readonly pointer guard and keyboard Open also passed after the probe waited for the real warm-tooltip exit. The User then opens the original owned Canvas, selects the linked rectangle through its stable element deep link, and activates `Duplicate as new item` from the real keyboard context menu. The Notes API returns 200. It contains the original `Sticky01` rectangle with its original `/t/<id>` link, the original bound label, and a new rectangle plus bound label whose links are null. No new rectangle gains a distinct Task link within the existing bounded poll. The exact test assertion remains. Evidence: `artifacts/merge-round-7c2/canvas-text-977-final-success.log` at head e92fbdae7. The failing assertion is `Duplicate links a new Task`. The earlier pointer hit trace confirms `CANVAS`, `excalidraw__canvas interactive`, and Edit mode. Both retained and current upstream textarea prohibitions passed. Relevant code: `CanvasView.svelte` action `duplicate-item`, `CanvasReact.tsx` `duplicateLinked` and `itemLinks`, and `conversionApi.ts` item creation. Determine whether item creation failed or its follow-up could not attach the link. Keep the original Task unchanged. Keep the duplicate accessible and offer recovery if the new item exists. Add a real production regression and distinct-identity checks. This round does not claim an orphaned item or data loss without that evidence.
Author
Owner

Starting #1075 repair on branch job/7cfix-small at base 357c856e3d. I will trace duplicate item creation and linking, add a regression, and keep this issue in its own commit series.

Starting #1075 repair on branch job/7cfix-small at base 357c856e3d2a26f8853781b15b51ad16fc561ced. I will trace duplicate item creation and linking, add a regression, and keep this issue in its own commit series.
Author
Owner

Finding: on the real production build, the duplicate shape and its bound text both persist with distinct stable IDs, while both links remain null; the original shape keeps its original Task link. The bounded 60-second Notes API poll failed on Duplicate links a new Task. This run does not establish whether the new Task record exists. I changed the duplicate path to use the inserted renderer scene as the canonical conversion snapshot and added a direct Open action if item creation succeeds but a concurrent drawing change prevents attachment. The regression now checks distinct drawing/Task IDs and both element backlinks.

Finding: on the real production build, the duplicate shape and its bound text both persist with distinct stable IDs, while both links remain null; the original shape keeps its original Task link. The bounded 60-second Notes API poll failed on `Duplicate links a new Task`. This run does not establish whether the new Task record exists. I changed the duplicate path to use the inserted renderer scene as the canonical conversion snapshot and added a direct Open action if item creation succeeds but a concurrent drawing change prevents attachment. The regression now checks distinct drawing/Task IDs and both element backlinks.
Author
Owner

Follow-up evidence for #1075: the production duplicate copy has a stable 8-character ID in conversion plans, while Excalidraw keeps the copied drawing under its source UUID until the shared event projection. itemLinks compared those different IDs, so it skipped the new shape after Task creation. The copied rectangle and bound label persisted with no link; the original Task remained intact. The fix matches via the stable portable scene projection, applies the link to the renderer element, and retains the title/body recheck against concurrent edits. A focused production regression is being added for both Task backlinks.

Follow-up evidence for #1075: the production duplicate copy has a stable 8-character ID in conversion plans, while Excalidraw keeps the copied drawing under its source UUID until the shared event projection. `itemLinks` compared those different IDs, so it skipped the new shape after Task creation. The copied rectangle and bound label persisted with no link; the original Task remained intact. The fix matches via the stable portable scene projection, applies the link to the renderer element, and retains the title/body recheck against concurrent edits. A focused production regression is being added for both Task backlinks.
Author
Owner

Finished #1075 on branch job/7cfix-small, based on 357c856e3.

The copied drawing uses a stable portable ID while Excalidraw retains its UUID internally. The link pass now matches through the portable scene projection and updates the original renderer element. It still compares the copied title and body after the asynchronous Task write, so a concurrent drawing edit cannot receive stale content. If an item was created but could not be linked, its toast offers Open created item alongside Undo.

The focused production test verifies distinct shape and bound-label IDs, a distinct Task, the new Task-to-drawing backlink, and retention of the original backlink. Files: apps/web/src/lib/canvas/CanvasReact.tsx, CanvasView.svelte, apps/web/e2e/canvas-duplicate-1075.mjs.

Validation output:

Test Files  2 passed (2)
Tests       17 passed (17)
Canvas duplicate: new Task, copied drawing and label, original and new backlinks, six macOS screenshots passed.

Screenshots attached:
390 light, 390 dark, 820 light, 820 dark, 1440 light, 1440 dark.

Decision: if a concurrent edit prevents safe linking, keep the created item directly reachable and preserve the drawing and original Task.

Head: 755fecd479.

Finished #1075 on branch job/7cfix-small, based on 357c856e3. The copied drawing uses a stable portable ID while Excalidraw retains its UUID internally. The link pass now matches through the portable scene projection and updates the original renderer element. It still compares the copied title and body after the asynchronous Task write, so a concurrent drawing edit cannot receive stale content. If an item was created but could not be linked, its toast offers Open created item alongside Undo. The focused production test verifies distinct shape and bound-label IDs, a distinct Task, the new Task-to-drawing backlink, and retention of the original backlink. Files: apps/web/src/lib/canvas/CanvasReact.tsx, CanvasView.svelte, apps/web/e2e/canvas-duplicate-1075.mjs. Validation output: ```text Test Files 2 passed (2) Tests 17 passed (17) Canvas duplicate: new Task, copied drawing and label, original and new backlinks, six macOS screenshots passed. ``` Screenshots attached: [390 light](https://git.kayg.org/attachments/4b889eec-5cb9-419a-8cec-8f259826a227), [390 dark](https://git.kayg.org/attachments/d2c17b67-54c8-44e0-b8e3-6b448ae1a8a9), [820 light](https://git.kayg.org/attachments/79689daa-d6a9-4082-98a7-c4d7f8ccbe0f), [820 dark](https://git.kayg.org/attachments/feab27c8-9fba-4c49-8af5-29944f2ab5e2), [1440 light](https://git.kayg.org/attachments/4d2fedb6-97b7-46ba-a685-2f48134c6bbd), [1440 dark](https://git.kayg.org/attachments/4ac39b3a-117b-49ba-a767-9f54153e78c2). Decision: if a concurrent edit prevents safe linking, keep the created item directly reachable and preserve the drawing and original Task. Head: 755fecd4795661327aa72a2232b17dacaef32ade.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#1075
No description provided.