diff --git a/docs/adr/001-markdown-som-mellanformat.md b/docs/adr/001-markdown-som-mellanformat.md new file mode 100644 index 0000000..a66b297 --- /dev/null +++ b/docs/adr/001-markdown-som-mellanformat.md @@ -0,0 +1,227 @@ +# ADR-001: Markdown som mellanformat + +## Status + +Accepterad + +## Kontext och problembeskrivning + +För att konvertera SFS-författningar från källdata (JSON) till olika output-format (HTML, Git, vektorembeddings) behövde vi välja en arkitektur för dataflödet. + +Huvudalternativen var: + +1. **Direkt konvertering**: JSON → HTML, JSON → Git, JSON → Vector (separata pipelines) +2. **Mellanformat**: JSON → [Mellanformat] → (HTML/Git/Vector/etc) + +Utmaningarna var: + +- **Code duplication**: Varje exporter skulle behöva implementera samma parsing-logik +- **Konsistens**: Hur garantera att HTML-versionen och Git-versionen är identiska? +- **Mänsklig läsbarhet**: Utvecklare och bidragsgivare måste kunna granska output +- **Versionskontroll**: Ska mellan-representationen kunna versionshanteras? +- **Temporal processing**: Var i kedjan ska temporal filtrering appliceras? +- **Underhållbarhet**: Ändringar i parsing-logik ska inte kräva uppdateringar i alla exporters + +## Beslut + +Vi använder **Markdown med HTML-taggar** som mellanformat mellan JSON-källdata och alla output-format. + +### Arkitektur + +``` +JSON (Regeringskansliet) + ↓ +[format_sfs_text_as_markdown] + ↓ +Markdown med
-taggar och selex:-attribut + ↓ +├─→ [apply_temporal] → Markdown (rent) → HTML +├─→ [apply_temporal] → Markdown (rent) → Git commits +├─→ [apply_temporal] → Markdown (rent) → Vector embeddings +└─→ Markdown (med taggar) → Publiceras som md-markers +``` + +### Varför Markdown? + +**Mänsklig läsbarhet**: +```markdown +## 1 kap. Inledande bestämmelser + +### 1 § +Denna författning gäller för... +``` + +**Semantisk struktur** (behålls via HTML i Markdown): +```html +
+## 1 kap. Inledande bestämmelser +... +
+``` + +**Versionskontroll**: +- Markdown är text-baserat → perfekt för Git diff +- Granskare kan läsa ändringar direkt på GitHub +- Merge conflicts är läsbara och lösbara + +### Implementation + +**Steg 1: JSON → Markdown** (`formatters/format_sfs_text.py`) +- Konverterar JSON-strukturen till Markdown-rubriker +- Lägger till `
`-taggar med CSS-klasser +- Extraherar och annoterar temporal metadata som `selex:`-attribut + +**Steg 2: Markdown → Output-format** +- **HTML**: `markdown.markdown()` + custom extensions → HTML +- **Git**: Temporal filtrering + commit med markdown-filer +- **Vector**: Temporal filtrering + chunking + embedding +- **md-markers**: Ingen transformation (publiceras som är) + +## Konsekvenser + +### Positiva + +- **Single source of truth**: All parsing-logik finns på ett ställe (`format_sfs_text.py`) +- **Konsistens**: Alla output-format utgår från samma Markdown-representation +- **Granskning**: Pull requests visar Markdown-diff som är läsbar för människor +- **Flexibilitet**: Lätt att lägga till nya output-format + - Vill du ha PDF? Konvertera Markdown → PDF med pandoc + - Vill du ha EPUB? Markdown → EPUB med tooling +- **Standard tooling**: Markdown har enormt ekosystem (parsers, linters, previewers) +- **Hybrid format**: HTML-i-Markdown ger både läsbarhet och semantik +- **Debug-vänligt**: Kan inspektera Markdown-filer manuellt vid problem +- **Cacheable**: Markdown-filer kan sparas och återanvändas +- **Testbarhet**: Enkelt att skriva tester mot Markdown-output + +### Negativa + +- **Extra konverteringssteg**: JSON → Markdown → HTML tar mer tid än direkt JSON → HTML + - Mitigering: Prestandan är acceptabel, och flexibiliteten väger tyngre + +- **HTML-i-Markdown komplexitet**: Inte alla Markdown-renderare hanterar HTML perfekt + - Mitigering: Vi använder beprövade bibliotek (`markdown` för Python) + +- **Temporal metadata i HTML-attribut**: Okonventionellt för Markdown + - Mitigering: Dokumenterat i ADR-004, fungerar i praktiken + +- **Två Markdown-varianter**: `md-markers` (med taggar) vs `md` (rent) + - Mitigering: Tydlig separation, olika användningsfall + +### Tekniska konsekvenser + +- **Format-specificering**: `--formats md-markers` vs `--formats md` + - `md-markers`: Bevarar all metadata, för vidare processing + - `md`: Rendad version efter temporal filtrering + +- **Temporal processing**: Sker EFTER Markdown-generering + - Markdown → `apply_temporal(target_date)` → Rendad Markdown + +- **Lazy evaluation**: Temporal filtrering kan postponas till senare + - `md-markers` sparar alla möjligheter öppna + +## Alternativ som övervägdes + +### 1. Direkt JSON → HTML/Git/Vector + +**Fördelar**: +- Snabbare (färre steg) +- Enklare arkitektur + +**Varför inte valt**: +- Code duplication: Varje exporter måste parsa JSON +- Konsistensproblem: Olika exporters kan tolka JSON olika +- Ingen human-readable mellanrepresentation +- Svårt att granska output (JSON är inte läsbart som Markdown) + +### 2. XML som mellanformat (TEI eller custom) + +```xml + + + Inledande bestämmelser + + Denna författning gäller... + + + +``` + +**Fördelar**: +- Strikt struktur med validering +- Etablerad standard (TEI) inom juridisk text + +**Varför inte valt**: +- Mindre läsbart för människor +- Högre inlärningströskel +- Mindre ekosystem än Markdown +- Svårare att granska i pull requests +- Overkill för vårt användningsfall + +### 3. JSON som mellanformat (normaliserad struktur) + +**Varför inte valt**: +- Inte mänskligt läsbart +- Svårt att versionskontrollera (JSON diff är svårläst) +- Inget naturligt sätt att representera flytande text med rubriker + +### 4. AST (Abstract Syntax Tree) + +```python +{ + "type": "document", + "children": [ + {"type": "chapter", "number": "1", "heading": "..."}, + {"type": "paragraph", "number": "1", "content": "..."} + ] +} +``` + +**Varför inte valt**: +- Rent programmatiskt format, inte läsbart +- Måste serialiseras för att inspekteras +- Ingen standard representation +- Kan inte versionskontrolleras meningsfullt + +## Relaterade beslut + +- [ADR-004](004-semantiska-temporal-taggar.md) - Selex-attribut i Markdown +- [ADR-003](003-git-commits-historiska-datum.md) - Markdown-filer committas till Git + +## Noteringar + +- **Implementationer**: + - `formatters/format_sfs_text.py` - JSON → Markdown konvertering + - `formatters/frontmatter_manager.py` - YAML frontmatter i Markdown + - `temporal/apply_temporal.py` - Temporal filtrering av Markdown + - `exporters/html/html_export.py` - Markdown → HTML med `markdown.markdown()` + - `exporters/vector/chunking.py` - Markdown → Chunks för embeddings + +- **Markdown flavor**: CommonMark-kompatibel med HTML-extension + - Rubriker: Standard Markdown (`##`, `###`, `####`) + - Paragrafer: Standard Markdown (dubbla radbrytningar) + - Semantik: HTML `
` och `
` taggar + - Links: Standard Markdown-länkar + auto-linking + +- **Frontmatter**: YAML frontmatter för metadata + ```yaml + --- + beteckning: "2024:100" + rubrik: "Författning om exempel" + ikraft_datum: "2025-01-01" + --- + ``` + +- **Fördelar med två varianter**: + - **md-markers**: För vidare processing, AI-analys, temporal queries + - **md**: För publicering, läsning, GitHub Pages + +- **Future-proof**: Om nya output-format behövs (PDF, DOCX, LaTeX): + - Använd befintlig Markdown → Konvertera med standard tooling + - Ingen ändring i core parsing-logik behövs + +- **Exempel på Markdown-ekosystem som vi drar nytta av**: + - `python-markdown`: Markdown → HTML konvertering + - GitHub/GitLab: Automatisk rendering av `.md` filer + - Markdown linters: Kvalitetskontroll av output + - Markdown previewers: Live-förhandsvisning under utveckling + - Pandoc: Potentiell framtida konvertering till andra format diff --git a/docs/adr/002-import-fran-regeringskansliet.md b/docs/adr/002-import-fran-regeringskansliet.md new file mode 100644 index 0000000..7392289 --- /dev/null +++ b/docs/adr/002-import-fran-regeringskansliet.md @@ -0,0 +1,141 @@ +# ADR-002: Import från Regeringskansliet istället för PDF-crawling + +## Status + +Accepterad + +## Kontext och problembeskrivning + +För att konvertera SFS-författningar till olika format behövde vi en källdatakälla. Det finns två huvudsakliga alternativ för att få tillgång till författningstexter: + +1. **PDF-crawling**: Ladda ner publicerade PDF:er från olika källor och extrahera text +2. **Strukturerad data-import**: Använda API:er som tillhandahåller strukturerad data (JSON/XML) + +Utmaningarna med PDF-crawling: + +- Text extraction från PDF är opålitlig (tabeller, fotnoter, formatering går förlorad) +- Ingen semantisk struktur (kapitel, paragrafer, rubriker måste detekteras heuristiskt) +- Temporal metadata (ikraftträdandedatum, upphävanden) finns inte i PDF:en +- OCR-fel vid scannade dokument +- Layout-beroende parsing (när PDF-layouten ändras, bryts parsern) + +Alternativen för strukturerad data: + +- **Riksdagens API** (`data.riksdagen.se`) - XML-format, fokus på riksdagsarbete +- **Regeringskansliets rättsdatabas** (`beta.rkrattsbaser.gov.se`) - JSON via Elasticsearch API + +## Beslut + +Vi använder **Regeringskansliets Elasticsearch API** (`beta.rkrattsbaser.gov.se`) som primär källdatakälla för SFS-författningar. + +### API-detaljer + +- **Endpoint**: `https://beta.rkrattsbaser.gov.se/elasticsearch/SearchEsByRawJson` +- **Format**: JSON via Elasticsearch queries +- **Innehåll**: Fullständig författningstext med strukturerad metadata +- **Metadataexempel**: + - Beteckning (`2024:100`) + - Departement + - Ikraftträdandedatum + - Ändringshistorik + - Rubrikstruktur (avdelningar, kapitel, paragrafer) + +## Konsekvenser + +### Positiva + +- **Strukturerad data**: JSON med tydlig hierarki (avdelningar → kapitel → paragrafer) +- **Rik metadata**: Departement, datum, ändringshistorik inkluderad +- **Tillförlitlighet**: Officiell källa från Regeringskansliet +- **Automatisering**: Enkel att hämta via HTTP POST requests +- **Versionshantering**: Ändringsförfattningar och ursprungsdokument finns +- **Undviker PDF-problem**: Ingen text extraction, ingen OCR, ingen layout-parsing +- **Temporal data**: Ikraftträdande och upphävanden finns i metadata +- **Konsistent format**: Alla författningar i samma JSON-schema + +### Negativa + +- **Beta-status**: API:et är markerat som "beta", kan förändras + - Mitigering: Versionshantering av downloader-skript, tester för att upptäcka breaking changes +- **Ingen SLA**: Inget officiellt servicenivåavtal eller versionsstöd + - Mitigering: Lokalt cachning av nedladdad JSON i `data/sfs_json/` +- **Proprietärt API**: Regeringskansliets eget format, inte en öppen standard + - Mitigering: Abstraktionslager i `downloaders/` gör byte av källa möjligt +- **Nätverksberoende**: Kräver internetanslutning för initial hämtning + - Mitigering: Offline-körning möjlig med lokalt cachad data + +### Tekniska konsekvenser + +- **Downloader-arkitektur**: Implementationen i `downloaders/rkrattsbaser_api.py` abstraherar API-anrop +- **Fallback**: `downloaders/riksdagen_api.py` finns som backup-källa vid behov +- **Caching-strategi**: JSON sparas lokalt för att undvika upprepade API-anrop +- **Rate limiting**: Implementerad delay mellan requests för att respektera servern + +## Alternativ som övervägdes + +### 1. PDF-crawling från Regeringskansliets webbplats + +**Varför inte valt**: + +- Opålitlig text extraction +- Ingen strukturerad metadata +- Kräver komplex layout-parsing +- Temporal information måste extraheras heuristiskt från text +- Högre underhållskostnad när PDF-format ändras + +### 2. Riksdagens API (data.riksdagen.se) + +```xml + + 2024:100 + ... + +``` + +**Fördelar**: + +- Officiellt API med stabil uptime +- XML-format + +**Varför inte valt**: + +- Fokus på riksdagsarbete, inte konsoliderade författningar +- Mindre detaljerad metadata för författningar +- XML-parsing mer komplext än JSON +- Regeringskansliets data är mer författningsfokuserad + +**Notering**: Vi behåller `riksdagen_api.py` som fallback-källa + +### 3. Scraping från [svenskforfattningssamling.se](https://svenskforfattningssamling.se/) + +**Varför inte valt**: + +- Inget officiellt API +- Scraping kan bryta när webbplatsen uppdateras + +## Relaterade beslut + +- [ADR-004](004-semantiska-temporal-taggar.md) - Temporal metadata kommer från Regeringskansliets API + +## Noteringar + +- **Implementationer**: + - `downloaders/rkrattsbaser_api.py` - Primär implementation + - `downloaders/riksdagen_api.py` - Backup-källa + - `downloaders/download_sfs_docs.py` - CLI för att hämta författningar + +- **Användning**: + + ```bash + # Hämta specifik författning + python downloaders/download_sfs_docs.py --ids "2024:100" --source rkrattsbaser + + # Hämta alla författningar + python downloaders/download_sfs_docs.py --ids all --source rkrattsbaser + ``` + +- **Caching**: Nedladdad JSON sparas i `data/sfs_json/` för offline-användning + +- **Rate limiting**: Implementerad 1-sekunds delay mellan requests för att respektera servern + +- **Framtidsutsikter**: Om API:et tas bort eller ändras drastiskt kan vi falla tillbaka på Riksdagens API eller implementera en hybrid-lösning diff --git a/docs/adr/003-git-commits-historiska-datum.md b/docs/adr/003-git-commits-historiska-datum.md new file mode 100644 index 0000000..0a73aa8 --- /dev/null +++ b/docs/adr/003-git-commits-historiska-datum.md @@ -0,0 +1,220 @@ +# ADR-003: Git-commits med historiska datum för versionshistorik + +## Status + +Accepterad + +## Kontext och problembeskrivning + +Lagstiftning har en inneboende temporal dimension - författningar stiftas, ändras och upphävs vid specifika datum. För att göra denna historik tillgänglig och navigerbar behövde vi ett sätt att representera hur en författning såg ut vid olika tidpunkter genom historien. + +Utmaningarna var: + +1. **Historisk representation**: Hur visar vi hur en författning såg ut 2010 vs 2024? +2. **Navigerbarhet**: Användare ska kunna "scrolla" bakåt i tiden +3. **Versionshantering**: Varje ändring ska vara spårbar med exakt datum +4. **Teknisk enkelhet**: Systemet ska vara lätt att förstå och använda +5. **Standardverktyg**: Helst undvika custom databaser eller proprietära system + +Alternativen inkluderade: + +- Separata filer per version med datum i filnamn +- Databas med temporal data (PostgreSQL temporal tables) +- Custom versionshanteringssystem +- Git med manipulerade commit-datum + +## Beslut + +Vi använder **Git med backdated commits** där varje författning och ändring får en commit med det faktiska historiska datumet då den trädde i kraft eller utfärdades. + +### Teknisk implementation + +**Miljövariabler för datum**: +```python +env = { + 'GIT_AUTHOR_DATE': '2010-01-01 12:00:00 +0100', + 'GIT_COMMITTER_DATE': '2010-01-01 12:00:00 +0100' +} +subprocess.run(['git', 'commit', '-m', message], env=env) +``` + +**Commit-strategi**: + +1. **Initial commit**: Skapas med `utfardadDateTime` (utfärdandedatum) + - Innehåller ursprungsversionen av författningen + - Temporal filtrering appliceras upp till utfärdandedatumet + +2. **Ändrings-commits**: Skapas med respektive `ikraft_datum` + - Varje ändring får en separat commit + - Commiten visar hur författningen ser ut efter ändringen trätt i kraft + +3. **Upphävande-commits**: Skapas när en författning upphävs + - Markerar när en författning slutar gälla + +**Branch-struktur**: +- Commits skapas på en dedikerad branch (t.ex. `git-export-YYYYMMDD`) +- Branch kan pushas till separat repository (`se-lex/sfs`) + +### Exempel på commit-historik + +``` +2024-07-01 ✏️ Ändra SFS 2010:100 - SFS 2024:500 +2023-01-01 ✏️ Ändra SFS 2010:100 - SFS 2023:50 +2010-01-15 📜 SFS 2010:100 om exempel +``` + +När man gör `git checkout ` får man exakt hur författningen såg ut vid det datumet. + +## Konsekvenser + +### Positiva + +- **Git som tidsmaskin**: `git log --since="2015-01-01" --until="2016-01-01"` visar alla ändringar under ett år +- **Diff mellan versioner**: `git diff ` visar exakt vad som ändrats +- **Standardverktyg**: Alla Git-klienter fungerar (GitHub, GitLab, gitk, SourceTree, etc.) +- **Gratis hosting**: GitHub/GitLab tillhandahåller gratis hosting och webb-UI +- **Blame-funktion**: `git blame` visar exakt när varje rad ändrades +- **Decentraliserat**: Varje klon innehåller hela historiken +- **Visuell representation**: GitHub/GitLab visar automatiskt commit-graf och tidslinje +- **API-tillgång**: Git-hostar erbjuder REST API:er för att hämta historiska versioner + +### Negativa + +- **Okonventionell användning**: Git är inte designat för backdated commits + - Mitigering: Tydlig dokumentation, separata branches för Git-export + +- **Commit-ordning**: Git sorterar efter commit-datum, inte när commiten skapades + - Mitigering: Detta är faktiskt önskat beteende - vi vill ha kronologisk ordning + +- **Merge-komplexitet**: Svårt att merge:a historiska branches + - Mitigering: Git-export är en one-way operation, inget merging behövs + +- **Repository-storlek**: Många commits kan göra repositoryt stort + - Mitigering: SFS har ~50 000 författningar, hanteras fint av Git + +- **Author vs Committer**: Båda datum sätts till historiskt datum + - Mitigering: Konsekvent beteende, men metadata om faktiskt skapandedatum går förlorad + +- **Duplicate-hantering**: Risk för dubbla commits med samma meddelande + - Mitigering: Implementerad check i `check_duplicate_commit_message()` + +### Tekniska konsekvenser + +- **Temporal processing**: Varje commit-punkt kräver temporal filtrering upp till det datumet +- **Branch-isolation**: Git-commits måste ske på dedikerad branch +- **Clean state**: Branchen rensas innan ny export (`remove_all_commits_on_branch`) +- **Performance**: Sekventiell processning av alla författningar tar tid + - Optimering: Batch-processing i `temporal_commits_batch_processor.py` + +## Alternativ som övervägdes + +### 1. Separata filer med datum i namn + +``` +2010-100/2010-01-15.md +2010-100/2023-01-01.md +2010-100/2024-07-01.md +``` + +**Varför inte valt**: + +- Ingen inbyggd diff-funktionalitet +- Svårt att navigera mellan versioner +- Ingen standardiserad tooling +- Måste bygga custom UI för att visa ändringar + +### 2. PostgreSQL temporal tables + +```sql +CREATE TABLE laws ( + id INT, + content TEXT, + valid_from DATE, + valid_to DATE +); +``` + +**Varför inte valt**: + +- Kräver databas-infrastruktur +- Mindre tillgängligt för användare (kräver SQL-kunskap) +- Ingen visuell representation utan custom UI +- Svårare att hosta och dela publikt + +### 3. Custom versionshanteringssystem + +**Varför inte valt**: + +- Reinventing the wheel +- Måste bygga all tooling från grunden +- Ingen befintlig community eller ekosystem +- Högre underhållskostnad + +### 4. Git tags istället för commits + +``` +git tag "2010-100-v1" +git tag "2010-100-v2" +``` + +**Varför inte valt**: + +- Tags visar inte temporal progression lika tydligt +- Inget naturligt sätt att se alla ändringar kronologiskt +- `git log` blir mindre användbart +- Tags är metadata, inte innehåll + +### 5. Separata branches per författning + +``` +branches: 2010-100, 2010-101, 2010-102, ... +``` + +**Varför inte valt**: + +- 50 000+ branches blir ohanterbart +- Svårt att se alla lagändringar kronologiskt +- Branch-explosion överbelastar Git-UI:s + +## Relaterade beslut + +- [ADR-004](004-semantiska-temporal-taggar.md) - Temporal metadata som driver commit-genereringen +- [ADR-002](002-import-fran-regeringskansliet.md) - Källdata för utfärdande- och ikraftträdandedatum + +## Noteringar + +- **Implementationer**: + - `exporters/git/generate_commits.py` - Skapar initial och ändrings-commits + - `exporters/git/git_utils.py` - Git-operationer med `GIT_AUTHOR_DATE` och `GIT_COMMITTER_DATE` + - `exporters/git/temporal_commits_batch_processor.py` - Batch-processing för prestanda + +- **Användning**: + + ```bash + # Exportera till Git med historiska commits + python sfs_processor.py --formats git --filter 2024 + + # Efter export, navigera i historiken + cd + git log --oneline --since="2020-01-01" + git show + git diff + ``` + +- **Output-repository**: https://github.com/se-lex/sfs + - Innehåller all SFS-lagstiftning med historiska commits + - Publikt tillgänglig för utvecklare och jurister + - API-åtkomst via GitHub REST API + +- **Commit-meddelanden**: Använder emojis för att indikera typ av ändring + - 📜 Initial författning + - ✏️ Ändring av författning + - 🗑️ Upphävande + +- **Performance**: ~50 000 författningar tar flera timmar att processa + - Optimering: Batch-processing, parallellisering övervägs + +- **Framtida förbättringar**: + - Metadata-fil per commit för att bevara faktiskt skapandedatum + - Signerade commits för autenticitet + - Incremental updates istället för full rebuild diff --git a/docs/adr/004-semantiska-temporal-taggar.md b/docs/adr/004-semantiska-temporal-taggar.md new file mode 100644 index 0000000..b6a816a --- /dev/null +++ b/docs/adr/004-semantiska-temporal-taggar.md @@ -0,0 +1,163 @@ +# ADR-004: Semantiskt val av taggar för temporal data + +## Status + +Accepterad + +## Kontext och problembeskrivning + +Författningar i SFS förändras över tid - paragrafer träder i kraft vid olika datum, upphävs, eller ändras. För att korrekt kunna: + +- Visa hur en författning såg ut vid ett specifikt datum +- Filtrera bort upphävda bestämmelser +- Hantera ikraftträdanderegler +- Skapa historiska versioner i Git +- Generera semantiska vektorembeddings för endast gällande regelverk + +...behövde vi ett semantiskt system för att märka upp temporal information i Markdown-filerna. + +Utmaningarna var: + +1. **Bevara temporal metadata** genom hela processing-kedjan (JSON → Markdown → HTML/Git/Vector) +2. **Standardkompatibilitet**: Markdown ska vara läsbart både för människor och maskiner +3. **Filtreringslogik**: Enkelt att identifiera och filtrera baserat på datum +4. **Namnrymd**: Undvika kollisioner med standard HTML-attribut +5. **Juridisk precision**: Fånga skillnaden mellan "upphävd", "ännu ej ikraftträdd", och "gällande" + +## Beslut + +Vi använder **custom HTML-attribut med `selex:`-prefix** för temporal metadata i Markdown-filer. + +### Attributschema + +```html +
+#### 1 § +... +
+ +
+### Upphävda bestämmelser +... +
+ +
+#### 5 § +... +
+``` + +### Attributdefinitioner + +| Attribut | Typ | Beskrivning | Exempel | +|----------|-----|-------------|---------| +| `selex:status` | Enum | Juridisk status: `ikraft`, `upphavd`, `upphord` | `selex:status="ikraft"` | +| `selex:ikraft_datum` | Date (ISO 8601) | Datum då sektionen träder i kraft | `selex:ikraft_datum="2025-01-01"` | +| `selex:upphor_datum` | Date (ISO 8601) | Datum då sektionen upphör att gälla | `selex:upphor_datum="2023-12-31"` | +| `selex:ikraft_villkor` | String | Villkor för ikraftträdande (vid avsaknad av exakt datum) | `selex:ikraft_villkor="den dag regeringen bestämmer"` | + +### Filtreringslogik + +`temporal/apply_temporal.py` implementerar följande regler för ett givet `target_date`: + +1. Sektioner med `selex:status="upphavd"` eller `"upphord"` → **tas bort helt** +2. Sektioner med `selex:upphor_datum <= target_date` → **tas bort helt** +3. Sektioner med `selex:ikraft_datum > target_date` → **tas bort helt** (ej ikraftträtt ännu) +4. Sektioner med `selex:ikraft_datum <= target_date` → **behålls, temporal attribut tas bort** +5. Nestlade sektioner: Om överordnad sektion tas bort → alla underordnade tas också bort + +## Konsekvenser + +### Positiva + +- **Bevarad semantik**: Temporal metadata följer med genom hela kedjan +- **Enkel parsing**: Standard regex kan extrahera `selex:*` attribut +- **Markdown-kompatibilitet**: Filerna är fortfarande läsbara Markdown (HTML i Markdown är standard) +- **Namnrymdsseparation**: `selex:`-prefix undviker kollisioner med andra attribut +- **Precision**: Distinkt hantering av olika temporala tillstånd +- **Testbarhet**: Lätt att verifiera filtreringslogik med unit tests +- **ISO 8601-datum**: Standardiserat datumformat (`YYYY-MM-DD`) som är sorterbara och internationellt vedertagna + +### Negativa + +- **Custom schema**: Inte en etablerad standard som TEI eller Akoma Ntoso + - Mitigering: Dokumenterat schema, möjligt att konvertera till andra format senare +- **Markdown rendering**: Vissa Markdown-renderare visar attributen synligt + - Mitigering: I `md`-format rensas attributen bort, `md-markers` är för vidare bearbetning +- **Manuell synk**: Attributen måste hållas konsistenta med källdata (JSON från Regeringskansliet) + - Mitigering: Automatisk generering från JSON i `formatters/format_sfs_text.py` + +### Teknisk skuld + +- **Framtida standardisering**: Om juridisk XML-standard blir vedertagen (TEI, Akoma Ntoso) kan migration behövas +- **Valideringsschema**: Inget formellt XML-schema för `selex:`-attributen ännu + - Åtgärd: Överväg JSON Schema eller XML Schema för validering i framtiden + +## Alternativ som övervägdes + +### 1. YAML frontmatter per sektion + +```markdown +--- +status: ikraft +ikraft_datum: 2025-01-01 +--- +#### 1 § +... +``` + +**Varför inte valt**: + +- Frontmatter är per-fil, inte per-sektion +- Svårare att parsa med regex +- Bryter Markdown-flödet + +### 2. Kommentarbaserad metadata + +```markdown + +#### 1 § +... +``` + +**Varför inte valt**: + +- Osynlig i vissa renderare (svårare att debugga) +- Ingen semantisk koppling mellan kommentar och innehåll +- Svårare att matcha sektion till metadata + +### 3. Standard HTML data-attribut + +```html +
+``` + +**Varför inte valt**: + +- `data-*` attribut är för custom application data, inte domain-specifik semantik +- Vi ville tydligt signalera att detta är Selex-specifik metadata + +### 4. TEI (Text Encoding Initiative) XML + +```xml +
+``` + +**Varför inte valt**: + +- Mycket tungt för vårt användningsfall +- Kräver komplett XML-struktur, inte kompatibelt med Markdown +- Högre inlärningströskel + +## Relaterade beslut + +- [ADR-002](002-import-fran-regeringskansliet.md) - Källdata för temporal information + +## Noteringar + +- Implementationen finns i: + - `temporal/apply_temporal.py` - Filtreringslogik + - `formatters/format_sfs_text.py` - Generering av attribut från JSON + - `temporal/title_temporal.py` - Temporal bearbetning av titlar +- Testad med 100+ författningar från SFS +- Datumsystemet hanterar både absoluta datum (ISO 8601) och villkor (text) diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..48af0ad --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,35 @@ +# Architecture Decision Records (ADR) + +Denna katalog innehåller Architecture Decision Records (ADR) för sfs-processor projektet. + +## Vad är ADR? + +Architecture Decision Records är dokument som fångar viktiga arkitektoniska beslut som fattats under projektets utveckling, tillsammans med kontexten och konsekvenserna av dessa beslut. + +## Format + +Vi använder [MADR](https://adr.github.io/madr/) (Markdown Any Decision Records) som mall för våra ADR:er. Varje ADR följer denna struktur: + +- **Titel**: Kort beskrivning av beslutet +- **Status**: Föreslagen, Accepterad, Avvisad, eller Föråldrad +- **Kontext**: Bakgrund och problemställning +- **Beslut**: Vad har vi bestämt +- **Konsekvenser**: Positiva och negativa effekter av beslutet + +## Index över ADR:er + +| ADR | Titel | Status | +|-----|-------|--------| +| [ADR-001](001-markdown-som-mellanformat.md) | Markdown som mellanformat | Accepterad | +| [ADR-002](002-import-fran-regeringskansliet.md) | Import från Regeringskansliet istället för PDF-crawling | Accepterad | +| [ADR-003](003-git-commits-historiska-datum.md) | Git-commits med historiska datum för versionshistorik | Accepterad | +| [ADR-004](004-semantiska-temporal-taggar.md) | Semantiskt val av taggar för temporal data | Accepterad | + +## Skapa en ny ADR + +När du fattar ett nytt viktigt arkitektoniskt beslut: + +1. Skapa en ny fil med nästa nummer: `XXX-kort-beskrivning.md` +2. Använd MADR-mallen +3. Uppdatera index-tabellen ovan +4. Commit gärna filen tillsammans med koden som implementerar beslutet