I read this as an investigation task - find whether a fail-closed authentication probe exists for the `openai-codex` provider resolving to `CodexAuxiliaryClient`. Let me start with parallel exploration.

<analysis>
**Literal Request**: Find a supported fail-closed auth probe for the `openai-codex` provider whose resolution returns `CodexAuxiliaryClient`.
**Actual Need**: Identify, with exact code refs and runnable command shapes, whether any genuinely read-only/authenticated endpoint or status interface exists that can validate production credentials without persisting content, delivering messages, or mutating state - and recommend one implementation path plus test/receipt fields.
**Success Looks Like**: A definitive determination (a-d) with exact file/line references, client method signatures, config/credential resolution, and a concrete runnable probe command plus fail-closed semantics comparison.
</analysis>

Let me launch parallel exploration.


The codebase is large. Let me narrow to the specific symbols in the task: `CodexAuxiliaryClient`, `openai-codex` provider, Task26 provider-auth receipt, and the active plan.


This gives me strong context. The snapshots under `.omo/evidence/task26/...` mirror the real `/home/cube/projects/richard/hermes-agent` source. Let me examine the actual hermes-agent source and the Task26 provider-auth candidate artifacts


Let me examine the actual hermes-agent source: the provider resolver and CodexAuxiliaryClient, and the provider-auth test/controller that produced the "no models.list probe" finding


The key is `resolve_provider_client` in `agent/auxiliary_client.py:3934`, `get_codex_auth_status` in `hermes_cli/auth.py`, and `test_dualcoach_admin_provider_auth.py`. Let me read the provider resolution code, the codex auth status function, and the provider-auth test


Now I understand the provider-auth machinery. The critical question: when `_resolve_provider_client` returns a `CodexAuxiliaryClient` for `openai-codex`, does `.models.list()` work? The test uses a fake `_Client` with `.models.list`. But `CodexAuxiliaryClient` is a wrapper. Let me examine:
1. `dualcoach_admin.provider_auth_check` - what probe it runs on the resolved client.
2. `CodexAuxiliaryClient` class - whether it exposes `.models`.
3. `get_codex_auth_status` - the OAuth status interface.

Let me read these.Let me examine the dualcoach_admin provider-auth implementation, the CodexAuxiliaryClient class definition, and the codex auth status function


Now let me read the `dualcoach_admin.py` provider_auth implementation to see exactly what probe it runs, how `_resolve_provider_client` is wired, and the error handling.


Let me read the provider_auth_check, _resolve_provider_client, and _probe functions fully


Let me check the top constants in `dualcoach_admin.py`, the Codex base URL/token reading, `_MODEL_LIST_UNSUPPORTED_PROVIDERS`, and confirm the frozen receipt outcome


The bash broker is restricted to `gh`/`curl`. Let me read the frozen gate receipt for the candidate and the Codex client build/read token functions.


Now let me check the top-level gate-receipt-v1.json and what artifacts exist for the candidates, to confirm the actual frozen run outcome


Let me look at the fd937a candidate and its artifacts, plus the profile-baseline and the actual run receipt if any. Let me check the fd937a candidate directory.


Let me check the fd937a checkpoint/manifest to understand why there are two candidates and which was the final run. Let me read its checkpoint and check for a run receipt in the task26 logs. Let me also read the fd937a artifacts gate-receipt to see if it differs


I have the core evidence. Let me verify the CLI auth-status command shape and how `openai-codex: logged in` is produced, to pin the runnable (b) command.


Let me confirm the runnable CLI command shapes — `auth_status_command` and `doctor` codex check.


I have all the evidence needed. Here is the determination.

