Skip to content

Import hexagonal architecture enforcement - #8

Merged
leynos merged 13 commits into
mainfrom
import-hex-architecture-enforcement
May 16, 2026
Merged

Import hexagonal architecture enforcement#8
leynos merged 13 commits into
mainfrom
import-hex-architecture-enforcement

Conversation

@leynos

@leynos leynos commented May 10, 2026

Copy link
Copy Markdown
Owner

Summary

This branch imports BeatCue's local hexagonal architecture enforcement trial from the Episodic mechanism and adapts it to BeatCue's package names, composition-root exception, and infrastructure boundaries.

Execplan: docs/execplans/import-hex-architecture-enforcement.md

It adds an ast-based checker that expands package-barrel re-exports, verifies the current beatcue/ skeleton, and uses fixture packages to prove the intended future domain, application, adapter, and config boundaries. It also wires the architecture gate into make lint, records the accepted decision in ADR 003, and completes the ExecPlan retrospective with prior-art and extraction notes.

Review walkthrough

Validation

  • make check-fmt 2>&1 | tee /tmp/check-fmt-beatcue-import-hex-architecture-enforcement.out: passed.
  • make lint 2>&1 | tee /tmp/lint-beatcue-import-hex-architecture-enforcement.out: passed; Ruff ran first, then make check-architecture.
  • make typecheck 2>&1 | tee /tmp/typecheck-beatcue-import-hex-architecture-enforcement.out: passed.
  • make test 2>&1 | tee /tmp/test-beatcue-import-hex-architecture-enforcement.out: passed, 11 passed.
  • make markdownlint 2>&1 | tee /tmp/markdownlint-beatcue-import-hex-architecture-enforcement.out: passed.
  • make nixie 2>&1 | tee /tmp/nixie-beatcue-import-hex-architecture-enforcement.out: passed.
  • coderabbit review --agent: completed; valid Oxford-comma finding was fixed, and stale blank-line/spelling findings were verified against the current files and recorded in the ExecPlan.

Notes

The implementation exceeded the original 700-line production tolerance during the checker import. The ExecPlan records the escalation and the later user direction to proceed. No runtime dependency was added.

The main follow-up is to extract the reusable checker core into a small df12/internal tool with a TOML or JSON policy schema before trying the mechanism in Prosidy Darn.

Summary by Sourcery

Introduce a repository-local hexagonal architecture checker, wire it into the lint workflow, and document the enforced import boundaries and workflow for contributors.

Enhancements:

  • Add a static AST-based import checker with BeatCue-specific architecture policies and CLI entrypoint to enforce hexagonal boundaries.
  • Implement re-export resolution and shared import-resolution helpers to ensure barrel modules and star imports cannot hide forbidden dependencies.

Build:

  • Extend the Makefile with a check-architecture target and integrate it into the lint pipeline.

Documentation:

  • Document the architecture checker, its Makefile targets, and enforced rules in the developers' guide and add ADR 003 plus an execution plan detailing the design and retrospective.

Tests:

  • Add fixture-based architecture tests and relative-import edge-case coverage to validate allowed and forbidden dependency graphs and current BeatCue compliance.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 2500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 575e2a51-1f0e-4f33-bc3f-ec8db9296baf

📥 Commits

Reviewing files that changed from the base of the PR and between e7878e5 and 6c7da0e.

📒 Files selected for processing (1)
  • docs/execplans/import-hex-architecture-enforcement.md

Hexagonal Architecture Enforcement Implementation

Imports and adapts a repository-local AST-based hexagonal architecture checker (from Episodic) into BeatCue, enforcing package dependency boundaries through static analysis and package-barrel re-export expansion (explicit and star imports). The checker is policy-driven (domain, application, adapter, composition-root and infrastructure groups) and reports ARCH001 violations.

Core Architecture Package (beatcue/architecture/)

  • checker.py: AST scanner that builds a re-export index from package init.py files (explicit and star re-exports), classifies modules via ArchitecturePolicy, and emits ArchitectureViolation instances; exposes check_architecture() and result/violation dataclasses.
  • policy.py: ModuleGroup and ArchitecturePolicy (rule_id "ARCH001"); provides default_policy() for BeatCue and fixture_policy(package) for fixture packages. Includes a composition-root exception allowing beatcue.config and an infrastructure group for external/tooling prefixes.
  • reexports.py: Static symbol→origin re-export index builder; prefers literal all, falls back to inferred public symbols, and guards against recursion during star-expansion.
  • _imports.py: Utilities to compute dotted module names from filesystem paths and resolve relative/absolute from ... import ... AST nodes.
  • cli.py and main.py: CLI entrypoint (python -m beatcue.architecture) with --package, --root and --fixture-policy flags; prints violations to stderr and returns exit codes 0 (pass), 1 (violations), 2 (errors).

Integration & Tooling

  • Makefile: Adds check-architecture target (depends on build and uv) that runs the checker via the project virtual environment; make lint now invokes check-architecture after Ruff.
  • Dev dependency: hypothesis>=6.152.7 added for property-based tests.

Design & Operational Documents

  • ExecPlan: docs/execplans/import-hex-architecture-enforcement.md added and referenced — a living ExecPlan capturing the trial, constraints (local checker, no runtime deps), quantitative tolerances (including the noted production-file/line tolerance exceedance), risk register, milestones and retrospective.
  • ADR 003: docs/adr-003-hexagonal-architecture-enforcement.md records the accepted decision to adopt AST-based static enforcement, documents checker behaviour and ARCH001, and documents the beatcue.config composition-root exception and limitations.
  • Developers’ guide and roadmap: developers-guide.md documents make check-architecture, ARCH001 and fixture-based testing; docs/roadmap.md marks the CI fitness-function item done and clarifies it can run before the package skeleton using fixture packages.

Tests & Fixtures

  • Fixtures: new fixture packages under tests/fixtures/architecture/ covering allowed and forbidden graphs, re-export and relative-import edge cases, composition-root wiring, inbound/outbound adapter scenarios and star-reexport handling.
  • Tests:
    • tests/test_architecture_checker.py: parameterised tests and Hypothesis properties for violations, allowed graphs, input validation, policy directionality, module-name round-trips and relative-import base behaviour.
    • tests/test_architecture_cli.py: CLI and module-entrypoint tests, --fixture-policy behaviour and error handling.
    • tests/test_architecture_reexports.py: verifies star-import resolution, selection of the last resolvable all, fallback to inferred symbols and index idempotency.
  • Validation reported as passing: check-fmt, lint (including check-architecture), typecheck, tests (11 passed), markdownlint and nixie. CodeRabbit review completed; findings addressed and recorded.

Notes & Follow-up

  • The ExecPlan documents the imported implementation exceeding the original 700-line production-file tolerance.
  • No runtime dependencies were added.
  • Main follow-up: extract the reusable checker core into a small internal tool with a TOML/JSON policy schema for reuse across projects.

Walkthrough

Introduce a repository-local static architecture checker enforcing hexagonal import boundaries via AST analysis; expose it as python -m beatcue.architecture, add make check-architecture and run it from make lint; include fixture packages, tests (unit, parametrised and property), and documentation.

Changes

Hexagonal Architecture Enforcement

