Files
buzz/desktop-new
morgmart c05b85c421 desktop-new: tile address model and shared InlineTile
Implements the foundation the composer sits on: a reference is an address
(kind + identity), never the letters of a name. One shared InlineTile serves
both the composer and the conversation, mounted in the editor through a React
node view.

- shared/tiles/address.ts: kind + id, canonical buzz:// form, parse/format.
- shared/tiles/faceResolver.ts: resolves the displayed face from an address at
  render time, so a rename never edits anyone's draft or enters undo history.
  Community-scoped cache with an explicit reset.
- shared/ui/InlineTile.tsx: the one component, person/agent/channel kinds.
- features/composer/tileNode.ts: the document node. Stores only the address.
- New semantic tokens: --space-tile-inset, --space-tile-gap, --radius-tile.
- Specimen page at /design/components/inline-tile covering kinds, in-sentence
  use, read-only, unresolved, truncation, and activation.

Findings while building, all now covered by tests:
- A React node view REPAIRS a caret boundary. With static markup, Home before a
  leading tile landed after it; with the node view both Home and ArrowLeft land
  correctly. Only the pointer click on a leading tile's left edge still fails —
  now the single known caret gap, still marked test.fail().
- useSyncExternalStore needs a reference-stable snapshot. Building a fresh
  unresolved face per call was an infinite render loop that unmounted the whole
  editor. Unresolved faces are cached like resolved ones.
- An unresolved tile must not announce an abbreviated identity to a screen
  reader. TileFace now carries , and the accessible name says
  "Unresolved person" rather than reading the stand-in aloud.

Falsifiability checked by breaking each protection in turn: selectable:false,
the address text projection, and the community reset each turn tests red.

Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
2026-09-06 15:20:42 -07:00
..
…
…