<results>
<files>
- /home/cube/projects/richard/hermes-agent/gateway/platforms/dualcoach_admin.py  — provider-auth gate (`provider_auth_check` l.396, `_probe` l.306, `_models_list` l.291, `_MODEL_LIST_UNSUPPORTED_PROVIDERS` l.42, exit table l.65–93)
- /home/cube/projects/richard/hermes-agent/agent/auxiliary_client.py — `resolve_provider_client` l.3934; `CodexAuxiliaryClient.__init__` l.1421; `_CODEX_AUX_BASE_URL` l.502 = `https://chatgpt.com/backend-api/codex`; `_build_codex_client` l.2471; `_read_codex_access_token` l.1869
- /home/cube/projects/richard/hermes-agent/hermes_cli/auth.py — `get_codex_auth_status` l.5977; `get_auth_status` l.6145 (routes `openai-codex` → codex)
- /home/cube/projects/richard/hermes-agent/hermes_cli/auth_commands.py — `auth_status_command` l.509 (prints `<provider>: logged in`)
- /home/cube/projects/richard/hermes-agent/hermes_cli/doctor.py — codex auth row l.1090 (reads `get_codex_auth_status`)
- /home/cube/projects/richard/traning coach/.omo/evidence/task26/dualcoach-provider-auth-candidate-ca49f7561f22b870cc70aa135d15eef66129e3a39ffa3c4be284f0484a345706/ — sealed candidate (gate-receipt PASS on test gates; checkpoint SEALED)
- /home/cube/projects/richard/traning coach/.omo/senpi-task/logs/st_01a00008.jsonl — line 226 records the frozen outcome: `probe_unknown` / exit 29 for the installed command
</files>

<answer>
## Honest determination: (d) is the accurate server-side verdict; (b) exists as the only read-only supported auth surface, and it is local, not server-validating.

### (a) A genuinely read-only authenticated endpoint supported by `CodexAuxiliaryClient`? — No.
`CodexAuxiliaryClient.__init__` (`agent/auxiliary_client.py:1421`) exposes only `self.chat`, `self.api_key`, `self.base_url`, `close()`, and the private `self._real_client`. The only callable it wraps is `chat.completions.create` (the `_CodexCompletionsAdapter` translating to the Responses API) — that is generation/delivery, not read-only. It does not expose `.models` directly. The gate's `_models_list` (`dualcoach_admin.py:291`) falls back to `client._real_client.models.list`, which is the underlying OpenAI instance pointed at `_CODEX_AUX_BASE_URL = https://chatgpt.com/backend-api/codex` (l.502). That backend has no stable, documented `/models` contract. Calling it does not return a list-shaped success, so `_probe` fails closed to `PROBE_UNKNOWN` (29) — exactly what the frozen installed command produced (recorded in `st_01a00008.jsonl:226`). It cannot be relied on as a read-only auth success endpoint.

### (b) An OAuth/session/token status interface tied to the exact production credentials? — Yes, but local only.
- `get_codex_auth_status()` (`hermes_cli/auth.py:5977`) reads the credential pool (`agent.credential_pool.load_pool("openai-codex")`) then the legacy provider state, returning `logged_in`, `auth_store`, `last_refresh`, `source`, and `api_key`. It decodes the JWT only for expiry (`_codex_access_token_is_expiring(..., 0)`), performing **no network call**.
- Runnable, read-only, ties to the exact production store:
  - `hermes auth status openai-codex` (`auth_status_command`, `auth_commands.py:509`) → prints `openai-codex: logged in` or `openai-codex: logged out (<reason>)`.
  - `hermes doctor` → row `OpenAI Codex auth: (logged in)` via `get_codex_auth_status` (`doctor.py:1090`).
- **Semantics:** this proves the token exists locally, has a decodable shape, and is not past its JWT `exp`. It does **not** prove the token is valid against production — a revoked, server-side-invalidated, or rate-limited token still reports `logged_in: True`. Fail-closed value: a `False`/absent token is a reliable credential-missing signal.

### (c) A minimal production-path request that is an authenticated synthetic probe without persisting content or delivery? — No.
The only request `CodexAuxiliaryClient` can actually make is `chat.completions.create` → Responses generation, which bills usage and can persist/deliver. The `models.list` probe is the intended read-only alternative but is unsupported on the codex base URL. There is no server-present, read-only, non-generating call supported by this client.

### (d) No supported probe? — Effectively yes for the server-present path.
For `openai-codex` → `CodexAuxiliaryClient`, the honest, fail-closed reading is: there is no genuinely read-only **server-validating** endpoint. The existing `models.list` probe correctly fails closed (`probe_unknown`/29). The only supported read-only gap that closes is the **local** token-status interface in (b).

