# ADR-0025 — Contextbewuste pil en toevoegacties in het modulecontract

**Status:** aanvaard 2026-08-09

**Hoort bij:** [`docs/design/ten210-contextbewuste-pil.html`](../../design/ten210-contextbewuste-pil.html)
· TEN-210 · TEN-179

**Raakt:** `E-NAV-10`, de modulecontracten uit TEN-179, de AI-gate voor gevoelige
domeinen en alle lokale toevoeg-affordanties op module-, kern- en appoppervlakken.

---

## Context

De centrale pil staat op alle shellschermen en heeft twee helften: vastleggen en
assistent. Beide zijn nu algemeen. Module- en appschermen houden daarom daarnaast een
eigen toevoegactie. Dat veroorzaakt dubbele bediening en lokale knoppen die met de
centrale balk botsen.

De oude inventarisatie telde 32 bronbestanden met een `floatingActionButton:`. Die
methode beschrijft niet wat een gebruiker rendert. De route-audit van 9 augustus 2026
vindt **42 actieve route- of modale oppervlakken** met een lokale toevoeg-affordantie:
31 primair via een FAB, 3 via inline invoer, 2 via de AppBar en 6 via andere
inhoudsacties. Dat zijn 40 unieke route- of detailrenderers; twee renderers bedienen
ieder twee verschillende routes/contracten. Twee van de 32 statisch gevonden FAB-schermen horen
bij de gepensioneerde module Vastgoed en zijn voor ieder lid onbereikbaar.

De eigenaar heeft gekozen dat de pil alle lokale toevoeg-affordanties vervangt, ook
inline invoerrijen. Het volledige bestaande formulier blijft de functionele norm. De
assistent krijgt meer mee dan alleen een module-id, maar de bestaande gevoelige-
domein-gate blijft beslissend. TEN-179 stelt tegelijk dat bijdragen van een module aan
andere app-oppervlakken in één generiek modulecontract horen, niet in losse lijsten.

Twee codefeiten begrenzen de uitvoering. Ten eerste staan `/inbox`, `/agenda`,
`/lijstjes`, `/lijstjes/:id`, `/instellingen` en `/gezin-beheren` als top-level routes
buiten `AppShell`; daar rendert de pil vandaag niet. Op de shellroutes `/mijn-leven` en
`/dashboards` rendert hij wel, direct naast respectievelijk “Nieuwe map” en “Widget
toevoegen”. Ten tweede krijgen `SavingsGoalDetail`, `VacationDetailScreen` en
`ReceptDetailScreen` hun record via `Navigator.push`, niet via een go_router-parameter.
Route-afleiding alleen kan op die schermen dus niet weten welk record actief is.

## Besluit

### B1 — Eén toevoegingang, via de pil en een volwaardige drawer

Op een omgezet oppervlak is de plushelft van de pil de enige algemene
toevoeg-affordantie. Hij opent een drawer met hetzelfde volledige formulier en dezelfde
rechten als de lokale affordantie die hij vervangt.

- Er komt geen generiek `CaptureSheet` als verplichte tussenstap op een modulescherm.
- Een drawer mag meerdere acties tonen wanneer een scherm aantoonbaar meer dan één
  toevoegtype heeft, bijvoorbeeld sportteam + sportevenement of rekening + pas.
- Boodschappen is de minimale volledigheidsproef: productregels, geparste hoeveelheid,
  expliciete winkelkeuze (ook “geen winkel”) en het bestaande detailpad naar link/foto
  blijven beschikbaar.
- Bewerken, verwijderen, afvinken, favoriet maken, statusacties en hoeveelheid `+`/`−`
  zijn geen toevoeg-affordanties en blijven op hun inhoudelijke plek.
- Het doel hoeft geen klassiek domeinrecord te zijn. Een dashboardwidget, een
  springboardmap en een lokaal of uitgenodigd huishoudlid zijn beheerde dingen en tellen
  mee: ook hun lokale knop veroorzaakt de dubbele bediening die TEN-210 oplost.
