Reconcile late durable workflow outcomes - #324
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves post-turn diagnosability and recovery by reconciling ordinary-turn “timed out after durable submission” effects with the eventual terminal state of the canonical durable workflow instance, while preserving the immutable turn-time receipt.
Changes:
- Add late-terminal reconciliation that records an actor-scoped
late_terminalphase when a durable workflow later reachescompleted/failed/cancelled. - Persist and prefer identity-bearing
tool_invocationsfor failed turns and MCP-facing diagnostics, with bounded hydration when persisted diagnostics are empty. - Extend tests to cover routing reconstruction, terminal reconciliation idempotency, and diagnostics hydration/preference rules.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/backend/test_turn_execution_record_service_execution_summary.py | Adds coverage for routing reconstruction and durable terminal reconciliation journaling/idempotency. |
| tests/backend/test_subworkflow_budget_diagnosability.py | Ensures failed-turn persistence includes tool_invocations and workflow identity fields. |
| tests/backend/test_rag_turn_execution_records_mcp_read_tools.py | Verifies MCP diagnostics prefer top-level identity-bearing invocations and hydrate empty tool history. |
| tests/backend/test_durable_workflow_system.py | Ensures durable instance completion triggers reconciliation for conversation-turn sourced instances. |
| src/backend/workflows/durable/instance_manager.py | Triggers best-effort reconciliation on durable terminal transitions for conversation turns. |
| src/backend/services/turn_execution_record_service.py | Adds reconciliation function and improves debug-driven routing/tool-invocation extraction. |
| src/backend/services/turn_execution_diagnostics_service.py | Adds bounded tool-invocation summarisation and hydration fallbacks for diagnostics. |
| src/backend/integrations/internal_mcp/catalogue.py | Prefers top-level invocations and enriches summaries with workflow/instance/transport identities. |
Comments suppressed due to low confidence (1)
src/backend/services/turn_execution_record_service.py:12837
- Routing synthesis reads only
llm_debug["tool_invocations"]. Many legacy debug payloads still store the tool list underinvocations, which means this function will ignore tool activity entirely and default toplain_response. Consider falling back toinvocationswhentool_invocationsisn't present (while still respecting an explicitly emptytool_invocationslist).
for raw_invocation in tool_invocations:
if not isinstance(raw_invocation, Mapping):
continue
Comment on lines
+11155
to
+11158
| tool_invocations=( | ||
| _debug_list("tool_invocations") | ||
| or _debug_list("invocations") | ||
| ), |
| "verdict": "represented_workflow_execution", | ||
| "source": "synthesised_from_tool_invocation", | ||
| } | ||
| if _is_write_tool(_safe_str(raw_invocation.get("name"))): |
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.
What changed
completed,failed, orcancelledlate_terminaljournal phasetool_invocationson failed turns and recover represented workflow, instance, effect, and transport identities in Jira-facing diagnosticsRoot cause
The workflow handler could durably submit an instance and then exhaust the MCP database/handler deadline. The turn correctly returned a partial receipt, but PyMongo deadline unwinding meant the handler-level late callback never observed the eventual durable terminal state. The failed-turn projection also read the obsolete
invocationskey, while the adaptive path emitstool_invocations, leaving the durable record with zero calls.Impact
Post-turn diagnostics now distinguish the immutable turn result from the later canonical workflow outcome. A completed durable instance resolves the effect journal without retrying the effect, and exact workflow/instance/execution identifiers remain available for recovery and support.
Validation
live-kb-prompt-641f144c-4820-42ac-8622-51c2fc695ea0now shows 3 tool calls, exact instanceaa8ad9a5-b78e-4542-9431-f0a546196d4d, andlate_terminal=succeededA broader touched-file run passed 126 tests; 11 pre-existing benchmark/dashboard tests still fail at their operator-authority guard before reaching the changed code.