Synced from monorepo

Synced from monorepo

Changes:
- Workspace server: surface preview-proxy metrics through the hub metric pump
- Shell: reclaim a session’s retained state in one entry
- Shell: reclaim a session’s resident state in one entry
- Pager: withhold key event types from Alacritty builds that double keys
- Tools: cancel a session’s subagents when it closes
- Pager: keep the whole plan in scrollback and separate reasoning from output in minimal mode
- Pager: probe terminal version over DA2 and include it with feedback
- SuperGrok Plus: identity, CLI, and analytics tier surfaces
- Shell: inherit the session process scope into subagents
- Pager: build @-file-search matcher lazily on first use
- Tools: fix description and output contradictions in tool definitions
- Workspace: degrade @-file-search instead of aborting on thread exhaustion
- Tools: reap a session’s LSP servers when it closes
- Tools: fix contradictions and defects in tool descriptions, schemas, and harness pools
- MCP: reap stdio MCP children on session close
- Shell: reuse spawn-time skill discovery for session telemetry
- Tools: stop leaking shell-wrapper positional params into sourced scripts (fixes activate_conda under persistent/static shell)
- Shell: self-heal corrupt session-search SQLite cache
- Workspace: cap workspace-server tokio workers on many-core hosts
- Shell: reap a session’s child processes when it closes
- Crash handler: capture SIGABRT so panic-aborts leave crash reports
- CLI chat proxy: team-scoped Grok Code managed-config admin routes
- MCP: add CLI enable/disable for MCP servers
- Shell: cap tokio worker threads for startup thread demand
- Workspace: harden git_commit and add git_sync_base operation
- Circuit breaker: add feature-gated gRPC retry policy

Source-Revision: 2a818575225183d8ca915f5632a09b8067b5156a
This commit is contained in:
grokkybara[bot] 2026-07-28 22:50:19 +00:00
commit 5da6962e4a
192 changed files with 10337 additions and 3421 deletions

View file

