# Final evidence — image paste feedback

[PR #23832](https://git.cafe/pingdotgg/t3code/pulls/23832), [GitHub #23832](https://github.com/pingdotgg/t3code/pull/23832). Frozen head [3b5b338](https://github.com/pingdotgg/t3code/commit/3b5b33831afbfd8ae4eb875f097dc26bac4743bc); baseline [23bd753](https://github.com/pingdotgg/t3code/commit/23bd753806eb9db5a315fbf9ac6563d355f20b3a).

This is a real loopback web-client pass against the parent-owned server, synthetic fixture project and isolated `/tmp/ev-23832/home-after`. No production home/database was read, copied, seeded, or opened. No provider work, auth changes, other machines, uploads to a forge, forge comments, or commits. All repository shell calls used explicit cwd `/home/ubuntu/wt/pr-23832`.

## Evidence map

- `head-3b5b338-{1440,390}/` and `baseline-23bd753-{1440,390}/`: idle, preparing, ready, natural-ready stills; original natural and barrier X11 videos; frame observations; source/served/browser provenance.
- `diffs/{1440,390}/{idle,preparing,ready}/`: before, after, raw per-channel absolute difference and 50/50 blend with magenta changed-pixel boundary (luminance difference >16). No crop, alignment transformation, broad mask or difference amplification. All six pairs have both required diff images.
- `head-3b5b338-matrix/`, `baseline-23bd753-matrix/`: original X11 interaction recordings, timestamped observations and row screenshots. `narration.md` ties checkpoints to `ffprobe` durations. `video-manifest.json` retains probes and hashes; `artifact-manifest.json` indexes final evidence.
- `input-manifest.json`: original deterministic input SHA256/bytes. `one.png` 3200×2000, `retina.png` 5120×3200, tiny fixtures 48×48; malformed bad.png is >10MiB invalid PNG. Original files live under `inputs/`.

## Matrix

Rows described as observed are backed by both state snapshots and owned ffmpeg x11grab recordings, not snapshots alone. Preparation readiness means Preview exists and is **enabled**. It never means upload completion or send acceptance.

| Row | Baseline observation | Final head observation / limits |
| --- | --- | --- |
| One image | No tile while encode result held; one valid tile after release. | One source tile before release; existing text retained, ordinary inline-reference insertion after readiness. Same thumbnail `<img>` node survives the swap (`sameImageNode: true`). Source decode initially displays filename fallback; no filename flash after thumbnail has decoded or during ready swap. Selected-range run preserves text; does not claim native clipboard selection integration. `part-0`. |
| Several / overlap | Earlier batch appears only on completion; separately pasted tiny image can finish first. | Three first-batch sources visible while held; second tiny paste accepted independently; all four resolve once. Ready tiles precede pending tiles, so later tiny-002 moves ahead of earlier pending batch; eventual order is tiny-002, one, retina, tiny-001 on both revisions. No cross-batch loss/duplication. `part-0`. |
| Slow large screenshot | Empty visual gap during preparation, eventual valid image. | Natural run separate from bounded hold; source tile stays through blur. Frame observations show no disappearance/DOM replacement once tile appears. Separate recorded editing/blur/scroll-attempt and compressed-preview check in `part-9`; no populated timeline scroll or GPU/performance claim. |
| Attachment limit | 99 visible while last slot reserved; rejects extras; 100 after release. | 100 visible including preparing slot; rejected retina and later tiny do not add tiles; capacity error remains after success. 100-ready extra paste rejected. Removal frees capacity; retry produces one tile. `part-3`. |
| Send during preparation | Button and Enter reach existing compression guard; prompt retained. | Real **Submit message** button click and Enter each show “Still compressing a pasted image”; image/text retained and route stays draft. Guard observed, not a persisted-command proof. **Post-release accepted-message row UNVERIFIED**: no provider turn initiated, no accepted message/receipt asserted. Existing stopped-thread send path also unverified. `part-1`. |
| Cancel/remove | No preparing removal control; ready tile can be removed. | Preparing removal before release prevents resurrection; retry works. Ready removal uses product Confirm when referenced. `part-1`. No discard-all-draft cancellation claim. |
| Failure / race | >10MiB malformed PNG fails; good sibling and retry survive. | Bad temporary tile clears, good sibling survives, readable failure appears, retry succeeds. Additional recorded native-decode failure while good sibling is held: remove failed bad tile, trigger newer unsupported-SVG validation error, release sibling; newer error remains and canceled failure is not reported (`newerErrorPreserved`, `cancelledFailureNotReported` true). No artificial rejection needed; only native encode-result hold. `part-2`, head-only `part-6` (baseline has no preparing removal). |
| Non-image paste | Ordinary text, HTML/plain text, .txt intake retained; no image placeholders. | Same observed content policy, no ghost image. >32KiB (45,000 characters) folds to pasted-text.txt; synthetic Ctrl+Shift+V keydown + paste keeps it inline. `part-4` covers 17,500-character below-threshold input; `part-8` is actual above-threshold/literal coverage. Native OS clipboard shortcut unverified. |
| Draft navigation | New draft A/B scoped completion (recorded follow-up). | New draft A held, real New thread UI creates B; B text/image independent, return to A has its own text and exactly one ready image. `part-7`. Existing stopped-thread A, switching back before release, reload durability, B-send acceptance unverified. |
| Shared intake | Picker/drop use same eventual intake. | Actual file input (`setInputFiles`) and synthetic DragEvent/DataTransfer through editor drop handler show same source tile and ready cleanup. `part-5`. Pending-question attachment/answer path unverified. |

## Disclosure and controls

Clipboard input is a synthetic `ClipboardEvent`/`DataTransfer` dispatched to the focused real editor using bytes from the input fixtures. No draft-store mutation, fake UI, forged upload state, or fabricated accepted message. The attachment picker uses the real file input. Drag/drop and literal-paste keydown are synthetic events through product handlers.

The barrier calls **native** `OffscreenCanvas.convertToBlob`, then holds delivery of results only for canvas width >=1000, automatically releasing each result within <=3s; width256 source thumbnails are unheld. Runs may use more than one native encode. Native results are unchanged; no timer/UI/progress mutation. Natural recordings use no barrier and make no speed claim. Browser observation uses animation-frame sampling for evidence, not product animation or a test wait.

Head frame samples at both widths: zero tile disappearances after first tile, zero image-node replacements; initial filename fallback ends before first decoded thumbnail (about 0.29–0.48s in these captures). Those observed intervals are diagnostic, not a latency guarantee. No subsequent filename fallback during preparation→ready. This corrects any overbroad “no filename ever” claim.

New drafts in this fixture do not establish completed server upload. Preparing tile can show **0%**, and enabled Preview indicates compression/local image readiness. A ready-stage upload warning/progress gap may remain in the draft. No “upload complete” or “message accepted” conclusion follows from these screenshots.

## What else changed

Inspected raw idle/ready/preparing pairs plus highlighted overlays:

- Intended preparing change: source tile and remove control, composer grows by tile row, centered new-thread heading/composer content shift accordingly. At 390px there is no horizontal overflow introduced by the one-tile case. Blur leaves it expanded.
- Idle 1440: 30 pixels above diff threshold, entirely the unrelated server thread’s elapsed-minute label. Idle 390: zero pixels above threshold. Composer text, controls, background, right panel and layout otherwise match.
- Ready 1440: 27 pixels above threshold, elapsed-minute label plus a few thumbnail pixels. Ready 390: four threshold pixels in the thumbnail. The head inherits a thumbnail from the source while baseline derives it later; no different final layout/spacing/text/inline chip/send control observed. Raw absolute diffs retain lower-valued thumbnail changes; the threshold is only for overlay outlining.
- Theme/contrast and image crop visually match. No leftover placeholder in recorded ready/removal/failure/navigation states. No timing/GPU claim. Error states change intentionally for canceled failures; newer error preservation recorded.
- Overlapping batch visual order is completion-based (ready before pending), disclosed above. No claim of stable original acceptance order across overlapping pastes.

## Boundaries

1440×1000 CSS light and 390×844 CSS dark, DPR1, same owned headed Chromium/Xvfb. Narrow run is **responsive web**, not native mobile. Electron shell/native clipboard, all native mobile, remote/relay/tunnel, provider adapters, pending questions, accepted post-release sends, and coherent existing-thread navigation remain unverified. Settings/palette/keybinding feature entrypoints do not introduce image intake here; literal-paste shortcut was exercised synthetically. Shared intake picker/drop were included.

Old `head-1440/`, old-head trial responses and PAUSED.md are historical/provisional; they are **not final evidence**. Final directories always include `head-3b5b338` or `baseline-23bd753`.

## Rebuild and handoff

The existing driver remains at `127.0.0.1:18089`; no new browser or server is needed. Auditor may run:

```sh
python3 /tmp/ev-23832/rebuild-one.py --rebuild-one --sha 3b5b33831afbfd8ae4eb875f097dc26bac4743bc --width 1440 --output-tag audit-1
```

Run with explicit cwd `/home/ubuntu/wt/pr-23832`. Use width390 for dark responsive web. `--output-tag` preserves final captures by writing a new directory. The script requires clean frozen HEAD, uses Settings UI for theme, records both unheld and bounded runs, removes its pasted image afterward, and records file/served/browser provenance. It does not swap source or start/stop a server. Preview readiness checks the actual button's enabled property; a trial click can be intercepted by the remove overlay at390px, and mere existence is insufficient.

Matrix replays: `run-part.py <new-evidence-prefix> <0..9>` with the same live driver, current real fixture draft active, and helpers in this directory. Part6 requires head (preparing cancellation); baseline has no such control. Part7 creates a separate synthetic new draft through UI. No draft-store writes. `swap.py` is an explicit serialized eight-file source swap used for this pass, not needed for one-head auditor capture. Never run concurrent driver requests or source swaps.

Owned persistent processes retained for the parent: driver837734, Xvfb837976, Chromium837983. Parent server831670 at15441 and web830168 at7401 were never started or stopped by this task. Parent owns teardown. See `final-state.json` for final checks. Browser is left about:blank; native encode wrappers are restored; no recorder remains running.
