Skip to content

fix: warn when H5I_AGENT is invalid - #489

Merged
Koukyosyumei merged 3 commits into
h5i-dev:mainfrom
snowyukitty:fix/invalid-h5i-agent-warning
Aug 13, 2026
Merged

Koukyosyumei merged 3 commits into
h5i-dev:mainfrom
snowyukitty:fix/invalid-h5i-agent-warning

Conversation

@snowyukitty

Copy link
Copy Markdown
Contributor

An invalid but present H5I_AGENT currently falls back to human without telling the user. Emit one warning on stderr when the value fails the existing identity grammar, while preserving the human fallback and successful create behavior.

Unset identities remain silent, valid values keep their current behavior, JSON stdout stays parseable, and the warning does not echo the invalid value. The integration test covers punctuation, whitespace, empty, overlong, non-ASCII, valid, trimmed, and unset identities. The manual now documents the validation and fallback behavior.

Closes #458

Testing

  • cargo test --locked --no-default-features --test env_integration create_warns_for_invalid_agent_identity_without_contaminating_json -- --exact
  • cargo test --locked --no-default-features --bin h5i
  • cargo clippy --locked --no-default-features --bin h5i --test env_integration -- -D warnings
  • cargo build --locked --no-default-features --bin h5i --test env_integration
  • python scripts/gen_manual.py

snowyukitty and others added 3 commits August 11, 2026 20:31
The env-var table claimed H5I_AGENT drives "the branch namespace and
automatic runtime profile selection", then that an invalid value falls
back to `human`. Only the first half falls back. AgentRuntime::detect()
reads the raw var and matches starts_with("codex") on it, so
H5I_AGENT=codex.code warns "using 'human'", namespaces the env under
human/, and still hands the box Codex credentials and OpenAI egress via
the auto-picked `agent` profile. The row told the reader the opposite.

Scope the fallback to the namespace and put back the concrete claude /
codex values the rewrite had dropped — "which runtime a box is scoped
to" is what someone reads this row to find out. Regenerated the /manual/
HTML from it so the freshness gate stays green.

Also document warn_invalid_agent_identity, including why the rejected
value is not echoed, and why agent_identity warns at all rather than
falling through in silence.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
CI's `clippy --workspace --all-targets -- -D warnings` failed on Linux
and macOS with collapsible_if on the nested `if let Some(value)` /
`if !value.is_empty()` in the new identity test. It did not reproduce
for the author: collapsible_if only learned to fire across a `let`
binding in clippy 1.97, and older clippy says nothing.

Clippy's own suggestion is a let-chain, which is exactly wrong to commit
here. CI compiles the pull_request MERGE commit, so it sees main's
edition 2024 and let chains parse; this branch is based on an older main
that is still edition 2021, where the same line is a hard parse error.
Anyone building the branch alone would hit it.

`Option::filter` collapses the nesting without a let chain, so it builds
on both editions and reads as the one condition it always was: skip the
empty-string case, which has nothing to look for and would match every
haystack via `contains("")`.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>

@Koukyosyumei Koukyosyumei left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The behavior is right and the test earns its keep.

The core change is narrow and correct: agent_identity() now distinguishes "unset" from "present but unusable" instead of collapsing both through a filter(...).unwrap_or(...), so the silent bare-shell case stays silent while a typo'd identity says so. NotUnicode routes to the same warning rather than being swallowed, which is the case the old .ok() dropped on the floor. Not echoing the rejected value is the right call for ambient input of unknown provenance, and the test pins that rather than trusting it.

The test table is the part I'd have asked for if it weren't already here: punctuation, embedded whitespace, empty, overlong, non-ASCII, valid, trimmed-valid, and unset, each asserting the manifest agent, the env id, the branch, and that stdout stays parseable JSON. That last assertion is what keeps the warning from becoming a breaking change for anything piping --json.

Three commits added on top while reviewing:

  • 6f1f854d0 corrects the H5I_AGENT row in the manual. It claimed the fallback covers "the branch namespace and automatic runtime profile selection", but only the namespace falls back. AgentRuntime::detect() reads the raw var and from_identity matches starts_with("codex") on it, so H5I_AGENT=codex.code warns "using 'human'", namespaces under human/, and still hands the box Codex credentials and OpenAI egress. The row told the reader the opposite of what happens.
  • f33d3134e fixes the CI break: clippy 1.97 fires collapsible_if across the nested if let Some(value) / if !value.is_empty(), which is invisible on older clippy. Worth noting that clippy's own suggestion here is a trap: it proposes a let-chain, and CI compiles the merge commit (edition 2024, parses fine) while this branch is still edition 2021, where the same line is a hard parse error. Option::filter collapses it on both.

Two things for follow-up rather than blockers:

  1. agent_identity() validates and falls back, but AgentRuntime::detect() bypasses it entirely and re-reads the raw var, so an invalid identity still selects a runtime from the unvalidated string. Unifying those would change behavior (codex.code would flip from Codex to Claude credentials), so it does not belong in a warning-only PR, but it is the actual split underneath the doc bug fixed above.
  2. This branch is based on an edition-2021 main. It merges cleanly and CI tests the merge, so nothing is broken, but a rebase would make what you build locally match what CI checks.

@Koukyosyumei
Koukyosyumei merged commit 0232c3b into h5i-dev:main Aug 13, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An invalid $H5I_AGENT silently degrades to human

2 participants