docs(f16): the 1.18.0 assessment measured -- 0 of 19 forms moved, three features assessed and none built

The F15 report's shape repeated: result table, denominator discipline, one
command per claim. What the measurement changed against the order's own
framing:

- orchestrations CANNOT be lifted (1.1.1 is still the head on PyPI), so F15's
  "the two floors are lifted together, there is no partial bump" is measurably
  weaker after F16 -- and eight of the nineteen probe checks live in that
  unmoved package, which is a property of the denominator, not a strength of
  the probe.
- foundry/openai were NOT forced up; the coupling the order read belongs to the
  LATEST releases, not the pinned 1.8.2. They were lifted for a measured reason
  instead (two BREAKING bullets name core AND foundry in the same line).
- ONE of the order's transcriptions deviated from the source: #8219 lazy
  loading is foundry/foundry-hosting/openai -- NOT core. Consequence, not
  pedantry: had the floors stayed at 1.8.2, the change the order named as the
  prime suspect for golden stderr would never have reached po at all.
- (a) touches NO U row. The wall-clock timeout is B4's own sketch word and G1;
  and the primitive is `max_duration_seconds` degrading gracefully via
  `budget_state["truncated"]` + a log line -- NOT a typed stop reason, so it
  does not satisfy B4's "every breach -> a structured event, never a silent
  stop". Recommendation: do not adopt it as B4's half. STATE's prohibition
  stands, untouched.
- (b) does not move U13: `approval_mode` is 0 in src/ and 0 in tests/ (102 in
  the venv). #7988 hardens the cooperative-marker path G4 already refused.
- (c) does not break: po's own parameters are typed `Sequence[Any] | None` and
  all seven callsites pass lists, so sequence-only inputs are the only form po
  can produce. 74 passed across the five middleware-bearing suites; no fix was
  needed and none was made.

My own probe was WRONG FIRST and that is written down: five checks read
CHANGED/MISSING in BOTH versions because my queries sliced a Protocol stub,
counted `self`, and demanded two names be adjacent. Running it against BOTH
versions is what made the instrument failure visible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-12 17:18:46 +02:00
commit 9f14c642c8
2 changed files with 524 additions and 1 deletions

View file

