Skip to content

fix: lost answers in human-gate races - #459

Open
jeromevdl wants to merge 1 commit into
mainfrom
fix/answered-gate-race
Open

jeromevdl wants to merge 1 commit into
mainfrom
fix/answered-gate-race

Conversation

@jeromevdl

Copy link
Copy Markdown
Contributor

Issue

A human answer could arrive after the question grace window but before the CLI exited or the orchestrator bound its callback. The persisted answer was then either treated as no gate, allowing the stage to complete without delivering it, or misclassified as a callback conflict.

Fix

  • Keep a stage parked when it still owns a pending or already-decided gate, then resume the conversation with the persisted answer.
  • Recover the answer-before-bind race using strongly consistent DynamoDB reads and strict stage, lane, and callback ownership checks.
  • Share one legacy-compatible ownership predicate across runtime and orchestrator paths.
  • Validate gate decisions against the supported answered, approved, and rejected statuses.

Validation

  • npm test: 158 files, 2,846 tests passed.
  • Frontend: 77 files, 540 tests passed.
  • TypeScript, formatting, lint-staged, secret scanning, and pre-commit checks passed.

@jeromevdl jeromevdl changed the title Fix lost answers in human-gate races fix: lost answers in human-gate races Sep 11, 2026
@jeromevdl jeromevdl added the bug Something isn't working label Sep 15, 2026

@JWThewes JWThewes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The change is focused, and the shared ownership predicate fits the existing runtime/orchestrator patterns. I ran six relevant suites (579 tests passed) and an additional durable replay check confirming that an unused early-answer callback does not prevent completion.

Requesting changes for the answer/steering ordering issue below. The new recovery path can resume before the course correction attached to the same answer has been persisted. Please make the complete answer available before early resume and add a regression test for that interleaving.

Comment on lines +894 to +898
answeredEarly =
isHumanTaskAnswerStatus(gateAfterBindFailure?.status) &&
ownsExpectedStage &&
callbackIdCompatible &&
callbackOwnerCompatible;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Preserve attached steering before resuming an early answer

An answered status does not mean the answer request has finished persisting its payload. In lambda/intents/index.js, answerHumanTask saves the HUMAN decision before createSteering saves the optional course correction. This new recovery branch can observe the decision between those writes and resume immediately, while run-stage consumes pending steering once at entry.

I reproduced this with a deterministic test delaying the STEER write after the answer CAS: the resumed stage consumed an empty steering list, and the answer endpoint subsequently returned 200. The agent can therefore proceed without guidance submitted alongside the answer; that guidance may arrive at a later stage or never reach the agent if this was the final stage.

Please make the complete answer, including attached steering, available before treating it as resumable, and cover this interleaving in a regression test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants