Editor: pasting an image from iOS (Telegram) creates an Image not available block #1036

Open
opened 2026-10-04 06:23:49 +00:00 by kayg · 13 comments
Owner

Owner report (2026-10-04, iOS Safari)

"I copied an image from Telegram on iOS and when I pasted it in a note, an image block spawned but it said 'Image not available'."

Expected

Pasting an image (from any app: iOS share sheet/clipboard, macOS screenshots, browser images, Telegram/WhatsApp) uploads it as a Home file (files over app: next to the note or the attachments rule) and inserts a working image block that renders immediately (optimistic local preview while uploading, then the real file). Failure → a clear inline error with Retry, never a dead "Image not available" block.

Likely causes to check

iOS clipboard gives an image as a Blob/File with type image/jpeg or image/heic and sometimes an empty name or a blob: URL / webkit-fake-url:// src in pasted HTML; the editor may insert the HTML instead of uploading the clipboard File; HEIC may not be accepted; the upload may not attach the resulting item ID to the block.

Verification

Unit tests for the paste handler with File, Blob without name, HEIC, HTML-with-img-only, and mixed text+image clipboards; e2e on WebKit (Playwright webkit with iPhone emulation) pasting an image and seeing it render after reload; real check on the iPad/iPhone simulator via the Mac VM if the macvm.lock is free.

## Owner report (2026-10-04, iOS Safari) "I copied an image from Telegram on iOS and when I pasted it in a note, an image block spawned but it said 'Image not available'." ## Expected Pasting an image (from any app: iOS share sheet/clipboard, macOS screenshots, browser images, Telegram/WhatsApp) uploads it as a Home file (files over app: next to the note or the attachments rule) and inserts a working image block that renders immediately (optimistic local preview while uploading, then the real file). Failure → a clear inline error with Retry, never a dead "Image not available" block. ## Likely causes to check iOS clipboard gives an image as a Blob/File with type image/jpeg or image/heic and sometimes an empty name or a `blob:` URL / `webkit-fake-url://` src in pasted HTML; the editor may insert the HTML <img src> instead of uploading the clipboard File; HEIC may not be accepted; the upload may not attach the resulting item ID to the block. ## Verification Unit tests for the paste handler with File, Blob without name, HEIC, HTML-with-img-only, and mixed text+image clipboards; e2e on WebKit (Playwright webkit with iPhone emulation) pasting an image and seeing it render after reload; real check on the iPad/iPhone simulator via the Mac VM if the macvm.lock is free.
Author
Owner

Starting #1036 on branch job/paste-1036, based on 85294fc72c (origin/dev).

Starting #1036 on branch job/paste-1036, based on 85294fc72cf76a707ef30b2ba38d9c9da75afc57 (origin/dev).
Author
Owner

Finding: packages/editor/src/attachmentPaste.ts intercepts image File pastes only when onFiles is set, but apps/web/src/lib/notes/NoteEditorSurface.svelte calls liveNoteExtensions without onImageFiles. The clipboard image therefore falls through to HTML parsing, where an iOS temporary URL can become a persisted image source. I will wire this to the shared Home upload queue and keep pending/retry UI outside the Markdown document.

Finding: packages/editor/src/attachmentPaste.ts intercepts image File pastes only when onFiles is set, but apps/web/src/lib/notes/NoteEditorSurface.svelte calls liveNoteExtensions without onImageFiles. The clipboard image therefore falls through to HTML parsing, where an iOS temporary URL can become a persisted image source. I will wire this to the shared Home upload queue and keep pending/retry UI outside the Markdown document.
Author
Owner

Implementation committed as b3eda71a1. Notes now consume clipboard image bytes before HTML parsing, preserve mixed text, and keep temporary clipboard URLs out of the saved Markdown. Image bytes use the shared Home upload queue and stay in a local pending/retry state until upload succeeds. The editor and web checks pass; the iPhone-profile WebKit end-to-end run and screenshots are in progress.