Layer / File(s) Summary
Import-resolution helpers & module-name computation
beatcue/architecture/_imports.py
Compute dotted module names from filesystem paths, resolve from ... import ... (relative and absolute), and compute relative-import bases used by re-export expansion.
Re-export indexer and export inference
beatcue/architecture/reexports.py
Scan package __init__.py files, collect top-level from ... import ... re-exports, expand from ... import * by preferring literal __all__ or inferring public symbols, guard recursion, and emit symbol→origin mappings for star-expansion.
Architecture policy and groups
beatcue/architecture/policy.py
ModuleGroup classifies modules by prefixes and declares allowed import groups; ArchitecturePolicy orders groups and provides group_for; _beatcue_groups builds groups for composition root, domain, application, inbound/outbound adapters, generic adapter and infrastructure; expose default_policy() and fixture_policy().
Checker orchestration and import scanning
beatcue/architecture/checker.py
Implement check_architecture: validate package root, build re-export index, walk package sources, enumerate imports via AST (including star re-exports), map imported targets to module+symbol contexts, deduplicate, compute groups via policy, and aggregate ArchitectureViolation results into ArchitectureCheckResult.
Package API, CLI, Makefile and dev deps
beatcue/architecture/__init__.py, beatcue/architecture/__main__.py, beatcue/architecture/cli.py, Makefile, pyproject.toml
Export public API symbols, add __main__ entrypoint, implement CLI with --package, --root, --fixture-policy, add make check-architecture target (runs python -m beatcue.architecture via virtual env), run checker from make lint, and add hypothesis to dev deps.
Fixture test packages
tests/fixtures/architecture/*
Add multiple fixture package scenarios modelling allowed and forbidden import patterns: adapter re-exports, star-reexports, domain ports, composition-root wiring, CLI/config wiring, and explicit boundary violations.
Re-export index tests
tests/test_architecture_reexports.py
Test star-import resolution through package root __all__, __all__ precedence (last literal wins), fallback to inferred public symbols, and idempotence of build_reexport_index.
Checker and CLI tests
tests/test_architecture_checker.py, tests/test_architecture_cli.py
Parametrised fixture tests asserting exact violation fields and rendered diagnostics; tests for allowed fixture graphs and current production package; input validation tests for check_architecture; Hypothesis property tests for compute_module_name and relative_import_base; CLI tests for normal, None, fixture-policy, missing-root, unknown-argument and module-entrypoint behaviours.
Architecture ADR, ExecPlan and developer docs
docs/adr-003-hexagonal-architecture-enforcement.md, docs/developers-guide.md, docs/execplans/import-hex-architecture-enforcement.md, docs/roadmap.md
Document the design, goals, constraints, risk register, decision log, implementation notes, developer guidance for make check-architecture and lint gating, and mark roadmap task 1.2.2 complete.
  • Possibly related PRs:
    • leynos/episodic#87: Both PRs modify Makefile lint gating to run an additional checker command after Ruff.

Poem

Hexagons trace the code's design,
AST walks every dotted line,
Policy checks who may call,
Fixtures show the rise and fall,
Makefile gates keep boundaries fine.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title directly describes the main change: importing and implementing a hexagonal architecture enforcement checker for BeatCue. Fully aligned with the substantial changeset.
Description check ✅ Passed Description comprehensively explains the PR scope: checker implementation, re-export handling, CLI integration, Makefile wiring, documentation, testing, and validation steps. Directly related to the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch import-hex-architecture-enforcement

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Comment @coderabbitai help to get the list of available commands and usage tips.

@leynos
leynos marked this pull request as ready for review May 13, 2026 22:38
@sourcery-ai

sourcery-ai Bot commented May 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a local, AST-based hexagonal architecture checker under beatcue/architecture, wires it into make lint, and documents the enforced import boundaries and workflow, backed by fixture-based tests and an ADR/ExecPlan.

Sequence diagram for make lint invoking the architecture checker

sequenceDiagram
    actor Developer
    participant Make as make_lint
    participant Ruff as ruff_check
    participant ArchTarget as make_check_architecture
    participant CLI as beatcue.architecture.cli.main
    participant Checker as check_architecture
    participant Reexp as build_reexport_index
    participant Policy as default_policy

    Developer->>Make: make lint
    Make->>Ruff: ruff check
    Ruff-->>Make: exit 0
    Make->>ArchTarget: make check-architecture
    ArchTarget->>CLI: python -m beatcue.architecture
    CLI->>Checker: check_architecture(package_root, package, policy)
    Checker->>Reexp: build_reexport_index(root, package)
    Reexp-->>Checker: reexport_index
    Checker->>Policy: default_policy()
    Policy-->>Checker: ArchitecturePolicy
    Checker-->>CLI: ArchitectureCheckResult
    CLI->>CLI: print(violation.render()) [for each violation]
    CLI-->>ArchTarget: exit code (0/1)
    ArchTarget-->>Make: exit code (0/1)
    Make-->>Developer: lint result
Loading

File-Level Changes

Change Details Files
Introduce an AST-based architecture checker and CLI for enforcing hexagonal import boundaries.
  • Implement core checker logic that walks imports, classifies modules into policy groups, and reports ARCH001 violations for disallowed dependencies.
  • Add reusable import-resolution helpers for computing module names and resolving relative/absolute imports.
  • Provide a CLI and main entrypoint wrapping the checker with arguments for package root, package name, and fixture policies.
  • Expose checker types and fixture_policy via the beatcue.architecture package API.
beatcue/architecture/checker.py
beatcue/architecture/_imports.py
beatcue/architecture/cli.py
beatcue/architecture/__main__.py
beatcue/architecture/__init__.py
Add policy and re-export resolution to support BeatCue-specific hexagonal rules and barrel-module expansion.
  • Define ArchitecturePolicy and ModuleGroup types plus default BeatCue policy and fixture_policy with domain/application/adapter/composition_root/infrastructure groups.
  • Implement re-export resolution that scans package init.py files, handles explicit and star re-exports, and respects all when present.
  • Add infrastructure module classification (e.g., rich, cyclopts, cv2, librosa, transformers, cuprum, cmdmox) as a dedicated group.
beatcue/architecture/policy.py
beatcue/architecture/reexports.py
Add fixture-based tests and packages that prove future hexagonal boundaries and re-export handling.
  • Create architecture enforcement tests that run the checker over fixture packages and the real beatcue tree, asserting both violations and allowed graphs.
  • Add fixtures modelling domain/application/adapter/config layouts, including cases where domain/application import adapters directly, via barrels, and via star re-exports.
  • Add fixtures for composition-root wiring and relative-import edge cases to validate helper behaviour.
tests/test_architecture_enforcement.py
tests/fixtures/architecture/application_imports_adapter/*
tests/fixtures/architecture/application_imports_domain_port/*
tests/fixtures/architecture/application_imports_reexported_adapter/*
tests/fixtures/architecture/application_imports_star_reexported_adapter/*
tests/fixtures/architecture/composition_root_wires_adapters/*
tests/fixtures/architecture/domain_imports_adapter/*
Wire the architecture checker into the build and document the new quality gate and ADR.
  • Add a check-architecture Make target that runs python -m beatcue.architecture via uv and make lint invoke this target after Ruff.
  • Document the checker usage, behaviour, and fixture strategy in the developers’ guide and add ADR 003 capturing the accepted enforcement decision.
  • Add a detailed ExecPlan describing constraints, implementation steps, risks, outcomes, and future extraction guidance.
  • Tidy a pre-existing Markdown code example to satisfy formatting/lint expectations.
Makefile
docs/developers-guide.md
docs/adr-003-hexagonal-architecture-enforcement.md
docs/execplans/import-hex-architecture-enforcement.md
docs/complexity-antipatterns-and-refactoring-strategies.md
uv.lock

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

sourcery-ai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot added the Roadmap label May 13, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 313540a81d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread beatcue/architecture/policy.py Outdated
coderabbitai[bot]

This comment was marked as resolved.

leynos added 5 commits May 14, 2026 11:13
Add a self-contained ExecPlan for importing Episodic's hexagonal
architecture checker into BeatCue.

Cover the planned implementation, validation gates, prior-art notes,
and postmortem questions before any checker code is changed.
Add a repo-local architecture checker for BeatCue's planned hexagonal
package boundaries. The checker parses imports with `ast`, expands package
barrel re-exports, reports forbidden dependency directions, and exposes a
small CLI entrypoint for local gates.

Add fixture packages and tests for domain, application, adapter, re-export,
star re-export, composition-root, and current-package cases. Keep the
ExecPlan updated with validation evidence and review findings.
Add the `check-architecture` Makefile target and run it from `make lint`
after Ruff so the local lint gate enforces BeatCue's package boundary.

Document the accepted architecture fitness function in ADR 003, add
contributor guidance for the new target, and complete the ExecPlan
postmortem with prior-art and extraction notes.
Record the completed gate run, branch push, and draft pull request status in
the ExecPlan so the living plan matches the published branch state.
Tighten architecture violation assertions so tests lock down both rendered
messages and structured violation fields. Add CLI entrypoint coverage and
valid relative-import cases for package and module imports.

Split imported symbols from imported modules in the checker so policy
classification only sees module names, and record the review follow-up in the
ExecPlan.
@lodyai
lodyai Bot force-pushed the import-hex-architecture-enforcement branch from 25a8b0d to 9c25c94 Compare May 14, 2026 09:14
coderabbitai[bot]

This comment was marked as resolved.

leynos added 2 commits May 14, 2026 11:25
Give inbound adapters their own allowed-import set so CLI code can import the
composition root without gaining permission to import outbound adapters
directly.

Add fixture coverage for the accepted CLI-to-config route and the forbidden
CLI-to-outbound-adapter route, and record the policy decision in the ExecPlan.
Resolve the package-root source path directly through `__init__.py` and make
literal `__all__` handling follow last-assignment semantics instead of stopping
on dynamic assignments.

Add regression coverage for package-root star re-exports and final resolvable
`__all__` assignments. Also narrow `check-architecture` prerequisites to avoid
redundant build work and align the ExecPlan status note with completion.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
docs/execplans/import-hex-architecture-enforcement.md (1)

910-914: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make the revision note match the final status.

Replace IN PROGRESS with COMPLETE at Line 913 so the document has one authoritative state.

Triage: [type:docstyle]

Patch
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/execplans/import-hex-architecture-enforcement.md` around lines 910 -
914, Update the revision note so the document reflects its final state by
replacing the text "Status changed to `IN PROGRESS`" with "Status changed to
`COMPLETE`" in the line containing that phrase (the line that currently reads
"Status changed to `IN PROGRESS`, branch publication progress was recorded, and
implementation may now proceed within the stated tolerances.").
beatcue/architecture/policy.py (1)

131-164: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Harden outbound adapter import permissions.

Line 163 reuses adapter_allowed, which still includes inbound_adapter. Remove that cross-adapter permission and give outbound adapters a dedicated allow-list so ARCH001 blocks outbound→inbound imports.

Patch
     inbound_adapter_allowed = frozenset({
         "application",
         "composition_root",
         "domain",
         "inbound_adapter",
     })
+    outbound_adapter_allowed = frozenset({
+        "application",
+        "domain",
+        "infrastructure",
+        "outbound_adapter",
+    })
     adapter_allowed = frozenset({
         "adapter",
         "application",
         "domain",
         "infrastructure",
         "inbound_adapter",
         "outbound_adapter",
@@
         ModuleGroup(
             name="outbound_adapter",
             module_prefixes=(f"{package}.adapters.outbound",),
-            allowed_groups=adapter_allowed,
+            allowed_groups=outbound_adapter_allowed,
         ),

Based on learnings: "Dependencies point inward: CLI and library adapters → application services → domain model and ports; outbound adapters → domain-owned ports".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@beatcue/architecture/policy.py` around lines 131 - 164, The current
adapter_allowed frozenset includes "inbound_adapter", which lets outbound
adapters import inbound ones; change this by removing "inbound_adapter" from
adapter_allowed and create a new dedicated frozenset (e.g.,
outbound_adapter_allowed =
frozenset({"adapter","application","domain","infrastructure","outbound_adapter"}))
then update the ModuleGroup for outbound_adapter to use outbound_adapter_allowed
instead of adapter_allowed; keep inbound_adapter_allowed as-is for the inbound
ModuleGroup and ensure any other uses of adapter_allowed still match the
intended inbound/adapters policy.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@beatcue/architecture/policy.py`:
- Around line 131-164: The current adapter_allowed frozenset includes
"inbound_adapter", which lets outbound adapters import inbound ones; change this
by removing "inbound_adapter" from adapter_allowed and create a new dedicated
frozenset (e.g., outbound_adapter_allowed =
frozenset({"adapter","application","domain","infrastructure","outbound_adapter"}))
then update the ModuleGroup for outbound_adapter to use outbound_adapter_allowed
instead of adapter_allowed; keep inbound_adapter_allowed as-is for the inbound
ModuleGroup and ensure any other uses of adapter_allowed still match the
intended inbound/adapters policy.

In `@docs/execplans/import-hex-architecture-enforcement.md`:
- Around line 910-914: Update the revision note so the document reflects its
final state by replacing the text "Status changed to `IN PROGRESS`" with "Status
changed to `COMPLETE`" in the line containing that phrase (the line that
currently reads "Status changed to `IN PROGRESS`, branch publication progress
was recorded, and implementation may now proceed within the stated
tolerances.").

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1700ba79-e647-4bce-8099-08f8520d0c29

📥 Commits

Reviewing files that changed from the base of the PR and between 9c25c94 and ddfd0ea.

📒 Files selected for processing (8)
  • beatcue/architecture/policy.py
  • docs/execplans/import-hex-architecture-enforcement.md
  • tests/fixtures/architecture/inbound_cli_imports_config/application.py
  • tests/fixtures/architecture/inbound_cli_imports_config/cli.py
  • tests/fixtures/architecture/inbound_cli_imports_config/config.py
  • tests/fixtures/architecture/inbound_cli_imports_outbound_adapter/adapters/outbound.py
  • tests/fixtures/architecture/inbound_cli_imports_outbound_adapter/cli.py
  • tests/test_architecture_enforcement.py

Fail fast when the architecture checker is given a missing or non-directory
package root. Tighten outbound adapter permissions so they do not inherit the
fallback adapter policy.

Document fixture noqa suppressions and add regression coverage for root
validation, adapter permission splits, and final `__all__` assignment
semantics.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/test_architecture_enforcement.py (1)

1-451: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Split this test module to satisfy the 400-line limit.

Break this file into focused test modules (for example checker, re-exports, and CLI) and keep each under the repository cap to preserve maintainability and policy compliance.

As per coding guidelines, "Files must not exceed 400 logical lines: Decompose large modules into subpackages".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_architecture_enforcement.py` around lines 1 - 451, This test
module exceeds the 400-line policy; split it into multiple focused test files
(e.g., test_architecture_checker.py, test_architecture_reexports.py,
test_architecture_cli.py) so each file is under 400 logical lines. Move tests
that exercise check_architecture and fixture_policy (including
test_checker_reports_fixture_boundary_violations,
test_checker_accepts_allowed_fixture_graphs,
test_production_checker_accepts_current_beatcue_package,
test_checker_rejects_missing_package_root,
test_checker_rejects_file_package_root,
test_fixture_policy_keeps_inbound_and_outbound_permissions_distinct) into the
checker file; move reexport-related tests
(test_reexport_index_resolves_star_imports_from_package_root,
test_reexport_index_uses_last_resolvable_all_assignment,
test_explicit_all_exports_uses_final_assignment,
test_explicit_all_exports_returns_none_when_final_assignment_is_unresolved, and
references to build_reexport_index and _explicit_all_exports) into the reexports
file; and move CLI tests (test_cli_default_invocation_accepts_current_package,
test_cli_none_argv_accepts_current_package,
test_cli_fixture_policy_reports_fixture_violations,
test_cli_fixture_policy_switches_from_default_policy) into the CLI file.
Preserve the original imports (check_architecture, fixture_policy,
relative_import_base, architecture_main, build_reexport_index,
_explicit_all_exports) and FIXTURE_ROOT variable where needed, update
module-level fixtures/parametrize decorators to their new files, and run pytest
to confirm no import paths or name collisions remain.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@tests/test_architecture_enforcement.py`:
- Around line 1-451: This test module exceeds the 400-line policy; split it into
multiple focused test files (e.g., test_architecture_checker.py,
test_architecture_reexports.py, test_architecture_cli.py) so each file is under
400 logical lines. Move tests that exercise check_architecture and
fixture_policy (including test_checker_reports_fixture_boundary_violations,
test_checker_accepts_allowed_fixture_graphs,
test_production_checker_accepts_current_beatcue_package,
test_checker_rejects_missing_package_root,
test_checker_rejects_file_package_root,
test_fixture_policy_keeps_inbound_and_outbound_permissions_distinct) into the
checker file; move reexport-related tests
(test_reexport_index_resolves_star_imports_from_package_root,
test_reexport_index_uses_last_resolvable_all_assignment,
test_explicit_all_exports_uses_final_assignment,
test_explicit_all_exports_returns_none_when_final_assignment_is_unresolved, and
references to build_reexport_index and _explicit_all_exports) into the reexports
file; and move CLI tests (test_cli_default_invocation_accepts_current_package,
test_cli_none_argv_accepts_current_package,
test_cli_fixture_policy_reports_fixture_violations,
test_cli_fixture_policy_switches_from_default_policy) into the CLI file.
Preserve the original imports (check_architecture, fixture_policy,
relative_import_base, architecture_main, build_reexport_index,
_explicit_all_exports) and FIXTURE_ROOT variable where needed, update
module-level fixtures/parametrize decorators to their new files, and run pytest
to confirm no import paths or name collisions remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ca0dea17-7bea-4e57-a561-55e3d9c966c8

📥 Commits

Reviewing files that changed from the base of the PR and between 7dc6ea8 and c4e5bd2.

📒 Files selected for processing (5)
  • beatcue/architecture/checker.py
  • beatcue/architecture/policy.py
  • beatcue/architecture/reexports.py
  • tests/fixtures/architecture/application_imports_star_reexported_adapter/adapters/__init__.py
  • tests/test_architecture_enforcement.py

leynos added 3 commits May 14, 2026 12:03
Separate the architecture enforcement tests into checker, CLI, and re-export
modules so each file stays under the 400-line policy while preserving the same
coverage.

Keep the checker tests focused on policy and import-resolution behaviour, move
CLI entrypoint tests into their own module, and isolate re-export resolver
coverage in a dedicated file.
Add exact command-line diagnostics, public `python -m` entrypoint coverage,
and invalid-root handling for the architecture checker CLI.

Add Hypothesis-based invariant tests for module-name computation,
relative-import bases, policy classification, and deterministic re-export
indexing. Mark the completed roadmap fitness-function item so the roadmap
matches the implemented gate.
Remove inbound adapters from the generic adapter permission set so shared
adapter modules cannot depend on inbound adapters. Allow outbound adapters
to import shared adapter utilities through their dedicated policy set.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/execplans/import-hex-architecture-enforcement.md`:
- Around line 601-603: Update the Stage C inbound permission list so that the
`inbound_adapter` allowed imports include `composition_root` in addition to
`domain`, `application`, and `inbound_adapter`; locate the rule block that
currently enumerates allowed imports for `inbound_adapter` (mentions `domain`,
`application`, and `inbound_adapter`) and add `composition_root` to the list to
match the later decision log and fixtures.

In `@docs/roadmap.md`:
- Around line 68-70: The roadmap shows task 1.2.2 checked while still declaring
"Requires 1.2.1" which is unchecked; update the document so dependency
sequencing is consistent by either marking task 1.2.1 as complete (check the box
for 1.2.1) if it is done, or remove/adjust the "Requires 1.2.1" line in task
1.2.2 to reflect the true prerequisite (e.g., change or remove the Requires
statement), making sure references to "1.2.2" and "1.2.1" in the roadmap remain
accurate and use dotted notation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7cc79347-0001-439e-9374-7b22e6590ffc

📥 Commits

Reviewing files that changed from the base of the PR and between 8abf192 and 85091b4.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • beatcue/architecture/cli.py
  • beatcue/architecture/policy.py
  • docs/execplans/import-hex-architecture-enforcement.md
  • docs/roadmap.md
  • pyproject.toml
  • tests/test_architecture_checker.py
  • tests/test_architecture_cli.py
  • tests/test_architecture_reexports.py

Comment thread docs/execplans/import-hex-architecture-enforcement.md Outdated
Comment thread docs/roadmap.md
Update the ExecPlan's inbound adapter rule to include composition-root
imports, matching the implemented policy and fixture coverage.

Clarify that the roadmap fitness-function task can precede the package
skeleton because it uses fixture packages for the future boundaries.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/execplans/import-hex-architecture-enforcement.md`:
- Line 1: Change the level-1 heading from Title Case to sentence case: replace
"# Import Hexagonal Architecture Enforcement" with "# Import hexagonal
architecture enforcement" so it follows the documentation style guide; ensure
the new heading text appears exactly as "Import hexagonal architecture
enforcement" in the file and keep the rest of the document unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 564f5203-f714-48ce-95fd-0439cc613bcf

📥 Commits

Reviewing files that changed from the base of the PR and between 85091b4 and e7878e5.

📒 Files selected for processing (2)
  • docs/execplans/import-hex-architecture-enforcement.md
  • docs/roadmap.md

Comment thread docs/execplans/import-hex-architecture-enforcement.md Outdated
Use sentence case for the architecture enforcement ExecPlan title to match the
documentation style guide.
@leynos
leynos merged commit 2624c08 into main May 16, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant