Stress round 6 validated three falsification arms, and every validated approach rested only on run-level declarations nobody can attribute to one approach. declare_requirement now takes a required approach_id (a mandate id or own-proposal; an unknown id is refused naming the valid ones), and a ValidatedProposal whose approach has neither a mandate requirement nor a declaration under its own id becomes validator.Unsupported - a Rejection subclass carrying the validator's own ruling, reported as `unsupported` in coverage, the outcome artefact, the settlement and the judge, and never counted or summed. The rule is active whenever the debate held the declaration tool, the micro base included; the road and pre-pass paths are untouched. Declaration quality is not judged, so the rule can be satisfied by declaring any document the run read. The v1 gate's row 6 probes pass; its artefact half reads IKKE MÅLT because stress round 6 predates approach-addressed declarations, and IKKE MÅLT is never green - it fails the exit code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
202 lines
9.7 KiB
Markdown
202 lines
9.7 KiB
Markdown
# 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](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`.
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```bash
|
|
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 fire 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é»).
|
|
- **UNSUPPORTED** — tallene holdt, men ingen krav i kunnskapsbasen ble erklært som bindende for
|
|
akkurat denne tilnærmingen. Den telles ikke som validert og summeres ikke. Skriv kravet inn i
|
|
bestillingen (`requirement` på tilnærmingen), eller la kjøringen erklære det.
|
|
- **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.)
|
|
|
|
## Hver tilnærming kan dømmes for seg
|
|
|
|
Kjører du med `--outbox-dir` (og `--run-id`), legger kjøringen igjen **én artefakt per vurdert
|
|
tilnærming** — `run-001-led-retrofit-proposal.json`, `run-001-driftsavtale-proposal.json`, og så
|
|
videre — ikke bare for den kjøringen bar videre.
|
|
|
|
Det er ikke en bokføringsdetalj. Uten det kunne bare den valgte tilnærmingen få en fagdom, og de
|
|
andre du bestilte ville aldri nådd læringssløyfa: de ble vurdert, rapportert i oppgjøret, og deretter
|
|
glemt. Nå står de hver for seg i køen din:
|
|
|
|
```
|
|
uv run python -m portfolio_optimiser.hitl pending --outbox-dir utboks --verdict-dir innboks
|
|
run-001 c91cb2fe1aa139a9 validated [led-retrofit]
|
|
run-001 4f0a1d77b2e5c318 rejected [driftsavtale]
|
|
```
|
|
|
|
Hvordan du svarer på dem står i [ekspert-svar.md](ekspert-svar.md). En tilnærming med status
|
|
NOT EVALUATED har ingen artefakt — kjøringen produserte aldri et forslag for den, så det er ingenting
|
|
å dømme.
|
|
|
|
## 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](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å.
|
|
|
|
## Hvis kjøringen skal spørre en ekstern tjeneste
|
|
|
|
Skal agentene kunne slå opp i en tjeneste dere allerede har — et prisregister, målerdata, et
|
|
avtaleregister — settes den opp med `--mcp-config`:
|
|
|
|
```json
|
|
{"servers": [
|
|
{"name": "prisregister", "transport": "http", "url": "https://intern.example/mcp",
|
|
"allowed_tools": ["lookup_unit_price"], "timeout_seconds": 15,
|
|
"credential_env": "PRISREGISTER_TOKEN"}
|
|
]}
|
|
```
|
|
|
|
Tre ting er verdt å vite som bestiller:
|
|
|
|
- **Du må navngi hvilke verktøy som er tillatt.** Tom liste er ikke lov. Uten det ville tjenesten
|
|
selv bestemt hva agentene får lov til å kalle.
|
|
- **Alt som vil bli kontaktet, står i kunngjøringen** — før første kall, på `Contacts:`-linja, med
|
|
både servernavn og tillatte verktøy. En kjøring når aldri en tjeneste den ikke har navngitt. Det
|
|
gjelder også når du ikke bruker `--mandate`.
|
|
- **Passord og nøkler skal aldri i fila.** `credential_env` navngir en miljøvariabel; verdien leses
|
|
derfra. Er variabelen ikke satt, blir kjøringen nektet — heller det enn å ringe tjenesten anonymt
|
|
og få svar med feil tilgang.
|
|
|
|
Uten `--mcp-config` gjøres ingen nettverkskall i det hele tatt.
|
|
|
|
### Etterpå: hva ble faktisk kalt
|
|
|
|
Kunngjøringen er en **tillatelse** — den sier hva kjøringen *kan* kontakte. Den sier ikke om
|
|
agentene brukte tjenesten eller lot den ligge. Derfor fører kjøringen også et **kall-spor**, som
|
|
følger med artefaktene under `provenance.external_calls`:
|
|
|
|
```json
|
|
"external_calls": [{"server": "prisregister", "tool": "lookup_unit_price"}]
|
|
```
|
|
|
|
En tom liste er en påstand, ikke et hull: ingenting utenfor prosessen ble kontaktet. Verktøy som
|
|
kjører lokalt (som dokumentsøket) telles ikke med — de er ikke kontakt med noen.
|
|
|
|
**Hva sporet ikke sier.** Det viser at verktøyet ble kalt, og hvilken server det tilhører. Det er
|
|
ikke bevis for at tjenestens svar er det tallet som havnet i forslaget, og det er ingen kontrollert
|
|
gjengivelse av hva tjenesten svarte. Skal svaret etterprøves, må det gjøres mot tjenesten selv.
|
|
|
|
En sjelden detalj, tatt med fordi den ellers ville sett ut som en feil: hvis to servere tilbyr
|
|
verktøy med **samme navn**, står `server` tomt. Rammeverket oppgir bare verktøynavnet, så de to lar
|
|
seg ikke skille — og da er «vet ikke» riktigere enn å gjette på den ene.
|