- Een bevestiging of omzetting binnen een al begonnen workflow is geen aparte
  toevoegingang. “Maak taak” op een Vandaag-suggestie, de bevestig-/doorstuurkaart van
  Assistent en inboxtriage houden hun inhoudelijke plek: zij accepteren of routeren al
  aanwezige, vooringevulde inhoud en concurreren niet met een leeg toevoegformulier.

Een lokale affordantie verdwijnt pas in dezelfde merge waarin de pilactie, drawer,
rechten, velden en tests voor dat oppervlak aanwezig zijn.

### B2 — De actieregistratie is onderdeel van TEN-179

> **HERZIEN 9 augustus 2026 na panel-review — lees dit eerst.**
> De publicatieregel hieronder ("publiceren bij mount, intrekken bij unmount") is
> **ongeldig in de huidige shell**. `StatefulShellRoute.indexedStack` houdt takken
> gemount; een detailscherm in een andere tab blijft dus publiceren en zou volgens de
> "meest specifieke actieve context wint"-regel winnen van het scherm dat de gebruiker
> ziet. Er is een expliciet **actieve-tak-signaal** nodig: mount is niet hetzelfde als
> zichtbaar. Zie de sectie "Panel-revisies" onderaan.


TEN-210 krijgt geen eigen `switch (moduleId)` en geen losse actielijst in de shell. Het
generieke modulecontract uit TEN-179 draagt voortaan ook **contextacties**. Een
registratie bevat ten minste:

1. een stabiele actie-id en de module- of kernoppervlak-id;
2. het toepassingsgebied: landing, detail, onderdeel, rol en eventuele profielconditie;
3. de gelokaliseerde semantische naam;
4. de drawer/formulierbouwer en de vereiste lokale schermcontext;
5. dezelfde zichtbaarheid-, rechten- en toegangspoorten als de oude affordantie;
6. het gedrag na opslaan (`sluit` of de herzienbare `blijfOpen`-variant);
7. optioneel een projector naar begrensde assistentcontext.

De actieve gerenderde subtree publiceert zijn toepasselijke `ScreenActionContext` aan
de shell en trekt die publicatie bij unmount weer in. Route-afleiding blijft de
modulefallback, maar wint nooit van de specifiekere context van het actieve
detailscherm. De mechanieketappe moet met een Navigator-push-test bewijzen dat een
detailscherm de pil bereikt en dat terugnavigeren de vorige context herstelt.

De taxonomie volgt TEN-179: eerst generieke actietypen — nieuw hoofdrecord,
dagregistratie, kindrecord, recordgebonden toevoeging, bulk/inline invoer en beheerd
UI-/huishoudobject — en alleen
een modulespecifieke uitbreiding waar de formulierinventaris aantoont dat een generiek
type niet volstaat. Kern- en appoppervlakken gebruiken hetzelfde contract via een eigen
registratie; zij worden niet vermomd als `ModuleDescriptor`.

### B3 — Lokale actiecontext en verzonden assistentcontext zijn gescheiden

`ScreenActionContext` is lokaal en mag routeparameters, record-id's, rol,
profielcondities, gekozen winkel, actieve sectie en formulierdefaults bevatten. Deze
gegevens zijn nodig om de juiste drawer te openen. Zij gaan **niet** automatisch naar
de AI-dienst.

`AssistantScreenContext` wordt pas gemaakt wanneer de gebruiker de AI-helft aantikt.
Het is een momentopname van de actuele, gefilterde schermview met deze harde grenzen:

- alleen velden uit de allowlist hieronder;
- maximaal 20 lichte rij- of recordsamenvattingen;
- geen database-objecten, verborgen/gefilterde rijen, verwijderde records of gegevens
  die niet op het huidige scherm beschikbaar zijn;
- geen lokale record-id's, deel-/rechtenmetadata of technische routes in het externe
  verzoek;
- geen vrije notities, chatgeschiedenis uit andere contexten, bijlagen, afbeeldingen,
  scans, documentinhoud, URL-inhoud of geheime/identificerende nummers;
- opbouw uitsluitend na een expliciete tik, geen prefetch; de context wordt zichtbaar
  als chip/regel in de geopende assistent en kan daar worden verwijderd;
- de momentopname geldt voor die geopende assistentsessie en wordt niet als nieuw
  domeinrecord opgeslagen.