I checked the free Mac VM lock. The VM has no Xcode simctl utility (xcrun: error: unable to find utility "simctl"), so an iOS Simulator run is unavailable. The focused run uses Playwright WebKit with its iPhone 13 profile.

Implementation committed as b3eda71a1. Notes now consume clipboard image bytes before HTML parsing, preserve mixed text, and keep temporary clipboard URLs out of the saved Markdown. Image bytes use the shared Home upload queue and stay in a local pending/retry state until upload succeeds. The editor and web checks pass; the iPhone-profile WebKit end-to-end run and screenshots are in progress. I checked the free Mac VM lock. The VM has no Xcode `simctl` utility (`xcrun: error: unable to find utility "simctl"`), so an iOS Simulator run is unavailable. The focused run uses Playwright WebKit with its iPhone 13 profile.
Author
Owner

Finding: the first iPhone-profile WebKit run consumed the clipboard but omitted the caption. EditorView.pasteHTML() calls handlePaste again, so passing the original DataTransfer re-entered the image handler. The editor test now checks that sanitized rich text is handed back without that event; all 11 focused editor tests pass after the fix. I am rebuilding the web app and will rerun the WebKit flow.

Finding: the first iPhone-profile WebKit run consumed the clipboard but omitted the caption. `EditorView.pasteHTML()` calls `handlePaste` again, so passing the original DataTransfer re-entered the image handler. The editor test now checks that sanitized rich text is handed back without that event; all 11 focused editor tests pass after the fix. I am rebuilding the web app and will rerun the WebKit flow.
Author
Owner

Finished — #1036

Built: iOS-style clipboard image paste in Notes now uploads real clipboard image bytes through the shared Home upload queue. It keeps mixed text, removes temporary HTML image elements, shows local pending previews outside Markdown, and replaces each preview with a Home file reference after upload. Failures remain inline with a Retry action; the retry uses the same queued image. Safari's items-only clipboard, nameless images, HEIC, data URLs, and readable HTML image URLs are handled. Browser-unsupported stored images can use the server preview.

Files:

  • packages/editor/src/attachmentPaste.ts, attachmentPaste.test.ts, extensions.ts, image.ts, index.ts
  • apps/web/src/lib/notes/imagePaste.ts, imagePaste.test.ts, NoteEditorSurface.svelte, NoteImageView.svelte, editorHost.ts, editor-types/attachmentPaste.d.ts, editor-types/image.d.ts, editor-types/index.d.ts
  • apps/web/e2e/paste-1036.mjs, apps/web/package.json, bench/paste-1036.mjs

Head: 6a38ccf8b4e3c52889f99bafd938ee6dc5a63ce9 (Exercise retryable image paste failures on WebKit). The branch includes the one required merge from origin/dev (96645f925). Worktree is clean. Build output was cleaned with cargo clean; apps/web/build and apps/web/.svelte-kit were removed.

Gate output

cargo fmt --check completed with no output (exit 0).

cargo build -p calternal-server:

Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 05s

packages/editor focused test: 1 file, 11 tests passed. packages/editor check: svelte-check found 0 errors and 0 warnings.

apps/web focused test: 1 file, 3 tests passed. apps/web check: storage/type/motion guards passed; svelte-check found 0 errors and 0 warnings.

Production build completed:

✓ built in 28.10s
Wrote site to "build"
✔ done

Focused WebKit run, production app with iPhone 13 emulation and Mac platform screenshot contexts:

$ bunx --silent --package=playwright@1.63.0 playwright --version && bun e2e/paste-1036.mjs
Version 1.63.0
CSP REPORTS paste-1036: 0 across 1 pages
WEBKIT PASTE PASSED (iPhone 13)
SAVED MARKDOWN 
# Telegram image paste

The copied photo belongs below.

**Copied from Telegram**


![Telegram-photo.png](<../Photos/2026/2026-10-04/Telegram-photo.png>)

SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/phone-390-light.png
SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/phone-390-dark.png
SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/tablet-820-light.png
SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/tablet-820-dark.png
SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/desktop-1440-light.png
SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/desktop-1440-dark.png
PASTE-1036 E2E PASSED

