Compare commits
3 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
24996d66bd |
|||
|
9d6c53f6e1 |
|||
|
13f6c28dc0 |
13 changed files with 152 additions and 36 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "dynamisk-rettsstat",
|
||||
"displayName": "Den dynamiske rettsstaten",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.2",
|
||||
"description": "Plugin for Claude som kjører modellen i Den dynamiske rettsstaten på egne tall: finn leddet som binder, følg tiltaket over tid, simuler egne scenarioer og endre modellen.",
|
||||
"author": {
|
||||
"name": "Kjell Tore Guttormsen"
|
||||
|
|
|
|||
3
BIDRA.md
3
BIDRA.md
|
|
@ -4,6 +4,9 @@ Modellen er en første versjon, og notatet *Den dynamiske rettsstaten* er skreve
|
|||
Har du forbedret modellen, rettet en feil eller prøvd den mot data, tas det gjerne imot. Denne siden sier hvordan du
|
||||
sender det, og hva et bidrag må ha for at det kan vurderes.
|
||||
|
||||
Arbeidet er avsluttet (november 2026), og det er ikke planlagt nye versjoner. Et bidrag blir derfor ikke nødvendigvis
|
||||
tatt inn her. Lisensen (MIT) lar deg gi ut din egen utgave.
|
||||
|
||||
## Slik sender du det
|
||||
|
||||
Repositoryet ligger på en egen Forgejo-server der utenforstående ikke kan registrere seg, så bidrag kommer på
|
||||
|
|
|
|||
29
CHANGELOG.md
29
CHANGELOG.md
|
|
@ -2,6 +2,35 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 2026-11-11 — arbeidet er avsluttet (ingen ny versjon)
|
||||
|
||||
- README og `BIDRA.md` sier nå at arbeidet er avsluttet, og at det ikke er planlagt nye versjoner. Versjon 0.1.2 er den
|
||||
siste. Pluginen selv er ikke endret: ferdighetene, modellen, kjernen og fasiten er de samme som i 0.1.2.
|
||||
|
||||
## 0.1.2 — 2026-11-11
|
||||
|
||||
- Notatet omtaler nå selv at utgangspunktet i modellene med kø i domstolen ikke er en eksakt likevekt (avsnitt 10,
|
||||
«Utgangspunktet i modellene med kø»). README og `docs/forbehold.md` sa at notatet ikke nevner det; det er rettet.
|
||||
Modellen, kjernen og fasiten er uendret: notatets kode er den samme som ved commit 2badc25.
|
||||
|
||||
## 0.1.1 — 2026-11-11
|
||||
|
||||
Etter forfatterens prøve av 0.1.0 i Cowork.
|
||||
|
||||
- README: hva som er målt i Cowork, og hva som ikke er det. Zip-fila fra Forgejo lastes opp som den er, de fire
|
||||
ferdighetene virker, diagnosen og forløpet gir notatets tall, og kontrollen gir «bit for bit som notatet» også med
|
||||
Python 3.13.18, numpy 2.5.3 og scipy 1.18.1 på Linux. Ikke målt der: en egen simulering med figur, installasjon av
|
||||
numpy og scipy, og om en arbeidskopi blir liggende til neste økt.
|
||||
- Rettet: `miljo` sa at kontrollen «sammenligner med toleranse, ikke bit for bit» når numpy eller scipy ikke er
|
||||
notatets versjoner. Det stemte ikke: kontrollen sammenligner alltid byte for byte først, og i Cowork ga numpy 2.5.3
|
||||
bit for bit. Meldingen sier nå at tallene kan avvike i siste siffer, og at kontrollen sier hva de gjør.
|
||||
- Nytt: `kontroll --alt` viser alle linjene som er ulike. Før ble alt etter de 40 første per sammenligning bare
|
||||
talt («… linjer til»), uten noen måte å få dem fram på. Linja sier nå hvordan.
|
||||
- Ferdigheten `simuler`: spørsmålet før kjøringen skal kunne besvares med ja eller nei. I prøven ble det et valg
|
||||
mellom varianter, og kjøringen ble stående.
|
||||
- Ferdigheten `forbedre`: ligger arbeidskopien et sted brukeren ikke åpner selv, som i Cowork, sier Claude hvor, og
|
||||
tilbyr den som zip-fil sammen med kontrollutskriften.
|
||||
|
||||
## 0.1.0 — 2026-11-11
|
||||
|
||||
Første versjon.
|
||||
|
|
|
|||
|
|
@ -43,7 +43,10 @@ justice chain (mostly non-programmers) and researchers. The note and its code li
|
|||
- Skill frontmatter has only `name` and `description` (other keys make claude.ai reject an uploaded skill).
|
||||
- `${CLAUDE_PLUGIN_ROOT}` and `${CLAUDE_PLUGIN_DATA}` are substituted in skill text, but they are not environment
|
||||
variables in Bash. Skills write them literally into the command; `kjor.py` treats an empty `--data` or one containing
|
||||
`${` as not given and falls back to `~/.dynamisk-rettsstat`.
|
||||
`${` as not given and falls back to `~/.dynamisk-rettsstat`. Both were substituted in Cowork too (operator's test
|
||||
2026-11-11: the plugin under `/root/.claude/plugins/synced/<id>/dynamisk-rettsstat`, data under
|
||||
`/root/.claude/plugins/data/dynamisk-rettsstat-synced`). Cowork ran the commands in a Linux machine where numpy and
|
||||
scipy were already installed in the system Python, so the venv path is untested there.
|
||||
- Skills never invent numbers, show the numbers as understood before computing, divide yearly figures by 12 and say
|
||||
so, relay script numbers verbatim, carry the caveats, and never install anything without asking. A
|
||||
`rettsstat-modell/` in the user's folder is used only after asking, and only after `kontroll --rask` on it has been
|
||||
|
|
@ -64,7 +67,8 @@ justice chain (mostly non-programmers) and researchers. The note and its code li
|
|||
- Reproduction check against the note: `.venv/bin/python modell/kjor.py kontroll` (full run; about 1.5 minutes on the
|
||||
development machine, measured 2026-11-11) or `.venv/bin/python modell/kjor.py kontroll --rask` (skips the full run of
|
||||
`sim.py`). Six parts: core and `fasit/` against the note's checksums, `diagnose`, `forlop`, full run, extensions'
|
||||
limit cases, scenario runner against `fasit/data`.
|
||||
limit cases, scenario runner against `fasit/data`. `--alt` shows every differing line instead of the first 40 per
|
||||
comparison.
|
||||
- Try the skills' commands: `python3 modell/kjor.py diagnose eksempler/eksempel_domstol.json`,
|
||||
`python3 modell/kjor.py forlop eksempler/eksempel_domstol.json`,
|
||||
`python3 modell/kjor.py scenario eksempler/scenarioer/sjokkstorrelse_kjede.json --ut <scratch folder>` (`forlop` and
|
||||
|
|
|
|||
60
README.md
60
README.md
|
|
@ -9,6 +9,10 @@ arbeider i straffesakskjeden og for forskere som vil prøve, etterprøve eller f
|
|||
Prinsippet bak notatet: «Innsatsen for å håndheve lover og regler bør løpende stå i forhold til hvor mye, og hvor
|
||||
alvorlig, de faktisk brytes.» Straffebud og strafferammer ligger fast.
|
||||
|
||||
**Status:** Arbeidet er avsluttet (november 2026), og det er ikke planlagt nye versjoner. Versjon 0.1.2 er den siste.
|
||||
Pluginen kan brukes og bygges videre på fritt etter lisensen. Innspill og rettelser kan fortsatt sendes på e-post, se
|
||||
[Slik er arbeidet gjort](#slik-er-arbeidet-gjort).
|
||||
|
||||
## Install
|
||||
|
||||
I Claude Code:
|
||||
|
|
@ -18,16 +22,18 @@ claude plugin marketplace add https://git.fromaitochitta.com/open/ktg-plugin-mar
|
|||
claude plugin install dynamisk-rettsstat@ktg-plugin-marketplace
|
||||
```
|
||||
|
||||
I Claude Cowork: last ned repositoryet som zip fra Forgejo-siden (`https://git.fromaitochitta.com/open/dynamisk-rettsstat`)
|
||||
og last det opp som plugin.
|
||||
I Claude Cowork: last ned zip-fila for nyeste utgivelse fra
|
||||
[utgivelsessiden](https://git.fromaitochitta.com/open/dynamisk-rettsstat/releases) og last den opp som plugin. Cowork
|
||||
tar zip-fila slik den er.
|
||||
|
||||
Det som trengs:
|
||||
- **Python 3.** Flaskehalsdiagnosen trenger ikke noe mer.
|
||||
- **numpy og scipy** for forløpet over tid, simuleringene og kontrollen. Mangler de, spør Claude før noe installeres,
|
||||
og installerer dem da fra PyPI i en egen mappe for pluginen (krever internett). Ingenting installeres uten at du
|
||||
sier ja.
|
||||
sier ja. I Cowork fantes begge fra før da pluginen ble prøvd, så ingenting ble installert.
|
||||
|
||||
Status: prøvd i Claude Code. Ikke prøvd i Cowork ennå.
|
||||
Status: prøvd i Claude Code og i Cowork. Hva som er målt i Cowork, og hva som ikke er det, står under «Prøvd i
|
||||
Cowork» lenger ned.
|
||||
|
||||
## Hva du kan gjøre med den
|
||||
|
||||
|
|
@ -125,9 +131,10 @@ Notatet, simuleringskoden og PDF-ene ligger i
|
|||
låst med sha256 i `modell/kjerne/KILDE.json`. En test feiler hvis en av dem endres.
|
||||
- Kontrollen måler kjernen og fasiten mot notatets egne sjekksummer, kjører hele notatets simulering og
|
||||
sammenligner med notatets 22 datafiler og utskriftene, og kjører notatets scenariofiler gjennom scenariokjøreren.
|
||||
Målt 2026-11-11 med Python 3.14.0, numpy 2.5.4 og scipy 1.18.1: alle 22 datafilene er like byte for byte, og 14 av
|
||||
14 scenariofiler gjenskaper notatets datafiler byte for byte. Med andre versjoner av numpy og scipy sier kontrollen
|
||||
om tallene er like innenfor én enhet i siste siffer.
|
||||
Målt 2026-11-11 med Python 3.14.0, numpy 2.5.4 og scipy 1.18.1 (macOS): alle 22 datafilene er like byte for byte,
|
||||
og 14 av 14 scenariofiler gjenskaper notatets datafiler byte for byte. Samme dag i Cowork med Python 3.13.18,
|
||||
numpy 2.5.3 og scipy 1.18.1 (Linux): samme resultat. Med andre versjoner av numpy og scipy sier kontrollen om
|
||||
tallene er like bit for bit eller innenfor én enhet i siste siffer.
|
||||
- Scenariokjøreren kaller kjernen uendret. Scenariofilene i `eksempler/scenarioer/notatet/` gjenskaper notatets
|
||||
datafiler, og testene sammenligner dem med fasiten.
|
||||
|
||||
|
|
@ -142,8 +149,10 @@ python3 -m venv .venv
|
|||
.venv/bin/python -m pytest
|
||||
```
|
||||
|
||||
Kontrollen skal ende med `Nivå: bit for bit som notatet.` når Python, numpy og scipy er versjonene over.
|
||||
`pip install --group dev` trenger pip 25.1 eller nyere.
|
||||
Kontrollen skal ende med `Nivå: bit for bit som notatet.` når Python, numpy og scipy er versjonene over. Med andre
|
||||
versjoner kan den ende med `Nivå: innenfor toleranse`; det er ikke sett i noen av målingene. `kontroll --alt` viser
|
||||
alle linjene som er ulike, ikke bare de 40 første per sammenligning. `pip install --group dev` trenger pip 25.1
|
||||
eller nyere.
|
||||
|
||||
## Forbedre modellen selv
|
||||
|
||||
|
|
@ -164,6 +173,31 @@ skal kunne endre den:
|
|||
Forskere som bruker git, kan også klone dette repositoryet og starte Claude Code med `claude --plugin-dir .` i mappa.
|
||||
Slik sender du en forbedring tilbake: [BIDRA.md](BIDRA.md).
|
||||
|
||||
## Prøvd i Cowork
|
||||
|
||||
Forfatteren prøvde v0.1.0 i Cowork i Claude-skrivebordsappen 2026-11-11. Dette ble målt:
|
||||
|
||||
- **Installasjon.** Zip-fila for v0.1.0 fra Forgejo ble lastet opp uten advarsler, og de fire ferdighetene var på
|
||||
plass.
|
||||
- **Diagnosen** ga tallene som står i dette dokumentet, på eksempeltallene (1,28 og 19 %), på de norske tallene
|
||||
(1,09 / 1,04 / 0,88 / 1,09) og på egne tall oppgitt per år. Claude delte årstallene på 12, viste tallene slik de
|
||||
var forstått, og spurte før regningen.
|
||||
- **Forløpet** ga 7,2 måneder, 19 % nå og 12 % om 12 måneder, også i en ny økt.
|
||||
- **Kontrollen** endte med `Nivå: bit for bit som notatet.`: 22 av 22 datafiler og 14 av 14 scenariofiler.
|
||||
- **Miljøet.** Cowork kjørte kommandoene i en Linux-maskin (Ubuntu 24.04) der Python 3.13.18, numpy 2.5.3 og scipy
|
||||
1.18.1 fantes fra før. Pluginen installerte derfor ingenting.
|
||||
- **Arbeidskopi.** En kopi med frafallet fra domstolskøen satt til 0,02 ga `Nivå: endret`, med 11 av 22 datafiler
|
||||
flyttet. Kopien ble laget i Linux-maskinen, og Claude ga den tilbake som en zip-fil sammen med kontrollutskriften.
|
||||
|
||||
Ikke målt i Cowork:
|
||||
|
||||
- En egen simulering fra «hva om …» til tabell og figur. Prøven stoppet ved spørsmålet Claude stilte før kjøringen.
|
||||
Scenariokjøreren selv ble kjørt av kontrollen.
|
||||
- Installasjon av numpy og scipy fra pluginen, siden de fantes fra før.
|
||||
- Om en arbeidskopi blir liggende til neste økt.
|
||||
|
||||
Windows er ikke prøvd, verken i Cowork eller i Claude Code.
|
||||
|
||||
## Status og begrensninger
|
||||
|
||||
- Modellen er ikke kalibrert på norske data. Parameterne er stiliserte, og simuleringene illustrerer mekanismer. De
|
||||
|
|
@ -172,10 +206,12 @@ Slik sender du en forbedring tilbake: [BIDRA.md](BIDRA.md).
|
|||
- Bare ett ledd har kø i modellen. Alle simuleringene antar feilfrie observasjoner, og resultatene er enkeltbaner
|
||||
uten parameterusikkerhet.
|
||||
- I modellene med kø i domstolen er utgangspunktet nesten, men ikke helt, en likevekt: uten noe sjokk går
|
||||
kriminaliteten fra 1,000 til 1,018 og saksbehandlingstiden fra 3,0 til 4,6 måneder over 240 måneder. Notatet nevner
|
||||
det ikke. En liten del av det kjedescenarioene viser, er denne driften, og sammendraget viser hvor langt den har kommet fram
|
||||
til sjokket.
|
||||
kriminaliteten fra 1,000 til 1,018 og saksbehandlingstiden fra 3,0 til 4,6 måneder over 240 måneder. Notatet
|
||||
omtaler det under begrensningene i avsnitt 10. En liten del av det kjedescenarioene viser, er denne driften, og
|
||||
sammendraget viser hvor langt den har kommet fram til sjokket.
|
||||
- Kostnader og gevinster er ikke regnet i kroner.
|
||||
- Svarene er tekst og tabeller, med tilbud om en figur etter en simulering. Pluginen bruker ikke det Cowork ellers
|
||||
kan av visuelle svar. Det er en opplagt videreutvikling for den som vil bygge videre på den.
|
||||
- Diagnosen regner på tallene slik de er oppgitt, og kapasitetsbehovet er et grovt anslag.
|
||||
|
||||
Alle forbeholdene, for modellen, diagnosen, forløpet og de norske tallene: [docs/forbehold.md](docs/forbehold.md).
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ Ferdighetene tar med de forbeholdene som gjelder for svaret de gir.
|
|||
måleimperfeksjon. Resultatene er enkeltbaner uten parameterusikkerhet.
|
||||
- **Bare ett ledd har kø.** I notatets simuleringer er det domstolen; i `forlop` er det leddet som binder i dine tall.
|
||||
Etterforskning, påtale og straffegjennomføring har ellers verken kø, frafall eller kapasitet i modellen.
|
||||
- **Utgangspunktet i modellene med kø er nesten, men ikke helt, en likevekt.** Notatet kaller starttilstanden
|
||||
«utgangslikevekten», men i modellene der domstolen har kø, står den ikke helt i ro: saker som faller fra køen
|
||||
- **Utgangspunktet i modellene med kø er nesten, men ikke helt, en likevekt.** I modellene der domstolen har kø,
|
||||
står starttilstanden ikke helt i ro: saker som faller fra køen
|
||||
(henleggelse, foreldelse), blir aldri trukket fra kriminaliteten i modellens regnskap. Kjørt helt uten sjokk, med
|
||||
notatets verdier, går kriminaliteten fra 1,000 til 1,007 i måned 11, 1,015 i måned 120 og 1,018 i måned 240, og
|
||||
saksbehandlingstiden fra 3,0 til 3,1, 4,2 og 4,6 måneder, fortsatt stigende (målt 2026-11-11 med notatets kode,
|
||||
`eksempler/scenarioer/uten_sjokk_kjede.json`). Notatet nevner det ikke. En liten del av det kjedescenarioene viser
|
||||
etter sjokket, er denne driften.
|
||||
`eksempler/scenarioer/uten_sjokk_kjede.json`). Notatet omtaler det under begrensningene i avsnitt 10. En liten del
|
||||
av det kjedescenarioene viser etter sjokket, er denne driften, og den er ikke trukket fra i notatets tabeller og
|
||||
figurer.
|
||||
- **Kostnader er ikke regnet i kroner.** Målfunksjonen er stilt opp, men ikke brukt. Ingen kostnader eller gevinster
|
||||
er tallfestet, og modellens størrelser er normaliserte, ikke årsverk eller kroner.
|
||||
- **Beslutningsreglene er stiliserte.** Reglene for påtale og budsjett er representasjoner av hvordan myndighetene kan
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Kommandoer:
|
|||
forlop <fil> ["ledd"] stabilitetssjekk og forløp måned for måned (numpy og scipy)
|
||||
scenario <fil> [--ut <mappe>] kjør en scenariofil (numpy og scipy)
|
||||
notatet [--ut <mappe>] kjør notatets simuleringer uendret, om lag 1-2 min (numpy og scipy)
|
||||
kontroll [--rask] kontroller at modellen regner som notatet
|
||||
kontroll [--rask] [--alt] kontroller at modellen regner som notatet (--alt: vis alle ulike linjer)
|
||||
miljo [--opprett] vis Python, numpy og scipy; --opprett installerer dem i en egen mappe
|
||||
arbeidskopi <mappe> lag en kopi av modellen som du kan endre
|
||||
|
||||
|
|
@ -568,8 +568,8 @@ def rapport_miljo(valg: Valg) -> None:
|
|||
if samme_som_notatet(regner, laast):
|
||||
print("Versjonene av numpy og scipy er de samme som notatets, så kontroll kan gi bit for bit.")
|
||||
else:
|
||||
print("Versjonene av numpy og scipy er ikke de samme som notatets: kontroll sammenligner da "
|
||||
"med toleranse, ikke bit for bit.")
|
||||
print("Versjonene av numpy og scipy er ikke de samme som notatets. Tallene kan da avvike i siste "
|
||||
"siffer; kontroll sier om de er like bit for bit eller innenfor toleranse.")
|
||||
|
||||
|
||||
def kjor_prosess(kommando: list[str]) -> int:
|
||||
|
|
@ -608,8 +608,8 @@ def opprett_miljo(valg: Valg) -> int:
|
|||
print()
|
||||
rapport_miljo(valg)
|
||||
if toleranse:
|
||||
print("\nNumpy og scipy er ikke notatets låste versjoner. Resultatene kontrolleres da med toleranse, "
|
||||
"ikke bit for bit.")
|
||||
print("\nNotatets låste versjoner av numpy og scipy lot seg ikke installere, så nyere versjoner er "
|
||||
"installert. Kjør kontroll for å se om tallene er like bit for bit eller innenfor toleranse.")
|
||||
return OK
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,11 @@
|
|||
"""Gjenskapingskontroll: sjekk at modellen i denne mappa regner som notatet.
|
||||
|
||||
Bruk:
|
||||
python3 kjor.py kontroll [--rask]
|
||||
python3 kontroll.py [--rask] (med en Python som har numpy og scipy)
|
||||
python3 kjor.py kontroll [--rask] [--alt]
|
||||
python3 kontroll.py [--rask] [--alt] (med en Python som har numpy og scipy)
|
||||
|
||||
--alt viser alle linjene som er ulike. Uten den vises de 40 første per sammenligning, og
|
||||
resten telles.
|
||||
|
||||
Kontrollene, hver med én linje dom og detaljer bare ved avvik:
|
||||
1. Kjernen og fasit: sha256 for filene i kjerne/ og fasit/ mot notatets verdier, som står som
|
||||
|
|
@ -118,7 +121,8 @@ SCENARIO_TREGE = ("mpc11",)
|
|||
|
||||
LIK, TOLERANSE, ENDRET, IKKE_KJORT = "lik", "toleranse", "endret", "ikke kjørt"
|
||||
RANG = {LIK: 0, TOLERANSE: 1, IKKE_KJORT: 2, ENDRET: 3}
|
||||
MAKS_LINJER = 40 # linjer med forskjeller som vises per sammenligning
|
||||
MAKS_LINJER = 40 # linjer med forskjeller som vises per sammenligning (alle med --alt)
|
||||
VISNING = {"alt": False} # settes av --alt i main()
|
||||
SLINGRING = 1e-9 # relativ slingring når avviket sammenlignes med én enhet i siste siffer
|
||||
UTVIDELSER = "Utvidelser" # merkelappen for kontroll 5
|
||||
|
||||
|
|
@ -220,8 +224,9 @@ def vis_tall(x: float) -> str:
|
|||
def forskjeller(fasit: list[str], naa: list[str]) -> list[str]:
|
||||
"""Linjene som er ulike, som en kort diff (notatet / nå)."""
|
||||
linjer = list(difflib.unified_diff(fasit, naa, "notatet", "nå", lineterm="", n=0))
|
||||
if len(linjer) > MAKS_LINJER:
|
||||
linjer = [*linjer[:MAKS_LINJER], f"... ({len(linjer) - MAKS_LINJER} linjer til)"]
|
||||
if len(linjer) > MAKS_LINJER and not VISNING["alt"]:
|
||||
linjer = [*linjer[:MAKS_LINJER],
|
||||
f"... ({len(linjer) - MAKS_LINJER} linjer til; «kontroll --alt» viser alle)"]
|
||||
return linjer
|
||||
|
||||
|
||||
|
|
@ -594,10 +599,11 @@ def niva(dommer: list[Dom], *, rask: bool, arbeidskopi: bool) -> list[str]:
|
|||
|
||||
def main(argv: list[str]) -> int:
|
||||
"""Kjør kontrollene og skriv dommen. Returnerer exit-koden."""
|
||||
if argv not in ([], ["--rask"]):
|
||||
print("Bruk: kjor.py kontroll [--rask]", file=sys.stderr)
|
||||
if len(set(argv)) != len(argv) or not set(argv) <= {"--rask", "--alt"}:
|
||||
print("Bruk: kjor.py kontroll [--rask] [--alt]", file=sys.stderr)
|
||||
return 2
|
||||
rask = argv == ["--rask"]
|
||||
rask = "--rask" in argv
|
||||
VISNING["alt"] = "--alt" in argv
|
||||
arbeidskopi = (ROT / ARBEIDSKOPI_MERKE).is_file()
|
||||
regnemiljo = har_numpy_scipy()
|
||||
print(f"Kontroll av modellen i {MODELL}" + (" (arbeidskopi)" if arbeidskopi else "") + "\n", flush=True)
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ python3 "${CLAUDE_PLUGIN_ROOT}/modell/kjor.py" --data "${CLAUDE_PLUGIN_DATA}" ar
|
|||
`rettsstat-modell/`, og sier hvilket nivå kontrollen gir den.
|
||||
- `modell/kontroll.py` i kopien har notatets sjekksummer som faste verdier; det er dem kontrollen måler mot. Endre
|
||||
den ikke: da sier kontrollen ikke lenger noe om notatet.
|
||||
- Ligger kopien et sted brukeren ikke åpner selv (i Cowork kjører kommandoene i øktas egen Linux-maskin, og kopien
|
||||
havner der), si hvor den ligger, og tilby å gi den som en zip-fil sammen med hele utskriften fra kontrollen.
|
||||
|
||||
**Forskere som bruker git** kan i stedet klone pluginens repository (`https://git.fromaitochitta.com/open/dynamisk-rettsstat.git`),
|
||||
endre der og starte Claude Code med pluginen fra klonen: `claude --plugin-dir .` i mappa. Da bruker ferdighetene
|
||||
|
|
@ -131,6 +133,8 @@ python3 "${CLAUDE_PLUGIN_ROOT}/modell/kjor.py" --data "${CLAUDE_PLUGIN_DATA}" --
|
|||
|
||||
- Den fulle kontrollen kjører hele notatets simulering og tar et par minutter. Mens du prøver deg fram, kan du legge
|
||||
til `--rask` (hopper over den fulle kjøringen av `sim.py`); kjør den fulle før du sier hva endringen gjør.
|
||||
- Utskriften viser de 40 første linjene som er ulike i hver sammenligning, og teller resten («… linjer til»). Vil
|
||||
brukeren se alt som har flyttet seg, eller skal utskriften sendes med en forbedring, legg til `--alt`.
|
||||
- Kontrollen måler mot notatets egne sjekksummer, som står fast i `modell/kontroll.py`, ikke mot filene i kopien.
|
||||
Den har seks deler, nummerert slik i utskriften:
|
||||
1. kjernen (`sim.py`, `diagnose.py`, `forlop.py`) og fasiten (27 filer) mot notatets sjekksummer;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ Exit-koder:
|
|||
python3 "${CLAUDE_PLUGIN_ROOT}/modell/kjor.py" --data "${CLAUDE_PLUGIN_DATA}" miljo --opprett
|
||||
```
|
||||
|
||||
Gjengi det kommandoen sier (blant annet om resultatene da kontrolleres bit for bit eller med toleranse), og kjør
|
||||
Gjengi det kommandoen sier (blant annet om versjonene av numpy og scipy er notatets), og kjør
|
||||
forløpet på nytt. Feiler installasjonen, gjengi meldingen og si at diagnosen fortsatt kan brukes uten tilleggene.
|
||||
- **2**: skriptet har stoppet med en melding. Les den:
|
||||
- *Feil i inndata*, *Fant ikke fila*, *ikke gyldig JSON* eller *Fant ikke leddet*: gjengi meldingen med vanlige ord,
|
||||
|
|
|
|||
|
|
@ -91,7 +91,9 @@ stopper kjøringen uansett valg når politiets effektivitet, tilliten, innsatsen
|
|||
Si det rett ut: i den modellen er det en endring i kjernen, og det er ferdigheten `forbedre`. Den koblede modellen
|
||||
uten beslutningsregler (`simulate_chain`) kan ofte svare på det samme spørsmålet; tilby den.
|
||||
|
||||
Spør: «Skal jeg kjøre dette?» Kjør ikke før brukeren har sagt ja.
|
||||
Spør: «Skal jeg kjøre dette?» Kjør ikke før brukeren har sagt ja. Spørsmålet står alene til slutt og skal kunne
|
||||
besvares med ja eller nei. Legg ikke et valg mellom varianter inn i det («de tre, eller alle fire?»): da er «ja» ikke
|
||||
lenger et svar, og kjøringen blir stående. Forslag til flere kjøringer kommer etter svaret, i trinn 7.
|
||||
|
||||
## 3. Skriv scenariofila
|
||||
|
||||
|
|
@ -136,7 +138,7 @@ Exit-koder:
|
|||
python3 "${CLAUDE_PLUGIN_ROOT}/modell/kjor.py" --data "${CLAUDE_PLUGIN_DATA}" miljo --opprett
|
||||
```
|
||||
|
||||
Gjengi det kommandoen sier (blant annet om resultatene da kontrolleres bit for bit eller med toleranse), og kjør på
|
||||
Gjengi det kommandoen sier (blant annet om versjonene av numpy og scipy er notatets), og kjør på
|
||||
nytt. Feiler installasjonen, gjengi meldingen og si at diagnosen fortsatt kan brukes uten tilleggene.
|
||||
- **2**: skriptet har stoppet med en melding, og ingenting er skrevet. Les den:
|
||||
- *Feil i scenariofila … startlikevekt: startpunktet er ikke en likevekt …*: en grunnparameter er endret. Gjengi
|
||||
|
|
|
|||
|
|
@ -345,7 +345,12 @@ def test_opprett_faller_tilbake_og_sier_toleranse(
|
|||
monkeypatch.setattr(kjor_modul, "rapport_miljo", lambda _valg: None)
|
||||
assert kjor_modul.main(["--data", str(tmp_path), "miljo", "--opprett"]) == 0
|
||||
assert [k[-2:] for k in kommandoer] == [["-r", str(MODELL / "requirements.txt")], ["numpy>=2.0", "scipy"]]
|
||||
assert "kontrolleres da med toleranse, ikke bit for bit" in capsys.readouterr().out
|
||||
ut = capsys.readouterr().out
|
||||
assert "lot seg ikke installere, så nyere versjoner er installert" in ut
|
||||
assert "bit for bit eller innenfor toleranse" in ut
|
||||
# Measured in Cowork 2026-11-11: numpy 2.5.3 (not the pinned 2.5.4) still gave bit for bit,
|
||||
# so the message must not promise a tolerance comparison.
|
||||
assert "ikke bit for bit" not in ut
|
||||
|
||||
|
||||
def test_opprett_som_feiler_gir_kode_3(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
|
|
|
|||
|
|
@ -45,6 +45,20 @@ def test_tekst_endret(fasit: str, naa: str) -> None:
|
|||
assert resultat.detaljer
|
||||
|
||||
|
||||
def test_mange_forskjeller_kuttes_og_alt_viser_resten(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""Cowork-prøven 2026-11-11: 274 linjer ble kuttet uten at brukeren kunne få dem fram."""
|
||||
fasit = [f"linje {i}" for i in range(60)]
|
||||
naa = [f"rad {i}" for i in range(60)]
|
||||
kort = kontroll.forskjeller(fasit, naa)
|
||||
assert len(kort) == kontroll.MAKS_LINJER + 1
|
||||
assert kort[-1].endswith("linjer til; «kontroll --alt» viser alle)")
|
||||
monkeypatch.setattr(kontroll, "VISNING", {"alt": True})
|
||||
alle = kontroll.forskjeller(fasit, naa)
|
||||
assert "-linje 59" in alle
|
||||
assert "+rad 59" in alle
|
||||
assert not any("linjer til" in linje for linje in alle)
|
||||
|
||||
|
||||
DAT = "t K Q\n0.00000 1.00000 0.29100\n0.50000 1.10000 0.30000\n"
|
||||
|
||||
|
||||
|
|
@ -183,6 +197,18 @@ def test_manglende_fasit(lett_kopi: Path, hjem: Path) -> None:
|
|||
assert "norge_2025: fant ikke fasit/diagnose_norge_2025.txt" in prosess.stdout
|
||||
|
||||
|
||||
def test_kontroll_avviser_ukjent_valg(hjem: Path) -> None:
|
||||
prosess = kjor("kontroll", "--alle", hjem=hjem)
|
||||
assert prosess.returncode == 2
|
||||
assert "Bruk: kjor.py kontroll [--rask] [--alt]" in prosess.stderr
|
||||
|
||||
|
||||
def test_kontroll_med_alt_gir_samme_dom(lett_kopi: Path, hjem: Path) -> None:
|
||||
prosess = kjor("--modell", str(lett_kopi), "kontroll", "--rask", "--alt", hjem=hjem)
|
||||
assert prosess.returncode == 0, prosess.stdout + prosess.stderr
|
||||
assert "Nivå (uten full kjøring, --rask): bit for bit som notatet." in prosess.stdout
|
||||
|
||||
|
||||
def test_diagnose_krever_eksakt_likhet(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
"""Funn 10: én enhet i siste siffer i diagnosen er endret, ikke innenfor toleranse."""
|
||||
fasit = tmp_path / "fasit"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue