Skip to content

feat(hexagonal-spring-rules): add new architecture rules and examples - #41

Merged
Arc-E-Tect merged 20 commits into
mainfrom
improve-hexagonal-spring-rules
Jul 18, 2026
Merged

feat(hexagonal-spring-rules): add new architecture rules and examples#41
Arc-E-Tect merged 20 commits into
mainfrom
improve-hexagonal-spring-rules

Conversation

@Arc-E-Tect

@Arc-E-Tect Arc-E-Tect commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

Extends the hexagonal-spring-rules ArchUnit rule pack with five new rule classes, closes a coverage gap around the rule pack's own self-tests, and adds six new example projects (plus documentation) demonstrating each new feature end-to-end.

New rules

  • RulePackConfigurationTest — fails fast with an actionable message when architectureValidator.basePackage/inPorts/outPorts/domainModel are left unconfigured, instead of every rule silently passing on an empty import scope.
  • TypeLeakageTest — flags JPA entities and web DTOs leaking into port signatures or the domain model.
  • CycleFreedomTest — detects package cycles in adapter and domain-model packages.
  • DependencyInjectionStyleTest — forbids @Autowired field injection in adapters, services, and the domain model.
  • NamingConventionTest — opt-in suffix conventions for ports and adapters (architectureValidator.hexagonalArchitecture.namingConventionsEnabled).
  • Per-rule opt-out via architectureValidator.rulesDisabled, honored by every existing and new rule class.
  • RulePackConfiguration.adapters() now merges the split inboundAdapters/outboundAdapters properties with the legacy adapters aggregate, matching what the Architecture Validator plugin actually sends.

Bug fixes

  • CycleFreedomTest stripped the leading .. off configured package roots before building its ArchUnit slice pattern, anchoring it to the start of the FQN so cycles in any realistically nested base package went undetected (passed vacuously). Fixed and covered by a regression test that fails against the old code and passes against the new.
  • SpringHexagonalArchitectureTest.servicesShouldNotAccessRepositoriesDirectly was incorrectly flagging a @Service implementing its own in-port (the standard Hexagonal pattern) as a violation, because interface implementation is itself a visible ArchUnit dependency and the rule's allow-list omitted in-ports.
  • .gitignore's unanchored out/ pattern silently excluded every application/port/out/ fixture package from git (matches any directory named out, not just IntelliJ's root build output) — builds passed locally against files that were never actually committed, but failed in CI. Anchored the pattern to the repo root and renamed the affected fixture (and single-module-spring example) packages from port.in/port.out to port.inbound/port.outbound, consistent with the convention already used elsewhere, so this class of collision can't recur.

New self-test coverage

  • Added compliant/violating fixture pairs and assertions for every rule class, including the previously-uncovered CycleFreedomTest, TypeLeakageTest, DependencyInjectionStyleTest, and NamingConventionTest.

New example projects (examples/architecture-validator/)

  • hexagonal-spring-misconfigured — fail-fast validation
  • hexagonal-spring-type-leakage — JPA entity leaking through an outbound port
  • hexagonal-spring-cycle-detection — package cycle between two adapter packages
  • hexagonal-spring-rules-disabled — per-rule opt-out, proven selective (one rule skipped, another still fails)
  • hexagonal-spring-field-injection@Autowired field injection
  • hexagonal-spring-naming-conventions — opt-in naming rules

Every example README now includes the actual architectureValidator { } configuration block and a code snippet of the specific violation, not just prose description. single-module-spring's README and fixtures were also corrected to match its actual (previously undocumented) failure set.

Arc-E-Tect and others added 20 commits July 18, 2026 10:51
…uration

What changed:

- Added RulePackConfiguration.requireConfigured() to validate required Architecture Validator properties.

- Enforced the validation from basePackage() so all rule classes fail early on misconfiguration.

- Added RulePackConfigurationTest with requiredArchitecturePropertiesShouldBeConfigured().

