MAF core 1.9.0 -> 1.16.0, orchestrations 1.0.1 -> 1.1.1. De to kan ikke loeftes hver for seg: orchestrations 1.1.1 krever selv core>=1.15.0. Iron Law: vakt-testen kjoert ROED mot 1.9.0 (2 failed) FOER pinnen ble roert. Gulvet bor i EN konstant og pyproject-asserten deriverer sin streng fra den. NEVNER: 16 private/ugaranterte former, derivert fra repoets EGNE siteringer, alle 16 sjekket mot begge versjoner, 2 endret seg. Kjent-positiv: MiddlewareFailure flippet NO -> YES. KP-kandidaten _compaction.py ble FORKASTET (teller 0 i begge, diskriminerer ingenting). DEN FARLIGE ENDRINGEN er den ordren navnga - formen som fortsatt importerer, men har flyttet semantikk i stillhet. En park skriver naa TO checkpoints og bare EN baerer plan-review-typen, saa en feildeklarert _ALLOWED_CHECKPOINT_TYPES toemmer ikke lenger listingen: den taper nOEyaktig den checkpointen som betyr noe, get_latest returnerer den ANDRE, og _parks `latest is None`-vakt passerte mens kjOEringen svarte rc=0 og skrev et spOErsmaal som aldri kan baere svaret. Vakten sjekker naa EGENSKAPEN den alltid mente (request_id in pending_request_info_events - et DEKLARERT felt) i stedet for symptomet som pleide aa innebaere den, og fjerner dermed en privat avhengighet i stedet for aa legge til en. ExperimentalWarning-paret P4 pkt. 2 betalte for aa BEHOLDE er borte fordi MAF sluttet aa sende det: _feature_stage.py emitterer ved FOERSTE BRUK, ikke ved import. Goldenens stderr regenerert som BESLUTNING (fire -> to linjer); site-packages- maskeringen BEHOLDT (spannet er ubebodd, ikke pensjonert). Load-bearing MAALT mot HELE suiten, gronn kontroll 1089/5, stdout BYTE-UENDRET (ea8c534773acdbe41ae68f2c55724d69aaf8be4f): M1 revert av vakten -> 1 rod. EN mutasjon ble IKKE rod og staar som aerlighets-grense, ikke som gate: spikens checkpoint_ids[-1] er rekkefolge-avhengig (Path.glob), altsaa flaky. Rapport: docs/2026-09-02-f15-maf-pinnen.md Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
177 lines
11 KiB
Markdown
177 lines
11 KiB
Markdown
# F15 — MAF-pinnen løftet 1.9.0 → 1.16.0
|
||
|
||
> **Ordre:** `20260829T155150Z-30491335-from-.claude` (operatørbeslutning 29.08: operatøren betaler
|
||
> for F15 nå; F3 og F16 TIER 2 er UTSATT og er **ikke** rørt her).
|
||
> **Grunnlag:** [MAF-gjelden — omfang](2026-08-29-maf-gjelden-omfang.md) § 2.
|
||
> Hvert tall under kommer fra en kommando kjørt i denne økten.
|
||
|
||
## 0. Resultat
|
||
|
||
| | |
|
||
|---|---|
|
||
| `agent-framework-core` | **1.9.0 → 1.16.0** |
|
||
| `agent-framework-orchestrations` | **1.0.1 → 1.1.1** (krever selv `core>=1.15.0` — de to gulvene kan ikke løftes hver for seg) |
|
||
| `agent-framework-foundry` / `-openai` | 1.8.2 / 1.8.2, **uendret** (målt etter `uv sync`) |
|
||
| Ny transitiv | `msgspec` 0.21.1 |
|
||
| Testsuite | **1089 passed / 5 skipped / 0 failed** (før: 1087 passed + 2 failed = samme 1089 ikke-skippede; ingen test tapt eller lagt til) |
|
||
| `uv run ruff check .` | All checks passed |
|
||
| `uv run ruff format --check .` | 187 files already formatted |
|
||
| `uv run mypy src` | Success, 34 source files |
|
||
| Golden `demo-transcript.stdout` | **BYTE-UENDRET**, `ea8c534773acdbe41ae68f2c55724d69aaf8be4f` |
|
||
| Golden `demo-transcript.stderr` | **REGENERERT** — fire linjer → to. Beslutning, ikke rydding; se § 3 |
|
||
|
||
## 1. Iron Law — vakten var rød først
|
||
|
||
`tests/test_maf_version_guard.py` er testen. Diffen som løfter gulvet til 1.16.0 lå uncommittet i
|
||
treet fra en tidligere økt, og ble **kjørt rød mot 1.9.0 før pinnen ble rørt**:
|
||
|
||
```
|
||
2 failed, 2 passed (test_installed_maf_version_is_supported, test_pyproject_pins_...)
|
||
```
|
||
|
||
Gulvet bor nå i **én** konstant (`_MIN_VERSION`), og `pyproject`-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. Etter bumpen: 4 passed.
|
||
|
||
## 2. Nevner-disiplin — tre tall
|
||
|
||
**16 distinkte private/ugaranterte MAF-former leaner po på. 16 sjekket (19 mekaniske sjekker).
|
||
2 endret seg.**
|
||
|
||
Inventaret er **derivert fra repoets egne siteringer**, ikke oppfunnet: hver underscore-modul-
|
||
referanse i `src/` (`grep -rnoE "_[a-z_]+\.py:[0-9-]+" src/`) pluss hver MAF-form en søm faktisk
|
||
overstyrer eller konstruerer. Instrumentet (`probe.py`) kjørte mot BEGGE versjoner; det er efemert
|
||
og bor ikke i repoet.
|
||
|
||
| Form | 1.9.0 | 1.16.0 |
|
||
|---|---|---|
|
||
| P1 `BaseChatClient._inner_get_response` kw-only (messages/stream/options) | OK | OK |
|
||
| P2 `BaseChatClient._build_response_stream` | OK | OK |
|
||
| P3 `…_magentic:MagenticPlanReviewRequest` (allowlist-streng) | OK | OK |
|
||
| P4 `…_magentic:MagenticPlanReviewResponse` (allowlist-streng) | OK | OK |
|
||
| P5 strengt stall-sjekk `stall_count > max_stall_count` | OK | OK |
|
||
| P6 reset-sjekk `reset_count >= max_reset_count` | OK | OK |
|
||
| P7 `next_speaker not in _participant_registry.participants`-fallback | OK | OK |
|
||
| P8 nøyaktig ÉN `ctx.request_info` i `_magentic.py` | OK (1) | OK (1) |
|
||
| P9 `is_request_satisfied` på ledgeren | OK (8) | OK (8) |
|
||
| P10 `list_checkpoints` svelger blokkert type til `logger.warning` | OK | OK (men se § 4) |
|
||
| P11 `get_latest` velger på timestamp · P11b `allowed_checkpoint_types=` | OK | OK |
|
||
| P12 runner matcher på graf-signatur | OK | OK |
|
||
| P13 `…_base_group_chat_orchestrator` + `reached max_rounds`-meldingen | OK | OK |
|
||
| P14 `extend_instructions` to-arg GA-signatur (`_sessions.py`) | OK | OK |
|
||
| P15 console-exportere gatet på flagget · P15b `ENABLE_INSTRUMENTATION` | OK | OK |
|
||
| **P16 `ExperimentalWarning`-emisjonen goldenen pinner** | 2 linjer | **0 linjer — ENDRET** |
|
||
| **Checkpoint-antallet per park (ikke i proben — fanget av suiten)** | 1 lesbar | **2 — ENDRET** |
|
||
|
||
**Kjent-positiv (L93): proben KAN oppdage en endret form.** `MiddlewareFailure` (ny i 1.15.0) er en
|
||
delta målt uavhengig i § 2 av omfangsdokumentet. Kontrollen flippet **NO → YES** over bumpen. Den
|
||
andre kandidaten, `_compaction.py`s `@experimental`-markører, er **forkastet som kjent-positiv**:
|
||
den teller 0 i BEGGE versjoner, altså diskriminerer den ingenting — målt, ikke antatt.
|
||
|
||
**Ærlighets-grense, uttalt:** proben sjekker FORMER. Den mest konsekvensrike endringen (§ 4) var
|
||
usynlig for den og ble fanget av testsuiten. En form-probe er gulvet, ikke beviset — nevneren over
|
||
skal leses som «16 former sjekket mekanisk», ikke «alt som kunne endre seg er sjekket».
|
||
|
||
## 3. Golden stderr — regenerert som beslutning
|
||
|
||
**Målt:** null `ExperimentalWarning` fyrer på import under 1.16.0, mens `@experimental`-dekoratørene
|
||
fortsatt FINNES i treet (3 i `_skills.py`, 5 i `_harness/_memory.py`). Verifisert mot exit-status
|
||
(`import portfolio_optimiser` → rc 0, `IMPORT-OK`) før det negative resultatet ble lest som et faktum.
|
||
|
||
**Rotårsak, lest ut av kilden:** `_feature_stage.py:411` bruker `_add_runtime_warning(...)` — 1.16.0
|
||
emitterer advarselen ved **første bruk**, ikke ved dekorering/import. Demoen instansierer verken
|
||
`SkillResource` eller `MemoryStore`, så de to linjene sluttet å bli sendt **oppstrøms**. De ble
|
||
aldri dempet av oss.
|
||
|
||
Fasiten er derfor regenerert fra en faktisk kjøring gjennom den **uendrede** normalisereren:
|
||
fire linjer → to (blanklinje + `arbeidskopi:`). `stdout` er byte-uendret, og
|
||
`test_normalisation_does_not_mask_a_new_warning` er fortsatt grønn — P4 pkt. 2s garanti om at en NY
|
||
advarsel når stderr står. Span 1 (`site-packages`-maskeringen) er **beholdt**: spannet er ubebodd,
|
||
ikke pensjonert, og en advarsel som kommer tilbake skal fortsatt felle pinnen med stien maskert.
|
||
|
||
Påstandene om «fire linjer» er rettet der de er LEVENDE (`tracing.py`, `test_tracing_loadbearing.py`,
|
||
`test_explore_loadbearing.py`, `test_golden_transcript_loadbearing.py`, `CLAUDE.md` ×3, og
|
||
operatørens `docs/plan/2026-08-12-demo-runbook.md`). De daterte plan-/reviewdokumentene er historikk
|
||
og er IKKE omskrevet.
|
||
|
||
## 4. Den farlige endringen — en vakt som gikk inert i stillhet
|
||
|
||
Ordren ba spesifikt om formen som «fortsatt IMPORTERER men har endret SEMANTIKK i stillhet». Det er
|
||
denne, og den traff en load-bearing garanti:
|
||
|
||
**Målt:** under 1.16.0 skriver én park **TO** checkpoint-filer. Bare den ene bærer plan-review-typen.
|
||
Med en feildeklarert `_ALLOWED_CHECKPOINT_TYPES` blir derfor listingen **ikke lenger tom** — den
|
||
taper nøyaktig den checkpointen som betyr noe, `get_latest` returnerer den ANDRE, og `explore._park`s
|
||
vakt (`latest is None`) passerte. Kjøringen svarte `rc=0` og skrev et spørsmål som peker på en
|
||
checkpoint som aldri kan bære svaret: **nøyaktig den døde spørsmålsfila laget finnes for å nekte**,
|
||
nå stille.
|
||
|
||
Per-fil-måling (samme park, samme katalog):
|
||
|
||
| fil | FULL allowlist | TOM allowlist |
|
||
|---|---|---|
|
||
| `76ac52bf…` (bærer forespørselen) | ok | **BLOCKED** |
|
||
| `b3fe53b7…` | ok | ok |
|
||
|
||
**Fiksen tester egenskapen den alltid mente, ikke symptomet som pleide å innebære den:** vakten
|
||
sjekker nå at checkpointen den navngir faktisk bærer DENNE forespørselen, mot det **deklarerte**
|
||
feltet `WorkflowCheckpoint.pending_request_info_events` — ikke mot den private, emergente
|
||
«blokkert ⇒ tom listing»-oppførselen. Det fjerner en privat avhengighet i stedet for å legge til en.
|
||
|
||
```python
|
||
if latest is None or str(request.request_id) not in latest.pending_request_info_events:
|
||
raise CheckpointUnreadable(...)
|
||
```
|
||
|
||
**Load-bearing MÅLT** mot HELE suiten, grønn kontroll 1089/5:
|
||
**M1** — reverter vakten til `latest is None`: **1 rød**
|
||
(`test_a_park_with_no_readable_checkpoint_refuses_instead_of_writing_a_dead_question`), restaurert
|
||
og `shasum -c` OK.
|
||
|
||
**Checkpoint-formen verifisert med FAKTISK KJØRING, ikke import:**
|
||
`tests/test_async_plan_review_loadbearing.py` (19 tester) driver park → spørsmålsfil → svarfil →
|
||
resume i en fersk interpreter, og er grønn. Det er den kjøringen ordren ba om.
|
||
|
||
## 5. Spiken traff den samme fella — og gaten er ÆRLIG svakere enn M1
|
||
|
||
`spikes/e_magentic.py` gjenopptok fra `checkpoint_ids[-1]` — SISTE element i en glob-ordnet listing,
|
||
nøyaktig det `explore._park`s egen docstring advarer mot. Med to checkpoints døde resumen på
|
||
`RuntimeError: No pending requests found in workflow context.` Spiken velger nå den checkpointen som
|
||
bærer forespørselen, som produksjonen.
|
||
|
||
**MÅLT, og det motsier det jeg antok:** mutasjonen som setter `[-1]` tilbake ble **IKKE rød**
|
||
(1089 passed). Feilen er **rekkefølge-avhengig** (`Path.glob`) — den ble observert rød i den første
|
||
fullkjøringen etter bumpen og grønn med samme effektive valg her. Spikens gamle form er altså
|
||
**flaky, ikke deterministisk gal**, og fiksen står på den observerte feilen pluss fjerningen av et
|
||
dokumentert anti-mønster — **ikke** på en gate. Sagt høyt fordi en mutasjon som ikke ble rød ikke er
|
||
et bevis, og å presentere den som ett ville vært den vakuøse gaten dette repoet teller instanser av.
|
||
|
||
## 6. Fant IKKE, og bygde IKKE
|
||
|
||
- **Ingen F3. Ingen F16 TIER 2.** Utsatt av operatøren; ikke rørt, ikke forberedt.
|
||
- Ingen publisering, ingen push, ingen release.
|
||
- **README-ens hosting-begrunnelse mistet sitt premiss og er RETTET, ikke gjenåpnet:**
|
||
`agent-framework-foundry-hosting` krever `core>=1.13.0`, og treet låser nå 1.16.0 — så
|
||
versjonsgrunnen til stdlib-serveren er borte. Om pakka skal adopteres er et ÅPENT spørsmål denne
|
||
bumpen bevisst ikke gjenåpner; det som er målt og shippet er fortsatt stdlib-serveren.
|
||
- **Ordrens steg 0 om STATE-linjen er en no-op:** `git stash list` er tom OG `STATE.md:20` sier
|
||
allerede at den er tom. Linje 36 er en sann historisk merknad om økt 73. Det var ingenting å
|
||
rette, og det sies her i stedet for å produsere en kosmetisk endring.
|
||
|
||
## 7. Verifiseringslogg
|
||
|
||
| # | Påstand | Kommando |
|
||
|---|---|---|
|
||
| 1 | Vakten rød på 1.9.0 før pinnen | `uv run pytest tests/test_maf_version_guard.py -q` → 2 failed |
|
||
| 2 | Installerte versjoner etter bump | `importlib.metadata.version(...)` → core 1.16.0, orch 1.1.1, foundry/openai 1.8.2 |
|
||
| 3 | 16 former / 19 sjekker, begge versjoner | `probe.py` mot 1.9.0 (0 CHANGED) og 1.16.0 (1 CHANGED) |
|
||
| 4 | Kjent-positiv virker | KP1 `MiddlewareFailure` NO → YES |
|
||
| 5 | Kjent-positiv-kandidat forkastet | KP2 `_compaction.py` `@experimental` = 0 i begge |
|
||
| 6 | Advarslene borte, ikke import-feil | `python -c "import portfolio_optimiser"` → rc 0 + `warnings.catch_warnings` → 0 |
|
||
| 7 | Rotårsak | `_feature_stage.py:411` `_add_runtime_warning` |
|
||
| 8 | To checkpoints, én bærer forespørselen | per-fil `decode_checkpoint_value` med FULL vs TOM allowlist |
|
||
| 9 | M1 rød, restaurert | full suite → 1 failed; `shasum -c` OK |
|
||
| 10 | M2 ikke rød | full suite → 1089 passed |
|
||
| 11 | Grønn kontroll + de tre portene | `pytest` 1089/5 · `ruff check` · `ruff format --check` · `mypy src` |
|
||
| 12 | stdout byte-uendret | `shasum` → `ea8c534773acdbe41ae68f2c55724d69aaf8be4f` |
|
||
| 13 | Demoens stdout fortsatt 61 linjer | `python -m portfolio_optimiser.simulation \| wc -l` → 61 |
|