[Feature] Sidecars travel to git too: notes, ink, seal #541

Closed
opened 2026-07-22 11:31:48 +00:00 by brenno · 12 comments
Owner

Problem / motivation

Media now travels to a git repository (#540). The sidecars still do not, and the pre-commit warning still says so:

  • .ink.json — the drawing layer
  • .user-notes.json — the presenter's own notes
  • .seal.json — the seal and signature

Nothing under lib/services/git/ writes any of them. Save a deck to a folder and they travel; move that deck to git and they are gone, with no error to point at. The same reasoning that put media in the repo applies: if presentations live in git, the work that belongs to them lives there too.

The three are not one job

Notes are the easy case. Small, textual, and D7 already decided the merge: .notes takes git's ordinary text merge. Write it next to deck.md on a stable path, like the chart data — not in the content-addressed pool, where every edited character would mint a new blob and orphan the last one.

Ink is the hard case. D7 decided the outcome — the merge driver unions the stroke sets, because two people drawing on one slide did not disagree — but the design says explicitly that per-stroke identity and erasure-versus-union are consequences belonging to the annotation file format, not to the storage design. That format question comes first, and the merge=ocideck-ink driver is still unwritten (§14 lists it as open, and it has had nothing to act on because no sidecar reached the repo at all).

The seal is a different kind of question, not a bigger one. A seal is a statement about a specific artefact. What does it mean once the deck lives in a branch that can be rewritten, cherry-picked or force-pushed? Possibly it should travel and be re-verified on open; possibly a sealed deck should not be committed at all. That decision belongs with whoever owns the seal design, and it should be made before code, not during.

Proposed order

  1. Notes — self-contained, decided, small.
  2. Ink — settle stroke identity in the annotation format first, then the merge driver, then the write path.
  3. Seal — decide what a seal means under version control before writing anything.

Regression guard

Extend test/git_omissions_warning_test.dart as each one lands: the warning must lose exactly the line that became untrue and keep the rest. A warning that overstates is one people learn to dismiss wholesale — which is why media was removed from it in #540 rather than left in "just in case".

**Problem / motivation** Media now travels to a git repository (#540). The sidecars still do not, and the pre-commit warning still says so: - `.ink.json` — the drawing layer - `.user-notes.json` — the presenter's own notes - `.seal.json` — the seal and signature Nothing under `lib/services/git/` writes any of them. Save a deck to a folder and they travel; move that deck to git and they are gone, with no error to point at. The same reasoning that put media in the repo applies: if presentations live in git, the work that belongs to them lives there too. **The three are not one job** *Notes* are the easy case. Small, textual, and D7 already decided the merge: `.notes` takes git's ordinary text merge. Write it next to `deck.md` on a stable path, like the chart data — not in the content-addressed pool, where every edited character would mint a new blob and orphan the last one. *Ink* is the hard case. D7 decided the outcome — the merge driver **unions** the stroke sets, because two people drawing on one slide did not disagree — but the design says explicitly that per-stroke identity and erasure-versus-union are consequences belonging to the *annotation file format*, not to the storage design. That format question comes first, and the `merge=ocideck-ink` driver is still unwritten (§14 lists it as open, and it has had nothing to act on because no sidecar reached the repo at all). *The seal* is a different kind of question, not a bigger one. A seal is a statement about a specific artefact. What does it mean once the deck lives in a branch that can be rewritten, cherry-picked or force-pushed? Possibly it should travel and be re-verified on open; possibly a sealed deck should not be committed at all. That decision belongs with whoever owns the seal design, and it should be made before code, not during. **Proposed order** 1. Notes — self-contained, decided, small. 2. Ink — settle stroke identity in the annotation format first, then the merge driver, then the write path. 3. Seal — decide what a seal means under version control before writing anything. **Regression guard** Extend `test/git_omissions_warning_test.dart` as each one lands: the warning must lose exactly the line that became untrue and keep the rest. A warning that overstates is one people learn to dismiss wholesale — which is why media was removed from it in #540 rather than left in "just in case".
Author
Owner

Opgepakt — deel 1 (notities). Tak: feat/notities-naar-git. Reikwijdte: lib/services/git/deck_repo_serializer.dart, lib/services/user_notes_codec.dart, lib/state/tabs_provider_git.dart, lib/widgets/shell/shell_actions_git.dart, plus test/git_omissions_warning_test.dart en het ontwerpdocument.

Ink en zegel blijven bewust liggen: die wachten op een besluit over respectievelijk streekidentiteit in het annotatieformaat en wat een zegel onder versiebeheer betekent. Die twee zijn van jou, niet van deze tak.

Eén ding dat tijdens het lezen opviel en wat ik hier meeneem: D7 belooft dat .notes gewoon door git's tekst-merge gaat, maar UserNotesCodec.encode schrijft de hele sidecar op één regel. Op één regel is élke wijziging een botsing op dezelfde regel — de belofte klopt dan niet. De repo-kant krijgt daarom een ingesprongen vorm, zodat de merge per notitie werkt zoals D7 zegt.

Opgepakt — deel 1 (notities). Tak: `feat/notities-naar-git`. Reikwijdte: `lib/services/git/deck_repo_serializer.dart`, `lib/services/user_notes_codec.dart`, `lib/state/tabs_provider_git.dart`, `lib/widgets/shell/shell_actions_git.dart`, plus `test/git_omissions_warning_test.dart` en het ontwerpdocument. Ink en zegel blijven bewust liggen: die wachten op een besluit over respectievelijk streekidentiteit in het annotatieformaat en wat een zegel onder versiebeheer betekent. Die twee zijn van jou, niet van deze tak. Eén ding dat tijdens het lezen opviel en wat ik hier meeneem: D7 belooft dat `.notes` gewoon door git's tekst-merge gaat, maar `UserNotesCodec.encode` schrijft de hele sidecar op één regel. Op één regel is élke wijziging een botsing op dezelfde regel — de belofte klopt dan niet. De repo-kant krijgt daarom een ingesprongen vorm, zodat de merge per notitie werkt zoals D7 zegt.
Author
Owner

Deel 1 (notities) staat op main9450a772, PR #673. Het issue blijft open voor ink en zegel.

De notities gaan als deck.user-notes.json naast deck.md, op een vast pad, en komen bij het openen op de juiste dia terug. De waarschuwing verloor exact die ene regel.

D7 klopte niet zoals het er stond. Het besluit zegt dat dit bestand door git's gewone tekst-merge gaat zodat twee auteurs op verschillende dia's schoon samenvoegen. Maar jsonEncode zet de sidecar op één regel, en dan botst élke wijziging met élke andere. De repo-kopie wordt nu ingesprongen geschreven; de kopie op schijf blijft compact. Bijgewerkt in §9.7 en in D7 zelf.

Wat de review opleverde, want dat is de helft van dit werk. Drie manieren waarop notities stil verdwenen — alle drie ontstaan dóór deze wijziging, en daarmee slechter dan de waarschuwing die hij verving:

  1. de offline-wachtrij (SyncEngine leidt deletes af uit wat lokaal ontbreekt);
  2. de merge, bij het gewoonste geval dat er is — twee auteurs, notities op verschillende dia's, beider werk weg met status merged;
  3. "ik kon het niet lezen" werd "ik gooi het weg", en later bleek dat ook "ik schrijf eroverheen" te zijn.

En reparatie 2 landde eerst op het REST-pad terwijl native het pad is dat de app kiest zodra git er is. mergeRemote geeft nu per kant een lezer mee.

Bijvangst voor #518: de klasseratchet dwong het hele native oplosblok naar de servicelaag (resolveRepoDeckMerge). TabsNotifier staat 16 regels ónder zijn oude plafond en dat plafond is meeverlaagd.

Apart gemeld: #670 — een native merge verwijdert data/*.json, zowel in de faaltak als bij een geslaagde merge. Dat stond er vóór deze tak al.

Wat hier open blijft, en waarom het op jou wacht en niet op werk:

  • Ink — de union-merge is besloten, maar per-streek-identiteit en wissen-tegenover-verenigen horen bij het annotatieformaat. Dat besluit eerst.
  • Zegel — wat betekent een zegel op een tak die herschreven, gecherrypickt of geforceerd geduwd kan worden? Reist hij mee en wordt hij bij het openen herverifieerd, of hoort een verzegeld deck helemaal niet gecommit te worden?
**Deel 1 (notities) staat op main** — `9450a772`, PR #673. Het issue blijft open voor ink en zegel. De notities gaan als `deck.user-notes.json` naast `deck.md`, op een vast pad, en komen bij het openen op de juiste dia terug. De waarschuwing verloor exact die ene regel. **D7 klopte niet zoals het er stond.** Het besluit zegt dat dit bestand door git's gewone tekst-merge gaat zodat twee auteurs op verschillende dia's schoon samenvoegen. Maar `jsonEncode` zet de sidecar op één regel, en dan botst élke wijziging met élke andere. De repo-kopie wordt nu ingesprongen geschreven; de kopie op schijf blijft compact. Bijgewerkt in §9.7 en in D7 zelf. **Wat de review opleverde, want dat is de helft van dit werk.** Drie manieren waarop notities stil verdwenen — alle drie ontstaan dóór deze wijziging, en daarmee slechter dan de waarschuwing die hij verving: 1. de offline-wachtrij (`SyncEngine` leidt `deletes` af uit wat lokaal ontbreekt); 2. de merge, bij het gewoonste geval dat er is — twee auteurs, notities op verschillende dia's, beider werk weg met status *merged*; 3. "ik kon het niet lezen" werd "ik gooi het weg", en later bleek dat ook "ik schrijf eroverheen" te zijn. En reparatie 2 landde eerst op het REST-pad terwijl native het pad is dat de app kiest zodra git er is. `mergeRemote` geeft nu per kant een lezer mee. **Bijvangst voor #518:** de klasseratchet dwong het hele native oplosblok naar de servicelaag (`resolveRepoDeckMerge`). `TabsNotifier` staat 16 regels ónder zijn oude plafond en dat plafond is meeverlaagd. **Apart gemeld:** #670 — een native merge verwijdert `data/*.json`, zowel in de faaltak als bij een geslaagde merge. Dat stond er vóór deze tak al. **Wat hier open blijft, en waarom het op jou wacht en niet op werk:** - **Ink** — de union-merge is besloten, maar per-streek-identiteit en wissen-tegenover-verenigen horen bij het annotatieformaat. Dat besluit eerst. - **Zegel** — wat betekent een zegel op een tak die herschreven, gecherrypickt of geforceerd geduwd kan worden? Reist hij mee en wordt hij bij het openen herverifieerd, of hoort een verzegeld deck helemaal niet gecommit te worden?
Author
Owner

Twee ontwerpbesluiten genomen, 22-07-2026. Ze stonden de resterende twee delen in de weg, en nu niet meer.

Zegel (deel 3): alleen op een tag, niet op een tak.
Een verzegeld deck mag naar een release-tag, niet naar een werkbranch. Dat sluit aan bij wat een zegel bedoelt — díé bytes, dít artefact — en een tak biedt dat niet: die kan herschreven, gecherrypickt en geforceerd geduwd worden, en een zegel dat zoiets overleeft zegt niets meer. Een tag is bedoeld als momentopname en staat onder refbescherming (P8).

Gevolg voor de bouw: het zegel reist mee in de commitset van een versie-uitgifte, en een gewone opslag naar een werkbranch weigert een verzegeld deck met uitleg — dus de huidige waarschuwing wordt daar een weigering, geen melding achteraf. Een zegel heeft daarmee géén merge-semantiek nodig: twee versies van één zegel is geen conflict maar een vergissing, en op een tag kan het niet ontstaan.

Ink (deel 2): wissen wordt een grafsteen.
De vereniging blijft de merge, maar het annotatieformaat krijgt per streek een stabiele identiteit én een gewist-markering, zodat een wissing een merge overleeft.

De reden om níét voor pure vereniging te kiezen: dan komt een gewiste streek terug. Dat is precies het gedrag dat in deel 1 bij de notities is dichtgezet — een wissing die terugkomt is erger dan een die niet werkt, want de gebruiker dacht dat het weg was. "Nooit inhoud verliezen" mag niet omslaan in "niets kan weg".

Gevolg voor de bouw, en dit is de volgorde: eerst het annotatieformaat (streekidentiteit + grafsteen, met een versieverhoging en een leespad voor oude bestanden), dán de merge-driver merge=ocideck-ink, dán het schrijfpad. De driver moet bovendien in de app reproduceerbaar zijn, want een kloon gemaakt door een ander werktuig heeft hem niet.

Beide besluiten gaan naar docs/design/GIT_STORAGE.md §14/D7 zodra ik eraan toekom; ze staan hier zodat ze niet aan deze reactie vastzitten.

**Twee ontwerpbesluiten genomen, 22-07-2026.** Ze stonden de resterende twee delen in de weg, en nu niet meer. **Zegel (deel 3): alleen op een tag, niet op een tak.** Een verzegeld deck mag naar een release-tag, niet naar een werkbranch. Dat sluit aan bij wat een zegel bedoelt — díé bytes, dít artefact — en een tak biedt dat niet: die kan herschreven, gecherrypickt en geforceerd geduwd worden, en een zegel dat zoiets overleeft zegt niets meer. Een tag is bedoeld als momentopname en staat onder refbescherming (P8). Gevolg voor de bouw: het zegel reist mee in de commitset van een versie-uitgifte, en een gewone opslag naar een werkbranch weigert een verzegeld deck met uitleg — dus de huidige waarschuwing wordt daar een weigering, geen melding achteraf. Een zegel heeft daarmee géén merge-semantiek nodig: twee versies van één zegel is geen conflict maar een vergissing, en op een tag kan het niet ontstaan. **Ink (deel 2): wissen wordt een grafsteen.** De vereniging blijft de merge, maar het annotatieformaat krijgt per streek een stabiele identiteit én een gewist-markering, zodat een wissing een merge overleeft. De reden om níét voor pure vereniging te kiezen: dan komt een gewiste streek terug. Dat is precies het gedrag dat in deel 1 bij de notities is dichtgezet — een wissing die terugkomt is erger dan een die niet werkt, want de gebruiker dacht dat het weg was. "Nooit inhoud verliezen" mag niet omslaan in "niets kan weg". Gevolg voor de bouw, en dit is de volgorde: eerst het annotatieformaat (streekidentiteit + grafsteen, met een versieverhoging en een leespad voor oude bestanden), dán de merge-driver `merge=ocideck-ink`, dán het schrijfpad. De driver moet bovendien in de app reproduceerbaar zijn, want een kloon gemaakt door een ander werktuig heeft hem niet. Beide besluiten gaan naar `docs/design/GIT_STORAGE.md` §14/D7 zodra ik eraan toekom; ze staan hier zodat ze niet aan deze reactie vastzitten.
Author
Owner

Je twee ontwerpbesluiten staan nu in GIT_STORAGE.md, waar je schreef dat ze hoorden (PR #702, op main). Het issue blijft open voor de bouw.

D12 is nieuw — het zegel hoort op een tag, niet op een tak — met de redenering en de twee gevolgen voor de bouw: meereizen in de commitset van een versie-uitgifte, en een gewone opslag naar een werkbranch die een verzegeld deck weigert in plaats van er achteraf over te waarschuwen.

D7 is aangevuld met de grafsteen, inclusief de bouwvolgorde, want die is niet vrij: eerst het annotatieformaat (streekidentiteit + grafsteen, met versieverhoging en leespad voor oude bestanden), dan de driver, dan het schrijfpad.

§9.7 draagt ze allebei. Daar stond nog dat erasure-vs-union "een keuze is die bij het annotatieformaat hoort, niet bij dit document" — precies de zin die je besluit inhaalde. Ik heb erbij gezet waarom de twee antwoorden tegengesteld zijn, want dat is de vraag die de volgende lezer stelt: ink is werk dat twee mensen allebei kunnen toevoegen, een zegel is een uitspraak van één iemand over één exacte set bytes.

Wat er niet in zit is de bouw. Voor het zegel is dat nu een afgebakende klus; voor ink begint hij bij een formaatwijziging met versieverhoging. Beide horen in een eigen ronde.

Je twee ontwerpbesluiten staan nu in `GIT_STORAGE.md`, waar je schreef dat ze hoorden (PR #702, op main). **Het issue blijft open** voor de bouw. **D12 is nieuw** — het zegel hoort op een tag, niet op een tak — met de redenering en de twee gevolgen voor de bouw: meereizen in de commitset van een versie-uitgifte, en een gewone opslag naar een werkbranch die een verzegeld deck **weigert** in plaats van er achteraf over te waarschuwen. **D7 is aangevuld** met de grafsteen, inclusief de bouwvolgorde, want die is niet vrij: eerst het annotatieformaat (streekidentiteit + grafsteen, met versieverhoging en leespad voor oude bestanden), dan de driver, dan het schrijfpad. **§9.7 draagt ze allebei.** Daar stond nog dat erasure-vs-union "een keuze is die bij het annotatieformaat hoort, niet bij dit document" — precies de zin die je besluit inhaalde. Ik heb erbij gezet waarom de twee antwoorden tegengesteld zijn, want dat is de vraag die de volgende lezer stelt: ink is werk dat twee mensen allebei kunnen toevoegen, een zegel is een uitspraak van één iemand over één exacte set bytes. **Wat er niet in zit is de bouw.** Voor het zegel is dat nu een afgebakende klus; voor ink begint hij bij een formaatwijziging met versieverhoging. Beide horen in een eigen ronde.
Author
Owner

Opgepakt — deel 3 (het zegel). Tak: feat/zegel-naar-git-541. Ink laat ik liggen: dat begint bij een formaatwijziging met versieverhoging en hoort een eigen ronde te krijgen, precies zoals je schreef.

Reikwijdte volgens D12: het zegel reist mee in de commitset van een versie-uitgifte, en een gewone opslag naar een werkbranch weigert een verzegeld deck mét uitleg in plaats van er achteraf over te waarschuwen. Dus services/git/deck_repo_serializer.dart (de commitset), het opslagpad in state/tabs_provider_git.dart, en test/git_omissions_warning_test.dart — die moet exact de zegelregel verliezen en de inkregel houden.

Ik begin met de code tegen D12 te leggen; is de weigering er ergens al half, dan meld ik dat voordat ik bouw.

Opgepakt — deel 3 (het zegel). Tak: `feat/zegel-naar-git-541`. Ink laat ik liggen: dat begint bij een formaatwijziging met versieverhoging en hoort een eigen ronde te krijgen, precies zoals je schreef. Reikwijdte volgens D12: het zegel reist mee in de commitset van een versie-uitgifte, en een gewone opslag naar een werkbranch weigert een verzegeld deck mét uitleg in plaats van er achteraf over te waarschuwen. Dus `services/git/deck_repo_serializer.dart` (de commitset), het opslagpad in `state/tabs_provider_git.dart`, en `test/git_omissions_warning_test.dart` — die moet exact de zegelregel verliezen en de inkregel houden. Ik begin met de code tegen D12 te leggen; is de weigering er ergens al half, dan meld ik dat voordat ik bouw.
Author
Owner

Deel 3 (het zegel) staat op main — `0949cc2c` (PR #733). Het issue blijft open voor ink.

Wat er nu gebeurt. Een verzegeld deck wordt geweigerd bij het opslaan naar git, met uitleg, in plaats van mee te gaan terwijl het zegel stil wegvalt. De weigering staat in het opslagpad zelf en niet alleen in een dialoog: dat is de enige plek waar élke aanroeper langskomt, en een poort die je omzeilt door een andere knop te gebruiken is geen poort. De interface legt hem uit met één knop en zonder "toch opslaan".

De waarschuwing verloor exact de zegelregel en houdt de tekeningen, zoals je regressie-eis vroeg. Twee tests bewaken dat: dat de weigering komt, en dat er bij een verzegeld deck mét tekeningen niet alsnog twee dialogen achter elkaar staan.

Nu het punt dat er echt toe doet, want het is een bevinding en geen verslag.

Je besluit noemde twee gevolgen voor de bouw. Het tweede is af. Het eerste is niet te bouwen zoals het er staat, en dat had ik niet gezien toen ik het issue oppakte:

het zegel reist mee in de commitset van een versie-uitgifte

tagRelease tagt de kop van de standaardbranch en commit niets. Er ís op dat moment geen commitset om in mee te reizen. En de enige weg naar de standaardbranch is een gemergede PR vanaf een werkbranch — precies wat dit besluit nu voor een verzegeld deck weigert.

Netto: een verzegeld deck kan op dit moment helemaal niet meer naar de repo. Dat is eerlijker dan het zegel stil laten vallen — daarom heb ik de weigering wél gebouwd — maar het is een doodlopende weg, en die mag niet als opgelost in de boeken komen.

Welke kant open moet is van jou. De drie mogelijkheden staan uitgeschreven bij D13 in GIT_STORAGE.md:

  1. Verzegelen wordt een handeling van het uitbrengentagRelease commit het zegel naar de standaardbranch en tagt dan, zodat een zegel nooit als werkstand op een tak staat.
  2. De verzegelcommit mag één keer op een werkbranch en reist mee door de merge; de weigering geldt alleen voor látere opslagen van een al verzegeld deck.
  3. Een verzegeld deck wordt nooit gecommit — de tag is het artefact en het zegel wordt bij het openen herrekend uit de getagde bytes.

Tot dat besluit er is, wijst de weigering naar een bestand of een .ocideck-pakket, en zegt er met zoveel woorden bij dat de tag-route er nog niet is. Liever dat dan een weg beloven die niet bestaat.

Bijvangst: twee besluiten deelden het nummer D12 — "How media comes back" en "A seal belongs on a tag". Allebei worden ze elders in het document én vanuit de code aangehaald, dus was niet te zien welke bedoeld werd. Het jongste (het zegel) is D13 geworden; het oudste blijft, want D5 verwijst ernaar.

Ink blijft liggen, zoals je schreef: dat begint bij het annotatieformaat met een versieverhoging en hoort een eigen ronde te krijgen.

Poort: make check groen op main zelf, ná de rebase op #730.

**Deel 3 (het zegel) staat op main** — \`0949cc2c\` (PR #733). Het issue blijft open voor ink. **Wat er nu gebeurt.** Een verzegeld deck wordt geweigerd bij het opslaan naar git, met uitleg, in plaats van mee te gaan terwijl het zegel stil wegvalt. De weigering staat in het opslagpad zelf en niet alleen in een dialoog: dat is de enige plek waar élke aanroeper langskomt, en een poort die je omzeilt door een andere knop te gebruiken is geen poort. De interface legt hem uit met één knop en zonder "toch opslaan". **De waarschuwing verloor exact de zegelregel** en houdt de tekeningen, zoals je regressie-eis vroeg. Twee tests bewaken dat: dat de weigering komt, en dat er bij een verzegeld deck mét tekeningen niet alsnog twee dialogen achter elkaar staan. **Nu het punt dat er echt toe doet, want het is een bevinding en geen verslag.** Je besluit noemde twee gevolgen voor de bouw. Het tweede is af. **Het eerste is niet te bouwen zoals het er staat**, en dat had ik niet gezien toen ik het issue oppakte: > het zegel reist mee in de commitset van een versie-uitgifte `tagRelease` tagt de kop van de standaardbranch en **commit niets**. Er ís op dat moment geen commitset om in mee te reizen. En de enige weg naar de standaardbranch is een gemergede PR vanaf een werkbranch — precies wat dit besluit nu voor een verzegeld deck weigert. Netto: **een verzegeld deck kan op dit moment helemaal niet meer naar de repo.** Dat is eerlijker dan het zegel stil laten vallen — daarom heb ik de weigering wél gebouwd — maar het is een doodlopende weg, en die mag niet als opgelost in de boeken komen. Welke kant open moet is van jou. De drie mogelijkheden staan uitgeschreven bij D13 in `GIT_STORAGE.md`: 1. **Verzegelen wordt een handeling van het uitbrengen** — `tagRelease` commit het zegel naar de standaardbranch en tagt dan, zodat een zegel nooit als werkstand op een tak staat. 2. **De verzegelcommit mag één keer** op een werkbranch en reist mee door de merge; de weigering geldt alleen voor látere opslagen van een al verzegeld deck. 3. **Een verzegeld deck wordt nooit gecommit** — de tag is het artefact en het zegel wordt bij het openen herrekend uit de getagde bytes. Tot dat besluit er is, wijst de weigering naar een bestand of een `.ocideck`-pakket, en zegt er met zoveel woorden bij dat de tag-route er nog niet is. Liever dat dan een weg beloven die niet bestaat. **Bijvangst: twee besluiten deelden het nummer D12** — "How media comes back" en "A seal belongs on a tag". Allebei worden ze elders in het document én vanuit de code aangehaald, dus was niet te zien welke bedoeld werd. Het jongste (het zegel) is D13 geworden; het oudste blijft, want D5 verwijst ernaar. **Ink blijft liggen**, zoals je schreef: dat begint bij het annotatieformaat met een versieverhoging en hoort een eigen ronde te krijgen. Poort: `make check` groen op main zelf, ná de rebase op #730.
Author
Owner

Ink deel 1 — het formaat — staat op main: ecfec9b2 (PR #748). Het issue blijft open voor de driver, het schrijfpad en het zegel.

D7 schrijft de volgorde voor en die is niet vrij: eerst het annotatieformaat, dan de driver, dan het schrijfpad. Dit is de eerste.

Elke streek draagt nu een id. De unie moet weten wélke streken dezelfde zijn. Zonder identiteit is het enige houvast de puntenlijst, en dan verenigen twee kopieën van dezelfde tekening tot een dubbel getrokken lijn.

Wissen zet een grafsteen in plaats van weg te gooien. Dit is de plek waar de intuïtie fout is, en jouw besluit had gelijk: weggooien is wat je verwacht, en het is precies verkeerd zodra het bestand gemerged wordt — de andere kant heeft de streek nog, de unie brengt hem terug, en de gebruiker zág hem verdwijnen. De tekenaar slaat een gemarkeerde streek over, dus op het scherm verandert er niets.

erased wordt alleen geschreven wanneer het waar is: een bestand vol "erased": false is ruis in iets dat mensen in een diff lezen.

Versie 2, met een leespad — en één eerlijk gevolg. Een sidecar van versie 1 leest door en elke streek krijgt een verse id. Dat betekent dat twee kopieën van zo'n oud bestand verschillende ids krijgen en verenigen tot dubbele lijnen. Zichtbaar en herstelbaar, en daarom te verkiezen boven stil één van beide kanten laten vallen; het staat als zodanig in de code. Andersom leest niet: een oudere build zou de grafstenen niet begrijpen en gewiste streken weer tekenen.

Een bestaande test viel om, en dat verdiende hij. sidecar_version_test noemde versie 2 "uit de toekomst" — dat is nu de huidige. De toetsen staan op Codec.version + 1, zodat ze bij de volgende formaatwijziging niet opnieuw stilletjes de verkeerde vraag stellen.

De uniemergeregel staat als eigenschap in de nieuwe tests, inclusief een gewiste streek komt niet terug, zodat het formaat niet kan wegdrijven van wat de driver straks nodig heeft.

make check groen: 6007 tests. GIT_STORAGE D7 draagt de aantekening.

Wat er nog ligt, en wat waarop wacht:

Deel Stand
Ink — driver merge=ocideck-ink te bouwen; moet ook in de app reproduceerbaar zijn, want een kloon van een ander gereedschap heeft hem niet
Ink — schrijfpad naar de repo daarna
Zegel wacht op jou — de drie wegen staan bij D13

Dat laatste is het scherpst en ik herhaal het hier omdat het makkelijk wegzakt: sinds de weigering gebouwd is, kan een verzegeld deck op dit moment helemaal niet meer naar de repo. Dat is eerlijker dan het zegel stil laten wegvallen, maar het is een doodlopende weg tot die keuze er is.

**Ink deel 1 — het formaat — staat op main:** `ecfec9b2` (PR #748). Het issue blijft open voor de driver, het schrijfpad en het zegel. D7 schrijft de volgorde voor en die is niet vrij: eerst het annotatieformaat, dan de driver, dan het schrijfpad. Dit is de eerste. **Elke streek draagt nu een `id`.** De unie moet weten wélke streken dezelfde zijn. Zonder identiteit is het enige houvast de puntenlijst, en dan verenigen twee kopieën van dezelfde tekening tot een dubbel getrokken lijn. **Wissen zet een grafsteen in plaats van weg te gooien.** Dit is de plek waar de intuïtie fout is, en jouw besluit had gelijk: weggooien is wat je verwacht, en het is precies verkeerd zodra het bestand gemerged wordt — de andere kant heeft de streek nog, de unie brengt hem terug, en de gebruiker zág hem verdwijnen. De tekenaar slaat een gemarkeerde streek over, dus op het scherm verandert er niets. `erased` wordt alleen geschreven wanneer het waar is: een bestand vol `"erased": false` is ruis in iets dat mensen in een diff lezen. **Versie 2, met een leespad — en één eerlijk gevolg.** Een sidecar van versie 1 leest door en elke streek krijgt een verse id. Dat betekent dat twee kopieën van zo'n oud bestand verschillende ids krijgen en verenigen tot dubbele lijnen. Zichtbaar en herstelbaar, en daarom te verkiezen boven stil één van beide kanten laten vallen; het staat als zodanig in de code. Andersom leest niet: een oudere build zou de grafstenen niet begrijpen en gewiste streken weer tekenen. **Een bestaande test viel om, en dat verdiende hij.** `sidecar_version_test` noemde versie 2 "uit de toekomst" — dat is nu de huidige. De toetsen staan op `Codec.version + 1`, zodat ze bij de volgende formaatwijziging niet opnieuw stilletjes de verkeerde vraag stellen. De uniemergeregel staat als eigenschap in de nieuwe tests, inclusief *een gewiste streek komt niet terug*, zodat het formaat niet kan wegdrijven van wat de driver straks nodig heeft. `make check` groen: 6007 tests. GIT_STORAGE D7 draagt de aantekening. **Wat er nog ligt, en wat waarop wacht:** | Deel | Stand | |---|---| | Ink — driver `merge=ocideck-ink` | te bouwen; moet ook in de app reproduceerbaar zijn, want een kloon van een ander gereedschap heeft hem niet | | Ink — schrijfpad naar de repo | daarna | | Zegel | **wacht op jou** — de drie wegen staan bij D13 | Dat laatste is het scherpst en ik herhaal het hier omdat het makkelijk wegzakt: sinds de weigering gebouwd is, kan een verzegeld deck op dit moment **helemaal niet** meer naar de repo. Dat is eerlijker dan het zegel stil laten wegvallen, maar het is een doodlopende weg tot die keuze er is.
Author
Owner

Nee als iets is verzegeld dan is het ook echt afgekaart en klaar. Dan kun je het rapport niet meer wijzigen. Maar het is niet aan het git-systeem om dat op te lossen. Git is hier een bestandssysteem niet een enforcer.

Nee als iets is verzegeld dan is het ook echt afgekaart en klaar. Dan kun je het rapport niet meer wijzigen. Maar het is niet aan het git-systeem om dat op te lossen. Git is hier een bestandssysteem niet een enforcer.
Author
Owner

Opgepakt — ink deel 2 en 3 (de union-merge in de app en het schrijfpad naar de repo). Tak: feat/ink-naar-git-driver-541. Verwachte reikwijdte: lib/services/git/deck_merge.dart (union met grafstenen naast _mergedUserNotes), lib/services/git/deck_repo_serializer.dart (ink-sidecar in de commitset, leespad terug), de omissions-waarschuwing verliest exact de inkregel, test/git_omissions_warning_test.dart en nieuwe merge-tests. Het zegel blijft op jouw D13-keuze wachten.

Opgepakt — ink deel 2 en 3 (de union-merge in de app en het schrijfpad naar de repo). Tak: feat/ink-naar-git-driver-541. Verwachte reikwijdte: lib/services/git/deck_merge.dart (union met grafstenen naast _mergedUserNotes), lib/services/git/deck_repo_serializer.dart (ink-sidecar in de commitset, leespad terug), de omissions-waarschuwing verliest exact de inkregel, test/git_omissions_warning_test.dart en nieuwe merge-tests. Het zegel blijft op jouw D13-keuze wachten.
Author
Owner

Ink deel 2 en 3 — de merge en het schrijfpad — staan op main: c56073b6 (PR #759), en 'make check' is dáár groen gedraaid (6.028 tests). Daarmee is het ink-spoor van dit issue af.

  • Unie met grafstenen in mergeDeckVersions, voor beide vlakken; bewezen tegen échte git (git_native_merge_test): twee tekenaars verenigen, en een gumbeurt overleeft de merge.
  • Schrijfpad naast deck.md (deck.ink.json, ingesprongen), met de notitie-aanraakregels gedeeld via één _repoSidecarState; de sync-delete-lus wist geen ink-bestand dat niet van ons is.
  • Driver bewust minimaal, met twee gemeten afwijkingen van de schets (vastgelegd bij Fase 3): binding in clone-lokaal .git/info/attributes (een gecommitte .gitattributes koopt niets — onbekende driver tekst-merged gewoon) en een altijd-falende driver als config-override per merge-aanroep — laat het bestand schoon op onze kant, de resolver schrijft de unie.
  • De 'Niet alles gaat mee naar git'-dialoog is opgeheven — geen ware regel meer over; vijf sleutels × 31 talen opgeruimd. De bewaker-ronde vóór de merge dwong nog twee documentcorrecties af: FILE_FORMAT §6.2 (v2-voorbeeld mét id/erased; de reis-belofte) en de USER_GUIDE-overbelofte over de MIAUW-dispositie — die reist níét mee; #756 is daarvoor ingediend.

Wat dit issue nog openhoudt: alleen het zegel. De drie wegen staan bij D13 in GIT_STORage.md; tot die keuze kan een verzegeld deck niet naar de repo (de weigering is eerlijk, maar het blijft een doodlopende weg).

**Ink deel 2 en 3 — de merge en het schrijfpad — staan op main:** c56073b6 (PR #759), en 'make check' is dáár groen gedraaid (6.028 tests). Daarmee is het ink-spoor van dit issue af. - **Unie met grafstenen** in mergeDeckVersions, voor beide vlakken; bewezen tegen échte git (git_native_merge_test): twee tekenaars verenigen, en een gumbeurt overleeft de merge. - **Schrijfpad** naast deck.md (deck.ink.json, ingesprongen), met de notitie-aanraakregels gedeeld via één _repoSidecarState; de sync-delete-lus wist geen ink-bestand dat niet van ons is. - **Driver bewust minimaal**, met twee gemeten afwijkingen van de schets (vastgelegd bij Fase 3): binding in clone-lokaal .git/info/attributes (een gecommitte .gitattributes koopt niets — onbekende driver tekst-merged gewoon) en een altijd-falende driver als config-override per merge-aanroep — laat het bestand schoon op onze kant, de resolver schrijft de unie. - **De 'Niet alles gaat mee naar git'-dialoog is opgeheven** — geen ware regel meer over; vijf sleutels × 31 talen opgeruimd. De bewaker-ronde vóór de merge dwong nog twee documentcorrecties af: FILE_FORMAT §6.2 (v2-voorbeeld mét id/erased; de reis-belofte) en de USER_GUIDE-overbelofte over de MIAUW-dispositie — die reist níét mee; #756 is daarvoor ingediend. **Wat dit issue nog openhoudt: alleen het zegel.** De drie wegen staan bij D13 in GIT_STORage.md; tot die keuze kan een verzegeld deck niet naar de repo (de weigering is eerlijk, maar het blijft een doodlopende weg).
Author
Owner

Opgepakt — het zegel, langs je besluit van 14:55: git is een bestandssysteem, geen enforcer. Dat lees ik als: de weigering (gitRefusesSealedDeck, D13) gaat eruit, en het zegel reist als gewone sidecar mee (deck.seal.json naast deck.md), zoals het .ocideck-pakket het al doet — zegel als metadata, bij het openen teruggehangen. Afgekaart-en-klaar blijft de app zelf bewaken (een verzegeld deck is alleen-lezen); de opslag bewaakt niets.

Tak: feat/zegel-reist-mee-541. Reikwijdte: lib/services/git/deck_repo_sidecars.dart en deck_repo_serializer.dart (weigering eruit, zegel-sidecar erin), lib/state/tabs_provider_git.dart, lib/widgets/shell/shell_actions_git.dart (weigeringstekst + l10n-opruiming), lib/services/git/deck_merge.dart, de bijbehorende tests, en GIT_STORAGE.md D13/§9.7 die het besluit gaan dragen.

Opgepakt — het zegel, langs je besluit van 14:55: git is een bestandssysteem, geen enforcer. Dat lees ik als: de weigering (gitRefusesSealedDeck, D13) gaat eruit, en het zegel reist als gewone sidecar mee (deck.seal.json naast deck.md), zoals het .ocideck-pakket het al doet — zegel als metadata, bij het openen teruggehangen. Afgekaart-en-klaar blijft de app zelf bewaken (een verzegeld deck is alleen-lezen); de opslag bewaakt niets. Tak: feat/zegel-reist-mee-541. Reikwijdte: lib/services/git/deck_repo_sidecars.dart en deck_repo_serializer.dart (weigering eruit, zegel-sidecar erin), lib/state/tabs_provider_git.dart, lib/widgets/shell/shell_actions_git.dart (weigeringstekst + l10n-opruiming), lib/services/git/deck_merge.dart, de bijbehorende tests, en GIT_STORAGE.md D13/§9.7 die het besluit gaan dragen.
brenno 2026-07-23 18:54:03 +00:00
Author
Owner

Het zegel staat op main — en daarmee is dit issue helemaal af: 04a01a2e (PR #775). Notities (9450a772), ink-formaat (ecfec9b2), ink-merge en -schrijfpad (c56073b6) en nu het zegel: alle drie de sidecars uit de openingstekst reizen.

Uitgevoerd langs je besluit van 14:55: git is een bestandssysteem, geen enforcer. De weigering (D13) is ingetrokken — gitRefusesSealedDeck, GitSaveStatus.sealed, de dialoog en drie l10n-sleutels × 31 talen zijn weg. deck.seal.json gaat als gewone sidecar naast deck.md mee, komt bij het openen terug, en overleeft de merge van welke kant hij ook komt (beide kanten verzegeld → onze kant, deterministisch — twee versies van één zegel is een vergissing, geen conflict). Dat een verzegeld rapport afgekaart is, bewaakt de app zoals hij al deed: alleen-lezen. D13 is herschreven en draagt je uitspraak letterlijk.

Eén eerlijke grens, opgeschreven in FILE_FORMAT §6.6: de zegelhash gaat over de bytes van de oorspronkelijke .md, en de repo-kopie herschrijft assetpaden. Een deck uit git meldt zijn zegel dus als 'hier niet na te rekenen' in plaats van vals tamper-alarm te slaan — precies zoals het .ocideck-pakket dat al deed. Narekenen blijft sha512sum tegen het origineel.

Bijvangst die er echt toe doet: op het REST-pad werd géén enkele sidecar ooit geschreven naar een branch waar hij nog niet stond — readBlob gooit notFound, en de aanraakcontrole las élke worp als 'niet aanraken'. Dat raakte ook de notities, ink en dispositie uit de eerdere delen van dit issue. repoFileReaderFor vertaalt notFound nu naar null; regressietest op het eerste-opslag-pad zit erbij.

Keten: make check groen (dekking 86,0%), secrets- en SAST-scan 0 bevindingen, bewaker-ronde zonder blokkerende bezwaren. Wat er níét in zit: DAST (ZAP staat nog niet ingericht), en verzegelen-bij-tagRelease — dat hoeft ook niet meer, want de gewone opslagroute staat open.

**Het zegel staat op main — en daarmee is dit issue helemaal af:** `04a01a2e` (PR #775). Notities (`9450a772`), ink-formaat (`ecfec9b2`), ink-merge en -schrijfpad (`c56073b6`) en nu het zegel: alle drie de sidecars uit de openingstekst reizen. Uitgevoerd langs je besluit van 14:55: **git is een bestandssysteem, geen enforcer.** De weigering (D13) is ingetrokken — `gitRefusesSealedDeck`, `GitSaveStatus.sealed`, de dialoog en drie l10n-sleutels × 31 talen zijn weg. `deck.seal.json` gaat als gewone sidecar naast `deck.md` mee, komt bij het openen terug, en overleeft de merge van welke kant hij ook komt (beide kanten verzegeld → onze kant, deterministisch — twee versies van één zegel is een vergissing, geen conflict). Dat een verzegeld rapport afgekaart is, bewaakt de app zoals hij al deed: alleen-lezen. D13 is herschreven en draagt je uitspraak letterlijk. **Eén eerlijke grens, opgeschreven in FILE_FORMAT §6.6:** de zegelhash gaat over de bytes van de oorspronkelijke `.md`, en de repo-kopie herschrijft assetpaden. Een deck uit git meldt zijn zegel dus als 'hier niet na te rekenen' in plaats van vals tamper-alarm te slaan — precies zoals het `.ocideck`-pakket dat al deed. Narekenen blijft `sha512sum` tegen het origineel. **Bijvangst die er echt toe doet:** op het REST-pad werd géén enkele sidecar ooit geschreven naar een branch waar hij nog niet stond — `readBlob` gooit notFound, en de aanraakcontrole las élke worp als 'niet aanraken'. Dat raakte ook de notities, ink en dispositie uit de eerdere delen van dit issue. `repoFileReaderFor` vertaalt notFound nu naar null; regressietest op het eerste-opslag-pad zit erbij. Keten: make check groen (dekking 86,0%), secrets- en SAST-scan 0 bevindingen, bewaker-ronde zonder blokkerende bezwaren. Wat er níét in zit: DAST (ZAP staat nog niet ingericht), en verzegelen-bij-tagRelease — dat hoeft ook niet meer, want de gewone opslagroute staat open.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#541
No description provided.