- Updated hexagonal-spring-rules/README.adoc to document RulePackConfigurationTest in the rule table.

Why:

- Misconfigured consumers could previously import zero classes and pass architecture rules vacuously, producing false green builds.

How it works:

- Throws AssertionError with explicit remediation guidance when architectureValidator.basePackage is blank.

- Throws AssertionError when architectureValidator.inPorts, architectureValidator.outPorts, and architectureValidator.domainModel are all empty.

- Kept existing packages()/property() helper behavior unchanged; the change is additive.

Side effects and caveats:

- Consumers now fail immediately with a clear message instead of silently passing when configuration is missing/blank.

- Verification builds were run with --no-configuration-cache due to a pre-existing project issue with external process execution during configuration.

Outcomes:

- Verified hexagonal-spring-rules build succeeds.

- Verified direct helper behavior with a temporary src/test/java test (fail when missing, pass when configured), then removed the temporary test.

- Verified end-to-end in the example project with intentional misconfiguration and restored the example files afterward; baseline intentional failures remain.
What changed:

- Added new rule class TypeLeakageTest with three additive architecture rules:

  - portsShouldNotExposeJpaEntities()

  - domainModelShouldNotReferenceJpaEntities()

  - portsShouldNotExposeWebDtos()

- Implemented signature-focused leakage detection for port methods (return and parameter types) and direct dependency checks for domain model classes.

- Covered both jakarta.persistence.Entity and javax.persistence.Entity annotation names for compatibility.

- Updated hexagonal-spring-rules/README.adoc rule table to document TypeLeakageTest.

Why:

- Existing rules prevented broad framework leakage but did not specifically guard against common hexagonal boundary violations where JPA entity types or web DTO transport types leak into ports and core domain code.

- This could allow persistence or transport concerns to couple with application contracts and domain model types.

How:

- Uses ArchUnit rule style consistent with existing rule pack structure (ClassFileImporter, base package import, because clauses, allowEmptyShould(true), check(classes)).

- Applies method-signature conditions to in-port and out-port methods for explicit contract-level detection.

- Applies domain dependency condition to detect JPA entity references from domain model packages.

Side effects and caveats:

- The example project was temporarily wired to a local rule-pack jar and temporary fixtures were introduced only for smoke verification, then fully restored.

- No existing rule class source files were modified; this is additive via one new class plus README documentation.

Outcomes:

- Verified ./gradlew clean build --no-configuration-cache succeeds in hexagonal-spring-rules.

- Verified independent smoke failures for each new rule in the example project:

  - TypeLeakageTest.portsShouldNotExposeJpaEntities

  - TypeLeakageTest.domainModelShouldNotReferenceJpaEntities

  - TypeLeakageTest.portsShouldNotExposeWebDtos

- Verified positive case with no leakage: TypeLeakageTest XML reported tests=3, failures=0.

- Verified example project behavior returns to its original intentional failure pattern after restoration.
What changed:

- Added CycleFreedomTest with two ArchUnit slice-based cycle rules:

  - adapterPackagesShouldBeFreeOfCycles()

  - domainModelShouldBeFreeOfCycles()

- Implemented per-root slice pattern normalization to apply SlicesRuleDefinition.slices().matching(...).should().beFreeOfCycles() across configured package roots.

- Added graceful no-op behavior when adapters/domainModel package arrays are empty to avoid false failures in partially configured projects.

- Updated README.adoc rule table with CycleFreedomTest coverage.

Why:

- Existing layer-boundary rules do not detect intra-layer package cycles.

- Cycles inside adapter or domain package trees increase coupling and reduce maintainability, so they need explicit enforcement.

How it works:

- Imports classes from RulePackConfiguration.basePackage() with test classes excluded, consistent with existing rule-pack style.

- Builds slice patterns per configured package root using the required (**)-style matching and checks each slice graph for cycles.

- Uses allowEmptyShould(true) on cycle rules and early return when no target roots are configured.

Side effects and caveats:

- Verification used temporary example fixtures to create adapter and domain cycles, then removed them fully; no fixture code is retained.

- Example project was temporarily wired to the local rule-pack jar for end-to-end validation, then restored to its original dependency setup.

Outcomes:

- Verified hexagonal-spring-rules build succeeds (./gradlew clean build --no-configuration-cache).

- Verified adapter cycle scenario fails at CycleFreedomTest.adapterPackagesShouldBeFreeOfCycles().

- Verified domain cycle scenario fails at CycleFreedomTest.domainModelShouldBeFreeOfCycles().

- Verified no-cycle baseline and restored example both keep CycleFreedomTest green (tests=2, failures=0) and preserve original intentional example failures.
…verage

What changed:

- Enabled java-test-fixtures in hexagonal-spring-rules/build.gradle and wired test fixtures into test classpath.

- Added RulePackSelfTest under src/test/java to execute all rule methods against compliant and targeted violating fixtures.

- Added compliant fixture package tree under src/testFixtures/java/com/arc_e_tect/fixtures/compliant.

- Added violating fixture scenarios under src/testFixtures/java/com/arc_e_tect/fixtures/violating, one scenario per rule expectation across SpringHexagonalArchitectureTest, DomainIsolationTest, DependencyDirectionTest, and PortContractTest.

Why:

- The rule pack previously compiled but had no in-repo runtime proof that each rule actually fires on violations and stays silent on compliant structures.

- This change closes that regression gap by making rule behavior executable and repeatable inside the module build.

How:

- RulePackSelfTest sets architectureValidator.* system properties per scenario, instantiates rule classes, and asserts pass/fail outcomes with JUnit.

- Fixture sources are isolated in testFixtures so they are available to tests but excluded from the main published jar.

- Scenario design keeps unrelated rules green while intentionally failing only the targeted rule per case.

Side effects and caveats:

- Verification commands use --no-configuration-cache due existing build script version-resolution behavior invoking gh during configuration time.

- No example-project source files were modified.

Outcomes:

- ./gradlew clean build --no-configuration-cache succeeded in hexagonal-spring-rules.

- ./gradlew test --tests '*RulePackSelfTest*' --no-configuration-cache succeeded.

- RulePackSelfTest report shows tests=14, failures=0, errors=0, skipped=0.

- Main binary jar contains only main rule classes; fixture and self-test classes are absent.
What changed:

- Added RulePackConfiguration.isRuleDisabled(String ruleId) and parsing support for architectureValidator.rules.disabled as a comma-separated list of rule identifiers.

- Added JUnit 5 Assumptions.assumeFalse guards at the top of every @test method in SpringHexagonalArchitectureTest, DomainIsolationTest, DependencyDirectionTest, and PortContractTest.

- Used stable rule identifiers in ClassSimpleName.methodName format for all guarded methods.

- Updated README.adoc Architecture Validator Properties table with architectureValidator.rules.disabled, including identifier format and example value.

Why:

- Consumers needed a way to disable a single rule without dropping the entire rule pack dependency.

- Without targeted opt-out, teams with intentional exceptions had to accept all-or-nothing rule enforcement.

How it works:

- RulePackConfiguration reads architectureValidator.rules.disabled from system properties, trims and filters values, and exposes a boolean lookup per rule id.

- Each affected rule method now short-circuits via assumeFalse when its identifier is present, causing JUnit to mark the test as SKIPPED instead of PASSED or FAILED.

- Existing architectural assertions were left unchanged; only the precondition guard was introduced.

Side effects and caveats:

- End-to-end verification required temporary forwarding of archRulesDisabled in the example project's testArchitecture task because Gradle Test workers do not inherit CLI JVM -D properties by default.

- Temporary example wiring and local-jar substitution used for verification were fully reverted; only hexagonal-spring-rules files are committed.

Outcomes:

- hexagonal-spring-rules build succeeded with the new guards enabled.

- Baseline example run (no disabled ids) retained prior failing behavior with no skipped external rule-pack tests.

