## Summary
검토 대상은 `stage-04-revision.md` (sha256 `433ec13cb3d3acff244abf2ea38da70c11db8acfd7d15310826f0c896b94d9b6`, stage_n 4)이며 index의 동일 경로·SHA와 일치한다. 원자 승인 명령, 단일 Telegram 메시지, capability manifest 및 derived queue 계약은 이전의 내구성·중복전송 BLOCK을 실질적으로 닫았다. 그러나 loopback HTTP에서 불가능한 `__Host-` cookie와 전역 dashboard 중지 명령이 console/lifecycle 계약을 깨므로 현재는 BLOCK / REQUEST CHANGES다.

## Claims
- 단일 `ApprovalCommand`와 customer-scoped `flock`, fsync+rename commit, gateway-only claim/send, ambiguous reconciliation은 web/owner-Telegram 경쟁을 같은 linearization point로 수렴시킨다 (`stage-04-revision.md:5-14`).
- 4096 UTF-16 rendered-length domain revalidation과 generic chunk helper 배제는 승인 1건과 customer Telegram send 1건의 경계를 명시한다 (`stage-04-revision.md:16-20`).
- Manifest-first incompatible-write gate와 stored-event reader requirement 검사는 mixed-version activation/route/schedule/outbound를 fail closed로 만든다 (`stage-04-revision.md:22-28`).
- 실제 Hermes loopback dashboard는 HTTP `127.0.0.1` bind이며 session token을 SPA에 주입한다 (`hermes_cli/web_server.py:217-218, 295-324, 12782-12869`).
- 현 cookie implementation도 loopback HTTP에는 `__Host-`/`__Secure-` prefix가 Secure를 요구하여 사용할 수 없다고 명시한다 (`hermes_cli/dashboard_auth/cookies.py:20-43`).

## Analysis
### Stage 1 — Spec compliance
Revision 4는 기존 draft-only owner Telegram path를 공통 command transaction으로 교체하고, queue를 committed command projection으로 만들어 approval/queue 사이 crash window를 제거했다. retry/resend은 별도 immutable attempt와 explicit authority만 허용하고, `call_started` 이후에는 ambiguous로 멈추므로 Telegram의 외부 exactly-once를 과장하지 않는다. 고객 단일-message requirement도 editor와 domain service 양쪽에서 강제한다.

Capability manifest는 writer ownership, atomic upgrade, event-required reader version, rollback tests를 포함하므로 profile/gateway/dashboard skew를 출시 전 gate할 수 있다. Isolated profile service와 adapter 또한 unified dashboard profile ambiguity를 피하려는 방향으로는 적절하다.

그러나 bootstrap은 service가 HTTP loopback이라는 명시된 topology와 browser-enforced `__Host-` cookie semantics가 양립하지 않는다. 이 상태에서는 launch bearer를 cookie/CSRF console session으로 downgrade하는 주 계약이 동작하지 않는다. 또 lifecycle의 generic `hermes dashboard --stop`은 모든 dashboard process를 죽여 isolated service라는 계약과 rollback scope를 위반한다.

### Stage 2 — Architecture
원자 log/derived queue 선택의 강한 반대 논지는 full-file copy-on-write가 append보다 비싸고 attempt state/claim recovery가 더 복잡하다는 점이다. 단일 customer와 correctness-first 목표에서는 fsync+rename snapshot과 one command linearization point가 그 비용을 정당화한다. 이 선택은 independent queue drift, dashboard direct send, automatic ambiguous resend보다 더 안전하다.

Console에는 launch bearer 자체가 loopback owner capability인 것이 명확히 한정되어 있어 OAuth identity를 거짓으로 주장하지 않는다. 다만 bearer bootstrap 후의 narrower session must be browser-operable. HTTP loopback을 유지하는 경우 bare cookie가 필요하며, TLS를 선택하는 경우 service/tunnel/certificate trust lifecycle까지 명세해야 한다. 전자는 existing repository cookie policy와 일치하고 새 surface가 작으므로 적절하다.

