# 가족 지침이 이 계약의 주인으로 지목한 것 src/messaging/CLAUDE.md:36 - 반대로 **노출하지 않는 것은 `implementation`으로 낮춘다.** starter가 노출하지 않는 하위 모듈을 src/messaging/CLAUDE.md:37 `implementation`으로 내린 것이, JSON codec이 `ObjectMapper`를 private으로만 쓰고 Jackson을 src/messaging/CLAUDE.md:38 `implementation`으로 둔 것이 그 예다. src/messaging/CLAUDE.md:39 - 이 규칙은 문서가 아니라 `MessagingPublicSurfaceContractTest`가 붙들고 있다. leaf의 production src/messaging/CLAUDE.md:40 source에서 public/protected 시그니처에 등장하는 vendor 라이브러리를 뽑아 그 leaf의 src/messaging/CLAUDE.md:41 `build.gradle`이 `api`로 선언했는지 대조하고, starter의 `api` closure에 broker client 두 개가 src/messaging/CLAUDE.md:42 들어오지 않는 것도 함께 본다. Spring Framework/Boot는 대상이 아니다 — 조립 경계 안에서만 src/messaging/CLAUDE.md:43 등장하고 adopter가 이름 부를 일이 없다. src/messaging/CLAUDE.md:44 - 새 public 타입은 그 모듈의 계약이다. 삭제·시그니처 변경은 breaking change로 취급한다. # 그 시험 클래스가 놓인 트리 src/app-bootstrap/src/test/java/dev/caskeleton/bootstrap/contract/messaging/MessagingPublicSurfaceContractTest.java src/messaging 아래 동명 파일 : 0 개 가족 test 트리 : 24 개 · 이 파일의 트리 : src/app-bootstrap/src/test 이 파일의 @Test 3 · @Tag 0 · @Disabled 0 :73 void vendorTypesInPublicSignaturesAreDeclaredApi() { :94 void theScanIsNotVacuous() { :114 void neitherBrokerSdkReachesAnAdoptersCompileClasspath() { # 가족 경로에서 도는 워크플로의 트리거 전부와 실행 명령 messaging-certification.yml:15 on: messaging-certification.yml:16 pull_request: messaging-certification.yml:17 paths: messaging-certification.yml:18 - "src/messaging/**" messaging-certification.yml:19 - ".github/workflows/messaging-certification.yml" messaging-certification.yml:20 schedule: messaging-certification.yml:21 - cron: "41 4 * * 3" messaging-certification.yml:22 workflow_dispatch: messaging-certification.yml:52 run: ./gradlew :messaging:messaging-kafka:verifyMessagingCertificationEvidence --no-daemon --stacktrace # 경로 필터가 없는 워크플로 ci-quality-gates.yml:1 name: ci-quality-gates ci-quality-gates.yml:2 ci-quality-gates.yml:3 on: ci-quality-gates.yml:4 pull_request: ci-quality-gates.yml:5 push: ci-quality-gates.yml:6 branches: ["main"] ci-quality-gates.yml:7 workflow_dispatch: ci-quality-gates.yml:8 ci-quality-gates.yml:9 permissions: on 블록(1-9)의 paths 필터 : 0 건 ci-quality-gates.yml:19 jobs: ci-quality-gates.yml:20 quality-gates: ci-quality-gates.yml:21 runs-on: ubuntu-latest ci-quality-gates.yml:22 steps: ci-quality-gates.yml:48 - name: Check quality, public paths, and dependency locks ci-quality-gates.yml:49 working-directory: src ci-quality-gates.yml:50 run: ./gradlew check verifyPublicPathSnapshot verifyDependencyLocks --warning-mode=fail --no-daemon --stacktrace ci-quality-gates.yml:51 # Named as its own step because nothing else runs it: `check` does not depend on ci-quality-gates.yml:52 # graphqlStableTest, so the lane's required-class guard — the check that its module-boundary ci-quality-gates.yml:53 # suite has not silently stopped being discovered — protected nothing in CI. A separate step ci-quality-gates.yml:54 # keeps the aggregate invocation below byte-identical, which ConditionalTransportQualification ci-quality-gates.yml:55 # ContractTest asserts on, and the two tasks do not overlap. # check 가 정말 이 프로젝트의 test 를 포함하는가 $ ./gradlew :app-bootstrap:check --dry-run :app-bootstrap:test SKIPPED :app-bootstrap:functionalTest SKIPPED :app-bootstrap:check SKIPPED 루트 test 규약이 거는 유일한 필터 : src/build.gradle:549 tasks.named('test') { src/build.gradle:550 useJUnitPlatform { src/build.gradle:551 excludeTags 'quarantine' src/build.gradle:552 } src/build.gradle:553 } # 이름으로 골라 실제로 돌리면 $ ./gradlew :app-bootstrap:test --tests '...MessagingPublicSurfaceContractTest' BUILD SUCCESSFUL 결과 디렉터리 test/ · MessagingPublicSurfaceContractTest tests=3 failures=0 skipped=0 # 가족 태스크로 같은 이름을 고르면 $ ./gradlew :messaging:messaging-kafka:test --tests '...MessagingPublicSurfaceContractTest' > No tests found for given includes: [dev.caskeleton.bootstrap.contract.messaging.MessagingPublicSurfaceContractTest](--tests filter) BUILD FAILED