docs(s54): --report CLI surface + truthful costsim kost_mot_verdi seam note

This commit is contained in:
Kjell Tore Guttormsen 2026-07-24 01:38:10 +02:00
commit 0343b42d88
3 changed files with 21 additions and 3 deletions

View file

@ -25,6 +25,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
fail-fast `load_dimension` loader and structured refusals (rc 1, no traceback) for misuse and
mode-exclusivity violations. The prior-verdict fold is on the `--bundle-dir` path only; a
`--docs-dir`-only run is single-shot.
- Value report (S5.4): a read-only `--report [--json] --ledger <file>` surface on `run.py` that
rolls up the accumulated `SavingsLedger` — per-project + portfolio totals (dimension-free-deduped
integer øre), flagged cross-dimension overlaps (each counted once), and per-entry provenance — as
a human table or deterministic JSON. Makes no model calls; mode-exclusive (only `--ledger`/`--json`
permitted with `--report`, which requires `--ledger`). Honest scope boundary: the report core
(`value_report.py`) now **exists** but is deliberately **not** wired into `costsim`'s
`kost_mot_verdi` placeholder — that cost-vs-value integration is a separate, deferred step. The
`costsim` seam note was reworded from the stale "fylles av S5.4 verdirapport" to a truthful
forward reference so `costsim`'s own output no longer claims the wiring is done.
- Azure/Foundry offline preflight config gate (`preflight.py`, S4.1).
- Offline live-dry-run drill (`--live-dry-run`, S4.2): walks the whole path up to the eager
client build and stops before the first model call — zero chat calls.

View file

@ -98,19 +98,27 @@ when the seam is detached, so the loop cannot silently degrade into theater.
extension point) via a deterministic, schema-validated manifest that runs *before* the loop is
implemented and exercised against committed fixtures — no bundle has yet been materialized from
a live source.
- **Run:** the `run.py` CLI has **two modes** — a documented partition, since one invocation
- **Run:** the `run.py` CLI has **three modes** — a documented partition, since one invocation
cannot exercise every flag:
- **Single-project**`PROJECT_ID --docs-dir <dir>`, plus optional `--bundle-dir`,
`--verdict-dir`, `--outbox-dir` (which requires `--run-id`), `--dimension-config`,
`--decision`/`--rationale`, and `--live-dry-run`.
- **Portfolio**`--portfolio`, plus optional `--goals`, `--ledger`, `--dimension-config`;
it stops early and prints a `goal reached: …` line when the accumulated ledger meets a goal.
- **Value report (S5.4, read-only)**`--report --ledger <file>` rolls up the ledger's realized
savings to stdout: per-project totals, the portfolio total, flagged cross-dimension overlaps
(each counted once), and per-entry provenance. Add `--json` for deterministic JSON instead of
the human table. It makes **no model calls** and is mode-exclusive — only `--ledger`/`--json`
are permitted alongside `--report`; `--report` requires `--ledger`, and a stray `--json`
without `--report` is refused (rc 1, never silently ignored).
```bash
# Single-project, offline drill (builds contracts + clients, stops before the first model call):
uv run python -m portfolio_optimiser.run FV42-GSV-E1 --docs-dir <docs> --bundle-dir <bundle> --live-dry-run
# Portfolio run with a savings goal checked against an accumulated ledger:
uv run python -m portfolio_optimiser.run --portfolio --goals goals.json --ledger ledger.json
# Read-only value report over an accumulated ledger (human table; add --json for JSON):
uv run python -m portfolio_optimiser.run --report --ledger ledger.json
```
The **prior-verdict fold — the learning step — happens only on the `--bundle-dir` path**; a

View file

@ -235,7 +235,7 @@ def build_estimate_table(
"kjoring_kostet_ore": total_ore,
"kjoring_kostet_kr": _ore_to_kr_str(total_ore),
"kvalitetssikret_modellert_besparelse_ore": None,
"note": "fylles av S5.4 verdirapport",
"note": "S5.4 verdirapport-kjernen finnes; kost-mot-verdi-wiring gjenstår",
},
}
@ -269,7 +269,8 @@ def _format_table_text(table: dict[str, Any]) -> str:
lines += [
"",
f"kost-mot-verdi: kjøringen kostet ~{kmv['kjoring_kostet_kr']} (modellert øvre grense); "
"kvalitetssikret modellert besparelse fylles av S5.4 verdirapport",
"kvalitetssikret modellert besparelse: S5.4 verdirapport-kjernen finnes, "
"kost-mot-verdi-wiring gjenstår",
"",
"Adopsjonssti: start liten (én dimensjon, ett prosjekt, lavt tak) → eskaler med tilliten.",
]