portfolio-hub 404(미등록 포트폴리오)가 retryable 로 분류되어 백오프·상한 없이 초당 영구 재시도되던 버그(issue #13, 실측 930회) 정정. 거버넌스: 전부 change-req (신규 REQ 없음, dcy-015 OQ-3; 백오프 env 는 REQ-019 흡수). - REQ-017: 404/400/422 → LedgerPermanentError 분류 (409 conflict / 408·429·5xx· network retryable 불변). LedgerPort 에 permanent 타입 추가 - REQ-019: 영속 → 터미널 delivery_failed 즉시(재시도 0). retryable 지수 백오프 +jitter+next_retry_at, max_attempts 초과 시 dead-letter delivery_failed. list_pending 이 백오프 행 스킵(head-of-line 보호). 마이그레이션 007(status enum +next_retry_at). 백오프 env(base/cap/max-attempts) - REQ-018: 터미널/dead-letter WARN + WriterStats.delivery_failed 카운터 가시화 - REQ-020: runtime-flows/data-model/interface-contract 정합 단일 터미널 delivery_failed(permanent/dead-letter, last_outcome 로 사유 구분) — conflict_blocked 패턴과 동형. dead-letter 는 운영자 재처리 가능 상태. 검증: 단위 311 passed/34 skipped, 인프라 게이트(PG+RabbitMQ) 345 passed, ruff clean. 신규 test_ledger_outbox_backoff + adapter/PG 테스트, 기존 retryable 백오프 정합. BAT-019 release-candidate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
24 KiB
0. 문서 상태
이 문서의 현재 상태와 식별 정보를 기록한다. 문서 추적과 승인 흐름에 필요한 최소 메타데이터를 적는다.
- 상태: confirmed
- 문서 ID: dcy-015_20260608_ledger-outbox-permanent-error-backoff-cap
- 이슈명: portfolio-hub 404(미등록 포트폴리오)가 retryable 로 분류되어 백오프·상한 없이 영구 재시도됨
- 작성 시각(KST): 2026-06-08 14:21 KST
- 마지막 갱신 시각(KST): 2026-06-08 18:10 KST
- 대체됨: 없음
- 후속 Discovery 참조: 없음
- 생성된 REQ 참조: REQ-017/019/018/020 (전부 change-req, 신규 REQ 없음 — OQ-3). REQ-018=CHG-20260608-03, REQ-017/019/020=CHG-20260608-01. 백오프 env 는 REQ-019 에 흡수. delivery: BAT-019
1. 계획 상태 요약
현재 Discovery가 어떤 배경에서 작성되고 있는지, 연계 문서가 있는지, 지금 시점의 해석이 무엇인지 짧게 요약한다.
- 연계 문서 현황:
- 관련 점수 파일: 미생성
- 관련 TODO/메모: GitHub issue #13 (fourblocks2020/trex-core), 관련 issue #11(dcy-011, ledger silent skip)
- 해석:
- portfolio-hub 가 미등록 포트폴리오에 404 를 반환하면 ledger outbox 가 이를
LedgerRetryableError(일시적 실패)로 분류해 백오프·상한·터미널 상태 없이 초당 1회 영구 재시도하는 버그를 정식 SDLC 주기로 착수한다(실측: buy 행 930회 재시도). - 이번 Discovery에서는 (1) 영속(permanent) 오류(404 등 명백한 클라이언트 오류) 분류 분리, (2) retryable 에 지수 백오프 + max-attempts + dead-letter, (3) 터미널 실패 가시화의 범위를 판정한다. 이미 Implemented·released 된 ledger 어댑터/outbox 계약 변경이므로, 거버넌스는 OQ-3 결정에 따라 기존 REQ(REQ-017/019/018/020)
change-req로 처리하고 신규 REQ 는 원칙적으로 생성하지 않는다.
- portfolio-hub 가 미등록 포트폴리오에 404 를 반환하면 ledger outbox 가 이를
2. 요구사항 판정 결과
이번 요청이 기존 요구사항과 비교해 신규인지, 유사한지, 중복인지 판단하고 그 근거를 남긴다.
- 판정: 신규
- 근거
- 기존 Discovery(dcy-001~dcy-014) 중 ledger outbox 의 영속 오류 분류·백오프·상한·dead-letter 를 다룬 문서는 없다. dcy-004(portfolio-hub ledger 연동)는 경로를 도입했고, dcy-010(safety-sell 영속 거부 backoff)은 다른 경로(safety-sell→KIS)의 per-slot 쿨다운이며, dcy-011(issue #11)은 portfolio_id 누락 skip 가시화로 본 이슈(전송 단계 404)와 원인이 다르다.
- 변경이 이미 Implemented·released 된 LedgerPort/portfolio-hub 어댑터(REQ-017)와 outbox durability(REQ-019)의 오류 분류·상태 계약을 바꾸므로, 기존 Discovery 미세 조정이 아니라 독립 주기로 추적하는 것이 명확하다.
3. 문제점의 요약
문제의 현재 상태, 기대 상태, 관련 이해관계자, 제약사항을 정리한다. Discovery의 핵심 맥락을 가장 먼저 이해할 수 있어야 한다.
- 현재 상태
trex_core/adapters/ledger/portfolio_hub.py(79~95)는 응답을 분류할 때 2xx→성공, 409→LedgerConflictError(터미널), 그 외 4xx/5xx 전부→LedgerRetryableError로 보낸다(파일 헤더 계약:4xx (other)/5xx => LedgerRetryableError). 따라서 404(portfolio 없음)처럼 재시도로 절대 해소되지 않는 영속 오류가 일시적 오류와 동일하게 취급된다.trex_core/application/ledger_outbox.py(137~142)는LedgerConflictError→conflict_blocked(터미널),LedgerRetryableError→행을pending유지 +attempts += 1이 전부다. 지수 백오프·max-attempts 상한·dead-letter 상태가 없다. ledger 루프는ledger_interval_sec(기본 1.0초)마다list_pending(limit=32)를 FIFO 로 다시 집어 재시도한다.trex_core/adapters/persistence/sql/002_create_ledger_outbox.sql(20~21)의 status CHECK 는pending/completed/conflict_blocked3개뿐이다. 즉 비-409 영속 실패를 담을 터미널 실패 상태가 스키마에 없다.- 결과(실측, instance
trex-admin-daily-trading,portfolio_id=PF-test미등록): buy 행attempts=930, sell 행attempts=9, 둘 다status=pending last_outcome=retryable_failure. 멈출 때까지 초당 1회 영구 호출. - baseline 문서(
docs/project-structure.md,docs/runtime-flows.md,docs/data-model.md)는 존재하며 최신이다. ledger outbox 처리는 기존 runtime flow 에 포함된다.
- 기대 상태
- 404 등 명백한 클라이언트(영속) 오류는 retryable 이 아니라 터미널 실패 상태로 분류되어 재시도가 즉시 중단된다.
- 진짜 일시적 오류(5xx·네트워크·429 등)는 지수 백오프 + max-attempts 로 재시도하되, 상한 초과 시 dead-letter 로 전이되어 무한 1초 재시도가 사라진다.
- 터미널/dead-letter 실패가 WARN 로그·메트릭과 구분되는 status 로 가시화되어, 운영자가 "기록이 영영 안 됨" 을 인지하고 head-of-line 잠식이 해소된다.
- 이해관계자
- 문서 작성자(AI agent) — Discovery/REQ/Batch 산출물 작성
- 리뷰어/승인자 — ledger 오류 분류·outbox 상태 계약 변경 승인
- 운영 담당자 — 영속 실패 가시화·미등록 포트폴리오 조치
- portfolio-hub 운영 — 무한 404 호출 spam 제거로 부하 경감
- 제약사항
- 이미 released 된 LedgerPort/portfolio-hub 어댑터·outbox durability 변경이므로 ad-hoc 수정이 아니라 정식 SDLC(change-req 또는 신규 REQ) 경유가 필요하다.
- outbox status enum 확장은 스키마 마이그레이션을 동반하며 기존
conflict_blocked터미널 패턴과 정합해야 한다. - 영속 오류 분류가 과하면(예: 등록 지연으로 인한 일시적 404) 정상 거래의 ledger 를 영구 실패시킬 수 있어 분류 경계가 중요하다.
주요 사용자 시나리오
사용자 또는 운영자가 실제로 어떤 상황에서 이 변경을 필요로 하는지 대표 시나리오를 적는다.
- 운영자가 미등록 portfolio_id 로 거래를 발생시킨다 → ledger 전송이 404 → 즉시 터미널 실패로 표시되고 WARN/메트릭으로 노출되어, 초당 무한 재시도 없이 운영자가 portfolio 등록 등 조치한다.
- portfolio-hub 가 일시적으로 5xx/네트워크 장애를 낸다 → ledger outbox 가 지수 백오프로 재시도하고, max-attempts 초과 시 dead-letter 로 전이해 무한 재시도를 막는다.
- 영속 실패 행이 다수 쌓여도 FIFO 배치(limit=32)를 잠식하지 않아 신규 ledger 행이 지연 없이 처리된다.
4. 이번에 정의할 변경
이번 Discovery에서 다루는 핵심 변경 항목을 목록으로 적는다. 기능, 구조, 규칙 변경을 함께 포함해도 된다.
- ledger 어댑터(portfolio-hub) 오류 분류를 분리한다 — 404(및 명백한 클라이언트 오류)를 retryable 이 아니라 영속 오류(LedgerPermanentError 등) 로 매핑해 outbox 가 터미널 실패로 처리하게 한다.
- outbox retryable 처리에 지수 백오프 + jitter + max-attempts 를 도입하고, 상한 초과 시 단일 터미널 상태
delivery_failed(dead-letter, 사유 저장)로 전이한다.list_pending이next_retry_at미도래 행을 건너뛰어 head-of-line 잠식을 막는다. - outbox status enum 에 단일 터미널
delivery_failed추가 +next_retry_at컬럼 스키마 마이그레이션. (영속·dead-letter 공용, 사유로 구분) - 터미널/dead-letter 실패를 WARN 로그·메트릭으로 가시화한다(dcy-011 #11 가시화 패턴 정합).
- ledger baseline 문서에 오류 분류·백오프·터미널 상태 흐름을 반영한다.
영향 범위
변경이 미칠 코드/문서/운영 범위를 명시해 REQ 정제와 batch planning에서 추정 누락을 줄인다.
- 코드 영향:
trex_core/adapters/ledger/portfolio_hub.py— 404/400/422 등 영속 오류 분류(신규LedgerPermanentError매핑), 계약 헤더 갱신trex_core/application/ledger_outbox.py— 영속 오류→delivery_failed터미널, retryable 지수 백오프+jitter + max-attempts →delivery_failed(dead-letter),list_pending의next_retry_at스킵trex_core/adapters/persistence/sql/— ledger_outbox status enum 에delivery_failed추가 +next_retry_at컬럼 마이그레이션trex_core/runtime/config.py— 백오프 base/cap·max-attempts env 설정(dcy-010 관례)- LedgerPort 계약(에러 타입) — 영속 오류 타입 추가
- 문서 영향:
docs/runtime-flows.md— ledger outbox 오류 분류·백오프·터미널/dead-letter 흐름 반영docs/data-model.md— ledger_outbox status enum 확장 반영docs/interface-contract.md— ledger 어댑터 오류 분류 계약(필요 시)
- 운영 영향:
- 미등록 포트폴리오의 무한 404 spam 제거 → portfolio-hub 부하·로그 오염 경감
- 터미널/dead-letter 가시화 + 운영자 재처리 경로 필요
5. 요구사항 목록
실제로 구현과 검증으로 이어질 요구사항을 기능/비기능으로 나누어 정리하고, 범위 경계를 명확히 적는다.
기능 요구사항
- FR-1: portfolio-hub 어댑터는 영속(클라이언트) 오류를 retryable 과 분리한다 — 404·400·422(OQ-1)를
LedgerPermanentError(가칭)로 매핑하고, outbox 는 이를 터미널 실패 상태로 처리해 재시도하지 않는다. 408·429·5xx·네트워크·(보수적으로)401/403 은 retryable 로 유지한다. - FR-2: 진짜 일시적 오류(5xx·네트워크·408/429 등)는 지수 백오프 + jitter(
delay = min(base × 2^(attempts-1), cap),next_retry_at기준)로 재시도하고, max-attempts 초과 시 터미널delivery_failed(dead-letter)로 전이한다. 백오프 base/cap·max-attempts 는 env 설정(dcy-010 관례). 무한 1초 재시도를 제거한다. - FR-3: ledger_outbox 에 단일 터미널 실패 상태
delivery_failed를 추가(영속·dead-letter 공용, 사유 저장)하고next_retry_at컬럼 + status enum 마이그레이션을 추가한다.list_pending은next_retry_at > now(백오프 중) 행을 건너뛰어 FIFO head-of-line 잠식을 막는다. - FR-4: 터미널/dead-letter 실패 발생 시 WARN 로그 + 메트릭으로 가시화하고, status 로 정상
pending과 구분되게 한다(issue #11/dcy-011 가시화 패턴 정합). - FR-5:
docs/runtime-flows.md·docs/data-model.md(및 필요 시docs/interface-contract.md)에 오류 분류·백오프·터미널 상태 흐름을 반영한다.
비기능 요구사항
성능, 운영성, 일관성, 자동화 안정성 등 기능 외 요구사항을 적는다.
- NFR-1: 외부 호출 절제 — 영속 오류는 재시도하지 않고, 일시적 오류는 백오프로 호출 빈도를 제한해 portfolio-hub spam 이 발생하지 않아야 한다.
- NFR-2: 가시성 — ledger 가 끝내 기록되지 않는 실패는 메모리 카운터나 무성 pending 이 아니라 status·로그·메트릭으로 영구 관측 가능해야 한다(무성 영속 실패 금지).
- NFR-3: 처리량 보호 — 영속/백오프 대기 행이 FIFO 배치를 잠식해 신규 ledger 행 처리를 지연시키지 않아야 한다.
- NFR-4: 정합성 — 상태 전이(pending↔backoff↔terminal/dead-letter)와 멱등(correlation_id, REQ-019)이 깨지지 않아야 한다.
범위 경계
이번 반복에서 반드시 포함할 범위와 명시적으로 제외할 범위를 구분한다.
- In Scope
- 영속 오류 분류 분리(404 등 → 터미널)
- retryable 지수 백오프 + max-attempts + dead-letter + list_pending 백오프 스킵
- 터미널/dead-letter 가시화(로그/메트릭/status)
- status enum 마이그레이션 + ledger baseline 문서 갱신
- Out of Scope
- safety-sell→KIS 영속 거부 backoff(dcy-010/REQ-052 에서 별도 처리 — 경로 다름)
- portfolio_id 누락 ledger skip(dcy-011/#11 에서 처리)
- dead-letter 행의 재처리 트리거(운영 명령/자동 재처리) — 이번 주기는 재처리 가능한 dead-letter 상태 제공까지이며, 재처리 트리거/자동화는 후속 분리(issue #13 핵심 해소에 불요)
6. 리스크/가정 목록
불확실성과 전제 조건을 분리해서 적는다. 리스크는 영향과 완화 방안을, 가정은 현재 판단의 전제를 기록한다.
리스크
- R-1 (Medium, OQ-1 으로 완화): 영속 오류 분류가 과하면 정상 거래의 ledger 가 영구 실패로 버려질 수 있다.
- 완화 방안: OQ-1 으로 permanent 범위를 404/400/422 로 한정했고, dcy-011 의 admission-time portfolio_id 검증으로 ledger 404 의 등록-지연 false-positive 가능성이 크게 줄었다. 잔여 false-positive 도 dead-letter 가 폐기가 아니라 운영자 재처리 가능 상태라 복구 가능하다.
- R-2 (Medium): status enum 확장 마이그레이션이 기존
conflict_blocked/pending/completed와 정합하지 않으면 outbox 처리가 깨질 수 있다.- 완화 방안: 기존 터미널(
conflict_blocked) 패턴을 그대로 따르는 새 터미널 상태를 추가하고, 마이그레이션·상태 전이를 테스트로 검증한다.
- 완화 방안: 기존 터미널(
- R-3 (Medium): dead-letter/터미널 행이 단순 포기되면 체결은 됐는데 ledger 영구 누락(P&L 왜곡)이 고착된다.
- 완화 방안: dead-letter 를 운영자 재처리 가능 상태로 두고, dcy-011 의
find_ledger_gap_slots(REQ-055)·skip 가시화와 연계해 누락을 추적·복구한다.
- 완화 방안: dead-letter 를 운영자 재처리 가능 상태로 두고, dcy-011 의
가정
아직 확정되지 않았지만 현재 문서 작성의 기반이 되는 전제를 적는다.
- A-1: dcy-011(#11) 이 ledger skip 가시화(WARN+카운터, REQ-018)와
find_ledger_gap_slots(REQ-055) 를 이미 구현했으므로, 본 이슈의 터미널 실패 가시화도 동일 패턴으로 정합하게 추가할 수 있다. - A-2: dcy-010(REQ-052/053) 의 백오프/쿨다운 + env 설정 관례가 있어, ledger 백오프 정책의 파라미터·설정 방식을 유사하게 설계할 수 있다(경로는 다름).
- A-3: 409 가 이미
conflict_blocked터미널 상태로 처리되므로, 영속/ dead-letter 도 같은 터미널 상태 패턴으로 추가하면 outbox 처리 구조 변경을 최소화할 수 있다.
오픈 질문
답을 아직 모르는 항목을 적는다. 추정으로 덮지 말고 REQ 초안 작성 이전에 확인할 질문으로 남긴다.
- OQ-1: 영속(permanent) 분류 범위 — 404 만 터미널로 보는가, 400/422 등 명백한 클라이언트 오류도 포함하는가? 408/429 같은 일시성 4xx 는 retryable 유지가 맞는가?
- 상태: Answered (2026-06-08, 사용자 결정 — 404/400/422 영속)
- 결정: 404·400·422 = 영속(터미널, 재시도 0), 408·429·5xx·네트워크 = retryable + 백오프, 401/403 은 보수적으로 retryable+백오프(토큰 일시 갱신 가능성). 근거: dcy-011 이 admission 에서 portfolio_id 를 universe 검증(
unknown_portfolio거부)하므로 ledger 단계 404 는 타이밍 lag 이 아니라 portfolio-hub 미등록 = 진짜 config 갭 → 재시도로 해소 불가. 400/422 도 동일 payload 재전송으로 풀리지 않음. - 반영 위치: FR-1, R-1, DATA
- OQ-2: 백오프·상한 정책 — 지수 백오프 파라미터(base/max), max-attempts 값, dead-letter 상태명·전이 조건은?
- 상태: Answered (2026-06-08, 사용자 결정 — 추천안 채택)
- 결정: (1) 지수 백오프 + jitter —
delay = min(base × 2^(attempts-1), cap),next_retry_at컬럼 추가,list_pending은next_retry_at > now행을 건너뜀(head-of-line 해소). (2) max-attempts 초과 시 터미널 전이. 백오프 base/cap·max-attempts 는 env 설정(dcy-010 REQ-052/053 관례; 예:TREX_LEDGER_RETRY_BASE_SEC/_CAP_SEC/TREX_LEDGER_MAX_ATTEMPTS, 구체 default 는 REQ 정제에서 확정). (3) 단일 터미널 상태delivery_failed— 영속(즉시)과 dead-letter(백오프 소진) 둘 다 이 상태로 두고 사유(reason/last_error)를 저장해 구분(conflict_blocked가 단일 상태인 것과 동일 패턴, 스키마 최소 변경). (4) dead-letter 는 폐기 아님 — 운영자 재처리 가능 상태. - 반영 위치: FR-2, FR-3, 4. 변경 항목/영향 범위
- OQ-3: 거버넌스 경로 — 기존 REQ(REQ-017 어댑터, REQ-019 outbox, REQ-018/055 가시화, REQ-020 문서)의 change-req 로 처리할지, 신규 REQ 로 추적할지?
- 상태: Answered (2026-06-08, 사용자 결정 — change-req 우선)
- 결정: 기존 Implemented REQ 본문 수정(change-req)으로 처리한다. change-req 대상 — REQ-017(LedgerPort + portfolio-hub 어댑터: 404/400/422→
LedgerPermanentError분류, 계약 헤더 갱신), REQ-019(ledger outbox durability: 지수 백오프+jitter+next_retry_at+max-attempts+단일 터미널delivery_failed+status enum/컬럼 마이그레이션+list_pending백오프 스킵+env 설정), REQ-018(체결→원장 fill hook: 터미널/dead-letter WARN+메트릭 가시화 — dcy-011 의ledger_skipped카운터 패턴 정합,find_ledger_gap_slotsREQ-055 연계), REQ-020(ledger 레이어 baseline 문서 정합: runtime-flows/data-model 갱신). 백오프 env 설정은 REQ-019 에 흡수. 신규 REQ 는 원칙적으로 생성하지 않으며, dead-letter 운영자 재처리 트리거를 이번 주기에 포함하기로 하면 REQ 정제에서 소형 신규 REQ 가능(조건부). - 반영 위치: 1. 거버넌스 해석, R-1~R-3 완화 방안, 8. 확인 체크
오픈 질문 처리 기준
Open: 아직 답이 없고 다음 단계 진행에 영향이 있는 상태다. 문서에 유지한다.Answered: 답이 확정된 상태다. 관련 본문/요구사항에 반영한 뒤 오픈 질문 목록에서는 제거하거나 resolved 기록으로 이동한다.Deferred: 지금 단계에서 결정하지 않고 다음 단계 또는 후속 이슈로 넘기는 상태다. 넘길 대상과 이유를 반드시 적는다.Dropped: 더 이상 유효하지 않은 질문이다. 삭제 사유를 짧게 남기고 목록에서 제거한다.
7. 초기 성공 기준
이 변경이 성공했다고 판단할 기준을 측정 가능하게 정의한다. 가능하면 데이터 출처까지 연결한다.
- S-1: 404 응답이 즉시 터미널 실패 상태로 전이되고 재시도가 0회 추가된다(미등록 포트폴리오 시나리오에서 attempts 폭증 없음).
- S-2: 일시적 오류(5xx 등)가 지수 백오프로 재시도되고 max-attempts 초과 시 dead-letter 로 전이된다(무한 1초 재시도 0건).
- S-3: 터미널/dead-letter 실패가 WARN/메트릭·구분 status 로 가시화되어 정상 pending 과 구별된다.
- S-4: 영속/백오프 대기 행이
list_pendingFIFO 배치를 잠식하지 않아 신규 행이 지연 없이 처리된다.
측정 방식 및 데이터 출처
각 성공 기준을 어떻게 측정할지와 어떤 데이터나 문서를 근거로 쓸지 적는다.
- S-1 측정 방식: 404 응답 fixture 단위 테스트에서 터미널 상태 전이·재시도 0 확인 / 데이터 출처: portfolio_hub 어댑터·outbox 테스트, ledger_outbox status/attempts
- S-2 측정 방식: 5xx 반복 fixture 에서 백오프 간격 증가·max-attempts 후 dead-letter 확인 / 데이터 출처: outbox 처리 테스트, next_retry_at/attempts/status
- S-3 측정 방식: 터미널/dead-letter 발생 시 WARN·메트릭·status 확인 / 데이터 출처: 데몬 로그, 메트릭, ledger_outbox status
- S-4 측정 방식: 영속/백오프 대기 행 다수 + 신규 행 주입 시 신규 행 처리 확인 / 데이터 출처: list_pending 결과, 처리 순서/지연
8. REQ로 넘기기 전 확인 체크
REQ 초안 작성 단계로 넘기기 전에 무엇이 확정되어야 하는지 확인한다. 미완료 항목은 후속 결정이 필요함을 뜻한다.
- 범위(In Scope/Out of Scope) 확정
- 기준: permanent 분류(OQ-1)·백오프 정책(OQ-2)·거버넌스(OQ-3)·dead-letter 재처리 범위 확정으로 In/Out of Scope 채워짐
- 성공 지표의 측정 방식/데이터 출처 확정
- 기준: S-1~S-4 의 테스트/검증 출처가 실제 실행 가능한 형태로 지정됨
- High 영향 리스크 우선순위 및 해소 책임자 지정
- 기준: R-1(영속 분류 과대)·R-2(스키마 마이그레이션)·R-3(누락 고착)의 change-req 대상(REQ-017/019/018/020)이 OQ-3 으로 확정됨. 해소 실무 책임자 배정은 REQ/batch planning 단계로 넘김(비차단).
- 모든 오픈 질문(OQ)
Open상태 없음 확인- 기준: OQ-1~OQ-3 모두
Answered,Open0개
- 기준: OQ-1~OQ-3 모두
- Freeze 확정 담당자(CONFIRMED_BY) 지정
- 기준: Confirmed By = Justin Ko (사람 승인자 지정 완료)
9. 파일 처리 결과
이 Discovery 문서 생성/갱신 결과와 참조 문서를 기록한다. 이후 추적과 리뷰 시 근거로 사용한다.
- 처리 결과: 생성
- 생성 경로: docs/discovery/dcy-015_20260608_ledger-outbox-permanent-error-backoff-cap.md
- 참조 문서:
- GitHub issue #13 (fourblocks2020/trex-core) — portfolio-hub 404 영구 재시도 버그
- docs/discovery/dcy-004_20260604_portfolio-hub-ledger-integration.md — portfolio-hub ledger 경로 도입 근거
- docs/discovery/dcy-011_20260608_buy-intent-portfolio-id-required-symbol-resolve.md — ledger skip 가시화·find_ledger_gap_slots 패턴(A-1)
- docs/discovery/dcy-010_20260607_safety-sell-persistent-rejection-backoff.md — 백오프/쿨다운 설계 관례(A-2, 경로 다름)
- trex_core/adapters/ledger/portfolio_hub.py:79-95, trex_core/application/ledger_outbox.py — 404 분류·백오프 부재 지점
10. 사용자 결정 필요 항목 요약
사용자나 승인자가 결정해야 하는 항목만 모아 정리한다. 결정, 확인, 데이터 요청을 구분해서 적는다.
DECIDE
- (없음 — OQ-1/OQ-2/OQ-3 및 dead-letter 재처리 범위 확정으로 해소)
결정 완료(2026-06-08): OQ-1 영속 분류 = 404/400/422 터미널(408/429/5xx/네트워크 retryable, 401/403 보수적 retryable) / OQ-2 백오프 = 지수+jitter+
next_retry_at·max-attempts(env)·단일delivery_failed터미널(사유 저장)·dead-letter 운영자 재처리 가능 / dead-letter 재처리 트리거(운영 명령/자동화)는 본 주기 Out of Scope, 후속 분리(이번 주기는 재처리 가능한 상태 제공까지).
CONFIRM
- 없음 — 거버넌스 경로는 OQ-3 으로 확정됨(REQ-017/019/018/020 change-req, REQ-055 연계, 신규 REQ 원칙적 없음).
DATA
- (비차단, REQ/delivery 단계) portfolio-hub 의 실제 4xx/5xx 응답 의미(404=영속, 429=rate-limit 등) 규약. 구현/검증 단계에서 실 응답·portfolio-hub 명세로 확정하며, OQ-1 의 404/400/422 영속 분류가 본 Discovery 의 FR/성공 기준을 충분히 정의하므로 confirm 을 차단하지 않는다.
11. Discovery Freeze
REQ 초안 작성 인계 시점의 확정 플래그와 섹션 참조만 기록한다. 내용 재작성 없이 원본 섹션을 링크로 대신한다.
섹션 참조
- 범위: # 5. 요구사항 목록 > 범위 경계
- 리스크/오픈 질문: # 6. 리스크/가정 목록
- 성공 기준: # 7. 초기 성공 기준
- 인계 전 확인: # 8. REQ로 넘기기 전 확인 체크
- 사용자 결정 필요: # 10. 사용자 결정 필요 항목 요약
Freeze 플래그
- Handoff Decision: 승인
- Handoff Rationale: confirm-discovery 완료. 오픈 질문 OQ-1~OQ-3 모두 Answered (영속 분류=404/400/422 / 백오프=지수+jitter+next_retry_at·max-attempts env·단일
delivery_failed터미널 / 거버넌스=REQ-017/019/018/020 change-req, 신규 REQ 원칙적 없음). C 유형 플레이스홀더 0개, 저장소 사실관계 일치. dead-letter 재처리 트리거는 Out of Scope(후속). DATA(portfolio-hub 오류 규약)는 REQ/delivery 단계 비차단. REQ 초안 작성 인계 가능. - Ready for REQ Drafting: true
- Confirmed By: Justin Ko
- Confirmed At (KST): 2026-06-08 15:00 KST