Skip to content

fix(approvals): poll with originating context, not empty result.raw#5

Merged
tino-cmd merged 1 commit into
mainfrom
fix/approval-poll-context
Jul 20, 2026
Merged

fix(approvals): poll with originating context, not empty result.raw#5
tino-cmd merged 1 commit into
mainfrom
fix/approval-poll-context

Conversation

@tino-cmd

@tino-cmd tino-cmd commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Problem

CoreAdapter.handle_approval read workflow_id/run_id/activity_id from
result.raw, but Core's public evaluate response
(GovernanceVerdictPublicResponse) never echoes them. So with a real
ApprovalPoller configured (HITL), POST /api/v1/governance/approval was
polled with empty IDs — Core could never match the pending approval, and
the poll rejected/timed out.

Reachable only when a poller is wired; the default no-poller adapter rejects
outright (fail-safe), which is why it stayed latent. The same root cause
exists in the openbox-sdk-ts base SDK and is fixed there too.

Fix

Thread the originating context into the approval seam, mirroring
on_completed_hook_result(result, context):

  • handle_approval(result, context=None) — optional ActivityContext;
    CoreAdapter prefers it and keeps result.raw as a backward-compat fallback.
  • Async lifecycle path builds the context from the event (workflow_id/
    run_id from the payload; activity_id from the envelope).
  • Async hook path passes the span-resolved context.
  • The sync hook path was already correct (resolves ctx → poller directly)
    and is unchanged.

Backward compatibility

Call sites pass context only when the adapter's signature accepts it, via
adapter_accepts_context — the same signature-inspection already used for
on_completed_hook_result. Adapters defined as handle_approval(self, result)
keep working unchanged.

Tests

+3 tests in test_runtime_delegation.py: polls with context IDs when
result.raw is empty, raw fallback without context, and the lifecycle
threading the event context.

  • Full suite: 372 passed
  • ruff: clean
  • mypy: at the pre-existing baseline (no new errors)

CoreAdapter.handle_approval read workflow_id/run_id/activity_id from
result.raw, but Core's evaluate response never echoes them, so a configured
ApprovalPoller polled with empty IDs. Thread the originating ActivityContext
into handle_approval(result, context=None) — the async lifecycle path builds
it from the event, the async hook path passes the span-resolved context —
preferring it over result.raw, which is kept as a backward-compatible
fallback.

Call sites pass context only when the adapter signature accepts it
(adapter_accepts_context, the same inspection already used for
on_completed_hook_result), so adapters defined as handle_approval(self,
result) keep working. The sync hook path was already correct. Mirrors the
openbox-sdk-ts base SDK fix.
@tino-cmd
tino-cmd merged commit c4dc2ad into main Jul 20, 2026
2 checks passed
@tino-cmd
tino-cmd deleted the fix/approval-poll-context branch July 20, 2026 19:27
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