| … | … | @@ -148,43 +148,94 @@ native record"*. That is right about *choosing what to attach* and wrong about * |
| 148 | 148 | per-target, and baking a target's ceiling into the canonical record is the shape this whole model |
| 149 | 149 | exists to refuse. |
| 150 | 150 | |
| 151 | | ### 6.6.1 A variant is not a duplicate — it is an EDGE |
| 151 | ### 6.6.1 ★ The pyramid IS the object — mip-map levels, not variants |
| 152 | 152 | |
| 153 | | The worry is that storing a downsampled copy breaks content-addressing. It does not, and the reason |
| 154 | | is worth stating precisely: |
| 153 | **Revised 2026-09-05 (user).** An earlier version of this section modelled a downsample as a separate |
| 154 | blob joined to its original by a `variant-of` edge. **The mip-map model is better and dissolves the |
| 155 | problem**, so it supersedes that. |
| 155 | 156 | |
| 156 | | **Dedup was never "one file per logical image." It was "identical bytes stored once."** A downsample |
| 157 | | has different bytes, so it is a different object by definition. What is actually lost is the |
| 158 | | *automatic* knowledge that two objects are the same picture at different fidelities — and that is a |
| 159 | | relation, which this model already has a primitive for. |
| 157 | A texture in a game is not a file plus a set of related smaller files. It is **one asset containing a |
| 158 | pyramid of levels**, bound and sampled as a single thing; the *consumer* picks a level by how much of |
| 159 | the screen it covers. Media here should work the same way. |
| 160 | 160 | |
| 161 | 161 | ``` |
| 162 | | (variant, variant-of, original) + the parameters that produced it |
| 162 | blob "sunset.jpg" → manifest (itself content-addressed) |
| 163 | level 0 4096px oid a3f… |
| 164 | level 1 2048px oid 9c1… |
| 165 | level 2 1024px oid 44b… |
| 166 | level 3 512px oid e07… |
| 163 | 167 | ``` |
| 164 | 168 | |
| 165 | | Exactly the shape of an `alias` edge (`interaction.md` §3.3): alias says *two names, one thing*; |
| 166 | | `variant-of` says *two byte-sets, one image at different fidelities*. Same mechanism, and it makes |
| 167 | | the relation explicit and inspectable instead of implicit and lost. |
| 169 | **No `variant-of` edge is needed, because the levels were never separate objects.** The relation is |
| 170 | not asserted and then maintained — it is the structure of the asset. |
| 168 | 171 | |
| 169 | | ⛔ **A variant records WHO derived it.** §8's rule — *"never re-encode a record you did not author"* — |
| 170 | | cost two of wj62's posts. A bridge-produced downsample is a derived artifact and must never be |
| 171 | | attributed as the author's bytes; the `variant-of` edge carries the deriver. That keeps the wj62 |
| 172 | | failure class out of media. |
| 172 | **It sidesteps the overlay's limitation instead of fighting it.** §6.6.2 previously recorded that |
| 173 | sparse fetch of one blob is impossible because hyper-overlay addresses a file by a whole-file blake2b |
| 174 | hash, so a prefix cannot be authenticated. A pyramid needs no prefix: **every level is a whole file |
| 175 | with its own oid**, which is exactly what the overlay already does well. Fetch the tiny manifest, |
| 176 | choose a level, fetch that one oid — ordinary `ensureLocal`. We get sparseness **by level**, which is |
| 177 | the property that was wanted. |
| 173 | 178 | |
| 174 | | ### 6.6.2 Three tiers, and the one we cannot have yet |
| 179 | **Bridges SELECT rather than downsample.** A bridge picks the level nearest its target's ceiling. |
| 180 | Downsampling then happens **once, at authoring, deterministically** — like generating mips at asset |
| 181 | build time — instead of per delivery on every bridge. That is strictly better than §6.6's |
| 182 | "derive on demand", and it keeps the honesty requirement: the chosen level is reported in `loss[]`. |
| 175 | 183 | |
| 176 | | | | when | cost | |
| 177 | | |---|---|---| |
| 178 | | | **derive on demand** | bridges | CPU per delivery; the bridge must hold full bytes. **The default** — no storage concept at all | |
| 179 | | | **stored variant + `variant-of` edge** | a peer that genuinely cannot hold or fetch full fidelity (a phone) | a second blob, explicitly related. Dedup intact | |
| 180 | | | **sparse fetch of one blob** | *the shape we would want* | ⛔ **not expressible today** | |
| 184 | **Cost is the mip cost and it is bounded:** 1 + ¼ + 1/16 + … = **4/3** of the base image. Known in |
| 185 | advance, unlike an open-ended set of variants. |
| 186 | |
| 187 | **We already ship one.** `hypernote/lib/media/video-processor.js:7-11` defines |
| 188 | `HLS_LEVELS` — 480p/720p/1080p with per-level codec profiles — and filters `l.height <= srcHeight`, |
| 189 | so it never upscales. A bitrate ladder *is* a mip chain for video. It exists, in Bare, on this |
| 190 | substrate; what is missing is generalising it to images and naming it as the model. |
| 191 | |
| 192 | **Where the analogy breaks — three places, all worth knowing:** |
| 193 | |
| 194 | 1. **Mip levels come from a fixed filter; media ladders are target-driven.** hypernote picks |
| 195 | `baseline`/`main`/`high` profiles per level, not one filter. Levels are chosen against real |
| 196 | network ceilings, not powers of two. |
| 197 | 2. **Never upscale.** A level is a *floor*, not a guarantee — an asset smaller than the lowest level |
| 198 | has one level. hypernote already encodes this; the manifest must not imply levels it lacks. |
| 199 | 3. **Text has no pyramid.** `strip()` is lossy but not a ladder. This model covers media and identity |
| 200 | (§6.6.3), not prose. |
| 201 | |
| 202 | ⛔ **Who derived a level still matters.** §8's *"never re-encode a record you did not author"* cost two |
| 203 | of wj62's posts. Levels generated at authoring are the author's; a level a bridge generated later is |
| 204 | derived, and the manifest must say so rather than presenting it as authored bytes. |
| 205 | |
| 206 | ### 6.6.3 The same model for identity — LOD, not personas |
| 207 | |
| 208 | The user's observation extends past media, and the existing framing was already reaching for it: |
| 209 | `SOCIAL-GRAPH-NAVIGATION.md` says *"identity is a section of the sheaf — one keypair (global |
| 210 | section), but context-dependent presentation that can vary locally."* |
| 181 | 211 | |
| 182 | | The third is the elegant one: a progressive format lets a byte prefix decode as a lower resolution, |
| 183 | | so one blob serves every fidelity with no variants at all. **hyper-overlay blocks it** — it addresses |
| 184 | | a file by a whole-file blake2b `contentHash`, so a prefix cannot be authenticated against the |
| 185 | | registered oid. Getting there needs per-blob merkle verification, which the overlay does not have. |
| 212 | Mip-map sharpens it: those presentations are **derived coarsenings of one canonical profile**, not |
| 213 | independently maintained variants. And it is already structural, exactly as visibility is — keet |
| 214 | holds member profiles **per room**, so which room you are in decides which level of you resolves. |
| 215 | |
| 216 | ``` |
| 217 | level 0 full profile close contacts, DM rooms |
| 218 | level 1 name + avatar rooms you are a member of |
| 219 | level 2 handle only a public room |
| 220 | ``` |
| 221 | |
| 222 | ⛔ **The rule the analogy gives us: a lower level may OMIT, never CONTRADICT.** A mip level is a |
| 223 | blurrier version of the same image, never a different picture. So your name in a public room may be |
| 224 | absent; it may not be a *different* name. That is what keeps progressive disclosure from becoming |
| 225 | deception, and it would not have been obvious without the analogy. |
| 226 | |
| 227 | **Genuinely different personas are a different ACCOUNT**, not a lower level — the SLIP-48 |
| 228 | `accountIndex` (§3 #1) already provides them, unlinked and unlinkable. So the two cases separate |
| 229 | cleanly: |
| 230 | |
| 231 | | | mechanism | linkable? | |
| 232 | |---|---|---| |
| 233 | | less of me in this room | a lower profile level | yes — same account | |
| 234 | | a different me | a different account from the same seed | no | |
| 186 | 235 | |
| 187 | | Worth recording as the thing to want, because it would delete tier two entirely. |
| 236 | ⚠ **The cost is real and should be stated:** within one account you cannot present a *different* face |
| 237 | in two rooms, only less of the same one. Wanting a different face means paying for a separate account, |
| 238 | which cannot be linked back. That is a deliberate product constraint, not an oversight. |
| 188 | 239 | |
| 189 | 240 | ## 6.7 Moderation — rooms and edges, no new primitive |
| 190 | 241 | |