"This is the type label of our dishwasher" plus a photo → one raw source with the label transcribed and the photo beside it.
Model: Attachment(MediaType, Bytes, Caption); FactStatement and RawSource carry attachments. RawSource.Validate rejects unsupported media types (jpeg/png/webp/gif allowed), empty and >8 MiB.
PortINoteStore: CreateAsync(path, byte[]) for binaries and BrowseUrl(path) for a human link into the store. Gitea implements both; contract test added.
Drafter: images go to the Messages API as base64 image blocks ahead of the text; the prompt asks for exact transcription of every identifier printed and [unreadable] where it cannot read, never a guess.
Deposit: pictures land as raw/<note-stem>-<n>.<ext> (so they follow the note's suffix), listed in attachments: frontmatter and embedded with  at the end of the body. Obsidian and the distill agent see them next to the note.
Page: "Add picture" (file picker, camera on phones) or paste (facts.js moves clipboard images onto the hidden InputFile, so they stream like picked files). Browser-side resize to 1600px JPEG. Thumbnails with remove. The raw page lists attachments with links to the Gitea file.
Machine API unchanged.
Suite: 140 green (contract for binary create on the Gitea fake, image-block test on the Anthropic fake, deposit + record tests with a picture).
"This is the type label of our dishwasher" plus a photo → one raw source with the label transcribed and the photo beside it.
- **Model**: `Attachment(MediaType, Bytes, Caption)`; `FactStatement` and `RawSource` carry attachments. `RawSource.Validate` rejects unsupported media types (jpeg/png/webp/gif allowed), empty and >8 MiB.
- **Port** `INoteStore`: `CreateAsync(path, byte[])` for binaries and `BrowseUrl(path)` for a human link into the store. Gitea implements both; contract test added.
- **Drafter**: images go to the Messages API as base64 image blocks ahead of the text; the prompt asks for exact transcription of every identifier printed and `[unreadable]` where it cannot read, never a guess.
- **Deposit**: pictures land as `raw/<note-stem>-<n>.<ext>` (so they follow the note's suffix), listed in `attachments:` frontmatter and embedded with `` at the end of the body. Obsidian and the distill agent see them next to the note.
- **Page**: "Add picture" (file picker, camera on phones) or paste (`facts.js` moves clipboard images onto the hidden `InputFile`, so they stream like picked files). Browser-side resize to 1600px JPEG. Thumbnails with remove. The raw page lists attachments with links to the Gitea file.
- Machine API unchanged.
Suite: 140 green (contract for binary create on the Gitea fake, image-block test on the Anthropic fake, deposit + record tests with a picture).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
A statement may carry images (a type label, for instance). The drafter
sees them as image blocks and transcribes what is printed; the deposit
stores each picture beside the note as raw/<stem>-<n>.<ext>, lists it in
the frontmatter and embeds it in the body. INoteStore gains a binary
create and a browse URL, so the raw page can link to the pictures. The
page takes pictures from a file picker (camera on phones) or from paste,
resized in the browser to 1600px.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
"This is the type label of our dishwasher" plus a photo → one raw source with the label transcribed and the photo beside it.
Attachment(MediaType, Bytes, Caption);FactStatementandRawSourcecarry attachments.RawSource.Validaterejects unsupported media types (jpeg/png/webp/gif allowed), empty and >8 MiB.INoteStore:CreateAsync(path, byte[])for binaries andBrowseUrl(path)for a human link into the store. Gitea implements both; contract test added.[unreadable]where it cannot read, never a guess.raw/<note-stem>-<n>.<ext>(so they follow the note's suffix), listed inattachments:frontmatter and embedded withat the end of the body. Obsidian and the distill agent see them next to the note.facts.jsmoves clipboard images onto the hiddenInputFile, so they stream like picked files). Browser-side resize to 1600px JPEG. Thumbnails with remove. The raw page lists attachments with links to the Gitea file.Suite: 140 green (contract for binary create on the Gitea fake, image-block test on the Anthropic fake, deposit + record tests with a picture).
🤖 Generated with Claude Code