FF [100%] =================================== FAILURES =================================== __________ test_schedule_rewind_recovers_exact_legacy_activity_shape ___________ def test_schedule_rewind_recovers_exact_legacy_activity_shape() -> None: runtime = object.__new__(TelegramNutritionOnboardingRuntime) legacy = ( "활동 수준: 보통. 주 3회, 회당 60분 정도의 중간 강도 근력운동을 " "희망합니다. 평소 걷기·이동은 하루 약 6,000~8,000보 수준입니다." ) rationale = ( "주 3회, 회당 60분 정도의 중간 강도 근력운동을 희망합니다. " "평소 걷기·이동은 하루 약 6,000~8,000보 수준입니다." ) original = { field: onboarding_domain.example_answer(field) for field in onboarding_domain.QUESTION_FIELDS } original["activity_category"] = legacy document = { "state": "customer_attestation", "cursor": 22, "answers": dict(original), "reconciliation": { "answers_digest": "stale", "state": "resolved", }, } runtime.domain = SimpleNamespace( QUESTION_FIELDS=onboarding_domain.QUESTION_FIELDS, load_mutable_session=Mock(return_value=document), save_session=Mock(), build_status=Mock( return_value=SimpleNamespace( state=SimpleNamespace(value="collecting"), answer_count=21, next_field="schedule_constraints", ) ), OnboardingState=SimpleNamespace( COLLECTING=SimpleNamespace(value="collecting") ), ) service = SimpleNamespace( session_path=Path("/private/workflow.json"), customer_key="client_001", ) status = runtime._rewind_collection( service=service, authority="customer-authority", evidence="customer-evidence", target_cursor=21, ) expected = dict(original) expected["activity_category"] = "moderate" expected["activity_rationale"] = rationale expected.pop("schedule_constraints") > assert document["answers"] == expected E AssertionError: assert {'activity_ca...d': '보통', ...} == {'activity_ca...d': '보통', ...} E E Omitting 19 identical items, use -vv to show E Differing items: E {'activity_category': '활동 수준: 보통. 주 3회, 회당 60분 정도의 중간 강도 근력운동을 희망합니다. 평소 걷기·이동은 하루 약 6,000~8,000보 수준입니다.'} != {'activity_category': 'moderate'} E {'activity_rationale': '주 3회 근력 운동'} != {'activity_rationale': '주 3회, 회당 60분 정도의 중간 강도 근력운동을 희망합니다. 평소 걷기·이동은 하루 약 6,000~8,000보 수준입니다.'} E Use -v to get more diff tests/gateway/test_telegram_nutrition_onboarding.py:2065: AssertionError ________ test_recovered_answers_resubmit_to_valid_baseline_and_summary _________ tmp_path = PosixPath('/tmp/pytest-of-cube/pytest-7664/test_recovered_answers_resubmi0') def test_recovered_answers_resubmit_to_valid_baseline_and_summary( tmp_path: Path, ) -> None: authority = onboarding_domain.OnboardingAuthority( customer_key="client_001", customer_user_id=10, customer_chat_id=-100, customer_topic_id=20, owner_user_id=12, owner_chat_id=-100, owner_topic_id=22, consent_notice_version="privacy-v1", consent_granted=True, customer_enabled=False, ) service = onboarding_domain.NutritionOnboardingService( profile_root=tmp_path, customer_key="client_001", enforce_current_authority=False, enforce_reconciliation=True, ) evidence = onboarding_domain.MessageEvidence( actor_user_id=10, chat_id=-100, topic_id=20, message_id=1, update_id=101, ) service.start_or_resume(authority=authority, evidence=evidence) status = None for index, field in enumerate(onboarding_domain.QUESTION_FIELDS): value = onboarding_domain.example_answer(field) if field == "activity_category": value = ( "활동 수준: 보통. 주 3회, 회당 60분 정도의 중간 강도 " "근력운동을 희망합니다. 평소 걷기·이동은 하루 약 " "6,000~8,000보 수준입니다." ) status = service.submit_answer( field=field, value=value, authority=authority, evidence=onboarding_domain.MessageEvidence( actor_user_id=10, chat_id=-100, topic_id=20, message_id=index + 2, update_id=index + 102, ), ) assert status is not None service.record_reconciliation( answers_digest=canonical_digest( service.reconciliation_answers(authority=authority) ), advisory={"summary_ko": "수정 전 요약"}, clarifications=[], authority=authority, ) runtime = object.__new__(TelegramNutritionOnboardingRuntime) runtime.domain = onboarding_domain rewound = runtime._rewind_collection( service=service, authority=authority, evidence=onboarding_domain.MessageEvidence( actor_user_id=10, chat_id=-100, topic_id=20, message_id=30, update_id=130, ), target_cursor=21, ) assert rewound.next_field == "schedule_constraints" completed = service.submit_answer( field="schedule_constraints", value="없음", authority=authority, evidence=onboarding_domain.MessageEvidence( actor_user_id=10, chat_id=-100, topic_id=20, message_id=31, update_id=131, ), ) assert completed.state.value == "customer_attestation" answers = service.reconciliation_answers(authority=authority) summary = render_authoritative_customer_summary(answers) service.record_reconciliation( answers_digest=canonical_digest(answers), advisory={"summary_ko": summary}, clarifications=[], authority=authority, ) > attested = service.attest_baseline( authority=authority, evidence=onboarding_domain.MessageEvidence( actor_user_id=10, chat_id=-100, topic_id=20, message_id=32, update_id=132, ), ) tests/gateway/test_telegram_nutrition_onboarding.py:2213: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ../../../.hermes/profiles/dualcoachtest/workspace/checkin_cli/checkin_cli/nutrition_onboarding.py:219: in attest_baseline baseline = build_onboarding_baseline(answers, as_of=date.today()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ raw_answers = {'activity_category': '활동 수준: 보통. 주 3회, 회당 60분 정도의 중간 강도 근력운동을 희망합니다. 평소 걷기·이동은 하루 약 6,000~8,000보 수준입니다.', 'activity_rationale': '주 3회 근력 운동', 'allergies': {'items': [], 'status': 'none'}, 'budget_band': '보통', ...} def build_onboarding_baseline( raw_answers: dict[str, object], *, as_of: date, ) -> NutritionOnboardingBaseline: import hashlib import json payload = dict(raw_answers) raw_dob = payload.pop("date_of_birth", None) if not isinstance(raw_dob, str): raise ValueError("date_of_birth is required") date_of_birth = date.fromisoformat(raw_dob) payload["adult_age"] = derive_adult_age(date_of_birth, as_of=as_of) payload["reference_date"] = as_of payload["source_value_digest"] = hashlib.sha256( json.dumps(raw_answers, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode() ).hexdigest() > return NutritionOnboardingBaseline.model_validate(payload) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E pydantic_core._pydantic_core.ValidationError: 1 validation error for NutritionOnboardingBaseline E activity_category E Input should be 'sedentary', 'light', 'moderate', 'very_active' or 'extra_active' [type=enum, input_value='활동 수준: 보통. ...000보 수준입니다.', input_type=str] E For further information visit https://errors.pydantic.dev/2.13/v/enum ../../../.hermes/profiles/dualcoachtest/workspace/checkin_cli/checkin_cli/nutrition_onboarding_models.py:216: ValidationError =========================== short test summary info ============================ FAILED tests/gateway/test_telegram_nutrition_onboarding.py::test_schedule_rewind_recovers_exact_legacy_activity_shape FAILED tests/gateway/test_telegram_nutrition_onboarding.py::test_recovered_answers_resubmit_to_valid_baseline_and_summary 2 failed in 0.40s