Synced from monorepo

Synced from monorepo

Changes:
- grok-shell: send an expired external-provider credential to the sign-in flow, not a 401 loop
- pager: clickable ▲ jumps to the top of the response being read
- grok-shell: keep a large task log from making the completion message too long
- Plan viewer scrollbar: widen grab zone to the border column; fix striped thumb in Terminal.app
- pager: poll the tmux probe teardown grace instead of sleeping it
- security: vendor-compat MCP kill switch is now actually enforced when reported as on
- grok-shell: restore session eviction when a leader client disconnects
- Bump rust-toolchain to 1.93.0
- workspace: lexical-normalize permission path patterns before glob matching
- pager: reject garbage Enter in the /resume picker
- pager: show Mermaid affordances in plan mode preview
- pager: drop manage-account link from /session-info
- workspace: auto-approve read-only git queries; defer write floor to auto classifier
- Add free-form pattern editor to the "Always allow" command prompt
- grok-shell: fix /btw caching
- pager: Tab walks answers in the ask_user_question card
- External-provider auth refresh: single 7s attempt instead of 3×5s
- pager: don't resurrect finished background tasks as Running when completion arrives first
- pager: report tmux truecolor clamping in Doctor
- Fix plan viewer scrollbar click+drag hijacked by comment gutter
- pager/shell: stop double Recap after the same last turn
- sampler: preserve x-should-retry through stream collection
- pager: clear plan-mode indicator immediately when the user approves a plan
- pager: tmux does not re-read its config on reattach

Source-Revision: 64c4de99cc822b25ce9c54ab5a4f372093d0885d
This commit is contained in:
grokkybara[bot] 2026-08-03 08:17:57 +00:00
commit 780d1388ff
323 changed files with 12258 additions and 7226 deletions

View file

