Files
clean-architecture-backend-…/CLAUDE.md
T
DongHyeonkaandClaude Opus 5 e34519113b fix(ci): 실행되지 않거나 실패할 수 없던 CI 게이트 정상화
가장 큰 것: 문서화된 아키텍처 게이트가 규칙을 하나도 실행하지 않았다.
워크플로 7곳과 CLAUDE.md 가 --tests '*CleanArchitectureTest' 를 지정했으나
그 이름의 클래스는 존재하지 않는다. 4곳은 매칭 0건으로 하드 실패하고,
3곳은 다른 필터와 병기돼 아키텍처 규칙 0개를 돌고 초록으로 통과했다.
필터를 패키지 글롭 dev.caskeleton.bootstrap.architecture.* 로 교체했다.
*ArchitectureTest 글롭은 20개 중 12개만 잡고 ArchRuleDiscoveryContractTest 등
8개를 놓치므로 쓰지 않았다.

그 외:
- ci-gate-matrix 의 release_blocking 이 강제되지 않아 trivy-fs 가 빨개도
  release-gate 가 초록이던 것을 실제 의존으로 연결
- build-logic TestKit 이 어떤 CI 에서도 돌지 않던 것을 ci-quality-gates 에 연결
- jpa-next-* 3개, object-storage, fileserver-pr 의 실패할 수 없거나
  트리거되지 않던 잡 정리
- 릴리스 태그 네임스페이스 분열로 v* 태그가 web·websocket 게이트를
  건너뛰던 것 수정
- 워크플로 SHA 잠금 28개 재생성 (verify-gradle-wrapper.sh)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 16:52:44 +09:00

7.3 KiB
Raw Blame History

CLAUDE.md

Repository guidance for the Java 21 + Spring Boot 4.0.8 Clean Architecture template.

Prime Directive

Preserve architecture before optimizing for speed. The following eight HARD-STOP conditions are a synchronized summary of the canonical local policy in AGENTS.md:

  1. domain-core gains framework, transport, database, or cloud dependencies.
  2. A controller directly uses a repository, Spring Data interface, or persistence entity.
  3. An inbound DTO leaks into application-core or domain-core.
  4. Business rules move into mappers, filters, configuration, settings, or controllers.
  5. Project dependencies violate src/config/architecture/modules.json or the Gradle dependency gate.
  6. Completion is claimed without the relevant verification or a named reason it could not run.
  7. A repository/corpus conclusion is made without evidence proportional to its scope and risk.
  8. Non-trivial work closes without the required LLM Wiki capture or a reported capture block.

If this summary drifts from AGENTS.md, AGENTS.md wins and this summary must be resynchronized.

Gradle policy authorities

  • src/config/architecture/modules.json: every registered leaf identity, repository-relative source paths, Gradle paths, allowed production project dependency edges, and the exact runtime memberships of both composition roots. The registry owns the leaf list and its size; no document restates the count, because a number written in prose drifts the moment a leaf is added.
  • src/settings.gradle: fail-closed registry validation, project inclusion, and directory mapping.
  • src/build.gradle: verifyCleanArchitectureDependencies and the other architecture-wide verification tasks.

Commit policy is human-only: agents do not stage, commit, amend, or push implementation changes.

Proportional workflow

  • Low risk: work in the owning leaf, follow its nearest guidance, and run the focused check.
  • Medium risk: use the relevant Superpowers design, planning, TDD, debugging, and review workflows in proportion to the affected boundaries.
  • High risk: make architecture and behavior decisions explicit, use staged architecture/spec/quality review, and run architecture-wide verification authorized by the task.

Risk comes from change surface and runtime, security, data, or public-contract impact, not file count.

Module families

src/config/architecture/modules.json owns the complete leaf list. Root guidance summarizes families; the nearest src/**/CLAUDE.md owns local rules. verifyDocumentedLeafCount fails the build when a policy document states a leaf count that the registry does not agree with.

