- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다 - 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5 (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를 techviz 로 만들었다 - 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs 돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다. Concept 이 인용한 코드가 SSOT 에 없어 뺐다 - candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
13 KiB
kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, body, assets, evidence, source
| kind | slug | title | topic | project | status | sourceRevision | rootTreeNode | evidenceCapturedOn | body | assets | evidence | source | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CASE | a10-f001-readme | 표가 증거로 지목한 시험이 그 표를 반증한다 | caching-and-redis | clean-architecture-backend-template | 게시 전 | 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 | case:a10-f001-readme | 2026-09-02 | case-a10-f001-readme.body.md |
|
|
|
표가 증거로 지목한 시험이 그 표를 반증한다
리프 README 의 준비도 표와 그 아래 두 문단이 이 리프의 상태를 없음으로 적는다. 표가 둘째 열의 증거로 이름을 대 놓은 시험이 그 빈들이 조립된다고 단언하고, 같은 README 의 산문이 세 줄 뒤에서 같은 기능을 제공한다고 적는다.
관계
- 문서 계약 테스트의 단언 경계 밖에 발견된 드리프트 세 건이 전부 있었다 그 테스트가 단언하는 범위 밖에서 문서와 코드가 어긋났다.
- README의 세 가지 사실 오류 같은 README 에서 확인한 다른 사실 오류다.
- 산문이 선언한 게이트는 빌드에 있는 게이트가 아니다 문서와 빌드를 대조하는 규칙이다.
문제
이 리프의 README 는 준비도 보고를 자기 주제로 삼는다. 세 질문을 합치지 말라고 못 박고, 축마다 증거를 지정한 다음 표를 놓는다.
결론
둘째 축의 증거로 이름을 댄 시험이 RedisSdkAutoConfigurationTest 다. 그 시험이 RedisRuntimeClient 와 RedisRuntimeOwner 를 hasSingleBean 으로 단언한다. 표가 그 둘을 조립되지 않는다고 적은 자리다.
같은 README 도 자기와 어긋난다. 표에서 세 줄 뒤 산문이 이 모듈은 Lettuce 연결 수명과 명령 타임아웃과 재연결 재생 차단을 제공한다고 적는다. 표 둘째 행이 없음이라고 적은 바로 그것이다.
수를 세면 이렇다.
sdk/lettuce/connection 에 아홉 파일 1,473 줄이 있다. RedisTopologyClientFactory 600, RedisRuntimeOwner 316, SentinelFailoverObserver 153, RedisConnectionRegistry 142 줄이다.
의미 포트 행은 다섯 이름을 한 칸에 묶는다. 그중 넷은 아홉 파일 2,598 줄로 있고 세션 하나만 표가 맞다. 세션 쪽은 패키지 자체가 없고, 남은 여덟 건은 코드가 아니라 문장과 선택자 값이다.
상태 기여자 행도 틀렸다. RedisHealthContributor 88 줄과 RedisCorrectnessRoles 62 줄이 있다.
자동 설정에는 @Bean 메서드가 일곱 있다. 여섯은 조건 없이 조립되고, 일곱째 redisRequired 에는 @Conditional 이 붙어 세션·멱등·레이트리밋·리스 중 하나가 Redis 를 고를 때만 생긴다. 조립되는 자리를 못 찾은 것은 게이트웨이와 의미 어댑터다.
빌드 파일 주석은 절반만 틀렸다. 주석의 주어는 SDK 이고, sdk 패키지의 어떤 파일도 그 간선들을 임포트하지 않는다. 괄호 안의 일반화가 틀렸다. 메인 소스 전체로 넓히면 애플리케이션 코어를 일곱 파일이, 공유 계약을 세 파일이 임포트한다. 등록된 간선 셋 중 adapter:outbound:support 만 실제로 0 이다.
같은 주석은 그 어댑터들이 제거됐다고도 적는다. 위에서 센 파일들이 그것이다. 그리고 간선을 남겨 두는 이유로 든 문장 — 여기서 무언가가 그것에 대해 컴파일되기 때문이 아니라는 것 — 도 뒤집힌다.
스무 줄 뒤에 있는 별개 주석 쪽은 맞다. spring-data-redis 와 io.micrometer 임포트는 실제로 0 이다.
판정은 P2 다. 코드 결함이 아니라 문서 결함인데 이 저장소 기준으로는 무겁다.
첫째, 이 문서는 정직한 준비도 보고를 자기 주제로 삼고, 축마다 증거를 지정하기까지 한다. 그 증거가 문서를 반증한다.
둘째, 방향이 이례적이다. 보통의 표류는 없는 것을 있다고 하는데 여기는 있는 것을 없다고 한다. 포크한 쪽은 있는 것을 다시 만들거나, 있는 줄도 모른 채 지나친다.
셋째 근거는 자동 설정 안의 문장이다. 이 클래스가 생기기 전까지 설정 검증 메서드에 프로덕션 호출자가 없었다고 적는다.
검증 환경
확인 방식 : 패키지별 파일과 줄 수 계수, @Bean 메서드와 조건 계수, 임포트 계수 소스 수정 : x
재현 조건
- README 가 세 축마다 지정한 증거를 읽는다.
- 둘째 축의 증거로 지목된 시험이 무엇을 단언하는지 읽는다.
- 준비도 표 네 행과 그 아래 두 문단을 읽고, 세 줄 뒤 산문까지 이어 읽는다.
- 표가 없다고 적은 자리마다 패키지의 파일과 줄 수를 센다.
- 의미 포트 행이 든 다섯 이름과 실제 패키지 이름을 대조하고, 행에 없는 패키지는 합계에서 뺀다.
- 세션을 리프 메인 전체에서 문자열로 검색한다.
- 자동 설정의 @Bean 메서드를 조건 애너테이션까지 함께 읽는다.
- 빌드 파일이 등록한 간선 셋을 각각 임포트하는 파일을 세고, 주석의 주어인 sdk 패키지만으로도 센다.
- 스무 줄 뒤의 별개 주석과 그 주장을 확인한다.
본문
README 는 준비도가 서로 다른 세 질문이며 하나로 합치면 안 된다는 문장으로 시작하고, 축마다 무엇을 증거로 삼는지까지 적는다.
표가 지목한 증거
:::evidence key="a10-f001-readme" alt="README 가 준비도 세 축마다 지정한 증거, 준비도 표 네 행, 표 아래 두 문단. 표에서 세 줄 뒤 같은 README 의 산문이 이 모듈이 제공한다고 적는 목록. 그리고 둘째 축의 증거로 지목된 시험이 어떤 빈들을 단언하는지 출력한 터미널 기록." caption="표는 연결 수명과 의미 포트와 상태 기여자를 없음으로 적음 · 세 줄 뒤 산문은 같은 모듈이 Lettuce 연결 수명을 제공한다고 적음 · 표가 증거로 지목한 시험은 RedisRuntimeClient 와 RedisRuntimeOwner 를 hasSingleBean 으로 단언 — 46줄 · exit 0" zoom="true" :::
| **Spring composition 구현** | `APP_REDIS_ENABLED=true`에서 실제 bean이 조립된다 | `RedisSdkAutoConfigurationTest` |
그 시험이 무엇을 단언하는지 보면 이렇다.
assertThat(context).hasSingleBean(RedisSdkSettings.class);
...
assertThat(context).hasSingleBean(RedisRuntimeClient.class);
...
assertThat(context).hasSingleBean(RedisRuntimeOwner.class);
표는 같은 둘을 조립되지 않는다고 적는다.
| Topology client / connection lifecycle | 없음 | 없음 | 없음 |
| cache / session / idempotency / rate limit / lease semantic port | 없음 | 없음 | 없음 |
| role-aware health·readiness contributor | 없음 | 없음 | 없음 |
같은 README 가 세 줄 뒤에서
모듈은 Lettuce connection lifecycle,
finite command timeout, reconnect replay 차단, finite request queue/admission, positive/negative
TTL, absolute soft/hard expiry, deterministic bounded TTL jitter, digest-protected v2 binary
envelope, HMAC physical key,
invalidation, closed-catalog
`EVALSHA -> NOSCRIPT -> SCRIPT LOAD -> digest verify -> EVALSHA` recovery를 제공한다.
표 둘째 행이 없음이라고 적은 것을 산문이 제공한다고 적는다. 어긋난 것은 문서 전체가 아니라 표와 그 아래 두 문단이다.
수를 세면
:::evidence key="a10-f001-readme-counts" alt="표가 없다고 적은 자리의 파일 수와 줄 수. 의미 포트 행이 든 다섯 이름 중 구현이 있는 넷의 합계와, 그 행에 이름이 없어 합계에서 뺀 두 패키지. 세션 문자열의 리프 전체 계수. 상태 기여자의 줄 수. 자동 설정의 @Bean 메서드 전부와 거기 붙은 조건 애너테이션. 빌드 파일이 등록한 간선 셋과 앞 주석, 그 간선들을 임포트하는 파일 수와 주석의 주어인 sdk 패키지만의 계수, 그리고 스무 줄 뒤의 별개 주석을 출력한 터미널 기록." caption="연결 패키지 9 파일 1,473 줄 · 표가 든 다섯 포트 중 넷이 9 파일 2,598 줄이고 세션만 없음 · @Bean 일곱 중 하나에 @Conditional · 등록 간선 셋 중 둘은 열 파일이 임포트하고 support 만 0 · 주석의 주어인 sdk 패키지만 보면 0 — 58줄 · exit 0" zoom="true"
:::
# sdk/lettuce/connection : 9 파일 1473 줄
600 sdk/lettuce/connection/RedisTopologyClientFactory.java
316 sdk/lettuce/connection/RedisRuntimeOwner.java
153 sdk/lettuce/connection/SentinelFailoverObserver.java
142 sdk/lettuce/connection/RedisConnectionRegistry.java
# 표가 든 다섯 포트 중 구현이 있는 넷
cache 2 파일 641 줄
idempotency 2 파일 835 줄
ratelimit 3 파일 516 줄
lease 2 파일 606 줄
합계 9 파일 2598 줄
# 다섯째 session : 패키지 없음, main 전체에서 session 문자열 8
# 그 행에 이름이 없어 뺀 패키지 : realtime 591 줄, keyspace 106 줄
# 상태 기여자 : 88 + 62
의미 포트 행은 다섯 이름을 한 칸에 묶는데 그중 하나만 맞다. 세션은 패키지가 없고, 리프 메인 전체에서 그 문자열 여덟 건이 전부 javadoc 산문과 역할 선택자 값이다. realtime 과 keyspace 는 그 행에 없는 이름이라 합계에서 뺐다.
@Bean 은 일곱, 무조건은 여섯
273: @Bean(destroyMethod = "close")
274- public RedisRuntimeOwner redisRuntimeOwner(RedisRuntimeClient client, RedisSdkSettings settings) {
297: @Bean(RedisCorrectnessRoles.OPTIONAL_HEALTH_CONTRIBUTOR)
298- public HealthIndicator redisOptional(RedisRuntimeOwner owner, RedisSdkSettings settings) {
324: @Bean(RedisCorrectnessRoles.REQUIRED_HEALTH_CONTRIBUTOR)
325- @Conditional(RedisCorrectnessRoleBound.class)
326- public HealthIndicator redisRequired(RedisRuntimeOwner owner, RedisSdkSettings settings) {
일곱째만 조건부다. 세션·멱등·레이트리밋·리스 중 하나가 Redis 를 고를 때 생긴다. 나머지 여섯은 스위치 하나로 조립된다. 어디서도 조립되지 않는 것은 게이트웨이와 의미 어댑터 둘이다.
빌드 파일의 의존성 주석
// Registered edges the semantic port adapters need. The SDK itself imports nothing from them
// today (0 imports across main source) — the semantic cache/session/idempotency/rate-limit
// adapters that did were removed and are restored by Phase E of
// …
// because that restoration is the module's stated responsibility, not because anything here
// compiles against them.
implementation project(':application-core')
implementation project(':shared-contract')
implementation project(':adapter:outbound:support')
주어절은 맞다.
dev.caskeleton.application 7 파일
dev.caskeleton.shared 3 파일
dev.caskeleton.adapter.outbound.support 0 파일
# 주석의 주어인 sdk 패키지만 보면 : 0
sdk 패키지는 세 간선 어디에서도 임포트하지 않는다. 틀린 것은 괄호 안의 일반화다. 메인 소스로 넓히면 열 파일이 임포트하고, 셋 중 support 만 주석대로 0 이다.
같은 주석이 그 어댑터들은 제거됐다고 적는데, 위에서 센 파일들이 그것이다. 간선을 남겨 두는 이유로 든 문장도 뒤집힌다 — 여기서 무언가가 그것에 대해 컴파일되기 때문이 아니라고 적혀 있는데, 컴파일된다.
스무 줄 뒤의 별개 주석은 맞다.
// Deliberately absent:
// org.springframework.data:spring-data-redis — … Zero imports.
// io.micrometer:micrometer-core — … Zero imports.
어긋난 방향
표가 없다고 적은 자리마다 코드가 있다. 보통의 표류는 반대 방향이다. 이 문서를 읽고 분기하는 쪽은 이미 있는 코드를 다시 구현하거나, 조립되지 않은 채 존재하는 코드의 존재 자체를 모른다.
순서를 시사하는 문장이 자동 설정 안에 있다.
* RedisSdkSettings#validate()} the fail-fast its own documentation claims — until this class
* existed the method had no production caller at all.
확인하지 못한 것
README 가 마지막으로 갱신된 시점과 자동 설정이 추가된 시점을 이력에서 대조하지 않았다. 자동 설정 javadoc 의 문장이 순서를 시사할 뿐이다.