Skip to content

Checkpoint diffs never resolve: ProviderRuntimeIngestion placeholder preempts CheckpointReactor git capture #585

@eggfriedrice24

Description

@eggfriedrice24

Bug

Turn diffs ("Loading checkpoint diff…" / "Filesystem checkpoint is unavailable for turn N") never resolve after a Codex turn completes, even when the project is a valid git repository.

Root cause

There is a race between two independent event handlers that both react to turn completion:

  1. ProviderRuntimeIngestion handles turn.diff.updated events and immediately dispatches thread.turn.diff.complete with a placeholder checkpoint entry:

    • checkpointRef: "provider-diff:<eventId>" (not a real git ref)
    • status: "missing"
    • files: []

    (apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts, lines 1064-1083)

  2. CheckpointReactor handles turn.completed events and is supposed to capture a real git-ref-based checkpoint via CheckpointStore.captureCheckpoint, then dispatch thread.turn.diff.complete with the actual diff data.

    (apps/server/src/orchestration/Layers/CheckpointReactor.ts, lines 150-298)

The problem: ProviderRuntimeIngestion wins the race and inserts the placeholder into thread.checkpoints first. When CheckpointReactor later processes turn.completed, it checks:

if (thread.checkpoints.some((checkpoint) => checkpoint.turnId === turnId)) {
  return; // ← early exit, real capture never happens
}

(line 169)

Since the placeholder already has the same turnId, the real git checkpoint is never captured. The DiffPanel then tries to resolve provider-diff:UUID via git rev-parse, which fails because it's not an actual git ref.

Observed behavior

  • Server logs show thread.turn-diff-completed events with checkpointRef: "provider-diff:..." and status: "missing"
  • DiffPanel shows "Loading checkpoint diff..." indefinitely, then "Filesystem checkpoint is unavailable for turn N"
  • No refs/t3/checkpoints/ git refs are created for the affected turns

Reproduction

  1. Add any git-initialized project
  2. Send a message that triggers file changes (e.g., "add a comment to README")
  3. Wait for turn to complete
  4. Open the diff panel → stuck on "Loading checkpoint diff..."

Suggested fix

The dedup check in CheckpointReactor (line 169) should either:

  • Only skip if an existing checkpoint has a non-placeholder status (i.e., skip "missing" entries), or
  • Replace/upgrade placeholder checkpoints with the real git-based checkpoint when one becomes available

Additionally, there is a secondary CWD inconsistency worth noting: CheckpointReactor turn-completion capture prefers sessionRuntime.cwd while CheckpointDiffQuery only uses resolveThreadWorkspaceCwd. If these ever diverge, refs would be written to one repo but looked up in another.

Environment

  • T3 Code dev (main branch)
  • Codex provider with GPT-5.4
  • Linux (Arch)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions