feat(collab): sessie-controller — de tab↔sessie-brug (increment 3b van #996) #1001

Merged
brenno merged 1 commit from collab/inc3b-session-controller into main 2026-07-30 17:42:51 +00:00
Owner

Increment 3b van #996: de brug tussen het tab-deck en een samenwerksessie (COLLABORATION.md §5.7).

CollabSessionController verbindt de twee richtingen: een lokale bewerking wordt tegen de sessie gediffed (increment 3a) en de ops ingediend; een wijziging die de sessie toepast (de commit van de autoriteit, of een op van een co-auteur op afstand) vloeit terug, gemerged op het lokale deck zodat niet-syncbare velden (tabelrijen, annotaties) behouden blijven — de merge is applyOps(local, deckDiffToOps(local, session)), die per constructie alleen het syncbare oppervlak raakt.

Twee waarborgen stoppen de echo-lus: een _applyingRemote-vlag onderdrukt her-indienen terwijl een wijziging op afstand wordt weggeschreven, en een terug-geëchood deck levert sowieso een lege diff op, zodat luisteraar-timing niet uitmaakt.

Riverpod- en Flutter-vrij (met read/write-callbacks), dus het subtiele deel is headless getest: host↔gast-propagatie beide kanten op, de merge die een lokale tabelbewerking behoudt door een rename op afstand heen, een structurele invoeging, en de echo-guard die geen op toevoegt.

Hiermee is de collab-laag zelf compleet en getest (snapshot, sessie-levenscyclus, editor→op-diff, bidirectionele controller). Resteert (3c): de Riverpod-provider die er per tab één bezit, de per-tab override in app_shell, en de start/deelnemen-UI — de app-lijm die dit gebruiker-zichtbaar maakt en de draaiende app vereist voor verificatie.

make check groen (dekking 87,4%, 743 bestanden).

Increment 3b van #996: de brug tussen het tab-deck en een samenwerksessie (COLLABORATION.md §5.7). `CollabSessionController` verbindt de twee richtingen: een lokale bewerking wordt tegen de sessie gediffed (increment 3a) en de ops ingediend; een wijziging die de sessie toepast (de commit van de autoriteit, of een op van een co-auteur op afstand) vloeit terug, **gemerged** op het lokale deck zodat niet-syncbare velden (tabelrijen, annotaties) behouden blijven — de merge is `applyOps(local, deckDiffToOps(local, session))`, die per constructie alleen het syncbare oppervlak raakt. Twee waarborgen stoppen de echo-lus: een `_applyingRemote`-vlag onderdrukt her-indienen terwijl een wijziging op afstand wordt weggeschreven, en een terug-geëchood deck levert sowieso een lege diff op, zodat luisteraar-timing niet uitmaakt. Riverpod- en Flutter-vrij (met read/write-callbacks), dus het subtiele deel is headless getest: host↔gast-propagatie beide kanten op, de merge die een lokale tabelbewerking behoudt door een rename op afstand heen, een structurele invoeging, en de echo-guard die geen op toevoegt. Hiermee is de **collab-laag zelf compleet en getest** (snapshot, sessie-levenscyclus, editor→op-diff, bidirectionele controller). **Resteert (3c):** de Riverpod-provider die er per tab één bezit, de per-tab override in `app_shell`, en de start/deelnemen-UI — de app-lijm die dit gebruiker-zichtbaar maakt en de draaiende app vereist voor verificatie. `make check` groen (dekking 87,4%, 743 bestanden).
feat(collab): session controller bridging a tab deck and a session (#996)
All checks were successful
scans / scans (pull_request) Successful in 3m26s
330fbd0855
Increment 3b of #996: the bidirectional bridge (COLLABORATION.md §5.7). A
local edit is diffed against the session and its ops submitted; a change
the session applies (the authority's commit, or a remote co-author's op)
flows back, merged onto the local deck so non-syncable fields (table
rows, annotations) survive — the merge is applyOps(local, deckDiffToOps(
local, session)), which by construction touches only the syncable surface.

Two guards stop the echo loop: an _applyingRemote flag suppresses
re-submission while writing a remote change, and belt-and-braces an
echoed deck diffs empty, so listener timing cannot matter. Riverpod- and
Flutter-free (plain read/write callbacks), so the subtle part is unit-
tested headlessly: host<->guest propagation both ways, the merge keeping
a local table edit through a remote rename, a structural insert, and the
echo guard appending no op.

The Riverpod provider that owns one per tab and the start/join UI (§5.7)
are the remaining app glue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit f2caf4f520 into main 2026-07-30 17:42:51 +00:00
Sign in to join this conversation.
No description provided.