Mirrors `fabro model list` output below the existing Providers panel.
Server-side provider + query filters, debounced search, sortable
columns, and a hover/focus popover that surfaces model aliases.
Genericizes SortHeader so non-runs tables can reuse it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hovering the clock chip on a run header now reveals wall-clock-since-created
alongside active (inference + tools) time. Also extends formatDurationMs to
render hours and days for long-running runs instead of inflating minutes.
Large GiB values rendered without separators (2173 GiB). Format the
numeric part with toLocaleString so it reads 2,173 GiB.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The resources page mixed precise and rounded values (8.2%, 5.0s,
51.8 GiB). Round everything to whole units for at-a-glance reading.
Add an optional fractionDigits param to formatBytesAsMemory and
formatDurationMs (default 1, so sandbox memory limits and turn
durations keep their decimals) and have settings-resources opt into
fractionDigits 0. formatPercent now uses Math.round.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
build_disk_usage_response only summed scratch/ run dirs and logs/*.log,
omitting objects/ (SlateDB + artifacts), sessions/, and vaults/ — a ~30x
undercount of "Fabro managed" storage on the resources page.
Measure the whole storage_dir tree for total_size_bytes so it can't drift
as new subdirectories are added. Reclaimable stays a curated estimate that
matches what `fabro system prune` actually frees. A residual "other"
summary row keeps `fabro system df` totals consistent and surfaces as a
"Database & artifacts" table row.
Also add a KiB tier to formatBytesAsMemory so small storage values render
human-readably instead of raw byte counts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
Adds server-visible resource reporting and a compact Resources settings
tab for CPU, memory, and the filesystem that contains Fabro storage.
## Changes
- Adds `GET /api/v1/system/resources` backed by `sysinfo`, including CPU
sampling, cgroup-aware memory reporting, storage filesystem matching,
and Fabro-managed disk byte totals.
- Extends the OpenAPI contract and regenerates the Rust and TypeScript
API clients.
- Adds a deterministic demo-mode resources route.
- Adds `/settings/resources` with 5 second polling and panels for
overview, CPU, memory, disk, and notes.
- Adds server integration/unit coverage and web route/render coverage.
## Screenshot

## Verification
- `cargo build -p fabro-api`
- `cd lib/packages/fabro-api-client && bun run generate`
- `cargo nextest run -p fabro-server --features test-support --test it
api::system`
- `cargo test -p fabro-server resource_sampler::tests`
- `cd apps/fabro-web && bun test`
- `cd apps/fabro-web && bun run typecheck`
- `cd apps/fabro-web && bun run build`
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy --workspace --all-targets -- -D
warnings`
---
[](https://github.com/compound-engineering)
🤖 Generated with GPT-5 via [Codex](https://openai.com/codex)
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
Promotes the most useful per-run state into the Overview tab so users no
longer have to tab-hop to read the basics of a run.
- **Adds a horizontal summary panel** above the workflow graph (right
column only — does not span the stages sidebar) with five columns:
**Created by · Changes · Sandbox · Cost · Artifacts**. Quiet-uppercase
labels (`text-[10px] uppercase tracking-[0.08em] text-fg-muted`) over
regular-weight values. Skeleton loaders while queries are in flight; em
dash in muted color for missing/zero data.
- **Promotes the PR chip** out of the meta strip into a
`SECONDARY_BUTTON_CLASS`-style pill next to the Actions menu, visible on
every tab. Pill renders only when a PR exists.
- Lifts `formatBytesAsMemory`, `formatCpuCores`, `formatUsdMicros` to
`lib/format.ts` so the panel can reuse them.
- New `RunSummaryPanel` is split into a smart wrapper (owns the SWR
hooks) + a presentational `RunSummaryPanelView` (prop-driven) for clean
test seams.
- All 7 `Principal` kinds (user / agent / system / slack / webhook /
worker / anonymous) map to glyph + label; user kind uses login-initial
avatar.
## Screenshots
Captured against a real local Fabro server (`fabro server start`) on
demo runs — these only exercise the Created-by column (the other cells
display em dashes because the demo runs have no PR / diff / billing /
artifacts data). The em-dash states **are** the intended empty-state
design.
### Overview tab — full page

### Header + tabs + summary panel close-up

### Summary panel detail

> The PR pill (mint icon + `#number` next to Actions) is unverified
visually because no demo run on this server has an associated PR — but
the rendering path is the same `SECONDARY_BUTTON_CLASS` markup as the
Actions button and is conditioned on `run.pullRequestUrl && run.number
!= null`. See the [HTML
prototype](https://github.com/fabro-sh/fabro/blob/feat/run-overview-summary-panel/.context/run-overview-options.html)
for the locked design.
## Test plan
- [x] `cd apps/fabro-web && bun run typecheck` clean (only pre-existing
assistant-ui errors)
- [x] `bun test` — +12 new passes, no new failures (387 pass / 5 fail /
2 errors vs baseline 375 / 6 / 3)
- [x] Manual: load `/runs/<id>` against a real server, confirm panel +
em dashes render correctly
- [ ] Manual on a run **with** a PR: verify the pill appears next to
Actions and opens the PR in a new tab
- [ ] Manual on a run **with** rich data (diff / billing / sandbox
resources / artifacts): verify each column populates correctly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary
This is a cleanup pass over the configurable LLM provider/catalog work
from issue #210. It addresses reuse, quality, and efficiency findings
from the phase 0-9 review without changing the public provider settings
contract.
Notable changes:
- skip LLM client initialization during run preflight when the workflow
has no LLM nodes
- make preflight provider checks use alias-aware `Client::has_provider`
- resolve `run.model.fallbacks` through the catalog instead of the old
empty-key bridge
- paginate `/models` before cloning returned rows
- share label parsing, provider default-adapter lookup, enum
expected-value formatting, and billing token formatting helpers
- use catalog provider display names for OpenAI-compatible agent
profiles
- align process-env configured-provider discovery with
`EnvCredentialSource`
## Verification
- `cargo check -p fabro-config -p fabro-model -p fabro-auth -p
fabro-agent -p fabro-workflow -p fabro-server -p fabro-cli`
- `cargo nextest run -p fabro-config parse_labels_keeps_key_value_pairs`
- `cargo nextest run -p fabro-workflow resolve_fallback_chain_resolves`
- `cargo nextest run -p fabro-auth configured_providers`
- `cargo nextest run -p fabro-server list_models`
- `cargo +nightly-2026-04-14 fmt --check --all`
- `cargo +nightly-2026-04-14 clippy -p fabro-model -p fabro-auth -p
fabro-workflow -p fabro-server -p fabro-agent -p fabro-config -p
fabro-cli --all-targets -- -D warnings`
- `cd apps/fabro-web && bun test app/routes/run-billing.test.tsx`
- `cd apps/fabro-web && bun run typecheck`
- `git diff --check`
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reuse shared frontend formatting and SSE dedupe helpers, tighten typed sandbox handling, remove obsolete run DTOs, and collapse auth-session revoke into a single store operation.
Replaces native title attribute with a portal-based Tooltip component on
the events-feed elapsed times and the run header's last-event timestamp,
showing the full datetime (e.g. "04/24/2026, 1:23:40 PM") on hover.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a `last_event_at` timestamp to RunProjection (set in apply_event so
every event ticks the field) and surface it through RunSummary and the
RunListItem board response. Backed by an OpenAPI extension so both the
Rust and TypeScript clients pick up the new optional field.
In the web UI, the run-detail header gains a "Last activity Xm ago"
badge next to the elapsed-time chip, driven by a 30-second ticker so the
relative time stays current between event refreshes.
The fabro-server tests.rs hunk is incidental rustfmt drift surfaced by
running `cargo fmt --all` over the workspace; including it keeps CI's
fmt-check green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop unjustified useMemo around byteCount, add void to mutate(), let
errorMessage return undefined for non-Error values so the description
doesn't duplicate the retry button label, and reuse formatBytes (hoisted
to lib/format.ts from insights-editor) so log size renders as "1.23 MB"
instead of "1,234,567 bytes".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>