Skip to content

feat: deepen ACTION scope behind action_scope(ctx)#15

Merged
lesnik512 merged 2 commits into
mainfrom
feat/action-scope
Jun 26, 2026
Merged

feat: deepen ACTION scope behind action_scope(ctx)#15
lesnik512 merged 2 commits into
mainfrom
feat/action-scope

Conversation

@lesnik512

@lesnik512 lesnik512 commented Jun 25, 2026

Copy link
Copy Markdown
Member

What

Two things, on one branch:

  1. Feature — a public action_scope(ctx) context manager so commands reach Scope.ACTION dependencies without touching modern_di's container interface:

    @app.command()
    @inject
    def my_command(ctx: typer.Context) -> None:
        for job_name in job_names:
            with action_scope(ctx) as action:
                action.resolve_provider(Dependencies.job).run()
  2. Planning convention — adopt the portable two-axis convention from lesnik512/planning-convention (v1.0.0), as applied in the sibling modern-di repo, replacing the single CONTEXT.md.

Feature: deepen ACTION scope

Before, ACTION scope leaked build_child_container() to every call site (the command injected modern_di.Container and built a child by hand). REQUEST scope was deep behind @inject; ACTION was shallow. This pulls scope-nesting behind one named interface — leverage (one interface for every scope) and locality (nesting lives in action_scope).

  • Multiple actions per command preserved — each with action_scope(ctx) block is its own ACTION container (the loop case ACTION exists for). See planning/decisions/2026-06-25-action-scope-multiple-actions-per-command.md.
  • @inject now always builds the per-command REQUEST container and stashes it on ctx.meta (per-invocation, isolated — not ctx.obj, shared app state), so request-scoped singletons are shared between injected params and action-resolved deps.
  • The manual FromDI(Container) pattern still works and stays tested (backward compatible).

Planning convention

  • architecture/ — living capability truth (scopes.md, injection.md); the promotion target.
  • planning/.convention-version, README, index.py validator/indexer, _templates/, changes/, decisions/, deferred.md.
  • Seeded with the real artifacts for this change (the 2026-06-25.01-action-scope bundle + decision); deferred.md records the still-open ctx.obj container-seam candidate.
  • lint-ci runs planning/index.py --check; adds just index / just check-planning; CLAUDE.md points at architecture/ and planning/.

Verification

just test-ci — 11 passed, 100% coverage (planning/index.py is never imported, so the --cov=. gate is unaffected). just lint-ci clean (ruff + planning validation). just check-planningplanning: OK.

🤖 Generated with Claude Code

lesnik512 and others added 2 commits June 25, 2026 23:52
Add a public `action_scope(ctx)` context manager that yields a fresh
ACTION-scoped container (a child of the command's REQUEST container).
Commands no longer inject `modern_di.Container` and call
`build_child_container()` by hand to reach ACTION scope. Multiple
actions per command are preserved: each `with action_scope(ctx)` block
is its own action scope, so a command can open one per unit of work.

`@inject` now always builds the per-command REQUEST container and
stashes it on `ctx.meta`, so `action_scope` can parent the ACTION
container onto it. Request-scoped singletons are therefore shared
between injected params and deps resolved inside an action scope.

The manual `FromDI(Container)` + `build_child_container()` pattern still
works and remains tested.

Also correct stale CLAUDE.md architecture notes (module-global
`_container`, public `build_command_container`) and add CONTEXT.md
naming the app container / command container / action scope seams.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…TEXT.md

Replace the single CONTEXT.md with the portable two-axis planning
convention from lesnik512/planning-convention (v1.0.0), as applied in the
sibling modern-di repo:

- architecture/ — living capability truth (README, scopes.md, injection.md),
  the promotion target on every ship.
- planning/ — .convention-version, README (portable convention), index.py
  validator/indexer, _templates/ (change/design/plan/decision/release),
  changes/, decisions/, deferred.md.

Seed it with the real artifacts for this branch's feature: the
2026-06-25.01-action-scope change bundle (design.md + plan.md) and the
action-scope-multiple-actions-per-command decision. deferred.md records the
still-open ctx.obj container-seam candidate from the architecture review.

Wire-up: lint-ci runs `planning/index.py --check`; add `just index` /
`just check-planning`; CLAUDE.md points at architecture/ and planning/.

index.py is copied from canonical; only its ruff-noqa comment is adapted to
this repo's lint config (D213 ignored, so D212 is suppressed), matching how
modern-di adapts it. planning/index.py is never imported, so test-ci's
`--cov=.` 100% gate is unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lesnik512 lesnik512 merged commit 3e9eb47 into main Jun 26, 2026
6 checks passed
@lesnik512 lesnik512 deleted the feat/action-scope branch June 26, 2026 07:36
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