#### Allowlist per kernoppervlak en module

“Zichtbaar” betekent: onderdeel van de actuele gefilterde view, niet alle rijen van de
onderliggende repository.

| Oppervlak/module | Schermgegevens die naar de assistent mogen |
| --- | --- |
| Agenda | actieve periode/filter; zichtbare titel, begin/einde, hele-dag-status, locatie en bronmodule |
| Taken | mijn/alle-filter; zichtbare titel, categorie, deadline en voltooiingsstatus |
| Lijstjes / Bewaarlijsten | overzicht: zichtbare lijstnaam, soort en open aantal; detail: huidige lijstnaam/soort en zichtbare titel, hoeveelheid, sectie en afvinkstatus |
| Boodschappen | huidige lijstnaam, gekozen winkel en zichtbare producttitel, hoeveelheid, winkel/sectie en afvinkstatus; nooit link of foto |
| Documenten | zichtbaar type, label, houderweergavenaam, verloopdatum en herinneringsstatus; nooit bestand, scan of documentnummer |
| Vaste kosten | zichtbare naam, categorie, bedrag, frequentie en eerstvolgende betaaldatum |
| Inkomsten | zichtbare naam, categorie, bedrag, frequentie en eerstvolgende betaaldatum |
| Spaardoelen | zichtbaar doelnaam, doelbedrag, voortgang, maandinleg en doeldatum; op detail ook zichtbare bijdragebedragen/datums |
| Verzekeringen | zichtbare naam, verzekeraar, premie/frequentie, dekking en verleng-/opzegdatum; nooit polisnummer of scan |
| Abonnementen | zichtbare naam, categorie, bedrag/frequentie en verleng-/opzegdatum |
| Leningen | zichtbare soort/verstrekker, saldo, rente, maandlast en looptijd; nooit contractnummer |
| Bankrekeningen | zichtbare banknaam, rekeningtype en maandkosten; nooit IBAN-delen of pasnummers |
| Garanties | zichtbaar product, merk, winkel, aankoopdatum en verloopdatum; nooit bon of bijlage |
| Wagenpark | zichtbaar merk/model, jaar, APK-/servicedatum en itemlabels; nooit kenteken of document |
| Sportkalender | actieve periode/teamfilter; zichtbare teamnaam, sport, evenementtype, begin/einde en locatie |
| Schoolvakanties | actieve periode; zichtbare naam/type, begin/einde en schooljaar |
| Verjaardagen | zichtbare naam, soort datum, dag/maand en eerstvolgende voorkomen; geen cadeaunotitie |
| Co-ouderschap | actieve periode; zichtbaar kindweergavenaam, relatie, patroon en begin/einde |
| Gezinsafspraken | huidig onderdeel/rubriek; zichtbare titel, kindweergavenaam, status, bedrag/beloning en rooster-/uitbetaaldatum; geen bonnetjes of vrije notities |
| Routines | zichtbare routinetitel, dagdeel/dagen en voortgang van vandaag |
| Gewicht | zichtbare meetdatum en meetwaarde, doel en schermperiode |
| Pillen & vitamines | zichtbare middelnaam, dosis, schema, volgende inname en lage-voorraadstatus |
| Cyclus | actieve datum/periode; zichtbare fase/bloeding, klachten/tags, stemming, energie en slaap; geen vrije notitie |
| Onderhoud | zichtbaar item/object/type, status, interval, laatste/volgende datum en kosten |
| Afvalkalender | actieve periode; zichtbare afvalsoort, ophaaldatum, herhaling en pauzestatus; nooit import-URL |
| Vakantieplanning | actieve tab; zichtbare bestemming, status, aankomst/vertrek en aantal personen; op detail ook sectie en zichtbare itemtitel/datum/tijd/type |
| Beweging | actieve periode; zichtbare sport/type, datum/tijd, duur en locatie |
| Maaltijden | actieve week/dag; zichtbare gerechtnaam, maaltijdtype, datum en macro's |
| Recepten | actieve zoekterm/filter; zichtbare receptnaam, categorie/tags, bereidingstijd en macro's; op detail maximaal 20 zichtbare ingrediënten/stappen |
| Voorraad | zichtbare itemnaam, hoeveelheid/eenheid, locatie, houdbaarheidsstatus en minimumvoorraadstatus |

