[Bugfix] Fix completion approval problem#63
Open
droidlyx wants to merge 2 commits intoResearAI:mainfrom
Open
Conversation
…for default reply target Quest 014's user had to send "同意" four times before complete_quest fired: the React workspace's default `reply_to_interaction_id` always resolved to the most recent threaded `progress` heartbeat (e.g. mailbox-poll `__noop__`) even when an unresolved `quest_completion_approval` decision was waiting behind it in the feed. `findReplyTargetId` previously walked the feed once and returned at the first artifact with either `replyMode === 'blocking'` or `replyMode === 'threaded' && interactionId`. Because that single loop returned on the threaded fallback as soon as it saw a recent heartbeat, the older blocking decision was never reached. Split into two passes: first scan for a blocking / `expectsReply` artifact; only when none exists fall back to the latest threaded interaction. Export the function so it can be unit tested. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…action is unresolved While quest 014 waited for a user reply on its quest_completion_approval decision_request, the runtime emitted ~12 `__noop__` mailbox-poll progress heartbeats over four hours. Each one was committed to git, recorded in the interaction journal, and queued for connector delivery — and each one pushed the actual approval request further down the user's feed, making "同意" land on a heartbeat instead of the decision. Add `_has_unresolved_blocking_interaction(quest_root)` which scans `open_requests` for any waiting entry — by construction these are always blocking, since `_update_interaction_state` only inserts into `open_requests` for `reply_mode='blocking'` calls. In `interact()`, short-circuit before the existing dedupe block: when the incoming call is a `__noop__` / `__mailbox_poll__` progress heartbeat and a blocking interaction is still waiting on the user, return `status='suppressed_blocking_pending'` without recording an artifact. The substantive-progress path is unchanged, so a real status update (e.g. "training crashed at step 1200") still records normally even during a blocking wait. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes a UX bug exposed by quest 014: ending an autonomous quest required
the user to send "同意" four times before
complete_questfired. The issue is fixed in twoself-contained commits:
Commit 1 — UI default reply target.
findReplyTargetIdwalked thefeed once and returned at the first artifact whose
replyModewas'blocking'or'threaded'. The mailbox-poll__noop__heartbeatsalways sat after the actual
quest_completion_approvaldecision, sothe threaded fallback fired first and the blocking decision was never
reached. Split into two passes: prefer any unresolved blocking /
expectsReplyartifact; only fall back to the latest threaded onewhen none exists. Function is now exported and unit-tested.
Commit 2 — Suppress noop heartbeats while a blocking interaction is
pending. Added
_has_unresolved_blocking_interaction(quest_root)(any
open_requestsentry withstatus='waiting'is by constructionblocking, since
_update_interaction_stateonly inserts onreply_mode='blocking'). Ininteract(), short-circuit before theexisting dedupe block: when the call is a
__noop__/__mailbox_poll__progress heartbeat and a blocking interaction isstill waiting, return
status='suppressed_blocking_pending'withoutrecording an artifact. Substantive progress messages still record
normally — only mailbox-poll noops are suppressed.
Together: the UI no longer mis-routes "同意" onto a heartbeat, and the
runtime stops emitting heartbeats that would push the actual approval
request further down the user's feed in the first place.
AI Assistance
This PR was prepared with AI assistance and reviewed locally before submission.