{ "assetKey": "a19-f014-kafka-msg", "kind": "terminal", "command": "set -e\nset -o pipefail\nB=src/app-bootstrap/src/main/java/dev/caskeleton/bootstrap\nA=src/messaging/messaging-spring-boot-starter/src/main/java/dev/caskeleton/messaging/autoconfigure\nstrip() { sed -E 's#^src/[^:]*/src/(main|test)/java/dev/caskeleton/([^:]*)/([^:/]+):([0-9]+):# \\1 · \\2/\\3:\\4 #'; }\ncut_range() { awk -v f=\"$2\" -v a=\"$3\" -v b=\"$4\" 'NR>=a && NR<=b {printf \" %s:%d %s\\n\", f, NR, $0}' \"$1\"; }\n\necho \"# 가족 문서가 이 항목을 어떻게 들고 있는가\"\ngrep -n 'MSG-015' src/messaging/CLAUDE.md | cut -c1-150 | sed 's#^# messaging/CLAUDE.md:#'\n\necho\necho \"# 두 스택의 설정 클래스와 생산자 빈\"\ncut_range $B/messaging/KafkaSenderConfig.java bootstrap/messaging/KafkaSenderConfig.java 37 39\ncut_range $B/messaging/KafkaSenderConfig.java bootstrap/messaging/KafkaSenderConfig.java 61 63\nawk 'NR>=126 && NR<=131 {printf \" autoconfigure/KafkaMessagingAutoConfiguration.java:%d %s\\n\", NR, $0}' $A/KafkaMessagingAutoConfiguration.java\n\necho\necho \"# 플랫폼 쪽이 켜지는 사슬\"\ngit grep -n 'prefix = MessagingSettings.PREFIX, name = \"enabled\"' -- 'src/**/*.java' | strip\ngit grep -n '\"kafka\", KafkaMessagingAutoConfiguration.class' -- 'src/**/*.java' | strip\n\necho\necho \"# broker 만 준 시험이 통과하는 이유 — 게이트 뒤 설정을 손으로 등록한다\"\ngit grep -n 'withUserConfiguration(KafkaAdapterConfig' -- 'src/**/*.java' | strip\nO=src/app-bootstrap/src/test/java/dev/caskeleton/adapter/outbound/OptionalAdapterBeanGatingTest.java\nawk 'NR>=59 && NR<=70 {printf \" test · OptionalAdapterBeanGatingTest.java:%d %s\\n\", NR, $0}' $O\necho \" 두 시험이 컴포지션 루트를 쓰는가 :\"\nfor f in src/adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/MessagingConfigTest.java $O; do\n n=$(grep -c 'CaSkeletonApplication' \"$f\" || true)\n printf \" %-40s CaSkeletonApplication 언급 %s 건\\n\" \"$(basename $f)\" \"${n:-0}\"\ndone\necho \" KafkaSenderConfig 가 그 슬라이스에 등록되는가 :\"\nfor f in src/adapter/outbound/messaging/src/test/java/dev/caskeleton/adapter/outbound/messaging/MessagingConfigTest.java $O; do\n n=$(grep -c 'KafkaSenderConfig' \"$f\" || true)\n printf \" %-40s KafkaSenderConfig 언급 %s 건\\n\" \"$(basename $f)\" \"${n:-0}\"\ndone\n\necho\necho \"# 이 조합을 거르는 검증기가 있는가\"\nV=$(find src -name CapabilityDependencyValidator.java -path '*/main/*')\nawk 'NR>=64 && NR<=80 {printf \" CapabilityDependencyValidator.java:%d %s\\n\", NR, $0}' $V\n\necho\necho \"# 운영 문서가 이 키를 무엇이라고 설명하는가\"\nawk 'NR>=26 && NR<=32 {printf \" docs/runbooks/outbox-publish-failed.md:%d %s\\n\", NR, $0}' docs/runbooks/outbox-publish-failed.md\n\necho\necho \"# 출하 설정이 두 키를 어떻게 주는가\"\ngrep -n 'APP_MESSAGING_ENABLED\\|APP_MESSAGING_BROKER' src/config/runtime/compose-profile-contracts.json | head -8 | sed 's#^# compose-profile-contracts.json:#'\nfor f in src/.env src/.env.example src/.env.local.example; do\n [ -f \"$f\" ] && grep -n 'APP_MESSAGING_BROKER\\|APP_MESSAGING_ENABLED' \"$f\" | sed \"s#^# $(basename $f):#\"\ndone\n\necho\necho \"# KafkaSenderConfig 가 조건에서 물러나는가\"\nawk 'NR>=60 && NR<=65 {printf \" KafkaSenderConfig.java:%d %s\\n\", NR, $0}' $B/messaging/KafkaSenderConfig.java\n\necho\necho \"# 이음매 설정 클래스 자신은 스캔 대상인가\"\nhead -1 $B/messaging/KafkaSenderConfig.java | sed 's#^# KafkaSenderConfig.java:1 #'\nn=$(grep -c 'bootstrap\\\\.messaging' $B/CaSkeletonApplication.java || true)\necho \" AUTO_CONFIGURED_PACKAGES 가 bootstrap.messaging 을 제외하는가 : ${n:-0} 건\"\n\necho\necho \"# 이음매 쪽 생산자가 요구하는 설정 빈은 어디서 오는가\"\ngit grep -n 'EnableConfigurationProperties(KafkaAdapterSettings.class)' -- 'src/**/*.java' | strip\ngit grep -n 'Import({MessagingConfig.class, KafkaAdapterConfig.class})\\|prefix = \"app.messaging\", name = \"enabled\"' -- 'src/**/*.java' | strip\n\necho\necho \"# 그 설정 클래스가 컴포넌트 스캔으로 들어올 수 있는가\"\nawk 'NR>=41 && NR<=57 {printf \" CaSkeletonApplication.java:%d %s\\n\", NR, $0}' $B/CaSkeletonApplication.java\nawk 'NR>=100 && NR<=101 {printf \" CaSkeletonApplication.java:%d %s\\n\", NR, $0}' $B/CaSkeletonApplication.java\ngrep -n 'adapter\\\\\\\\.outbound\\\\\\\\.messaging' $B/CaSkeletonApplication.java | sed -E 's#^([0-9]+): *# CaSkeletonApplication.java:\\1 #'\necho \" ConfigurationPropertiesScan 목록에 adapter.outbound.messaging 이 있는가 :\"\nn=$(awk 'NR>=58 && NR<=82' $B/CaSkeletonApplication.java | grep -c 'adapter.outbound.messaging' || true)\necho \" $n 건\"\n\necho\necho \"# broker=kafka 를 쓰는 시험마다 같은 파일이 enabled 를 주는가\"\nfor f in $(git grep -l 'app.messaging.broker=kafka' -- 'src/**/*.java' | grep '/test/'); do\n b=$(grep -c 'app.messaging.broker=kafka' \"$f\" || true)\n e=$(grep -c 'app.messaging.enabled=' \"$f\" || true)\n printf \" %-46s broker=kafka %s 줄 · enabled= %s 줄\\n\" \"$(basename $f)\" \"$b\" \"$e\"\ndone\necho \" enabled 를 한 줄도 주지 않는 파일의 시험 이름 :\"\nfor f in $(git grep -l 'app.messaging.broker=kafka' -- 'src/**/*.java' | grep '/test/'); do\n e=$(grep -c 'app.messaging.enabled=' \"$f\" || true)\n if [ \"$e\" = \"0\" ]; then grep -n 'void .*(' \"$f\" | sed -E \"s#^([0-9]+): *# $(basename $f):\\1 #\"; fi\ndone\n", "cwd": "/shared/codebase/clean-architecture-backend-template", "exitCode": 0, "executedAt": "2026-09-04T01:37:31+00:00", "sourceRevision": "21234e38cdb9a926cbc92bb97a2aee2e4a7d2916", "raw": "evidence/raw/a19-f014-kafka-msg.txt", "svg": "evidence/rendered/a19-f014-kafka-msg.svg", "rawSha256": "fdb9acc28d9e2de8a714af9359e84d2bf8690abcf165381dafe4d25b658688c8", "lines": 140, "redaction": "비밀값 없음" }