portfolio-optimiser/docs/bestille-en-kjoring.md
Kjell Tore Guttormsen 30bcdd3544 docs(mandate): how a domain expert commissions a run — and one honesty fix the run itself exposed
`docs/bestille-en-kjoring.md` is the commissioning half of the expert-facing pair
(`ekspert-svar.md` is the judging half): the mandate file field by field, how to
run it, and — separated deliberately — what a commission does NOT do. It directs
what is evaluated, never what is approved.

Registered in _LIVE_DOCS, so it cannot silently fall behind the code.

The example output in it is COPIED FROM A REAL RUN, not composed, and running
that run is what found the defect fixed here: three approaches against the same
cost line each validated at 30000 NOK, and the settlement printed
"Validated total: 90000 NOK". Commissioned approaches are ALTERNATIVES — they
usually attack the same line — so summing them reports money the project cannot
realise. A domain expert reading that total would reasonably believe the run
found 90k.

The settlement now reports how many approaches held and which one the run
carries: a selection, not an arithmetic claim. That also removes the last money
addition from this module, which is the right place for it not to be.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ULCqjLF61rehj5cZmdUoR3
2026-08-05 16:31:27 +02:00

6.2 KiB

Bestille en kjøring

Dette dokumentet er for deg som bestiller en kjøring — fagpersonen som vet hvilke tilnærminger det er verdt å prøve på et prosjekt, og som vil vite nøyaktig hva systemet skal gjøre før det gjør det. Søsterdokumentet ekspert-svar.md handler om det motsatte enden: å avgi dommen etterpå.

Ærlighetsmerking. Bestillingen styrer hva som vurderes. Den styrer aldri hva som godkjennes. Den deterministiske validatoren gjelder uendret for en tilnærming du selv har bedt om — ber du om noe tallene ikke bærer, blir det avvist, og avvisningen kommer tilbake til deg med begrunnelsen.

Oppdragsfila

En bestilling er én JSON-fil. Du gir den til kjøringen med --mandate.

{
  "objective": "Kutt energikostnad i BYGG-KONTOR-NORD uten ombygging, med tiltak som kan gjennomføres i 2026.",
  "approaches": [
    {
      "id": "led-retrofit",
      "label": "LED-retrofit av kontorbelysning",
      "description": "Drift mener armaturene er originale og har gått langt forbi oppgitt levetid."
    },
    {
      "id": "driftsavtale",
      "label": "Reforhandling av driftsavtale",
      "description": "Avtalen er ikke justert siden 2019 og dekker areal vi ikke lenger disponerer."
    }
  ],
  "allow_own_proposals": true,
  "success_criteria": "Minst ett tiltak som passerer validatoren og som drift kan stå inne for."
}
Felt Hva det gjør
objective Hva kjøringen er til for, i klartekst. Påkrevd — en kjøring uten uttalt hensikt er nettopp det denne fila finnes for å hindre.
approaches Tilnærmingene du vil ha vurdert. Hver får sin egen vurdering og sin egen linje i oppgjøret.
allow_own_proposals true (standard): systemet foreslår også sitt eget, i tillegg til dine. false: kun dine.
success_criteria Hva du vil regne som vellykket. Gjengis ordrett i kunngjøringen; ingenting tolker den maskinelt.

Om id: den er nøkkelen tilnærmingen rapporteres under. To tilnærminger kan ikke dele id (da ville de kollapset til én linje i oppgjøret), og own-proposal er reservert for systemets eget forslag.

Om description: den mates ordrett inn til modellen. Det er her fagkunnskapen din faktisk gjør en forskjell — hvorfor du tror tilnærmingen er verdt å prøve er nøyaktig det systemet ikke kan lese seg til av kostnadstallene.

Enten tilnærminger eller egne forslag. En fil med tom approaches og allow_own_proposals: false blir avvist: da har kjøringen ingenting å gjøre.

Å kjøre den

