feat: model core, launcher, reproduction check and the first two skills

The core in modell/kjerne/ is an unmodified copy of sim.py, diagnose.py and
forlop.py from den-dynamiske-rettsstaten @2badc25, pinned by sha256.
kjor.py is the single entry point; kontroll.py reproduces the note's 22 data
files and printed results. Skills: diagnose and forlop (Norwegian).

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-11-11 13:53:32 +01:00
commit 464ad38b49
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q
51 changed files with 11207 additions and 0 deletions

168
docs/inndata.md Normal file
View file

@ -0,0 +1,168 @@
# Inndata for `diagnose` og `forlop`
`diagnose` og `forlop` leser samme fil: en JSON-fil med ett objekt per ledd i straffesakskjeden. Denne siden
beskriver hvert felt slik kjernens kode leser det (`modell/kjerne/diagnose.py`: `sjekk`, `analyser`, `TALLFELT`;
`modell/kjerne/forlop.py`: `les_styring`, `modell`). Kjernen er en uendret kopi av koden i notatet *Den dynamiske
rettsstaten* (commit 2badc25).
## Enheter
| Hva | Enhet |
|---|---|
| Strømmer (innstrømning, kapasitet, skjult avgang) | saker per **måned** |
| Beholdninger (restanse, restansemål) | saker (et antall, ikke per måned) |
| Tider (mål for saksbehandlingstid, forsinkelse) | måneder |
| Andeler | desimaltall mellom 0 og 1 (0.2 betyr 20 %) |
Tall skrives med punktum som desimaltegn og uten tusenskille: `29044.5`, ikke `29 044,5`.
## Oppbygning
```json
{
"merknad": "fri tekst, valgfritt",
"styring": {"forsinkelse": 3, "reaktivitet": 3},
"ledd": [
{"navn": "Politi", "innstromning": 150, "kapasitet": 175, "restanse": 300, "maal_tid": 2},
{"navn": "Domstol", "innstromning": 134.32, "kapasitet": 105.263, "restanse": 588.95, "maal_tid": 3,
"prognose_innstromning": 134.32, "maks_andel_utenom": 0.2}
]
}
```
- `ledd` (påkrevd): en liste med minst ett ledd, **i kjedens rekkefølge**. Rekkefølgen brukes: leddene etter
skranken omtales som leddene som får sakene sine gjennom den, og `forlop` regner hva flere avgjorte saker betyr
for dem.
- `styring` (valgfritt): brukes bare av `forlop`. Se under.
- Andre felt på øverste nivå (for eksempel `merknad` og `kilder`) leses ikke av koden. Bruk dem til å skrive ned
hvor tallene kommer fra.
## Feltene i hvert ledd
| Felt | Påkrevd | Enhet | Standard | Brukes til |
|---|---|---|---|---|
| `navn` | ja | tekst | – | navnet i utskriften; `forlop` kan velge leddet med dette navnet |
| `innstromning` | ja | saker/mnd | – | utnyttelsen, og restanseveksten når `restanse_for_12_mnd` mangler |
| `kapasitet` | ja | saker/mnd | – | det leddet kan avgjøre per måned **slik det virker nå** |
| `restanse` | ja | saker | – | saker i kø nå |
| `maal_tid` | ett av de to | mnd | – | mål for saksbehandlingstid; restansemålet blir `maal_tid` × `kapasitet` |
| `restanse_maal` | ett av de to | saker | – | akseptabel restanse; brukes i stedet for `maal_tid` når begge er oppgitt |
| `prognose_innstromning` | nei | saker/mnd | `innstromning` | strømmen når balansen er gjenopprettet; kapasiteten dimensjoneres etter den |
| `maks_andel_utenom` | nei | andel, under 1 | 0 | hvor stor andel av sakene som kan ledes til forenklede reaksjoner |
| `restanse_for_12_mnd` | nei | saker | – | restansen for tolv måneder siden; gir observert vekst i restansen |
| `skjult_avgang` | nei | saker/mnd | 0 | saker som avsluttes uten behandling og som er regnet med i `kapasitet` |
| `innstromning_for_okning` | nei | saker/mnd | 95 % av kapasiteten | bare `forlop`: strømmen før den begynte å øke |
Krav som kontrolleres før regningen (`sjekk`):
- `navn`, `innstromning`, `kapasitet` og `restanse` må finnes, og `maal_tid` eller `restanse_maal`.
- `navn` må være tekst.
- Alle tallfeltene må være tall som er 0 eller større og endelige. `true`/`false` godtas ikke.
- `kapasitet` minus `skjult_avgang` må være større enn 0.
- `maks_andel_utenom` må være mindre enn 1.
Brudd på kravene gir en norsk melding som sier hvilket ledd og hvilket felt det gjelder, og ingen regning.
**Feltnavn med skrivefeil blir ikke oppdaget.** Koden leser bare feltene over og ser bort fra alt annet. Står det
`prognose_innstrømning` (med ø) eller `maks_andel_utenfor`, regner verktøyet stille med standardverdien. Feltnavnene
skrives uten æ, ø og å, nøyaktig som i tabellen.
## Hvordan feltene brukes i regningen
Med Z = `kapasitet` − `skjult_avgang` (avgangen med behandling):
| Størrelse | Regnes som |
|---|---|
| Utnyttelse | `innstromning` / Z |
| Saksbeh.tid | `restanse` / `kapasitet`. Vises bare når målet er `maal_tid`; med `restanse_maal` står det «-». Det er ikke målt saksbehandlingstid |
| Restansemål | `restanse_maal`, ellers `maal_tid` × `kapasitet` |
| Restansevekst per måned | (`restanse` − `restanse_for_12_mnd`) / 12, ellers `innstromning` − `kapasitet` (minst 0) |
| Restanse over målet | `restanse` − restansemålet (minst 0) |
| Skranken som binder | høyest utnyttelse på to desimaler; er den lik, leddet der restanseveksten er størst i forhold til Z |
| Leddet binder | utnyttelsen er over 1, eller restansen vokser |
| Utnyttelse med saker ledet utenom | (1 − `maks_andel_utenom`) × `prognose_innstromning` / Z |
| Kapasitetsbehov | ((1 − `maks_andel_utenom`) × `prognose_innstromning` + restanse over målet / 24) / 0,95 |
Kapasitet bestilles bare når (1 − `maks_andel_utenom`) × `prognose_innstromning` + restanse over målet / 24 er større
enn Z. Faste verdier i regningen, som i notatets koordinerte regel (`ENDO` i `sim.py`): målutnyttelse 0,95, restansen
avvikles over 24 måneder, og bestilt kapasitet virker gradvis fra 6 til 24 måneder etter vedtak.
## `styring` (bare `forlop`)
| Felt | Enhet | Standard | Tillatt | Betyr |
|---|---|---|---|---|
| `forsinkelse` | mnd | 3 | over 0, høyst 60 | tiden fra kriminalitetsbildet endrer seg til innsatsen er endret (statistikk, beslutning, iverksetting) |
| `reaktivitet` | – | 3 | over 0, høyst 50 | prosent mer innsats per prosent avvik fra målet (3 betyr at 10 % over målet gir 30 % mer innsats) |
Uten `styring` brukes regime A i notatet (3 og 3), og `forlop` sier fra om det. Står `styring` i fila, men ett av
feltene mangler, brukes standardverdien for det feltet uten merknad.
## Hva `forlop` krever i tillegg
`forlop` legger leddet som binder (eller leddet du velger med navn) inn som modellens ledd med kø. Det stopper med en
melding når tallene ligger utenfor det modellen dekker:
- Innstrømningen før økningen (`innstromning_for_okning`, eller 95 % av Z når feltet mangler) må ligge mellom 86 og
98 % av Z. Utenfor det ville modellens regel ha endret kapasiteten allerede før økningen.
- `prognose_innstromning` (eller `innstromning`) må være høyere enn innstrømningen før økningen, og ikke mer enn om
lag 3 ganger så høy.
- Restansemålet må være større enn 0 (`maal_tid` eller `restanse_maal` over 0).
Leddet velges med navnet slik det står i fila, med samme store og små bokstaver, mellomrom og komma.
## Vanlige feil
**Årstall i stedet for månedstall.** Strømmene (`innstromning`, `kapasitet`, `skjult_avgang`, `prognose_innstromning`,
`innstromning_for_okning`) er per måned. Årstall deles på 12. Beholdningene (`restanse`, `restanse_for_12_mnd`,
`restanse_maal`) deles **ikke** på 12: de er antall saker på et tidspunkt. `maal_tid` er i måneder (60 dager er 2).
**Kapasitet som ikke virker ennå.** `kapasitet` er det leddet avgjør per måned nå. Kapasitet som er bevilget, men ikke
virker ennå, skal ikke med. Trekk den fra behovet verktøyet regner ut.
**Kapasitet med skjult avgang.** Er tallet for kapasitet hentet fra avgjorte saker, og noen av dem ble avsluttet uten
behandling (for eksempel henlagt på grunn av manglende kapasitet), oppgis de som `skjult_avgang`. Verktøyet trekker dem
da fra kapasiteten. Trekk dem ikke fra selv i tillegg, og oppgi ikke `skjult_avgang` hvis `kapasitet` ikke inneholder
dem.
**`maal_tid` eller `restanse_maal`.** `maal_tid` passer når restansen er hele køen og målet er en saksbehandlingstid.
`restanse_maal` passer når målet er et antall saker, eller når restansen bare er en del av køen (for eksempel saker
eldre enn tre måneder). Oppgis begge, brukes `restanse_maal`, og `maal_tid` blir stående ubrukt.
**Andel som prosent.** `maks_andel_utenom` er en andel: `0.2`, ikke `20`.
**Saksenheter.** Hvert ledd kan telle i sine egne enheter (anmeldelser, saker, dommer). Bare utnyttelsen sammenlignes
på tvers av ledd.
## Eksempelfilene
### `eksempler/eksempel_domstol.json`: stiliserte tall
Tallene er ikke norske. Domstolen er modellens tall i måned 24 i avsnitt 9.5 i notatet (`sim.py`, koordinert regel),
ganget med 1000: innstrømning og prognose 134,32 saker/mnd, kapasitet 105,263 (0,10/0,95 × 1000), og restanse 588,95,
som er restansen over målet (273,16) pluss 3 × kapasiteten. De tre andre leddene er satt under full utnyttelse for å
vise diagnosen. `styring` er regime A (forsinkelse 3, reaktivitet 3).
| Ledd | Innstrømning | Kapasitet | Restanse | Mål | Annet |
|---|---|---|---|---|---|
| Politi | 150 | 175 | 300 | 2 mnd | |
| Påtale | 140 | 160 | 200 | 1,5 mnd | høyst 10 % utenom |
| Domstol | 134,32 | 105,263 | 588,95 | 3 mnd | prognose 134,32; høyst 20 % utenom |
| Kriminalomsorg | 90 | 100 | 150 | 2 mnd | |
`diagnose` gir utnyttelse 1,28 i domstolen og 19 % mer kapasitet, som i avsnitt 9.5. `forlop` gir kritisk forsinkelse
7,2 måneder, 19 % mer kapasitet nå og 12 % til året etter.
### `eksempler/norge_2025.json`: offentlige norske tall
Årstall delt på 12. Kilden til hvert tall står i feltet `kilder` i fila, og tall merket «anslag» der er utledet, ikke
oppgitt i kilden. Tallene for politi og domstoler gjelder 2025. For fengsel er avgangen fra 2025 og køen fra oktober
2025 og oktober 2026.
| Ledd | Slik er feltene brukt |
|---|---|
| Politi og påtale | `restanse` er saker eldre enn tre måneder, så målet er `restanse_maal` (10 % av innkomne saker). `skjult_avgang` er lovbrudd henlagt på grunn av manglende saksbehandlingskapasitet (30 334 / 12). |
| Tingrett, meddomsrett | innkomne og avgjorte saker per måned, `maal_tid` 3; `restanse_for_12_mnd` er et anslag |
| Lagmannsrett, bevisanke | to kategorier lagt sammen; `restanse_for_12_mnd` er et anslag |
| Fengsel | `kapasitet` (iverksettelser i fengsel) og `innstromning` (avgang pluss køvekst) er anslag; `maal_tid` 2 (60 dager) |
`diagnose` gir utnyttelse 1,09 for politi og påtale, 1,04 for tingretten, 0,88 for lagmannsretten og 1,09 for fengsel.
Forbeholdene ved disse tallene står i `docs/forbehold.md`.