Sub-scope 05 (cache-redis) sdk/lettuce/{command,connection,codec,observability} — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T04:47:40+00:00

=== OWNED FILES ===
ba89d938899ab92cf3c4d45facfea03dee1368c8 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/ByteArrayCodec.java 38
2dc49adbd86e934e3fc66a6c7abd50b63afbf1d5 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/DoubleCodec.java 57
32a4a8acb6f48d36deb7727532f4d4261685094c main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/JsonEnvelopeFraming.java 206
89d996cd317067144f662ac11bd2dc284722ccbf main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/LongCodec.java 56
77f6e2e5cf3ce677e40041c3f9c7547b170d77a1 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/RedisCodecRegistry.java 203
68e4685bae9138b285c1d4d857dc973a4e88f79a main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/Utf8StringCodec.java 39
fa5ffcfc22983ade442f48a47f50fe0ddc43cb9f main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/VersionedJsonCodec.java 106
7a2f709f6deba7a8e22d33edd77887c7c20a353a main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandAdmission.java 32
fa34b73b14534f84b549177ca99f75a26b918700 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandExecutionContext.java 156
70d9570303805749615e76cc4d2c488dd367ae45 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuard.java 278
41098f8de3bf0c10ed8abdce07f9b106372a50be main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandRequest.java 87
a55e4fd3b6a1cc3d140ab37179c777676909759e main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/ExecutionCertainty.java 43
e5228fcf891ed04864d190c4b6dc8c0275fa1866 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/LettuceExceptionTranslator.java 234
f3134a239b1b77c674c9f612af9e8bf64d64c4b1 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/QueueingRedisCommandExecutor.java 134
7e51cf05ea83b97191474a44c4652380358e8554 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/ReactiveRedisCommandExecutor.java 88
b9e63268abe98778298e62faaeda66c7d8739180 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandCatalog.java 136
a5e60cab2033eadb33a69cfd309568a353c87e42 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiff.java 145
18bb7d816ea6e088d6730b37a0e7ac808197dd2d main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandPolicy.java 95
1a64df2654ff5f22b787c92a9eb8d9934946ef73 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandPolicyLoader.java 268
e54187b76418ed537f77f11c37c34ccf0c2b768e main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisServerCommandMetadata.java 29
977f8e89a52ba9c3b62be4b6f1da677d520bd60e main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/SyncRedisCommandExecutor.java 100
0def0f4aee46a15ec87343cb2b2ba120ee0f1ae6 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisConnectionKind.java 75
6fc28d3e46dedab9e8314ed18af6eda412d0ab59 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisConnectionLease.java 28
6d74f61bb9be6537da97574027af6e8d7bcc7966 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisConnectionRegistry.java 142
ff404b80d826bb2c50fcdc3b4477c6b0dca19a39 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisCredentialRole.java 32
850e71b4410735b9169ba12760c1095979244872 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisLease.java 44
84a9b13cc707d13e0b627a03aa55af9fe61c6d87 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisRuntimeClient.java 83
bbb465c6bfd766bdcd2bf5c8156b7fd6ba996670 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisRuntimeOwner.java 316
d4d23ae941e401f1da4ce515210346f335dbb000 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisTopologyClientFactory.java 600
1e3f37c50fc407b67a9f67bab5ae1c3b1f138f0d main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserver.java 153
29749551acb95daae4c8a38f89af5f0cf4490c12 main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/observability/NoThrowObservationSink.java 88
d9fa4a2c8ebe4bd89d2f845cc4c2158671a4e25f main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/observability/RedisObservation.java 203
443eef8d46a40284bf563109d0f61eb40112065d test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/RedisCodecRegistryTest.java 94
5e5d6d76496bd95eab31cc857e80c7da2a12301b test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/codec/VersionedJsonCodecTest.java 216
fbe267c5fa2d90a95e91263bf819211ec68752b4 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuardTest.java 368
917f7e0656a54da796c2dc2557a2972d0fd6fa8a test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/LettuceExceptionTranslatorTest.java 138
af77d26f91f6b5bc4abb8cc88dd0019b3b359151 test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/ObservationIsolationTest.java 147
cfb95d32b43012a9630855b2d990c7f1dcf9141a test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java 119
7e23f55e3acde280f5e1ef52e581588b3663b22d test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandPolicyLoaderTest.java 199
8e41ef7b84ef71971e1a90d6a7cfdd91eea38f8b test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisConnectionRegistryTest.java 100
cd5253c6f86b78453909dad203560f821094843f test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/RedisRuntimeOwnerTest.java 238
dcb70191c7df1fc78ea25a95dbf6eb40eddf44de test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java 109
daf77cad4cf7fead3f9a6fd5817000c4893f350c test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/observability/RedisObservationTest.java 108
1e14e4c319fe43d940b2ea66595800df458af277 test/resources/redis-sdk/golden/order-summary-v1.json 0

main: 32  test: 11  resource: 1
=== 8.1 reachability: 이 sub-scope 타입들의 production 소비자 ===
CommandPolicyGuard: main 참조 파일 17
RedisCommandCatalog: main 참조 파일 4
RedisCommandPolicyLoader: main 참조 파일 1
RedisCommandMetadataDiff: main 참조 파일 0
SentinelFailoverObserver: main 참조 파일 0
RedisConnectionRegistry: main 참조 파일 1
QueueingRedisCommandExecutor: main 참조 파일 1
RedisCodecRegistry: main 참조 파일 0
NoThrowObservationSink: main 참조 파일 3
$ git grep -n 'SentinelFailoverObserver' -- 'adapter/outbound/cache-redis/src' | grep -v 'connection/SentinelFailoverObserver.java'
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:20:class SentinelFailoverObserverTest {
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:29:    SentinelFailoverObserver observer = new SentinelFailoverObserver(16);
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:40:    SentinelFailoverObserver observer = new SentinelFailoverObserver(16);
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:50:    SentinelFailoverObserver observer = new SentinelFailoverObserver(16);
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:67:    SentinelFailoverObserver observer = new SentinelFailoverObserver(2);
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:81:    SentinelFailoverObserver observer = new SentinelFailoverObserver(4);
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/connection/SentinelFailoverObserverTest.java:90:    assertThatThrownBy(() -> new SentinelFailoverObserver(0))
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/operations/LiveRedisSentinelPromotionTest.java:15:import dev.caskeleton.adapter.outbound.cache.redis.sdk.lettuce.connection.SentinelFailoverObserver;
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/operations/LiveRedisSentinelPromotionTest.java:40: * <p>The unit suite can prove that {@link SentinelFailoverObserver} counts what it is told and that
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/operations/LiveRedisSentinelPromotionTest.java:105:  private static SentinelFailoverObserver observer;
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/operations/LiveRedisSentinelPromotionTest.java:146:    observer = new SentinelFailoverObserver(1_000);
exit=0

$ git grep -n 'RedisCommandMetadataDiff' -- 'adapter/outbound/cache-redis/src' | grep -v 'command/RedisCommandMetadataDiff.java'
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:12:class RedisCommandMetadataDiffTest {
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:19:    RedisCommandMetadataDiff diff =
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:20:        RedisCommandMetadataDiff.compare(
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:35:    RedisCommandMetadataDiff diff =
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:36:        RedisCommandMetadataDiff.compare(
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:51:    RedisCommandMetadataDiff diff =
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:52:        RedisCommandMetadataDiff.compare(
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:65:    RedisCommandMetadataDiff diff =
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:66:        RedisCommandMetadataDiff.compare(
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:78:    RedisCommandMetadataDiff diff =
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:79:        RedisCommandMetadataDiff.compare(
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:91:    RedisCommandMetadataDiff diff =
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandMetadataDiffTest.java:92:        RedisCommandMetadataDiff.compare(
exit=0

=== 8.2 sync/reactive 실행자가 같은 guard 경로를 지나는가 ===
$ grep -n 'guard\|admission\|translator\|observationSink' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/SyncRedisCommandExecutor.java | head -20
17: * Synchronous execution of a guarded command.
25:  private final CommandPolicyGuard guard;
26:  private final LettuceExceptionTranslator translator;
28:  private final Consumer<RedisObservation> observationSink;
33:   * @param guard the admission guard
34:   * @param translator the driver failure translator
36:   * @param observationSink receives one completed observation per execution
39:      CommandPolicyGuard guard,
40:      LettuceExceptionTranslator translator,
42:      Consumer<RedisObservation> observationSink) {
43:    this.guard = Objects.requireNonNull(guard, "guard must be non-null");
44:    this.translator = Objects.requireNonNull(translator, "translator must be non-null");
47:    this.observationSink = NoThrowObservationSink.wrap(observationSink);
51:   * Executes a guarded command and waits for its result.
56:   * @throws RedisOperationException when the guard refuses the command or the driver fails
60:    CommandAdmission admission = guard.validate(request);
63:            admission.descriptor(), admission.connectionKind(), deploymentMode, admission.slot());
66:    // Only the Redis call is inside the guarded region. Recording the success used to sit here too,
70:      result = await(request.invocation().get(), admission.timeout());
73:          translator.translate(failure, context(admission, startedAt));
exit=0

$ grep -n 'guard\|admission\|translator\|observationSink' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/ReactiveRedisCommandExecutor.java | head -20
13: * Reactive execution of a guarded command.
21:  private final CommandPolicyGuard guard;
22:  private final LettuceExceptionTranslator translator;
24:  private final Consumer<RedisObservation> observationSink;
29:   * @param guard the admission guard
30:   * @param translator the driver failure translator
32:   * @param observationSink receives one completed observation per execution
35:      CommandPolicyGuard guard,
36:      LettuceExceptionTranslator translator,
38:      Consumer<RedisObservation> observationSink) {
39:    this.guard = Objects.requireNonNull(guard, "guard must be non-null");
40:    this.translator = Objects.requireNonNull(translator, "translator must be non-null");
46:    this.observationSink = NoThrowObservationSink.wrap(observationSink);
50:   * Executes a guarded command.
60:          CommandAdmission admission = guard.validate(request);
63:                  admission.descriptor(),
64:                  admission.connectionKind(),
66:                  admission.slot());
69:              .timeout(admission.timeout())
70:              .doOnSuccess(result -> observationSink.accept(observation.succeeded(0)))
exit=0

=== 8.3 정책 이름 교차 검사 (sub-scope 04 §37 이월 확정) ===
$ grep -n 'everyAdvancedCommandDeclaresThePermitPolicyItRequires' -A 10 adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandPolicyLoaderTest.java
114:  void everyAdvancedCommandDeclaresThePermitPolicyItRequires() {
115-    loader.loadDefault().values().stream()
116-        .filter(policy -> policy.support() == CommandSupport.ADVANCED_TYPED)
117-        .forEach(
118-            policy ->
119-                assertThat(policy.requiredPolicyName())
120-                    .as("command '%s'", policy.commandId())
121-                    .isPresent());
122-  }
123-
124-  @Test
exit=0

$ git grep -n 'RedisOperationContext' -- 'adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command'
adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuardTest.java:229:  // RedisOperationContext.requireReplyWithinBudget, and is covered against real replies by the
exit=0

=== 8.4 정책 문서의 필드 목록 대 loader가 받는 필드 ===
$ grep -n 'private static final Set<String> FIELDS' -A 15 adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/RedisCommandPolicyLoader.java
39:  private static final Set<String> FIELDS =
40-      Set.of(
41-          "minimum-version",
42-          "risk",
43-          "support",
44-          "access",
45-          "blocking",
46-          "optional-block",
47-          "read-only",
48-          "retry-safe",
49-          "may-be-ambiguous",
50-          "timeout-profile",
51-          "key-spec",
52-          "required-policy");
53-
54-  /**
exit=0

$ sed -n '7,19p' adapter/outbound/cache-redis/src/main/resources/redis-sdk/redis-command-policy.yml
# Fields and their defaults:
#   risk             required   R1 | R2 | R3 | R4
#   support          required   TYPED | ADVANCED_TYPED | RAW_ONLY | ADMIN_ONLY | VERSION_GATED | BLOCKED
#   minimum-version  "7.2"      lowest server version that carries the command
#   access           derived    TYPED->APPLICATION, ADVANCED_TYPED/VERSION_GATED->APPLICATION_ADVANCED,
#                               RAW_ONLY->RAW_GATEWAY, ADMIN_ONLY->ADMIN_READONLY, BLOCKED->NONE
#   blocking         false      occupies its connection until the server replies or the block expires
#   read-only        false      never mutates the dataset
#   retry-safe       read-only  may be retried after a failure that could have reached the server
#   may-be-ambiguous !read-only a failure may leave the outcome unknown
#   timeout-profile  derived    R1->FAST, R2->COLLECTION, R3->ADMIN, blocking->BLOCKING
#   key-spec         "1 1 1"    "<first> <last> <step>", "none", or "movable"
#   required-policy  -          permit policy name an R2 command demands
exit=0

$ grep -n 'optional-block' adapter/outbound/cache-redis/src/main/resources/redis-sdk/redis-command-policy.yml
666:    optional-block: true
673:    optional-block: true
exit=0

=== 8.4b 관측: 태그 집합이 닫혀 있는가 ===
$ grep -n 'Set.of\|TAG\|tags()' adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/observability/RedisObservation.java | head -20
exit=0

=== 8.4c 제거된 중복 mechanism의 흔적 ===
$ grep -n 'validateReply' -B 2 -A 10 adapter/outbound/cache-redis/src/main/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/lettuce/command/CommandPolicyGuard.java
107-  }
108-
109:  // There is deliberately no validateReply(...) here.
110-  //
111-  // This class used to carry one, and nothing called it. Reply budgets were — and are — enforced by
112-  // RedisOperationContext.requireReplyWithinBudget, which the typed operations call at the point
113-  // where the reply is decoded and its real size is known. Two mechanisms for one rule, with the
114-  // more visible one dead, is worse than one: a reader finds the guard's method, assumes replies
115-  // are bounded during admission, and writes an operation that never bounds its own.
116-  //
117-  // Admission cannot do this job anyway. The guard runs before the command is sent, so the only
118-  // reply size available to it is the estimate the request declared. The authority has to sit
119-  // where the bytes actually arrive.
exit=0

