# Likums-as-Code Latvijas Republikas likumi kā strukturēti dati: katrs likums ir viens XML fails, kas atbilst shēmai `schemas/likumi-0.1.xsd`. Tāds pats stils kā `MK-noteikumi-as-Code` (Act, TextVersion, Source, DataVersion, ID shēma, pārbaudes). PPP Asociācijas (PPPA) pilotprojekta **Valsts PirmKods** daļa. Dati katru dienu tiek ielādēti PPPA Valsts Datu Ezerkrātuvē kā datu kopa **B20**; datu līgums — [contracts/B20-likumi.odcs.yaml](contracts/B20-likumi.odcs.yaml). > Šie nav oficiāli dati. Juridiski saistošs ir oficiālajā izdevumā „Latvijas Vēstnesis” publicētais teksts. ## Struktūra ``` Likums-as-Code/ ├── schemas/likumi-0.1.xsd # shēma, nosaukumtelpa urn:pppa:vpk:likumi:0.1 ├── data/.xml # viens fails katram likumam ├── verification/.verify.json ├── tools/convert.py # likumi.lv konsolidētā teksta Word → XML ├── tools/validate.py # XSD + faila nosaukums = @id ├── likumi.yaml # katalogs ├── contracts/B20-likumi.odcs.yaml # datu līgums (ODCS v3) └── README.md ``` ## Dokumenta uzbūve `Law @id` → `Act` (rekvizīti), `TextVersion` (redakcija un grozījumi), `Source` (iesniegtais fails, SHA-256), `EnactingFormula`, `Body` (`Chapter` → `Article` → `Part` → `Point` → `Point`), `TransitionalProvisions`, `EuReference`, `InForceStatement`, `Adoption`, `Promulgation`, `Signatory`, `Annex`, `DataVersion`. - `TextVersion @basis`: `consolidated` (konsolidētā redakcija, `@asOf` = attēlotās redakcijas datums) vai `original`. - `Article`, `Part`, `Point @status`: `in_force` vai `deleted` (izslēgta vienība paliek failā ar izslēgšanas tekstu). - `Note`: redakcijas atzīmes "(Ar grozījumiem, kas izdarīti ar …)" un "(… likuma redakcijā …)" pie attiecīgās vienības. - `kind`: apraksta birka (purpose, scope, definition, lead, item, provision, delegation, in_force, transitional, deleted), nevis juridiska klasifikācija. ## Avots: likumi.lv lapa (HTML) `tools/convert.py` pieņem arī likumi.lv likuma lapu (`.html`) — Word eksportu nevar lejupielādēt automātiski. `tools/html_source.py` no lapas izveido to pašu rindkopu secību, ko dod Word fails, un convert.py to strukturē ar tiem pašiem noteikumiem. ``` python3 tools/html_source.py fetch # lapa + grozījumu likumu lapas python3 tools/convert.py /.html data/.xml ``` - Numuri (pants, daļa, punkts) lapā ir drukāti tekstā, tāpēc tie tiek ņemti tieši, nevis skaitīti kā Word numerācijā. - Grozījumu saraksts (`TextVersion/Amendment`) tiek veidots no grozījumu likumiem, uz kuriem atsaucas redakcijas piezīmes, un katra grozījuma lapas pases (pieņemts, publicēts, stājas spēkā). Grozījums, kas tekstā neatstāja piezīmi (piem., valūtas maiņa uz eiro), sarakstā var nebūt. - Iestarpināta nodaļa: „II¹ nodaļa” → `c2.1` (`n="2¹"`), „Piektā A nodaļa” → `c5.1` (`n="5A"`). - Panti bez nosaukuma („2.pants. (1) …”) un izslēgti panti („28.pants. (Izslēgts …)”) tiek atpazīti. - Bloki pēc paraksta, kas nav likuma teksts (piem., „PIEZĪMES”), un izslēgtas atsauces uz regulām netiek iekļauti; tie ir verification failā. - Kataloga ierakstiem no HTML ir `likumi_id` un `source: html`. - Ja noslēgumā nav „Likums Saeimā pieņemts …” (piem., Augstākās Padomes likumi), pieņemšanas datums tiek ņemts no likumi.lv pases; tas ir verification failā. - ES atsauce ar vienu aktu bez saraksta: ievadteikums kļūst par vienīgo `Item`. CELEX tiek noteikts arī formai „(ES) 2022/2557” (direktīva L, regula R, lēmums D). - Sadaļa virs nodaļām („A sadaļa …”, piem., PPP likums, kapitāla daļu likums) → `Chapter kind="division"`, ID `…sA`; nodaļas ir tajā ieliktas, to ID paliek pēc drukātā numura (`c1` … `c30`). - Pielikumi (likumi.lv bloki pēc paraksta) → `Annex` ar `Heading`, `Title` un `Line` katrai rindkopai vai tabulas rindai (šūnas atdalītas ar „ | ”); „1.¹ pielikums” → `ann1s1`. Pielikumu teksts ir pilnības skaitā. - Divi likumi, pieņemti vienā dienā: otrais saņem ID ar `-2` (… `-9`), izšķir `likumi.yaml` pēc `likumi_id` (piem., `lv-lik-2002-10-31-2`). - Pants, kas pieņemts, bet vēl nav spēkā (likumi.lv rāda tikai nosaukumu un piezīmi „Pants stājas spēkā … un iekļauts likuma redakcijā uz …”) → `status="pending"`, bez teksta. - Numuru varianti: „8.pants (1) …” (bez punkta), „644.¹⁸A pants” → `art644s18a`, pārejas noteikumu „48.¹ …” → `tp.p48s1`. - Augstākās Padomes likumu paraksti („Latvijas Republikas Augstākās Padomes priekšsēdētājs …”, „… sekretārs …”) → `Signatory`. - Lielapjoma ielāde: tiek ieņemts tikai fails, kas atbilst XSD un kura teksta pilnība ir 99–101 %; pārējie paliek ārpus `data/` ar iemeslu atskaitē. Salīdzinājums ar Word avotu (lv-lik-2000-10-19): tie paši nodaļu, pantu un daļu identifikatori, tie paši rekvizīti un noslēgums; HTML versijā 12 vietās nav Word eksporta salipušo punktu, un tai nav neviena konvertora lēmuma pārbaudei (Word: 15). ## Identifikatori | Vienība | Paraugs | Piemērs | |---|---|---| | Likums | `lv-lik-[-N]` | `lv-lik-2000-10-19` | | Nodaļa | `.cN` | `lv-lik-2000-10-19.c2` | | Pants | `.artN`, 28¹ → `art28s1` | `lv-lik-2000-10-19.art28s1` | | Daļa | `.dN`, 4¹ → `d4s1` | `lv-lik-2000-10-19.art10.d4s1` | | Punkts | `<…>.pN` (rekursīvi) | `lv-lik-2000-10-19.art2.d2.p7` | | Pārejas noteikumi | `.tp`, `.tp.pN` | `lv-lik-2000-10-19.tp.p31.p1` | | ES atsauce | `.eu`, `.eu.N` | `lv-lik-2000-10-19.eu.2` | | Pielikums | `.annN` | `lv-lik-2000-10-19.ann1` | Likumiem nav numura, tāpēc ID pamatā ir Saeimas pieņemšanas datums. Vienā datumā pieņemtus likumus atšķir ar `-2`, `-3`. ## Akoma Ntoso Shēma nav Akoma Ntoso, bet ir pārveidojama uz to bez informācijas zuduma: | likumi-0.1 | Akoma Ntoso (OASIS LegalDocML) | |---|---| | `Law` | `akomaNtoso/act` | | `Act` | `meta/identification` FRBRWork (datums, izdevējs, veids) | | `TextVersion @asOf` | FRBRExpression (`FRBRdate`), `meta/lifecycle` | | `TextVersion/Amendment` | `lifecycle/eventRef` + `passiveModifications` | | `Source` | FRBRManifestation | | `EnactingFormula` | `preamble/formula` | | `Chapter` | `chapter` (eId `chap_N`); `kind="division"` → `part` (eId `part_A`) | | `Article` | `article` (eId `art_N`) | | `Part` | `paragraph` (eId `art_N__para_M`) | | `Point` | `point` (eId `…__point_K`) | | `TransitionalProvisions` | `hcontainer name="transitional"` | | `Note` | `authorialNote` | | `Annex` | `attachments/attachment` (eId `att_N`) | | `InForceStatement`, `Adoption`, `Promulgation`, `Signatory` | `conclusions` | ID pārveide: `.c` → `chap_`, `.art` → `art_`, `.d` → `__para_`, `.p` → `__point_`, `s1` → `_1` (piem., `art10.d4s1` → `art_10__para_4_1`). Pārveidotājs `tools/to_akn.py` vēl nav izveidots. ## Pārbaudes `tools/validate.py`: XSD (struktūra, ID formāts, ID unikalitāte) un faila nosaukums = `@id`. `tools/convert.py` katram failam raksta `verification/.verify.json`: vienību skaits, avota un XML teksta zīmju skaits (bez atstarpēm) un saraksts ar vietām, kur konvertors pieņēma lēmumu (piem., Word numurs "41" interpretēts kā daļa 4¹, nenumurēta rindkopa pievienota iepriekšējai vienībai). Šīs vietas pārbauda cilvēks. ## Statuss Paraugs: 1 likums ("Par sabiedrisko pakalpojumu regulatoriem", redakcija uz 2026-04-03) — 9 nodaļas, 57 panti, 248 daļas, 131 punkts, 73 redakcijas atzīmes, 21 grozījums; XSD derīgs; teksta pilnīgums 99,4 % (76 028 no 76 482 zīmēm); 15 vietas pārbaudei. Avota Word failā daži vārdi ir salipuši (piem., "izveidesun"); konvertors tekstu nelabo.