Retire a caveat the fix made false, and turn a stale warning into a technique
Four of the five fields the caveat said were silently lost are now persisted, so the caveat is retired rather than trimmed. What was genuinely unique in it -- the inbox predicate being a vestige that must stay unused -- moved into the Event bullet where the shape is described; what merely duplicated the entity leaf went. Only `themes` remains unpersisted, and since nothing reads it back it is a note rather than a hazard. The regeneration warning is reframed rather than deleted. It said the ORM generator had drifted from the committed bindings; that no longer reproduces -- regenerating from the unchanged shape gives byte-identical output. What survives is the technique that established it: run the generator on unchanged input first, so an ORM diff separates cleanly into the author's change and the generator's own. A warning became a way of working. The same stale claim sat independently in the commands leaf and was found by grep, not by the briefing. Recorded where the screen hazards live: the edit form seeds its inputs on first render, so mounted before its event lands in the reactive set it stays blank -- the same class as a value that is empty until a read arrives. Verified rather than assumed: the misleading French date example flagged for correction exists nowhere in the doctrine. It lives in a shape comment and the binding generated from it, both outside this pass, and is noted as such.
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
# Doc-debt — app-architecture
|
||||
|
||||
> Presence of a block = doc to update. Processed → delete the block; no blocks left → delete this file.
|
||||
> One block = one "big change": `why` + `files` + `verify` (leaves to review).
|
||||
|
||||
## Raw markers (consolidate into blocks, then delete)
|
||||
- TOUCHED src/shared/context/FestipodDataContext.tsx @2026-08-17 (session 0b064e8b-1717-421f-a20e-a4318ad217b1)
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
type: caveat
|
||||
summary: Two values a screen must not read as data — currentUserId is EMPTY until my profile document resolves, and an ownership answer can be UNKNOWN; both look like ordinary values, neither means "no"
|
||||
last_checked: 2026-08-16
|
||||
summary: Values a screen must not read as data once — currentUserId is EMPTY until my profile document resolves, an ownership answer can be UNKNOWN, and a useState seeded from an unresolved read (UpdateEventScreen) freezes blank; all look like ordinary values, none mean "no"
|
||||
last_checked: 2026-08-17
|
||||
---
|
||||
|
||||
# Pitfall: "not answered yet" looks exactly like an answer
|
||||
@@ -28,3 +28,9 @@ Rendering it as "not yours" silently denies an owner their own event. Rendering
|
||||
Never derive permission from `unknown` either. A screen that opens an editor because the answer "was not a refusal" is editing on a guess; the edit route consults the same three-state answer the control does, and renders `unknown` as its own pending state — [[knowledge_screen-pattern]].
|
||||
|
||||
> The participation→profile join is **not** the screen's business — it is done in the provider (`resolveParticipantUser`). Full mechanics: `data-layer` → [[knowledge_context-internals]].
|
||||
|
||||
## A `useState` seed freezes on whatever the first render saw
|
||||
|
||||
`UpdateEventScreen` reads `const event = eventId ? getEvent(eventId) : undefined;` from the reactive data plane, then seeds every editable field from it: `useState(event?.title ?? '')`, and likewise for `startDate`, `endDate`, `startTime`, `endTime`, `location`, `description`. A `useState` initializer runs **once**, at mount — unlike a value read directly in the render body, it does not track `event` afterwards.
|
||||
|
||||
If the screen mounts before the event has landed in the reactive set — a direct navigation to the edit route, a slow reconnect — every field seeds to `''` and **stays blank**: the later, successful read of `event` never reaches state that already initialized. Nothing throws and nothing looks wrong; the form is simply empty. Same hazard as `currentUserId` and the ownership answer above — "not ready yet" reads as an ordinary value — just caught by `useState` instead of by a query result. Pre-existing, not fixed.
|
||||
|
||||
Reference in New Issue
Block a user