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>
36 KiB
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 (prosedyren denne økten gjentar) og P12 — MAF-gjelden (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 iFileCheckpointStorage— klassen po faktisk konstruerer. - P14: «to-arg» i F15 betyr to argumenter BESIDES
self. Min versjon telteselfog 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. KP3–KP5 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
SecretStringa masked value wrapper rather than astrsubclass 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 (l. 271–289) 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)» — 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 U1–U19. 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)» — python-1.17.0
U-raden, ordrett:
«U13 | HITL-gates | Tool approval (
@tool(approval_mode='always_require')Py /ApprovalRequiredAIFunctionC#);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 |
ApprovalRequiredAIFunctioner 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-hookscore extra (#7918)» — 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: BudgetMiddlewares 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
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 (
pyprojectversion = "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.mdtrenger INGEN_LIVE_DOCS-oppføring, og regelen er verifisert mot KODEN, ikke mot prosa:tests/test_doc_constant_sync_loadbearing.py:59har_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 girruff check .121 errors ogruff format --check .82 files would be reformatted — og alle ligger iscratchpad/(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 aldrigit add-et. Ekskludert:All checks passed!/211 files already formatted. docs/presentasjon-portfolio-optimiser.htmlogscratchpad/er ikke committet.git add -Aoggit add docser 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.pys_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__er0.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_orchestrations1.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_secondsfaktisk degraderer som dokumentert mot et ekte endepunkt, om#7988s approval-binding endrer noe observerbart, og om#8127s «align provider credential handling» endrer en ekte token-henting (po sin credential-konstruksjon henter ingen token —az loginer 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, menagent-framework-foundry-hostinger 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» |