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:
parent
47348d13ec
commit
b41c75a578
92 changed files with 9410 additions and 3788 deletions
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in a new issue