@ -0,0 +1,523 @@
# F16 — MAF-pinnen løftet 1.16.0 → 1.18.0, og tre 1.17/1.18-funksjoner målt mot U-radene
> **Ordre:** `20260912T144902Z-9152424098-from-.claude` (operatørbeslutning 12.09: ja til F16 før
> stresstesten; veivalg **D = d1**). **NOK 0 — ingen betalt kjøring, ingen modellkall.**
> **Grunnlag:** [F15](2026-09-02-f15-maf-pinnen.md) (prosedyren denne økten gjentar) og
> [P12 — MAF-gjelden](2026-09-11-p12-maf-gjeld.md) (rad-for-rad-tellingen den bygger på).
> Hvert tall under kommer fra en kommando kjørt i denne økten. **Konformans er gulvet, aldri
> beviset.**
## 0. Resultat
| | |
|---|---|
| `agent-framework-core` | **1.16.0 → 1.18.0** (gulv `>=1.16.0,<2``>=1.18.0,<2`) |
| `agent-framework-foundry` | **1.8.2 → 1.13.0** (gulv `>=1.8.2``>=1.13.0`) |
| `agent-framework-openai` | **1.8.2 → 1.14.3** (gulv `>=1.8.2``>=1.14.3`) |
| `agent-framework-orchestrations` | **1.1.1 → 1.1.1 — UENDRET**, fordi 1.1.1 fortsatt er siste utgivelse (gulv `>=1.1.1` urørt) |
| Nye/endrede transitive | **ingen nye pakker**`uv lock` rapporterte kun de tre oppdateringene, 84 pakker før og etter |
| Vakten FØR bumpen | **2 failed, 2 passed** (Iron Law — rød først) |
| Vakten ETTER bumpen | **4 passed** |
| Private/ugaranterte former | **16 former · 19 sjekker mekanisk · 0 endret** (+ form 17 re-målt ved KJØRING: uendret) — se § 2 |
| Testsuite | **1577 passed / 5 skipped** — identisk med basislinjen målt på DENNE HEAD før bumpen; 0 tester tapt, 0 lagt til |
| `tests/test_async_plan_review_loadbearing.py` | **19 passed** (park → spørsmålsfil → svarfil → resume, egen interpreter) |
| Golden `demo-transcript.stdout` | **BYTE-UENDRET**, `ea8c534773acdbe41ae68f2c55724d69aaf8be4f` |
| Golden `demo-transcript.stderr` | **BYTE-UENDRET**, `ede3e2f685ce6a14ad9888e9de421d1a66f6c611` — fortsatt TO linjer |
| `uv run ruff check .` | **All checks passed!** (ekskl. `scratchpad/`, se § 6) |
| `uv run ruff format --check .` | **211 files already formatted** (ekskl. `scratchpad/`) |
| `uv run mypy src` | **Success: no issues found in 37 source files** |
| De tre funksjonene | **MÅLT, IKKE BYGGET** — § 4 (a)/(b)/(c)/(d) |
**`shasum -a 1` over fil-INNHOLDET, aldri `git hash-object`.** De to er ulike av konstruksjon (git
hasher over `blob <len>\0` + innhold); se CLAUDE.mds egen rad om dette.
## 1. PyPI-målingen, som avgjorde hvilke gulv som KUNNE flyttes
Målt med PyPIs JSON-API (`curl`), `info.version` + `info.requires_dist`, og for de pinnede
versjonene `…/pypi/<pakke>/<versjon>/json`:
| pakke | låst før | siste på PyPI | publisert | egne `agent-framework`-krav (siste) | krav i den PINNEDE 1.8.2 |
|---|---|---|---|---|---|
| `agent-framework-core` | 1.16.0 | **1.18.0** | 2026-09-10T09:28:54Z | — | — |
| `agent-framework-foundry` | 1.8.2 | **1.13.0** | 2026-09-10T09:28:59Z | `core<2,>=1.17.0`, `openai<2,>=1.14.2` | `core<2,>=1.9.0`, `openai<2,>=1.8.2` |
| `agent-framework-openai` | 1.8.2 | **1.14.3** | 2026-09-10T09:29:06Z | `core<2,>=1.17.0` | `core<2,>=1.9.0` |
| `agent-framework-orchestrations` | 1.1.1 | **1.1.1** | 2026-08-21T23:22:41Z | `core<2,>=1.15.0` | (samme) |
Core 1.17.0 ble publisert 2026-09-03T09:53:33Z. PMs tall er reprodusert **eksakt** på alle fire
pakker; ingen avvik.
**TO av ordrens egne premisser ble FELT av målingen, og målingen vinner.**
**(i) `orchestrations` kan ikke løftes — det finnes ingenting å løfte det til.** 1.1.1 (2026-08-21)
er fortsatt hodet på PyPI, og kravet `core<2,>=1.15.0` er tilfredsstilt av 1.18.0. F15s
`pyproject`-kommentar sa «de to gulvene løftes SAMMEN (F15) — det finnes ingen delvis bump». Det var
sant om F15s bump. Etter F16 er det **målt svakere**: core kan løftes uten at orchestrations kan, og
kommentaren sier nå det. Konsekvensen er strukturell for § 2: åtte av de nitten sjekkene bor i
`agent_framework_orchestrations`, altså i en pakke som **ikke flyttet**, og de kan derfor ikke
avvike over denne bumpen. Det står som en egenskap ved nevneren, ikke som en styrke ved proben.
**(ii) `foundry` og `openai` ble IKKE tvunget opp.** Ordren leste koblingen av de SISTE
utgivelsene (begge krever `core>=1.17.0`), men den PINNEDE 1.8.2 krever bare `core<2,>=1.9.0`
målt. Resolveren beholdt derfor 1.8.2 mot core 1.18.0 og løste rent. **Konfigurasjon A** (core
1.18.0 + foundry/openai 1.8.2) ble faktisk kjørt, og var grønn på vakten (4), de 19
async-plan-review-testene og golden-transkriptet (4) — 27 tester pluss en ren `backends`-import.
Det står her i stedet for å bli skjult.
**De ble likevel løftet, av en annen og målt grunn:** to av 1.17/1.18s BREAKING-punkter navngir
**core OG foundry i SAMME punkt** (`#7918` sequence-only middleware-inputer, `#8127`
`SecretString`). Et 1.9.0-æra foundry mot en 1.18.0 core er da halvparten av en koordinert endring
— nøyaktig «importerer fortsatt, men semantikken har flyttet i stillhet»-klassen F15 § 4 målte og
som er hele grunnen til at denne pinnen er en tripwire. Gulvene er satt til det `uv sync` **faktisk
installerte**, målt etter synken med `importlib.metadata.version`, aldri gjettet før:
```
core 1.18.0 · foundry 1.13.0 · openai 1.14.3 · orchestrations 1.1.1
```
(`agent_framework.__version__` er en `0.0.0`-plassholder og er ikke brukt noe sted — guardens egen
docstring sier hvorfor.)
## 2. Nevner-disiplin — fire tall, aldri «19/19»
**16 distinkte private/ugaranterte MAF-former leaner po på · 19 sjekker mekanisk av proben ·
0 av de 19 endret seg · form 17 (checkpoint-antallet per park) er IKKE i proben og ble re-målt ved
KJØRING, også uendret.**
Formen er F15 § 2s, og den er gjentatt med vilje. `pyproject`-kommentaren sa tidligere «de 19
private formene»; **19 er SJEKKE-tallet, ikke FORM-tallet**, og en setning som sier «19/19» uten å
navngi nevneren gjentar nøyaktig feilen F15 § 2 rettet. Inventaret er F15s, derivert fra repoets
egne siteringer (`grep -rnoE "_[a-z_]+\.py:[0-9-]+" src/` pluss hver MAF-form en søm overstyrer
eller konstruerer). Instrumentet er efemert og bor i privat scratch, aldri i repoet; det kjørte mot
**BEGGE** versjoner (core-wheelene 1.16.0 og 1.18.0 lastet ned og pakket ut side om side), så
«før»-kolonnen er **re-kjørt, ikke sitert**.
| Form | eier | 1.16.0 | 1.18.0 |
|---|---|---|---|
| P1 `BaseChatClient._inner_get_response` kw-only (messages/stream/options) | core | OK | OK |
| P2 `BaseChatClient._build_response_stream` | core | OK | OK |
| P3 `MagenticPlanReviewRequest` (allowlist-streng) | orch 1.1.1 | OK | OK |
| P4 `MagenticPlanReviewResponse` (allowlist-streng) | orch 1.1.1 | OK | OK |
| P5 strengt stall-sjekk `stall_count > …max_stall_count` | orch 1.1.1 | OK | OK |
| P6 reset-sjekk `reset_count >= …max_reset_count` | orch 1.1.1 | OK | OK |
| P7 `next_speaker not in …participants`-fallback | orch 1.1.1 | OK | OK |
| P8 nøyaktig ÉN `ctx.request_info` i `_magentic.py` | orch 1.1.1 | OK (1) | OK (1) |
| P9 `is_request_satisfied` på ledgeren | orch 1.1.1 | OK (8) | OK (8) |
| P10 `FileCheckpointStorage.list_checkpoints` svelger blokkert type → `logger.warning` | core | OK | OK |
| P11 `get_latest` velger på timestamp · P11b `allowed_checkpoint_types=` | core | OK | OK |
| P12 runner nekter restore ved graf-signatur-avvik | core | OK (2 steder) | OK (2 steder) |
| P13 `reached max_rounds`-meldingen i group-chat-orkestratoren | orch 1.1.1 | OK | OK |
| P14 `extend_instructions` to-arg GA-signatur (`_sessions.py`) | core | OK | OK |
| P15 console-exportere gatet på flagget · P15b `ENABLE_INSTRUMENTATION` | core | OK | OK |
| P16 `ExperimentalWarning` emitteres ved FØRSTE BRUK (`_add_runtime_warning`) | core | OK | OK |
| *(støtte)* `WorkflowCheckpoint.pending_request_info_events` deklarert — feltet F15s fiks flyttet vakten over på | core | OK | OK |
| **Form 17 — checkpoint-filer per park, målt ved KJØRING** | core | 2 (F15) | **2, og nøyaktig ÉN bærer forespørselen** |
**P12 fortjener en presisering:** po siterer `_runner.py:275-279`
(`explore.py:1374` og `:1996`). **Linjenumrene har flyttet seg fire linjer** i 1.18.0 — sitatet er
ikke lenger presist — men FORMEN proben sjekker
(`self._graph_signature_hash != checkpoint.graph_signature_hash`) står på to steder i begge
versjoner. Det er grunnen til at proben sjekker formen og ikke linja; siteringene i `explore.py` er
BEVISST ikke rettet, fordi de er kommentarer om hvor premisset ble lest, og en oppdatering ville
krevd at hver framtidig bump redigerte prosa i stedet for å måle.
**Min egen probe var FEIL FØRST, og det er nevner-disiplin anvendt på instrumentet.** Første
versjon rapporterte **CHANGED/MISSING i BEGGE versjoner** på fem sjekker (P5, P6, P10, P11, P14).
Ingen av dem hadde endret seg: spørringene mine var gale.
- **P10/P11:** regexen sliced `CheckpointStorage`-PROTOKOLLEN, hvis kropp er en bar `...`. Formen
bor i `FileCheckpointStorage` — klassen po faktisk konstruerer.
- **P14:** «to-arg» i F15 betyr to argumenter BESIDES `self`. Min versjon telte `self` og fikk 3.
- **P5/P6:** komparasjonen leser
`self._magentic_context.stall_count > self._manager.max_stall_count`; regexen min krevde at de to
navnene var naboer.
Et «fant ingenting» fra feil spørring er ikke et faktum (Verifiseringsloven ansikt 4). Hadde
kolonnene blitt lest som funn, ville F16 rapportert fem falske endringer; hadde bare
«før»-kolonnen blitt kjørt, ville de vært usynlige. **Å kjøre proben mot BEGGE versjoner er dét som
gjorde instrumentfeilen synlig** — fem rader like i begge kolonner er et instrument som ikke måler,
ikke en form som forsvant.
**Kjent-positiv er OBLIGATORISK, og denne bumpen har en sterk en.** Proben må kunne oppdage en
endring, ellers måler den ingenting:
| kontroll | 1.16.0 | 1.18.0 | diskriminerer? |
|---|---|---|---|
| **KP1** `max_duration`/`stop_reason`-tokens i `_tools.py` (`#7772`, ny i 1.18.0) | **0** | **24** | **JA — 0 → 24** |
| **KP2** antall `Sequence[` i `_middleware.py` (`#7918`) | 36 | 39 | ja (svakere: en telling, ikke en form) |
| KP3 `_agent_hooks.py` finnes (ekstraen fjernet i 1.17.0) | present | present | nei |
| KP4 `@experimental`-markører i `_skills.py` | 3 | 3 | nei |
| KP5 `SkillsProvider` uten `@experimental` | no-marker | no-marker | nei |
| KP6 `MiddlewareFailure` (F15s kjent-positiv) | YES | YES | **nei lenger** |
| KP7 `FileSkillsSource` finnes | YES | YES | nei |
**KP1 er F16s kjent-positiv.** **KP6 er F15s, og den er FORKASTET her på samme grunnlag F15 forkastet
`_compaction.py`:** `MiddlewareFailure` kom i 1.15.0, altså før begge kolonnene, og teller YES i
BEGGE — den diskriminerer ingenting over DENNE bumpen. En kontroll som var gyldig i forrige bump er
ikke automatisk en kontroll i denne. KP3KP5 og KP7 er stabilitets-observasjoner, ikke kontroller,
og er merket som det.
**Ærlighets-grensen fra F15 gjelder uendret:** proben sjekker **FORMER** — statiske egenskaper ved
kilden. F15s mest konsekvensrike funn var en egenskap ved **KJØRINGEN** (hvor mange checkpoints en
park skriver), og det var usynlig for enhver form-probe uansett hvor mange former den teller. **En
form-probe er gulvet, aldri beviset — suiten er beviset.** Nevneren skal leses som «19 sjekker over
16 former», ikke «alt som kunne endre seg er sjekket»; ingenting her påstår at 16 er uttømmende.
**Og åtte av de nitten sjekkene bor i en pakke som ikke flyttet** (§ 1 (i)), så den reelle
mekaniske nevneren for core-deltaet er **11 sjekker**.
## 3. Goldenene og de fire risikoradene — målt, ikke antatt
Release-notatene er hentet i denne økten via GitHubs release-API og siteres med URL og versjon:
- <https://github.com/microsoft/agent-framework/releases/tag/python-1.17.0> — publisert
`2026-09-03T09:49:35Z` (målt; matcher PM)
- <https://github.com/microsoft/agent-framework/releases/tag/python-1.18.0> — publisert
`2026-09-10T09:23:52Z` (målt; matcher PM)
**ÉN AVSKRIFT AVVEK, og avviket rapporteres:** ordren tilskrev lazy-loading-punktet (`#8219`) til
**core + foundry + openai**. Kilden sier **`agent-framework-foundry`, `agent-framework-foundry-hosting`,
`agent-framework-openai`** — **core er IKKE på lista**. Det er ikke pedanteri: hadde
`foundry`/`openai` blitt stående på 1.8.2 (konfigurasjon A, § 1 (ii)), ville endringen ordren
utpekte som hovedmistenkt for golden `stderr` **ikke nådd po i det hele tatt**. Den nådde po kun
fordi gulvene ble løftet. To andre småavvik, uten konsekvens: `#8127` navngir **ti** pakker (ordren
sa «core+foundry+openai m.fl.»), og checkpoint-punktet er ÉTT punkt med **tre** PR-numre
(`#7798`, `#7948`, `#8215`), ikke ett.
### Rad 1 — `SecretString` (1.18.0, BREAKING)
> «**agent-framework-anthropic**, **agent-framework-azure-ai-search**, **agent-framework-azure-cosmos**,
> **agent-framework-bedrock**, **agent-framework-copilotstudio**, **agent-framework-core**,
> **agent-framework-foundry**, **agent-framework-gemini**, **agent-framework-mem0**,
> **agent-framework-openai**: [BREAKING] Make `SecretString` a masked value wrapper rather than a
> `str` subclass and align provider credential handling ([#8127])»
**Treffer IKKE po, og det er målt.** `SecretString` = **0** treff i `src/` + `tests/`; **27** i
installert core, **4** i installert foundry 1.13.0 — og alle fire foundry-treffene er i
`_embedding_client.py`, på `api_key`-typingen. `FoundryChatClient.credential` er typet
`AzureCredentialTypes | AzureTokenProvider | None` (`_chat_client.py:168`), altså et
credential-OBJEKT fra `azure.core.credentials`. po sender nettopp et objekt
(`backends.py:150`: `ManagedIdentityCredential() if _is_hosted() else AzureCliCredential()`) og
aldri en api-nøkkel-streng. `import portfolio_optimiser.backends` → rc 0; witness
`tests/test_hosted_backend_loadbearing.py`**8 passed**.
### Rad 2 — lazy loading av Foundry/OpenAI (1.18.0)
> «**agent-framework-foundry**, **agent-framework-foundry-hosting**, **agent-framework-openai**:
> Lazily load Foundry and OpenAI integrations to avoid unnecessary import-time dependencies
> ([#8219])»
Dette er klassen endring som flyttet golden `stderr` i F15 (der sluttet MAF å sende
`ExperimentalWarning` ved import). **Målt: den flyttet ingenting.** Demoen kjørt live etter bumpen
skriver **to** linjer på stderr (blanklinje + `arbeidskopi:`), byte-for-byte det goldenen bærer
gjennom den **UENDREDE** normalisereren, og `stdout` er **61 linjer** — F15s tall.
```
shasum -a 1 tests/golden/demo-transcript.stdout → ea8c534773acdbe41ae68f2c55724d69aaf8be4f (FØR og ETTER)
shasum -a 1 tests/golden/demo-transcript.stderr → ede3e2f685ce6a14ad9888e9de421d1a66f6c611 (FØR og ETTER)
```
**Ingen regenerering, altså ingen beslutning å ta.** `test_normalisation_does_not_mask_a_new_warning`
er grønn, og `tests/test_golden_transcript_loadbearing.py`**4 passed**. Span 1
(`site-packages`-maskeringen) er fortsatt beholdt og fortsatt ubebodd.
### Rad 3 — checkpoint-validering ved lagring (1.18.0)
> «**agent-framework-core**: Finalize abandoned functional-workflow streams, restore fan-in edge
> buffers, and validate checkpoint state when saving ([#7798], [#7948], [#8215])»
**Form 17 er re-målt ved KJØRING, ikke ved import**, fordi det er en egenskap ved kjøringen: en ekte
CLI-park (scriptet, offline, **null modellkall**) skriver **2** checkpoint-filer, og **nøyaktig ÉN**
nevner forespørselens `request_id` — identisk med F15s måling under 1.16.0. F15s fiks
(`str(request.request_id) not in latest.pending_request_info_events`) hviler derfor på en egenskap
som fortsatt holder, og `#8215` endret ikke antallet.
```
park rc: 0 · checkpoint-filer: 2 · request_id: bd2a03b7-…
1973dcc2-… bytes=10809 mentions_request_id=1
5f89e535-… bytes=2039 mentions_request_id=0
```
Witness: `tests/test_async_plan_review_loadbearing.py`**19 passed** (park → spørsmålsfil →
svarfil → resume i en **fersk interpreter**). Det er den kjøringen ordren ba om.
### Rad 4 — sti-normalisering og skill-revalidering (1.18.0, BREAKING-experimental)
> «**agent-framework-core**: [BREAKING - experimental] Centralize file, memory, session, and skill
> path normalization ([#8123])»
> «**agent-framework-core**: Revalidate discovered skill paths immediately before use ([#8151])»
**Treffer IKKE po målbart.** P14 (`extend_instructions` to-arg GA-signatur i `_sessions.py`) er
**uendret** (§ 2), og MAFs `FileSkillsSource` laster fortsatt po sine to skills **2 av 2**
(`shared/skills/expert-reviewer`, `shared/skills/falsification-reviewer`), med
`get_skills(context: SkillsSourceContext)`-signaturen **identisk** i begge versjoner. Det er
premisset § 5 (d1) hviler på, og det står.
### Rad 5 og 6 — funnet i denne økten, og hvordan
**Metoden:** release-notatene ble gruppert mot po sitt EGET invariant-vokabular
(`grep -niE "mcp init|initialization|event.loop|concurren|checkpoint|middleware|credential|lazily|skill path"`
over begge notatene), i stedet for å lese dem for hva som ser viktig ut generelt. To punkter traff
navngitte po-invarianter som ingen av ordrens fire rader dekket:
**(5) 1.17.0:** «**agent-framework-core**: Surface the underlying MCP initialization error when
cancellation masks a connection failure ([#7704])». Treffer kø-(x)-raden i CLAUDE.md ordrett —
`_unwrap_ingest_error` finnes fordi anyio pakker alt som forlater en task group i en
`BaseExceptionGroup`, og «detach `initialize()`» er én av de fem mutasjonene som gater den. En
oppstrøms endring i hvordan en maskert init-feil overflates kan flytte hva som når vår unwrapper.
**Målt: ingen endring i utfall** — `tests/test_ingest_golden_mcp.py` + `tests/test_hosting_loadbearing.py`
**22 passed**.
**(6) 1.17.0:** «**agent-framework-core**, **agent-framework-foundry**, **agent-framework-openai**:
Document the same-event-loop concurrency contract for shared chat clients ([#7680])». Treffer
Fase 4d-raden (NG1-guarden: hostet inngang er koroutiner på ÉN asyncio-løkke, **aldri** tråder).
Dette er **dokumentasjon**, ikke atferd, og retningen er bekreftende: MAF skriver nå ned den
kontrakten po sin egen rad resonnerte seg til. Ingen endring bestilt; witness som over.
## 4. Vurderingen — MÅLT, IKKE BYGGET
Ingen av funksjonene under er bygget. Ingen ny middleware, ingen timeout-søm, intet vektorlager,
ingen ny CLI-flate, ingen ny U-rad. U-radene siteres ORDRETT fra
[§ 15.1](research/2026-06-23-prior-art-platform.md) (l. 271289) og BUILD/GUARD-radene fra § 15.2/§ 15.3.
### (a) Tidsgrense og stoppårsak i verktøy-løkka — 1.18.0
> «**agent-framework-core**: Add a maximum-duration bound and stop-reason signal to the tool
> invocation loop ([#7772](https://github.com/microsoft/agent-framework/pull/7772))» —
> [python-1.18.0](https://github.com/microsoft/agent-framework/releases/tag/python-1.18.0)
**ORDRENS SPØRSMÅL BÆRER ET FEIL PREMISS, og det rettes her: ingen U-rad ville flytte seg.** Det
finnes ingen U-rad for en verktøy-løkke-timeout blant U1U19. Raden dette treffer er en **BUILD**-rad:
> «B4 | **Termineringskontrakt + budsjett-circuit-breakers** | Magentic-limits defaulter til `None`
> (ubegrenset); ingen kost-tak by default | Krev eksplisitte verdier ved oppstart (fail-fast hvis
> mangler): `max_iterations`, `max_stall`, `cost_budget_tokens`, **wall-clock-timeout**. Alle brudd
> → strukturert event (aldri stille stopp).»
pluss «G1 | Magentic-limits = `None` (ubegrenset) | B4: krev eksplisitte verdier, fail-fast».
**wall-clock-timeout står ORDRETT i B4s skisse, og er den ENE av B4s fire som po aldri bygde.**
**Hva po gjør i dag:** `Budget`/`TokenMeter` per kjøring og `PortfolioBudget`/`PortfolioMeter` over
passet (`ledger.py`), håndhevet i `BudgetMiddleware` med pre-call-guard; `max_rounds` via
`meter.tick_round`; brudd → `BudgetExceeded(kind, limit, observed)`, og på den hostede flaten
`429` med trippelen som STRUKTUR (`hosting.py:44`, `:254`). **Ingen wall-clock-grense noe sted.**
STATE forbyr eksplisitt å bygge den («**IKKE BYGG:** timeout-sømmen fra 1a», STATE.md l. 34), og
**dette forbudet er URØRT.**
**Hva primitiven faktisk er (målt i installert kode, ikke lest av notatet):** `max_duration`
0 treff i `src/`, **21** i installert core. Det publiserte navnet er
**`max_duration_seconds`**, en nøkkel i `FunctionInvocationConfiguration`
(`_tools.py:1487`), satt per klient (`client.function_invocation_configuration["max_duration_seconds"] = 30.0`).
**Og «stop-reason signal» er IKKE en typet verdi en kaller får:** literalen `stop_reason` har
**0** treff i installert core (`stopReason` finnes ett sted, i `_mcp.py`, en MCP-feltnavn).
Mekanismen er `_apply_batch_limit_decision` (`_tools.py:3078`): ved overskridelse settes
`options["tool_choice"] = "none"` og `budget_state["truncated"] = True`, pluss en `logger.info`.
Altså **graceful degradation** — modellen tvinges til et tekstsvar — dokumentert som
**«best-effort»**: klokka sjekkes ETTER hver batch, aldri før.
**Hva den ville koste, og anbefalingen:** primitiven gjør **ikke** den håndrullede sømmen unødvendig,
og det er en forskjell i KANAL, ikke i dekning. po sitt budsjettregime er typede nekter med tre
felt om ÉN ledger; `max_duration_seconds` gir et logglinje-varsel og en intern dict-flagg, og
**degraderer stille inn i et vellykket svar**. En kjøring som traff taket ville altså sett ut som en
kjøring som konkluderte — nøyaktig det `budget_stop` er et EGET felt (aldri `stop_reason`) for å
forhindre, og nøyaktig det 429-raden finnes for. B4s «alle brudd → strukturert event (aldri stille
stopp)» er derfor **ikke** oppfylt av primitiven. **Anbefaling: ikke adopter den som B4s
wall-clock-halvdel.** Skal en wall-clock-grense en gang bygges, er primitiven likevel verdt å bruke
som et **ytre**, billig nett under vår egen typede nekt (den er gratis, den er per klient, og den
stopper en løpsk verktøy-løkke vi ellers bare ser i tokenregnskapet) — men det er en egen ordre, og
STATEs forbud står til operatøren flytter det.
### (b) Godkjenninger bundet til stabile funksjonskall-forekomster — 1.17.0
> «**agent-framework-ag-ui**, **agent-framework-core**, **agent-framework-devui**,
> **agent-framework-openai**: Bind approvals to stable function-call occurrences while preserving
> legacy approval compatibility ([#7988](https://github.com/microsoft/agent-framework/pull/7988))» —
> [python-1.17.0](https://github.com/microsoft/agent-framework/releases/tag/python-1.17.0)
**U-raden, ordrett:**
> «U13 | HITL-gates | Tool approval (`@tool(approval_mode='always_require')` Py /
> `ApprovalRequiredAIFunction` C#); `RequestPort`/`request_info()`;
> `MagenticPlanReviewRequest`/`.approve()`/`.revise()` | …/workflows/human-in-the-loop | ✅ (se F2)»
**Svaret er kallsted-tellingen:**
| konstrukt | `src/` | `tests/` | installert core 1.18.0 |
|---|---|---|---|
| `approval_mode` | **0** | **0** | 102 |
| `FunctionApprovalRequest` | **0** | **0** | — |
**U13 flytter seg IKKE.** po bruker U13 gjennom `MagenticPlanReviewRequest`/`.approve()`/`.revise()`
(F4s synkrone `--plan-review` og U12s asynkrone `--checkpoint-dir`/`--resume`, gatet av de 19
async-testene) og gjennom sin EGEN forslagsgate (`--proposal-review`, MAJOR-2). **Tool-approval-stien
er den halvdelen po aldri tok**, og det er en eksplisitt beslutning eldre enn denne bumpen:
> «G4 | `ApprovalRequiredAIFunction` er **kooperativ markør**, ikke hard enforcement | Håndhev
> godkjenning i invoker-koden, ikke stol på markøren»
`#7988` gjør nettopp den markør-stien mer robust — en approval bindes nå til en stabil
funksjonskall-forekomst i stedet for å kunne feilmatches over avbrudd og resume. **Det er en
forbedring av en sti po ikke bruker.** P12 hadde U13 som «delvis» og forblir «delvis» — statusen er
uendret, og det er premisset (`approval_mode` = 0 i `src`) som er re-målt, ikke statusen som er
revurdert. **Anbefaling: ingen endring.** G4s resonnement (håndhev i vår egen kode) er uberørt av at
markøren er blitt stabilere; det som ville flyttet U13 er en beslutning om å gate
`emit_savings_proposal` på MAFs tool-approval i stedet for på vår egen `--proposal-review`, og det
er en misjonsbeslutning, ikke en pinne-konsekvens.
### (c) BREAKING: sequence-only middleware-inputer — 1.17.0 — MÅLT, IKKE VURDERT
> «**agent-framework-core**, **agent-framework-foundry**: [BREAKING] Restore sequence-only agent
> middleware inputs and remove the experimental `agent-hooks` core extra
> ([#7918](https://github.com/microsoft/agent-framework/pull/7918))» —
> [python-1.17.0](https://github.com/microsoft/agent-framework/releases/tag/python-1.17.0)
**U-raden, ordrett:**
> «U8 | Intercept av tool-calls (blokkerende validator) | Middleware-pipeline `.Use()`;
> `FunctionMiddleware` (`InvokingAsync`/`InvokedAsync`) | …/agents/agent-pipeline | ✅»
**PMs eksponeringsmåling er reprodusert eksakt:** to `FunctionMiddleware`-subklasser
(`mcp_tools.py:197` `ToolCallRecorder`, `explore.py:352` `ExplorationToolRecorder`) og **sju**
`middleware=`-kallsteder (`run.py:1270`, `workflow.py:68` og `:93`, `explore.py:1346`, `:1358`,
`:1741`, `:2033`). `agent-hooks`/`agent_hooks` = **0** treff i `src/`, `tests/`, `pyproject.toml` og
`uv.lock` — po deklarerer ikke den ekstraen som ble fjernet.
**DEN BREKKER IKKE, og grunnen er STRUKTUREL — ikke flaks.** po sine egne parametre er typet
`Sequence[Any] | None` (`workflow.py:54` og `:80`), og hvert av de sju kallstedene sender en LISTE:
`explore.py:1741`/`:2033` literale lister, `run.py:1262-1270` `debate_middleware: list[Any]`,
`workflow.py`/`explore.py:1346`/`:1358` videresender en `Sequence`. En sequence-only inngang er
altså allerede den eneste formen po kan produsere. **Dette er ikke PMs lesning av kilden lenger —
det er suiten:**
| witness | tall |
|---|---|
| Full suite | **1577 passed / 5 skipped** — identisk med basislinjen |
| `test_explore_loadbearing` + `test_budget` + `test_scripted_explore_door_loadbearing` + `test_debate_navigation_cost_loadbearing` + `test_tool_call_path_loadbearing` | **74 passed** |
**Hvilken test ville fanget det:** de fem over konstruerer agenter MED middleware og asserterer på
det middlewaren produserer. Skarpest er `test_tool_call_path_loadbearing.py` (5 armer) og
`test_debate_navigation_cost_loadbearing.py` (11 armer) — begge leser
`RunResult.debate_tool_calls`/`ExplorationTrace.tool_calls`, altså sinken recorderen appender til,
så en middleware som ikke ble **montert** gir et tomt spor og en rød arm. `tests/test_budget.py`
er den tredje: `BudgetMiddleware`s pre-call-guard er dét som gjør S3.4-taket håndhevet, og en
umontert budsjett-middleware ville brutt guard-testene direkte. **Ingen fiks var nødvendig, og
ingen ble laget** — F16 er landet med suiten grønn på 1.18.0.
### (d) Vektorlager-abstraksjonen — 1.18.0, IKKE tatt i bruk
> «**agent-framework-core**: Add shared vector-store abstractions, portable filters, and an
> in-memory vector store ([#8014], [#8115])» · «**agent-framework-qdrant**: Add the alpha Qdrant
> vector-store connector ([#8154])» · «**agent-framework-postgres**: Add the alpha PostgreSQL/pgvector
> connector ([#8155])» — [python-1.18.0](https://github.com/microsoft/agent-framework/releases/tag/python-1.18.0)
U10 leser ordrett «Vektorlagre | Azure AI Search, Cosmos, Qdrant, Redis, Postgres (innebygde
abstraksjoner)», og **den tas fortsatt ikke i bruk: gjenfinningen er OKFs jobb og ikke MAFs, og et
vektorlager inne i MAF ville flyttet D7-portabiliteten — `shared/`-kjernen og `okf.py` er ren
stdlib nettopp så begge stacker konsumerer samme bundles uendret — uten å flytte misjonen ett
skritt.**
## 5. d1 — SkillsProvider-avvisningen står, med en begrunnelse som er sann mot 1.18.0
Operatøren valgte **d1** fra P12 § 7 (D). Setningen i
`docs/plan/2026-08-23-magentic-utforskningssloeyfe.md` § D.2 l. 370 leste:
> «NEI — `ExperimentalFeature.SKILLS`; egen loader virker; commons eier innholdet»
**Den første av de tre grunnene var død allerede i 1.16.0** (P12 § 2: `SkillsProvider` har ingen
`@experimental`-markør; de tre markørene i `_skills.py` gjelder MCP-formene). **Re-målt mot 1.18.0
er det uendret:** de tre markørene er alle `ExperimentalFeature.MCP_SKILLS`, på `MCPSkillResource`,
`MCPSkill` og `MCPSkillsSource`, og `SkillsProvider`/`FileSkillsSource` bærer ingen. ÉN setning er
erstattet — tabellen er ikke skrevet om, U5 er ikke gjenåpnet, ingenting er bygget.
## 6. Fant IKKE, og bygde IKKE
- **Ingen av de tre funksjonene er bygget.** Ingen ny middleware, ingen timeout-søm, intet
vektorlager, ingen ny CLI-flate, ingen ny U-rad. STATEs «IKKE BYGG: timeout-sømmen fra 1a» står.
- **Ingen push, ingen tagg, ingen versjonsbump av po** (`pyproject` `version = "1.1.0"` urørt).
- **CHANGELOG: det finnes INGEN levende `## [Unreleased]`-seksjon.** Øverste post er
`## [1.1.0] - 2026-08-14`. Én er ikke laget, fordi po sin versjon ikke er bumpet: å åpne en
Unreleased-seksjon for en avhengighets-pinne ville vært å opprette en utgivelsesflate ordren
eksplisitt forbyr å røre. Pinnen er dokumentert der den er håndhevet
(`pyproject`-kommentarene og guardens docstring) pluss dette notatet.
- **`docs/2026-09-12-f16-maf-1180.md` trenger INGEN `_LIVE_DOCS`-oppføring, og regelen er verifisert
mot KODEN, ikke mot prosa:** `tests/test_doc_constant_sync_loadbearing.py:59` har
`_DATED = re.compile(r"\d{4}-\d{2}")`, og `_is_archive()` klassifiserer enhver datert sti som et
point-in-time-opptak. Denne stien matcher.
- **De tre portene måles med `scratchpad/` EKSKLUDERT, og det sies høyt.** Bart kjørt gir
`ruff check .` **121 errors** og `ruff format --check .` **82 files would be reformatted** — og
**alle** ligger i `scratchpad/` (47 distinkte filer, alle under den ene katalogen; målt).
`scratchpad/` er utracket og eies av en **parallell sesjon**; den er ikke øktens, og den er aldri
`git add`-et. Ekskludert: `All checks passed!` / `211 files already formatted`.
- **`docs/presentasjon-portfolio-optimiser.html` og `scratchpad/` er ikke committet.** `git add -A`
og `git add docs` er ikke brukt; hver fil er navngitt.
- **STATEs «⚠️ UPUSHET = 1 (`6eb58e5`; `ls-remote` = `ce22b0e`)» var STALE.** Målt ved øktstart:
`git rev-parse HEAD` = `6eb58e5`, `git ls-remote origin refs/heads/main` = `6eb58e5` — **UPUSHET
= 0**. Rettet i STATE.
- **`explore.py`s `_runner.py:275-279`-siteringer er BEVISST ikke rettet** selv om linjene flyttet
fire hakk (§ 2). De sier hvor et premiss ble lest; formen de siterer er gatet av proben.
- **Modul-docstringen i guarden sier fortsatt «verified `1.9.0`»** om at distribusjonsversjonen er
lesbar mens `__version__` er `0.0.0`. Det er et historisk måleresultat om KONTRASTEN, ikke om
hvilken versjon som er installert, og det er latt stå heller enn å produsere en kosmetisk diff.
## 7. Honesty limits
- **Form-proben er gulvet, aldri beviset.** Den sjekker statiske egenskaper ved kilden. F15s
farligste funn var en egenskap ved kjøringen og var usynlig for enhver form-probe. Suiten er
beviset; form 17 er re-målt ved kjøring nettopp fordi proben ikke kan se den.
- **Åtte av de nitten sjekkene bor i `agent_framework_orchestrations` 1.1.1, som ikke flyttet.** De
kan ikke avvike over denne bumpen, og «0 av 19 endret» skal leses med det.
- **16 er ikke en uttømmende liste** over hva som kunne endre seg — det er hva repoets egne
siteringer og sømmer gjorde synlig.
- **Konfigurasjon A er målt på 27 tester, ikke på hele suiten.** Påstanden «resolverens eget valg er
også grønt» har den nevneren, ikke 1577.
- **Ingen betalt kjøring, NOK 0.** Ingen modellkall mot Azure eller en lokal backend. Alt som krever
en levende modell er derfor **ikke målt**, inkludert: om `max_duration_seconds` faktisk degraderer
som dokumentert mot et ekte endepunkt, om `#7988`s approval-binding endrer noe observerbart, og om
`#8127`s «align provider credential handling» endrer en ekte token-henting (po sin
credential-konstruksjon henter ingen token — `az login` er operatørens manuelle steg — så det
ligger utenfor det en gratis kjøring kan se).
- **`ref`-en for de 1.17/1.18-punktene som treffer pakker po ikke installerer** (`ag-ui`, `devui`,
`foundry-hosting`, `lab`, vektorlager-konnektorene) er lest, men ikke målt mot po: pakkene er ikke
i treet, så det finnes ingen kallsted-telling å gjøre.
- **`#8045`** («foundry-hosting: [BREAKING - beta] Restrict checkpoint deserialization by default»)
ser ut som en treffer på po sin `_ALLOWED_CHECKPOINT_TYPES`, men **`agent-framework-foundry-hosting`
er ikke installert** (po kjører stdlib-serveren, Fase 4d) — ingen eksponering, og det er derfor
ikke en rad.
## 8. Verifiseringslogg — én kommando per påstand
| # | Påstand | Kommando |
|---|---|---|
| 1 | Ordrekøen hadde ÉN ordre (min), innboksen 3 meldinger | `find ~/.claude/coord/portfolio-optimiser/{orders,inbox} -type f \| wc -l` → 1 / 3, rc 0 |
| 2 | HEAD = remote, UPUSHET = 0 | `git rev-parse HEAD` + `git ls-remote origin refs/heads/main` → begge `6eb58e5` |
| 3 | Fire PyPI-versjoner + krav | `curl -s https://pypi.org/pypi/<pakke>/json``info.version` + `info.requires_dist` |
| 4 | Den PINNEDE 1.8.2 krever bare `core>=1.9.0` | `curl -s https://pypi.org/pypi/agent-framework-foundry/1.8.2/json` |
| 5 | Basislinje på DENNE HEAD, før bumpen | `uv run pytest -q` → 1577 passed / 5 skipped |
| 6 | Goldenene FØR | `shasum -a 1 tests/golden/demo-transcript.{stdout,stderr}``ea8c534…` / `ede3e2f…` |
| 7 | Vakten RØD først | `uv run pytest tests/test_maf_version_guard.py -q`**2 failed, 2 passed** |
| 8 | Låsen flyttet kun core i første trinn | `uv lock` → «Updated agent-framework-core v1.16.0 -> v1.18.0» |
| 9 | Konfigurasjon A grønn på 27 tester | `uv run pytest tests/test_maf_version_guard.py tests/test_async_plan_review_loadbearing.py tests/test_golden_transcript_loadbearing.py -q` → 4 + 19 + 4 |
| 10 | Installerte versjoner ETTER | `uv run python -c "import importlib.metadata as m; …"` → 1.18.0 / 1.13.0 / 1.14.3 / 1.1.1 |
| 11 | Vakten GRØNN | `uv run pytest tests/test_maf_version_guard.py -q` → 4 passed |
| 12 | 19 sjekker / 16 former, BEGGE versjoner | `probe.py` mot utpakkede wheels 1.16.0 og 1.18.0 → `diff` = kun KP1/KP2 |
| 13 | Kjent-positiv diskriminerer | KP1 `max_duration`/`stop_reason` i `_tools.py`: **0 → 24** |
| 14 | F15s kjent-positiv gjelder ikke her | KP6 `MiddlewareFailure`: YES i BEGGE → forkastet |
| 15 | Form 17 ved KJØRING | ekte CLI-park → 2 checkpoints, 1 nevner `request_id` |
| 16 | Checkpoint-stien grønn i egen interpreter | `uv run pytest tests/test_async_plan_review_loadbearing.py -q`**19 passed** |
| 17 | `SecretString` treffer ikke po | `grep -rF SecretString src/ tests/` → 0; `…/agent_framework_foundry/` → 4, alle i `_embedding_client.py` |
| 18 | `credential` er et objekt, ikke en streng | `_chat_client.py:168``AzureCredentialTypes \| AzureTokenProvider \| None` |
| 19 | Lazy loading flyttet ikke stderr | `uv run python -m portfolio_optimiser.simulation` → stderr 2 linjer, stdout 61 |
| 20 | Goldenene ETTER | `shasum -a 1 …` → uendret `ea8c534…` / `ede3e2f…` |
| 21 | `approval_mode` = 0 i po | `grep -rF approval_mode src/ tests/` → 0 / 0 (venv 102) |
| 22 | Middleware-eksponeringen | `grep -rn "class .*FunctionMiddleware" src/` → 2; `grep -rn "middleware=" src/` → 7 |
| 23 | `agent-hooks` ikke deklarert | `grep -rF -e agent-hooks -e agent_hooks src/ tests/ pyproject.toml uv.lock` → 0 |
| 24 | (c) brekker ikke — witnesses | 5 middleware-bærende suiter → **74 passed** |
| 25 | (a) primitivens ekte navn og kanal | `grep -rn max_duration_seconds .venv/…/_tools.py``FunctionInvocationConfiguration`; `_tools.py:3078` `budget_state["truncated"]` |
| 26 | (a) «stop_reason» er ikke en typet verdi | `grep -rniE "stop_?reason" .venv/…/agent_framework/` → 1 treff (`_mcp.py`, `stopReason`) |
| 27 | Rad 4: skills lastes 2/2 | `FileSkillsSource("shared/skills").get_skills(ctx)`**2 av 2** |
| 28 | Rad 4: de tre markørene er MCP-formene | `grep -n -A2 "@experimental" .venv/…/_skills.py` → 3 × `MCP_SKILLS` |
| 29 | Rad 5/6 witnesses | `uv run pytest tests/test_ingest_golden_mcp.py tests/test_hosting_loadbearing.py -q`**22 passed** |
| 30 | Release-notatene, ordrett + dato | GitHub release-API for `python-1.17.0` / `python-1.18.0` |
| 31 | Full suite ETTER, på committet tre | `uv run pytest -q` → 1577 passed / 5 skipped |
| 32 | Tre porter, `scratchpad/` ekskludert | `ruff check . --exclude scratchpad` · `ruff format --check . --exclude scratchpad` · `mypy src` |
| 33 | Lint-støyen ligger UTELUKKENDE i `scratchpad/` | `ruff check . --output-format=concise \| cut -d/ -f1 \| sort \| uniq -c` → 47 × `scratchpad` |
| 34 | `_LIVE_DOCS`-regelen | `tests/test_doc_constant_sync_loadbearing.py:59` `_DATED = re.compile(r"\d{4}-\d{2}")` |
| 35 | NOK 0 | ingen `--profile azure`-kjøring; parken er scriptet offline med banneret «NO MODEL WAS CALLED» |