Synced from monorepo

Changes:
- Detect the herdr multiplexer
- Mark /gboom as non-production code
- Bound peak memory when loading a large session
- Add a subagent lifecycle soak bounding threads, fds, and heap
- Stream inherited replay to bound fork memory
- Copy full plan from plan approval with y
- Stop armed signature verification from deleting the managed-deny smoke policy
- Add source-tagged terminal version telemetry
- Show the UI instantly and fetch models and settings in the background
- Session test helpers
- computer_reason on the ConversationHistoryDone trailer
This commit is contained in:
grokkybara[bot] 2026-07-26 20:03:03 +01:00
commit b41c75a578
92 changed files with 9410 additions and 3788 deletions

View file

@ -1218,6 +1218,10 @@ pub struct TerminalTelemetry {
pub term_var: String,
pub tmux_version: String,
pub xtversion: String,
/// Raw, as its source reported it — shapes vary (`"3.5.6"`,
/// `"20240203-110809-5046fc22"`, `"7402"`). Empty when unknown.
pub term_version: String,
pub term_version_source: String,
pub host_os: String,
pub display_server: String,
pub modifier_cmd_fate: String,
@ -1847,6 +1851,8 @@ mod tests {
term_var: "xterm-256color".into(),
tmux_version: "".into(),
xtversion: "".into(),
term_version: "".into(),
term_version_source: "none".into(),
host_os: "linux".into(),
display_server: "unknown".into(),
modifier_cmd_fate: "unknown".into(),

View file

@ -72,7 +72,7 @@ impl IdentityAttrs {
/// reach init).
#[derive(Debug, Clone, Copy, Default)]
pub struct ExternalOtelRemotePolicy {
/// Fleet kill switch: flush, then drop subsequent emissions in-process.
/// Remote-policy force-disable: flush, then drop subsequent emissions in-process.
pub force_disable: bool,
/// Force the content gates off regardless of local env/config.
pub lock_content_gates: bool,
@ -219,17 +219,55 @@ fn active_handle() -> Option<Arc<ExternalTelemetry>> {
handle().filter(|ext| ext.active.load(Ordering::Relaxed))
}
/// Fail-closed OTEL gate. Defaults open; the leader closes it before init and
/// re-opens it when settings arrive (or immediately for a pure env-API-key
/// leader, which has no remote policy to fetch).
///
/// On the leader, opening is the synchronizing event: `OtelGate::apply_and_open`
/// applies the remote force-disable (`active = false`) and then opens here, so
/// an emitter whose `Acquire` read observes the `Release` open also observes
/// `active = false`; the emit-path `active` load can therefore stay `Relaxed`.
/// Closing is fail-safe and stays `Relaxed`. The follower path force-disables
/// without re-opening and relies on eventual visibility, acceptable because the
/// policy is tighten-only.
static SETTINGS_RESOLVED: AtomicBool = AtomicBool::new(true);
/// Close the gate (leader preinit + account switch).
pub fn suppress_external_otel_until_settings() {
SETTINGS_RESOLVED.store(false, Ordering::Relaxed);
}
/// Open the gate. `Release` publishes the force-disable applied just before it.
pub fn mark_external_otel_settings_resolved() {
if !SETTINGS_RESOLVED.swap(true, Ordering::Release) {
tracing::debug!("external otel: settings resolved, emission gate opened");
}
}
/// Read the gate. `Acquire` pairs with the `Release` open.
#[inline]
pub fn is_settings_gate_open() -> bool {
SETTINGS_RESOLVED.load(Ordering::Acquire)
}
/// Cheap check used by the fan-out hook and the split-sink call sites:
/// registry present AND the runtime emission gate set. A stale `true` read
/// only costs a wasted mapping, never an export ([`emit`] re-checks).
/// registry present AND the runtime emission gate set AND the settings gate
/// open. A stale `true` read only costs a wasted mapping, never an export
/// ([`emit`] re-checks).
pub fn is_active() -> bool {
matches!(EXTERNAL.get(), Some(Some(ext)) if ext.active.load(Ordering::Relaxed))
is_settings_gate_open()
&& matches!(EXTERNAL.get(), Some(Some(ext)) if ext.active.load(Ordering::Relaxed))
}
/// Map and emit one typed telemetry event. No-op unless the stream is active
/// and the event has an `external = …` mapping. Synchronous and cheap (the
/// batch processor queues; nothing blocks on I/O).
pub fn emit<T: crate::events::TelemetryEvent>(data: &T) {
// Fail-closed: suppress until the leader confirms the remote policy; open by
// default for everyone else.
if !is_settings_gate_open() {
return;
}
let Some(ext) = active_handle() else {
return;
};
@ -267,8 +305,8 @@ pub(crate) fn set_identity_on(ext: &ExternalTelemetry, attrs: IdentityAttrs) {
}
/// Apply remote policy when `RemoteSettings` arrive (post-auth, alongside
/// [`set_identity`]). **TIGHTEN-ONLY**: may clear `active` (fleet kill switch
/// — flushes, then drops subsequent emissions) and may force content gates
/// [`set_identity`]). **TIGHTEN-ONLY**: may clear `active` (remote-policy
/// force-disable, flushes then drops subsequent emissions) and may force content gates
/// off; it can never enable a stream that env/config left off, and never
/// loosens gates mid-run.
pub fn apply_remote_policy(policy: ExternalOtelRemotePolicy) {

View file

@ -960,6 +960,44 @@ async fn remote_gate_lock_forces_gates_off_and_never_on() {
);
}
/// All tests that mutate `SETTINGS_RESOLVED` must hold this lock.
static GATE_TEST_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
#[test]
fn settings_gate_suppresses_until_resolved() {
let _serial = GATE_TEST_LOCK.lock().unwrap_or_else(|e| e.into_inner());
struct RestoreGate;
impl Drop for RestoreGate {
fn drop(&mut self) {
super::mark_external_otel_settings_resolved();
}
}
let _restore = RestoreGate;
// Baseline: default open.
super::mark_external_otel_settings_resolved();
assert!(super::is_settings_gate_open(), "gate defaults open");
// Leader closes it at the start of its auth/network phase.
super::suppress_external_otel_until_settings();
assert!(
!super::is_settings_gate_open(),
"gate must be closed until settings resolve"
);
assert!(
!super::is_active(),
"is_active must be false while the settings gate is closed"
);
// Settings response arrives (policy evaluated) → reopen.
super::mark_external_otel_settings_resolved();
assert!(
super::is_settings_gate_open(),
"gate must reopen after settings are resolved"
);
}
// ─────────────────────────────────────────────────────────────────────────────
// Metric increment derivation
// ─────────────────────────────────────────────────────────────────────────────

View file

@ -137,6 +137,8 @@ pub(super) static ALLOWED_STRING_KEYS: &[&str] = &[
"terminal.multiplexer",
"terminal.tmux_version",
"terminal.term_var",
"terminal.term_version",
"terminal.term_version_source",
"skip_reason",
"auto_cadence_reason",
];
@ -491,6 +493,8 @@ mod tests {
"terminal.multiplexer",
"terminal.tmux_version",
"terminal.term_var",
"terminal.term_version",
"terminal.term_version_source",
"skip_reason",
"auto_cadence_reason",
];