The count defect was two things; only the one that is not ours is left

`bug_participant-count-stays-at-zero` described a failure that no longer exists
and an open question that turned out to be the same failure seen from the other
side. It becomes `caveat_participant-count-one-connection-lag`, and the type
change is the point: what remains is a bounded delay whose cause sits entirely
outside the application, not a defect this repo can act on.

Gone from it: the multi-inbox race, "never converges", and the withdrawal
asymmetry recorded as unexplained. That asymmetry WAS the race — with one inbox
per document both paths now share the identical one-connection lag, so nothing
is left unaccounted for.

What it says now: the count needs one connection more than the write that
produced it, because the layer does not notify you of your own actions — a
deposit into an inbox you watch raises no push, and a write to your own document
is not re-read in the writing session. Both measured, both raised with the
provider, and neither compensated here: a retry or a poll is precisely what the
doctrine forbids.

Repaired alongside: the leaves that still described DELETE-then-INSERT, the
materializer's old shape, and the probe cookbook's tally of open defects. The
two new primitives are recorded where the shared utilities are listed, marked
unit-tested.
This commit is contained in:
Sylvain Duchesne
2026-08-17 00:10:16 +02:00
parent 0d925c7cb9
commit e780c5246c
11 changed files with 50 additions and 74 deletions
@@ -15,7 +15,7 @@ summary: What is implemented today (event + meeting point lifecycle, profiles, c
- User profile, profile update, profile sharing
- Friends list (connections), another user's profile
> **Signing up is wired step by step, and the flow as a whole does not yet deliver an honest count.** Each step is honest: `joinEvent` persists a Participation and deposits into the event's inbox, where its owner reads it; `leaveEvent` deletes the Participation authoritatively (concept `data-layer`, [[caveat_participation-deletion]]); neither succeeds in silence, and the confirmation the user sees follows the write. Driven end to end in a real browser, the sign-up nonetheless **announces a success ahead of what it shows**: the user is told they participate, and the count they see stays at 0 through the session and the first reconnect, only catching up on the second ([[bug_participant-count-stays-at-zero]]). Honest steps do not add up to an honest flow, and nothing short of exercising the whole thing shows it (concept `bdd-testing`, [[cookbook_live-probe]]). Treat the bullet above as *screens reachable*, not as a working journey. Public discovery — a user seeing another user's public event — works too.
> **Signing up is wired step by step, and the count a bystander sees lags the flow by one connection.** Each step is honest: `joinEvent` persists a Participation and deposits into the event's inbox, where its owner reads it; `leaveEvent` deletes the Participation authoritatively (concept `data-layer`, [[caveat_participation-deletion]]); neither succeeds in silence, and the confirmation the user sees follows the write. Driven end to end in a real browser, the signer's own confirmation is instant and correct, but the `participantCount` a bystander sees stays at 0 through the session and the first reconnect, only catching up on the second — a known layer limitation, not data loss (concept `data-layer`, [[caveat_participant-count-one-connection-lag]]). Nothing short of exercising the whole thing end to end shows this kind of gap (concept `bdd-testing`, [[cookbook_live-probe]]). Treat the bullet above as *screens reachable*, not as an instantly-consistent journey. Public discovery — a user seeing another user's public event — works too.
> **Updating an event is reserved to its declarer**, and the interface says so rather than discovering it late: the edit route is decided by ownership, and the confirmation follows the write instead of preceding it (concept `app-architecture`, [[knowledge_screen-pattern]]). Owner-only is not a policy choice here — it is the only reading the data model allows ([[knowledge_data-scopes-and-discovery]]).