Skip to content

feat(validator): check that feature packages belong to their feature - #29

Open
Statyk7 wants to merge 3 commits into
mainfrom
feat/feature-ownership-checks
Open

Statyk7 wants to merge 3 commits into
mainfrom
feat/feature-ownership-checks

Conversation

@Statyk7

@Statyk7 Statyk7 commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Description

Closes #24.

Adds feature ownership checks to the layer validator. Until now it only checked that a package's name matches its feature folder. All new checks are errors, so the hook blocks on them:

Rule Example message
A data package depends on its own domain iota_data does not depend on iota_domain
Only dependencies counts, not dev_dependencies or overrides mu_data declares mu_domain only outside dependencies
A data package never exists without a domain in its feature kappa_data is a data layer but features/kappa/ has no kappa_domain
A domain package never depends on the Flutter SDK lambda_domain depends on the Flutter SDK through flutter

Sources: Dependency rules in project_structure.md, the feature archetypes in overview.md, and "This layer is pure Dart" in domain.md.

Implementation. The pubspec reader now records the section each dependency comes from and any sdk: value. The Flutter check catches any runtime dependency with sdk: flutter, including flutter_localizations. Packages that use Flutter without declaring the SDK themselves (for example flutter_bloc) need dependency resolution and are left to #28.

Fixtures. Four new invalid features (iota, kappa, lambda, mu) each plant one rule, with an --all and an incremental test for each. beta_data and theta_data now depend on their own domain so each still plants a single violation, and a new test asserts that. alpha_data now also reports the missing own-domain dependency: adding it would create a cycle with the planted domain → data violation, as its pubspec comment explains.

Docs. The Hooks section of README.md lists what the validator checks. The ffca-layer-auditor agent and the ffca-audit skill include feature ownership in the deterministic pass. The hook's behavior is unchanged, so CLAUDE.md is untouched.

Not included. The warning for a presentation package that does not depend on its own existing domain waits for severity levels in #21.

Review fixes. An independent review before team review found two issues here, both fixed:

  • A dependency cycle was attributed to whichever package the walk reached first, which differed between --all and incremental runs. It is now reported on the cycle's alphabetically first package, and discovery is sorted so reports never depend on file system order.
  • The pubspec reader assumed 2-space indentation and silently dropped 4-space dependency entries. It now reads the indentation from the section's first entry; gamma_presentation's fixture uses 4 spaces.

Verified locally: dart analyze, dart format, dart test (37 tests, 13 new), and hooks/validate_layers_test.sh (15 cases) pass.

Type of Change

  • New feature (feat)
  • Bug fix (fix)
  • Code refactor (refactor)
  • Documentation (docs)
  • CI change (ci)
  • Chore (chore)

🤖 Generated with Claude Code

https://claude.ai/code/session_017Vxxv9fVFGupLXEnmx5bSq

Add feature ownership checks to the layer validator, all errors:

- A data package depends on its own feature's domain under
  `dependencies`; a dev dependency or override does not count.
- A data package never exists in a feature without a domain package.
- A domain package never depends on the Flutter SDK.

The pubspec reader now records each dependency's section and `sdk:`
value. New invalid fixtures (iota, kappa, lambda, mu) plant one rule
each; beta_data and theta_data now depend on their own domain so they
still plant a single violation.

Closes #24

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Vxxv9fVFGupLXEnmx5bSq
@Statyk7
Statyk7 requested a review from a team as a code owner October 14, 2026 17:39
@Statyk7 Statyk7 mentioned this pull request Oct 15, 2026
1 of 6 tasks
…ubspecs

A dependency cycle was reported on whichever package the walk reached
first, which differed between --all and incremental runs, so a
suppression for it worked in one mode and not the other. It is now
reported on the cycle's alphabetically first package, and discovery is
sorted so reports do not depend on file system order.

The pubspec reader assumed dependency entries indented by two spaces and
silently dropped 4-space ones. It now takes the indentation from the
section's first entry.

Found in review of #29.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Vxxv9fVFGupLXEnmx5bSq
Statyk7 added a commit that referenced this pull request Oct 15, 2026
…rity

Brings the review fixes from #29: deterministic cycle attribution and
4-space pubspec indentation. The cycle and indentation tests now assert
the rule IDs this branch adds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Vxxv9fVFGupLXEnmx5bSq
Statyk7 added a commit that referenced this pull request Oct 15, 2026
From a review of #29, #30 and #31:

- Check imports of undeclared workspace packages against the rules
  table. A Dart workspace resolves them, so `product_presentation` could
  import `cart_data` without either mode noticing. A forbidden layer
  reports that layer rule; an allowed one reports the new
  undeclared-dependency error.
- On a pubspec edit, run import checks and suppression validation for
  the edited package only, so a clean edit never blocks on a
  dependent's existing Dart findings.
- Skip missing-primary-barrel in incremental mode while a package has no
  lib/, so a new package can be scaffolded pubspec first.
- Read directives with a scanner that stops at the first declaration,
  follows multi-line directives, and reads every URI, so imports inside
  strings are ignored and both sides of a conditional import are checked.
- Check every barrel at the root of a data package's lib/, following
  relative exports one level, for exported DTOs and mappers.
- Report a `//` suppression naming a pubspec-only rule, and group
  suppression findings under the file the comment is in.
- Fix CLAUDE.md, which said dart only runs for pubspec edits, and cite
  the barrel rule's actual sources.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Vxxv9fVFGupLXEnmx5bSq

@erickzanardo erickzanardo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

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.

feat: check that feature packages belong to their feature

2 participants