The e2e injected two upload failures and verified touch and keyboard Retry, the 44 px target, saved Markdown without temporary URLs, and a loaded image after reload. No Rust source changed, so Rust clippy/tests were not run. The full web/editor suites and full e2e/adversarial matrices remain for the merge round under the shared verification policy. The new bench/paste-1036.mjs profile was not measured because this is not a performance issue.

Screenshots (WebKit, Mac platform emulation; 390, 820 and 1440 px, light and dark):

UX gaps closed

  • Mixed clipboard text stays in the Note while temporary <img> elements are removed.
  • Preview, upload failure and Retry stay out of saved Note content; uploaded files render after reload.
  • Retry works by touch and keyboard and uses an accessible 44 px target.
  • Unsupported browser image formats get a server-preview fallback and inline retry state.

UX gaps left / known gaps

  • The Mac VM had no simctl utility, so the requested iPhone/iPad Simulator check could not run. The issue's WebKit iPhone emulation passed.
  • If a clipboard supplies only an opaque temporary URL and no image bytes or readable image URL, the app cannot recover the image. It shows the inline Retry state and does not save a broken block; paste again after copying the image.
  • Full suites, full e2e and adversarial matrices were not run in this branch job; the merge round owns them.
  • The production build emitted existing vendor use client directive warnings and completed successfully.

Decisions not specified in DESIGN

  • Keep pending uploads as ProseMirror decorations in the Notes host, then write a normal relative Home file reference only after upload succeeds. This prevents transient blob or iOS clipboard URLs from entering Markdown.
  • Fetch HTML image URLs only when they resolve to actual image bytes (same-origin or CORS-readable); reject fake schemes into the inline retry state.
  • Reuse the shared upload queue's screenshot purpose for pasted images and serialize insertion completion in clipboard order.

For the merge round: run cd packages/editor && bun run test and cd apps/web && bun run test for full Vitest coverage; run the standard full e2e and adversarial matrices on the combined branch.

