De linux-gate: één nachtrun, de claims rechtgezet, en een poort die de volgende ziet verrotten #1944

Merged
brenno merged 5 commits from feat/poort-gedateerde-beweringen into main 2026-09-03 11:01:27 +00:00
Owner

Samenvatting

Een bewering over een gemeten grootheid verrot terwijl de boom stilstaat. docs/CHECKS.md beloofde op twee plekken dat een rode main zich ruim binnen de tijd meldt die het werkelijk kost; gemeten op 2026-09-03 was de mediaan van merge tot oordeel 54 minuten. De claim was juist toen hij werd opgeschreven en stapte rond 2026-08-23 omhoog zonder dat er iets aan die werkstroom veranderde. Geen poort zag het, en geen poort kón het zien: er stond geen datum bij.

Dat is een eigen klasse. De poorten op de code zijn sterk, en docs_claims_match_code_test.dart houdt de getallen vast die een constante achter zich hebben. Een looptijd heeft die niet — dit is de documentatie-tegenhanger van check_reference_data.dart: dezelfde vraag, gesteld over onze eigen metingen in plaats van over andermans releases.

Twee helften, en de tweede houdt de eerste eerlijk

Het register (gemetenBeweringen) noemt per levende meting waar ze staat, wat gemeten is, wanneer, en waarmee je hermeet. Elk anker draagt de meetdatum, zodat het document en het register niet uiteen kunnen lopen op precies het getal waar het om gaat. Verdwijnt een anker, dan is de bewering herschreven zonder dat het register meebewoog — dat is een faal, geen stilte.

De basislijn (looptijdBasislijn) telt élke looptijduitdrukking in docs/CHECKS.md, CONTRIBUTING.md en docs/BUILD.md. Zonder die helft bewaakt het register alleen wat iemand eraan heeft toegevoegd, en is de volgende ongedateerde belofte net zo onzichtbaar als de vorige. Komt er een uitdrukking bij, dan valt de poort om met een keuze: meet hem en registreer hem, of zet hem op de basislijn omdat het geschiedenis is.