- Positive run with SpringHexagonalArchitectureTest.servicesShouldNotAccessRepositoriesDirectly produced a targeted skip and reduced failing count accordingly.

- Negative run with SomeClass.nonexistentMethod produced no skips and matched baseline behavior.
What changed:

- Added DependencyInjectionStyleTest with fieldsShouldNotBeAutowired() in the Spring rule pack.

- Implemented a noFields() ArchUnit rule that targets fields declared in classes from configured adapters, applicationServices, and domainModel packages.

- Enforced prohibition of org.springframework.beans.factory.annotation.Autowired on fields with allowEmptyShould(true) and a constructor-injection rationale.

- Updated README.adoc rule table to document DependencyInjectionStyleTest coverage.

Why:

- Field injection hides required dependencies and weakens testability and architectural clarity in Hexagonal Spring applications.

- The existing rule pack enforced layer boundaries but did not enforce dependency-wiring style.

How it works:

- The rule imports configured application classes via ClassFileImporter and evaluates fields by declaring-class package residency.

- Any field-level @Autowired in targeted layers triggers an ArchUnit assertion failure; compliant constructor-injected classes pass unchanged.

Side effects and caveats:

- Verification used temporary example-project wiring to the locally built rule-pack jar and a temporary @Autowired annotation for smoke testing; both were fully reverted.

- No persistent changes were made outside hexagonal-spring-rules for this task.

Outcomes:

- hexagonal-spring-rules build succeeded after adding DependencyInjectionStyleTest.

- Baseline example run with unmodified code showed DependencyInjectionStyleTest present and passing.

- Smoke test with temporary field @Autowired failed at DependencyInjectionStyleTest.fieldsShouldNotBeAutowired() as expected.

- Post-revert example run returned to its original intentional failure profile.
…re rules

What changed:

- Added NamingConventionTest with three opt-in ArchUnit rules:

  - inputPortsShouldHaveConsistentSuffix() accepts UseCase or Port suffixes.

  - outputPortsShouldHaveConsistentSuffix() enforces Port suffix.

  - adaptersShouldHaveConsistentSuffix() enforces Repository/Adapter for @repository and Controller for @Controller/@RestController.

- Added RulePackConfiguration.namingConventionsEnabled() reading architectureValidator.namingConventions.enabled with default false.

- Documented NamingConventionTest in README 'What This Rule Pack Checks' and added architectureValidator.namingConventions.enabled to the properties table.

Why:

- Naming conventions are a common companion to Hexagonal rules because they make architectural roles explicit during code review and IDE navigation.

- This check is intentionally opt-in because naming policies are team-specific and more opinionated than boundary and dependency rules.

How:

- Implemented the naming checks in a dedicated rule class (separate from existing rule classes) using ArchUnit class predicates with allowEmptyShould(true).

- Guarded every test method with assumeTrue so disabled-by-default behavior is explicit and reported as SKIPPED when not enabled.

- Kept existing rule logic unchanged and additive-only.

Verification:

- ./gradlew build succeeded in hexagonal-spring-rules.

- Default-off behavior showed NamingConventionTest tests as SKIPPED in architecture XML reports.

- With opt-in enabled, each naming rule was validated by introducing one temporary violation at a time and observing targeted failure messages.

- Negative case with opt-in enabled and unmodified example classes showed NamingConventionTest with 0 failures.

- Temporary example wiring/fixtures were fully reverted; only rule-pack and README changes remain.
What changed:

- Moved the Javadoc block describing coreApplicationLayerShouldHaveNoFrameworkDependencies() out of domainModelShouldOnlyDependOnJavaCoreAndDomainModel().

- Repositioned that block directly above the coreApplicationLayerShouldHaveNoFrameworkDependencies() @test method where it belongs.

- Left all executable rule logic, assumptions, annotations, and assertions unchanged.

Why:

- The comment was previously embedded inside a different method body, which was syntactically valid but semantically misleading during maintenance and review.

