# dynamisk-rettsstat This file is for development sessions in this repo. It is not loaded as plugin context, and `claude plugin validate` warns about a `CLAUDE.md` in the plugin root; that warning is expected. ## Context A Claude plugin (Claude Code and Cowork) that runs the model behind the concept note *Den dynamiske rettsstaten* on the user's own numbers: find the binding link in the criminal justice chain (`diagnose`), follow the measure over time (`forlop`), run scenarios (`simuler`) and change the model (`forbedre`). Users are Norwegian: people working in the justice chain (mostly non-programmers) and researchers. The note and its code live in `~/repos/den-dynamiske-rettsstaten` (read-only from here). Open, non-commercial; nothing here is for sale. ## Stack - Skills only: `skills//SKILL.md`. No hooks, no MCP servers, no mod, no top-level `bin/` (Cowork refuses a plugin with one). - `modell/kjor.py`: the single entry point, Python 3.9+ standard library only. Finds a Python with numpy and scipy for the commands that need them; installs nothing unless `miljo --opprett` is run. - `modell/kjerne/`: `sim.py`, `diagnose.py`, `forlop.py`, unmodified copies from the note's repo, pinned by sha256 in `modell/kjerne/KILDE.json`. numpy and scipy pinned in `modell/requirements.txt` (as the note). - `fasit/`: reference output (22 data files, printouts) that `kontroll` compares against. - `docs/`: `inndata.md`, `modellkart.md`, `forbehold.md` (and later `scenarioformat.md`, `utvidelser.md`), Norwegian. - `eksempler/`: `eksempel_domstol.json` (stylized), `norge_2025.json` (public Norwegian figures). ## Conventions - **Never edit `modell/kjerne/`.** It is synced from the note's repo: copy the three files at a given commit, update the commit and sha256 values in `KILDE.json`, rebuild `fasit/` and run `kontroll`. A test fails if a file does not match its sha256. No lint on the core. Changes to the model go in `modell/utvidelser/` or in a user's working copy. - User-facing text (skills, docs, script messages) is Norwegian bokmål, plain and direct, with the note's terms (ledd, skranke, restanse, utnyttelse, saksbehandlingstid, ledet utenom, den koordinerte regelen). Code, comments and this file may be English. - Facts in docs and skills are read from the code or the note, never from memory. Where they differ, the code wins. - The note's core sentence is quoted verbatim: «Innsatsen for å håndheve lover og regler bør løpende stå i forhold til hvor mye, og hvor alvorlig, de faktisk brytes.» Short form: «Straffebud og strafferammer ligger fast.» - 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`. - 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. - Exit codes of `kjor.py`: 0 ok, 1 differences found by `kontroll`, 2 input or usage error (a core `sys.exit("...")` passes through as 2 with the message unchanged), 3 numpy/scipy missing. ## Commands - Development environment (versions pinned in `pyproject.toml`, group `dev`): `python3 -m venv .venv && .venv/bin/pip install --group dev` - Tests: `.venv/bin/pytest` (fast, about 1.5 min); `.venv/bin/pytest -m treg` runs the note's full simulation (about 2.5 min) - Lint and types (the core is excluded in `pyproject.toml`): `.venv/bin/ruff check .` and `.venv/bin/mypy .` - Reproduction check against the note: `.venv/bin/python modell/kjor.py kontroll` (full run, about 75 s) or `.venv/bin/python modell/kjor.py kontroll --rask` - Try the skills' commands: `python3 modell/kjor.py diagnose eksempler/eksempel_domstol.json`, `python3 modell/kjor.py forlop eksempler/eksempel_domstol.json` - Validate the plugin: `claude plugin validate .` - Load the plugin locally: `claude --plugin-dir .` ## Workflow - Remote is Forgejo (`git.fromaitochitta.com`), never GitHub. Visibility, catalog entry and the move to `open/` are the operator's decisions. - `PLAN.md` and `STATE.md` are local working files (gitignored). - Conventional Commits. Do not commit working documents.