Etter reviewens to funn: den tredje doera har naa sitt eget vitne (M16), og project_id narrowes i stedet for aa defaultes. 16 mutasjoner, 15 roede, kontroll 1275/5. Baerer ogsaa den TREDJE vakuoese armen denne oekten produserte - M16s foerste form erklaerte id-ene paa rot-index og ett konsept, og sto groenn fordi S7a-3 holdt rot-indeksen utenfor enighets-settet med vilje. Og et funn som er MAALT, RAPPORTERT og IKKE FIKSET fordi det ligger utenfor ordren: --mandate selv staar ikke i report_forbidden, saa --report --ledger X --mandate Y dropper kommisjonen i stillhet. F4-gapets klasse, paa et flagg som er eldre enn denne ordren. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
160 KiB
portfolio-optimiser
Note for visitors — what this file is. This is the working agreement between the repository and the AI coding agent that builds it (the Claude Code convention), and it is written in Norwegian because that is the maintainer's working language. It doubles as the repository's invariant ledger: each block below records a design decision, the measurement that forced it, and the test that turns red when the decision is undone.
You need none of it to use the framework — start with the README. It is published anyway, because the reasoning behind a decision is worth more than the decision, and because a rule kept out of sight is a rule that drifts without anyone noticing.
Kontekst
Generisk, åpent Python-rammeverk på Microsoft Agent Framework (MAF) som finner kostnadsbesparelser INNI hvert prosjekt i en portefølje av uavhengige prosjekter. Multi-agent samarbeid genererer kandidat-tiltak; en obligatorisk deterministisk validator avgjør verdiene; fageksperter vurderer via HITL, og systemet lærer av dommene. Publiseres på Forgejo for alle som har MAF.
Bakgrunn og beslutninger: research (§15 implementeringsregister), plan. Løpende state: STATE.md (local-only).
Stack
Python ≥3.10. MAF (agent-framework-core 1.16.0, -orchestrations 1.1.1 — F15, 02.09). Pakkehåndtering: uv. To backend-profiler: Azure/Foundry (full) + lokal (fallback).
Konvensjoner
- Type hints overalt (
mypyder mulig). Pydantic for validering/IR. rufffor lint+format.pytestfor test.- Modell-valg som konfig (modell-map rolle→Foundry-deployment), ikke spredt i kode.
- Metode kodifiseres som Agent Skill (
agentskills.io:SKILL.md+scripts/+references/). - Datatilgang: in-process
FunctionTooler default-sømmen i kjørestien. MCP er wiret som opt-in i kjørestien (mcp_tools.py+--mcp-config, Trekk B 2026-08-05): konkrete eksterne servere blir verktøy agentene kan kalle UNDER debatten. Uten konfig gjøres null nettverkskall og verktøylista er uendret. Tre regler er load-bearing: allowlist er påkrevd (tom liste ville latt motparten bestemme hva agentene får kalle), hver server og hvert tillatte verktøy navngis i kunngjøringen før første kall (også uten--mandate— ingen udeklarert egress), og--live-dry-runåpner ingenting. Egen søm fraingest_mcp.py(kildedokumenter FØR kjøring, null-argument-tools) — samme protokoll, ulik jobb.build_mcp_server(datasource.py) er fortsatt kun demo. Data-source-konfig JSON-Schema-validert, fail-fast. shared/er en git subtree avportfolio-optimiser-commons(source of truth, R1 realisert 2026-07-03; publisert iopen/2026-08-04 —commons-remoten peker fortsatt på den private namespacen og virker uendret). Synk er pull-only: endringer committes i commons og hentes medgit subtree pull --prefix=shared commons main --squash. ALDRIgit subtree pushfra konsument — re-split lekker hele konsument-historikken inn i commons (observert + opprydd 2026-07-03). Seshared/README.md. Wheelen bærer treet som pakkede data siden Fase 4a — se invarianten under.
Kommandoer
- Sync:
uv sync— installerer to konsoll-kommandoer:portfolio-optimiser(CLI,run:main) ogportfolio-optimiser-demo(offline-beviset,simulation:main).python -m-formene virker uendret og er byte-identiske på stdout (målt). Bevisst KUN to av femmain()—costsim/hitl/preflighter operatørverktøy, ikke produktets inngang, og hvert navn her er et navn frysen må bære. Pinnet avtests/test_console_entry_points.pymot den INSTALLERTE distribusjonens metadata, ikke mot TOML-en: en[project.scripts]-linje som aldri eruv sync-et er en påstand, ikke en kommando. - Test:
uv run pytest - Lint:
uv run ruff check .+uv run ruff format . - Type:
uv run mypy src
Arbeidsflyt (invarianter)
-
Rent teknisk rammeverk: deployer eier DPIA/ROS/behandlingsformål. Bygg IKKE compliance-funksjoner — kun tekniske forutsetninger (lokal-only, provenance, ingen stille egress) + disclaimer.
-
90%-prinsipp: bygg den generiske kjernen + tydelige extension points; jakt IKKE de siste 10 %.
-
Deterministisk validator er obligatorisk og blokkerende — aldri valgfri plugin.
-
Framework-nøytral kontekst-søm: OKF-bundle-navigasjon (
okf.py) og den delteshared/-kjernen er ren stdlib — nullagent_framework/mcp-import, så samme bundles konsumeres uendret av begge stacker (D7-portabel). Håndhevet avtests/test_okf.py::test_okf_is_maf_free; importér aldri MAF inn i kontekst-laget. -
OKF-navigert bundle-kontekst (ikke stuffing): på bundle-stien bygges agent-lese-konteksten ved å NAVIGERE bundelen (
okf.bundle_context: index + frontmatter + cross-links, progressiv disclosure) — aldri keyword-chunk-stuffing (målbilde §2/§4).type: verdict-laget ekskluderes fra denne konteksten: tidligere dommer når hypotese-prompten KUN via den gatede ExpeL-folden. Load-bearing:test_bundle_context_excludes_verdict_layer+ empty-store-kontrollen itest_step1_expel_loadbearing.py(realiseringssignalet lekker aldri inn via kontekst). -
Navigasjons-kontrakten er hierarkisk, og escape — ikke dybde — er forbudt (
method-spec§3 Steg 1):navigate_bundlefølger cross-links REKURSIVT, dybde-først i først-sett-rekkefølge; ledende/betyr bundle-rot (aldri filsystem-absolutt), alt annet er relativt til den LENKENDE filas katalog; dedup skjer på resolvert sti (så./a.md==a.md, og sykler termineres).safe_resolveer den ENESTE inn-/ut-av-bundle-testen (fail-closed) — den erstattet den pensjonerte «separator = utenfor bundelen»-heuristikken, som forvekslet dybde med escape. Manglendeindex.mder feil KUN i bundle-rota (navigasjon følger lenker, aldri katalog-enumerering). Rendering er FLAT uansett dybde; nestedeindex.mder navigasjon, ikke innhold. Gaten er commons-eide nav-goldens (shared/examples/nav-golden-*/expected-read-context.md, byte-nivå fasit):test_nav_golden_hierarchy_*(positiv) +test_nav_golden_escape_*(negativ — en gate som bare kan bli grønn beviser ingenting). Et hopp er TOLERERT, men ikke lenger TAUST (21.08):_walkregistrerer hver lenke den ikke fulgte påBundle.skipped— hvilken fil lenken sto i, lenketeksten ORDRETT (operatøren redigerer den teksten, ikke den resolverte stien), og hvilken av de TO grunnene som gjaldt:outside-bundle(escape — ofte bevisst, en lenke til nabobasen) ellermissing(inne i basen, ingen lesbar fil — nesten alltid en skrivefeil). Den tredje grenen,canonical in seen, er DEDUP og registreres ALDRI — den er korrekt navigasjon og dét som terminerer sykler; en implementasjon som logget hvertcontinueville rapportert en frisk base som halvlest. Toleransen er URØRT (§4 krever at det ikke kastes) — dette er synlighet, ikke en ny nekt. Feltet DEFAULTER til tom tuppel, og det er MOTSATT avcost_baseline_anchoreds «påkrevd uten default»: en tom trace er et ærlig POSITIVT utsagn («hver lenke ble fulgt»,external_calls-presedensen), mens en manglende bool måtte påstå noe om en hendelse og begge påstandene ville iblant vært usanne. Sporet forlater kjøringen påRunResult.skipped_links(RUN-nivå — navigasjonen skjer ÉN gang per kjøring, før noe forslag finnes) ogDryRunReport.skipped_links, aldri påProvenanceStamp, som beskriver gaten som dømte ÉN kandidat.run.skipped_links_noticeer ENESTE renderer, tar den alt oppløste tuppelen og returnererNonenår ingenting ble hoppet over (omisjon, aldri tom rad —announce-regelen); reason-TOKENET printes rått, så det finnes ingen andre display-vokabular å drifte fra feltet. Ingenting av dette nårbundle_context(som bygges avindex_summary+context_filesalene) — dét er hva som holder nav-goldenene byte-uendret, ogBundle(har fortsatt ÉN konstruksjons-sted (okf.py, inavigate_bundle). Load-bearing MÅLT (tests/test_navigation_visibility_loadbearing.py), åtte mutasjoner alle røde mot HELE suiten + grønn kontroll 897/5: detachmissing-registreringen (6 røde) · detachoutside-bundle(2 røde) · kollaps de to grunnene til én (2 røde) · registrer dedup-grenen (1 rød) · renderer returnerer alltid linja (3 røde — inkl. kontrollene, altså er omisjonen selv gatet) · detach dry-run-printen (1 rød) · detach full-run-printen (1 rød) · konstant tom trace ut avrun_project(4 røde). -
Kuraterte skrivere kan ikke forfalske ingest-stempelet (
ingest-spec§3):write_concept_fileer repoets ene authoring-primitiv som materialiserer en konseptfil fra CALLER-oppgitt frontmatter, og avviser derfor det KOMPLETTE eierskaps-stempelet (generated: true+ingest_manifest) medIngestStampError— mens hver halvdel alene er lovlig (kuratert innhold kan bære ett provenance-felt). Validering, ALDRI reparasjon: ingenting skrives. Uten dette kunne en kuratert fil bli stille slettet av en senere re-materialisering, som fjerner nøyaktig det som bærer stempelet.generated-verdien er FAIL-CLOSED på YAML-1.1-sannhetsformer, ikke bare literalen"true"(funn 21.08, økt 52):_YAML_TRUE_LITERALS({"true", "yes", "on"}, case-insensitivt) er ENESTE vokabular, målt mot PyYAML sinsafe_load-resolver — bare1/barey/ner BEVISST UTELATT (resolves til int/streng, aldri bool, så en YAML-leser ville uansett ikke lest dem som stempelet). Uten dette var sjekken inert kun i kraft av at pinnetllm-ingestion-okf v0.3.2skriver strengen"true"— en fremtidiguv syncmot en skrivemåte somyes/onville latt vakten slutte å vokte uten én lokal diff. Load-bearing MÅLT (tests/test_ingest_stamp_fail_closed_loadbearing.py), fire mutasjoner alle røde mot HELE suiten: revert til literalen"true"(2 røde — de nye sannhetsformene alene) · over-widen til å inkludere1/y(1 rød) ·and→or(4 røde, halv-stempel-lovligheten brutt) · detach gaten helt (4 røde). -
IngestErrormå overleve anyio-task-gruppene (kø-(x), 2026-08-03):stdio_clientogClientSessioner hver sin task group, og anyio pakker ALT som forlater en av dem i enBaseExceptionGroup. Derfor nåddestdio_call_tools egne feil (mcp_tool_error,mcp_non_text_content) kalleren som en exception group — aldri somIngestError, som er typen hele Door A fanger og switcher på viacode._unwrap_ingest_errorpakker ut og re-raiser den eide feilen; alt annet re-raises URØRT (innsnevring, aldri blanket re-raise). Duck-typet på.exceptions, fordiexcept*/ExceptionGrouper 3.11+ og repoet er>=3.10. Ingen canned-tool-test kunne fanget dette — de går aldri inn i en task group; defekten dukket opp første gang koden faktisk ble kjørt. En MCP-server på ingest-stien må eksponere en null-argument-tool (URL-en bærer begge koordinatene, tool kalles med{}), sådatasource.build_mcp_serverkan IKKE serve den —retrieve_cost_docs(query)har et påkrevd argument og returnerer et error-result. De to er separate sømmer med vilje. Load-bearing MÅLT (tests/test_ingest_golden_mcp.py), fem mutasjoner alle røde: detach unwrappingen · detachinitialize()· gjør feilkoden generisk · detachisError-grenen · endre ett byte av bodyen. -
MCP-timeouten må komponeres MED anyios eget cancel scope, ikke
asyncio.wait_forutenfra (kø-(z), 2026-08-03): STATE-premisset ("en utypetTimeoutErrorre-raises urørt") var FEIL — målt mot en EKTE hengende server gaasyncio.wait_for(run(), timeout=...)aldri enTimeoutErrori det hele tatt; den kansellererrun()UTENFRA strukturen anyio selv eier (stdio_client/ClientSession), og de to kansellerings-mekanismene komponerer ikke — målt utfall var enanyio.BrokenResourceErrorinni enBaseExceptionGroup(en bakgrunns-reader-task mistet skrive-enden midt i nedrigging). Fiksen eranyio.fail_after(timeout_seconds)NESTET INNI begge task-gruppene, der anyio rigger ned sin egen struktur rent og raiser en renTimeoutError. Innsnevringen dekker IKKE bare typen: builtinTimeoutErrorer ogsåsocket.timeout(≥3.10) ogasyncio.TimeoutError(≥3.11), så et ubetingetexcept TimeoutErrorville mislabelt en HVILKEN SOM HELSTTimeoutErrorsommcp_timeout— reviewet FØR commit (advisor) fant nøyaktig dette. Retteslen eranyio.CancelScope.cancelled_caught: kun scopet som faktisk traff SIN EGEN deadline tjenermcp_timeout-koden, ellers re-raises urørt (speiler_unwrap_ingest_errors eierskaps-regel). Ingen levende utløser finnes i dag for en "fremmed"TimeoutErrorpå denne stien — MÅLT: MCPs eget per-request read-timeout (ClientSession.send_request) konverterer sinanyio.fail_aftertilMcpErrorFØR den når oss, og en tool som raiserTimeoutErrorserver-side blir et ordinærtisError-resultat (samme som enhver annen tool-exception) — begge verifisert empirisk, ikke antatt. Diskriminatoren er likevel pinned med en syntetisk test (raiser fraStdioServerParameters-konstruksjon, inni fail_after-scopet men FØR noen task group), fordi defektklassen ellers ikke har en nåbar sti å bevise den mot. Load-bearing MÅLT (tests/test_ingest_golden_mcp.py) mot HELE 625-suiten, fire mutasjoner alle røde: detach hele oversettelsen · revert tilasyncio.wait_for· relabel koden · detachcancelled_caught-gaten (behold kun scope-presence).anyiopromotert fra transitiv (viamcp) til deklarert direkte dep (pyproject.toml) — modulen importerer den nå direkte. -
Door A-innholdsgaten kan IKKE bo i
materialize— den bor rundt den (P2/S1.b, 2026-08-09):materializeer en REN delegasjon til det pinnedellm_ingestion_okfv0.3.2smaterialize_bundle, som stager i minnet og utfører sin EGEN disk-fase; det finnes ingen callback mellom de to, så en gate plassert «i skrivepunktet» kunne bare kjørt ETTER at bytene hadde landet — en opprydding, ikke en gate (planens premiss, felt ved måling FØR bygging).materialize_gateder derfor: kopier bundelen → materialiser inn i kopien → skann det som ble generert → publiser eller forkast. Kopien er BÆRENDE: bibliotekets §3 eierskaps-skann, kollisjons-gaten mot kuratert innhold og §6 index-merge leser alle den EKSISTERENDE bundelen — staging i en tom katalog mister alle tre og publiserer en bundle uten kuraterte naboer og deres index-lenker (datatap forkledd som sikkerhetsfiks; MÅLT av kun ÉN test, 809 andre merket ingenting).materializeforblir UGATET med vilje — fire golden-suiter pinner bytene, og en kaller som vil ha gaten ber om den ved navn. Utfall per BUNDLE, diagnostikk per DOKUMENT: delvis publisering ville etterlatt bundle + index som svarer til INTET manifest, menimport_bundleitererer forbi første avvisning så hvert funn rapporteres. Trust følger ORIGIN, aldri channel (Origin.EXTERNAL/Channel.AUTOMATIC= UNTRUSTED) — ikke et av guardens toPolicy-preset:PRESET_USER_UPLOADbærerquarantine_default=Truesom Door A ikke har. Den laveste dispositionen erwarn, ikkeallow(warn < quarantine_review < fail_secure;allowfinnes ikke) — en gate skrevet mot== allowville avvist hvert dokument noensinne. Funnene tillog.md(OKF §7), ALDRI konsept-frontmatter — der ville de brutt fire goldener. Guarden shipper ingenpy.typed: mypy-override ALENE gjør sømmen type-BLIND, så_stamp_line+ koersering stopperAnyved grensen. Load-bearing MÅLT (tests/test_ingest_content_gate_loadbearing.py), fem mutasjoner alle røde + grønn kontroll: detach gaten · la den fyre ETTER publisering ·Origin.INTERNAL· tom staging-katalog · rapporter kun første avvisning. Målingen felte en VAKUØS test først: en hard injeksjon scorerfail_secureunder BEGGE tierene, såOrigin.INTERNAL-mutasjonen lot alle tre avvisningstestene stå grønne — beslutningen så dekket ut uten å være testet. Båndet der tieren faktisk avgjør er høy-entropi-innhold (quarantine_reviewvswarn), og testen ble skrevet mot nøyaktig det. -
shared/leses som PAKKEDE DATA, med arbeidstreet som overstyring (Fase 4a): wheelen bærer en byte-identisk speiling av heleshared/-treet underportfolio_optimiser/_shared/(hatchling force-include ipyproject.toml), ogshared_root()løser ved KALL-tid i fast rekkefølge:PORTFOLIO_SHARED_ROOT→ arbeidstreetsshared/når det finnes → pakket kopi. Arbeidstreet er autoritativt i en checkout — det er dét som holder pull-only-subtree- kontrakten og de byte-eksakte goldenene urørt (målt: goldens shasum-identiske før/etter, ogshared/selv urørt). Den pakkede kopien er dét som gjør wheel og container mulig uten klone (målt før: 1.0.0-wheelen bar 58 filer, null undershared/; etter: 122, hvorav 64 under_shared/, og sdist→wheel-kjeden bærer treet). Speilingen er ALDRI en redigert derivat — byte-identitet er egenskapen som lar commons-goldenene fortsatt gate den pakkede kopien. Load-bearing MÅLT (tests/test_shared_packaged_data_loadbearing.py, ekteuv buildi fixturen — pakkekonfigen er selv en søm), tre mutasjoner alle røde mot hele suiten: detach fallbacken (1 rød) · detach force-include (3 røde) · snu rekkefølgen (1 rød — ordnings-testen var grønn før fiksen; dens kontroll på at pakket kopi FINNES er det som gjør flippen målbar). -
AZURE-profilen leser MILJØET sitt ved kall-tid, ikke operatørens laptop (Fase 4b): endepunktet løses som første IKKE-TOMME av
_ENDPOINT_ENVS— vårt egetPORTFOLIO_FOUNDRY_PROJECT_ENDPOINTFØRST, deretter Foundrys injiserteFOUNDRY_PROJECT_ENDPOINT. Vårt vinner (det er dét enhver doc, recipe og test setter, så en eksport av det er en bevisst handling; en plattformverdi som stille overstyrte den ville vært uforklarlig utenfra), og fallbacken er dét som lar samme image kjøre hostet uten ekstra wiring. Presedensen gjelder VERDIER, ikke deklarasjoner — et eksportert-men-tomt eget navn faller igjennom i stedet for å skygge et ekte injisert inn i en fail-fast. Feilmeldingen navngir BEGGE: operatøren i en container og operatøren på en laptop leter etter hver sin variabel. Credential velges av samme miljø:AzureCliCredentiallokalt (konstruksjon henter INGEN token —az loginer operatørens manuelle steg),ManagedIdentityCredentialnårFOUNDRY_HOSTING_ENVIRONMENTer satt, fordi containeren ikke har noen Azure CLI og plattformen mynter den en egen Entra-identitet ved deploy. IkkeDefaultAzureCredential: Learns egen MAF-veiledning sier «prefer a specific credential such asManagedIdentityCredentialto avoid unintended credential probing» — probing ville vandret en kjede som ikke KAN lykkes der, og gjort en konfigfeil om til en treg en. Markøren leses på truthiness, ikke presence: en eksportert tom verdi er et shell-uhell, ikke et hosting-signal. Klienten eksponerer INGEN credential-attributt (målt), så testene observerer via enFoundryChatClient-recorder — med én UPATCHET arm, ellers ville de kun bevist at vi sender noe som hetercredential. Load-bearing MÅLT (tests/test_hosted_backend_loadbearing.py), fire mutasjoner alle røde mot hele suiten + grønn kontroll: detach credential-valget · presence i stedet for truthiness · detach fallbacken · snu presedensen. Fail-fast-testen ble skrevet VAKUØS først (repoets 08-09-klasse):PORTFOLIO_FOUNDRY_PROJECT_ENDPOINTINNEHOLDERFOUNDRY_PROJECT_ENDPOINT, så asserten på det injiserte navnet var oppfylt av vårt eget; den fjerner nå vårt navn før den sjekker. -
Hostet inngang er en WRAPPER rundt
run_projectpå ÉN asyncio-løkke (Fase 4d):main.py→hosting.pyserverer hosting-kontrakten (port 8088/PORTpå truthiness,GET /readiness,POST /invocations, SIGTERM → exit 0) med stdlib asyncio — ALDRIas_agent()(validator, baseline-forankring, checker-gate og ledger ligger UTENFOR grafen, spike §5) og ALDRI tråder (NG1-guarden:http.servers trådvariant ville lagt samtidige kjøringer på OS-tråder der S3.3-resonnementet ikke holder; samtidige invocations interleaver som koroutiner — samme modell somrun_portfolios bølger, og/readinesssvarer mens en kjøring venter på modell-I/O, målt). Formen er MÅLT, ikke valgt: hosting-pakkasInvocationsHostServerfinnes kun i bygg som krever core>=1.13.0 (treet låser 1.9.0; eneste 1.9-kompatible bygg er en forlatt alfa med defekt metadata — importerermcpudeklarert), og et gjenbrukt bygget workflow er SINGLE-USE på 1.9.0 (målt kall-serie [2, 0, 0] — rundetaket persisterer i objektet, så gjenbruk gir TOMME kjøringer; ferskt objekt per kall er ren kontroll). Payloaden whitelistes pårun_projects signatur — ukjente felt NEKTES ved navn (400), aldri stille droppet (valg-doc §0-fella anvendt på vår egen flate);profiledefaulter tilazureKUN her (containeren har ingen lokal endpoint;run_projects egen default forblir LOCAL). Feilmapping ærlig:ValueError(pydantic-kontrakter subklasser den) → 400,BudgetExceeded→ 429 (EGEN rad under, 14.08), alt annet → 500{error_type, error}(speilerRunFailure), og enRejectioner en VELLYKKET kjøring → 200 — det negative utfallet tilhører payloaden, aldri transporten.outbox.outcome_payloader den ENE kopien av validated/rejected-forgreningen (delt av fil-skriveren og HTTP-responsen — to kopier drifter, kø-(p)-regelen). Container-innpakningen (Dockerfile/azure.yaml) ER FJERNET 14.08 — se python-only-invarianten under; resten av denne raden står, formain.pystartes nå direkte (python main.py). Load-bearing MÅLT (tests/test_hosting_loadbearing.py), seks mutasjoner alle røde mot hele suiten på riktig test: detach felt-mappingen · dropp ukjente felt stille · flipp 400/500 · detach azure-defaulten · detach SIGTERM-handleren · detach main.py-shimen (de to siste fanges KUN av subprosess-testen — P4-presedensen). Chunked request-bodies støttes ikke, og under CPU-bundne strekk (CBC-solven) står readiness — uttalt, ikke skjult. -
Whitelisten må komponere med den EKTE
run_project, og artefaktene gates som RÅ TEKST (Fase 4e): alle 4d-testene gainvokeen stand-in som sluker**kwargs, så whitelisten kunne navngi et feltrun_projectikke tar — eller sende samme argument to ganger — uten at én test merket det, mens en levende container svarte 500. Sømmen errun._default_factory, ikke payloaden:client_factoryNEKTES av whitelisten med vilje (en kaller av en hostet agent skal aldri velge serverens modellklient), så å patche factory-defaulten er eneste injeksjonspunkt flaten etterlater (samme argumenttest_run_cli_loadbearinggjør formain()). Testen sender HVERT whitelistet felt og asserterer dekningen mot_ALLOWED_FIELDS, så et felt lagt til senere ikke kan gli forbi uøvet. Profilen er LOCAL, ikke den hostede defaulten: AZURE-armen slår opp et Foundry-deployment-navn i modell-mappet FØR noen klient bygges (run.pystempler provenance med det), så den kan ikke fullføre offline — containeren trenger altsåPORTFOLIO_MODEL_MAPeller et utfyltdata/model_map.json, ikke bare et endepunkt (målt her, ikke antatt). Artefakt-halvdelen av denne raden er PENSJONERT 14.08 sammen medDockerfile/azure.yaml(rå-tekst-gaten pinnet--platform linux/amd64+ ÉN kopi av startkommandoen; to av radens fem mutasjoner traff nettopp den). Whitelist-halvdelen står URØRT. Load-bearing MÅLT (tests/test_hosting_loadbearing.py), de tre gjenværende mutasjonene alle røde på riktig test og på INGEN annen: sendproject_idto ganger · whitelist et feltrun_projectikke tar · fjernbundle_dirfra whitelisten. -
Et tak som fyrer er IKKE en krasj —
BudgetExceededfår sin EGEN kanal (429), og trippelen bæres som STRUKTUR (1b-køen, 14.08): prosjektets første levende kjøring døde pårounds limit=12 observed=13, og den hostede flaten svarte500 {error_type, error}— altså nøyaktig det samme den sier når modell-endepunktet faller. Beslutningen er S3.4-invarianten anvendt på transporten:budget_stopble holdt UTENFORstop_reasonfordi de to stoppene betyr motsatte ting, og å svare ressurs-utmattelse på krasj-kanalen gjør «det gikk ikke» uleselig på nøyaktig samme måte. IKKE 200, og det er dét som skiller den fraRejection: enRejectioner en kjøring som KONKLUDERTE (og hører derfor i payloaden), mens et uttømt budsjett produserte ingenproposali det hele tatt — en 2xx ville latt en automatisk kaller bokføre «analysert» for en kjøring som analyserte ingenting. 429 fordi betingelsen oppstår av en TILDELING (max_rounds/max_tokenser whitelistede request-felt, og å heve dem er kallerens egen botemiddel), aldri av en serverfeil — derfor 4xx, ikke 5xx.kind/limit/observedlegges ut som felt, ALDRIstr(exc)(kø-(y): de beskriver ÉN ledger, og «hvilket tak bandt, og hvor langt forbi» er hele det operative spørsmålet);error_typeholdes UTE — den nøkkelen tilhører feilkanalen, og en kaller som switcher på dens tilstedeværelse skal ikke finne den her.budget_exhausteder IKKE foldet inn ioutcome_type, og kunne ikke vært det:outbox.outcome_payloader den ENE kopien av den forgreningen og tarValidatedProposal | Rejection, som en uttømt kjøring ikke har noen av. Ærlighets-grense, uttalt: ingenRetry-After— å vente endrer ingenting, botemiddelet er et større tak eller å akseptere stoppet, og en header som lover tid ville vært en løgn. Load-bearing MÅLT (tests/test_hosting_loadbearing.py), fem mutasjoner alle røde mot HELE suiten, hver med sin egen signatur + grønn kontroll 867/4: detach armen (2 røde) · flat streng i stedet for struktur (1 rød — struktur-testen ALENE, altså rir den ikke på status-asserten) · ekkolimitsomobserved(1 rød) · utvid armen tilException(6 røde, inkl. 400-armen) · stempleerror_typepå budsjett-kroppen (1 rød). 500-armens vitne ble byttet, ikke slettet: den eksisterende testen brukteBudgetExceededsom sin 500-prøve, så å bare legge til en ny arm ville etterlatt krasj-kanalen uten vitne — den bærer nå en ekte ikke-budsjett-RuntimeError, og er dét som holder den nye armen SMAL. -
Påstander flaten gjør om SEG SELV gates som rå tekst, linjeforankret (Fase 3, A5): to påstander bodde i prosa der ingen test kunne se dem, og begge drev. (1)
env.templatesa at credential resolves viaDefaultAzureCredential— den har ALDRI gjort det; gaten leser de klassenebackends.pyfaktisk konstruerer fra selve tilordningslinja, ikke fra modulen, fordi kommentarene NAVNGIRDefaultAzureCredentialfire ganger for å begrunne hvorfor den ikke brukes — en fil-bred substring-gate ville vært rød på nøyaktig den prosaen den beskytter (repoets 08-09-klasse, fjerde gang). (2) README-ens wheel-filnavn bærer versjonen bygget stempler på fila, så en versjonsbump ville stille etterlatt en publisert install-kommando som peker på en fil som ikke finnes. Hver positiv assert er paret med en KONTROLL på at det søkes etter noe som finnes — en ekstraktor som stille finner null lager en gate som bare kan bli grønn. Load-bearing MÅLT (tests/test_public_surface_claims_loadbearing.py) mot HELE suiten, begge røde på riktig test og på INGEN annen: gjeninnfør credential-påstanden (2 røde, 844 grønne) · la wheel-filnavnet drifte (1 rød, 845 grønne). Bumpen selv var den tredje målingen —pyproject1.0.0 → 1.1.0 gjorde README-gaten rød alene, FØR README ble rettet.repo-standard-gaten kan IKKE verifisere denne fasen: den var OK/20 sjekker før arbeidet startet, ogRELEASE-STALEer strukturelt blind for repo med null utgivelser (org-ops hovedbok #18). Bevisene er Forgejo-APIet, filinnholdet og ren-klon-kjøringen. -
GOVERNANCE er en LENKE, aldri en kopi (org-ops D11): én kanonisk
GOVERNANCE.mdbor irepo-standardog hvert repo lenker den fra README. Å skrive vår egen ville gjort oss til kopi nr. 12 av en fil D11-bølgen holder på å rydde vekk. Bus-faktor 1 står uttalt i den kanoniske teksten, ikke i vår. -
Stoppkriterier + budsjett-tak påkrevd ved oppstart (fail-fast, aldri ubegrenset loop).
-
Group Chat maker-checker som debatt-default (IKKE Magentic, som er eksperimentell).
-
To falsifiserere, samme kandidat (Steg 3/4, målbilde §2/§6): den deterministiske validatoren gater tallene (blokkerende), checkeren gater resonnementet. Checkeren avslutter turen med en
VERDICT: APPROVE/VERDICT: REJECT — <grunn>-linje; et eksplisitt avslag blokkerer et ellers validert forslag (run_projectoverflater begge debatt-deltakere viaoutput_from=agentsog overstyrer utfallet til en checker-kilde-Rejection). Gaten er opt-in-reject (fail-open ved manglende markør), ogprovenance.validator_decisionforblir ærlig — den speiler KUN validatoren, aldri checkeren (de to falsifisererne blandes aldri). Load-bearing:tests/test_checker_gate_loadbearing.pyblir rød ved BEGGE detach-punkt (revertoutput_from, eller fjern override). Checkeren «må faktisk gate, ELLER vi slutter å kalle det maker-checker». -
Informert forbedring, bundet (Steg 5, målbilde §5/§7):
generate_via_llms ytremax_attempts-løkke er ikke lenger blind — validatorens forrigeRejection.reasonmates inn i neste forsøks prompt (_build_messages(prior_rejection=...)), så proposeren korrigerer i stedet for å gjenta. Kun den mest-nylige falsifiseringen (last, ikke akkumulert), kun grunnen (aldri forrige proposal-JSON), under EKSISTERENDE tak (meter.tick_round+max_attempts— ingen ny løkke; «forbedre til god nok» uten tak er forbudt). Eneste per-forsøk-falsifiserer her er validatoren; å seede generering med checker-kritikken er run-nivå og separat scoped (IKKE bygget her) — så koden påstår ikke mer enn den gjør. Load-bearing:tests/test_step5_refine_loadbearing.pyblir rød når reason-injeksjonen detaches (utfallet flipper aldri + reason-verbatim-asserten faller); kontrollen beviser at løkka forblir bundet. -
Falsifiserings-historikken FORLATER generate-løkka som typet returverdi (Steg 5, del 2):
generate_via_llmreturnererGenerationResult(outcome, refinements)— ikke lenger bareValidatedProposal | Rejection. Før dette forbrukte løkka hverRejectioninternt (last) og DROPPET den, så Steg 5 var det ene av åtte steg uten observerbart utfall. Returverdi, ikke out-parameter/callback: en returnert verdi kan ikke bli stille tapt av en kaller som glemmer å sende en samler, og mypy tvinger hvert kallsted til å ta stilling.refinementsbærer KUN avvisninger som faktisk ble matet tilbake i et senere forsøks prompt — ved uttømt budsjett ER den siste avvisningenoutcome, den informerte ingenting, og å telle den med ville vært dobbeltføring (en «samle alt»-implementasjon består den positive testen og faller på kontrollen). Taket er URØRT:max_attempts+meter.tick_roundstår, oglastdriver fortsatt prompten alene (prompt-veksten er uendret).run.pyakkumulerer på tvers av_evaluate-kallene, så_evaluate_mandateer urørt;RunResult.refinementser defaultet (coverage-presedensen), og med mandat er den KONKATENERT på tvers av tiltak, ikke nøklet per tiltak (uttalt ærlighets-grense).scripted_factorytar nåstr | reply_selectorper rolle, så simuleringens proposer korrigerer seg innholds-nøklet uten en andre scriptet kropp. Load-bearing MÅLT (tests/test_step5_history_loadbearing.py), fire mutasjoner: detach returneringen · samle-alt · detach run-wiringen · reverter simuleringens proposer til konstant svar. -
Lang/async fil-løkke (Steg 7, målbilde §3/§7):
run_project(verdict_dir=...)er den lange tilbakemeldings-tidsskalaen — en ekspert/persona dropper en verdict-fil (vanlig JSON, RAW-laget per §10 R2) i en inbox-mappe ETTER en kjøring, og en separat, senere kjøringload_verdicts_from_dir→store.addmerger den inn FØR Steg-1-folden (ingen endring i folden), så dommen når neste hypotese. Rolledeling (§3, ufravikelig): systemet LESER mappa; eksperten/personaen SKRIVER den —run_projectpersisterer ALDRI sin egen fangede dom tilbake (det er outbox/Steg 8). Merge, aldri erstatt (run_portfolio-tråding intakt); tolerant last (manglende mappe / fremmede / halvskrevne filer hoppes over, ikke raises — RAW-lag, kontrastokf.load_ir_projections fail-fast);idleses verbatim, re-mintes aldri.write_verdicter den offentlige authoring-primitiven (persona/test + framtidig Steg 8), men wires IKKE inn irun_project. Load-bearing:tests/test_step7_async_loop_loadbearing.py— en dom droppet etter Run A MÅ nå Run B's prompt (Run B bruker FERSK store → overføringen er fil-løkka, ikke in-memory-carryover); tom-inbox-kontroll beviser kausalitet. Markør = realiseringsverdi som finnes ingen steder i bundelen (ikke frøets 0.82). -
Gated wiki-promotering (Steg 8, målbilde §3/§6/§7): når en ekspert/persona GODKJENNER et utfall, løfter
verdicts.promote_verdictdet fra RAW output-laget inn i kontekst-laget (OKF-bundelen) som entype: verdict-konseptfil, navigerbar av neste kjøringsseed_store_from_bundle. Gaten er fail-closed: en ikke-godkjent dom (decision ∉ {approved, approved_with_adjustment}) raiserPromotionRefusedog skriver/linker INGENTING — kun menneske/persona-godkjent kunnskap når wikien, aldri rå agent-output (selv-forurensning). Provenance-stemplet (hvem/eksperiment/når;timestamper påkrevd keyword, ingen wall-clock-default → deterministisk). OKF-skriveren bor iokf.pyog er ren stdlib (D7-portabel, MAF-fri — håndhevet avtest_okf_is_maf_free); navigasjon følger KUN index-cross-links, såpromote_verdictlinker filen iindex.mdvia en NØYTRAL label (ellers lekker signalet inn iindex_summary→bundle_contextutenom gaten). R4 = valgfri+gated:promote_verdicter en offentlig opt-in-primitiv, wires IKKE inn irun_project(speilerwrite_verdict— systemet leser; gaten/personaen promoterer). Ærlighets-grenser: promotert fil er MINIMAL (læringssignal kun somdescription/body-prosa, reproduserer ikke seedens strukturerterealization_rateo.l.); id = læringsnøkkel, så to godkjenninger om samme kandidat deler filnavn (last-write-wins, somwrite_verdict) — wikien vokser én kuratert fil per distinkt kandidat, ikke per dom-hendelse. Load-bearing-trio (tests/test_step8_promotion_loadbearing.py): gaten avviser ikke-godkjent dom (RØD uten gate); godkjent dom er navigerbar (RØD nårlink_in_indexdetaches); promotert signal holdes ute avbundle_context(RØD når en beskrivende index-label lekker det inn). Index-RMW er ikke-atomisk (enprosess-MVP). -
En dom nøkles på SIN kandidat, ikke bundelens ene IR-projeksjon (S3.2):
seed_store_from_bundleleser hvertype: verdict-fils EGNE strukturelle felt fra frontmatter (affected_codes/measure_type/claimed_saving_nok); mangler de, faller nøklingen tilbake tilbundle_candidate_features— så hver pre-S3.2-seed står uendret (fallbacken er BÆRENDE: fjernes den, brekker step1-suiten ved collection). Uten dette kollapset en bundle med dommer om flere kandidater dem på ÉN nøkkel, og en dom om kandidat B scoret perfekt strukturell match mot kandidat As query. ALLE TRE felt eller ingen: en delvis erklæring raiserVerdictFrontmatterErrori stedet for å slås sammen med bundle-kandidaten — sammenslåingen ville myntet en nøkkel som tilhører INGEN av kandidatene. Validering, ALDRI reparasjon (speilerwrite_concept_file); den tolerante hopp-over-regelen hører til RAW-innboks-laget.claimed_saving_nokparses medjson.loads— SAMME literal-regel IR-projeksjonen gikk gjennom — og skrives tilbake somstr()av råverdien, fordi_mint_idhasher den (30000≠30000.0; en normaliserende skriver ville splittet én kandidats signal på to id-er).promote_verdictskriver de tre feltene, så en promotert dom ikke utgir seg for målbundelens kandidat; nøkkelen er signal-fri, så Steg-8s no-leak-egenskap står. Semantikken er bestemt HER — commons' seeding-regel (method-spec§3 Steg 1) hadde ikke kommet; D7-speiling forblir ÅPEN. Load-bearing MÅLT (tests/test_step32_multicandidate_loadbearing.py+test_step8_promotion_loadbearing.py), fem mutasjoner alle røde: detach per-dom-nøklingen · detach feltenepromote_verdictskriver · gjør en delvis/uparsebar nøkkel tolerant · normaliser magnituden ved skriving · fjern fallbacken (kontroll). -
Den deterministiske gaten er FORANKRET i prosjektets faktiske kostbaseline (S4.0, F3/F8): før S4.0 resonnerte HVER stage kun om tall forslaget selv oppga, så en internt konsistent hallusinasjon klarerte hele gaten.
validate_proposal(..., baseline=...)avstemmer nå hvertaffected_itemmotCostBaseline(ir.py) i en stage 0 — FØR løseren (billigst, og den eneste som skiller en oppdiktet linje fra en ekte; å bruke en CBC-solve på tall som ikke tilhører prosjektet er arbeid på et krav som uansett ikke kan valideres). To uavhengige avvisninger: ukjent kostkode, og ekte kode medquantity/unit_costutenfortolerance(default 5 %, konfig) relativt til BASELINE-verdien. Validering, ALDRI reparasjon — forslaget avvises, aldri stilltiende korrigert til baselinen. Argumentet er VALGFRITT (None= pre-S4.0-oppførsel), men begge run-stier SETTER det: road-stien fraproject.cost_items(alltid — estimatet ER prosjektet), bundle-stien KUN når bundelen shippercost-baseline.json(load_optional_cost_baseline) — en pre-amendment-bundle er legitimt uforankret, og det er dét som holder commons-goldenene byte-identiske. Toleransen stopper ved fravær: en baseline som FINNES men er malformed raiser på BEGGE loaderne (å lese korrupt som «ingen baseline» ville gitt en uforankret gate i forkledning — samme resonnement somread_spend). F8: metode-cap-en slås opp iMETHOD_CAPS-registeret (måletype→brøk, injiserbart), ikke motenergy_efficiency-literalen — en andre metode er nå data, ikke en redigering av validatoren. Format- og toleranse-semantikken er bestemt LOKALT (commons-amendmentet D-A pkt. 2 kom aldri, som i S3.2); D7-speiling ÅPEN. Load-bearing MÅLT (tests/test_s40_cost_baseline_loadbearing.py), seks mutasjoner alle røde: detach avstemmings-stagen · detach magnitude-toleransen · detach road-wiringen · detach bundle-wiringen · ignorer det injiserte cap-registeret · gjør den valgfrie loaderen tolerant. En UFORANKRET kjøring sier det nå — og BEGGE utsagn stammer fra kjøringens ENE oppslag, aldri en andre lesing av bundelen (21.08):ProvenanceStamp.cost_baseline_anchoreder PÅKREVD uten default (begge defaults lyver:Truelar en glemsom konstruktør påstå en ankring som ikke skjedde,Falseunderrapporterer en ekte — en binær kjensgjerning om en falsifiserer har ingen ærlig default), ogDryRunReportbærer det samme fordi en dry-run stopper før noe stempel finnes.run.cost_baseline_notice(anchored)er ENESTE renderer, tar den alt oppløste BOOLEANEN, og returnererNonenår kjøringen ER forankret — omisjon, aldri en tom rad (announce-regelen). IKKE foldet inn imandate.announce, og det er en MÅLING: den fyrer kun med--mandate, så nettopp de bare bundle-dry-runsene defekten ble målt på ville fortsatt sagt ingenting — og den renderes FØRrun_project, altså før noen har oppløst baselinen. Utboksen trengte ingen endring (write_proposaldumper hele stempelet). Ankeringen forblir VALGFRI: dette er synlighet, ikke en ny nekt, og golden-transkriptet er byte-uendret fordi demoen kjører en base som HAR fila. Portefølje-armen er DEFENSIV og uttalt (ingen referanse-prosjekt setterbundle_dir, så den er unåbar i dag —budget_stop-presedensen; testen driver en craftedPortfolioResult). Load-bearing MÅLT (tests/test_baseline_visibility_loadbearing.py), seks mutasjoner alle røde mot HELE suiten + grønn kontroll 885/5: konstant stamp-wiring (3 røde) · konstant dry-run-wiring (1 rød) · detach dry-run-printen (1 rød) · renderer returnerer alltid linja (2 røde — inkl. den forankrede kontrollen, altså er omisjonen selv gatet) · detach full-run-printen (1 rød) · detach portefølje-printen (1 rød). Det PÅKREVDE feltet tvang fem eksisterende test-konstruktører til å ta stilling — det er egenskapen, ikke friksjonen. -
Globalt token-tak håndheves FØR kall, aldri bare etterpå (S3.4, F10):
PortfolioBudget+PortfolioMeterer ÉN ledger over hele porteføljepasset (og — seedet avread_spend— på tvers av pass), mens per-runBudget/TokenMeterer uendret. Taket har tre tenner, med hver sin jobb: (1) oppstartsnekt — en rest som ikke kan finansiere én kjøring raiserBudgetRefusedFØR noe lastes (et pass som har råd til null prosjekter er en caller-feil, ikke et resultat); (2) wave-assembly — et prosjekt som ikke kan finansieres blir ALDRI STARTET, og passet stopper strukturert (budget_stop+stopped_early, fullførte runs bevart). Aldri-startet er poenget: et ufinansiert prosjekt som bare avbrytes har allerede kostet kall. Fordi hele bølgen sjekkes mot SAMME før-bølge-rest, reserverer admission hver members krav — ellers overforplikter en bølge av k taket med inntil k kjøringer; (3) pre-call-guard iBudgetMiddleware— et kall resten ikke kan betale for NEKTES i stedet for å gjøres (post-charge-sjekken består: ekte usage kjennes først etterpå, så guarden stopper NESTE kall, aldri det som er i lufta).budget_stoper et EGET felt, aldristop_reason: et mål-stopp er suksess, dette er ressurs-utmattelse — å slå dem sammen ville gjort «vi stoppet» uleselig.record/checker SPLITTET iPortfolioMeterfordi tokens leverandøren allerede har fakturert må nå ledgeren selv når samme charge bryter run-taket. Spend-fila er vår EGEN regnskapstilstand:read_spendraiser på korrupt innhold (kontrast det tolerante RAW-inbox-laget — å lese korrupt som null ville gitt tilbake et allerede brukt budsjett), ogwrite_spendtar et PÅKREVDstamputen wall-clock-default (byte-determinisme, speilerpromote_verdict).portfolio_meterogmeter_factoryer gjensidig utelukkende — en factory-meter er ubundet, så begge sammen ville gitt et pass som SER capped ut uten å være det. Load-bearing MÅLT (tests/test_portfolio_budget_loadbearing.py+tests/test_budget.py), seks mutasjoner alle røde: detach wave-sjekken · detach pre-call-guarden · detach bølge-reservasjonen · sjekk run-taket før global kreditering · detach oppstartsnekten · gjørread_spendtolerant. -
BudgetExceededs tre felt beskriver ÉN og samme ledger (kø-(y)):kind/limit/observeder ett strukturert stopp-event, ogobservedvar det udefenderte tredje feltet — MÅLT: fire av fem raise-steder (TokenMeter.charge,tick_round, og BEGGE armene iexhausted()) kunne rapportere hvilken som helst verdi uten at 621 tester merket det; barePortfolioMeter.checkvar dekket. Fellen som skjulte det:spikes/_harness.py:41har sin EGEN kopi avBudgetExceeded/TokenMeter, såspikes/test_harness.pysobserved-assert dekker IKKE den shippede modulen — produksjonenstick_roundhadde null direkte test.exhausted()er det ENESTE stedet som VELGER ledger (S3.4-guarden), så en refusal som sierportfolio_tokensmens den rapporterer runets eget forbruk ville villedet enhver leser. Testene bygges medobserved != limit: ved nøyaktig-uttømt sammenfaller de to, og en test skrevet der kan ikke skille dem — den ville passert på en implementasjon som ekkoet taket tilbake som forbruket. Ingen defekt funnet i verdiene selv (kontrast (x)/(p)): trippelen var koherent alle fem steder, gapet var rent dekning. Load-bearing MÅLT (tests/test_budget.py), ni mutasjoner alle røde: femobserved-mutasjoner (inkl. kontrollen) + fire ekko-mutasjoner. -
Pengetall kvantiseres i ÉN orden, fra ÉN kilde (kø-(p)):
ledger.to_oreer rammeverkets ENE NOK→øre-konvertering (Decimal, ROUND_HALF_UP), og den brukes per pengebeløp — deretter summeres HELTALL.run.pyimporterer den; aldri en egen kopi (to kopier av en penge-konvertering drifter, og en driftet kopi setter de to sidene av en mål-sammenligning på hver sin skala — S4.0sREPLIES-presedens). Før dette summerterun.pys mål-baselineProject.total_cost-FLOATS og kvantiserte totalen ÉN gang, mensSavingsLedgersummerte per-kandidat-heltall — og de to ordenene møttes i nøyaktig ETT punkt:_goal_limit_if_reached, der et prosent-mål avgjør om et porteføljepass stopper tidlig. Målt divergens: tre linjer à60000.005NOK er18000003øre kvantisert først, men18000001summert først (float-drift til180000.01499999998) — nok til å vippe et mål. Kvantiser-først valgt fordi hverCostItemER et beløp (S4.0 gjorde per-linjequantity/unit_costtil validatorens grunnsannhet), og fordi heltallsaddisjon er assosiativ → rekkefølge-uavhengig under D-D-bølgemodellen, som float-folden ikke er. To kallsteder, ikke ett: portefølje- og per-prosjekt-baselinen er separate, og en fiks på bare den ene OVERLEVDE hele suiten (målt). Load-bearing MÅLT (tests/test_money_quantization_loadbearing.py), fem mutasjoner alle røde: detach portefølje-baselinen · detach per-prosjekt-baselinen · gjeninnfør en privat kopi irun.py· endre avrundingsmodus · larealizegå utenomto_ore. Ærlighets-grense:sum_claimed_saving_nok(run.py:_aggregate) er BEVISST urørt — et float-NOK-rapportfelt som aldri kvantiseres og aldri sammenlignes mot ledgeren, altså utenfor ordens-defekten. -
En BETALT test får sin EGEN opt-in, og instrumentet bevises GRATIS (Fase 1b, siste trinn):
tests/test_full_run_live.pykjører helerun_project-stien mot et ekte Foundry-deployment, og gates på fire ting — de to Foundry-variablene,PORTFOLIO_MODEL_MAP, og et TREDJE, distinktPORTFOLIO_LIVE_FULL_RUNlest på truthiness (4b-invarianten). Den tredje variabelen er load-bearing, ikke pynt:test_foundry_profile_live.py(klient-probe) ogtest_portfolio_live.py(fan-out) gatet på nøyaktig SAMME to variabler, så å gjenbruke det paret ville betydd at en operatør som eksporterer dem for den BILLIGE ett-ords-proben også fyrer den dyre fullkjøringen — altså at måleprotokollens stige («bevis så mye som mulig før det dyre trinnet, så en feil er attribuerbar») kollapser til ett trinn. MÅLT: med begge Foundry-variablene satt SKIPPET den dyre, og den billige var grønn. Regelen gjelder HVER betalt arm, ellers er den ingen regel:test_portfolio_live.pypasserer ingenclient_factoryog er derfor selv en betalt kjøring — den fyrte på to-variabel-paret fra et bartuv run pytest, og ble gatet på den TREDJE variabelen i samme slengen. Å la den stå ville gjort denne raden halvt usann den dagen den ble skrevet; en invariant som beskriver én av to armer er en påstand flaten gjør om seg selv uten dekning, som er nøyaktig Fase 3-klassen. Den billige klient-proben beholder to-variabel-gaten med vilje — den ER det billige trinnet.PORTFOLIO_MODEL_MAPer med av en annen grunn — attribusjon: uten den feiler kjøringen av en KONFIGURASJONS-årsak som ser ut som en modell-feil. Asserten bor i ÉN kopi (conftest.assert_full_run_contract, kø-(p)) og er smal med vilje: fraværet av{run_id}-parse-failures.json(økt 35-invarianten «filens tilstedeværelse er signalet») + atvalidator_decisionavgjorde. EnrejectedBESTÅR — påstanden som felles er at det strukturerte skjemaet ER akseptert av det levende endepunktet, ikke at modellen resonnerer godt; å krevevalidatedville vært en modell-dømmekraft-påstand ingen enkelt kjøring kan bære. Iron Law uten å betale to ganger: et betalt kall kan ikke kjøres rødt-så-grønt, så diskrimineringen bevises OFFLINE avtests/test_live_full_run_contract.py— to armer over samme helper (én parse-feil → kontrakten MÅ feile; alle parser → MÅ passere). Load-bearing MÅLT, to mutasjoner med hver sin distinkte signatur: detach artefakt-sjekken (T1 rød ALENE — kontrakten degraderer da tiltest_portfolio_live.pyslen(runs)==1-klasse) · raise ubetinget (T2 rød ALENE — den motsatte vakuiteten, en live-test som bare kan bli rød). Det betalte kallet er MÅLINGEN, aldri beviset på at måleinstrumentet virker. -
Kostnadsdisiplin: utvikle primært på lokal profil (gratis); Foundry/Azure (privat tenant finnes) kun til målrettet, minimal verifisering; billigste modeller + små syntetiske data + harde token-tak. Ingen tunge test-kjøringer.
-
Offline simulering = primært metode-bevis (kostnadsdrevet, erstatter §11.8): operatøren kjører IKKE MAF mot ekte modell (verken Azure/Foundry eller Ollama — API for begge repoene er for kostbart privat).
portfolio_optimiser.simulationdriverrun_projectmed en SKRIPTET syntetisk chat-klient (ScriptedChatClientpåOpenAIChatCompletionClient— IKKE bareBaseChatClient, ellers no-op-erBudgetMiddleware) over to kjøringer adskilt av en promotering, og viser at læringssløyfa lukkes: Run A's godkjente persona-dom (markør fraværende fra bundelen) →promote_verdict→ re-seed → Run B's hypotese-prompt bærer markøren (tom-wiki-kontroll på Run A beviser kausalitet). Ærlighet (§1, ufravikelig): beviser plumbing + deterministisk ryggrad + at dataflyten lukkes — IKKE at en levende LLM ville produsert forslaget/dommen (skriptede stand-ins). Den genuine modell-atferd-sammenligningen lever på Claude-SDK-siden (minimal API-kjøring). Skriptet klient = MAF-side stillas, IKKE delt (shared/forblir framework-nøytralt). Kjøresuv run python -m portfolio_optimiser.simulation. Load-bearing:tests/test_simulation_loadbearing.pyblir RØD når promoteringen detaches. -
Demoen KJØRER begge tidsskalaer, og de bæres av HVER SIN markør (P1/S1.a): Steg 7-linja sa «lang fil-løkke», men
simulate_learning_loopkalterun_projectUTENverdict_dir— dommen kom som funksjonsargument (verdict_input, den KORTE i-kjøring-fangsten). Nå skriver en ekspert en faktisk fil (write_verdict) i en innboks MELLOM kjøringene, og Run B fårverdict_dir=. Hvorfor en ANDRE markør og ikke persona-dommen gjennom innboksen: Steg 7 (innboks) og Steg 8 (promotering) er to ULIKE mekanismer som begge ender i Run B's hypotese-prompt — med én delt markør kunne hver av dem båret den alene, ogtest_simulation_loadbearing.pys promoterings-assert ville stått GRØNN med promoteringen detached, altså blitt vakuøs.simulate_learning_loopraiser derforValueErrornårinbox_marker == marker. Innboksen ligger VED SIDEN AV bundle-kopien, aldri inni: en dom-fil inne i bundelen når neste kjøring som navigerbar kontekst, som er en annen mekanisme i denne sin forkledning. Sentinel-id(aldri myntet) —_mint_idhasher kandidat- featurene, så en myntet id kolliderer med den promoterte dommens, ogVerdictStore.adder first-write-wins per id. Load-bearing MÅLT (tests/test_step7_demo_inbox_loadbearing.py), tre mutasjoner røde + grønn kontroll: detachverdict_dir=· la Run B lese en TOM mappe · sett innboks-markøren til en verdi som FINNES i bundelen. -
Det skriptede manuset nøkles på PROSJEKT-ID-en, og det er MÅLT:
scripted_proposer(candidates)bygger simuleringens proposer fra etScriptedCandidate-register, så et nytt prosjekt er en data-oppføring (demo-uke-plan §4 risiko 2) — ikke et andre håndskrevet manus. Hvorfor ikke kostkode/tiltaksnavn: to prompt-former når selectoren — debatt-prompten bærer hele bundle-konteksten, mens genererings-prompten (generate._build_messages) bærerProject: {id} - {name}pluss debatt-outputen som kontekst, altså selectorens EGET tidligere svar. Kostkode og tiltaksnavn står derfor i genererings-prompten kun fordi manuset selv la dem der; å nøkle på dem ville nøklet manuset på sin egen output. Prosjekt-ID-en er den ene identifikatoren BEGGE former bærer og som RAMMEVERKET stempler. Validering, ALDRI reparasjon: null treff — eller mer enn ett — raiserScriptedCandidateError; et default-svar ville besvart et uregistrert prosjekt med et ANNET prosjekts tall, som på skjermen er umulig å skille fra en riktig kjøring, og en tvetydig blob er et DATA-problem som skal falle på generalprøven, ikke avgjøres av register-rekkefølgen.flip_keyMÅ være fraværende fra bundelen (ellers bærer forsøk 1s prompt den allerede).simulate_learning_looptarproject_idved siden avbundle_dir. Load-bearing MÅLT (tests/test_content_keyed_script_loadbearing.py), fem mutasjoner alle røde + grønn kontroll: detach nøklingen · én global flip-key · fallback ved ukjent prosjekt · første-treff ved tvetydighet · detachproject_id-argumentet. Flip-key-testen ble skrevet om under målingen — første form asserterte på FØRSTE register-oppføring, der «den matchede kandidatens nøkkel» og «candidates[0]s nøkkel» sammenfaller; den kunne ikke skille de to implementasjonene. -
Demoen kjører FORANKRET, og baselinen DERIVERES fra manuset (P4 pkt. 0): før dette regnet validatoren i demoen kun på tall forslaget selv oppga — S4.0-forankringen aktiveres bare når kunnskapsbasen shipper
cost-baseline.json, og ingen bundle undershared/har den. Reserven kan aldri få fila DER (pull-only subtree + kriterium 8 krever goldenene byte-uendret), men det er en plasserings-begrensning:materialize_anchored_bundleKOPIERER bundelen og legger fila til utenforshared/, og kjørestien (run.py→load_optional_cost_baseline) er da NØYAKTIG samme søm en levert bundle ville brukt. Retningen på avledningen er bærende: reservens tall er syntetiske, så manus-registeret er eneste grunnsannhet —baseline_from_scripted_candidateavleder i KODE, aldri en andre håndskrevet kopi av de samme tallene (to kilder drifter, og drift er nøyaktig det 10 %-prøven modellerer). På GO-dagen snus retningen (plan P3 b: registeret skrives FRA levert fil). Begge skriptede svar må oppgi SAMME kostlinjer (ValueErrorellers): var de ulike, ville hypotese #1 blitt avvist av stage 0 istedenfor av P90 — samme REJECTED-linje på skjermen, annen mekanisme. Forankringen er usynlig i alt annet stdout (målt: eneste diff mot uforankret er KUNNSKAPSBASE-blokka), derfor printes den erklærte baselinen, og derfor erprovenanceet PÅKREVD argument til_baseline_lines— kallstedet som velger bundelen er det eneste som vet hvor tallene kom fra. Load-bearing MÅLT (tests/test_anchored_reserve_loadbearing.py), fem mutasjoner røde + grønn kontroll: detach main-wiringen · detach fil-skrivingen · la filnavnet drifte · detach to-svars-enigheten · returner et literal i stedet for det avledede. Målingen felte TESTEN først (samme klasse som 08-06): «ingen kostbaseline erklært» INNEHOLDER «kostbaseline erklært», ogENERGI-TOTAL-ELstår allerede i Steg 2-linja — begge assertene overlevde detach-mutasjonen. De to grenene deler nå ingen ordlyd. -
Demoens stderr: rund-taket dempes,
ExperimentalWarning-paret PINNES (P4 pkt. 2): målt 08-09 var stderr seks linjer.quiet_expected_round_cap_notice()dropper KUN «reached max_rounds=…; forcing completion» — en hendelse demoen selv provoserer (maker/checker kjører til taket) — via et filter på den EMITTERENDE loggeren (ROUND_CAP_LOGGER, lest ut av MAFs kilde). Logger-filtre gjelder kun loggeren posten ble logget GJENNOM; en forfars filtre konsulteres aldri. Filteret installeres imain(), ALDRI ved import — en bibliotek-modul skal ikke omkonfigurere loggingen til en konsument. De toExperimentalWarning-linjene dempes IKKE: de fyrer mensportfolio_optimiser/__init__.pyimportererrun→agent_framework, altså alltid FØRsimulationsin egen importblokk, under BEGGE kjøreformer — så å dempe dem ville krevd et warnings-filter inne i bibliotekpakken, dvs. at rammeverket bestemmer hva MAF får si til enhver konsument. En wrapper bak konsoll-kommandoen ble avvist av en andre grunn: da ville de to kjøreformene skrevet ULIK stderr, og en byte-fasit ville pinnet kommandoen i stedet for programmet. Dempingen er smal ved konstruksjon — nøklet på meldingen, ikke loggeren — nettopp så pkt. 3-pinnen fortsatt kan felles av en NY advarsel. Load-bearing MÅLT (tests/test_demo_stderr_quiet_loadbearing.py), fem mutasjoner røde + grønn kontroll: detachmain()-kallet (subprosess-testen er ENESTE som fanger det — de tre filter-testene installerer filteret selv) · la filteret droppe alt · installer ved import · pluss de to entry-point-mutasjonene. -
Demo-transkriptet er sjekket inn som fasit, og masken er SPANN-avgrenset (P4 pkt. 3): kriterium 6 er selv-identitet — to kjøringer av en REGREDERT demo er like enige som to kjøringer av en riktig, så fasiten må forlate prosessen.
tests/golden/demo-transcript.stdouter stdout ORDRETT (målt byte-identisk over kjøringer OG i fersk klon), og er derfor også demoens abortsti: feiler live-kjøringen, ER fila transkriptet.….stderrer normalisert på nøyaktig to MÅLTE miljø-spann —site-packages-prefikset og temp-katalogen bak(arbeidskopi: …), derpo-sim--prefikset holdes SYNLIG fordi det er en egenskap ved programmet (mkdtemp(prefix=…)), ikke ved miljøet; pinnet stderr er TO linjer (var fire til og med core 1.9.0 — se F15-raden). Masken må ikke kunne vokse: P4 pkt. 2 betalte for at en NY advarsel fortsatt når stderr, og en normalisering som maskerte hele linjer ville opphevet det i ett trekk — derfor ertest_normalisation_does_not_mask_a_new_warningkontrollen som forbyr det (MÅLT: en droppende normaliserer med fasiten regenerert under seg holder BEGGE likhets-testene grønne og felles kun av kontrollen).PYTHONIOENCODINGpinnes, ellers måler sammenligningen operatørens locale i stedet for programmet. Regenerering er en beslutning, aldri rydding — fasiten kan ikke bevise sin egen kjøring, den pinner outputen P3-kriteriene ble målt mot. Hashen radene under fører ershasum -a 1av INNHOLDET, aldri git-blob-id-en (S7a-3 pkt. 4). De to er ulike av konstruksjon — git hasher overblob <len>\0+ innhold — såea8c534773acdbe41ae68f2c55724d69aaf8be4fer sha1 av fila, mensgit hash-objectpå samme fil gir55bdea3ad20616480d81b9e7544604b248a541c9(stderr-goldenen:ede3e2f…innhold /12893ec…blob). MÅLT etter at en økt søkte uttømmende etterea8c534…som git-objekt, ikke fant det, og leste fraværet som at ni invariant-rader siterte en fantomverdi — Verifiseringsloven ansikt 4 mot ens eget instrument: et negativt resultat fra feil spørring er ikke et faktum. Radene var RIKTIGE hele veien; det som manglet var etiketten, og den står nå i hver av dem. -
Frø-setningen AVLEDES fra kjøringen (P4 pkt. 4): demoen sier høyt hvor Kjøring B's tidligere dommer kommer fra, og splitten (
_verdict_origin_line) regnes ut — linja rett over printer allerede antallet, så en håndskrevet «én av tre» ville vært den andre kopien som drifter (samme regel som pkt. 0-baselinen), og ville blitt sagt uendret etter at en framtidig bundle shipper en ANDRE frøsatt dom. Klassifisereren er de to markørene demoen alt sporer; den hviler på at den frøsatte dommen bærer INGEN av dem, som MÅLES på levert bundle. Planens forhåndsskrevne ordlyd var FEIL mot levert innhold («én av de TO») — målt henter Kjøring B TRE: én fulgte med kunnskapsbasen, to er demoens egne (én per tidsskala). Load-bearing MÅLT (tests/test_p4_honesty_sentences_loadbearing.py+ golden-transkriptet), fem mutasjoner alle røde- grønn kontroll: ett byte i en stdout-linje · detach dempingen · over-normaliser stderr · literal splitt (fanget av INGENTING i 800 tester bortsett fra skille-testen) · detach frø-setningens print.
-
Delt ekspert-persona som Agent Skill (§8, framework-nøytral): ekspert-reviewer-personaen bor i
shared/skills/expert-reviewer/(SKILL.md+references/example-verdict.json) og er den ENE delte artefakten begge stacker instansierer reviewer-en fra.shared/forblir REN DATA — MAF-siden leser den viaportfolio_optimiser.persona.load_persona_example(call-time, fail-fast), Claude-SDK- søskenet med sin egen loader mot samme JSON. Dette AV-STUBBER simuleringen: persona-dommen (decision- rationale + sporet markør) hentes nå fra artefaktet ved call-time, ikke en inline-literal — så
personaen er genuint konsumert og kan ikke råtne stille. Decision er binær (
approved/rejected—FeedbackContractrun-stien tar;approved_with_adjustmentavvises der, bor kun i bundle-seedens frontmatter + promoterings-gaten); realiseringskorreksjonen lever i rationale-prosaen, ikke et tredje enum. SKILL.md-prosaen nevner ALDRI en konkret framework (maf-guarden er import-formet). Load-bearing- trio (tests/test_persona_skill_loadbearing.py): struktur+framework-nøytralitet (RØD på framework- import), eksempelet er gyldig pipeline-input inkl.FeedbackContract(RØD på skjema-/kontrakt-drift, på en throwaway-kopi — aldri den git-tracked fixturen), og sim-ens markør følger artefakt-fila (RØD i det øyeblikk personaen re-inlines).
- rationale + sporet markør) hentes nå fra artefaktet ved call-time, ikke en inline-literal — så
personaen er genuint konsumert og kan ikke råtne stille. Decision er binær (
-
Den råe svarteksten fanges i en KALLER-EID SINK, ikke i en returverdi (Fase 1b, funn 1):
generate._fetch_parsedkastet hvert uparsebart modellsvar iexcept: continue, så prosjektets første levende kjøring brant tolv runder på formatfeil og etterlot null tegn av det modellen faktisk sa — enhver videre betalt kjøring ville vært gjetning. HVOR teksten overflates er avgjort av en MÅLING, ikke av symmetri med Steg 5:meter.tick_round()raiserBudgetExceededINNE i_fetch_parsed, og uten mandat fanger ingen den (run.pys eneexcept BudgetExceededer mandat-armen) — så på nøyaktig den stien fangsten finnes for, RETURNERERgenerate_via_llmingenting. Et felt påGenerationResult(Steg 5-formen) er derfor blindt for den, og et outbox-artefakt skrevet ETTER kjøringen likeså. Sinken speiler i stedetmeter: en kaller-eid akkumulator løkka muterer, hvis innhold kalleren holder uansett hvordan løkka endte. Steg 5s «returverdi, ikke out-parameter» gjelder en verdi som NÅR kalleren; her gjør den ikke det, og å kopiere regelen blindt ville gjenoppbygd defekten ett lag opp. Artefaktet{run_id}-parse-failures.jsonskrives fra enfinally, ikkeexcept BudgetExceeded— enhver exception ut av genereringen ødelegger samme bevis, og en liste over exception-typer er en liste som blir foreldet. Teksten er VERBATIM (en forkortelse gjør beviset om til en parafrase), og fila skrives KUN når noe faktisk feilet, så dens tilstedeværelse ER signalet. Byte-determinisme påstås IKKE for dette ene artefaktet — innholdet er en levende modells prosa. Load-bearing MÅLT (tests/test_parse_failure_capture_loadbearing.py), seks mutasjoner alle røde mot HELE suiten + grønn kontroll 859/4: detach fangsten (3 røde) · flytt skrivingen ut avfinally(1 rød, KUN budsjett-testen) · detach run-wiringen (2 røde, generate-testen grønn) · skriv artefaktet alltid (kontrollen + den eksisterendea5-inerthetstesten) · trunker teksten til 40 tegn (3 røde) · trunker til 100 tegn slik at sentinelen OVERLEVER (1 rød — verbatim-asserten alene, den skarpe diskriminatoren). Ærlighets-grense:_charge_usagekan raise FØR parse, og et svar tapt der er ikke en parse-feil og fanges ikke. -
Proposeren får en GRAMMATIKK, og skjemaet er DERIVERT + fail-closed (Fase 1b, funn 1b):
generate_via_llmsenderoptions={"response_format": proposal_response_format()}på hvert genererings-kall. Formen er MÅLT, ikke valgt:ChatOptions.response_formattartype[BaseModel] | Mapping, og BEGGE profiler ærer den — LOCAL (OpenAIChatCompletionClient) sender en Mapping ordrett til Chat Completions, AZURE (FoundryChatClient→RawFoundryChatClient→RawOpenAIChatClient) konverterer SAMME envelope til Responses-APIetstext.format. Klassen er AVVIST på bevis: gitt en klasse konverterer klienten medtype_to_response_format_param, som (målt) emittererminimum/exclusiveMinimum/minItems/prefixItemsog etassumptions-node hvisadditionalPropertieser et SKJEMA — fire ting Azures publiserte subset utelukker (Learn: «Unsupported type-specific keywords» +additionalProperties: falsei hvert objekt). Vår egen mapping er eneste måte å styre hva som når tråden. Å stripe beskrankningene koster ingenting: skjemaets jobb er FORM, validatorens jobb er VERDIER —minItems/gt=0gjenreises av pydantic i_parse_irog avvalidate_proposal. Skjemaet DERIVERES fraSavingsProposal(strict_json_schema), aldri håndskrevet: en andre kopi av en form som alt bor iir.pydrifter stille, og modellen ville fortsatt blitt bestilt for den gamle.assumptionsKAN IKKE bare droppes, og det er en MÅLING: feltet er det ene uttrykksløse (fri-form map av 2-tupler), menvalidator._monte_carlofaller tilbake påitem.unit_costfor hver kode uten bånd — uten bånd i det hele tatt er alle 512 samples IDENTISKE og P10 == P50 == P90. Den stokastiske falsifisereren ville gått inert mens den fortsatt rapporterte persentiler: repoets kardinalklasse (en gate som bare kan bli grønn). Derfor bærer WIRE-en et array av navngitte entries og_parse_irfolder det tilbake til IR-ens map — additivt, aldri erstatning (map-formen parser uendret; alle scriptede svar i suiten og golden-transkriptet bruker den). Sanitiseren er fail-closed (StructuredOutputUnsupported) påprefixItems/oneOf/allOf/fri-form map uten deklarert override — validering, ALDRI reparasjon (speilerwrite_concept_file). Prompt-linja «Respond with ONLY a JSON object» + parse-retry + funn-1-fangsten står URØRT: en leverandør som ignorererresponse_formatmå fortsatt få beskjed, og backstoppen er poenget. Load-bearing MÅLT (tests/test_structured_output_loadbearing.py), seks mutasjoner alle røde + grønn kontroll 864/4: detach wiringen (1 rød) · detach sanitiseren (3 røde) · droppassumptionsfra skjemaet (1 rød) · fail-closed → stille reparasjon (1 rød) · detach normaliseringen (3 røde) · erstatning i stedet for tillegg (2 røde — T5 PLUSS golden-transkriptet, et uavhengig vitne). T3 ble skrevet VAKUØS først (repoets 08-09-klasse, sjette gang): den påsto å bli rød nårassumptionsforsvant fra skjemaet, men den scriptede klienten ignorerer skjemaet — påstanden ble bevist usann av M3 og testen fikk en DIREKTE assert på skjemaet. ÆRLIGHETS-GRENSE, UTTALT: ingen betalt kjøring er gjort, så at det emitterte skjemaet ER akseptert av det levende endepunktet er IKKE verifisert — testen beviser konformitet med det DOKUMENTERTE subsettet, ikke aksept. Ollamas oppførsel påresponse_formater likeledes uverifisert. -
Overleverings-pakka ER
git archive HEAD, aldri en kuratert kopi (Fase 5):scripts/make-handover-package.shbygger én zip en ekstern organisasjon deployer uten å klone repoet. Tracked files only er hele eksponerings-kontrollen —STATE.md,*.local.mdog.enver gitignorert, så de KAN ikke komme inn; et filter vedlikeholdt i skriptet ville vært den andre kopien av den regelen, og den andre kopien er den som drifter (kø-(p)). Mottakeren får altså HEAD selv. Versjonen LESES frapyproject.toml— et hardkodet tall her ville råtnet ved neste bump nøyaktig som README-ens wheel-filnavn gjorde (Fase 3).DEPLOY.mdligger i treet og blir dermed med i arkivet av seg selv; den bærer mottakerens tre første spørsmål — hvem gjør hva (plattform-operatør / bestiller / fagperson), prosessen ende-til-ende, og hvorfor det ikke finnes et chat-grensesnitt (flaten erPOST /invocations, ogas_agent()er bevisst vraket fordi validator, baseline-forankring, checker-gate og ledger ligger UTENFOR grafen — et chat-lag ville rutet forespørsler rundt nøyaktig det som gjør svaret etterprøvbart). Den navngir også det 4e målte deploy-kravet som ingen rad hadde skrevet ned: pakketmodel_map.jsonbærerREPLACE-WITH-*, så utenPORTFOLIO_MODEL_MAPstarter tjenesten, svarer på/readinessog feiler HVER invocation. Gaten ertests/test_handover_package_loadbearing.py, og DEPLOY.md-asserten er LINJEFORANKRET:PORTFOLIO_FOUNDRY_PROJECT_ENDPOINTINNEHOLDERFOUNDRY_PROJECT_ENDPOINT, så en delstreng-assert på det injiserte navnet ville vært oppfylt av vårt eget (repoets 08-09-klasse, femte gang). -
Overleveringen er KUN kjørbar Python, og fraværet er FJERNING — ikke filtrering (14.08, operatørdirektiv etter ekstern test):
Dockerfileogazure.yamler slettet fra TREET. Sømmen er valgt av den eksisterende invarianten, ikke av smak: pakka ERgit archive HEAD, så å ekskludere filene fra arkivet ville krevd en kurerings-mekanisme (skript-filter ellerexport-ignore) — den andre kopien av «hva mottakeren får», fri til å drifte fra HEAD, altså nøyaktig kø-(p)-regelen raden over finnes for. Å beholde dem som «opt-in» ville ikke oppfylt direktivet i det hele tatt. Fjerning holder arkivet ukurert OG gjør fraværet til en egenskap ved HEAD, som er det eneste en gate kan måle. De to gatene som pinnet flaten er håndtert BEVISST, aldri stille svekket: 4e-rå-tekst-gaten (--platform linux/amd64+ ÉN kopi av startkommandoen) er SLETTET med et notat der den sto — en gate som pinner en fjernet flate kan bare bli grønn — og handover-gatens_REQUIRED_MEMBERSer ikke bare fratatt de to navnene, men erstattet av en POSITIV fraværs-assert; å kun slutte å KREVE dem ville gitt en gate som ikke kan skille «fjernet» fra «shippes fortsatt». Matchingen skjer på arkiv-MEDLEMSNAVN, ikke på prosa (dokumentene må kunne forklare at ingen image shippes — repoets 08-09-klasse, sjette gang), og dokument-gaten forbyr kommando-FRAGMENTER (docker build,azd deploy), ikke ordet. Startkommandoen har nå ÉN kopi igjen — DEPLOY.md-enspython main.py— og den navngir inngangen subprosess-testen faktisk kjører. Ærlighets-grense, uttalt: azd/hosted-agent-stien finnes ikke lenger i pakka; hvordan prosessen driftes er mottakerens valg.git archive HEADleser HEAD, ikke arbeidstreet, så gaten er ekte men forsinket med én commit (funn 35). Load-bearing MÅLT (tests/test_handover_package_loadbearing.py). -
Sporing er OPT-IN, og «av» betyr at MAF ALDRI kalles (U14, økt 55):
PORTFOLIO_OTELleses på truthiness (4b-regelen) og er ENESTE bryter; uten den kallesconfigure_otel_providersikke i det hele tatt — spans LAGES fortsatt (ENABLE_INSTRUMENTATIONdefaulterTrue,observability.py:697) og kastes, så ingenting KAN forlate prosessen. Et kall med tom exporter-liste ville derimot installert providere og lest hverOTEL_EXPORTER_OTLP_*i det omkringliggende miljøet — «av» må være fravær av kall, ikke kall uten innhold. To regler er MÅLT, ikke valgt (observability.py:849bygger exporter-lista i fast rekkefølge: (1) env-avledede OTLP-exportere UBETINGET, (2) de innsendte, (3)ConsoleSpanExporter()— default-sink stdout — nårenable_console_exporterser sann fra argument ELLERENABLE_CONSOLE_EXPORTERS): (a)enable_console_exporters=Falsesendes EKSPLISITT i BEGGE moduser, ellers gir en operatør med den variabelen eksportert et span-dump på stdout — nøyaktig det S6 målte som ødeleggende for golden-transkriptet; (b)consoleNEKTER når en OTLP-endepunkt-variabel finnes, fordi steg (1) ville lagt til en nettverks-exporter ordet «console» lover ikke er der. Validering, ALDRI reparasjon — vi fjerner ikke operatørens miljøvariabel bak ryggen på dem (write_concept_file-regelen); nekten NAVNGIR variabelen.otlputen deklarert endepunkt nektes også: providere med ingenting å eksportere til er en kjøring som SER sporet ut og ikke er det. En ukjent verdi nektes ved navn, aldri stille fallback til av.tracing_noticeer ENESTE renderer, tar den alt oppløsteTracingSetupog returnererNonenår sporing er av — omisjon, aldri tom rad (announce-regelen), og her bærende utover stil: demoens pinnede stderr er TO linjer (FIRE før F15). Tre kallsteder, ikke ett (run.main,simulation.main,hosting.main): demoen er et skriptet bevis, ikke produktet, og en søm bare demoen når ville latt de to inngangene en virksomhet faktisk kjører være usporbare. OTLP-exporter-PAKKENE er BEVISST ikke deklarert (egress + grpc/protobuf-vekt i et publisert wheel; MAF raiser selv enImportErrorsom navngir pakka) — uttalt ærlighets-grense.PLAN_CREATED/REPLANNED/PROGRESS_LEDGER_UPDATED-eventene planen navngir er IKKE bygget: de hører til utforskningssløyfa (U4) som ikke finnes ennå, og en emitter skrevet før kallstedet er en form gjettet i stedet for målt. Load-bearing MÅLT (tests/test_tracing_loadbearing.py), ni mutasjoner alle røde mot HELE suiten + grønn kontroll 943/5: exporteren tar sin stdout-default (4 røde) ·enable_console_exportersoverlatt til miljøet (3 røde — inkludert den ATFERDSMESSIGE, som kjører demoen med variabelen eksportert; uten den ville raden bare vært en keyword-assert) · detach console-nekten (4 røde) · detach otlp-endepunkt-nekten (1 rød) · ukjent modus faller stille til av (2 røde) · «av» kaller MAF likevel + renderer returnerer alltid en linje (9 røde, hvorav TRE i tester som fantes fra før —test_golden_transcriptsin da fire-linjers (nå to-linjers) stderr ogtest_portfolio_cli_offlines stille-pass — altså er omisjonen gatet av uavhengige vitner) · detach demo-wiringen + detach CLI-wiringen (5 røde) · detach hosting-wiringen (1 rød, KUN subprosess-testen — P4-presedensen). -
Utforskningssløyfa er en MANDAT-FORMER, og de tre garantinivåene er strukturelle (U4+U13 synkron, økt 56):
explore.pylegger en Magentic-manager OVER den normative sløyfa —prompt + kunnskapsbaser → Mandate → run_project(mandate=…)UENDRET, Steg 3s maker-checker urørt (commons-eid og normativ). Manageren velger VEI; det som forlater friheten ermandate.Mandate, aldri et forslag. Nivå 1 =quick_validate-verktøyet (SAMMEvalidate_proposal, SAMME baseline, men rådgivende — når ALDRI provenance); nivå 2 = pipelinen som stempler; nivå 3 = skriverettigheter, som kun pipelinen har.explore()skriver INGENTING. Mandatet bygges fra hypotesiserens MERKEDE turer (HYPOTHESIS: {"label","rationale"}), aldri fra sluttsvaret — sluttsvaret er RÅTT per design, og en parser på det ville gjort det til et forslag. Markøren er dét som gjør fail-closed mulig: en umerket tur er ikke en påstand (ingen stillhet å lukke), mens en MERKET-men-uleselig linje raiser (write_concept_file-regelen). Frø-approaches bevares ALLTID og FØRST — også når sløyfa fant ingenting og også ved stopp (§ C.6 dør 1 er en bevaringsregel, ikke en belønning for å bli ferdig). Tre kanaler, aldri én: tokens OG runder raiserBudgetExceeded(rundene somkind="exploration_rounds", oversatt av VÅRT lag fordi orkestreringen MÅLT ikke raiser ved sitt eget rundetak — den returnerer en kanonisk assistent-melding som ved transporten er uskillbar fra suksess), mens alt semantisk er en VERDI istop(S3.4-splitten: utmattelse og utfall er ikke samme sak). Diskriminatoren mellom «nådde taket» og «ble kappet av taket» er SISTE ledgersis_request_satisfied— samme felt orkestratoren selv forgrener på (:1106) — aldri termineringsmeldingen, som er en inline f-string (:1253) uten konstant å pinne mot og som en modells eget sluttsvar kan inneholde.speaker_knownsjekkes FØRST og slår alt annet: ennext_speakeruten treff gir stille sluttsvar med NULL deltakerarbeid (:1128-1131), altså et plausibelt svar ingen jobbet for (E2-klassen) — sløyfas egne funn holdes da tilbake, frøene ikke. Kontrakten nekter tre ting ved konstruksjon: hvert av seks felt er PÅKREVD uten default (MAF defaultermax_round_count/max_reset_counttil ubegrenset, så et utelatt felt faller ikke tilbake til noe forsiktig, men til détmethod-spec§8 forbyr);max_reset_count=0nektes — MÅLT, ikke resonnert:reset_count >= max_reset_countmot en teller som starter på 0 gjør at kjøringen terminerer FØR første runde med kunfacts+plan, null ledger-events og «maximum reset count», altså en utforskning som utforsket ingenting, forkledd som en stall som aldri skjedde (max_stall_count=0er derimot LOVLIG — strengt>gjør 0 til «reset ved første stallede runde»); ogmax_plan_revisions>0medenable_plan_review=Falsenektes (en cap på en hendelse som ikke kan skje).max_plan_revisionsfinnes fordi A3 MÅLTE at enrevisekoster 2 manager-kall, null ledger-kall og null runder og så spør PÅ NYTT — under rundetaket alene er en alltid-reviderende ekspert ubundet forbruk under vakter som alle ser tilfredse ut. Ved cap: typet stopp, ALDRI en påtvunget approve (repair av et menneskes beslutning er den verste sorten). U14s tre utsatte events er landet (plan_created/replanned/progress_ledger_updatedsom span-events på ÉNexploration-span) — emisjon er UBETINGET og «av» betyr at OTel kaster dem, samme form MAFs egen instrumentering alt har; en flagget emitter ville vært en andre oppløsning av regelentracing.pyeier. Uttalt ærlighets-grense: eventene registreres når event-strømmen foldes, så REKKEFØLGEN er tro og tidsstemplene er ikke øyeblikkene manageren handlet. Load-bearing MÅLT (tests/test_explore_loadbearing.py, 32 tester), tolv mutasjoner alle røde mot HELE suiten + grønn kontroll 975/5: detach rundetak-oversettelsen (1 rød) · test rundetaket FØR tilfredsstillelse (1 rød — den motsatte feilen, som gjør en fullført utforskning til en budsjettfeil) · detach ukjent-taler-sjekken (1) ·BudgetMiddlewareav manageren, deltakerne beholder den (1) · detach revisjons-capen (1) · dropp frø-bevaringen (3) · la en ukjent-taler-kjøring levere funnene videre (1) · detach alle tre span-events (1) · tillatmax_reset_count=0(1) · gjør en merket-men- uleselig hypotese tolerant (1) · laread_bundleskrive i basen den leser (1) · send spans til OTels default-sink (2). TO av dem FALSIFISERTE testen først, og begge er repoets vakuøs-gate-klasse: (i) skrivefrihets-testen drev kunexplore(), men enScriptedChatClientreturnerer TEKST og emitterer aldri et verktøykall — så ingen scriptet kjøring når en verktøykropp, og hele lesesømmen (eneste sted en skriving realistisk kan komme fra) lå utenfor gaten; testen kaller nå hvert verktøy DIREKTE. (ii) stdout-testen bruktecapsys, menConsoleSpanExportersout-default bindes nåropentelemetry.sdk.trace.exportFØRST importeres — under pytest er det stdout ved COLLECTION, somcapsysaldri ser; spans lå faktisk på stdout mens asserten var grønn. Dét er ikke en test-quirk å omgå, det er nøyaktig faktumet U14 finnes for, og arven er P4-presedensen: subprosessen er målingen. Begge armene kjøres nå i et barn (av: null trace-data noe sted;PORTFOLIO_OTEL=console: spanet +progress_ledger_updatedpå stderr og stdout tomt), medEXPLORATION-OKpå stderr som kontroll — uten den ville «stdout var tomt» vært like sant om et barn som krasjet ved import. Ærlighets-grenser, uttalt: multi-base-dispatch (Approach.bundle_id, § C.7) venter tilrun_projecttar mer enn énbundle_dir— å shippe feltet før konsumenten er en form gjettet i stedet for målt;quick_validate-dommene hypotesiseren så bor ikke iExplorationResult, de er nivå 1 og hører hjemme i{run_id}-exploration.jsonsom CLI-wiringen skriver; utforskningsrollene løses viaresolve_modelsdefault-fallback til en operatør mapper dem eksplisitt; at en LEVENDE modell kaller verktøyene er ikke bevist offline (samme klasse som structured-output-grensen). -
Utforskningens KALLSTEDER: sporet er kaller-eid, og whitelisten ble en TREDELING (økt 57):
--explore "<prompt>" --explore-config FILEirun.py,explore_prompt+explore_contractpå den hostede flaten, ogsimulate_explorationsom et TREDJE sim-scenario — alle opt-in, alle over den uendrede sløyfa.ExplorationTraceer en KALLER-EID akkumulator (funn-1-sinken, ett lag opp), og formen er tvunget av en måling, ikke valgt:explore()raiserBudgetExceededpå rundetaket og tokentaket fyrer fra middleware midt i løpet — på BEGGE stier konstrueres aldri etExplorationResult, mens § C.2 krever at artefaktet er lesbart «uansett hvilken vakt som fyrte». Steg-5-regelen («returverdi, ALDRI en out-parameter») styrer en verdi som NÅR kalleren; her gjør den ikke det, og å kopiere regelen blindt ville gjenoppbygd defekten den ble skrevet mot.ExplorationResult.ledger_log/.plan_reviewsBYGGES FRA akkumulatoren (tuple(trace.ledger)), aldri ved siden av — to beholdere om ett faktum er kø-(p).{run_id}-exploration.jsonskrives fra enfinally(write_parse_failures-presedensen) viaexplore.trace_payload→outboxs plain-mapping-skriver (RAW-laget forblir MAF-fritt);completeder et EGET påkrevd felt, fordi enstop: nullsom betyr BÅDE «avsluttet normalt» og «vi fikk aldri vite» er stillhetencost_baseline_anchoredble påkrevd for å lukke. Åtte CLI-nekter, alle ved navn, hvorav to bærer en beslutning: (i)--explore+--mandateer TO KILDER TIL ETT MANDAT og NEKTES, aldri slås sammen —explore()tar objective fra prompten og hardkoderallow_own_proposals=True, så komposisjon ville stille overskrevet tre felt operatøren skrev selv; nekten NAVNGIR biblioteksdøra (seed_approaches), fordi § C.6 dør 1 er et ekte behov flaten ikke betjener. (ii)enable_plan_review=truenektes på BEGGE flater FØRexplore()kalles, og det er en TYPE-måling:ExplorationErrorer enRuntimeErrorog ligger utenformain()s(ValueError, FileNotFoundError, ValidationError)-tuppel og utenfor hostings 400-arm, så å overlate den til sløyfa ville gitt traceback på CLI-en og 500 — krasj-kanalen — på HTTP. (TracingConfigErrorer derimot enValueError; 400-armen dekket den alt.) Etter nektene er hver konfig-formetExplorationErrorUNÅBAR fra begge inngangene ved konstruksjon; det som fortsatt kan slippe ut (uleselig merket hypotese, uttømt budsjett) er RUN-en som feiler, ikke kalleren som tar feil. Hostings whitelist er nå_REQUIRED/_OPTIONAL/_CONSUMED: utforskningsfeltene er IKKErun_project-parametre, så Fase 4e-beviset fikk en NEGATIV halvdel — hvert videresendt felt MÅ finnes iinspect.signature(run_project), hvert konsumert felt MÅ ikke; uten den ville et felt som glir fra konsumert til videresendt vært nøyaktig driften 4e finnes for. Demo-scenarioet er nåbart ved NAVN og bare der (main()kaller det ikke, og at golden-transkriptet er byte-uendret etter at det ble lagt til ER målingen av det), med en vakuitets-vakt: en label kunnskapsbasen ALLEREDE oppgir refuseres, fordi den ville nådd hypotese-prompten som ordinær kontekst enten utforskningen kjørte eller ei —simulate_learning_loops to-markør-vakt i demo-form. Manager- manuset nøkles på PROMPT-STADIET, ikke prosjekt-ID-en, og det er ikke et unntak frascripted_proposer-regelen: manageren får FEM ulike spørsmål og prosjekt-ID-en er konstant over alle fem.--outbox-diruten--run-idNEKTES i utforskningsblokka, og det er en HOIST — ikke en andre kopi av regelen:run_projecteier outbox-kontrakten og nekter på sin FØRSTE setning, tidlig nok for enhver sti som fantes før U4, men utforskningen kjører FORAN det kallet — uten hoisten brukes hele utforskningsbudsjettet på modellkall før nekten, og artefakt-skrivingen hoppes over, så ikke engang regnskapet over hva som ble brukt overlever. Funnet i review FØR commit; testen asserterer at INGEN modellkall skjedde, ikke bare at rc er 1 — ved exit-koden ser en nekt etter forbruket identisk ut. Scenarioet har BEVISST intetlabel_in_bundle-felt: vakten raiser før et resultat finnes, så feltet kunne kun værtFalse, og en assert på det ville vært grønn mot enhver implementasjon — vakten ER kontrollen, og en alltid-sann gjentakelse av den ville bare gjort den ekte lettere å avfeie. Load-bearing MÅLT (tests/test_explore_callsites_loadbearing.py, 24 tester), sytten mutasjoner alle røde mot HELE suiten, hver mot kontrollen som gjaldt da (990/5 for CLI-en + sporet, 996/5 for hosting, 998/5 for sim-scenarioet, 999/5 for de to siste): detach sink-appenden (1) · andre liste for rundene (4) · detach--mandate-nekten (1) · detach--explore-config-nekten (1) · skriv artefaktet kun ved fullført kjøring (1) · detach CLI-ensmandate=(1) · slippenable_plan_reviewgjennom, CLI (1) · detach--bundle-dir-kravet, CLI (1) · detach--live-dry-run-nekten (1) · fjern--explorefra portefølje-partisjonen (1) · videresend de konsumerte feltene (2) · detach hostingsmandate=(1) · detachenable_plan_review-nekten, hosting (1) · detachbundle_dir-kravet, hosting (1) · detach sim-scenarioetsmandate=(1) · detach vakuitets-vakten (1) · detach outbox/run-id-hoisten (1). ÉN MUTASJON FALSIFISERTE TESTEN FØRST (repoets vakuøs-gate-klasse, syvende gang): portefølje-testen asserterte kun at meldingen nevnte--explore, og sto GRØNN uten partisjonen — kjøringen falt da gjennom til «--explorerequires--bundle-dir», som nevner--exploreogså. To nekter som deler en delstreng er «assert aldri på ordlyd to grener deler», fanget av sin egen mutasjon; testen navngir nå--portfolio. Ærlighets-grenser, uttalt: multi-base (Approach.bundle_id, § C.7) er FORTSATT ikke bygget —run_projecttar énbundle_dir; utforskningens egne modellkall er UANNONSERTE (annonseringens kontrakt er at en KOMMISJON erklæres før arbeidet den bestiller, og førexplore()returnerer finnes ingen —exploration_noticedekker gapet i det sløyfa er ferdig);BudgetExceededut av--exploretracebacker som den gjør for debatten i dag; og den HOSTEDE flaten gir ingen innsyn i hva som formet mandatet — det er ingen outbox der og intet utforskningsfelt i_response_payload, så ledgeren og de rådgivende dommene når kun CLI-ens artefakt. En bevisst scope-grense, men uttalt, fordi flatens hele argument er at svaret er etterprøvbart. -
Multi-base er en PARTISJON, aldri en videre
run_project-signatur (U4+U13 del 3, § C.7, økt 58): planens § C.7 og økt 56s egen ærlighets-grense leste som om leveransen var «run_projecttar mer enn énbundle_dir». Den kan ikke det, og nekten er STRUKTURELL: på bundle-stien avlederrun_projectFIRE enkeltverdier fra DEN basen — prosjektet (_project_from_bundle, som fail-faster når basens egenvalidator-input.jsonikke navngir det forespurte prosjektet), validatorens stage-0-baseline (S4.0s hele poeng er at gaten er forankret i DETTE prosjektets kostlinjer), agentenes lesekontekst og ExpeL-nøkkelen — og returnerer ETT stempletRunResult. En andre katalog på den signaturen ville tvunget et stille velg-en for alle fire, som er den gjettede-form-klassen repoet nekter. Planens egen setning sier det samme lest nært: «pipelinen kjøres per bundle som i dag (run_portfolio-formen)» = N kall, ikke ETT kall med N. Premisset ble felt FØR bygging; ordren ba selv om nettopp den sjekken. Konsekvensen er at INGEN eksisterende kaller endrer signatur — CLI, hosting og simulation sender fortsatt én base hver, og kan fortsatt gjøre det. Tre sømmer: (1)mandate.Approach.bundle_id, default"", så hvert mandat skrevet før i dag er fortsatt gyldig OG dispatchbart uendret; (2)mandate.route_by_bundle— ren partisjon ibundle_ids-rekkefølge (aldri i approach-rekkefølge: spend-ordenen er en egenskap ved hvordan kjøringen ble konfigurert, ikke ved hvordan en modell tilfeldigvis sekvenserte hypotesene), fail-fast på et mandat som ikke kan utføres som skrevet (load_mandate-regelen — en kjøring skal aldri gå videre på en stille degradert bestilling); (3)run.run_mandate_across_bundles— dispatchen. Den tar INGENproject_id-parameter, og det er designet: hver bases prosjekt leses fra DEN basens egen IR-projeksjon, altså nøyaktig verdien_project_from_bundleallerede fail-faster mot, så en kaller-oppgitt konstant kunne uansett bare vært riktig for én base av N — den eksisterende fail-fasten blir rutingsnøkkelen, og gjetningen forsvinner. EttVerdictStoretrådes på tvers (kryss-base-læring,run_portfolio-formen), og delt INSTANS er påstanden — ikke lik verdi (se vakuitets-funnet under). En base ingen approach navngir kjøres IKKE (en kjøring koster penger, og bestillingen ba om ingenting der); med NØYAKTIG én base absorberer den alt uten navn, som ikke er en gjetning men det eneste mulige svaret — og det er dét som holder hvert pre-multi-base-mandat dispatchbart.explore()stemplerbundle_idpå hver MYNTET approach, men skriver ALDRI om et frø (§ C.6 dør 1 er en bevaringsregel — å fylle inn feltet på ekspertens vegne ville satt deres navn på en rutingsbeslutning de ikke tok); frøene VALIDERES i stedet, FØR første modellkall (økt-57-hoisten: ved unntaket alene ser en nekt etter forbruket identisk ut med en før). En umerket markør med flere baser NEKTES (HypothesisParseError), med én base resolveres den. Budsjett: de to S3.4-tennene som HAR mening her — oppstartsnekt (BudgetRefused) og aldri-startet +budget_stop+not_evaluated-rader iMultiBaseResult.unreached; bølge-reservasjonen har ingen motpart, for dispatchen er SEKVENSIELL. Ærlighets-grenser, uttalt: en base som RAISER propagerer (collect-and-continue tilhørerrun_portfolio, der kalleren sendte inn en batch uavhengige prosjekter); utenportfolio_meterer taket antall rutede baser ×max_tokens, hver kjøring bundet for seg; outboxen er IKKE wiret (N kjøringer trenger Nrun_id-er, og å mynte dem her ville defaultet en nøkkel repoet krever at en kaller oppgir); og CLI-en er BEVISST urørt — § C.8 ber om ETT nytt kallsted irun.py(--explore, levert i 57), og et repeterbart--bundle-direr en NY operatørflate, altså en egen beslutning. Load-bearing MÅLT (tests/test_multibase_loadbearing.py, 22 tester), tolv mutasjoner alle røde mot HELE suiten + grønn kontroll 1020/5 og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): detach myntetbundle_id(2 røde) · stille gjennomfall ved >1 base (1) · ukjent id resolvert etter rekkefølge (1) · frø-sjekk etter forbruket (2 — asserten er på at NULL modellkall skjedde, ikke på unntaket) · ruteren gjetter første base (1) · uroutbar approach droppet (1) · dispatchen kollapser til én base (5) ·project_idfra første base (2) · detach aldri-startet-tannen (1) ·unreachedurapportert (1) · fersk store per base (1) · detach oppstartsnekten (2). ÉN MUTASJON FALSIFISERTE TESTEN FØRST (repoets vakuøs-gate-klasse, åttende gang): store-testen sammenlignet med==, ogVerdictStoreer en pydantic-modell med VERDI-likhet — tre ulike TOMME stores er alle like, så «fersk store per base» lot HELE suiten stå grønn. Delt instans er påstanden, så testen asserterer nå påis. -
«Be om svar, BRUKE svarene» er nåbar fra CLI-en, og gaten er den ANDRE halvdelen (F4, økt 63): før dette nektet BEGGE operatørflatene
enable_plan_review(run.py,hosting.py) og eneste dør varexplore(..., plan_reviewer=...)— MÅLT mot kilden, ikke lest ut av reviewens prosa.--plan-reviewbygger enterminal_plan_reviewer()og gir den til den UENDREDE sløyfa: operatøren vises planen og svarerapproveellerrevise <hva>; en revisjon går tilbake til manageren, som replanlegger og spør IGJEN om den NYE planen. Diskriminatoren er dét siste — en dør som printer planen, leser linja og kaster den består «operatøren ble spurt» og feiler målbildet (repoets vakuøs-gate-klasse); T1 er derfor bygget somtest_explore_loadbearings T15 løftet til CLI-nivå og er RØD mot en alltid-godkjenn-reviewer. Vitnet er{run_id}-exploration.json, ikke skrapet stdout:trace_payloadbærer alt tre (rekkefølge, beslutning, feedback verbatim) og skrives fra enfinally, så den ene kjøringen som mest trenger beviset — den et tak eller en ubesvart review kappet — etterlater det. Fail-closed på operatørens EGEN input: alt utenfor det lukkede vokabularet spørres på nytt (aldri lest som en beslutning), og EOF raiserPlanReviewInputError— å lese stillhet som ja ville latt en autonom sløyfe kjøre på en plan ingen signerte, usynlig. Strømmene resolveres ved KALL-tid (shared_root()-idiomet), ellers svarer reviewer-en fra strømmen som fantes da den ble BYGGET. Fire nekter, alle ved navn, hvorav to lukker et stille dropp ingen test dekket:report_forbidden(report-modus returnerer FØR hver utforsknings-nekt) og portefølje-partisjonen. De to konfig-avhengige nektene DELER tokenetenable_plan_reviewog har derfor bevisst ULIK særtekst («no reviewer was offered» / «no review is ever requested») — den eksisterende testen asserterte på det delte tokenet og er rettet (økt-57-mutasjonen, niende gang). Hosting NEKTER fortsatt, og det er en beslutning: reviewen er synkron, så den ville blokkert HTTP-requesten på et menneske OG event-løkka som svarer/readiness— meldingen navngir nå CLI-døra i stedet for å påstå at biblioteket er den eneste (Fase 3-klassen). Mid-løp-spørsmål er IKKE bygget, og fraværet er MÅLT:_magentic.pyhar nøyaktig ETTctx.request_info(:1044, plan review) i hele modulen, så stacken kan ikke levere et spørsmål midt i løpet uten en ny emitter. Reviewens «kun plan-review FØR løpet» er derimot upresist: samme forespørsel fyrer også ved re-plan etter en stall (is_stalled=True), så døra ER nåbar midt i en kjøring på den ene måten stacken støtter. Load-bearing MÅLT (tests/test_plan_review_cli_door_loadbearing.py, 12 tester), elleve mutasjoner alle røde mot HELE suiten + grønn kontroll 1040/5 og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): detachplan_reviewer-wiringen (5 røde) · EOF blir en godkjenning (1) · alltid-godkjenn (3) · alt som ikke er en revisjon blir en signatur (1) · dropp--plan-reviewfra portefølje-partisjonen (1) · dropp den frareport_forbidden(1) · detach--plan-review requires --explore(1) · detach review-uten-reviewer-nekten (2, hvorav én i en test som fantes fra før) · detach reviewer-ingen-spør-nekten (1) · hostet nekt beholder påstanden fra før F4 (1) · strømmene fanget ved bygge-tid (1). -
Plan-reviewen kan besvares over DAGER, og det eneste som krysser prosessgrensen er DISK (U12 + asynkron U13, planens § D.2 rad 3, økt 64): F4 gjorde «be om svar, BRUKE svarene» nåbar, men bare SYNKRONT —
terminal_plan_reviewerblokkerer løkka på et menneske ved en terminal, så svaret må komme mens prosessen lever.--checkpoint-dirPARKERER i stedet reviewen (FileCheckpointStorage+{run_id}-plan-review.json), og--resume <run_id>leser svaret fra--review-inboxi en prosess som ALDRI så kjøringen. MÅLT FELLE (ansikt 4):list_checkpoints(_checkpoint.py:386-388) svelger en blokkert deserialisering til enlogger.warningog returnerer TOM liste — uten BEGGEMagenticPlanReviewRequest/…Responseiallowed_checkpoint_typesfeiler en resume som et FRAVÆR, ikke som en feil, og en test som asserterte «listingen er tom, altså er det ingenting å gjenoppta» ville vært GRØNN mot nøyaktig den defekten._ALLOWED_CHECKPOINT_TYPEShar derfor ÉN kopi ogcheckpoint_storageer ENESTE konstruksjonssted (BEGGE prosesser må deklarere dem; en andre kopi er kø-(p)-driften). Vi er LOUDERE enn rammeverket der det tier: en tom listing ved park raiserCheckpointUnreadablei stedet for å skrive et spørsmål ingen kan besvare. Diskriminatoren er den ANDRE halvdelen: en dør som skriver en spørsmålsfil og en resume som leser en svarfil består begge «eksperten ble spurt» — så måltesten krever at etreviseskrevet dag 1 får manageren til å REPLANLEGGE og stille et NYTT spørsmål (indeks 1, nyttrequest_id) i en fersk interpreter, med en approve-kontroll som beviser at døra også kan AVSLUTTE (en gate som bare kunne parke igjen er en hengning i løkkeklær). Budsjettet og revisjons-capen spenner over suspensjonen:meter.charge(parked.tokens_spent)(gjennomcharge, ikke ved å settetokens— ladingen re-tester taket) ogtrace.ledger.extend(parked.ledger), ellers får hver park et helt budsjett på nytt: S3.4-klassen, ubundet forbruk under vakter som alle ser tilfredse ut. Enrevisekoster to manager-kall, emitterer null ledger og bruker null runde (§ F, A3), såmax_plan_revisionser det ENESTE båndet på den. Fail-closed på ekspertens EGEN fil:request_id-mismatch, ord utenfor vokabularet ogreviseuten innhold refuseres alle ved navn.hitl.pending_plan_reviewser registeret over hvem som fortsatt venter — tolerant på LESE-siden, fail-closed på BESLUTTE-siden, og joinen er pårequest_idi BEGGE ender (to distinkte sømmer, MÅLT: hver har sin egen mutasjon og sin egen røde test). Load-bearing MÅLT (tests/test_async_plan_review_loadbearing.py, 17 tester), tretten mutasjoner alle røde mot HELE suiten + grønn kontroll 1059/5 og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): tom_ALLOWED_CHECKPOINT_TYPES(11 røde) · park uten checkpoint (1) · resume alltid-approve (2) · tolerantrequest_id(1) · tolerant vokabular (1) ·reviseuten feedback (1) · detachmeter.charge(1) · detachtrace.plan_reviews.extend(1) · detach ledger/hypotese-carry-overen (1) ·pending_plan_reviewsignorererrequest_id(1) · detach to-dører-nekten (1) · detach outbox/run-id-hoisten (1) · detach--resume-armen irequired_scripted_roles(4 — MAJOR-2sKeyError: 'navigator'på den andre flaten som bygger en utforskning). ÉN MUTASJON FALSIFISERTE SUITEN (repoets vakuøs-gate-klasse, TIENDE gang):trace.plan_reviews .extend(parked.plan_reviews)kunne detaches med HELE suiten grønn (1058/5) — capen leserparked.plan_reviewsDIREKTE, så den binder uansett, og de to første legene er identiske under begge implementasjoner. Gaten måtte derfor bli det TREDJE leget, der artefaktet ellers taper dag 1s revisjon og to ULIKE planer deler indeks 1; den nye testen er rød mot mutasjonen og alene. Ærlighets-grenser, uttalt: den hostede flaten NEKTER fortsatt (en synkron review ville blokkert både requesten og event-løkka som svarer/readiness); en park MIDT i løpet (etter en stall) har ingen nåbar sti under det skriptede manuset, så carry-overen som betjener den drives gjennom en CRAFTED parkert tilstand (budget_stop-presedensen); og resume-legetsPlanReviewParkeder et NORMALT utfall, ikke en feil. -
Katalogkallet koster O(BASER), aldri O(KORPUS) — og det er stigens billigste trinn, ikke dens dyreste (ordre
20260825T213645Z, økt 65):list_bundlesreturnerte hele rot-indeksens body for HVER konfigurert base samtidig, pluss ett JSON-objekt per ufulgt kryss-lenke. Begge vokser med korpuset, så prisen på å finne ut hvilke baser som finnes ble satt av hvor mye de inneholder — progressiv disclosure snudd på hodet (målbilde §2/§4). MÅLT medo200k_base, instrumentet først validert mot commons' egne fasittall: 112 116 tokens over tre flate Vegnormal-baser, og 124 942 over de 171 grenbasene som erstattet dem — grenformen (vegnormal-okf8145c23) lukket bundle-siden (−82…92 % påread_bundle) og gjorde katalogsiden VERRE, nøyaktig som det repoet forutså. Etter: 362 og 21 448 (per base 37 372 → 121 og 731 → 125). Et premiss ble felt FØR noe ble bygget på det: «indeksbodyen forteller hva basen handler om» er USANT for maskin-importerte baser — grenbasenesindex.mdhar verken frontmatter eller prosa, den er en ren lenkeliste (målt: 959 bytes, første tegn-), så feltet var dyrt OG innholdsløst der. Fast vindu, aldri en andel av basen (_CATALOGUE_EXCERPT_CHARS = 200): en andel skalerer med korpuset igjen, bare med mindre konstant. Avkorting ANNONSERES som FELT (index_truncatedved siden av utdraget, aldri en markør limt inn i det —BudgetExceededs kø-(y)-regel), og en base som PASSER blir ikke merket avkortet og får hele bodyen: omisjon, aldri en løgn i noen av retningene. En ufulgt lenke overlever som ANTALL — økt 51s «et hopp er tolerert, men ikke lenger taust» står, mens per-lenke-detaljen blir liggende der den er handlingsbar (RunResult.skipped_links/DryRunReport.skipped_links) og ikke rir med i et kall hvis hele jobb er å være billig. Hele indeksen er fortsatt ETTread_file(id, "index.md")unna — et disclosure-nivå, ikke datatap. Taket (500 tegn/base) bor i TESTEN, ikke iexplore.py: en test som importerte implementasjonens budsjett ville flyttet seg med det, og å heve budsjettet er nøyaktig regresjonen gaten finnes for. Load-bearing MÅLT (tests/test_catalogue_cost_loadbearing.py, 7 armer), ni mutasjoner alle røde mot HELE suiten- grønn kontroll 1066/5 og golden
demo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): ingen binding (4 røde) · bundet men vakuøst (2) · stille kutt (1) · over-annonsert (1) · per-lenke-lista rir med igjen (1) · det ufulgte faktumet slettet (1) · suffiks i stedet for ordrett prefiks (2) · en andel i stedet for fast vindu (2) ·documentsgjort konstant (1). M9 ble kjørt fordidocumentsvar et felt uten gate — et felt ingen test kan se, råtner. MAJOR-1 var IKKE nødvendig: bindingen sitter i verktøykroppen bak en uendret CLI-flate. Ærlighets-grenser, uttalt:navigate_bundlekalles fortsatt per base per katalogkall (I/O og veggklokke, ikke tokens — ikke målt her); ingen LEVENDE modell har kalt det nye verktøyet, så at en manager velger BEDRE med et utdrag enn med hele indeksen er ikke bevist (structured-output-grensens klasse); og ordrens nevner for N100:2023 var 34 mens disken viser 40 — tallene bruker den målte nevneren. Måling:docs/2026-08-26-katalogkostnaden.md.
- grønn kontroll 1066/5 og golden
-
Et fravær ved en signeringsport sies i ORD; i dataene sies det ved å være borte (PM-tillegg 4, økt 77):
PlanReviewRequest.current_progressogParkedExploration.current_progressble begge bygget medstr(review.current_progress). Verdien er enMagenticProgressLedger | Noneog erNonei hver kjøring målt så langt, såstr()ga de fire tegneneNone, rendererens truthiness-vakt fant dem ikke-tomme, og eksperten som skulle SIGNERE en plan ble vist en «progress so far»-seksjon hvis eneste innhold var ordetNone— og de samme fire tegnene ble skrevet inn i{run_id}-plan-review.json, det ENESTE som krysser prosessgrensen i U12s asynkrone dør._progress_texter den ENE konverteringen (ved siden av_plan_text): fravær blir tom streng, aldri"None". Datalaget sier fravær ved å være tomt (Bundle.skippeds tom-tuppel-regel), mens TERMINALEN sier det i ord — det er den ene flaten der omisjon er feil, fordi stillhet ved en port noen signerer er nøyaktig détPlanReviewInputErroralt nekter for EOF. Målingen endret testen: å reversere BEGGE kallsteder lot KUN en kildeinspeksjons-arm bli rød — en lint, ikke en gate, fordi de første armene konstruerer enPlanReviewRequestselv og aldri går inn i noen av stedene. Hvert sted har nå et ATFERDSMESSIG vitne som driver den EKTE døra: terminalen for den synkrone, den parkerte spørsmålsFILA for den asynkrone. Load-bearing MÅLT (tests/test_plan_review_progress_line_loadbearing.py, 7 armer), fem mutasjoner alle røde mot HELE suiten, hver med sin egen signatur + grønn kontroll 1202/5 og golden BYTE-UENDRET: begge steder reversert (3 røde) · det synkrone alene (2) · det parkerte alene (2) · terminalen går stille igjen (2) · plassholderen fyrer alltid og sluker en ekte ledger (1, kontrollen alene). Recorder-wiringen iresume_explorationer URØRT (uvitnet, defensiv — S2b). -
evidence_foravleder en tier KUN for nøkkelen SPEC §5.3 tierer (PM-tillegg 5, økt 77):evidence_for(path, key="sources")REISTEValueError. Tieren ble avledet UBETINGET gjennomtrust_tier, som nekter en oppføring utenby-aktør — riktig, fordi en tillitsgrad avledet av en oppføring som identifiserer ingen mynter den proveniensen den påstår å lese. Menbyer påkrevd av en VERIFIKASJONS-oppføring (SPEC §5.2), ikke av enhver provenienss-nøkkel: den avtalte segmenterte formen bærersegment_id/source_offset, ensources-liste bærerid/resource. Vakten tilhørende ÉN nøkkel ble anvendt på ALLE.trust_tierer URØRT —_TIERED_KEYnavngir den ene nøkkelen §5.3 tierer, og enhver annen nøkkel kommer tilbake medstate/reason/items_seen/entriesogtier=None.admits_falsificationflyttet MED, og det er samme faktum, ikke scope-krype: den lestetier != "unverified", ogNone != "unverified"er SANT, så ensources-liste som FINNES ville klarert en terskel om verifisering; den navngir nå tierene som klarerer. For hver verdi som var nåbar før endringen er de to skrivemåtene identiske — derfor står de eksisterende K5-armene grønne, og derfor er dette en innstramming og ikke en ny regel. Målingen korrigerte testen: enverified-verdi UTEN aktør når aldritrust_tiergjennomevidence_fori det hele tatt — dekoderen nekter formen først, somunreadable/unsupported-flow; begge vakter asserteres nå der hver av dem FAKTISK bor. Defekten fantes fordi parameteren aldri var ØVET: alle 11 kallsteder brukte defaulten (målt ved B4s slutt). Load-bearing MÅLT (tests/test_evidence_key_parameter_loadbearing.py, 6 armer), fire mutasjoner alle røde mot HELE suiten + grønn kontroll 1208/5 og golden BYTE-UENDRET: avled tieren ubetinget (3 røde) · reverter K5-terskelen (1, konsekvens-armen alene) · «fiks» det ved aldri å tiere (3, inkludert to eksisterende falsifiserings-armer) · løsnetrust_tieri stedet (2, inkludert dens egen eksisterende gate). -
read_bundlekoster O(DOKUMENTER i én base), aldri O(bytes av den — S2c/MAJOR-3, økt 77): verktøyet returnerteokf.bundle_context, altså HELE den navigerte basen, og fordi utforskningens deltakere deler ÉN samtalehistorikk red det enefunction_result-et med i hver senere prompt til full pris uten at noen ba om det igjen. MÅLT FØRST, med nevner, og committet som docs før én linje kode ble rørt (docs/2026-09-02-read-bundle-kontekstkostnad.md): 3 861 / 10 406 / 12 595 o200k-tokens for de tre eksempelbasene, 5 kopier per CLI---explore-kjøring (navigatør ×1, manager ×3, hypotesiser ×1) = 54 % / 59 % / 59 % av ALLE prompt-tokens. Instrumentet ble validert mot en KJENT POSITIV før bruk (det reproduserte commons' egne publisertebundle_context-fasittall eksakt), og prompten måles som tekst +function_call+function_result—.textalene måler en kontekstbærende prompt til noen få tegn. Formen er katalogens, ett trinn ned på stigen (list_bundles= hvilke baser finnes,read_bundle= hva er i DENNE,read_file= hva sier dokumentet): én oppføring per konseptfil medname,type,title,chars. Etter: 259 tokens på tunnelbasen, utforskningens prompt-tokens −77 / −90 / −91 %. Listen bygges avBundle.context_files, ALDRIfiles— det er dén property som droppertype: verdict-laget (og nestedeindex.md) på hvert nivå, og en liste bygget avfilesville rutet tidligere dommer foran navigatøren UTENOM den gatede ExpeL-folden mens hver kostnads-arm forble grønn. Et premiss ble felt før noe ble bygget på det: «indeksbodyen er basens egen navigasjonsprosa, så den hører hjemme her» — tunnelbasens rot-indeks er alene 4 763 tegn ≈ 1 400 tokens, altså nesten hele taket, for et felt katalogen alt gir et bundet utdrag av ogread_file(id, "index.md")fortsatt gir helt. Taket bor i TESTEN (_CEILING_CHARS = 1 500), katalogtakets regel av katalogtakets grunn. AVVIK fra ordren, uttalt: ordren ordlegger gaten i o200k-TOKENS; gaten bounder TEGN, forditiktokenikke er en prosjektavhengighet og en gate som skipper når en valgfri pakke mangler er en gate som kan være stille fraværende — konverteringen er MÅLT (748 tegn / 259 tokens = 2,89 tegn/token), og ordrens eget kriterium er verifisert direkte én gang av instrumentet. «Ikke utløs» er bevist som en MÅLING, ikke som en forsikring: debattens treokf.bundle_context-kopier er byte-identiske før og etter i alle tre baser (12 047 / 32 567 / 39 104 prompt-tokens, hver prompt uendret) — sterkere enn å påstå atrun.pyikke ble rørt. Verktøybeskrivelsen og navigatørens instruksjon er oppdatert i samme trekk: begge påsto «read its navigated context», og en beskrivelse som lyver om kroppen er modellens instruks (Fase 3-klassen, påstander flaten gjør om SEG SELV). To eksisterende asserts ville blitt VAKUØSE i stillhet (read_bundle(...) != ""er sant for enhver liste,test_explore_loadbearing.py+test_bundle_id_reconciliation_loadbearing.py) og er styrket, ikke latt stå. Load-bearing MÅLT (tests/test_read_bundle_cost_loadbearing.py, 6 armer), sju mutasjoner alle røde mot HELE suiten + grønn kontroll 1 195/5 (fra 1 189/5, supersett, 0 fjernet) og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): reverter sømmen (7 røde) · bygg frafiles(3) · bundet men VAKUØS tom liste (6) · droppchars(2) · bær indeksbodyen likevel (4) ·read_filetrunkerer (2 — inkludert katalog-gaten, et uavhengig vitne) · detachreconcile_bundle_id(1). Ærlighets-grenser, uttalt: dette er IKKE «−59 % kostnad» — en navigatør som åpner k dokumenter betaler kread_file-resultater, og gevinsten er at den betaler for det den VALGTE og at hvert resultat rir fra SITT kall og framover; at en LEVENDE modell velger BEDRE med en liste enn med hele konteksten er IKKE bevist (structured-output-grensens klasse); multiplikatoren 5 gjelder dette manuset (misjonsreview-v2§ 4 målte 7× med et annet); debattens 3× er PM-ens egen beslutning og er urørt; prefiks-caching (≈ 60 % debatt / ≈ 40 % utforskning cachebart som koden står) er NOTERT, ikke bygget. Et fravær som var instrumentfeil, ikke faktum: første ETTER-kjøring rapporterte 0 kopier på to baser — sonden var en midtskive som traff norske tegn prompten serialiserer escaped; byttet til et ASCII-konseptfilnavn ga 5, som før. -
Ekspertdommen kan ikke oppstå av STILLHET, og fraværet er en FØRSTEKLASSES tilstand (F2, non-goal 3, økt 66):
run_projectKREVDEverdict_inputog kjørtecapture_verdictubetinget, CLI-en defaultet det til{"approved", "reviewed by expert"}, og hosting listet det som PÅKREVD. Netto: hver flaggløs kjøring myntet en ekspertgodkjenning ingen ga, den gikk inn i den delte storen, ogrun_portfoliobar den inn i neste prosjekts hypotese-prompt som en prior expert verdict — på flaten som ble overlevert 14.08.RunResult.verdicter nåVerdict | None, ogNoneer hva stillhet produserer: ingenting myntes, ingenting lagres, ingenting varsles. Prinsippet sto allerede skrevet i repoet —RunFailures docstring: å fylle et felt med en dummy legger FABRIKKERT proveniens inn i aggregatet. Traceability koster ingenting, fordi nøkkelen DERIVERES fra kandidaten:RunResult.verdict_key(property, ikke lagret felt — en andre kopi av en nøklingsregel er kø-(p)) erverdicts.verdict_keys alt dokumenterte formål, identisk medverdict.idnår en dom BLE gitt, og fortsatt meningsfull når ingen ble det; det er den outboxen og den hostede responsen stempler, så et artefakt fra en ukommentert kjøring er fortsatt dømbart og joiner tilbake via Steg-7-innboksen. Halv dom NEKTES på begge dører (FeedbackContracter ENESTE sted formen valideres, og CLI-en nekter ved navn FØR enhver mode-dispatch): den manglende halvdelen er ekspertens å skrive, aldri vår å defaulte — validering, ALDRI reparasjon (write_concept_file-presedensen). Hosting er WIDENING, ikke bryting:verdict_inputflyttet_REQUIRED_FIELDS→_OPTIONAL_FIELDS, så hvert kall som finnes ute virker uendret; en kaller som utelot det fikk før 400 på et felt som ikke KUNNE fylles ærlig. De to mode-partisjonene fikk--decision/--rationaleinn — og det er en KONSEKVENS, ikke scope-krype: kommentarene på begge stedene sa ordrett at en ærlig nekt var uimplementerbar fordi de non-None argparse-defaultene gjorde en eksplisitt verdi uskillbar fra defaulten. Med defaultene borte er den implementerbar, og «refused, never ignored» er partisjonens egen regel.run.verdict_noticeer ENESTE renderer og leser dommen av kjøringens EGET stempel, ikke av argv. Ærlighets-grense, uttalt: referanse-fixturens SYNTETISKEverdict_input-rader står URØRT — de er merket SYNTETISK på fire steder og er reviewens F5 (måling av misjonspåstanden), ikke F2;Project.verdict_inputer nå valgfri, så en rad UTEN dom er lovlig. Load-bearing MÅLT (tests/test_ungiven_verdict_loadbearing.py, 15 armer), åtte mutasjoner alle røde mot HELE suiten + grønn kontroll 1080/5 og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): detach fangst-gaten (5 røde) · gjeninnfør argparse-defaultene (22) · hosting krever fortsatt feltet (1) · CLI-en REPARERER en halv dom (2) · kontrakten reparerer en halv dom (1) ·verdict_keylest av dommen i stedet for derivert (2) · begge partisjons-radene fjernet (2) · rendereren påstår en dom som aldri ble gitt (2). ÉN MUTASJON FALSIFISERTE TESTEN FØRST (repoets vakuøs-gate-klasse, ELLEVTE gang):--report-armen brukte et bart--report, som nekter med rc 1 uansett fordi--ledgermangler — testen sto GRØNN med partisjons-raden fjernet. Den kjører nå mot en argv report-modus ellers ville AKSEPTERT (gyldig--ledger+ en kontroll som beviser rc 0 uten flaggene), så rc 1 er mutantens motsatte utfall. Migreringsnote: ingen ekstern kaller brekker — hosting utvider, CLI-ens gamle flaggform er uendret, og det som ENDRER seg er at en flaggløs kjøring nå SIER at ingen dømte i stedet for å påstådecision=approved. -
Planen et menneske signerer er TEKST, aldri en objekt-repr — og fraværet av repr er en EGEN, bredere assert (BLOCKER-1, økt 67): fire steder gjorde
str(review.plan)på en MAFMessagesom ikke har noen__str__(MÅLT:type(Message).__str__ is object.__str__), så BEGGE HITL-dørene viste og lagret<agent_framework._types.Message object at 0x…>: terminalen F4 spør ved (explore.py:1395), de to opptakene iplan_reviews(:1404approve,:1418revise) og den PARKERTE spørsmålsfila U12 (:1478) — det ENESTE som krysser prosessgrensen. En ekspert som svarteapprovesignerte blindt. Fiksen er den eksisterende_plan_text(:966) på alle fire; ingen ny hjelper. Fire asserts var grønne mot defekten fordi de var TRUTHINESS eller SELV-SAMMENLIGNING:reviews[1]["plan"] != "",waiting[0].plan, ogreviews[0]["plan"][:40] in out— den siste sammenlignet den samme repr-en med seg selv, så de to flatene var enige mens begge var uleselige. Diskriminatoren er innhold som KUN kan komme avMessage.text: MAF komponerer plan-meldingen rundt managerens svar ORDRETT (målt), så en sentinel i det skriptede svaret er til stede når teksten ble tatt og fraværende når repr-en ble det. Sentinelen bor i etreason-felt fordi ingenting leser dem — å nøkle den til en ANSWER ville endret kjøringen den måler.str(review.current_progress)(:1396/:1479) er BEVISST urørt: den er enMagenticProgressLedger | None, ikke enMessage, og pydantic renderer den lesbart (målt) — men i disse kjøringene er denNone, så terminalen skriver «progress so far: None». Annen defekt, annen ordre. Load-bearing MÅLT (tests/test_plan_review_cli_door_loadbearing.py+tests/test_async_plan_review_loadbearing.py), fire mutasjoner — ÉN PER LINJE, fordi ordrens ene samlede revert undertestet og:1418er revise-grenens egen kopi som ellers ikke hadde noe rødt vitne::1395→ 1 rød (stdout) ·:1404→ 2 ·:1418→ 1 (T1 alene) ·:1478→ 1 (async T9). Golden byte-uendret. -
Generalprøven kan ÅPNE en base, og artefaktet sier hvilken (MAJOR-1, økt 67):
--scripted-repliestok ÉN konstant streng per rolle, så ingen skriptet rolle kunne emittere etfunction_call— MÅLT 0 verktøykall / 0 approaches / 1 runde på 4/4 baser, mens hvert annet felt i{run_id}-exploration.jsonså ut som en kjøring som hadde virket. Måleprotokollens gratis trinn («bevis så mye som mulig før det dyre») kunne altså ikke bevise at navigatøren åpner noe, og etter en BETALT kjøring kunne ingen lese om den gjorde det. To halvdeler, hver gatet så den ANDRE ikke kan bære den. (a)ExplorationToolRecorder— enFunctionMiddlewarepå utforskningsagentene som registrerer NAVN +bundle_id-argumentet i KALL-REKKEFØLGE på den kaller-eideExplorationTrace;trace_payloadskriver det ved siden avquick_validations. SØSKEN avmcp_tools.ToolCallRecorder, aldri en gjenbruk: den filtrerer til KONFIGURERTE eksterne verktøy, dedupliserer per(server, tool)og returnerer SORTERT, fordi dens rad er en egress-påstand; denne beholder rekkefølge uten dedup, fordi et sortert dedupet sett ikke kan skille en generalprøve som LESTE en base fra en som bare listet dem. Å generalisere den ene til å tjene begge ville brutt den andre. RESULTATET registreres ALDRI — det er basens innhold, altså nettopp det MAJOR-3 målte til 73–93 % av alle prompt-tokens. Wiret i BEGGE workflow-byggene (explore()OGresume_exploration()) — men resume-armen er DEFENSIV og UVITNET, og det er målt, ikke antatt (budget_stop-presedensen): å detache KUN den andre forekomsten lot hele suiten stå grønn (1087/5), fordi ingen park/resume-scenario under det skriptede manuset når en verktøykropp. Den står fordi et gjenopptatt leg ellers ville registrert null verktøykall — samme stille gap somplan_reviews.extendi økt 64 — ikke fordi en test holder den. (b) et trinn-MANUS — en utforskningsrolle kan få en LISTE der et trinn er tekst eller ETT{"call": "<tool>", "args": {…}}. Formen utvider den ENE kanoniske_inner_get_response-kroppen (S2.5), aldri en andre klient: manuset ligger VED SIDEN AV selektoren (en selektor returnererstrved kontrakt, og et verktøykall er ikke tekst), og et utløpt manus faller tilbake på selektoren — degradering til konstantformen, ikke til stillhet. Listeformen NEKTES for debattens roller ved navn, og hvert malformet trinn nektes ved navn (validering, ALDRI reparasjon). Å skripte navigatøren er IKKE nok, og det er MÅLT: med en KONSTANT manager konkluderer kjøringen etter én runde uten å ha gitt noen deltaker en tur, såtool_callsforblir tomt uansett hva navigatøren fikk. Manageren må selv få et trinn-manus — én tekst per stadium (fakta, plan, ledger, ledger, sluttsvar), samme grunnsimulation._exploration_manager_replynøkler på PROMPTEN og ikke prosjekt-ID-en: manageren får fem ULIKE spørsmål og én konstant svarer alle fem med første rundes ledger. Kontroll-testen med konstant navigatør (og manager i stadier) er dét som holder de to formene fra hverandre. Load-bearing MÅLT (tests/test_scripted_explore_door_loadbearing.py, 12 armer), ni mutasjoner alle røde mot HELE suiten + grønn kontroll 1087/5 og golden BYTE-UENDRET: detach recorderen fra begge byggene (1) · dropptool_callsfratrace_payload(3) · sorter+dedupliser sinken (2) · registrer navnet uten basen (3) · nekt listeformen igjen (2) · aksepter lista men emitter tekst (1) · toler et malformet trinn (1) · la en debattrolle ta listeformen (1) · dropp ukjent-nøkkel-whitelisten (1). ÉN MUTASJON FALSIFISERTE TESTEN FØRST (repoets vakuøs-gate-klasse, TOLVTE gang): nekt-testen brukte{"invoke": …}og sto GRØNN med forms-sjekken detached — UKJENT-NØKKEL-grenen fanget den i stedet, så nekten under test hadde intet vitne. To grener, to armer, to mutasjoner. Ærlighets-grense, uttalt: at en LEVENDE modell kaller verktøyene er fortsatt ikke bevist (structured-output-grensens klasse) — dette gjør den GRATIS halvdelen av stigen ekte, ikke den betalte. -
MAF-pinnen er en TRIPWIRE, ikke en frys — og det som gjorde løftet farlig var IKKE en form som forsvant (F15, 02.09, core 1.9.0 → 1.16.0, orchestrations 1.0.1 → 1.1.1): de to kan ikke løftes hver for seg (orchestrations 1.1.1 krever selv
core>=1.15.0). Gulvet bor i ÉN konstant (_MIN_VERSIONitests/test_maf_version_guard.py) ogpyproject-asserten DERIVERER sin forventede streng fra den — to literaler for ett faktum drifter (kø-(p)), og et driftet gulv er en vakt som slutter å vokte uten én lokal diff. 17 private/ugaranterte former, derivert fra repoets EGNE siteringer (hver_modul.py:linje-referanse isrc/+ hver form en søm overstyrer eller konstruerer); 16 sjekket MEKANISK av en probe mot begge versjoner (1 endret), den 17. funnet av TESTSUITEN (endret) — 2 endret totalt. Splitten er ikke pedanteri: «2 av 16» ville tilskrevet proben et funn den ikke gjorde, og skjult at proben sjekker statiske egenskaper ved KILDEN mens den farlige endringen var en egenskap ved KJØRINGEN — nevner-disiplin anvendt på mitt eget instrument. Kjent-positiv:MiddlewareFailure(ny i 1.15.0) flippet NO → YES, altså KAN proben oppdage endring;_compaction.pys@experimental-markører ble FORKASTET som kjent-positiv fordi de teller 0 i BEGGE versjoner og derfor ikke diskriminerer noe. Den farlige endringen var den ordren navnga — formen som fortsatt importerer, men har flyttet semantikk i stillhet: en park skriver nå TO checkpoints og bare ÉN bærer plan-review-typen, så en feildeklarert_ALLOWED_CHECKPOINT_TYPEStømmer ikke lenger listingen — den taper nøyaktig den checkpointen som betyr noe,get_latestreturnerer den ANDRE, og_parkslatest is None-vakt passerte mens kjøringen svarterc=0og skrev et spørsmål som aldri kan bære svaret. Vakten sjekker nå EGENSKAPEN den alltid mente (str(request.request_id) in latest.pending_request_info_events— et DEKLARERT felt) i stedet for symptomet som pleide å innebære den, og fjerner dermed en privat avhengighet i stedet for å legge til en.ExperimentalWarning-paret P4 pkt. 2 betalte for å BEHOLDE er borte fordi MAF sluttet å sende det —_feature_stage.pys_add_runtime_warningemitterer ved FØRSTE BRUK, ikke ved import, og demoen instansierer ingen av de to typene; goldenens stderr er derfor TO linjer, regenerert som en BESLUTNING, menssite-packages-maskeringen er BEHOLDT (spannet er ubebodd, ikke pensjonert) ogtest_normalisation_does_not_mask_a_new_warningfortsatt er grønn. Load-bearing MÅLT mot HELE suiten, grønn kontroll 1089/5 ogdemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): M1 revert av vakten → 1 rød. ÉN MUTASJON BLE IKKE RØD, og det står som en ÆRLIGHETS-GRENSE, ikke som en gate: spikens gjenopptak fracheckpoint_ids[-1](siste element i en glob-ordnet listing — nøyaktig anti-mønsteret_parks docstring advarer mot) feilet i den første fullkjøringen etter bumpen og var GRØNN ved mutasjonen, altså rekkefølge-avhengig og flaky. Fiksen står på den observerte feilen, ikke på et rødt vitne. Rapport:docs/2026-09-02-f15-maf-pinnen.md. -
Falsifisering MOT PROVENIENS: en dom hviler på det basen faktisk BÆRER, og det den ikke kunne fortelle deg er en del av dommen (B4, Steg 1–13, økt 75+76):
parse_frontmatterer linjeorientert og leser en flow-verdi som ÉN streng, såverified: { by: …, at: … }— SPEC §5.2s kanoniske form — nådde konsumenten som ulesbar tekst, og en blokkform nådde den som tom streng. Begge så ut som «ingen proveniens». Den defekten er den samme fra begge sider, og produsenten MÅLTE den selv:llm-ingestion-okfs egen guard-parser avviser sin EGEN golden (docs/okf-nokkelinventar.md:219,OKFFrontmatterError … '[') — bekreftet på nytt ved Steg 13 mot62b6192. Ett skann, to LESERE, aldri to parsere:_split_frontmatterer modulens ENESTE sted---sammenlignes (gatet av en skanner-tellende arm, M14 → 1 rød), ogdecode_flow_valueer den ene navngitte sømmen over de rå linjene. Dekoderen er nøkkel-agnostisk (aldri hardkodet{id, resource}— den avtalte segmenterte formen legger tilsegment_id/source_offset, så en to-nøkkels dekoder ville nektet nøyaktig de basene sømmen finnes for; M3 → 12 røde) og gjør ingen YAML-1.1-koersering (yes/on/1forblir strenger — en bevisst divergens fra PyYAMLs resolver, skrevet ned i stedet for arvet i stillhet; M4 → 1 rød, en ratchet grønn ved konstruksjon). Tre tilstander, og den tredje ER poenget:evidence_forsvarerpresent/absent/unreadable, og den ulesbare bærer trippelen(state, reason, items_seen)— «hvilken FORM» og «hvor MANGE» er to ulike operative spørsmål,BudgetExceeded-kø-(y)-regelen anvendt på en dokumentleser. Å kollapseunreadableinn iabsentgjør en dom om MANGLENDE bevis til bevis for FRAVÆR (M7 → 4 røde); å rapportere én fast form for alle (M8 → 9 røde). K5-terskelen bor ÉTT sted (admits_falsification:presentOG en tier overunverified) og har TO konjunkter som måles hver for seg (M19a → 2 røde, M19b → 1 rød). Nevneren er skrevet ned: SPEC §5.1 navngir SEKS oppføringsnøkler og produsenten skriver TO (62b6192), så terskelen krever kun det som faktisk emitteres — å kreveauthor/usage_count/last_modifiedville gjort den unåbar i praksis mens den så streng ut på papiret.adjudicationhar en TREDJE token som er VÅR: vokabularet på tråden er lukket (proposed|adjudicated), ogunknowner hva FRAVÆR betyr — aldri noe et dokument får erklære (M20a → 2 røde), og en bærer som gir fra seg en payload uten tilstanden er vokabularet uten sømmen (M20b → 1 rød).evidence_forKUNNE IKKE drive den (D-e → 5 røde): MÅLT eradjudicationen SKALAR, og begge gyldige verdier kommer tilbake som ETT identiskunreadable/unsupported-flow-record, så den ruten kan ikke skille dem i det hele tatt;parse_frontmatterer skalarleseren over SAMME skann. Skriveren nekter nøyaktig det leseren ikke kan lese, og det er strukturelt, ikke en konvensjon:verified_fieldogwrite_concept_filereiser den SAMME navngitteFlowDecodeError(M5 → 5 røde, M16 → 3 røde, M17 → 1 rød). Det usikre tegnsettet er TRANSKRIBERT fra produsentens eget_FLOW_UNSAFE_RE(materialize.py:176,[,\[\]{}]|:\s) — ikke oppfunnet — og er BEVISST smalere: vår parseparator er kolon-MELLOMROM, så":\t"kan ikke restrukturere en av våre par. Ko-drift er stengt av skrivesidens gate, ikke bare oppdagbar via en ekstern referent: planen spådde at M9 (skriver OG dekoder flyttes til blokkform sammen) ville la rundturen stå GRØNN. MÅLT er den spådommen ikke konstruerbar — skriveren kan ikke flytte alene (M9a → 26 røde + 8 feil), fordirender_frontmatterenlinjer hver verdi OGwrite_concept_filenekter formen; M9 krevde derfor at BEGGE vaktene ble slått av samtidig, og ga 17 røde inkludert rundturen. Det er et sterkere utfall enn planen ba om, og det er skrevet ned som målt, ikke som spådd. Navigasjonen forblir TOLERANT mens dekoderen nekter (OKF SPEC §4), bevist med BYTES: M10 → 1 rød, ett navngitt vitne, mens begge nav-goldenene og demo-transkriptet står. Identitet er PARET(bundle_id, concept_id)(D6/B1), ogoriginhar TRE verdier:okf.reconcile_bundle_ider den ENE avledningsregelen — konseptets egen frontmatter først, rot-index.mdsom fallback, mountets basename til sist — ogResolvedBundleId.originsier hvilken (declared-concept/declared-index/mount-derived). Påkrevd uten default, avcost_baseline_anchoreds grunn: begge defaults ville løyet om en hendelse. Ikke en boolean — en kaller som ikke kan skille «konseptet sa det» fra «vi falt tilbake to ganger» har fått et stempel den ikke kan revidere (D-i → 3 røde). MÅLT: null^bundle_id-treff noe sted undershared/,src/,tests/mot en kjent-positiv kontroll på 31 filer med^type:, så begge erklærte grener er DEFENSIVE (budget_stop-presedensen) og drives fra CRAFTED baser; alle 27bundle_dirs=-kallsteder står grønne. ⚠️ TO SETNINGER I DENNE RADEN ER ENDRET 03.09 — se slakke-raden nederst (S7a-3 pkt. 1): mount-avviket NEKTER ikke lenger (erklært vinner), og «begge erklærte grener er DEFENSIVE» gjelder kun dette repoet — K2 erklærer nøkkelen i 619 filer.explore._bundle_indexforblir REN — to av dens egne armer konfigurerer kataloger som ikke finnes og forventer en id-feil, ikke en I/O-feil — så avstemmingen skjer der en base faktisk ÅPNES:explore.read_bundle(M11a → 1 rød),run_projects bundle-arm (M11b → 2 røde) og dispatcheren (M11c → 1 rød, som erstattet en privatPath(raw).name-kopi). En base uten lesbarindex.mder ukjent, ikke uerklært —navigate_bundles fail-fast propagerer.BundleIdMismatchsubklasserValueErrorså den lander på CLI-ens nekt-tuppel og hostings 400-arm, aldri krasj-kanalen; nekten måles på null modellkall, ikke på exit-koden (M12 → 2 røde. Ærlighets-grense, MÅLT: planens påstand «exit-koden forblir 1 uansett» HOLDER IKKE for denne argv — mutanten reiserBudgetExceeded: rounds limit=12 observed=13før noen nekt, så sink-asserten nås aldri. Asserten på KALL er likevel riktig design; den er det som ville fanget en nekt-etter-forbruk som DID returnerte rent). En kryss-base-kollisjon rapporteres, aldri droppet i stillhet (D2):VerdictStore.adder first-write-wins og_mint_idekskluderer korpuset ved konstruksjon, så to baser som beskriver SAMME kandidat kollapser på én dom._mint_ider URØRT (normativ ishared/method-spec.md, commons-eid) ogaddlikeså — en drop DER kan like gjerne være mot en Steg-7-innboksdom eller et bundle-frø. Regnskapet bor i dispatcheren, som er det ENE stedet som holder id→base-kartet (M13 → 2 røde). Id-en hentes frarun_projects EKSISTERENDEnotify-søm, aldri fraRunResult.verdict(D-l):notifyfyrer INNE i fangst-blokka, altså nøyaktig når en dom finnes (F2), og båsen bygges FERSK hver iterasjon — hoistes den ut, leser en senere base forrige bases dom og fabrikkerer en kollisjon som aldri skjedde (D-l → 1 rød).MultiBaseResult.collisionsDEFAULTER til tom tuppel (skipped_links-halvdelen: en tom trace er et ærlig POSITIVT utsagn), ogcollision_noticereturnererNonepå den — omisjon, aldri tom rad. Metoden er en DELT Agent Skill, forfattet i commons (D4):shared/skills/falsification- reviewer/kommer KUN viagit subtree pull— lokal forfatting ville gitt et wheel søskenet aldri arver, og INGEN test i suiten oppdager det avviket. Terminologi-gaten er den som biter (OKF bundlei kundevendt prosa → M18a, 1 rød), og den er paret med en KJENT-POSITIV kontroll på at regexen KAN finne strengen. Rammeverks-nøytraliteten har ÉN kopi (test_method_spec_is_framework_neutral), utvidet av Amendment 2 fraexpert-revieweralene tilGUARDED_SKILL_DIRS— den nye skillen hadde ingen vakt i det hele tatt (M18b → 1 rød, egen signatur) — pluss en fail-closed arm som blir rød når et fremtidig subtree-pull bringer en TREDJE skill som ikke er listet. Det verkede eksempelet materialiseres frafrontmatter_verbatimORDRETT (Amendment 3): den linjeorientertefrontmatter-projeksjonen kan ved konstruksjon ikke bære blokkform, så å bygge fra den ville gjort det ulesbare tilfelletabsentog armen ville stått GRØNN mens den beviste det motsatte av sin egen docstring. Eksempelets egen dom erundecided, ikkesurvived— en påstand hvis ene mulige gjendriver var ulesbar ble aldri angrepet. Load-bearing MÅLT: 30 mutasjoner, ALLE røde mot HELE suiten, grønn kontroll 1189 passed / 5 skipped, alle tre byte-fasitene OK ogdemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f); node-ID-supersettet holder strengt (1094 → 1194, 0 fjernet). Per mutasjon: M1 27 · M2 2 · M3 12 · M4 1 · M5 5 · M6 1 · M7 4 · M8 9 · M9a 26+8E · M9 17 · M10 1 · M11a 1 · M11b 2 · M11c 1 · M12 2 · M13 2 · M14 1 · M15 1 · M16 3 · M17 1 · M18a 1 · M18b 1 · M19a 2 · M19b 1 · M20a 2 · M20b 1 · D-b 1 · D-e 5 · D-i 3 · D-l 1. TRE av planens spådde signaturer ble FALSIFISERT av målingen, og de står som målt: M9s «rundturen forblir grønn» (ikke konstruerbar), M12s «exit-koden forblir 1» (mutanten reiser i stedet), og M17s spådde PAR (kun 1 rød —verified_field("a: b", …)runder faktisk trippen, fordi_find_pair_separatortar FØRSTE kolon-mellomrom og verdien beholder sitt eget kolon). Operatørbeslutninger: D1 én dekoder-søm · D2 dispatcher-side kollisjonsregnskap · D3 én linjekilde bak begge lesere · D4 skillen forfattes i commons · D5 ingen ny avhengighet (ingen PyYAML) · D6/B1 identitet =(bundle_id, concept_id), konseptet først. D7-speiling er ÅPEN for dekoder-semantikken, som S3.2 og S4.0. Ærlighets-grenser, uttalt:evidence_for(path, key=…)med en ANNEN nøkkel ennverifiedREISER for enhver verdi som dekoder til oppføringer utenby, forditieravledes ubetinget — MÅLT: alle 11 eksisterende kallsteder bruker defaulten, så parameteren har aldri vært øvet, og det er RAPPORTERT, ikke fikset (utenfor denne ordren);verified_fieldvaliderer ikkeat; og at en LEVENDE modell kaller falsifiseringsskillen godt er ikke bevist (structured-output-grensens klasse). -
Den TREDJE projeksjonen inn i
CostBaselineDERIVERES fra en tabell som alt er i basen — og den nekter heller enn å oppfinne (MAJOR-4, økt 78):cost-baseline.jsoner håndskrevet per prosjekt ogbaseline_from_projecttilhører veg-domenet, så et INGESTERT anbudskorpus kunne navigeres og aldri forankres.okf.derive_cost_baseline(bundle, *, project_id)leser prisskjemaet.project_ider PÅKREVD keyword, ikke lest av basen:run._project_from_bundlefail-faster alt kjøringens id mot basensvalidator-input.json, så en andre lesing her ville vært kø-(p) — og ville dratt en IR-projeksjon inn i en funksjon hvis hele input er en tabell. PREMISSET BLE MÅLT FØR NOE BLE BYGGET PÅ DET, og ordrens to pekere navnga TO ULIKE FORMER:examples/*/expected-bundle/bærer PIPE-tabeller, men hver eneste av dem er csv-/sql-kilt og rendret avrender.render_table— xlsx-stien når ALDRIrender_table. Målt (pandoc 3.10.2, produsentens egen_PANDOC_WRITER = "markdown"+_PANDOC_ARGS = ("--eol=lf", "--wrap=none"), mot produsentens egentests/fixtures/two-line-krav.xlsxog et håndlagt Prisskjema):extract._extract_officekonverterer, oginbox.pygir teksten videre tilrender_inbox_concept(sanitized_text, …)URØRT — resultatet er en pandoc SIMPLE table, der dash-linja definerer kolonne-spennene. En pipe-only leser ville altså vært INERT på nøyaktig det korpuset MAJOR-4 finnes for, og en simple-only leser inert på eksemplene ordren pekte på. Begge leses, av TO skannere over ÉN rollemapping og ÉN tallgrammatikk (_split_frontmatter-formen: ett skann, to lesere), aldri to kopier av semantikken. Span-slicing, ALDRI splitt på whitespace: K2s hele form er tomme priseceller, og en whitespace-splitt kollapser dem og skyver hver senere verdi én kolonne til venstre — en feilmapping som leses som DATA (M16 → 3 røde). Ingen skjønn noe sted: header-vokabularet er lukket og matches EKSAKT (en delstrengregel ville lattEnhetspris eks. mvaog… inkl. mvakreve samme rolle, og leseren ville valgt mellom to priser), tallgrammatikken er lukket og dot-desimal (målt output er1250.0/42.5, så et komma ville kjøpt ingenting og importert1,250s tusenskille-vs-desimal-tvetydighet gratis — et håndskrevet norsk1 250,50er en NEKTET celle, uttalt), og hver tvetydighet er en nekt: ingen kandidat-tabell, mer enn én, to kolonner om samme rolle, to rader med samme kostkode. Delvis priset skjema nekter i SIN HELHET — ikke forsiktighet: en halvderivert base forankrer noen koder mensProvenanceStamp.cost_baseline_anchoredrapportererTrue, og den biten er påkrevd-uten-default nettopp fordi begge defaults ville løyet. Skannet overcontext_files, aldrifiles(MAJOR-3-regelen).CostBaselineDerivationErrorsubklasserValueError(BundleIdMismatch-presedensen) — CLI-ens nekt-tuppel og hostings 400-arm, aldri krasj-kanalen. Wiret bak--derive-cost-baseline, ALDRI stille: ÉN oppløsning irun.pys bundle-arm tjener både full kjøring oglive_dry_run, og nekten PROPAGERER i stedet for å degradere til fil-lasteren (load_mandate-regelen — en kaller som ba om derivasjon og fikk en uforankret kjøring er besvart av en stille nedgradert ordre). Tre CLI-nekter, alle ved NAVN: krever--bundle-dir, refusert i--portfolio(ved navn, ikke ved gjennomfall til--bundle-dir-kravet —--explore-presedensen) og ireport_forbidden(report-modus returnerer FØR nekten, så en utelatelse er et stille DROPP, ikke en nekt — F4-gapet). FIXTUREN er MÅLT, ikke håndskrevet: begge basene undertests/fixtures/er pandocs output ORDRETT, og den uprisede er K2s faktiske pre-award-form — kolonnene OVERLEVER som blanke (målt), så tabellen ER en kandidat og nekten blir den skarpe: leseren identifiserer kolonnene, leser tomme celler og nekter ved navn.validator-input.jsonskrives KUN i testen, aldri inn i den innsjekkede fixturen (measure/claimed_saving_noker menneskets/mandatets).pytest.raises(ValueError)ville IKKE gatet arm (b), og det er MÅLT, ikke resonnert: M17 (drop positivitetsvakten) får mutanten til å reisepydantic_core.ValidationError—isinstance(e, ValueError) is True,isinstance(e, CostBaselineDerivationError) is False— så en løsere arm ville stått grønn mot nøyaktig den mutasjonen den finnes for. Load-bearing MÅLT (tests/test_cost_baseline_derivation_loadbearing.py, 22 armer), 18 mutasjoner alle røde mot HELE suiten + grønn kontroll 1230 passed / 5 skipped (fra 1208/5, supersett, 0 fjernet) og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): M1 detach run-wiringen (2 røde) · M2 fallback ved nekt (1) · M3 hopp over uprisede rader (2) · M4 fabrikkér null (1) · M4b fabrikkér null uten tom-celle-nekten (1) · M17 drop positivitetsvakten (1) · M5 transponer mengde/enhetspris (3) · M6 skannfiles(1) · M7 ta første tabell ved tvetydighet (1) · M8 ta første kolonne ved duplisert rolle (1) · M9 last-write-wins på duplisert kode (1) · M10 utvid tallgrammatikken (1) · M11 drop simple-skanneren (3) · M12 drop pipe-skanneren (7) · M13 detach--bundle-dir-nekten (1) · M14 drop frareport_forbidden(1) · M15 drop fra portefølje-partisjonen (1) · M16 whitespace-splitt (3). Ærlighets-grenser, uttalt: NS 3451 seksjonsrader (kode + overskrift, ingen mengde, inne i et ellers priset ark) er IKKE klassifisert — K2 selv var ikke tilgjengelig å måle her, så et slikt ark NEKTER, og regelen skrives når noen kan måle den ekte formen (en rad som er tom over alle tre kolonner er derimot en blank spacer og hoppes over); stempelet sier AT en kjøring var forankret, aldri HVILKEN av de tre projeksjonene forankret den; den hostede flaten er BEVISST urørt (feltet er ikke i whitelisten, så 4e-halvdelene står uendret); og ingen LEVENDE K2-fil er lest — fixturen er syntetisk, og at produsenten faktisk emitterer denne formen for K2s Prisskjema er MÅLT på pandoc-stien, ikke på K2. -
Den ERKLÆRTE
bundle_id-en er identiteten; monteringsnavnet er en filsystem-tilfeldighet (S7a-3 pkt. 1, økt 81): til 03.09 NEKTETreconcile_bundle_iden base som erklærte en id katalogen ikke bar. Målt mot den første leverte basen som erklærer sin egen id (K2: 618 av 630 konseptfiler + rot-index.md, allek2-trinn1-20260903, levert somK2-bundle-20260903) var følgen at basen ikke kunne åpnes slik den var levert — botemiddelet var å montere den på nytt for hånd, én gang per leveranse, for alltid. Det er en konsument som avviser en produsents legitime output over et katalognavn. PM-beslutning: konsumenten slakker. Erklært vinner (konsept → rot-index → mount, B1s rekkefølge URØRT), avviket REGISTRERES —ResolvedBundleId.mountbærer den overkjørte katalogen,ProvenanceStamp.bundle_id_sourceogDryRunReport.bundle_id_sourcebærer hele oppløsningen inn i artefaktene, ogbundle_id_noticeer ENESTE renderer, med TO kallsteder (returnererNoneved enighet — omisjon, aldri tom rad; omisjonen er selv gatet, M5 → 2 røde inkludert et UAVHENGIG eksisterende vitne itest_navigation_visibility_loadbearing). Stempel-feltet er PÅKREVD uten default avcost_baseline_anchoreds grunn, og her skjerpet:Noneer en VERDI (veg-stien har ingen base), så et utelatt felt måtte bety det samme som «ingen base» — nøyaktig stillheten kravet lukker. Det som FORTSATT nekter er den ekte kollisjonen: to KONSEPTER i ÉN base som erklærer ULIKE id-er (assert_declared_ids_agree, kalt ved hver dør som ÅPNER en base). Rot-index.mder IKKE med i enighets-settet — B1 anvendt en gang til: konsept-slår-index er en PRESEDENS-regel, så en index i utakt med sine konsepter er fallbacken som taper, ikke to konsepter som kolliderer; å folde indeksen inn ville nektet nøyaktig de K2-formede basene slakken finnes for (M3 → 1 rød). Sjekken er en EGEN funksjon, ikke en gren ireconcile_bundle_id: den trenger en navigert bundle, resolveren må forbli REN (_bundle_indexløser id-er for kataloger som kanskje ikke finnes), og separat gir den sin egen mutasjon per dør (M1/M2 → 1 rød hver).explore._bundle_indexløser nå den erklærte id-en, og det er en KONSEKVENS — ikke scope-krype: den bruktePath(raw).namemens dispatcheren bruktereconcile_bundle_id(raw).id; så lenge avviket ble nektet KUNNE de ikke divergere, men med erklært-vinner mynterexplore()approaches som navngir MOUNTET mens dispatcheren ruter på ERKLÆRINGEN — en utforskning hvis eget mandat er uruterbart (M9 → 2 røde, M11 → 1 rød). Uleselig base faller tilbake til basenavnet i stedet for å reise, fordi to av_bundle_indexs egne armer konfigurerer kataloger som ikke finnes og forventer en ID-feil, ikke en I/O-feil — ingenting utvides: den indeksen svarer på hvilke id-er som kan NAVNGIS, og en base ingen kan lese nektes et øyeblikk senere av den døra som faktisk åpner den. Load-bearing MÅLT (tests/test_bundle_id_slack_loadbearing.py, 13 armer), ti mutasjoner alle røde mot HELE suiten + grønn kontroll 1243/5 og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): M1 detach gaten irun_project(1) · M2 detach den iread_bundle(1) · M3 fold indeksen inn i enighets-settet (1) · M4 gjeninnfør mount-nekten (9) · M5 rendereren skriver alltid linja (2) · M6 detach CLI-utskriften (1) · M7 konstant stempel-wiring (1) · M8 konstant dry-run-wiring (2) · M9_bundle_indextilbake til mountet (2) · M11 dispatcheren tilbake til mountet (1). TRE ARMER Itest_bundle_id_reconciliation_loadbearingble SKREVET OM, ikke slettet — (e)/(f)/(j) pinnet nekten beslutningen fjernet; (j) ble SKARPERE enn den den erstattet (erklært id ruter, mountet nektes — to implementasjoner som skiller seg i BEGGE halvdeler, ikke i en exit-kode). Ærlighets-grenser, uttalt: utenconcept_namesvarer rot-index.md, så en base hvis index erklærer X mens konseptene erklærer Y løser til X (B1s rekkefølge, urørt); portefølje-armen er BEVISST IKKE wiret — der erbundle_id_sourceNoneved konstruksjon (intet referanse-prosjekt setterbundle_dir), så en tredje utskrift ville vært død kode; det er en ANNEN avgjørelse enncost_baseline_anchoreds, som wiret nettopp den armen DEFENSIVT og drev den fra en craftedPortfolioResult, og den står her fordi stillhet om asymmetrien er det eneste gale svaret. Og dispatcherens «to baser deler id»-nekt er NYLIG NÅBAR — den krevde før to monteringer med samme basenavn, nå kolliderer to ULIKT navngitte kataloger som erklærer samme id. Kontrakt:docs/okf-konsum-kontrakter.md § 3.1. -
Stigen har tre trinn:
list_bundles→read_bundle→read_dir→read_file(S7a-3 pkt. 2, økt 81): MAJOR-3 bygderead_bundleom fra HELE basen til én oppføring per konseptfil, og på de tre eksempelbasene var det −77…91 %. Så kom det første EKTE korpuset: K2 navigerer til 629 konsepter bak 478 nestede indekser, og en listing av 629 koster 42 761 o200k-tokens som rir i 7 av 12 prompter = 89 % av alle prompt-tokens. Bindingen holdt asymptotisk og priset likevel hele korpuset, fordi prisen på å finne ut HVA en base inneholder var satt av hvor mye den inneholder. De 478 indeksene ble dessuten BYGGET av navigasjonen, KONSUMERT av den og så flatet ut — agenten så 629 søsken og fikk aldri vite at korpuset hadde en form. MÅLT ETTER: rotnivået er 3 954 tegn / 1 495 tok, listing-tokens 307 573 → 12 595, og utforskningens prompt-tokens 343 826 → 49 225 (−86 %). BEFORE og AFTER er kjørt i SAMME økt med samme kode (BEFORE er en mutasjon), og BEFORE reproduserer S7a-2s publiserte tall til 0,03 % — den kjent-positive kontrollen på instrumentet.okf.directory_listinger ENESTE renderer og begge verktøy ER den på hvert sitt nivå; to kopier av en listing-regel ville drevet til to svar om én base (kø-(p)). ET PREMISS I ORDREN BLE FELT FØR NOE BLE BYGGET PÅ DET:context_fileshar ALDRI holdt hierarkiet tilbake — hverBundleFile.nameer allerede den fulle bundle-relative stien, så treet var utledbart fra navnene; det var RENDERINGEN som flatet det ut. Dét er grunnen til atbundle_contextog begge nav-goldenene er BYTE-IDENTISKE etter endringen (ordrens eget krav), gratis og ikke av forsiktighet. Kataloger utledes av STIER, aldri avindex.md(en nestet indeks er navigasjon, ikke innhold), og listingen bygges avcontext_files, ALDRIfiles— en katalog-TELLING frafilesville reklamert for dokumenter navigatøren ikke får se (N2 → 7 røde). Hver sti er BUNDLE-RELATIV, altså brukbar ordrett som neste kalls argument — en nivå-relativ form måtte komponeres av en modell, og en sti som aldri fantes er verre enn ingen sti (_index_excerpt-regelen, ett trinn opp; N7 → 1 rød).documentspå en katalog-oppføring er antallet i hele SUBTREET — hva subtreet holder, ikke hva ettread_dirreturnerer — og beskrivelsen sier hvilken av de to det er. Ukjent sti NEKTES ved navn (BundlePathNotFound,ValueError-subklasse somBundleIdMismatch): en tom listing er umulig å skille fra en katalog som finnes og er tom (N5 → 1 rød). Verktøybeskrivelsene og navigatørens instruksjon flyttet i SAMME commit — en beskrivelse som lyver om kroppen ER modellens instruks (Fase 3-klassen; N9 → 1 rød). TO EKSISTERENDE ASSERTS VILLE BLITT VAKUØSE I STILLHET og er styrket:len(payload)er nå antallet NØKLER (tre, alltid), såtest_read_bundle_cost_loadbearings størrelses-arm talte nøkler, og write-frihets-armen itest_explore_loadbearingkalte ikke det nye verktøyet i det hele tatt. AVVIK fra ordren, uttalt og målt: ordren binder «K2 < 1 500 tegn» — K2 kan ikke være en testavhengighet (utenfor repoet; MAJOR-3-gaten har samme begrensning), og tallet er ikke oppnåelig: rota bærer 39 identifiserbare oppføringer og måler 3 954 tegn. Gaten binder derfor 1 500 tegn per listing over basene den KAN se, pluss egenskapen som ga fallet (kostnaden følger oppføringer på ETT nivå, ikke dokumenter i basen), med en FLAT kontroll over 5× taket — uten den ville en grønn binding like gjerne betydd at fixturen var liten. Ordrens ANDRE binding («read_dirover største katalog bundet») er MÅLT med den SHIPPEDE funksjonen over alle 478 nivåer i K2: verste nivå noe sted er 6 073 tegn / 2 094 tok (65 underkataloger) = 4,9 % av den flate formens 42 761 — dyrere enn rota fordi hver sti er bundle-relativ, altså den målte prisen på at en sti er brukbar ORDRETT i neste kall. Load-bearing MÅLT (tests/test_hierarchical_navigation_loadbearing.py, 9 armer), ni mutasjoner alle røde mot HELE suiten + grønn kontroll 1252/5 og golden BYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): N1 reverter sømmen (4) · N2 bygg frafiles(7) · N3 bundet men VAKUØST tom (12) · N4 droppchars(5) · N5 ukjent sti blir en tom listing (1) · N6read_dirikke registrert (6) · N7 nivå-relative navn (1) · N8 katalog-tellingen konstant (2) · N9 instruksjonen beskriver den gamle stigen (1). Ærlighets-grenser, uttalt: dette er ikke «−86 % for enhver kjøring» (en navigatør som stiger ned k nivåer betaler k listinger); at en LEVENDE modell navigerer bedre med en struktur enn med 629 flate dokumenter er IKKE bevist (structured-output-grensens klasse); multiplikatoren gjelder dette manuset; ognavigate_bundlekalles fortsatt per verktøykall (I/O, ikke tokens — ikke målt). Måling:docs/2026-09-03-hierarkisk-navigasjon-k2.md. -
Sporet sier HVILKE dokumenter navigatøren åpnet, ikke bare hvilken base (S7a-3 pkt. 3, økt 81):
ExplorationToolRecorderregistrerte NAVN +bundle_idi kall-rekkefølge (MAJOR-1). Over de tre eksempelbasene holdt det — 39 konsepter, og en kjøring som åpnet to av dem etterlot et spor en operatør kunne resonnere om. Over K2 gjør det ikke: 629 konsepter, ogtool_callsleserread_file, k2to ganger, så hvilke to av 629 kan ikke leses ut av leveransen i det hele tatt — økt 77 og 81 måtte begge instrumentere kjøringen for hånd for å svare.ToolCall.pathregistreres forread_fileOGread_dir; et spor som navnga dokumentene men ikke katalogene ville sagt hvor en kjøring ENDTE uten å si hvordan den kom dit. RESULTATET registreres fortsatt ALDRI, og det er MAJOR-1s beslutning gjentatt nettopp fordi pkt. 3 er øyeblikket den var lettest å oppheve: resultatet ER basens innhold, målt til 89 % av hver prompt-token i en K2-kjøring.""for et verktøy som ikke tar argumentet —bundle_ids egen regel anvendt på det andre feltet; en verdi oppfunnet for et argument ingen sendte er falsk attribusjon. ÉN argumentleser for begge felt (_string_argument, kø-(p)): to kopier av «les denne nøkkelen ut av begge formeneFunctionInvocationContexttillater» ville stått fritt til å være uenige om hva et fraværende argument betyr. Load-bearing MÅLT (tests/test_tool_call_path_loadbearing.py, 5 armer), fire mutasjoner alle røde mot HELE suiten + grønn kontroll 1257/5 og golden BYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f): P1 detach registreringen (3) · P2 dropppathfratrace_payload(3, inkludert et EKSISTERENDE vitne) · P3 koerser en ikke-streng til en etikett (2) · P4 les kun Mapping-formen (2). -
Forslaget kan OPPSTÅ fra kommisjonen og basens eget prisskjema — og ordrens diagnose var feil (S7b-forberedelse, økt 82): ordren sa at forslaget *leses fra en håndskrevet
validator-input.json. Symptomet er ekte — en base uten fila nekter medFileNotFoundErrorfør første modellkall — men diagnosen ble felt FØR noe ble bygget på den:SavingsProposalhar ALLTID blitt konstruert avgenerate._parse_irfra MODELLENS svar; fila er en fasit VED SIDEN AV kjørestien, påkrevd kun som prosjektets IDENTITET. Det skillet avgjorde at S7b er to sømmer, ikke én, og at bare den ANDRE er bygget her. Nevneren: tre lesere, ikke én —run.py:453(hver bundle-kjøring),verdicts.py:507(kun med ikke-tom store) ogrun.py:1662, dispatcherens rutingsnøkkel, som bevisst ikke tarproject_idfordi den leser den derfra. Å gjøre IR-projeksjonen valgfri er den ANDRE sømmen: MÅLT, dokumentert, IKKE bygget. Arbeidsdelingen er hele designet: eksperten sier HVA (Approach.label→measure, VERBATIM), HVILKE linjer (affected_codes) og HVOR MYE (claimed_saving_nok); dokumentet sier MENGDE og PRIS (derive_cost_baseline, MAJOR-4).candidate_from_approachoppfinner ingenting og nekter ved NAVN på alle tre gap. Anslaget bor påApproach, aldri påMandate—settles egen regel: tilnærminger er ALTERNATIVER og summeres aldri, så ett tall på mandatnivå ville vært tvetydig over N; og det er IKKE kjøringens MÅL (contracts.GoalContracteier nettopp ett sådant), hvilket står skrevet der feltet innføres, ellers leses det som den(p)-driften modulen forbyr. Null modellkall er STRUKTURELT:run.evaluate_mandate_candidateser SYNC, så den kan ikke awaite et chat-kall — ingen mutasjon av kroppen kan stille innføre ett; CLI-armen asserterer det likevel ATFERDSMESSIG (_default_factorypatchet til å raise), fordi rc 0 alene også er utfallet til en dør som gjorde ingenting.allow_own_proposalsfår ennot_evaluated-RAD, ikke en nekt: raden kan ikke fylles uten en modell, men å utelate den gjør den uskillbar fra en tilnærming ingen bestilte (ApproachOutcomes egen regel), og å nekte hele kjøringen ville vært feil andre veien — feltet defaulter tilTrue. Fixturen brukes URØRT, og dét er armens poeng:test_cost_baseline_derivation_loadbearingmå kalle_runnable()og skrive envalidator-input.jsoninn i en kopi førrun_projectser på den. Load-bearing MÅLT (tests/test_proposal_from_mandate_loadbearing.py, 18 armer), seksten mutasjoner, FEMTEN røde mot HELE suiten + grønn kontroll 1275/5 (fra 1257, supersett, 0 fjernet) og goldendemo-transcript.stdoutBYTE-UENDRET (shasum -a 1=ea8c534773acdbe41ae68f2c55724d69aaf8be4f, INNHOLD — ikke git-blob): M1 detach CLI-dispatchen (1) · M2 fabrikkér et anslag (2) · M3 default kodene til hele skjemaet (1) · M4 toler en ukjent kode (1) · M5 bygg lazily (1) · M6 utelat own-proposal-raden (1) · M8 detach--mandate-nekten (1) · M9 detach--derive-cost-baseline-nekten (1) · M10 dropp fra portefølje-partisjonen (1) · M11 dropp frareport_forbidden(1) · M12measureer ikke ekspertens ord (1) · M13 baseline-rekkefølge i stedet for ekspertens (1) · M14 rut på mount-navnet (1) · M15 fabrikkér usikkerhetsbånd (1) · M16 detach enighets-gaten ved DENNE døra (1).evaluate_mandate_candidateser den TREDJE døra som ÅPNER en base, og den fikk sitt EGET vitne (M16): S7a-3s rad enumererer dørene med vilje («separat gir den sin egen mutasjon per dør»), fordi en uvitnet kopi kan regrere ALENE mens de to andre står grønne.project_idNARROWES, aldri defaultes:args.project_id or ""ville nåddderive_cost_baselineog myntet enCostBaseline(project_id="")— en fabrikkert identitet, nøyaktig formencost_baseline_anchoreder påkrevd-uten-default for å forby; unåbar i dag, så det er en assert og ikke en default som stille er uenig med guarden over. TRE MUTASJONER FALSIFISERTE TESTEN FØRST (repoets vakuøs-gate-klasse, TRETTENDE til FEMTENDE gang): (i) M5 sto GRØNN — armen asserterte kunpytest.raises, og BEGGE implementasjoner reiser mens ingen rad når kalleren uansett, så de er uskillbare utenfra; det er økt 57s regel («en nekt etter forbruket ser identisk ut ved exit-koden») anvendt på CBC-solves, og testen TELLER nå solves med en kontroll som beviser at telleren beveger seg. (ii) M14 sto GRØNN — armen bruktef"not-{declared}", som matcher verken mount eller erklæring, og fixturene erklærer ingenbundle_id(S7a-3 målte null^bundle_id-treff undertests/), så de to SAMMENFALLER der; den nye armen bygger en base som erklærer en id ulik katalognavnet og asserterer BEGGE halvdeler. (iii) M16s FØRSTE arm erklærte de to id-ene på rot-index.mdog den ene konseptfila, og sto GRØNN — S7a-3 holdt rot-indeksen UTENFOR enighets-settet med vilje, fordi konsept-slår-index er en PRESEDENS-regel: en index i utakt med sine konsepter er fallbacken som taper, ikke to konsepter som kolliderer. Armen bruker nå TO konseptfiler. ÉN MUTASJON FORBLIR GRØNN, OG DET ER EN ÆRLIGHETS-GRENSE — IKKE EN GATE: M7 (døm UTEN baselinen) er strukturelt uobserverbar, fordi kandidaten er BYGGET fra baselinen og stage 0 derfor avstemmer med 0 % avvik ved konstruksjon;baseline=står som en DEFENSIV, uvitnet søm (budget_stop-presedensen), ikke som noe en test holder. Flere ærlighets-grenser, uttalt:assumptionser TOM (et bånd kan ikke avledes fra én pris), så Monte Carlo er degenerert (P10 == P50 == P90) mens stage 3 fortsatt rapporterer persentiler — det som binder er stage 0, stage 2/4b og pydanticsclaimed <= total;measureer ikke bare prosa, men stage 5sMETHOD_CAPS-oppslagsnøkkel, så en ekspert-label treffer metode-cap-en kun om den ER et registrert metodenavn; den hostede flaten er BEVISST urørt (feltet er ikke i whitelisten, så 4e-halvdelene står uendret); og ingen LEVENDE K2-fil er lest — fixturen er syntetisk, som i MAJOR-4. MÅLT, RAPPORTERT, IKKE FIKSET (utenfor ordren):--mandateselv står IKKE ireport_forbidden, så--report --ledger X --mandate YDROPPER kommisjonen i stillhet — F4-gapets klasse, på et flagg som er eldre enn denne ordren. Måling:docs/2026-09-03-forslag-fra-mandat.md. -
STATE.md er local-only (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet.
-
Prosess: Voyage-plugin (
/trekbrief → /trekplan → /trekexecute → /trekreview) per større fase.
Communication patterns
When linking to local files in responses, use named markdown links — [Human-friendly name](file:///absolute/path), never bare file:// URLs or autolinks <file://...>, always absolute paths (never ~/ or relative), one bullet per file when there are several. (Bare file:// URLs render only the first as clickable across multiple lines; named links stay independently clickable.)