- Placing the Javadoc above the intended method restores accurate API documentation and prevents confusion about rule intent.

How:

- Performed a comment-only relocation in DomainIsolationTest.java without modifying method behavior.

Side effects and constraints:

- No architecture rule behavior changes were introduced.

- No additional files were changed.

Outcomes:

- ./gradlew build in hexagonal-spring-rules succeeded after the change.

- git diff for DomainIsolationTest.java shows only comment movement.

- ./gradlew testArchitecture in examples/architecture-validator/single-module-spring kept the same intentional failure profile as before.
What changed:\n- Updated .gitignore pattern from /**/req_prompts.md to /**/*prompts.md.\n\nWhy:\n- The repository now uses multiple prompt specification files (for example req_prompts.md and example_prompts.md), and only ignoring one filename left similar prompt artifacts tracked by mistake.\n\nHow:\n- Replaced the single-file ignore with a suffix-based prompts pattern that matches all prompt markdown variants in nested directories.\n\nSide effects and constraints:\n- This change affects only ignore behavior for untracked files and does not alter any source code or build behavior.\n\nOutcomes:\n- Prompt markdown helper files are now consistently excluded from version control noise.
What changed:\n- Updated CycleFreedomTest.toSlicePattern to preserve a leading .. wildcard when present in configured package roots.\n- Kept trailing normalization while returning ..<package>.(**) for wildcard-prefixed roots so ArchUnit slice matching works for nested base packages.\n- Added a regression self-test in RulePackSelfTest that asserts adapter cycle detection fails on a deep fixture package graph.\n- Added dedicated cycle fixture classes under src/testFixtures for the self-test scenario.\n- Refined RulePackConfiguration guidance text to reference inbound/outbound package names used by current defaults.\n\nWhy:\n- The previous slice pattern transformation stripped the leading wildcard, anchoring matches to the beginning of class names and allowing real nested package cycles to pass vacuously.\n\nHow:\n- Captured whether the configured root starts with .., normalized only redundant prefixes/suffixes, then rebuilt the slice pattern with the leading wildcard when required.\n- Added fixture-backed regression coverage so future refactors cannot reintroduce vacuous cycle passes.\n\nSide effects and constraints:\n- Cycle rules now evaluate real nested packages instead of empty sets, so consumers with actual cycles will correctly fail architecture checks.\n- No plugin API changes were introduced.\n\nOutcomes:\n- Adapter cycle detection behavior now matches rule intent across realistic package layouts and is protected by regression tests.
…ntions