### Stage 3 — Constructive synthesis
1. HTTP loopback service에는 prefix 없는 cookie 이름, `HttpOnly`, `SameSite=Strict`, `Path=/`, no `Domain`, server-memory signature/rotation을 사용한다. `__Host-` hardening은 real HTTPS direct-root deployment가 생길 때만 선택한다.
2. Service lifecycle은 `systemctl --user restart physique-coach-dashboard.service`로만 소유한다. 9120 collision은 unrelated dashboard-wide stop 대신 process ownership/port conflict를 report하고 operator-confirmed, narrowly scoped recovery로 처리한다.
3. Frontend verification sentinel을 actual `hermes_cli/web_dist/index.html` and Vite manifest로 바꾸고 `--skip-build` startup contract과 일치시킨다.
4. `e2e` marker를 strict-marker registry에 등록하고 real Telegram test credential preflight/default exclusion을 명시한다. Normal full suite must not touch Telegram; explicit E2E command must only target test credentials.

### Stage 4 — Security, quality, performance
`web/vite.config.ts:85-88` writes `../hermes_cli/web_dist`, and `cmd_dashboard` checks that same destination under `--skip-build` (`hermes_cli/main.py:10981-10999`), so the plan's `web/dist` artifact is not its runtime artifact. Also `pyproject.toml:348-355` registers no `e2e` marker despite strict markers, so the exact E2E ledger cannot currently collect safely as written.

## Root Cause
The revision correctly made sensitive domain state explicit but carried two generic dashboard assumptions into a profile-isolated HTTP service: HTTPS-only cookie-prefix semantics and a process-wide dashboard stop command. These are lifecycle/boundary mismatches, not recoverable runtime fallbacks.

## Findings
1. **HIGH — `stage-04-revision.md:33-34` — `__Host-physique-coach` cannot operate on the specified HTTP loopback origin.** `__Host-` requires Secure, while `127.0.0.1:9120` is HTTP; browser bootstrap cannot persist/send the console cookie. Use an HTTP-compatible bare cookie with explicit attributes or specify a full TLS topology; test persistence/replay in a real browser. [reported P1]
2. **HIGH — `stage-04-revision.md:47` — `hermes dashboard --stop` is not isolated.** Existing `cmd_dashboard` finds/kills all dashboards (`hermes_cli/main.py:10848-10867`), contrary to the unit-only lifecycle guarantee. Restrict operations to `physique-coach-dashboard.service`; make port recovery narrow and explicit. [reported P1]
3. **MEDIUM — `stage-04-revision.md:48` — stated web build artifact conflicts with `--skip-build`.** Vite output and launcher sentinel are `hermes_cli/web_dist`, not `web/dist`. Correct the artifact/check or set one validated `HERMES_WEB_DIST`. [reported P2]
4. **MEDIUM — `stage-04-revision.md:80` — E2E marker/credential isolation is absent.** Strict markers currently register no `e2e`; registering the test without config fails collection, while leaving it unmarked makes `-m e2e` select nothing. Register it and require dedicated-credential preflight/default exclusion. [reported P2]

## Recommendations
1. Resolve the HTTP-cookie contradiction before implementation; require a browser-level bootstrap/persist/replay assertion.
2. Remove `hermes dashboard --stop` from this plan and use unit-scoped systemd lifecycle only.
3. Correct the frontend artifact ledger to `hermes_cli/web_dist` and validate the exact `--skip-build` sentinel before restart.
4. Add pyproject marker policy and explicit real-E2E credential gate.
5. Retain the atomic command, derived queue, one-message, capability-manifest, capability-first adapter and real-process concurrency contracts unchanged.

## Architectural Status
BLOCK

## Code Review Recommendation
REQUEST CHANGES

## Tradeoffs
| Option | Benefit | Cost / constraint |
|---|---|---|
| Bare HTTP-only loopback console cookie | Works over existing SSH-tunnel topology; matches repository policy | Loses `__Host-` prefix; require exact Host/Origin and no Domain/Path widening |
| TLS-terminated console with `__Host-` cookie | Strong browser prefix guarantee | Requires certificate, termination, tunnel URL and operational trust lifecycle |
| Unit-scoped systemd lifecycle | Preserves isolated dashboard boundary | Must explicitly handle port conflict rather than kill every dashboard |
| Generic `hermes dashboard --stop` | Clears a possible stale dashboard | Terminates unrelated dashboards; unacceptable for this plan |
