Graduate the shell out of spikes/ into apps/lumbridge

The product was spikes/gpui-shell: a cargo workspace of its own, named in the
root manifest's exclude list. It inherited neither unsafe_code = "forbid" nor
clippy pedantic, and ./scripts/ci.sh never compiled it. Every test written into
it silently never ran, and apps/lumbridge was an eleven-line stub printing a
version string.

Four separate research passes over the sidebar, settings, devices, and theme
work independently discovered they were about to write substantial new code into
that directory. Graduating first means writing it once.

- apps/lumbridge is the product; spikes/ui-shell-model becomes
  crates/lumbridge-ui-fixture and joins the workspace.
- scripts/ci.sh takes --headless and --ui. The headless pass excludes the two UI
  crates by name, so a contributor changing lumbridge-core does not wait on a
  window toolkit, and a runner that cannot carry GPUI still gates everything
  else. A new crate is headless by default rather than silently joining the slow
  job.
- scripts/native-libs.sh replaces the ad-hoc symlink in the launcher, and says
  which apt package actually fixes the problem instead of working around it
  silently. The stale libxcb/libxkbcommon symlinks in the old spike target
  directory are gone; only libxkbcommon-x11.so was ever needed.
- deny.toml and cargo deny check licenses. spikes/README.md called GPUI's
  licence closure a hard gate and the scorecard scored it pending; graduation
  makes it the product's closure, so it is enforced rather than described. Two
  rejections were reviewed and allowed with the reasoning recorded in the file:
  webpki-roots under CDLA-Permissive-2.0 (Mozilla's CA store, data not code,
  reached through ureq) and libfuzzer-sys under NCSA (reached only under
  all-features via gpui's image decoder; no shipped build links it).

Clippy pedantic across both crates is clean at -D warnings. render was 353
lines; render_sidebar, render_tabs, and render_root come out of it, which the
sidebar rework needed anyway. The remaining over-length functions are single
declarative element trees and carry per-function allows with reasons, not a
blanket suppression.

Decision 0017 records the two calls this forces: published gpui 0.2.2 behind an
accessibility adapter rather than an unpinned Zed revision and an MSRV bump, and
Floem frozen rather than maintained in parity or deleted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Metal Agent
2026-08-31 23:05:12 -07:00
co-authored by Claude Opus 5
parent 834b73e831
commit 316fa32745
21 changed files with 9111 additions and 10660 deletions
+8 -1
View File
@@ -8,8 +8,15 @@ license.workspace = true
repository.workspace = true
[dependencies]
gpui = "0.2.2"
lumbridge-core = { path = "../../crates/lumbridge-core" }
lumbridge-harness = { path = "../../crates/lumbridge-harness" }
lumbridge-runtime = { path = "../../crates/lumbridge-runtime" }
lumbridge-storage = { path = "../../crates/lumbridge-storage" }
lumbridge-terminal = { path = "../../crates/lumbridge-terminal" }
lumbridge-ui-fixture = { path = "../../crates/lumbridge-ui-fixture" }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
[lints]
workspace = true
File diff suppressed because it is too large Load Diff
+369
View File
@@ -0,0 +1,369 @@
use std::collections::BTreeSet;
use lumbridge_ui_fixture::PaneId as FixturePaneId;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub(crate) struct PanelId(u64);
impl PanelId {
pub(crate) const fn get(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) enum PanelKind {
Terminal,
Browser,
Markdown,
Review,
}
impl PanelKind {
pub(crate) const ALL: [Self; 4] = [Self::Terminal, Self::Browser, Self::Markdown, Self::Review];
pub(crate) const fn label(self) -> &'static str {
match self {
Self::Terminal => "Terminal",
Self::Browser => "Browser",
Self::Markdown => "Markdown",
Self::Review => "Review",
}
}
pub(crate) const fn description(self) -> &'static str {
match self {
Self::Terminal => "A real local shell with its own runtime actor",
// Not a web engine. There is no browser in this build; the panel
// renders a placeholder surface and says so.
Self::Browser => "A placeholder surface. No web engine is embedded yet",
Self::Markdown => "Local notes, plans, and architecture",
Self::Review => "Repository changes and approval boundaries",
}
}
/// What a newly created panel is pointed at.
///
/// Every one of these used to name a specific machine — this developer's,
/// as it happens. A panel's target is whatever it was actually launched
/// against, and a new panel has been launched against nothing but the
/// local shell.
const fn default_target(self) -> &'static str {
match self {
Self::Terminal => "local shell",
Self::Browser => "no surface attached",
Self::Markdown => "local document",
Self::Review => "working tree",
}
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub(crate) enum SeedPane {
CodexRuntime,
ClaudeUi,
PiDocs,
Architecture,
AcpPreview,
RuntimeReview,
}
impl SeedPane {
pub(crate) const fn fixture_id(self) -> FixturePaneId {
match self {
Self::CodexRuntime => FixturePaneId::CodexRuntime,
Self::ClaudeUi => FixturePaneId::ClaudeUi,
Self::PiDocs => FixturePaneId::PiDocs,
Self::Architecture => FixturePaneId::Architecture,
Self::AcpPreview => FixturePaneId::AcpPreview,
Self::RuntimeReview => FixturePaneId::RuntimeReview,
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub(crate) struct WorkspacePanel {
pub(crate) id: PanelId,
pub(crate) kind: PanelKind,
pub(crate) title: String,
pub(crate) target: String,
pub(crate) attached: bool,
pub(crate) seed: Option<SeedPane>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub(crate) struct PanelRegistry {
schema_version: u32,
panels: Vec<WorkspacePanel>,
selected: PanelId,
next_id: u64,
}
impl Default for PanelRegistry {
fn default() -> Self {
Self::first_run()
}
}
impl PanelRegistry {
/// The workspace a first run opens with.
///
/// Three real local shells and nothing else. This used to seed six panes
/// announcing "Codex · runtime / metal · Tailscale SSH", "Claude Code · UI
/// / `MacBook` Air · local" and a Pi pane on a saved host — none of which
/// existed. Every one was a `/bin/sh`. A pane claims a harness when one has
/// actually been launched into it, and until then it is a terminal.
///
/// Three, not one: `visible_panel_count` branches at 1100 px and 2800 px,
/// so a single-panel default renders one pane on an ultrawide.
pub(crate) fn first_run() -> Self {
let seeds = [
(PanelKind::Terminal, "Terminal 1", "local shell", None),
(PanelKind::Terminal, "Terminal 2", "local shell", None),
(PanelKind::Terminal, "Terminal 3", "local shell", None),
];
let panels = seeds
.into_iter()
.enumerate()
.map(|(index, (kind, title, target, seed))| WorkspacePanel {
id: PanelId(index as u64 + 1),
kind,
title: title.to_owned(),
target: target.to_owned(),
attached: index < 5,
seed,
})
.collect();
Self {
schema_version: 1,
panels,
selected: PanelId(1),
next_id: 7,
}
}
pub(crate) fn from_json(json: &str) -> Result<Self, String> {
let registry: Self = serde_json::from_str(json).map_err(|error| error.to_string())?;
registry.validate()?;
Ok(registry)
}
pub(crate) fn to_json(&self) -> Result<String, String> {
serde_json::to_string(self).map_err(|error| error.to_string())
}
fn validate(&self) -> Result<(), String> {
if self.schema_version != 1 {
return Err(format!(
"unsupported panel snapshot version {}",
self.schema_version
));
}
if self.panels.is_empty() || self.attached_count() == 0 {
return Err("a workspace must retain one attached panel".to_owned());
}
let ids = self
.panels
.iter()
.map(|panel| panel.id)
.collect::<BTreeSet<_>>();
if ids.len() != self.panels.len() || ids.iter().any(|id| id.get() == 0) {
return Err("panel IDs must be unique and non-zero".to_owned());
}
if self
.panel(self.selected)
.is_none_or(|panel| !panel.attached)
{
return Err("the selected panel must be attached".to_owned());
}
let max_id = ids.iter().map(|id| id.get()).max().unwrap_or(0);
if self.next_id <= max_id {
return Err("the next panel ID must exceed every persisted ID".to_owned());
}
Ok(())
}
pub(crate) fn panels(&self) -> &[WorkspacePanel] {
&self.panels
}
pub(crate) fn panel(&self, id: PanelId) -> Option<&WorkspacePanel> {
self.panels.iter().find(|panel| panel.id == id)
}
pub(crate) fn selected(&self) -> PanelId {
self.selected
}
pub(crate) fn attached_ids(&self) -> Vec<PanelId> {
self.panels
.iter()
.filter(|panel| panel.attached)
.map(|panel| panel.id)
.collect()
}
pub(crate) fn detached_ids(&self) -> Vec<PanelId> {
self.panels
.iter()
.filter(|panel| !panel.attached)
.map(|panel| panel.id)
.collect()
}
pub(crate) fn attached_count(&self) -> usize {
self.panels.iter().filter(|panel| panel.attached).count()
}
pub(crate) fn select(&mut self, id: PanelId) -> bool {
if self.panel(id).is_none_or(|panel| !panel.attached) || self.selected == id {
return false;
}
self.selected = id;
true
}
pub(crate) fn select_attached_at(&mut self, index: usize) -> bool {
self.attached_ids()
.get(index)
.copied()
.is_some_and(|id| self.select(id))
}
pub(crate) fn move_horizontal(&mut self, delta: isize) -> bool {
let attached = self.attached_ids();
let Some(position) = attached.iter().position(|id| *id == self.selected) else {
return false;
};
// checked_add_signed rather than a round trip through isize: the cast
// pair could wrap on a 32-bit target, and the bounds check that followed
// it was doing the work this does directly.
let Some(next) = position.checked_add_signed(delta) else {
return false;
};
let Some(id) = attached.get(next) else {
return false;
};
self.select(*id)
}
pub(crate) fn create(&mut self, kind: PanelKind) -> PanelId {
let id = PanelId(self.next_id);
self.next_id += 1;
let sequence = self
.panels
.iter()
.filter(|panel| panel.kind == kind)
.count()
+ 1;
let title = match kind {
PanelKind::Terminal => format!("Terminal · {sequence}"),
PanelKind::Browser => format!("Browser · {sequence}"),
PanelKind::Markdown => format!("Notes · {sequence}"),
PanelKind::Review => format!("Review · {sequence}"),
};
let selected_position = self
.panels
.iter()
.position(|panel| panel.id == self.selected)
.expect("selected panel exists");
self.panels.insert(
selected_position + 1,
WorkspacePanel {
id,
kind,
title,
target: kind.default_target().to_owned(),
attached: true,
seed: None,
},
);
self.selected = id;
id
}
pub(crate) fn detach(&mut self, id: PanelId) -> bool {
if self.attached_count() == 1 || self.panel(id).is_none_or(|panel| !panel.attached) {
return false;
}
let attached_before = self.attached_ids();
let detached_position = attached_before
.iter()
.position(|candidate| *candidate == id)
.expect("attached panel appears in attached IDs");
self.panels
.iter_mut()
.find(|panel| panel.id == id)
.expect("panel exists")
.attached = false;
if self.selected == id {
let remaining = self.attached_ids();
self.selected = remaining[detached_position.min(remaining.len() - 1)];
}
true
}
pub(crate) fn attach(&mut self, id: PanelId) -> bool {
let Some(panel) = self.panels.iter_mut().find(|panel| panel.id == id) else {
return false;
};
if panel.attached {
return false;
}
panel.attached = true;
self.selected = id;
true
}
}
#[cfg(test)]
mod tests {
use super::{PanelId, PanelKind, PanelRegistry};
#[test]
fn dynamic_panels_receive_monotonic_ids_and_insert_beside_selection() {
let mut registry = PanelRegistry::first_run();
let browser = registry.create(PanelKind::Browser);
let terminal = registry.create(PanelKind::Terminal);
assert_eq!(browser, PanelId(7));
assert_eq!(terminal, PanelId(8));
assert_eq!(registry.selected(), terminal);
assert_eq!(registry.panels()[2].id, terminal);
assert_eq!(registry.panels()[1].id, browser);
}
#[test]
fn identity_and_detached_state_round_trip_without_reuse() {
let mut registry = PanelRegistry::first_run();
let created = registry.create(PanelKind::Markdown);
assert!(registry.detach(created));
let json = registry.to_json().unwrap();
let mut restored = PanelRegistry::from_json(&json).unwrap();
assert!(restored.detached_ids().contains(&created));
assert_eq!(restored.create(PanelKind::Review), PanelId(8));
}
#[test]
fn detach_preserves_panel_and_reattach_restores_same_identity() {
let mut registry = PanelRegistry::first_run();
let id = registry.create(PanelKind::Terminal);
assert!(registry.detach(id));
assert!(registry.panel(id).is_some());
assert!(registry.attach(id));
assert_eq!(registry.selected(), id);
}
#[test]
fn invalid_or_empty_snapshots_are_rejected() {
assert!(PanelRegistry::from_json("{}").is_err());
assert!(
PanelRegistry::from_json(
r#"{"schema_version":1,"panels":[],"selected":1,"next_id":2}"#
)
.is_err()
);
}
}
+629
View File
@@ -0,0 +1,629 @@
//! Footer usage for the spike, fed by real probes through the real ledger.
//!
//! Profiles are *declared*; numbers are not. A profile exists as soon as the
//! shell knows a pane is running a harness, so the footer can name the account
//! it cannot read. Observations only ever come from a [`UsageProbe`]. A harness
//! with no adapter yet therefore renders the honest-gap path under its own
//! name — "Claude Code · Anthropic · … usage unavailable" — rather than
//! borrowing another pane's number or showing a zero.
//!
//! The only adapter that exists today is the Codex quota probe. It is started
//! at launch unless `LUMBRIDGE_CODEX_PROBE=0` is set, and if the `codex` binary
//! is absent the probe simply fails to start and its profiles keep rendering as
//! unavailable.
use std::collections::BTreeMap;
use lumbridge_core::{
AccountProfile, AccountProfileId, FooterUsage, UsageLedger, UsageProjection, UsageProvenance,
format_duration_ms,
};
use lumbridge_harness::claude::{ClaudeCodeProbe, ClaudeCodeProbeOptions};
use lumbridge_harness::codex::{CodexProbe, CodexProbeOptions};
use lumbridge_harness::{MonotonicWallClock, ProbeHealth, UsageProbe};
use crate::panel_registry::SeedPane;
/// Harnesses the seeded panes run, whether or not an adapter exists for them.
struct DeclaredProfile {
seed: SeedPane,
id: &'static str,
harness: &'static str,
provider: &'static str,
model: &'static str,
account: &'static str,
}
/// Only harnesses with a real adapter behind them.
///
/// A third entry declared "Pi · spark-1 · laguna-s-2.1 · self-hosted" with no
/// probe of any kind, so the strip carried a permanent empty rail for a harness
/// the user was not running. Declaring a profile is a promise that the gap is
/// real; declaring one nothing can ever fill is just a fabricated row.
///
/// The seed mapping stays: it is how a live reading lands under the pane that
/// produced it, once a harness can actually be launched into a pane.
const DECLARED: &[DeclaredProfile] = &[
DeclaredProfile {
seed: SeedPane::CodexRuntime,
id: "codex-app-server-primary",
harness: "Codex",
provider: "ChatGPT",
model: "primary window",
account: "subscription",
},
// The Claude pane maps to the five-hour window, not the token total: it is
// the limit that actually stops work, and it is what "how much do I have
// left" means. The transcript total is still declared by the probe and
// still shows in the strip once it reports.
DeclaredProfile {
seed: SeedPane::ClaudeUi,
id: "claude-code-five-hour",
harness: "Claude Code",
provider: "Anthropic",
model: "five-hour window",
account: "subscription",
},
];
pub(crate) struct UsageFeed {
ledger: UsageLedger,
clock: MonotonicWallClock,
profiles: BTreeMap<AccountProfileId, AccountProfile>,
seeds: Vec<(SeedPane, AccountProfileId)>,
probes: Vec<Box<dyn UsageProbe>>,
health: BTreeMap<AccountProfileId, ProbeHealth>,
probe_status: String,
}
/// Which probes to start.
///
/// Passed in rather than read from the environment inside the constructor:
/// a test that wanted a probe-free feed used to set a process-wide environment
/// variable, which required `unsafe` and silently disabled both probes for
/// every other test in the binary.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct UsageFeedOptions {
pub(crate) codex: bool,
pub(crate) claude: bool,
}
impl UsageFeedOptions {
/// Reads the documented opt-out switches. The only place the environment
/// is consulted, so a caller can always ask for something else.
fn from_env() -> Self {
let enabled = |name: &str| std::env::var_os(name).is_none_or(|value| value != "0");
Self {
codex: enabled("LUMBRIDGE_CODEX_PROBE"),
claude: enabled("LUMBRIDGE_CLAUDE_PROBE"),
}
}
/// Declares every profile and starts nothing.
#[cfg(test)]
pub(crate) const fn none() -> Self {
Self {
codex: false,
claude: false,
}
}
}
impl UsageFeed {
pub(crate) fn start() -> Self {
Self::start_with(UsageFeedOptions::from_env())
}
pub(crate) fn start_with(options: UsageFeedOptions) -> Self {
let mut profiles = BTreeMap::new();
let mut seeds = Vec::new();
for declared in DECLARED {
let Ok(profile) = AccountProfile::new(
declared.id,
declared.harness,
declared.provider,
declared.model,
declared.account,
) else {
continue;
};
seeds.push((declared.seed, profile.id().clone()));
profiles.insert(profile.id().clone(), profile);
}
let mut feed = Self {
ledger: UsageLedger::new(),
clock: MonotonicWallClock::start(),
profiles,
seeds,
probes: Vec::new(),
health: BTreeMap::new(),
probe_status: "no usage adapter running".to_owned(),
};
feed.start_codex_probe(options.codex);
feed.start_claude_probe(options.claude);
feed
}
/// Starts the Codex quota probe unless the user opted out.
///
/// A failure here is not an error state for the shell: the profiles stay
/// declared and render as unavailable, which is exactly what they should do
/// when no adapter can run.
fn start_codex_probe(&mut self, enabled: bool) {
if !enabled {
"codex probe disabled".clone_into(&mut self.probe_status);
return;
}
match CodexProbe::start(CodexProbeOptions::default()) {
Ok(probe) => {
for profile in probe.profiles() {
self.profiles
.entry(profile.id().clone())
.or_insert_with(|| profile.clone());
self.health
.insert(profile.id().clone(), ProbeHealth::Starting);
}
self.probes.push(Box::new(probe));
"codex probe starting".clone_into(&mut self.probe_status);
}
Err(error) => {
self.probe_status = format!("codex probe unavailable · {error}");
}
}
}
/// Starts the Claude Code transcript probe unless the user opted out.
///
/// This one reads files rather than launching anything, so it has no
/// harness to fail to find — a missing projects directory simply reports
/// nothing until Claude Code creates it.
fn start_claude_probe(&mut self, enabled: bool) {
if !enabled {
// Say so, rather than leaving whatever the Codex path last wrote.
// A disabled probe that reports nothing about itself is
// indistinguishable from one that failed to start.
"claude probe disabled".clone_into(&mut self.probe_status);
return;
}
match ClaudeCodeProbe::start(ClaudeCodeProbeOptions::default()) {
Ok(probe) => {
for profile in probe.profiles() {
self.profiles
.entry(profile.id().clone())
.or_insert_with(|| profile.clone());
self.health
.insert(profile.id().clone(), ProbeHealth::Starting);
}
self.probes.push(Box::new(probe));
}
Err(error) => {
self.probe_status = format!("claude probe unavailable · {error}");
}
}
}
/// Which declared profile a seeded panel belongs to.
///
/// Panels created at runtime are plain shells with no harness, so they map
/// to nothing rather than borrowing another pane's account.
pub(crate) fn profile_for_seed(&self, seed: Option<SeedPane>) -> Option<&AccountProfileId> {
let seed = seed?;
self.seeds
.iter()
.find(|(candidate, _)| *candidate == seed)
.map(|(_, id)| id)
}
/// Drains every probe into the ledger. Returns whether anything changed.
pub(crate) fn tick(&mut self) -> bool {
let mut changed = false;
for probe in &mut self.probes {
let outcome = probe.poll();
let health = outcome.health();
for profile in probe.profiles() {
// A probe may announce a profile after it starts: the per-model
// weekly limits are named by the provider's response, so they
// cannot be declared up front. Without this they would report
// readings the strip has no profile to render them against.
if self
.profiles
.insert(profile.id().clone(), profile.clone())
.is_none()
{
changed = true;
}
if self.health.insert(profile.id().clone(), health) != Some(health) {
changed = true;
}
}
for observation in outcome.into_observations() {
// A rejected observation is a real signal, not a crash: the
// ledger refuses anything that would move a profile's stream
// backwards. Dropping it preserves the append-only invariant.
if self.ledger.record(observation).is_ok() {
changed = true;
}
}
}
if changed {
self.probe_status = self.summarize_health();
}
changed
}
fn summarize_health(&self) -> String {
if self.probes.is_empty() {
return "no usage adapter running".to_owned();
}
let ready = self
.health
.values()
.filter(|health| matches!(health, ProbeHealth::Ready))
.count();
let faulted = self
.health
.values()
.filter(|health| health.is_faulted())
.count();
if faulted > 0 {
return format!("{} probes · {faulted} faulted", self.probes.len());
}
format!("{} probes · {ready} ready", self.probes.len())
}
pub(crate) fn probe_status(&self) -> &str {
&self.probe_status
}
fn projection(&self, id: &AccountProfileId) -> UsageProjection {
self.ledger.project(id, self.clock.last_emitted_ms())
}
/// Advances the feed's read clock. Kept separate from [`Self::tick`] so
/// rendering never mutates the clock mid-frame.
pub(crate) fn advance(&mut self) {
let _ = self.clock.now_ms();
}
/// Every harness the footer should account for, in a stable order.
///
/// The seeded panes come first so the strip does not reorder itself as
/// readings arrive, then any probe profile that has actually reported. A
/// probe profile with nothing to say — Codex's secondary window on an
/// account that has none — is left out rather than shown as an empty rail,
/// because the strip is for harnesses the user is running, not for every
/// row a probe could theoretically fill.
pub(crate) fn strip(&self) -> Vec<UsageSegment> {
let mut ordered: Vec<&AccountProfileId> = self.seeds.iter().map(|(_, id)| id).collect();
for id in self.profiles.keys() {
if !ordered.contains(&id) && self.projection(id).is_available() {
ordered.push(id);
}
}
let mut segments: Vec<UsageSegment> = ordered
.into_iter()
.filter_map(|id| self.segment(id))
.collect();
// Keep one harness's quotas together. Claude Code alone reports four,
// and a strip that interleaves them with Codex reads as eight unrelated
// numbers instead of two accounts. Stable within a group, so a segment
// never moves under the pointer.
let mut order: Vec<String> = Vec::new();
for segment in &segments {
if !order.contains(&segment.label) {
order.push(segment.label.clone());
}
}
segments.sort_by_key(|segment| {
(
order
.iter()
.position(|label| *label == segment.label)
.unwrap_or(usize::MAX),
// Quotas before spend within a harness. "How much is left" is
// the question; "how much was used" is the footnote.
usize::from(segment.consumed_permille.is_none()),
)
});
segments
}
/// The shortest unambiguous name for a quota window.
///
/// The provider's own wording — "five-hour window", "Fable weekly" — is
/// right in a detail view and far too long in a strip that has to hold six
/// of them.
fn short_scope(model: &str) -> String {
match model {
"five-hour window" => "5h".to_owned(),
"seven-day window" => "7d".to_owned(),
"session transcripts" => "tokens".to_owned(),
other => other
.strip_suffix(" weekly")
.map_or_else(|| other.to_owned(), |name| format!("{name} wk")),
}
}
fn segment(&self, id: &AccountProfileId) -> Option<UsageSegment> {
let profile = self.profiles.get(id)?;
let projection = self.projection(id);
let footer = FooterUsage::new(profile, &projection);
let consumed_permille = projection.consumed_permille();
Some(UsageSegment {
id: id.clone(),
label: profile.harness().to_uppercase(),
scope: Self::short_scope(profile.model()),
consumed_permille,
// "How much do I have left" is the question an engineer actually
// asks. Consumption stays available in the expanded detail.
// With a ceiling, lead with what is left. Without one, the honest
// headline is what was spent — a profile that reports real
// consumption but no quota must not read as "no reading".
//
// Show a decimal only when the value actually has one. Codex
// reports whole percents, so "81.0% left" would claim a tenth of a
// percent of resolution that no one measured.
headline: consumed_permille
.map(|permille| {
let left = 1_000_u64.saturating_sub(permille);
if left % 10 == 0 {
format!("{}% left", left / 10)
} else {
format!("{}.{}% left", left / 10, left % 10)
}
})
.or_else(|| {
let consumed = projection.consumed()?;
let unit = projection.unit()?;
Some(format!("{} used", unit.format_amount(consumed)))
}),
// Ten percent of a window is the point at which the number stops
// being background information and starts being a decision about
// what to run next.
critical: consumed_permille.is_some_and(|permille| permille >= 900),
// A profile that reports spend but no ceiling and no reset should
// say so where the reset would go, rather than leaving a silent
// gap that reads as "we just haven't shown it yet".
reset: projection.resets_in_ms().map_or_else(
|| {
(projection.is_available() && projection.limit().is_none())
.then(|| "no quota reported".to_owned())
},
|remaining| Some(format!("resets {}", format_duration_ms(remaining))),
),
burn: footer.burn(),
burn_provenance: projection.burn_provenance(),
trust: footer.trust(),
provenance: projection.provenance(),
})
}
/// Profiles that have produced at least one usable reading.
pub(crate) fn reporting_profile_count(&self) -> usize {
self.profiles
.keys()
.filter(|id| self.projection(id).is_available())
.count()
}
pub(crate) fn declared_profile_count(&self) -> usize {
self.profiles.len()
}
pub(crate) fn shutdown(&mut self) {
for probe in &mut self.probes {
probe.shutdown();
}
self.probes.clear();
}
}
impl Drop for UsageFeed {
fn drop(&mut self) {
self.shutdown();
}
}
/// One harness's standing in the footer strip.
///
/// `remaining` and `reset` are `None` when there is nothing to report. That is
/// deliberately not an empty string: the renderer has to decide what a gap
/// looks like rather than printing a blank where a number belongs.
pub(crate) struct UsageSegment {
pub(crate) id: AccountProfileId,
pub(crate) label: String,
/// The window this segment is about, in the shortest form that stays
/// unambiguous: `5h`, `7d`, `fable wk`, `tokens`. One account has several
/// quotas and the strip has to name which one it is showing.
pub(crate) scope: String,
pub(crate) consumed_permille: Option<u64>,
/// What to lead with: how much is left when a ceiling is known, how much
/// was spent when it is not, and nothing at all when there is no reading.
pub(crate) headline: Option<String>,
/// Nearly gone. Drives the headline's colour, never the meter's: the meter
/// carries provenance, and mixing the two would make a trustworthy reading
/// and an alarming one look the same.
pub(crate) critical: bool,
pub(crate) reset: Option<String>,
pub(crate) burn: String,
pub(crate) burn_provenance: UsageProvenance,
pub(crate) trust: String,
pub(crate) provenance: UsageProvenance,
}
#[cfg(test)]
mod tests {
use super::{DECLARED, UsageFeed, UsageFeedOptions};
use crate::panel_registry::SeedPane;
use lumbridge_core::UsageProvenance;
/// Never starts a probe, so the test cannot depend on an installed harness,
/// on the user's transcripts, or on a status-line bridge being present.
fn declared_only_feed() -> UsageFeed {
UsageFeed::start_with(UsageFeedOptions::none())
}
#[test]
fn a_declared_harness_with_no_adapter_shows_a_gap_under_its_own_name() {
let feed = declared_only_feed();
let segment = feed
.strip()
.into_iter()
.find(|segment| segment.label.starts_with("CLAUDE CODE"))
.expect("Claude Code is declared");
assert!(
segment.headline.is_none(),
"a harness with no adapter must not show a number"
);
assert_eq!(segment.trust, "no usage source");
}
#[test]
fn panels_without_a_seed_have_no_profile() {
let feed = declared_only_feed();
assert!(feed.profile_for_seed(None).is_none());
assert!(
feed.profile_for_seed(Some(SeedPane::Architecture))
.is_none()
);
}
#[test]
fn nothing_reports_until_a_probe_produces_a_reading() {
let feed = declared_only_feed();
assert_eq!(feed.declared_profile_count(), DECLARED.len());
assert_eq!(
feed.reporting_profile_count(),
0,
"declaring a profile must not imply a reading"
);
}
#[test]
fn the_codex_pane_maps_onto_the_probe_profile_id() {
let feed = declared_only_feed();
let id = feed
.profile_for_seed(Some(SeedPane::CodexRuntime))
.expect("the Codex pane declares a profile");
assert_eq!(
id.as_str(),
"codex-app-server-primary",
"a live reading must land under the pane that produced it"
);
}
#[test]
fn the_strip_lists_every_declared_harness_even_with_no_readings() {
let feed = declared_only_feed();
let strip = feed.strip();
assert_eq!(strip.len(), DECLARED.len());
let labels: Vec<&str> = strip.iter().map(|segment| segment.label.as_str()).collect();
assert_eq!(labels, ["CODEX", "CLAUDE CODE"]);
for segment in &strip {
assert!(
segment.headline.is_none() && segment.reset.is_none(),
"a harness with no adapter must report no figure at all"
);
assert!(!segment.provenance.is_available());
assert_eq!(segment.provenance, UsageProvenance::Unavailable);
}
}
#[test]
fn a_fractional_reading_keeps_its_decimal() {
use lumbridge_core::{UsageObservation, UsageUnit, UsageWindow};
let mut feed = declared_only_feed();
let id = feed
.profile_for_seed(Some(SeedPane::CodexRuntime))
.expect("declared")
.clone();
feed.advance();
let now_ms = feed.clock.last_emitted_ms();
feed.ledger
.record(
UsageObservation::counted(
id.clone(),
UsageUnit::WindowPermille,
185,
UsageProvenance::ProviderReported,
now_ms.saturating_sub(1_000),
)
.expect("available")
.with_limit(1_000)
.expect("a positive limit")
.with_window(UsageWindow::until(now_ms + 3_600_000))
.expect("inside the window"),
)
.expect("ordered");
let segment = feed
.strip()
.into_iter()
.find(|segment| segment.id == id)
.expect("present");
assert_eq!(segment.headline.as_deref(), Some("81.5% left"));
}
#[test]
fn a_segment_reports_what_is_left_not_what_was_used() {
use lumbridge_core::{UsageObservation, UsageUnit, UsageWindow};
let mut feed = declared_only_feed();
let id = feed
.profile_for_seed(Some(SeedPane::CodexRuntime))
.expect("the Codex pane declares a profile")
.clone();
// The feed reads a real wall clock, so the fixture has to sit inside a
// window that is still open now rather than at an arbitrary epoch.
feed.advance();
let now_ms = feed.clock.last_emitted_ms();
feed.ledger
.record(
UsageObservation::counted(
id.clone(),
UsageUnit::WindowPermille,
180,
UsageProvenance::ProviderReported,
now_ms.saturating_sub(1_000),
)
.expect("available")
.with_limit(1_000)
.expect("a positive limit")
.with_window(UsageWindow::until(now_ms + 3_600_000))
.expect("inside the window"),
)
.expect("ordered");
let segment = feed
.strip()
.into_iter()
.find(|segment| segment.id == id)
.expect("the Codex segment is present");
assert_eq!(
segment.headline.as_deref(),
Some("82% left"),
"a whole-percent source must not render a tenth it never measured"
);
assert_eq!(segment.consumed_permille, Some(180));
assert_eq!(
segment.reset.as_deref(),
Some("resets 1h 0m"),
"a windowed reading reports its reset"
);
}
#[test]
fn a_segment_with_no_reading_offers_no_figure_to_render() {
let feed = declared_only_feed();
for segment in feed.strip() {
assert!(segment.headline.is_none());
assert!(segment.reset.is_none());
assert!(
!segment.burn.contains("/hr"),
"a rate needs readings this segment does not have"
);
assert_eq!(segment.consumed_permille, None);
}
}
}