F15-rapporten og CLAUDE.md-raden sa "16 former, alle 16 sjekket, 2 endret seg".
Den formuleringen var usann, og tabellen sa det selv to rader lenger ned: den ene
av de to endrede formene (checkpoint-antallet per park) var ALDRI blant de seksten
- proben saa den ikke, testsuiten fant den. "2 av 16" tilskrev dermed proben et
funn den ikke gjorde, og skjulte at nevneren for den mekaniske sjekken er 1.
Rettet til det som faktisk ble maalt: 17 former leant paa · 16 sjekket MEKANISK
(1 endret) · den 17. funnet av SUITEN (endret) · 2 endret totalt. Grunnen staar
ogsaa skrevet: proben sjekker statiske egenskaper ved KILDEN, mens den farlige
endringen var en egenskap ved KJOERINGEN, og ingen form-probe kan se den uansett
hvor mange former den teller.
Lagt til en aerlighets-grense paa selve fiksen som manglet: vakten hviler paa at
get_latest returnerer checkpointen som BAERER forespoerselen. Maalt sant i dag og
dekket av 19 gronne tester - men skriver MAF en gang en checkpoint ETTER at
forespoerselen er reist, nekter _park en gyldig kjoering. Fail-closed-retningen,
saa det er en grense aa kjenne, ikke en defekt aa fikse.
Ingen historikk-omskriving: commit-kroppen til ef2f1cb baerer fortsatt den gamle
formuleringen, og det staar her i stedet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
194 lines
12 KiB
Markdown
194 lines
12 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
|
||
|
||
**17 distinkte private/ugaranterte MAF-former leaner po på · 16 sjekket MEKANISK av proben
|
||
(19 sjekker), hvorav 1 endret seg · den 17. ble funnet av TESTSUITEN, og den endret seg også ·
|
||
2 endret seg totalt.**
|
||
|
||
**Den formen er stilt opp slik fordi den første formuleringen var usann.** Et tidligere utkast sa
|
||
«16 former, 16 sjekket, 2 endret» — men den ene av de to (checkpoint-antallet per park) var aldri
|
||
blant de seksten; proben så den ikke. «2 av 16» ville altså tilskrevet proben et funn den ikke
|
||
gjorde, og skjult at nevneren for den mekaniske sjekken er 1. Nevner-disiplin gjelder også mitt eget
|
||
instrument.
|
||
|
||
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 — form 17, 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 — statiske egenskaper ved kilden. Den mest
|
||
konsekvensrike endringen (§ 4) er en egenskap ved KJØRINGEN (hvor mange checkpoints en park skriver),
|
||
og den er usynlig for enhver form-probe uansett hvor mange former den teller. Den ble fanget av
|
||
testsuiten. En form-probe er gulvet, ikke beviset, og nevneren skal leses som «16 former sjekket
|
||
mekanisk» — ikke «alt som kunne endre seg er sjekket». Det finnes ingen påstand her om at 17 er en
|
||
uttømmende liste; 17 er det repoets egne siteringer og sømmer gjorde synlig.
|
||
|
||
## 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.
|
||
|
||
**Ærlighets-grense på selve fiksen, uttalt:** vakten hviler på at `get_latest` returnerer den
|
||
checkpointen som BÆRER forespørselen. Det er målt sant i dag, og park → spørsmål → svar → resume →
|
||
andre park er dekket av 19 grønne tester — men skulle MAF en gang skrive en checkpoint ETTER at
|
||
forespørselen er reist, ville `_park` nekte en gyldig kjøring. Det er fail-closed-retningen (en nekt,
|
||
aldri et dødt spørsmål), så det står som en grense å kjenne, ikke som en defekt å fikse.
|
||
|
||
**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) |
|
||
| 3b | Form 17 endret, funnet av suiten, ikke av proben | full suite → `test_a_park_with_no_readable_checkpoint…` failed |
|
||
| 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 |
|