Skip to content

fix: record unanswered questions an unattended turn could not ask - #807

Merged
0xKT merged 2 commits into
mainfrom
fix/unanswered_question_event
Sep 27, 2026
Merged

0xKT merged 2 commits into
mainfrom
fix/unanswered_question_event

Conversation

@ZuyiZhou

@ZuyiZhou ZuyiZhou commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

An unattended turn could ask a question and leave no trace a person can read.

raven agent -m already lists calls the permission gate refused (#708). It said nothing about a question nobody could answer. On the web, a sub-agent turn with no page subscribed to the session binds no asker (start_ask_turn(None) in raven/rpc/spine.py). The host ask_user tool still tells the model "user did not answer; proceed with best judgment". That sentence is the tool result the model reads. Opening the session later showed no event for the question.

Questions that were never put to anyone are now recorded on the turn: a sub-agent ask_user or elicitation with no asker, a question that gives up waiting for the conversation lock, a round trip that is structurally unavailable, and a host ask_user call whose answer comes back empty. A one-shot call has no broker at all, so it returns at that guard; the questions _prepare accepts are recorded there too, and the same error string is what the model still reads. A call _prepare rejects is not recorded. The turn's save writes one assistant entry with a question_unanswered notice, which is what a reopened session draws. A one-shot prints the same questions after the reply. That list does not change the exit status: the turn continued, which is what the model was told to do. A refusal is still the run that exits 3.

Type

  • Fix
  • Feature
  • Docs
  • CI / tooling
  • Refactor
  • Other

Verification

  • Relevant tests pass locally
  • Relevant lint / type checks pass locally
  • User-facing docs or screenshots are updated when needed
uv run --frozen --python 3.12 --extra dev ruff check raven/agent/loop/turn_path.py raven/agent/tools/ask_user.py tests/test_ask_user_tool.py tests/test_cli_one_shot_spine.py tests/test_agents_research_flow_report_shape.py
  All checks passed

uv run --frozen --python 3.12 --extra dev ruff format --check <same files>
  already formatted

uv run --frozen --python 3.12 --extra dev pytest -q \
  tests/test_ask_user_tool.py::test_a_call_with_no_broker_records_the_normalized_questions \
  tests/test_ask_user_tool.py::test_error_paths_return_plain_strings \
  tests/test_cli_one_shot_spine.py::test_a_one_shot_ask_user_call_with_no_broker_is_what_gets_reported \
  tests/test_agents_research_flow_report_shape.py::test_the_bounce_scaffolding_never_becomes_history \
  tests/test_agent_loop_session_stamps.py::test_an_unanswered_question_is_stored_as_a_notice
  5 passed

cd ui-tui && npm run lint:i18n
  i18n: generated catalogue is up to date

PYTHONPATH=. uv run --frozen --python 3.12 --extra dev python scripts/check_source_language.py origin/main...HEAD
  exit 0

make check-commits && PR_TITLE="fix: record unanswered questions an unattended turn could not ask" make check-pr-title
  exit 0

git diff --check origin/main...HEAD
  exit 0

git merge-tree --write-tree HEAD origin/main
  clean

Reverting raven/agent/tools/ask_user.py to its parent makes both new no-broker tests fail with an empty record. Reverting raven/agent/loop/turn_path.py to the parent, where filing was a method, makes test_the_bounce_scaffolding_never_becomes_history raise AttributeError: '_Loop' object has no attribute '_file_unanswered'. Both files were restored afterwards. The earlier reverts (notice not stored, ACP ask and elicitation not recorded, one-shot report not printed) still stand for those paths.

The full suite was not run. A run of the touched CLI modules in this terminal also failed existing assertions that search Rich output for a plain substring (help flags, and 1 action(s) were refused). Those assertions fail the same way with this diff's refusal printer left unchanged. The type checker was not rerun locally; CI's python lint job runs it on the head.

Risk

  • Security impact considered
  • Backward compatibility considered
  • Rollback path is clear for risky changes

The model is still told to continue. Nothing new is approved. The one-shot exit status is unchanged: unanswered questions are reported and do not by themselves exit 3. The notice is one more assistant entry on the session, with notice.kind question_unanswered, so a client that already draws runtime notices draws this one. Rollback is reverting the commit.

Related Issues

#708

A one-shot listed only the calls a gate refused. A sub-agent turn with
no page subscribed bound no asker, and the sentence telling the model
to proceed was the only trace, so opening the session later showed
nothing.
@ZuyiZhou
ZuyiZhou requested a review from LivXue as a code owner September 26, 2026 16:24

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Blocking: the no-broker one-shot path must record its unanswered questions before this can merge.

I left one inline finding. I reviewed the actual PR delta against GitHub's current base (2f5027cdf); the local github/main ref was stale, so I also separated the two already-merged intervening commits from this PR. I covered the repository rules and runtime/TUI domain guidance, the diff, production callers and persistence paths, relevant history, backward compatibility, test quality (including whether the new tests bypass production behavior), and the runtime architecture boundary.

Verification:

  • uv run pytest tests/test_acp_ask_user.py tests/test_acp_elicitation.py tests/test_agent_loop_session_stamps.py tests/test_ask_user_tool.py tests/test_cli_agent_commands.py tests/test_cli_one_shot_spine.py -x - 235 passed.
  • uv run python scripts/check_source_language.py 2f5027cdfc279a96ba3fb69ac351f5652b63f0dc...HEAD - passed.
  • git diff --check 2f5027cdfc279a96ba3fb69ac351f5652b63f0dc...HEAD - passed.
  • A direct no-broker AskUserTool reproduction returned the existing configuration error and left turn.unanswered empty.

make check-source-language could not run because make is unavailable in this environment; the canonical checker it wraps passed when invoked directly.

Comment thread raven/agent/tools/ask_user.py
The no-broker return is the path a one-shot call takes, so the note on
the empty-answer branch never ran and the report stayed empty. The
notice is filed by a function, because a stub that borrows _save_turn
has no loop method of its own.

@gloryfromca gloryfromca left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No blockers; this can merge as far as I am concerned.

The prior blocker is fixed: the production no-broker and missing-conversation paths now record normalized, valid questions before preserving their existing error returns, and the one-shot regression test exercises that path through AskUserTool and the runner. Moving unanswered-notice filing to a module-level helper also preserves callers that borrow _save_turn on a stub.

For this revision I reviewed the delta from 73725bb71050, the updated full PR diff, the affected callers and persistence path, compatibility of existing error returns, the regression tests (including whether they reach production behavior), repository rules/domain terminology, and the existing runtime architecture boundary. I found no additional issue.

Verification:

  • uv run pytest tests/test_acp_ask_user.py tests/test_acp_elicitation.py tests/test_agent_loop_session_stamps.py tests/test_ask_user_tool.py tests/test_cli_agent_commands.py tests/test_cli_one_shot_spine.py tests/test_agents_research_flow_report_shape.py -x - 283 passed.
  • uv run python scripts/check_source_language.py 2f5027cdfc279a96ba3fb69ac351f5652b63f0dc...HEAD - passed.
  • git diff --check 2f5027cdfc279a96ba3fb69ac351f5652b63f0dc...HEAD - passed.

@0xKT
0xKT merged commit bcbc295 into main Sep 27, 2026
27 of 30 checks passed
@0xKT
0xKT deleted the fix/unanswered_question_event branch September 27, 2026 02:30
@0xKT 0xKT mentioned this pull request Sep 27, 2026
12 tasks
0xKT added a commit that referenced this pull request Sep 27, 2026
## Summary

Bump the package version from 0.2.2 to 0.2.3 for the next release. Only
pyproject.toml and uv.lock change.

Since v0.2.2, main merged 13 PRs: three features (#802 an experimental
Curator that cultivates harness-of-harnesses workers, #805 one header
per desk pane, #806 upgrade from the page with progress), four fixes
(#792 and #799 name grok and copilot connection failures, #807 records
the questions an unattended turn could not ask, #808 keeps the report
shape on interrupted research turns) and six docs PRs. None carries a
BREAKING CHANGE footer, so this is a patch bump, the way v0.2.1 and
v0.2.2 were for their features. The tag and release notes follow once
this lands.

## Type

- [ ] Fix
- [ ] Feature
- [ ] Docs
- [ ] CI / tooling
- [ ] Refactor
- [x] Other

## Verification

- `uv lock` on a clean worktree cut from origin/main: Resolved 251
packages, Updated raven v0.2.2 -> v0.2.3
- `git diff --stat origin/main..HEAD`: pyproject.toml and uv.lock, 2
insertions, 2 deletions
- `PYTHONPATH=. python scripts/check_commit_messages.py
origin/main..HEAD`: exit 0
- `npx commitlint --from origin/main --to HEAD --config
commitlint.config.cjs`: exit 0
- `uv version` in the worktree: raven 0.2.3
- No test run: the change is version metadata only.

- [ ] Relevant tests pass locally
- [x] Relevant lint / type checks pass locally
- [ ] User-facing docs or screenshots are updated when needed

## Risk

No code change. Rollback is reverting this commit before any v0.2.3 tag
is pushed.

- [ ] Security impact considered
- [x] Backward compatibility considered
- [x] Rollback path is clear for risky changes

## Related Issues

N/A

Co-authored-by: Claude (claude-fable-5-1) <noreply@anthropic.com>
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.

3 participants