Vastgoed staat niet in de actieve allowlist omdat de descriptor `retired` is. Bij een
latere terugkeer krijgt de opvolgende module een nieuw, expliciet contract; de oude
schermen worden niet stil hergebruikt.

De vijf nieuw getelde oppervlakken krijgen bewust geen rij in deze AI-allowlist.
`ScreenActionContext` mag lokaal de inboxmodus, springboardindeling, het dashboardbord en
het beheer-/uitnodigingsrecht dragen, maar Inbox-tekst, mapnamen, dashboardindeling,
ledenlijsten en uitnodigingsgegevens zijn niet als assistentcontext goedgekeurd. De
AI-helft blijft daar dus algemeen totdat een latere ADR per oppervlak een begrensde
projectie vastlegt. De toevoegactie zelf blijft wel contextbewust en volledig bruikbaar.

### B4 — De gevoelige-domein-gate onderdrukt alle getoonde context

> **HERZIEN 9 augustus 2026 na panel-review — lees dit eerst.**
> De gate hieronder sleutelt op het domein van het **oppervlak**. Dat is te grof:
> inhoud erft die gevoeligheid niet. Bewezen lek — Routines (domein gezondheid)
> spiegelt titel én notities de agenda in met `sourceModuleId: kRoutinesModuleId`
> (`routines_providers.dart:256-272`); Agenda heeft geen domein, dus de gevoelige tak
> wordt nooit betreden en "Insuline 22:00" gaat mee, ook met gezondheids-AI uit.
> **De gate draait voortaan per rij, op herkomst:**
> `sourceModuleId → moduleDescriptor → domain.sensitive`. Een rij zonder herkomst valt
> terug op het domein van zijn eigen oppervlak; zelf getypte tekst is de erkende grens.
> Zie de sectie "Panel-revisies" onderaan en TEN-225.


Voor `geld` en `gezondheid` wordt vóór contextopbouw én direct vóór het AI-verzoek
`AiGate.allows(AiCapability.chat, domainId: …)` gecontroleerd.

- Open: de allowlist van B3 mag worden geprojecteerd.
- Dicht of nog onbekend: de AI-helft blijft volledig algemeen. De semantische naam is
  “Assistent”, de geopende assistent toont geen modulechip en het verzoek bevat geen
  module-, scherm- of recordcontext.
- Voor Pillen & vitamines en Cyclus onderdrukt een nog gesloten toegangsslot de context
  eveneens. De AI-gate blijft de beslissende privacytoestemming; het toegangsslot is
  daarnaast een kijk-over-de-schouder-maatregel.

De plushelft en zijn lokale drawer blijven werken wanneer AI niet is toegestaan. De
AI-gate mag dus nooit een handmatig formulier blokkeren.

### B5 — Icoon, voorleesbare naam en zichtbaarheid

Het zichtbare icoon van de plushelft blijft `AppIcons.add`. `_PillHalf` rendert geen
tekstlabel; de label-string gaat naar `Semantics(label:)`. Daarom verandert per
contextactie de **voorleesbare naam**, niet de pilbreedte. Voorbeelden:

- één actie: “Gewichtsmeting toevoegen”;
- meerdere acties: “Toevoegen in Sportkalender”;
- algemene terugval: “Snel vastleggen”.

De AI-helft krijgt bij toegestane context een naam als “Vraag over gewicht”; bij een
dichte gate blijft het “Assistent”. De zichtbare bevestiging van AI-context staat na
openen in de assistent, niet als tekst in de pil.

### B6 — Terugval op algemeen

> **AANGEVULD 9 augustus 2026 na panel-review — lees dit eerst.**
> De terugval-condities hieronder noemen het **toegangsslot** niet. `GezondheidGuard` is
> een widget in de subtree en geen router-regel: op een vergrendeld medicatiescherm
> mount het scherm niet, publiceert het geen context, en leidt de pil de module alsnog
> uit de route af — waarna hij het volledige medicatieformulier over het gesloten slot
> heen opent. **Een gesloten toegangsslot is een terugval-conditie** en hoort in de lijst
> hieronder. Zie de sectie "Panel-revisies" onderaan.


