Skip to content

app-server: preserve thread git info across live snapshots#1

Draft
Fuiste wants to merge 2 commits into
mainfrom
fix/thread-git-info-live-snapshots
Draft

app-server: preserve thread git info across live snapshots#1
Fuiste wants to merge 2 commits into
mainfrom
fix/thread-git-info-live-snapshots

Conversation

@Fuiste
Copy link
Copy Markdown
Owner

@Fuiste Fuiste commented Apr 13, 2026

Summary

This PR implements a small server-side correctness fix for thread git identity in the app-server.

Several live-thread lifecycle paths rebuilt Thread values from config snapshots and ended up emitting git_info: None, even when canonical git metadata was already available from persisted thread metadata or rollout summaries. That made downstream UI state vulnerable to branch/repo identity loss during thread reads, forks, and listener reattachment.

This patch keeps the API shape unchanged and narrows the change to app-server state assembly.

Root Cause

build_thread_from_snapshot(...) constructs a Thread from in-memory snapshot/config state, but it does not hydrate git metadata. A few lifecycle paths were using that snapshot as the final truth for the thread returned to clients.

That meant thread.gitInfo could be dropped on:

  • thread/start
  • loaded thread/read
  • thread listener reattach / watch-manager upsert
  • resumed fork history
  • ephemeral thread/fork

Materialized fork responses also needed a small fallback because the newly created fork summary could still be blank for git metadata even though the source rollout had the branch/origin information.

What Changed

Commit 1: fix(app-server): preserve thread git info in live snapshots

  • Added best_available_thread_git_info(...) in codex-rs/app-server/src/codex_message_processor.rs
    • prefers persisted thread metadata from the state DB
    • falls back to rollout-derived summary
    • returns None only if neither source has git metadata
  • Added build_thread_from_snapshot_with_git_info(...)
    • wraps the existing snapshot builder
    • hydrates thread.git_info from canonical sources after the snapshot is built
  • Switched the affected lifecycle paths to use the hydrated builder
  • Added a narrow materialized-fork fallback so the fork response can recover git info from the source rollout when the fresh fork summary does not yet have it
  • Reused the same conversion path in summary_to_thread(...) for consistency

Commit 2: test(app-server): cover git info hydration on read and fork

Added focused regression coverage for the failure modes this patch targets:

  • loaded thread/read preserves persisted git metadata
  • materialized thread/fork preserves branch/origin identity
  • ephemeral thread/fork preserves branch/origin identity

There is already existing resume coverage in thread_resume_prefers_persisted_git_metadata_for_local_threads, which still passes and helps confirm the patch remains aligned with the existing persisted-metadata preference.

Scope / Non-Goals

This PR intentionally does not:

  • add new RPCs
  • add new Thread fields
  • change the app-server protocol shape
  • add PR merge/closure detection
  • change thread/metadata/update semantics
  • change rollout git capture semantics

The goal is only to stop dropping already-known branch/repo identity in server responses.

Validation

Targeted tests run:

  • cargo test -p codex-app-server --test all thread_read_loaded_thread_preserves_persisted_git_info
  • cargo test -p codex-app-server --test all thread_fork_preserves_git_info
  • cargo test -p codex-app-server --test all thread_resume_prefers_persisted_git_metadata_for_local_threads

Repo-mandated cleanup run:

  • just fix -p codex-app-server
  • just fmt

Additional note:

  • An earlier broad cargo test -p codex-app-server run surfaced three unrelated failures in command_exec and realtime_conversation. I did not touch those areas, and I did not rerun the full suite after just fix because the repo instructions explicitly say not to rerun tests after the fix/fmt pass.

Why This Helps

This does not solve stale PR attachment state by itself, but it leaves the architecture in a better place by making thread.gitInfo a more trustworthy representation of thread branch/repo identity across the lifecycle paths that were previously lossy.

That gives downstream clients a cleaner foundation for any future PR-state revalidation behavior.

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