2 lines
70 KiB
JSON
2 lines
70 KiB
JSON
{"audit_request":{"assertions":[{"assertion_id":"A01","condition":"생성 시점","line_end":43,"line_start":43,"modality":"observed","object":"생성 시 프로젝트 개정 = 1","predicate":"has_cardinality","quote":"- **생성 시 프로젝트 개정**: `1`","scope":"branch-contract-packet","source_surface":"SURF-5C2946076712CA348472","subject":"브랜치 계약 패킷"},{"assertion_id":"A02","condition":"unconditional","line_end":44,"line_start":44,"modality":"observed","object":"패킷 스키마 contract_packet: 1","predicate":"has_schema","quote":"- **패킷 스키마**: `contract_packet: 1`","scope":"branch-contract-packet","source_surface":"SURF-5C2946076712CA348472","subject":"브랜치 계약 패킷"},{"assertion_id":"A03","condition":"완료 판정 시","line_end":45,"line_start":45,"modality":"must","object":"application port와 transaction runner architecture test 통과","predicate":"requires","quote":"- **완료 조건**: application port와 transaction runner architecture test가 통과한다","scope":"branch completion","source_surface":"SURF-5C2946076712CA348472","subject":"브랜치 완료 조건"},{"assertion_id":"A04","condition":"상속한 프로젝트 결정 DEC-CA-SKELETON-OPERATIONAL-CONTRACT-TRANSACTION-001@1","line_end":52,"line_start":52,"modality":"must","object":"Spring transaction annotation 대신 TransactionPort 또는 TransactionalUseCaseRunner","predicate":"uses","quote":"| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-TRANSACTION-001@1` | application은 Spring transaction annotation 대신 TransactionPort 또는 TransactionalUseCaseRunner를 사용한다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |","scope":"application transaction management","source_surface":"SURF-5C2946076712CA348472","subject":"application"},{"assertion_id":"A05","condition":"상속한 프로젝트 결정 DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MODULE-LAYOUT-001@1","line_end":53,"line_start":53,"modality":"must","object":"domain-core·application-core·adapter-*·shared-contract·app-bootstrap·sample-portfolio 책임 분리","predicate":"other","quote":"| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MODULE-LAYOUT-001@1` | Gradle multi-module에서 domain-core·application-core·adapter-*·shared-contract·app-bootstrap·sample-portfolio 책임을 분리한다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |","scope":"module layout","source_surface":"SURF-5C2946076712CA348472","subject":"Gradle multi-module"},{"assertion_id":"A06","condition":"unconditional","line_end":58,"line_start":58,"modality":"must","object":"branch-local 결정 (이 packet에서 복제하지 않음)","predicate":"owns","quote":"> 기존 branch-local 결정은 아래 `## Decision Evidence Map / 결정-근거 매핑`의 D-row가 소유하며 이 packet에서 복제하지 않는다.","scope":"branch-local decision ownership","source_surface":"SURF-5C2946076712CA348472","subject":"Decision Evidence Map D-row"},{"assertion_id":"A07","condition":"unconditional","line_end":215,"line_start":215,"modality":"observed","object":"내 프로젝트에서의 동작을 자동으로 보장하지 않음","predicate":"other","quote":"> 공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다.","scope":"claims-to-verify caveat","source_surface":"SURF-4C01B2C1F8437310BC7F","subject":"공식 문서·사례 근거"},{"assertion_id":"A08","condition":"검증 필요","line_end":219,"line_start":219,"modality":"unknown","object":"Spring @Transactional propagation/isolation/rollback policy 표현력 동등 capture (검증 대상)","predicate":"other","quote":"| `TransactionPort` abstraction 이 Spring `@Transactional` 의 propagation / isolation / rollback policy 전 표현력을 동등하게 capture 가능한지 | UNIL-TX-C2 가 명시한 `Runnable` 시그니처는 단순 — `REQUIRES_NEW`, `NESTED`, `noRollbackFor`, `timeout` 등 전 옵션 표현 가능한지 미증명 | port interface design 에 transaction options 별 method 정의 + 통합 테스트로 outbox/audit row REQUIRES_NEW 동작 확인 | `partially-implemented` (2026-05-28 round 2) — `inWrite` / `inRead` / `inNew` 3 메서드 + `Supplier<T>` / `Runnable` 시그니처 (D11). `NESTED` / `NEVER` / `noRollbackFor` / `timeout` 는 의도적으로 미노출 (브랜치 노트 forbidden 와 일관). `TransactionPort.inNew` Javadoc 에 D12 의 pool-sizing 공식과 loop anti-pattern 명시 + `application-core/CLAUDE.md` / `adapter-persistence/CLAUDE.md` 에 cross-link. `REQUIRES_NEW` 의 실제 outbox 동작 통합 검증은 `feature-domain-event-outbox-contract` 로 위임. |","scope":"transaction abstraction expressiveness","source_surface":"SURF-4C01B2C1F8437310BC7F","subject":"TransactionPort abstraction"},{"assertion_id":"A09","condition":"application 패키지","line_end":220,"line_start":220,"modality":"unknown","object":"org.springframework.transaction.annotation.Transactional import (actually-implemented, 검증 대상)","predicate":"forbids","quote":"| application package 의 ArchUnit rule 이 `org.springframework.transaction.annotation.Transactional` import 를 실제로 catch | `AUCP-C1` 의 PREDICATE/CONDITION 모델로 import 검사 가능 (bytecode 기반) — but rule wording 필요 | ArchUnit rule `noClasses().that().resideInAPackage(\"..application..\").should().dependOnClassesThat().haveFullyQualifiedName(\"org.springframework.transaction.annotation.Transactional\")` 작성 + violating PR 통합 테스트 | `actually-implemented` (2026-05-28) — `app-bootstrap/src/test/.../CleanArchitectureTest#application_does_not_use_spring_transactional_annotation` 으로 작성. `sample-portfolio` 을 `app-bootstrap` testImplementation 으로 추가해 ArchUnit scope 에 포함. 기존 `sample-portfolio` UserService / PostService 에서 `@Transactional` 제거 시 rule 통과 확인 (`./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest'`). |","scope":"archunit transactional import","source_surface":"SURF-4C01B2C1F8437310BC7F","subject":"application ArchUnit rule"},{"assertion_id":"A10","condition":"검증 필요","line_end":223,"line_start":223,"modality":"unknown","object":"팀 내 일관성 (ArchUnit + checkstyle rule, actually-implemented, 검증 대상)","predicate":"enforces","quote":"| use case naming convention (`*UseCase` / `*Port`) 이 팀 내 일관성으로 강제 가능 | D1 이 UNSUPPORTED_DECISION — Spring 공식 권고 부재 | ArchUnit class naming rule + checkstyle rule 작성 | `actually-implemented` (2026-05-28) — `inbound_port_implementations_end_with_use_case` ArchUnit rule 작성. `*Port` outbound naming 은 별도 rule 으로 추후 추가 가능 (현재는 inbound 만). |","scope":"naming convention enforcement","source_surface":"SURF-4C01B2C1F8437310BC7F","subject":"use case naming convention (*UseCase/*Port)"},{"assertion_id":"A11","condition":"unconditional","line_end":194,"line_start":194,"modality":"must_not","object":"공식 best practice 로 승격 (company-case-study 로 표기)","predicate":"forbids","quote":"> 각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시. company-tech-blog 증거는 `company-case-study` 로 표기하며 공식 best practice 로 승격하지 않음.","scope":"evidence promotion policy","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"company-tech-blog 증거"},{"assertion_id":"A12","condition":"D1","line_end":198,"line_start":198,"modality":"must","object":"inbound port = *UseCase, outbound port = *Port","predicate":"other","quote":"| D1 | inbound port = `*UseCase`, outbound port = `*Port` naming convention | `raw/official-docs/arch-hexagonal-cockburn.md#HEX-COCKBURN-ORIG-C3` (port = plug-point for conversation with external agency), `raw/official-docs/arch-hexagonal-cockburn.md#HEX-COCKBURN-ORIG-C4` (adapter converts port API to device signals) | `engineering-blog` (Cockburn 개인 블로그 — `official-standard` 아님) | HEX-COCKBURN-ORIG-C3/C4 Does not prove: `*UseCase` (inbound) 와 `*Port` (outbound) 의 specific suffix convention — Cockburn 은 \"primary/secondary port\" 일반 개념만 명시. `*UseCase` suffix 는 buckpal / ca-tmpl 자체 차용 |","scope":"port naming","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"port naming convention (D1)"},{"assertion_id":"A13","condition":"D3","line_end":200,"line_start":200,"modality":"must","object":"transaction boundary (Spring @Transactional 직접 import 금지, TransactionPort/TransactionalUseCaseRunner 사용)","predicate":"owns","quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |","scope":"transaction boundary ownership","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"application use case (D3)"},{"assertion_id":"A14","condition":"D9 read-only query","line_end":206,"line_start":206,"modality":"may","object":"readOnly transaction + READ_REPOSITORY capability 만 선언","predicate":"requires","quote":"| D9 | read-only query use case 는 `readOnly` transaction + `READ_REPOSITORY` capability 만 선언 가능 | `raw/official-docs/spring-tx-management-reference.md#SPRING-TX-MGR-C6` (readOnly 속성이 REQUIRED/REQUIRES_NEW propagation 한정 적용), `raw/official-docs/spring-tx-management-reference.md#SPRING-TX-MGR-C3` (default propagation = REQUIRED — readOnly 적용 가능 전제) | `official-vendor-doc` | SPRING-TX-MGR-C6 Does not prove: driver level flush mode 변경의 구체 동작 — Spring Data JPA / Hibernate session statistics 측정은 별도 PoC 필요. `READ_REPOSITORY` capability 자체는 ca-tmpl 자체 contract |","scope":"read-only capability","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"read-only query use case (D9)"},{"assertion_id":"A15","condition":"D10","line_end":207,"line_start":207,"modality":"must_not","object":"org.springframework.web / JPA entity / adapter implementation import (ArchUnit fitness function)","predicate":"forbids","quote":"| D10 | application package 가 `org.springframework.web` / JPA entity / adapter implementation import 금지 (ArchUnit fitness function) | UNSUPPORTED_DECISION (ArchUnit 의 정적 검사 가능 범위는 별도 source — 본 branch cited raw 에 ArchUnit 직접 인용 없음) | n/a | [[raw/official-docs/archunit-conditional-on-property-3-layer-pattern]] (`AUCP-C1~C5`) fetch + ArchUnit fitness function source 보강 필요 |","scope":"application import restriction","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"application package (D10)"},{"assertion_id":"A16","condition":"D11","line_end":208,"line_start":208,"modality":"must","object":"Supplier<T> / Runnable (checked exception 미노출, 호출측 RuntimeException wrap)","predicate":"has_schema","quote":"| D11 | `TransactionPort` 콜백 시그니처는 `Supplier<T>` / `Runnable` (checked exception 노출 안 함). 호출 측에서 `RuntimeException` 으로 wrap | `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C2`, `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C3` (Spring `TransactionTemplate.execute(TransactionCallback) throws TransactionException` 도 동일 제약 + \"RuntimeException ... rollback ... propagated\") | `official-vendor-doc` | TX-TMPL-C2/C3 Does not prove: `Supplier<T>` 가 `TransactionCallback<T>` 와 동등하다는 명시적 진술 — Spring 공식이 별도 functional interface `TransactionCallback` 을 둔 것은 사실. ca-tmpl 의 `Supplier<T>` 채택은 boilerplate 감소를 위한 자체 결정 |","scope":"callback signature","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"TransactionPort 콜백 시그니처 (D11)"},{"assertion_id":"A17","condition":"D12","line_end":209,"line_start":209,"modality":"must_not","object":"loop 안 호출 금지 (새 physical JDBC connection 획득, pool sizing 제약)","predicate":"forbids","quote":"| D12 | `inNew` (PROPAGATION_REQUIRES_NEW) 호출은 새 physical JDBC connection 획득. Pool sizing 제약 명시 + loop 안 호출 금지 | `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C1`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C2`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C3`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C4` | `official-vendor-doc` (Spring 공식 직접 인용 — \"always uses an independent physical transaction\" + \"new database connection\" + \"exhaustion of the connection pool\" + \"Do not use ... unless your connection pool is appropriately sized\") | `max_inNew_depth` 의 실제 측정은 도메인 use case 별 통합 테스트 필요 — `feature-domain-event-outbox-contract` outbox 구현 단계에서 확정 |","scope":"requires_new connection usage","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"inNew (PROPAGATION_REQUIRES_NEW) 호출 (D12)"},{"assertion_id":"A18","condition":"D13","line_end":210,"line_start":210,"modality":"must_not","object":"spring-tx / web / JPA annotation (단 @Service/@Component 는 허용)","predicate":"forbids","quote":"| D13 | `application-core` 는 `org.springframework.stereotype.{Service,Component}` 허용 (DI 등록 목적). `spring-context` / `spring-beans` 의존은 유지하되 `spring-tx` / web / JPA annotation 은 forbidden | UNSUPPORTED_DECISION — Spring 공식이 \"application layer 에서 `@Service` 허용 / 금지\" 를 직접 진술한 source 없음. ca-tmpl 의 실용주의 자체 결정 | `project-decision` | 대안: `@Configuration` manual bean 등록 — boilerplate 폭발. 대안 채택 시 D13 retract 검토 |","scope":"application-core dependency","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"application-core (D13)"},{"assertion_id":"A19","condition":"feature-rate-limit-idempotency-contract merge 전","line_end":211,"line_start":211,"modality":"must_not","object":"feature-rate-limit-idempotency-contract merge 전까지 사용 금지 (ArchUnit rule 강제)","predicate":"forbids","quote":"| D14 | `@UseCaseCapability(idempotency = Idempotency.KEYED)` 사용은 `feature-rate-limit-idempotency-contract` merge 전까지 금지 | `project-decision` — key source / storage / TTL 미정 시 undefined behavior 회피. 후속 branch 가 정의되기 전까지 임시 freeze | `project-decision` | freeze 자체는 ArchUnit rule (`inbound_port_implementations_do_not_declare_keyed_idempotency`) 로 강제. merge 시점에 rule 제거 + KEYED 활성 |","scope":"idempotency freeze","source_surface":"SURF-8E1983742FB3C84C5E7D","subject":"@UseCaseCapability idempotency KEYED (D14)"},{"assertion_id":"A20","condition":"adapter bypass 또는 domain transaction API 직접 참조 시","line_end":394,"line_start":394,"modality":"observed","object":"adapter가 application 구현체 우회 또는 domain이 transaction API 직접 참조 시 경계 붕괴","predicate":"has_failure_behavior","quote":"- adapter가 application 구현체를 우회하거나 domain이 transaction API를 직접 참조하면 경계가 무너진다.","scope":"boundary failure","source_surface":"SURF-4A07C0D558A38806E68A","subject":"application/domain 경계"},{"assertion_id":"A21","condition":"unconditional","line_end":395,"line_start":395,"modality":"observed","object":"본 port 규칙","predicate":"consumes","quote":"- query bypass·transaction concurrency·module layout 계약이 본 port 규칙을 소비한다.","scope":"downstream consumers","source_surface":"SURF-4A07C0D558A38806E68A","subject":"query bypass·transaction concurrency·module layout 계약"},{"assertion_id":"A22","condition":"unconditional","line_end":388,"line_start":388,"modality":"must","object":"inbound port는 use case capability 추상화, outbound port는 외부 기술 의존 추상화","predicate":"other","quote":"- inbound port는 use case capability를, outbound port는 외부 기술 의존을 추상화한다.","scope":"port abstraction","source_surface":"SURF-0DEC04DBB2D865B62999","subject":"inbound port / outbound port"},{"assertion_id":"A23","condition":"transaction 시작·종료 시","line_end":389,"line_start":389,"modality":"must","object":"TransactionPort (transaction 시작·종료 요청; domain은 framework annotation 미인지)","predicate":"uses","quote":"- transaction 시작·종료는 application boundary가 `TransactionPort`를 통해 요청하고 domain은 framework annotation을 알지 않는다.","scope":"transaction control","source_surface":"SURF-0DEC04DBB2D865B62999","subject":"application boundary"},{"assertion_id":"A24","condition":"unconditional","line_end":390,"line_start":390,"modality":"must","object":"dependency direction (architecture test)","predicate":"validates","quote":"- read-only와 write use case fixture를 분리해 dependency direction을 architecture test로 검증한다.","scope":"dependency direction test","source_surface":"SURF-0DEC04DBB2D865B62999","subject":"read-only/write use case fixture 분리"},{"assertion_id":"A25","condition":"포함 범위","line_end":83,"line_start":83,"modality":"must","object":"command/query 분리 기준 (포함)","predicate":"other","quote":"- command/query 분리 기준.","scope":"included-scope","source_surface":"SURF-450E626892A2979FD6D5","subject":"본 branch 범위"},{"assertion_id":"A26","condition":"포함 범위","line_end":86,"line_start":86,"modality":"must","object":"use case transaction/capability/idempotency 선언 기준 (포함)","predicate":"other","quote":"- use case transaction/capability/idempotency 선언 기준.","scope":"included-scope","source_surface":"SURF-450E626892A2979FD6D5","subject":"본 branch 범위"},{"assertion_id":"A27","condition":"제외 범위","line_end":91,"line_start":91,"modality":"must_not","object":"특정 command bus framework (제외)","predicate":"other","quote":"- 특정 command bus framework.","scope":"excluded-scope","source_surface":"SURF-450E626892A2979FD6D5","subject":"본 branch 범위"},{"assertion_id":"A28","condition":"제외 범위","line_end":92,"line_start":92,"modality":"must_not","object":"CQRS 인프라 강제 (제외)","predicate":"forbids","quote":"- CQRS 인프라 강제.","scope":"excluded-scope","source_surface":"SURF-450E626892A2979FD6D5","subject":"본 branch 범위"},{"assertion_id":"A29","condition":"제외 범위","line_end":93,"line_start":93,"modality":"must_not","object":"domain-specific workflow engine (제외)","predicate":"other","quote":"- domain-specific workflow engine.","scope":"excluded-scope","source_surface":"SURF-450E626892A2979FD6D5","subject":"본 branch 범위"}],"candidate_manifest_sha256":"2f73fc164fbf9161a7e90b88cbe90c5ea3bbfc19ef13062c9250e3cf42617d2a","candidates":[{"assertion_a":"A04","assertion_b":"A05","candidate_id":"SEM-CBDE4F76A1CFA54CE6DA","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A08","assertion_b":"A09","candidate_id":"SEM-AA592D614F3D40327A28","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A08","assertion_b":"A13","candidate_id":"SEM-51EE5A52B439DBF62991","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A08","assertion_b":"A16","candidate_id":"SEM-507F0AA13C2095AB9A1F","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A08","assertion_b":"A17","candidate_id":"SEM-8B7E9F23F1729258919F","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A08","assertion_b":"A23","candidate_id":"SEM-F7016C9A81661F41DC39","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A09","assertion_b":"A10","candidate_id":"SEM-D608EDA1C37381DFB9FA","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A09","assertion_b":"A13","candidate_id":"SEM-257332D9A10B584B4B05","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A10","assertion_b":"A12","candidate_id":"SEM-7212CEF2ACD31B9B3BEF","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A11","assertion_b":"A13","candidate_id":"SEM-D1091C5F4DABA55917EB","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A13","assertion_b":"A16","candidate_id":"SEM-FBDF3AFCF69883E42EAB","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A13","assertion_b":"A17","candidate_id":"SEM-D57757805F08FD1B6ADE","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A13","assertion_b":"A23","candidate_id":"SEM-274AB6DE02A325AE9B3D","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A14","assertion_b":"A16","candidate_id":"SEM-8581409615A0EA06068E","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A14","assertion_b":"A17","candidate_id":"SEM-EAC6F9B7AA014A193381","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A16","assertion_b":"A17","candidate_id":"SEM-F917B8B8D86EC62532B4","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A16","assertion_b":"A23","candidate_id":"SEM-1376540EFF71536876A7","grouping_key":{"condition":"","predicate":"","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A18","assertion_b":"A19","candidate_id":"SEM-22FE36C61D9DF359A806","grouping_key":{"condition":"","predicate":"forbids","scope":"","subject":""},"rule_ids":["C6"]},{"assertion_a":"A25","assertion_b":"A26","candidate_id":"SEM-3BD4B427962D49AEFE87","grouping_key":{"condition":"포함 범위","predicate":"other","scope":"included-scope","subject":"본 branch 범위"},"rule_ids":["BASE"]},{"assertion_a":"A27","assertion_b":"A29","candidate_id":"SEM-7CC7194F4DD836A7B98F","grouping_key":{"condition":"제외 범위","predicate":"other","scope":"excluded-scope","subject":"본 branch 범위"},"rule_ids":["BASE"]}],"coverage":{"assertions":29,"candidate_pairs":20,"eligible_surfaces":6,"processed_surfaces":6},"document_sha256":"17bf090e5f3daa25ebc29c1677997bf98db56dc0bd283ac9b62174758ca0c76d","explicit_blocking":[],"mode":"local","ontology_sha256":"76d41a29233c830e1940ebb3244263e2b9bfb8dd6a01f2a1d1c51ce5a1b10468","output_schema":"semantic-audit-result/v1","schema_version":"semantic-verdict-request/v1","subject":"raw/branch-notes/feature-application-port-usecase-contract.md"},"audit_request_sha256":"810f2ebe480a46dda3f326a9e70a713fe2365081b53be7e620ab5f78d7043d41","audit_result":{"auditor":{"contract_version":"semantic-coherence/v1","model_id":"claude-opus-4-8","run_id":"a9fcefde6e3df15d6"},"mode":"local","request_sha256":"810f2ebe480a46dda3f326a9e70a713fe2365081b53be7e620ab5f78d7043d41","schema_version":"semantic-audit-result/v1","subject":"raw/branch-notes/feature-application-port-usecase-contract.md","verdicts":[{"candidate_id":"SEM-CBDE4F76A1CFA54CE6DA","evidence_a":{"line_end":52,"line_start":52,"quote":"| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-TRANSACTION-001@1` | application은 Spring transaction annotation 대신 TransactionPort 또는 TransactionalUseCaseRunner를 사용한다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |"},"evidence_b":{"line_end":53,"line_start":53,"quote":"| `DEC-CA-SKELETON-OPERATIONAL-CONTRACT-MODULE-LAYOUT-001@1` | Gradle multi-module에서 domain-core·application-core·adapter-*·shared-contract·app-bootstrap·sample-portfolio 책임을 분리한다 | Work Item 완료 조건에 적용 | [[raw/project-notes/ca-skeleton-operational-contract]] |"},"proof_manifest":null,"rationale":"A04 (inherited DEC-...-TRANSACTION-001: application uses TransactionPort instead of Spring annotation) and A05 (inherited DEC-...-MODULE-LAYOUT-001: Gradle multi-module responsibility split) are two distinct inherited project decisions covering different contract properties (transaction management vs module layout). Both apply to the same Work Item completion but neither takes over the other's responsibility.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-AA592D614F3D40327A28","evidence_a":{"line_end":219,"line_start":219,"quote":"| `TransactionPort` abstraction 이 Spring `@Transactional` 의 propagation / isolation / rollback policy 전 표현력을 동등하게 capture 가능한지 | UNIL-TX-C2 가 명시한 `Runnable` 시그니처는 단순 — `REQUIRES_NEW`, `NESTED`, `noRollbackFor`, `timeout` 등 전 옵션 표현 가능한지 미증명 | port interface design 에 transaction options 별 method 정의 + 통합 테스트로 outbox/audit row REQUIRES_NEW 동작 확인 | `partially-implemented` (2026-05-28 round 2) — `inWrite` / `inRead` / `inNew` 3 메서드 + `Supplier<T>` / `Runnable` 시그니처 (D11). `NESTED` / `NEVER` / `noRollbackFor` / `timeout` 는 의도적으로 미노출 (브랜치 노트 forbidden 와 일관). `TransactionPort.inNew` Javadoc 에 D12 의 pool-sizing 공식과 loop anti-pattern 명시 + `application-core/CLAUDE.md` / `adapter-persistence/CLAUDE.md` 에 cross-link. `REQUIRES_NEW` 의 실제 outbox 동작 통합 검증은 `feature-domain-event-outbox-contract` 로 위임. |"},"evidence_b":{"line_end":220,"line_start":220,"quote":"| application package 의 ArchUnit rule 이 `org.springframework.transaction.annotation.Transactional` import 를 실제로 catch | `AUCP-C1` 의 PREDICATE/CONDITION 모델로 import 검사 가능 (bytecode 기반) — but rule wording 필요 | ArchUnit rule `noClasses().that().resideInAPackage(\"..application..\").should().dependOnClassesThat().haveFullyQualifiedName(\"org.springframework.transaction.annotation.Transactional\")` 작성 + violating PR 통합 테스트 | `actually-implemented` (2026-05-28) — `app-bootstrap/src/test/.../CleanArchitectureTest#application_does_not_use_spring_transactional_annotation` 으로 작성. `sample-portfolio` 을 `app-bootstrap` testImplementation 으로 추가해 ArchUnit scope 에 포함. 기존 `sample-portfolio` UserService / PostService 에서 `@Transactional` 제거 시 rule 통과 확인 (`./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest'`). |"},"proof_manifest":null,"rationale":"A08 is a claim-to-verify about TransactionPort's expressiveness (can it capture propagation/isolation/rollback); A09 is a separate claim-to-verify that the application ArchUnit rule actually catches the org.springframework...Transactional import. Different concerns (abstraction coverage vs static enforcement), mutually compatible.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-51EE5A52B439DBF62991","evidence_a":{"line_end":219,"line_start":219,"quote":"| `TransactionPort` abstraction 이 Spring `@Transactional` 의 propagation / isolation / rollback policy 전 표현력을 동등하게 capture 가능한지 | UNIL-TX-C2 가 명시한 `Runnable` 시그니처는 단순 — `REQUIRES_NEW`, `NESTED`, `noRollbackFor`, `timeout` 등 전 옵션 표현 가능한지 미증명 | port interface design 에 transaction options 별 method 정의 + 통합 테스트로 outbox/audit row REQUIRES_NEW 동작 확인 | `partially-implemented` (2026-05-28 round 2) — `inWrite` / `inRead` / `inNew` 3 메서드 + `Supplier<T>` / `Runnable` 시그니처 (D11). `NESTED` / `NEVER` / `noRollbackFor` / `timeout` 는 의도적으로 미노출 (브랜치 노트 forbidden 와 일관). `TransactionPort.inNew` Javadoc 에 D12 의 pool-sizing 공식과 loop anti-pattern 명시 + `application-core/CLAUDE.md` / `adapter-persistence/CLAUDE.md` 에 cross-link. `REQUIRES_NEW` 의 실제 outbox 동작 통합 검증은 `feature-domain-event-outbox-contract` 로 위임. |"},"evidence_b":{"line_end":200,"line_start":200,"quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |"},"proof_manifest":null,"rationale":"A13 (D3) declares application use case as owner of the transaction boundary using TransactionPort; A08 verifies whether that TransactionPort abstraction fully captures Spring @Transactional expressiveness. A08's caveat ('미증명', partial exposure) is a verification concern, not an opposing value on the ownership property — it supplies a compatible verification detail.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-507F0AA13C2095AB9A1F","evidence_a":{"line_end":219,"line_start":219,"quote":"| `TransactionPort` abstraction 이 Spring `@Transactional` 의 propagation / isolation / rollback policy 전 표현력을 동등하게 capture 가능한지 | UNIL-TX-C2 가 명시한 `Runnable` 시그니처는 단순 — `REQUIRES_NEW`, `NESTED`, `noRollbackFor`, `timeout` 등 전 옵션 표현 가능한지 미증명 | port interface design 에 transaction options 별 method 정의 + 통합 테스트로 outbox/audit row REQUIRES_NEW 동작 확인 | `partially-implemented` (2026-05-28 round 2) — `inWrite` / `inRead` / `inNew` 3 메서드 + `Supplier<T>` / `Runnable` 시그니처 (D11). `NESTED` / `NEVER` / `noRollbackFor` / `timeout` 는 의도적으로 미노출 (브랜치 노트 forbidden 와 일관). `TransactionPort.inNew` Javadoc 에 D12 의 pool-sizing 공식과 loop anti-pattern 명시 + `application-core/CLAUDE.md` / `adapter-persistence/CLAUDE.md` 에 cross-link. `REQUIRES_NEW` 의 실제 outbox 동작 통합 검증은 `feature-domain-event-outbox-contract` 로 위임. |"},"evidence_b":{"line_end":208,"line_start":208,"quote":"| D11 | `TransactionPort` 콜백 시그니처는 `Supplier<T>` / `Runnable` (checked exception 노출 안 함). 호출 측에서 `RuntimeException` 으로 wrap | `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C2`, `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C3` (Spring `TransactionTemplate.execute(TransactionCallback) throws TransactionException` 도 동일 제약 + \"RuntimeException ... rollback ... propagated\") | `official-vendor-doc` | TX-TMPL-C2/C3 Does not prove: `Supplier<T>` 가 `TransactionCallback<T>` 와 동등하다는 명시적 진술 — Spring 공식이 별도 functional interface `TransactionCallback` 을 둔 것은 사실. ca-tmpl 의 `Supplier<T>` 채택은 boilerplate 감소를 위한 자체 결정 |"},"proof_manifest":null,"rationale":"A16 (D11) fixes the TransactionPort callback signature as Supplier<T>/Runnable; A08 flags a verification concern that this simple signature leaves NESTED/noRollbackFor/timeout etc. intentionally unexposed. The two agree on the signature and one adds the expressiveness-limit caveat — compatible detail, no conflict.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-8B7E9F23F1729258919F","evidence_a":{"line_end":219,"line_start":219,"quote":"| `TransactionPort` abstraction 이 Spring `@Transactional` 의 propagation / isolation / rollback policy 전 표현력을 동등하게 capture 가능한지 | UNIL-TX-C2 가 명시한 `Runnable` 시그니처는 단순 — `REQUIRES_NEW`, `NESTED`, `noRollbackFor`, `timeout` 등 전 옵션 표현 가능한지 미증명 | port interface design 에 transaction options 별 method 정의 + 통합 테스트로 outbox/audit row REQUIRES_NEW 동작 확인 | `partially-implemented` (2026-05-28 round 2) — `inWrite` / `inRead` / `inNew` 3 메서드 + `Supplier<T>` / `Runnable` 시그니처 (D11). `NESTED` / `NEVER` / `noRollbackFor` / `timeout` 는 의도적으로 미노출 (브랜치 노트 forbidden 와 일관). `TransactionPort.inNew` Javadoc 에 D12 의 pool-sizing 공식과 loop anti-pattern 명시 + `application-core/CLAUDE.md` / `adapter-persistence/CLAUDE.md` 에 cross-link. `REQUIRES_NEW` 의 실제 outbox 동작 통합 검증은 `feature-domain-event-outbox-contract` 로 위임. |"},"evidence_b":{"line_end":209,"line_start":209,"quote":"| D12 | `inNew` (PROPAGATION_REQUIRES_NEW) 호출은 새 physical JDBC connection 획득. Pool sizing 제약 명시 + loop 안 호출 금지 | `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C1`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C2`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C3`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C4` | `official-vendor-doc` (Spring 공식 직접 인용 — \"always uses an independent physical transaction\" + \"new database connection\" + \"exhaustion of the connection pool\" + \"Do not use ... unless your connection pool is appropriately sized\") | `max_inNew_depth` 의 실제 측정은 도메인 use case 별 통합 테스트 필요 — `feature-domain-event-outbox-contract` outbox 구현 단계에서 확정 |"},"proof_manifest":null,"rationale":"A08 references verifying REQUIRES_NEW/inNew outbox behavior; A17 (D12) supplies the concrete constraint on inNew (new physical JDBC connection, pool sizing, no loop calls). One supplies a compatible constraint the other flags for verification; no mutually exclusive value.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F7016C9A81661F41DC39","evidence_a":{"line_end":219,"line_start":219,"quote":"| `TransactionPort` abstraction 이 Spring `@Transactional` 의 propagation / isolation / rollback policy 전 표현력을 동등하게 capture 가능한지 | UNIL-TX-C2 가 명시한 `Runnable` 시그니처는 단순 — `REQUIRES_NEW`, `NESTED`, `noRollbackFor`, `timeout` 등 전 옵션 표현 가능한지 미증명 | port interface design 에 transaction options 별 method 정의 + 통합 테스트로 outbox/audit row REQUIRES_NEW 동작 확인 | `partially-implemented` (2026-05-28 round 2) — `inWrite` / `inRead` / `inNew` 3 메서드 + `Supplier<T>` / `Runnable` 시그니처 (D11). `NESTED` / `NEVER` / `noRollbackFor` / `timeout` 는 의도적으로 미노출 (브랜치 노트 forbidden 와 일관). `TransactionPort.inNew` Javadoc 에 D12 의 pool-sizing 공식과 loop anti-pattern 명시 + `application-core/CLAUDE.md` / `adapter-persistence/CLAUDE.md` 에 cross-link. `REQUIRES_NEW` 의 실제 outbox 동작 통합 검증은 `feature-domain-event-outbox-contract` 로 위임. |"},"evidence_b":{"line_end":389,"line_start":389,"quote":"- transaction 시작·종료는 application boundary가 `TransactionPort`를 통해 요청하고 domain은 framework annotation을 알지 않는다."},"proof_manifest":null,"rationale":"A23 describes the mechanism (application boundary requests transaction start/end via TransactionPort, domain unaware of framework annotation); A08 is the verification concern about that abstraction's expressiveness. Compatible — mechanism plus its open verification detail.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D608EDA1C37381DFB9FA","evidence_a":{"line_end":220,"line_start":220,"quote":"| application package 의 ArchUnit rule 이 `org.springframework.transaction.annotation.Transactional` import 를 실제로 catch | `AUCP-C1` 의 PREDICATE/CONDITION 모델로 import 검사 가능 (bytecode 기반) — but rule wording 필요 | ArchUnit rule `noClasses().that().resideInAPackage(\"..application..\").should().dependOnClassesThat().haveFullyQualifiedName(\"org.springframework.transaction.annotation.Transactional\")` 작성 + violating PR 통합 테스트 | `actually-implemented` (2026-05-28) — `app-bootstrap/src/test/.../CleanArchitectureTest#application_does_not_use_spring_transactional_annotation` 으로 작성. `sample-portfolio` 을 `app-bootstrap` testImplementation 으로 추가해 ArchUnit scope 에 포함. 기존 `sample-portfolio` UserService / PostService 에서 `@Transactional` 제거 시 rule 통과 확인 (`./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest'`). |"},"evidence_b":{"line_end":223,"line_start":223,"quote":"| use case naming convention (`*UseCase` / `*Port`) 이 팀 내 일관성으로 강제 가능 | D1 이 UNSUPPORTED_DECISION — Spring 공식 권고 부재 | ArchUnit class naming rule + checkstyle rule 작성 | `actually-implemented` (2026-05-28) — `inbound_port_implementations_end_with_use_case` ArchUnit rule 작성. `*Port` outbound naming 은 별도 rule 으로 추후 추가 가능 (현재는 inbound 만). |"},"proof_manifest":null,"rationale":"A09 (ArchUnit rule forbidding the Transactional import) and A10 (ArchUnit + checkstyle naming-convention rule) are two distinct fitness functions enforcing different contract properties (import restriction vs *UseCase/*Port naming). Both actually-implemented, no overlap.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-257332D9A10B584B4B05","evidence_a":{"line_end":220,"line_start":220,"quote":"| application package 의 ArchUnit rule 이 `org.springframework.transaction.annotation.Transactional` import 를 실제로 catch | `AUCP-C1` 의 PREDICATE/CONDITION 모델로 import 검사 가능 (bytecode 기반) — but rule wording 필요 | ArchUnit rule `noClasses().that().resideInAPackage(\"..application..\").should().dependOnClassesThat().haveFullyQualifiedName(\"org.springframework.transaction.annotation.Transactional\")` 작성 + violating PR 통합 테스트 | `actually-implemented` (2026-05-28) — `app-bootstrap/src/test/.../CleanArchitectureTest#application_does_not_use_spring_transactional_annotation` 으로 작성. `sample-portfolio` 을 `app-bootstrap` testImplementation 으로 추가해 ArchUnit scope 에 포함. 기존 `sample-portfolio` UserService / PostService 에서 `@Transactional` 제거 시 rule 통과 확인 (`./gradlew :app-bootstrap:test --tests '*CleanArchitectureTest'`). |"},"evidence_b":{"line_end":200,"line_start":200,"quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |"},"proof_manifest":null,"rationale":"A13 (D3) owns the forbidden policy (application must not import Spring @Transactional, uses TransactionPort); A09 supplies the concrete ArchUnit enforcement of exactly that policy. Same direction and meaning, one adds the enforcement mechanism — not a drifting restatement.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7212CEF2ACD31B9B3BEF","evidence_a":{"line_end":223,"line_start":223,"quote":"| use case naming convention (`*UseCase` / `*Port`) 이 팀 내 일관성으로 강제 가능 | D1 이 UNSUPPORTED_DECISION — Spring 공식 권고 부재 | ArchUnit class naming rule + checkstyle rule 작성 | `actually-implemented` (2026-05-28) — `inbound_port_implementations_end_with_use_case` ArchUnit rule 작성. `*Port` outbound naming 은 별도 rule 으로 추후 추가 가능 (현재는 inbound 만). |"},"evidence_b":{"line_end":198,"line_start":198,"quote":"| D1 | inbound port = `*UseCase`, outbound port = `*Port` naming convention | `raw/official-docs/arch-hexagonal-cockburn.md#HEX-COCKBURN-ORIG-C3` (port = plug-point for conversation with external agency), `raw/official-docs/arch-hexagonal-cockburn.md#HEX-COCKBURN-ORIG-C4` (adapter converts port API to device signals) | `engineering-blog` (Cockburn 개인 블로그 — `official-standard` 아님) | HEX-COCKBURN-ORIG-C3/C4 Does not prove: `*UseCase` (inbound) 와 `*Port` (outbound) 의 specific suffix convention — Cockburn 은 \"primary/secondary port\" 일반 개념만 명시. `*UseCase` suffix 는 buckpal / ca-tmpl 자체 차용 |"},"proof_manifest":null,"rationale":"A12 (D1) declares the inbound=*UseCase / outbound=*Port naming convention; A10 supplies the enforcement (inbound_port_implementations_end_with_use_case ArchUnit rule, *Port rule deferred). Consistent convention plus its enforcement detail.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D1091C5F4DABA55917EB","evidence_a":{"line_end":194,"line_start":194,"quote":"> 각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시. company-tech-blog 증거는 `company-case-study` 로 표기하며 공식 best practice 로 승격하지 않음."},"evidence_b":{"line_end":200,"line_start":200,"quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |"},"proof_manifest":null,"rationale":"A11 states the evidence-promotion policy (company-tech-blog evidence tagged company-case-study, not promoted to official best practice); A13 (D3) applies that policy in its evidence column (company-case-study + engineering-blog + UNSUPPORTED_DECISION for the CONTRARY forbidden shape). A13 follows A11; compatible application, no conflict.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-FBDF3AFCF69883E42EAB","evidence_a":{"line_end":200,"line_start":200,"quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |"},"evidence_b":{"line_end":208,"line_start":208,"quote":"| D11 | `TransactionPort` 콜백 시그니처는 `Supplier<T>` / `Runnable` (checked exception 노출 안 함). 호출 측에서 `RuntimeException` 으로 wrap | `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C2`, `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C3` (Spring `TransactionTemplate.execute(TransactionCallback) throws TransactionException` 도 동일 제약 + \"RuntimeException ... rollback ... propagated\") | `official-vendor-doc` | TX-TMPL-C2/C3 Does not prove: `Supplier<T>` 가 `TransactionCallback<T>` 와 동등하다는 명시적 진술 — Spring 공식이 별도 functional interface `TransactionCallback` 을 둔 것은 사실. ca-tmpl 의 `Supplier<T>` 채택은 boilerplate 감소를 위한 자체 결정 |"},"proof_manifest":null,"rationale":"A13 (D3) mandates use of TransactionPort as the transaction-boundary abstraction; A16 (D11) supplies its callback signature (Supplier<T>/Runnable, no checked exceptions). Signature detail under the mandated abstraction — compatible, no takeover.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-D57757805F08FD1B6ADE","evidence_a":{"line_end":200,"line_start":200,"quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |"},"evidence_b":{"line_end":209,"line_start":209,"quote":"| D12 | `inNew` (PROPAGATION_REQUIRES_NEW) 호출은 새 physical JDBC connection 획득. Pool sizing 제약 명시 + loop 안 호출 금지 | `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C1`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C2`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C3`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C4` | `official-vendor-doc` (Spring 공식 직접 인용 — \"always uses an independent physical transaction\" + \"new database connection\" + \"exhaustion of the connection pool\" + \"Do not use ... unless your connection pool is appropriately sized\") | `max_inNew_depth` 의 실제 측정은 도메인 use case 별 통합 테스트 필요 — `feature-domain-event-outbox-contract` outbox 구현 단계에서 확정 |"},"proof_manifest":null,"rationale":"A13 (D3) mandates TransactionPort/TransactionalUseCaseRunner for the transaction boundary; A17 (D12) supplies the concrete usage constraint on its inNew method (new physical connection, pool sizing, no loop calls). Compatible constraint detail.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-274AB6DE02A325AE9B3D","evidence_a":{"line_end":200,"line_start":200,"quote":"| D3 | application use case 가 transaction boundary 의 owner — but Spring `@Transactional` 직접 import 금지, `TransactionPort` / `TransactionalUseCaseRunner` abstraction 사용 | `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C1`, `raw/company-tech-blogs/transaction-port-clean-ddd-spring-medium.md#UNIL-TX-C2`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C1`, `raw/company-tech-blogs/transaction-port-vassilis-soum-github-readme.md#VSOUM-TX-C2` / **OSS PRECEDENT (closure-based pattern)**: `raw/company-tech-blogs/axonframework-transactionmanager-spring-adapter.md#AXON-TX-C1`, `#AXON-TX-C2` (Axon `TransactionManager.executeInTransaction(Runnable)` + `fetchInTransaction(Supplier<T>)` 시그니처는 ca-tmpl `inWrite(Supplier)` 와 1:1 매칭, 3.6k stars enterprise OSS), `#AXON-TX-C3` (`SpringTransactionManager(PlatformTransactionManager)` adapter 구조 ca-tmpl `SpringTransactionPort` 와 동일) / **CONTRARY EVIDENCE (다수파 = `@Transactional` 직접 부착)**: `raw/company-tech-blogs/buckpal-archunit-lombok-allowlist-direct-transactional.md#BUCKPAL-TX-C1`, `#BUCKPAL-TX-C2` (Buckpal hex-arch 공식 reference 가 `@Component @Transactional` 직접 application service 부착, abstraction 없음) / **CONTRARY (Spring Modulith)**: `raw/company-tech-blogs/spring-modulith-archunit-generated-exemption-and-violations-as-data.md#SPRING-MOD-TX-C1` (`@ApplicationModuleListener` 가 meta-annotation 으로 `@Transactional` 재노출 — Spring 공식 incubator 가 forbidden 방향과 정반대) | `company-case-study + engineering-blog` (TransactionPort pattern 자체) + `company-case-study` (Axon enterprise OSS precedent) + **UNSUPPORTED_DECISION (CONTRARY for specific shape)** | (1) **closure-based abstraction 패턴 자체는 강화됨** — Axon (3.6k stars) + Spanner SDK 가 동일 closure 시그니처 사용. (2) **그러나 `TransactionPort` literal 명칭 + `inWrite`/`inRead`/`inNew` 3중 메소드 구조는 OSS 1:1 매칭 없음** — Axon 은 `TransactionManager` + 2 메소드. ca-tmpl 의 specific shape 은 자체 결정. (3) **forbidden 정책은 OSS 다수파 (Buckpal) 와 Spring 공식 incubator (Modulith) 양쪽과 충돌** — multi-Gradle-module Hexagonal context 에서 application 모듈 순수성을 위한 자체 stricter taste. UNSUPPORTED_DECISION(CONTRARY) for forbidden enforcement |"},"evidence_b":{"line_end":389,"line_start":389,"quote":"- transaction 시작·종료는 application boundary가 `TransactionPort`를 통해 요청하고 domain은 framework annotation을 알지 않는다."},"proof_manifest":null,"rationale":"A13 (D3) owns the claim that application use case controls the transaction boundary via TransactionPort forbidding direct @Transactional; A23 restates the same direction (application boundary requests start/end via TransactionPort) and adds the compatible detail that domain stays unaware of framework annotations. Meaning is preserved, so not RESTATEMENT_DRIFT — it supplies a compatible detail.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-8581409615A0EA06068E","evidence_a":{"line_end":206,"line_start":206,"quote":"| D9 | read-only query use case 는 `readOnly` transaction + `READ_REPOSITORY` capability 만 선언 가능 | `raw/official-docs/spring-tx-management-reference.md#SPRING-TX-MGR-C6` (readOnly 속성이 REQUIRED/REQUIRES_NEW propagation 한정 적용), `raw/official-docs/spring-tx-management-reference.md#SPRING-TX-MGR-C3` (default propagation = REQUIRED — readOnly 적용 가능 전제) | `official-vendor-doc` | SPRING-TX-MGR-C6 Does not prove: driver level flush mode 변경의 구체 동작 — Spring Data JPA / Hibernate session statistics 측정은 별도 PoC 필요. `READ_REPOSITORY` capability 자체는 ca-tmpl 자체 contract |"},"evidence_b":{"line_end":208,"line_start":208,"quote":"| D11 | `TransactionPort` 콜백 시그니처는 `Supplier<T>` / `Runnable` (checked exception 노출 안 함). 호출 측에서 `RuntimeException` 으로 wrap | `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C2`, `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C3` (Spring `TransactionTemplate.execute(TransactionCallback) throws TransactionException` 도 동일 제약 + \"RuntimeException ... rollback ... propagated\") | `official-vendor-doc` | TX-TMPL-C2/C3 Does not prove: `Supplier<T>` 가 `TransactionCallback<T>` 와 동등하다는 명시적 진술 — Spring 공식이 별도 functional interface `TransactionCallback` 을 둔 것은 사실. ca-tmpl 의 `Supplier<T>` 채택은 boilerplate 감소를 위한 자체 결정 |"},"proof_manifest":null,"rationale":"A14 (D9) fixes read-only query use cases to readOnly transaction + READ_REPOSITORY capability; A16 (D11) fixes the TransactionPort callback signature. Different aspects (capability declaration vs callback shape), mutually compatible.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-EAC6F9B7AA014A193381","evidence_a":{"line_end":206,"line_start":206,"quote":"| D9 | read-only query use case 는 `readOnly` transaction + `READ_REPOSITORY` capability 만 선언 가능 | `raw/official-docs/spring-tx-management-reference.md#SPRING-TX-MGR-C6` (readOnly 속성이 REQUIRED/REQUIRES_NEW propagation 한정 적용), `raw/official-docs/spring-tx-management-reference.md#SPRING-TX-MGR-C3` (default propagation = REQUIRED — readOnly 적용 가능 전제) | `official-vendor-doc` | SPRING-TX-MGR-C6 Does not prove: driver level flush mode 변경의 구체 동작 — Spring Data JPA / Hibernate session statistics 측정은 별도 PoC 필요. `READ_REPOSITORY` capability 자체는 ca-tmpl 자체 contract |"},"evidence_b":{"line_end":209,"line_start":209,"quote":"| D12 | `inNew` (PROPAGATION_REQUIRES_NEW) 호출은 새 physical JDBC connection 획득. Pool sizing 제약 명시 + loop 안 호출 금지 | `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C1`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C2`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C3`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C4` | `official-vendor-doc` (Spring 공식 직접 인용 — \"always uses an independent physical transaction\" + \"new database connection\" + \"exhaustion of the connection pool\" + \"Do not use ... unless your connection pool is appropriately sized\") | `max_inNew_depth` 의 실제 측정은 도메인 use case 별 통합 테스트 필요 — `feature-domain-event-outbox-contract` outbox 구현 단계에서 확정 |"},"proof_manifest":null,"rationale":"A14 (D9) governs read-only (readOnly + READ_REPOSITORY) use cases; A17 (D12) governs inNew (REQUIRES_NEW) usage. Distinct transaction modes, no mutual exclusion — complementary constraints on different use-case types.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-F917B8B8D86EC62532B4","evidence_a":{"line_end":208,"line_start":208,"quote":"| D11 | `TransactionPort` 콜백 시그니처는 `Supplier<T>` / `Runnable` (checked exception 노출 안 함). 호출 측에서 `RuntimeException` 으로 wrap | `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C2`, `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C3` (Spring `TransactionTemplate.execute(TransactionCallback) throws TransactionException` 도 동일 제약 + \"RuntimeException ... rollback ... propagated\") | `official-vendor-doc` | TX-TMPL-C2/C3 Does not prove: `Supplier<T>` 가 `TransactionCallback<T>` 와 동등하다는 명시적 진술 — Spring 공식이 별도 functional interface `TransactionCallback` 을 둔 것은 사실. ca-tmpl 의 `Supplier<T>` 채택은 boilerplate 감소를 위한 자체 결정 |"},"evidence_b":{"line_end":209,"line_start":209,"quote":"| D12 | `inNew` (PROPAGATION_REQUIRES_NEW) 호출은 새 physical JDBC connection 획득. Pool sizing 제약 명시 + loop 안 호출 금지 | `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C1`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C2`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C3`, `raw/official-docs/spring-tx-propagation-required-new-nested-official.md#SPRING-PROP-C4` | `official-vendor-doc` (Spring 공식 직접 인용 — \"always uses an independent physical transaction\" + \"new database connection\" + \"exhaustion of the connection pool\" + \"Do not use ... unless your connection pool is appropriately sized\") | `max_inNew_depth` 의 실제 측정은 도메인 use case 별 통합 테스트 필요 — `feature-domain-event-outbox-contract` outbox 구현 단계에서 확정 |"},"proof_manifest":null,"rationale":"A16 (D11) defines the TransactionPort callback signature; A17 (D12) defines the inNew connection/pool constraint. Two different facets of the same TransactionPort contract, compatible with each other.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-1376540EFF71536876A7","evidence_a":{"line_end":208,"line_start":208,"quote":"| D11 | `TransactionPort` 콜백 시그니처는 `Supplier<T>` / `Runnable` (checked exception 노출 안 함). 호출 측에서 `RuntimeException` 으로 wrap | `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C2`, `raw/official-docs/transaction-template-spring-official.md#TX-TMPL-C3` (Spring `TransactionTemplate.execute(TransactionCallback) throws TransactionException` 도 동일 제약 + \"RuntimeException ... rollback ... propagated\") | `official-vendor-doc` | TX-TMPL-C2/C3 Does not prove: `Supplier<T>` 가 `TransactionCallback<T>` 와 동등하다는 명시적 진술 — Spring 공식이 별도 functional interface `TransactionCallback` 을 둔 것은 사실. ca-tmpl 의 `Supplier<T>` 채택은 boilerplate 감소를 위한 자체 결정 |"},"evidence_b":{"line_end":389,"line_start":389,"quote":"- transaction 시작·종료는 application boundary가 `TransactionPort`를 통해 요청하고 domain은 framework annotation을 알지 않는다."},"proof_manifest":null,"rationale":"A16 (D11) supplies the callback signature detail; A23 supplies the usage mechanism (application boundary requests transaction via TransactionPort, domain annotation-agnostic). Detail plus mechanism for the same abstraction, no conflicting value.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-22FE36C61D9DF359A806","evidence_a":{"line_end":210,"line_start":210,"quote":"| D13 | `application-core` 는 `org.springframework.stereotype.{Service,Component}` 허용 (DI 등록 목적). `spring-context` / `spring-beans` 의존은 유지하되 `spring-tx` / web / JPA annotation 은 forbidden | UNSUPPORTED_DECISION — Spring 공식이 \"application layer 에서 `@Service` 허용 / 금지\" 를 직접 진술한 source 없음. ca-tmpl 의 실용주의 자체 결정 | `project-decision` | 대안: `@Configuration` manual bean 등록 — boilerplate 폭발. 대안 채택 시 D13 retract 검토 |"},"evidence_b":{"line_end":211,"line_start":211,"quote":"| D14 | `@UseCaseCapability(idempotency = Idempotency.KEYED)` 사용은 `feature-rate-limit-idempotency-contract` merge 전까지 금지 | `project-decision` — key source / storage / TTL 미정 시 undefined behavior 회피. 후속 branch 가 정의되기 전까지 임시 freeze | `project-decision` | freeze 자체는 ArchUnit rule (`inbound_port_implementations_do_not_declare_keyed_idempotency`) 로 강제. merge 시점에 rule 제거 + KEYED 활성 |"},"proof_manifest":null,"rationale":"A18 (D13) forbids spring-tx/web/JPA annotations in application-core (while allowing @Service/@Component); A19 (D14) forbids @UseCaseCapability KEYED idempotency until feature-rate-limit-idempotency-contract merges. Both are forbids-predicate rules but on entirely different objects — no mutually exclusive value on a shared property.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-3BD4B427962D49AEFE87","evidence_a":{"line_end":83,"line_start":83,"quote":"- command/query 분리 기준."},"evidence_b":{"line_end":86,"line_start":86,"quote":"- use case transaction/capability/idempotency 선언 기준."},"proof_manifest":null,"rationale":"A25 (command/query separation criteria) and A26 (use case transaction/capability/idempotency declaration criteria) are two distinct in-scope items enumerated for the same branch. Each adds a compatible member to the included-scope set; neither overrides the other.","verdict":"COMPLEMENTARY"},{"candidate_id":"SEM-7CC7194F4DD836A7B98F","evidence_a":{"line_end":91,"line_start":91,"quote":"- 특정 command bus framework."},"evidence_b":{"line_end":93,"line_start":93,"quote":"- domain-specific workflow engine."},"proof_manifest":null,"rationale":"A27 (specific command bus framework) and A29 (domain-specific workflow engine) are two distinct excluded-scope items. Each adds a compatible member to the exclusion set; they do not conflict.","verdict":"COMPLEMENTARY"}]},"auditor":{"contract_version":"semantic-coherence/v1","model_id":"claude-opus-4-8","run_id":"a9fcefde6e3df15d6"},"auditor_contract_sha256":"1cbc67c27e5183a272687f635e3682a26d56785a1cf144da562eb7edd8f6cbce","coverage":{"candidate_pairs":20,"dropped_pairs":0,"eligible_surfaces":6,"processed_pairs":20,"processed_surfaces":6},"document_id":"09116c13c5b25234dfa58c700fe589e56dd281baaa22e8e300cd4d6dd6f69dfb","document_sha256":"17bf090e5f3daa25ebc29c1677997bf98db56dc0bd283ac9b62174758ca0c76d","findings":{"blocking":0,"readiness_blocking":0,"verified":0},"mode":"local","ontology_sha256":"5d601b96f0ca4d75eea89e9086c38e3acf2c4f0c7833846ef58c6a5719603126","policy_sha256":"0465598e9c1c4f2c3400ba51bf4719aa4890d60d56dc83304fb2224e660562b7","proof_manifest_sha256":"37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570","schema_version":"semantic-certificate/v1","semantic_audit_sha256":"b7dfb0022714307e16f9403187c2290e8a61a9d59cf5b28be42da7f9a9c2c1f2","subject":"raw/branch-notes/feature-application-port-usecase-contract.md","typed_contract_graph_sha256":"481fc3335a494c454ab13ad1d6a6ddccdec99aa8e083f6720ff8886bfa19cc89","verdict":"PASS"}
|