portfolio-optimiser · v1.1.0 · teknisk gjennomgang
Et åpent Python-rammeverk på Microsoft Agent Framework som leter etter kostnadsbesparelser inni hvert prosjekt i en portefølje: arkitekturen, tilbakemeldingssløyfene og harnessen, fra formålet ned til hver enkelt søm.
For AI-arkitekter og utviklere · inntil 60 minutter · alle påstander har kildelinje til repoet (git.fromaitochitta.com/open/portfolio-optimiser, HEAD 50c9763, 2026-09-18)
01Agenda
Det du skal sitte igjen med: helheten (hvorfor systemet er bygget som en portrekke med mennesker i begge ender) og detaljen (hvilken modul, hvilket tak, hvilken fil som krysser hvilken grense). Hver slide har en kildelinje du kan slå opp.
02Lesehjelp
Figurene i dette decket bruker samme visuelle språk hele veien, så du kan lese en ny figur uten å lære den på nytt.
Tall står alltid med nevner. «Ikke verifisert» betyr nettopp det. Kildelinjen nederst peker på fil og linje i repoet.
Del 1 · Formålet
Hva rammeverket faktisk løser, hvem som har hvilken rolle i sløyfen, og hva det med vilje ikke gjør.
03Del 1 · Formålet
Kilde: README.md:9-13 · README.md:265-279 · src/portfolio_optimiser/data/reference_projects.json
04Del 1 · Formålet
Kilde: src/portfolio_optimiser/workflow.py:26-45 · src/portfolio_optimiser/validator.py:648-748 · shared/method-spec.md:54
05Del 1 · Formålet
Non-goals er ikke mangler. De er grenser noen har bestemt, og de forklarer hvorfor kjernen er så liten.
| Det er ikke | Det er |
|---|---|
| Et compliance-produkt | Tekniske forutsetninger: lokal drift, provenance på hvert forslag, ingen stille egress. Behandlingsformål, DPIA og ROS eies av den som tar det i bruk. |
| En porteføljereallokator | Besparelser inni hvert prosjekt. Å flytte budsjett mellom prosjekter, og å rangere prosjekter mot hverandre, ligger over metoden. |
| Autonom beslutningstaking | Validatoren kan bare blokkere. Å godkjenne et tiltak er fagekspertens valg, og rammeverket iverksetter ingenting på agentenes ord. |
| En nøkkelferdig vertikal | Generisk kjerne med navngitte extension points — datakilder, kostnadsmodeller, personaer. De siste 10 % av et domene er deployerens. |
| En modell-benchmark | Ende-til-ende-beviset kjører offline mot en scripted stand-in. Det viser at sløyfen lukkes, ikke hvor godt en gitt LLM foreslår eller dømmer. |
Status, uten pynt. Én live-kjøring mot et ekte endepunkt er gjennomført (14.08.2026): første forsøk døde på rundetaket, gjenkjøringen endte i et korrekt rejected. Ingen kjøring har ennå gitt et validert forslag mot en live modell, og ingen ekte ekspertdom har kommet inn i treet ennå.
Kilde: README.md:265-303 · shared/method-spec.md:26-33
06Del 1 · Formålet
Bygg den generiske kjernen og navngi sømmene. De siste 10 % av et domene er deployerens.
Én vedlikeholder, ingen SLA, MIT. Issues er signaler; pull requests tas ikke imot.
Behandlingsformål, DPIA og ROS eier den som tar det i bruk. Vi bygger ikke compliance-funksjoner.
Kilde: README.md:14-19 · README.md:335-349 · docs/extending.md:294-321
Del 2 · Arkitekturen overordnet
Lagene, de åtte stegene, kartet over koden, den delte kjernen, de to backend-profilene og de fire kjøremodusene.
07Del 2 · Arkitekturen overordnet
Kilde: shared/method-spec.md:36-50 · src/portfolio_optimiser/verdicts.py:699-773
08Del 2 · Arkitekturen overordnet
Kilde: README.md:351-376 · shared/method-spec.md:56-58
09Del 2 · Arkitekturen overordnet
.py-filer og 22 019 linjer under src/. To av filene er __init__.py, så 39 er moduler, og 13 av dem importerer agent_framework. Lagdelingen er framstillerens lesning; modulene ligger flatt, og bare evals/ er en pakke.Den ene grensen koden håndhever. tests/test_okf.py holder en liste, _MAF_FREE_MODULES, med ni moduler — okf, dimension, mandate, outbox, costsim, hitl, notify, semretrieval, proposal_review — og en AST-sjekk går rødt hvis noen av dem importerer agent_framework eller mcp. AST, ikke tekstsøk, så en docstring som omtaler rammeverket ikke utløser den. ingest og ingest_mcp har egne vakter, og hitl og notify har i tillegg en transitiv importgraf-vakt. Det er dette som lar en søsken-implementasjon på Claude Agent SDK gjenbruke lagene nederst uendret.
Kilde: tests/test_okf.py:22-32 · tests/test_okf.py:476-500 · tests/test_hitl_loadbearing.py:273 · find src -name "*.py" | xargs wc -l
10Del 2 · Arkitekturen overordnet
shared/ skjer ved kall: PORTFOLIO_SHARED_ROOT først, så arbeidstreets shared/ når den finnes, ellers den pakkede kopien i distribusjonen.Kilde: shared/README.md · src/portfolio_optimiser/shared_root.py:20-38 · pyproject.toml:111-112
11Del 2 · Arkitekturen overordnet
PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT først, så det plattform-injiserte FOUNDRY_PROJECT_ENDPOINT. Presedensen gjelder verdier, ikke erklæringer, så et eksportert-men-tomt navn faller gjennom i stedet for å skygge for et ekte.Kostnadsdisiplin. Utvikling skjer på local, som er gratis. Foundry brukes bare til målrettet, minimal verifisering. Credential-figuren og hele leverandørsømmen tas i Del 5.
Kilde: src/portfolio_optimiser/backends.py:87-91 · backends.py:105-122 · backends.py:125-172 · src/portfolio_optimiser/data/model_map.json
12Del 2 · Arkitekturen overordnet
CLI-en har 36 distinkte flagg. Ett kall kan ikke utøve dem alle, så modusene er skrevet ned som en partisjon, og kombinasjoner som ville vært tvetydige nektes i stedet for å bli tolket.
| Modus | Påkrevd | Hva den gjør |
|---|---|---|
| Enkeltprosjekt | PROJECT_ID --docs-dir | Én kjøring mot ett prosjekt. Valgfritt --bundle-dir, --verdict-dir, --outbox-dir (krever --run-id), --explore, --proposal-review, --scripted-replies, --live-dry-run. |
| Multi-base | --across-bundle gjentatt, --mandate, --run-id, --outbox-dir | Én bestilling, flere kunnskapsbaser, sekvensielt. Én verdict-store tres gjennom alle, så en dom mot base k når base k+1. |
| Portefølje | --portfolio | Referanseprosjektene etter hverandre. Valgfritt --goals og --ledger; stopper tidlig når målet er nådd. |
| Verdirapport | --report --ledger | Leser bare. Null modellkall. Ruller opp realiserte besparelser per prosjekt, med provenance per post. |
Nektet, aldri stilltiende ignorert. --live-dry-run og --scripted-replies er begge offline-moduser og nektes sammen. --json uten --report nektes. --report tåler bare --ledger og --json ved siden av seg. --across-bundle nekter --bundle-dir, --portfolio, --explore og --prepass-payload, fordi hver av dem løser opp én base.
Kilde: src/portfolio_optimiser/run.py:2826-3145 (37 add_argument, hvorav én er posisjonsargumentet project_id) · run.py:3185 · run.py:3265-3271 · run.py:3434 · run.py:4051
Del 3 · Elementene
Nå går vi gjennom sømmene én for én: kunnskapsbasen, navigasjonen, ingest-laget, kontraktene, debatten, validatoren, ekspert-sløyfen og artefaktene en kjøring etterlater seg.
13Del 3 · Elementene
Hvorfor et åpent format. OKF er leverandørnøytralt, så de samme bundlene konsumeres uendret av begge referanseimplementasjonene. Kunnskapen overlever den enkelte agent-stacken.
Kilde: README.md:305-333 · shared/method-spec.md:38-44 · src/portfolio_optimiser/okf.py:44-50
14Del 3 · Elementene
declare_requirement, legges på kun når kravloggen er koblet på. En logg som ikke ser hva som ble åpnet, ville godtatt hver eneste erklæring.| Form, målt på K2-korpuset (630 konseptdokumenter) | o200k-tokens i én kjørings prompter | Endring |
|---|---|---|
| Hele bundlen utlevert, i tre kopier | 1 947 342 (99,1 % av promptene) | utgangspunkt |
| Peker + de fire verktøyene, like-for-like | 753 | −99,96 % |
| Peker + en debatt som faktisk går stigen | 8 942 | −99,5 % |
Kilde: src/portfolio_optimiser/explore.py:1199-1612 · src/portfolio_optimiser/okf.py:914-975 · docs/invarianter.md:1719-1734
15Del 3 · Elementene
Status og et målt dokumentavvik. Laget er kjørt kun mot committede fixtures; ingen bundle er ennå materialisert fra en live kilde. Pinnene i pyproject.toml er llm-ingestion-okf v0.8.5 (linje 71) og llm-ingestion-guard v1.4.0 (linje 80), mens docs/extending.md:86 og ingest.py-docstringen fortsatt sier v0.3.2 og v0.3.4. Dokumentene er utdaterte, ikke koden.
Kilde: src/portfolio_optimiser/ingest.py:1-33 · src/portfolio_optimiser/ingest_mcp.py:99 · pyproject.toml:71,80 · README.md:288-296
16Del 3 · Elementene
BindingRequirement bærer stien og kravets eget nummer som frontmatteren skriver det, aldri en parafrase — målt bakgrunn: 0 av 26 fasit-konsepter ble noen gang åpnet, i begge runder, mens hver kjøring likevel produserte forslag.To ting som IKKE er det samme. TerminationContract og Budget er ressurstak; GoalContract er et domenemål — en besparelse i øre eller prosent — og det målet bor ett sted, ikke i mandatet. McpConfig er extra=forbid, så en forvillet "credential": "sk-…" blir en nekt i stedet for en ignorert nøkkel.
Kilde: src/portfolio_optimiser/contracts.py:31-101 · ir.py:15-63 · mandate.py:46-156 · budget.py:67-81 · provenance.py:53-104 · explore.py:65-99 · mcp_tools.py:50-58
17Del 3 · Elementene
output_from=agents er load-bearing: uten den gir get_outputs() bare orkestratorens «reached max rounds»-melding, og både proposerens forslag og checkerens dom går tapt. run.py skiller dem på author_name. På grenen uten pre-pass-payload har debatten de samme fire navigasjonsverktøyene som utforskningen.Slik ser en falsifisering ut når den reiser tilbake til modellen — hele blokken, ordrett:
Your previous proposal was REJECTED by the deterministic validator.
Reason: {prior_rejection.reason}
Produce a REVISED SavingsProposal that resolves this.
Checker-porten er fail-open. Bare en eksplisitt VERDICT: REJECT blokkerer. Mangler markøren, eller er den uleselig, står den deterministiske validatoren alene som port. Stadiene i den porten er Del 3b; MAF-objektene rundt debatten er Del 5.
Kilde: src/portfolio_optimiser/workflow.py:26-117 · generate.py:362-367 · generate.py:701-793 · run.py:673-687 · run.py:1331-1346
18Del 3 · Elementene
| Sømmen | Slik utvider du | Regelen bak |
|---|---|---|
| Eget prosjekt | data/reference_projects.json + en docs-mappe | Kun konfig og dokumenter. En test nekter hardkodede prosjekt-id-er i src/. |
| Datakilde | retrieval.retrieve() bak en FunctionTool | Sti-sjekken er fail-closed, og sitatet er eksakt ved konstruksjon, ikke ved kontroll. |
| Modell-map | data/model_map.json, PORTFOLIO_MODEL_MAP | Konfig, ikke kode. Plassholdere feiler fail-fast før en klient bygges. |
| Ingest-kilde | materialize(http_get=…) | http-familien er det dokumenterte eksempelet. Nett er et kwarg, aldri et manifest-felt. |
| MCP | ingest-adapter, og --mcp-config i debatten | Allowlist er påkrevd, og hver server og hvert tillatte verktøy navngis før første kall. |
| Retriever / embedder | Retriever- og Embedder-protokollene | LUKKET registry — aldri en import-sti, som ville vært kodekjøring ved konfig-lasting. |
| Notifier | build_notifier(config, allow_egress=…) | Egress er et kode-kwarg per kjøring, aldri et konfig-felt. Webhooken er eneste egress-punkt. |
client_factory | run_project(client_factory=…) | Det ekte backend-byttet. Det står ikke i docs/extending.md — en reell dokumentasjonsglipe. |
Bevisste kutt, ikke gjeld. Full taksonomi for motstridende ekspertdommer, checkpointing av en kjøring og parallell fan-out er skrevet ned som kutt, hver med sømmen navngitt. To sømmer til finnes i koden uten å stå i utvidelsesdokumentet: METHOD_CAPS (metodetaket i validatoren) og personabytte ved å re-peke shared/.
Kilde: docs/extending.md:15-321 · src/portfolio_optimiser/semretrieval.py:215-226 · notify.py:175 · run.py:1097 · validator.py:52 · persona.py:30-47
19Del 3 · Elementene
Rejection. Stage 2 og 3 regner, de nekter ikke. Stadienavnene i rapporten kommer fra rejection_stage(), som er en RAPPORT og ikke en port.Et tredje utfall ligger utenfor validatoren. Unsupported er definert i validator.py, men produseres i run.py etter at validatoren har sagt ja.
Kilde: src/portfolio_optimiser/validator.py:648-748 · validator.py:749-775 · docs/invarianter.md
20Del 3 · Elementene
Ærlig om LP-en: x = 0 er alltid tillatt, så «infeasible» har ingen kodesti. Et ikke-optimalt svar fra CBC er en miljøfeil og kaster CbcUnavailable, aldri en Rejection.
Kilde: src/portfolio_optimiser/validator.py:129-145 · validator.py:148-164 · validator.py:697-719
21Del 3 · Elementene
Stage 0 avstemmer hver affected_item mot prosjektets egen CostBaseline: koden må finnes, og avviket i mengde og enhetspris må ligge innenfor 5 % av baselinen.
| Prosjekt | 01.1 enhetspris | Σ prosjekt | Utfall |
|---|---|---|---|
| FV42-GSV-E1 | 850 000 | 6 721 500 | validated |
| RV13-RAS-TP | 1 450 000 | 7 529 700 | rejected |
| BRU-LAKS-REHAB | 620 000 | 3 099 700 | rejected |
| SKOLE-VVS-OPPGR | 480 000 | 4 640 000 | rejected |
READMEs portefølje-demo sender det SAMME forslaget mot alle fire. Alle fire bærer kostnadskoden 01.1, men til fire ulike beløp. Ett validert forslag, tre avvisninger. Ingenting ved forslaget endret seg.
SYNTETISK. De fire referanseprosjektene er AI-forfattede placeholders i data/reference_projects.json, ikke faktiske prosjekttall.
Kilde: src/portfolio_optimiser/validator.py:225-279 · src/portfolio_optimiser/data/reference_projects.json · README.md steg 6
22Del 3 · Elementene
Kilde: src/portfolio_optimiser/validator.py:471-491 · validator.py:494-571 · validator.py:574-645 · validator.py:388-408
23Del 3 · Elementene
Unsupported arver fra Rejection. Hver konsument som spør «er dette validert?» med isinstance(..., ValidatedProposal) svarer nei uten å endres, så utfallet blir aldri talt eller summert som en suksess. Konsumentene som NAVNGIR statusen sjekker klassen først.Uttalt svakhet: deklarasjonens KVALITET vurderes ikke. Regelen spør om et krav ble deklarert, ikke om deklarasjonen var god.
Kilde: src/portfolio_optimiser/run.py:589-597 · validator.py:113-126 · outbox.py:106-146
24Del 3 · Elementene
| Tak | Hvor det bor | Hva som skjer når det slår |
|---|---|---|
| Debattrunder | with_max_rounds (workflow.py:113) | Hardt tak. En debatt som ikke konvergerer terminerer ikke seg selv. |
| Refinement-forsøk | self_repair(max_attempts=3) | Første ValidatedProposal, ellers siste Rejection. max_attempts ≤ 0 nektes. |
| Token-tak | BudgetMiddleware, strict_usage=True | Nekter kallet FØR det gjøres når taket er brukt opp. Manglende usage gir UsageUnavailable, aldri stille telling. |
| Portefølje-måler | PortfolioBudget + PortfolioMeter | BudgetRefused ved START når passet ikke kan finansiere én kjøring. Nekt, aldri reparasjon. |
| Utforskningstak | ExplorationContract (explore.py:65-101) | Seks felt, ingen defaults. MAF-ens egne defaults er ubegrenset, så et utelatt felt ville falt tilbake på den ene formen spec-en forbyr. |
| Parse-feil | _fetch_parsed (generate.py:642-672) | Retryen bærer GRUNNEN inn i neste prompt. Før dette ble de samme bytene sendt på nytt. |
Kilde: src/portfolio_optimiser/budget.py:67-256 · validator.py:778-796 · explore.py:65-101 · generate.py:310-319 · generate.py:642-672
25Del 3 · Elementene
Kilde: src/portfolio_optimiser/provenance.py:53-105 · outbox.py:81-90
26Del 3 · Elementene
unkeyed_verdicts og rapporterer dem, i stedet for å slippe dem i stillhet.Halv dom nektes ved navn. --decision og --rationale går sammen eller ikke i det hele tatt. Fram til 1.1.0 defaultet --decision til approved, så hver flaggløs kjøring myntet en godkjenning ingen ga og bar den inn i neste prosjekts hypotese. Den defaulten er borte.
Kilde: src/portfolio_optimiser/verdicts.py:73-110 · verdicts.py:214-277 · verdicts.py:300-374 · run.py:1551-1560 · run.py:3166-3177
27Del 3 · Elementene
Outboxens verdict_id minus innboksens id-er. Svaret er hvilke kandidater som fortsatt venter på et menneske.
Rutingtabell på kostnadskode-PREFIKS, ikke på measure. Measure er åpen prosa og ble målt som ikke-diskriminerende.
Uroutbar rute får expert=None og sendes likevel ut. Flere treff gir laveste id og ambiguous=True.
Kilde: src/portfolio_optimiser/verdicts.py:673 · verdicts.py:699-773 · hitl.py:159-165 · hitl.py:347-391
28Del 3 · Elementene
_dump(payload) = json.dumps(payload, sort_keys=True, indent=2) + "\n" # UTF-8
Sorterte nøkler, to mellomrom innrykk, eksplisitt avsluttende linjeskift. Ingen wall-clock og ingen uuid: run_id kommer fra kalleren, så samme kjøring gir byte-identiske filer.
| Fil | Hva den bærer |
|---|---|
| -proposal.json | forslaget og provenance-stemplet |
| -outcome.json | validated, rejected eller unsupported, med verdict_id |
| -coverage.json | stoppgrunn og én rad per approach |
| -runconfig.json | profil, modeller, tak og top_k |
| -debate.json | verktøykall og deklarerte krav |
| -multibase.json | fullførte kjøringer, kollisjoner, budsjettstopp |
| Fil | Hva den bærer |
|---|---|
| -prepass.json | forhåndspasset |
| -exploration.json | sporet fra Magentic-utforskningen |
| -plan-review.json | planen som venter på en signatur |
| -proposal-reviews.json | menneskets approve/revise per forsøk |
| -parse-failures.json | svar som ikke lot seg parse, ordrett |
To dokumenterte unntak. write_parse_failures hevder ikke byte-determinisme, fordi innholdet er levende modellprosa, og skriver fra en finally. write_exploration er byte-deterministisk, men skriver også fra en finally.
Kilde: src/portfolio_optimiser/outbox.py:44-46 · outbox.py:49-447
29Del 3 · Elementene
To nøkler, én telling. Lagringsnøkkelen er trippelen prosjekt, dimensjon og kandidat-identitet. Sumnøkkelen er dimensjonsfri, så den samme besparelsen realisert under to dimensjoner telles ÉN gang og flagges som overlapp. Verdirapporten kaller ledgerens dedupliserte aksessorer og summerer aldri postene på nytt.
Kilde: src/portfolio_optimiser/ledger.py:45-58 · ledger.py:92-241 · value_report.py:48-115 · README.md steg 7
Del 4 · Arbeidsflyten og sløyfene
Arbeidet er ikke én løkke, men et knippe sløyfer med svært ulik lengde: en chat-tur på sekunder, en terminal-review på minutter, en ekspert-dom på dager, en realisert besparelse på måneder. De korte lever i minnet. Alt som er tregere enn én kjøring krysser som fil.
30Del 4 · Arbeidsflyten og sløyfene
Kilde: shared/method-spec.md §3 · src/portfolio_optimiser/run.py:1180-1187 · src/portfolio_optimiser/verdicts.py:699-773 · docs/knowledge-base-recipe.md:12
31Del 4 · Arbeidsflyten og sløyfene
Ingen henger, alltid en typet stopp. BudgetExceeded(kind, limit, observed) med kind i {tokens, rounds, exploration_rounds}. Standardtakene er max_rounds = 3 og max_tokens = 100 000, og et cap-objekt nekter å konstrueres med en ikke-positiv verdi. Tokens telles fra leverandørens egen usage, aldri et ord-estimat.
Kilde: src/portfolio_optimiser/run.py:168-169 · generate.py:559 · workflow.py:110-116 · explore.py:82-99 · budget.py:30-44 · validator.py:39
32Del 4 · Arbeidsflyten og sløyfene
Spec-en sier det som en regel: de to falsifikatorene er «the deterministic validator (numbers) and the debate checker (reasoning) — they judge the same candidate and are never conflated». Den tredje porten er yngre: et forslag hvis approach ikke erklærte noe krav i kunnskapsbasen blir unsupported, verken validert eller avvist.
Kilde: shared/method-spec.md §2, §9 · src/portfolio_optimiser/validator.py:39, :67-68, :97-114 · run.py:673-687 · README.md:502-509
33Del 4 · Arbeidsflyten og sløyfene
Kilde: shared/method-spec.md §3 Steg 7, §8 · src/portfolio_optimiser/generate.py, workflow.py, proposal_review.py, hitl.py, verdicts.py, ledger.py, costsim.py, stress.py · docs/knowledge-base-recipe.md:12
34Del 4 · Arbeidsflyten og sløyfene
RunResult.refinements, så en leser kan se hva kjøringen faktisk ble fortalt.Målt, ikke antatt. Før parse-grunnen ble båret videre, kalte _fetch_parsed modellen med byte-identisk prompt. Én betalt kjøring (kontrakt-sorasen-04) brukte elleve av sine tolv runder på svar som feilet på samme måte, fordi ingenting noensinne fortalte modellen hva som var galt.
Kilde: src/portfolio_optimiser/generate.py:282-327, :642-673 · workflow.py:100-116 · run.py:664-687, :204-214 · budget.py:44
35Del 4 · Arbeidsflyten og sløyfene
Avbryter inne i forsøksløkka på en kandidat validatoren alt godtok. Lukket vokabular: approve eller revise <tekst>. Et revise kjøper ett forsøk til, og preger ingen dom.
Et menneske signerer Magentic-planen før løkka kjører. Løkka venter. Derfor nekter den hostede flaten den: å blokkere en forespørsel på et menneske blokkerer også /readiness.
En offline hva-hvis over modell-mappet og prislista, i hele øre. Null modellkall. Kjøringskost blir en beslutning i forkant, ikke en overraskelse etterpå.
Kilde: src/portfolio_optimiser/simulation.py:124-128, :505-525 · proposal_review.py:23-27, :248-305 · hosting.py:200-205 · costsim.py:1-16 · README.md:114-118
36Del 4 · Arbeidsflyten og sløyfene
Kilde: shared/method-spec.md §3 Steg 7-8, §5, §6 · src/portfolio_optimiser/run.py:1180-1187 · verdicts.py:214-240, :673-678, :732-736 · ledger.py:216-226 · README.md:231-237
37Del 4 · Arbeidsflyten og sløyfene
| Sted i arbeidsflyten | Menneske? | Døra | Hva skjer uten |
|---|---|---|---|
| Steg 1 til 6, hele kjøringen | Nei. Ved validatoren og checker-porten er mennesket fraværende ved konstruksjon | ingen | kjøringen fullfører og skriver no expert verdict given; verdict key=… |
| Review av et validert forslag | Valgfritt | --proposal-review | ingen review, og intet ekstra forsøk kjøpes |
Plan review under --explore | Påkrevd når den er slått på | --plan-review | input som slutter uten svar er en feil, aldri et samtykke |
| Dom på denne kjøringen | Valgfritt | --decision + --rationale | ingen dom registreres; halve nektes ved navn |
| Dom dager senere | Valgfritt | innboks-mappa | neste kjøring folder ingenting nytt inn |
| Promotion inn i wikien | Påkrevd | promote_verdict | wikien vokser ikke; ingenting krysser porten |
| Realisert besparelse | Påkrevd | ledger.realize | --report nekter: savings ledger not found |
De to halvdelene. --decision og --rationale går sammen eller ikke i det hele tatt. Fram til 1.1.0 defaultet --decision til approved, så hver flaggløs kjøring registrerte en godkjenning ingen hadde gitt. Den defaulten er borte.
Status, uten pynt. Ingen ekte ekspert-dom har kommet inn i treet ennå. Hver seedet dom er en syntetisk, AI-forfattet seed som er merket som det. Én live-kjøring mot et ekte endepunkt har fullført, den 14.08.2026: første forsøk døde på rundetaket (BudgetExceeded, rounds 12/13), gjenkjøringen konkluderte korrekt i rejected. Ingen kjøring har ennå produsert et validert forslag mot en levende modell.
Kilde: README.md:172-177, :231-237, :281-297, :545-556 · src/portfolio_optimiser/run.py:746-758, :3162-3176 · ledger.py:213-218 · verdicts.py:706-708 · docs/ekspert-svar.md:7-11
38Del 4 · Arbeidsflyten og sløyfene
| Begrep | Ordrett fra shared/method-spec.md |
|---|---|
| Context layer §2 | «one curated, version-controlled knowledge bundle per project (an 'LLM wiki') in the open OKF format» |
| Output layer §2 | «a run-scoped folder structure of raw results … Append-heavy, never part of the wiki.» |
| Promotion gate §2 | «the only path from the output layer into the context layer. Only expert-approved knowledge crosses it.» |
| IR §2, §7.1 | «the typed intermediate representation of a candidate measure» |
| Store §2, §4.2 | «the in-memory collection of historical verdicts retrieval ranks over» |
| Fold §2, §3 Steg 1 | «the injection of retrieved prior verdicts into the hypothesis prompt» |
| Begrep | Ordrett fra shared/method-spec.md |
|---|---|
| Two falsifiers §2, §9 | «the deterministic validator (numbers) and the debate checker (reasoning) — they judge the same candidate and are never conflated» |
| Mandate §3 | «one project, plus the objective its candidates are generated against» |
| Navigate, never stuff §3 Steg 1 | «MUST be built by navigating its OKF bundle with progressive disclosure — never by stuffing the whole bundle … into the prompt» |
| Refinement §3 Steg 5 | «Only the reason is carried — never the prior proposal JSON» |
| Long loop §3 Steg 7 | «The system MUST be fully resumable across runs separated in time — no live-session assumption.» |
| Fail-closed §6 | «a verdict whose decision is not in {approved, approved_with_adjustment} MUST be refused with an error, writing and linking NOTHING.» |
Hvorfor ordrett. Spec-en ligger i shared/, som er et git subtree delt med søsken-implementasjonen på Claude Agent SDK. Et begrep som glir her, glir i to stacker samtidig. Derfor siteres definisjonen med paragrafnummer, ikke parafraseres.
Kilde: shared/method-spec.md §2, §3, §6, §7.1, §9 · shared/README.md
39Del 4 · Arbeidsflyten og sløyfene
Kilde: src/portfolio_optimiser/outbox.py:106-148, :206-244, :321-349, :378-412 · hitl.py:159-165, :221-259 · value_report.py:48-87 · docs/ekspert-svar.md:100-104
Del 5 · MAF-harnessen
Rammeverket under rammeverket. Hva MAF er, hvilke byggeklosser det tilbyr, hvilke av dem dette repoet faktisk tok i bruk, og hvilke det lot stå — med grunnen skrevet ned hver gang.
40Del 5 · MAF-harnessen
Ett SDK for agenter og multi-agent-arbeidsflyter i .NET, Python og Go. Python-pakken agent-framework 1.0.0 kom 02.04.2026. Det distribueres som en pakkefamilie på 39 underpakker, ikke som ett hjul.
Learn, ordrett: «Semantic Kernel and AutoGen pioneered the concepts of AI agents and multi-agent orchestration. The Agent Framework is the direct successor, created by the same teams.»
agent-framework. Blått = pinnet og installert i dette repoet; grått = finnes, men er ikke en avhengighet her.Kilde: pyproject.toml:8-31 · uv.lock · learn.microsoft.com/agent-framework/overview/#why-agent-framework · pypi.org/project/agent-framework-core/
41Del 5 · MAF-harnessen
ctx.request_info er koblet, men slått av: 0 kallsteder i src sender True, så biblioteket er eneste dør. Navnene er de gjeldende etter GA-omdøpingen i april 2026; ChatAgent, @ai_function og setup_observability() finnes bare i den etterslepende API-referansen.Kilde: learn.microsoft.com/agent-framework/workflows/orchestrations/ · …/agents/observability · …/support/upgrade/python-2026-significant-changes · docs/2026-09-11-p12-maf-gjeld.md § 3
42Del 5 · MAF-harnessen
| MAF-element | Brukt? | Hvor | Hvorfor |
|---|---|---|---|
GroupChatBuilder | ja, hver kjøring | workflow.py:104-113 | Maker-checker er debatt-default. selection_func sykler proposer → checker; output_from=agents løfter begge utdataene ut |
Agent | ja | workflow.py:63 | To deltakere, bygget friske per kjøring sammen med sine klienter (B7) |
OpenAIChatCompletionClient · FoundryChatClient | ja, én per profil | backends.py:150, :160-164 | Sømmen mot leverandøren. Chat Completions og ikke streaming, fordi usage da fylles ut None-trygt |
FunctionTool / @tool | ja, default | tools.py:24, :46 | Datasømmen i kjørestien er in-process. Ingen nettverkskall for å nå kunnskapsbasen |
ChatMiddleware | ja | budget.py:228 | BudgetMiddleware leser usage etter hvert kall og kortslutter med BudgetExceeded; strict_usage gjør manglende usage til hard feil |
MagenticBuilder | opt-in, --explore | explore.py:1816-1822 | Utforskning ligger OVER åttestegs-sløyfen, aldri inni debatten |
| MCP-verktøy | opt-in, --mcp-config | mcp_tools.py:154, :170 | Eksterne servere blir verktøy agentene kan kalle under debatten. Allowlist er påkrevd |
configure_otel_providers | opt-in, PORTFOLIO_OTEL | tracing.py:160 | Av betyr at MAF aldri kalles: et kall med tom eksportørliste ville likevel installert providere og lest hver OTEL_EXPORTER_OTLP_*-variabel |
Én rad er halvveis. ContextProvider er med, men den bærende bruken er format_fewshot() strengkonkatenert inn i prompten (run.py:1557), ikke MAFs egen injeksjon. Å lukke det står som åpent punkt F3.
Kilde: src/portfolio_optimiser/{workflow,backends,tools,budget,explore,mcp_tools,tracing}.py · docs/invarianter.md
43Del 5 · MAF-harnessen
WorkflowBuilder: 0 treff i src. De eneste Workflow-objektene er de to byggerne bygger selvSequential / Concurrent / Handoff: portefølje-fan-out er håndskrevet asyncio.gathershared/method-spec.md §3 er normativ og eies av commonsWorkflow.as_agent(): et bygget workflow er engangs (målt klientkall-serie [2, 0, 0]), og det ville servert ugatede forslagSkillsProvider, DevUI, OTLP-eksportører: egen laster, ingen prod-UI, og eksportørene er egress i et hjulvalidator.py, ir.py og okf.py, sier i sin egen docstring at de aldri skal importere agent_framework. tests/test_okf.py::test_okf_is_maf_free gjør påstanden til noe som kan feile.Kilde: src/portfolio_optimiser/hosting.py:19-23 · docs/2026-09-11-p12-maf-gjeld.md § 3 (U1, U2, U5, U8) · docs/invarianter.md:32
44Del 5 · MAF-harnessen
DefaultAzureCredential: Learn fraråder det for å unngå utilsiktet credential-probing, som ville gjort en konfigurasjonsfeil om til en treg feil.Dokumentasjonen motsier seg selv her. Samme Learn-side sier både at plattformen injiserer «a nonempty value» og at variabelen er «set to 1». Repoet leser den på truthiness og ikke på tilstedeværelse, så en eksportert-men-tom verdi er et shell-uhell og ikke et hosting-signal.
Kilde: src/portfolio_optimiser/backends.py:28-30, :45, :49, :146-164 · docs/invarianter.md:183 · learn.microsoft.com/azure/foundry/agents/how-to/configure-hosted-agent-env-variables
45Del 5 · MAF-harnessen
output_from=agents gir get_outputs() bare orkestratorens «reached max rounds»-melding. run.py skiller de to utdataene på author_name.Kilde: src/portfolio_optimiser/workflow.py:78, :104-116 · src/portfolio_optimiser/budget.py:228 · kalt fra run.py
46Del 5 · MAF-harnessen
max_reset_count må være positiv, og det er en måling: grensesjekken er reset_count >= max_reset_count mot en teller som starter på null, så taket 0 er allerede nådd før første runde.Hvorfor nektet hostet. Plan review er synkron og blokkerer sløyfen. En HTTP-forespørsel har ingen anmelder, så kallet ville hengt — og stoppet den samme event-loopen som svarer på /readiness. Operatørdøren er CLI-en.
Kilde: src/portfolio_optimiser/explore.py:63-117, :1816-1830 · src/portfolio_optimiser/hosting.py:200-205 · learn.microsoft.com/agent-framework/workflows/orchestrations/magentic
47Del 5 · MAF-harnessen
traceparent inn i MCP-kall for klientåpnede transporter, som er nøyaktig de to som er tillatt her.To detaljer som ikke er kosmetiske. Strukturert utdata sendes som en JSON-Schema-mapping og ikke som en Pydantic-klasse: gitt en klasse emitterer klientens konverter minimum, exclusiveMinimum, minItems og prefixItems, fire ting den publiserte strict-undermengden utelukker. Og den skriptede offline-klienten arver OpenAIChatCompletionClient framfor å være en frisk BaseChatClient, ellers ville BudgetMiddleware stilltiende blitt en no-op.
Kilde: src/portfolio_optimiser/mcp_tools.py:50-61, :237-241 · tracing.py:41-46, :63, :160-197 · generate.py:65-67, :219-235 · simulation.py:379-388
48Del 5 · MAF-harnessen
pyproject-assertet utleder sin forventede streng fra den: to literaler for ett faktum driver fra hverandre, og et drevet gulv er en vakt som slutter å vokte uten en lokal diff. Orchestrations står på 1.1.1 fordi 1.1.1 fortsatt er siste utgivelse på PyPI.Funn 99, 08.09 — den beste live-historien i repoet. Tre quick_validate-kall feilet mot en bundle-id modellen hadde funnet på. MAF gjør et kastende verktøy om til «Error: Function failed.» med detaljen undertrykt med mindre include_detailed_errors er satt, teller det som en feil, og stopper etter DEFAULT_MAX_CONSECUTIVE_ERRORS_PER_REQUEST = 3. Det ene nektet visste og modellen ikke, nemlig hvilke id-er som finnes, nådde den aldri. Fiksen: verktøyet returnerer nå et strukturert nekt som navngir id-ene.
Kilde: docs/2026-09-02-f15-maf-pinnen.md · docs/2026-09-11-p12-maf-gjeld.md · docs/2026-09-12-f16-maf-1180.md:21-22 · docs/2026-09-08-funn-99-chatclient-refusal.md:46-50 · tests/test_maf_version_guard.py:26-31
Del 6 · Kvalitetsmetoden og målt status
Et måleresultat er aldri et faktum om verden. Hvert tall i denne delen bærer nevneren sin, og der nevneren mangler står det «ikke målt» — aldri null.
49Del 6 · Kvalitetsmetoden og målt status
Målingen er ikke at testen er grønn. Målingen er mutasjonen: koble sømmen fra i en kopi, kjør hele suiten, tell hvor mange tester som blir røde.
pytest --co mot hver fil 18.09.2026. Mutasjonstallene står i hovedbokens egne rader.Fellen har et navn i repoet: «grønn-men-død». Fase 2 er der den ble funnet. run_portfolio hadde ikke parametrene bundle_dir/verdict_dir i det hele tatt, så ingen tidligere dom nådde noen hypotese-prompt, mens docstringen kalte det kryss-prosjekt-læring — og testen var grønn fordi den bare sjekket retrieved, aldri prompten.
Jernloven gjelder også vaktene selv. F15s versjonsvakt ble kjørt RØD først: 2 failed, så 4 passed. Og da v1-gaten ble uavhengig gjennomgått 17.09 overlevde 10 av 20 mutanter; etter herding var 20 av 20 røde.
Kilde: README.md:375 · docs/review-2026-07.md:57 · docs/invarianter.md:3093 · docs/2026-09-02-f15-maf-pinnen.md · STATE.md § Driftsmodell
50Del 6 · Kvalitetsmetoden og målt status
docs/invarianter.md er 3 176 linjer og 94 rader (talt 18.09.2026). Rader adresseres med grep på overskriften, aldri med linjenummer. Åtte av dem:
| Regelen | Målingen som tvang den fram | Går rød |
|---|---|---|
| To falsifiserere over én kandidat: validatoren gater tallene, checkeren gater resonnementet. De blandes aldri. | Metodespeken §2/§6, steg 3 og 4 | test_checker_gate_loadbearing.py, rød på begge frakoblingspunkter |
Gaten er forankret i prosjektets egen kostnadsbasis. Stadium 0 avstemmer mot CostBaseline før solveren. Validering, aldri reparasjon. | Før S4.0 resonnerte hvert stadium bare om tall forslaget selv leverte, så en internt konsistent hallusinasjon klarerte hele gaten | test_s40_cost_baseline_loadbearing.py, 6 mutasjoner røde |
| Et kravnummer er ikke en pris. | P20 del B, 15.09: 10.4 er erklært ingen steder og står i 12 av 274 dokumenter. Ordrens egen regel ble målt falsk mot begge sine kjent-positive | docs/invarianter.md:2750 |
En ekspertdom kan ikke oppstå av stillhet. RunResult.verdict er Verdict | None. | F2, økt 66: hver flaggløs kjøring myntet en godkjenning ingen ga, den gikk i det delte lageret, og den ble båret inn i neste prosjekts prompt — på flaten som ble overlevert 14.08 | test_ungiven_verdict_loadbearing.py, 15 armer, 8 mutasjoner røde |
| Penger kvantiseres i én rekkefølge, fra én kilde: per beløp, så summeres heltallene. | Tre linjer à 60000,005 NOK er 18 000 003 øre kvantisert først, 18 000 001 summert først. En fiks på bare ett av de to kallstedene overlevde hele suiten | test_money_quantization_loadbearing.py, 5 mutasjoner røde |
| Sporing er opt-in, og «av» betyr at MAF aldri kalles. | Et kall med tom exporter-liste ville installert providers og lest hver OTEL_EXPORTER_OTLP_* i omgivelsene. «Av» må være fravær av kallet | test_tracing_loadbearing.py, 9 mutasjoner røde |
| En nekt modellen skal kunne rette seg etter er en returverdi, aldri en raise. | Funn 99, 08.09: MAF gjør en raise om til Error: Function failed., undertrykker detaljen og teller den mot grensen på 3 påfølgende verktøyfeil. Modellen gjettet på JSON-formatet, som var riktig hele veien | test_run_cli_chatclient_refusal.py, 8 armer, 7 mutasjoner røde |
| Målingene leser en FROSSET kopi av korpuset, pinnet med sha256 — aldri et annet repos build-mappe. | 17.09 kl. 17:43: nabo-repoet bygde om r761-2025, gatens rad 6 og 7 ble IKKE MÅLT og fem tester falt, for en endring ingen her hadde gjort | test_frozen_bundles_loadbearing.py, 17 armer, 8 mutasjoner røde |
Hovedboken ble flyttet 18.09.2026. CLAUDE.md hadde vokst til 310 919 byte mot Claude Codes kutt på 150 000 tegn, så omtrent halvparten av reglene nådde ingen økt. Etter flyttingen er fila 6 033 byte, og 93 rader står ordrett i hovedboken.
Kilde: docs/invarianter.md · STATE.md § NESTE · talt med grep -c '^- \*\*' docs/invarianter.md
51Del 6 · Kvalitetsmetoden og målt status
Dette er ikke «−N % kostnad» for en kjøring. Det som er målt er hvert verktøys eget bidrag til prompt-tokens. En navigatør som går k nivåer ned betaler k listinger; gevinsten er at den betaler for det den valgte. Instrumentet ble validert mot et kjent-positivt først: det reproduserte commons sine egne publiserte tall eksakt (3 861 / 10 406 / 12 595).
Kilde: docs/invarianter.md:1027, :1104, :1719 · docs/2026-08-26-katalogkostnaden.md · docs/2026-09-03-hierarkisk-navigasjon-k2.md
52Del 6 · Kvalitetsmetoden og målt status
uv run pytest -q --co (kun innsamling; suiten ble ikke kjørt). STATE fører hovedtreet som 1 984 passed / 5 skipped / 5 xfailed.To forsøk samme dag, begge dokumentert. Måleprotokollen fra 14.08 fører første forsøk som RC=1 med BudgetExceeded på rundetaket (rounds 12/13), som en uhåndtert traceback; det ble senere den hostede 429-armen. Gjenkjøringen samme dag (protokollens § 6) konkluderte i rejected: validatoren tok en kostlinje modellen hadde funnet på, på toleranseporten fordi bundlen ikke bar noen baseline. README beskriver gjenkjøringen. Kilde: docs/2026-08-14-fase1b-forste-levende-kjoring.md:35-60 og :189-224.
Kilde: docs/2026-08-14-fase1b-forste-levende-kjoring.md:36, :55 · README.md:281, :284 · docs/2026-08-25-fable-misjonsreview.md:21, :22 · docs/2026-09-14-p16-stressrunde-1.md:178
53Del 6 · Kvalitetsmetoden og målt status
fasit.must_cite). Runde 5–6 rapporterer i stedet grounded per TILNÆRMING, 20 approach-rader. De to nevnerne er ulike og tallene er ikke direkte sammenlignbare; de står som publisert. Runde 3 er publisert både som 1 av 32 og som 1 av 26 pluss P17bs 0 av 6. Og en sammendragslinje i STATE blander de to målene: «0/26, 0/26, 1/32, 2/20, 1/20, 1/20» har skiftende nevner, og den siste verdien tilhører named, ikke grounded — runde 6 leser grounded 3 av 20. Konklusjonen overlever korreksjonen; aritmetikken i linja gjør det ikke.«N100 = FERDIG» fra økt 102 er motsagt av P16 til P22. Mekanikken virker og navigerer ekte korpus; de faglige treffene kommer ikke. Ingen faktura er lest i noen runde, så hvert NOK-tall er et listepris-anslag. Og som P22 selv skriver: at must_refuse falt fra 5 av 5 til 2 av 5 er ikke bevis for at systemet er blitt verre, det er bevis for at den forrige målingen ikke kunne skille.
Kilde: docs/2026-09-14-p16-stressrunde-1.md · -p18- · -p19- · -p20- · -p21- · docs/2026-09-16-p22-stressrunde-6.md · STATE.md
Del 7 · Etter v1.1
v1.1.0 ble sluppet 14.08.2026, og det er den siste utgivelsen. Alt etter den datoen er måling. Denne delen sier hva planen kaller destinasjonen, hvor langt unna vi er, og hva som med vilje ikke skal bygges.
54Del 7 · Etter v1.1
Ferdig-kriteriet, ordrett fra PLAN.md § Destinasjonen: «Én ekte kostnadsrapport for shared/examples/bygg-energi-mikro, laget gjennom tre tilbakemeldingsrunder med operatøren som fagperson. Hver runde endret rapporten målbart, og i runde 3 kunne fagpersonen beholde minst 80 % uendret.»
Økt 102 konkluderte «N100 = FERDIG». P16 til P22 motsa den. Seks betalte runder på syntetiske mandater, uten et menneske i sløyfa, produserte ingen rapport en fagperson har rettet.
Mekanikken virker: stigen navigerer ekte korpus, gaten avviser med sanne grunner, og i runde 6 ble 10 av 20 tilnærminger validert. De faglige treffene fulgte ikke med: grounded nådde aldri over 3 av 20.
«v1» ble omdefinert fra en tag til en produkttilstand — repoet står allerede på 1.1.0. Kriteriet ble skrevet så det kan FELLES, og en ny syntetisk stressrunde 7 er eksplisitt forbudt.
En ramme planen ber om at ikke skjules: én person er bestiller, fagperson og operatør. «Det er en kjent begrensning.» Loggen i PLAN.md har åtte rader, og seks av dem sier «ingen bevegelse på kriteriet». En serie av dem er i seg selv et funn.
Kilde: PLAN.md § Destinasjonen, § Problemet vi løser, § Rammer, § Logg · STATE.md (local-only, ikke publisert)
55Del 7 · Etter v1.1
uv run python -m portfolio_optimiser.evals.v1_gate — deterministisk, ingen modellkall, ingen kvote. Hver nevner kommer utenfra det som måles.
approach_id. Gaten skriver en attestering på hver kjøring: «rad 1–2 beviser ikke at en fagperson skrev feedbacken; det bekrefter operatøren.»Kilde: src/portfolio_optimiser/evals/v1_gate.py:1-15 · PLAN.md § Ferdig-kriteriet · STATE.md § NESTE · gaten kjørt 18.09.2026 (exit 1)
56Del 7 · Etter v1.1
| Strøm | Status | Hva som gjenstår, målt | Kilde |
|---|---|---|---|
| Rad 2: bind runden til en KJØRING gaten selv kan verifisere | PÅGÅR | Ordre i køen fra 17.09. PM re-målte 18.09: rad 2 ble 3 av 3 grønn på håndskrevne outcome.json og coverage.json pluss os.utime. «Kjøringen finnes» er implementert som «en fil med det navnet finnes», og det oppfyller touch. | ordre …-1292712426 |
| Rapportfila en fagperson faktisk leser | PLANLAGT | Avgjort 17.09: en ny, lesbar fil bygget fra utboksen. Den finnes ikke i dag, og verken --report eller proposal-filene er noe en fagperson leser. 80 %-regelen måles mot den. | PLAN.md åpent spm. 2 |
| Kapabilitetsordrer, én per rød rad og type | PLANLAGT | Rad 3 står 3 av 8. Fem typer mangler vei inn: fjern en retning, lett på et krav, konseptgrafer, skills, inline kontekst. grep relax i src gir 0 mekanismer. | PLAN.md § Nevnere |
| P22 funn 1: falsifiseringsarmens spørsmål | ÅPENT (operatørbeslutning) | Ingen stage i gaten spør om kunnskapsbasen bærer et krav som støtter retningen. must_refuse 2 av 5 i runde 6. Anslått én økt. | P22 § 4 |
named og terskelen | ÅPENT SPØRSMÅL | 1 av 20 fjerde runde på rad. Å be modellen gjengi ref gjør den til noe den blir BEDT om; derfor står raden som diagnose. | PLAN.md åpent spm. 6 |
| Hosting | BYGGET, IKKE TATT I BRUK | Inngangen finnes fra fase 4d: main.py rundt run_project på én asyncio-løkke, med readiness og invocations. Dockerfile og azure.yaml ble fjernet 14.08 til fordel for én startkommando, agent-framework-foundry-hosting er ikke installert i treet, og ingen deployment er målt. | docs/invarianter.md:192 |
| Prisskjemaet som tabell med kolonner | KRYSS-REPO | Observasjon videresendt til llm-ingestion-okf, ikke bestilt: et prisskjema med kolonner ville latt --derive-cost-baseline forankre stadium 0. Det leverte skjemaet er uleselig i FORM, ikke fraværende i byte. | S7c-målingen |
| MAF-gjelden: context provideren som ikke bærer noe | UTSATT | Skopet 29.08, ikke bygget. Strukturelt, ikke en enlinjes: context_providers er et konstruksjonsargument på Agent, mens proposeren kaller chat_client.get_response() direkte. | docs/2026-08-29-maf-gjelden-omfang.md:26-38 |
En strukturell spenning — dette er en lesning, ikke repoets tekst (antakelse). Rad 6 kan bare måles mot artefakter yngre enn regelen, og ordren sier gaten ikke når exit 0 «før en ny stressrunde finnes». Planen forbyr samtidig en ny stressrunde på syntetiske mandater. Begge holder bare hvis runden som løsner rad 6 er én av de tre ekte fagperson-rundene. Det står ingen steder, og må bekreftes av operatøren.
Måle-hygiene som egen sak. Samme commit bærer tre suite-tall — 1 967, 1 962 og 1 917 — og ingen av dem lot seg gjenfinne. Regelen ordren setter er kort: før et suite-tall med kommandoen som ga det. Tallet i denne presentasjonen er 1 995 samlet, målt 18.09 med uv run pytest -q --co.
Kilde: PLAN.md § Ferdig-kriteriet, § Åpne spørsmål · STATE.md § NESTE · ordre 20260917T223645Z-1292712426 · docs/2026-09-16-p22-stressrunde-6.md § 4
57Del 7 · Etter v1.1
PLAN.md § Hva som IKKE skal bygges og § Rammer, pluss READMEs non-goals.Fire forbud til, ført i STATE: Magentic er ikke debatt-default — utforskningen legges OVER Group Chat-sløyfa, aldri inni. git subtree push fra en konsument skjer aldri; shared/ er pull-only. MAF-evals og SkillsProvider er avvist som flate. Og på den navngitte ikke-bygg-lista: timeout-sømmen fra 1a, N101, oppslagsdøra --question og --docs-dir-omveien.
Kilde: PLAN.md § Hva som IKKE skal bygges, § Rammer · README.md:265 · STATE.md § Låste beslutninger, § NESTE
58Avslutning
Klon, uv sync, uv run pytest, og så de sju stegene. Ingen CI i organisasjonen: testsuiten fra en ren klone er verifikasjonen.
To git-pinnede sikkerhetskomponenter må oppgis ved siden av wheelen; pinnene bor i pyproject.toml.
Solo-vedlikeholdt, MIT. Issues er signaler; pull requests tas ikke imot.
Kilde: README.md «Install» og «Walk the whole chain offline» · pyproject.toml
59Avslutning
Kilde: README.md «How it works» · docs/invarianter.md · src/portfolio_optimiser/run.py, validator.py, verdicts.py, ledger.py
Spørsmål
Alt i dette decket kan slås opp. Start her:
git.fromaitochitta.com/open/portfolio-optimiser
README (engelsk), docs/invarianter.md (hovedboken), docs/extending.md
git.fromaitochitta.com/open/portfolio-optimiser-commons
shared/method-spec.md, shared/ingest-spec.md, ekspert-persona som Agent Skill, eksempelbundle + golden suite
learn.microsoft.com/agent-framework/
Overview, orchestrations, observability, og «Python 2026 significant changes» for navneendringene
docs/kort-presentasjon.html (12 slides, allmennpublikum)
docs/presentasjon-fagpersonens-bidrag.html, docs/presentasjon-bygge-kunnskapsbase.html
Decket er AI-generert (Claude Code) med menneskelig gjennomgang. Hvert tall bærer nevner og kilde; det som ikke er verifisert, står som det.