## Finished — #1036 **Built:** iOS-style clipboard image paste in Notes now uploads real clipboard image bytes through the shared Home upload queue. It keeps mixed text, removes temporary HTML image elements, shows local pending previews outside Markdown, and replaces each preview with a Home file reference after upload. Failures remain inline with a Retry action; the retry uses the same queued image. Safari's items-only clipboard, nameless images, HEIC, data URLs, and readable HTML image URLs are handled. Browser-unsupported stored images can use the server preview. **Files:** - `packages/editor/src/attachmentPaste.ts`, `attachmentPaste.test.ts`, `extensions.ts`, `image.ts`, `index.ts` - `apps/web/src/lib/notes/imagePaste.ts`, `imagePaste.test.ts`, `NoteEditorSurface.svelte`, `NoteImageView.svelte`, `editorHost.ts`, `editor-types/attachmentPaste.d.ts`, `editor-types/image.d.ts`, `editor-types/index.d.ts` - `apps/web/e2e/paste-1036.mjs`, `apps/web/package.json`, `bench/paste-1036.mjs` **Head:** `6a38ccf8b4e3c52889f99bafd938ee6dc5a63ce9` (`Exercise retryable image paste failures on WebKit`). The branch includes the one required merge from `origin/dev` (`96645f925`). Worktree is clean. Build output was cleaned with `cargo clean`; `apps/web/build` and `apps/web/.svelte-kit` were removed. ### Gate output `cargo fmt --check` completed with no output (exit 0). `cargo build -p calternal-server`: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 05s ``` `packages/editor` focused test: 1 file, 11 tests passed. `packages/editor` check: `svelte-check found 0 errors and 0 warnings`. `apps/web` focused test: 1 file, 3 tests passed. `apps/web` check: storage/type/motion guards passed; `svelte-check found 0 errors and 0 warnings`. Production build completed: ```text ✓ built in 28.10s Wrote site to "build" ✔ done ``` Focused WebKit run, production app with iPhone 13 emulation and Mac platform screenshot contexts: ```text $ bunx --silent --package=playwright@1.63.0 playwright --version && bun e2e/paste-1036.mjs Version 1.63.0 CSP REPORTS paste-1036: 0 across 1 pages WEBKIT PASTE PASSED (iPhone 13) SAVED MARKDOWN # Telegram image paste The copied photo belongs below. **Copied from Telegram** ![Telegram-photo.png](<../Photos/2026/2026-10-04/Telegram-photo.png>) SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/phone-390-light.png SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/phone-390-dark.png SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/tablet-820-light.png SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/tablet-820-dark.png SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/desktop-1440-light.png SCREENSHOT /home/kayg/Developer/calternal-wt/paste-1036/artifacts/paste-1036/desktop-1440-dark.png PASTE-1036 E2E PASSED ``` The e2e injected two upload failures and verified touch and keyboard Retry, the 44 px target, saved Markdown without temporary URLs, and a loaded image after reload. No Rust source changed, so Rust clippy/tests were not run. The full web/editor suites and full e2e/adversarial matrices remain for the merge round under the shared verification policy. The new `bench/paste-1036.mjs` profile was not measured because this is not a performance issue. **Screenshots (WebKit, Mac platform emulation; 390, 820 and 1440 px, light and dark):** - [Phone, light](https://git.kayg.org/attachments/5ca62b86-1db2-4780-b945-d5bd4b329d20) · [Phone, dark](https://git.kayg.org/attachments/4c81c136-af39-41ec-a8d9-c74ca6912cf4) - [Tablet, light](https://git.kayg.org/attachments/ae5503a0-2072-48fc-98da-b07577109bf7) · [Tablet, dark](https://git.kayg.org/attachments/31034e67-04e2-4293-b8d2-5a93443cafd9) - [Desktop, light](https://git.kayg.org/attachments/3be60c92-97a2-4add-ae61-c9fb9fc4542c) · [Desktop, dark](https://git.kayg.org/attachments/7de8ceb6-8ab5-4512-83f9-0b6a3857e43d) ### UX gaps closed - Mixed clipboard text stays in the Note while temporary `<img>` elements are removed. - Preview, upload failure and Retry stay out of saved Note content; uploaded files render after reload. - Retry works by touch and keyboard and uses an accessible 44 px target. - Unsupported browser image formats get a server-preview fallback and inline retry state. ### UX gaps left / known gaps - The Mac VM had no `simctl` utility, so the requested iPhone/iPad Simulator check could not run. The issue's WebKit iPhone emulation passed. - If a clipboard supplies only an opaque temporary URL and no image bytes or readable image URL, the app cannot recover the image. It shows the inline Retry state and does not save a broken block; paste again after copying the image. - Full suites, full e2e and adversarial matrices were not run in this branch job; the merge round owns them. - The production build emitted existing vendor `use client` directive warnings and completed successfully. ### Decisions not specified in DESIGN - Keep pending uploads as ProseMirror decorations in the Notes host, then write a normal relative Home file reference only after upload succeeds. This prevents transient blob or iOS clipboard URLs from entering Markdown. - Fetch HTML image URLs only when they resolve to actual image bytes (same-origin or CORS-readable); reject fake schemes into the inline retry state. - Reuse the shared upload queue's `screenshot` purpose for pasted images and serialize insertion completion in clipboard order. **For the merge round:** run `cd packages/editor && bun run test` and `cd apps/web && bun run test` for full Vitest coverage; run the standard full e2e and adversarial matrices on the combined branch.
Author
Owner

