Sub-scope 03 (httpclient) resilience/** — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T05:29:08+00:00

=== OWNED FILES ===
11a188e9944de7f9a9176c1cd0b9462b0f5292d4 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AmbiguousFailure.java 21
2c7865dc11efe442369926498ddaaa807dfd35fa main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptBudget.java 19
464198c200d6cd5bcd06f92808889fe8e232ebdd main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptBudgetCalculator.java 40
a93d860a126338067419b976f632df11c356d8da main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptCall.java 13
26b571da2a14976174819ab073e59c8adf01d376 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptCircuitBreaker.java 69
cd0790c034022816d975323ee5e6bd7bd011caeb main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptOutcome.java 73
183de4db6c5fb7e4124d7f1d7f993c510efcf7ef main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptProgress.java 31
00ca67c6f78446bc50d74eb8cf755177f615eb70 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptProgressTracker.java 75
617fcae4c19b55e390517e83b6b5af9da8eb7d08 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptRateLimiter.java 29
d306c441d5ad12c6f78c648e1932d5f8b8e5587a main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptResiliencePipeline.java 135
b7d3fb2d075b16c28d65a43a2e82804b3253d8d0 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/BackoffStrategy.java 11
358dfa09be4194c60b49fdc7635c998c880018f9 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/BlockingAttemptBulkhead.java 57
bc90242c8844b849ea2f2b4c1114511d09a1458a main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/BlockingLogicalCall.java 28
46848fcd8808370bf0e62a2c550c252bf3d4ed00 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/BlockingRetryCoordinator.java 64
3ee96a734846f38ba828694397f568cac8d9ab19 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/Deadline.java 33
04e7d007c360ab3494c5c95d46962fd869d9b990 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DeadlineCalculator.java 22
ae18bf166bdebc1fe5958a2d461291f01c945b3c main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DeadlineGuard.java 36
ed8fa2a4c7cefcad29b6f03189117596ad97e4e1 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultExecutionEvidenceClassifier.java 32
2ad13a74289c71848cfcea369cf94f7e106c493f main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultRetryEligibilityEngine.java 133
3aa9ac4ee7d8631871d40481b8e74d4690d36e74 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ExecutionEvidenceClassifier.java 10
bd908670ae736f3a3b3d21db5627fd271e5474dd main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ExponentialFullJitterBackoff.java 93
e94078d67cefa9ec656c3d458385404208bdf49f main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/Http2EvidenceMapper.java 24
97144eb2b67b5af9715c2786250e2e7fbd9c1666 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/Http2ProtocolEvidence.java 40
48a3876a7c05766e623bee39d404e6dce91753e1 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/LogicalAdmissionLimiter.java 44
5d51cdaf82a109c658316aac08e587cbaf26f6e3 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ProtocolEvidence.java 26
8b0986a8a69a34192f4d1c5535561c0afd56a3b7 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ReactiveLogicalCall.java 28
93c4ac3e856f73bce071421471518ca7d4dce064 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ReactiveRetryCoordinator.java 59
a0957ebb899074b2e745601d512a5bf3074f9364 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ResilienceRegistry.java 62
a7738acb9523d32e8fbf7bb67eded4b97fbb35a5 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ResilienceRejectionRecorder.java 93
3839bb0fa0c6207550e3f49d3ddc2f8812520791 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryAllowed.java 22
e63ee2e7151ed63710c3320da88d3db6dbbb6539 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryBudget.java 36
d55e0406ec42fb7e98141570d7be17a0bb0467d0 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryBudgetSnapshot.java 28
de6512387689e3308ef6e5cf914c9e16a0e232ff main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryContext.java 77
82f51add27b2f754d11eabbaeaed601adac91167 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryCoordinator.java 13
f868279a15690cfbf94a05fb5484110009f9d7cc main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryDecision.java 7
7b26fd2bd6808da0a5b2e69e24fd87df45f8e086 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryDenied.java 47
1580a68f10234e8c9dadcdf5d280934b67d6105f main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryEligibilityEngine.java 13
0f4bb4ee5ab1e2e29b22bafdeea078f5e6f68791 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/Sleeper.java 29
64959264dae8b30f8010d2952e7b25bd4f4576f2 main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/TokenBucketRetryBudget.java 74
683ff1f0ff4e6cbae182906cf87083fa86d273ad test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptResiliencePipelineTest.java 87
3faa418425ef981ffe0cdcce5bd2c833cccfa1ee test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/BlockingRetryCoordinatorTest.java 224
143e9f13f728815df52b90d067dd9955105ddc64 test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DeadlineCalculatorTest.java 70
7b2806757d20fe7a95b3c8c9c23dc72cee1b7691 test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ExecutionEvidenceClassifierTest.java 69
00d62297d10374fe7774a84d83c62356b46c30ab test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/Http2EvidenceMapperTest.java 51
ca47780a5ec194bc8e287baffc7791345254fe4c test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/ReactiveRetryCoordinatorTest.java 180
835ebb43f5daf2737c95c4cb2aff0d6f0166b450 test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryBudgetTest.java 59
0906157f9b630ce1ded435bc6a441b33caedaba8 test/java/dev/caskeleton/adapter/outbound/httpclient/resilience/RetryEligibilityEngineTest.java 205

main: 39  test: 8  main LOC:  1746 total
=== 8.1 회로 permission 반환 경로 ===
$ grep -n 'releasePermission' -r adapter/outbound/httpclient/src app-bootstrap/src
exit=1

$ grep -n 'tryAcquirePermission\|onCompleted\|release()\|onError\|onSuccess' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptResiliencePipeline.java
83:    if (!circuitBreaker.tryAcquirePermission()) {
88:    if (!rateLimiter.tryAcquirePermission()) {
94:      rateLimiter.onCompleted();
106:        circuitBreaker.onError(System.nanoTime() - started, upstreamFailure.get());
108:        circuitBreaker.onSuccess(System.nanoTime() - started);
113:      circuitBreaker.onError(System.nanoTime() - started, failure);
119:    bulkhead.release();
120:    rateLimiter.onCompleted();
exit=0

$ grep -n 'boolean tryAcquirePermission\|void onSuccess\|void onError\|String state' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/AttemptCircuitBreaker.java
14:  boolean tryAcquirePermission();
16:  void onSuccess(long durationNanos);
18:  void onError(long durationNanos, Throwable failure);
20:  String state();
25:      public boolean tryAcquirePermission() {
30:      public void onSuccess(long durationNanos) {
35:      public void onError(long durationNanos, Throwable failure) {
40:      public String state() {
49:      public boolean tryAcquirePermission() {
54:      public void onSuccess(long durationNanos) {
59:      public void onError(long durationNanos, Throwable failure) {
64:      public String state() {
exit=0

=== 8.2 PARTIAL_RESPONSE 분기 도달성 (후보 추적) ===
$ grep -rn 'ExecutionEvidence.PARTIAL_RESPONSE' adapter/outbound/httpclient/src/main
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultRetryEligibilityEngine.java:40:    if (context.evidence() == ExecutionEvidence.PARTIAL_RESPONSE) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultExecutionEvidenceClassifier.java:20:      return ExecutionEvidence.PARTIAL_RESPONSE;
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/jdk/JdkFailureClassifier.java:83:            ExecutionEvidence.PARTIAL_RESPONSE,
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/jdk/JdkFailureClassifier.java:103:          ExecutionEvidence.PARTIAL_RESPONSE,
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/http3/JettyHttp3FailureClassifier.java:41:            ExecutionEvidence.PARTIAL_RESPONSE,
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/reactor/ReactorFailureClassifier.java:94:            ExecutionEvidence.PARTIAL_RESPONSE,
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/reactor/ReactorFailureClassifier.java:114:          ExecutionEvidence.PARTIAL_RESPONSE,
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/apache/ApacheFailureClassifier.java:121:          ExecutionEvidence.PARTIAL_RESPONSE,
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/apache/ApacheFailureClassifier.java:136:          lastObservedStage, ExecutionEvidence.PARTIAL_RESPONSE, category, reason);
exit=0

$ grep -n 'firstByteDelivered' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultRetryEligibilityEngine.java adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultExecutionEvidenceClassifier.java
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultRetryEligibilityEngine.java:28:    if (context.firstByteDelivered()) {
adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultExecutionEvidenceClassifier.java:19:    if (progress.responseBytesDelivered() > 0 || progress.firstByteDelivered()) {
exit=0

=== 8.3 재시도 결정표의 순서 ===
$ grep -n 'return RetryDenied\|return AmbiguousFailure\|return RetryAllowed\|case ' adapter/outbound/httpclient/src/main/java/dev/caskeleton/adapter/outbound/httpclient/resilience/DefaultRetryEligibilityEngine.java
20:      return RetryDenied.maxAttempts();
23:      return RetryDenied.budgetExhausted();
26:      return RetryDenied.bodyNotReplayable();
29:      return RetryDenied.responseAlreadyDelivered();
32:      return RetryDenied.runtimeDraining();
35:      return RetryDenied.deadline();
38:      return RetryDenied.permanentFailure(context.failureCategory().name());
48:      return AmbiguousFailure.remoteOutcomeUnknown();
68:      case 408 ->
73:      case 425 -> {
81:      case 429 ->
85:      case 401 ->
91:      case 500 ->
95:      case 502, 503, 504 ->
105:      case POOL_ACQUIRE_TIMEOUT -> RetryAllowed.of("POOL_ACQUIRE_TIMEOUT");
106:      case DNS -> RetryAllowed.of("DNS");
107:      case CONNECT -> RetryAllowed.of("CONNECT");
108:      case PROXY -> RetryAllowed.of("PROXY");
109:      case TLS_TRANSIENT -> RetryAllowed.of("TLS_TRANSIENT");
110:      case REQUEST_WRITE, RESPONSE_TIMEOUT, RESPONSE_TRUNCATED ->
114:      case NONE -> RetryDenied.success();
115:      case CIRCUIT_OPEN, RATE_LIMIT_REJECTED, BULKHEAD_REJECTED ->
125:      return RetryAllowed.of(reason);
129:      return RetryDenied.deadline();
131:    return RetryAllowed.after(reason, retryAfter.get());
exit=0

=== 8.4 test 밀도 ===
$ git ls-files 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/resilience' | xargs -n1 basename
AttemptResiliencePipelineTest.java
BlockingRetryCoordinatorTest.java
DeadlineCalculatorTest.java
ExecutionEvidenceClassifierTest.java
Http2EvidenceMapperTest.java
ReactiveRetryCoordinatorTest.java
RetryBudgetTest.java
RetryEligibilityEngineTest.java
exit=0

$ git grep -hc '  void [a-z]' -- 'adapter/outbound/httpclient/src/test/java/dev/caskeleton/adapter/outbound/httpclient/resilience' | paste -sd+ | bc
main: line 8: bc: command not found
exit=127

