Vier RFC’s beschrijven lagen van dezelfde machine, van buiten naar binnen.
RFC-026, Werkvoorraad. Welke artikelen verrijkt moeten worden en in welke volgorde. Levert taken op.
RFC-027, Enrichment Quality. De rollen, de poorten en de faalvormen die bepalen of één artikel goed verrijkt is. Verbruikt taken.
RFC-028, Steps and Runtimes. Hoe één stap uit die keten draait.
RFC-029, Test Fixtures. De maatlat voor het geheel.
Deze RFC is de eerste laag.
RFC-033, Bouwplan. In welke volgorde je de knopen aandoet die hier geselecteerd zijn, en wat een venster is. Verbruikt de afbakening van deze RFC.
RFC-027 beschrijft hoe je één wet goed verrijkt. Deze RFC gaat over de vraag die daarvoor komt: welke wetten, en welke delen daarvan, moeten verrijkt worden om een bepaalde uitvoering mogelijk te maken, en hoe weet je dat je klaar bent.
Een wet staat niet op zichzelf. De Wet op de zorgtoeslag rekent met een toetsingsinkomen dat in de Awir staat, met een verzekeringsplicht uit de Zorgverzekeringswet, met een inkomensbegrip uit de Wet inkomstenbelasting, en met bedragen die bij ministeriële regeling worden vastgesteld. Elk van die wetten verwijst weer verder. Wie een wet verrijkt en de verwijzingen volgt, staat binnen drie stappen voor het halve belastingrecht.
De werkvoorraad die er nu is, kan dat niet aan. jobs heeft een law_id en een
priority tussen 0 en 100. law_entries heeft law_id als primaire sleutel met
één status per wet, zonder versie en zonder artikel. Er is geen veld waarin staat
dat een wet in de lijst staat omdat een andere wet hem nodig had. Een taak die
volgt uit een andere taak is niet te onderscheiden van een taak die iemand met de
hand heeft ingevoerd, en de prioriteit van de afgeleide taak heeft geen relatie
met die van zijn oorzaak.
Het gevolg is meetbaar in ronde 2 van het enricher-archief. De zorgtoeslag is van bovenaf verrijkt en bindt daardoor aan outputs die de Awir en de Zorgverzekeringswet niet produceren, omdat die nog niet verrijkt zijn. Zes van de zeven bindingsbevindingen komen daarvandaan en zijn dus geen fouten in de zorgtoeslag.
Requirement 4 en 5 komen uit dezelfde asymmetrie.
Een bekend gat is een norm waarvan we weten dat hij nog niet is ingevuld, en waarvan we weten waar de invulling hoort te staan. Een open norm die bij ministeriële regeling wordt uitgewerkt, terwijl die regeling nog niet geoogst is. Dat gat is niet schadelijk. De wet wordt niet uitgevoerd tot de invulling er is, of de uitvoering blijft vragen om een invoer waarvan de ambtenaar weet dat het antwoord in beleidsdocument X staat. Het gat is bovendien werk dat weggezet kan worden: een agent of een analist zoekt het document op. Wat de aanleiding was om dat gat te vullen, doet er niet toe.
Een stil gat is een werking die we niet kennen. Een algemene wet die zichzelf van toepassing verklaart op de materiewet, een beleidsregel die de bevoegdheid inperkt, een wijzigingswet die niet is meegenomen. Daar geeft de uitvoering een antwoord dat fout is, en niemand ziet het.
Bekende gaten zijn een normale toestand van het corpus en hoeven de verrijking niet op te houden. Stille gaten zijn de enige echte faalvorm. Elke keuze hieronder om de sluiting te begrenzen is toegestaan zolang die keuze een bekend gat produceert en geen stil gat.
Het ontwerp gebruikt de analogie met een package manager, en die gaat verder dan een losse vergelijking.
| software | wet |
|---|---|
| package | wet |
| compilatie-eenheid | artikel |
| symbool | lid of onderdeel |
| import van een symbool | ”als bedoeld in artikel 8, tweede lid” |
| type-only import | definitorische verwijzing |
| runtime-import | uitvoerende verwijzing |
| optionele dependency, niet ingeschakeld | delegatie naar een beleidsregel |
| lockfile met hashes | sidecar met een hash per fragment |
| resolve tegenover build | traversal tegenover verrijking |
| feature die een optionele dependency uitschakelt | artikel buiten de hot path |
| trait-impl elders in de crate | artikel dat een ander artikel wijzigt |
| entry point en tree shaking | scenario als wortel |
De analogie breekt op de cycli, en dat kost iets. Cycli zijn hier normaal. Een package manager weigert ze en bouwt in topologische volgorde; wetten verwijzen over en weer en er is geen volgorde die dat oplost. Zie de sectie over cycli.
Knopen zijn (wet, versie, artikel). Uitvoeringsdocumenten en beleidsregels zijn
knopen van dezelfde soort. De wet zelf is een groepering van knopen.
Het artikel is de eenheid van werk en status; het lid is de eenheid van precisie.
Een kant heeft daarom een adres binnen zijn doel: de verwijzing naar “artikel 8,
tweede lid van de Awir” is een kant naar knoop awir#8 met adres 2. Dat is de
verhouding tussen een compilatie-eenheid en een symbool. Je hercompileert de hele
module, en tegelijk weet de afhankelijkheidsanalyse welk symbool je gebruikt.
Een gevraagd lid trekt daarom altijd zijn hele artikel mee. Leden zijn niet zelfstandig leesbaar, want een tweede lid begint geregeld met “In afwijking van het eerste lid” en een agent die alleen dat lid krijgt, vertaalt iets anders dan er staat. De marginale kosten zijn bovendien laag: de dure stap is het lezen en kwalificeren van het artikel, en de overige leden meenemen kost daarbovenop weinig.
Het adres doet drie dingen. Het bepaalt welke tekst de agent als het gevraagde fragment aangeboden krijgt, met het hele artikel eromheen als context. Het stuurt de invalidatie, want verandert lid 3 terwijl de afhankelijkheid op lid 2 zit, dan is de afhankelijke wet niet geraakt. En het maakt de graaf precies genoeg om bruikbaar te zijn zonder het aantal knopen te vermenigvuldigen.
Die granulariteit is het belangrijkste antwoord op de uitwaaiering, en hij zit op de traversal en niet op de verrijking. Een verwijzing tussen wetten is bijna nooit “de Awir” maar “het toetsingsinkomen, bedoeld in artikel 8 van de Awir”. Dat staat er letterlijk, en het is al een symboolimport. Wie de wet als traversal-eenheid neemt, volgt bij artikel 8 ook de verwijzingen van de andere 86 artikelen en ziet de sluiting openklappen. Wie het artikel als traversal-eenheid neemt, volgt de drie verwijzingen die artikel 8 zelf heeft. De oneindigheid komt dus voort uit een te grove traversal en niet uit het recht.
De verrijkingseenheid en de traversal-eenheid vallen niet samen.
Kom je wet X tegen, dan verrijk je X helemaal. Alle artikelen, ook de artikelen die niemand gevraagd heeft. De uitgaande verwijzingen van al die artikelen volg je daarentegen niet. Alleen de artikelen die de reden waren dat X binnenkwam, en wat daarbinnen op ze inwerkt, leveren kanten die de sluiting laten groeien. Die verzameling heet de hot path.
Cargo doet hetzelfde. Het bouwt het hele package en niet alleen de functie die je aanroept, terwijl het optionele dependencies achter uitgeschakelde features niet ophaalt.
De winst van breed verrijken zit in requirement 2. Een half verrijkte wet is een wet met gaten waarvan niemand weet of ze bewust zijn, en de volgende aanvrager die een ander artikel nodig heeft, begint opnieuw. Een wet die in één keer af is, is voor iedere volgende wortel meteen klaar. Het haalt bovendien de druk van de vraag of de hot path wel compleet is: mist hij een artikel, dan is dat artikel toch verrijkt, en het gevolg blijft beperkt tot een kant die niet gevolgd is.
De prijs is reëel. De Wet inkomstenbelasting helemaal verrijken omdat er één inkomensbegrip nodig is, kost een veelvoud van wat de wortel vraagt, en de Zorgverzekeringswet liep in ronde 1 al op één artikel tegen de outputlimiet van het model. Daarom splitst de wet-taak in tweeën: de hot path blokkeert de wortel en heeft diens prioriteit, de rest van de wet blokkeert niets en draait erachteraan. De wortel wacht op wat hij nodig heeft en het corpus wordt alsnog compleet.
Kanten uit artikelen buiten de hot path worden vastgelegd en niet gevolgd. Dat is een bekend gat volgens requirement 4, en de sluitings-poort telt het niet als bevinding. Groeit de hot path later omdat een andere wortel dat artikel nodig heeft, dan wordt de kant alsnog gevolgd. De hot path is een eigenschap van de wortel en niet van de wet.
De splitsing van de vorige sectie vraagt een uitvoeringsmodus die er niet was. De hot path blokkeert de wortel en de rest van de wet draait erachteraan, en dat is alleen uitvoerbaar als een run precies de knopen kan verrijken die de hot path noemt. Die knopen liggen niet naast elkaar in het document: het toetsingsinkomen zit in artikel 8 van de Awir, het partnerbegrip in artikel 3, en daartussen staan vier artikelen die deze wortel niet nodig heeft.
Een enrich-run verwerkte tot nu toe een aaneengesloten venster in
documentvolgorde vanaf een cursor (enrich_cursor in de sidecar naast de wet,
RFC-028 onder Windowing). Er was geen manier om te zeggen welk artikel je wilt.
Wie artikel 8 wilde verrijken, moest het venster opschuiven tot 8 erin viel en
betaalde de zeven artikelen ervoor.
enrich-once --article 8 noemt één entry en verrijkt die ene. Twee eigenschappen
horen bij die modus, en allebei beschermen ze de gewone wandeling.
De cursor blijft staan. Gericht werk is geen voortgang door het document, en
een run die één entry repareert mag de gewone wandeling niet voorbij artikelen
duwen die geen agent heeft gezien. De terminatie van de venstermodus verandert
daar niet door: de cursor schuift nog steeds alleen op wanneer een venster
gelopen is, in ceil(entries / vensterbreedte) geslaagde runs.
Een entrynummer dat de wet niet heeft, laat de run falen met dat nummer in de melding. De alternatieve uitkomst, een run die stil niets verrijkt, is niet te onderscheiden van een run die niets te doen vond, en het aanroepende commando is juist de plek waar een verkeerd nummer vandaan komt.
De sluiting is de eerste aanleiding. Die wordt per artikel bepaald terwijl de uitvoering per wet liep, en zonder gericht verrijken is de splitsing van de wet-taak een tekening en geen opzet die draait.
Een wet waarop gewacht werd, komt alsnog in het corpus. Dan wil je precies de
artikelen opnieuw verrijken die daardoor vrijkomen, en welke dat zijn volgt uit
de graaf: de knopen met een delegates-to-kant naar de regeling die nu een
document heeft. Dat is de tweede werkvoorraad die haar werk teruggeeft aan de
eerste. De vraag staat in de graaf en niet in het wetsbestand, want de
corpustoestand hoort daar niet (RFC-031), en het antwoord is een lijst
entrynummers en geen lijst wetten.
Eén fout artikel herstellen kostte tot nu toe het hele venster. Dat is duur en het is bovendien onnauwkeurig: de andere entries in dat venster worden opnieuw aangeboden aan een agent die er niets aan hoeft te doen.
Requirement 2 blijft daarbij overeind. Een knoop die af is, blijft af, en de sidecar met de hash per fragment beslist dat. Gericht verrijken kiest welke knoop aan de beurt is; het geeft geen vrijbrief om een knoop over te doen die niemand ongeldig heeft verklaard.
De hot path is niet de verzameling gevraagde artikelen. Artikel 10 kan bepalen wat artikel 8 betekent, en dan hoort 10 er ook bij, met zijn eigen uitgaande kanten.
Drie manieren waarop dat gebeurt.
Een artikel verwijst naar het gevraagde artikel. “In afwijking van artikel 8” staat in artikel 10 en de invloed loopt van 10 naar 8, terwijl de verwijzing de andere kant op wijst. De resolver moet binnen een wet dus ook de omgekeerde vraag beantwoorden: wie verwijst naar dit artikel. Binnen één wet is dat goedkoop, want de tekst ligt er al, en daarom geldt hier het omgekeerde van de regel voor verwijzingen naar buiten: binnen een wet resolven we volledig en in beide richtingen, daarbuiten smal en vooruit.
Niet elke inkomende verwijzing hoort erbij. “Het bedrag, bedoeld in artikel 8” gebruikt artikel 8 en verandert het niet. “In afwijking van”, “onverminderd”, “in aanvulling op” en “is niet van toepassing” doen dat wel. De inkomende kant krijgt daarom een strekking, gebruikend of wijzigend, en alleen de wijzigende trekt het bronartikel de hot path in. De lexicale signalen daarvoor zijn dezelfde connectieven die de dekkingscheck van RFC-027 al kent.
De omhullende structuur bepaalt mee wat er staat. Een begripsbepaling aan het
begin van een afdeling geldt voor die hele afdeling zonder dat enig artikel
ernaar verwijst. Een reikwijdtebepaling in hoofdstuk 1 werkt op alles daaronder.
Welke van die bepalingen op artikel 8 werken, volgt uit waar 8 staat, en daarom
is placement uit schema 0.7.0 de scoperegel: de
begripsbepalingen van elke omhullende container zitten in de hot path van elk
artikel daarbinnen.
Dat is ook de reden dat een artikel nooit zonder zijn pad naar de agent gaat. Een artikel dat zijn kopjes kwijt is, mist de helft van zijn betekenis, en een model dat op zo’n tekst is gebouwd is niet te repareren met een betere prompt. De structuur reist mee als het pad “Hoofdstuk 3 Besluiten > Afdeling 3.3 Advisering”, zoals de bronpoort hem al vastlegt.
Bepalingen die op de hele wet werken. Overgangsrecht, een hardheidsclausule, slotbepalingen, delegatiegrondslagen. Die noemen geen artikelnummers en zijn dus met verwijzingen niet te vinden. Dit is de lokale variant van de algemene wet (zie de sectie hieronder). Per wet is dat een handvol artikelen, en omdat de wet toch in zijn geheel verrijkt wordt, is de enige beslissing die overblijft of hun kanten gevolgd worden.
Hetzelfde patroon staat daarmee op drie schalen. Het hele artikel gaat mee omdat
leden niet zelfstandig leesbaar zijn. De omhullende bepalingen van de wet gaan mee
omdat ze zonder verwijzing werken. En de algemene wetten werken door omdat ze
zichzelf van toepassing verklaren. Het gaat elke keer om wat op een artikel
inwerkt zonder dat er een verwijzing naartoe staat, en elke keer staat het
antwoord in het document zelf: de structuur (placement) en de zelfverklaarde
reikwijdte (applies-to).
Kanten zijn getypeerd, omdat de traversalregel per type verschilt.
uses-definition betekent dat een knoop de betekenis van een begrip uit een
andere knoop nodig heeft. computes-with betekent dat er een waarde berekend moet
worden. Dat verschil is het verschil tussen een type-import en een
runtime-import, en het is de tweede grote begrenzer. Een definitorische verwijzing
sleept niets mee: je hebt de tekst van dat ene artikel nodig en verder niets. Een
uitvoerende trekt zijn eigen keten mee. Wie die twee niet onderscheidt, verrijkt
het halve belastingrecht om te weten wat “partner” betekent.
delegates-to verbindt een open norm met het document dat hem invult, en wordt
niet gevolgd. Zie de volgende sectie.
applies-to loopt tegen de leesrichting in: van de algemene wet naar de
materiewet. De bron van die kant is de reikwijdtebepaling van de algemene wet
zelf; zie de sectie over algemene wetten.
amends verbindt een wijzigingswet met wat hij wijzigt, en is vooral relevant
voor invalidatie.
Een delegates-to-kant wordt niet automatisch gevolgd. Hij levert een
open_term op en daar houdt de sluiting op.
Dit is de derde en waarschijnlijk grootste begrenzer. Delegatie is waar het corpus explodeert: er zijn duizenden ministeriële regelingen en beleidsregels, en een enricher die ze volgt komt nooit klaar. Tegelijk is het gat dat je overhoudt onschadelijk, want het is een bekend gat in de zin van de vorige sectie.
Een open term met een delegated_to en een delegation_type is daarmee een
afgerond resultaat. De sluiting stopt daar, en de kant zelf gaat naar een tweede
werkvoorraad, van gevonden gaten, met een eigen prioritering. Iemand zoekt dat
document op, laat het oogsten, en dan vindt de resolver van RFC-003 de invulling
vanzelf via implements. Dat kan een agent zijn of een mens; het is
analistenwerk en de aanleiding doet er niet toe.
De kant staat in de graaf en niet in het wetsbestand. Dat is een gevolg van
RFC-031: of de invullende regeling vandaag geoogst is, is een toestand van het
corpus, en die hoort in de index die weggegooid en opnieuw opgebouwd kan worden.
Het wetsbestand zegt alleen dat de term open is en wie hem mag invullen. De oude
velden expected_source, searched en resolved_by van norm_gaps bestaan
daarom niet meer, en de tweede werkvoorraad neemt hun werk over.
Dat maakt de vraag naar beleidsregels ook opportunistisch in plaats van volledig. Er is geen omgekeerde index over het hele corpus nodig om te weten welke beleidsregels bestaan. Je verrijkt, je krijgt open termen met een adres erbij, en dan zoek je gericht.
Blijft over de klasse die je niet met een markering kunt afvangen: de wet die zichzelf van toepassing verklaart terwijl de materiewet daar niets over zegt. De Awb is op vrijwel elk besluit van een bestuursorgaan van toepassing zonder dat de Wet op de zorgtoeslag dat vermeldt. Wie vanuit de materiewet zoekt, vindt hem nooit. Dit is het stille gat uit requirement 5.
In het staats- en bestuursrecht heet die klasse de algemene wet. Aanwijzing 2.46 van de Aanwijzingen voor de regelgeving geeft de lijst en de werking: afwijking van de Awb, Boek 1 van het Burgerlijk Wetboek, de Algemene termijnenwet en de AWR vergt een zwaarwichtig belang. Een eerdere versie van dit ontwerp noemde ze “kaderwetten” en hield er een handgeschreven lijst naast; aangewezen wetten gingen als kaart naast de diepte mee, zonder dieptepunt te kosten en zonder dat erin of eruit gelopen werd. Dat is geschrapt, om drie redenen. De term botst met het vak en met het corpus: een kaderwet is een wet die de invulling aan lagere regels delegeert, en daarvan staan er vijftien echte in het corpus. De lijst gooide twee tegengestelde gevallen op één hoop: de Awir stond erop terwijl de materiewetten er dik naar verwijzen en de traversal hem gewoon vindt, zodat de uitzondering daar alleen de producent buiten het plan hield die eerder vertaald moest worden dan zijn lezer. En het kaartmechanisme beantwoordde de vraag niet waarvoor het bestond: een kaart ontstond alleen op een verwijzing die de traversal tegenkwam, dus of de Awb-kaart verscheen hing af van toevallige citaten elders in de sluiting (vanaf de zorgtoeslag wel op diepte 1, via de Zvw, en niet op diepte 0) en zei niets over toepasselijkheid, terwijl de besluit-machinerie waar het om gaat op geen enkele diepte via verwijzingen binnenkomt.
Er blijft een relatie over, met een bron in de wettekst. Elke algemene wet
bevat zijn eigen reikwijdtebepaling (“Deze wet geldt voor inkomensafhankelijke
regelingen”, Awir artikel 1). Dat is de applies-to-kant hierboven: zodra de
algemene wet geoogst en verrijkt is, komen die kanten uit de reikwijdtebepaling
zelf. Een lijst ernaast die kan verouderen is dan niet meer nodig.
De garantie die de kaart moest geven hangt aan een output. Een output met
legal_character BESCHIKKING valt per definitie onder het Awb-regime, en de
toetsbare formulering (“een output die een besluit representeert heeft een
beslistermijn en een bezwaarpad”) sleutelt daarop. Een besluit dat verrijkt is
zonder dat de Awb-termijnen erin zitten, faalt op die poort, ook wanneer de
traversal de Awb nooit heeft gezien.
Tot de Awb verrijkt is en die poort bestaat, is de Awb-werking een bekend gat met een naam, en geen kaart die dekking suggereert.
Een sluiting heeft een beginpunt nodig, en “verrijk de zorgtoeslag” is er geen, want daaruit volgt niet wanneer je klaar bent.
Het bruikbare beginpunt is een scenario. De BDD-features zijn de entry points, zoals bij tree-shaking. “Deze burger met dit inkomen krijgt dit bedrag” bepaalt welke outputs berekend moeten kunnen worden, en daaruit volgt welke knopen nodig zijn. De stopconditie is dan niet dat de graaf leeg is maar dat de scenario’s draaien.
Een dieptelimiet en een budget blijven bestaan als vangnet achter deze stopconditie. Ze markeren en loggen wat ze afkappen, volgens requirement 4.
Er zit een kip-ei in de opzet: de afhankelijkheden zijn pas bekend na verrijking, terwijl de verrijking gestuurd moet worden op de afhankelijkheden. Dat lost een package manager op door resolven en bouwen te scheiden, en hier werkt dat ook.
De resolve-stap is goedkoop en leest alleen verwijzingen uit de wettekst: welk artikel verwijst naar welk artikel van welke wet, met een type erbij. Dat is grotendeels mechanisch, want “als bedoeld in artikel 8 van de Algemene wet inkomensafhankelijke regelingen” is een vaste vorm, met een lichte agent voor de rest. Uitkomst zijn kanten en geen YAML.
De enrich-stap is duur en draait alleen over de knopen in de sluiting.
De resolve-stap blijft smal en draait alleen over de sluiting. Cargo werkt zo: de resolver haalt metadata op van de packages in de dependency tree en niet van de hele registry. Wie omgekeerde vragen wil beantwoorden (“welke wetten hangen van dit artikel af”), heeft een brede index nodig, en dat is bij cargo ook een aparte dienst die naast de resolver staat. Zo’n index is hier later te bouwen op dezelfde resolve-stap, en hij hoeft niet in de enricher-lus te zitten.
Wetten verwijzen over en weer, dus de graaf is niet acyclisch en er is geen topologische volgorde om in te bouwen.
Daaruit volgt een concrete verandering in wat er nu staat: de bindingspoort mag geen wet-poort zijn maar moet een sluitings-poort zijn. Zolang een binding wijst naar een knoop die zelf nog in de werkvoorraad staat, is dat geen bevinding maar een openstaande taak. Pas als de sluiting leeg is, telt een onvervulde binding als fout. Dat verklaart de zes van zeven bindingsbevindingen uit ronde 2 en haalt ze weg zonder de controle te verzwakken.
De status hoort per knoop en niet per wet, en hij hoort naast de wet in een sidecar bij de toestandsdatum. De wet-YAML zelf is het contract dat de engine leest en daar hoort geen procesadministratie in.
Per fragment: welke enricher-versie, welke schemaversie, de poortuitslagen, de markeringen, en een hash van de brontekst. Die hash is de invalidatie. Verandert de toestand door een wijzigingswet, dan vervalt de status van precies de artikelen die veranderd zijn en niet van de wet als geheel. Dat is de integriteitscheck die een lockfile ook doet, en het is de voorwaarde voor requirement 2: zonder hash is hergebruik van eerder werk een gok.
De graaf komt in Postgres, maar als afgeleide. De waarheid staat in de bestanden en de index is weg te gooien en opnieuw op te bouwen. Twee bronnen van waarheid lopen uit elkaar, en de bestanden zijn degene die gereviewd worden.
De index neemt alleen documenten op vanaf schemaversie 0.7.0. Daaronder ontbreekt
placement, staat enables als tweede kanaal naast open_terms, en zegt een
untranslatable niet welke waarden hij blokkeert. Zo’n document bevat de kanten
en de markeringen die de graaf nodig heeft niet.
Een harde ondergrens is hier goedkoper dan een index die half gevulde knopen
bevat, en hij voorkomt de fout die de eerste twee enricher-rondes waardeloos
maakte: alfamateriaal dat meetelde in een meting die over de enricher hoorde te
gaan. Een wet verschijnt in de graaf zodra hij op het nieuwe schema staat, wat de
index meteen tot voortgangsmeter van de migratie maakt.
Schema 0.7.0 biedt daarvoor drie dingen die 0.5.6 niet heeft: placement als
scoperegel, markings met een target waaruit blijkt wat een gat kost, en
declares voor het artikel dat een documenteigenschap vaststelt in plaats van
iets te berekenen. declares kwam erbij toen bleek dat het corpus vrijwel geen
artikelen kent die niets kunnen uitdrukken; wat eruitziet als een leeg artikel
is doorgaans een bepaling van een soort waar niemand naar had gezocht. RFC-027
werkt dat uit.
Daarnaast trekt 0.7.0 de open norm samen in open_terms, ook waar de wet geen
invuller aanwijst, en verwijdert het enables. RFC-031 legt uit waarom die
beweging bij de vorige hoort: de graaf heeft één kant per open norm nodig, en
drie velden die dezelfde delegatie beschrijven leveren drie kanten waarvan er
twee nergens heen gaan.
Dat geldt voor de verrijkte kant. De resolve-stap leest brontekst en heeft die ondergrens niet nodig, dus kanten kunnen bestaan naar knopen die zelf nog geen 0.7.0-document hebben. Zo’n knoop staat in de graaf als bekend en onverrijkt, en dat is de toestand die de werkvoorraad nodig heeft.
Een taak is een knoop plus de wortels waarvoor hij nodig is. Prioriteit is het maximum over die wortels. Dezelfde knoop die vanuit twee wortels gevraagd wordt, is één taak met twee redenen en niet twee taken.
Dat geeft ook gratis antwoord op de vraag waarom iets in de wachtrij staat, en het maakt de prioritering van afgeleid werk afhankelijk van zijn oorzaak in plaats van van een los ingevuld getal.
Naast deze voorraad staat de tweede, van gevonden gaten uit de delegatiesectie. Die twee zijn bewust gescheiden, want ze hebben verschillende uitvoerders en verschillende afwegingen.
De verwachting is dat de graaf uiteenvalt in gemeenschappen die met rechtsgebieden samenvallen: sociale zekerheid rond de Awir en de Wet inkomstenbelasting, omgevingsrecht rond de Omgevingswet, met de algemene wetten als kanten dwars door alles heen.
Als dat klopt, is het bruikbaar: de sluiting van een scenario ligt dan grotendeels binnen één cluster plus een paar algemene wetten, en dan is de werkvoorraad per gebied planbaar in plaats van per wet. Het is toetsbaar zodra de resolve-stap over genoeg corpus heeft gedraaid, door de modulariteit van de graaf te meten. Tot dan is het een vermoeden.
De werking van een algemene wet die nog niet geoogst en verrijkt is, blijft een
gat. De poort op legal_character vangt de vorm (een beschikking zonder
termijnen faalt), maar de inhoud van het Awb-regime zit er pas in wanneer de
applies-to-kanten er zijn.
De resolve-stap moet verwijzingen herkennen die niet in de standaardvorm staan. Impliciete verwijzingen (“de daartoe bevoegde minister”) vindt hij niet.
Een open term die verkeerd geadresseerd is, wijst de zoeker naar het verkeerde
document. De poort kan controleren dát delegated_to gevuld is, niet of het
klopt.
Deze RFC zegt niets over de vraag wanneer een wet opnieuw verrijkt moet worden omdat de enricher beter is geworden. Dat is een herbouwvraag en de sidecar-versies zijn er de grondstof voor.
De bindingscheck van RFC-027 wordt een sluitings-poort. Een binding naar een knoop die zelf nog in de werkvoorraad staat, is daar geen bevinding maar een openstaande taak, en pas bij een lege sluiting telt een onvervulde binding als fout.
De goedkoopste eerste stap is de sidecar met status per fragment, inclusief de hash. Die is los bruikbaar, want hij maakt hergebruik meteen veilig, en hij is nodig voor al het andere.
Daarna de resolve-stap over de wetten die nu in de ronde zitten, zodat de graaf bestaat voordat er iets op gebouwd wordt.
Daarna de poort op legal_character, omdat die de gevaarlijkste faalvorm
afdekt: een verrijkte beschikking zonder termijn- en bezwaarmodellering.
Daarna de werkvoorraad met herkomst, en pas dan de sluitings-poort, want die heeft de werkvoorraad nodig om te weten wat nog open staat.
De visualisatie van de graaf staat in een apart ontwerp en is geen voorwaarde voor het bovenstaande.
Hoe de verrijking de reikwijdtebepaling van een algemene wet omzet in
applies-to-kanten, hoe breed zo’n kant mag zijn (“vrijwel elk besluit” is geen
lijst BWB-nummers), en wie die kanten reviewt.
Is de sidecar een bestand naast de wet of een map. Bij fijne fragmentatie wordt één bestand groot.
Deze RFC is in het Nederlands terwijl RFC-027 en RFC-028 in het Engels staan. Dat moet een keer één kant op.
An exploration by Bureau Architectuur of the Dutch Ministry of Economic Affairs and Climate Policy into the possibilities of transparent, executable legislation.
GitHub repository
How it works
Stay informed
Roadmap (Dutch)
Documentation
Research
Bureau Architectuur
Ministry of Economic Affairs and Climate Policy