@ -1,9 +1,10 @@
//! E2E: the coding-data privacy upsell banner — shown on the welcome screen
//! for an opted-out OAuth user under the `privacy_notice_rollout` flag,
//! persisting into the agent view, and acked (never re-shown) via both
//! buttons: `[Customize in settings]` opens the settings chooser and stamps
//! `[privacy].privacy_banner_acked`; `[Accept]` opts the user in through the
//! shell's `PUT /privacy/coding-data-retention` round trip before acking.
//! buttons: `[Opt out]` dismisses on the spot, stamping
//! `[privacy].privacy_banner_acked` without waiting on the server; `[Opt in]`
//! opts the user in through the shell's `PUT /privacy/coding-data-retention`
//! round trip and acks only once that succeeds.
//!
//! Drives the real pager binary through a PTY against the shared mock
//! inference server (isolated `$HOME`), with a seeded opted-out OAuth entry
@ -27,20 +28,20 @@ use xai_grok_pager_pty_harness::{
const ROWS: u16 = 50;
const COLS: u16 = 120;
const BANNER_TITLE: &str = "Help improve Grok";
const CUSTOMIZE: &str = "[Customize in settings]";
const ACCEPT: &str = "[Accept]";
const OPT_OUT: &str = "[Opt out]";
const OPT_IN: &str = "[Opt in]";
const ACK: &str = "BANNERACK";
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[ignore] // opt-in: spawns the real pager binary in a PTY (CI runs with --ignored)
async fn privacy_banner_welcome_customize_ack_persists() {
run_customize().await.expect("privacy banner customize e2e");
async fn privacy_banner_welcome_opt_out_ack_persists() {
run_opt_out().await.expect("privacy banner opt-out e2e");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[ignore] // opt-in: spawns the real pager binary in a PTY (CI runs with --ignored)
async fn privacy_banner_persists_into_agent_view_and_accept_opts_in() {
run_accept().await.expect("privacy banner accept e2e");
async fn privacy_banner_persists_into_agent_view_and_opt_in_shares() {
run_opt_in().await.expect("privacy banner opt-in e2e");
}
/// Rollout flag forced on (env override beats remote settings) and the
@ -53,7 +54,7 @@ fn banner_env_ops() -> [EnvOp<'static>; 2] {
]
}
async fn run_customize() -> Result<()> {
async fn run_opt_out() -> Result<()> {
let content = ContentController::start()
.await
.context("start mock server")?;
@ -66,29 +67,27 @@ async fn run_customize() -> Result<()> {
let mut pager = spawn_pager(&binary, &content, project.path()).context("spawn pager")?;
wait_for_banner(&mut pager)?;
assert!(
pager.contains_text(ACCEPT),
"welcome banner is missing {ACCEPT}:\n{}",
pager.contains_text(OPT_IN),
"welcome banner is missing {OPT_IN}:\n{}",
pager.screen_contents()
);
click_text(&mut pager, CUSTOMIZE).context("click Customize")?;
click_text(&mut pager, OPT_OUT).context("click Opt out")?;
// Dismissal is local and immediate — it must not wait on the server, and
// must not detour into settings.
pager
.wait_for_text("Coding data sharing", Duration::from_secs(20))
.context("settings chooser opened on Coding data sharing")?;
.wait_for_text_absent(BANNER_TITLE, Duration::from_secs(10))
.context("banner dismissed by [Opt out]")?;
assert!(
pager.contains_text("Opt in") && pager.contains_text("Opt out"),
"chooser is missing the Opt in / Opt out choices:\n{}",
!pager.contains_text("Coding data,"),
"[Opt out] must answer the question, not open settings:\n{}",
pager.screen_contents()
);
// Customize acks immediately; the config write is async — poll for it.
// The config write is async — poll for it.
wait_for_ack_on_disk(&mut pager, content.home(), Duration::from_secs(10))?;
// Close the chooser, then the settings list, then quit gracefully.
pager.inject_keys(keys::ESC).context("close chooser")?;
pager.update(Duration::from_millis(300));
pager.inject_keys(keys::ESC).context("close settings")?;
pager.update(Duration::from_millis(300));
quit_via_double_ctrl_c(&mut pager)?;
drop(pager);
@ -110,7 +109,7 @@ async fn run_customize() -> Result<()> {
Ok(())
}
async fn run_accept() -> Result<()> {
async fn run_opt_in() -> Result<()> {
let content = ContentController::start()
.await
.context("start mock server")?;
@ -136,12 +135,12 @@ async fn run_accept() -> Result<()> {
pager.screen_contents()
);
click_text(&mut pager, ACCEPT).context("click Accept")?;
click_text(&mut pager, OPT_IN).context("click Opt in")?;
// Ack only lands after the shell's PUT round trip confirms 2xx.
pager
.wait_for_text_absent(BANNER_TITLE, Duration::from_secs(20))
.context("banner disappeared after Accept")?;
.context("banner disappeared after [Opt in]")?;
wait_for_ack_on_disk(&mut pager, content.home(), Duration::from_secs(10))?;
let put_bodies: Vec<_> = content

View file

@ -1,4 +1,4 @@
//! E2E: the settings modal's locked `Coding data sharing` row, driven off
//! E2E: the settings modal's locked coding-data row, driven off
//! the seeded auth entry through the full pipeline (auth.json → shell
//! `GrokAuth` → auth meta → `AppView::coding_data_sharing_lock()` →
//! `PagerLocalSnapshot` → render):
@ -33,11 +33,16 @@ use xai_grok_pager_pty_harness::{
const ROWS: u16 = 50;
const COLS: u16 = 120;
const BANNER_TITLE: &str = "Help improve Grok";
const ROW_LABEL: &str = "Coding data sharing";
/// Head of the row's label (`Coding data, retention, and training`). The
/// modal truncates long labels, so match the stable prefix.
const ROW_LABEL: &str = "Coding data";
const CHEVRON: &str = "\u{203A}"; //
const ZDR_REASON: &str = "Your team has Zero Data Retention.";
const TEAM_REASON: &str = "Managed by your team admin.";
const DESCRIPTION_PREFIX: &str = "Controls whether";
/// Head of the row's description in `settings/defs.rs`. Kept short so it
/// can't span one of the modal's word wraps — `contains_text` joins rows
/// with `\n`, so a match on wrapped copy would silently never fire.
const DESCRIPTION_PREFIX: &str = "Opt-in to provide SpaceXAI";
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[ignore] // opt-in: spawns the real pager binary in a PTY (CI runs with --ignored)
@ -222,7 +227,7 @@ fn open_settings_and_grab_row_line(pager: &mut PtyHarness) -> Result<String> {
pager.inject_keys(keys::ENTER).context("commit filter")?;
pager
.wait_for_text(ROW_LABEL, Duration::from_secs(20))
.context("Coding data sharing row visible")?;
.context("coding-data row visible")?;
pager.update(Duration::from_millis(500));
let screen = pager.screen_contents();
screen
@ -235,7 +240,7 @@ fn open_settings_and_grab_row_line(pager: &mut PtyHarness) -> Result<String> {
/// Expand the focused row with `→` (Browse-mode `KeyCode::Right` inserts the
/// focused key into `expanded_keys`) and wait for `reason` to render.
/// Callers reach here from [`open_settings_and_grab_row_line`], which leaves
/// the Coding data sharing row focused.
/// the coding-data row focused.
fn expand_focused_row(pager: &mut PtyHarness, reason: &str) -> Result<()> {
pager.inject_keys(keys::RIGHT).context("expand row")?;
pager.update(Duration::from_millis(300));