feat(reconciler): repair broken client transcripts before persist#73
Merged
Conversation
Mirror CLI face's _repair_loaded_transcript_if_needed pattern in the HTTP chat-completions reconciler. Catches orphaned tool_use, ordering violations, and incomplete assistant turns before they reach the provider — without this, Anthropic returns HTTP 400. Healthy transcripts pass through unchanged (Layer 1 diagnostic is <10ms). The repair runs as Step 1 of reconcile_client_history, before the store.save persist. 🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
manojp99
added a commit
that referenced
this pull request
Jun 23, 2026
Cuts v0.9.0 release with chat-completions session resume, client-authoritative reconciliation, and zero-config opencode session continuity via X-Session-Id header. See CHANGELOG.md [0.9.0] for details: PR #71, #72, #73. Generated with [Amplifier](https://github.com/microsoft/amplifier) Co-authored-by: Manoj Prabhakar Paidiparthy <mpaidiparthy@microsoft.com> Co-authored-by: Amplifier <240397093+microsoft-amplifier@users.noreply.github.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.
Why
The CLI face's
_runtime.py:_repair_loaded_transcript_if_needed()runsdiagnose_transcript/repair_transcript(fromamplifier_foundation.session) before replaying a resumed session — catching orphanedtool_usewithout pairedtool_result, ordering violations, and incomplete assistant turns. Without this, providers (notably Anthropic) reject the next LLM call with HTTP 400.The HTTP face had no equivalent.
_reconciler.py:reconcile_client_historywould overwrite the stored copy with whatever the client sent (broken or not), the runner would replay it as-is, and Anthropic would return 400. This gap was discovered because_session_runner.pywas a copy-and-adapt ofmake_turn_handlerthat dropped the repair step.What changed
src/amplifier_agent_http/_reconciler.py—reconcile_client_historynow runs Layer-1 repair as Step 1, before thestore.savepersist:line_num(required by foundation's incomplete-turns fallback path)diagnose_transcript— returns immediately on healthy transcripts (<10ms, pure)repair_transcript, stripsline_numfrom output, logs aWARNINGwithfailure_modes/orphaned_tool_ids/session_idfor operator visibilityHealthy transcripts are identity-equal after the pass — no mutation, no overhead beyond the diagnostic call.
tests/http/test_reconciler.py— 3 new tests (8 existing pass unchanged):test_reconciler_repairs_orphaned_tool_use_before_persist— broken transcript (OpenAI-style orphanedtool_calls) is repaired; no unmatched tool call ids in resulttest_reconciler_healthy_transcript_passes_through_unchanged— healthy transcript is identity-equal after the passtest_reconciler_logs_warning_with_failure_modes_on_repair—caplogcaptures WARNING containingfailure_modes=and thesession_idCHANGELOG.md— entry under[Unreleased] ### Changed.