feat(decisioning): TaskHandoff create_media_buy on_complete + on_failure hooks#561
Merged
bokelley merged 1 commit intoMay 4, 2026
Merged
Conversation
…ure hooks Closes the v1.5.1 follow-up flagged in PR #550. Adopters returning ctx.handoff_to_task(...) from create_media_buy(proposal_id=...) now get the same single-ledger D3 guarantee as the inline path: the proposal transitions CONSUMING → CONSUMED via the framework's on_complete hook when the bg task lands; failure paths release the reservation so the buyer can retry. Previous gap: HITL accept-proposal flows left the proposal in CONSUMING until eviction. No data leak, but reverse-index lookup couldn't hydrate, and a second create_media_buy(proposal_id=X) after a HITL rejection would hit PROPOSAL_NOT_COMMITTED until eviction. Mechanism: * _project_handoff gets on_failure paired with on_complete; inner _fail() helper centralizes 'invoke on_failure (best effort) then registry.fail' across all four failure branches. * _invoke_platform_method forwards both kwargs into _project_handoff on the handoff path; fires on_complete inline before sync return; fires on_failure on every adapter exception path. * handler.py:create_media_buy replaces the local try/except + post-call mark_consumed branches with two closures passed to _invoke_platform_method. Single source of truth for inline + HITL. 3 new tests: handoff happy path, handoff failure releases reservation, end-to-end retry-after-release. All 5 existing finalize-handoff tests still pass. 4014 passed (was 3966 on main + concurrent CI work). Zero regressions. ruff + mypy clean.
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 the v1.5.1 follow-up flagged in PR #550. Adopters returning `ctx.handoff_to_task(...)` from `create_media_buy(proposal_id=...)` now get the same single-ledger D3 guarantee as the inline path: the proposal transitions `CONSUMING → CONSUMED` via the framework's `on_complete` hook when the bg task lands; failures release the reservation so the buyer can retry.
The previous gap: HITL accept-proposal flows left the proposal in `CONSUMING` until the eviction window passed. No data leak, but the reverse-index lookup couldn't hydrate, and a second `create_media_buy(proposal_id=X)` after a HITL rejection would hit `PROPOSAL_NOT_COMMITTED` until eviction.
Mechanism
Test plan
🤖 Generated with Claude Code