Skip to content

Add first-class local-first image attachments - #79

Merged
callumalpass merged 4 commits into
mainfrom
agent/first-class-attachments
Aug 2, 2026
Merged

Add first-class local-first image attachments#79
callumalpass merged 4 commits into
mainfrom
agent/first-class-attachments

Conversation

@callumalpass

@callumalpass callumalpass commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Outcome

Adds first-class image attachments across native Android/iOS and mdbase collections. Browser product builds remain cloud-only; OPFS exists only in the E2E fixture.

Task frontmatter is the portable source of truth for membership:

attachments:
  - "[[Attachments/receipt.jpg]]"

Binary metadata stays in storage descriptors/the filesystem. Body embeds are optional presentation, with distinct Attach image and Insert in Notes actions.

Local-first behavior

  • Stages and verifies native bytes before publishing membership; Android SAF preserves the final image MIME and Android/iOS bridges refuse existing destinations.
  • Native file stores do not advertise or support replacement until it can be committed portably and atomically.
  • Stores mdbase bytes in IndexedDB first, journals remote mutations, recovers uploads after interruption, and invalidates cached bytes when the authority reports a new digest.
  • Includes file descriptors and bytes in collection adoption/migration snapshots.
  • Gives occurrences inherited attachment references without duplicating bytes.
  • Detach removes membership but always retains bytes. TaskNotes exposes no permanent attachment deletion for any provider until its authority can atomically prove the file is unreferenced and delete it.
  • Uses canonical UUID-backed paths and verifies expected size plus SHA-256.

UI

  • Adds accessible attachment controls after Notes with thumbnails, sync/recovery state, open, inline insertion, and explicit non-destructive Detach.
  • Explains that Detach keeps the file and permanent deletion is not yet available.
  • Keeps inline insertion in the live editor draft, so Notes typed during slow uploads or validation cannot be overwritten.
  • Opens a blank image target synchronously to survive popup blocking, then reports download failures visibly.
  • Resolves native and mdbase attachment images in Markdown preview.

Verification

  • pnpm verify: 84 files / 430 tests; 4,982 conformance passes; formatting, typecheck, lint, coverage gates, mdbase oracle, and production build green.
  • pnpm test:production-smoke: 6/6 green.
  • Full isolated Playwright desktop/mobile matrix: 86 passed, 4 intentional skips.
  • Real beta.23 mdbase cloud E2E: adoption/restart recovery, upload/list/download/exact bytes, frontmatter membership, offline reconciliation, cache replacement, and conflict flow green.
  • Rebuilt Android APK: Java 21 unit tests, lint, install, native exact-byte attachment/preview/detach/relaunch flow green.
  • Android retained-folder SAF: provider reports image/png, duplicate write is rejected with original bytes unchanged, and 250-record exercise green.
  • Independent final technical and documentation reviews report no actionable findings.
  • iOS build is delegated to PR CI.

Upstream contracts

@callumalpass
callumalpass marked this pull request as ready for review August 2, 2026 13:33
@callumalpass
callumalpass merged commit 98a063a into main Aug 2, 2026
4 checks passed
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.

1 participant