Als geen contextactie van toepassing is — geen registratie, ontbrekende vereiste
context, onvoldoende recht of een rol-/profielconditie die niet geldt — opent de
plushelft de algemene vastlegdrawer. Hij verdwijnt niet en wordt niet inactief. Het
semantische label valt tegelijk terug op “Snel vastleggen”.

Een ontbrekende registratie voor een oppervlak dat in de route-audit wél een lokale
toevoeg-affordantie heeft, is tijdens de migratie geen geldige eindstand: dat oppervlak
houdt zijn lokale affordantie totdat zijn contract compleet is.

Hetzelfde geldt voor getelde routes buiten de shell: Inbox, Agenda, Lijstjes,
Instellingen en Gezin beheren houden hun lokale affordanties totdat de pil daar
daadwerkelijk rendert. Deze ADR kiest niet stil een routerverbouwing; dat werk moet
aansluiten op ADR-0024/E-NAV-12 en eerst als zelfstandige mechanieketappe landen.

### B7 — Lijstachtige drawers blijven standaard open

Voor Taken, gewone lijstdetails en Boodschappen geldt voorlopig `blijfOpen`: na een
geslaagde toevoeging blijft de drawer open, het opgeslagen invoerveld wordt geleegd,
keuzes die voor een reeks gelden (zoals winkel) blijven staan en de invoer houdt focus.
“Klaar”, terugvegen of buiten de drawer tikken keert terug naar het scherm.

Dit is een expliciet herzienbare aanname, geen universele eigenschap van alle drawers.

## Gevolgen

### Positief

- Eén vaste toevoegingang vervangt dubbele knoppen en inline varianten zonder
  formuliermogelijkheden te verliezen.
- Nieuwe modules kunnen via hetzelfde TEN-179-contract aan pil, assistent, Vandaag,
  dashboard en instellingen bijdragen.
- Actiecontext kan rijk zijn zonder dat lokale route-id's of complete records vanzelf
  naar de AI-dienst gaan.
- De gevoelige-domein-gate is zichtbaar eerlijk: dicht betekent algemeen, ook in label
  en openingsscherm.
- Schermlezers horen de werkelijke actie terwijl het zichtbare plus-icoon stabiel blijft.

### Negatief en risico's

- Inline toevoegen krijgt een drawerhandeling en kan ondanks `blijfOpen` trager voelen.
- Meervoudige, record- en rolgebonden acties vragen meer contract- en testoppervlak dan
  de oude FAB-bestandstest liet zien.
- Maximaal twintig zichtbare samenvattingen is bewust minder context dan de hele
  schermdataset; sommige vragen vereisen een vervolgvraag.
- Een fout in de contextprojector kan privacygevoeliger zijn dan een fout in de lokale
  drawer. Allowlist-, gate- en verzoektests zijn daarom een mergevoorwaarde.
- Tijdens de gefaseerde migratie bestaan oude en nieuwe patronen naast elkaar, maar
  nooit beide voor dezelfde al omgezette actie.

## Stopvoorwaarden

De uitvoering stopt voor de betrokken groep, zonder schermspecifieke workaround, als:

1. de pil niet betrouwbaar op Inbox, Agenda, Lijstjes, Instellingen of Gezin beheren kan
   worden gerenderd zonder de in ADR-0024 gekozen shelltopologie te breken;
2. een Navigator-gepusht detailscherm zijn actieve record-/sectiecontext niet kan
   publiceren en bij pop herstellen;
3. de drawer niet alle velden, rechten of bijlagenpaden van het vervangen formulier kan
   dragen;
4. de gevoelige-domein-gate context wel uit het verzoek maar niet uit label of zichtbare
   assistentchip onderdrukt;
5. een inline lijstflow niet meerdere toevoegingen achter elkaar kan uitvoeren zonder
   de drawer telkens opnieuw te openen.

## Wat de eigenaar nog kan omdraaien

