fix(maf): en vakt som gikk inert i STILLHET, funnet ved aa loefte pinnen (F15, ORDRE 20260829T155150Z)

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>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-02 19:35:49 +02:00
commit ef2f1cbe61
15 changed files with 366 additions and 54 deletions

View file

@ -16,7 +16,7 @@ Generisk, åpent Python-rammeverk på **Microsoft Agent Framework (MAF)** som fi
Bakgrunn og beslutninger: [research](docs/research/2026-06-23-prior-art-platform.md) (§15 implementeringsregister), [plan](docs/plan/2026-06-23-incremental-plan.md). Løpende state: `STATE.md` (local-only). Bakgrunn og beslutninger: [research](docs/research/2026-06-23-prior-art-platform.md) (§15 implementeringsregister), [plan](docs/plan/2026-06-23-incremental-plan.md). Løpende state: `STATE.md` (local-only).
## Stack ## Stack
Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To backend-profiler: Azure/Foundry (full) + lokal (fallback). Python ≥3.10. MAF (`agent-framework-core` 1.16.0, `-orchestrations` 1.1.1 — F15, 02.09). Pakkehåndtering: `uv`. To backend-profiler: Azure/Foundry (full) + lokal (fallback).
## Konvensjoner ## Konvensjoner
- Type hints overalt (`mypy` der mulig). Pydantic for validering/IR. - Type hints overalt (`mypy` der mulig). Pydantic for validering/IR.
@ -605,7 +605,7 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
live-kjøringen, ER fila transkriptet. `…​.stderr` er normalisert på nøyaktig to MÅLTE miljø-spann — live-kjøringen, ER fila transkriptet. `…​.stderr` er normalisert på nøyaktig to MÅLTE miljø-spann —
`site-packages`-prefikset og temp-katalogen bak `(arbeidskopi: …)`, der `po-sim-`-prefikset holdes `site-packages`-prefikset og temp-katalogen bak `(arbeidskopi: …)`, der `po-sim-`-prefikset holdes
SYNLIG fordi det er en egenskap ved programmet (`mkdtemp(prefix=…)`), ikke ved miljøet; pinnet SYNLIG fordi det er en egenskap ved programmet (`mkdtemp(prefix=…)`), ikke ved miljøet; pinnet
stderr er fire linjer. **Masken må ikke kunne vokse:** P4 pkt. 2 betalte for at en NY advarsel stderr er TO linjer (var fire til og med core 1.9.0 — se F15-raden). **Masken må ikke kunne vokse:** P4 pkt. 2 betalte for at en NY advarsel
fortsatt når stderr, og en normalisering som maskerte hele linjer ville opphevet det i ett trekk — fortsatt når stderr, og en normalisering som maskerte hele linjer ville opphevet det i ett trekk —
derfor er `test_normalisation_does_not_mask_a_new_warning` kontrollen som forbyr det (MÅLT: en derfor er `test_normalisation_does_not_mask_a_new_warning` kontrollen som forbyr det (MÅLT: en
droppende normaliserer med fasiten regenerert under seg holder BEGGE likhets-testene grønne og droppende normaliserer med fasiten regenerert under seg holder BEGGE likhets-testene grønne og
@ -755,7 +755,7 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
også: providere med ingenting å eksportere til er en kjøring som SER sporet ut og ikke er det. En også: providere med ingenting å eksportere til er en kjøring som SER sporet ut og ikke er det. En
ukjent verdi nektes ved navn, aldri stille fallback til av. **`tracing_notice` er ENESTE renderer**, ukjent verdi nektes ved navn, aldri stille fallback til av. **`tracing_notice` er ENESTE renderer**,
tar den alt oppløste `TracingSetup` og returnerer `None` når sporing er av — omisjon, aldri tom rad tar den alt oppløste `TracingSetup` og returnerer `None` når sporing er av — omisjon, aldri tom rad
(`announce`-regelen), og her bærende utover stil: demoens pinnede stderr er FIRE linjer. **Tre (`announce`-regelen), og her bærende utover stil: demoens pinnede stderr er TO linjer (FIRE før F15). **Tre
kallsteder, ikke ett** (`run.main`, `simulation.main`, `hosting.main`): demoen er et skriptet bevis, kallsteder, ikke ett** (`run.main`, `simulation.main`, `hosting.main`): demoen er et skriptet bevis,
ikke produktet, og en søm bare demoen når ville latt de to inngangene en virksomhet faktisk kjører ikke produktet, og en søm bare demoen når ville latt de to inngangene en virksomhet faktisk kjører
være usporbare. **OTLP-exporter-PAKKENE er BEVISST ikke deklarert** (egress + grpc/protobuf-vekt i være usporbare. **OTLP-exporter-PAKKENE er BEVISST ikke deklarert** (egress + grpc/protobuf-vekt i
@ -769,7 +769,7 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
raden bare vært en keyword-assert) · detach console-nekten (4 røde) · detach otlp-endepunkt-nekten raden bare vært en keyword-assert) · detach console-nekten (4 røde) · detach otlp-endepunkt-nekten
(1 rød) · ukjent modus faller stille til av (2 røde) · «av» kaller MAF likevel + renderer returnerer (1 rød) · ukjent modus faller stille til av (2 røde) · «av» kaller MAF likevel + renderer returnerer
alltid en linje (9 røde, hvorav TRE i tester som fantes fra før — `test_golden_transcript` sin alltid en linje (9 røde, hvorav TRE i tester som fantes fra før — `test_golden_transcript` sin
fire-linjers stderr og `test_portfolio_cli_offline`s stille-pass — altså er omisjonen gatet av da fire-linjers (nå to-linjers) stderr og `test_portfolio_cli_offline`s stille-pass — altså er omisjonen gatet av
uavhengige vitner) · detach demo-wiringen + detach CLI-wiringen (5 røde) · detach hosting-wiringen uavhengige vitner) · detach demo-wiringen + detach CLI-wiringen (5 røde) · detach hosting-wiringen
(1 rød, KUN subprosess-testen — P4-presedensen). (1 rød, KUN subprosess-testen — P4-presedensen).
- **Utforskningssløyfa er en MANDAT-FORMER, og de tre garantinivåene er strukturelle (U4+U13 - **Utforskningssløyfa er en MANDAT-FORMER, og de tre garantinivåene er strukturelle (U4+U13
@ -1179,6 +1179,36 @@ Python ≥3.10. MAF (`agent-framework-core` 1.9.0). Pakkehåndtering: `uv`. To b
intet vitne. To grener, to armer, to mutasjoner. Ærlighets-grense, uttalt: at en LEVENDE modell intet vitne. To grener, to armer, to mutasjoner. Ærlighets-grense, uttalt: at en LEVENDE modell
kaller verktøyene er fortsatt ikke bevist (structured-output-grensens klasse) — dette gjør den kaller verktøyene er fortsatt ikke bevist (structured-output-grensens klasse) — dette gjør den
GRATIS halvdelen av stigen ekte, ikke den betalte. GRATIS halvdelen av stigen ekte, ikke den betalte.
- **MAF-pinnen er en TRIPWIRE, ikke en frys — og det som gjorde løftet farlig var IKKE en form som
forsvant (F15, 02.09, core 1.9.0 → 1.16.0, orchestrations 1.0.1 → 1.1.1):** de to kan ikke løftes
hver for seg (orchestrations 1.1.1 krever selv `core>=1.15.0`). Gulvet bor i ÉN konstant
(`_MIN_VERSION` i `tests/test_maf_version_guard.py`) 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. **16 private/ugaranterte former, derivert fra repoets
EGNE siteringer** (hver `_modul.py:linje`-referanse i `src/` + hver form en søm overstyrer eller
konstruerer), alle 16 sjekket mot begge versjoner; **2 endret seg.** Kjent-positiv: `MiddlewareFailure`
(ny i 1.15.0) flippet NO → YES, altså KAN proben oppdage endring; `_compaction.py`s
`@experimental`-markører ble FORKASTET som kjent-positiv fordi de teller 0 i BEGGE versjoner og
derfor ikke diskriminerer noe. **Den farlige endringen var den ordren navnga — formen som fortsatt
importerer, men har flyttet semantikk i stillhet:** en park skriver nå **TO** checkpoints og bare
ÉN bærer plan-review-typen, så en feildeklarert `_ALLOWED_CHECKPOINT_TYPES` **tømmer ikke lenger
listingen** — den taper nøyaktig den checkpointen som betyr noe, `get_latest` returnerer den ANDRE,
og `_park`s `latest is None`-vakt passerte mens kjøringen svarte `rc=0` og skrev et spørsmål som
aldri kan bære svaret. Vakten sjekker nå EGENSKAPEN den alltid mente (`str(request.request_id) in
latest.pending_request_info_events` — et DEKLARERT felt) i stedet for symptomet som pleide å
innebære den, og fjerner dermed en privat avhengighet i stedet for å legge til en. **`ExperimentalWarning`-paret
P4 pkt. 2 betalte for å BEHOLDE er borte fordi MAF sluttet å sende det** — `_feature_stage.py`s
`_add_runtime_warning` emitterer ved FØRSTE BRUK, ikke ved import, og demoen instansierer ingen av
de to typene; goldenens stderr er derfor TO linjer, regenerert som en BESLUTNING, mens
`site-packages`-maskeringen er BEHOLDT (spannet er ubebodd, ikke pensjonert) og
`test_normalisation_does_not_mask_a_new_warning` fortsatt er grønn. Load-bearing MÅLT mot HELE
suiten, grønn kontroll **1089/5** og `demo-transcript.stdout` BYTE-UENDRET
(`ea8c534773acdbe41ae68f2c55724d69aaf8be4f`): M1 revert av vakten → 1 rød. **ÉN MUTASJON BLE IKKE
RØD, og det står som en ÆRLIGHETS-GRENSE, ikke som en gate:** spikens gjenopptak fra
`checkpoint_ids[-1]` (siste element i en glob-ordnet listing — nøyaktig anti-mønsteret `_park`s
docstring advarer mot) feilet i den første fullkjøringen etter bumpen og var GRØNN ved mutasjonen,
altså rekkefølge-avhengig og flaky. Fiksen står på den observerte feilen, ikke på et rødt vitne.
Rapport: `docs/2026-09-02-f15-maf-pinnen.md`.
- **STATE.md er local-only** (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet. - **STATE.md er local-only** (gitignored). Voyage session-state er efemert; STATE.md er kanonisk kontinuitet.
- Prosess: Voyage-plugin (`/trekbrief → /trekplan → /trekexecute → /trekreview`) per større fase. - Prosess: Voyage-plugin (`/trekbrief → /trekplan → /trekexecute → /trekreview`) per større fase.

View file

@ -631,10 +631,12 @@ only an expert has:
`PORT`, `GET /readiness`, `POST /invocations`, clean SIGTERM exit) from `PORT`, `GET /readiness`, `POST /invocations`, clean SIGTERM exit) from
`portfolio_optimiser.hosting`, wrapping `run_project` — never `Workflow.as_agent()`, which `portfolio_optimiser.hosting`, wrapping `run_project` — never `Workflow.as_agent()`, which
would bypass the deterministic validator and the rest of the gate chain. No protocol library would bypass the deterministic validator and the rest of the gate chain. No protocol library
is used: the prerelease `agent-framework-foundry-hosting` requires is used: the contract is a small stdlib-asyncio server instead (single event loop, no threads —
`agent-framework-core>=1.13.0` while this tree locks 1.9.0, so the contract is a small the same concurrency model as the portfolio waves). Note that the version reason this choice was
stdlib-asyncio server instead (single event loop, no threads — the same concurrency model as originally made for is retired: the prerelease `agent-framework-foundry-hosting` requires
the portfolio waves). `agent-framework-core>=1.13.0`, and since F15 (2026-09-02) this tree locks 1.16.0. Whether to adopt
that package is an open question this bump deliberately did not reopen — the stdlib server is what
is measured and shipped.
```bash ```bash
uv sync --frozen --no-dev # the exact locked resolution every measurement ran against uv sync --frozen --no-dev # the exact locked resolution every measurement ran against

View file

@ -0,0 +1,177 @@
# 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 |

View file

@ -45,10 +45,15 @@ Alt annet i dette dokumentet er målt mandag 10. august mot det pinnede transkri
uv run python -m portfolio_optimiser.simulation uv run python -m portfolio_optimiser.simulation
``` ```
Forventet: **exit 0**, **61 linjer stdout**, **4 linjer stderr**. Forventet: **exit 0**, **61 linjer stdout**, **2 linjer stderr**.
Stderr er fire linjer og skal være der: to `ExperimentalWarning` fra MAF (Skills + MemoryStore), Stderr er to linjer og skal være der: en blanklinje og
en blanklinje, og `(arbeidskopi: <systemets temp-katalog>/po-sim-…)`. `(arbeidskopi: <systemets temp-katalog>/po-sim-…)`.
**Endret 02.09 (F15):** til og med MAF core 1.9.0 sto det også to `ExperimentalWarning`-linjer her
(Skills + MemoryStore), og runbooken sa fire. Core 1.16.0 flytter den advarselen fra importtid til
FØRSTE BRUK, og demoen bruker ingen av de to typene — så linjene er borte fordi MAF sluttet å sende
dem, ikke fordi noe ble dempet. Ser du dem likevel, kjører du en eldre kjerne enn pinnen.
**Katalogen varierer, prefikset gjør ikke det.** På macOS er temp-katalogen `/var/folders/…/T/`, **Katalogen varierer, prefikset gjør ikke det.** På macOS er temp-katalogen `/var/folders/…/T/`,
**ikke** `/tmp/` — så linja på skjermen blir lang og stygg, og det er riktig. `po-sim-` er den delen **ikke** `/tmp/` — så linja på skjermen blir lang og stygg, og det er riktig. `po-sim-` er den delen

View file

@ -9,12 +9,12 @@ dependencies = [
# og `[all]` trekker inn de fortsatt-beta integrasjonene (azure-ai-search/cosmos/ollama/…) som # og `[all]` trekker inn de fortsatt-beta integrasjonene (azure-ai-search/cosmos/ollama/…) som
# tvinger pre-releases og drar med en ALPHA pydantic. Offisiell guide: installer kun det du trenger. # tvinger pre-releases og drar med en ALPHA pydantic. Offisiell guide: installer kun det du trenger.
# Beta-integrasjoner legges til per-fase (med snevert pre-release-scope) når de faktisk trengs. # Beta-integrasjoner legges til per-fase (med snevert pre-release-scope) når de faktisk trengs.
"agent-framework-core>=1.9.0,<2", # kjerne (GA) — to-sidig pin (S2.5): major-bump krever re-verifisering av privat-API-premissene (test_maf_version_guard) "agent-framework-core>=1.16.0,<2", # kjerne (GA) — to-sidig pin (S2.5): major-bump krever re-verifisering av privat-API-premissene (test_maf_version_guard). F15 (02.09): løftet fra 1.9.0; de 19 private formene re-verifisert mot 1.16.0, se docs/2026-09-02-f15-maf-pinnen.md
"agent-framework-foundry>=1.8.2", # Azure/Foundry-profil: FoundryChatClient (GA) "agent-framework-foundry>=1.8.2", # Azure/Foundry-profil: FoundryChatClient (GA)
"azure-identity>=1.25", # S4.1: AzureFoundryBackend passes an explicit AzureCliCredential (Foundry requires it); already transitive via foundry — promoted to a declared direct dep (zero new install weight) "azure-identity>=1.25", # S4.1: AzureFoundryBackend passes an explicit AzureCliCredential (Foundry requires it); already transitive via foundry — promoted to a declared direct dep (zero new install weight)
"agent-framework-openai>=1.8.2", # OpenAI + OpenAI-kompatible lokale endpoints (GA) → lokal profil "agent-framework-openai>=1.8.2", # OpenAI + OpenAI-kompatible lokale endpoints (GA) → lokal profil
# Promotert dev→core i Fase 2 (MVP-runtime, ikke lenger spike-only): # Promotert dev→core i Fase 2 (MVP-runtime, ikke lenger spike-only):
"agent-framework-orchestrations>=1.0.0", # GA orchestration builders (GroupChat/Concurrent/Magentic); resolves med core 1.9.0 "agent-framework-orchestrations>=1.1.1", # GA orchestration builders (GroupChat/Concurrent/Magentic); krever selv core>=1.15.0, så de to gulvene løftes SAMMEN (F15) — det finnes ingen delvis bump
"pulp>=2.8", # deterministisk validator-solver; PuLP bundler CBC i wheelen (R2). Installert 3.3.2. "pulp>=2.8", # deterministisk validator-solver; PuLP bundler CBC i wheelen (R2). Installert 3.3.2.
# PuLP 4.0 vil kreve `pip install pulp[cbc]` + COIN_CMD (Fase-migrasjonsnotat). # PuLP 4.0 vil kreve `pip install pulp[cbc]` + COIN_CMD (Fase-migrasjonsnotat).
"mcp>=1.28.0", # tynn lokal-mappe MCP-server (Step 7) — GA (resolverte 1.28.0) per Step 1-beslutning "mcp>=1.28.0", # tynn lokal-mappe MCP-server (Step 7) — GA (resolverte 1.28.0) per Step 1-beslutning

View file

@ -517,9 +517,22 @@ async def checkpoint_until_plan_review(storage_dir: str) -> dict[str, Any]:
checkpoints = await _checkpoint_storage(storage_dir).list_checkpoints( checkpoints = await _checkpoint_storage(storage_dir).list_checkpoints(
workflow_name=workflow.name workflow_name=workflow.name
) )
request_id = pending[0].request_id if pending else None
# F15 (core 1.16.0, MEASURED): a park now leaves TWO checkpoints, and only one of them carries
# the plan-review request. Naming the LAST entry of a listing was correct while there was one;
# with two it picks by whatever ``Path.glob`` returned and the resume dies on "No pending
# requests found in workflow context." The id handed across the process boundary is therefore
# the one whose ``pending_request_info_events`` holds THIS request — the same property
# ``explore._park`` asserts, rather than a position in an unordered listing.
carrying = [
c
for c in checkpoints
if request_id is not None and str(request_id) in c.pending_request_info_events
]
return { return {
"request_id": pending[0].request_id if pending else None, "request_id": request_id,
"checkpoint_ids": [c.checkpoint_id for c in checkpoints], "checkpoint_ids": [c.checkpoint_id for c in checkpoints],
"resume_checkpoint_id": str(carrying[-1].checkpoint_id) if carrying else None,
"outputs": [str(o) for o in (result.get_outputs() or [])], "outputs": [str(o) for o in (result.get_outputs() or [])],
} }

View file

@ -1534,18 +1534,27 @@ async def _park(
``get_latest`` rather than the last entry of a listing: it picks by timestamp ``get_latest`` rather than the last entry of a listing: it picks by timestamp
(``_checkpoint.py:424``), while the listing's order is whatever ``Path.glob`` returned. (``_checkpoint.py:424``), while the listing's order is whatever ``Path.glob`` returned.
An EMPTY listing is refused (``CheckpointUnreadable``) rather than parked around. That is the The checkpoint named here must be the one that carries THIS question, and that is asserted
one place this layer is louder than the framework: a blocked deserialisation is swallowed into against the declared ``pending_request_info_events`` field rather than inferred from the
a warning upstream, so the alternative to raising here is a question file whose answer can listing being non-empty. **The weaker form went inert under core 1.16.0 (F15, measured):** a
never be applied an exploration that fails as an absence, days later, to somebody who has park now writes TWO checkpoints, and only one of them carries a plan-review type. A
already written their answer. mis-declared ``_ALLOWED_CHECKPOINT_TYPES`` therefore no longer empties the listing it drops
exactly the checkpoint that matters, ``get_latest`` returns the OTHER one, and the old
``latest is None`` guard passed while the question file named a checkpoint that can never bear
the answer. That is the silent dead question this layer exists to refuse, so the guard now
checks the property it always meant rather than the symptom that used to imply it.
Refusing is where this layer is louder than the framework: a blocked deserialisation is
swallowed into a warning upstream, so the alternative to raising here is a question whose
answer can never be applied an exploration that fails as an absence, days later, to somebody
who has already written their answer.
""" """
latest = await checkpoint_storage(checkpoint_dir).get_latest(workflow_name=workflow.name) latest = await checkpoint_storage(checkpoint_dir).get_latest(workflow_name=workflow.name)
if latest is None: if latest is None or str(request.request_id) not in latest.pending_request_info_events:
raise CheckpointUnreadable( raise CheckpointUnreadable(
f"the exploration reached a plan review but no checkpoint could be read back from " f"the exploration reached a plan review but no checkpoint carrying it could be read "
f"{checkpoint_dir!r}: without one the review can never be resumed, so it is refused " f"back from {checkpoint_dir!r}: without one the review can never be resumed, so it is "
f"here rather than written as a question nobody can answer" f"refused here rather than written as a question nobody can answer"
) )
review = request.data review = request.data
return ParkedExploration( return ParkedExploration(

View file

@ -218,7 +218,7 @@ def tracing_notice(setup: TracingSetup) -> str | None:
``None`` when tracing is off omission, never an empty row (``mandate.announce``'s rule, the ``None`` when tracing is off omission, never an empty row (``mandate.announce``'s rule, the
one ``cost_baseline_notice`` and ``skipped_links_notice`` follow). Here it is load-bearing past one ``cost_baseline_notice`` and ``skipped_links_notice`` follow). Here it is load-bearing past
style: the pinned demo stderr is four lines, and a "tracing: off" row would have made it five. style: the pinned demo stderr is two lines, and a "tracing: off" row would have made it three.
The OTLP form names the VARIABLE beside the value, because the variable is what the operator The OTLP form names the VARIABLE beside the value, because the variable is what the operator
edits and prints one row per declared endpoint rather than only the first, so a run exporting edits and prints one row per declared endpoint rather than only the first, so a run exporting

View file

@ -1,4 +1,2 @@
<SITE-PACKAGES>/agent_framework/_skills.py:121: ExperimentalWarning: [SKILLS] SkillResource is experimental and may change or be removed in future versions without notice.
<SITE-PACKAGES>/agent_framework/_harness/_memory.py:651: ExperimentalWarning: [HARNESS] MemoryStore is experimental and may change or be removed in future versions without notice.
(arbeidskopi: <TMPDIR>/po-sim-<SUFFIKS>) (arbeidskopi: <TMPDIR>/po-sim-<SUFFIKS>)

View file

@ -250,9 +250,12 @@ async def test_s4_pending_plan_review_resumes_in_a_fresh_process(tmp_path: Path)
assert first["request_id"], "no plan review was raised -- nothing to resume" assert first["request_id"], "no plan review was raised -- nothing to resume"
assert first["outputs"] == [] assert first["outputs"] == []
assert first["checkpoint_ids"], "no checkpoint was written -- the resume would be vacuous" assert first["checkpoint_ids"], "no checkpoint was written -- the resume would be vacuous"
# F15: the id must be the checkpoint that CARRIES the review, not the last entry of a listing.
# Under core 1.16.0 a park leaves two checkpoints and only one of them can bear the answer.
assert first["resume_checkpoint_id"], "no checkpoint carries the pending review"
resumed = run_resume_subprocess( resumed = run_resume_subprocess(
str(storage), request_id=first["request_id"], checkpoint_id=first["checkpoint_ids"][-1] str(storage), request_id=first["request_id"], checkpoint_id=first["resume_checkpoint_id"]
) )
assert resumed["outputs"] == ["FINAL: the worker did it."] assert resumed["outputs"] == ["FINAL: the worker did it."]
assert resumed["pending_after_resume"] == 0 assert resumed["pending_after_resume"] == 0

View file

@ -903,7 +903,7 @@ def test_an_untraced_exploration_writes_nothing_to_stdout_or_stderr() -> None:
A subprocess and not ``capsys``, for the reason recorded above ``_CHILD_EXPLORATION`` and the A subprocess and not ``capsys``, for the reason recorded above ``_CHILD_EXPLORATION`` and the
stakes are the pinned artefacts: ``tests/golden/demo-transcript.stdout`` is byte-fixed and the stakes are the pinned artefacts: ``tests/golden/demo-transcript.stdout`` is byte-fixed and the
demo's stderr is fixed at four lines, so one stray span dump would break both. demo's stderr is fixed at two lines, so one stray span dump would break both.
``EXPLORATION-OK`` on stderr is the control. Without it, "stdout was empty" would be equally ``EXPLORATION-OK`` on stderr is the control. Without it, "stdout was empty" would be equally
true of a child that crashed on import, which is the fourth face of the verification law: an true of a child that crashed on import, which is the fourth face of the verification law: an

View file

@ -17,8 +17,13 @@ program output, and both were measured to differ between a fresh clone and the w
2. the temp directory behind ``(arbeidskopi: ...)`` a fresh ``mkdtemp`` suffix every run, under a 2. the temp directory behind ``(arbeidskopi: ...)`` a fresh ``mkdtemp`` suffix every run, under a
``TMPDIR`` that is per-user. ``TMPDIR`` that is per-user.
Both are masked; everything else is compared byte for byte. Pinned stderr is four lines: the two Both are masked; everything else is compared byte for byte. **Pinned stderr is two lines: a blank
warnings, a blank line, and the ``arbeidskopi:`` line. line and the ``arbeidskopi:`` line it was four until core 1.16.0 (F15, measured).** MAF moved the
``ExperimentalWarning`` emission from decoration time to first USE (``_feature_stage.py``'s
``_add_runtime_warning``), and the demo instantiates neither ``SkillResource`` nor ``MemoryStore``,
so the two warning lines stopped being emitted upstream they were never suppressed here. Span 1's
``site-packages`` masking is KEPT for that reason: the span is currently unoccupied, not retired,
and a warning that returns must still trip this pin with its path masked.
**The narrowness is the point, and it is under test.** P4 pkt. 2 damped the round-cap notices with a **The narrowness is the point, and it is under test.** P4 pkt. 2 damped the round-cap notices with a
filter keyed on the MESSAGE precisely so that a NEW warning from a MAF bump, or a subtree pull filter keyed on the MESSAGE precisely so that a NEW warning from a MAF bump, or a subtree pull

View file

@ -22,25 +22,33 @@ import pytest
_DIST = "agent-framework-core" _DIST = "agent-framework-core"
#: F15 (2026-08-30): the floor lives in ONE place and the ``pyproject`` assert below DERIVES its
#: expected pin string from it. Two literals for one fact drift (the kø-(p) rule), and a drifted
#: floor is a guard that stops guarding without a local diff.
_MIN_MAJOR = 1
_MIN_MINOR = 16
_MIN_VERSION = f"{_MIN_MAJOR}.{_MIN_MINOR}.0"
def assert_supported_maf_version(version_str: str) -> None: def assert_supported_maf_version(version_str: str) -> None:
"""Raise ``ValueError`` when ``version_str`` is outside the supported ``>=1.9.0,<2`` range, naming """Raise ``ValueError`` when ``version_str`` is outside the supported ``>=1.16.0,<2`` range,
the private-API premises to re-verify before a bump. Pure string parse no import side effects, naming the private-API premises to re-verify before a bump. Pure string parse no import side
so a fake version can be passed directly (the RED-proof) without touching the real install.""" effects, so a fake version can be passed directly (the RED-proof) without touching the real
install."""
parts = version_str.split(".") parts = version_str.split(".")
major = int(parts[0]) major = int(parts[0])
minor = int(parts[1]) if len(parts) > 1 else 0 minor = int(parts[1]) if len(parts) > 1 else 0
if not (major == 1 and minor >= 9): if not (major == _MIN_MAJOR and minor >= _MIN_MINOR):
raise ValueError( raise ValueError(
f"{_DIST} {version_str} is outside the supported range >=1.9.0,<2. Before bumping, " f"{_DIST} {version_str} is outside the supported range >={_MIN_VERSION},<2. Before "
"re-verify the private-API premises the offline sim relies on: the _inner_get_response " "bumping, re-verify the private-API premises the offline sim relies on: the "
"keyword-only signature (messages/options/stream) and the _build_response_stream " "_inner_get_response keyword-only signature (messages/options/stream) and the "
"construction. Update the pin in pyproject.toml once confirmed." "_build_response_stream construction. Update the pin in pyproject.toml once confirmed."
) )
def test_installed_maf_version_is_supported() -> None: def test_installed_maf_version_is_supported() -> None:
"""T-2.5d: the real installed distribution (verified 1.9.0) passes the guard — read from """T-2.5d: the real installed distribution (verified 1.16.0) passes the guard — read from
``importlib.metadata.version``, NOT ``agent_framework.__version__`` (a 0.0.0 placeholder).""" ``importlib.metadata.version``, NOT ``agent_framework.__version__`` (a 0.0.0 placeholder)."""
assert_supported_maf_version(importlib.metadata.version(_DIST)) assert_supported_maf_version(importlib.metadata.version(_DIST))
@ -53,13 +61,18 @@ def test_guard_rejects_future_major() -> None:
def test_guard_rejects_too_old_minor() -> None: def test_guard_rejects_too_old_minor() -> None:
"""T-2.5d: a pre-1.9 minor (``1.8.0``) also trips the guard (the pin is two-sided).""" """T-2.5d / F15: the PREVIOUS floor (``1.9.0``) now trips the guard — the pin is two-sided, and
with pytest.raises(ValueError, match="private-API premises"): this is the arm that makes the F15 lift measurable rather than asserted. ``1.15.0`` is rejected
assert_supported_maf_version("1.8.0") too: ``agent-framework-orchestrations`` 1.1.1 requires ``core>=1.15.0``, but 1.16.0 is the
version whose private-API premises were actually re-verified."""
for stale in ("1.8.0", "1.9.0", "1.15.0"):
with pytest.raises(ValueError, match="private-API premises"):
assert_supported_maf_version(stale)
def test_pyproject_pins_agent_framework_core_below_2() -> None: def test_pyproject_pins_agent_framework_core_below_2() -> None:
"""T-2.5d: ``pyproject.toml`` pins ``agent-framework-core>=1.9.0,<2`` — the install-time half of """T-2.5d: ``pyproject.toml`` pins ``agent-framework-core>=1.16.0,<2`` — the install-time half of
the guard (the test above is the test-time half).""" the guard (the test above is the test-time half). The expected string is DERIVED from
``_MIN_VERSION`` so the two halves cannot drift apart."""
pyproject = (Path(__file__).resolve().parents[1] / "pyproject.toml").read_text(encoding="utf-8") pyproject = (Path(__file__).resolve().parents[1] / "pyproject.toml").read_text(encoding="utf-8")
assert "agent-framework-core>=1.9.0,<2" in pyproject assert f"agent-framework-core>={_MIN_VERSION},<2" in pyproject

View file

@ -240,7 +240,7 @@ def test_notice_is_omitted_when_tracing_is_off() -> None:
"""T8a: no tracing → no line at all (``mandate.announce``'s rule). """T8a: no tracing → no line at all (``mandate.announce``'s rule).
The same rule ``cost_baseline_notice`` and ``skipped_links_notice`` follow, and it is The same rule ``cost_baseline_notice`` and ``skipped_links_notice`` follow, and it is
load-bearing beyond style here: the pinned demo stderr is four lines, and a "tracing: off" row load-bearing beyond style here: the pinned demo stderr is two lines, and a "tracing: off" row
would have made it five. would have made it five.
""" """
assert tracing.tracing_notice(tracing.TracingSetup(mode=None, endpoints=())) is None assert tracing.tracing_notice(tracing.TracingSetup(mode=None, endpoints=())) is None

73
uv.lock generated
View file

@ -15,17 +15,18 @@ resolution-markers = [
[[package]] [[package]]
name = "agent-framework-core" name = "agent-framework-core"
version = "1.9.0" version = "1.16.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "msgspec" },
{ name = "opentelemetry-api" }, { name = "opentelemetry-api" },
{ name = "pydantic" }, { name = "pydantic" },
{ name = "python-dotenv" }, { name = "python-dotenv" },
{ name = "typing-extensions" }, { name = "typing-extensions" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/f1/38/5b4f1f69cfe62ecf0b66838a09d82678dfc0a90084e16b3f1c0f52aa53c3/agent_framework_core-1.9.0.tar.gz", hash = "sha256:09c5f18a43209f6db53dfe0da25d3dfbf1e5176a930a8ec3859091687d8f80a2", size = 449168, upload-time = "2026-06-18T09:42:48.308Z" } sdist = { url = "https://files.pythonhosted.org/packages/b0/96/14e04d00dfc2653677f3f97fa6b348bd202dc4bf4eba4621caabd93ee607/agent_framework_core-1.16.0.tar.gz", hash = "sha256:47ee37b4f6201add7a8a8f9cc39ffe43438c24360b53b116f61ba075e6962d94", size = 584318, upload-time = "2026-08-28T01:10:39.244Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/d9/4b/1c0140cfbb134c51d335274948bcbdcee837a3bdad86bea92ef6b7235d13/agent_framework_core-1.9.0-py3-none-any.whl", hash = "sha256:aa33c588ec839dc7fc8e4768f4ff3d3cd44d4b38d7aa9733f5ee0a37ff4de956", size = 496431, upload-time = "2026-06-18T09:42:46.613Z" }, { url = "https://files.pythonhosted.org/packages/ed/17/7abbfc9e560911967dd5b96a8b6cea537d35efab18f8f77367429159b637/agent_framework_core-1.16.0-py3-none-any.whl", hash = "sha256:382a6a0332cdc3144ffcf14b07a9a38c3ef42afc06dde8230226b850fe4cc76e", size = 641893, upload-time = "2026-08-28T01:10:29.874Z" },
] ]
[[package]] [[package]]
@ -59,14 +60,14 @@ wheels = [
[[package]] [[package]]
name = "agent-framework-orchestrations" name = "agent-framework-orchestrations"
version = "1.0.1" version = "1.1.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "agent-framework-core" }, { name = "agent-framework-core" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/ca/e7/e6a123b74995bba5eaa9e4491e2db3cf94ebd8508df0abefffdec3f86468/agent_framework_orchestrations-1.0.1.tar.gz", hash = "sha256:8441488edb1512d50e0ca70e0bee3ae87a023636cbe860b57b80103b4bac50ec", size = 61003, upload-time = "2026-07-21T19:50:42.112Z" } sdist = { url = "https://files.pythonhosted.org/packages/d8/6f/08ec1b5fb78fe3f64c4d44d696f28ca0a27b839e262e0ff1a422fc518f6e/agent_framework_orchestrations-1.1.1.tar.gz", hash = "sha256:0ea801653b4d3a6578676cf98ee73696b7006f514d5261126144ba76fa0998bf", size = 61785, upload-time = "2026-08-21T23:22:52.954Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/47/5d/a662a69014881e5ee593b39f64b97c0d34fc036c333eab73e9bc10019308/agent_framework_orchestrations-1.0.1-py3-none-any.whl", hash = "sha256:eb10454d462728ab83db14ba42d2c870f58d536966b9b60b525e5e504aa7e8c9", size = 67069, upload-time = "2026-07-21T19:50:13.408Z" }, { url = "https://files.pythonhosted.org/packages/8e/9f/cd51d0859817020606ff2e030ee8b6325f0654cb64f360e01005dee7c97b/agent_framework_orchestrations-1.1.1-py3-none-any.whl", hash = "sha256:14964cf53ce7f30b5cbaeaaa171b5ae15a274ce183d94f646e35d619b2170210", size = 68448, upload-time = "2026-08-21T23:22:41.505Z" },
] ]
[[package]] [[package]]
@ -1159,6 +1160,62 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/5e/75/bd9b7bb966668920f06b200e84454c8f3566b102183bc55c5473d96cb2b9/msal_extensions-1.3.1-py3-none-any.whl", hash = "sha256:96d3de4d034504e969ac5e85bae8106c8373b5c6568e4c8fa7af2eca9dbe6bca", size = 20583, upload-time = "2025-03-14T23:51:03.016Z" }, { url = "https://files.pythonhosted.org/packages/5e/75/bd9b7bb966668920f06b200e84454c8f3566b102183bc55c5473d96cb2b9/msal_extensions-1.3.1-py3-none-any.whl", hash = "sha256:96d3de4d034504e969ac5e85bae8106c8373b5c6568e4c8fa7af2eca9dbe6bca", size = 20583, upload-time = "2025-03-14T23:51:03.016Z" },
] ]
[[package]]
name = "msgspec"
version = "0.21.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/e3/60/f79b9b013a16fa3a58350c9295ddc6789f2e335f36ea61ed10a21b215364/msgspec-0.21.1.tar.gz", hash = "sha256:2313508e394b0d208f8f56892ca9b2799e2561329de9763b19619595a6c0f72c", size = 319193, upload-time = "2026-04-12T21:44:50.394Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/96/38/d591d9f66d43d897ecbd249f2833665823d19c8b043f16619bc8343e23df/msgspec-0.21.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72d9cd03241b8b2edb2e12dcc66c500fa480d8cbd71a8bac105809d468882064", size = 195172, upload-time = "2026-04-12T21:43:45.062Z" },
{ url = "https://files.pythonhosted.org/packages/69/1a/6899188b5982ec1324e0c629b7801eed2db987f6634fab58abd9fc82d317/msgspec-0.21.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed2ab278200e743a1d2610a4e0c8fc74f6cecb8548544cdec43f927bd9265238", size = 188316, upload-time = "2026-04-12T21:43:46.641Z" },
{ url = "https://files.pythonhosted.org/packages/9e/95/7e591b4fa11fdbbf9891164473c23420a8c781ef553295abe416bf335f42/msgspec-0.21.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:dd677e3001fdfed9186de72eab434da2976303cd5eb9550921d3d0c3e3e168ce", size = 216565, upload-time = "2026-04-12T21:43:48.081Z" },
{ url = "https://files.pythonhosted.org/packages/19/86/714feeaf3b84cf2027235681725593840153dedd2868578f9f2715e296bb/msgspec-0.21.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f667b90b37fad734a91671abd68e0d7f4d066862771b87e91c53996dcb7a9027", size = 222689, upload-time = "2026-04-12T21:43:49.385Z" },
{ url = "https://files.pythonhosted.org/packages/7d/b9/4384243e814f2579e5205e17d170b9c1a30121afd1393298d904817a7fa7/msgspec-0.21.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:49880fd20fdbcfe1b793f07dd83f12572bab679c9800352c8b2240289aa46a06", size = 222343, upload-time = "2026-04-12T21:43:50.612Z" },
{ url = "https://files.pythonhosted.org/packages/04/01/4b227d9c4057346271043632bad41979cf8c3dca372e41bb1f7d546395b2/msgspec-0.21.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae0162e22849a5e91eaad907766525107523b0daea3df267a9fcb5ba4e0936ae", size = 225607, upload-time = "2026-04-12T21:43:52.129Z" },
{ url = "https://files.pythonhosted.org/packages/c1/ce/27021d1c3e5da837743092a7b7a5e8818397e1f4c05ee8b068bd7d1fd78a/msgspec-0.21.1-cp310-cp310-win_amd64.whl", hash = "sha256:f041a2279f31e3a53319005e4d60ba77c085cfcbe394cdc7ce803c2d01fe9449", size = 188392, upload-time = "2026-04-12T21:43:53.384Z" },
{ url = "https://files.pythonhosted.org/packages/80/2b/daf7a8d6d7cf00e0dcd0439178b284ade701234abdcadf3385601da04fbd/msgspec-0.21.1-cp310-cp310-win_arm64.whl", hash = "sha256:1bf17cbd7b28a5dffc7e764c654eed8ccde5e0f1de7970628608304640d4ce4e", size = 174191, upload-time = "2026-04-12T21:43:54.6Z" },
{ url = "https://files.pythonhosted.org/packages/ba/7f/bbc4e74cd33d316b75541149e4d35b163b63bce066530ae185a2ec3b5bfc/msgspec-0.21.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b504b6e7f7a22a24b27232b73034421692147865162daaec9f3bf62439007c87", size = 193131, upload-time = "2026-04-12T21:43:56.094Z" },
{ url = "https://files.pythonhosted.org/packages/c1/60/504886af1aaf854112663b842d5eea9a15d9588f9bf7d0d2df736424b84d/msgspec-0.21.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4692b7c1609155708c4418f88e92f63c13fdf08aa095c84bae82bad75b53389b", size = 186597, upload-time = "2026-04-12T21:43:57.242Z" },
{ url = "https://files.pythonhosted.org/packages/fa/54/d24ddeaa65b5278c9e67f48ce3c17a9831e8f3722f3c8322ee120aca22ef/msgspec-0.21.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d3124010b3815451494c85ff345e693cb9fe5889cfcbbef39ed8622e0e72319c", size = 215158, upload-time = "2026-04-12T21:43:58.442Z" },
{ url = "https://files.pythonhosted.org/packages/9f/75/bb79c8b89a93ae23cd33c0d802373f16feaf9633f05d8af77091350dda0a/msgspec-0.21.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6badc03b9725352219cca017bfe71c61f2fbd0fb5982b410ac17c97c213deb30", size = 219856, upload-time = "2026-04-12T21:44:00.015Z" },
{ url = "https://files.pythonhosted.org/packages/b4/9c/c5ca26b46f0ebbd3a6683695ef89396712cb9e4199fd1f0bc1dd968216b1/msgspec-0.21.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5d2d4116ebe3035a78d9ec76e99a9d64e5fa6d44fe61a9c5de7fd1acf54bcc69", size = 220314, upload-time = "2026-04-12T21:44:01.548Z" },
{ url = "https://files.pythonhosted.org/packages/c8/31/645a351c4285dce40ed6755c3dcc0aa648e26dacb20a98018fe2cce5e87b/msgspec-0.21.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0d1009f6715f5bff3b54d4ff5c7428ad96197e0534e1645b8e9b955890c84664", size = 223215, upload-time = "2026-04-12T21:44:02.884Z" },
{ url = "https://files.pythonhosted.org/packages/09/af/8bf15736a6dd3cb4f90c5467f6dc39197d2daaf10754490cdc0aa17b7312/msgspec-0.21.1-cp311-cp311-win_amd64.whl", hash = "sha256:c6faffe5bb644ec884052679af4dfd776d4b5ca90e4a7ec7e7e319e4e6b93a6e", size = 188554, upload-time = "2026-04-12T21:44:04.151Z" },
{ url = "https://files.pythonhosted.org/packages/ef/29/cc7db3a165b62d16e64a83f82eccb79655055cb5bc1f60459a6f9d7c82f2/msgspec-0.21.1-cp311-cp311-win_arm64.whl", hash = "sha256:ee9e3f11fa94603f7d673bf795cfa31b549c4a2c723bc39b45beb1e7f5a3fb99", size = 174517, upload-time = "2026-04-12T21:44:05.66Z" },
{ url = "https://files.pythonhosted.org/packages/6e/cf/317224852c00248c620a9bcf4b26e2e4ab8afd752f18d2a6ef73ebd423b6/msgspec-0.21.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4248cf0b6129b7d230eacd493c17cc2d4f3989f3bb7f633a928a85b7dcfa251", size = 196188, upload-time = "2026-04-12T21:44:07.181Z" },
{ url = "https://files.pythonhosted.org/packages/6d/81/074612945c0666078f7366f40000013de9f6ba687491d450df699bceebc9/msgspec-0.21.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5102c7e9b3acff82178449b85006d96310e690291bb1ea0142f1b24bcb8aabcb", size = 188473, upload-time = "2026-04-12T21:44:08.736Z" },
{ url = "https://files.pythonhosted.org/packages/8a/37/655101799590bcc5fddb2bd3fe0e6194e816c2d1da7c361725f5eb89a910/msgspec-0.21.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:846758412e9518252b2ac9bffd6f0e54d9ff614f5f9488df7749f81ff5c80920", size = 218871, upload-time = "2026-04-12T21:44:09.917Z" },
{ url = "https://files.pythonhosted.org/packages/b5/d1/d4cd9fe89c7d400d7a18f86ccc94daa3f0927f53558846fcb60791dce5d6/msgspec-0.21.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:21995e74b5c598c2e004110ad66ec7f1b8c20bf2bcf3b2de8fd9a3094422d3ff", size = 225025, upload-time = "2026-04-12T21:44:11.191Z" },
{ url = "https://files.pythonhosted.org/packages/24/bf/e20549e602b9edccadeeff98760345a416f9cce846a657e8b18e3396b212/msgspec-0.21.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6129f0cca52992e898fd5344187f7c8127b63d810b2fd73e36fca73b4c6475ee", size = 222672, upload-time = "2026-04-12T21:44:12.481Z" },
{ url = "https://files.pythonhosted.org/packages/b4/68/04d7a8f0f786545cf9b8c280c57aa6befb5977af6e884b8b54191cbe44b3/msgspec-0.21.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ef3ec2296248d1f8b9231acb051b6d471dfde8f21819e86c9adaaa9f42918521", size = 227303, upload-time = "2026-04-12T21:44:13.709Z" },
{ url = "https://files.pythonhosted.org/packages/cc/4d/619866af2840875be408047bf9e70ceafbae6ab50660de7134ed1b25eb86/msgspec-0.21.1-cp312-cp312-win_amd64.whl", hash = "sha256:d4ab834a054c6f0cbeef6df9e7e1b33d5f1bc7b86dea1d2fd7cad003873e783d", size = 190017, upload-time = "2026-04-12T21:44:14.977Z" },
{ url = "https://files.pythonhosted.org/packages/5e/2e/a8f9eca8fd00e097d7a9e99ba8a4685db994494448e3d4f0b7f6e9a3c0f7/msgspec-0.21.1-cp312-cp312-win_arm64.whl", hash = "sha256:628aaa35c74950a8c59da330d7e98917e1c7188f983745782027748ee4ca573e", size = 175345, upload-time = "2026-04-12T21:44:16.431Z" },
{ url = "https://files.pythonhosted.org/packages/7e/74/f11ede02839b19ff459f88e3145df5d711626ca84da4e23520cebf819367/msgspec-0.21.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:764173717a01743f007e9f74520ed281f24672c604514f7d76c1c3a10e8edb66", size = 196176, upload-time = "2026-04-12T21:44:17.613Z" },
{ url = "https://files.pythonhosted.org/packages/bb/40/4476c1bd341418a046c4955aff632ec769315d1e3cb94e6acf86d461f9ed/msgspec-0.21.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:344c7cd0eaed1fb81d7959f99100ef71ec9b536881a376f11b9a6c4803365697", size = 188524, upload-time = "2026-04-12T21:44:18.815Z" },
{ url = "https://files.pythonhosted.org/packages/ca/d9/9e9d7d7e5061b47540d03d640fab9b3965ba7ae49c1b2154861c8f007518/msgspec-0.21.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48943e278b3854c2f89f955ddc6f9f430d3f0784b16e47d10604ee0463cd21f5", size = 218880, upload-time = "2026-04-12T21:44:20.028Z" },
{ url = "https://files.pythonhosted.org/packages/74/66/2bb344f34abb4b57e60c7c9c761994e0417b9718ec1460bf00c296f2a7ea/msgspec-0.21.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9aa659ebb0101b1cbc31461212b87e341d961f0ab0772aaf068a99e001ec4aa", size = 225050, upload-time = "2026-04-12T21:44:21.577Z" },
{ url = "https://files.pythonhosted.org/packages/1a/84/7c1e412f76092277bf760cef12b7979d03314d259ab5b5cafde5d0c1722d/msgspec-0.21.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7b27d1a8ead2b6f5b0c4f2d07b8be1ccfcc041c8a0e704781edebe3ae13c484", size = 222713, upload-time = "2026-04-12T21:44:22.83Z" },
{ url = "https://files.pythonhosted.org/packages/4e/27/0bba04b2b4ef05f3d068429410bc71d2cea925f1596a8f41152cccd5edb8/msgspec-0.21.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38fe93e86b61328fe544cb7fd871fad5a27c8734bfda90f65e5dbe288ae50f61", size = 227259, upload-time = "2026-04-12T21:44:24.11Z" },
{ url = "https://files.pythonhosted.org/packages/b0/2d/09574b0eea02fed2c2c1383dbaae2c7f79dc16dcd6487a886000afb5d7c4/msgspec-0.21.1-cp313-cp313-win_amd64.whl", hash = "sha256:8bc666331c35fcce05a7cd2d6221adbe0f6058f8e750711413d22793c080ac6a", size = 189857, upload-time = "2026-04-12T21:44:25.359Z" },
{ url = "https://files.pythonhosted.org/packages/46/34/105b1576ad182879914f0c821f17ee1d13abb165cb060448f96fe2aff078/msgspec-0.21.1-cp313-cp313-win_arm64.whl", hash = "sha256:42bb1241e0750c1a4346f2aa84db26c5ffd99a4eb3a954927d9f149ff2f42898", size = 175403, upload-time = "2026-04-12T21:44:26.608Z" },
{ url = "https://files.pythonhosted.org/packages/5a/ad/86954e987d1d6a5c579e2c2e7832b65e0fff194179fdac4f581536086024/msgspec-0.21.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fab48eb45fdbfbdb2c0edfec00ffc53b6b6085beefc6b50b61e01659f9f8757f", size = 196261, upload-time = "2026-04-12T21:44:27.807Z" },
{ url = "https://files.pythonhosted.org/packages/d1/a1/c5e46c3e42b866199365e35d11dddfd1fbd8bba4fdb3c52f965b1607ce94/msgspec-0.21.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3cb779ea0c35bc807ff941d415875c1f69ca0be91a2e907ab99a171811d86a9a", size = 188729, upload-time = "2026-04-12T21:44:28.99Z" },
{ url = "https://files.pythonhosted.org/packages/85/7d/1e29a319d678d6cb962ae5bdf32a6858ebdf38f73bc654c0e9c742a0c2c8/msgspec-0.21.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:68604db36b3b4dd9bf160e436e12798a4738848144cea1aca1cb984011eb160f", size = 219866, upload-time = "2026-04-12T21:44:31.104Z" },
{ url = "https://files.pythonhosted.org/packages/25/1f/cca084ca2572810fff12ea9dbdcbe39eac048f40daf4a9077b49fcbe8cee/msgspec-0.21.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3d6b9dc50948eaf65df54d2fd0ff66e6d8c32f116037209ee861810eb9b676cb", size = 224993, upload-time = "2026-04-12T21:44:32.649Z" },
{ url = "https://files.pythonhosted.org/packages/71/94/d2120fc9d419a89a3a7c13e5b7078798c4b392a96a02a6e2b3ce43a8766c/msgspec-0.21.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:52c5e21930942302394429c5a582ce7e6b62c7f983b3760834c2ce107e0dd6df", size = 223535, upload-time = "2026-04-12T21:44:33.839Z" },
{ url = "https://files.pythonhosted.org/packages/75/17/42418b66a3ad972a89bab73dd78b79cc6282bb488a25e73c853cee7443b9/msgspec-0.21.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:abbb39d65681fa24ed394e01af3d59d869068324f900c61d06062b7fb9980f2f", size = 227222, upload-time = "2026-04-12T21:44:35.093Z" },
{ url = "https://files.pythonhosted.org/packages/c4/33/265c894268cca88ff67b144ca2b4c522fc8b9a6f1966a3640c70516e78e1/msgspec-0.21.1-cp314-cp314-win_amd64.whl", hash = "sha256:5666b1b560b97b6ec2eb3fca8a502298ebac56e13bbca1f88523538ce83d01ea", size = 193810, upload-time = "2026-04-12T21:44:36.612Z" },
{ url = "https://files.pythonhosted.org/packages/3b/8f/a6d35f25bf1fc63c492fdd88fdce01ba0875ead48c2b91f90f33653b4131/msgspec-0.21.1-cp314-cp314-win_arm64.whl", hash = "sha256:d8b8578e4c83b14ceea4cef0d0b747e31d9330fe4b03b2b2ad4063866a178f93", size = 179125, upload-time = "2026-04-12T21:44:38.198Z" },
{ url = "https://files.pythonhosted.org/packages/c6/39/74839641e64b99d87da55af0fc472854d42b46e2183b9e2a67fe1bb2a512/msgspec-0.21.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:15f523d51c00ebad412213bfe9f06f0a50ec2b93e0c19e824a2d267cabb48ea2", size = 200171, upload-time = "2026-04-12T21:44:39.414Z" },
{ url = "https://files.pythonhosted.org/packages/70/9b/ce0cca6d2d87fcd4b6ff97600790494e64f26a2c55d61507cd2755c16193/msgspec-0.21.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:4e47390360583ba3d5c6cb44cf0a9f61b0a06a899d3c2c00627cedebb2e2884b", size = 192879, upload-time = "2026-04-12T21:44:40.882Z" },
{ url = "https://files.pythonhosted.org/packages/a7/08/673a7bb05e5702dc787ddd3011195b509f9867927970da59052211929987/msgspec-0.21.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f60800e6299b798142dc40b0644da77ceac5ea0568be58228417eae14135c847", size = 226281, upload-time = "2026-04-12T21:44:42.181Z" },
{ url = "https://files.pythonhosted.org/packages/7d/45/86508cf57283e9070b3c447e3ab25b792a7a0855a3ea4e0c6d111ac34c97/msgspec-0.21.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5f8e9dfcd98419cf7568808470c4317a3fb30bef0e3715b568730a2b272a20d7", size = 229863, upload-time = "2026-04-12T21:44:43.442Z" },
{ url = "https://files.pythonhosted.org/packages/2c/62/e7c9367cd08d590559faacd711edbae36840342843e669440363f33c7d36/msgspec-0.21.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:92d89dfad13bd1ea640dc3e37e724ed380da1030b272bdf5ecafb983c3ad7c75", size = 230445, upload-time = "2026-04-12T21:44:44.806Z" },
{ url = "https://files.pythonhosted.org/packages/42/b4/c0f54632103846b658a10930025f4de41c8724b5e4805a5f3b395586cb7e/msgspec-0.21.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0d03867786e5d7ba25d666df4b11320c27170f4aeafcb8e3a8b0a50a4fb742ca", size = 231822, upload-time = "2026-04-12T21:44:46.343Z" },
{ url = "https://files.pythonhosted.org/packages/ea/1d/0d85cc79d0ccf5508e9c846cc66552a6a16bf92abd1dbd8362617f7b35cd/msgspec-0.21.1-cp314-cp314t-win_amd64.whl", hash = "sha256:740fbf1c9d59992ca3537d6fbe9ebbf9eaf726a65fbf31448e0ecbc710697a63", size = 206650, upload-time = "2026-04-12T21:44:47.601Z" },
{ url = "https://files.pythonhosted.org/packages/90/91/56c5d560f20e6c20e9e4f55bd0e458f7f162aa689ee350346c04c48eac0b/msgspec-0.21.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0d2cc73df6058d811a126ac3a8ad63a4dfa210c82f9cf5a004802eaf4712de90", size = 183149, upload-time = "2026-04-12T21:44:48.833Z" },
]
[[package]] [[package]]
name = "multidict" name = "multidict"
version = "6.7.1" version = "6.7.1"
@ -1542,10 +1599,10 @@ dev = [
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "agent-framework-core", specifier = ">=1.9.0,<2" }, { name = "agent-framework-core", specifier = ">=1.16.0,<2" },
{ name = "agent-framework-foundry", specifier = ">=1.8.2" }, { name = "agent-framework-foundry", specifier = ">=1.8.2" },
{ name = "agent-framework-openai", specifier = ">=1.8.2" }, { name = "agent-framework-openai", specifier = ">=1.8.2" },
{ name = "agent-framework-orchestrations", specifier = ">=1.0.0" }, { name = "agent-framework-orchestrations", specifier = ">=1.1.1" },
{ name = "anyio", specifier = ">=4.14" }, { name = "anyio", specifier = ">=4.14" },
{ name = "azure-identity", specifier = ">=1.25" }, { name = "azure-identity", specifier = ">=1.25" },
{ name = "llm-ingestion-guard", git = "https://git.fromaitochitta.com/open/llm-ingestion-pipeline-security.git?rev=v0.3.4" }, { name = "llm-ingestion-guard", git = "https://git.fromaitochitta.com/open/llm-ingestion-pipeline-security.git?rev=v0.3.4" },