Skip to content

fix(cli): preserve result metadata routing (#358 #401) - #20

Merged
cermm merged 3 commits into
mainfrom
fix/issue358-result-meta-early-exit-t7ed34534
Aug 17, 2026
Merged

fix(cli): preserve result metadata routing (#358 #401)#20
cermm merged 3 commits into
mainfrom
fix/issue358-result-meta-early-exit-t7ed34534

Conversation

@cermm

@cermm cermm commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Summary

  • preserve result-metadata FD ownership across early CLI exits
  • fail closed for ambient TUI parse failures
  • honor explicit classic-CLI routing, including argparse-equivalent --cl
  • claim unique abbreviated --result-meta-f=FD before parse-failure publication
  • stop metadata scanning at the chat-side -- terminator
  • add focused route, fault, ownership, abbreviation, and terminator regression coverage

Exact publication gate

  • base: 4a440e09c09987945430d8c77d2e027c3dec723b
  • head: 6bf83f8f0e536a8fd0b8a0aee2ff675ca46a675b
  • tree: ed643ab6a0d6f093f306e5b426b6d67e039facf7
  • independently reviewed repair diff SHA-256: 5f274c8da5e5355161766e9ea6b14baa9c034cc8f2b888c4a38f73e3803f088b

Verification

  • scripts/run_tests.sh tests/hermes_cli/test_result_metadata.py tests/hermes_cli/test_result_metadata_cli.py: 64 passed
  • /home/michal/wc-infrastructure: PYTHONDONTWRITEBYTECODE=1 python3 -m unittest tests.test_hermes_runtime_receipt -q: 28 passed
  • uvx ruff check hermes_cli/main.py tests/hermes_cli/test_result_metadata_cli.py: passed
  • python3 -m py_compile hermes_cli/main.py tests/hermes_cli/test_result_metadata_cli.py: passed
  • git diff --check: passed
  • independent specification review: PASS
  • independent security review: PASS

Exact-head required checks and fresh exact-head Codex review remain mandatory before merge. Live activation/default canary/model A-B/profile rollout remain separate and were not performed. Issues cermm/wc-infrastructure#358, NousResearch#359, and NousResearch#401 must not be closed by this PR.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 824d59882c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hermes_cli/main.py Outdated
Comment on lines +2326 to +2328
if action is None and option.startswith("-") and not option.startswith("--"):
action = actions.get(option[:2])
attached = action is not None and len(option) > 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Handle combined short flags when detecting the query

When a parse error follows a valid combined short form such as hermes chat -Qqhello --result-meta-fd FD --max-turns nope, argparse recognizes -Qqhello as -Q plus -q hello, but this scanner treats the entire token as the first -Q action and never records the query. _eligible_result_metadata_parse_failure_argv() therefore returns false, causing main() to close the descriptor without the promised unknown-failure frame; parse short-option clusters with argparse-equivalent semantics before deciding eligibility.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

@cermm
cermm force-pushed the fix/issue358-result-meta-early-exit-t7ed34534 branch from 824d598 to 53087da Compare August 17, 2026 00:44
@cermm

cermm commented Aug 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 53087da251

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hermes_cli/main.py Outdated
action = actions.get(option)
attached = "=" in token
attached_value = token.split("=", 1)[1] if attached else None
if action is None and option.startswith("--"):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor abbreviated metadata flags during early claiming

When argparse accepts a unique abbreviation such as hermes chat --query hello --result-meta-f=FD --max-turns nope, this branch recognizes the abbreviated option, but _early_claim_result_metadata_argv() only looks for the exact --result-meta-fd spelling. Consequently no owner exists in the parse-error handler, so the descriptor receives no terminal failure frame despite the invocation selecting result metadata; apply the same abbreviation semantics during the early claim and duplicate check.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

Comment thread hermes_cli/main.py Outdated
Comment on lines +2399 to +2402
if action is None:
if token.startswith("-") and not query_values:
return False
index += 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stop metadata scanning at the option terminator

For an invalid invocation such as hermes chat -q hello -- --result-meta-fd FD, argparse treats everything after -- as positional text and rejects it, but the early scan still claims FD and this loop continues past the terminator because a query was already found. The new parse-failure path then writes metadata to that unrelated pipe and converts the usage error to exit 0; return false when the chat-side scanner encounters --.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

@cermm
cermm force-pushed the fix/issue358-result-meta-early-exit-t7ed34534 branch from 53087da to 6bf83f8 Compare August 17, 2026 01:13
@cermm

cermm commented Aug 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review exact head 6bf83f8

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6bf83f8f0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cli.py Outdated
owner = getattr(cli, "result_meta_fd", None)
if owner is None or owner.closed:
return False
cli._publish_abnormal_result_metadata(interrupted=False)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve interrupts in fallback metadata

When KeyboardInterrupt occurs after the descriptor is claimed but before the narrower query handlers run—for example during _prepare_agent_startup() or _init_agent()—the new broad BaseException fallback reaches this call and publishes failed=true, interrupted=false, and failure_class="unknown_failure". This violates the metadata contract that distinguishes user cancellation from unexpected failure and can cause automation to retry or report a cancelled run as an error; retain the caught exception and pass interrupted=True for KeyboardInterrupt in both this direct-API path and the sibling startup fallback in hermes_cli/main.py.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

@cermm

cermm commented Aug 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review exact head dcdcdb4

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

hermes-agent/hermes_cli/main.py

Lines 13186 to 13187 in dcdcdb4

_early_processed_argv = _coalesce_session_name_args(sys.argv[1:])
early_result_meta_owner = _early_claim_result_metadata_argv(_early_processed_argv)

P2 Badge Guard the descriptor throughout pre-parser startup

For a valid metadata invocation, ownership is acquired here before quarantine cleanup, interrupted-install recovery, and the full parser/subcommand construction, but no surrounding guard handles the owner until parsing begins. At the exact head, a KeyboardInterrupt during recovery or a BaseException from one of the subsequent parser-building imports therefore exits without publishing interrupted/failure metadata; this is a fresh gap outside the newly added _prepare_agent_startup() fallback, so ownership cleanup/publication needs to cover the entire interval after this claim.

AGENTS.md reference: AGENTS.md:L54-L57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hermes_cli/main.py
Comment on lines +2501 to +2504
if index + 1 >= len(argv) or argv[index + 1].startswith("-"):
return False
query_values.append(argv[index + 1])
index += 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject empty queries in parse-failure eligibility

When an invocation passes an empty query as a separate argument, such as hermes chat -q '' --result-meta-fd FD --max-turns nope, argparse accepts the empty string but _validate_result_metadata_args() would reject it as no query. This scanner instead appends '', treats the invocation as eligible, publishes an unknown-failure frame, and changes the usage error from exit 2 to exit 0; apply the same nonempty-query check used for the attached-value branch.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

@cermm

cermm commented Aug 17, 2026

Copy link
Copy Markdown
Owner Author

@codex review exact head ea21372

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ea21372a09

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread hermes_cli/main.py
Comment on lines +2528 to +2529
if len(query_values) != 1:
return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Accept repeated query options in parse-failure routing

When a parse error follows an otherwise valid invocation with repeated query options, such as hermes chat -q first -q second --result-meta-fd FD --max-turns nope, argparse permits both query flags and would use the last value, but this exact-one check declares the already-claimed owner ineligible. The descriptor is therefore closed without the promised unknown-failure frame; mirror argparse's last-value-wins behavior while still rejecting an empty effective query.

AGENTS.md reference: AGENTS.md:L54-L57

Useful? React with 👍 / 👎.

@cermm
cermm merged commit bf0f8dc into main Aug 17, 2026
30 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.

1 participant