fix: findings from the Cowork test, released as v0.1.1
The operator tested v0.1.0 in Cowork on 2026-11-11. README now says what was measured there and what was not. - miljo: no longer claims that kontroll compares "with tolerance, not bit for bit" when numpy or scipy differ from the note's versions. kontroll always compares byte for byte first, and numpy 2.5.3 gave bit for bit. - kontroll --alt: show every differing line. The cut-off line now names the option instead of only counting the lines left out. - skill simuler: the question before a run must be answerable with yes or no. In the test it became a choice between variants and the run stalled. - skill forbedre: offer the working copy as a zip when the user cannot open the folder it was made in, as in Cowork. 263 tests pass; full kontroll: bit for bit with the note. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
parent
19858bbda9
commit
a2608eec50
11 changed files with 126 additions and 29 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "dynamisk-rettsstat",
|
||||
"displayName": "Den dynamiske rettsstaten",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"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"
|
||||
|
|
|
|||
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -2,6 +2,24 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 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
|
||||
|
|
|
|||
50
README.md
50
README.md
|
|
@ -18,16 +18,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 +127,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 +145,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 +169,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
|
||||
|
|
@ -176,6 +206,8 @@ Slik sender du en forbedring tilbake: [BIDRA.md](BIDRA.md).
|
|||
det ikke. 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).
|
||||
|
|
|
|||
|
|
@ -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