Preserve thread context when retrying or editing turns (#33211)

## What changed

- Add experimental `beforeTurnId` support to `thread/fork` for copying history strictly before a turn, including an in-progress turn.
- Use before-turn forks for TUI backtracking and safety retries so the replacement prompt retains thread context instead of recreating the branch from the preceding turn or a new thread.
- Add experimental `deferGoalContinuation` support so safety-retry forks can inherit an active goal while waiting for the replacement turn before automatic continuation resumes.
- Hide duplicated nested-review prompts when replaying history or selecting a prompt to edit.

## Testing

- Cover before-turn truncation, fork validation, active-goal inheritance, TUI safety retries, backtracking, and nested-review replay.

GitOrigin-RevId: 4915d85ae1929a0b8c40f3ed7dca29c7a5bdcdf3
This commit is contained in:
Felipe Coury authored and copyberry committed 2026-07-15 02:35:49 +00:00
1 parent e4711f2a3b
commit d88db19144
25 files changed
+1343 -96

No files matched your search

@@ -501,6 +501,12 @@ pub struct ThreadForkParams {
#[ts(optional = nullable)]
pub last_turn_id: Option<String>,
/// Optional turn id to fork before, excluding that turn and all later turns.
/// Cannot be combined with `last_turn_id`.
#[experimental("thread/fork.beforeTurnId")]
#[ts(optional = nullable)]
pub before_turn_id: Option<String>,
/// [UNSTABLE] Specify the rollout path to fork from.
/// If specified, the thread_id param will be ignored.
#[experimental("thread/fork.path")]
@@ -561,6 +567,12 @@ pub struct ThreadForkParams {
#[experimental("thread/fork.excludeTurns")]
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub exclude_turns: bool,
/// When true, carry the source thread's current goal into the fork without
/// starting its initial automatic continuation. The next explicit turn owns
/// the goal lifecycle, and normal automatic continuation resumes after it.
#[experimental("thread/fork.deferGoalContinuation")]
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
pub defer_goal_continuation: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS, ExperimentalApi)]