uv run python -m portfolio_optimiser.run BYGG-KONTOR-NORD \
  --docs-dir shared/examples/bygg-energi-mikro \
  --bundle-dir shared/examples/bygg-energi-mikro \
  --mandate oppdrag.json \
  --scripted-replies replies.json

--mandate virker i begge moduser. I porteføljemodus (--portfolio) gjelder bestillingen hvert prosjekt i passet, og hvert prosjekt gjør opp for seg.

Vil du se hva kjøringen ville gjort, uten å bruke penger? Legg til --live-dry-run. Da skrives kunngjøringen, og kjøringen stopper før første modellkall.

Fila leses strengt. Mangler den, eller er den feilformet, blir kjøringen nektet (rc 1) — den går aldri videre på en halvlest bestilling. Det er med vilje: et oppgjør som beskriver arbeid ingen har bestilt, er verre enn ingen bestilling.

Hva du får: kunngjøringen

Før noe koster penger, skriver kjøringen hva den skal gjøre:

Run mandate for BYGG-KONTOR-NORD
  Objective:   Kutt energikostnad i BYGG-KONTOR-NORD uten ombygging, ...
  Evaluates:   2 expert-proposed approach(es) + the system's own proposals
                 1. led-retrofit — LED-retrofit av kontorbelysning
                 2. driftsavtale — Reforhandling av driftsavtale
  Stops at:    3 rounds / 100000 tokens
  Contacts:    no external services
  Success:     Minst ett tiltak som passerer validatoren ...

Kjører du med --dimension-config, kommer det en Scoped to:-linje til. Linjer for ting kjøringen ikke har — avgrensning, tallmål — utelates i stedet for å stå tomme: en tom linje ville lest som en beslutning ingen har tatt.

Contacts er egress-erklæringen: en kjøring når aldri en ekstern tjeneste den ikke har navngitt her. Stops at er takene — systemet kjører aldri en ubegrenset løkke.

Hva du får: oppgjøret

Etter kjøringen svarer den for bestillingen, én linje per tilnærming:

Mandate outcome
  led-retrofit         VALIDATED          30000 NOK   LED-retrofit av kontorbelysning
  driftsavtale         REJECTED      claimed 240000 exceeds feasible 90000
  own-proposal         NOT EVALUATED budget exhausted before this approach was evaluated
  Validated: 1 of 3 approaches — best 30000 NOK (the outcome this run carries)

De tre statusene betyr forskjellige ting, og forskjellen er poenget:

  • VALIDATED — tallene holdt. Beløpet er det validatoren slapp gjennom.
  • REJECTED — tilnærmingen ble vurdert, og falt på tallene. Grunnen står der; det er den du kan gjøre noe med (ofte er den «regnet mot feil grunnlag», ikke «dårlig idé»).
  • NOT EVALUATED — kjøringen rakk den aldri. Den er ikke avvist, og den er ikke glemt.

En tilnærming du bestilte forsvinner aldri i stillhet. Det er hele grunnen til at oppgjøret finnes.

Tilnærmingene summeres ikke. Flere av dem angriper som regel samme kostnadslinje, så de er alternativer — ikke besparelser som legges oppå hverandre. Derfor står det hvor mange som holdt og hvilken kjøringen bærer videre, aldri en sum. (Dette ble oppdaget ved å faktisk kjøre den: tre tilnærminger mot samme linje ga «totalt 90 000», som ingen av dem kunne innfri.)

Hva bestillingen ikke gjør

  • Den overstyrer ikke validatoren. Se ærlighetsmerkingen øverst.
  • Den avgjør ikke om et tiltak skal gjennomføres. Det gjør et menneske, etterpå — se ekspert-svar.md.
  • Den setter ikke et tallmål. Sparemålet har ett hjem, målkonfigurasjonen (--goals, som gjelder porteføljemodus). To kopier av samme tall drifter fra hverandre, så oppdraget bærer hensikten i ord og gjengir tallet hvis det finnes.
  • Den lagrer seg ikke som kunnskap. Bestillingen er en instruks for én kjøring. Det som lærer systemet noe, er dommen du avgir etterpå.