Approved from the screenshots (pasted image renders at 390/820/1440 px, light and dark; WebKit e2e with retry passes). Ships in small round 5 together with the Settings sidebar fix (#1039/#1040). Real iPhone + Telegram check by the owner after deploy.

Approved from the screenshots (pasted image renders at 390/820/1440 px, light and dark; WebKit e2e with retry passes). Ships in small round 5 together with the Settings sidebar fix (#1039/#1040). Real iPhone + Telegram check by the owner after deploy.
Author
Owner

Starting merge-round send-back fix on job/paste-1036, based on origin/dev at 6074f71d18abe73b2b4255acb564f275a9acc851.

I am tracing the collaborative history failure at the rich paste boundary. Existing assertions will remain unchanged.

Starting merge-round send-back fix on `job/paste-1036`, based on `origin/dev` at `6074f71d18abe73b2b4255acb564f275a9acc851`. I am tracing the collaborative history failure at the rich paste boundary. Existing assertions will remain unchanged.
Author
Owner

Finding: the mounted regression fails before the paste handler can call preventDefault. collectImageFiles() calls Array.from(dt.files) and then Array.from(dt.items) without guarding either collection. The rich-paste transfer used by the unchanged collaborative history test provides getData() but omits both collections, which throws TypeError: undefined is not iterable at packages/editor/src/attachmentPaste.ts:164. The captured failure is the mounted editor must handle rich paste: expected false to be true.

Finding: the mounted regression fails before the paste handler can call `preventDefault`. `collectImageFiles()` calls `Array.from(dt.files)` and then `Array.from(dt.items)` without guarding either collection. The rich-paste transfer used by the unchanged collaborative history test provides `getData()` but omits both collections, which throws `TypeError: undefined is not iterable` at `packages/editor/src/attachmentPaste.ts:164`. The captured failure is `the mounted editor must handle rich paste: expected false to be true`.
Author
Owner

Finding: after preventing the clipboard collection exception, the same unchanged history test reached its next assertion and found zero image nodes. The sanitizer had removed the valid HTTPS <img> before ProseMirror could include it in the rich-paste transaction. It also surfaced a JSDOM gap: EditorView.pasteHTML() creates a global ClipboardEvent, which JSDOM does not provide.

Fix: keep safe HTTP(S) image nodes in the synchronous rich paste, pass only a clipboard-free replay event to ProseMirror, and update the existing image node after upload with addToHistory: false. The 500-step mounted collaboration test now passes unchanged; pending upload/error state remains a ProseMirror decoration outside Yjs history.

Finding: after preventing the clipboard collection exception, the same unchanged history test reached its next assertion and found zero image nodes. The sanitizer had removed the valid HTTPS `<img>` before ProseMirror could include it in the rich-paste transaction. It also surfaced a JSDOM gap: `EditorView.pasteHTML()` creates a global `ClipboardEvent`, which JSDOM does not provide. Fix: keep safe HTTP(S) image nodes in the synchronous rich paste, pass only a clipboard-free replay event to ProseMirror, and update the existing image node after upload with `addToHistory: false`. The 500-step mounted collaboration test now passes unchanged; pending upload/error state remains a ProseMirror decoration outside Yjs history.
Author
Owner

Finished on job/paste-1036 at head b01dc7ddce2f250e602c059e70c6f1f28ed6aaa1.

Built

  • Rich image paste consumes the clipboard event synchronously even when files or items is missing.
  • Safe HTTP(S) image nodes remain in the one rich-paste document transaction. Their Home source is updated after upload without adding another Yjs Undo step.
  • Temporary clipboard URLs remain outside Note Markdown while upload and retry state live in ProseMirror decorations.
  • Added the missing-collections regression test. Existing collaborative storm assertions are unchanged.

Files: packages/editor/src/attachmentPaste.ts, packages/editor/src/attachmentPaste.test.ts, apps/web/src/lib/notes/NoteEditorSurface.svelte, apps/web/src/lib/notes/imagePaste.ts, and apps/web/src/lib/notes/editor-types/attachmentPaste.d.ts.

Decisions

  • DESIGN §9 does not specify how a rich HTML image without clipboard bytes joins asynchronous upload. Keep absolute HTTP(S) nodes in the original paste transaction, upload them in the background, then update only src with addToHistory: false. The mounted Note keeps one paste Undo step.
  • Treat absent clipboard file collections as empty. ProseMirror still handles safe rich content synchronously.

UX gaps closed

  • Rich mixed paste no longer crashes or drops the image from collaborative history.
  • Temporary image URLs do not enter Markdown. Pending upload and Retry remain outside Yjs history.

UX gaps left / For the merge round

  • Run bun run test:e2e:paste-1036 in apps/web to prove iPhone WebKit consumes the paste, preserves mixed text, retries upload failure, uploads to Home, and renders after reload. Run the real iOS Safari/macOS check per the Mac VM procedure if available; this job did not run browser or Mac interop checks.
  • origin/dev advanced from 6074f71d to d0fc1f463 at 11:33:21 +0200 while the full web suite was running. The required one-time fetch/merge had completed before the gates; I did not repeat it. The merge round should include current origin/dev and run its combined gates. Current branch status is ahead 8, behind 10.

Gates

apps/web: bun run check

$ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
User browser caches use userStorage; only documented device/public-link exceptions remain.
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/paste-1036/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

packages/editor: bun run check

$ bun run typecheck
$ svelte-check --tsconfig ./tsconfig.json
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/paste-1036/packages/editor
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

packages/editor: bun run test --maxWorkers=2

$ vitest run --config ./vitest.config.ts "--maxWorkers=2"

 RUN  v4.1.11 /home/kayg/Developer/calternal-wt/paste-1036/packages/editor

 Test Files  18 passed (18)
      Tests  410 passed (410)
   Start at  11:31:13
   Duration  36.27s (transform 6.24s, setup 725ms, import 15.40s, tests 17.50s, environment 31.10s)

apps/web: bun run test --maxWorkers=2

$ vitest run "--maxWorkers=2"

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/paste-1036/apps/web

 Test Files  160 passed (160)
      Tests  1117 passed (1117)
   Start at  11:31:56
   Duration  208.55s (transform 28%, environment 26%, import 23%, tests 16%, setup 6%)

Environment  |component| jsdom was created 53 times · 81.48s total, 34% of tracked time,  

cargo clean: Removed 1 file, 356B total. No Rust code changed, so no Rust gates were needed. Generated web output was deleted. No screenshots or build artifacts were committed.

READY FOR MERGE: yes; merge round should include the latest origin/dev noted above.

Finished on `job/paste-1036` at head `b01dc7ddce2f250e602c059e70c6f1f28ed6aaa1`. ## Built - Rich image paste consumes the clipboard event synchronously even when `files` or `items` is missing. - Safe HTTP(S) image nodes remain in the one rich-paste document transaction. Their Home source is updated after upload without adding another Yjs Undo step. - Temporary clipboard URLs remain outside Note Markdown while upload and retry state live in ProseMirror decorations. - Added the missing-collections regression test. Existing collaborative storm assertions are unchanged. Files: `packages/editor/src/attachmentPaste.ts`, `packages/editor/src/attachmentPaste.test.ts`, `apps/web/src/lib/notes/NoteEditorSurface.svelte`, `apps/web/src/lib/notes/imagePaste.ts`, and `apps/web/src/lib/notes/editor-types/attachmentPaste.d.ts`. ## Decisions - DESIGN §9 does not specify how a rich HTML image without clipboard bytes joins asynchronous upload. Keep absolute HTTP(S) nodes in the original paste transaction, upload them in the background, then update only `src` with `addToHistory: false`. The mounted Note keeps one paste Undo step. - Treat absent clipboard file collections as empty. ProseMirror still handles safe rich content synchronously. ## UX gaps closed - Rich mixed paste no longer crashes or drops the image from collaborative history. - Temporary image URLs do not enter Markdown. Pending upload and Retry remain outside Yjs history. ## UX gaps left / For the merge round - Run `bun run test:e2e:paste-1036` in `apps/web` to prove iPhone WebKit consumes the paste, preserves mixed text, retries upload failure, uploads to Home, and renders after reload. Run the real iOS Safari/macOS check per the Mac VM procedure if available; this job did not run browser or Mac interop checks. - `origin/dev` advanced from `6074f71d` to `d0fc1f463` at 11:33:21 +0200 while the full web suite was running. The required one-time fetch/merge had completed before the gates; I did not repeat it. The merge round should include current `origin/dev` and run its combined gates. Current branch status is ahead 8, behind 10. ## Gates `apps/web: bun run check` ```text $ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/paste-1036/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `packages/editor: bun run check` ```text $ bun run typecheck $ svelte-check --tsconfig ./tsconfig.json Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/paste-1036/packages/editor Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `packages/editor: bun run test --maxWorkers=2` ```text $ vitest run --config ./vitest.config.ts "--maxWorkers=2" RUN v4.1.11 /home/kayg/Developer/calternal-wt/paste-1036/packages/editor Test Files 18 passed (18) Tests 410 passed (410) Start at 11:31:13 Duration 36.27s (transform 6.24s, setup 725ms, import 15.40s, tests 17.50s, environment 31.10s) ``` `apps/web: bun run test --maxWorkers=2` ```text $ vitest run "--maxWorkers=2" RUN v5.0.1 /home/kayg/Developer/calternal-wt/paste-1036/apps/web Test Files 160 passed (160) Tests 1117 passed (1117) Start at 11:31:56 Duration 208.55s (transform 28%, environment 26%, import 23%, tests 16%, setup 6%) Environment |component| jsdom was created 53 times · 81.48s total, 34% of tracked time, ``` `cargo clean`: `Removed 1 file, 356B total`. No Rust code changed, so no Rust gates were needed. Generated web output was deleted. No screenshots or build artifacts were committed. READY FOR MERGE: yes; merge round should include the latest `origin/dev` noted above.
Author
Owner

Correction to the apps/web: bun run test --maxWorkers=2 transcript above. Its final diagnostic lines were:

Environment  |component| jsdom was created 53 times · 81.48s total, 34% of tracked time
             create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files)
             learn more: https://vitest.dev/guide/improving-performance#test-environments
Correction to the `apps/web: bun run test --maxWorkers=2` transcript above. Its final diagnostic lines were: ```text Environment |component| jsdom was created 53 times · 81.48s total, 34% of tracked time create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files) learn more: https://vitest.dev/guide/improving-performance#test-environments ```
Author
Owner

Final head update: 42ca0a35e019ac3c4df1f252fd11126f005c4315. After the full gates, I clarified one source comment to state that HTTP(S) HTML images are retained only when clipboard file bytes are absent. The focused editor paste test passed afterward: Test Files 1 passed (1) and Tests 12 passed (12). Worktree is clean; current branch status is ahead 9, behind 10 from the origin/dev update recorded above.

Final head update: `42ca0a35e019ac3c4df1f252fd11126f005c4315`. After the full gates, I clarified one source comment to state that HTTP(S) HTML images are retained only when clipboard file bytes are absent. The focused editor paste test passed afterward: `Test Files 1 passed (1)` and `Tests 12 passed (12)`. Worktree is clean; current branch status is ahead 9, behind 10 from the `origin/dev` update recorded above.
Author
Owner

Deployed to production (2026-10-04, small round 6 = c39ffe5d9)

Round: dev d0fc1f463 + job/setside-1039 + job/paste-1036 (web only). Gates on the round: web check COMPLETED 2005 FILES 0 ERRORS 0 WARNINGS, web tests Tests 1118 passed (1118), editor tests Tests 410 passed (410), PASTE-1036 E2E PASSED (WebKit, 390/820/1440 light/dark, image saved as a Home file and rendered after reload). Staging healthy first.

## Deployed to production (2026-10-04, small round 6 = c39ffe5d9) Round: dev d0fc1f463 + job/setside-1039 + job/paste-1036 (web only). Gates on the round: web check `COMPLETED 2005 FILES 0 ERRORS 0 WARNINGS`, web tests `Tests 1118 passed (1118)`, editor tests `Tests 410 passed (410)`, `PASTE-1036 E2E PASSED` (WebKit, 390/820/1440 light/dark, image saved as a Home file and rendered after reload). Staging healthy first.
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#1036
No description provided.