Zonder deze ADR opnieuw te openen kan de eigenaar geen extra velden aan de AI-allowlist
toevoegen, de gevoelige gate omzeilen of een parallelle actielijst toestaan. De volgende
keuzes zijn wél expliciet herzienbaar en vragen bij wijziging een korte ADR-herziening:

1. `blijfOpen` na opslaan op lijstachtige schermen;
2. het maximum van 20 zichtbare samenvattingen (alleen lager of na privacyherweging
   hoger);
3. welke nu toegestane velden per module worden geschrapt of verder gemaskeerd;
4. of een module met meerdere acties direct het meest waarschijnlijke formulier opent
   of eerst een actiekeuze in dezelfde drawer toont;
5. of de zichtbare contextchip in de assistent per vraag of per geopende sessie geldt;
6. of aanvullende domeinen naast Geld en Gezondheid als gevoelig worden gemarkeerd.

## Afgewezen alternatieven

- **De algemene vastlegdrawer met voorgekozen module:** voegt een tussenstap toe en kan
  de volledige moduleformulieren niet betrouwbaar vervangen.
- **Lokale knoppen naast de pil behouden:** laat de oorspronkelijke dubbele bediening
  bestaan.
- **Context onzichtbaar meesturen:** kost dezelfde privacy- en implementatieruimte maar
  maakt niet controleerbaar wat de assistent weet.
- **Het module-icoon laten wisselen:** introduceert tientallen te leren iconen en helpt
  een schermlezer niet.
- **De plus uitschakelen zonder moduleactie:** maakt de universele pil half leeg en
  ontneemt de algemene vastlegroute.
- **Losse TEN-210-actieregistratie:** dupliceert het modulecontract dat TEN-179 juist als
  één bron definieert.

---

## Panel-revisies — 9 augustus 2026

Vier onafhankelijke lenzen (codex, Claude/Opus, GLM, DeepSeek V4 Flash) hebben deze ADR
adversarieel getoetst tegen de code. Alle vier kwamen zelfstandig op dezelfde kern uit.
De bevindingen hieronder zijn daarna door de hoofdsessie nageverifieerd; waar dat niet
lukte staat het als PLAUSIBEL.

### De kern: "context" is één woord voor drie onafhankelijke kanalen

Deze ADR beschrijft één beheerste context. In de code zijn het er drie, zonder
gemeenschappelijk knooppunt:

1. **Lokale recordcontext** uit gemounte subtrees (B2).
2. **De nieuwe allowlist-projectie** naar de assistent (B3).
3. **De bestaande assistent**, die bij elke vraag `_contextForAll()` uitvoert
   (`lib/features/assistant/presentation/assistant_providers.dart:108`, opbouw `:353-402`)
   en hele repositories uitleest — zonder enige `AiGate`-controle in dat bestand.

Zolang die drie niet achter één afdwingbare grens zitten, is de privacybelofte niet
controleerbaar: de contextchip kan netjes twintig rijen tonen terwijl het echte verzoek
de volledige dump bevat. Dit is **huidig gedrag**, niet iets dat TEN-210 introduceert —
daarom staat het apart als **TEN-225**.

### De vormfout: de gate hoort per rij, niet per scherm

`AiGate.allows()` sleutelt op een `domainId` dat bij het **oppervlak** hoort
(`lib/core/ai/ai_gate.dart:33-41`). Inhoud erft die gevoeligheid niet.

**Bewezen geval:** Routines is een gezondheidsmodule en spiegelt titel én notities de
agenda in (`routines_providers.dart:256-272`), met `sourceModuleId: kRoutinesModuleId`.
Agenda is een kernoppervlak zonder domein, dus de gevoelige-domein-tak wordt nooit
betreden. Een rij "Insuline 22:00" gaat daarmee mee, óók als de gebruiker
gezondheids-AI heeft uitgezet.

### Eigenaarsbesluit 9 augustus 2026 — drie wijzigingen

**1. De gate draait per rij, op herkomst.** Een rij erft de gevoeligheid van zijn
**bronmodule**, niet van het scherm waarop hij staat. Het veld daarvoor bestaat al:
`sourceModuleId` staat op agenda-items (`calendar_event.dart:31`), taken
(`task.dart:76`), vaste kosten en Vandaag-rijen, en de spiegelmachinerie
(`primitive_mirror.dart`) vult hem consequent. De regel is dus afdwingbaar zonder nieuw
datamodel: `sourceModuleId → moduleDescriptor → domain.sensitive` bepaalt of een rij mee
mag.

