Synced from monorepo

Synced from monorepo

Changes:
- Temporarily disable session share link creation in the TUI
- Do not approve plan on empty Enter from the revise prompt
- Expose chat product Skills via ACP available_commands_update
- Return immediately from a blocking wait on an already-completed ACP task
- Split headless pager module for clearer structure
- Stop git worktree prune from removing user registrations on resume
- Use compaction sampler tokenizer for item token counts
- Opt-in extra root CAs via GROK_EXTRA_CA_BUNDLE
- Cancel all session subagents when the user stops
- Let the session persistence actor exit when its session ends
- Make fullscreen terminal resize much cheaper on long sessions
- Report honestly from kill_task when an ACP task does not exist
- Hide /usage for external-auth deployments
- Forward the history-load trailer’s computer_reason to the client
- Remove ineffective no-op tool reminder
- Declare slash-command screen-mode support in one place
- Keep settings enum picker on the committed value until Enter
- Reap a PTY’s full process tree
- Stream tool calls from headless mode over ACP
- Bridge gateway task lifecycle to ACP for chat session background tasks
- Don’t warn about truncated history on a suppressed replay
- Fit full-replace summarizer input and recover on context-length errors
- Stop dropping agents over an unrecognized frontmatter color
- Add /undo as a slash alias for /rewind
- Harden sleep/wake token-refresh paths against forced re-login
- Add session/list ACP method
- Give each sampling backend its own conversion module
- Treat an unenrolled child process as a lint error
- Suppress the cancelled marker on send-now wake turns
- Stop tearing down Roslyn on every edit, and read C# diagnostics

Source-Revision: 2a28b4a86cfc4a4c133c35b7fc2a6a9964387c39
This commit is contained in:
grokkybara[bot] 2026-07-30 19:07:40 +00:00
commit dd04f397b1
367 changed files with 29489 additions and 10051 deletions

View file

@ -0,0 +1,75 @@
#[allow(unused_imports)]
use super::common::*;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[ignore]
async fn plan_revise_empty_enter_does_not_approve() {
let content = ContentController::start().await.expect("start content");
content.set_response(format!("{MOCK_RESPONSE_SENTINEL} first turn done."));
let binary = pager_binary().expect("resolve pager binary");
let mut harness = PtyHarness::spawn_with_content_env_in_dir(
&binary,
DEFAULT_ROWS,
DEFAULT_COLS,
&content,
&["--yolo", "--trust", "--no-leader"],
&[],
Some(content.home()),
)
.expect("spawn pager");
harness
.wait_for_text(WELCOME_SCREEN_SENTINEL, WELCOME_TIMEOUT)
.expect("welcome");
harness.inject_keys(b"go\r").expect("first turn");
harness
.wait_for_text(MOCK_RESPONSE_SENTINEL, Duration::from_secs(40))
.expect("first turn streams");
let dir = session_dir(&content, &mut harness);
std::fs::write(dir.join("plan.md"), plan_body("REV", 8)).expect("seed plan.md");
let _expectation = expect_tool_turn(&content, "call_plan_rev", "exit_plan_mode", "{}".into());
harness
.inject_keys(b"present the plan\r")
.expect("submit plan prompt");
harness
.wait_for_text("request changes", Duration::from_secs(60))
.unwrap_or_else(|e| {
panic!(
"plan approval never parked: {e}\nscreen:\n{}",
harness.screen_contents()
)
});
harness.inject_keys(b"s").expect("focus revise prompt");
for _ in 0..5 {
harness.update(Duration::from_millis(100));
}
harness.inject_keys(b"\r").expect("empty Enter");
for _ in 0..10 {
harness.update(Duration::from_millis(100));
}
let screen = harness.screen_contents();
assert!(
screen.contains("Type revision notes, or press a to approve."),
"empty Enter must toast a nudge, not approve; screen:\n{screen}"
);
assert!(
screen.contains("request changes") && screen.contains("Waiting on plan approval"),
"empty Enter must leave plan approval open; screen:\n{screen}"
);
assert!(
!screen.contains("Enter:approve"),
"footer must not advertise Enter as approve; screen:\n{screen}"
);
assert!(
!screen.contains("panicked"),
"pager panicked\nscreen:\n{screen}"
);
harness.quit().expect("clean quit");
}

View file

@ -23,6 +23,8 @@ mod embedded_mode_boots_without_hanging_on_blocked_backend;
mod initial_prompt_positional_auto_submits;
#[path = "pty_e2e/input_echoes_at_idle_prompt.rs"]
mod input_echoes_at_idle_prompt;
#[path = "pty_e2e/plan_revise_empty_enter_does_not_approve.rs"]
mod plan_revise_empty_enter_does_not_approve;
#[path = "pty_e2e/renders_on_action.rs"]
mod renders_on_action;
#[path = "pty_e2e/requirements_version_failure_exits_2_with_guidance.rs"]

View file

@ -848,6 +848,9 @@ fn slash_enters_filter_mode_and_chars_go_to_query_no_action_leak() {
SettingsKeyOutcome::ActionPair(a, b) => {
panic!("filter mode leaked ActionPair({a:?}, {b:?}) for char {c:?}");
}
SettingsKeyOutcome::ActionThenClose(a) => {
panic!("filter mode leaked ActionThenClose({a:?}) for char {c:?}");
}
SettingsKeyOutcome::Close => {
panic!("filter mode unexpectedly closed on char {c:?}");
}