Family Responsibility Stable dependency direction
domain-core Pure domain model, invariants, events, ports Java stdlib and registered value-only contracts
application-core Commands, use cases, application policies, transaction ports domain-core, shared-contract
adapter:inbound:* HTTP, gRPC, GraphQL, WebSocket transport boundaries application/domain/shared contracts
adapter:outbound:persistence-* JPA/PostgreSQL and MongoDB persistence adapters application/domain/shared contracts as registered
adapter:outbound:* support, messaging, cache, notification, storage, file, HTTP client, identifier capabilities application/domain/shared and registered support edge
shared-contract Skeleton-wide operational contracts Java stdlib only
messaging:* Vendored messaging platform: a product with its own API, SPI, adapters and composition boundary, not a layer of this application messaging:* only — it depends on no domain-core, application-core, or shared-contract type
sample-portfolio Fixture/reference consumer registered runtime leaves; never a production dependency
app-bootstrap Spring Boot entrypoint and composition root registered runtime leaves

The messaging:* family is the one entry that is not a Clean Architecture layer, and it is listed so that the exception is stated rather than inferred from a directory. It is a vendored library — its own *-api leaves are its ports, its broker leaves are its adapters, its starter is its composition root — and the messaging module review (docs/reviews/2026-08-14-messaging-module-code-review.md MSG-023 §6.2) chose that layout deliberately over folding it into adapter:outbound:*. This application is supposed to reach it the way it reaches any library: through an application-owned port satisfied by an anti-corruption bridge in adapter:outbound:messaging. That bridge does not exist yet (MSG-015), so today the composition root wires the starter directly; src/messaging/CLAUDE.md holds the detail.

Never infer an individual leaf's Gradle path, allowed dependency, or test command from this table. Read its gradle_path, allowed_dependencies, and runtime_memberships from src/config/architecture/modules.json; derive the focused test from that Gradle path.

Layer workflow

For a full use case, work in this order:

domain-core
  -> application-core
  -> adapter:outbound:* (or persistence/identifier)
  -> adapter:inbound:*
  -> app-bootstrap wiring

Layer-only work stays inside that registered leaf plus its tests. If a required fix crosses a layer or writable scope, stop and request context rather than expanding silently.

Testing

  • domain-core: pure JUnit unit tests.
  • application-core: use-case tests with hand-rolled fakes; no web or persistence context.
  • inbound adapters: focused transport slice/contract tests.
  • persistence adapters: mapping/port contract tests; use a real datastore only when vendor semantics require it.
  • other outbound adapters: port contract tests with fake external systems; no real network.
  • identifier: pure deterministic unit tests.
  • bootstrap/settings: binding, validation, wiring, and architecture tests.

From src/, read the owning leaf's gradle_path from config/architecture/modules.json and run ./gradlew <gradle-path>:test --console=plain. Architecture-wide commands:

./gradlew verifyCleanArchitectureDependencies --console=plain
./gradlew :app-bootstrap:test --tests 'dev.caskeleton.bootstrap.architecture.*' --console=plain
./gradlew verifyPublicPathSnapshot --console=plain
./gradlew verifyEnvKeys --console=plain

Use public-path and env-key checks only when their surfaces changed. Full test or check requires the controller's workflow authorization.

Advisory and reporting

Use dependency-DAG/topological reasoning and 35 materially distinct alternatives when that many exist; use fewer when the option set is smaller. Judgment findings include falsifiable assumptions and counterarguments. Deterministic compile, dependency, secret, or failed-test findings use Rule → Evidence → Fix without manufactured debate.

Citation verification is profile-based: none for review-lite, blocking citations for review-standard, and all material citations for audit-deep/regulated. Durable reports are triggered by high risk, at least 3 blocking findings, an architecture decision, explicit user request, or the regulated profile. Otherwise a concise result is allowed.

LLM Wiki capture

For non-trivial implementation or workflow changes, use the exact vault path and capture sequence in AGENTS.md. If the controller explicitly excludes wiki writes for a dispatched task, report the handoff instead of writing outside scope.