Skip to content

fix(trajectory): snapshot authoritative loop history - #84

Merged
zhanghanduo merged 2 commits into
mainfrom
codex/fix-trajectory-history-83
Oct 29, 2026
Merged

zhanghanduo merged 2 commits into
mainfrom
codex/fix-trajectory-history-83

Conversation

@zhanghanduo

Copy link
Copy Markdown
Collaborator

Closes #83.

Trajectory JSON reconstructed assistant turns from the executable subset of calls and tool messages from result callbacks. This duplicated first-turn assistants when synthetic replies had already been appended, omitted later synthetic replies, and could write an immediate invalid-call result before its assistant because response hooks ran in background tasks. Regression tests reproduce all three failures against main.

Stream JSON snapshots from the loop's live history at coalesced flush boundaries and at completion/cancellation, including every native call, engine-generated reply, post-processed result body, injection, rollback and compaction. Await trajectory hooks to keep response/result events ordered. Keep diagnostic annotations separate from history, release discarded references after snapshots, and preserve atomic replacement, forensic spools on failed writes, image redaction and configured body limits. JSONL continues to record execution events and original tool outputs.

The JSON conversation now follows the normalizer's reasoning policy and native content-block shape; consumers needing flattened text should use messages.text_of. The documented snapshot contract excludes transient request addenda and provider middleware edits. Includes an independent release fragment without changing the package version.

Validation:

  • pytest -q: 2373 passed, 1 skipped.
  • Regression coverage compares snapshots with captured model-request history and final loop results; covers first/later capped turns, dropped/blocked/skipped/restarted calls, truncated arguments, rewrites, reasoning formats, image visibility, cancellation, coalescing, disabled formats and atomic-write failure.
  • Ruff and strict Pyright: passed.
  • Release-fragment and unconsumed-field checks: passed.
  • uv build: source distribution and wheel built successfully.

zhanghanduo and others added 2 commits October 29, 2026 20:06
- Skip the forced flush when cancellation arrives after on_loop_end, so the
  terminal snapshot is not replaced by an empty envelope.
- Re-bind diagnostics by content fingerprint when compaction or a thinking
  reset substitutes shallow copies of assistant messages.
- Degrade non-JSON values instead of failing every later snapshot.
- Restore the hook-only contract (messages/tool_calls None or empty).
- Count tool results toward coalesced snapshots again.
- Keep the spool incremental: re-render only from the first new or changed
  message, detected by reference signatures.
- Omit thinking_blocks annotations already present as native content.
- Drop dead _message_count state and redundant history rebinding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zhanghanduo
zhanghanduo merged commit 71c43a8 into main Oct 29, 2026
5 checks passed
@zhanghanduo
zhanghanduo deleted the codex/fix-trajectory-history-83 branch October 29, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant