# Task 1 evidence — profile-local wizard domain

## Scope

- Implemented only within the isolated physique profile's local check-in domain and its event contract.
- No Telegram service, gateway, default Hermes configuration, legacy bridge, token, or delivery target was changed.

## TDD evidence

1. Characterization baseline, before feature code: `21 passed` via `./.venv/bin/pytest -q`.
2. Red: added `tests/test_wizard_domain.py`; `pytest -q tests/test_wizard_domain.py` failed because `checkin_cli.wizard` did not exist (`ModuleNotFoundError`).
3. Green: implemented persistent owner/topic-bound sessions, version-checked transitions, final-only event append, safety acknowledgement audit, and separate workout finalization.
4. Regression: `./.venv/bin/pytest -q` → `44 passed in 0.49s`.

## Verifier follow-up hardening

Independent verification found three domain-boundary defects. Red tests first reproduced each:

- a completed owner/topic/KST-day morning could incorrectly start a second canonical session;
- calendar-invalid days were accepted or could reach Pydantic as an uncaught exception;
- oversized pain, training-plan, training-summary, and note text could bypass the answer boundary.

The repaired behavior is now covered by the 21-test wizard suite:

- regular same-day start returns the completed record in `completed_review` state; concurrent starts share one draft under the profile lock;
- only `start_morning_correction` can open a same-day replacement, and its final event uses `event_type=correction` plus `supersedes=<original event id>`;
- invalid calendar days and bounded-text violations return `invalid` without draft/event mutation;
- restart and correction remain exact-owner/exact-topic-bound.

Repeated explicit corrections are additionally pinned by regression: a second same-day correction follows the latest finalized correction event, producing one `original → correction → correction` `supersedes` chain and exactly one eligible current check-in.

## Acceptance coverage

- Same KST day start resumes the same opaque 128-bit (32 hex char) session at the stored next step.
- Foreign owner, foreign topic, stale/replayed actions, invalid bodyweight/calories, and duplicate callbacks are rejected with no final event.
- A compact morning draft emits no event until the explicit summary `save`; its final event requires bodyweight, sleep duration/quality, condition, pain, calories, and training plan.
- Urgent symptom transitions immediately to the safety stop. Only `acknowledge` appends a non-trend `safety_audit` event.
- A post-workout final event requires only completion, training summary, quality, and pain; it carries no bodyweight/calories and does not enter trends.
- Versioned schema validation for final morning and workout events passes.
- Existing correction/supersedes behavior remains covered by the pre-existing regression suite.

## Manual profile-local CLI seam

Executed against a disposable temporary local home, with no network or personal values printed:

```json
{"started":"advanced","opaque_session_id_length":32,"next_step":"sleep_duration","event_exists_before_save":false}
```

## Cleanup and quality

- Temporary manual-test home removed.
- All created/modified Python modules are below 250 pure LOC: `wizard.py` 180, `wizard_models.py` 43, `wizard_storage.py` 111.
- `compileall` passed. Ruff and basedpyright executables are not installed in the existing profile-local venv; no replacement package was installed.
