fix(import): het faalbeleid per dia werkt echt (#812) #819

Merged
brenno merged 6 commits from fix/import-faalbeleid-812 into main 2026-07-24 20:13:06 +00:00
Owner

SlideFailurePolicy bestond, werd netjes gezet, en werd nooit gelezen: elke dia kreeg best-effort, en skip/rasterize waren onbereikbaar. Dit maakt er een echt beslismoment van.

Sluit #812.

Wat er nu gebeurt

Bij een import van één bestand verschijnt een vraag zodra er dia's zijn die écht iets kwijtraken — per dia een keuze uit Zo volledig mogelijk (de dia zo compleet mogelijk, met een 'niet overgenomen'-notitie ernaast), Alleen de afbeelding (houd het beeld, laat de tekst vallen) en Overslaan (alleen een notitie die zegt waarom). De redenen per dia staan erbij: zonder te weten wát er misging is de keuze een gok. Eén knop zet alles tegelijk om, en Niet meer vragen laat de import het voortaan zelf doen.

De bulk-wachtrij vraagt bewust niets en neemt alles zo volledig mogelijk over — tien bestanden maal een vraag per dia is geen route.

Drie grenzen die de tests vastleggen

  • Het beleid raakt alleen dia's met écht verlies. Een dia die schoon converteert blijft ongemoeid, ook bij "overslaan voor alles". Anders zou één keuze een heel deck opruimen.
  • Afbreken breekt af. Een eerste versie zette een null (afbreken, of het venster wegklikken) stilzwijgend om in "ga door met de standaard" — daarmee was de vraag een schijnvertoning.
  • De standaardkeuze vernietigt niets. Dit is de scherpste, en hij kwam boven bij het schrijven van de documentatie: de uitleg beloofde "wat u niet aanraakt wordt zo volledig mogelijk overgenomen", terwijl de voorselectie op imageOnly stond zodra een dia een afbeelding had. Wie niets aanraakte en op Importeren drukte, verloor juist de tekst van díé dia's. Elke dia begint nu op best-effort, en het veld ProblemSlide.suggestedPolicy is geschrapt: een voorstel dat tegelijk de standaard is, is geen voorstel maar een besluit dat voor je genomen is.

Twee dingen eerlijk benoemd

rasterize heet nu imageOnly. De oude naam beloofde renderen. Het bronproject riep daarvoor LibreOffice aan als extern proces; dat gebeurt hier niet — geen subproces, geen externe afhankelijkheid. Wat die code feitelijk deed zodra er een plaatje was, is precies dit: houd de afbeeldingen, laat de rest vallen. Een dia zónder afbeelding valt terug op overslaan, want een afbeeldingsdia zonder afbeelding is niets. De gids zegt dit met zoveel woorden, zodat de naam geen verwachting wekt die hij niet waarmaakt.

De import is nu tweefasig. prepare() leest en classificeert, PreparedImport.build(policies:) bouwt. Reden: de vraag valt ertússen, en een Keynote van vijftig dia's parseer je niet twee keer om één vraag te kunnen stellen. importBytes() blijft bestaan als wikkel voor wie niets te vragen heeft (de wachtrij, en de tests).

Terzijde: de knoppenrij is een Wrap en geen Row. Met de labels in 31 talen loopt een vaste rij over, en dan is de laatste knop onbereikbaar — Iers en Hongaars zijn daar het krapst.

Poort

make check groen (exit 0), 6555 tests, dekking 86,5%, geen basislijn verhoogd en geen plafond geraakt. Gerebased op de huidige main en daarna opnieuw geverifieerd. Geen pubspec.yaml-wijziging, dus geen SBOM-ronde.

Docs: USER_GUIDE, CHANGELOG, SOURCE_MAP, KNOWN_LIMITATIONS, FAQ. Onderweg zijn drie onjuiste beweringen in SOURCE_MAP rechtgezet — waaronder de regel die al vóór deze tak beweerde dat het faalbeleid werd toegepast.

🤖 Generated with Claude Code

`SlideFailurePolicy` bestond, werd netjes gezet, en werd **nooit gelezen**: elke dia kreeg best-effort, en `skip`/`rasterize` waren onbereikbaar. Dit maakt er een echt beslismoment van. Sluit #812. ## Wat er nu gebeurt Bij een import van **één bestand** verschijnt een vraag zodra er dia's zijn die écht iets kwijtraken — per dia een keuze uit **Zo volledig mogelijk** (de dia zo compleet mogelijk, met een 'niet overgenomen'-notitie ernaast), **Alleen de afbeelding** (houd het beeld, laat de tekst vallen) en **Overslaan** (alleen een notitie die zegt waarom). De redenen per dia staan erbij: zonder te weten wát er misging is de keuze een gok. Eén knop zet alles tegelijk om, en *Niet meer vragen* laat de import het voortaan zelf doen. De **bulk-wachtrij vraagt bewust niets** en neemt alles zo volledig mogelijk over — tien bestanden maal een vraag per dia is geen route. ## Drie grenzen die de tests vastleggen - **Het beleid raakt alleen dia's met écht verlies.** Een dia die schoon converteert blijft ongemoeid, ook bij "overslaan voor alles". Anders zou één keuze een heel deck opruimen. - **Afbreken breekt af.** Een eerste versie zette een `null` (afbreken, of het venster wegklikken) stilzwijgend om in "ga door met de standaard" — daarmee was de vraag een schijnvertoning. - **De standaardkeuze vernietigt niets.** Dit is de scherpste, en hij kwam boven bij het schrijven van de documentatie: de uitleg beloofde "wat u niet aanraakt wordt zo volledig mogelijk overgenomen", terwijl de voorselectie op `imageOnly` stond zodra een dia een afbeelding had. Wie niets aanraakte en op Importeren drukte, verloor juist de tekst van díé dia's. Elke dia begint nu op best-effort, en het veld `ProblemSlide.suggestedPolicy` is geschrapt: een voorstel dat tegelijk de standaard is, is geen voorstel maar een besluit dat voor je genomen is. ## Twee dingen eerlijk benoemd **`rasterize` heet nu `imageOnly`.** De oude naam beloofde renderen. Het bronproject riep daarvoor LibreOffice aan als extern proces; dat gebeurt hier niet — geen subproces, geen externe afhankelijkheid. Wat die code feitelijk deed zodra er een plaatje was, is precies dit: houd de afbeeldingen, laat de rest vallen. Een dia zónder afbeelding valt terug op overslaan, want een afbeeldingsdia zonder afbeelding is niets. De gids zegt dit met zoveel woorden, zodat de naam geen verwachting wekt die hij niet waarmaakt. **De import is nu tweefasig.** `prepare()` leest en classificeert, `PreparedImport.build(policies:)` bouwt. Reden: de vraag valt ertússen, en een Keynote van vijftig dia's parseer je niet twee keer om één vraag te kunnen stellen. `importBytes()` blijft bestaan als wikkel voor wie niets te vragen heeft (de wachtrij, en de tests). Terzijde: de knoppenrij is een `Wrap` en geen `Row`. Met de labels in 31 talen loopt een vaste rij over, en dan is de laatste knop onbereikbaar — Iers en Hongaars zijn daar het krapst. ## Poort `make check` groen (exit 0), 6555 tests, dekking 86,5%, geen basislijn verhoogd en geen plafond geraakt. Gerebased op de huidige main en daarna opnieuw geverifieerd. Geen `pubspec.yaml`-wijziging, dus geen SBOM-ronde. Docs: `USER_GUIDE`, `CHANGELOG`, `SOURCE_MAP`, `KNOWN_LIMITATIONS`, `FAQ`. Onderweg zijn drie onjuiste beweringen in `SOURCE_MAP` rechtgezet — waaronder de regel die al vóór deze tak beweerde dat het faalbeleid werd toegepast. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
`SlideFailurePolicy` werd gezet maar nooit gelezen: elke dia kreeg
best-effort en `skip`/`rasterize` waren onbereikbaar. De bouwer past het
beleid nu per bron-dia toe, en de service kreeg een tweefase-vorm — `prepare`
leest en classificeert, `PreparedImport.build` bouwt met het gekozen beleid —
zodat de vraag ertússen past zonder het bestand twee keer te parseren.

`rasterize` heet nu `imageOnly`. Rasteriseren impliceert renderen, en dat kan
hier niet: geen subproces, geen externe afhankelijkheid. Wat de bron-code
feitelijk deed was 'houd alleen de afbeeldingen', en zo heet het nu.

De belangrijkste regel zit in de bouwer en heeft een eigen test: het beleid
geldt alleen voor dia's met écht verlies. Anders zou één keuze 'overslaan' een
heel deck opruimen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bij een enkelvoudige import verschijnt de vraag zodra er dia's zijn die écht
iets kwijtraken: per dia zo volledig mogelijk, alleen de afbeelding, of
overslaan — met de redenen erbij, want zonder te weten wát er misging is de
keuze een gok. Het voorstel staat voorgeselecteerd, er is één knop die alles
tegelijk omzet, en "niet meer vragen" laat de import het voortaan zelf doen.

De bulk-wachtrij vraagt bewust niets: tien bestanden maal een vraag per dia is
geen route.

Twee dingen die de tests afdwongen. Afbreken breekt nu ook werkelijk af — een
eerste versie zette een null stilzwijgend om in "ga door met de standaard",
waarmee de vraag een schijnvertoning was. En de knoppenrij is een Wrap: met de
teksten in 31 talen loopt een vaste rij over, en dan is de laatste knop niet
meer te bereiken.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
De drie keuzelabels zijn bewust kort gehouden — ze staan als knoppen naast
elkaar. Iers en Hongaars zijn de langste; die passen binnen de Wrap die de
dialoog daarvoor gebruikt, en zijn de eerste die overlopen als de breedte ooit
krimpt. "Dia" volgt het woord dat de presentatorweergave al gebruikt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
De uitleg boven de dialoog belooft dat wat je niet aanraakt zo volledig
mogelijk wordt overgenomen. De voorselectie deed het tegenovergestelde: die
stond op het "voorstel" uit ProblemSlide, en dat was `imageOnly` zodra een dia
een afbeelding had. Wie niets aanraakte en op Importeren drukte, verloor juist
de tekst van díé dia's — de dialoog loog over zijn eigen standaardhandeling.

Elke dia begint nu op best-effort. Het voorstel-veld is helemaal weg: een
voorstel dat tegelijk de standaard is, is geen voorstel maar een besluit dat
voor je genomen is, en dit besluit was destructief. Wil advies terugkomen, dan
komt het terug als advies, náást een veilige standaard.

Twee tests leggen het vast: de destructieve keuze staat niet voorgeselecteerd,
en niets aanraken levert overal best-effort op.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
USER_GUIDE beschrijft wanneer de vraag verschijnt, wat de drie keuzes doen en
dat de wachtrij niets vraagt. Expliciet: "Alleen de afbeelding" rendert géén
dia — er is geen extern programma en geen subproces; wat overblijft is wat er
als plaatje in het bestand zat.

Drie beweringen in SOURCE_MAP klopten niet en zijn rechtgezet: `buildDeck`
bestaat niet (het is `DeckBuilder.build`), de regel beweerde al vóór deze tak
dat het faalbeleid werd toegepast (dat was juist níét zo), en "valt terug op de
eerste afbeelding" is bij twee bronafbeeldingen een twoImages-dia.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(import): de source map beschreef nog het geschrapte voorstel-veld (#812)
All checks were successful
scans / scans (pull_request) Successful in 3m19s
50c65343fe
De regel voor `import_decision_dialog.dart` zei dat elke rij op de
`suggestedPolicy` van `ProblemSlide` begint. Dat veld bestaat sinds 98240b5f
niet meer, en juist omdat het weg is: de voorselectie stond op `imageOnly`
zodra een dia een afbeelding had, en dat vernietigde de tekst van precies de
dia's waar de dialoog naar vraagt. De docs beschreven dus het gedrag dat de
fix heeft weggehaald.

Nu staat er wat de code doet — alles begint op `bestEffort` — plus de reden,
zodat niemand het "voorstel" per ongeluk terugbouwt als standaard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit c50d1b1e6d into main 2026-07-24 20:13:06 +00:00
brenno deleted branch fix/import-faalbeleid-812 2026-07-24 20:13:07 +00:00
Sign in to join this conversation.
No description provided.