From 930285096dd054db810c8d6b5881d5e83ef0bd5f Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 25 Jun 2026 19:42:35 +0300 Subject: [PATCH 1/3] chore: adopt canonical planning convention Vendor index.py + _templates/ verbatim from lesnik512/planning-convention (v1.0.0), slim every bundle's frontmatter to the lean form (summary-only specs; plans carry none; date/slug derived from the dir/file name), rewrite planning/README.md to the canonical Quick-path + Conventions prose, wire the planning validator into just lint-ci, add a check-planning recipe, record the applied version in planning/.convention-version. Co-Authored-By: Claude Opus 4.8 (1M context) --- Justfile | 7 +- planning/.convention-version | 1 + planning/README.md | 77 +++++++--- planning/_templates/change.md | 9 +- planning/_templates/decision.md | 3 - planning/_templates/design.md | 9 +- planning/_templates/plan.md | 12 +- planning/_templates/release.md | 39 ++++++ .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../2026-05-31.07-asyncclient/design.md | 7 - .../changes/2026-05-31.07-asyncclient/plan.md | 8 -- .../2026-05-31.08-recordedtransport/design.md | 7 - .../2026-05-31.08-recordedtransport/plan.md | 8 -- .../design.md | 7 - .../2026-05-31.09-release-0.1.0-prep/plan.md | 8 -- .../2026-06-01.01-auth-coercion/design.md | 7 - .../2026-06-01.01-auth-coercion/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../2026-06-03.02-thin-httpx2-wrapper/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../design.md | 7 - .../plan.md | 8 -- .../changes/2026-06-05.02-bulkhead/design.md | 7 - .../changes/2026-06-05.02-bulkhead/plan.md | 8 -- .../2026-06-05.03-docs-sync-0.4/design.md | 7 - .../2026-06-05.03-docs-sync-0.4/plan.md | 8 -- .../changes/2026-06-05.04-streaming/design.md | 7 - .../changes/2026-06-05.04-streaming/plan.md | 8 -- .../2026-06-05.05-observability/design.md | 7 - .../2026-06-05.05-observability/plan.md | 8 -- .../design.md | 7 - .../2026-06-05.06-extension-slot-docs/plan.md | 8 -- .../design.md | 7 - .../2026-06-05.07-v0.7-docs-expansion/plan.md | 8 -- .../2026-06-06.01-modern-di-recipe/design.md | 7 - .../2026-06-06.01-modern-di-recipe/plan.md | 8 -- .../2026-06-07.01-sync-client/design.md | 7 - .../changes/2026-06-07.01-sync-client/plan.md | 8 -- .../2026-06-07.02-decoder-error/design.md | 7 - .../2026-06-07.02-decoder-error/plan.md | 8 -- .../2026-06-07.03-deep-audit/design.md | 7 - .../changes/2026-06-07.03-deep-audit/plan.md | 8 -- .../design.md | 7 - .../2026-06-08.01-send-with-response/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../2026-06-08.03-post-080-doc-sweep/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../2026-06-08.05-small-fixes-mop-up/plan.md | 8 -- .../2026-06-08.06-test-mop-up/design.md | 7 - .../changes/2026-06-08.06-test-mop-up/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../2026-06-08.08-readme-link-cleanup/plan.md | 8 -- .../2026-06-10.01-multi-decoder/design.md | 7 - .../2026-06-10.01-multi-decoder/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../2026-06-12.01-delta-audit/design.md | 7 - .../changes/2026-06-12.01-delta-audit/plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../change.md | 7 - .../change.md | 7 - .../2026-06-14.01-deep-audit/design.md | 7 - .../changes/2026-06-14.01-deep-audit/plan.md | 8 -- .../design.md | 7 - .../2026-06-14.01-docs-ux-restructure/plan.md | 8 -- .../change.md | 7 - .../design.md | 7 - .../2026-06-14.03-security-hardening/plan.md | 8 -- .../2026-06-14.04-audit-correctness/change.md | 7 - .../change.md | 7 - .../2026-06-14.06-audit-doc-fixes/change.md | 7 - .../change.md | 7 - .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../change.md | 7 - .../design.md | 7 - .../plan.md | 8 -- .../design.md | 7 - .../plan.md | 8 -- .../2026-06-23.03-response-body-cap/design.md | 7 - .../2026-06-23.03-response-body-cap/plan.md | 8 -- planning/index.py | 132 ++++++++++++++---- 114 files changed, 209 insertions(+), 862 deletions(-) create mode 100644 planning/.convention-version create mode 100644 planning/_templates/release.md diff --git a/Justfile b/Justfile index 6d392ee..529fedb 100644 --- a/Justfile +++ b/Justfile @@ -15,11 +15,16 @@ lint-ci: uv run ruff format --check uv run ruff check --no-fix uv run ty check + uv run python planning/index.py --check -# Print the planning change index (grouped by status) to stdout. +# Print the planning change index (flat, newest-first) to stdout. index: uv run python planning/index.py +# Validate planning bundles + decisions; CI runs this via lint-ci. +check-planning: + uv run python planning/index.py --check + test *args: uv run --no-sync pytest {{ args }} diff --git a/planning/.convention-version b/planning/.convention-version new file mode 100644 index 0000000..3eefcb9 --- /dev/null +++ b/planning/.convention-version @@ -0,0 +1 @@ +1.0.0 diff --git a/planning/README.md b/planning/README.md index 401b955..f74a081 100644 --- a/planning/README.md +++ b/planning/README.md @@ -4,12 +4,42 @@ Specs, plans, and change history for `httpware`. The living truth about *what the system does now* lives in [`architecture/`](../architecture/) at the repo root; this directory records *how it got there*. +## Quick path (start here) + +> The fast lane for making a change. The full reference is in +> [Conventions](#conventions) below — read it only when this isn't enough. + +**1. Choose a lane — first matching rule wins:** + +1. Any of: needs design judgment · new file/module · public-API change · + cross-cutting or multi-file · non-trivial test design → **Full** + (`design.md` + `plan.md`) +2. Purely mechanical: typo · dep bump · linter/formatter/CI tweak · + mechanical rename · single-line config → **Tiny** (no bundle, conventional + commit) +3. Small-but-real, none of the above: ≲30 LOC net · ≤2 files · no new file · + no public-API change · one straightforward test → **Lightweight** + (`change.md`) + +Ambiguous between two? Take the heavier. A `change.md` that outgrows its lane +splits into `design.md` + `plan.md`. + +**2. Create the bundle** (Full / Lightweight only): +`planning/changes/YYYY-MM-DD.NN-/`, where `.NN` is a zero-padded +intra-day counter. Copy the matching template from +[`_templates/`](_templates/). + +**3. Ship in the implementing PR:** hand-edit the affected +`architecture/.md`, finalize the bundle's `summary:` to the +realized result, and run `just check-planning` before pushing. + ## Conventions -> This section is the portable convention — identical across the -> modern-python repos. The generated change listing (`just index`) and the `## Other` pointers below are repo-local. To adopt elsewhere, -> copy this section plus [`_templates/`](_templates/) and point that repo's -> `CLAUDE.md` Workflow + truth home at it. +> This is the portable convention, sourced from the canonical repo +> [`lesnik512/planning-convention`](https://github.com/lesnik512/planning-convention) +> (applied version in [`.convention-version`](.convention-version)). To update +> it, run that repo's `APPLY.md` flow. The generated change index (`just index`) +> and the `## Other` pointers below are repo-local. ### Two axes, never mixed @@ -32,10 +62,11 @@ A change is a folder `changes/YYYY-MM-DD.NN-/`: (`.01`, `.02`, …) that breaks same-date ties so the timeline sorts stably. - `` — kebab-case description, not a story ID. -`summary` is written when the change is created (it is the change's -one-liner). The implementing PR then sets `status: shipped` and fills `pr` -and `outcome` **in the branch**, alongside the code and the `architecture/` -promotion — no post-merge bookkeeping, no folder move. +`summary` is written when the change is created (the intent one-liner) and +**finalized at ship** to state the realized result — set in the implementing +PR, alongside the code and the `architecture/` promotion. No post-merge +bookkeeping, no folder move. `date` and `slug` are never written — they are +read from the bundle's directory name. ### Three lanes @@ -53,32 +84,38 @@ into `design.md` + `plan.md`. - **`design.md`** — the spec: the *thinking* (why, design, trade-offs, scope). - **`plan.md`** — the plan: the *sequencing* (the executor's task checklist). - **`change.md`** — both, condensed, for the lightweight lane. -- **`decisions/-.md`** — one file per design decision taken - (especially options *rejected*), each with a revisit trigger, so reviews don't - re-litigate them; listed by `just index`. - **`releases/.md`** — per-release user-facing notes. - **`audits/-.md`** — findings from a code/docs/bug-hunt sweep; spawns fix changes. - **`retros/-.md`** — what we learned after a body of work. - **`deferred.md`** — real-but-unscheduled items, each with a revisit trigger. +- **`decisions/-.md`** — one file per design decision taken + (especially options *rejected*), each with a revisit trigger; listed by + `just index`. Templates live in [`_templates/`](_templates/). ### Frontmatter -`design.md` / `change.md`: `status` (draft|approved|shipped|superseded), -`date`, `slug`, `summary` (single line), `supersedes`, `superseded_by`, `pr`, -`outcome`. `plan.md`: `status`, `date`, `slug`, `spec`, `pr`. -`decisions/*.md`: `status` (accepted|superseded), `date`, `slug`, `summary`, -`supersedes`, `superseded_by`, `pr`. -Files in `architecture/` carry **no** frontmatter — living prose, dated by git. +`date` and `slug` are **derived from the directory / file name** — never +repeated in frontmatter. So: + +- `design.md` / `change.md`: `summary` (single line) only. +- `plan.md`: **no frontmatter** — its identity is the bundle directory. +- `decisions/*.md`: `status` (accepted|superseded), `summary`, and optional + `supersedes` / `superseded_by`. +- Files in `architecture/` carry **no** frontmatter — living prose, dated by git. + +**`summary`** is one line: written at creation as the intent, then **finalized +at ship** to state the realized result — what shipped and its effect. It is the +only field the index renders. ## Index The listing is **generated**, not maintained — run `just index` to print it: -changes grouped by `status` (In progress / Shipped / Superseded), then -decisions newest-first. The frontmatter in each bundle / decision file is the -single source of truth; there is no committed copy to drift. +changes as a flat newest-first list, then decisions newest-first. Each bundle's +`summary` frontmatter (and the directory name, which supplies `date`/`slug`) is +the single source of truth; there is no committed copy to drift. ## Other diff --git a/planning/_templates/change.md b/planning/_templates/change.md index 7ffec26..d4c8962 100644 --- a/planning/_templates/change.md +++ b/planning/_templates/change.md @@ -1,12 +1,5 @@ --- -status: draft -date: YYYY-MM-DD -slug: my-change -summary: One line — shown in the generated index. Fill at ship time. -supersedes: null -superseded_by: null -pr: null -outcome: null +summary: One line — shown in the generated index. Written at creation; finalize at ship to state the realized result. --- # Change: One-line capitalized title diff --git a/planning/_templates/decision.md b/planning/_templates/decision.md index 940fb37..45ccaf0 100644 --- a/planning/_templates/decision.md +++ b/planning/_templates/decision.md @@ -1,11 +1,8 @@ --- status: accepted # accepted | superseded -date: YYYY-MM-DD -slug: my-decision summary: One line — shown in `just index`. supersedes: null superseded_by: null -pr: null # PR/commit where the decision was made or recorded --- # One-line capitalized title diff --git a/planning/_templates/design.md b/planning/_templates/design.md index b9e11c9..d63e22d 100644 --- a/planning/_templates/design.md +++ b/planning/_templates/design.md @@ -1,12 +1,5 @@ --- -status: draft -date: YYYY-MM-DD -slug: my-change -summary: One line — shown in the generated index. Fill at ship time. -supersedes: null -superseded_by: null -pr: null -outcome: null +summary: One line — shown in the generated index. Written at creation; finalize at ship to state the realized result. --- # Design: One-line capitalized title diff --git a/planning/_templates/plan.md b/planning/_templates/plan.md index f2b90e8..132d720 100644 --- a/planning/_templates/plan.md +++ b/planning/_templates/plan.md @@ -1,11 +1,3 @@ ---- -status: draft -date: YYYY-MM-DD -slug: my-change -spec: my-change -pr: null ---- - # — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use @@ -46,9 +38,7 @@ in the spec. ```bash git add path/to/file.py - git commit -m ": - - Co-Authored-By: Claude Opus 4.7 (1M context) " + git commit -m ": " ``` --- diff --git a/planning/_templates/release.md b/planning/_templates/release.md new file mode 100644 index 0000000..7372d7e --- /dev/null +++ b/planning/_templates/release.md @@ -0,0 +1,39 @@ +# modern-di + + + + + +## Feature + +- **.** What it adds and how to use it. + +## Fix + +- **.** What was broken, now fixed (reference the issue/regression). + +## Internal refactors + +- **.** What changed under the hood, stated as no behavior change. + +## Packaging + +- Metadata / build / dependency changes visible to installers. + +## Why + +Context a reader needs for the headline change. Omit for small releases. + +## Downstream + +What integrations (FastAPI, Litestar, FastStream, Typer, `modern-di-pytest`) +must do — e.g. bump their `modern-di` floor — or "No action needed" when there +is no API change. + +## Internals + +- Coverage / tooling notes (e.g. 100% line coverage across Python 3.10–3.14). diff --git a/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/design.md b/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/design.md index 93be299..92fc344 100644 --- a/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/design.md +++ b/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: bmad-to-superpowers-transition summary: Bootstrapped the planning workflow -supersedes: null -superseded_by: null -pr: 6 -outcome: 'Bootstrapped the planning workflow' --- # bmad → superpowers transition (design) diff --git a/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/plan.md b/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/plan.md index bdb1718..12ff9bb 100644 --- a/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/plan.md +++ b/planning/changes/2026-05-31.01-bmad-to-superpowers-transition/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: bmad-to-superpowers-transition -spec: bmad-to-superpowers-transition -pr: 6 ---- - # bmad → superpowers transition Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.02-shipped-work-review/design.md b/planning/changes/2026-05-31.02-shipped-work-review/design.md index 198dd43..a09d26c 100644 --- a/planning/changes/2026-05-31.02-shipped-work-review/design.md +++ b/planning/changes/2026-05-31.02-shipped-work-review/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: shipped-work-review summary: 0.1.0-era review of shipped stories -supersedes: null -superseded_by: null -pr: 7 -outcome: '0.1.0-era review of shipped stories' --- # Retrospective code review — stories 1-1 through 1-5 diff --git a/planning/changes/2026-05-31.03-middleware-protocol-and-chain/design.md b/planning/changes/2026-05-31.03-middleware-protocol-and-chain/design.md index 442aec3..598084d 100644 --- a/planning/changes/2026-05-31.03-middleware-protocol-and-chain/design.md +++ b/planning/changes/2026-05-31.03-middleware-protocol-and-chain/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: middleware-protocol-and-chain summary: Shipped in 0.1.0; survived the v0.2 pivot -supersedes: null -superseded_by: null -pr: 8 -outcome: 'Shipped in 0.1.0; survived the v0.2 pivot' --- # Middleware protocol and chain composition (design) diff --git a/planning/changes/2026-05-31.03-middleware-protocol-and-chain/plan.md b/planning/changes/2026-05-31.03-middleware-protocol-and-chain/plan.md index 1da5b54..6330762 100644 --- a/planning/changes/2026-05-31.03-middleware-protocol-and-chain/plan.md +++ b/planning/changes/2026-05-31.03-middleware-protocol-and-chain/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: middleware-protocol-and-chain -spec: middleware-protocol-and-chain -pr: 8 ---- - # Middleware protocol and chain composition Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.04-phase-shortcut-decorators/design.md b/planning/changes/2026-05-31.04-phase-shortcut-decorators/design.md index 01051b7..002bee8 100644 --- a/planning/changes/2026-05-31.04-phase-shortcut-decorators/design.md +++ b/planning/changes/2026-05-31.04-phase-shortcut-decorators/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: phase-shortcut-decorators summary: Shipped in 0.1.0; survived the v0.2 pivot -supersedes: null -superseded_by: null -pr: 9 -outcome: 'Shipped in 0.1.0; survived the v0.2 pivot' --- # Phase-shortcut decorators (design) diff --git a/planning/changes/2026-05-31.04-phase-shortcut-decorators/plan.md b/planning/changes/2026-05-31.04-phase-shortcut-decorators/plan.md index 25161f4..5a0d92e 100644 --- a/planning/changes/2026-05-31.04-phase-shortcut-decorators/plan.md +++ b/planning/changes/2026-05-31.04-phase-shortcut-decorators/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: phase-shortcut-decorators -spec: phase-shortcut-decorators -pr: 9 ---- - # Phase-shortcut decorators Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.05-request-immutability-helpers/design.md b/planning/changes/2026-05-31.05-request-immutability-helpers/design.md index 8e1f33e..a3b3f27 100644 --- a/planning/changes/2026-05-31.05-request-immutability-helpers/design.md +++ b/planning/changes/2026-05-31.05-request-immutability-helpers/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: request-immutability-helpers summary: Shipped in 0.1.0; removed by the v0.2 pivot *(superseded by thin-httpx2-wrapper)* -supersedes: null -superseded_by: 2026-06-03.02-thin-httpx2-wrapper -pr: 10 -outcome: 'Shipped in 0.1.0; removed by the v0.2 pivot' --- # Request / Response immutability helper expansion (design) diff --git a/planning/changes/2026-05-31.05-request-immutability-helpers/plan.md b/planning/changes/2026-05-31.05-request-immutability-helpers/plan.md index 737e51f..6eb95a3 100644 --- a/planning/changes/2026-05-31.05-request-immutability-helpers/plan.md +++ b/planning/changes/2026-05-31.05-request-immutability-helpers/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: request-immutability-helpers -spec: request-immutability-helpers -pr: 10 ---- - # Request / Response immutability helper expansion Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/design.md b/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/design.md index abaa034..f18247c 100644 --- a/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/design.md +++ b/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: msgspec-decoder-via-extras summary: Shipped in 0.1.0; carry-forward decoder -supersedes: null -superseded_by: null -pr: 11 -outcome: 'Shipped in 0.1.0; carry-forward decoder' --- # msgspec decoder via extras (design) diff --git a/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/plan.md b/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/plan.md index df878ef..b8542a1 100644 --- a/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/plan.md +++ b/planning/changes/2026-05-31.06-msgspec-decoder-via-extras/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: msgspec-decoder-via-extras -spec: msgspec-decoder-via-extras -pr: 11 ---- - # msgspec decoder via extras Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.07-asyncclient/design.md b/planning/changes/2026-05-31.07-asyncclient/design.md index 305e3e3..6fa1222 100644 --- a/planning/changes/2026-05-31.07-asyncclient/design.md +++ b/planning/changes/2026-05-31.07-asyncclient/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: asyncclient summary: Shipped in 0.1.0; rewritten by the v0.2 pivot *(superseded by thin-httpx2-wrapper)* -supersedes: null -superseded_by: 2026-06-03.02-thin-httpx2-wrapper -pr: 12 -outcome: 'Shipped in 0.1.0; rewritten by the v0.2 pivot' --- # AsyncClient (design) diff --git a/planning/changes/2026-05-31.07-asyncclient/plan.md b/planning/changes/2026-05-31.07-asyncclient/plan.md index 130cbde..c10d715 100644 --- a/planning/changes/2026-05-31.07-asyncclient/plan.md +++ b/planning/changes/2026-05-31.07-asyncclient/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: asyncclient -spec: asyncclient -pr: 12 ---- - # AsyncClient Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.08-recordedtransport/design.md b/planning/changes/2026-05-31.08-recordedtransport/design.md index 7312383..b14d384 100644 --- a/planning/changes/2026-05-31.08-recordedtransport/design.md +++ b/planning/changes/2026-05-31.08-recordedtransport/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: recordedtransport summary: Shipped in 0.1.0; removed by the v0.2 pivot *(superseded by thin-httpx2-wrapper)* -supersedes: null -superseded_by: 2026-06-03.02-thin-httpx2-wrapper -pr: 13 -outcome: 'Shipped in 0.1.0; removed by the v0.2 pivot' --- # RecordedTransport (design) diff --git a/planning/changes/2026-05-31.08-recordedtransport/plan.md b/planning/changes/2026-05-31.08-recordedtransport/plan.md index 3c1198d..3c76339 100644 --- a/planning/changes/2026-05-31.08-recordedtransport/plan.md +++ b/planning/changes/2026-05-31.08-recordedtransport/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: recordedtransport -spec: recordedtransport -pr: 13 ---- - # RecordedTransport Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-05-31.09-release-0.1.0-prep/design.md b/planning/changes/2026-05-31.09-release-0.1.0-prep/design.md index 655aa14..d9ef4fd 100644 --- a/planning/changes/2026-05-31.09-release-0.1.0-prep/design.md +++ b/planning/changes/2026-05-31.09-release-0.1.0-prep/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-05-31 -slug: release-0.1.0-prep summary: 0.1.0 released -supersedes: null -superseded_by: null -pr: 14 -outcome: '0.1.0 released' --- # Release 0.1.0 prep (design) diff --git a/planning/changes/2026-05-31.09-release-0.1.0-prep/plan.md b/planning/changes/2026-05-31.09-release-0.1.0-prep/plan.md index 2d6c6fd..c64745e 100644 --- a/planning/changes/2026-05-31.09-release-0.1.0-prep/plan.md +++ b/planning/changes/2026-05-31.09-release-0.1.0-prep/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-05-31 -slug: release-0.1.0-prep -spec: release-0.1.0-prep -pr: 14 ---- - # Release 0.1.0 prep Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-01.01-auth-coercion/design.md b/planning/changes/2026-06-01.01-auth-coercion/design.md index 786f4f8..64d3100 100644 --- a/planning/changes/2026-06-01.01-auth-coercion/design.md +++ b/planning/changes/2026-06-01.01-auth-coercion/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-01 -slug: auth-coercion summary: Shipped (Epic 2); removed by the v0.2 pivot *(superseded by thin-httpx2-wrapper)* -supersedes: null -superseded_by: 2026-06-03.02-thin-httpx2-wrapper -pr: 16 -outcome: 'Shipped (Epic 2); removed by the v0.2 pivot' --- # Auth coercion (design) diff --git a/planning/changes/2026-06-01.01-auth-coercion/plan.md b/planning/changes/2026-06-01.01-auth-coercion/plan.md index 433c76c..d41b281 100644 --- a/planning/changes/2026-06-01.01-auth-coercion/plan.md +++ b/planning/changes/2026-06-01.01-auth-coercion/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-01 -slug: auth-coercion -spec: auth-coercion -pr: 16 ---- - # Auth coercion as middleware Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/design.md b/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/design.md index 9662a69..947692d 100644 --- a/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/design.md +++ b/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-02 -slug: docs-reorg-and-mkdocs summary: Docs reorg + mkdocs scaffolding -supersedes: null -superseded_by: null -pr: 17 -outcome: 'Docs reorg + mkdocs scaffolding' --- # Docs reorg and minimal mkdocs site (design) diff --git a/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/plan.md b/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/plan.md index 99b5e11..f430dff 100644 --- a/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/plan.md +++ b/planning/changes/2026-06-02.01-docs-reorg-and-mkdocs/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-02 -slug: docs-reorg-and-mkdocs -spec: docs-reorg-and-mkdocs -pr: 17 ---- - # Docs reorg + minimal mkdocs site implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-02.02-project-hygiene-tidy/design.md b/planning/changes/2026-06-02.02-project-hygiene-tidy/design.md index 843a1ff..c97110c 100644 --- a/planning/changes/2026-06-02.02-project-hygiene-tidy/design.md +++ b/planning/changes/2026-06-02.02-project-hygiene-tidy/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-02 -slug: project-hygiene-tidy summary: Repo hygiene pass -supersedes: null -superseded_by: null -pr: 18 -outcome: 'Repo hygiene pass' --- # Project hygiene tidy (design) diff --git a/planning/changes/2026-06-02.02-project-hygiene-tidy/plan.md b/planning/changes/2026-06-02.02-project-hygiene-tidy/plan.md index feea447..6f40a77 100644 --- a/planning/changes/2026-06-02.02-project-hygiene-tidy/plan.md +++ b/planning/changes/2026-06-02.02-project-hygiene-tidy/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-02 -slug: project-hygiene-tidy -spec: project-hygiene-tidy -pr: 18 ---- - # Project hygiene tidy implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-03.01-input-validation-pass/design.md b/planning/changes/2026-06-03.01-input-validation-pass/design.md index dea3b24..1cca417 100644 --- a/planning/changes/2026-06-03.01-input-validation-pass/design.md +++ b/planning/changes/2026-06-03.01-input-validation-pass/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-03 -slug: input-validation-pass summary: Input-validation hardening -supersedes: null -superseded_by: null -pr: 19 -outcome: 'Input-validation hardening' --- # Input-validation pass (design) diff --git a/planning/changes/2026-06-03.01-input-validation-pass/plan.md b/planning/changes/2026-06-03.01-input-validation-pass/plan.md index 18cd18c..a9069a1 100644 --- a/planning/changes/2026-06-03.01-input-validation-pass/plan.md +++ b/planning/changes/2026-06-03.01-input-validation-pass/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-03 -slug: input-validation-pass -spec: input-validation-pass -pr: 19 ---- - # Input-validation pass implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-03.02-thin-httpx2-wrapper/design.md b/planning/changes/2026-06-03.02-thin-httpx2-wrapper/design.md index e85efd1..d801618 100644 --- a/planning/changes/2026-06-03.02-thin-httpx2-wrapper/design.md +++ b/planning/changes/2026-06-03.02-thin-httpx2-wrapper/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-03 -slug: thin-httpx2-wrapper summary: Shipped 0.2.0 — the thin-wrapper pivot -supersedes: [2026-05-31.05-request-immutability-helpers, 2026-05-31.07-asyncclient, 2026-05-31.08-recordedtransport, 2026-06-01.01-auth-coercion] -superseded_by: null -pr: 20 -outcome: 'Shipped 0.2.0 — the thin-wrapper pivot' --- # Design: thin httpx2 wrapper (v0.2 pivot) diff --git a/planning/changes/2026-06-03.02-thin-httpx2-wrapper/plan.md b/planning/changes/2026-06-03.02-thin-httpx2-wrapper/plan.md index 5a41af4..4c65333 100644 --- a/planning/changes/2026-06-03.02-thin-httpx2-wrapper/plan.md +++ b/planning/changes/2026-06-03.02-thin-httpx2-wrapper/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-03 -slug: thin-httpx2-wrapper -spec: thin-httpx2-wrapper -pr: 20 ---- - # Thin httpx2 wrapper (v0.2 pivot) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-04.01-pydantic-optional-extra/design.md b/planning/changes/2026-06-04.01-pydantic-optional-extra/design.md index 355908c..5d99185 100644 --- a/planning/changes/2026-06-04.01-pydantic-optional-extra/design.md +++ b/planning/changes/2026-06-04.01-pydantic-optional-extra/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-04 -slug: pydantic-optional-extra summary: Shipped 0.3.0 — pydantic moves to an extra -supersedes: null -superseded_by: null -pr: 21 -outcome: 'Shipped 0.3.0 — pydantic moves to an extra' --- # Spec: pydantic as an optional extra (0.3.0) diff --git a/planning/changes/2026-06-04.01-pydantic-optional-extra/plan.md b/planning/changes/2026-06-04.01-pydantic-optional-extra/plan.md index f5d3558..0cfd6d8 100644 --- a/planning/changes/2026-06-04.01-pydantic-optional-extra/plan.md +++ b/planning/changes/2026-06-04.01-pydantic-optional-extra/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-04 -slug: pydantic-optional-extra -spec: pydantic-optional-extra -pr: 21 ---- - # Pydantic-as-optional-extra (0.3.0) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-04.02-v0.2-retro-and-housekeeping/design.md b/planning/changes/2026-06-04.02-v0.2-retro-and-housekeeping/design.md index f6c9540..e066cbd 100644 --- a/planning/changes/2026-06-04.02-v0.2-retro-and-housekeeping/design.md +++ b/planning/changes/2026-06-04.02-v0.2-retro-and-housekeeping/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-04 -slug: v0.2-retro-and-housekeeping summary: Post-0.2 retro + housekeeping -supersedes: null -superseded_by: null -pr: 21 -outcome: 'Post-0.2 retro + housekeeping' --- # Spec: v0.2 retrospective and planning/ housekeeping diff --git a/planning/changes/2026-06-05.01-retry-and-retry-budget/design.md b/planning/changes/2026-06-05.01-retry-and-retry-budget/design.md index 00f5c00..7760b53 100644 --- a/planning/changes/2026-06-05.01-retry-and-retry-budget/design.md +++ b/planning/changes/2026-06-05.01-retry-and-retry-budget/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: retry-and-retry-budget summary: Shipped 0.4.0 — Retry + RetryBudget -supersedes: null -superseded_by: null -pr: 22 -outcome: 'Shipped 0.4.0 — Retry + RetryBudget' --- # Spec: Retry middleware + RetryBudget (0.4.0, slice A of Epic 3) diff --git a/planning/changes/2026-06-05.01-retry-and-retry-budget/plan.md b/planning/changes/2026-06-05.01-retry-and-retry-budget/plan.md index c10df78..120c3f8 100644 --- a/planning/changes/2026-06-05.01-retry-and-retry-budget/plan.md +++ b/planning/changes/2026-06-05.01-retry-and-retry-budget/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: retry-and-retry-budget -spec: retry-and-retry-budget -pr: 22 ---- - # Retry middleware + RetryBudget (0.4.0 slice 1) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-05.02-bulkhead/design.md b/planning/changes/2026-06-05.02-bulkhead/design.md index 296c94e..aa672d8 100644 --- a/planning/changes/2026-06-05.02-bulkhead/design.md +++ b/planning/changes/2026-06-05.02-bulkhead/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: bulkhead summary: Shipped 0.4.0 — Bulkhead -supersedes: null -superseded_by: null -pr: 23 -outcome: 'Shipped 0.4.0 — Bulkhead' --- # Spec: Bulkhead middleware (0.4.0, Epic 3 slice 2) diff --git a/planning/changes/2026-06-05.02-bulkhead/plan.md b/planning/changes/2026-06-05.02-bulkhead/plan.md index d49c122..ece683a 100644 --- a/planning/changes/2026-06-05.02-bulkhead/plan.md +++ b/planning/changes/2026-06-05.02-bulkhead/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: bulkhead -spec: bulkhead -pr: 23 ---- - # Bulkhead middleware (0.4.0, Epic 3 slice 2) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-05.03-docs-sync-0.4/design.md b/planning/changes/2026-06-05.03-docs-sync-0.4/design.md index 4ddc56a..def7a2e 100644 --- a/planning/changes/2026-06-05.03-docs-sync-0.4/design.md +++ b/planning/changes/2026-06-05.03-docs-sync-0.4/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: docs-sync-0.4 summary: 0.4 docs sync -supersedes: null -superseded_by: null -pr: 25 -outcome: '0.4 docs sync' --- # Spec: User-docs freshness pass for 0.4 (Epic 3 story 3-6) diff --git a/planning/changes/2026-06-05.03-docs-sync-0.4/plan.md b/planning/changes/2026-06-05.03-docs-sync-0.4/plan.md index cbfdff5..1a32c96 100644 --- a/planning/changes/2026-06-05.03-docs-sync-0.4/plan.md +++ b/planning/changes/2026-06-05.03-docs-sync-0.4/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: docs-sync-0.4 -spec: docs-sync-0.4 -pr: 25 ---- - # Docs-sync 0.4 (Epic 3 story 3-6) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-05.04-streaming/design.md b/planning/changes/2026-06-05.04-streaming/design.md index f1d2149..b09e13a 100644 --- a/planning/changes/2026-06-05.04-streaming/design.md +++ b/planning/changes/2026-06-05.04-streaming/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: streaming summary: Shipped 0.5.0 — stream() -supersedes: null -superseded_by: null -pr: 26 -outcome: 'Shipped 0.5.0 — stream()' --- # Spec: AsyncClient.stream context manager (0.5.0, Epic 4 story 4-3) diff --git a/planning/changes/2026-06-05.04-streaming/plan.md b/planning/changes/2026-06-05.04-streaming/plan.md index 20d8e58..eb055b6 100644 --- a/planning/changes/2026-06-05.04-streaming/plan.md +++ b/planning/changes/2026-06-05.04-streaming/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: streaming -spec: streaming -pr: 26 ---- - # AsyncClient.stream + Retry-refuses-streamed-body (0.5.0, Epic 4 story 4-3) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-05.05-observability/design.md b/planning/changes/2026-06-05.05-observability/design.md index c082d92..85ae062 100644 --- a/planning/changes/2026-06-05.05-observability/design.md +++ b/planning/changes/2026-06-05.05-observability/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: observability summary: Shipped 0.6.0 — logging + OTel events -supersedes: null -superseded_by: null -pr: 27 -outcome: 'Shipped 0.6.0 — logging + OTel events' --- # Spec: Resilience observability — structured logging + opt-in OTel attribute enrichment (0.6.0, Epic 5) diff --git a/planning/changes/2026-06-05.05-observability/plan.md b/planning/changes/2026-06-05.05-observability/plan.md index a923fbb..ae70348 100644 --- a/planning/changes/2026-06-05.05-observability/plan.md +++ b/planning/changes/2026-06-05.05-observability/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: observability -spec: observability -pr: 27 ---- - # Resilience observability (0.6.0, Epic 5 re-scoped) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-05.06-extension-slot-docs/design.md b/planning/changes/2026-06-05.06-extension-slot-docs/design.md index dce43ba..94ecfd4 100644 --- a/planning/changes/2026-06-05.06-extension-slot-docs/design.md +++ b/planning/changes/2026-06-05.06-extension-slot-docs/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: extension-slot-docs summary: Shipped 0.7.0 — middleware docs -supersedes: null -superseded_by: null -pr: 28 -outcome: 'Shipped 0.7.0 — middleware docs' --- # Spec: Extension-slot docs (Epic 3 story 3-6) diff --git a/planning/changes/2026-06-05.06-extension-slot-docs/plan.md b/planning/changes/2026-06-05.06-extension-slot-docs/plan.md index 0dacc32..5854561 100644 --- a/planning/changes/2026-06-05.06-extension-slot-docs/plan.md +++ b/planning/changes/2026-06-05.06-extension-slot-docs/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: extension-slot-docs -spec: extension-slot-docs -pr: 28 ---- - # Extension-slot docs (0.7.0, Epic 3 story 3-6) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-05.07-v0.7-docs-expansion/design.md b/planning/changes/2026-06-05.07-v0.7-docs-expansion/design.md index cbb73d9..6534503 100644 --- a/planning/changes/2026-06-05.07-v0.7-docs-expansion/design.md +++ b/planning/changes/2026-06-05.07-v0.7-docs-expansion/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-05 -slug: v0.7-docs-expansion summary: Shipped 0.7.0 — first-cut user docs -supersedes: null -superseded_by: null -pr: 28 -outcome: 'Shipped 0.7.0 — first-cut user docs' --- # Spec: v0.7 docs expansion (Middleware + Resilience + Errors + Testing) diff --git a/planning/changes/2026-06-05.07-v0.7-docs-expansion/plan.md b/planning/changes/2026-06-05.07-v0.7-docs-expansion/plan.md index 5e987e9..f46acf1 100644 --- a/planning/changes/2026-06-05.07-v0.7-docs-expansion/plan.md +++ b/planning/changes/2026-06-05.07-v0.7-docs-expansion/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-05 -slug: v0.7-docs-expansion -spec: v0.7-docs-expansion -pr: 28 ---- - # v0.7 docs expansion (Resilience + Errors + Testing + OTel wiring) Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-06.01-modern-di-recipe/design.md b/planning/changes/2026-06-06.01-modern-di-recipe/design.md index 5db111d..442c329 100644 --- a/planning/changes/2026-06-06.01-modern-di-recipe/design.md +++ b/planning/changes/2026-06-06.01-modern-di-recipe/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-06 -slug: modern-di-recipe summary: modern-di DI recipe doc -supersedes: null -superseded_by: null -pr: 29 -outcome: 'modern-di DI recipe doc' --- # Spec: `modern-di` setup-friction recipe diff --git a/planning/changes/2026-06-06.01-modern-di-recipe/plan.md b/planning/changes/2026-06-06.01-modern-di-recipe/plan.md index 7032619..3c692a9 100644 --- a/planning/changes/2026-06-06.01-modern-di-recipe/plan.md +++ b/planning/changes/2026-06-06.01-modern-di-recipe/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-06 -slug: modern-di-recipe -spec: modern-di-recipe -pr: 29 ---- - # `modern-di` recipe + `AsyncClient.aclose()` Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-07.01-sync-client/design.md b/planning/changes/2026-06-07.01-sync-client/design.md index 9f29d2d..1d36a88 100644 --- a/planning/changes/2026-06-07.01-sync-client/design.md +++ b/planning/changes/2026-06-07.01-sync-client/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-07 -slug: sync-client summary: Shipped 0.8.0 — sync Client + Async* rename -supersedes: null -superseded_by: null -pr: 31 -outcome: 'Shipped 0.8.0 — sync Client + Async* rename' --- # Spec: Sync `Client` + httpx2-aligned `Async*` rename diff --git a/planning/changes/2026-06-07.01-sync-client/plan.md b/planning/changes/2026-06-07.01-sync-client/plan.md index 5be27ed..b6b2dcb 100644 --- a/planning/changes/2026-06-07.01-sync-client/plan.md +++ b/planning/changes/2026-06-07.01-sync-client/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-07 -slug: sync-client -spec: sync-client -pr: 31 ---- - # Sync `Client` + httpx2-aligned `Async*` rename — Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-07.02-decoder-error/design.md b/planning/changes/2026-06-07.02-decoder-error/design.md index 8e5227d..39c9192 100644 --- a/planning/changes/2026-06-07.02-decoder-error/design.md +++ b/planning/changes/2026-06-07.02-decoder-error/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-07 -slug: decoder-error summary: Shipped 0.8.1 — DecodeError at seam B -supersedes: null -superseded_by: null -pr: 32 -outcome: 'Shipped 0.8.1 — DecodeError at seam B' --- # Spec: `DecodeError` — close the decoder-exception gap at Seam 3 diff --git a/planning/changes/2026-06-07.02-decoder-error/plan.md b/planning/changes/2026-06-07.02-decoder-error/plan.md index c8aa13a..839ba37 100644 --- a/planning/changes/2026-06-07.02-decoder-error/plan.md +++ b/planning/changes/2026-06-07.02-decoder-error/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-07 -slug: decoder-error -spec: decoder-error -pr: 32 ---- - # DecodeError Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-07.03-deep-audit/design.md b/planning/changes/2026-06-07.03-deep-audit/design.md index e08d8d9..79377de 100644 --- a/planning/changes/2026-06-07.03-deep-audit/design.md +++ b/planning/changes/2026-06-07.03-deep-audit/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-07 -slug: deep-audit summary: Deep audit; findings closed across 0.8.1-0.8.6 -supersedes: null -superseded_by: null -pr: 32 -outcome: 'Deep audit; findings closed across 0.8.1-0.8.6' --- # Spec: Deep audit of httpware — code + docs diff --git a/planning/changes/2026-06-07.03-deep-audit/plan.md b/planning/changes/2026-06-07.03-deep-audit/plan.md index fbf5578..889bb36 100644 --- a/planning/changes/2026-06-07.03-deep-audit/plan.md +++ b/planning/changes/2026-06-07.03-deep-audit/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-07 -slug: deep-audit -spec: deep-audit -pr: 32 ---- - # Deep Audit Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.01-send-with-response/design.md b/planning/changes/2026-06-08.01-send-with-response/design.md index 59ef80d..06237eb 100644 --- a/planning/changes/2026-06-08.01-send-with-response/design.md +++ b/planning/changes/2026-06-08.01-send-with-response/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: send-with-response summary: Shipped 0.8.2 — send_with_response -supersedes: null -superseded_by: null -pr: 33 -outcome: 'Shipped 0.8.2 — send_with_response' --- # Spec: `send_with_response` — atomic (raw response, decoded body) pair diff --git a/planning/changes/2026-06-08.01-send-with-response/plan.md b/planning/changes/2026-06-08.01-send-with-response/plan.md index 2c27fb0..6d5680e 100644 --- a/planning/changes/2026-06-08.01-send-with-response/plan.md +++ b/planning/changes/2026-06-08.01-send-with-response/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: send-with-response -spec: send-with-response -pr: 33 ---- - # `send_with_response` Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.02-retry-budget-cluster/design.md b/planning/changes/2026-06-08.02-retry-budget-cluster/design.md index b3bf461..f657254 100644 --- a/planning/changes/2026-06-08.02-retry-budget-cluster/design.md +++ b/planning/changes/2026-06-08.02-retry-budget-cluster/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: retry-budget-cluster summary: Shipped 0.8.3 — 7 RetryBudget findings -supersedes: null -superseded_by: null -pr: 34 -outcome: 'Shipped 0.8.3 — 7 RetryBudget findings' --- # Spec: Retry/Budget cluster — close 7 audit findings (0.8.3) diff --git a/planning/changes/2026-06-08.02-retry-budget-cluster/plan.md b/planning/changes/2026-06-08.02-retry-budget-cluster/plan.md index 02e139d..d0b594b 100644 --- a/planning/changes/2026-06-08.02-retry-budget-cluster/plan.md +++ b/planning/changes/2026-06-08.02-retry-budget-cluster/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: retry-budget-cluster -spec: retry-budget-cluster -pr: 34 ---- - # Retry/Budget Cluster Implementation Plan (0.8.3) > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.03-post-080-doc-sweep/design.md b/planning/changes/2026-06-08.03-post-080-doc-sweep/design.md index 0fe6b5d..b2924b0 100644 --- a/planning/changes/2026-06-08.03-post-080-doc-sweep/design.md +++ b/planning/changes/2026-06-08.03-post-080-doc-sweep/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: post-080-doc-sweep summary: Post-0.8.0 doc sweep -supersedes: null -superseded_by: null -pr: 34 -outcome: 'Post-0.8.0 doc sweep' --- # Spec: Post-0.8.0 doc-staleness sweep diff --git a/planning/changes/2026-06-08.03-post-080-doc-sweep/plan.md b/planning/changes/2026-06-08.03-post-080-doc-sweep/plan.md index f3bdda0..1786948 100644 --- a/planning/changes/2026-06-08.03-post-080-doc-sweep/plan.md +++ b/planning/changes/2026-06-08.03-post-080-doc-sweep/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: post-080-doc-sweep -spec: post-080-doc-sweep -pr: 34 ---- - # Post-0.8.0 Doc-Staleness Sweep Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.04-otel-partial-install/design.md b/planning/changes/2026-06-08.04-otel-partial-install/design.md index f693161..2eb2175 100644 --- a/planning/changes/2026-06-08.04-otel-partial-install/design.md +++ b/planning/changes/2026-06-08.04-otel-partial-install/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: otel-partial-install summary: Shipped 0.8.4 — OTel partial-install guards -supersedes: null -superseded_by: null -pr: 35 -outcome: 'Shipped 0.8.4 — OTel partial-install guards' --- # Spec: OTel partial-install hardening (0.8.4) diff --git a/planning/changes/2026-06-08.04-otel-partial-install/plan.md b/planning/changes/2026-06-08.04-otel-partial-install/plan.md index 872b21f..f2a3151 100644 --- a/planning/changes/2026-06-08.04-otel-partial-install/plan.md +++ b/planning/changes/2026-06-08.04-otel-partial-install/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: otel-partial-install -spec: otel-partial-install -pr: 35 ---- - # OTel Partial-Install Hardening Implementation Plan (0.8.4) > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.05-small-fixes-mop-up/design.md b/planning/changes/2026-06-08.05-small-fixes-mop-up/design.md index 6660577..66ddfbb 100644 --- a/planning/changes/2026-06-08.05-small-fixes-mop-up/design.md +++ b/planning/changes/2026-06-08.05-small-fixes-mop-up/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: small-fixes-mop-up summary: Shipped 0.8.5 — 4 small audit findings -supersedes: null -superseded_by: null -pr: 36 -outcome: 'Shipped 0.8.5 — 4 small audit findings' --- # Spec: Small-fixes mop-up (0.8.5) diff --git a/planning/changes/2026-06-08.05-small-fixes-mop-up/plan.md b/planning/changes/2026-06-08.05-small-fixes-mop-up/plan.md index 1f4e56e..b7ecfdd 100644 --- a/planning/changes/2026-06-08.05-small-fixes-mop-up/plan.md +++ b/planning/changes/2026-06-08.05-small-fixes-mop-up/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: small-fixes-mop-up -spec: small-fixes-mop-up -pr: 36 ---- - # Small-Fixes Mop-Up Implementation Plan (0.8.5) > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.06-test-mop-up/design.md b/planning/changes/2026-06-08.06-test-mop-up/design.md index c8cff75..33cbcf3 100644 --- a/planning/changes/2026-06-08.06-test-mop-up/design.md +++ b/planning/changes/2026-06-08.06-test-mop-up/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: test-mop-up summary: Shipped 0.8.6 — test-only audit findings -supersedes: null -superseded_by: null -pr: 37 -outcome: 'Shipped 0.8.6 — test-only audit findings' --- # Spec: Test mop-up (0.8.6) diff --git a/planning/changes/2026-06-08.06-test-mop-up/plan.md b/planning/changes/2026-06-08.06-test-mop-up/plan.md index e61fa47..141cc8f 100644 --- a/planning/changes/2026-06-08.06-test-mop-up/plan.md +++ b/planning/changes/2026-06-08.06-test-mop-up/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: test-mop-up -spec: test-mop-up -pr: 37 ---- - # Test Mop-Up Implementation Plan (0.8.6) > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/design.md b/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/design.md index d7131d0..2d4fb28 100644 --- a/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/design.md +++ b/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: mkdocs-gh-pages-migration summary: Docs host -> GitHub Pages -supersedes: null -superseded_by: null -pr: 38 -outcome: 'Docs host -> GitHub Pages' --- # Spec: Migrate docs hosting from ReadTheDocs to GitHub Pages diff --git a/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/plan.md b/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/plan.md index fc9f7aa..be92571 100644 --- a/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/plan.md +++ b/planning/changes/2026-06-08.07-mkdocs-gh-pages-migration/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: mkdocs-gh-pages-migration -spec: mkdocs-gh-pages-migration -pr: 38 ---- - # mkdocs GitHub Pages Migration Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-08.08-readme-link-cleanup/design.md b/planning/changes/2026-06-08.08-readme-link-cleanup/design.md index 540c71d..3dab8d1 100644 --- a/planning/changes/2026-06-08.08-readme-link-cleanup/design.md +++ b/planning/changes/2026-06-08.08-readme-link-cleanup/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-08 -slug: readme-link-cleanup summary: README link cleanup -supersedes: null -superseded_by: null -pr: 39 -outcome: 'README link cleanup' --- # Spec: README + top-level link cleanup, plus one-shot link audit diff --git a/planning/changes/2026-06-08.08-readme-link-cleanup/plan.md b/planning/changes/2026-06-08.08-readme-link-cleanup/plan.md index c49fa25..8c8e371 100644 --- a/planning/changes/2026-06-08.08-readme-link-cleanup/plan.md +++ b/planning/changes/2026-06-08.08-readme-link-cleanup/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-08 -slug: readme-link-cleanup -spec: readme-link-cleanup -pr: 39 ---- - # README + top-level link cleanup Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-10.01-multi-decoder/design.md b/planning/changes/2026-06-10.01-multi-decoder/design.md index 57b5e1d..2a3d160 100644 --- a/planning/changes/2026-06-10.01-multi-decoder/design.md +++ b/planning/changes/2026-06-10.01-multi-decoder/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-10 -slug: multi-decoder summary: Shipped 0.9.0 — multi-decoder routing -supersedes: null -superseded_by: null -pr: 41 -outcome: 'Shipped 0.9.0 — multi-decoder routing' --- # Spec: multi-decoder routing — `decoders=[...]` with type-dispatched claim policy diff --git a/planning/changes/2026-06-10.01-multi-decoder/plan.md b/planning/changes/2026-06-10.01-multi-decoder/plan.md index bfa206c..aa81c26 100644 --- a/planning/changes/2026-06-10.01-multi-decoder/plan.md +++ b/planning/changes/2026-06-10.01-multi-decoder/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-10 -slug: multi-decoder -spec: multi-decoder -pr: 41 ---- - # Multi-Decoder Routing Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-10.02-decoder-instance-cache/design.md b/planning/changes/2026-06-10.02-decoder-instance-cache/design.md index 1d26e25..fe13734 100644 --- a/planning/changes/2026-06-10.02-decoder-instance-cache/design.md +++ b/planning/changes/2026-06-10.02-decoder-instance-cache/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-10 -slug: decoder-instance-cache summary: Shipped 0.9.0 — per-instance decoder cache -supersedes: null -superseded_by: null -pr: 42 -outcome: 'Shipped 0.9.0 — per-instance decoder cache' --- # Spec: decoder per-instance cache — drop module-level `@lru_cache` diff --git a/planning/changes/2026-06-10.02-decoder-instance-cache/plan.md b/planning/changes/2026-06-10.02-decoder-instance-cache/plan.md index 08567e4..15fc657 100644 --- a/planning/changes/2026-06-10.02-decoder-instance-cache/plan.md +++ b/planning/changes/2026-06-10.02-decoder-instance-cache/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-10 -slug: decoder-instance-cache -spec: decoder-instance-cache -pr: 42 ---- - # Per-Instance Decoder Cache Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-12.01-delta-audit/design.md b/planning/changes/2026-06-12.01-delta-audit/design.md index 3843fe8..b9683a8 100644 --- a/planning/changes/2026-06-12.01-delta-audit/design.md +++ b/planning/changes/2026-06-12.01-delta-audit/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-12 -slug: delta-audit summary: 0.9.0 delta audit; closed via 0.9.1 -supersedes: null -superseded_by: null -pr: 43 -outcome: '0.9.0 delta audit; closed via 0.9.1' --- # Spec: Delta audit of the 0.9.0 multi-decoder epic — code + docs diff --git a/planning/changes/2026-06-12.01-delta-audit/plan.md b/planning/changes/2026-06-12.01-delta-audit/plan.md index 69659fb..3b984cd 100644 --- a/planning/changes/2026-06-12.01-delta-audit/plan.md +++ b/planning/changes/2026-06-12.01-delta-audit/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-12 -slug: delta-audit -spec: delta-audit -pr: 43 ---- - # 0.9.0 Delta Audit Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Task 2 must run inline in the main session** — the Workflow tool is a main-session orchestration tool and is not available to dispatched subagents. diff --git a/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/design.md b/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/design.md index 2041d3a..18807cf 100644 --- a/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/design.md +++ b/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-13 -slug: msgspec-nested-customtype-fix summary: Shipped 0.9.1 — nested-CustomType guard -supersedes: null -superseded_by: null -pr: 43 -outcome: 'Shipped 0.9.1 — nested-CustomType guard' --- # Spec: Fix `MsgspecDecoder.can_decode` false-positive on nested CustomType diff --git a/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/plan.md b/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/plan.md index 727ce00..ee049c4 100644 --- a/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/plan.md +++ b/planning/changes/2026-06-13.01-msgspec-nested-customtype-fix/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-13 -slug: msgspec-nested-customtype-fix -spec: msgspec-nested-customtype-fix -pr: 43 ---- - # MsgspecDecoder Nested-CustomType Fix Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/design.md b/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/design.md index 3169ffc..1c7a5c4 100644 --- a/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/design.md +++ b/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-13 -slug: circuit-breaker-and-timeout summary: Shipped 0.10.0 — CircuitBreaker + AsyncTimeout -supersedes: null -superseded_by: null -pr: 51 -outcome: 'Shipped 0.10.0 — CircuitBreaker + AsyncTimeout' --- # Spec: CircuitBreaker + AsyncTimeout — completing the resilience suite diff --git a/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/plan.md b/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/plan.md index 4e14bbb..2ce7b06 100644 --- a/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/plan.md +++ b/planning/changes/2026-06-13.02-circuit-breaker-and-timeout/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-13 -slug: circuit-breaker-and-timeout -spec: circuit-breaker-and-timeout -pr: 51 ---- - # CircuitBreaker + AsyncTimeout Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. diff --git a/planning/changes/2026-06-13.03-portable-planning-convention/design.md b/planning/changes/2026-06-13.03-portable-planning-convention/design.md index b344723..f3c08cf 100644 --- a/planning/changes/2026-06-13.03-portable-planning-convention/design.md +++ b/planning/changes/2026-06-13.03-portable-planning-convention/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-13 -slug: portable-planning-convention summary: Adopt the portable two-axis convention: per-capability `architecture/` truth files + `changes/` bundles, full history backfill, byte-identical Conventions. -supersedes: null -superseded_by: null -pr: 55 -outcome: 'Shipped via PR #55 — two-axis convention adopted: architecture/ truth + planning/changes/ bundles; engineering.md split into 8 files; 40 pairs archived.' --- # Design: Adopt the portable two-axis planning convention diff --git a/planning/changes/2026-06-13.04-docs-accuracy-fixes/change.md b/planning/changes/2026-06-13.04-docs-accuracy-fixes/change.md index 053261c..e2d5cb9 100644 --- a/planning/changes/2026-06-13.04-docs-accuracy-fixes/change.md +++ b/planning/changes/2026-06-13.04-docs-accuracy-fixes/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-13 -slug: docs-accuracy-fixes summary: Fixed 5 verified factual errors from the [docs audit](audits/2026-06-13-docs-audit.md): RetryBudget formula, modern-di 2.x recipe, contributing-doc CI/grep claim, `just lint` comment, middleware stable-contracts list (+ AsyncTimeout non-finite wording). -supersedes: null -superseded_by: null -pr: f203821 -outcome: Shipped — 5 verified doc-accuracy fixes (B1 RetryBudget formula, B2 modern-di 2.x recipe, I1/I2 contributing-doc, I3 middleware contracts, AsyncTimeout wording). Pushed directly to main (no PR). --- # Change: Fix verified doc-accuracy bugs from the docs audit diff --git a/planning/changes/2026-06-13.05-docs-audit-followups/change.md b/planning/changes/2026-06-13.05-docs-audit-followups/change.md index 8cbbe56..b68887a 100644 --- a/planning/changes/2026-06-13.05-docs-audit-followups/change.md +++ b/planning/changes/2026-06-13.05-docs-audit-followups/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-13 -slug: docs-audit-followups summary: Second docs-audit batch: corrected the overstated invariant-enforcement claims in `CLAUDE.md` + `architecture/overview.md` (only `print()`/blanket-`type: ignore` are machine-checked), readability findings R1–R3, and documented the public `STATUS_TO_EXCEPTION` (G5). -supersedes: null -superseded_by: null -pr: 58 -outcome: Shipped via #58 (squash a132c1e) — invariant-enforcement claim corrected in CLAUDE.md + architecture/overview.md, plus readability findings R1/R2/R3 and STATUS_TO_EXCEPTION docs (G5). --- # Change: Docs-audit follow-ups — invariant-enforcement wording + readability diff --git a/planning/changes/2026-06-14.01-deep-audit/design.md b/planning/changes/2026-06-14.01-deep-audit/design.md index 7790cfa..3b97cad 100644 --- a/planning/changes/2026-06-14.01-deep-audit/design.md +++ b/planning/changes/2026-06-14.01-deep-audit/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: deep-audit summary: Full-codebase deep audit (perf/security/supply-chain gaps + correctness/concurrency/refactoring/test quality). [Report](audits/2026-06-14-deep-audit.md): 35 confirmed; all remediated across #62–#66 (non-streaming hard body cap deferred). -supersedes: null -superseded_by: null -pr: null -outcome: Audit complete - 35 confirmed findings, all remediated across #62 (pydantic High+2 Mediums), #63 (security cluster), #64 (correctness), #65 (test quality), #66 (docs). Non-streaming hard body cap deferred (planning/deferred.md). --- # Design: Full-codebase deep audit (perf · security · refactoring · bugs) diff --git a/planning/changes/2026-06-14.01-deep-audit/plan.md b/planning/changes/2026-06-14.01-deep-audit/plan.md index 8f3ab27..0d6ea63 100644 --- a/planning/changes/2026-06-14.01-deep-audit/plan.md +++ b/planning/changes/2026-06-14.01-deep-audit/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-14 -slug: deep-audit -spec: deep-audit -pr: null ---- - # deep-audit — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-14.01-docs-ux-restructure/design.md b/planning/changes/2026-06-14.01-docs-ux-restructure/design.md index 2ccf2c3..868858c 100644 --- a/planning/changes/2026-06-14.01-docs-ux-restructure/design.md +++ b/planning/changes/2026-06-14.01-docs-ux-restructure/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: docs-ux-restructure summary: Thin README front-door + canonical `docs/index.md` (G3), why-httpware hook (G1), runnable jsonplaceholder example (G4), nav reorder + architecture links, base-client scrub. G2 dropped; G6 (decoder guide) still open. -supersedes: null -superseded_by: null -pr: 60 -outcome: Shipped via #60 (squash 480cea8) — thin README front-door + canonical docs/index.md (G3), why-httpware hook (G1), runnable jsonplaceholder example (G4), nav reorder + architecture links, base-client scrub. G2 dropped; G6 (decoder guide) still open. --- # Design: Docs-UX restructure — thin README, canonical site, runnable first example diff --git a/planning/changes/2026-06-14.01-docs-ux-restructure/plan.md b/planning/changes/2026-06-14.01-docs-ux-restructure/plan.md index 992b02b..2bc3f3b 100644 --- a/planning/changes/2026-06-14.01-docs-ux-restructure/plan.md +++ b/planning/changes/2026-06-14.01-docs-ux-restructure/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-14 -slug: docs-ux-restructure -spec: docs-ux-restructure -pr: 60 ---- - # docs-ux-restructure — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-14.02-pydantic-import-isolation/change.md b/planning/changes/2026-06-14.02-pydantic-import-isolation/change.md index ceaaf0e..1ea8f69 100644 --- a/planning/changes/2026-06-14.02-pydantic-import-isolation/change.md +++ b/planning/changes/2026-06-14.02-pydantic-import-isolation/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: pydantic-import-isolation summary: Guarded the pydantic import so the decoder module loads without the extra and the `architecture/extras.md` Seam-C invariant holds for pydantic. Closed the [deep-audit](audits/2026-06-14-deep-audit.md) High + 2 folded Mediums. -supersedes: null -superseded_by: null -pr: 62 -outcome: Shipped via #62 — pydantic import guarded behind is_pydantic_installed so the decoder module loads without the extra; the architecture/extras.md Seam-C isolation invariant is now true for pydantic. Closed deep-audit High + 2 folded Mediums. --- # Change: Guard the pydantic import so the decoder module loads without the extra diff --git a/planning/changes/2026-06-14.03-security-hardening/design.md b/planning/changes/2026-06-14.03-security-hardening/design.md index 28a6a2c..14d3f75 100644 --- a/planning/changes/2026-06-14.03-security-hardening/design.md +++ b/planning/changes/2026-06-14.03-security-hardening/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: security-hardening summary: Closed the [deep-audit](audits/2026-06-14-deep-audit.md) security cluster: URL secret redaction centralized at the `_emit_event` chokepoint (userinfo + sensitive query/fragment keys), opt-in `max_error_body_bytes` + `ResponseTooLargeError` bounding the `stream()` error pre-read, and `trust_env` + header-reachability docs. Non-streaming hard body cap deferred. -supersedes: null -superseded_by: null -pr: 63 -outcome: Shipped via #63 — URL secret redaction centralized at the _emit_event chokepoint, opt-in max_error_body_bytes + ResponseTooLargeError bound the stream() error pre-read, trust_env + header-reachability docs. Non-streaming hard body cap deferred (planning/deferred.md). --- # Design: Security hardening — URL secret redaction + bounded error-body reads diff --git a/planning/changes/2026-06-14.03-security-hardening/plan.md b/planning/changes/2026-06-14.03-security-hardening/plan.md index f5e5738..6559271 100644 --- a/planning/changes/2026-06-14.03-security-hardening/plan.md +++ b/planning/changes/2026-06-14.03-security-hardening/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-14 -slug: security-hardening -spec: security-hardening -pr: 63 ---- - # security-hardening — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-14.04-audit-correctness/change.md b/planning/changes/2026-06-14.04-audit-correctness/change.md index 40c0180..ff93330 100644 --- a/planning/changes/2026-06-14.04-audit-correctness/change.md +++ b/planning/changes/2026-06-14.04-audit-correctness/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: audit-correctness summary: Closed 8 [deep-audit](audits/2026-06-14-deep-audit.md) correctness + public-API findings: RetryBudget token ordering, two `OverflowError` crashes, the redaction triple-slash, the msgspec guard, streaming-body symmetry, the RetryBudget docstring caveat, and `middleware/__all__`. -supersedes: null -superseded_by: null -pr: 64 -outcome: Shipped via #64 - 8 correctness + public-API findings (RetryBudget token ordering, _parse_retry_after and full_jitter_delay OverflowError, redaction triple-slash, msgspec guard, streaming-body symmetry, RetryBudget docstring, middleware __all__). --- # Change: Deep-audit correctness + public-API fixes diff --git a/planning/changes/2026-06-14.05-audit-test-quality/change.md b/planning/changes/2026-06-14.05-audit-test-quality/change.md index 24d0a8f..9345c57 100644 --- a/planning/changes/2026-06-14.05-audit-test-quality/change.md +++ b/planning/changes/2026-06-14.05-audit-test-quality/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: audit-test-quality summary: Closed 11 [deep-audit](audits/2026-06-14-deep-audit.md) test-quality findings: sync-terminal + CookieConflict coverage, the `StatusError.__init__` invariant, missing status constructions, sync mirrors, typing overloads, a deterministic bulkhead barrier, a pinned budget clock, an observability assertion, and the `TimeoutError` circuit trigger. -supersedes: null -superseded_by: null -pr: 65 -outcome: Shipped via #65 - 11 test-quality findings (sync terminal + CookieConflict coverage, StatusError __init__ invariant, missing status constructions, sync mirrors, typing overloads, deterministic bulkhead barrier, pinned budget clock, observability assertion, TimeoutError circuit trigger). --- # Change: Deep-audit test-quality findings diff --git a/planning/changes/2026-06-14.06-audit-doc-fixes/change.md b/planning/changes/2026-06-14.06-audit-doc-fixes/change.md index 5de7a9f..a5567b0 100644 --- a/planning/changes/2026-06-14.06-audit-doc-fixes/change.md +++ b/planning/changes/2026-06-14.06-audit-doc-fixes/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-14 -slug: audit-doc-fixes summary: Closed the [deep-audit](audits/2026-06-14-deep-audit.md) doc-accuracy findings: `Client.stream()` docs, terminal-call attribution, the four auto-raise sites, the pydantic upper bound, and root import paths. -supersedes: null -superseded_by: null -pr: 66 -outcome: Shipped via #66 - 5 doc-accuracy findings (Client.stream docs, terminal attribution, errors auto-raise sites, pydantic upper bound, root import paths). --- # Change: Deep-audit documentation accuracy fixes diff --git a/planning/changes/2026-06-15.01-custom-decoder-guide/change.md b/planning/changes/2026-06-15.01-custom-decoder-guide/change.md index eb4206d..9e95420 100644 --- a/planning/changes/2026-06-15.01-custom-decoder-guide/change.md +++ b/planning/changes/2026-06-15.01-custom-decoder-guide/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-15 -slug: custom-decoder-guide summary: Docs: a "write your own `ResponseDecoder`" guide for Seam B, mirroring `docs/middleware.md`. Closed deferred item G6. -supersedes: null -superseded_by: null -pr: 67 -outcome: Shipped docs/decoders.md (the Seam B "write your own ResponseDecoder" guide); closed deferred item G6. --- # Change: Add a "Writing a custom decoder" guide diff --git a/planning/changes/2026-06-16.01-per-verb-with-response/design.md b/planning/changes/2026-06-16.01-per-verb-with-response/design.md index 236e2eb..3f96355 100644 --- a/planning/changes/2026-06-16.01-per-verb-with-response/design.md +++ b/planning/changes/2026-06-16.01-per-verb-with-response/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-16 -slug: per-verb-with-response summary: Added `get_with_response` … `request_with_response` siblings (required `response_model`, returns `(Response, T)`) to both clients. Shipped 0.12.0; closed the deferred "Per-verb-with-response siblings" item. -supersedes: null -superseded_by: null -pr: 68 -outcome: Shipped 0.12.0 — 6 per-verb *_with_response siblings (get/post/put/patch/delete/request) on both clients, returning (Response, T). Closed the deferred "Per-verb-with-response siblings" item. --- # Design: Per-verb `*_with_response` siblings diff --git a/planning/changes/2026-06-16.01-per-verb-with-response/plan.md b/planning/changes/2026-06-16.01-per-verb-with-response/plan.md index 6db24b9..4d3adcc 100644 --- a/planning/changes/2026-06-16.01-per-verb-with-response/plan.md +++ b/planning/changes/2026-06-16.01-per-verb-with-response/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-16 -slug: per-verb-with-response -spec: per-verb-with-response -pr: 68 ---- - # per-verb-with-response — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/design.md b/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/design.md index f1b41ce..5966cb4 100644 --- a/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/design.md +++ b/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-16 -slug: circuit-breaker-rate-mode summary: Added an opt-in time-based failure-rate trip mode to the circuit breaker (classic stays default). Shipped 0.13.0; closed deferred item "CircuitBreaker v2 (a)". -supersedes: null -superseded_by: null -pr: 69 -outcome: Shipped 0.13.0 — opt-in time-based failure-rate trip mode (failure_rate_threshold + window_seconds + minimum_calls) on both breakers; classic stays default. Closed the "CircuitBreaker v2 (a)" deferred item; count-based windows, slow-call axis, and manual control + state remain deferred. --- # Design: CircuitBreaker v2 — time-based failure-rate trip mode diff --git a/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/plan.md b/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/plan.md index 96659b0..9ebcc4d 100644 --- a/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/plan.md +++ b/planning/changes/2026-06-16.02-circuit-breaker-rate-mode/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-16 -slug: circuit-breaker-rate-mode -spec: circuit-breaker-rate-mode -pr: 69 ---- - # circuit-breaker-rate-mode — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-16.03-circuit-breaker-state/design.md b/planning/changes/2026-06-16.03-circuit-breaker-state/design.md index f6dcbde..7fd2001 100644 --- a/planning/changes/2026-06-16.03-circuit-breaker-state/design.md +++ b/planning/changes/2026-06-16.03-circuit-breaker-state/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-16 -slug: circuit-breaker-state summary: Read-only `state` property + public `CircuitState` enum on the circuit breaker. Shipped 0.14.0; closed the read-only-state half of the deferred CircuitBreaker introspection item. -supersedes: null -superseded_by: null -pr: 70 -outcome: Shipped 0.14.0 — public CircuitState enum + read-only state property on both breakers (raw stored read). Closed the read-only-state half of the deferred CircuitBreaker introspection item; manual control (force_open/force_closed) remains deferred. --- # Design: Read-only `state` introspection on the circuit breaker diff --git a/planning/changes/2026-06-16.03-circuit-breaker-state/plan.md b/planning/changes/2026-06-16.03-circuit-breaker-state/plan.md index 2a33db1..fb93aa2 100644 --- a/planning/changes/2026-06-16.03-circuit-breaker-state/plan.md +++ b/planning/changes/2026-06-16.03-circuit-breaker-state/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-16 -slug: circuit-breaker-state -spec: circuit-breaker-state -pr: 70 ---- - # circuit-breaker-state — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-16.04-delta-audit-followups/change.md b/planning/changes/2026-06-16.04-delta-audit-followups/change.md index 637e6d7..d8bc142 100644 --- a/planning/changes/2026-06-16.04-delta-audit-followups/change.md +++ b/planning/changes/2026-06-16.04-delta-audit-followups/change.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-16 -slug: delta-audit-followups summary: Closed the [2026-06-16 delta audit](audits/2026-06-16-delta-audit.md) Low findings: rate-mode HALF_OPEN probe-failure re-open test + document-as-intended note. Tests + doc only, no release. -supersedes: null -superseded_by: null -pr: 71 -outcome: Closed the 2026-06-16 delta-audit Low findings — rate-mode probe-failure re-open test (async+sync) + document-as-intended note. No source behavior change. --- # Change: Close the 2026-06-16 delta-audit Low findings diff --git a/planning/changes/2026-06-23.01-retry-policy-extraction/design.md b/planning/changes/2026-06-23.01-retry-policy-extraction/design.md index c743267..fe8cc15 100644 --- a/planning/changes/2026-06-23.01-retry-policy-extraction/design.md +++ b/planning/changes/2026-06-23.01-retry-policy-extraction/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-23 -slug: retry-policy-extraction summary: Extract a stateless _RetryPolicy decision module from the duplicated AsyncRetry/Retry __call__ loops. -supersedes: null -superseded_by: null -pr: 76 -outcome: Shipped via #76 — decision logic moved into a stateless _RetryPolicy.decide; AsyncRetry/Retry are now thin loop drivers, the ~110-line sync/async duplication is gone, behaviour byte-identical (718 tests, 100% coverage). New seam suite tests/test_retry_policy.py; promoted into architecture/resilience.md. Internal refactor — no release. --- # Design: Extract a deep `_RetryPolicy` decision module diff --git a/planning/changes/2026-06-23.01-retry-policy-extraction/plan.md b/planning/changes/2026-06-23.01-retry-policy-extraction/plan.md index a69e4bc..2810d0f 100644 --- a/planning/changes/2026-06-23.01-retry-policy-extraction/plan.md +++ b/planning/changes/2026-06-23.01-retry-policy-extraction/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-23 -slug: retry-policy-extraction -spec: retry-policy-extraction -pr: 76 ---- - # retry-policy-extraction — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-23.02-decoder-resolver-extraction/design.md b/planning/changes/2026-06-23.02-decoder-resolver-extraction/design.md index d477cce..4010133 100644 --- a/planning/changes/2026-06-23.02-decoder-resolver-extraction/design.md +++ b/planning/changes/2026-06-23.02-decoder-resolver-extraction/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-23 -slug: decoder-resolver-extraction summary: Extract a _DecoderResolver (+ generic _BoundDecoder) for Seam B, collapsing the 4-site resolve/raise/decode/wrap smear in client.py. -supersedes: null -superseded_by: null -pr: 77 -outcome: Shipped via #77 — resolution + pre-flight MissingDecoderError + DecodeError wrapping moved into _DecoderResolver/_BoundDecoder (decoders/_resolver.py); the 4 send/send_with_response sites collapse to resolve→dispatch→bound.decode, both _dispatch_decoder methods removed, decoder+model sealed together. Behaviour byte-identical (723 tests, 100% coverage). New seam suite tests/test_decoder_resolver.py; promoted into architecture/decoders.md. Internal refactor — no release. --- # Design: Extract a `_DecoderResolver` for Seam B diff --git a/planning/changes/2026-06-23.02-decoder-resolver-extraction/plan.md b/planning/changes/2026-06-23.02-decoder-resolver-extraction/plan.md index f7ab438..afef9fd 100644 --- a/planning/changes/2026-06-23.02-decoder-resolver-extraction/plan.md +++ b/planning/changes/2026-06-23.02-decoder-resolver-extraction/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-23 -slug: decoder-resolver-extraction -spec: decoder-resolver-extraction -pr: 77 ---- - # decoder-resolver-extraction — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/changes/2026-06-23.03-response-body-cap/design.md b/planning/changes/2026-06-23.03-response-body-cap/design.md index 5e361d0..982b1d8 100644 --- a/planning/changes/2026-06-23.03-response-body-cap/design.md +++ b/planning/changes/2026-06-23.03-response-body-cap/design.md @@ -1,12 +1,5 @@ --- -status: shipped -date: 2026-06-23 -slug: response-body-cap summary: Replace error-only max_error_body_bytes with a status-agnostic, decoded-byte max_response_body_bytes cap enforced by a streaming capped-accumulator terminal. -supersedes: null -superseded_by: null -pr: 78 -outcome: Shipped via #78 — max_error_body_bytes removed (breaking, pre-1.0) for status-agnostic max_response_body_bytes, enforced at the non-streaming terminal and stream()'s error pre-read via a shared _read_capped accumulator counting decoded bytes (catches compression bombs); Content-Length kept as early-reject only. ResponseTooLargeError gained a declared/streamed reason; >=1 validated. Not retried / not breaker-counted; cap-wins on over-cap retryable 5xx. None-cap keeps the plain send() fast path (.elapsed preserved). 756 tests, 100% coverage. Promoted into architecture/client.md + errors.md; release note 0.15.0. --- # Design: Status-agnostic response-body cap diff --git a/planning/changes/2026-06-23.03-response-body-cap/plan.md b/planning/changes/2026-06-23.03-response-body-cap/plan.md index 060315d..a0e57d0 100644 --- a/planning/changes/2026-06-23.03-response-body-cap/plan.md +++ b/planning/changes/2026-06-23.03-response-body-cap/plan.md @@ -1,11 +1,3 @@ ---- -status: shipped -date: 2026-06-23 -slug: response-body-cap -spec: response-body-cap -pr: 78 ---- - # response-body-cap — implementation plan > **For agentic workers:** REQUIRED SUB-SKILL: Use diff --git a/planning/index.py b/planning/index.py index 392860a..8916661 100644 --- a/planning/index.py +++ b/planning/index.py @@ -2,24 +2,29 @@ """ Generate the planning index from frontmatter. -Run via ``just index``. Globs ``planning/changes/*/`` (each bundle's ``design.md``, -falling back to ``change.md``) and ``planning/decisions/*.md``, reads their -frontmatter, and prints a Markdown listing to stdout — changes grouped by lifecycle -status, then decisions newest-first. Never writes a file: the listing is a query over -the files, not a committed artifact. +Run via ``just index``. Globs ``planning/changes/*/`` (each bundle's +``design.md``, falling back to ``change.md``) and ``planning/decisions/*.md``, +reads their frontmatter, and prints a Markdown listing to stdout — changes +then decisions, newest-first. Never writes a file: +the listing is a query over the files, not a committed artifact. + +``date`` and ``slug`` are derived from the directory / file name, not +frontmatter — the name is the single source of truth for both. """ import pathlib +import re import sys CHANGES_DIR = pathlib.Path(__file__).parent / "changes" DECISIONS_DIR = pathlib.Path(__file__).parent / "decisions" -GROUPS: tuple[tuple[str, tuple[str, ...]], ...] = ( - ("In progress", ("draft", "approved")), - ("Shipped", ("shipped",)), - ("Superseded", ("superseded",)), -) +VALID_DECISION_STATUS = {"accepted", "superseded"} +BUNDLE_RE = re.compile(r"^(?P\d{4}-\d{2}-\d{2})\.\d{2}-(?P.+)$") +DECISION_RE = re.compile(r"^(?P\d{4}-\d{2}-\d{2})-(?P.+)$") +ALLOWED_BUNDLE_FILES = {"design.md", "plan.md", "change.md"} +SPEC_REQUIRED = ("summary",) +DECISION_REQUIRED = ("status", "summary") def parse_frontmatter(text: str) -> dict[str, str]: @@ -31,6 +36,8 @@ def parse_frontmatter(text: str) -> dict[str, str]: for line in lines[1:]: if line.strip() == "---": break + if line[:1] in (" ", "\t"): + continue key, sep, value = line.partition(": ") if not sep: continue @@ -39,8 +46,17 @@ def parse_frontmatter(text: str) -> dict[str, str]: return fields +def _named(fields: dict[str, str], name: str, pattern: re.Pattern[str]) -> dict[str, str]: + """Inject ``date``/``slug`` derived from a dir/file name into ``fields``.""" + match = pattern.match(name) + if match: + fields["date"] = match.group("date") + fields["slug"] = match.group("slug") + return fields + + def load_bundles() -> list[dict[str, str]]: - """Read every bundle's spec frontmatter under ``CHANGES_DIR``.""" + """Read each bundle's summary; derive date/slug from the directory name.""" bundles: list[dict[str, str]] = [] for bundle in sorted(CHANGES_DIR.iterdir()): if not bundle.is_dir(): @@ -50,7 +66,7 @@ def load_bundles() -> list[dict[str, str]]: spec = bundle / "change.md" if not spec.exists(): continue - fields = parse_frontmatter(spec.read_text(encoding="utf-8")) + fields = _named(parse_frontmatter(spec.read_text(encoding="utf-8")), bundle.name, BUNDLE_RE) fields["path"] = f"changes/{bundle.name}/{spec.name}" fields["name"] = bundle.name bundles.append(fields) @@ -58,14 +74,14 @@ def load_bundles() -> list[dict[str, str]]: def load_decisions() -> list[dict[str, str]]: - """Read frontmatter from every decision file under ``DECISIONS_DIR``.""" + """Read each decision's frontmatter; derive date/slug from the file name.""" decisions: list[dict[str, str]] = [] if not DECISIONS_DIR.is_dir(): return decisions for path in sorted(DECISIONS_DIR.glob("*.md")): if path.name == "README.md" or path.name.startswith("_"): continue - fields = parse_frontmatter(path.read_text(encoding="utf-8")) + fields = _named(parse_frontmatter(path.read_text(encoding="utf-8")), path.stem, DECISION_RE) fields["path"] = f"decisions/{path.name}" fields["name"] = path.stem decisions.append(fields) @@ -73,13 +89,12 @@ def load_decisions() -> list[dict[str, str]]: def format_row(bundle: dict[str, str]) -> str: - """Render one bundle or decision as a Markdown list item.""" + """Render one bundle as a Markdown list item.""" slug = bundle.get("slug", "?") path = bundle.get("path", "") - pr = bundle.get("pr") or "—" date = bundle.get("date", "") summary = bundle.get("summary") or "(no summary)" - line = f"- **[{slug}]({path})** (#{pr}, {date}) — {summary}" + line = f"- **[{slug}]({path})** ({date}) — {summary}" if bundle.get("supersedes"): line += f" _(supersedes {bundle['supersedes']})_" if bundle.get("superseded_by"): @@ -88,26 +103,85 @@ def format_row(bundle: dict[str, str]) -> str: def render(bundles: list[dict[str, str]], decisions: list[dict[str, str]]) -> str: - """Render the full Markdown listing: changes by status, then decisions.""" + """Render the full Markdown listing: changes then decisions, newest-first.""" out = ["# Planning index", "", "_Generated by `just index` — do not edit._", "", "## Changes", ""] - for title, statuses in GROUPS: - out += [f"### {title}", ""] - rows = sorted( - (b for b in bundles if b.get("status") in statuses), - key=lambda b: b.get("name", ""), - reverse=True, - ) - out += [format_row(b) for b in rows] if rows else ["_None._"] - out.append("") - out += ["## Decisions", ""] + change_rows = sorted(bundles, key=lambda b: b.get("name", ""), reverse=True) + out += [format_row(b) for b in change_rows] if change_rows else ["_None._"] + out += ["", "## Decisions", ""] decision_rows = sorted(decisions, key=lambda d: d.get("name", ""), reverse=True) out += [format_row(d) for d in decision_rows] if decision_rows else ["_None._"] out.append("") return "\n".join(out).rstrip() + "\n" +def _require(fields: dict[str, str], keys: tuple[str, ...], rel: str, violations: list[str]) -> None: + """Append a violation for each required key that is absent or empty.""" + violations.extend(f"{rel}: missing or empty frontmatter key '{key}'" for key in keys if not fields.get(key)) + + +def _check_spec_file(path: pathlib.Path, rel: str, violations: list[str]) -> None: + """Validate a design.md / change.md spec file (requires `summary`).""" + fields = parse_frontmatter(path.read_text(encoding="utf-8")) + _require(fields, SPEC_REQUIRED, rel, violations) + + +def _check_bundle(bundle: pathlib.Path, violations: list[str]) -> None: + """Validate one change bundle directory.""" + rel = f"changes/{bundle.name}" + if BUNDLE_RE.match(bundle.name) is None: + violations.append(f"{rel}: directory name is not 'YYYY-MM-DD.NN-slug'") + violations.extend( + f"{rel}/{child.name}: unexpected file in bundle (allowed: {', '.join(sorted(ALLOWED_BUNDLE_FILES))})" + for child in sorted(bundle.iterdir()) + if child.name not in ALLOWED_BUNDLE_FILES + ) + design = bundle / "design.md" + change = bundle / "change.md" + if not design.exists() and not change.exists(): + violations.append(f"{rel}: bundle has neither design.md nor change.md") + for spec_file in (design, change): + if spec_file.exists(): + _check_spec_file(spec_file, f"{rel}/{spec_file.name}", violations) + # plan.md carries no frontmatter — its identity comes from the bundle dir. + + +def _check_decision(path: pathlib.Path, violations: list[str]) -> None: + """Validate one decision file (requires `status` + `summary`).""" + rel = f"decisions/{path.name}" + if DECISION_RE.match(path.stem) is None: + violations.append(f"{rel}: file name is not 'YYYY-MM-DD-slug.md'") + fields = parse_frontmatter(path.read_text(encoding="utf-8")) + _require(fields, DECISION_REQUIRED, rel, violations) + status = fields.get("status", "") + if status and status not in VALID_DECISION_STATUS: + violations.append(f"{rel}: invalid status '{status}' (allowed: {', '.join(sorted(VALID_DECISION_STATUS))})") + + +def check() -> list[str]: + """Validate every bundle and decision; return the list of violation strings.""" + violations: list[str] = [] + for bundle in sorted(CHANGES_DIR.iterdir()): + if bundle.is_dir(): + _check_bundle(bundle, violations) + if DECISIONS_DIR.is_dir(): + for path in sorted(DECISIONS_DIR.glob("*.md")): + if path.name == "README.md" or path.name.startswith("_"): + continue + _check_decision(path, violations) + return violations + + def main() -> int: - """Print the listing to stdout.""" + """Print the listing to stdout, or validate bundles with --check.""" + if "--check" in sys.argv[1:]: + violations = check() + if violations: + sys.stderr.write(f"planning: {len(violations)} violation(s)\n") + for violation in violations: + sys.stderr.write(f" - {violation}\n") + return 1 + sys.stdout.write("planning: OK\n") + return 0 sys.stdout.write(render(load_bundles(), load_decisions())) return 0 From e69de0bebde5eb82e811c211b548067b2fa859aa Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 25 Jun 2026 19:42:48 +0300 Subject: [PATCH 2/3] docs: compact CLAUDE.md to invariant summaries + capability index Collapse the Architecture-invariants / Module-layout / Protocol-seams / Testing deep-dives that duplicated architecture/*.md into terse invariant summaries plus a capability-to-file index table, and add the promotion reminder. Promote the orphan Code-conventions section into a new architecture/conventions.md, and add architecture/README.md as the capability index with the promotion rule. CLAUDE.md 113 to 60 lines. Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 115 ++++++++++-------------------------- architecture/README.md | 36 +++++++++++ architecture/conventions.md | 32 ++++++++++ 3 files changed, 99 insertions(+), 84 deletions(-) create mode 100644 architecture/README.md create mode 100644 architecture/conventions.md diff --git a/CLAUDE.md b/CLAUDE.md index b23c890..be74f91 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,90 +8,45 @@ Guidance for AI agents (Claude Code, etc.) working in this repository. **Where to find what:** -- [`architecture/`](architecture/) (repo root) — the per-capability living truth (overview, client, middleware, decoders, errors, resilience, optional extras, testing); the promotion target on every ship. **Read the relevant file before changing that capability.** -- [`planning/README.md`](planning/README.md) — the planning conventions (two axes, change bundles, three lanes, frontmatter) + the change Index. +- [`architecture/`](architecture/) (repo root) — the per-capability living truth, one file per capability ([`architecture/README.md`](architecture/README.md) is the index). The promotion target on every ship. **Read the relevant file before changing that capability.** +- [`planning/README.md`](planning/README.md) — the planning convention (Quick path + the two-axis convention) and the generated change Index. - [`planning/changes//`](planning/changes/) — per-change bundles (`design.md` + `plan.md`, or `change.md` for the lightweight lane). -- [`planning/decisions/-.md`](planning/decisions/) — design decisions taken (esp. options rejected with a load-bearing reason), each with a Revisit trigger; listed by `just index`. -- [`planning/audits/`](planning/audits/) — findings reports + `scripts/` tooling. -- [`planning/retros/`](planning/retros/) — retrospectives. -- [`planning/releases/`](planning/releases/) — per-version release notes (also published on GitHub Releases). -- [`planning/deferred.md`](planning/deferred.md) — review-surfaced, not-yet-actionable items. -- [`planning/_templates/`](planning/_templates/) — design/plan/change templates. +- [`planning/decisions/`](planning/decisions/), [`planning/audits/`](planning/audits/), [`planning/retros/`](planning/retros/), [`planning/releases/`](planning/releases/), [`planning/deferred.md`](planning/deferred.md) — decisions, findings sweeps, retrospectives, release notes, and deferred items. -**Per-feature workflow:** brainstorming → `design.md` in `planning/changes//` → writing-plans → `plan.md` in the same bundle → executing-plans (or subagent-driven-development) → requesting-code-review → finishing-a-development-branch. On ship, promote the conclusions into the affected `architecture/.md` by hand and set `status: shipped` + `pr` + `outcome` in the implementing PR — there is no folder move. The change listing is generated: run `just index`. A design decision taken without a code change — especially a candidate rejected with a load-bearing reason — is recorded as `planning/decisions/YYYY-MM-DD-.md` (the `decision.md` template, frontmatter `status: accepted|superseded`), each with a **Revisit trigger** so future reviews don't re-litigate it; listed by `just index`. Topic slugs are kebab-case descriptions (`msgspec-decoder-adapter`), not story IDs. +## Workflow -## Commands - -This project uses `just` (task runner) and `uv` (package manager). - -```bash -just install # uv lock --upgrade && uv sync --all-extras --frozen --group lint -just lint # eof-fixer + ruff format + ruff check --fix + ty check -just lint-ci # same checks without auto-fixing (used in CI) -just test # uv run pytest (with coverage by default) -just test-branch # pytest with branch coverage -``` - -`just test` passes extra args to pytest: - -```bash -just test tests/test_client.py -just test tests/test_client.py -k test_get_returns_typed_response -``` - -Without `just`: - -```bash -uv run ruff format . && uv run ruff check . --fix && uv run ty check -uv run pytest -``` - -## Architecture invariants - -These are non-negotiable, but **most are NOT machine-checked — don't rely on CI to catch a violation.** Enforced by ruff: `print()` (`T201`) and a blanket `# type: ignore` (`PGH003`). Partially: `httpx2._` (ruff `SLF001` catches attribute access, not a *used* private import). Review-only: the future-import and global-logging bans. +Planning follows the portable two-axis convention — `architecture/` (repo root) is the living **truth home** and promotion target; `planning/changes/` holds the per-change bundles. **Start at the [Quick path](planning/README.md#quick-path-start-here)** in `planning/README.md` to choose a lane (Full / Lightweight / Tiny), create a bundle, and ship — that file is the authoritative spec. Run `just check-planning` to validate bundles and `just index` to print the change listing. -- **No `httpx2` private API**: `grep -rE 'httpx2\._' src/httpware/` should return zero matches (run in review — not wired into CI). Public symbols only. -- **No `from __future__ import annotations`**: Python 3.11+ floor; PEP 604/585 syntax is native. -- **No `print()`**: enforced by ruff. -- **No global logging config**: no `logging.basicConfig()`, no bare `logging.getLogger()`. Acquire `logging.getLogger("httpware")` or `logging.getLogger(f"httpware.{module}")` only. -- **Type suppressions**: use `# ty: ignore[]`, never `# type: ignore` or `# mypy: ignore`. - -## Code conventions - -- **Modules**: `snake_case` (`client.py`, `errors.py`, `middleware/chain.py`). -- **Classes**: `PascalCase`. `Http` is two letters: `AsyncClient`, not `ASYNCClient`. -- **Methods**: `snake_case`. No `a` prefix on async methods (match `httpx2`); `aclose()` is the sole exception. -- **Private symbols**: `_leading_underscore`. Cross-module private code lives in `_internal/`. -- **Imports**: absolute paths inside `src/httpware/`; relative imports only within the same subpackage. -- **Docstrings**: PEP 257. Module/class/public-method required; `D1` (missing docstring) is ignored. -- **Exception construction**: status-keyed `StatusError` subclasses (the 4xx/5xx tree) take a single positional `response: httpx2.Response` and do NOT override `__init__` — all fields via `exc.response.*`. This rule scopes to `StatusError` only; non-status `ClientError` subclasses such as `DecodeError`, `MissingDecoderError`, `BulkheadFullError`, `RetryBudgetExhaustedError`, and `CircuitOpenError` deliberately define `__init__` with keyword-only fields. See `architecture/errors.md`. +## Commands -## Module layout +This project uses `just` (task runner) and `uv` (package manager). `just --list` is the source of truth; non-obvious notes: -``` -src/httpware/ -├── __init__.py # public exports + __all__ -├── client.py # AsyncClient + Client (thin wrappers over httpx2.AsyncClient / httpx2.Client) -├── errors.py # status-keyed exception hierarchy holding httpx2.Response -├── middleware/ # protocol, Next type, chain composition, phase decorators -├── decoders/ # ResponseDecoder protocol + Pydantic/msgspec adapters -├── _internal/ # private cross-module helpers -└── py.typed -``` +- `just lint` auto-fixes; `just lint-ci` is the read-only CI variant (and runs the planning validator). +- `just test` runs pytest with coverage and forwards extra args: `just test tests/test_client.py -k test_name`. +- Without `just`: `uv run ruff format . && uv run ruff check . --fix && uv run ty check && uv run pytest`. -## Protocol seams +## Architecture -Three documented internal boundaries. AI agents must respect them — never cross a seam except through its documented protocol. +> Quick orientation. The authoritative, code-current account of each capability lives in [`architecture/`](architecture/). **When a change alters a capability's behavior, update the matching `architecture/.md` in the same PR** — that promotion is what keeps `architecture/` true; code that changes without it silently rots the truth home. -1. **Seam A** — `Client`/`AsyncClient` ↔ `Middleware`/`AsyncMiddleware` — middleware chain composed at `Client.__init__` and `AsyncClient.__init__`, frozen for the client's lifetime. Internal terminal calls `httpx2.Client.send` or `httpx2.AsyncClient.send`, maps exceptions, raises `StatusError` on 4xx/5xx. Sync and async surfaces are kept at parity. -2. **Seam B** — `Client`/`AsyncClient` ↔ `ResponseDecoder` list — both clients take `decoders: Sequence[ResponseDecoder] | None` (a *list*, not a single decoder; `None` resolves against installed extras, pydantic-first). When `response_model` is provided, `send`/`send_with_response` (sync and async alike) walk the list and the first decoder whose `can_decode(model: type) -> bool` returns True runs `decode(content: bytes, model: type[T]) -> T`; if no decoder claims the model, `MissingDecoderError` is raised *before* the HTTP call. Decoder exceptions are wrapped as `DecodeError` at the seam. Full contract: [`architecture/decoders.md`](architecture/decoders.md). -3. **Seam C** — `httpware` ↔ optional extras — each opt-in dependency imported only inside its dedicated module. +`httpware` is a thin wrapper over `httpx2` (`httpx2.Request`/`httpx2.Response` are public surface, not abstracted away) built around three documented protocol seams. **Invariants that must not break:** -## Testing +- **Three protocol seams, crossed only through their protocols.** Seam A: `Client`/`AsyncClient` ↔ middleware chain, composed at `__init__` and frozen for the client's lifetime; the internal terminal calls `httpx2.*.send`, maps exceptions, and raises `StatusError` on 4xx/5xx. Seam B: clients ↔ `decoders: Sequence[ResponseDecoder] | None` — first decoder whose `can_decode` is True runs; `MissingDecoderError` raises *before* the HTTP call if none claims the model; decoder failures wrap as `DecodeError`. Seam C: `httpware` ↔ optional extras — each opt-in dependency imported only inside its dedicated module. +- **Sync/async parity.** `Client` and `AsyncClient` carry identical features (typed decoding, middleware, resilience, `stream()`); a change to one surface must mirror to the other. +- **House invariants** (most review-only, not CI-checked): no `httpx2._` private API; no `from __future__ import annotations` (3.11+ floor); no `print()` (ruff `T201`); no global logging config (`logging.getLogger("httpware")` / namespaced children only); type suppressions use `# ty: ignore[]`, never `# type: ignore`. +- **Errors.** Status-keyed `StatusError` subclasses take a single positional `response` and never override `__init__`; non-status `ClientError` subclasses (`DecodeError`, `MissingDecoderError`, `BulkheadFullError`, `RetryBudgetExhaustedError`, `CircuitOpenError`, `ResponseTooLargeError`) do. -- `pytest-asyncio` auto mode — async tests do NOT need `@pytest.mark.asyncio`. -- Property-based tests (Hypothesis) for concurrency-sensitive code: `RetryBudget`, `Bulkhead`, retry interleaving. Files named `test_*_props.py`. -- Tests inject `httpx2.MockTransport` via `AsyncClient(httpx2_client=httpx2.AsyncClient(transport=mock))` for async or `Client(httpx2_client=httpx2.Client(transport=mock))` for sync. No `respx`, no `RecordedTransport`. +| Capability | File | +|---|---| +| What httpware is + architectural invariants + module layout | [`architecture/overview.md`](architecture/overview.md) | +| Sync `Client` / async `AsyncClient` parity, `stream()` | [`architecture/client.md`](architecture/client.md) | +| Seam A — middleware protocol, `Next`, chain composition | [`architecture/middleware.md`](architecture/middleware.md) | +| Seam B — `ResponseDecoder` protocol, pydantic/msgspec resolution | [`architecture/decoders.md`](architecture/decoders.md) | +| Status-keyed exception tree, construction invariant, redaction | [`architecture/errors.md`](architecture/errors.md) | +| Resilience suite (retry, budget, bulkhead, circuit breaker, timeout) | [`architecture/resilience.md`](architecture/resilience.md) | +| Seam C — optional extras isolation | [`architecture/extras.md`](architecture/extras.md) | +| House code conventions (naming, imports, docstrings) | [`architecture/conventions.md`](architecture/conventions.md) | +| Testing conventions | [`architecture/testing.md`](architecture/testing.md) | ## When in doubt @@ -100,14 +55,6 @@ Three documented internal boundaries. AI agents must respect them — never cros ## Agent skills -### Issue tracker - -Issues live in GitHub Issues (`modern-python/httpware`), managed via the `gh` CLI; external PRs are not a triage surface. See `planning/agents/issue-tracker.md`. - -### Triage labels - -Canonical defaults — `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix` (the last already exists). See `planning/agents/triage-labels.md`. - -### Domain docs - -Single-context — one `CONTEXT.md` at the repo root + ADRs under `planning/adr/`. See `planning/agents/domain.md`. +- **Issue tracker** — Issues live in GitHub Issues (`modern-python/httpware`), managed via the `gh` CLI; external PRs are not a triage surface. See `planning/agents/issue-tracker.md`. +- **Triage labels** — Canonical defaults: `needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`, `wontfix`. See `planning/agents/triage-labels.md`. +- **Domain docs** — Single-context: one `CONTEXT.md` at the repo root + ADRs under `planning/adr/`. See `planning/agents/domain.md`. diff --git a/architecture/README.md b/architecture/README.md new file mode 100644 index 0000000..0f7fb53 --- /dev/null +++ b/architecture/README.md @@ -0,0 +1,36 @@ +# Architecture + +This directory is the **living per-capability truth** about what `httpware` +does *now* — one file per capability, living prose, dated by git (no +frontmatter). It is the promotion target on every ship: the *why* and *how it +got here* live in [`planning/`](../planning/), the *what it is today* lives +here. + +## Capability files + +- **[overview.md](overview.md)** — what `httpware` is (a thin `httpx2` wrapper) + and the cross-cutting architectural invariants. +- **[client.md](client.md)** — the sync `Client` / async `AsyncClient` pair and + their parity contract (typed decoding, middleware chain, resilience, `stream()`). +- **[middleware.md](middleware.md)** — Seam A: the middleware protocol, `Next` + type, and chain composition at client construction. +- **[decoders.md](decoders.md)** — Seam B: the `ResponseDecoder` protocol and + the pydantic / msgspec decoder resolution. +- **[errors.md](errors.md)** — the status-keyed exception tree raised on 4xx/5xx + and the `StatusError` construction invariant. +- **[resilience.md](resilience.md)** — the stdlib resilience suite (retry, retry + budget, bulkhead, circuit breaker, timeout) composed via the middleware chain. +- **[extras.md](extras.md)** — Seam C: optional dependencies imported only inside + their dedicated modules. +- **[conventions.md](conventions.md)** — house code conventions: naming, imports, + docstrings, exception construction. +- **[testing.md](testing.md)** — the testing conventions (`pytest-asyncio` auto + mode, mock transports, property-based tests). + +## Promotion rule + +When a change alters a capability's behavior, **hand-edit the matching +`architecture/.md` in the same PR** — the edit rides in the same +diff and is reviewed with the code, never applied as a separate post-merge step. +That promotion is what keeps this directory true; code that changes without it +silently rots the truth home. diff --git a/architecture/conventions.md b/architecture/conventions.md new file mode 100644 index 0000000..54346d5 --- /dev/null +++ b/architecture/conventions.md @@ -0,0 +1,32 @@ +# Code conventions + +The naming, import, and docstring conventions every module in `src/httpware/` +follows. These are house style, not machine-checked beyond what ruff enforces; +treat a violation as a review blocker. + +## Naming + +- **Modules**: `snake_case` (`client.py`, `errors.py`, `middleware/chain.py`). +- **Classes**: `PascalCase`. `Http` is two letters: `AsyncClient`, not + `ASYNCClient`. +- **Methods**: `snake_case`. No `a` prefix on async methods (match `httpx2`); + `aclose()` is the sole exception. +- **Private symbols**: `_leading_underscore`. Cross-module private code lives in + `_internal/`. + +## Imports + +- Absolute paths inside `src/httpware/`; relative imports only within the same + subpackage. + +## Docstrings + +- PEP 257. Module / class / public-method docstrings are required; `D1` + (missing docstring) is ignored, so the requirement is review-enforced. + +## Exception construction + +Status-keyed `StatusError` subclasses take a single positional +`response: httpx2.Response` and do **not** override `__init__`; non-status +`ClientError` subclasses deliberately do. This invariant — and which subclasses +fall on each side — lives in [`errors.md`](errors.md). From 9a599ba5fc1220635b083e1995ee8a0b70f2491c Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 25 Jun 2026 19:48:33 +0300 Subject: [PATCH 3/3] chore: vendor generic release.md template --- planning/_templates/release.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/planning/_templates/release.md b/planning/_templates/release.md index 7372d7e..5081187 100644 --- a/planning/_templates/release.md +++ b/planning/_templates/release.md @@ -1,4 +1,4 @@ -# modern-di +# @@ -30,10 +30,9 @@ Context a reader needs for the headline change. Omit for small releases. ## Downstream -What integrations (FastAPI, Litestar, FastStream, Typer, `modern-di-pytest`) -must do — e.g. bump their `modern-di` floor — or "No action needed" when there -is no API change. +What dependents must do — e.g. bump their version floor — or "No action +needed" when there is no API change. Omit if the project has no downstreams. ## Internals -- Coverage / tooling notes (e.g. 100% line coverage across Python 3.10–3.14). +- Coverage / tooling notes.