Skip to content

test(go): domain schema + errors — Python parity + UTC/customer_escalation divergence locks#94

Open
couragehong wants to merge 1 commit intofeat/go-migrationfrom
yg/phase-a8-domain-schema-errors-tests
Open

test(go): domain schema + errors — Python parity + UTC/customer_escalation divergence locks#94
couragehong wants to merge 1 commit intofeat/go-migrationfrom
yg/phase-a8-domain-schema-errors-tests

Conversation

@couragehong
Copy link
Copy Markdown
Contributor

Summary

  • What: internal/domain/{schema,errors}_test.go 신규. 테스트 only, production 코드 변경 없음.
  • Why: PR test(go): policy rerank + novelty — formula / sort / Python parity gates #92 (policy/{rerank,novelty})에 이은 follow-up — domain/{schema,errors}.go도 PR #90으로 들어왔으나 테스트 0건. silent regression 위험 closing.
  • Scope: agents/tests/test_record_builder.py:L167-188 단 1 case 포팅 + decision_record.py / errors.py / record_builder._parse_domain (Python 측 unit test 사실상 0건)에 first-time 커버리지.

Python 대비

영역 처리 비고
_parse_domain (record_builder.py:L621-655) 19 enum 매칭 + alias gap divergence locked (Python customer_escalation→CustomerSuccess, Go→General)
generate_record_id / generate_group_id 9 case (basic / cap / 한글 / punct / underscore / empty / UTC) 각각 python3 출력으로 검증
validate_evidence_certainty (read-only) 6 case truth table + 비-mutation 검증 Python L215-224
ensure_evidence_certainty_consistency 6 case (양 분기 독립 / marker dedup / partially_supported 보존) Python L226-242
embedding_text_for_record 6 case (insight win / trim / fallback / whitespace / both empty / payload untrimmed) Python L21-30
make_error 4 case (full shape / hint omit / generic / wrapped errors.As) Python L93-118
10 error code constants + 10 RuneError vars wire 값 + Code/Retryable 락 Python parity 7건 + Go-specific 3건 분리
Domain (19) / Status (4) / Certainty (3) enum wire values 전부 락 paired-swap 안전

Python ↔ Go divergence witness (Phase-A debt locked at test layer)

production 차원에서 align할지 추후 결정할 두 건을 테스트가 명시적으로 락:

  • TestParseDomain_CustomerEscalationDivergesFromPython: Python record_builder.py:L646customer_escalation → CUSTOMER_SUCCESS alias 보유. Go 미보유 → DomainGeneral fallback. 테스트가 Go 동작 락 + TODO 주석 + fix recipe.
  • TestGenerateRecordID_NonUTCTimestamp_DivergesFromPython + _UTCBoundaryShiftsDate_DivergesFromPython: Python decision_record.py:L247timestamp.strftime (LOCAL TZ); Go schema.go:L266이 ts.UTC().Format (강제 UTC). KST 00:30 → Python "2026-04-29" / Go "2026-04-28". 테스트가 Go의 UTC normalization 락 + TODO + production 임팩트 코멘트 (cross-team recall 모호성).

errors.As-기반 wrap unwrap (TestMakeError_WrappedRuneErrorUnwrapsViaErrorsAs_GoSpecific)은 Go 전용 enhancement — Python isinstance 비공개 unwrap 안 함. 이름·코멘트로 명시.

강화 포인트 (Python 미가드)

  • ParseDomain 19 enum × _AllNineteenEnumsRoundTrip (탑 레벨 락) + paired-swap 가드는 별도 _WireValues 위임 (자체 코멘트로 명시)
  • ParseDomain 첫 매칭 우선 (ops_security → security, data_design → design)
  • GenerateRecordID 한글 (결정_사항_검토), email@foo.com (전체 단어 drop), my_var (underscore variant 유지), ___ (all-underscores → 빈 strip → drop)
  • EnsureEvidenceCertaintyConsistency 양 분기 독립 fire + marker 중복 방지 + partially_supported 비-downgrade
  • ValidateEvidenceCertainty 비-mutation: cert/status/missing/evidence 전 필드 snapshot
  • EmbeddingTextForRecord payload fallback 시 trim 미적용 락 (vector 보존)
  • MakeError 래핑 RuneError unwrap (Go-specific)
  • 시간대 결정성: _ "time/tzdata" 임포트로 alpine/scratch에서도 LoadLocation 안전

Validation

  • go test -count=1 -race ./internal/domain/ → ok 1.4s, 33 함수 / 129 subtest
  • gofmt -l (이 PR 신규 파일) → clean
  • go vet ./... → clean
  • 사전 multi-agent review: 3 서브에이전트 (adversarial / Python parity / Go style) 발견 사항 14건 반영 — HIGH 3 (UTC divergence misclassification / Retryable 비-Python-parity rename / round-trip tautology 코멘트) + MED 8 (untrimmed payload / mutation snapshot 보강 / type-assert consistency / _ "time/tzdata" / nil 테스트 삭제 등) + LOW 3.

Cross-Agent Invariants

테스트 파일 2개만 추가. scripts/bootstrap-mcp.sh, agent 스크립트, Codex/Claude/Gemini/OpenAI 지시서, SKILL.md, commands/rune/*.toml, AGENT_INTEGRATION.md 모두 미수정 → 모든 invariant trivially 만족.

Notes for Reviewers

  • Risk (Phase-A debt lock-in): customer_escalation alias + UTC normalization 두 divergence는 Go 동작을 lock. Python parity 원하면 별도 production-fix PR — schema.go::domainList{"customer_escalation", DomainCustomerSuccess} (customer_success 앞) 추가 / GenerateRecordID.UTC() 호출 제거. 두 건 모두 cross-team 결정이 필요한 사안 (UTC normalization은 cross-team recall 일관성 vs Python parity trade-off).
  • Risk (Python recovery_hint 비-replicated): Go 의 Err* predefined vars는 Code+Retryable만 보유 (Message/RecoveryHint는 빈 placeholder). Python errors.py L38-89의 rich hint 텍스트는 caller가 채우는 형태로 위임. 이 PR은 그 design choice 자체를 락하지는 않음 — 별도 결정 필요 시 _CodeAndRetryableMatchPython에 hint 검증 추가.
  • BC: 없음 (test-only).
  • Follow-up PR: lifecycle/shutdown_test.go (InflightTracker concurrency + ZeroizeDEK dead-store 가드 + GracefulShutdown timeout). 이후 adapters/vault/endpoint_test.go (URL parsing edge case 보강).

🤖 Generated with Claude Code

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