What changed:\n- Renamed the inbound port package path from application.port.in to application.port.inbound and updated OrderUseCase package declaration/imports accordingly.\n- Updated OrderController to depend on the inbound port interface instead of a concrete OrderService type.\n- Removed @service from OrderService to keep the application service as a plain class, while preserving the intentional repository coupling violation.\n- Refreshed the single-module example README to describe the updated fixture shape and the exact expected failing rules.\n\nWhy:\n- The rule pack expects inbound/outbound package conventions that use inbound/outbound naming.\n- The external rule set also requires application services to remain framework-agnostic plain classes, so annotating the service with @service added unintended behavior.\n\nHow:\n- Applied package and import updates across the fixture classes and synchronized documentation to the observed rule outcomes.\n\nSide effects and constraints:\n- The example remains intentionally non-compliant for architecture validation demonstrations, but now fails for the intended reasons without conflicting stereotype assumptions.\n\nOutcomes:\n- The baseline single-module example now matches current rule-pack semantics and documentation expectations.
What changed:\n- Reworked SpringHexagonalArchitectureTest.servicesShouldNotAccessRepositoriesDirectly from an allow-list dependency rule to a targeted deny-list rule.\n- The rule now asserts that @service classes must not depend on adapter packages, using noClasses().should().dependOnClassesThat().resideInAnyPackage(adapters).\n- Added clarifying Javadoc that explains why the deny-list model is correct for Hexagonal services that implement in-port interfaces.\n\nWhy:\n- The previous allow-list approach incorrectly penalized valid service-to-inport relationships because ArchUnit observes the implemented interface dependency, creating false positives.\n\nHow:\n- Switched from classes().should().onlyDependOnClassesThat(...) to noClasses().should().dependOnClassesThat(...adapters).\n- Kept the existing rule id and disabled-rule wiring unchanged to preserve configuration compatibility.\n\nSide effects and constraints:\n- The rule remains focused on preventing direct service access to adapters/repositories while allowing normal in-port implementation patterns.\n\nOutcomes:\n- Services now fail only for the architectural violation the rule is intended to catch, reducing noise in example and consumer projects.
What changed:\n- Added six new Gradle example projects under examples/architecture-validator/:\n  - hexagonal-spring-misconfigured\n  - hexagonal-spring-type-leakage\n  - hexagonal-spring-cycle-detection\n  - hexagonal-spring-rules-disabled\n  - hexagonal-spring-field-injection\n  - hexagonal-spring-naming-conventions\n- Each project includes full scaffolding (wrapper, settings, build script, version catalog, source fixture, and README).\n- Wired all new examples to resolve plugin and external rule-pack artifacts from mavenLocal first.\n- Documented each fixture's observed expected violations and remediation guidance in project READMEs.\n- Updated hexagonal-spring-rules README example section to link all seven available example projects (existing single-module plus six new ones).\n\nWhy:\n- The rule-pack now includes multiple new rules and DSL options that need runnable, focused demonstrations for users and maintainers.\n\nHow:\n- Created one fixture per feature area, then iterated against architecture test output to keep each example aligned to its intended rule behavior.\n- Captured required sanity checks in docs, including opt-in and selective-disable behavior where applicable.\n\nSide effects and constraints:\n- These projects are intentionally non-compliant by design so architecture checks fail in specific, teachable ways.\n- The type-leakage fixture disables PortContractTest.portsShouldOnlyDependOnJavaCoreAndDomainModel to isolate TypeLeakageTest output in that scenario.\n\nOutcomes:\n- The repository now has a complete example suite covering fail-fast configuration, type leakage, cycle detection, per-rule opt-out, field injection, and naming conventions.
…perties

What changed:\n- Extended RulePackConfiguration.adapters() to merge values from architectureValidator.adapters, architectureValidator.inboundAdapters, and architectureValidator.outboundAdapters.\n- De-duplicated merged adapter package patterns before returning them to rule classes.\n- Updated class-level documentation to describe the split adapter properties and their relationship to the legacy aggregate property.\n\nWhy:\n- The plugin now exposes inboundAdapters and outboundAdapters explicitly. Reading only the legacy adapters property caused rule coverage gaps when consumers configured the split properties without the aggregate fallback.\n\nHow:\n- Combined the three package arrays via stream flattening and distinct filtering to build a single adapter package set consumed by architecture rules.\n\nSide effects and constraints:\n- Existing consumers using only architectureValidator.adapters continue to work unchanged.\n- Consumers using split adapter properties now receive full rule coverage without extra compatibility wiring.\n\nOutcomes:\n- Adapter-scoped rules evaluate the same package set the plugin configuration intends, improving consistency across old and new configuration styles.
…e edge cases

What changed:\n- Added regression fixture types under hexagonal-spring-rules testFixtures for a service that implements its own in-port.\n- Extended RulePackSelfTest to preserve and restore inboundAdapters/outboundAdapters system properties during tests.\n- Added regression test springHexagonalArchitectureShouldPassServicesRuleWhenServiceImplementsItsOwnInPort.\n- Added regression test dependencyDirectionShouldFailCoreRuleWhenOnlySplitAdapterPropertiesAreConfigured.\n\nWhy:\n- Recent rule behavior and configuration compatibility updates introduced subtle edge cases that can silently regress without targeted fixture coverage.\n- A valid @service implementing an in-port should not be treated as an adapter access violation.\n- Consumers using only split adapter properties (inbound/outbound) must still trigger adapter dependency checks.\n\nHow:\n- Introduced a focused regression fixture package and wired new self-tests to assert pass/fail semantics for both scenarios.\n- Kept tests aligned with real system-property keys used by the plugin and rule-pack configuration.\n\nSide effects and constraints:\n- Changes are test-only; production rule logic is unchanged in this commit.\n\nOutcomes:\n- Rule-pack regression suite now guards both semantics and configuration-path correctness for the updated architecture rules.
What changed:\n- Expanded README content for all architecture-validator Spring example projects, including single-module-spring and the six hexagonal-spring-* examples.\n- Added explicit configuration sections showing architectureValidator settings used by each fixture.\n- Added concrete violation snippets and clarified which rule IDs should fail or be skipped in each scenario.\n- Improved fix guidance with precise rename/mapping/config steps tied to observed failures.\n\nWhy:\n- The examples are intended to be teaching fixtures; terse descriptions were not enough to explain why each failure appears or how to reproduce and remediate it.\n- Several examples depend on nuanced behavior (fail-fast config checks, selective rule disabling, opt-in naming checks) that must be documented explicitly to avoid confusion.\n\nHow:\n- Rewrote README sections to include files/purpose context, configuration blocks, expected outcome semantics, and remediation actions aligned with actual architecture-test output.\n\nSide effects and constraints:\n- Documentation-only changes; no fixture source code or build logic was modified in this commit.\n\nOutcomes:\n- Architecture example docs now function as step-by-step reference material for interpreting and fixing each rule-pack violation pattern.
What changed:\n- Reworked the jacoco-marker example README to explain the marker annotation semantics and the ArchUnit convention enforced by AbstractCoverageExclusionConventionsTest.\n- Added explicit compliant vs non-compliant code examples showing justification usage.\n- Added a concrete test subclass wiring snippet and exact expected failure output format.\n\nWhy:\n- Readers needed clearer guidance on when coverage exclusion is legitimate and how the convention test enforces accountability through required justifications.\n\nHow:\n- Expanded narrative context and embedded short focused snippets for usage patterns, wiring, and expected test results.\n\nSide effects and constraints:\n- Documentation-only change in the example project.\n\nOutcomes:\n- The README now serves as a practical quickstart for adopting marker-based coverage exclusions with enforceable governance.
The unanchored `out/` .gitignore rule (meant for IntelliJ's root build
output) matched every nested `application/port/out/` package directory
in hexagonal-spring-rules' test fixtures, silently excluding them from
git even though they existed and compiled locally. CI checked out a
tree missing these files entirely, failing with "package ... does not
exist". Anchor the rule to the repo root and add the orphaned files.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…t to inbound/outbound

Consistent with the rest of the codebase (plugin defaults, examples): a
port package literally named "out" collides with the common .gitignore
convention for IDE build-output directories, which is what silently
excluded these fixtures from git in the first place. Renaming removes
the dependency on the .gitignore anchor being exactly right, matching
why inbound/outbound was already adopted everywhere else.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@Arc-E-Tect
Arc-E-Tect merged commit 8a0a226 into main Jul 18, 2026
4 checks passed
@Arc-E-Tect
Arc-E-Tect deleted the improve-hexagonal-spring-rules branch July 18, 2026 18:13
Arc-E-Tect added a commit that referenced this pull request Jul 18, 2026
# [0.5.0](v0.4.7...v0.5.0) (2026-07-18)

### ✨ New and updated features

* **hexagonal-spring-rules:** add new architecture rules and examples ([#41](#41)) ([8a0a226](8a0a226)), closes [#41](#41)

### 📝 Documentation

* **sedr-library:** update README version to 0.4.7 [skip ci] ([4b590b1](4b590b1))
@Arc-E-Tect

Copy link
Copy Markdown
Owner Author

🎉 This PR is included in version 0.5.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

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