**2. De context wordt begrensd door het actieve scherm.** Dat is niet alleen een
privacymaatregel maar een kwaliteitsmaatregel: nu gaat er bij elke vraag een brede dump
mee, terwijl we uit het scherm al weten welke module relevant is. Minder én relevanter.

**3. Eén getypeerd knooppunt.** Alles wat richting het model gaat, gaat door één
gesloten, getypeerde serializer die module, domein, veldnamen en recordlimiet kent, en
die een projector niet kan omzeilen. Vandaag accepteert `AiRequest` willekeurige strings
en serialiseert de proxy die zonder veldcontrole; "een optionele projector plus negatieve
tests" is geen grens.

### De erkende grens van deze regels

Herkomst dekt **afgeleide** rijen. **Zelf getypte tekst dekt hij niet:** een handmatig
ingevoerde agenda-afspraak "GGZ-intake" heeft geen herkomst en is niet van andere tekst
te onderscheiden zonder de inhoud te inspecteren — wat zelf weer verzending zou vergen.

De eigenaar accepteert die grens expliciet, mits de app er duidelijk over is: wat je op
dit scherm ziet gaat mee, gevoelige modules kun je uitzetten, en wat je zelf typt blijft
je eigen verantwoordelijkheid. Een voorbewerker op het toestel die wél naar inhoud kan
kijken zonder dat er iets de telefoon verlaat, is genoteerd als **toekomstige stap** en
is geen voorwaarde voor TEN-210.

### Besluiten uit deze ADR die herzien moeten worden

- **B2** — "publiceren bij mount, intrekken bij unmount" is ongeldig in de huidige
  shell. `StatefulShellRoute.indexedStack` houdt takken gemount; een detailscherm in een
  andere tab blijft dus publiceren en wint van het scherm dat de gebruiker ziet. Er is
  een expliciet **actieve-tak-signaal** nodig; mount is niet hetzelfde als zichtbaar.
- **B4** — de gate-check moet per rij op herkomst draaien (zie boven), niet alleen op het
  domein van het oppervlak.
- **B6** — de terugval-lijst noemt het **toegangsslot** niet. `GezondheidGuard` is een
  widget en geen router-regel, dus op een vergrendeld medicatiescherm leidt de pil de
  module nog steeds uit de route af en opent hij het volledige formulier over het slot
  heen. Het slot hoort in de terugval-condities.
- **De telleenheid.** Deze ADR telt route-oppervlakken, terwijl het probleem
  (dubbele bediening) zich op het niveau van **affordanties** afspeelt. Eén
  "Maaltijden-oppervlak" is in werkelijkheid een zwevende knop plus zeven dagrijen plus
  een veegactie per maaltijd. En twee generieke toevoegsystemen komen in de telling
  helemaal niet voor: de favorietenbalk in de shell-AppBar en het add-slot op
  dashboardwidgets. Zonder die mee te tellen houdt `/taken` ná de volledige migratie nog
  steeds meerdere toevoegknoppen — precies wat B1 belooft weg te nemen.

### Correctie op de tellingen
41 actieve oppervlakken (niet 42) en 30 met een zwevende knop (niet 31): rij #5
`/module/bewaarlijsten` is sinds TEN-207 een doorverwijzing. Onafhankelijk bevestigd door
drie lenzen én door de etappe-0-lane, die het getal zelf uit de code afleidde. De
eindpoort die "exact 42" eist is daarmee onhaalbaar zonder deze correctie.

### Gevolg voor de fasering
Etappe 0 (contract en inventaris) is af en raakt niets van het bovenstaande — puur
additief. **Etappe 1 gaat niet van start in zijn huidige vorm.** De volgorde wordt
omgekeerd: eerst het knooppunt en het actieve-tak-signaal, met de per-rij-gate erin, en
pas als die aantoonbaar werken verdwijnt de eerste lokale knop.