## Recommended fail-closed implementation path (single)
Keep the existing `provider_auth_check` flow as the authority (it already fails closed) and add one codex-specific branch that uses the local status interface from (b) to make the failure *classifiable* instead of ambiguous:

1. In `provider_auth_check` (`dualcoach_admin.py:396`), in the `openai-codex` path (only when `_resolve_canonical_provider` returns it and it is not in `_MODEL_LIST_UNSUPPORTED_PROVIDERS`):
   - call `hermes_cli.auth.get_codex_auth_status()`; if `logged_in` is `False` → short-circuit to `CREDENTIAL_MISSING` (exit 22) **before** building the client / probing; do not run `_probe`.
   - if `logged_in` is `True` → proceed to the existing `_resolve_provider_client` + `_probe`; on codex this yields `PROBE_UNKNOWN` (29) → fail closed, **never** `READY`.
2. Never copy `status["api_key"]` or `status["source"]` into the receipt/stdout — only consume the `logged_in` boolean. Keeps token redaction intact.
3. Optionally append `"auth_status_scope": "local"` and `"auth_status_source": "hermes_cli.auth.get_codex_auth_status"` to `_receipt_payload` when the branch runs.

Rationale: this converts an ambiguous `probe_unknown` into a clear `credential_missing` when the OAuth token is genuinely absent/expired locally, while the server probe still guards against falsely asserting `READY` when only a stale local token exists. It is read-only, touches no provider/account state, and never generates or delivers.

Runnable shapes (read-only):
- `dualcoach_admin provider-auth check --json --receipt-dir <dir>` (current frozen command; codex → `probe_unknown`, exit 29).
- `hermes auth status openai-codex` (local status; `openai-codex: logged in` / `logged out (<reason>)`).
- `hermes doctor` (codex auth row is local-status only).

## Exact tests
Add to `tests/gateway/test_dualcoach_admin_provider_auth.py` (new parametrized cases, mirroring the existing `_check` helper), monkeypatching `admin._load_production_config`, `admin._resolve_provider_client`, and a `get_codex_auth_status` stub in `admin`:
- provider `openai-codex`, status `{"logged_in": False}` → assert `result is ProviderAuthResult.CREDENTIAL_MISSING`, `exit is ProviderAuthExit.CREDENTIAL_MISSING` (22), resolver `calls == []`, `payload["success"] is False`.
- provider `openai-codex`, status `{"logged_in": True}` but resolver returns `(None, None)` → `CREDENTIAL_MISSING`; resolver called once with `("openai-codex", model)`.
- provider `openai-codex`, status `{"logged_in": True}`, resolver returns a `CodexAuxiliaryClient`-shaped obj without a usable models list → `PROBE_UNKNOWN` (29).
- redaction: a stub status containing a bogus token value must not appear in `json.dumps(receipt.payload)` or CLI stdout.

## Receipt fields (unchanged schema, plus codex-branch additions)
- Base (unchanged): `schema` = `dualcoach-provider-auth-receipt-v1`, `command`, `command_version`, `timestamp_utc`, `candidate_digest`, `config_sha256`, `provider_adapter` = `"agent.auxiliary_client.resolve_provider_client"`, `provider_adapter_version` = `"v1"`, `probe` = `"models.list"`, `result`, `exit_code`, `success`, `configured_provider` = `"openai-codex"`, `receipt_sha256`.
- Codex branch additions: `auth_status_scope` = `"local"`, `auth_status_source` = `"hermes_cli.auth.get_codex_auth_status"`.
- Redaction: `config_sha256` derived from the `_redacted_config` (secrets stripped); the codex branch must emit no `api_key`/token/source value on stdout or disk.
</result>

<next_steps>
I recommend, with the evidence above, that no `READY` result is ever produced for `openai-codex`; the correct status to preserve is `probe_unknown`/29 on the server probe, optionally upgrading to `credential_missing`/22 via the local `get_codex_auth_status` pre-gate only when the token is provably absent/expired locally. This matches the sealed candidate and the frozen fail-closed outcome. No code changes were made (read-only investigation, per request).
</next_steps>