I read this as a hands-on, isolated simulation request - I’ll identify the existing onboarding and daily-check-in test/domain surfaces, run both with realistic and adversarial Korean interactions in a disposable no-network environment, and report transcript-level evidence without editing files or contacting live services.


The usable simulation surfaces are local domain/bridge tests rather than a live transport. I found both flows and will now exercise them against temporary profile/state roots, with socket access disabled at process level and no Telegram adapter send path involved.


I have enough context to run the customer journeys. The simulation will use only `TemporaryDirectory`, fake consent/route evidence, the onboarding domain plus its navigation parser, and the standalone daily wizard/bridge; an audit hook will fail the process on any socket operation.


The first disposable attempt proved an authority precondition before any flow state was written: `customer_enabled=True` is rejected with `ValueError: onboarding target must remain disabled`. Post-consent onboarding therefore requires consent granted while activation is still disabled; I’ll rerun with that canonical state.


The second attempt exposed a second exact setup requirement before state creation: the onboarding store will not create the profile root itself (`onboarding profile root cannot be opened safely`). I’ll pre-create only the disposable profile directory, as production provisioning would, and continue.


Onboarding completed locally through customer attestation (`owner_review`, baseline persisted). The daily flow then hit only a harness-construction mismatch: `PhysiqueCheckinConfig` has no `enabled` constructor field; enablement is handled by its config loader. I’ll rerun the daily domain/bridge with the exact six-field config contract.


The daily simulation reached 10/12, but my harness looked for “나중에 계속” in the flattened `buttons` field. Navigation is rendered only in `button_rows`; the customer UI itself has the control, but consumers must traverse rows. I’ll rerun using the rendered row structure and finish/save.


I read this as a completed isolated customer QA run - I’ll report both flow outcomes, exact friction, and transcript evidence.

## Outcome

Both customer-facing flows completed:

- **Post-consent onboarding:** `collecting -> customer_attestation -> owner_review`
- **nutrition_daily:** finalized as one `nutrition_checkin` event
- Live profile touched: **no**
- Telegram messages sent: **0**
- Network socket events: **0**
- Repository files edited: **none**
- All state was under disposable `TemporaryDirectory` roots, deleted afterward.

## Transcript-like run

### 1. Nutrition onboarding

1. Started with consent granted and activation disabled:
   - `state=collecting`
   - `next=date_of_birth`
2. Entered `1994년 2월 18일` -> canonicalized to `1994-02-18`.
3. Entered malformed closed choice `남자 같아요`.
   - **Unexpectedly accepted** as raw text.
   - Cursor advanced from 1 to 2.
4. Used **Back**.
   - Cursor returned to `equation_sex_basis`.
   - Corrected with `남성` -> `male`.
5. Entered realistic Korean profile:
   - `172cm`, `68.4kg`
   - 보통 activity
   - 주 4회 웨이트 및 걷기
   - 감량 목표, `64kg`, `2026-12-15`
   - 갑각류 알레르기, 우유 불내증
   - 식품 선호·기피, 조리 환경, 예산 등
6. Used **Defer** at 6/22.
7. Reconstructed the service and resumed:
   - Same cursor: 6/22
   - Next field remained `goal_type`.
8. Entered malformed meal count `세 번쯤`.
   - Rejected with parser evidence:
     `ValueError: invalid literal for int() with base 10: '세 번쯤'`
   - Corrected to `하루 세 끼` -> `3`.
9. Used **Skip** for optional `schedule_constraints`.
   - Stored transport default `""`.
   - Reached `customer_attestation`.
10. Deterministic validation:
    - Issues: `[]`
    - Holds: `[]`
11. Used **Revise** from attestation.
    - Returned to `schedule_constraints`.
    - Entered `평일 점심은 회사 식당, 저녁은 20시 이후 가능`.
12. Final customer attestation:
    - `state=owner_review`
    - Baseline artifact existed in disposable storage.

### 2. nutrition_daily

1. Opened local wizard:
   - `오늘 체크인 · 약 2~3분`
   - Progress `1/12`
2. Entered malformed weight `육십팔점사`.
   - Rejected; stayed on `bodyweight`.
   - Notice: `입력을 확인하고 다시 시도해 주세요.`
3. Corrected to `68.4`.
4. Entered `2180` kcal.
5. Entered malformed macros:
   - `탄수 255 단백질 145 지방 62`
   - Rejected; stayed on `macros`.
6. Corrected to `255 145 62`.
7. Entered realistic meals, `2.3L` water.
8. Used **Back** from sleep to water.
   - Corrected water to `2.5L`.
9. Entered:
   - Sleep `6.8`, quality `4/5`
   - Digestion `normal`
   - Condition `4/5`
10. Used **Defer** at `appetite_stress`.
    - Active binding cleared.
    - Notice: `나중에 여기서 이어갈 수 있도록 임시 저장했습니다.`
11. Reopened from a new bridge/service instance.
    - Resumed exactly at progress `10/12`, `appetite_stress`.
12. Entered:
    - `식욕 3, 스트레스 2`
    - `퇴근 후 상체 웨이트 55분, 중간 강도`
13. Used **Skip** for optional note.
14. Opened **수정 -> 탄단지**.
    - Changed macros from `255 145 62` to `250 148 61`.
15. Final save:
    - Notice: `체크인을 저장했습니다.`
    - Confirmation: `✅ 오늘 체크인을 저장했습니다.`
    - Event count: `1`
    - Event type: `nutrition_checkin`
    - Saved facts:
      - Weight `68.4kg`
      - Calories `2180kcal`
      - Carbohydrate `250g`
      - Protein `148g`
      - Fat `61g`
      - Water `2.5L`
      - Sleep `6.8h`, quality `4/5`
      - Condition `4/5`

## Exact blockers and friction

1. **Post-consent authority is counterintuitive**
   - `customer_enabled=True` fails immediately:
     `ValueError: onboarding target must remain disabled`
   - Consent must be granted while customer activation remains disabled.

2. **Disposable profile root must already exist**
   - Missing root fails with:
     `ValueError: onboarding profile root cannot be opened safely`
   - The service creates onboarding descendants but not the profile root.

3. **Malformed closed-choice onboarding answers advance immediately**
   - `남자 같아요` was accepted for `equation_sex_basis`.
   - Invalid closed choices are not rejected at `submit_answer`; correction may be delayed until reconciliation unless the customer notices and uses Back.

4. **Meal-count rejection is generic at the customer surface**
   - The parser has a precise Python error, but runtime copy collapses failures to:
     `입력 형식을 확인해 주세요. 현재 질문에 다시 답해 주세요.`

5. **Navigation is present only in `button_rows`**
   - `나중에 계속` was not in flattened `prompt.buttons`.
   - Consumers inspecting only `buttons` will miss Back/Skip/Defer navigation.

6. **Daily invalid-field copy is overly generic**
   - Invalid macros produced:
     `현재 항목은(는) 숫자로 보내주세요.`
   - It does not restate the required three-number order, despite the normal macro prompt doing so.

7. **Onboarding completion is intentionally not activation**
   - Customer completion stops at `owner_review`.
   - Owner review/finalization is a separate non-customer action and was not simulated.


I read this as regression verification against the modified worktree - I’ll rerun both flows in disposable storage with socket operations blocked, exercise each named UX behavior through the current parser/bridge surfaces, and return exact PASS or blocker evidence without editing files.


The modified code now has explicit UX regression coverage and changed customer copy. I’ll verify both the focused test suite and an independent end-to-end disposable transcript, including persisted event values rather than relying only on prompt assertions.


The first independent rerun stopped before simulation because Python’s `asyncio` creates an internal local `socketpair`; the blanket socket audit correctly blocked that too. This is a harness-only blocker, not product behavior. I’ll allow local event-loop plumbing while rejecting DNS and outbound `socket.connect`, which preserves the no-network guarantee.


I read this as completed regression verification - both disposable flows now pass all requested checks with no product blockers.

## Result: PASS

Focused suite:

```text
tests/gateway/test_customer_nutrition_ux.py
18 passed in 0.39s
```

## Evidence

### Post-consent onboarding

- **Malformed closed choice rejected immediately — PASS**
  - Input: `남자 같아요`
  - Error: `invalid closed choice`
  - Cursor remained at `equation_sex_basis`, count stayed `1`.
  - Recovery: `답을 이해하지 못했어요. 입력한 내용은 저장하지 않았습니다.`

- **Inline Back/Skip/Defer rendered — PASS**
  - At optional `activity_rationale`, rendered actions were exactly:
    ```text
    이전 / 건너뛰기 / 나중에 계속
    ```
  - `force_reply=false`, so controls are directly usable.
  - Back returned from count 5 to count 4.
  - Skip stored the optional default and advanced to count 6.
  - Defer/resume reconstructed the service at the same cursor: `6/22`, `goal_type`.

- **Natural Korean shorthand — PASS**
  - `1990. 3. 2.` -> `1990-03-02`
  - `남자` -> `male`
  - `3` activity -> `moderate`
  - `살 빼기` -> `loss`
  - `없어요` -> structured none
  - `2` pregnancy answer -> `False`
  - `보통 하루 세끼 먹어요` -> `3`

- **Completion — PASS**
  - Validation issues: `0`
  - Safety holds: `0`
  - Final customer state: `owner_review`
  - Disposable baseline created successfully.

### nutrition_daily

- **Inline navigation rendered — PASS**
  - First question: `나중에 계속`
  - Subsequent question: `이전 / 나중에 계속`
  - Optional-note skip is rendered as the customer-facing `없음` one-tap button.

- **Invalid macros field-specific recovery — PASS**
  - Input: `대충 먹었어요`
  - Accepted: `false`
  - Remained at `macros`
  - Exact recovery:
    ```text
    입력한 내용은 저장하지 않았습니다.

    탄수화물·단백질·지방을 순서대로 입력해 주세요.
    예: 280 150 65
    ```

- **Defer/resume — PASS**
  - Notice: `나중에 여기서 이어갈 수 있도록 임시 저장했습니다.`
  - New bridge/service resumed at `water`, progress `5/12`.

- **Normal digestion mapping — PASS**
  - Button: `정상 · 매끈하고 부드러움 (4)`
  - Stored value: `normal`
  - Final event: `"digestion_summary": "normal"`

- **No-workout one-tap — PASS**
  - Buttons: `운동 안 함 / 운동 내용 입력`
  - `운동 안 함` advanced directly to `optional_note`.
  - Summary displayed `운동: -`.
  - Final event stored `"training_summary": ""`.

- **Edit/save — PASS**
  - Edited macros from `255 145 62` to `250 148 61`.
  - Returned to summary and saved successfully.
  - Exactly one event persisted:
    - `carbohydrate_g: 250`
    - `protein_g: 148`
    - `fat_g: 61`
  - Confirmation: `✅ 오늘 체크인을 저장했습니다.`

## Isolation

- Live profile touched: **false**
- Telegram messages sent: **0**
- Outbound DNS/connect events: **0**
- All simulation artifacts stayed under a temporary directory and were removed.
- Source files edited: **none**

One harness-only issue occurred initially: blocking every socket prevented `asyncio` from creating its local Unix `socketpair`. The rerun allowed local event-loop plumbing while still rejecting DNS and outbound connections. No product blocker remains.