Skip to content

fix: name the plan the release published, not a second compile of it - #250

Merged
kcrmin merged 1 commit into
developfrom
fix/int03-backtest-execution-handoff
Aug 9, 2026
Merged

fix: name the plan the release published, not a second compile of it#250
kcrmin merged 1 commit into
developfrom
fix/int03-backtest-execution-handoff

Conversation

@kcrmin

@kcrmin kcrmin commented Aug 9, 2026

Copy link
Copy Markdown
Member

INT03 run c0df2755-01eb-3660-b57e-be20ab73001a시뮬레이션을 시작하지도 못했습니다.

JobNotSatisfiable: compiled plan sha256:f98de8f7bde5c44eaadf82acad874d9ba7c10eae0d56030687fa706f49a2e850
is not resolvable

근본 원인 — 서로 다른 산출물의 해시를 비교하고 있었습니다

ImmutableStrategyReleaseCommandService.release() 안에 두 값이 있었습니다.

무엇의 해시인가 어디로 갔는가
release.contractPlan().planChecksum() StrategyBotCompiledPlanAssemblerstrategy-bot.v1 문서에 대해 계산 bot.launch_contract_plans.plan_checksum
plan.planHash() release()두 번째로 호출한 planService.compile()CompiledFlowPlan 메시지의 compiledPlanChecksum

둘은 같을 이유가 없습니다. 소비자(PostgresCompiledPlanSource)는 메시지의 값으로 정확히 그 테이블
조회하므로, 요청은 저장된 적 없는 행의 이름을 부른 것입니다.

저장도 조회도 정상이었습니다. producer 가 consumer 에게 잘못된 이름을 알려준 것입니다.

고친 방식 — 검사가 아니라 표현 불가능

forRelease 에서 해시 인자를 제거하고 release.contractPlan().planChecksum() 을 읽습니다. 두 값이
어긋나는 상태를 만들 방법이 없어집니다. 덤으로 중복 컴파일도 사라집니다 — prepare() 가 이미 컴파일하고
계약을 조립합니다.

시험 두 개가 이 결함을 가리고 있었습니다

배포까지 간 이유입니다.

  1. ImmutableStrategyReleaseCommandServiceTest:85 가 요청이 planPort.saved.planHash() 를 실어야
    한다고 단정했습니다. 시험이 결함을 불변식으로 고정하고 있었습니다. 계약 체크섬을 요구하도록 바꾸고,
    그 픽스처에서 두 값이 실제로 다르다는 단정을 추가해 우연히 통과할 수 없게 했습니다.
  2. ImmutableStrategyReleasePersistenceIntegrationTestContractPlan
    "sha256:" + "c".repeat(64) 로 만들고 HASH_C(= "c"*64)를 넘겼습니다. 같은 값이라 저장 행과
    메시지가 우연히 일치했습니다. 파일 내 다른 모든 해시와 구분되는 값으로 바꿨습니다.

시험

./gradlew test → BUILD SUCCESSFUL
  test 태스크 12개, backend-application 330 tests 재실행, 나머지 UP-TO-DATE
수정 전: releasesOneIndependentImmutableBotFromTheExactValidatedMeaning FAILED (옛 단정)
        persistence 통합 시험은 컴파일 오류로 호출부 노출

이 PR 이 담지 않은 것

같은 run 의 2차 장애(correlation ID 가 UUID 가 아니어서 terminal 실패 발행이 계약 위반으로 막힌 것)는
루트 소유입니다 — user-data 가 EC2 instance id 를 UUID 필드에 넣고 있었고, 같은 릴리스에 함께 올립니다.

backtest-engine 쪽 방어(발행 실패가 terminal 판정을 뒤집지 않게, correlation ID 를 기동 시 검증)는
backtest-engine #74 /
PR #75 입니다.

기존 run 을 대체·재실행하지 않았고, 신규 공개 release/backtest run 을 만들지 않았고, DLQ·워커·ASG·DB 를
건드리지 않았습니다.

🤖 Generated with Claude Code

INT03 run c0df2755 never started simulating. The worker resolved the request's
compiledPlanChecksum against bot.launch_contract_plans, found nothing, and failed with

  JobNotSatisfiable: compiled plan sha256:f98de8f7... is not resolvable

Two different digests were in play. The release stores
release.contractPlan().planChecksum() — the assembler's digest over the strategy-bot.v1
document. The request carried CompiledFlowPlan.planHash() from a second
planService.compile() call in release(), which is a digest of a different artifact. They
have no reason to be equal, so the request named a row that was never written.

Storage was correct and the query was correct. The producer told the consumer the wrong
name.

forRelease no longer accepts the digest. It reads release.contractPlan().planChecksum(),
which makes the divergence unrepresentable rather than merely checked, and removes the
redundant second compile — prepare() had already compiled and assembled the contract.

Two tests were hiding this, which is why it reached a deployment:

- ImmutableStrategyReleaseCommandServiceTest required the request to carry
  planPort.saved.planHash(). The test asserted the defect. It now requires the published
  contract checksum, plus an assertion that the two digests really differ in that fixture
  so it cannot pass by coincidence.
- ImmutableStrategyReleasePersistenceIntegrationTest built its ContractPlan with
  "sha256:" + "c".repeat(64) and passed HASH_C — the same value. The stored row and the
  message agreed by accident. The fixture now uses a digest distinct from every other
  hash in the file.

Full ./gradlew test is green: 12 test tasks, backend-application re-executed with 330
tests and the rest up to date from the previous run.

The correlation-ID half of this failure is root-owned and lands in the same release; the
backtest-engine hardening is backtest-engine #74 / PR #75.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kcrmin
kcrmin merged commit 5374e99 into develop Aug 9, 2026
2 checks passed
@kcrmin
kcrmin deleted the fix/int03-backtest-execution-handoff branch August 9, 2026 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant