diff --git a/amethyst/plans/2026-09-21-deck-0003-sno.md b/amethyst/plans/2026-09-21-deck-0003-sno.md index ee3b40aa87..f51e006d47 100644 --- a/amethyst/plans/2026-09-21-deck-0003-sno.md +++ b/amethyst/plans/2026-09-21-deck-0003-sno.md @@ -1,6 +1,8 @@ # DECK-0003 (SNO — Simple Nostr Objects) — feasibility and implementation plan -_Status: investigation. Nothing built yet._ +_Status: **built** on `claude/epic-ptolemy-48n37b`. The reader, the rasterizer, +the feed/thread rendering and kind-11333 avatars all ship; §6 records what +landed and what did not._ Source: (Draft, last updated 2026-09-16, requires `CYBERSPACE_V2.md` `2026-03-16-h34-corrected`). @@ -448,7 +450,37 @@ size that suits its context rather than refusing it." feed. Gate the thumbnail behind the same content-warning / follow-based rules the feed already applies to images, rather than inventing a new one. -## 6. Suggested sequencing +## 6. Sequencing — what landed + +Built in this order, each step verified before the next: + +1. `quartz/…/cyberspace/deck0003Sno/` — payload, §1.9 validator, built-in + palette, palette-event reader, kind 33331, kind 11333 + the §8.10 work gate. + **50 tests**: the 25-case rejection table generated from `sno-reference.py`, + the avatar ladder computed from §8.10's pseudocode, all seven live objects as + fixtures. +2. `commons/…/sno/SnoRasterizer` — CPU rasterizer, **15 tests**, one per rule §4 + decides, plus the depth ordering a painter's algorithm gets wrong. Checked by + eye too: the object named Triforce comes out as a Triforce. +3. `commonsUI/…/sno/` — Coil fetcher + `SnoThumbnail` for the cached static + view, `SnoObjectViewer` drawing straight to a bitmap for the drag (each drag + angle would otherwise be a half-megabyte cache entry), `SnoObjectCard` / + `SnoAvatarCard`, and a new `PlatformImage.toComposeImageBitmap()` beside the + existing Coil bridge. +4. `amethyst/…/note/types/SnoObject.kt` + `SnoAvatar.kt`, dispatched from + `NoteCompose` and `ThreadFeedView`, stored addressably/replaceably in + `LocalCache`, fetcher registered in both image loaders. + +**Decisions as taken:** D1 accept (parity with sno-core — all seven objects +read), D1b tolerate, D2 deferred, D3 read-only with the writer in quartz, D4 +inline quote + thread, D5 clamp at ±64 units. + +**Deliberately not wired:** kind 3330 bag items (D2), an authoring/modeling +tool, and replacing a user's NIP-01 profile picture with their cyberspace +avatar — that last one is a product decision about every feed row, not +plumbing. + +### The original plan 1. **Quartz parse + validate + built-in palette + the 25-case table.** No UI. Lands as a self-contained, fully tested module; `amy` can dump a parsed object for