| … | … | @@ -0,0 +1,89 @@ |
| 1 | # note to self — 2026-09-06 |
| 2 | |
| 3 | ok so this started as "settle the three decisions in #60" and turned into taking the whole |
| 4 | thing apart. writing it down because i'll forget why. |
| 5 | |
| 6 | ## what actually happened |
| 7 | |
| 8 | i asked to settle three things. one got settled and shipped (the facet shape, fine, small). |
| 9 | the other two turned out to be built on a claim that isn't true in the code — the spec says a |
| 10 | personal room's key comes from the identity root, but it's `hash(ns + did)`. from the DID. the |
| 11 | thing we spent #58 demoting *because* it rotates. so rotating a DID would change every address |
| 12 | in the room, which is the exact thing the favela:// scheme was invented to stop. |
| 13 | |
| 14 | and position. i'd been treating it as an address. it isn't, it's a view coordinate — keet |
| 15 | resolves everything by oplog and uses index only for where a message sits in a thread. a |
| 16 | counter assigned inside apply() is a function of the linearization and apply gets replayed on |
| 17 | reorg. so a "permalink" that can change afterwards. embedded in other people's bytes. |
| 18 | |
| 19 | both of those are things i'd have found by reading the source instead of reading our own docs |
| 20 | back to myself. that's the lesson, again. |
| 21 | |
| 22 | ## the bigger thing |
| 23 | |
| 24 | the room model was doing two jobs and only one of them worked. |
| 25 | |
| 26 | audience: doesn't work. adding someone gives them the whole history, leaving revokes nothing, |
| 27 | and to like a post you have to become a writer in someone's autobase — which means a popular |
| 28 | post turns every liker into a hypercore. that's a wall not a slope. |
| 29 | |
| 30 | container: fine, but a feed already does that. |
| 31 | |
| 32 | the tell was that all three failures are *obvious* if you call it a shared document and |
| 33 | *surprising* if you call it a room. we were being misled by our own noun. everyone who has it |
| 34 | has all of it. you don't walk in, you get a copy. |
| 35 | |
| 36 | so: feed and document are primitives. a room isn't one. a room is what you call it after |
| 37 | enough stuff has clustered and someone names it — same as a community, just one scale down. |
| 38 | which is neat because it means the same mechanism handles both and we stop having a special |
| 39 | case. |
| 40 | |
| 41 | and removing it *fixes* the scaling wall by accident rather than by design work. no room to |
| 42 | write into means your like lives in your own feed. writer sets stay at your own devices. |
| 43 | counts go per-observer, which we'd already committed to anyway. |
| 44 | |
| 45 | ## the lego thing |
| 46 | |
| 47 | the bit i keep coming back to. every join, follow, listing, bridge is two things fitting |
| 48 | together. the connection isn't an object, it's the event. we'd been modelling the receipt and |
| 49 | calling it the primitive. |
| 50 | |
| 51 | and then type comes from what a thing fits with, not from what it declares. two feeds are the |
| 52 | same kind if they click the same way — even with nobody in common. our current MI does |
| 53 | membership overlap, which can only ever find things that already overlap. that's the whole |
| 54 | difference and it's why this is worth doing. |
| 55 | |
| 56 | quake is the reason i believe it. nine tries stuck at 1.0 because we typed the connector by |
| 57 | geometry. changed it to what the thing *is* and it went to 1.78 with a third of pieces reusing. |
| 58 | the statistics never changed. only what the stud meant. |
| 59 | |
| 60 | ## what i got wrong today |
| 61 | |
| 62 | said test 5 could run against wj62 and loser-club. it can't. two rooms, three members and two |
| 63 | members, zero overlap. they're not a social network, they're two co-owned DIDs with device |
| 64 | rosters — of course the members don't overlap, roomKey is per-DID. |
| 65 | |
| 66 | which means the entire emergent layer is unfalsifiable until there's a network. can't be |
| 67 | cleverness'd around. build the thing first, but instrument every mating event from day one |
| 68 | with its type, because reconstructing types from state later is exactly the quake mistake. |
| 69 | |
| 70 | ## where it is now |
| 71 | |
| 72 | clean break from atproto and AP. not "atproto with markdown bolted on" — i caught myself |
| 73 | building the double-write codec into atproto-store today and that was the old thinking. bridges |
| 74 | come after, and they read us, we never read them. |
| 75 | |
| 76 | favela-peer exists. record store works — markdown files, content addressed, and i kept the four |
| 77 | invariants we paid for (never re-encode, verify local bytes against the pointer, return null |
| 78 | rather than a stale copy, del drops bytes not the record). boundary is a test not a promise. |
| 79 | |
| 80 | next: the log. feed = one identity's log, writers are its devices. then follow, then timeline |
| 81 | as a local projection. keet already has the identity and reaction machinery so most of it is |
| 82 | using what's there rather than writing it. |
| 83 | |
| 84 | ## don't forget |
| 85 | |
| 86 | - private means encrypted. unlisted just means harder to find. never let the ui blur those. |
| 87 | - the system detects, a person names. auto-naming a cluster is a political act. |
| 88 | - counts are per-observer. never sum them. |
| 89 | - if independent peers don't converge on the same clusters, emergence is a story and we drop it. |