@ -1,5 +1,5 @@
//! Subagent lifecycle soak: churn spawn/run/completion/eviction and assert
//! threads, fds, and heap/RSS reach steady state. A stub `ChildRunner` drives
//! threads, open files, and heap/RSS reach steady state. A stub `ChildRunner` drives
//! the real coordinator/transport.
//!
//! SUBAGENT_SOAK_CYCLES=20000 cargo test -p xai-grok-tools \
@ -45,7 +45,7 @@ impl Metric {
match self {
Metric::Rss => "rss",
Metric::Threads => "threads",
Metric::Fds => "fds",
Metric::Fds => "open_files",
}
}
@ -54,7 +54,7 @@ impl Metric {
match self {
Metric::Rss => "rss_bytes",
Metric::Threads => "threads",
Metric::Fds => "fds",
Metric::Fds => "open_files",
}
}
@ -69,7 +69,7 @@ impl Metric {
match self {
Metric::Rss => bounds.max_rss_growth_mib as f64,
Metric::Threads => bounds.max_thread_growth as f64,
Metric::Fds => bounds.max_fd_growth as f64,
Metric::Fds => bounds.max_open_files_growth as f64,
}
}
@ -81,7 +81,7 @@ impl Metric {
}
}
/// RSS is sampled on every unix; thread and fd counts are Linux-only.
/// RSS is sampled on every unix; thread and open-file counts are Linux-only.
fn expected_on_this_platform(self) -> bool {
match self {
Metric::Rss => true,
@ -100,22 +100,30 @@ impl MetricValue for ResourceSnapshot {
fn value_of(&self, metric: Metric) -> Option<usize> {
// Destructure so a new resource field is a compile error here, not a
// silently dropped metric.
let ResourceSnapshot { rss, threads, fds } = *self;
let ResourceSnapshot {
rss,
threads,
open_files,
} = *self;
match metric {
Metric::Rss => rss,
Metric::Threads => threads,
Metric::Fds => fds,
Metric::Fds => open_files,
}
}
}
impl MetricValue for ResourceGrowth {
fn value_of(&self, metric: Metric) -> Option<usize> {
let ResourceGrowth { rss, threads, fds } = *self;
let ResourceGrowth {
rss,
threads,
open_files,
} = *self;
match metric {
Metric::Rss => rss,
Metric::Threads => threads,
Metric::Fds => fds,
Metric::Fds => open_files,
}
}
}
@ -172,7 +180,7 @@ struct Bounds {
measure: u64,
concurrency: u64,
max_thread_growth: u64,
max_fd_growth: u64,
max_open_files_growth: u64,
max_rss_growth_mib: u64,
max_blocks_per_cycle: f64,
max_bytes_per_cycle: f64,
@ -187,9 +195,9 @@ impl Bounds {
warmup: env_parse("SUBAGENT_SOAK_WARMUP", MAX_COMPLETED_ENTRIES as u64),
measure: env_parse("SUBAGENT_SOAK_CYCLES", 512u64),
concurrency: env_parse("SUBAGENT_SOAK_CONCURRENCY", 16u64),
// RSS is looser than threads and fds to absorb allocator noise.
// RSS is looser than threads and open files to absorb allocator noise.
max_thread_growth: env_parse("SUBAGENT_SOAK_MAX_THREAD_GROWTH", 8u64),
max_fd_growth: env_parse("SUBAGENT_SOAK_MAX_FD_GROWTH", 16u64),
max_open_files_growth: env_parse("SUBAGENT_SOAK_MAX_OPEN_FILES_GROWTH", 16u64),
max_rss_growth_mib: env_parse("SUBAGENT_SOAK_MAX_RSS_GROWTH_MIB", 256u64),
max_blocks_per_cycle: env_parse("SUBAGENT_SOAK_MAX_BLOCKS_PER_CYCLE", 2.0f64),
max_bytes_per_cycle: env_parse("SUBAGENT_SOAK_MAX_BYTES_PER_CYCLE", 4096.0f64),
@ -595,7 +603,7 @@ fn assert_bounds(bounds: &Bounds, m: &Measurement) {
/// Keep this the only test in the binary that creates a `dhat::Profiler`.
#[tokio::test(flavor = "current_thread")]
#[ignore = "subagent soak; run with --ignored (SUBAGENT_SOAK_CYCLES bounds the measured window)"]
async fn subagent_lifecycle_soak_bounds_threads_fds_and_heap() {
async fn subagent_lifecycle_soak_bounds_threads_open_files_and_heap() {
#[cfg(feature = "dhat-heap")]
let _profiler = dhat::Profiler::builder().testing().build();
@ -646,7 +654,7 @@ mod tests {
let snapshot = ResourceSnapshot {
rss: Some(11),
threads: Some(22),
fds: Some(33),
open_files: Some(33),
};
assert_eq!(snapshot.value_of(Metric::Rss), Some(11));
assert_eq!(snapshot.value_of(Metric::Threads), Some(22));
@ -655,7 +663,7 @@ mod tests {
let growth = ResourceGrowth {
rss: Some(1),
threads: None,
fds: Some(3),
open_files: Some(3),
};
assert_eq!(growth.value_of(Metric::Rss), Some(1));
assert_eq!(growth.value_of(Metric::Threads), None);
@ -669,10 +677,10 @@ mod tests {
let snapshot = ResourceSnapshot {
rss: Some(1),
threads: None,
fds: Some(3),
open_files: Some(3),
};
let json = serde_json::to_string(&Wrap(snapshot)).expect("snapshot serializes");
assert_eq!(json, r#"{"rss_bytes":1,"threads":null,"fds":3}"#);
assert_eq!(json, r#"{"rss_bytes":1,"threads":null,"open_files":3}"#);
}
#[test]
@ -696,7 +704,7 @@ mod tests {
measure: 0,
concurrency: 0,
max_thread_growth: 3,
max_fd_growth: 5,
max_open_files_growth: 5,
max_rss_growth_mib: 7,
max_blocks_per_cycle: 1.0,
max_bytes_per_cycle: 2.0,
@ -729,7 +737,7 @@ mod tests {
measure: 4,
concurrency: 4,
max_thread_growth: 100,
max_fd_growth: 100,
max_open_files_growth: 100,
max_rss_growth_mib: 100,
max_blocks_per_cycle: 10.0,
max_bytes_per_cycle: 10_000.0,
@ -741,7 +749,7 @@ mod tests {
ResourceGrowth {
rss: Some(0),
threads: Some(0),
fds: Some(0),
open_files: Some(0),
}
}
@ -771,7 +779,7 @@ mod tests {
let growth = ResourceGrowth {
rss: None,
threads: Some(0),
fds: Some(0),
open_files: Some(0),
};
let failures = check_bounds(&generous_bounds(), &drained(growth, None));
assert!(
@ -814,7 +822,7 @@ mod tests {
let growth = ResourceGrowth {
rss: Some(200 * 1024 * 1024),
threads: Some(0),
fds: Some(0),
open_files: Some(0),
};
let failures = check_bounds(&generous_bounds(), &drained(growth, None));
assert!(
@ -828,7 +836,7 @@ mod tests {
let growth = ResourceGrowth {
rss: Some(100 * 1024 * 1024),
threads: Some(100),
fds: Some(100),
open_files: Some(100),
};
assert!(check_bounds(&generous_bounds(), &drained(growth, None)).is_empty());
}
@ -885,11 +893,11 @@ mod tests {
}
#[test]
fn check_bounds_flags_thread_and_fd_over_budget() {
fn check_bounds_flags_thread_and_open_files_over_budget() {
let growth = ResourceGrowth {
rss: Some(0),
threads: Some(200),
fds: Some(200),
open_files: Some(200),
};
let failures = check_bounds(&generous_bounds(), &drained(growth, None));
assert!(
@ -897,7 +905,7 @@ mod tests {
"{failures:?}"
);
assert!(
failures.iter().any(|f| f.starts_with("fds:")),
failures.iter().any(|f| f.starts_with("open_files:")),
"{failures:?}"
);
}