Verreweg het meeste dat er nu in staat is geschiedenis (#790 zette hem uit omdat hij 17,5 minuten kostte), en dat hoeft niet hermeten te worden. De basislijn is een teller, geen dekking.

Twee momenten

De structurele helft is van de boom af te lezen en zit in STATIC_GATES — dus in make check, check-no-coverage en de statische poort per PR.

De houdbaarheid hoort daar juist niet: die verandert van uitkomst zonder dat er een commit aan te pas komt, en draait dagelijks in time-degrading-checks.yml naast de CVE's, licenties, pins en referentiedata. Zat ze in de PR-poort, dan viel op een dag een willekeurige PR om op een bewering waar de indiener niets mee te maken heeft — en dan wordt de poort uitgezet in plaats van gevolgd.

Twee dingen die anders stil verkeerd gaan

Woordvormen tellen mee. De claim die dit veroorzaakte droeg geen cijfer. Een patroon dat alleen op \d+ minutes let had hem nooit gezien, dus half an hour, about an hour, an hour or so en a few minutes staan met naam in het patroon.

Tekst tussen backticks telt niet mee. Een uitdrukking in code-opmaak is een geciteerd woord, geen belofte — de documentatie van deze poort noemt de patronen zelf. Zonder die regel valt de poort om op zijn eigen beschrijving. Dezelfde afweging als in check_comment_language.dart, dat om dezelfde reden backticks laat vallen.

Wat hij niet ziet, hardop

De basislijn is een multiset van uitdrukkingen, geen plaatsbepaling. Wie in hetzelfde bestand één 22 minutes weghaalt en er elders een neerzet, komt er stil doorheen. Dat is de prijs van een teller die niet op regelnummers vastzit — die zou bij elke herwikkeling van een alinea omvallen en binnen een week uitgezet worden. De grens staat in de kop van het gereedschap én in CHECKS.md, want een poort waarvan niemand de blinde vlek kent wordt voor meer bewijs gehouden dan hij levert.

Beweringen zonder tijdseenheid (dekkingspercentages, testaantallen) blijven bij docs_claims_match_code_test.dart; die hebben wél een constante in de code.

Over de frictie

In 30 dagen raakten 63 commits die drie bestanden, maar slechts 11 diffregels een looptijduitdrukking. De basislijn schudt dus een handvol keer per maand — telkens op het moment dat je er iemand naar wilt laten kijken.

Testplan

  • make check-static groen (exitcode 0, zonder pipe gemeten), met de nieuwe poort op zijn plek in de keten
  • flutter test test/check_dated_claims_tool_test.dart test/docs_claims_match_code_test.dart test/docs_registration_test.dart — 32 tests groen
  • flutter analyze --fatal-infos schoon op beide nieuwe bestanden
  • Rood bewezen in alle drie de faalvormen: verdwenen anker, verlopen meting, nieuwe uitdrukking
  • Rood bewezen end-to-end: een regel met 8 minutes aan CONTRIBUTING.md → exitcode 1 met de uitdrukking bij naam; hersteld → exitcode 0
  • Toets dat de basislijn niet leeg telt — een patroon dat stil naast alles grijpt meldt nul afwijkingen en leest als groen
  • make check niet volledig gedraaid: de wijziging raakt geen lib/, en de volledige suite is op deze runner de duurste stap. De drie tests die deze wijziging kunnen breken zijn wel gedraaid.

Waarom dit één PR is en niet twee

Dit begon als #1941 (alleen de twee verrotte claims rechtzetten) met deze poort erachteraan. #1941 was groen, maar liep bij het mergen op The head branch is behind the base branch — en een rebase betekent een volledige nieuwe CI-ronde.

Op een runner die op dit moment de flessenhals is, zijn drie CI-rondes voor drie commits die elkaar toch al opvolgen niet te verdedigen. De commits blijven apart in de historie: eerst de correctie, dan het gereedschap, dan de bedrading. #1941 is gesloten ten gunste van deze.

## Samenvatting Een bewering over een **gemeten** grootheid verrot terwijl de boom stilstaat. `docs/CHECKS.md` beloofde op twee plekken dat een rode `main` zich ruim binnen de tijd meldt die het werkelijk kost; gemeten op 2026-09-03 was de mediaan van merge tot oordeel 54 minuten. De claim was juist toen hij werd opgeschreven en stapte rond 2026-08-23 omhoog zonder dat er iets aan die werkstroom veranderde. Geen poort zag het, en geen poort kón het zien: er stond geen datum bij. Dat is een eigen klasse. De poorten op de code zijn sterk, en `docs_claims_match_code_test.dart` houdt de getallen vast die een constante achter zich hebben. Een looptijd heeft die niet — dit is de documentatie-tegenhanger van `check_reference_data.dart`: dezelfde vraag, gesteld over onze eigen metingen in plaats van over andermans releases. ## Twee helften, en de tweede houdt de eerste eerlijk **Het register** (`gemetenBeweringen`) noemt per levende meting waar ze staat, wat gemeten is, wanneer, en waarmee je hermeet. Elk anker draagt de meetdatum, zodat het document en het register niet uiteen kunnen lopen op precies het getal waar het om gaat. Verdwijnt een anker, dan is de bewering herschreven zonder dat het register meebewoog — dat is een faal, geen stilte. **De basislijn** (`looptijdBasislijn`) telt élke looptijduitdrukking in `docs/CHECKS.md`, `CONTRIBUTING.md` en `docs/BUILD.md`. Zonder die helft bewaakt het register alleen wat iemand eraan heeft toegevoegd, en is de volgende ongedateerde belofte net zo onzichtbaar als de vorige. Komt er een uitdrukking bij, dan valt de poort om met een keuze: meet hem en registreer hem, of zet hem op de basislijn omdat het geschiedenis is. Verreweg het meeste dat er nu in staat *is* geschiedenis (`#790 zette hem uit omdat hij 17,5 minuten kostte`), en dat hoeft niet hermeten te worden. De basislijn is een teller, geen dekking. ## Twee momenten De structurele helft is van de boom af te lezen en zit in `STATIC_GATES` — dus in `make check`, `check-no-coverage` en de statische poort per PR. De houdbaarheid hoort daar juist niet: die verandert van uitkomst zonder dat er een commit aan te pas komt, en draait dagelijks in `time-degrading-checks.yml` naast de CVE's, licenties, pins en referentiedata. Zat ze in de PR-poort, dan viel op een dag een willekeurige PR om op een bewering waar de indiener niets mee te maken heeft — en dan wordt de poort uitgezet in plaats van gevolgd. ## Twee dingen die anders stil verkeerd gaan **Woordvormen tellen mee.** De claim die dit veroorzaakte droeg geen cijfer. Een patroon dat alleen op `\d+ minutes` let had hem nooit gezien, dus `half an hour`, `about an hour`, `an hour or so` en `a few minutes` staan met naam in het patroon. **Tekst tussen backticks telt niet mee.** Een uitdrukking in code-opmaak is een geciteerd woord, geen belofte — de documentatie van deze poort noemt de patronen zelf. Zonder die regel valt de poort om op zijn eigen beschrijving. Dezelfde afweging als in `check_comment_language.dart`, dat om dezelfde reden backticks laat vallen. ## Wat hij niet ziet, hardop De basislijn is een multiset van uitdrukkingen, geen plaatsbepaling. Wie in hetzelfde bestand één `22 minutes` weghaalt en er elders een neerzet, komt er stil doorheen. Dat is de prijs van een teller die niet op regelnummers vastzit — die zou bij elke herwikkeling van een alinea omvallen en binnen een week uitgezet worden. De grens staat in de kop van het gereedschap én in CHECKS.md, want een poort waarvan niemand de blinde vlek kent wordt voor meer bewijs gehouden dan hij levert. Beweringen zonder tijdseenheid (dekkingspercentages, testaantallen) blijven bij `docs_claims_match_code_test.dart`; die hebben wél een constante in de code. ## Over de frictie In 30 dagen raakten 63 commits die drie bestanden, maar slechts 11 diffregels een looptijduitdrukking. De basislijn schudt dus een handvol keer per maand — telkens op het moment dat je er iemand naar wilt laten kijken. ## Testplan - [x] `make check-static` groen (exitcode 0, zonder pipe gemeten), met de nieuwe poort op zijn plek in de keten - [x] `flutter test test/check_dated_claims_tool_test.dart test/docs_claims_match_code_test.dart test/docs_registration_test.dart` — 32 tests groen - [x] `flutter analyze --fatal-infos` schoon op beide nieuwe bestanden - [x] Rood bewezen in alle drie de faalvormen: verdwenen anker, verlopen meting, nieuwe uitdrukking - [x] Rood bewezen end-to-end: een regel met `8 minutes` aan CONTRIBUTING.md → exitcode 1 met de uitdrukking bij naam; hersteld → exitcode 0 - [x] Toets dat de basislijn niet leeg telt — een patroon dat stil naast alles grijpt meldt nul afwijkingen en leest als groen - [ ] `make check` niet volledig gedraaid: de wijziging raakt geen `lib/`, en de volledige suite is op deze runner de duurste stap. De drie tests die deze wijziging kunnen breken zijn wel gedraaid. ## Waarom dit één PR is en niet twee Dit begon als #1941 (alleen de twee verrotte claims rechtzetten) met deze poort erachteraan. #1941 was groen, maar liep bij het mergen op `The head branch is behind the base branch` — en een rebase betekent een volledige nieuwe CI-ronde. Op een runner die op dit moment de flessenhals is, zijn drie CI-rondes voor drie commits die elkaar toch al opvolgen niet te verdedigen. De commits blijven apart in de historie: eerst de correctie, dan het gereedschap, dan de bedrading. #1941 is gesloten ten gunste van deze.
Twee plekken beloofden dat een rode `main` zich "within ~half an hour" van de
merge meldt. Gemeten op 2026-09-03 tegen `action_run` op de forge klopt dat niet
meer: over de laatste tien dagen (61 post-merge-runs) duurt de poort zelf
mediaan 51 minuten, en van merge tot oordeel mediaan 54 met 85 op het
90e percentiel. De wachtrij op de capacity-1-runner komt daar bovenop; de
langste merge-tot-oordeel in het venster was 151 minuten.

De claim was niet fout toen hij werd opgeschreven — over de tien dagen dáárvoor
was de mediaan 29 minuten. Hij stapte rond 2026-08-23 omhoog zonder dat deze
werkstroom veranderde, en niets zag dat: er is geen poort die een looptijdclaim
narekent, en de boom hoeft er niet voor te bewegen. Dat staat er nu bij, zodat
de volgende lezer hem narekent in plaats van gelooft.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Een bewering over een gemeten grootheid verrot terwijl de boom stilstaat.
CHECKS.md beloofde op twee plekken "within ~half an hour" terwijl de meting op
54 minuten stond; er zat geen datum bij, dus er viel niets tegen te toetsen.

De poort heeft twee helften, en de tweede houdt de eerste eerlijk. Het register
noemt per levende meting waar ze staat, wat gemeten is, wanneer, en waarmee je
hermeet — met een letterlijk anker dat de meetdatum draagt, zodat proza en
register niet uiteen kunnen lopen. De basislijn telt daarnaast élke
looptijduitdrukking in de bewaakte documenten: zonder die helft bewaakt het
register alleen wat iemand eraan heeft toegevoegd, en is de volgende
ongedateerde belofte net zo onzichtbaar als de vorige.

De woordvormen staan er met naam in. De claim die dit veroorzaakte droeg geen
cijfer, en een patroon dat alleen op `\d+ minutes` let had hem nooit gezien.

Tekst tussen backticks telt niet mee: een uitdrukking in code-opmaak is een
geciteerd woord, geen belofte. Zonder die regel valt de poort om op zijn eigen
beschrijving, en dat is precies hoe een poort wordt uitgezet.

De test toetst alle drie de faalvormen rood — verdwenen anker, verlopen meting,
nieuwe uitdrukking — plus dat de basislijn niet leeg telt. Een groene poort die
niet rood kán worden is hier al een keer voor bewijs aangezien.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
feat(poort): de beweringpoort in de statische lijst en tegen de klok
Some checks failed
scans / scans (pull_request) Successful in 5m44s
web-gate / web-gate (pull_request) Has been cancelled
static-gate / static-gate (pull_request) Has been cancelled
2480026e3f
De structurele helft — staan de ankers er nog, is er een looptijduitdrukking bij
gekomen — is van de boom af te lezen en hoort daarom in STATIC_GATES, dus in
`make check`, `check-no-coverage` en de statische poort per PR.

De houdbaarheid hoort daar juist niet. Die verandert van uitkomst zonder dat er
een commit aan te pas komt, en draait dus dagelijks in time-degrading-checks.yml,
naast de CVE's, licenties, pins en referentiedata. Zat ze in de PR-poort, dan
viel op een dag een willekeurige PR om op een bewering waar de indiener niets
mee te maken heeft — en dan wordt de poort uitgezet in plaats van gevolgd.

CHECKS.md documenteert hem zoals de andere poorten, inclusief de blinde vlek die
hij heeft: de basislijn is een multiset, geen plaatsbepaling. Eén uitdrukking
weghalen en er elders in hetzelfde bestand een neerzetten komt er stil doorheen.
Dat staat er omdat een poort waarvan niemand de grens kent voor meer bewijs
wordt gehouden dan hij levert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
De trigger is nu twee keer verhuisd, beide keren omdat deze poort de duurste
bewoner is van de traagste runner. #1123 zette hem er ook per PR naast; dat
draaide de suite twee keer per wijziging en werd teruggedraaid. Wat overbleef
was `push: [main]`, en nagemeten op 2026-09-03 verdient ook dat zichzelf niet
terug.

Kosten: 7,6 merges per dag maal mediaan 51 minuten is ~6,5 uur per dag op een
runner met capaciteit 1. Opbrengst over 24 dagen: nul productregressies, één
echte rode main (een test die na #1777 was blijven staan en óók op macOS en
Windows faalde, dus een lokale `make check` ving hem net zo goed), en twaalf
alarmen over tests die op tijd gokten. Die laatste klasse was reëel en alleen
hier zichtbaar omdat deze machine traag is — maar #1911 heeft er een ratchet op
`Future.delayed` in `test/` overheen gezet, dus ze wordt nu bij de bron gestopt.

Daar komt de vertraging bij die hij anderen aandeed: hij deelt één host met de
capacity-4-baan, dus terwijl hij draaide wachtten de static-gate-runs die wél
per PR nodig zijn. Met `block_on_outdated_branch` aan verjaart een groene
PR-basis sneller naarmate die wachtrij langer is — dat overkwam #1941 vandaag.

Wat we inleveren is de toewijzing: rood wijst nu naar een nacht in plaats van
naar één merge. De faaltest noemt zichzelf en er zitten hooguit een handvol
commits tussen. De detectie zelf blijft: main kan nog steeds niet stil rood
staan, en static-gate draait onverkort per PR én op push naar main.

02:11 UTC, ruim vóór de tap-spiegelcheck (05:17) en de tijdsvervallende
controles (05:33), want deze run trekt de machine een uur lang leeg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
docs: vier plekken beweerden dat de linux-gate per merge draait
All checks were successful
scans / scans (pull_request) Successful in 5m47s
static-gate / static-gate (pull_request) Successful in 10m36s
web-gate / web-gate (pull_request) Successful in 8m5s
ff303401ab
De cadencewissel raakt meer dan de werkstroom zelf. CHECKS.md beschreef de
poort op vier plekken als post-merge (de inleiding, de tabelregel voor `make
test`, de sectiekop en de verdediging van de push-trigger), README noemde hem
"on demand" — wat al niet klopte vóór deze wissel — en COMPLIANCE.md en
security-insights.yml herhalen het naar buiten toe. Die laatste twee zijn
verantwoording aan derden; daar hoort geen verouderde bewering in te staan.

Eén alinea die nu weg is, was al fout vóór deze PR: CHECKS.md beloofde dat
snelle merges elkaars run opzij zetten, terwijl `cancel-in-progress` sinds #1890
op `false` staat. Ze stapelden dus juist op — drie tegelijk vanochtend.

De nieuwe poort van deze tak ving zijn eigen documentatiewijziging: zes
afwijkingen in de basislijn, waaronder een "29" waar ik per ongeluk de eenheid
had laten vallen. Dat is precies waarvoor hij bedoeld is, en de bijgewerkte
basislijn staat in dezelfde commit als de tekst die hem verschoof.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
brenno changed title from De looptijdclaim rechtgezet, en een poort die de volgende ziet verrotten to De linux-gate: één nachtrun, de claims rechtgezet, en een poort die de volgende ziet verrotten 2026-09-03 10:05:53 +00:00
Author
Owner

Twee commits erbij, na akkoord op de cadencevraag.

ci(linux-gate) — de poort draait niet meer op push: [main] maar op een schedule om 02:11 UTC, plus workflow_dispatch. Van ~6,5 uur runnertijd per dag naar ~50 minuten. De onderbouwing staat in de kop van de werkstroom: over 24 dagen leverde de per-merge-run nul productregressies op, één echte rode main die ook op macOS en Windows faalde (dus lokaal net zo goed te vangen), en twaalf alarmen over tijdgokkende tests — een klasse die #1911 inmiddels bij de bron stopt. Wat we inleveren is de toewijzing van rood aan één merge; de detectie blijft.

docs — vier plekken in CHECKS.md beschreven de oude trigger, plus README.md, COMPLIANCE.md en security-insights.yml. Die laatste twee zijn verantwoording aan derden. Eén alinea die nu weg is was al fout vóór deze PR: CHECKS.md beloofde dat snelle merges elkaars run opzij zetten, terwijl cancel-in-progress sinds #1890 op false staat — ze stapelden juist op, drie tegelijk vanochtend.

De poort uit deze tak ving zijn eigen documentatiewijziging met zes afwijkingen, waaronder een "29" waar ik de eenheid had laten vallen. Basislijn en register zijn bijgewerkt in dezelfde commit als de tekst die ze verschoof.

make check-static groen (exitcode 0), 57 tests groen inclusief security_insights, compliance_attestation, de README-linkcontroles en web_gate_triggers.

Twee commits erbij, na akkoord op de cadencevraag. **`ci(linux-gate)`** — de poort draait niet meer op `push: [main]` maar op een `schedule` om 02:11 UTC, plus `workflow_dispatch`. Van ~6,5 uur runnertijd per dag naar ~50 minuten. De onderbouwing staat in de kop van de werkstroom: over 24 dagen leverde de per-merge-run nul productregressies op, één echte rode `main` die ook op macOS en Windows faalde (dus lokaal net zo goed te vangen), en twaalf alarmen over tijdgokkende tests — een klasse die #1911 inmiddels bij de bron stopt. Wat we inleveren is de toewijzing van rood aan één merge; de detectie blijft. **`docs`** — vier plekken in CHECKS.md beschreven de oude trigger, plus README.md, COMPLIANCE.md en security-insights.yml. Die laatste twee zijn verantwoording aan derden. Eén alinea die nu weg is was al fout vóór deze PR: CHECKS.md beloofde dat snelle merges elkaars run opzij zetten, terwijl `cancel-in-progress` sinds #1890 op `false` staat — ze stapelden juist op, drie tegelijk vanochtend. De poort uit deze tak ving zijn eigen documentatiewijziging met zes afwijkingen, waaronder een "29" waar ik de eenheid had laten vallen. Basislijn en register zijn bijgewerkt in dezelfde commit als de tekst die ze verschoof. `make check-static` groen (exitcode 0), 57 tests groen inclusief `security_insights`, `compliance_attestation`, de README-linkcontroles en `web_gate_triggers`.
brenno merged commit d8bc1b436a into main 2026-09-03 11:01:27 +00:00
brenno deleted branch feat/poort-gedateerde-beweringen 2026-09-03 11:01:29 +00:00
Sign in to join this conversation.
No description provided.