# DualCoach Task 10 Evidence

## Verdict

PASS — the actual Hermes auxiliary-provider credential source is checked at gateway
startup, before customer activation, and immediately before generation claim. Failure
is actionable and secret-safe; fake reauthentication resumes the existing job.

## Reused behavior and exact gap

Reused:

- Hermes auxiliary client and credential-pool resolution;
- Task 9 retryable `generation_failed` state and stable job/request identity;
- existing startup, activation, and worker boundaries.

Confirmed gap:

- startup and activation did not gate on the credential source used by the auxiliary
  provider;
- pre-claim readiness was not consistently checked before lease acquisition;
- an auth-preflight error remained latched after successful in-process reauthentication.

Rejected extras:

- a global authentication framework;
- real OAuth/browser automation;
- Task 11 card UX;
- customer-facing features, speculative abstractions, future scaffolding, broad
  refactors, credential fallbacks, and manual job deletion.

## Credential boundary

The preflight resolves the actual auxiliary provider through `resolve_provider_client()`
and Hermes configuration/auth state (`providers.openai-codex.tokens` and the
`credential_pool.openai-codex` boundary). `~/.codex/auth.json` is not accepted as a
substitute for normal auxiliary-provider credentials.

No real credential value was printed, copied, retained, or placed in evidence.

## Implementation and failing-first evidence

The minimal Task 10 delta:

- gates gateway startup before Telegram setup;
- gates customer activation before mutation;
- gates generation immediately before lease claim;
- persists retryable `generation_failed` without claiming on auth failure;
- retains the same request/job identity after reauthentication;
- emits an actionable, redacted `hermes auth` recovery status.

Independent reviewer `st_019fe252` found a MEDIUM defect: successful reauthentication
did not clear the adapter's auth-preflight-owned error, so the same process remained
blocked. A same-instance regression proved the failure.

The repair clears `_nutrition_coaching_error` only when it exactly equals the private
auth-preflight marker. Unrelated initialization/configuration errors remain latched.

## Acceptance and manual evidence

Independent manual QA `st_019fe251`: CONFIRMED.

- valid auxiliary credential passes;
- missing, malformed, expired, and invalidated credentials fail before mutation/claim;
- Codex-only credential does not substitute;
- operator sees safe actionable reauthentication status;
- same adapter recovers after fake reauthentication without restart/manual reset;
- unrelated nutrition initialization error remains blocking;
- pre-claim failure records `generation_failed`;
- retry uses the same request and job identity and reaches attempt 2;
- concurrent/restart path has one winner;
- provider, Telegram, network, and customer-delivery counts: 0;
- secret sentinel appears in neither logs nor temporary files.

## Automated and adversarial verification

- Focused final Task 10 suite: 216 passed.
- Auxiliary-client domain: 223 passed.
- Credential-pool focused tests: 6 passed.
- Bootstrap/cutover focused matrices: 83 and 161 passed.
- Same-instance stale-readiness regression: PASS.
- Ruff: PASS.
- `py_compile` and `compileall`: PASS.
- `git diff --check` and whitespace checks: PASS.
- Exact changed-symbol type audit: 0 findings.
- Secret/token scan: no Task 10 leakage.
- No Task 11 behavior expansion.

Final reviewer `st_019fe252`: CONFIRMED. The preflight-owned marker clears on success,
unrelated errors remain, and startup/activation/pre-claim/job-identity invariants hold.

## Candidate identity

- 67-path candidate digest:
  `215aafe7af1f2056bb137c1ecc2d3dc728bb0f36bb9e1933f2c32f943b1823cd`
- JSON manifest SHA-256:
  `9b5bebeb4b92953b471cd3add0132e869380847b07c232a0900bf8c3a2248f57`
- Markdown manifest SHA-256:
  `6277b140226ee5cadab61c4fb0168d0d2939e2fcbde5d202ad213d936f1b9581`
- `gateway/platforms/nutrition_coaching.py`:
  `3f84d22721eadf9a1114d2df1dfc7af643533aff97e8ba9252135cdc87e03611`
- `gateway/platforms/telegram.py`:
  `9a715dc106169d4fe16e79f7287ca66e07901c59b157e7adf99caf797f43b0dc`
- `gateway/platforms/telegram_room_bootstrap_cutover.py`:
  `ba046344951736259812bbd8147b71dd1b5eeb0b1577b1a805ed761775748d9b`
- `tests/gateway/test_nutrition_coaching.py`:
  `acad223bdf7fd3676a2dda6803ed64b2d897a99d66188b1397d4dbfa46557d59`
- `tests/gateway/test_telegram_room_bootstrap_cutover.py`:
  `e6c72b4fa9771788be396e6cb1ed6012f6bd95a75be741bec665df5d94fcb67e`

JSON, Markdown header, Markdown verification digest, and independently recomputed raw
bytes agree. An earlier mismatch was caused by a verifier hashing newline-joined
`path + file_sha256` text instead of the recorded path-NUL-raw-bytes-NUL algorithm.

## Cleanup and non-touch

- Fake credential stores and providers only.
- No real OAuth, browser, network, provider, Telegram, activation, customer action, or
  delivery.
- Isolated temporary homes and type-audit output were removed.
- No commit, push, reset, stash, or clean.
- Unrelated dirty-worktree changes were preserved.

