Skip to content

chore: migrate off the planning/ convention - #42

Merged
lesnik512 merged 1 commit into
mainfrom
chore/migrate-off-planning
Sep 6, 2026
Merged

chore: migrate off the planning/ convention#42
lesnik512 merged 1 commit into
mainfrom
chore/migrate-off-planning

Conversation

@lesnik512

Copy link
Copy Markdown
Member

Migrates modern-di-fastapi off the planning/ convention and onto PR-body-as-spec, with CONTEXT.md owning the vocabulary and docs/adr/ holding rejected alternatives. Part of modern-python/.github#67.

Replaces the two-axis planning/ + architecture/ convention with PR-body-as-spec,
CONTEXT.md for vocabulary, and docs/adr/ for rejected alternatives, per
modern-python/.github#67.

  • planning/ deleted in full. changes/ held one design record whose content is the
    diff it describes, and git history is that record; releases/ held six notes
    verified byte-identical to the published GitHub Release bodies (3.0.1 and
    2.10.0 diffed against gh release view, differing only by a trailing newline
    GitHub adds), and the Releases are the record. deferred.md was empty and the
    change file listed non-goals rather than unscheduled work, so no issues needed
    drafting and there is no DRAFT-ISSUES file.
  • planning/decisions/ was empty, so ADR-0001 is rescued instead from the
    rationale buried in architecture/container-lifecycle.md and _compose_lifespan:
    why this package owns its lifespan composition rather than calling FastAPI's
    private _merge_lifespan_context. It keeps a revisit trigger.
  • architecture/ carried three prose pages about mechanism, all readable from
    main.py. The one enforceable claim was glossary.md's "the providers are the
    single source — there is no separate hardcoded table", now the INVARIANT test
    tests/test_connection_kinds.py. Verified against three cases: replacing
    classify_connection with an isinstance ladder fails it, naming the two
    providers literally in setup_di fails it, and narrowing the dispatch to
    HTTPConnection-typed providers — a change that restricts rather than
    duplicates — leaves it green.
  • CONTEXT.md defines only the two terms local to this integration; Container,
    Provider, Group, Scope, Resolution, Override and Connection stay modern-di's
    and are not redefined here. Both Avoid entries were audited against real
    usage and both had live stragglers, so the stragglers were fixed rather than
    the entries dropped: "per-request"/"request container" in README.md and in
    main.py's Dependency.call parameter, now per-connection; and "appends a
    lifespan ... merges with any existing lifespan=" in README.md's API table, now
    composes/nesting. Both README edits are user-visible strings — that table is
    rendered on PyPI. tests/test_routes.py's build_di_container parameter was
    renamed to connection_container for the same reason. test_websockets.py keeps
    request_container for the REQUEST-scoped child it builds by hand: that is a
    scope name for a real child container, not the per-connection one.
  • AGENTS.md gains Workflow and Where-a-fact-goes, loses the planning lanes and
    the architecture/ promotion rule, and states the ty-suppression spelling the
    justfile does not. docs/agents/domain.md is deliberately absent: this repo has
    no docs/agents/ tree and AGENTS.md has no Agent skills section to link one
    from, so authoring domain.md alone would be a half-rollout of a separate
    convention.
  • justfile and lint-ci drop index/check-planning/check-links; the offline lychee
    gate in _checks.yml replaces links.py (Add the offline link gate to the 18 green repos, and unpublish the ADRs in the two that have them .github#66), reporting 0
    errors over 32 unique links.

Beyond the recipe, and the reason this is chore: and not docs: release.yml
sourced the Release body from planning/releases/.md and hard-required one
for every stable tag, so deleting planning/ would have failed every future
stable release. It now uses GitHub's generated notes, byte-identical to
modern-di's post-migration workflow, which dropped the same gate in 1ea74ee
(modern-python/modern-di#449). This retires the mandatory-curated-notes policy;
a release wanting prose is edited after the fact with gh release edit.

Verification: just lint-ci clean, just test-ci 9 passed at 100% coverage,
lychee --offline 0 errors, and no remaining reference to planning/,
architecture/, check-planning, check-links or convention-version anywhere in the
tree.

Verification

  • just lint-ci — clean (eof-fixer, ruff format, ruff check, ty).
  • Test suite green at the repo's 100% coverage gate.
  • Offline link gate (lychee --offline --no-progress '**/*.md') — 0 errors.
  • No planning/, architecture/, check-planning, check-links or convention-version reference remains.

Note

release.yml previously read planning/releases/<tag>.md, both as a hard gate for stable tags and as the Release body source; deleting planning/ without changing it would have broken the next stable release. It now uses GitHub's generated notes, matching modern-di post-modern-python/modern-di#449. This retires the mandatory-curated-notes policy.

Replaces the two-axis planning/ + architecture/ convention with PR-body-as-spec,
CONTEXT.md for vocabulary, and docs/adr/ for rejected alternatives, per
modern-python/.github#67.

- planning/ deleted in full. changes/ held one design record whose content is the
  diff it describes, and git history is that record; releases/ held six notes
  verified byte-identical to the published GitHub Release bodies (3.0.1 and
  2.10.0 diffed against `gh release view`, differing only by a trailing newline
  GitHub adds), and the Releases are the record. deferred.md was empty and the
  change file listed non-goals rather than unscheduled work, so no issues needed
  drafting and there is no DRAFT-ISSUES file.
- planning/decisions/ was empty, so ADR-0001 is rescued instead from the
  rationale buried in architecture/container-lifecycle.md and _compose_lifespan:
  why this package owns its lifespan composition rather than calling FastAPI's
  private _merge_lifespan_context. It keeps a revisit trigger.
- architecture/ carried three prose pages about mechanism, all readable from
  main.py. The one enforceable claim was glossary.md's "the providers are the
  single source — there is no separate hardcoded table", now the INVARIANT test
  tests/test_connection_kinds.py. Verified against three cases: replacing
  classify_connection with an isinstance ladder fails it, naming the two
  providers literally in setup_di fails it, and narrowing the dispatch to
  HTTPConnection-typed providers — a change that restricts rather than
  duplicates — leaves it green.
- CONTEXT.md defines only the two terms local to this integration; Container,
  Provider, Group, Scope, Resolution, Override and Connection stay modern-di's
  and are not redefined here. Both _Avoid_ entries were audited against real
  usage and both had live stragglers, so the stragglers were fixed rather than
  the entries dropped: "per-request"/"request container" in README.md and in
  main.py's Dependency.__call__ parameter, now per-connection; and "appends a
  lifespan ... merges with any existing lifespan=" in README.md's API table, now
  composes/nesting. Both README edits are user-visible strings — that table is
  rendered on PyPI. tests/test_routes.py's build_di_container parameter was
  renamed to connection_container for the same reason. test_websockets.py keeps
  request_container for the REQUEST-scoped child it builds by hand: that is a
  scope name for a real child container, not the per-connection one.
- AGENTS.md gains Workflow and Where-a-fact-goes, loses the planning lanes and
  the architecture/ promotion rule, and states the ty-suppression spelling the
  justfile does not. docs/agents/domain.md is deliberately absent: this repo has
  no docs/agents/ tree and AGENTS.md has no Agent skills section to link one
  from, so authoring domain.md alone would be a half-rollout of a separate
  convention.
- justfile and lint-ci drop index/check-planning/check-links; the offline lychee
  gate in _checks.yml replaces links.py (modern-python/.github#66), reporting 0
  errors over 32 unique links.

Beyond the recipe, and the reason this is chore: and not docs: release.yml
sourced the Release body from planning/releases/<tag>.md and hard-required one
for every stable tag, so deleting planning/ would have failed every future
stable release. It now uses GitHub's generated notes, byte-identical to
modern-di's post-migration workflow, which dropped the same gate in 1ea74ee
(modern-python/modern-di#449). This retires the mandatory-curated-notes policy;
a release wanting prose is edited after the fact with `gh release edit`.

Verification: just lint-ci clean, just test-ci 9 passed at 100% coverage,
lychee --offline 0 errors, and no remaining reference to planning/,
architecture/, check-planning, check-links or convention-version anywhere in the
tree.
@lesnik512
lesnik512 merged commit 51269e3 into main Sep 6, 2026
7 checks passed
@lesnik512
lesnik512 deleted the chore/migrate-off-planning branch September 6, 2026 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant