Session 146 fixed `--run-id` across the seven doors and called it a class. It was not: the class
is every caller-supplied value that reaches a file name, and `write_outbox` composes
`{run_id}-{approach_id}`. Measured 20.09 -- `--approach-id a/../../../ESCAPE` answered 0 and put
the artefacts three levels above the directory the caller named. Counted rather than assumed: 11
path compositions in `outbox.py`, 2 such values, both now through one `_checked_name`.
The ledger sentence that said containment was UNREACHABLE after the string rule was untrue, and
the approach-id escape is the disproof -- the removed check would have caught it. It is back, but
in `outbox._artefact_path`, where the composition is, not in the door. That is the difference
that makes it reachable: the string rule lives in the door, while `run.py` hands its own
`--run-id` straight to the writers and goes past it. Checked before the directory is created, so
a refusal leaves nothing behind, and it covers the next flag someone interpolates into a name.
The judge's exact call now answers 3 with 0 files outside. Suite 2291/0/5/5 (746 s), ruff clean,
mypy 0. Both gates re-run after `git add`: v1 exit 1 (0/3, 0/3, 3/8, no report, 3/8, NOT
MEASURED, 1/20), B exit 1 (15/17, 0/2, 15/15 over 516 files, 0/3, 4/5, NOT MEASURED) -- no row
moved, and row 3's denominator held because the probe grew in place rather than as a new file.
Also: the presentation deck said 1.1.0 was the current version in two places. 1.2.0 now stands in
every tracked place that claims the repo's version. No bump, no tag, no new capability.
[skip-docs]
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
3528 lines
253 KiB
HTML
3528 lines
253 KiB
HTML
<!doctype html>
|
||
<html lang="no">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>portfolio-optimiser — arkitekturen, sløyfene og harnessen</title>
|
||
<style>
|
||
:root{
|
||
--fg:#151515;
|
||
--muted:#5a5a5a;
|
||
--line:#dcdcdc;
|
||
--soft:#f4f4f4;
|
||
--accent:#1c4e8a;
|
||
--accent-soft:#e6eef8;
|
||
--warn:#a03a1e;
|
||
--warn-soft:#fbe9e3;
|
||
--ok:#2f6b3a;
|
||
--ok-soft:#e5f1e7;
|
||
--pad-x:clamp(2rem, 5vw, 6rem);
|
||
}
|
||
*{box-sizing:border-box}
|
||
body{
|
||
margin:0; background:#ffffff; color:var(--fg);
|
||
font-family:"Helvetica Neue", Arial, "Segoe UI", system-ui, sans-serif;
|
||
font-size:clamp(1rem, 1.2vw, 1.45rem); line-height:1.42;
|
||
-webkit-font-smoothing:antialiased;
|
||
}
|
||
body:focus{outline:none}
|
||
body.js .slide{display:none}
|
||
body.js .slide.active{display:flex}
|
||
.slide{
|
||
min-height:100vh; display:flex; align-items:center;
|
||
padding:clamp(2rem, 4vh, 3.5rem) var(--pad-x) clamp(4.5rem, 8vh, 6rem);
|
||
border-bottom:1px solid var(--line);
|
||
}
|
||
body.js .slide{border-bottom:0}
|
||
.inner{width:100%; max-width:1600px; margin:0 auto}
|
||
|
||
.kicker{color:var(--muted); font-size:.68em; margin:0 0 1rem; letter-spacing:.02em}
|
||
.kicker .num{color:var(--accent); font-weight:700; margin-right:.6em}
|
||
.kicker .part{text-transform:uppercase; font-size:.85em; letter-spacing:.08em}
|
||
|
||
h1{font-size:clamp(2.4rem, 4.6vw, 5.2rem); line-height:1.05; letter-spacing:-.02em; font-weight:700; margin:0 0 1.4rem}
|
||
h2{font-size:clamp(1.6rem, 2.7vw, 3.1rem); line-height:1.1; letter-spacing:-.02em; font-weight:700; margin:0 0 1.2rem}
|
||
h3{font-size:.9em; font-weight:700; margin:0 0 .4rem; line-height:1.3}
|
||
.lede{font-size:1.15em; line-height:1.4; color:var(--muted); margin:0 0 1.4rem; max-width:60ch}
|
||
.point{font-size:1.2em; line-height:1.4; margin:0 0 1.2rem}
|
||
p{margin:0 0 .9rem} p:last-child{margin-bottom:0}
|
||
.small{font-size:.78em; line-height:1.5; color:var(--muted)}
|
||
.src{font-size:.66em; color:var(--muted); margin-top:1rem}
|
||
.src code{font-size:.95em}
|
||
ul{margin:0; padding-left:1.3em} li{margin:0 0 .5rem} li:last-child{margin-bottom:0}
|
||
b, strong{font-weight:700}
|
||
|
||
/* layout helpers */
|
||
.cols{display:grid; gap:clamp(1.2rem, 2.4vw, 2.6rem); grid-template-columns:repeat(auto-fit, minmax(15rem, 1fr)); margin:0 0 1.4rem}
|
||
.col{border-top:2px solid var(--fg); padding-top:.8rem; font-size:.84em; line-height:1.45}
|
||
.col.soft{border-top-color:var(--line)}
|
||
.col p{color:var(--muted); margin:0 0 .5rem}
|
||
.col p:last-child{margin-bottom:0}
|
||
.col .step{color:var(--accent); font-weight:700; display:block; margin-bottom:.25rem}
|
||
.col ul{padding-left:1.1em; color:var(--muted)} .col li{margin:0 0 .35rem}
|
||
|
||
.split{display:grid; grid-template-columns:minmax(0,1.15fr) minmax(0,1fr); gap:clamp(1.4rem, 3vw, 3.5rem); align-items:center}
|
||
.split.fig-left{grid-template-columns:minmax(0,1fr) minmax(0,1.15fr)}
|
||
.split.wide-fig{grid-template-columns:minmax(0,1.6fr) minmax(0,1fr)}
|
||
@media (max-width: 900px){ .split, .split.fig-left, .split.wide-fig{grid-template-columns:1fr} }
|
||
|
||
.callout{border-left:4px solid var(--accent); padding:.2rem 0 .2rem 1.2rem; font-size:.88em; line-height:1.5; color:var(--muted); margin:1.2rem 0 0}
|
||
.callout b{color:var(--fg)}
|
||
.callout.warn{border-left-color:var(--warn)}
|
||
.callout.ok{border-left-color:var(--ok)}
|
||
.rule{border:0; border-top:2px solid var(--fg); margin:1.4rem 0 1.2rem}
|
||
|
||
table{border-collapse:collapse; width:100%; font-size:.74em; line-height:1.4; margin:0 0 1rem}
|
||
th, td{text-align:left; vertical-align:top; padding:.5rem .8rem .5rem 0; border-bottom:1px solid var(--line); color:var(--muted)}
|
||
th{color:var(--fg); font-weight:700; border-bottom:2px solid var(--fg)}
|
||
td:first-child, th:first-child{color:var(--fg); font-weight:700; padding-right:1.4rem}
|
||
table.compact{font-size:.66em}
|
||
td.ok{color:var(--ok); font-weight:700} td.bad{color:var(--warn); font-weight:700}
|
||
|
||
pre{border:1px solid var(--line); background:var(--soft); padding:1rem 1.2rem; overflow-x:auto; font-size:.66em; line-height:1.6; margin:0 0 1.2rem}
|
||
code{font-family:ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size:.92em}
|
||
p code, li code, td code{background:var(--soft); padding:.05em .3em}
|
||
|
||
/* figures (inline SVG) */
|
||
figure{margin:0}
|
||
figure.fig{margin:.6rem 0 1rem}
|
||
figure.fig svg{width:100%; height:auto; max-height:58vh; display:block; font-family:inherit; margin:0 auto}
|
||
figure.fig.narrow svg{max-width:52rem; margin:0 auto}
|
||
figcaption{font-size:.7em; color:var(--muted); margin-top:.5rem; text-align:left}
|
||
/* SVG conventions — builders use these classes so all diagrams read as one system */
|
||
.fig svg .box{fill:#fff; stroke:var(--fg); stroke-width:2}
|
||
.fig svg .box.soft{fill:var(--soft); stroke:var(--muted); stroke-width:1.5}
|
||
.fig svg .box.accent{fill:var(--accent-soft); stroke:var(--accent); stroke-width:2}
|
||
.fig svg .box.warn{fill:var(--warn-soft); stroke:var(--warn); stroke-width:2}
|
||
.fig svg .box.ok{fill:var(--ok-soft); stroke:var(--ok); stroke-width:2}
|
||
.fig svg .box.dashed{stroke-dasharray:6 5}
|
||
.fig svg .lbl{fill:var(--fg); font-size:15px; font-weight:700}
|
||
.fig svg .sub{fill:var(--muted); font-size:12.5px}
|
||
.fig svg .tiny{fill:var(--muted); font-size:11px}
|
||
.fig svg .mono{font-family:ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size:12px; fill:var(--fg)}
|
||
.fig svg .edge{fill:none; stroke:var(--fg); stroke-width:2; marker-end:url(#arr)}
|
||
.fig svg .edge.soft{stroke:var(--muted); stroke-width:1.5; marker-end:url(#arr-soft)}
|
||
.fig svg .edge.accent{stroke:var(--accent); marker-end:url(#arr-accent)}
|
||
.fig svg .edge.warn{stroke:var(--warn); marker-end:url(#arr-warn)}
|
||
.fig svg .edge.dashed{stroke-dasharray:6 5}
|
||
.fig svg .edge.noarrow{marker-end:none}
|
||
.fig svg .band{fill:var(--soft); stroke:none}
|
||
.fig svg .band.accent{fill:var(--accent-soft)}
|
||
.fig svg .band.warn{fill:var(--warn-soft)}
|
||
.fig svg .band.ok{fill:var(--ok-soft)}
|
||
.fig svg .band-lbl{fill:var(--muted); font-size:11px; letter-spacing:.08em; text-transform:uppercase; font-weight:700}
|
||
.fig svg .hair{stroke:var(--line); stroke-width:1}
|
||
|
||
/* agenda / progress cards */
|
||
.agenda{display:grid; grid-template-columns:repeat(auto-fit, minmax(13rem,1fr)); gap:1rem; font-size:.82em}
|
||
.agenda .card{border:1px solid var(--line); padding:.9rem 1rem; line-height:1.4}
|
||
.agenda .card.now{border-color:var(--accent); background:var(--accent-soft)}
|
||
.agenda .card .n{color:var(--accent); font-weight:700; display:block; font-size:.85em}
|
||
.agenda .card .t{font-weight:700; display:block; margin:.15rem 0 .3rem}
|
||
.agenda .card .d{color:var(--muted); font-size:.85em}
|
||
|
||
.timebox{font-size:.7em; color:var(--muted); border:1px solid var(--line); display:inline-block; padding:.2rem .6rem; margin-left:.6rem; vertical-align:middle}
|
||
|
||
/* section divider slides */
|
||
.slide.divider{background:var(--soft)}
|
||
.slide.divider h1{font-size:clamp(2.2rem, 4.2vw, 4.6rem)}
|
||
.slide.divider .lede{max-width:70ch}
|
||
|
||
/* navigation */
|
||
#progress{position:fixed; top:0; left:0; height:3px; background:var(--accent); width:0; transition:width .15s linear; z-index:20}
|
||
#nav{position:fixed; left:0; right:0; bottom:0; z-index:20; display:flex; align-items:center; gap:1.2rem; padding:.6rem var(--pad-x); background:#fff; border-top:1px solid var(--line); font-size:.8rem; color:var(--muted)}
|
||
#nav button{font:inherit; color:var(--muted); background:none; border:1px solid var(--line); padding:.3rem .9rem; cursor:pointer}
|
||
#nav button:hover{color:var(--fg); border-color:var(--fg)}
|
||
#count{margin-left:auto; font-variant-numeric:tabular-nums}
|
||
#nav .hint{opacity:.8}
|
||
body:not(.js) #nav, body:not(.js) #progress{display:none}
|
||
|
||
@media print{
|
||
body.js .slide, body.js .slide.active{display:block}
|
||
.slide{min-height:0; break-after:page; page-break-after:always; border-bottom:0; padding:2rem 0}
|
||
.slide:last-child{break-after:auto; page-break-after:auto}
|
||
#nav, #progress{display:none}
|
||
body{font-size:11pt} h1{font-size:24pt} h2{font-size:19pt}
|
||
.slide.divider{background:#fff}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="progress"></div>
|
||
<svg width="0" height="0" style="position:absolute" aria-hidden="true">
|
||
<defs>
|
||
<marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#151515"/></marker>
|
||
<marker id="arr-soft" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#5a5a5a"/></marker>
|
||
<marker id="arr-accent" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#1c4e8a"/></marker>
|
||
<marker id="arr-warn" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0L10 5L0 10z" fill="#a03a1e"/></marker>
|
||
</defs>
|
||
</svg>
|
||
|
||
<!-- ===== part0-open.html ===== -->
|
||
|
||
<!-- tittel -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">portfolio-optimiser · v1.2.0 · teknisk gjennomgang</span></p>
|
||
<h1>Agentene foreslår. En beregning avgjør. Fagfolk dømmer.</h1>
|
||
<p class="lede">Et åpent Python-rammeverk på Microsoft Agent Framework som leter etter kostnadsbesparelser <b>inni</b> hvert prosjekt i en portefølje: arkitekturen, tilbakemeldingssløyfene og harnessen, fra formålet ned til hver enkelt søm.</p>
|
||
<p class="small">For AI-arkitekter og utviklere · inntil 60 minutter · alle påstander har kildelinje til repoet (<code>git.fromaitochitta.com/open/portfolio-optimiser</code>, HEAD 50c9763, 2026-09-18)</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- agenda -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">01</span><span class="part">Agenda</span></p>
|
||
<h2>Fra formål til søm: sju deler, hver med figurer.</h2>
|
||
<div class="agenda">
|
||
<div class="card"><span class="n">Del 1 · 6 min</span><span class="t">Formålet</span><span class="d">Problemet, hovedidéen, hva det ikke er</span></div>
|
||
<div class="card"><span class="n">Del 2 · 8 min</span><span class="t">Arkitekturen overordnet</span><span class="d">Lagene, én kjøring i åtte steg, repo-kartet, backend-profilene</span></div>
|
||
<div class="card"><span class="n">Del 3 · 14 min</span><span class="t">Elementene</span><span class="d">Kunnskapsbasen, ingest, debatten, validatoren, ekspert-sløyfen, artefaktene</span></div>
|
||
<div class="card"><span class="n">Del 4 · 10 min</span><span class="t">Arbeidsflyten og sløyfene</span><span class="d">Sekunder, minutter, dager, måneder: hvem lukker hva</span></div>
|
||
<div class="card"><span class="n">Del 5 · 8 min</span><span class="t">MAF-harnessen</span><span class="d">Hva MAF er, byggeklossene, hva som er valgt og valgt bort</span></div>
|
||
<div class="card"><span class="n">Del 6 · 5 min</span><span class="t">Kvalitetsmetoden og målt status</span><span class="d">Load-bearing tester, invariantene, hva som er vist og ikke vist</span></div>
|
||
<div class="card"><span class="n">Del 7 · 4 min</span><span class="t">Etter v1.1</span><span class="d">Destinasjonen, arbeidsstrømmene, hva som ikke skal bygges</span></div>
|
||
</div>
|
||
<p class="callout"><b>Det du skal sitte igjen med:</b> helheten (hvorfor systemet er bygget som en portrekke med mennesker i begge ender) <i>og</i> detaljen (hvilken modul, hvilket tak, hvilken fil som krysser hvilken grense). Hver slide har en kildelinje du kan slå opp.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- lesehjelp -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">02</span><span class="part">Lesehjelp</span></p>
|
||
<h2>Tre farger, én betydning hver.</h2>
|
||
<div class="split">
|
||
<div>
|
||
<p class="point">Figurene i dette decket bruker samme visuelle språk hele veien, så du kan lese en ny figur uten å lære den på nytt.</p>
|
||
<ul>
|
||
<li><b>Blått</b> er det som er valgt og i bruk på default-stien.</li>
|
||
<li><b>Rødt</b> er en port som nekter, blokkerer eller stopper.</li>
|
||
<li><b>Grønt</b> er et utfall som passerte, eller et resultat i verden.</li>
|
||
<li><b>Stiplet</b> er opt-in: finnes, men er av inntil noen slår det på.</li>
|
||
<li><b>Grått</b> er ikke i bruk, eller bare kontekst.</li>
|
||
</ul>
|
||
<p class="small">Tall står alltid med nevner. «Ikke verifisert» betyr nettopp det. Kildelinjen nederst peker på fil og linje i repoet.</p>
|
||
</div>
|
||
<figure class="fig narrow">
|
||
<svg viewBox="0 0 560 300" role="img" aria-label="Fargekonvensjoner i figurene">
|
||
<rect class="box accent" x="20" y="20" width="240" height="56"/>
|
||
<text class="lbl" x="36" y="44">Valgt, default-sti</text>
|
||
<text class="sub" x="36" y="64">f.eks. GroupChat-debatten</text>
|
||
<rect class="box warn" x="300" y="20" width="240" height="56"/>
|
||
<text class="lbl" x="316" y="44">Port som nekter</text>
|
||
<text class="sub" x="316" y="64">f.eks. Rejection, BudgetExceeded</text>
|
||
<rect class="box ok" x="20" y="100" width="240" height="56"/>
|
||
<text class="lbl" x="36" y="124">Passert / resultat</text>
|
||
<text class="sub" x="36" y="144">f.eks. ValidatedProposal, ledger</text>
|
||
<rect class="box accent dashed" x="300" y="100" width="240" height="56"/>
|
||
<text class="lbl" x="316" y="124">Opt-in</text>
|
||
<text class="sub" x="316" y="144">f.eks. --explore, --mcp-config</text>
|
||
<rect class="box soft" x="20" y="180" width="240" height="56"/>
|
||
<text class="lbl" x="36" y="204">Ikke i bruk / kontekst</text>
|
||
<text class="sub" x="36" y="224">f.eks. WorkflowBuilder-grafen</text>
|
||
<path class="edge" d="M300 208 L400 208"/>
|
||
<text class="sub" x="410" y="212">dataflyt eller kall</text>
|
||
<path class="edge soft dashed" d="M300 248 L400 248"/>
|
||
<text class="sub" x="410" y="252">valgfri eller senere kobling</text>
|
||
</svg>
|
||
</figure>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== part123a-intro.html ===== -->
|
||
<!-- 1-00 divider-formaalet -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 1 · Formålet</span></p>
|
||
<h1>Formålet</h1>
|
||
<p class="lede">Hva rammeverket faktisk løser, hvem som har hvilken rolle i sløyfen, og hva det med vilje ikke gjør.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 1-01 problemet -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">03</span><span class="part">Del 1 · Formålet</span></p>
|
||
<h2>Problemet er ikke å finne besparelser, men å vurdere dem, prosjekt for prosjekt.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 500" role="img" aria-label="En portefoelje av uavhengige prosjekter til venstre, og kostnadslinjene inni ett av dem til hoeyre">
|
||
<text class="band-lbl" x="40" y="28">Portefølje av uavhengige prosjekter</text>
|
||
<rect class="box dashed" x="40" y="40" width="430" height="360"/>
|
||
|
||
<rect class="box" x="70" y="64" width="370" height="58"/>
|
||
<text class="lbl" x="88" y="90">FV42-GSV-E1</text>
|
||
<text class="sub" x="88" y="110">Fv. 42 gang- og sykkelveg, etappe 1</text>
|
||
|
||
<rect class="box soft" x="70" y="150" width="370" height="58"/>
|
||
<text class="lbl" x="88" y="176">RV13-RAS-TP</text>
|
||
<text class="sub" x="88" y="196">Rv. 13 rassikring tunnelportal</text>
|
||
|
||
<rect class="box soft" x="70" y="236" width="370" height="58"/>
|
||
<text class="lbl" x="88" y="262">BRU-LAKS-REHAB</text>
|
||
<text class="sub" x="88" y="282">Bru over Lakselva, rehabilitering</text>
|
||
|
||
<rect class="box soft" x="70" y="322" width="370" height="58"/>
|
||
<text class="lbl" x="88" y="348">SKOLE-VVS-OPPGR</text>
|
||
<text class="sub" x="88" y="368">Skole, VVS-oppgradering</text>
|
||
|
||
<rect class="box warn dashed" x="40" y="420" width="430" height="60"/>
|
||
<text class="lbl" x="58" y="446">Reallokering MELLOM prosjekter</text>
|
||
<text class="tiny" x="58" y="468">utenfor scope — porteføljestyring ligger over metoden</text>
|
||
|
||
<path class="edge" d="M472 93 H556"/>
|
||
|
||
<rect class="box" x="560" y="40" width="600" height="360"/>
|
||
<text class="lbl" x="580" y="72">FV42-GSV-E1 — kostnadslinjene INNI prosjektet</text>
|
||
<path class="hair" d="M580 86 H1140"/>
|
||
<text class="tiny" x="580" y="106">kode</text>
|
||
<text class="tiny" x="650" y="106">beskrivelse</text>
|
||
<text class="tiny" x="940" y="106">mengde</text>
|
||
<text class="tiny" x="1140" y="106" text-anchor="end">enhetspris</text>
|
||
|
||
<text class="mono" x="580" y="134">01.1</text>
|
||
<text class="mono" x="650" y="134">Rigg og drift</text>
|
||
<text class="mono" x="940" y="134">1 rs</text>
|
||
<text class="mono" x="1140" y="134" text-anchor="end">850 000</text>
|
||
|
||
<text class="mono" x="580" y="164">02.3</text>
|
||
<text class="mono" x="650" y="164">Masseutskifting bløt grunn</text>
|
||
<text class="mono" x="940" y="164">4 200 m3</text>
|
||
<text class="mono" x="1140" y="164" text-anchor="end">420</text>
|
||
|
||
<text class="mono" x="580" y="194">03.1</text>
|
||
<text class="mono" x="650" y="194">Forsterkningslag knust grus</text>
|
||
<text class="mono" x="940" y="194">1 800 m3</text>
|
||
<text class="mono" x="1140" y="194" text-anchor="end">310</text>
|
||
|
||
<text class="mono" x="580" y="224">05.2</text>
|
||
<text class="mono" x="650" y="224">Asfalt Ab11</text>
|
||
<text class="mono" x="940" y="224">4 300 m2</text>
|
||
<text class="mono" x="1140" y="224" text-anchor="end">215</text>
|
||
|
||
<text class="mono" x="580" y="254">07.4</text>
|
||
<text class="mono" x="650" y="254">Kantstein granitt</text>
|
||
<text class="mono" x="940" y="254">2 400 m</text>
|
||
<text class="mono" x="1140" y="254" text-anchor="end">690</text>
|
||
|
||
<text class="mono" x="580" y="284">09.1</text>
|
||
<text class="mono" x="650" y="284">Veglysmaster LED</text>
|
||
<text class="mono" x="940" y="284">34 stk</text>
|
||
<text class="mono" x="1140" y="284" text-anchor="end">28 500</text>
|
||
|
||
<path class="hair" d="M580 302 H1140"/>
|
||
<text class="lbl" x="580" y="328">Σ 6 721 500 NOK over 6 linjer</text>
|
||
<text class="tiny" x="580" y="354">Et tiltak foreslås MOT disse linjene, og må navngi kodene sine her.</text>
|
||
<text class="tiny" x="580" y="378">Syntetisk referanseprosjekt: AI-forfattede plassholdere, ikke ekte estimater.</text>
|
||
</svg>
|
||
<figcaption>Besparelsen bor inni prosjektet. Rammeverket leter etter tiltak mot kostnadslinjene i ett prosjekt om gangen, og flytter aldri budsjett mellom prosjekter.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>README.md:9-13</code> · <code>README.md:265-279</code> · <code>src/portfolio_optimiser/data/reference_projects.json</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 1-02 tre-roller -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">04</span><span class="part">Del 1 · Formålet</span></p>
|
||
<h2>Tre roller: to språkmodeller som kan diskutere, og en beregning som ikke lar seg overtale.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 520" role="img" aria-label="Fagekspert bestiller, proposer og checker debatterer, en deterministisk validator avgjoer, og eksperten doemmer utfallet">
|
||
<rect class="box soft" x="40" y="180" width="180" height="110"/>
|
||
<text class="lbl" x="58" y="214">Fagekspert</text>
|
||
<text class="sub" x="58" y="238">bestiller med et</text>
|
||
<text class="sub" x="58" y="256">mandat</text>
|
||
<text class="tiny" x="58" y="278">ett prosjekt + retninger</text>
|
||
|
||
<path class="edge" d="M222 235 H274"/>
|
||
|
||
<text class="band-lbl" x="280" y="80">Debatt</text>
|
||
<rect class="box dashed" x="278" y="90" width="362" height="290"/>
|
||
|
||
<rect class="box accent" x="304" y="120" width="310" height="92"/>
|
||
<text class="lbl" x="322" y="152">proposer</text>
|
||
<text class="sub" x="322" y="176">foreslår ETT typet</text>
|
||
<text class="sub" x="322" y="196">kandidat-tiltak</text>
|
||
|
||
<path class="edge accent" d="M420 214 V254"/>
|
||
<path class="edge accent" d="M500 254 V214"/>
|
||
|
||
<rect class="box accent" x="304" y="256" width="310" height="92"/>
|
||
<text class="lbl" x="322" y="288">checker</text>
|
||
<text class="sub" x="322" y="312">angriper resonnementet</text>
|
||
<text class="sub" x="322" y="332">og avslutter med en dom</text>
|
||
|
||
<path class="edge" d="M644 235 H694"/>
|
||
|
||
<rect class="box warn" x="698" y="150" width="302" height="170"/>
|
||
<text class="lbl" x="716" y="184">Deterministisk validator</text>
|
||
<text class="sub" x="716" y="212">solver + Monte Carlo</text>
|
||
<text class="sub" x="716" y="234">obligatorisk og blokkerende</text>
|
||
<text class="sub" x="716" y="256">aldri en valgfri plugin</text>
|
||
<text class="tiny" x="716" y="290">Den avgjør TALLENE. Den kan bare blokkere.</text>
|
||
|
||
<path class="edge" d="M1004 182 H1034"/>
|
||
<path class="edge warn" d="M1004 236 H1034"/>
|
||
<path class="edge soft" d="M1004 290 H1034"/>
|
||
|
||
<rect class="box ok" x="1038" y="160" width="140" height="44"/>
|
||
<text class="lbl" x="1054" y="188">validated</text>
|
||
<rect class="box warn" x="1038" y="214" width="140" height="44"/>
|
||
<text class="lbl" x="1054" y="242">rejected</text>
|
||
<rect class="box soft" x="1038" y="268" width="140" height="44"/>
|
||
<text class="lbl" x="1054" y="296">unsupported</text>
|
||
|
||
<path class="edge" d="M1108 314 V438 H1006"/>
|
||
|
||
<rect class="box soft" x="698" y="400" width="302" height="80"/>
|
||
<text class="lbl" x="716" y="432">Fagekspert</text>
|
||
<text class="sub" x="716" y="458">dømmer utfallet, dager senere</text>
|
||
|
||
<path class="edge accent dashed" d="M696 440 H130 V294"/>
|
||
<text class="tiny" x="300" y="466">læringssløyfen — den lukkes først i neste kjøring (Del 4)</text>
|
||
</svg>
|
||
<figcaption>Samme fagperson står i begge ender: én bestiller kjøringen med et mandat, én dømmer utfallet etterpå. Imellom ligger én beregning som ikke lar seg overtale.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/workflow.py:26-45</code> · <code>src/portfolio_optimiser/validator.py:648-748</code> · <code>shared/method-spec.md:54</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 1-03 non-goals -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">05</span><span class="part">Del 1 · Formålet</span></p>
|
||
<h2>Fem ting rammeverket med vilje ikke er.</h2>
|
||
<p class="lede">Non-goals er ikke mangler. De er grenser noen har bestemt, og de forklarer hvorfor kjernen er så liten.</p>
|
||
<table>
|
||
<thead><tr><th>Det er ikke</th><th>Det er</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Et compliance-produkt</td><td>Tekniske forutsetninger: lokal drift, provenance på hvert forslag, ingen stille egress. Behandlingsformål, DPIA og ROS eies av den som tar det i bruk.</td></tr>
|
||
<tr><td>En porteføljereallokator</td><td>Besparelser inni hvert prosjekt. Å flytte budsjett mellom prosjekter, og å rangere prosjekter mot hverandre, ligger over metoden.</td></tr>
|
||
<tr><td>Autonom beslutningstaking</td><td>Validatoren kan bare blokkere. Å godkjenne et tiltak er fagekspertens valg, og rammeverket iverksetter ingenting på agentenes ord.</td></tr>
|
||
<tr><td>En nøkkelferdig vertikal</td><td>Generisk kjerne med navngitte extension points — datakilder, kostnadsmodeller, personaer. De siste 10 % av et domene er deployerens.</td></tr>
|
||
<tr><td>En modell-benchmark</td><td>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.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="callout"><b>Status, uten pynt.</b> É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 <code>rejected</code>. Ingen kjøring har ennå gitt et <i>validert</i> forslag mot en live modell, og ingen ekte ekspertdom har kommet inn i treet ennå.</p>
|
||
<p class="src">Kilde: <code>README.md:265-303</code> · <code>shared/method-spec.md:26-33</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 1-04 designfilosofi -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">06</span><span class="part">Del 1 · Formålet</span></p>
|
||
<h2>Designfilosofien: generisk kjerne, tydelige sømmer, mennesker på toppen.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 420" role="img" aria-label="Kontrast mellom en tradisjonell wiki skrevet for mennesker og en wiki skrevet for modellen med menneske-affordanser lagt paa toppen">
|
||
<text class="band-lbl" x="60" y="34">Tradisjonell wiki</text>
|
||
<rect class="box soft" x="60" y="46" width="470" height="330"/>
|
||
<rect class="box" x="86" y="76" width="418" height="76"/>
|
||
<text class="lbl" x="106" y="106">Skrevet for mennesker</text>
|
||
<text class="sub" x="106" y="132">prosa, kapitler, navigasjon for øyet</text>
|
||
<rect class="box" x="86" y="176" width="418" height="76"/>
|
||
<text class="lbl" x="106" y="206">Søk og lesing for mennesker</text>
|
||
<text class="sub" x="106" y="232">indeksert for den som browser</text>
|
||
<rect class="box dashed" x="86" y="276" width="418" height="76"/>
|
||
<text class="lbl" x="106" y="306">Maskintilgang skrudd på etterpå</text>
|
||
<text class="sub" x="106" y="332">et API over noe som ikke var ment for det</text>
|
||
|
||
<path class="edge" d="M548 211 H648"/>
|
||
|
||
<text class="band-lbl" x="670" y="34">Denne</text>
|
||
<rect class="box" x="670" y="46" width="470" height="330"/>
|
||
<rect class="box soft" x="696" y="76" width="418" height="76"/>
|
||
<text class="lbl" x="716" y="106">Menneske-affordanser som LAG PÅ TOPPEN</text>
|
||
<text class="sub" x="716" y="132">inbox-fil, promotion gate, rapporter</text>
|
||
<rect class="box accent" x="696" y="176" width="418" height="76"/>
|
||
<text class="lbl" x="716" y="206">Wikien er skrevet FOR modellen</text>
|
||
<text class="sub" x="716" y="232">agentens arbeidsminne og læringssubstrat</text>
|
||
<rect class="box ok" x="696" y="276" width="418" height="76"/>
|
||
<text class="lbl" x="716" y="306">Ingenting inn uten en godkjenning</text>
|
||
<text class="sub" x="716" y="332">fail-closed promotion gate</text>
|
||
</svg>
|
||
<figcaption>Rekkefølgen er snudd: den primære leseren av hver fil er modellen, ikke en person som browser. Menneskene er fortsatt avgjørende — de er bare et lag over, ikke under.</figcaption>
|
||
</figure>
|
||
<div class="cols">
|
||
<div class="col"><span class="step">90 %-prinsippet</span><p>Bygg den generiske kjernen og navngi sømmene. De siste 10 % av et domene er deployerens.</p></div>
|
||
<div class="col"><span class="step">Fork-and-own</span><p>Én vedlikeholder, ingen SLA, MIT. Issues er signaler; pull requests tas ikke imot.</p></div>
|
||
<div class="col"><span class="step">Rent teknisk rammeverk</span><p>Behandlingsformål, DPIA og ROS eier den som tar det i bruk. Vi bygger ikke compliance-funksjoner.</p></div>
|
||
</div>
|
||
<p class="src">Kilde: <code>README.md:14-19</code> · <code>README.md:335-349</code> · <code>docs/extending.md:294-321</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-00 divider-arkitekturen -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h1>Arkitekturen overordnet</h1>
|
||
<p class="lede">Lagene, de åtte stegene, kartet over koden, den delte kjernen, de to backend-profilene og de fire kjøremodusene.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-01 fem-lag -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">07</span><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h2>Fem lag, og porten sitter mellom agentene og alt som blir varig.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 590" role="img" aria-label="Fem lag stablet: kunnskap, agenter, deterministisk validator, HITL og laering, med en returpil tilbake til kunnskapslaget">
|
||
<rect class="box accent" x="120" y="40" width="560" height="80"/>
|
||
<text class="lbl" x="140" y="74">1 · Kunnskap — OKF-bundle («LLM-wiki»)</text>
|
||
<text class="sub" x="140" y="100">markdown + YAML-frontmatter, index.md, kryss-lenker</text>
|
||
<text class="sub" x="706" y="86">Det eneste laget som er varig.</text>
|
||
<path class="edge" d="M400 122 V146"/>
|
||
|
||
<rect class="box" x="120" y="150" width="560" height="80"/>
|
||
<text class="lbl" x="140" y="184">2 · Agenter — maker–checker i en GroupChat</text>
|
||
<text class="sub" x="140" y="210">proposer foreslår, checker angriper, hardt rundetak</text>
|
||
<text class="sub" x="706" y="196">Skriver ingenting selv.</text>
|
||
<path class="edge" d="M400 232 V256"/>
|
||
|
||
<rect class="box warn" x="120" y="260" width="560" height="80"/>
|
||
<text class="lbl" x="140" y="294">3 · Deterministisk validator</text>
|
||
<text class="sub" x="140" y="320">solver + Monte Carlo, obligatorisk og blokkerende</text>
|
||
<text class="lbl" x="706" y="294">Port 1 · tallene</text>
|
||
<text class="sub" x="706" y="318">kan bare blokkere, aldri godkjenne</text>
|
||
<path class="edge" d="M400 342 V366"/>
|
||
|
||
<rect class="box" x="120" y="370" width="560" height="80"/>
|
||
<text class="lbl" x="140" y="404">4 · HITL — en inbox-mappe</text>
|
||
<text class="sub" x="140" y="430">eksperten skriver en JSON-fil, systemet leser mappa</text>
|
||
<text class="sub" x="706" y="416">Dager eller uker senere. Ingen levende sesjon.</text>
|
||
<path class="edge" d="M400 452 V476"/>
|
||
|
||
<rect class="box ok" x="120" y="480" width="560" height="80"/>
|
||
<text class="lbl" x="140" y="514">5 · Læring — promotion gate</text>
|
||
<text class="sub" x="140" y="540">en godkjent dom løftes inn i wikien som en konseptfil</text>
|
||
<text class="lbl" x="706" y="514">Port 2 · hva som blir varig</text>
|
||
<text class="sub" x="706" y="538">fail-closed — bare godkjent kunnskap krysser</text>
|
||
|
||
<path class="edge accent" d="M118 520 H60 V80 H116"/>
|
||
<text class="tiny" x="44" y="300" transform="rotate(-90 44 300)" text-anchor="middle">lukkes i NESTE kjøring</text>
|
||
</svg>
|
||
<figcaption>Inndelingen i fem lag er framstillerens lesning. Spesifikasjonen selv navngir tre: context layer, output layer og promotion gate — og sier at separasjonen mellom dem er load-bearing.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>shared/method-spec.md:36-50</code> · <code>src/portfolio_optimiser/verdicts.py:699-773</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-02 atte-steg -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">08</span><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h2>Én kjøring, åtte steg, og sløyfen lukkes først i neste kjøring.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 480" role="img" aria-label="Seks steg paa rad inni en kjoering, og steg 7 og 8 under, med en bue tilbake til steg 1 i neste kjoering">
|
||
<text class="band-lbl" x="30" y="58">Inni én kjøring — steg 1 til 6</text>
|
||
<rect class="box" x="30" y="90" width="175" height="110"/>
|
||
<text class="lbl" x="46" y="120">1 · Understand</text>
|
||
<text class="sub" x="46" y="146">naviger bundlen,</text>
|
||
<text class="sub" x="46" y="166">fold inn tidligere</text>
|
||
<text class="sub" x="46" y="186">ekspertdommer</text>
|
||
<path class="edge" d="M207 145 H224"/>
|
||
|
||
<rect class="box" x="226" y="90" width="175" height="110"/>
|
||
<text class="lbl" x="242" y="120">2 · Hypothesise</text>
|
||
<text class="sub" x="242" y="146">ett typet kandidat-</text>
|
||
<text class="sub" x="242" y="166">tiltak, streng IR</text>
|
||
<path class="edge" d="M403 145 H420"/>
|
||
|
||
<rect class="box accent" x="422" y="90" width="175" height="110"/>
|
||
<text class="lbl" x="438" y="120">3 · Debate</text>
|
||
<text class="sub" x="438" y="146">maker–checker,</text>
|
||
<text class="sub" x="438" y="166">hardt rundetak</text>
|
||
<path class="edge" d="M599 145 H616"/>
|
||
|
||
<rect class="box warn" x="618" y="90" width="175" height="110"/>
|
||
<text class="lbl" x="634" y="120">4 · Validate</text>
|
||
<text class="sub" x="634" y="146">to falsifiserere:</text>
|
||
<text class="sub" x="634" y="166">tallene og</text>
|
||
<text class="sub" x="634" y="186">resonnementet</text>
|
||
<path class="edge" d="M795 145 H812"/>
|
||
|
||
<rect class="box" x="814" y="90" width="175" height="110"/>
|
||
<text class="lbl" x="830" y="120">5 · Refine</text>
|
||
<text class="sub" x="830" y="146">nytt forsøk informert</text>
|
||
<text class="sub" x="830" y="166">av nektgrunnen</text>
|
||
<path class="edge" d="M991 145 H1008"/>
|
||
|
||
<rect class="box" x="1010" y="90" width="175" height="110"/>
|
||
<text class="lbl" x="1026" y="120">6 · Propose</text>
|
||
<text class="sub" x="1026" y="146">validert forslag</text>
|
||
<text class="sub" x="1026" y="166">eller typet nekt</text>
|
||
|
||
<path class="edge" d="M1097 202 V286 H993"/>
|
||
|
||
<text class="band-lbl" x="618" y="312">På tvers av kjøringer, adskilt i tid — steg 7 og 8</text>
|
||
<rect class="box" x="814" y="330" width="175" height="110"/>
|
||
<text class="lbl" x="830" y="360">7 · Feedback</text>
|
||
<text class="sub" x="830" y="386">dager senere: en</text>
|
||
<text class="sub" x="830" y="406">JSON-fil i en mappe</text>
|
||
<path class="edge" d="M812 385 H797"/>
|
||
|
||
<rect class="box ok" x="618" y="330" width="175" height="110"/>
|
||
<text class="lbl" x="634" y="360">8 · Promote</text>
|
||
<text class="sub" x="634" y="386">godkjent dom løftes</text>
|
||
<text class="sub" x="634" y="406">inn i wikien</text>
|
||
|
||
<path class="edge accent" d="M614 385 H100 V206"/>
|
||
<text class="tiny" x="132" y="410">neste kjøring leser den nye konseptfila</text>
|
||
</svg>
|
||
<figcaption>Steg 1 til 6 skjer inni én kjøring. Steg 7 og 8 er en annen tidsskala helt: eksperten svarer dager senere, og en senere kjøring plukker det opp. Tilstandsmaskinen med vaktene tas i Del 4.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>README.md:351-376</code> · <code>shared/method-spec.md:56-58</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-03 repo-kart -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">09</span><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h2>Repo-kartet har seks lag, men bare én av grensene er håndhevet av koden.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 600" role="img" aria-label="Seks lag av moduler stablet, med MAF-importerende moduler markert i blaatt i hvert lag">
|
||
<text class="tiny" x="1170" y="24" text-anchor="end">Blå = importerer agent_framework · 13 av 39 moduler</text>
|
||
|
||
<rect class="band" x="30" y="36" width="1140" height="84"/>
|
||
<text class="lbl" x="48" y="70">Kjøreflater og ops</text>
|
||
<text class="tiny" x="48" y="94">7 moduler</text>
|
||
<rect class="box accent" x="250" y="58" width="180" height="30"/>
|
||
<text class="mono" x="262" y="79">run simulation</text>
|
||
<text class="mono" x="446" y="79">hosting preflight hitl costsim evals/v1_gate</text>
|
||
|
||
<rect class="band" x="30" y="130" width="1140" height="84"/>
|
||
<text class="lbl" x="48" y="164">Orkestrering</text>
|
||
<text class="tiny" x="48" y="188">7 moduler, alle MAF-bundne</text>
|
||
<rect class="box accent" x="250" y="152" width="620" height="30"/>
|
||
<text class="mono" x="262" y="173">workflow explore generate budget mcp_tools tracing backends</text>
|
||
|
||
<rect class="band" x="30" y="224" width="1140" height="84"/>
|
||
<text class="lbl" x="48" y="258">Validering</text>
|
||
<text class="tiny" x="48" y="282">2 moduler</text>
|
||
<text class="mono" x="250" y="267">validator stress</text>
|
||
<text class="sub" x="446" y="267">Porten som avgjør verdien har ingen MAF-import i det hele tatt.</text>
|
||
|
||
<rect class="band" x="30" y="318" width="1140" height="84"/>
|
||
<text class="lbl" x="48" y="352">Læring og HITL</text>
|
||
<text class="tiny" x="48" y="376">7 moduler</text>
|
||
<rect class="box accent" x="250" y="340" width="110" height="30"/>
|
||
<text class="mono" x="262" y="361">verdicts</text>
|
||
<text class="mono" x="376" y="361">proposal_review outbox notify persona ledger value_report</text>
|
||
|
||
<rect class="band" x="30" y="412" width="1140" height="84"/>
|
||
<text class="lbl" x="48" y="446">Kunnskap og ingest</text>
|
||
<text class="tiny" x="48" y="470">10 moduler</text>
|
||
<rect class="box accent" x="250" y="428" width="180" height="30"/>
|
||
<text class="mono" x="262" y="449">datasource tools</text>
|
||
<text class="mono" x="446" y="449">okf retrieval semretrieval prepass frozen_bundles</text>
|
||
<text class="mono" x="446" y="482">ingest ingest_mcp shared_root</text>
|
||
|
||
<rect class="band" x="30" y="506" width="1140" height="84"/>
|
||
<text class="lbl" x="48" y="540">Kontrakter og IR</text>
|
||
<text class="tiny" x="48" y="564">6 moduler</text>
|
||
<rect class="box accent" x="250" y="522" width="130" height="30"/>
|
||
<text class="mono" x="262" y="543">provenance</text>
|
||
<text class="mono" x="396" y="543">ir dimension contracts mandate reference_domain</text>
|
||
</svg>
|
||
<figcaption>Målt 18.09.2026: 41 <code>.py</code>-filer og 22 019 linjer under <code>src/</code>. To av filene er <code>__init__.py</code>, så 39 er moduler, og 13 av dem importerer <code>agent_framework</code>. Lagdelingen er framstillerens lesning; modulene ligger flatt, og bare <code>evals/</code> er en pakke.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Den ene grensen koden håndhever.</b> <code>tests/test_okf.py</code> holder en liste, <code>_MAF_FREE_MODULES</code>, med ni moduler — <code>okf</code>, <code>dimension</code>, <code>mandate</code>, <code>outbox</code>, <code>costsim</code>, <code>hitl</code>, <code>notify</code>, <code>semretrieval</code>, <code>proposal_review</code> — og en AST-sjekk går rødt hvis noen av dem importerer <code>agent_framework</code> eller <code>mcp</code>. AST, ikke tekstsøk, så en docstring som <i>omtaler</i> rammeverket ikke utløser den. <code>ingest</code> og <code>ingest_mcp</code> har egne vakter, og <code>hitl</code> og <code>notify</code> har i tillegg en <i>transitiv</i> importgraf-vakt. Det er dette som lar en søsken-implementasjon på Claude Agent SDK gjenbruke lagene nederst uendret.</p>
|
||
<p class="src">Kilde: <code>tests/test_okf.py:22-32</code> · <code>tests/test_okf.py:476-500</code> · <code>tests/test_hitl_loadbearing.py:273</code> · <code>find src -name "*.py" | xargs wc -l</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-04 delt-kjerne -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">10</span><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h2>Den delte kjernen er en git subtree, og begge stackene implementerer fra spec-en alene.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 520" role="img" aria-label="Commons-repoet til venstre med spesifikasjoner og fasit, med git subtree pull til to implementasjoner til hoeyre">
|
||
<rect class="box" x="40" y="70" width="420" height="340"/>
|
||
<text class="lbl" x="62" y="104">portfolio-optimiser-commons</text>
|
||
<text class="sub" x="62" y="128">source of truth — ingen kjørbar kode</text>
|
||
<path class="hair" d="M62 144 H438"/>
|
||
<text class="mono" x="62" y="176">method-spec.md 8-stegs-sløyfa</text>
|
||
<text class="mono" x="62" y="204">ingest-spec.md manifest + gate</text>
|
||
<text class="mono" x="62" y="232">CONCEPT.md forretningskonseptet</text>
|
||
<text class="mono" x="62" y="260">examples/ 3 bundles + fasit</text>
|
||
<text class="mono" x="62" y="288">skills/ expert-reviewer</text>
|
||
<text class="sub" x="62" y="326">Fasit-suiten er den ENESTE ground truth.</text>
|
||
<text class="tiny" x="62" y="356">Personaen ligger som en framework-nøytral Agent Skill</text>
|
||
<text class="tiny" x="62" y="376">(SKILL.md etter agentskills.io-mønsteret), og hver stack</text>
|
||
<text class="tiny" x="62" y="396">leser den samme JSON-en med sin egen loader.</text>
|
||
|
||
<path class="edge noarrow" d="M462 240 H580"/>
|
||
<text class="mono" x="470" y="228">git subtree pull --squash</text>
|
||
<path class="edge" d="M580 240 V190 H694"/>
|
||
<path class="edge" d="M580 240 V330 H694"/>
|
||
|
||
<rect class="box accent" x="698" y="130" width="462" height="120"/>
|
||
<text class="lbl" x="718" y="164">portfolio-optimiser (MAF)</text>
|
||
<text class="sub" x="718" y="190">shared/ som pull-only subtree</text>
|
||
<text class="tiny" x="718" y="216">Wheelen bærer treet som pakket data under</text>
|
||
<text class="tiny" x="718" y="236">portfolio_optimiser/_shared/, så en installert dist virker uten checkout.</text>
|
||
|
||
<rect class="box dashed" x="698" y="270" width="462" height="120"/>
|
||
<text class="lbl" x="718" y="304">portfolio-optimiser-claude (Claude Agent SDK)</text>
|
||
<text class="sub" x="718" y="330">samme bundles, samme fasit</text>
|
||
<text class="tiny" x="718" y="356">Bygget fra spesifikasjonen alene, uten å reversere referansekoden.</text>
|
||
<text class="tiny" x="718" y="376">PARKERT — ikke utviklet parallelt.</text>
|
||
|
||
<rect class="box warn" x="698" y="410" width="462" height="82"/>
|
||
<text class="lbl" x="718" y="440">ALDRI git subtree push fra en konsument</text>
|
||
<text class="tiny" x="718" y="464">Målt 03.07.2026: re-splitten lekket HELE konsumentens historikk</text>
|
||
<text class="tiny" x="718" y="484">inn i commons. Synk er pull-only, og alle endringer lander der først.</text>
|
||
</svg>
|
||
<figcaption>Oppslaget av <code>shared/</code> skjer ved kall: <code>PORTFOLIO_SHARED_ROOT</code> først, så arbeidstreets <code>shared/</code> når den finnes, ellers den pakkede kopien i distribusjonen.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>shared/README.md</code> · <code>src/portfolio_optimiser/shared_root.py:20-38</code> · <code>pyproject.toml:111-112</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-05 backend-profiler -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">11</span><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h2>To backend-profiler: local på loopback uten egress, azure mot Foundry.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 460" role="img" aria-label="Dataflyt fra profil og rolle gjennom modell-oppslaget til backend-valget og de to konkrete chat-klientene">
|
||
<rect class="box" x="30" y="140" width="190" height="120"/>
|
||
<text class="lbl" x="48" y="172">profil + rolle</text>
|
||
<text class="sub" x="48" y="198">local | azure</text>
|
||
<text class="tiny" x="48" y="224">proposer · checker</text>
|
||
<path class="edge" d="M222 200 H262"/>
|
||
|
||
<rect class="box" x="266" y="118" width="260" height="164"/>
|
||
<text class="lbl" x="284" y="150">resolve_model()</text>
|
||
<text class="tiny" x="284" y="176">1 · ukjent profil → ValueError</text>
|
||
<text class="tiny" x="284" y="198">2 · map[profil][rolle]</text>
|
||
<text class="tiny" x="284" y="220">3 · ellers map[profil][default]</text>
|
||
<text class="tiny" x="284" y="242">4 · REPLACE-WITH-* → ValueError</text>
|
||
<text class="tiny" x="284" y="268">PORTFOLIO_MODEL_MAP slår den pakkede</text>
|
||
<path class="edge" d="M528 200 H568"/>
|
||
|
||
<rect class="box" x="572" y="140" width="230" height="120"/>
|
||
<text class="lbl" x="590" y="172">get_backend(profile)</text>
|
||
<text class="sub" x="590" y="198">ChatBackend-protokoll</text>
|
||
<text class="tiny" x="590" y="224">returnerer én av to</text>
|
||
|
||
<path class="edge noarrow" d="M804 200 H834"/>
|
||
<path class="edge" d="M834 200 V110 H846"/>
|
||
<path class="edge" d="M834 200 V300 H846"/>
|
||
|
||
<rect class="box accent" x="850" y="52" width="320" height="116"/>
|
||
<text class="lbl" x="868" y="84">LocalBackend — utviklingsdefault</text>
|
||
<text class="mono" x="868" y="110">OpenAIChatCompletionClient</text>
|
||
<text class="tiny" x="868" y="134">127.0.0.1:11434/v1 — loopback, aldri en fjernvert</text>
|
||
<text class="tiny" x="868" y="156">Chat Completions, ikke Responses: usage uten None</text>
|
||
|
||
<rect class="box accent" x="850" y="240" width="320" height="130"/>
|
||
<text class="lbl" x="868" y="272">AzureFoundryBackend</text>
|
||
<text class="mono" x="868" y="298">FoundryChatClient</text>
|
||
<text class="tiny" x="868" y="322">credential er PÅKREVD — ingen lazy default</text>
|
||
<text class="tiny" x="868" y="342">AzureCliCredential på en utviklermaskin</text>
|
||
<text class="tiny" x="868" y="362">ManagedIdentityCredential i hostet container</text>
|
||
|
||
<rect class="box soft" x="30" y="310" width="790" height="130"/>
|
||
<text class="lbl" x="48" y="342">Det som faktisk ligger i data/model_map.json</text>
|
||
<text class="mono" x="48" y="374">local: default / proposer / checker = qwen3:4b</text>
|
||
<text class="mono" x="48" y="398">azure: default / proposer / checker = REPLACE-WITH-FOUNDRY-DEPLOYMENT</text>
|
||
<text class="tiny" x="48" y="426">Azure-profilen feiler altså fail-fast ut av boksen, helt til operatøren bytter dem ut.</text>
|
||
</svg>
|
||
<figcaption>Endepunktet leses ved kall, og vårt eget navn vinner: <code>PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT</code> først, så det plattform-injiserte <code>FOUNDRY_PROJECT_ENDPOINT</code>. Presedensen gjelder verdier, ikke erklæringer, så et eksportert-men-tomt navn faller gjennom i stedet for å skygge for et ekte.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Kostnadsdisiplin.</b> Utvikling skjer på <code>local</code>, som er gratis. Foundry brukes bare til målrettet, minimal verifisering. Credential-figuren og hele leverandørsømmen tas i Del 5.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/backends.py:87-91</code> · <code>backends.py:105-122</code> · <code>backends.py:125-172</code> · <code>src/portfolio_optimiser/data/model_map.json</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2-06 fire-moduser -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">12</span><span class="part">Del 2 · Arkitekturen overordnet</span></p>
|
||
<h2>Kjørestien har fire moduser, og de er en dokumentert partisjon.</h2>
|
||
<p class="lede">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.</p>
|
||
<table class="compact">
|
||
<thead><tr><th>Modus</th><th>Påkrevd</th><th>Hva den gjør</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Enkeltprosjekt</td><td><code>PROJECT_ID --docs-dir</code></td><td>Én kjøring mot ett prosjekt. Valgfritt <code>--bundle-dir</code>, <code>--verdict-dir</code>, <code>--outbox-dir</code> (krever <code>--run-id</code>), <code>--explore</code>, <code>--proposal-review</code>, <code>--scripted-replies</code>, <code>--live-dry-run</code>.</td></tr>
|
||
<tr><td>Multi-base</td><td><code>--across-bundle</code> gjentatt, <code>--mandate</code>, <code>--run-id</code>, <code>--outbox-dir</code></td><td>Én bestilling, flere kunnskapsbaser, sekvensielt. Én verdict-store tres gjennom alle, så en dom mot base <i>k</i> når base <i>k+1</i>.</td></tr>
|
||
<tr><td>Portefølje</td><td><code>--portfolio</code></td><td>Referanseprosjektene etter hverandre. Valgfritt <code>--goals</code> og <code>--ledger</code>; stopper tidlig når målet er nådd.</td></tr>
|
||
<tr><td>Verdirapport</td><td><code>--report --ledger</code></td><td>Leser bare. Null modellkall. Ruller opp realiserte besparelser per prosjekt, med provenance per post.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="callout warn"><b>Nektet, aldri stilltiende ignorert.</b> <code>--live-dry-run</code> og <code>--scripted-replies</code> er begge offline-moduser og nektes sammen. <code>--json</code> uten <code>--report</code> nektes. <code>--report</code> tåler bare <code>--ledger</code> og <code>--json</code> ved siden av seg. <code>--across-bundle</code> nekter <code>--bundle-dir</code>, <code>--portfolio</code>, <code>--explore</code> og <code>--prepass-payload</code>, fordi hver av dem løser opp én base.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/run.py:2826-3145</code> (37 <code>add_argument</code>, hvorav én er posisjonsargumentet <code>project_id</code>) · <code>run.py:3185</code> · <code>run.py:3265-3271</code> · <code>run.py:3434</code> · <code>run.py:4051</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3-00 divider-elementene -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 3 · Elementene</span></p>
|
||
<h1>Elementene i arkitekturen</h1>
|
||
<p class="lede">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.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3a-01 llm-wiki -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">13</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Kunnskapsbasen er en LLM-wiki (Karpathys idé) i OKF-format (Googles spec).</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 510" role="img" aria-label="En bundle-graf med index.md oeverst, tre konseptfiler under, og en verdict-fil markert som skjermet lag">
|
||
<rect class="box accent" x="430" y="30" width="240" height="70"/>
|
||
<text class="lbl" x="452" y="62">index.md</text>
|
||
<text class="tiny" x="452" y="86">reservert inngangspunkt</text>
|
||
|
||
<path class="edge noarrow" d="M550 102 H550 V150"/>
|
||
<path class="edge noarrow" d="M160 150 H940"/>
|
||
<path class="edge" d="M160 150 V186"/>
|
||
<path class="edge" d="M420 150 V186"/>
|
||
<path class="edge" d="M680 150 V186"/>
|
||
<path class="edge" d="M940 150 V186"/>
|
||
|
||
<rect class="box" x="60" y="190" width="200" height="80"/>
|
||
<text class="lbl" x="78" y="220">tiltak-led.md</text>
|
||
<text class="tiny" x="78" y="244">type: measure</text>
|
||
|
||
<rect class="box" x="320" y="190" width="200" height="80"/>
|
||
<text class="lbl" x="338" y="220">metode-mv.md</text>
|
||
<text class="tiny" x="338" y="244">type: methodology</text>
|
||
|
||
<rect class="box" x="580" y="190" width="200" height="80"/>
|
||
<text class="lbl" x="598" y="220">grunnlag.md</text>
|
||
<text class="tiny" x="598" y="244">type: evidence</text>
|
||
|
||
<rect class="box warn dashed" x="840" y="190" width="200" height="80"/>
|
||
<text class="lbl" x="858" y="220">dom-2026-03.md</text>
|
||
<text class="tiny" x="858" y="244">type: verdict</text>
|
||
|
||
<path class="edge accent" d="M262 232 H316"/>
|
||
<path class="edge accent" d="M522 252 H576"/>
|
||
<text class="tiny" x="268" y="222">kryss-lenke</text>
|
||
|
||
<rect class="box soft" x="60" y="300" width="380" height="190"/>
|
||
<text class="mono" x="80" y="332">---</text>
|
||
<text class="mono" x="80" y="354">type: measure</text>
|
||
<text class="mono" x="80" y="376">title: LED-retrofit 2026</text>
|
||
<text class="mono" x="80" y="398">ingest_manifest: kilder.json</text>
|
||
<text class="mono" x="80" y="420">---</text>
|
||
<text class="sub" x="80" y="452">type er det ENESTE påkrevde feltet.</text>
|
||
<text class="sub" x="80" y="474">Egendefinerte felt BEVARES.</text>
|
||
|
||
<rect class="box warn" x="620" y="300" width="440" height="130"/>
|
||
<text class="lbl" x="640" y="332">Verdict-laget er skjermet</text>
|
||
<text class="tiny" x="640" y="358">Ekskluderingen er en TYPE-SJEKK på hver fil idet den nås,</text>
|
||
<text class="tiny" x="640" y="378">på hvert nivå — aldri en egenskap ved lenkegrafen.</text>
|
||
<text class="tiny" x="640" y="402">Tidligere dommer når hypotesen bare gjennom den portede</text>
|
||
<text class="tiny" x="640" y="422">ExpeL-folden, aldri ved å bli lest som bundle-kunnskap.</text>
|
||
</svg>
|
||
<figcaption>Det er nettopp fordi egendefinerte felt må bevares at prosjektets egne lag — ekspertdommer og ingest-provenance — kan bo i frontmatteren uten å bryte formatet.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Hvorfor et åpent format.</b> OKF er leverandørnøytralt, så de <i>samme</i> bundlene konsumeres uendret av begge referanseimplementasjonene. Kunnskapen overlever den enkelte agent-stacken.</p>
|
||
<p class="src">Kilde: <code>README.md:305-333</code> · <code>shared/method-spec.md:38-44</code> · <code>src/portfolio_optimiser/okf.py:44-50</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3a-02 navigasjon-ikke-rag -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">14</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Navigasjon, ikke RAG: index først, lenker deretter, og verdict-laget er skjermet i verktøyet.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 410" role="img" aria-label="Fire navigasjonsverktoey som en trapp, og de fire portene paa read_file til hoeyre">
|
||
<rect class="box" x="30" y="30" width="340" height="70"/>
|
||
<text class="mono" x="50" y="60">list_bundles()</text>
|
||
<text class="tiny" x="50" y="84">hvilke baser finnes — O(baser), aldri O(korpus)</text>
|
||
<path class="edge" d="M200 102 V116"/>
|
||
|
||
<rect class="box" x="120" y="120" width="340" height="70"/>
|
||
<text class="mono" x="140" y="150">read_bundle(bundle_id)</text>
|
||
<text class="tiny" x="140" y="174">åpne ÉN base og list toppnivået</text>
|
||
<path class="edge" d="M290 192 V206"/>
|
||
|
||
<rect class="box" x="210" y="210" width="340" height="70"/>
|
||
<text class="mono" x="230" y="240">read_dir(bundle_id, path, …)</text>
|
||
<text class="tiny" x="230" y="264">én katalog, paginert: 10 av gangen, maks 50</text>
|
||
<path class="edge" d="M380 282 V296"/>
|
||
|
||
<rect class="box accent" x="300" y="300" width="340" height="70"/>
|
||
<text class="mono" x="320" y="330">read_file(bundle_id, path)</text>
|
||
<text class="tiny" x="320" y="354">ett dokument helt — og fire porter foran</text>
|
||
|
||
<rect class="box soft" x="700" y="30" width="470" height="140"/>
|
||
<text class="lbl" x="720" y="60">Dybde-først over lenker</text>
|
||
<text class="tiny" x="720" y="86">En katalog blir ALDRI enumerert. Ledende / betyr bundle-rot.</text>
|
||
<text class="tiny" x="720" y="108">Det er ESCAPE, ikke dybde, som er forbudt.</text>
|
||
<text class="tiny" x="720" y="130">Ufulgte lenker havner på Bundle.skipped med grunn:</text>
|
||
<text class="tiny" x="720" y="150">missing eller outside-bundle. Aldri stille.</text>
|
||
|
||
<rect class="box warn" x="700" y="190" width="470" height="180"/>
|
||
<text class="lbl" x="720" y="220">Fire porter på read_file</text>
|
||
<text class="tiny" x="720" y="246">1 · Verdict-laget — nektes ubetinget, på dokumentets EGEN frontmatter</text>
|
||
<text class="tiny" x="720" y="268">2 · Sti utenfor bundlen — safe_resolve, PathSecurityError</text>
|
||
<text class="tiny" x="720" y="290">3 · Katalog, ikke dokument — DirectoryPathRefused</text>
|
||
<text class="tiny" x="720" y="312">4 · Utenfor dimensjonen — DimensionScopeRefused</text>
|
||
<text class="sub" x="720" y="344">Nektene er RETURVERDIER, ikke exceptions.</text>
|
||
<text class="tiny" x="720" y="364">Grunnen reiser tilbake til modellen. Bytene gjør det aldri.</text>
|
||
</svg>
|
||
<figcaption>En femte funksjon, <code>declare_requirement</code>, legges på kun når kravloggen er koblet på. En logg som ikke ser hva som ble åpnet, ville godtatt hver eneste erklæring.</figcaption>
|
||
</figure>
|
||
<table class="compact">
|
||
<thead><tr><th>Form, målt på K2-korpuset (630 konseptdokumenter)</th><th>o200k-tokens i én kjørings prompter</th><th>Endring</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Hele bundlen utlevert, i tre kopier</td><td>1 947 342 (99,1 % av promptene)</td><td>utgangspunkt</td></tr>
|
||
<tr><td>Peker + de fire verktøyene, like-for-like</td><td>753</td><td>−99,96 %</td></tr>
|
||
<tr><td>Peker + en debatt som faktisk går stigen</td><td>8 942</td><td>−99,5 %</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/explore.py:1199-1612</code> · <code>src/portfolio_optimiser/okf.py:914-975</code> · <code>docs/invarianter.md:1719-1734</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3a-03 ingest -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">15</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Ingest-laget bygger bundlen FØR kjøringen, gjennom en content gate.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 430" role="img" aria-label="Ingest-pipeline fra manifest gjennom connectors og materialisering til en content gate og en ferdig OKF-bundle">
|
||
<rect class="box" x="30" y="120" width="200" height="120"/>
|
||
<text class="lbl" x="48" y="152">manifest</text>
|
||
<text class="sub" x="48" y="178">JSON-Schema-</text>
|
||
<text class="sub" x="48" y="198">validert, fail-fast</text>
|
||
<text class="tiny" x="48" y="222">polymorf kildetype</text>
|
||
<path class="edge" d="M232 180 H264"/>
|
||
|
||
<rect class="box" x="268" y="100" width="230" height="160"/>
|
||
<text class="lbl" x="286" y="132">connectors</text>
|
||
<text class="mono" x="286" y="160">file / CSV</text>
|
||
<text class="mono" x="286" y="182">sql</text>
|
||
<text class="mono" x="286" y="204">http</text>
|
||
<text class="tiny" x="286" y="230">MCP er en HttpGet-formet</text>
|
||
<text class="tiny" x="286" y="248">adapter i http-familien</text>
|
||
<path class="edge" d="M500 180 H532"/>
|
||
|
||
<rect class="box" x="536" y="120" width="200" height="120"/>
|
||
<text class="lbl" x="554" y="152">materialize</text>
|
||
<text class="sub" x="554" y="178">renderer konsept-</text>
|
||
<text class="sub" x="554" y="198">filer og index.md</text>
|
||
<text class="tiny" x="554" y="222">null modellkall</text>
|
||
<path class="edge" d="M738 180 H770"/>
|
||
|
||
<rect class="box warn" x="774" y="100" width="240" height="160"/>
|
||
<text class="lbl" x="792" y="132">materialize_gated</text>
|
||
<text class="sub" x="792" y="158">content gate</text>
|
||
<text class="tiny" x="792" y="184">llm-ingestion-guard skanner</text>
|
||
<text class="tiny" x="792" y="204">HVERT generert konsept</text>
|
||
<text class="tiny" x="792" y="224">FØR noe når bundlen</text>
|
||
<path class="edge" d="M1016 180 H1044"/>
|
||
|
||
<rect class="box ok" x="1048" y="120" width="130" height="120"/>
|
||
<text class="lbl" x="1064" y="152">OKF-</text>
|
||
<text class="lbl" x="1064" y="174">bundle</text>
|
||
<text class="tiny" x="1064" y="204">8-stegs-sløyfa</text>
|
||
<text class="tiny" x="1064" y="222">leser den</text>
|
||
|
||
<path class="edge warn" d="M894 264 V326"/>
|
||
<rect class="box warn" x="700" y="330" width="420" height="80"/>
|
||
<text class="lbl" x="718" y="360">Nektet kjøring skriver INGENTING</text>
|
||
<text class="tiny" x="718" y="384">Ingen halvferdig bundle, ingen delvis skrevet index —</text>
|
||
<text class="tiny" x="718" y="402">nekten er et utfall, ikke et avbrudd midtveis.</text>
|
||
|
||
<rect class="box soft" x="30" y="300" width="470" height="110"/>
|
||
<text class="lbl" x="48" y="330">Nettverk er et løfte per kjøring</text>
|
||
<text class="tiny" x="48" y="354">allow_network er et kwarg til materialize, default False,</text>
|
||
<text class="tiny" x="48" y="374">aldri et manifest-felt: manifestet kan ikke gi seg selv nett.</text>
|
||
<text class="tiny" x="48" y="394">En http-kilde nektes fail-fast uten eksplisitt opt-in.</text>
|
||
</svg>
|
||
<figcaption>Ingest kjører før sløyfen og gjør null modellkall. De gylne uttrekkene er bit-identiske på begge stacker, fordi begge implementerer fra den samme ingest-spec-en.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Status og et målt dokumentavvik.</b> Laget er kjørt kun mot committede fixtures; ingen bundle er ennå materialisert fra en live kilde. Pinnene i <code>pyproject.toml</code> er <code>llm-ingestion-okf</code> v0.8.5 (linje 71) og <code>llm-ingestion-guard</code> v1.4.0 (linje 80), mens <code>docs/extending.md:86</code> og <code>ingest.py</code>-docstringen fortsatt sier v0.3.2 og v0.3.4. Dokumentene er utdaterte, ikke koden.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/ingest.py:1-33</code> · <code>src/portfolio_optimiser/ingest_mcp.py:99</code> · <code>pyproject.toml:71,80</code> · <code>README.md:288-296</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3a-04 kontraktene -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">16</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Kontraktene er Pydantic, og de feiler før det første modellkallet.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 560" role="img" aria-label="Tre kolonner: kontrakter validert ved oppstart, typene som flyter gjennom kjoeringen, og provenance-stempelet paa hvert utfall">
|
||
<text class="band-lbl" x="30" y="30">Validert ved oppstart</text>
|
||
<rect class="band" x="30" y="40" width="360" height="490"/>
|
||
<rect class="box" x="48" y="58" width="324" height="88"/>
|
||
<text class="lbl" x="66" y="88">contracts.py — fire kontrakter</text>
|
||
<text class="tiny" x="66" y="112">DataSourceContract · ModelMapContract</text>
|
||
<text class="tiny" x="66" y="134">TerminationContract · FeedbackContract</text>
|
||
|
||
<rect class="box" x="48" y="158" width="324" height="88"/>
|
||
<text class="lbl" x="66" y="188">mandate.Mandate</text>
|
||
<text class="tiny" x="66" y="212">objective + approaches[] med id, label,</text>
|
||
<text class="tiny" x="66" y="234">bundle_id og en bindende requirement</text>
|
||
|
||
<rect class="box" x="48" y="258" width="324" height="68"/>
|
||
<text class="lbl" x="66" y="288">dimension.Dimension</text>
|
||
<text class="tiny" x="66" y="312">allowed_measure_types er påkrevd</text>
|
||
|
||
<rect class="box" x="48" y="338" width="324" height="88"/>
|
||
<text class="lbl" x="66" y="368">budget.Budget</text>
|
||
<text class="tiny" x="66" y="392">max_tokens og max_rounds, begge over 0</text>
|
||
<text class="tiny" x="66" y="414">nekter konstruksjon ellers — aldri ubegrenset</text>
|
||
|
||
<rect class="box" x="48" y="438" width="324" height="74"/>
|
||
<text class="lbl" x="66" y="468">explore.ExplorationContract</text>
|
||
<text class="tiny" x="66" y="492">seks felt, alle påkrevd, ingen default</text>
|
||
|
||
<path class="edge" d="M392 280 H424"/>
|
||
|
||
<text class="band-lbl" x="430" y="30">Gjennom kjøringen</text>
|
||
<rect class="band accent" x="430" y="40" width="340" height="490"/>
|
||
<rect class="box" x="448" y="70" width="304" height="140"/>
|
||
<text class="lbl" x="466" y="100">ir.SavingsProposal</text>
|
||
<text class="tiny" x="466" y="126">project_id · measure</text>
|
||
<text class="tiny" x="466" y="148">affected_items[] — minst én</text>
|
||
<text class="tiny" x="466" y="170">claimed_saving_nok over 0</text>
|
||
<text class="tiny" x="466" y="192">assumptions: kode → (low, high)</text>
|
||
|
||
<rect class="box" x="448" y="232" width="304" height="110"/>
|
||
<text class="lbl" x="466" y="262">ir.AffectedItem</text>
|
||
<text class="tiny" x="466" y="288">code · quantity, minst 0</text>
|
||
<text class="tiny" x="466" y="310">unit_cost over 0 · total</text>
|
||
<text class="tiny" x="466" y="332">summen begrenser claimed</text>
|
||
|
||
<rect class="box" x="448" y="364" width="304" height="126"/>
|
||
<text class="lbl" x="466" y="394">ir.CostBaseline</text>
|
||
<text class="tiny" x="466" y="420">project_id · items: kode → linje</text>
|
||
<text class="tiny" x="466" y="442">prosjektets faktiske kostnadslinjer —</text>
|
||
<text class="tiny" x="466" y="464">det validatoren forankrer mot</text>
|
||
|
||
<path class="edge" d="M772 280 H804"/>
|
||
|
||
<text class="band-lbl" x="810" y="30">På hvert utfall</text>
|
||
<rect class="band" x="810" y="40" width="360" height="490"/>
|
||
<rect class="box" x="828" y="70" width="324" height="242"/>
|
||
<text class="lbl" x="846" y="100">provenance.ProvenanceStamp</text>
|
||
<text class="tiny" x="846" y="128">citations — minst én, alltid</text>
|
||
<text class="tiny" x="846" y="152">model · role · token_usage</text>
|
||
<text class="tiny" x="846" y="176">validator_decision: validated | rejected</text>
|
||
<text class="tiny" x="846" y="200">cost_baseline_anchored: bool, uten default —</text>
|
||
<text class="tiny" x="846" y="220">begge defaultene ville løyet</text>
|
||
<text class="tiny" x="846" y="244">bundle_id_source · code_forms</text>
|
||
<text class="tiny" x="846" y="268">external_calls — tom liste er en PÅSTAND</text>
|
||
<text class="tiny" x="846" y="292">om at ingenting utenfor prosessen ble kontaktet</text>
|
||
|
||
<rect class="box soft" x="828" y="340" width="324" height="150"/>
|
||
<text class="lbl" x="846" y="370">Fail-fast, ikke tolerant</text>
|
||
<text class="tiny" x="846" y="396">load_contracts bygger de fire i rekkefølge og</text>
|
||
<text class="tiny" x="846" y="416">reiser på den FØRSTE som er malformert,</text>
|
||
<text class="tiny" x="846" y="436">før noen chat-klient finnes.</text>
|
||
<text class="tiny" x="846" y="462">Ingen degradering til noe som «virker likevel»:</text>
|
||
<text class="tiny" x="846" y="482">en tolerant baseline løsner porten i stillhet.</text>
|
||
</svg>
|
||
<figcaption>Feltene som kan lyve er enten påkrevde uten default, eller har en begrensning Pydantic håndhever ved konstruksjon. <code>BindingRequirement</code> 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.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>To ting som IKKE er det samme.</b> <code>TerminationContract</code> og <code>Budget</code> er ressurstak; <code>GoalContract</code> er et domenemål — en besparelse i øre eller prosent — og det målet bor ett sted, ikke i mandatet. <code>McpConfig</code> er <code>extra=forbid</code>, så en forvillet <code>"credential": "sk-…"</code> blir en nekt i stedet for en ignorert nøkkel.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/contracts.py:31-101</code> · <code>ir.py:15-63</code> · <code>mandate.py:46-156</code> · <code>budget.py:67-81</code> · <code>provenance.py:53-104</code> · <code>explore.py:65-99</code> · <code>mcp_tools.py:50-58</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3a-05 debatten -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">17</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Debatten er maker–checker i en GroupChat, med rundetak og en VERDICT-linje.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 540" role="img" aria-label="Sekvensdiagram mellom proposer, checker og den deterministiske validatoren, med stoppene under">
|
||
<rect class="box accent" x="60" y="20" width="260" height="64"/>
|
||
<text class="lbl" x="82" y="58">proposer</text>
|
||
<rect class="box accent" x="440" y="20" width="260" height="64"/>
|
||
<text class="lbl" x="462" y="58">checker</text>
|
||
<rect class="box warn" x="820" y="20" width="300" height="64"/>
|
||
<text class="lbl" x="842" y="58">deterministisk validator</text>
|
||
|
||
<path class="hair" d="M190 86 V400"/>
|
||
<path class="hair" d="M570 86 V400"/>
|
||
<path class="hair" d="M970 86 V400"/>
|
||
|
||
<text class="tiny" x="200" y="124">1 · ett typet kandidat-tiltak (streng IR via response_format)</text>
|
||
<path class="edge accent" d="M190 134 H564"/>
|
||
|
||
<text class="tiny" x="210" y="184">2 · angriper resonnementet, avslutter med VERDICT: APPROVE eller REJECT</text>
|
||
<path class="edge" d="M570 194 H196"/>
|
||
|
||
<text class="tiny" x="200" y="244">3 · revidert kandidat — selection_func sykler proposer, checker, proposer …</text>
|
||
<path class="edge accent" d="M190 254 H564"/>
|
||
|
||
<text class="tiny" x="580" y="314">4 · den konvergerte kandidaten går til porten</text>
|
||
<path class="edge" d="M570 324 H964"/>
|
||
|
||
<text class="tiny" x="230" y="374">5 · ved nekt: KUN Rejection.reason inn i neste forsøks prompt, aldri forrige JSON</text>
|
||
<path class="edge warn" d="M970 384 H196"/>
|
||
|
||
<rect class="box soft" x="60" y="420" width="520" height="100"/>
|
||
<text class="lbl" x="80" y="450">Ferske agenter, ferske klienter, per kjøring</text>
|
||
<text class="tiny" x="80" y="476">Målt: en gjenbrukt bygget workflow er ENGANGS — klientkall-serien</text>
|
||
<text class="tiny" x="80" y="496">[2, 0, 0] over tre .run() på ett objekt. Gjenbruk gir TOMME kjøringer,</text>
|
||
<text class="tiny" x="80" y="514">ikke bare forurensede. Derfor en fabrikk, ikke et delt objekt.</text>
|
||
|
||
<rect class="box warn" x="620" y="420" width="500" height="100"/>
|
||
<text class="lbl" x="640" y="450">Tre uavhengige stopp</text>
|
||
<text class="tiny" x="640" y="476">with_max_rounds(max_rounds) er det bindende taket</text>
|
||
<text class="tiny" x="640" y="496">make_termination(max_rounds × 2 + 1) er sikkerhetsnettet over det</text>
|
||
<text class="tiny" x="640" y="514">BudgetMiddleware nekter NESTE kall før det gjøres. Mer i Del 5.</text>
|
||
</svg>
|
||
<figcaption><code>output_from=agents</code> er load-bearing: uten den gir <code>get_outputs()</code> bare orkestratorens «reached max rounds»-melding, og både proposerens forslag og checkerens dom går tapt. <code>run.py</code> skiller dem på <code>author_name</code>. På grenen uten pre-pass-payload har debatten de samme fire navigasjonsverktøyene som utforskningen.</figcaption>
|
||
</figure>
|
||
<p class="point">Slik ser en falsifisering ut når den reiser tilbake til modellen — hele blokken, ordrett:</p>
|
||
<pre><code>Your previous proposal was REJECTED by the deterministic validator.
|
||
Reason: {prior_rejection.reason}
|
||
Produce a REVISED SavingsProposal that resolves this.</code></pre>
|
||
<p class="callout"><b>Checker-porten er fail-open.</b> Bare en eksplisitt <code>VERDICT: REJECT</code> 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.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/workflow.py:26-117</code> · <code>generate.py:362-367</code> · <code>generate.py:701-793</code> · <code>run.py:673-687</code> · <code>run.py:1331-1346</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3a-06 extension-points -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">18</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Utvidelsespunktene er navngitte sømmer, ikke plugin-magi.</h2>
|
||
<table class="compact">
|
||
<thead><tr><th>Sømmen</th><th>Slik utvider du</th><th>Regelen bak</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Eget prosjekt</td><td><code>data/reference_projects.json</code> + en docs-mappe</td><td>Kun konfig og dokumenter. En test nekter hardkodede prosjekt-id-er i <code>src/</code>.</td></tr>
|
||
<tr><td>Datakilde</td><td><code>retrieval.retrieve()</code> bak en <code>FunctionTool</code></td><td>Sti-sjekken er fail-closed, og sitatet er eksakt ved konstruksjon, ikke ved kontroll.</td></tr>
|
||
<tr><td>Modell-map</td><td><code>data/model_map.json</code>, <code>PORTFOLIO_MODEL_MAP</code></td><td>Konfig, ikke kode. Plassholdere feiler fail-fast før en klient bygges.</td></tr>
|
||
<tr><td>Ingest-kilde</td><td><code>materialize(http_get=…)</code></td><td><code>http</code>-familien er det dokumenterte eksempelet. Nett er et kwarg, aldri et manifest-felt.</td></tr>
|
||
<tr><td>MCP</td><td>ingest-adapter, og <code>--mcp-config</code> i debatten</td><td>Allowlist er påkrevd, og hver server og hvert tillatte verktøy navngis før første kall.</td></tr>
|
||
<tr><td>Retriever / embedder</td><td><code>Retriever</code>- og <code>Embedder</code>-protokollene</td><td>LUKKET registry — aldri en import-sti, som ville vært kodekjøring ved konfig-lasting.</td></tr>
|
||
<tr><td>Notifier</td><td><code>build_notifier(config, allow_egress=…)</code></td><td>Egress er et kode-kwarg per kjøring, aldri et konfig-felt. Webhooken er eneste egress-punkt.</td></tr>
|
||
<tr><td><code>client_factory</code></td><td><code>run_project(client_factory=…)</code></td><td>Det ekte backend-byttet. Det står ikke i <code>docs/extending.md</code> — en reell dokumentasjonsglipe.</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="callout"><b>Bevisste kutt, ikke gjeld.</b> 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: <code>METHOD_CAPS</code> (metodetaket i validatoren) og personabytte ved å re-peke <code>shared/</code>.</p>
|
||
<p class="src">Kilde: <code>docs/extending.md:15-321</code> · <code>src/portfolio_optimiser/semretrieval.py:215-226</code> · <code>notify.py:175</code> · <code>run.py:1097</code> · <code>validator.py:52</code> · <code>persona.py:30-47</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== part3b-gate.html ===== -->
|
||
<!-- 3b-01 validator-portrekke -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">19</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Validatoren er en portrekke, og den første porten som slår, avgjør.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 640" role="img" aria-label="Validatorens stadier i utfoerelsesrekkefoelge som en portrekke, med en nektrail til hoeyre">
|
||
<rect class="band warn" x="1046" y="36" width="114" height="482"/>
|
||
<text class="band-lbl" x="1103" y="277" text-anchor="middle" transform="rotate(90 1103 277)">NEKT</text>
|
||
|
||
<rect class="box warn" x="40" y="44" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="70">Stage 1 · Pydantic (ved konstruksjon)</text>
|
||
<text class="sub" x="436" y="70">claimed_saving_nok ≤ Σ item.total · båndet omslutter unit_cost</text>
|
||
<path class="edge warn" d="M1000 64 H1042"/>
|
||
<path class="edge" d="M230 84 V104"/>
|
||
|
||
<rect class="box warn" x="40" y="106" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="132">Stage 0 · cost-baseline</text>
|
||
<text class="sub" x="436" y="132">koden må finnes i baselinen · avvik over 5 % av baseline nektes</text>
|
||
<path class="edge warn" d="M1000 126 H1042"/>
|
||
<path class="edge" d="M230 146 V166"/>
|
||
|
||
<rect class="box warn" x="40" y="168" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="194">Stage 0b · forankring mot input</text>
|
||
<text class="sub" x="436" y="194">verbatim · treghet · kodeform · klausulnummer (fire underkontroller)</text>
|
||
<path class="edge warn" d="M1000 188 H1042"/>
|
||
<path class="edge" d="M230 208 V228"/>
|
||
|
||
<rect class="box accent" x="40" y="230" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="256">Stage 2 · solver (CBC LP)</text>
|
||
<text class="sub" x="436" y="256">max Σ x_i, s.t. Σ x_i ≤ 0,30 · Σ total_i, 0 ≤ x_i ≤ total_i</text>
|
||
<path class="edge" d="M230 270 V290"/>
|
||
|
||
<rect class="box accent" x="40" y="292" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="318">Stage 3 · Monte Carlo</text>
|
||
<text class="sub" x="436" y="318">512 trekk · Uniform(low, high) · seed 20260624 · P10 / P50 / P90</text>
|
||
<path class="edge" d="M230 332 V352"/>
|
||
|
||
<rect class="box warn" x="40" y="354" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="380">Stage 4 · P90-blokk</text>
|
||
<text class="sub" x="436" y="380">claimed over P90 feasible nektes (strukturell overgrense)</text>
|
||
<path class="edge warn" d="M1000 374 H1042"/>
|
||
<path class="edge" d="M230 394 V414"/>
|
||
|
||
<rect class="box warn" x="40" y="416" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="442">Stage 4b · nominal-blokk</text>
|
||
<text class="sub" x="436" y="442">claimed over nominal feasible nektes, uavhengig av stage 4</text>
|
||
<path class="edge warn" d="M1000 436 H1042"/>
|
||
<path class="edge" d="M230 456 V476"/>
|
||
|
||
<rect class="box warn" x="40" y="478" width="380" height="40"/>
|
||
<text class="lbl" x="56" y="504">Stage 5 · metodetak</text>
|
||
<text class="sub" x="436" y="504">energy_efficiency: claimed over 0,15 · Σ totals nektes</text>
|
||
<path class="edge warn" d="M1000 498 H1042"/>
|
||
<path class="edge ok" d="M230 518 V548"/>
|
||
|
||
<rect class="box ok" x="40" y="552" width="560" height="52"/>
|
||
<text class="lbl" x="56" y="574">ValidatedProposal(p10, p50, p90, nominal_feasible)</text>
|
||
<text class="tiny" x="56" y="594">alle porter passert</text>
|
||
</svg>
|
||
<figcaption>Returnerer ved FØRSTE port som slår. Stage 1 er en Pydantic-ValueError ved konstruksjon; de øvrige returnerer <code>Rejection</code>. Stage 2 og 3 regner, de nekter ikke. Stadienavnene i rapporten kommer fra <code>rejection_stage()</code>, som er en RAPPORT og ikke en port.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Et tredje utfall ligger utenfor validatoren.</b> <code>Unsupported</code> er definert i <code>validator.py</code>, men produseres i <code>run.py</code> etter at validatoren har sagt ja.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/validator.py:648-748</code> · <code>validator.py:749-775</code> · <code>docs/invarianter.md</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-02 solver-monte-carlo -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">20</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Solver og Monte Carlo: dette er hva som faktisk regnes.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 430" role="img" aria-label="LP-en, trekk-sloeyfen og desilene som gir P10, P50 og P90">
|
||
<rect class="box accent" x="40" y="30" width="320" height="150"/>
|
||
<text class="lbl" x="60" y="58">Stage 2 · CBC LP</text>
|
||
<text class="mono" x="60" y="86">max Σ x_i</text>
|
||
<text class="mono" x="60" y="108">s.t. Σ x_i ≤ 0,30 · Σ total_i</text>
|
||
<text class="mono" x="60" y="130">0 ≤ x_i ≤ total_i</text>
|
||
<text class="tiny" x="60" y="160">én kontinuerlig variabel per affected_item</text>
|
||
<path class="edge" d="M360 105 H430"/>
|
||
|
||
<rect class="box accent" x="430" y="30" width="330" height="150"/>
|
||
<text class="lbl" x="450" y="58">Stage 3 · Monte Carlo</text>
|
||
<text class="sub" x="450" y="86">512 trekk, ingen CBC per trekk</text>
|
||
<text class="sub" x="450" y="108">unit_cost ~ Uniform(low, high)</text>
|
||
<text class="sub" x="450" y="130">seed 20260624 (fast)</text>
|
||
<text class="tiny" x="450" y="160">poster uten bånd beholder oppgitt unit_cost</text>
|
||
<path class="edge" d="M760 105 H830"/>
|
||
|
||
<rect class="box" x="830" y="30" width="330" height="150"/>
|
||
<text class="lbl" x="850" y="58">Desiler</text>
|
||
<text class="mono" x="850" y="86">quantiles(n=10, inclusive)</text>
|
||
<text class="sub" x="850" y="112">nominal feasible kommer fra LP-en,</text>
|
||
<text class="sub" x="850" y="134">persentilene fra trekkene</text>
|
||
|
||
<path class="edge noarrow" d="M140 320 H1060"/>
|
||
<path class="edge noarrow" d="M340 310 V330"/>
|
||
<path class="edge noarrow" d="M600 310 V330"/>
|
||
<path class="edge noarrow" d="M860 310 V330"/>
|
||
<text class="lbl" x="340" y="360" text-anchor="middle">P10</text>
|
||
<text class="tiny" x="340" y="382" text-anchor="middle">rapporteres</text>
|
||
<text class="lbl" x="600" y="360" text-anchor="middle">P50</text>
|
||
<text class="tiny" x="600" y="382" text-anchor="middle">rapporteres</text>
|
||
<text class="lbl" x="860" y="360" text-anchor="middle">P90</text>
|
||
<text class="tiny" x="860" y="382" text-anchor="middle">porter</text>
|
||
<rect class="box warn" x="720" y="228" width="280" height="56"/>
|
||
<text class="sub" x="740" y="252">Bare P90 er en port:</text>
|
||
<text class="sub" x="740" y="272">claimed over P90 gir Rejection</text>
|
||
<path class="edge warn" d="M860 284 V306"/>
|
||
</svg>
|
||
<figcaption>P10 og P50 rapporteres på det validerte forslaget, men ingen av dem blokkerer noe. Stage 4b legger en uavhengig grense på det nominelle LP-svaret, fordi et oppoverskjevt bånd kan løfte P90 over nominal.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Ærlig om LP-en:</b> x = 0 er alltid tillatt, så «infeasible» har ingen kodesti. Et ikke-optimalt svar fra CBC er en miljøfeil og kaster <code>CbcUnavailable</code>, aldri en <code>Rejection</code>.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/validator.py:129-145</code> · <code>validator.py:148-164</code> · <code>validator.py:697-719</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-03 forankring-cost-baseline -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">21</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Et forslag kan ikke finne på kostnadslinjene det sparer mot.</h2>
|
||
<div class="split">
|
||
<div>
|
||
<p class="lede">Stage 0 avstemmer hver <code>affected_item</code> mot prosjektets egen <code>CostBaseline</code>: koden må finnes, og avviket i mengde og enhetspris må ligge innenfor 5 % av baselinen.</p>
|
||
<table class="compact">
|
||
<tr><th>Prosjekt</th><th>01.1 enhetspris</th><th>Σ prosjekt</th><th>Utfall</th></tr>
|
||
<tr><td>FV42-GSV-E1</td><td>850 000</td><td>6 721 500</td><td class="ok">validated</td></tr>
|
||
<tr><td>RV13-RAS-TP</td><td>1 450 000</td><td>7 529 700</td><td class="bad">rejected</td></tr>
|
||
<tr><td>BRU-LAKS-REHAB</td><td>620 000</td><td>3 099 700</td><td class="bad">rejected</td></tr>
|
||
<tr><td>SKOLE-VVS-OPPGR</td><td>480 000</td><td>4 640 000</td><td class="bad">rejected</td></tr>
|
||
</table>
|
||
<p class="small">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.</p>
|
||
<p class="callout warn"><b>SYNTETISK.</b> De fire referanseprosjektene er AI-forfattede placeholders i <code>data/reference_projects.json</code>, ikke faktiske prosjekttall.</p>
|
||
</div>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 900 560" role="img" aria-label="Ett forslag sendt mot fire prosjektbaselinjer, ett godkjent og tre avvist">
|
||
<rect class="box accent" x="230" y="20" width="440" height="76"/>
|
||
<text class="lbl" x="252" y="50">Ett forslag, fire prosjekter</text>
|
||
<text class="mono" x="252" y="76">01.1 · 1 stk à 850 000 · claimed 40 000</text>
|
||
<path class="edge" d="M380 96 C300 130 260 140 240 168"/>
|
||
<path class="edge" d="M430 96 C400 140 340 190 240 258"/>
|
||
<path class="edge" d="M470 96 C500 140 340 280 240 348"/>
|
||
<path class="edge" d="M520 96 C600 150 340 370 240 438"/>
|
||
|
||
<rect class="box ok" x="240" y="140" width="640" height="64"/>
|
||
<text class="lbl" x="262" y="166">FV42-GSV-E1</text>
|
||
<text class="sub" x="262" y="190">01.1 = 850 000 · innenfor toleransen · videre til solveren</text>
|
||
|
||
<rect class="box warn" x="240" y="230" width="640" height="64"/>
|
||
<text class="lbl" x="262" y="256">RV13-RAS-TP</text>
|
||
<text class="sub" x="262" y="280">01.1 = 1 450 000 · avviket er langt over 5 % · nektet</text>
|
||
|
||
<rect class="box warn" x="240" y="320" width="640" height="64"/>
|
||
<text class="lbl" x="262" y="346">BRU-LAKS-REHAB</text>
|
||
<text class="sub" x="262" y="370">01.1 = 620 000 · avviket er langt over 5 % · nektet</text>
|
||
|
||
<rect class="box warn" x="240" y="410" width="640" height="64"/>
|
||
<text class="lbl" x="262" y="436">SKOLE-VVS-OPPGR</text>
|
||
<text class="sub" x="262" y="460">01.1 = 480 000 · avviket er langt over 5 % · nektet</text>
|
||
|
||
<rect class="box soft" x="20" y="500" width="860" height="46"/>
|
||
<text class="sub" x="42" y="529">Alle fire siterer samme verdict id: dommen nøkles på KANDIDATEN, ikke på prosjektet.</text>
|
||
</svg>
|
||
<figcaption>Porten er forankret i prosjektets egne tall, ikke i forslagets interne aritmetikk.</figcaption>
|
||
</figure>
|
||
</div>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/validator.py:225-279</code> · <code>src/portfolio_optimiser/data/reference_projects.json</code> · <code>README.md</code> steg 6</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-04 stage0b-fire-underkontroller -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">22</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>En kode må ha en form, og et klausulnummer er ikke en pris.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 500" role="img" aria-label="Stage 0b sine fire underkontroller i rekkefoelge, med nektformuleringen for hver">
|
||
<rect class="box" x="40" y="20" width="330" height="70"/>
|
||
<text class="lbl" x="60" y="48">1 · verbatim</text>
|
||
<text class="sub" x="60" y="72">koden må stå i teksten</text>
|
||
<path class="edge warn" d="M370 55 H426"/>
|
||
<rect class="box warn" x="430" y="20" width="730" height="70"/>
|
||
<text class="sub" x="452" y="48">Koden er ikke en delstreng av inputen kjøringen fikk.</text>
|
||
<text class="tiny" x="452" y="72">Alle fire nekt starter med «ungrounded identifier {code}: it …»</text>
|
||
<path class="edge" d="M205 90 V110"/>
|
||
|
||
<rect class="box" x="40" y="112" width="330" height="70"/>
|
||
<text class="lbl" x="60" y="140">2 · treghet</text>
|
||
<text class="sub" x="60" y="164">kortere enn 3 tegn, eller overalt</text>
|
||
<path class="edge warn" d="M370 147 H426"/>
|
||
<rect class="box warn" x="430" y="112" width="730" height="70"/>
|
||
<text class="sub" x="452" y="140">«appears in N of the M documents this run was given»</text>
|
||
<text class="tiny" x="452" y="164">Grensen er max(10; 5 % av dokumentene). Nevneren står i meldingen, fordi Steg 5 mater den ordrett inn i neste forsøk.</text>
|
||
<path class="edge" d="M205 182 V202"/>
|
||
|
||
<rect class="box" x="40" y="204" width="330" height="70"/>
|
||
<text class="lbl" x="60" y="232">3 · kodeform</text>
|
||
<text class="sub" x="60" y="256">fritatt i baselinen eller identifier-form</text>
|
||
<path class="edge warn" d="M370 239 H426"/>
|
||
<rect class="box warn" x="430" y="204" width="730" height="70"/>
|
||
<text class="sub" x="452" y="232">«has no identifier form; the input offers N identifiers of its own»</text>
|
||
<text class="tiny" x="452" y="256">Slår IKKE når inputen ikke tilbyr identifikatorer i det hele tatt: en base kan ikke svares i en form den ikke bruker.</text>
|
||
<path class="edge" d="M205 274 V294"/>
|
||
|
||
<rect class="box" x="40" y="296" width="330" height="70"/>
|
||
<text class="lbl" x="60" y="324">4 · klausulnummer</text>
|
||
<text class="sub" x="60" y="348">kun når basen er UFORANKRET</text>
|
||
<path class="edge warn" d="M370 331 H426"/>
|
||
<rect class="box warn" x="430" y="296" width="730" height="70"/>
|
||
<text class="sub" x="452" y="324">«not one of the N this knowledge base declares»</text>
|
||
<text class="tiny" x="452" y="348">«an unanchored base carries no price for a clause number». Slår bare på komplementet: kravformet kode som IKKE står i vokabularet.</text>
|
||
<path class="edge ok" d="M205 366 V392"/>
|
||
|
||
<rect class="box ok" x="40" y="396" width="330" height="70"/>
|
||
<text class="lbl" x="60" y="424">forankret</text>
|
||
<text class="sub" x="60" y="448">videre til stage 2</text>
|
||
<rect class="box soft" x="430" y="396" width="730" height="70"/>
|
||
<text class="lbl" x="452" y="424">classify_codes: identifier | prose | requirement</text>
|
||
<text class="tiny" x="452" y="448">En RAPPORT om hva kjøringen gjorde av koden, ikke porten. Havner i provenance-stemplet som code_forms.</text>
|
||
</svg>
|
||
<figcaption>Fire underkontroller per berørt post, første treff vinner. Målt i P18 runde 2: to alminnelige ord fra en standards prosa (4 av 270 N500-dokumenter og 4 av 1 133 N200-dokumenter) passerte hele porten som kostnadskoder før kodeform-regelen fantes.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/validator.py:471-491</code> · <code>validator.py:494-571</code> · <code>validator.py:574-645</code> · <code>validator.py:388-408</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-05 tre-utfall -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">23</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Tre utfall, ikke to: validated, rejected og unsupported.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 480" role="img" aria-label="Regelen som gjoer et validert forslag til unsupported naar ingen krav ble deklarert">
|
||
<rect class="box accent" x="30" y="190" width="240" height="80"/>
|
||
<text class="lbl" x="50" y="220">validate_proposal</text>
|
||
<text class="tiny" x="50" y="244">den deterministiske porten</text>
|
||
<text class="tiny" x="50" y="262">avgjør bare TALLENE</text>
|
||
<path class="edge warn" d="M270 215 C305 215 300 92 330 92"/>
|
||
<path class="edge ok" d="M270 245 C305 245 300 352 330 352"/>
|
||
|
||
<rect class="box warn" x="330" y="60" width="250" height="64"/>
|
||
<text class="lbl" x="350" y="88">Rejection</text>
|
||
<text class="tiny" x="350" y="110">ingen persentiler, bare grunnen</text>
|
||
<path class="edge warn" d="M580 92 H986"/>
|
||
|
||
<rect class="box ok" x="330" y="320" width="250" height="64"/>
|
||
<text class="lbl" x="350" y="348">ValidatedProposal</text>
|
||
<text class="tiny" x="350" y="370">p10 · p50 · p90 · nominal</text>
|
||
<path class="edge" d="M580 352 H626"/>
|
||
|
||
<rect class="box dashed" x="630" y="250" width="310" height="200"/>
|
||
<text class="lbl" x="650" y="282">Tre vilkår, alle må holde</text>
|
||
<text class="sub" x="650" y="310">1 · kjøringen har et deklarert mandat</text>
|
||
<text class="sub" x="650" y="334">2 · approach har ikke sitt eget krav</text>
|
||
<text class="sub" x="650" y="358">3 · ingen deklarasjon på approach-id</text>
|
||
<text class="tiny" x="650" y="392">run.py:589-597, ikke et validator-stadium</text>
|
||
<text class="tiny" x="650" y="414">Unsupported bærer de validerte tallene videre</text>
|
||
<path class="edge warn" d="M940 300 C965 300 965 282 986 282"/>
|
||
<text class="tiny" x="963" y="272" text-anchor="middle">ja</text>
|
||
<path class="edge ok" d="M940 400 C965 400 965 412 986 412"/>
|
||
<text class="tiny" x="963" y="440" text-anchor="middle">nei</text>
|
||
|
||
<rect class="box warn" x="990" y="60" width="190" height="64"/>
|
||
<text class="lbl" x="1010" y="98">rejected</text>
|
||
<rect class="box warn dashed" x="990" y="250" width="190" height="64"/>
|
||
<text class="lbl" x="1010" y="288">unsupported</text>
|
||
<rect class="box ok" x="990" y="380" width="190" height="64"/>
|
||
<text class="lbl" x="1010" y="418">validated</text>
|
||
</svg>
|
||
<figcaption><code>Unsupported</code> arver fra <code>Rejection</code>. Hver konsument som spør «er dette validert?» med <code>isinstance(..., ValidatedProposal)</code> svarer nei uten å endres, så utfallet blir aldri talt eller summert som en suksess. Konsumentene som NAVNGIR statusen sjekker klassen først.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Uttalt svakhet:</b> deklarasjonens KVALITET vurderes ikke. Regelen spør om et krav ble deklarert, ikke om deklarasjonen var god.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/run.py:589-597</code> · <code>validator.py:113-126</code> · <code>outbox.py:106-146</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-06 tak-og-stoppkriterier -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">24</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Ingen ubegrenset sløyfe: hvert tak er påkrevd ved oppstart.</h2>
|
||
<table>
|
||
<tr><th>Tak</th><th>Hvor det bor</th><th>Hva som skjer når det slår</th></tr>
|
||
<tr><td>Debattrunder</td><td><code>with_max_rounds</code> (workflow.py:113)</td><td>Hardt tak. En debatt som ikke konvergerer terminerer ikke seg selv.</td></tr>
|
||
<tr><td>Refinement-forsøk</td><td><code>self_repair(max_attempts=3)</code></td><td>Første <code>ValidatedProposal</code>, ellers siste <code>Rejection</code>. <code>max_attempts ≤ 0</code> nektes.</td></tr>
|
||
<tr><td>Token-tak</td><td><code>BudgetMiddleware</code>, <code>strict_usage=True</code></td><td>Nekter kallet FØR det gjøres når taket er brukt opp. Manglende usage gir <code>UsageUnavailable</code>, aldri stille telling.</td></tr>
|
||
<tr><td>Portefølje-måler</td><td><code>PortfolioBudget</code> + <code>PortfolioMeter</code></td><td><code>BudgetRefused</code> ved START når passet ikke kan finansiere én kjøring. Nekt, aldri reparasjon.</td></tr>
|
||
<tr><td>Utforskningstak</td><td><code>ExplorationContract</code> (explore.py:65-101)</td><td>Seks felt, ingen defaults. MAF-ens egne defaults er ubegrenset, så et utelatt felt ville falt tilbake på den ene formen spec-en forbyr.</td></tr>
|
||
<tr><td>Parse-feil</td><td><code>_fetch_parsed</code> (generate.py:642-672)</td><td>Retryen bærer GRUNNEN inn i neste prompt. Før dette ble de samme bytene sendt på nytt.</td></tr>
|
||
</table>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 130" role="img" aria-label="Elleve av tolv runder brukt paa svar som feilet identisk">
|
||
<text class="sub" x="40" y="26">kontrakt-sorasen-04, runde-3-kjøring: 11 av 12 runder brukt på svar som feilet på samme måte</text>
|
||
<rect class="box warn" x="40" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="128" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="216" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="304" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="392" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="480" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="568" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="656" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="744" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="832" y="42" width="82" height="46"/>
|
||
<rect class="box warn" x="920" y="42" width="82" height="46"/>
|
||
<rect class="box soft" x="1008" y="42" width="82" height="46"/>
|
||
<text class="tiny" x="40" y="112">Alle elleve feilet på «claimed_saving_nok: 0», fordi ingenting fortalte modellen hva som var galt.</text>
|
||
</svg>
|
||
<figcaption>Målingen som gjorde retryen informert. Den tolvte runden er markert dempet fordi den ikke er en suksess, bare den siste.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/budget.py:67-256</code> · <code>validator.py:778-796</code> · <code>explore.py:65-101</code> · <code>generate.py:310-319</code> · <code>generate.py:642-672</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-07 provenance -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">25</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Hvert forslag bærer sitt eget provenance-stempel.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 520" role="img" aria-label="Provenance-stemplet festet til forslagsartefaktet, med de ni feltene">
|
||
<rect class="box" x="40" y="120" width="320" height="280"/>
|
||
<text class="lbl" x="62" y="152">{run_id}-proposal.json</text>
|
||
<rect class="box soft" x="64" y="176" width="272" height="86"/>
|
||
<text class="lbl" x="84" y="204">proposal</text>
|
||
<text class="tiny" x="84" y="226">SavingsProposal.model_dump()</text>
|
||
<text class="tiny" x="84" y="246">total er en property, så den er ikke med</text>
|
||
<rect class="box accent" x="64" y="284" width="272" height="94"/>
|
||
<text class="lbl" x="84" y="312">provenance</text>
|
||
<text class="tiny" x="84" y="334">ProvenanceStamp.model_dump()</text>
|
||
<text class="tiny" x="84" y="354">ni felt, ingen av dem valgfrie i praksis</text>
|
||
<path class="edge accent" d="M336 330 C380 330 390 270 428 270"/>
|
||
|
||
<rect class="box accent" x="430" y="30" width="730" height="460"/>
|
||
<text class="mono" x="452" y="70">citations</text>
|
||
<text class="sub" x="700" y="70">minst én, håndhevet av min_length=1</text>
|
||
<text class="mono" x="452" y="116">model · role</text>
|
||
<text class="sub" x="700" y="116">hvilken modell og hvilken rolle som svarte</text>
|
||
<text class="mono" x="452" y="162">validator_decision</text>
|
||
<text class="sub" x="700" y="162">"validated" eller "rejected", validatorens egen dom</text>
|
||
<text class="mono" x="452" y="208">token_usage</text>
|
||
<text class="sub" x="700" y="208">fra tilbyderens egne UsageDetails</text>
|
||
<text class="mono" x="452" y="254">cost_baseline_anchored</text>
|
||
<text class="sub" x="700" y="254">kjørte stage 0? Påkrevd uten default: begge defaults ville løyet</text>
|
||
<text class="mono" x="452" y="300">bundle_id_source</text>
|
||
<text class="sub" x="700" y="300">hvilken kunnskapsbase, eller None når ingen var involvert</text>
|
||
<text class="mono" x="452" y="346">code_forms</text>
|
||
<text class="sub" x="700" y="346">hver kode som identifier, prose eller requirement</text>
|
||
<text class="mono" x="452" y="392">external_calls</text>
|
||
<text class="sub" x="700" y="392">tom liste er en POSITIV påstand, ikke et fravær</text>
|
||
<rect class="box soft" x="452" y="418" width="686" height="54"/>
|
||
<text class="tiny" x="472" y="440">Feltene er STRUKTURERTE, ikke prosa: «var falsifikatoren forankret» er et operativt</text>
|
||
<text class="tiny" x="472" y="460">spørsmål som må kunne leses av en maskin.</text>
|
||
</svg>
|
||
<figcaption>Stemplet følger artefaktet ut av prosessen. Det gater ingenting; det gjør et hopp over stage 0 leselig i stedet for stille.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/provenance.py:53-105</code> · <code>outbox.py:81-90</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-08 ekspertsloeyfen -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">26</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Ekspertens dom kommer dager senere, som en fil i en mappe.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 560" role="img" aria-label="Ekspertsloeyfen fra outbox via innboksmappe til fewshot i neste kjoerings prompt">
|
||
<text class="band-lbl" x="40" y="34">KJØRING N</text>
|
||
<rect class="box" x="40" y="46" width="300" height="86"/>
|
||
<text class="lbl" x="60" y="74">{run_id}-outcome.json</text>
|
||
<text class="sub" x="60" y="98">bærer verdict_id</text>
|
||
<text class="tiny" x="60" y="118">nøkkelen finnes også uten at noen dømte</text>
|
||
<path class="edge" d="M340 89 H426"/>
|
||
|
||
<rect class="box soft" x="430" y="46" width="300" height="86"/>
|
||
<text class="lbl" x="450" y="74">Eksperten, dager senere</text>
|
||
<text class="sub" x="450" y="98">ingen levende sesjon antas</text>
|
||
<text class="tiny" x="450" y="118">kjøringen er for lengst avsluttet</text>
|
||
<path class="edge" d="M730 89 H816"/>
|
||
|
||
<rect class="box accent" x="820" y="46" width="340" height="86"/>
|
||
<text class="lbl" x="840" y="74">{verdict.id}.json</text>
|
||
<text class="mono" x="840" y="100">{decision, rationale}</text>
|
||
<text class="tiny" x="840" y="120">én fil per dom i innboksmappa</text>
|
||
<path class="edge" d="M990 132 V196"/>
|
||
|
||
<text class="band-lbl" x="40" y="184">KJØRING N+1</text>
|
||
<rect class="box" x="820" y="200" width="340" height="86"/>
|
||
<text class="lbl" x="840" y="228">load_verdicts_from_dir</text>
|
||
<text class="sub" x="840" y="252">tolerant: hopper over det den ikke forstår</text>
|
||
<text class="tiny" x="840" y="272">manglende mappe gir tom liste, ikke feil</text>
|
||
<path class="edge" d="M816 243 H740"/>
|
||
|
||
<rect class="box" x="430" y="200" width="300" height="86"/>
|
||
<text class="lbl" x="450" y="228">VerdictStore</text>
|
||
<text class="sub" x="450" y="252">in-memory, first-write-wins</text>
|
||
<text class="tiny" x="450" y="272">varig lagring er utsatt til fase 3</text>
|
||
<path class="edge" d="M426 243 H344"/>
|
||
|
||
<rect class="box accent" x="40" y="200" width="300" height="86"/>
|
||
<text class="lbl" x="60" y="228">retrieve, topp k</text>
|
||
<text class="sub" x="60" y="250">0,60 Jaccard over kodesettet</text>
|
||
<text class="sub" x="60" y="270">0,25 measure · 0,15 størrelsesbøtte</text>
|
||
<path class="edge accent" d="M190 286 V348"/>
|
||
|
||
<rect class="box accent" x="40" y="352" width="1120" height="80"/>
|
||
<text class="lbl" x="62" y="382">format_fewshot() settes FORAN generasjonskonteksten</text>
|
||
<text class="sub" x="62" y="410">run.py:1551-1560. Én linje per treff: [id] decision: rationale. Teksten i beskrivelsen rangerer ikke.</text>
|
||
|
||
<rect class="box soft" x="40" y="452" width="1120" height="86"/>
|
||
<text class="lbl" x="62" y="482">Id-en myntes av {sorterte koder, measure_type, claimed_saving_nok}, sha256[:16]</text>
|
||
<text class="sub" x="62" y="510">Identisk forslag gir identisk id. Det er slik en senere kjøring finner den tidligere dommen.</text>
|
||
<text class="tiny" x="62" y="530">Samme regel betyr at to dommer om samme kandidat deler filnavn: siste skriving vinner på disk, første i minnet.</text>
|
||
</svg>
|
||
<figcaption>ExpeL-folden. Folden er gatet på at basen har en IR-projeksjon å nøkle mot; en base uten en slik teller sine dommer som <code>unkeyed_verdicts</code> og rapporterer dem, i stedet for å slippe dem i stillhet.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Halv dom nektes ved navn.</b> <code>--decision</code> og <code>--rationale</code> går sammen eller ikke i det hele tatt. Fram til 1.1.0 defaultet <code>--decision</code> til <code>approved</code>, så hver flaggløs kjøring myntet en godkjenning ingen ga og bar den inn i neste prosjekts hypotese. Den defaulten er borte.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/verdicts.py:73-110</code> · <code>verdicts.py:214-277</code> · <code>verdicts.py:300-374</code> · <code>run.py:1551-1560</code> · <code>run.py:3166-3177</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-09 promotion-gate -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">27</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Promotion-porten er fail-closed: bare en godkjent dom blir wiki-kunnskap.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 430" role="img" aria-label="Promotion-porten som nekter alt som ikke er godkjent og skriver en type-verdict-fil naar den slipper gjennom">
|
||
<rect class="box" x="30" y="170" width="250" height="90"/>
|
||
<text class="lbl" x="50" y="200">Verdict</text>
|
||
<text class="sub" x="50" y="224">decision + rationale</text>
|
||
<text class="tiny" x="50" y="246">rått agent-output promoterer aldri seg selv</text>
|
||
<path class="edge" d="M280 215 H336"/>
|
||
|
||
<rect class="box accent" x="340" y="160" width="290" height="110"/>
|
||
<text class="lbl" x="360" y="190">promote_verdict</text>
|
||
<text class="sub" x="360" y="214">_APPROVED_DECISIONS:</text>
|
||
<text class="mono" x="360" y="238">approved</text>
|
||
<text class="mono" x="360" y="258">approved_with_adjustment</text>
|
||
<path class="edge warn" d="M630 195 C665 195 660 105 700 105"/>
|
||
<path class="edge ok" d="M630 235 C665 235 660 300 700 300"/>
|
||
|
||
<rect class="box warn" x="700" y="60" width="460" height="90"/>
|
||
<text class="lbl" x="722" y="90">PromotionRefused</text>
|
||
<text class="sub" x="722" y="114">skriver og lenker INGENTING</text>
|
||
<text class="tiny" x="722" y="136">samme nekt-familie som BudgetRefused og NotifyRefused</text>
|
||
|
||
<rect class="box ok" x="700" y="240" width="460" height="130"/>
|
||
<text class="lbl" x="722" y="270">promoted-verdict-{token}.md</text>
|
||
<text class="sub" x="722" y="294">frontmatter type: verdict, med sin EGEN strukturelle nøkkel</text>
|
||
<text class="sub" x="722" y="318">navigerbar for neste kjørings seed_store_from_bundle</text>
|
||
<text class="tiny" x="722" y="344">Indeks-lenken har en nøytral etikett, «Promotert ekspert-vurdering (gated)»,</text>
|
||
<text class="tiny" x="722" y="362">så signalet ikke kan lekke inn i prompten via bundle_context.</text>
|
||
</svg>
|
||
<figcaption>Tidsstempelet er et påkrevd argument uten wall-clock-default, så promoteringen er deterministisk og stempelet reproduserbart.</figcaption>
|
||
</figure>
|
||
<div class="cols">
|
||
<div class="col"><span class="step">hitl pending</span><p>Outboxens <code>verdict_id</code> minus innboksens id-er. Svaret er hvilke kandidater som fortsatt venter på et menneske.</p></div>
|
||
<div class="col"><span class="step">hitl route</span><p>Rutingtabell på kostnadskode-PREFIKS, ikke på <code>measure</code>. Measure er åpen prosa og ble målt som ikke-diskriminerende.</p></div>
|
||
<div class="col soft"><span class="step">Ingen match</span><p>Uroutbar rute får <code>expert=None</code> og sendes likevel ut. Flere treff gir laveste id og <code>ambiguous=True</code>.</p></div>
|
||
</div>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/verdicts.py:673</code> · <code>verdicts.py:699-773</code> · <code>hitl.py:159-165</code> · <code>hitl.py:347-391</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-10 outbox-artefakter -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">28</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>En kjøring etterlater seg deterministiske artefakter.</h2>
|
||
<pre><code>_dump(payload) = json.dumps(payload, sort_keys=True, indent=2) + "\n" # UTF-8</code></pre>
|
||
<p class="small">Sorterte nøkler, to mellomrom innrykk, eksplisitt avsluttende linjeskift. Ingen wall-clock og ingen uuid: <code>run_id</code> kommer fra kalleren, så samme kjøring gir byte-identiske filer.</p>
|
||
<div class="cols">
|
||
<div class="col">
|
||
<table class="compact">
|
||
<tr><th>Fil</th><th>Hva den bærer</th></tr>
|
||
<tr><td>-proposal.json</td><td>forslaget og provenance-stemplet</td></tr>
|
||
<tr><td>-outcome.json</td><td>validated, rejected eller unsupported, med verdict_id</td></tr>
|
||
<tr><td>-coverage.json</td><td>stoppgrunn og én rad per approach</td></tr>
|
||
<tr><td>-runconfig.json</td><td>profil, modeller, tak og top_k</td></tr>
|
||
<tr><td>-debate.json</td><td>verktøykall og deklarerte krav</td></tr>
|
||
<tr><td>-multibase.json</td><td>fullførte kjøringer, kollisjoner, budsjettstopp</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="col">
|
||
<table class="compact">
|
||
<tr><th>Fil</th><th>Hva den bærer</th></tr>
|
||
<tr><td>-prepass.json</td><td>forhåndspasset</td></tr>
|
||
<tr><td>-exploration.json</td><td>sporet fra Magentic-utforskningen</td></tr>
|
||
<tr><td>-plan-review.json</td><td>planen som venter på en signatur</td></tr>
|
||
<tr><td>-proposal-reviews.json</td><td>menneskets approve/revise per forsøk</td></tr>
|
||
<tr><td>-parse-failures.json</td><td>svar som ikke lot seg parse, ordrett</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<p class="callout warn"><b>To dokumenterte unntak.</b> <code>write_parse_failures</code> hevder ikke byte-determinisme, fordi innholdet er levende modellprosa, og skriver fra en <code>finally</code>. <code>write_exploration</code> er byte-deterministisk, men skriver også fra en <code>finally</code>.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/outbox.py:44-46</code> · <code>outbox.py:49-447</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3b-11 ledger-og-verdirapport -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">29</span><span class="part">Del 3 · Elementene</span></p>
|
||
<h2>Et validert forslag er en påstand. En ledger-post er et resultat.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 530" role="img" aria-label="Paastand mot resultat, med oere-regelen under">
|
||
<rect class="band accent" x="40" y="20" width="540" height="34"/>
|
||
<text class="band-lbl" x="60" y="42">PÅSTAND</text>
|
||
<rect class="band ok" x="620" y="20" width="540" height="34"/>
|
||
<text class="band-lbl" x="640" y="42">RESULTAT</text>
|
||
<path class="edge noarrow dashed" d="M600 20 V400"/>
|
||
|
||
<rect class="box" x="40" y="76" width="540" height="84"/>
|
||
<text class="lbl" x="62" y="104">Forslaget, med provenance</text>
|
||
<text class="sub" x="62" y="130">citations, modell, rolle, token_usage</text>
|
||
<text class="tiny" x="62" y="150">produsert av agentene under debatten</text>
|
||
|
||
<rect class="box ok" x="620" y="76" width="540" height="84"/>
|
||
<text class="lbl" x="642" y="104">Besparelsen materialiserte seg</text>
|
||
<text class="sub" x="642" y="130">en kontrakt ble endret, en faktura kom lavere</text>
|
||
<text class="tiny" x="642" y="150">et faktum om verden, ikke en slutning systemet kan trekke</text>
|
||
|
||
<rect class="box" x="40" y="176" width="540" height="84"/>
|
||
<text class="lbl" x="62" y="204">Den deterministiske validatoren</text>
|
||
<text class="sub" x="62" y="230">p10 · p50 · p90 · nominal_feasible</text>
|
||
<text class="tiny" x="62" y="250">tallene holdt, innenfor de rammene som ble oppgitt</text>
|
||
|
||
<rect class="box ok" x="620" y="176" width="540" height="84"/>
|
||
<text class="lbl" x="642" y="204">LedgerEntry, skrevet av et menneske</text>
|
||
<text class="sub" x="642" y="230">amount_ore: int, verdict_id, provenance-linje</text>
|
||
<text class="tiny" x="642" y="250">rammeverket skriver ALDRI ledgeren, og ingen kommando lager den som sideeffekt</text>
|
||
|
||
<rect class="box" x="40" y="276" width="540" height="84"/>
|
||
<text class="lbl" x="62" y="304">Checker-verdicten</text>
|
||
<text class="sub" x="62" y="330">resonnementet, ikke tallene</text>
|
||
<text class="tiny" x="62" y="350">to falsifikatorer på samme kandidat</text>
|
||
|
||
<rect class="box ok" x="620" y="276" width="540" height="84"/>
|
||
<text class="lbl" x="642" y="304">realize() er fail-closed</text>
|
||
<text class="sub" x="642" y="330">alt som ikke er godkjent gir RealizationRefused</text>
|
||
<text class="tiny" x="642" y="350">--report er kun lesing: null modellkall, null skriving</text>
|
||
|
||
<rect class="box soft" x="40" y="392" width="1120" height="118"/>
|
||
<text class="lbl" x="62" y="422">to_ore er rammeverkets ENE pengekonvertering</text>
|
||
<text class="mono" x="62" y="450">int((Decimal(str(nok)) * 100).quantize(Decimal("1"), rounding=ROUND_HALF_UP))</text>
|
||
<text class="sub" x="62" y="478">Kvantiser per beløp, SUMMER så heltallene. Tre linjer à 60 000,005 NOK gir 18 000 003 øre kvantisert først,</text>
|
||
<text class="sub" x="62" y="498">18 000 001 summert først. Heltallsaddisjon er assosiativ, så totalene er uavhengige av rekkefølge.</text>
|
||
</svg>
|
||
<figcaption>Å holde de to fra hverandre er en beslutning, ikke en mangel. Et validert forslag er en påstand systemet kan lage selv; en ledger-post er noe bare verden kan bekrefte.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>To nøkler, én telling.</b> 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.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/ledger.py:45-58</code> · <code>ledger.py:92-241</code> · <code>value_report.py:48-115</code> · <code>README.md</code> steg 7</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== part4-loops.html ===== -->
|
||
<!-- del4-divider -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h1>Arbeidsflyten og sløyfene</h1>
|
||
<p class="lede">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.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-ende-til-ende -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">30</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Arbeidsflyten går fra kunnskapsbase til realisert besparelse, og bare det midterste leddet er en kjøring.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 285" role="img" aria-label="Tidslinje i syv ledd fra kunnskapsbase til ledger, med aktør per ledd og to tilbakeføringer">
|
||
<rect class="box accent" x="8" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="82" y="40" text-anchor="middle">FAGPERSON</text>
|
||
<text class="lbl" x="82" y="64" text-anchor="middle">Kunnskapsbase</text>
|
||
<text class="tiny" x="82" y="88" text-anchor="middle">OKF-bundle: index.md</text>
|
||
<text class="tiny" x="82" y="104" text-anchor="middle">og konseptfiler</text>
|
||
<text class="tiny" x="82" y="120" text-anchor="middle">1-2 ukers arbeid</text>
|
||
|
||
<rect class="box" x="181" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="255" y="40" text-anchor="middle">OPERATØR</text>
|
||
<text class="lbl" x="255" y="64" text-anchor="middle">Bestillingen</text>
|
||
<text class="tiny" x="255" y="88" text-anchor="middle">mandat med approaches,</text>
|
||
<text class="tiny" x="255" y="104" text-anchor="middle">cost-baseline, tak</text>
|
||
<text class="tiny" x="255" y="120" text-anchor="middle">minutter</text>
|
||
|
||
<rect class="box soft" x="354" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="428" y="40" text-anchor="middle">MASKIN</text>
|
||
<text class="lbl" x="428" y="64" text-anchor="middle">Kjøringen</text>
|
||
<text class="tiny" x="428" y="88" text-anchor="middle">åtte steg: proposer,</text>
|
||
<text class="tiny" x="428" y="104" text-anchor="middle">checker, validator</text>
|
||
<text class="tiny" x="428" y="120" text-anchor="middle">sekunder til minutter</text>
|
||
|
||
<rect class="box soft" x="527" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="601" y="40" text-anchor="middle">MASKIN</text>
|
||
<text class="lbl" x="601" y="64" text-anchor="middle">Utboksen</text>
|
||
<text class="mono" x="601" y="88" text-anchor="middle">-proposal.json</text>
|
||
<text class="mono" x="601" y="104" text-anchor="middle">-outcome.json</text>
|
||
<text class="tiny" x="601" y="120" text-anchor="middle">byte-deterministisk</text>
|
||
|
||
<rect class="box accent" x="700" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="774" y="40" text-anchor="middle">FAGPERSON</text>
|
||
<text class="lbl" x="774" y="64" text-anchor="middle">Dommen</text>
|
||
<text class="mono" x="774" y="88" text-anchor="middle">innboks/{id}.json</text>
|
||
<text class="tiny" x="774" y="104" text-anchor="middle">én fil per dom</text>
|
||
<text class="tiny" x="774" y="120" text-anchor="middle">dager til uker</text>
|
||
|
||
<rect class="box accent" x="873" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="947" y="40" text-anchor="middle">FAGPERSON</text>
|
||
<text class="lbl" x="947" y="64" text-anchor="middle">Promotion</text>
|
||
<text class="tiny" x="947" y="88" text-anchor="middle">fail-closed port</text>
|
||
<text class="mono" x="947" y="104" text-anchor="middle">type: verdict</text>
|
||
<text class="tiny" x="947" y="120" text-anchor="middle">dager til måneder</text>
|
||
|
||
<rect class="box" x="1046" y="20" width="148" height="120"/>
|
||
<text class="tiny" x="1120" y="40" text-anchor="middle">OPERATØR</text>
|
||
<text class="lbl" x="1120" y="64" text-anchor="middle">Ledger</text>
|
||
<text class="tiny" x="1120" y="88" text-anchor="middle">realisert besparelse</text>
|
||
<text class="tiny" x="1120" y="104" text-anchor="middle">i hele øre, så --report</text>
|
||
<text class="tiny" x="1120" y="120" text-anchor="middle">måneder</text>
|
||
|
||
<path class="edge" d="M158 80 L179 80"/>
|
||
<path class="edge" d="M331 80 L352 80"/>
|
||
<path class="edge" d="M504 80 L525 80"/>
|
||
<path class="edge" d="M677 80 L698 80"/>
|
||
<path class="edge" d="M850 80 L871 80"/>
|
||
<path class="edge" d="M1023 80 L1044 80"/>
|
||
|
||
<path class="edge accent dashed" d="M774 142 L774 196 L428 196 L428 144"/>
|
||
<text class="tiny" x="601" y="190" text-anchor="middle">innboksen flettes inn FØR Steg 1-folden i neste kjøring</text>
|
||
|
||
<path class="edge accent" d="M947 142 L947 240 L82 240 L82 144"/>
|
||
<text class="tiny" x="500" y="258" text-anchor="middle">den promoterte dommen blir en fil i bundlen, og neste kjøring navigerer den som all annen kunnskap</text>
|
||
</svg>
|
||
<figcaption>Blå = fagpersonen handler. Hvit = operatøren. Grå = maskinen. De to tilbakeføringene er hele læringen: den stiplede er Steg 7, den heltrukne er Steg 8.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>shared/method-spec.md</code> §3 · <code>src/portfolio_optimiser/run.py:1180-1187</code> · <code>src/portfolio_optimiser/verdicts.py:699-773</code> · <code>docs/knowledge-base-recipe.md:12</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-tilstandsmaskin -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">31</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Én kjøring er en tilstandsmaskin der hvert tak er påkrevd, ikke valgfritt.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 440" role="img" aria-label="Tilstandsmaskin for én kjøring: steg 0 over løkka, steg 1 til 4 på rad, tre utfall, refine-sløyfe tilbake til steg 2">
|
||
<rect class="box soft dashed" x="50" y="10" width="1100" height="58"/>
|
||
<text class="lbl" x="70" y="34">Steg 0 · explore (opt-in, Magentic manager)</text>
|
||
<text class="tiny" x="70" y="56">ExplorationContract: seks tak, alle påkrevd, ingen default. En utelatt grense ville falt tilbake på en ubegrenset loop, ikke en forsiktig en.</text>
|
||
|
||
<rect class="box" x="50" y="110" width="250" height="95"/>
|
||
<text class="lbl" x="175" y="138" text-anchor="middle">Steg 1 · Forstå</text>
|
||
<text class="tiny" x="175" y="160" text-anchor="middle">rammeverket, deterministisk</text>
|
||
<text class="mono" x="175" y="182" text-anchor="middle">top_k = 3</text>
|
||
|
||
<rect class="box" x="333" y="110" width="250" height="95"/>
|
||
<text class="lbl" x="458" y="138" text-anchor="middle">Steg 2 · Hypotese</text>
|
||
<text class="tiny" x="458" y="160" text-anchor="middle">proposer-agenten</text>
|
||
<text class="mono" x="458" y="182" text-anchor="middle">én typet IR</text>
|
||
|
||
<rect class="box" x="616" y="110" width="250" height="95"/>
|
||
<text class="lbl" x="741" y="138" text-anchor="middle">Steg 3 · Debatt</text>
|
||
<text class="tiny" x="741" y="160" text-anchor="middle">proposer ⇄ checker</text>
|
||
<text class="mono" x="741" y="182" text-anchor="middle">max_rounds = 3</text>
|
||
|
||
<rect class="box" x="899" y="110" width="250" height="95"/>
|
||
<text class="lbl" x="1024" y="138" text-anchor="middle">Steg 4 · Valider</text>
|
||
<text class="tiny" x="1024" y="160" text-anchor="middle">validator + checker</text>
|
||
<text class="mono" x="1024" y="182" text-anchor="middle">0.30-grensen, p10/p50/p90</text>
|
||
|
||
<path class="edge" d="M300 157 L331 157"/>
|
||
<path class="edge" d="M583 157 L614 157"/>
|
||
<path class="edge" d="M866 157 L897 157"/>
|
||
|
||
<path class="edge soft noarrow" d="M1024 207 L1024 225"/>
|
||
<path class="edge soft noarrow" d="M175 225 L1024 225"/>
|
||
<path class="edge" d="M175 225 L175 248"/>
|
||
<path class="edge" d="M600 225 L600 248"/>
|
||
<path class="edge" d="M1015 225 L1015 248"/>
|
||
|
||
<rect class="box warn" x="50" y="250" width="250" height="70"/>
|
||
<text class="lbl" x="175" y="278" text-anchor="middle">Rejection</text>
|
||
<text class="tiny" x="175" y="300" text-anchor="middle">grunn, ingen persentiler</text>
|
||
|
||
<rect class="box soft" x="470" y="250" width="260" height="70"/>
|
||
<text class="lbl" x="600" y="278" text-anchor="middle">Unsupported</text>
|
||
<text class="tiny" x="600" y="300" text-anchor="middle">tallene holdt, intet krav erklært</text>
|
||
|
||
<rect class="box ok" x="880" y="250" width="270" height="70"/>
|
||
<text class="lbl" x="1015" y="278" text-anchor="middle">ValidatedProposal</text>
|
||
<text class="tiny" x="1015" y="300" text-anchor="middle">p10 / p50 / p90</text>
|
||
|
||
<path class="edge" d="M175 322 L175 335 L420 335 L420 348"/>
|
||
<rect class="box accent" x="333" y="350" width="250" height="70"/>
|
||
<text class="lbl" x="458" y="378" text-anchor="middle">Steg 5 · Refine</text>
|
||
<text class="mono" x="458" y="400" text-anchor="middle">max_attempts = 3</text>
|
||
<path class="edge accent" d="M520 348 L520 209"/>
|
||
|
||
<text class="tiny" x="600" y="372">kun SISTE reason,</text>
|
||
<text class="tiny" x="600" y="390">ordrett, aldri JSON-en</text>
|
||
<text class="tiny" x="600" y="408">og ingen CLI-flagg for taket</text>
|
||
|
||
<path class="edge" d="M600 322 L600 338 L960 338 L960 348"/>
|
||
<path class="edge" d="M1050 322 L1050 348"/>
|
||
<rect class="box" x="880" y="350" width="270" height="70"/>
|
||
<text class="lbl" x="1015" y="378" text-anchor="middle">Steg 6 · Utboks</text>
|
||
<text class="mono" x="1015" y="400" text-anchor="middle">{run_id}-*.json + verdict key</text>
|
||
</svg>
|
||
<figcaption>Steg 7 og 8 står ikke her. De skjer etter at prosessen er død, og er temaet tre slides fram.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Ingen henger, alltid en typet stopp.</b> <code>BudgetExceeded(kind, limit, observed)</code> med <code>kind</code> i <code>{tokens, rounds, exploration_rounds}</code>. Standardtakene er <code>max_rounds = 3</code> og <code>max_tokens = 100 000</code>, og et cap-objekt nekter å konstrueres med en ikke-positiv verdi. Tokens telles fra leverandørens egen <code>usage</code>, aldri et ord-estimat.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/run.py:168-169</code> · <code>generate.py:559</code> · <code>workflow.py:110-116</code> · <code>explore.py:82-99</code> · <code>budget.py:30-44</code> · <code>validator.py:39</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-tre-porter -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">32</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Tre porter dømmer den samme kandidaten, og de slås aldri sammen til ett felt.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 320" role="img" aria-label="Kandidaten gjennom validatoren til tre utfall, og checker-porten som bare kan overstyre et validert utfall">
|
||
<rect class="box" x="20" y="120" width="160" height="80"/>
|
||
<text class="lbl" x="100" y="152" text-anchor="middle">Kandidaten</text>
|
||
<text class="tiny" x="100" y="174" text-anchor="middle">den typede IR-en</text>
|
||
<path class="edge" d="M182 160 L226 160"/>
|
||
|
||
<rect class="box warn" x="230" y="90" width="270" height="140"/>
|
||
<text class="lbl" x="365" y="118" text-anchor="middle">Validatoren</text>
|
||
<text class="tiny" x="365" y="140" text-anchor="middle">TALLENE · blokkerende</text>
|
||
<text class="tiny" x="365" y="162" text-anchor="middle">stadie 0: cost-baseline, 5 % toleranse</text>
|
||
<text class="tiny" x="365" y="182" text-anchor="middle">0.30-grensen på hver kostnadslinje</text>
|
||
<text class="tiny" x="365" y="202" text-anchor="middle">Monte Carlo, seedet, 512 trekk</text>
|
||
|
||
<path class="edge soft noarrow" d="M502 160 L520 160"/>
|
||
<path class="edge soft noarrow" d="M520 70 L520 250"/>
|
||
<path class="edge" d="M520 70 L556 70"/>
|
||
<path class="edge" d="M520 160 L556 160"/>
|
||
<path class="edge" d="M520 250 L556 250"/>
|
||
|
||
<rect class="box warn" x="560" y="40" width="250" height="60"/>
|
||
<text class="lbl" x="685" y="66" text-anchor="middle">Rejection</text>
|
||
<text class="tiny" x="685" y="86" text-anchor="middle">grunn, ingen persentiler</text>
|
||
|
||
<rect class="box soft" x="560" y="130" width="250" height="60"/>
|
||
<text class="lbl" x="685" y="156" text-anchor="middle">Unsupported</text>
|
||
<text class="tiny" x="685" y="176" text-anchor="middle">intet krav erklært for retningen</text>
|
||
|
||
<rect class="box ok" x="560" y="220" width="250" height="60"/>
|
||
<text class="lbl" x="685" y="246" text-anchor="middle">ValidatedProposal</text>
|
||
<text class="tiny" x="685" y="266" text-anchor="middle">p10 / p50 / p90</text>
|
||
|
||
<path class="edge" d="M812 250 L876 250"/>
|
||
<rect class="box" x="880" y="200" width="290" height="100"/>
|
||
<text class="lbl" x="1025" y="228" text-anchor="middle">Checker-porten</text>
|
||
<text class="tiny" x="1025" y="250" text-anchor="middle">RESONNEMENTET · fail-open</text>
|
||
<text class="tiny" x="1025" y="270" text-anchor="middle">kun en eksplisitt VERDICT: REJECT</text>
|
||
<text class="tiny" x="1025" y="288" text-anchor="middle">overstyrer. Ingen markør blokkerer.</text>
|
||
|
||
<path class="edge warn" d="M1020 198 L1020 70 L814 70"/>
|
||
<text class="tiny" x="900" y="60" text-anchor="middle">REJECT overstyrer</text>
|
||
</svg>
|
||
<figcaption>Unsupported arver fra Rejection i koden, men er en egen type: tallene holdt, og nettopp derfor er det ikke en numerisk avvisning. Den summeres aldri.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Spec-en sier det som en regel:</b> 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 <code>unsupported</code>, verken validert eller avvist.</p>
|
||
<p class="src">Kilde: <code>shared/method-spec.md</code> §2, §9 · <code>src/portfolio_optimiser/validator.py:39</code>, <code>:67-68</code>, <code>:97-114</code> · <code>run.py:673-687</code> · <code>README.md:502-509</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-tidsskala-stigen -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">33</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Sløyfene er ikke like lange, og det er hele poenget med arkitekturen.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 420" role="img" aria-label="Tidsskala-stige i fem kolonner fra sekunder til måneder, med sløyfene plassert, hvem som lukker dem og hva som krysser">
|
||
<rect class="band" x="712" y="8" width="478" height="384"/>
|
||
<path class="hair" d="M238 30 L238 392"/>
|
||
<path class="hair" d="M476 30 L476 392"/>
|
||
<path class="hair" d="M714 30 L714 392"/>
|
||
<path class="hair" d="M952 30 L952 392"/>
|
||
<text class="band-lbl" x="124" y="24" text-anchor="middle">Sekunder</text>
|
||
<text class="band-lbl" x="362" y="24" text-anchor="middle">Minutter</text>
|
||
<text class="band-lbl" x="600" y="24" text-anchor="middle">Timer</text>
|
||
<text class="band-lbl" x="838" y="24" text-anchor="middle">Dager til uker</text>
|
||
<text class="band-lbl" x="1076" y="24" text-anchor="middle">Måneder</text>
|
||
|
||
<rect class="box soft" x="16" y="40" width="216" height="66"/>
|
||
<text class="sub" x="26" y="61">Chat-tur</text>
|
||
<text class="tiny" x="26" y="79">lukkes av modellen</text>
|
||
<text class="tiny" x="26" y="96">ChatResponse + usage_details</text>
|
||
<rect class="box soft" x="16" y="116" width="216" height="66"/>
|
||
<text class="sub" x="26" y="137">Debattrunde</text>
|
||
<text class="tiny" x="26" y="155">lukkes av checkerens VERDICT</text>
|
||
<text class="tiny" x="26" y="172">proposerens konvergerte tekst</text>
|
||
<rect class="box soft" x="16" y="192" width="216" height="66"/>
|
||
<text class="sub" x="26" y="213">Parse-feil-retry</text>
|
||
<text class="tiny" x="26" y="231">lukkes av IR-parseren</text>
|
||
<text class="tiny" x="26" y="248">kun parse-grunnen</text>
|
||
<rect class="box soft" x="16" y="268" width="216" height="66"/>
|
||
<text class="sub" x="26" y="289">Avvisning inn i refine</text>
|
||
<text class="tiny" x="26" y="307">lukkes av validatoren</text>
|
||
<text class="tiny" x="26" y="324">kun siste grunn, ordrett</text>
|
||
|
||
<rect class="box accent" x="254" y="40" width="216" height="66"/>
|
||
<text class="sub" x="264" y="61">--proposal-review</text>
|
||
<text class="tiny" x="264" y="79">et menneske ved tastaturet</text>
|
||
<text class="tiny" x="264" y="96">approve, eller revise med tekst</text>
|
||
<rect class="box accent" x="254" y="116" width="216" height="66"/>
|
||
<text class="sub" x="264" y="137">--plan-review, synkron</text>
|
||
<text class="tiny" x="264" y="155">et menneske ved tastaturet</text>
|
||
<text class="tiny" x="264" y="172">planen ut, godkjenning inn</text>
|
||
<rect class="box" x="254" y="192" width="216" height="66"/>
|
||
<text class="sub" x="264" y="213">costsim</text>
|
||
<text class="tiny" x="264" y="231">operatøren, før pengene</text>
|
||
<text class="tiny" x="264" y="248">en hva-hvis-tabell i hele øre</text>
|
||
<rect class="box" x="254" y="268" width="216" height="66"/>
|
||
<text class="sub" x="264" y="289">Run A / Run B, offline</text>
|
||
<text class="tiny" x="264" y="307">testsuiten og demoen</text>
|
||
<text class="tiny" x="264" y="324">to markører via filsystemet</text>
|
||
|
||
<rect class="box" x="492" y="40" width="216" height="66"/>
|
||
<text class="sub" x="502" y="61">Stressrunde + judge</text>
|
||
<text class="tiny" x="502" y="79">judgen leser rundens artefakter</text>
|
||
<text class="tiny" x="502" y="96">{run_id}-*.json + fasit.json</text>
|
||
<rect class="box" x="492" y="116" width="216" height="66"/>
|
||
<text class="sub" x="502" y="137">--across-bundle</text>
|
||
<text class="tiny" x="502" y="155">én bestilling, flere baser</text>
|
||
<text class="tiny" x="502" y="172">ett verdict-store på tvers</text>
|
||
|
||
<rect class="box accent" x="730" y="40" width="216" height="66"/>
|
||
<text class="sub" x="740" y="61">Parkert plan review</text>
|
||
<text class="tiny" x="740" y="79">et menneske, en annen dag</text>
|
||
<text class="tiny" x="740" y="96">spørsmålsfil + svarfil</text>
|
||
<rect class="box accent" x="730" y="116" width="216" height="66"/>
|
||
<text class="sub" x="740" y="137">Ekspert-dom i innboksen</text>
|
||
<text class="tiny" x="740" y="155">en fagperson skriver JSON</text>
|
||
<text class="tiny" x="740" y="172">{id}.json, én fil per dom</text>
|
||
<rect class="box" x="730" y="192" width="216" height="66"/>
|
||
<text class="sub" x="740" y="213">v1-gaten</text>
|
||
<text class="tiny" x="740" y="231">operatøren, per runde</text>
|
||
<text class="tiny" x="740" y="248">tre runder ekte tilbakemelding</text>
|
||
<rect class="box accent" x="730" y="268" width="216" height="66"/>
|
||
<text class="sub" x="740" y="289">Ny kunnskapsbase</text>
|
||
<text class="tiny" x="740" y="307">et team, 1-2 ukers arbeid</text>
|
||
<text class="tiny" x="740" y="324">kildefiler blir OKF-konsepter</text>
|
||
|
||
<rect class="box accent" x="968" y="40" width="216" height="66"/>
|
||
<text class="sub" x="978" y="61">Promotion i wikien</text>
|
||
<text class="tiny" x="978" y="79">et menneske, eksplisitt port</text>
|
||
<text class="tiny" x="978" y="96">type: verdict-konseptfil</text>
|
||
<rect class="box ok" x="968" y="116" width="216" height="66"/>
|
||
<text class="sub" x="978" y="137">Realisert besparelse</text>
|
||
<text class="tiny" x="978" y="155">virkeligheten: en lavere faktura</text>
|
||
<text class="tiny" x="978" y="172">LedgerEntry i hele øre</text>
|
||
<rect class="box" x="968" y="192" width="216" height="66"/>
|
||
<text class="sub" x="978" y="213">--report</text>
|
||
<text class="tiny" x="978" y="231">operatøren</text>
|
||
<text class="tiny" x="978" y="248">per prosjekt og portefølje</text>
|
||
|
||
<text class="band-lbl" x="951" y="384" text-anchor="middle">disse to kolonnene krysser bare som filer</text>
|
||
</svg>
|
||
<figcaption>Farge = hvem som lukker sløyfa. Grå: maskinen. Hvit: operatøren eller testsuiten. Blå: et menneske. Grønn: verden utenfor. Varighetene er lest ut av dokumentasjonen og koden, ikke målt med klokke. Repoet måler tokens og filer, aldri veggtid.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>shared/method-spec.md</code> §3 Steg 7, §8 · <code>src/portfolio_optimiser/generate.py</code>, <code>workflow.py</code>, <code>proposal_review.py</code>, <code>hitl.py</code>, <code>verdicts.py</code>, <code>ledger.py</code>, <code>costsim.py</code>, <code>stress.py</code> · <code>docs/knowledge-base-recipe.md:12</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-korte-sloyfer -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">34</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>De korte sløyfene lukkes på sekunder, og hver av dem bærer bare grunnen videre.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 430" role="img" aria-label="Tre sekvenspaneler: chat-tur, debattrunde, og avvisning inn i neste forsøk">
|
||
<rect class="band" x="0" y="26" width="1200" height="118"/>
|
||
<text class="band-lbl" x="16" y="44">Chat-tur</text>
|
||
<rect class="box" x="30" y="58" width="200" height="62"/>
|
||
<text class="lbl" x="130" y="94" text-anchor="middle">proposer</text>
|
||
<rect class="box" x="560" y="58" width="230" height="62"/>
|
||
<text class="lbl" x="675" y="94" text-anchor="middle">BaseChatClient</text>
|
||
<rect class="box soft" x="850" y="58" width="310" height="62"/>
|
||
<text class="sub" x="1005" y="82" text-anchor="middle">TokenMeter + BudgetMiddleware</text>
|
||
<text class="tiny" x="1005" y="102" text-anchor="middle">manglende usage feiler lukket</text>
|
||
<path class="edge" d="M232 80 L556 80"/>
|
||
<text class="tiny" x="394" y="74" text-anchor="middle">get_response(messages, response_format=…)</text>
|
||
<path class="edge" d="M556 112 L234 112"/>
|
||
<text class="tiny" x="394" y="106" text-anchor="middle">ChatResponse + usage_details, belastes straks</text>
|
||
<path class="edge soft" d="M792 90 L848 90"/>
|
||
|
||
<rect class="band" x="0" y="160" width="1200" height="118"/>
|
||
<text class="band-lbl" x="16" y="178">Debattrunde, GroupChat med round-robin</text>
|
||
<rect class="box" x="30" y="192" width="200" height="62"/>
|
||
<text class="lbl" x="130" y="228" text-anchor="middle">proposer</text>
|
||
<rect class="box" x="560" y="192" width="230" height="62"/>
|
||
<text class="lbl" x="675" y="228" text-anchor="middle">checker</text>
|
||
<rect class="box soft" x="850" y="192" width="310" height="62"/>
|
||
<text class="sub" x="1005" y="216" text-anchor="middle">max_rounds = 3</text>
|
||
<text class="tiny" x="1005" y="236" text-anchor="middle">begge deltakere overflates, så run.py</text>
|
||
<text class="tiny" x="1005" y="250" text-anchor="middle">kan skille dem på author_name</text>
|
||
<path class="edge" d="M232 214 L556 214"/>
|
||
<text class="tiny" x="394" y="208" text-anchor="middle">kandidaten, som prosa</text>
|
||
<path class="edge" d="M556 246 L234 246"/>
|
||
<text class="tiny" x="394" y="240" text-anchor="middle">VERDICT: APPROVE eller VERDICT: REJECT med grunn</text>
|
||
|
||
<rect class="band accent" x="0" y="294" width="1200" height="126"/>
|
||
<text class="band-lbl" x="16" y="312">Avvisning inn i neste forsøk</text>
|
||
<rect class="box warn" x="20" y="326" width="200" height="62"/>
|
||
<text class="lbl" x="120" y="362" text-anchor="middle">validatoren</text>
|
||
<rect class="box" x="420" y="326" width="300" height="62"/>
|
||
<text class="lbl" x="570" y="352" text-anchor="middle">prompt-byggeren</text>
|
||
<text class="tiny" x="570" y="376" text-anchor="middle">blokk 3 av fire mulige</text>
|
||
<rect class="box" x="920" y="326" width="250" height="62"/>
|
||
<text class="lbl" x="1045" y="352" text-anchor="middle">proposer</text>
|
||
<text class="tiny" x="1045" y="376" text-anchor="middle">forsøk i + 1</text>
|
||
<path class="edge" d="M222 356 L418 356"/>
|
||
<text class="tiny" x="320" y="338" text-anchor="middle">kun grunnen</text>
|
||
<text class="tiny" x="320" y="350" text-anchor="middle">aldri JSON-en</text>
|
||
<path class="edge" d="M722 356 L918 356"/>
|
||
<text class="tiny" x="820" y="338" text-anchor="middle">max_attempts = 3</text>
|
||
<text class="tiny" x="820" y="350" text-anchor="middle">kun den siste</text>
|
||
<text class="tiny" x="570" y="410" text-anchor="middle">fast rekkefølge: base · approach · rejection · feedback · parse-feil</text>
|
||
</svg>
|
||
<figcaption>Alle tre lukkes uten at noe forlater prosessen. Avvisningene samles opp i <code>RunResult.refinements</code>, så en leser kan se hva kjøringen faktisk ble fortalt.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Målt, ikke antatt.</b> Før parse-grunnen ble båret videre, kalte <code>_fetch_parsed</code> modellen med byte-identisk prompt. Én betalt kjøring (<code>kontrakt-sorasen-04</code>) brukte elleve av sine tolv runder på svar som feilet på samme måte, fordi ingenting noensinne fortalte modellen hva som var galt.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/generate.py:282-327</code>, <code>:642-673</code> · <code>workflow.py:100-116</code> · <code>run.py:664-687</code>, <code>:204-214</code> · <code>budget.py:44</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-mellomlange-sloyfer -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">35</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>De mellomlange sløyfene kjøper informasjon før pengene brukes, og beviser at læringen går gjennom filsystemet.</h2>
|
||
<div class="cols">
|
||
<div class="col">
|
||
<span class="step">Terminaldørene</span>
|
||
<p>Avbryter inne i forsøksløkka på en kandidat validatoren alt godtok. Lukket vokabular: <code>approve</code> eller <code>revise <tekst></code>. Et <code>revise</code> kjøper ett forsøk til, og preger ingen dom.</p>
|
||
</div>
|
||
<div class="col">
|
||
<span class="step">Planen, synkront</span>
|
||
<p>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å <code>/readiness</code>.</p>
|
||
</div>
|
||
<div class="col soft">
|
||
<span class="step">Før pengene</span>
|
||
<p>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å.</p>
|
||
</div>
|
||
</div>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 420" role="img" aria-label="Run A og Run B med to atskilte markører, den ene via promotion, den andre via innboksen">
|
||
<rect class="box soft" x="20" y="110" width="340" height="120"/>
|
||
<text class="lbl" x="190" y="140" text-anchor="middle">Run A</text>
|
||
<text class="tiny" x="190" y="164" text-anchor="middle">tom wiki, uinformert hypotese</text>
|
||
<text class="tiny" x="190" y="184" text-anchor="middle">validatoren falsifiserer første krav</text>
|
||
<text class="tiny" x="190" y="204" text-anchor="middle">det refinerte kravet validerer</text>
|
||
<text class="tiny" x="190" y="222" text-anchor="middle">personaen feller sin dom</text>
|
||
|
||
<rect class="box accent" x="440" y="40" width="320" height="100"/>
|
||
<text class="lbl" x="600" y="66" text-anchor="middle">Steg 8 · promotion</text>
|
||
<text class="tiny" x="600" y="88" text-anchor="middle">promote_verdict skriver en fil i bundlen</text>
|
||
<text class="tiny" x="600" y="106" text-anchor="middle">seed_store_from_bundle leser den igjen</text>
|
||
<text class="tiny" x="600" y="126" text-anchor="middle">markør 1: promoter, seed på nytt, fold</text>
|
||
|
||
<rect class="box accent" x="440" y="210" width="320" height="100"/>
|
||
<text class="lbl" x="600" y="236" text-anchor="middle">Steg 7 · innboksen</text>
|
||
<text class="tiny" x="600" y="258" text-anchor="middle">write_verdict legger {id}.json i mappa</text>
|
||
<text class="tiny" x="600" y="276" text-anchor="middle">load_verdicts_from_dir fletter den inn</text>
|
||
<text class="tiny" x="600" y="296" text-anchor="middle">markør 2: skriv fil, flett, fold</text>
|
||
|
||
<rect class="box soft" x="840" y="110" width="340" height="120"/>
|
||
<text class="lbl" x="1010" y="140" text-anchor="middle">Run B</text>
|
||
<text class="tiny" x="1010" y="164" text-anchor="middle">samme base, seedet på nytt</text>
|
||
<text class="tiny" x="1010" y="184" text-anchor="middle">begge markørene står i generasjons-</text>
|
||
<text class="tiny" x="1010" y="204" text-anchor="middle">prompten før hypotesen finnes</text>
|
||
|
||
<path class="edge accent" d="M362 150 L438 94"/>
|
||
<path class="edge accent" d="M362 192 L438 256"/>
|
||
<path class="edge accent" d="M762 94 L838 150"/>
|
||
<path class="edge accent" d="M762 256 L838 192"/>
|
||
|
||
<rect class="band ok" x="20" y="336" width="1160" height="66"/>
|
||
<text class="mono" x="600" y="362" text-anchor="middle">marker_in_run_a_prompt == False · marker_in_run_b_prompt == True</text>
|
||
<text class="mono" x="600" y="386" text-anchor="middle">inbox_marker_in_run_a_prompt == False · inbox_marker_in_run_b_prompt == True</text>
|
||
</svg>
|
||
<figcaption>To markører, med vilje forskjellige. Begge veiene ender i den samme prompten, og én delt markør ville latt den ene bære beviset alene. Ingenting krysser i minnet.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/simulation.py:124-128</code>, <code>:505-525</code> · <code>proposal_review.py:23-27</code>, <code>:248-305</code> · <code>hosting.py:200-205</code> · <code>costsim.py:1-16</code> · <code>README.md:114-118</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-lange-sloyfer -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">36</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>De lange sløyfene krysser prosessgrenser, og derfor krysser de alltid som filer.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 500" role="img" aria-label="Fem rader: hvem handler og når til venstre, hva som krysser grensen som fil til høyre">
|
||
<text class="band-lbl" x="40" y="30">Hvem handler, og når</text>
|
||
<text class="band-lbl" x="640" y="30">Hva som krysser grensen</text>
|
||
|
||
<rect class="box soft" x="40" y="50" width="520" height="78"/>
|
||
<text class="lbl" x="60" y="78">Kjøringen slutter</text>
|
||
<text class="tiny" x="60" y="98">rammeverket skriver utboksen og dør</text>
|
||
<text class="tiny" x="60" y="116">sekunder til minutter etter start</text>
|
||
<path class="edge" d="M562 89 L638 89"/>
|
||
<rect class="box" x="640" y="50" width="520" height="78"/>
|
||
<text class="mono" x="660" y="78">{run_id}-outcome.json</text>
|
||
<text class="tiny" x="660" y="98">byte-deterministisk, med verdict key</text>
|
||
<text class="tiny" x="660" y="116">nøkkelen en framtidig dom vil lande under</text>
|
||
|
||
<rect class="box accent" x="40" y="140" width="520" height="78"/>
|
||
<text class="lbl" x="60" y="168">Fagpersonen svarer</text>
|
||
<text class="tiny" x="60" y="188">leser utboksen, skriver én JSON-fil i innboksen</text>
|
||
<text class="tiny" x="60" y="206">dager til uker senere, i en helt annen prosess</text>
|
||
<path class="edge" d="M562 179 L638 179"/>
|
||
<rect class="box" x="640" y="140" width="520" height="78"/>
|
||
<text class="mono" x="660" y="168">innboks/{id}.json</text>
|
||
<text class="tiny" x="660" y="188">én fil per dom, tolerant lest: en halvskrevet fil hoppes over</text>
|
||
<text class="tiny" x="660" y="206">systemet leser innboksen, eksperten skriver den</text>
|
||
|
||
<rect class="box soft" x="40" y="230" width="520" height="78"/>
|
||
<text class="lbl" x="60" y="258">Neste kjøring</text>
|
||
<text class="tiny" x="60" y="278">fletter innboksen inn FØR Steg 1-folden</text>
|
||
<text class="tiny" x="60" y="296">en prosess som aldri så den forrige kjøringen</text>
|
||
<path class="edge" d="M562 269 L638 269"/>
|
||
<rect class="box" x="640" y="230" width="520" height="78"/>
|
||
<text class="mono" x="660" y="258">Relevant prior verdicts (ExpeL few-shot)</text>
|
||
<text class="tiny" x="660" y="278">de tre nærmeste dommene, rangert strukturelt</text>
|
||
<text class="tiny" x="660" y="296">limt foran hypotese-prompten</text>
|
||
|
||
<rect class="box accent" x="40" y="320" width="520" height="78"/>
|
||
<text class="lbl" x="60" y="348">Promotion-porten</text>
|
||
<text class="tiny" x="60" y="368">eksplisitt, fail-closed, aldri koblet inn i kjøringen</text>
|
||
<text class="tiny" x="60" y="386">dager til måneder senere</text>
|
||
<path class="edge" d="M562 359 L638 359"/>
|
||
<rect class="box" x="640" y="320" width="520" height="78"/>
|
||
<text class="mono" x="660" y="348">promoted-verdict-*.md</text>
|
||
<text class="tiny" x="660" y="368">type: verdict, med nøytral lenke fra index.md</text>
|
||
<text class="tiny" x="660" y="386">etiketten bærer ingen dom, ellers ville signalet lekket rundt porten</text>
|
||
|
||
<rect class="box ok" x="40" y="410" width="520" height="78"/>
|
||
<text class="lbl" x="60" y="438">Virkeligheten</text>
|
||
<text class="tiny" x="60" y="458">kontrakten ble endret, fakturaen kom lavere</text>
|
||
<text class="tiny" x="60" y="476">måneder senere, skrevet av et menneske</text>
|
||
<path class="edge" d="M562 449 L638 449"/>
|
||
<rect class="box" x="640" y="410" width="520" height="78"/>
|
||
<text class="mono" x="660" y="438">savings-ledger.json</text>
|
||
<text class="tiny" x="660" y="458">LedgerEntry i hele øre, aldri skrevet av rammeverket</text>
|
||
<text class="tiny" x="660" y="476">et validert forslag er en påstand, en ledger-rad er et resultat</text>
|
||
</svg>
|
||
<figcaption>Ingen av de fem lever i samme prosess som naboen. Systemet må være fullt gjenopptakbart mellom kjøringer atskilt i tid, uten antakelse om en levende sesjon.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>shared/method-spec.md</code> §3 Steg 7-8, §5, §6 · <code>src/portfolio_optimiser/run.py:1180-1187</code> · <code>verdicts.py:214-240</code>, <code>:673-678</code>, <code>:732-736</code> · <code>ledger.py:216-226</code> · <code>README.md:231-237</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-mennesket -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">37</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Ingen steder i kjørestien er et menneske påkrevd, og kjøringen sier det høyt når ingen dømte.</h2>
|
||
<table class="compact">
|
||
<tr><th>Sted i arbeidsflyten</th><th>Menneske?</th><th>Døra</th><th>Hva skjer uten</th></tr>
|
||
<tr><td>Steg 1 til 6, hele kjøringen</td><td>Nei. Ved validatoren og checker-porten er mennesket fraværende ved konstruksjon</td><td>ingen</td><td>kjøringen fullfører og skriver <code>no expert verdict given; verdict key=…</code></td></tr>
|
||
<tr><td>Review av et validert forslag</td><td>Valgfritt</td><td><code>--proposal-review</code></td><td>ingen review, og intet ekstra forsøk kjøpes</td></tr>
|
||
<tr><td>Plan review under <code>--explore</code></td><td>Påkrevd når den er slått på</td><td><code>--plan-review</code></td><td>input som slutter uten svar er en feil, aldri et samtykke</td></tr>
|
||
<tr><td>Dom på denne kjøringen</td><td>Valgfritt</td><td><code>--decision</code> + <code>--rationale</code></td><td>ingen dom registreres; halve nektes ved navn</td></tr>
|
||
<tr><td>Dom dager senere</td><td>Valgfritt</td><td>innboks-mappa</td><td>neste kjøring folder ingenting nytt inn</td></tr>
|
||
<tr><td>Promotion inn i wikien</td><td>Påkrevd</td><td><code>promote_verdict</code></td><td>wikien vokser ikke; ingenting krysser porten</td></tr>
|
||
<tr><td>Realisert besparelse</td><td>Påkrevd</td><td><code>ledger.realize</code></td><td><code>--report</code> nekter: <code>savings ledger not found</code></td></tr>
|
||
</table>
|
||
<p class="callout"><b>De to halvdelene.</b> <code>--decision</code> og <code>--rationale</code> går sammen eller ikke i det hele tatt. Fram til 1.1.0 defaultet <code>--decision</code> til <code>approved</code>, så hver flaggløs kjøring registrerte en godkjenning ingen hadde gitt. Den defaulten er borte.</p>
|
||
<p class="callout warn"><b>Status, uten pynt.</b> 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 (<code>BudgetExceeded</code>, rounds 12/13), gjenkjøringen konkluderte korrekt i <code>rejected</code>. Ingen kjøring har ennå produsert et validert forslag mot en levende modell.</p>
|
||
<p class="src">Kilde: <code>README.md:172-177</code>, <code>:231-237</code>, <code>:281-297</code>, <code>:545-556</code> · <code>src/portfolio_optimiser/run.py:746-758</code>, <code>:3162-3176</code> · <code>ledger.py:213-218</code> · <code>verdicts.py:706-708</code> · <code>docs/ekspert-svar.md:7-11</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-terminologi -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">38</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Begrepene er ikke våre, de står ordrett i spec-en som begge implementasjonene deler.</h2>
|
||
<div class="cols">
|
||
<div class="col">
|
||
<span class="step">Lagene og læringen</span>
|
||
<table class="compact">
|
||
<tr><th>Begrep</th><th>Ordrett fra <code>shared/method-spec.md</code></th></tr>
|
||
<tr><td>Context layer <span class="small">§2</span></td><td>«one curated, version-controlled knowledge bundle per project (an 'LLM wiki') in the open OKF format»</td></tr>
|
||
<tr><td>Output layer <span class="small">§2</span></td><td>«a run-scoped folder structure of raw results … Append-heavy, never part of the wiki.»</td></tr>
|
||
<tr><td>Promotion gate <span class="small">§2</span></td><td>«the only path from the output layer into the context layer. Only expert-approved knowledge crosses it.»</td></tr>
|
||
<tr><td>IR <span class="small">§2, §7.1</span></td><td>«the typed intermediate representation of a candidate measure»</td></tr>
|
||
<tr><td>Store <span class="small">§2, §4.2</span></td><td>«the in-memory collection of historical verdicts retrieval ranks over»</td></tr>
|
||
<tr><td>Fold <span class="small">§2, §3 Steg 1</span></td><td>«the injection of retrieved prior verdicts into the hypothesis prompt»</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="col">
|
||
<span class="step">Portene og reglene</span>
|
||
<table class="compact">
|
||
<tr><th>Begrep</th><th>Ordrett fra <code>shared/method-spec.md</code></th></tr>
|
||
<tr><td>Two falsifiers <span class="small">§2, §9</span></td><td>«the deterministic validator (numbers) and the debate checker (reasoning) — they judge the same candidate and are never conflated»</td></tr>
|
||
<tr><td>Mandate <span class="small">§3</span></td><td>«one project, plus the objective its candidates are generated against»</td></tr>
|
||
<tr><td>Navigate, never stuff <span class="small">§3 Steg 1</span></td><td>«MUST be built by navigating its OKF bundle with progressive disclosure — never by stuffing the whole bundle … into the prompt»</td></tr>
|
||
<tr><td>Refinement <span class="small">§3 Steg 5</span></td><td>«Only the reason is carried — never the prior proposal JSON»</td></tr>
|
||
<tr><td>Long loop <span class="small">§3 Steg 7</span></td><td>«The system MUST be fully resumable across runs separated in time — no live-session assumption.»</td></tr>
|
||
<tr><td>Fail-closed <span class="small">§6</span></td><td>«a verdict whose decision is not in {approved, approved_with_adjustment} MUST be refused with an error, writing and linking NOTHING.»</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<p class="callout"><b>Hvorfor ordrett.</b> Spec-en ligger i <code>shared/</code>, 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.</p>
|
||
<p class="src">Kilde: <code>shared/method-spec.md</code> §2, §3, §6, §7.1, §9 · <code>shared/README.md</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del4-artefakter -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">39</span><span class="part">Del 4 · Arbeidsflyten og sløyfene</span></p>
|
||
<h2>Hver artefakt en kjøring legger igjen, mater nøyaktig én senere sløyfe.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 430" role="img" aria-label="Seks artefaktfiler til venstre, den sløyfa hver av dem mater til høyre, med tidsavstand på pila">
|
||
<text class="band-lbl" x="40" y="26">Filen som blir liggende igjen</text>
|
||
<text class="band-lbl" x="600" y="26" text-anchor="middle">Tidsavstand</text>
|
||
<text class="band-lbl" x="740" y="26">Sløyfa den mater</text>
|
||
|
||
<rect class="box soft" x="40" y="40" width="420" height="52"/>
|
||
<text class="mono" x="60" y="72">{run_id}-outcome.json</text>
|
||
<path class="edge accent" d="M462 66 L736 66"/>
|
||
<text class="tiny" x="600" y="58" text-anchor="middle">dager</text>
|
||
<rect class="box accent" x="740" y="40" width="420" height="52"/>
|
||
<text class="sub" x="760" y="62">hitl pending: fagpersonens kø</text>
|
||
<text class="tiny" x="760" y="82">utboksens nøkler minus innboksens, én rad per vurdert approach</text>
|
||
|
||
<rect class="box soft" x="40" y="105" width="420" height="52"/>
|
||
<text class="mono" x="60" y="137">{run_id}-coverage.json</text>
|
||
<path class="edge accent" d="M462 131 L736 131"/>
|
||
<text class="tiny" x="600" y="123" text-anchor="middle">uker</text>
|
||
<rect class="box accent" x="740" y="105" width="420" height="52"/>
|
||
<text class="sub" x="760" y="127">v1-gaten</text>
|
||
<text class="tiny" x="760" y="147">hvorfor hver bestilt approach endte som den gjorde</text>
|
||
|
||
<rect class="box soft" x="40" y="170" width="420" height="52"/>
|
||
<text class="mono" x="60" y="202">{run_id}-plan-review.json</text>
|
||
<path class="edge accent" d="M462 196 L736 196"/>
|
||
<text class="tiny" x="600" y="188" text-anchor="middle">dager</text>
|
||
<rect class="box accent" x="740" y="170" width="420" height="52"/>
|
||
<text class="sub" x="760" y="192">den parkerte plan-reviewen</text>
|
||
<text class="tiny" x="760" y="212">svaret matches på request_id: et svar på et annet spørsmål nektes</text>
|
||
|
||
<rect class="box soft" x="40" y="235" width="420" height="52"/>
|
||
<text class="mono" x="60" y="267">{run_id}-debate.json</text>
|
||
<path class="edge accent" d="M462 261 L736 261"/>
|
||
<text class="tiny" x="600" y="253" text-anchor="middle">timer</text>
|
||
<rect class="box accent" x="740" y="235" width="420" height="52"/>
|
||
<text class="sub" x="760" y="257">stress-judgen</text>
|
||
<text class="tiny" x="760" y="277">hvilke dokumenter debatten åpnet. Tom liste ER signalet.</text>
|
||
|
||
<rect class="box soft" x="40" y="300" width="420" height="52"/>
|
||
<text class="mono" x="60" y="332">innboks/{id}.json</text>
|
||
<path class="edge accent" d="M462 326 L736 326"/>
|
||
<text class="tiny" x="600" y="318" text-anchor="middle">neste kjøring</text>
|
||
<rect class="box accent" x="740" y="300" width="420" height="52"/>
|
||
<text class="sub" x="760" y="322">ExpeL-folden i Steg 1</text>
|
||
<text class="tiny" x="760" y="342">flettes inn i storet før hypotesen finnes, aldri etterpå</text>
|
||
|
||
<rect class="box soft" x="40" y="365" width="420" height="52"/>
|
||
<text class="mono" x="60" y="397">savings-ledger.json</text>
|
||
<path class="edge accent" d="M462 391 L736 391"/>
|
||
<text class="tiny" x="600" y="383" text-anchor="middle">måneder</text>
|
||
<rect class="box accent" x="740" y="365" width="420" height="52"/>
|
||
<text class="sub" x="760" y="387">--report</text>
|
||
<text class="tiny" x="760" y="407">per prosjekt og portefølje, overlapp talt én gang</text>
|
||
</svg>
|
||
<figcaption>Utboksen og innboksen skal være to forskjellige mapper. Eierskapet er motsatt: systemet skriver utboksen, fagpersonen skriver innboksen.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/outbox.py:106-148</code>, <code>:206-244</code>, <code>:321-349</code>, <code>:378-412</code> · <code>hitl.py:159-165</code>, <code>:221-259</code> · <code>value_report.py:48-87</code> · <code>docs/ekspert-svar.md:100-104</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== part5-maf.html ===== -->
|
||
<!-- del5-divider -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h1>Harnessen: Microsoft Agent Framework</h1>
|
||
<p class="lede">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.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-hva-er-maf -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">40</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>MAF er Microsofts egen arvtaker etter Semantic Kernel og AutoGen, og Python-linjen er GA.</h2>
|
||
<p class="lede">Ett SDK for agenter og multi-agent-arbeidsflyter i .NET, Python og Go. Python-pakken <code>agent-framework</code> 1.0.0 kom 02.04.2026. Det distribueres som en pakkefamilie på 39 underpakker, ikke som ett hjul.</p>
|
||
<p class="callout"><b>Learn, ordrett:</b> «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.»</p>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 340" role="img" aria-label="Pakkefamilien: meta-pakken over agent-framework-core, med fire pinnede pakker uthevet og 35 andre dempet">
|
||
<rect class="box soft dashed" x="420" y="16" width="360" height="58"/>
|
||
<text class="lbl" x="600" y="42" text-anchor="middle">agent-framework (meta)</text>
|
||
<text class="tiny" x="600" y="62" text-anchor="middle">drar core[all] og dermed beta-integrasjoner — bevisst ikke brukt her</text>
|
||
<path class="edge dashed" d="M600 74 L600 108"/>
|
||
|
||
<rect class="box accent" x="380" y="112" width="440" height="62"/>
|
||
<text class="lbl" x="600" y="140" text-anchor="middle">agent-framework-core</text>
|
||
<text class="mono" x="600" y="161" text-anchor="middle">1.18.0 · pinnet >=1.18.0,<2</text>
|
||
|
||
<path class="edge" d="M500 174 L180 224"/>
|
||
<path class="edge" d="M560 174 L450 224"/>
|
||
<path class="edge" d="M660 174 L730 224"/>
|
||
<path class="edge soft" d="M760 174 L1020 224"/>
|
||
|
||
<rect class="box accent" x="40" y="228" width="250" height="88"/>
|
||
<text class="lbl" x="165" y="256" text-anchor="middle">-openai</text>
|
||
<text class="mono" x="165" y="278" text-anchor="middle">1.14.3</text>
|
||
<text class="tiny" x="165" y="300" text-anchor="middle">OpenAIChatCompletionClient</text>
|
||
|
||
<rect class="box accent" x="320" y="228" width="250" height="88"/>
|
||
<text class="lbl" x="445" y="256" text-anchor="middle">-foundry</text>
|
||
<text class="mono" x="445" y="278" text-anchor="middle">1.13.0</text>
|
||
<text class="tiny" x="445" y="300" text-anchor="middle">FoundryChatClient</text>
|
||
|
||
<rect class="box accent" x="600" y="228" width="250" height="88"/>
|
||
<text class="lbl" x="725" y="256" text-anchor="middle">-orchestrations</text>
|
||
<text class="mono" x="725" y="278" text-anchor="middle">1.1.1</text>
|
||
<text class="tiny" x="725" y="300" text-anchor="middle">GroupChatBuilder, MagenticBuilder</text>
|
||
|
||
<rect class="box soft" x="890" y="228" width="270" height="88"/>
|
||
<text class="lbl" x="1025" y="256" text-anchor="middle">+ 35 andre</text>
|
||
<text class="tiny" x="1025" y="278" text-anchor="middle">devui, mem0, redis, anthropic,</text>
|
||
<text class="tiny" x="1025" y="296" text-anchor="middle">a2a, postgres, qdrant … ikke her</text>
|
||
</svg>
|
||
<figcaption>Alle har prefikset <code>agent-framework</code>. Blått = pinnet og installert i dette repoet; grått = finnes, men er ikke en avhengighet her.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>pyproject.toml:8-31</code> · <code>uv.lock</code> · <code>learn.microsoft.com/agent-framework/overview/#why-agent-framework</code> · <code>pypi.org/project/agent-framework-core/</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-byggeklossene -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">41</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Fem lag er i bruk på default-stien, to er opt-in, og to står helt urørt.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 580" role="img" aria-label="MAFs byggeklosser i ni lag, fra agent og chat-klient nederst til DevUI øverst, med markering av hva som er brukt, opt-in og ubrukt">
|
||
<rect class="box accent" x="250" y="10" width="22" height="18"/>
|
||
<text class="tiny" x="282" y="24">brukt på default-stien</text>
|
||
<rect class="box accent dashed" x="470" y="10" width="22" height="18"/>
|
||
<text class="tiny" x="502" y="24">opt-in bak flagg eller env-variabel</text>
|
||
<rect class="box soft" x="790" y="10" width="22" height="18"/>
|
||
<text class="tiny" x="822" y="24">finnes i MAF, ikke brukt her</text>
|
||
|
||
<rect class="band accent" x="0" y="40" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="62">AGENT / CHATCLIENT</text>
|
||
<text class="tiny" x="14" y="80">modellkall og samtaletilstand</text>
|
||
<rect class="box accent" x="250" y="48" width="130" height="36"/>
|
||
<text class="mono" x="315" y="70" text-anchor="middle">Agent</text>
|
||
<rect class="box soft" x="395" y="48" width="160" height="36"/>
|
||
<text class="mono" x="475" y="70" text-anchor="middle">AgentSession</text>
|
||
<rect class="box accent" x="570" y="48" width="230" height="36"/>
|
||
<text class="mono" x="685" y="70" text-anchor="middle">OpenAIChatCompletionClient</text>
|
||
<rect class="box accent" x="815" y="48" width="170" height="36"/>
|
||
<text class="mono" x="900" y="70" text-anchor="middle">FoundryChatClient</text>
|
||
|
||
<rect class="band" x="0" y="98" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="120">TOOLS</text>
|
||
<text class="tiny" x="14" y="138">data inn i modellen</text>
|
||
<rect class="box accent" x="250" y="106" width="175" height="36"/>
|
||
<text class="mono" x="337" y="128" text-anchor="middle">@tool / FunctionTool</text>
|
||
<rect class="box accent dashed" x="440" y="106" width="120" height="36"/>
|
||
<text class="mono" x="500" y="128" text-anchor="middle">MCPStdioTool</text>
|
||
<rect class="box accent dashed" x="575" y="106" width="185" height="36"/>
|
||
<text class="mono" x="667" y="128" text-anchor="middle">MCPStreamableHTTPTool</text>
|
||
<rect class="box soft" x="775" y="106" width="150" height="36"/>
|
||
<text class="mono" x="850" y="128" text-anchor="middle">MCPWebsocketTool</text>
|
||
<rect class="box soft" x="940" y="106" width="130" height="36"/>
|
||
<text class="mono" x="1005" y="128" text-anchor="middle">hosted tools</text>
|
||
|
||
<rect class="band accent" x="0" y="156" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="178">ORCHESTRATIONS</text>
|
||
<text class="tiny" x="14" y="196">ferdige samarbeidsmønstre</text>
|
||
<rect class="box accent" x="250" y="164" width="150" height="36"/>
|
||
<text class="mono" x="325" y="186" text-anchor="middle">GroupChatBuilder</text>
|
||
<rect class="box accent dashed" x="415" y="164" width="140" height="36"/>
|
||
<text class="mono" x="485" y="186" text-anchor="middle">MagenticBuilder</text>
|
||
<rect class="box soft" x="570" y="164" width="150" height="36"/>
|
||
<text class="mono" x="645" y="186" text-anchor="middle">SequentialBuilder</text>
|
||
<rect class="box soft" x="735" y="164" width="155" height="36"/>
|
||
<text class="mono" x="812" y="186" text-anchor="middle">ConcurrentBuilder</text>
|
||
<rect class="box soft" x="905" y="164" width="135" height="36"/>
|
||
<text class="mono" x="972" y="186" text-anchor="middle">HandoffBuilder</text>
|
||
|
||
<rect class="band" x="0" y="214" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="236">WORKFLOWS (GRAF)</text>
|
||
<text class="tiny" x="14" y="254">eksplisitt kjørerekkefølge</text>
|
||
<rect class="box soft" x="250" y="222" width="140" height="36"/>
|
||
<text class="mono" x="320" y="244" text-anchor="middle">WorkflowBuilder</text>
|
||
<rect class="box soft" x="405" y="222" width="160" height="36"/>
|
||
<text class="mono" x="485" y="244" text-anchor="middle">Executor, add_edge</text>
|
||
<rect class="box accent dashed" x="580" y="222" width="185" height="36"/>
|
||
<text class="mono" x="672" y="244" text-anchor="middle">FileCheckpointStorage</text>
|
||
<rect class="box accent dashed" x="780" y="222" width="160" height="36"/>
|
||
<text class="mono" x="860" y="244" text-anchor="middle">ctx.request_info</text>
|
||
|
||
<rect class="band accent" x="0" y="272" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="294">MIDDLEWARE</text>
|
||
<text class="tiny" x="14" y="312">avskjærer hvert kall</text>
|
||
<rect class="box accent" x="250" y="280" width="140" height="36"/>
|
||
<text class="mono" x="320" y="302" text-anchor="middle">ChatMiddleware</text>
|
||
<rect class="box accent" x="405" y="280" width="170" height="36"/>
|
||
<text class="mono" x="490" y="302" text-anchor="middle">FunctionMiddleware</text>
|
||
<rect class="box soft" x="590" y="280" width="150" height="36"/>
|
||
<text class="mono" x="665" y="302" text-anchor="middle">AgentMiddleware</text>
|
||
<rect class="box soft" x="755" y="280" width="190" height="36"/>
|
||
<text class="mono" x="850" y="302" text-anchor="middle">MiddlewareTermination</text>
|
||
|
||
<rect class="band accent" x="0" y="330" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="352">CONTEXT PROVIDERS</text>
|
||
<text class="tiny" x="14" y="370">minne inn i prompten</text>
|
||
<rect class="box accent" x="250" y="338" width="150" height="36"/>
|
||
<text class="mono" x="325" y="360" text-anchor="middle">ContextProvider</text>
|
||
<rect class="box soft" x="415" y="338" width="150" height="36"/>
|
||
<text class="mono" x="490" y="360" text-anchor="middle">HistoryProvider</text>
|
||
<rect class="box soft" x="580" y="338" width="170" height="36"/>
|
||
<text class="mono" x="665" y="360" text-anchor="middle">Mem0 / Redis</text>
|
||
|
||
<rect class="band" x="0" y="388" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="410">OBSERVABILITY</text>
|
||
<text class="tiny" x="14" y="428">spor, logger, metrikker</text>
|
||
<rect class="box accent dashed" x="250" y="396" width="205" height="36"/>
|
||
<text class="mono" x="352" y="418" text-anchor="middle">configure_otel_providers</text>
|
||
<rect class="box soft" x="470" y="396" width="170" height="36"/>
|
||
<text class="mono" x="555" y="418" text-anchor="middle">OTLP-eksportører</text>
|
||
<rect class="box soft" x="655" y="396" width="130" height="36"/>
|
||
<text class="mono" x="720" y="418" text-anchor="middle">get_tracer()</text>
|
||
|
||
<rect class="band" x="0" y="446" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="468">HOSTING</text>
|
||
<text class="tiny" x="14" y="486">agenten som container</text>
|
||
<rect class="box soft" x="250" y="454" width="200" height="36"/>
|
||
<text class="mono" x="350" y="476" text-anchor="middle">Foundry hosted agents</text>
|
||
<rect class="box soft" x="465" y="454" width="180" height="36"/>
|
||
<text class="mono" x="555" y="476" text-anchor="middle">Workflow.as_agent()</text>
|
||
<rect class="box soft" x="660" y="454" width="185" height="36"/>
|
||
<text class="mono" x="752" y="476" text-anchor="middle">ResponsesHostServer</text>
|
||
|
||
<rect class="band" x="0" y="504" width="1200" height="52"/>
|
||
<text class="band-lbl" x="14" y="526">DEVUI</text>
|
||
<text class="tiny" x="14" y="544">utviklings-UI, ikke produksjon</text>
|
||
<rect class="box soft" x="250" y="512" width="110" height="36"/>
|
||
<text class="mono" x="305" y="534" text-anchor="middle">devui</text>
|
||
</svg>
|
||
<figcaption><code>ctx.request_info</code> er koblet, men slått av: 0 kallsteder i <code>src</code> sender <code>True</code>, så biblioteket er eneste dør. Navnene er de gjeldende etter GA-omdøpingen i april 2026; <code>ChatAgent</code>, <code>@ai_function</code> og <code>setup_observability()</code> finnes bare i den etterslepende API-referansen.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>learn.microsoft.com/agent-framework/workflows/orchestrations/</code> · <code>…/agents/observability</code> · <code>…/support/upgrade/python-2026-significant-changes</code> · <code>docs/2026-09-11-p12-maf-gjeld.md § 3</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-valgt-her -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">42</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Av alt MAF tilbyr, er det to orkestreringsbyggere og én chat-klient-søm som bærer hele kjørestien.</h2>
|
||
<table class="compact">
|
||
<tr><th>MAF-element</th><th>Brukt?</th><th>Hvor</th><th>Hvorfor</th></tr>
|
||
<tr><td><code>GroupChatBuilder</code></td><td class="ok">ja, hver kjøring</td><td><code>workflow.py:104-113</code></td><td>Maker-checker er debatt-default. <code>selection_func</code> sykler proposer → checker; <code>output_from=agents</code> løfter begge utdataene ut</td></tr>
|
||
<tr><td><code>Agent</code></td><td class="ok">ja</td><td><code>workflow.py:63</code></td><td>To deltakere, bygget friske per kjøring sammen med sine klienter (B7)</td></tr>
|
||
<tr><td><code>OpenAIChatCompletionClient</code> · <code>FoundryChatClient</code></td><td class="ok">ja, én per profil</td><td><code>backends.py:150</code>, <code>:160-164</code></td><td>Sømmen mot leverandøren. Chat Completions og ikke streaming, fordi usage da fylles ut None-trygt</td></tr>
|
||
<tr><td><code>FunctionTool</code> / <code>@tool</code></td><td class="ok">ja, default</td><td><code>tools.py:24</code>, <code>:46</code></td><td>Datasømmen i kjørestien er in-process. Ingen nettverkskall for å nå kunnskapsbasen</td></tr>
|
||
<tr><td><code>ChatMiddleware</code></td><td class="ok">ja</td><td><code>budget.py:228</code></td><td><code>BudgetMiddleware</code> leser usage etter hvert kall og kortslutter med <code>BudgetExceeded</code>; <code>strict_usage</code> gjør manglende usage til hard feil</td></tr>
|
||
<tr><td><code>MagenticBuilder</code></td><td>opt-in, <code>--explore</code></td><td><code>explore.py:1816-1822</code></td><td>Utforskning ligger OVER åttestegs-sløyfen, aldri inni debatten</td></tr>
|
||
<tr><td>MCP-verktøy</td><td>opt-in, <code>--mcp-config</code></td><td><code>mcp_tools.py:154</code>, <code>:170</code></td><td>Eksterne servere blir verktøy agentene kan kalle under debatten. Allowlist er påkrevd</td></tr>
|
||
<tr><td><code>configure_otel_providers</code></td><td>opt-in, <code>PORTFOLIO_OTEL</code></td><td><code>tracing.py:160</code></td><td>Av betyr at MAF aldri kalles: et kall med tom eksportørliste ville likevel installert providere og lest hver <code>OTEL_EXPORTER_OTLP_*</code>-variabel</td></tr>
|
||
</table>
|
||
<p class="callout"><b>Én rad er halvveis.</b> <code>ContextProvider</code> er med, men den bærende bruken er <code>format_fewshot()</code> strengkonkatenert inn i prompten (<code>run.py:1557</code>), ikke MAFs egen injeksjon. Å lukke det står som åpent punkt F3.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/{workflow,backends,tools,budget,explore,mcp_tools,tracing}.py</code> · <code>docs/invarianter.md</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-ikke-valgt -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">43</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Porten som avgjør verdien står utenfor grafen, og det er derfor grafen kan være så liten.</h2>
|
||
<div class="cols">
|
||
<div class="col soft">
|
||
<span class="step">Grafen</span>
|
||
<ul>
|
||
<li><code>WorkflowBuilder</code>: 0 treff i <code>src</code>. De eneste <code>Workflow</code>-objektene er de to byggerne bygger selv</li>
|
||
<li><code>Sequential</code> / <code>Concurrent</code> / <code>Handoff</code>: portefølje-fan-out er håndskrevet <code>asyncio.gather</code></li>
|
||
</ul>
|
||
</div>
|
||
<div class="col soft">
|
||
<span class="step">Debatten</span>
|
||
<ul>
|
||
<li>Magentic er ikke debatt-default. <code>shared/method-spec.md</code> §3 er normativ og eies av commons</li>
|
||
<li>Ingen blokkerende middleware. Primitivet finnes i installert core; porten er deterministisk Python utenfor grafen</li>
|
||
</ul>
|
||
</div>
|
||
<div class="col soft">
|
||
<span class="step">Flatene</span>
|
||
<ul>
|
||
<li><code>Workflow.as_agent()</code>: et bygget workflow er engangs (målt klientkall-serie [2, 0, 0]), og det ville servert ugatede forslag</li>
|
||
<li><code>SkillsProvider</code>, DevUI, OTLP-eksportører: egen laster, ingen prod-UI, og eksportørene er egress i et hjul</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 300" role="img" aria-label="Grafen med proposer og checker inne i en stiplet ramme, og validatoren utenfor rammen som mottar forslaget">
|
||
<rect class="box soft dashed" x="20" y="40" width="640" height="230"/>
|
||
<text class="band-lbl" x="40" y="66">MAF: GROUPCHAT-GRAFEN</text>
|
||
<rect class="box accent" x="50" y="85" width="260" height="56"/>
|
||
<text class="lbl" x="180" y="118" text-anchor="middle">Agent «proposer»</text>
|
||
<rect class="box accent" x="360" y="85" width="260" height="56"/>
|
||
<text class="lbl" x="490" y="118" text-anchor="middle">Agent «checker»</text>
|
||
<path class="edge" d="M310 105 L355 105"/>
|
||
<path class="edge" d="M355 125 L310 125"/>
|
||
<rect class="box" x="50" y="196" width="570" height="54"/>
|
||
<text class="lbl" x="335" y="219" text-anchor="middle">BaseChatClient · tools · middleware</text>
|
||
<text class="tiny" x="335" y="239" text-anchor="middle">alt agentene trenger for å snakke, telle og hente</text>
|
||
<path class="edge soft" d="M180 141 L180 192"/>
|
||
<path class="edge soft" d="M490 141 L490 192"/>
|
||
|
||
<text class="tiny" x="695" y="140" text-anchor="middle">forslaget</text>
|
||
<path class="edge" d="M660 155 L726 155"/>
|
||
|
||
<rect class="box warn" x="730" y="85" width="440" height="95"/>
|
||
<text class="lbl" x="950" y="115" text-anchor="middle">validator.py</text>
|
||
<text class="sub" x="950" y="137" text-anchor="middle">deterministisk og MAF-fri: importerer ikke agent_framework</text>
|
||
<text class="tiny" x="950" y="163" text-anchor="middle">validated · rejected · unsupported</text>
|
||
<path class="edge" d="M950 180 L950 202"/>
|
||
<rect class="box ok" x="730" y="206" width="440" height="64"/>
|
||
<text class="lbl" x="950" y="234" text-anchor="middle">ledger + value report</text>
|
||
<text class="tiny" x="950" y="255" text-anchor="middle">claim mot result, målt i ettertid</text>
|
||
</svg>
|
||
<figcaption>Elleve moduler, blant dem <code>validator.py</code>, <code>ir.py</code> og <code>okf.py</code>, sier i sin egen docstring at de aldri skal importere <code>agent_framework</code>. <code>tests/test_okf.py::test_okf_is_maf_free</code> gjør påstanden til noe som kan feile.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/hosting.py:19-23</code> · <code>docs/2026-09-11-p12-maf-gjeld.md § 3</code> (U1, U2, U5, U8) · <code>docs/invarianter.md:32</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-backend-profiler -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">44</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Hele leverandørvalget er én funksjon som returnerer en MAF-chat-klient; resten av koden ser ingen forskjell.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 520" role="img" aria-label="get_backend forgrener til lokal profil uten egress og til Azure Foundry-profil med endepunkt-rekkefølge og valg av credential">
|
||
<rect class="box" x="460" y="14" width="280" height="56"/>
|
||
<text class="mono" x="600" y="38" text-anchor="middle">get_backend(profile)</text>
|
||
<text class="tiny" x="600" y="58" text-anchor="middle">returnerer alltid en BaseChatClient</text>
|
||
<path class="edge" d="M540 70 L300 122"/>
|
||
<path class="edge" d="M660 70 L900 122"/>
|
||
<text class="tiny" x="380" y="104">profile=local</text>
|
||
<text class="tiny" x="760" y="104">profile=azure</text>
|
||
|
||
<rect class="box accent" x="60" y="126" width="460" height="56"/>
|
||
<text class="lbl" x="290" y="159" text-anchor="middle">LocalBackend</text>
|
||
<rect class="box" x="60" y="198" width="460" height="76"/>
|
||
<text class="mono" x="290" y="226" text-anchor="middle">OpenAIChatCompletionClient</text>
|
||
<text class="tiny" x="290" y="250" text-anchor="middle">Chat Completions, ikke streaming: usage fylles ut None-trygt</text>
|
||
<text class="tiny" x="290" y="266" text-anchor="middle">og Responses-klienten slapp et verktøy på /v1</text>
|
||
<rect class="box" x="60" y="290" width="460" height="76"/>
|
||
<text class="mono" x="290" y="318" text-anchor="middle">http://127.0.0.1:11434/v1</text>
|
||
<text class="tiny" x="290" y="342" text-anchor="middle">loopback, aldri en fjernvert. Konstruksjonen er offline:</text>
|
||
<text class="tiny" x="290" y="358" text-anchor="middle">ingen nettverkskall før en agent faktisk kjører</text>
|
||
<rect class="box ok" x="60" y="382" width="460" height="56"/>
|
||
<text class="lbl" x="290" y="415" text-anchor="middle">Ingen egress i lokal profil</text>
|
||
|
||
<rect class="box accent" x="680" y="126" width="460" height="56"/>
|
||
<text class="lbl" x="910" y="150" text-anchor="middle">AzureFoundryBackend</text>
|
||
<text class="mono" x="910" y="171" text-anchor="middle">FoundryChatClient(endpoint, model, credential)</text>
|
||
<rect class="box" x="680" y="198" width="460" height="86"/>
|
||
<text class="tiny" x="910" y="222" text-anchor="middle">endepunkt, i denne rekkefølgen, på VERDI og ikke deklarasjon:</text>
|
||
<text class="mono" x="910" y="246" text-anchor="middle">PORTFOLIO_FOUNDRY_PROJECT_ENDPOINT</text>
|
||
<text class="mono" x="910" y="270" text-anchor="middle">→ FOUNDRY_PROJECT_ENDPOINT → ValueError</text>
|
||
|
||
<path class="edge" d="M910 284 L910 312"/>
|
||
<polygon class="box warn" points="910,314 1110,356 910,398 710,356"/>
|
||
<text class="lbl" x="910" y="352" text-anchor="middle">FOUNDRY_HOSTING_ENVIRONMENT</text>
|
||
<text class="tiny" x="910" y="372" text-anchor="middle">satt og ikke tom?</text>
|
||
<path class="edge" d="M840 386 L800 426"/>
|
||
<path class="edge" d="M980 386 L1020 426"/>
|
||
<text class="tiny" x="795" y="414" text-anchor="end">nei</text>
|
||
<text class="tiny" x="1025" y="414">ja</text>
|
||
<rect class="box" x="680" y="430" width="215" height="56"/>
|
||
<text class="mono" x="787" y="455" text-anchor="middle">AzureCliCredential</text>
|
||
<text class="tiny" x="787" y="474" text-anchor="middle">på en laptop</text>
|
||
<rect class="box" x="925" y="430" width="215" height="56"/>
|
||
<text class="mono" x="1032" y="455" text-anchor="middle">ManagedIdentityCredential</text>
|
||
<text class="tiny" x="1032" y="474" text-anchor="middle">i en hostet container</text>
|
||
</svg>
|
||
<figcaption>Credential er alltid eksplisitt, aldri <code>DefaultAzureCredential</code>: Learn fraråder det for å unngå utilsiktet credential-probing, som ville gjort en konfigurasjonsfeil om til en treg feil.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Dokumentasjonen motsier seg selv her.</b> Samme Learn-side sier både at plattformen injiserer «a nonempty value» og at variabelen er «set to <code>1</code>». 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.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/backends.py:28-30</code>, <code>:45</code>, <code>:49</code>, <code>:146-164</code> · <code>docs/invarianter.md:183</code> · <code>learn.microsoft.com/azure/foundry/agents/how-to/configure-hosted-agent-env-variables</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-groupchat -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">45</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Debatten har tre uavhengige stopp, og ingen av dem er modellens eget skjønn.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 470" role="img" aria-label="GroupChat-sløyfen mellom proposer og checker med tre stoppmekanismer over og to utdata under">
|
||
<rect class="box warn" x="40" y="24" width="330" height="66"/>
|
||
<text class="mono" x="205" y="50" text-anchor="middle">with_max_rounds(max_rounds)</text>
|
||
<text class="tiny" x="205" y="72" text-anchor="middle">det harde taket (B4) — den bindende grensen</text>
|
||
<rect class="box warn" x="400" y="24" width="360" height="66"/>
|
||
<text class="mono" x="580" y="50" text-anchor="middle">termination_condition</text>
|
||
<text class="tiny" x="580" y="72" text-anchor="middle">sikkerhetsnett godt over taket, ikke eneste stopp</text>
|
||
<rect class="box warn" x="790" y="24" width="370" height="66"/>
|
||
<text class="mono" x="975" y="50" text-anchor="middle">BudgetMiddleware → BudgetExceeded</text>
|
||
<text class="tiny" x="975" y="72" text-anchor="middle">token-vakt på hvert kall, utenfor orkestreringen</text>
|
||
<path class="edge warn" d="M205 90 L205 132"/>
|
||
<path class="edge warn" d="M580 90 L580 132"/>
|
||
<path class="edge warn" d="M975 90 L975 132"/>
|
||
|
||
<text class="tiny" x="60" y="172">fresh_workflow(): friske agenter OG friske klienter per prosjektkjøring (B7) — et gjenbrukt workflow akkumulerer tråden</text>
|
||
|
||
<rect class="box" x="60" y="190" width="190" height="70"/>
|
||
<text class="mono" x="155" y="222" text-anchor="middle">selection_func</text>
|
||
<text class="tiny" x="155" y="242" text-anchor="middle">sykler rollene</text>
|
||
<path class="edge" d="M250 225 L305 225"/>
|
||
<rect class="box accent" x="310" y="190" width="220" height="70"/>
|
||
<text class="lbl" x="420" y="222" text-anchor="middle">Agent «proposer»</text>
|
||
<text class="tiny" x="420" y="242" text-anchor="middle">foreslår ett tiltak</text>
|
||
<path class="edge" d="M530 225 L605 225"/>
|
||
<rect class="box accent" x="610" y="190" width="220" height="70"/>
|
||
<text class="lbl" x="720" y="222" text-anchor="middle">Agent «checker»</text>
|
||
<text class="tiny" x="720" y="242" text-anchor="middle">kritiserer og flagger brudd</text>
|
||
<path class="edge" d="M720 260 L720 320 L155 320 L155 264"/>
|
||
<text class="tiny" x="440" y="340" text-anchor="middle">neste runde — og kun hvis ingen av de tre stoppene har slått til</text>
|
||
|
||
<path class="edge" d="M830 225 L895 225"/>
|
||
<rect class="box" x="900" y="190" width="250" height="70"/>
|
||
<text class="mono" x="1025" y="218" text-anchor="middle">get_outputs()</text>
|
||
<text class="tiny" x="1025" y="240" text-anchor="middle">output_from=agents</text>
|
||
<path class="edge" d="M975 260 L880 378"/>
|
||
<path class="edge" d="M1085 260 L1085 378"/>
|
||
<rect class="box" x="740" y="382" width="250" height="66"/>
|
||
<text class="lbl" x="865" y="410" text-anchor="middle">proposer-output</text>
|
||
<text class="tiny" x="865" y="431" text-anchor="middle">videre til generering (F1)</text>
|
||
<rect class="box" x="1000" y="382" width="170" height="66"/>
|
||
<text class="lbl" x="1085" y="410" text-anchor="middle">checker-verdict</text>
|
||
<text class="tiny" x="1085" y="431" text-anchor="middle">APPROVE | REJECT</text>
|
||
</svg>
|
||
<figcaption>Uten <code>output_from=agents</code> gir <code>get_outputs()</code> bare orkestratorens «reached max rounds»-melding. <code>run.py</code> skiller de to utdataene på <code>author_name</code>.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/workflow.py:78</code>, <code>:104-116</code> · <code>src/portfolio_optimiser/budget.py:228</code> · kalt fra <code>run.py</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-magentic -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">46</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Magentic har ingen forsvarlige standardverdier, så kontrakten krever hvert eneste tak eksplisitt.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 500" role="img" aria-label="ExplorationContract mater MagenticBuilder med fire tak pluss repoets eget revisjonstak, og utforskningen ender i mandat og validator">
|
||
<rect class="box warn" x="360" y="24" width="380" height="102"/>
|
||
<text class="mono" x="550" y="50" text-anchor="middle">max_plan_revisions</text>
|
||
<text class="tiny" x="550" y="74" text-anchor="middle">ikke et MAF-tak, men repoets eget: en plan-review-«revise»</text>
|
||
<text class="tiny" x="550" y="92" text-anchor="middle">koster to manager-kall, emitterer ingen progress ledger</text>
|
||
<text class="tiny" x="550" y="110" text-anchor="middle">og bruker ingen runde — rundetelleren ser den aldri</text>
|
||
<path class="edge warn" d="M550 126 L550 166"/>
|
||
|
||
<rect class="box" x="30" y="150" width="300" height="176"/>
|
||
<text class="lbl" x="180" y="178" text-anchor="middle">ExplorationContract</text>
|
||
<text class="mono" x="180" y="206" text-anchor="middle">max_round_count</text>
|
||
<text class="mono" x="180" y="230" text-anchor="middle">max_stall_count</text>
|
||
<text class="mono" x="180" y="254" text-anchor="middle">max_reset_count</text>
|
||
<text class="mono" x="180" y="278" text-anchor="middle">enable_plan_review</text>
|
||
<text class="tiny" x="180" y="306" text-anchor="middle">alle påkrevd, ingen har default</text>
|
||
<path class="edge" d="M330 236 L396 236"/>
|
||
|
||
<rect class="box accent" x="400" y="170" width="280" height="132"/>
|
||
<text class="lbl" x="540" y="214" text-anchor="middle">MagenticBuilder</text>
|
||
<text class="tiny" x="540" y="242" text-anchor="middle">deltakere: manager,</text>
|
||
<text class="tiny" x="540" y="260" text-anchor="middle">navigator, hypothesiser</text>
|
||
<text class="tiny" x="540" y="284" text-anchor="middle">defaulter selv til None = ubegrenset</text>
|
||
<path class="edge" d="M680 236 L756 236"/>
|
||
<text class="tiny" x="718" y="224" text-anchor="middle">Mandate</text>
|
||
|
||
<rect class="box ok" x="760" y="160" width="410" height="152"/>
|
||
<text class="mono" x="965" y="192" text-anchor="middle">run_project(mandate=…)</text>
|
||
<text class="mono" x="965" y="218" text-anchor="middle">validate_proposal()</text>
|
||
<text class="tiny" x="965" y="248" text-anchor="middle">nivå 2: hvert tall porteres her uansett.</text>
|
||
<text class="tiny" x="965" y="268" text-anchor="middle">Utforskningen foreslår; den avgjør ingenting.</text>
|
||
<text class="tiny" x="965" y="292" text-anchor="middle">hypothesiserens quick_validate er rådgivende, aldri provenance</text>
|
||
|
||
<path class="edge accent dashed" d="M480 344 L480 306"/>
|
||
<rect class="box accent dashed" x="340" y="348" width="270" height="118"/>
|
||
<text class="mono" x="475" y="378" text-anchor="middle">--plan-review</text>
|
||
<text class="tiny" x="475" y="402" text-anchor="middle">synkron: et menneske eller en persona</text>
|
||
<text class="tiny" x="475" y="420" text-anchor="middle">signerer planen før sløyfen kjører</text>
|
||
<text class="tiny" x="475" y="446" text-anchor="middle">NEKTET på den hostede flaten</text>
|
||
|
||
<path class="edge accent dashed" d="M700 344 L660 306"/>
|
||
<rect class="box accent dashed" x="650" y="348" width="330" height="118"/>
|
||
<text class="mono" x="815" y="378" text-anchor="middle">--checkpoint-dir</text>
|
||
<text class="tiny" x="815" y="402" text-anchor="middle">FileCheckpointStorage på BYGGEREN, målt:</text>
|
||
<text class="tiny" x="815" y="420" text-anchor="middle">checkpoint_storage= på run() er ikke bærende</text>
|
||
<text class="tiny" x="815" y="446" text-anchor="middle">park → spørsmålsfil → svarfil → resume</text>
|
||
</svg>
|
||
<figcaption><code>max_reset_count</code> må være positiv, og det er en måling: grensesjekken er <code>reset_count >= max_reset_count</code> mot en teller som starter på null, så taket 0 er allerede nådd før første runde.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Hvorfor nektet hostet.</b> 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å <code>/readiness</code>. Operatørdøren er CLI-en.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/explore.py:63-117</code>, <code>:1816-1830</code> · <code>src/portfolio_optimiser/hosting.py:200-205</code> · <code>learn.microsoft.com/agent-framework/workflows/orchestrations/magentic</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-verktoysoem -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">47</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Default-sømmen gjør null nettverkskall, og hver utvidelse må navngi seg selv før den brukes.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 470" role="img" aria-label="Tre soner: in-process verktøy uten nettverk, MCP som opt-in med tre porter, og OTel-eksport som opt-in med en nektregel">
|
||
<rect class="band accent" x="0" y="0" width="380" height="470"/>
|
||
<text class="band-lbl" x="20" y="28">I PROSESS — DEFAULT</text>
|
||
<rect class="box accent" x="30" y="60" width="320" height="104"/>
|
||
<text class="mono" x="190" y="92" text-anchor="middle">@tool / FunctionTool</text>
|
||
<text class="tiny" x="190" y="118" text-anchor="middle">navigasjonsverktøyene mot</text>
|
||
<text class="tiny" x="190" y="136" text-anchor="middle">kunnskapsbasen, pluss quick_validate</text>
|
||
<rect class="box ok" x="30" y="196" width="320" height="86"/>
|
||
<text class="lbl" x="190" y="232" text-anchor="middle">ingen nettverkskall</text>
|
||
<text class="tiny" x="190" y="256" text-anchor="middle">uten konfig er verktøylista uendret</text>
|
||
<text class="tiny" x="190" y="332" text-anchor="middle">Egen kjørbar søm for kildedokumenter</text>
|
||
<text class="tiny" x="190" y="350" text-anchor="middle">FØR kjøring: ingest_mcp.py.</text>
|
||
<text class="tiny" x="190" y="368" text-anchor="middle">Samme protokoll, annen jobb.</text>
|
||
<path class="edge dashed noarrow" d="M390 20 L390 450"/>
|
||
|
||
<text class="band-lbl" x="410" y="28">OPT-IN: --MCP-CONFIG</text>
|
||
<rect class="box accent dashed" x="410" y="60" width="400" height="66"/>
|
||
<text class="mono" x="610" y="88" text-anchor="middle">MCPStdioTool</text>
|
||
<text class="mono" x="610" y="112" text-anchor="middle">MCPStreamableHTTPTool</text>
|
||
<rect class="box warn" x="410" y="150" width="400" height="76"/>
|
||
<text class="lbl" x="610" y="178" text-anchor="middle">1 · allowlist er påkrevd</text>
|
||
<text class="tiny" x="610" y="202" text-anchor="middle">allowed_tools har min_length=1: en tom liste ville</text>
|
||
<text class="tiny" x="610" y="218" text-anchor="middle">latt motparten bestemme hva agentene får kalle</text>
|
||
<rect class="box warn" x="410" y="242" width="400" height="76"/>
|
||
<text class="lbl" x="610" y="270" text-anchor="middle">2 · kunngjort før første kall</text>
|
||
<text class="tiny" x="610" y="294" text-anchor="middle">hver server og hvert tillatt verktøy navngis i</text>
|
||
<text class="tiny" x="610" y="310" text-anchor="middle">kunngjøringen, også uten mandat: ingen udeklarert egress</text>
|
||
<rect class="box warn" x="410" y="334" width="400" height="76"/>
|
||
<text class="lbl" x="610" y="362" text-anchor="middle">3 · --live-dry-run åpner ingenting</text>
|
||
<text class="tiny" x="610" y="386" text-anchor="middle">og konfigen er extra="forbid", så en streifende</text>
|
||
<text class="tiny" x="610" y="402" text-anchor="middle">literal hemmelighet er en nekt, ikke en ignorert nøkkel</text>
|
||
<path class="edge dashed noarrow" d="M840 20 L840 450"/>
|
||
|
||
<text class="band-lbl" x="860" y="28">OPT-IN: PORTFOLIO_OTEL</text>
|
||
<rect class="box accent dashed" x="860" y="60" width="310" height="86"/>
|
||
<text class="mono" x="1015" y="92" text-anchor="middle">console</text>
|
||
<text class="tiny" x="1015" y="116" text-anchor="middle">skriver til stderr, slik at den byte-pinnede</text>
|
||
<text class="tiny" x="1015" y="132" text-anchor="middle">demoens stdout overlever</text>
|
||
<rect class="box accent dashed" x="860" y="166" width="310" height="86"/>
|
||
<text class="mono" x="1015" y="198" text-anchor="middle">otlp</text>
|
||
<text class="tiny" x="1015" y="222" text-anchor="middle">virker først når operatøren selv har</text>
|
||
<text class="tiny" x="1015" y="238" text-anchor="middle">installert en eksportørpakke</text>
|
||
<rect class="box warn" x="860" y="272" width="310" height="138"/>
|
||
<text class="lbl" x="1015" y="302" text-anchor="middle">console NEKTES</text>
|
||
<text class="tiny" x="1015" y="328" text-anchor="middle">når en OTLP-endepunktvariabel er</text>
|
||
<text class="tiny" x="1015" y="346" text-anchor="middle">deklarert i miljøet — fordi eksportører</text>
|
||
<text class="tiny" x="1015" y="364" text-anchor="middle">bygges fra de variablene ubetinget,</text>
|
||
<text class="tiny" x="1015" y="382" text-anchor="middle">og «bare konsoll» ville da vært løgn</text>
|
||
</svg>
|
||
<figcaption>MAF propagerer W3C <code>traceparent</code> inn i MCP-kall for klientåpnede transporter, som er nøyaktig de to som er tillatt her.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>To detaljer som ikke er kosmetiske.</b> Strukturert utdata sendes som en JSON-Schema-<i>mapping</i> og ikke som en Pydantic-klasse: gitt en klasse emitterer klientens konverter <code>minimum</code>, <code>exclusiveMinimum</code>, <code>minItems</code> og <code>prefixItems</code>, fire ting den publiserte strict-undermengden utelukker. Og den skriptede offline-klienten arver <code>OpenAIChatCompletionClient</code> framfor å være en frisk <code>BaseChatClient</code>, ellers ville <code>BudgetMiddleware</code> stilltiende blitt en no-op.</p>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/mcp_tools.py:50-61</code>, <code>:237-241</code> · <code>tracing.py:41-46</code>, <code>:63</code>, <code>:160-197</code> · <code>generate.py:65-67</code>, <code>:219-235</code> · <code>simulation.py:379-388</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del5-maf-gjeld -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">48</span><span class="part">Del 5 · MAF-harnessen</span></p>
|
||
<h2>Pinnen er en snubletråd og ikke en frys, og tellingen av hva vi bruker råtner på fire dager.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1240 300" role="img" aria-label="Tidslinje fra juni til september 2026 over MAF-gjelden og de to versjonsløftene F15 og F16">
|
||
<text class="lbl" x="140" y="46" text-anchor="middle">23.06.2026</text>
|
||
<text class="sub" x="140" y="70" text-anchor="middle">prior-art-registeret</text>
|
||
<path class="edge soft noarrow" d="M140 84 L140 162"/>
|
||
<text class="tiny" x="140" y="200" text-anchor="middle">19 MAF-kapabiliteter ført opp</text>
|
||
<text class="tiny" x="140" y="218" text-anchor="middle">som USE-rader, U1 til U19.</text>
|
||
<text class="tiny" x="140" y="236" text-anchor="middle">Dette er nevneren alt senere</text>
|
||
<text class="tiny" x="140" y="254" text-anchor="middle">måles mot</text>
|
||
|
||
<text class="lbl" x="390" y="46" text-anchor="middle">25.08 → 29.08</text>
|
||
<text class="sub" x="390" y="70" text-anchor="middle">misjonsgjennomgang</text>
|
||
<path class="edge soft noarrow" d="M390 84 L390 162"/>
|
||
<text class="tiny" x="390" y="200" text-anchor="middle">5 ja / 5 delvis / 9 nei av 19.</text>
|
||
<text class="tiny" x="390" y="218" text-anchor="middle">Fire dager senere: 6 / 5 / 8,</text>
|
||
<text class="tiny" x="390" y="236" text-anchor="middle">fordi checkpointing landet</text>
|
||
<text class="tiny" x="390" y="254" text-anchor="middle">imellom</text>
|
||
|
||
<text class="lbl" x="640" y="46" text-anchor="middle">02.09 · F15</text>
|
||
<text class="sub" x="640" y="70" text-anchor="middle">core 1.9.0 → 1.16.0</text>
|
||
<path class="edge soft noarrow" d="M640 84 L640 162"/>
|
||
<text class="tiny" x="640" y="200" text-anchor="middle">17 private former, 16 sjekket</text>
|
||
<text class="tiny" x="640" y="218" text-anchor="middle">mekanisk, 2 endret.</text>
|
||
<text class="tiny" x="640" y="236" text-anchor="middle">Vakten ble kjørt RØD først.</text>
|
||
<text class="tiny" x="640" y="254" text-anchor="middle">Suite: 1089 passed / 5 skipped</text>
|
||
|
||
<text class="lbl" x="890" y="46" text-anchor="middle">11.09 · P12</text>
|
||
<text class="sub" x="890" y="70" text-anchor="middle">re-måling på HEAD</text>
|
||
<path class="edge soft noarrow" d="M890 84 L890 162"/>
|
||
<text class="tiny" x="890" y="200" text-anchor="middle">6 / 5 / 8 uendret, rad for rad,</text>
|
||
<text class="tiny" x="890" y="218" text-anchor="middle">over 109 commits.</text>
|
||
<text class="tiny" x="890" y="236" text-anchor="middle">Av de seks ja-radene ligger</text>
|
||
<text class="tiny" x="890" y="254" text-anchor="middle">ÉN på default-stien: GroupChat</text>
|
||
|
||
<text class="lbl" x="1120" y="46" text-anchor="middle">12.09 · F16</text>
|
||
<text class="sub" x="1120" y="70" text-anchor="middle">core 1.16.0 → 1.18.0</text>
|
||
<path class="edge soft noarrow" d="M1120 84 L1120 162"/>
|
||
<text class="tiny" x="1120" y="200" text-anchor="middle">16 former · 19 sjekker ·</text>
|
||
<text class="tiny" x="1120" y="218" text-anchor="middle">0 endret.</text>
|
||
<text class="tiny" x="1120" y="236" text-anchor="middle">Suite: 1577 passed / 5 skipped,</text>
|
||
<text class="tiny" x="1120" y="254" text-anchor="middle">begge gullfilene byte-uendret</text>
|
||
|
||
<path class="edge" d="M40 170 L1200 170"/>
|
||
<circle cx="140" cy="170" r="8" fill="#1c4e8a"/>
|
||
<circle cx="390" cy="170" r="8" fill="#1c4e8a"/>
|
||
<circle cx="640" cy="170" r="8" fill="#1c4e8a"/>
|
||
<circle cx="890" cy="170" r="8" fill="#1c4e8a"/>
|
||
<circle cx="1120" cy="170" r="8" fill="#1c4e8a"/>
|
||
</svg>
|
||
<figcaption>Gulvet bor i én konstant, og <code>pyproject</code>-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.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Funn 99, 08.09 — den beste live-historien i repoet.</b> Tre <code>quick_validate</code>-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 <code>include_detailed_errors</code> er satt, teller det som en feil, og stopper etter <code>DEFAULT_MAX_CONSECUTIVE_ERRORS_PER_REQUEST = 3</code>. 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.</p>
|
||
<p class="src">Kilde: <code>docs/2026-09-02-f15-maf-pinnen.md</code> · <code>docs/2026-09-11-p12-maf-gjeld.md</code> · <code>docs/2026-09-12-f16-maf-1180.md:21-22</code> · <code>docs/2026-09-08-funn-99-chatclient-refusal.md:46-50</code> · <code>tests/test_maf_version_guard.py:26-31</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== part67-status.html ===== -->
|
||
<!-- del6-divider -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 6 · Kvalitetsmetoden og målt status</span></p>
|
||
<h1>Kvalitetsmetoden og målt status</h1>
|
||
<p class="lede">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.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del6-loadbearing -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">49</span><span class="part">Del 6 · Kvalitetsmetoden og målt status</span></p>
|
||
<h2>En load-bearing test er en test som FEILER når sømmen kobles fra.</h2>
|
||
<p class="lede">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.</p>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 480" role="img" aria-label="Fire steg fra søm til mutasjon, to utfall, og tre konkrete eksempler">
|
||
<rect class="box" x="10" y="20" width="265" height="76"/>
|
||
<text class="lbl" x="24" y="52">1 · Sømmen</text>
|
||
<text class="sub" x="24" y="74">en beslutning som er tatt i koden</text>
|
||
<rect class="box" x="315" y="20" width="265" height="76"/>
|
||
<text class="lbl" x="329" y="52">2 · Load-bearing test</text>
|
||
<text class="sub" x="329" y="74">skrevet for å feile, ikke for å passere</text>
|
||
<rect class="box" x="620" y="20" width="265" height="76"/>
|
||
<text class="lbl" x="634" y="52">3 · Mutasjon</text>
|
||
<text class="sub" x="634" y="74">sømmen kobles fra i en kopi</text>
|
||
<rect class="box" x="925" y="20" width="265" height="76"/>
|
||
<text class="lbl" x="939" y="52">4 · Hele suiten kjøres</text>
|
||
<text class="sub" x="939" y="74">én mutasjon per kjøring</text>
|
||
<path class="edge" d="M275 58 H313"/>
|
||
<path class="edge" d="M580 58 H618"/>
|
||
<path class="edge" d="M885 58 H923"/>
|
||
<path class="edge" d="M1057 96 V126 H752 V148"/>
|
||
<path class="edge warn" d="M1057 96 V148"/>
|
||
<rect class="box ok" x="620" y="150" width="265" height="92"/>
|
||
<text class="lbl" x="634" y="176">RØD</text>
|
||
<text class="sub" x="634" y="198">sømmen er vitnet: beslutningen</text>
|
||
<text class="sub" x="634" y="216">kan ikke fjernes i stillhet</text>
|
||
<rect class="box warn" x="925" y="150" width="265" height="92"/>
|
||
<text class="lbl" x="939" y="176">GRØNN</text>
|
||
<text class="sub" x="939" y="198">et FUNN, aldri en pass: fiks</text>
|
||
<text class="sub" x="939" y="216">testen, eller uttal sømmen</text>
|
||
<text class="sub" x="939" y="234">som uvitnet, med grunn</text>
|
||
<text class="band-lbl" x="10" y="292">Tre sømmer, tre tester, tellingen bak hver</text>
|
||
<rect class="box" x="10" y="306" width="380" height="156"/>
|
||
<text class="mono" x="24" y="334">test_checker_gate_loadbearing.py</text>
|
||
<text class="sub" x="24" y="360">Kobler checkeren fra utfallet.</text>
|
||
<text class="sub" x="24" y="380">Rød på TO uavhengige punkter:</text>
|
||
<text class="sub" x="24" y="400">reverter output_from=agents,</text>
|
||
<text class="sub" x="24" y="420">eller fjern overstyringen.</text>
|
||
<text class="tiny" x="24" y="444">2 armer</text>
|
||
<rect class="box" x="410" y="306" width="380" height="156"/>
|
||
<text class="mono" x="424" y="334">test_ungiven_verdict_loadbearing.py</text>
|
||
<text class="sub" x="424" y="360">Kobler dommen fra stillheten.</text>
|
||
<text class="sub" x="424" y="380">Hver flaggløs kjøring myntet en</text>
|
||
<text class="sub" x="424" y="400">ekspertgodkjenning ingen hadde gitt,</text>
|
||
<text class="sub" x="424" y="420">og den reiste til neste prosjekt.</text>
|
||
<text class="tiny" x="424" y="444">15 armer, 8 mutasjoner røde</text>
|
||
<rect class="box" x="810" y="306" width="380" height="156"/>
|
||
<text class="mono" x="824" y="334">test_frozen_bundles_loadbearing.py</text>
|
||
<text class="sub" x="824" y="360">Kobler målingen fra det frosne</text>
|
||
<text class="sub" x="824" y="380">korpuset. Avvik er høylytt,</text>
|
||
<text class="sub" x="824" y="400">fravær er en skip — de to</text>
|
||
<text class="sub" x="824" y="420">tilstandene blandes aldri.</text>
|
||
<text class="tiny" x="824" y="444">17 armer, 8 mutasjoner røde</text>
|
||
</svg>
|
||
<figcaption>Armtallene er lest med <code>pytest --co</code> mot hver fil 18.09.2026. Mutasjonstallene står i hovedbokens egne rader.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Fellen har et navn i repoet: «grønn-men-død».</b> Fase 2 er der den ble funnet. <code>run_portfolio</code> hadde ikke parametrene <code>bundle_dir</code>/<code>verdict_dir</code> 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 <code>retrieved</code>, aldri prompten.</p>
|
||
<p class="callout"><b>Jernloven gjelder også vaktene selv.</b> 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 <b>10 av 20 mutanter</b>; etter herding var <b>20 av 20 røde</b>.</p>
|
||
<p class="src">Kilde: <code>README.md:375</code> · <code>docs/review-2026-07.md:57</code> · <code>docs/invarianter.md:3093</code> · <code>docs/2026-09-02-f15-maf-pinnen.md</code> · <code>STATE.md § Driftsmodell</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del6-hovedboken -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">50</span><span class="part">Del 6 · Kvalitetsmetoden og målt status</span></p>
|
||
<h2>Hovedboken fører beslutningen, målingen som tvang den fram, og testen som går rød.</h2>
|
||
<p class="lede"><code>docs/invarianter.md</code> er 3 176 linjer og <b>94 rader</b> (talt 18.09.2026). Rader adresseres med grep på overskriften, aldri med linjenummer. Åtte av dem:</p>
|
||
<table class="compact">
|
||
<thead><tr><th>Regelen</th><th>Målingen som tvang den fram</th><th>Går rød</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>To falsifiserere over én kandidat: validatoren gater tallene, checkeren gater resonnementet. De blandes aldri.</td><td>Metodespeken §2/§6, steg 3 og 4</td><td><code>test_checker_gate_loadbearing.py</code>, rød på begge frakoblingspunkter</td></tr>
|
||
<tr><td>Gaten er forankret i prosjektets egen kostnadsbasis. Stadium 0 avstemmer mot <code>CostBaseline</code> før solveren. Validering, aldri reparasjon.</td><td>Før S4.0 resonnerte hvert stadium bare om tall forslaget selv leverte, så en internt konsistent hallusinasjon klarerte hele gaten</td><td><code>test_s40_cost_baseline_loadbearing.py</code>, 6 mutasjoner røde</td></tr>
|
||
<tr><td>Et kravnummer er ikke en pris.</td><td>P20 del B, 15.09: <code>10.4</code> 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</td><td><code>docs/invarianter.md:2750</code></td></tr>
|
||
<tr><td>En ekspertdom kan ikke oppstå av stillhet. <code>RunResult.verdict</code> er <code>Verdict | None</code>.</td><td>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</td><td><code>test_ungiven_verdict_loadbearing.py</code>, 15 armer, 8 mutasjoner røde</td></tr>
|
||
<tr><td>Penger kvantiseres i én rekkefølge, fra én kilde: per beløp, så summeres heltallene.</td><td>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</td><td><code>test_money_quantization_loadbearing.py</code>, 5 mutasjoner røde</td></tr>
|
||
<tr><td>Sporing er opt-in, og «av» betyr at MAF aldri kalles.</td><td>Et kall med tom exporter-liste ville installert providers og lest hver <code>OTEL_EXPORTER_OTLP_*</code> i omgivelsene. «Av» må være fravær av kallet</td><td><code>test_tracing_loadbearing.py</code>, 9 mutasjoner røde</td></tr>
|
||
<tr><td>En nekt modellen skal kunne rette seg etter er en returverdi, aldri en raise.</td><td>Funn 99, 08.09: MAF gjør en raise om til <code>Error: Function failed.</code>, undertrykker detaljen og teller den mot grensen på 3 påfølgende verktøyfeil. Modellen gjettet på JSON-formatet, som var riktig hele veien</td><td><code>test_run_cli_chatclient_refusal.py</code>, 8 armer, 7 mutasjoner røde</td></tr>
|
||
<tr><td>Målingene leser en FROSSET kopi av korpuset, pinnet med sha256 — aldri et annet repos build-mappe.</td><td>17.09 kl. 17:43: nabo-repoet bygde om <code>r761-2025</code>, gatens rad 6 og 7 ble IKKE MÅLT og fem tester falt, for en endring ingen her hadde gjort</td><td><code>test_frozen_bundles_loadbearing.py</code>, 17 armer, 8 mutasjoner røde</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="callout"><b>Hovedboken ble flyttet 18.09.2026.</b> <code>CLAUDE.md</code> 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.</p>
|
||
<p class="src">Kilde: <code>docs/invarianter.md</code> · <code>STATE.md § NESTE</code> · talt med <code>grep -c '^- \*\*' docs/invarianter.md</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del6-kontekstkostnad -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">51</span><span class="part">Del 6 · Kvalitetsmetoden og målt status</span></p>
|
||
<h2>Kontekstkostnaden ble målt før noe ble bygget, og den formet navigasjonen.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 500" role="img" aria-label="Fire målte kontekstkostnader, hver med søyle for før og etter">
|
||
<text class="lbl" x="10" y="40">list_bundles — katalogen</text>
|
||
<text class="sub" x="10" y="60">3 flate Vegnormal-baser, o200k_base</text>
|
||
<text class="tiny" x="10" y="78">docs/2026-08-26-katalogkostnaden.md</text>
|
||
<text class="tiny" x="420" y="42" text-anchor="end">før</text>
|
||
<rect class="box soft" x="430" y="24" width="560" height="24"/>
|
||
<text class="mono" x="1000" y="42">112 116 tok</text>
|
||
<text class="tiny" x="420" y="78" text-anchor="end">etter</text>
|
||
<rect class="box accent" x="430" y="60" width="5" height="24"/>
|
||
<text class="mono" x="1000" y="78">362 tok</text>
|
||
<line class="hair" x1="10" y1="110" x2="1190" y2="110"/>
|
||
|
||
<text class="lbl" x="10" y="158">read_bundle — payloaden</text>
|
||
<text class="sub" x="10" y="178">tunnel-basen, 5 kopier per kjøring</text>
|
||
<text class="tiny" x="10" y="196">docs/2026-09-02-read-bundle-kontekstkostnad.md</text>
|
||
<text class="tiny" x="420" y="160" text-anchor="end">før</text>
|
||
<rect class="box soft" x="430" y="142" width="560" height="24"/>
|
||
<text class="mono" x="1000" y="160">12 595 tok</text>
|
||
<text class="tiny" x="420" y="196" text-anchor="end">etter</text>
|
||
<rect class="box accent" x="430" y="178" width="12" height="24"/>
|
||
<text class="mono" x="1000" y="196">259 tok</text>
|
||
<line class="hair" x1="10" y1="228" x2="1190" y2="228"/>
|
||
|
||
<text class="lbl" x="10" y="276">K2: listing i alt</text>
|
||
<text class="sub" x="10" y="296">629 konsepter; 89 % til 26 % av prompt-tokens</text>
|
||
<text class="tiny" x="10" y="314">docs/2026-09-03-hierarkisk-navigasjon-k2.md</text>
|
||
<text class="tiny" x="420" y="278" text-anchor="end">før</text>
|
||
<rect class="box soft" x="430" y="260" width="560" height="24"/>
|
||
<text class="mono" x="1000" y="278">307 573 tok</text>
|
||
<text class="tiny" x="420" y="314" text-anchor="end">etter</text>
|
||
<rect class="box accent" x="430" y="296" width="23" height="24"/>
|
||
<text class="mono" x="1000" y="314">12 595 tok</text>
|
||
<line class="hair" x1="10" y1="346" x2="1190" y2="346"/>
|
||
|
||
<text class="lbl" x="10" y="394">bundle_context i debatten</text>
|
||
<text class="sub" x="10" y="414">K2: 648 962 tokens × 3 kopier = 99,1 % av prompt-tokens</text>
|
||
<text class="tiny" x="10" y="432">docs/invarianter.md:1719 — etter: en O(1)-peker</text>
|
||
<text class="tiny" x="420" y="396" text-anchor="end">før</text>
|
||
<rect class="box soft" x="430" y="378" width="560" height="24"/>
|
||
<text class="mono" x="1000" y="396">1 947 342 tok</text>
|
||
<text class="tiny" x="420" y="432" text-anchor="end">etter</text>
|
||
<rect class="box accent" x="430" y="414" width="5" height="24"/>
|
||
<text class="mono" x="1000" y="432">753 tok</text>
|
||
</svg>
|
||
<figcaption>Hver rad er skalert mot sin EGEN «før»-søyle; radene er ikke sammenlignbare med hverandre. Søyler under 5 px er tegnet som 5 px.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>Dette er ikke «−N % kostnad» for en kjøring.</b> Det som er målt er hvert verktøys eget bidrag til prompt-tokens. En navigatør som går <i>k</i> nivåer ned betaler <i>k</i> 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).</p>
|
||
<p class="src">Kilde: <code>docs/invarianter.md:1027</code>, <code>:1104</code>, <code>:1719</code> · <code>docs/2026-08-26-katalogkostnaden.md</code> · <code>docs/2026-09-03-hierarkisk-navigasjon-k2.md</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del6-vist-ikke-vist -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">52</span><span class="part">Del 6 · Kvalitetsmetoden og målt status</span></p>
|
||
<h2>Mekanismen er vist. At metoden gir verdi, er ikke vist.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 520" role="img" aria-label="To kolonner: hva som er vist og hva som ikke er vist">
|
||
<rect class="band ok" x="10" y="10" width="580" height="500"/>
|
||
<text class="band-lbl" x="32" y="42">Vist, med nevner</text>
|
||
<text class="lbl" x="32" y="86">Sløyfa lukkes ende til ende</text>
|
||
<text class="sub" x="32" y="106">offline, mot en skriptet stand-in-klient</text>
|
||
<text class="lbl" x="32" y="158">Gaten biter</text>
|
||
<text class="sub" x="32" y="178">18 av 20 rader avvist i runde 1, hver grunn sann</text>
|
||
<text class="lbl" x="32" y="230">Én levende kjøring, 14.08.2026</text>
|
||
<text class="sub" x="32" y="250">gpt-4.1-mini på Foundry; 1. forsøk RC=1 BudgetExceeded, gjenkjøring rejected</text>
|
||
<text class="lbl" x="32" y="302">Ingest-goldens er bit-identiske</text>
|
||
<text class="sub" x="32" y="322">fil/CSV og SQL, på begge stacker</text>
|
||
<text class="lbl" x="32" y="374">1 995 tester samlet 18.09.2026</text>
|
||
<text class="sub" x="32" y="394">179 testfiler, 124 av dem load-bearing</text>
|
||
<text class="lbl" x="32" y="446">Mutasjonene er talt, ikke antatt</text>
|
||
<text class="sub" x="32" y="466">en grønn mutasjon er et funn, aldri en pass</text>
|
||
|
||
<rect class="band warn" x="610" y="10" width="580" height="500"/>
|
||
<text class="band-lbl" x="632" y="42">Ikke vist</text>
|
||
<text class="lbl" x="632" y="86">Ingen validert forslag mot en levende modell</text>
|
||
<text class="sub" x="632" y="106">null, målt ved misjonsreview 25.08</text>
|
||
<text class="lbl" x="632" y="158">Ingen ekte ekspertdom i treet</text>
|
||
<text class="sub" x="632" y="178">hver seedet dom er merket AI-forfattet syntetikk</text>
|
||
<text class="lbl" x="632" y="230">Ingen base fra en levende kilde</text>
|
||
<text class="sub" x="632" y="250">ingest er kjørt mot fixtures og en lokal mock</text>
|
||
<text class="lbl" x="632" y="302">Claude SDK-søskenet er parkert</text>
|
||
<text class="sub" x="632" y="322">ikke utviklet parallelt</text>
|
||
<text class="lbl" x="632" y="374">Ingen stressrunde er et utvalg</text>
|
||
<text class="sub" x="632" y="394">én modell, ett deployment, én kjøring per sett</text>
|
||
<text class="lbl" x="632" y="446">Ingen faktura er lest</text>
|
||
<text class="sub" x="632" y="466">hvert NOK-tall er et listepris-anslag</text>
|
||
</svg>
|
||
<figcaption>Testtallet er målt i denne økten med <code>uv run pytest -q --co</code> (kun innsamling; suiten ble ikke kjørt). STATE fører hovedtreet som 1 984 passed / 5 skipped / 5 xfailed.</figcaption>
|
||
</figure>
|
||
<p class="callout"><b>To forsøk samme dag, begge dokumentert.</b> Måleprotokollen fra 14.08 fører første forsøk som RC=1 med <code>BudgetExceeded</code> 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 <code>rejected</code>: validatoren tok en kostlinje modellen hadde funnet på, på toleranseporten fordi bundlen ikke bar noen baseline. README beskriver gjenkjøringen. Kilde: <code>docs/2026-08-14-fase1b-forste-levende-kjoring.md:35-60</code> og <code>:189-224</code>.</p>
|
||
<p class="src">Kilde: <code>docs/2026-08-14-fase1b-forste-levende-kjoring.md:36</code>, <code>:55</code> · <code>README.md:281</code>, <code>:284</code> · <code>docs/2026-08-25-fable-misjonsreview.md:21</code>, <code>:22</code> · <code>docs/2026-09-14-p16-stressrunde-1.md:178</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del6-stressrunder -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">53</span><span class="part">Del 6 · Kvalitetsmetoden og målt status</span></p>
|
||
<h2>Seks betalte runder flyttet fasit-treffet fra 0 av 26 til 3 av 20 — og nevneren skiftet underveis.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 330" role="img" aria-label="Seks stressrunder med treff, nevner, tokenforbruk og hovedfunn, delt av et nevnerskille">
|
||
<text class="lbl" x="10" y="34">P16 · runde 1</text>
|
||
<text class="tiny" x="10" y="52">14.09.2026</text>
|
||
<rect class="box soft" x="10" y="66" width="160" height="20"/>
|
||
<text class="lbl" x="10" y="112">0 av 26</text>
|
||
<text class="sub" x="10" y="132">fasit-konsepter åpnet</text>
|
||
<text class="tiny" x="10" y="154">2 679 305 tokens</text>
|
||
<text class="tiny" x="10" y="184">Tre av sju kjøringer</text>
|
||
<text class="tiny" x="10" y="200">døde på rundetaket.</text>
|
||
<text class="tiny" x="10" y="216">Dokumentert kommando</text>
|
||
<text class="tiny" x="10" y="232">kunne ikke kjøres.</text>
|
||
|
||
<text class="lbl" x="205" y="34">P18 · runde 2</text>
|
||
<text class="tiny" x="205" y="52">14.09.2026</text>
|
||
<rect class="box soft" x="205" y="66" width="160" height="20"/>
|
||
<text class="lbl" x="205" y="112">0 av 26</text>
|
||
<text class="sub" x="205" y="132">fasit-konsepter åpnet</text>
|
||
<text class="tiny" x="205" y="154">289 054 tokens</text>
|
||
<text class="tiny" x="205" y="184">−89 % tokens mot</text>
|
||
<text class="tiny" x="205" y="200">runde 1, uendret treff.</text>
|
||
<text class="tiny" x="205" y="216">0 av 5 døde på taket.</text>
|
||
|
||
<text class="lbl" x="400" y="34">P19 · runde 3</text>
|
||
<text class="tiny" x="400" y="52">15.09.2026</text>
|
||
<rect class="box soft" x="400" y="66" width="160" height="20"/>
|
||
<rect class="box accent" x="400" y="66" width="5" height="20"/>
|
||
<text class="lbl" x="400" y="112">1 av 32</text>
|
||
<text class="sub" x="400" y="132">fasit-konsepter åpnet</text>
|
||
<text class="tiny" x="400" y="154">539 207 tokens (+1 umålt)</text>
|
||
<text class="tiny" x="400" y="184">F1: klausulnummeret</text>
|
||
<text class="tiny" x="400" y="200">10.4 ble validert som</text>
|
||
<text class="tiny" x="400" y="216">kostkode. Rundetaket</text>
|
||
<text class="tiny" x="400" y="232">kappet 5 av 5.</text>
|
||
|
||
<text class="lbl" x="595" y="34">P20 · runde 4</text>
|
||
<text class="tiny" x="595" y="52">15.09.2026</text>
|
||
<rect class="box soft" x="595" y="66" width="160" height="20"/>
|
||
<rect class="box accent" x="595" y="66" width="10" height="20"/>
|
||
<text class="lbl" x="595" y="112">2 av 32</text>
|
||
<text class="sub" x="595" y="132">fasit-konsepter åpnet</text>
|
||
<text class="tiny" x="595" y="154">896 492 tokens</text>
|
||
<text class="tiny" x="595" y="184">--max-rounds 5 var den</text>
|
||
<text class="tiny" x="595" y="200">største enkelteffekten:</text>
|
||
<text class="tiny" x="595" y="216">0 av 6 traff taket, eget</text>
|
||
<text class="tiny" x="595" y="232">forslag vurdert 6 av 6.</text>
|
||
|
||
<path class="edge noarrow dashed" d="M775 20 V300"/>
|
||
<text class="band-lbl" x="783" y="300">ulik nevner</text>
|
||
|
||
<text class="lbl" x="800" y="34">P21 · runde 5</text>
|
||
<text class="tiny" x="800" y="52">15.09.2026</text>
|
||
<rect class="box soft" x="800" y="66" width="160" height="20"/>
|
||
<rect class="box accent" x="800" y="66" width="8" height="20"/>
|
||
<text class="lbl" x="800" y="112">1 av 20</text>
|
||
<text class="sub" x="800" y="132">grunnet, per tilnærming</text>
|
||
<text class="tiny" x="800" y="154">1 130 145 tokens</text>
|
||
<text class="tiny" x="800" y="184">Første FORANKREDE</text>
|
||
<text class="tiny" x="800" y="200">runde: 0 av 20 validert.</text>
|
||
<text class="tiny" x="800" y="216">a4 bestod 5 av 5, men</text>
|
||
<text class="tiny" x="800" y="232">gaten nektet 20 av 20 —</text>
|
||
<text class="tiny" x="800" y="248">armen skilte ingenting.</text>
|
||
|
||
<text class="lbl" x="995" y="34">P22 · runde 6</text>
|
||
<text class="tiny" x="995" y="52">16.09.2026</text>
|
||
<rect class="box soft" x="995" y="66" width="160" height="20"/>
|
||
<rect class="box accent" x="995" y="66" width="24" height="20"/>
|
||
<text class="lbl" x="995" y="112">3 av 20</text>
|
||
<text class="sub" x="995" y="132">grunnet, per tilnærming</text>
|
||
<text class="tiny" x="995" y="154">913 320 tokens</text>
|
||
<text class="tiny" x="995" y="184">Validert 10 av 20,</text>
|
||
<text class="tiny" x="995" y="200">priset 16 av 20 — men</text>
|
||
<text class="tiny" x="995" y="216">must_refuse falt til 2</text>
|
||
<text class="tiny" x="995" y="232">av 5: ingen stage stiller</text>
|
||
<text class="tiny" x="995" y="248">falsifiseringsspørsmålet.</text>
|
||
</svg>
|
||
<figcaption>Runde 1–4 teller fasit-KONSEPTER åpnet (dokumenter i <code>fasit.must_cite</code>). Runde 5–6 rapporterer i stedet <code>grounded</code> 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. <b>Og en sammendragslinje i STATE blander de to målene:</b> «0/26, 0/26, 1/32, 2/20, 1/20, 1/20» har skiftende nevner, og den siste verdien tilhører <code>named</code>, ikke <code>grounded</code> — runde 6 leser <code>grounded</code> 3 av 20. Konklusjonen overlever korreksjonen; aritmetikken i linja gjør det ikke.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>«N100 = FERDIG» fra økt 102 er motsagt av P16 til P22.</b> 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 <code>must_refuse</code> 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.</p>
|
||
<p class="src">Kilde: <code>docs/2026-09-14-p16-stressrunde-1.md</code> · <code>-p18-</code> · <code>-p19-</code> · <code>-p20-</code> · <code>-p21-</code> · <code>docs/2026-09-16-p22-stressrunde-6.md</code> · <code>STATE.md</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del7-divider -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Del 7 · Etter v1.1</span></p>
|
||
<h1>Etter v1.1</h1>
|
||
<p class="lede">v1.2.0 er repoets versjon, satt 20.09.2026; v1.1.0 ble sluppet 14.08.2026 og er den siste TAGGEDE 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.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del7-destinasjonen -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">54</span><span class="part">Del 7 · Etter v1.1</span></p>
|
||
<h2>Destinasjonen er ikke en tag. Den er én rapport en fagperson har rettet tre ganger.</h2>
|
||
<p class="point">Ferdig-kriteriet, ordrett fra <code>PLAN.md § Destinasjonen</code>: «Én ekte kostnadsrapport for <code>shared/examples/bygg-energi-mikro</code>, 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.»</p>
|
||
<div class="cols">
|
||
<div class="col">
|
||
<span class="step">Hvorfor det ble omskrevet</span>
|
||
<p>Ø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.</p>
|
||
</div>
|
||
<div class="col">
|
||
<span class="step">Hva målingen faktisk viste</span>
|
||
<p>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: <code>grounded</code> nådde aldri over 3 av 20.</p>
|
||
</div>
|
||
<div class="col soft">
|
||
<span class="step">Hva som endret seg i planen</span>
|
||
<p>«v1» ble omdefinert fra en tag til en produkttilstand — repoet står allerede på 1.2.0. Kriteriet ble skrevet så det kan FELLES, og en ny syntetisk stressrunde 7 er eksplisitt forbudt.</p>
|
||
</div>
|
||
</div>
|
||
<p class="callout warn"><b>En ramme planen ber om at ikke skjules:</b> én person er bestiller, fagperson og operatør. «Det er en kjent begrensning.» Loggen i <code>PLAN.md</code> har åtte rader, og seks av dem sier «ingen bevegelse på kriteriet». En serie av dem er i seg selv et funn.</p>
|
||
<p class="src">Kilde: <code>PLAN.md § Destinasjonen</code>, <code>§ Problemet vi løser</code>, <code>§ Rammer</code>, <code>§ Logg</code> · <code>STATE.md</code> (local-only, ikke publisert)</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del7-gaten -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">55</span><span class="part">Del 7 · Etter v1.1</span></p>
|
||
<h2>Avstanden måles av en gate som kjører offline og returnerer exit 1.</h2>
|
||
<p class="lede"><code>uv run python -m portfolio_optimiser.evals.v1_gate</code> — deterministisk, ingen modellkall, ingen kvote. Hver nevner kommer utenfra det som måles.</p>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 420" role="img" aria-label="v1-gatens sju rader med krav, dagens tall og status">
|
||
<text class="band-lbl" x="24" y="24">rad</text>
|
||
<text class="band-lbl" x="64" y="24">krav</text>
|
||
<text class="band-lbl" x="840" y="24">i dag</text>
|
||
<text class="band-lbl" x="1000" y="24">status</text>
|
||
<line class="hair" x1="10" y1="34" x2="1190" y2="34"/>
|
||
|
||
<text class="lbl" x="24" y="66">1</text>
|
||
<text class="sub" x="64" y="66">runder med ekte fagperson på bygg-energi-mikro</text>
|
||
<text class="mono" x="840" y="66">0 av 3</text>
|
||
<rect class="box warn" x="1000" y="48" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="66" text-anchor="middle">RØD</text>
|
||
<line class="hair" x1="10" y1="86" x2="1190" y2="86"/>
|
||
|
||
<text class="lbl" x="24" y="118">2</text>
|
||
<text class="sub" x="64" y="118">runder som endret rapporten målbart mot forrige</text>
|
||
<text class="mono" x="840" y="118">0 av 3</text>
|
||
<rect class="box warn" x="1000" y="100" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="118" text-anchor="middle">RØD</text>
|
||
<line class="hair" x1="10" y1="138" x2="1190" y2="138"/>
|
||
|
||
<text class="lbl" x="24" y="170">3</text>
|
||
<text class="sub" x="64" y="170">tilbakemeldingstyper med vei inn OG handling</text>
|
||
<text class="mono" x="840" y="170">3 av 8</text>
|
||
<rect class="box warn" x="1000" y="152" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="170" text-anchor="middle">RØD</text>
|
||
<line class="hair" x1="10" y1="190" x2="1190" y2="190"/>
|
||
|
||
<text class="lbl" x="24" y="222">4</text>
|
||
<text class="sub" x="64" y="222">runde 3-rapport beholdt: minst 80 % av innholdslinjene</text>
|
||
<text class="mono" x="840" y="222">ingen rapport</text>
|
||
<rect class="box warn" x="1000" y="204" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="222" text-anchor="middle">RØD</text>
|
||
<line class="hair" x1="10" y1="242" x2="1190" y2="242"/>
|
||
|
||
<text class="lbl" x="24" y="274">5</text>
|
||
<text class="sub" x="64" y="274">MAF-punkter i bruk, hvert med peker til en tilbakemeldingstype</text>
|
||
<text class="mono" x="840" y="274">3 av 8</text>
|
||
<rect class="box warn" x="1000" y="256" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="274" text-anchor="middle">RØD</text>
|
||
<line class="hair" x1="10" y1="294" x2="1190" y2="294"/>
|
||
|
||
<text class="lbl" x="24" y="326">6</text>
|
||
<text class="sub" x="64" y="326">forslag validert UTEN erklæring fra tilnærmingen</text>
|
||
<text class="mono" x="840" y="326">prober 2 av 2</text>
|
||
<rect class="box dashed" x="1000" y="308" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="326" text-anchor="middle">IKKE MÅLT</text>
|
||
<line class="hair" x1="10" y1="346" x2="1190" y2="346"/>
|
||
|
||
<text class="lbl" x="24" y="378">7</text>
|
||
<text class="sub" x="64" y="378">named — diagnose, ingen terskel, flytter aldri exit-koden</text>
|
||
<text class="mono" x="840" y="378">1 av 20</text>
|
||
<rect class="box soft" x="1000" y="360" width="170" height="26"/>
|
||
<text class="tiny" x="1085" y="378" text-anchor="middle">DIAGNOSE</text>
|
||
</svg>
|
||
<figcaption>Tre farger, ikke to. <b>IKKE MÅLT feller exit-koden nøyaktig som RØD</b>, og blir aldri rendret som null: rad 6s prober er grønne, men stressrunde 6s artefakter er eldre enn regelen — 16 erklæringer bærer ingen <code>approach_id</code>. Gaten skriver en attestering på hver kjøring: «rad 1–2 beviser ikke at en fagperson skrev feedbacken; det bekrefter operatøren.»</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>src/portfolio_optimiser/evals/v1_gate.py:1-15</code> · <code>PLAN.md § Ferdig-kriteriet</code> · <code>STATE.md § NESTE</code> · gaten kjørt 18.09.2026 (exit 1)</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del7-arbeidsstrommer -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">56</span><span class="part">Del 7 · Etter v1.1</span></p>
|
||
<h2>Åtte arbeidsstrømmer står mellom gaten og exit 0.</h2>
|
||
<table class="compact">
|
||
<thead><tr><th>Strøm</th><th>Status</th><th>Hva som gjenstår, målt</th><th>Kilde</th></tr></thead>
|
||
<tbody>
|
||
<tr><td>Rad 2: bind runden til en KJØRING gaten selv kan verifisere</td><td>PÅGÅR</td><td>Ordre i køen fra 17.09. PM re-målte 18.09: rad 2 ble <b>3 av 3 grønn</b> på håndskrevne <code>outcome.json</code> og <code>coverage.json</code> pluss <code>os.utime</code>. «Kjøringen finnes» er implementert som «en fil med det navnet finnes», og det oppfyller <code>touch</code>.</td><td>ordre <code>…-1292712426</code></td></tr>
|
||
<tr><td>Rapportfila en fagperson faktisk leser</td><td>PLANLAGT</td><td>Avgjort 17.09: en ny, lesbar fil bygget fra utboksen. Den finnes ikke i dag, og verken <code>--report</code> eller proposal-filene er noe en fagperson leser. 80 %-regelen måles mot den.</td><td><code>PLAN.md</code> åpent spm. 2</td></tr>
|
||
<tr><td>Kapabilitetsordrer, én per rød rad og type</td><td>PLANLAGT</td><td>Rad 3 står 3 av 8. Fem typer mangler vei inn: fjern en retning, lett på et krav, konseptgrafer, skills, inline kontekst. <code>grep relax</code> i <code>src</code> gir 0 mekanismer.</td><td><code>PLAN.md § Nevnere</code></td></tr>
|
||
<tr><td>P22 funn 1: falsifiseringsarmens spørsmål</td><td>ÅPENT (operatørbeslutning)</td><td>Ingen stage i gaten spør om kunnskapsbasen bærer et krav som støtter retningen. <code>must_refuse</code> 2 av 5 i runde 6. Anslått én økt.</td><td>P22 § 4</td></tr>
|
||
<tr><td><code>named</code> og terskelen</td><td>ÅPENT SPØRSMÅL</td><td>1 av 20 fjerde runde på rad. Å be modellen gjengi <code>ref</code> gjør den til noe den blir BEDT om; derfor står raden som diagnose.</td><td><code>PLAN.md</code> åpent spm. 6</td></tr>
|
||
<tr><td>Hosting</td><td>BYGGET, IKKE TATT I BRUK</td><td>Inngangen finnes fra fase 4d: <code>main.py</code> rundt <code>run_project</code> på én asyncio-løkke, med readiness og invocations. <code>Dockerfile</code> og <code>azure.yaml</code> ble fjernet 14.08 til fordel for én startkommando, <code>agent-framework-foundry-hosting</code> er ikke installert i treet, og ingen deployment er målt.</td><td><code>docs/invarianter.md:192</code></td></tr>
|
||
<tr><td>Prisskjemaet som tabell med kolonner</td><td>KRYSS-REPO</td><td>Observasjon videresendt til <code>llm-ingestion-okf</code>, ikke bestilt: et prisskjema med kolonner ville latt <code>--derive-cost-baseline</code> forankre stadium 0. Det leverte skjemaet er uleselig i FORM, ikke fraværende i byte.</td><td>S7c-målingen</td></tr>
|
||
<tr><td>MAF-gjelden: context provideren som ikke bærer noe</td><td>UTSATT</td><td>Skopet 29.08, ikke bygget. Strukturelt, ikke en enlinjes: <code>context_providers</code> er et konstruksjonsargument på <code>Agent</code>, mens proposeren kaller <code>chat_client.get_response()</code> direkte.</td><td><code>docs/2026-08-29-maf-gjelden-omfang.md:26-38</code></td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="callout warn"><b>En strukturell spenning — dette er en lesning, ikke repoets tekst (antakelse).</b> 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.</p>
|
||
<p class="callout"><b>Måle-hygiene som egen sak.</b> 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 <code>uv run pytest -q --co</code>.</p>
|
||
<p class="src">Kilde: <code>PLAN.md § Ferdig-kriteriet</code>, <code>§ Åpne spørsmål</code> · <code>STATE.md § NESTE</code> · ordre <code>20260917T223645Z-1292712426</code> · <code>docs/2026-09-16-p22-stressrunde-6.md § 4</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- del7-ikke-bygges -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">57</span><span class="part">Del 7 · Etter v1.1</span></p>
|
||
<h2>Listen over hva som ikke skal bygges er skrevet ned, og den er like bindende som kriteriet.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 420" role="img" aria-label="To kolonner: hva som bygges mot v1 og hva som ikke skal bygges">
|
||
<rect class="band accent" x="10" y="10" width="580" height="400"/>
|
||
<text class="band-lbl" x="32" y="42">Bygges mot v1</text>
|
||
<text class="lbl" x="32" y="86">Rapportfila, bygget fra utboksen</text>
|
||
<text class="sub" x="32" y="106">avgjort 17.09; 80 %-regelen måles mot den</text>
|
||
<text class="lbl" x="32" y="150">Rundekatalogen, bundet til en ekte kjøring</text>
|
||
<text class="sub" x="32" y="170">v1-rounds/ er gitignored; formen står i --help</text>
|
||
<text class="lbl" x="32" y="214">De fem manglende tilbakemeldingsflatene</text>
|
||
<text class="sub" x="32" y="234">type 2, 4, 5, 6 og 8</text>
|
||
<text class="lbl" x="32" y="278">Stadiet som stiller falsifiseringsspørsmålet</text>
|
||
<text class="sub" x="32" y="298">P22 funn 1, anslått én økt</text>
|
||
<text class="lbl" x="32" y="342">Kostnadsmodell per analyse</text>
|
||
<text class="sub" x="32" y="362">planen låser seg ikke til dagens ene modell</text>
|
||
|
||
<rect class="band warn" x="610" y="10" width="580" height="400"/>
|
||
<text class="band-lbl" x="632" y="42">Bygges ikke</text>
|
||
<text class="lbl" x="632" y="86">Ny stressrunde på syntetiske mandater</text>
|
||
<text class="sub" x="632" y="106">og ingen niende tilbakemeldingstype</text>
|
||
<text class="lbl" x="632" y="150">Nye korpus: N400 og R762</text>
|
||
<text class="sub" x="632" y="170">basene publiseres ikke, ingen etatskontakt</text>
|
||
<text class="lbl" x="632" y="214">Compliance-funksjoner</text>
|
||
<text class="sub" x="632" y="234">DPIA, ROS og behandlingsformål eies av den som deployer</text>
|
||
<text class="lbl" x="632" y="278">Reallokering mellom prosjekter</text>
|
||
<text class="sub" x="632" y="298">besparelsene finnes INNI hvert prosjekt</text>
|
||
<text class="lbl" x="632" y="342">Autonom beslutning</text>
|
||
<text class="sub" x="632" y="362">validatoren kan bare blokkere; å godkjenne er fagpersonens</text>
|
||
</svg>
|
||
<figcaption>Venstre kolonne er planens arbeid mot ferdig-kriteriet. Høyre kolonne er <code>PLAN.md § Hva som IKKE skal bygges</code> og <code>§ Rammer</code>, pluss READMEs non-goals.</figcaption>
|
||
</figure>
|
||
<p class="callout warn"><b>Fire forbud til, ført i STATE:</b> Magentic er ikke debatt-default — utforskningen legges OVER Group Chat-sløyfa, aldri inni. <code>git subtree push</code> fra en konsument skjer aldri; <code>shared/</code> 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 <code>--question</code> og <code>--docs-dir</code>-omveien.</p>
|
||
<p class="src">Kilde: <code>PLAN.md § Hva som IKKE skal bygges</code>, <code>§ Rammer</code> · <code>README.md:265</code> · <code>STATE.md § Låste beslutninger</code>, <code>§ NESTE</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ===== part8-close.html ===== -->
|
||
|
||
<!-- kom i gang -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">58</span><span class="part">Avslutning</span></p>
|
||
<h2>Hele kjeden kan gås offline: sju kommandoer, null nettverk, null kostnad.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 430" role="img" aria-label="De sju offline-kommandoene fra README, i rekkefølge">
|
||
<rect class="box soft" x="10" y="20" width="270" height="70"/>
|
||
<text class="lbl" x="24" y="46">1 · Se kunnskapsbasen</text>
|
||
<text class="mono" x="24" y="68">ls shared/examples/bygg-energi-mikro/</text>
|
||
<text class="tiny" x="24" y="84">kuratert markdown, ikke en svart boks</text>
|
||
<path class="edge" d="M280 55 L318 55"/>
|
||
<rect class="box accent" x="320" y="20" width="270" height="70"/>
|
||
<text class="lbl" x="334" y="46">2 · Læringssløyfen lukkes</text>
|
||
<text class="mono" x="334" y="68">uv run portfolio-optimiser-demo</text>
|
||
<text class="tiny" x="334" y="84">Run A → ekspertdom → Run B, begge markører</text>
|
||
<path class="edge" d="M590 55 L628 55"/>
|
||
<rect class="box accent" x="630" y="20" width="270" height="70"/>
|
||
<text class="lbl" x="644" y="46">3 · Egne skriptede svar</text>
|
||
<text class="mono" x="644" y="68">run … --scripted-replies replies.json</text>
|
||
<text class="tiny" x="644" y="84">ender i ValidatedProposal</text>
|
||
<path class="edge" d="M900 55 L938 55"/>
|
||
<rect class="box warn" x="940" y="20" width="250" height="70"/>
|
||
<text class="lbl" x="954" y="46">4 · Se den si nei</text>
|
||
<text class="mono" x="954" y="68">claimed_saving_nok: 250000</text>
|
||
<text class="tiny" x="954" y="84">Rejection, uansett hvor sikker proposer var</text>
|
||
|
||
<path class="edge soft" d="M1065 90 L1065 130 L145 130 L145 168"/>
|
||
<rect class="box soft" x="10" y="170" width="270" height="70"/>
|
||
<text class="lbl" x="24" y="196">5 · Kostnad før du betaler</text>
|
||
<text class="mono" x="24" y="218">costsim --projects 4 --profile local</text>
|
||
<text class="tiny" x="24" y="234">øvre grense per rolle og modell, kilde oppgitt</text>
|
||
<path class="edge" d="M280 205 L318 205"/>
|
||
<rect class="box accent" x="320" y="170" width="270" height="70"/>
|
||
<text class="lbl" x="334" y="196">6 · Hele porteføljen</text>
|
||
<text class="mono" x="334" y="218">run --portfolio --scripted-replies …</text>
|
||
<text class="tiny" x="334" y="234">1 validated, 3 rejected: porten forankres per prosjekt</text>
|
||
<path class="edge" d="M590 205 L628 205"/>
|
||
<rect class="box ok" x="630" y="170" width="270" height="70"/>
|
||
<text class="lbl" x="644" y="196">7 · Det som faktisk er realisert</text>
|
||
<text class="mono" x="644" y="218">run --report --ledger savings-ledger.json</text>
|
||
<text class="tiny" x="644" y="234">leser en ledger du selv skrev; null modellkall</text>
|
||
|
||
<rect class="band" x="10" y="290" width="1180" height="120"/>
|
||
<text class="band-lbl" x="24" y="312">Hver skriptet kjøring skriver et banner</text>
|
||
<text class="sub" x="24" y="338">Det offline-beviset viser er at sløyfen lukkes og at porten biter. Det viser ikke hvor godt en gitt modell foreslår eller dømmer.</text>
|
||
<text class="sub" x="24" y="360">En skriptet kjøring som leser som en modellkjøring ville vært verre enn ingen offline-modus. Derfor sier banneret det høyt.</text>
|
||
<text class="sub" x="24" y="392">Deretter: egen bundle i --bundle-dir (trenger validator-input.json), så en lokal modell på loopback, så Foundry med minimal, målrettet verifisering.</text>
|
||
</svg>
|
||
<figcaption>De sju stegene i README-ens «Walk the whole chain offline», i den rekkefølgen de er ment å kjøres.</figcaption>
|
||
</figure>
|
||
<div class="cols">
|
||
<div class="col"><span class="step">Terskelen er lav med vilje</span><p>Klon, <code>uv sync</code>, <code>uv run pytest</code>, og så de sju stegene. Ingen CI i organisasjonen: testsuiten fra en ren klone <i>er</i> verifikasjonen.</p></div>
|
||
<div class="col"><span class="step">Wheelen er ikke nok alene</span><p>To git-pinnede sikkerhetskomponenter må oppgis ved siden av wheelen; pinnene bor i <code>pyproject.toml</code>.</p></div>
|
||
<div class="col"><span class="step">Fork-and-own</span><p>Solo-vedlikeholdt, MIT. Issues er signaler; pull requests tas ikke imot.</p></div>
|
||
</div>
|
||
<p class="src">Kilde: <code>README.md</code> «Install» og «Walk the whole chain offline» · <code>pyproject.toml</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- helheten -->
|
||
<section class="slide">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="num">59</span><span class="part">Avslutning</span></p>
|
||
<h2>Helheten på én side: fem lag, tre porter, to mennesker, én sløyfe tilbake.</h2>
|
||
<figure class="fig">
|
||
<svg viewBox="0 0 1200 470" role="img" aria-label="Hele arkitekturen samlet i én figur">
|
||
<!-- lag 1: mennesker inn -->
|
||
<rect class="band" x="10" y="10" width="1180" height="70"/>
|
||
<text class="band-lbl" x="24" y="30">Mennesker, inn</text>
|
||
<rect class="box" x="24" y="38" width="260" height="34"/><text class="sub" x="36" y="60">Fagfolk kuraterer kunnskapsbasen (OKF)</text>
|
||
<rect class="box" x="300" y="38" width="260" height="34"/><text class="sub" x="312" y="60">Operatør bestiller: mandat + cost-baseline</text>
|
||
<rect class="box soft" x="576" y="38" width="290" height="34"/><text class="sub" x="588" y="60">Ingest-laget materialiserer, content gate foran</text>
|
||
<rect class="box soft dashed" x="882" y="38" width="290" height="34"/><text class="sub" x="894" y="60">Opt-in: MCP-kilder, prepass-kutt, explore</text>
|
||
|
||
<!-- lag 2: maskinen -->
|
||
<rect class="band accent" x="10" y="95" width="1180" height="150"/>
|
||
<text class="band-lbl" x="24" y="115">Maskinen, én kjøring (MAF GroupChat + deterministisk validator)</text>
|
||
<rect class="box accent" x="24" y="128" width="200" height="50"/><text class="lbl" x="36" y="150">Naviger</text><text class="tiny" x="36" y="168">index.md først, fire verktøy</text>
|
||
<path class="edge" d="M224 153 L256 153"/>
|
||
<rect class="box accent" x="258" y="128" width="200" height="50"/><text class="lbl" x="270" y="150">Hypotese (IR)</text><text class="tiny" x="270" y="168">+ tidligere dommer foldet inn</text>
|
||
<path class="edge" d="M458 153 L490 153"/>
|
||
<rect class="box accent" x="492" y="128" width="200" height="50"/><text class="lbl" x="504" y="150">Debatt</text><text class="tiny" x="504" y="168">proposer ↔ checker, rundetak</text>
|
||
<path class="edge" d="M692 153 L724 153"/>
|
||
<rect class="box warn" x="726" y="128" width="200" height="50"/><text class="lbl" x="738" y="150">Validator</text><text class="tiny" x="738" y="168">tall: portrekke, blokkerende</text>
|
||
<path class="edge" d="M926 153 L958 153"/>
|
||
<rect class="box" x="960" y="128" width="212" height="50"/><text class="lbl" x="972" y="150">Utfall + provenance</text><text class="tiny" x="972" y="168">validated · rejected · unsupported</text>
|
||
<path class="edge warn dashed" d="M826 178 L826 210 L358 210 L358 180"/>
|
||
<text class="tiny" x="420" y="204">Refinement: avvisningsgrunnen inn i neste forsøk, maks 3, under token-tak</text>
|
||
<rect class="box soft" x="960" y="196" width="212" height="34"/><text class="tiny" x="972" y="217">{run_id}-*.json, deterministisk outbox</text>
|
||
|
||
<!-- lag 3: mennesker ut -->
|
||
<rect class="band" x="10" y="260" width="1180" height="70"/>
|
||
<text class="band-lbl" x="24" y="280">Mennesker, ut (dager senere)</text>
|
||
<rect class="box" x="24" y="288" width="340" height="34"/><text class="sub" x="36" y="310">Fagperson dømmer: {verdict.id}.json i innboks-mappe</text>
|
||
<rect class="box ok" x="380" y="288" width="300" height="34"/><text class="sub" x="392" y="310">Promotion gate, fail-closed → type: verdict</text>
|
||
<rect class="box ok" x="696" y="288" width="476" height="34"/><text class="sub" x="708" y="310">Realisert besparelse → ledger (menneske skriver) → --report</text>
|
||
|
||
<!-- sløyfe tilbake -->
|
||
<path class="edge accent" d="M530 322 L530 350 L124 350 L124 250 L124 180"/>
|
||
<text class="tiny" x="140" y="345">Neste kjøring leser dommen som wiki-kunnskap: læring på tvers av kjøringer, aldri i minnet</text>
|
||
|
||
<!-- bunn: portene -->
|
||
<rect class="band warn" x="10" y="370" width="1180" height="90"/>
|
||
<text class="band-lbl" x="24" y="390">Tre porter som aldri slås sammen</text>
|
||
<text class="sub" x="24" y="414"><tspan class="lbl">Validatoren</tspan> gater tallene. Kan bare blokkere, aldri godkjenne på agentenes ord.</text>
|
||
<text class="sub" x="24" y="434"><tspan class="lbl">Checkeren</tspan> gater resonnementet. <tspan class="lbl">Promotion-porten</tspan> gater hva som blir varig kunnskap: kun en godkjent dom.</text>
|
||
<text class="sub" x="24" y="454">Ingen ubegrenset sløyfe: rundetak, forsøkstak, token-tak og stoppkriterier er påkrevd ved oppstart, og hver søm har en test som feiler når den kobles fra.</text>
|
||
</svg>
|
||
<figcaption>Samme figur som i Del 2, nå med alt du har sett i mellomtiden lagt inn.</figcaption>
|
||
</figure>
|
||
<p class="src">Kilde: <code>README.md</code> «How it works» · <code>docs/invarianter.md</code> · <code>src/portfolio_optimiser/run.py</code>, <code>validator.py</code>, <code>verdicts.py</code>, <code>ledger.py</code></p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- takk / lenker -->
|
||
<section class="slide divider">
|
||
<div class="inner">
|
||
<p class="kicker"><span class="part">Spørsmål</span></p>
|
||
<h1>Spørsmål?</h1>
|
||
<p class="lede">Alt i dette decket kan slås opp. Start her:</p>
|
||
<div class="cols">
|
||
<div class="col">
|
||
<span class="step">Repoet</span>
|
||
<p><code>git.fromaitochitta.com/open/portfolio-optimiser</code></p>
|
||
<p>README (engelsk), <code>docs/invarianter.md</code> (hovedboken), <code>docs/extending.md</code></p>
|
||
</div>
|
||
<div class="col">
|
||
<span class="step">Den delte kjernen</span>
|
||
<p><code>git.fromaitochitta.com/open/portfolio-optimiser-commons</code></p>
|
||
<p><code>shared/method-spec.md</code>, <code>shared/ingest-spec.md</code>, ekspert-persona som Agent Skill, eksempelbundle + golden suite</p>
|
||
</div>
|
||
<div class="col">
|
||
<span class="step">Harnessen</span>
|
||
<p><code>learn.microsoft.com/agent-framework/</code></p>
|
||
<p>Overview, orchestrations, observability, og «Python 2026 significant changes» for navneendringene</p>
|
||
</div>
|
||
<div class="col">
|
||
<span class="step">For fagfolk og ledere</span>
|
||
<p><code>docs/kort-presentasjon.html</code> (12 slides, allmennpublikum)</p>
|
||
<p><code>docs/presentasjon-fagpersonens-bidrag.html</code>, <code>docs/presentasjon-bygge-kunnskapsbase.html</code></p>
|
||
</div>
|
||
</div>
|
||
<p class="small">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.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<div id="nav">
|
||
<button id="prev" type="button">← Forrige</button>
|
||
<button id="next" type="button">Neste →</button>
|
||
<span class="hint">Piltaster, mellomrom eller klikk. Home/End hopper til start/slutt. Uten JavaScript vises alt som én side.</span>
|
||
<span id="count"></span>
|
||
</div>
|
||
<script>
|
||
(function () {
|
||
var body = document.body;
|
||
var slides = Array.prototype.slice.call(document.querySelectorAll('.slide'));
|
||
if (!slides.length) return;
|
||
body.classList.add('js');
|
||
body.setAttribute('tabindex', '-1');
|
||
try { body.focus({ preventScroll: true }); } catch (err) { body.focus(); }
|
||
var progress = document.getElementById('progress');
|
||
var count = document.getElementById('count');
|
||
var current = -1;
|
||
function clamp(n) { return Math.max(0, Math.min(slides.length - 1, n)); }
|
||
function show(n) {
|
||
n = clamp(n);
|
||
if (n === current) return;
|
||
if (current >= 0) slides[current].classList.remove('active');
|
||
current = n;
|
||
slides[current].classList.add('active');
|
||
count.textContent = (current + 1) + ' / ' + slides.length;
|
||
progress.style.width = ((current + 1) / slides.length * 100) + '%';
|
||
window.scrollTo(0, 0);
|
||
if (history.replaceState) { history.replaceState(null, '', '#' + (current + 1)); }
|
||
else { location.hash = '#' + (current + 1); }
|
||
}
|
||
function fromHash() {
|
||
var n = parseInt((location.hash || '').replace('#', ''), 10);
|
||
return isNaN(n) ? 0 : n - 1;
|
||
}
|
||
function next() { show(current + 1); }
|
||
function prev() { show(current - 1); }
|
||
document.getElementById('next').addEventListener('click', function (e) { e.stopPropagation(); next(); });
|
||
document.getElementById('prev').addEventListener('click', function (e) { e.stopPropagation(); prev(); });
|
||
document.addEventListener('click', function (e) {
|
||
if (e.target.closest && e.target.closest('a, button, pre, code, table, svg')) return;
|
||
var sel = window.getSelection();
|
||
if (sel && String(sel).length > 0) return;
|
||
next();
|
||
});
|
||
function keyOf(e) {
|
||
if (e.code === 'Space' || e.key === 'Spacebar' || e.key === ' ') return ' ';
|
||
if (e.keyCode === 32) return ' ';
|
||
return e.key;
|
||
}
|
||
function onKey(e) {
|
||
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
||
var key = keyOf(e);
|
||
if (e.target && e.target.tagName === 'BUTTON' && (key === ' ' || key === 'Enter')) return;
|
||
switch (key) {
|
||
case 'ArrowRight': case 'ArrowDown': case 'PageDown': case ' ': case 'Enter':
|
||
e.preventDefault(); next(); break;
|
||
case 'ArrowLeft': case 'ArrowUp': case 'PageUp': case 'Backspace':
|
||
e.preventDefault(); prev(); break;
|
||
case 'Home': e.preventDefault(); show(0); break;
|
||
case 'End': e.preventDefault(); show(slides.length - 1); break;
|
||
}
|
||
}
|
||
document.addEventListener('keydown', onKey);
|
||
window.addEventListener('hashchange', function () { show(fromHash()); });
|
||
show(fromHash());
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|