Merge pull request #1403 from vercel-labs/fazxes/approval-answers-during-redraws

Keep approval answers when unrelated redraws are pending
This commit is contained in:
Pranit authored and GitHub committed 2026-10-22 12:32:44 -04:00
commit d0a52d0056
2 files changed
+46 -4

No files matched your search

+21
View File
@@ -2194,6 +2194,27 @@ test "file approval affirmative readiness requires settled committed geometry" {
try std.testing.expect(fileApprovalAffirmativeReady(&shell, prompt.projection().?));
}
test "inline file approval stays answerable through footer work but not a pending approval change" {
const alloc = std.testing.allocator;
var prompt = ApprovalPrompt{};
defer prompt.deinit(alloc);
const preview = diff_mod.FileChangePreview{ .path = "note.txt", .lines = &.{.{ .op = .addition, .new_line = 1, .text = "after" }}, .additions = 1, .deletions = 0, .truncated = false };
try std.testing.expect(try prompt.syncRequest(alloc, .{ .id = 41, .label = "ignored", .file = .{ .kind = .edit, .intent = .mutation, .preview = preview, .scope = .workspace_files } }));
var shell = TranscriptRuntime{ .layout = .{ .rows = 24, .cols = 96, .content_bottom = 20, .divider_top_row = 21, .input_row = 22, .divider_bottom_row = 23, .hint_row = 24 } };
defer shell.deinit(alloc);
shell.footer_viewport.has_frame = true;
shell.footer_viewport.geometry = .{ .top = 1, .top_divider = 1, .input_base = 2, .bottom_divider = fileApprovalDesiredRows(preview), .hint = fileApprovalDesiredRows(preview) };
try std.testing.expect(fileApprovalAffirmativeReady(&shell, prompt.projection().?));
// A status update, such as a new session title, repaints the footer.
shell.render_requests.request(.footer);
try std.testing.expect(fileApprovalAffirmativeReady(&shell, prompt.projection().?));
// A changed request or review asks for a modal frame and must paint first.
shell.render_requests.request(.modal);
try std.testing.expect(!fileApprovalAffirmativeReady(&shell, prompt.projection().?));
}
test "approval panel renders request context and numbered choices" {
var prompt = ApprovalPrompt{};
defer prompt.deinit(std.testing.allocator);
+25 -4
View File
@@ -360,11 +360,13 @@ pub const RenderRequestState = struct {
}
};
/// Pending work that can change what a file approval shows. Every change to an
/// approval's request, review, choice, or scroll position requests `.modal`, so
/// footer, transcript, and subagent panel frames only repaint around the
/// approval and must not hold back the user's answer.
fn reasonsAffectApproval(reasons: ReasonSet) bool {
var relevant = reasons;
relevant.remove(.animation);
relevant.remove(.notification);
return relevant.count() > 0;
return reasons.contains(.modal) or reasons.contains(.resize) or
reasons.contains(.external_damage) or reasons.contains(.first_frame);
}
test "compaction revisions request footer repaint without restarting animation" {
@@ -624,6 +626,25 @@ test "approval settlement ignores animation and notification presentation work"
try std.testing.expect(!state.settledForApproval());
}
test "approval settlement ignores footer, transcript, and subagent panel work" {
var state = RenderRequestState{};
for ([_]Reason{ .footer, .transcript, .subagent_panel }) |reason| {
state.request(reason);
try std.testing.expect(state.settledForApproval());
state.clearReason(reason);
}
for ([_]Reason{ .modal, .resize, .external_damage, .first_frame }) |reason| {
state.request(reason);
try std.testing.expect(!state.settledForApproval());
state.clearReason(reason);
}
// Unrelated work queued with an approval change still waits for the change.
state.request(.footer);
state.request(.modal);
try std.testing.expect(!state.settledForApproval());
}
test "animation phase and deadline publish only after a committed attempt" {
var state = RenderRequestState{
.animation_visible = true,