Imported from tuist/tuist (
server/lib/tuist_web/live/AGENTS.md). Install upstream withnpx skills add tuist/tuist --skill live. Copyright stays with the author.
Live (Web Layer)
This area owns LiveView pages and components for the web UI.
Responsibilities
- Login and sign-up mount the shared
GoogleOneTaphook; navigation cancels pending browser sign-in. Other authentication screens allow the required resources for later LiveView navigation but do not mount the chooser. - Automation forms show the name followed by independently collapsible When (condition), What (actions), and Recovery sections with one-sentence summaries. Creation starts with When and What expanded and Recovery collapsed; editing starts with all three collapsed. Metric automation forms keep the one-time checkbox immediately above Create/Save to apply actions to existing matches, including Slack. Its description states that, unchecked, tests that currently match get no actions unless they recover and match again. Show a read-only asynchronous count of currently eligible matches; refresh it on modal opening and condition/state changes, cancel stale requests, and keep save available if counting fails. Reset the checkbox on every modal opening and reflect the choice in the submit label. Record the request in history, not as an ongoing condition; event-driven automations do not expose it.
- Xcode cache task rows asynchronously preload the first 20 CAS outputs for displayed expandable tasks after the LiveView connects. Successful empty loads remove the disclosure and close the row; failures retain expansion so they can be retried. Collapse retains loaded pages and pending requests for immediate re-expansion; filtering, sorting, task-page changes, tab changes, and build refresh cancel pending loads and clear loaded output pages. Load more appends the next batch while keeping existing outputs visible, prevents duplicate requests, and retries failed batches without skipping them. Expanded rows show loading and error states; failed preloads retry on expansion.
- Module cache miss widgets, charts, filters, and history share four reasons: Changed, Upstream, Cold, and Evicted. History rows show a reason badge and tooltip; classification and prior remote-hit evidence belong in Builds.Analytics. Test-only runs read Module Cache results from their original build event when their own event has no lookups; the fallback is project scoped and never changes reported counts.
- Xcode machine metrics with recorded build-relative offsets appear as shared-clock tracks in Timeline; legacy metrics without an offset retain the Machine Metrics tab. Samples travel in a small hook reply independently of the step metadata download.
- Render LiveView pages and handle UI events.
- The Xcode build detail loads only the selected tab's breakdown/cache queries. The Timeline hook downloads all step metadata from the authorized
timeline.jsonHTTP endpoint (compressed by Bandit), while a small hook reply delivers machine metrics immediately. Step metadata never enters LiveView assigns or HTML. Keep metrics interactive above the step skeleton while metadata loads; abort downloads on navigation and reload on build completion. Keyboard navigation and step logs use cancellable async tasks scoped to the current build. Zoom, pan and search use the full metadata locally, with the full build duration initially visible. Older builds may have no timeline data. - Orchestrate UI state while delegating domain operations to
server/lib/tuist. - Module-cache pages reuse their loaded breakdown for charts. Relative date presets stay fixed across table and widget patches; changing the date selection or remounting creates a new snapshot. Detail history filters refresh their relative window without reloading analytics or branch choices; cursor pagination retains the history window. Failed async loads retry on a matching patch while successful or in-flight loads are reused. Module count failure only affects its widget value; charts gate on their own series. Detail totals cover every product under the selected module name.
- Bazel exposes test case automations through the shared project settings tabs. Keep quarantine setup and target-level skipping guidance in the Bazel flaky-tests documentation, not page banners.
- Bazel's Skipped policy option explains whole-target exclusion, including healthy tests, at the manual and automation action menus. Keep this guidance scoped to Bazel.
- Xcode overview charts opt into Noora's
data-lazy="true"behavior so charts below the viewport do not initialize while the visible analytics are loading.
Boundaries
- Domain logic belongs in
server/lib/tuistcontexts. - Frontend assets are in
server/assets.
Related Context
-
Web layer overview:
server/lib/tuist_web/AGENTS.md -
Business logic:
server/lib/tuist/AGENTS.md -
Gradle task analytics live under Builds at
/builds/tasksinGradleTasksLive. Omit the Tasks list heading and subtitle; retain the task name on detail pages. Task executions use the Gradle build runs Project cell (root project name and tags) and shared Ran by badge (CI, account name, or Unknown), retaining whole-row navigation to the execution detail. Task outcome badges use Succeeded (green), Failed (red), cache hits (blue), Up-to-date (purple), and skipped/no-source (neutral), consistently with the per-build tasks table. They follow the Test Case Runs table pattern: search, sorting, Branch filter, outcome/Ran by badges, duration, relative timestamps, and pagination. Task details show analytics and Task executions, with no Execution profile card. They have only Executions, Cache hit rate, and duration widgets; Executions is selected by default, and an inherited Tasks widget selection on detail falls back to Executions. Use the Builds-style Environment dropdown beside the date picker; limit table filters to Branch, applying the same cohort to analytics and history. Widget and metric selections replace the current browser history entry so Back returns to the preceding page. Use the shared Noora filter and sort menus in the task table toolbar, active filter chips, selectable widgets and chart for task analytics. The Cache hit rate widget charts a percentage from 0–100 with percentage-point trends (higher is better). Non-cacheable/unknown tasks show an explicit unavailable state without a numeric rate or trend. Legacy hits/misses widget URLs select hit rate. The duration widget defaults to p90 and switches between average and p50/p90/p99, using lowercase percentile labels. Keep cumulative task time in the table only. The duration chart includes the average and all three percentile series with a selectable legend, connects across unsampled intervals, and marks recorded samples (including genuine zero durations); duration increases are negative (red) and decreases positive (green); show “No change” when both values are zero, absolute changes when only the previous value is zero, and percentages otherwise; task duration columns use p50/p90/p99 like test cases. Show 0% for cacheable tasks without hits. When no hit rate is available, show Not cacheable or Unknown cacheability badges. Use Noora table cells for consistent column alignment and the Test Runs section spacing. Let the Noora table own horizontal scrolling so outer wrappers do not clip its border. Keep metrics inTuist.Gradleand its subcontexts. -
Gradle build Cache Summary uses five widgets: Task hits, Task misses, Hit rate, Cache downloads, and Cache uploads. Keep remote-miss diagnostics in task-level inspection rather than additional summary cards.
-
GradleTaskExecutionLiverenders/builds/build-runs/:build_run_id/tasks/:task_id. Scope lookups to both the selected project and parent build. Build Tasks, cacheable tasks, and task-overview execution rows navigate here. The page links back to its build and to the task overview with root project, build path, task path, and type preserved. Use sharedHelpers.GradleTaskoutcome labels and colors. -
Task execution details use one compact summary card (duration, runner, timestamp, cacheability, branch, shortened commit); show build identity and incremental status as further metadata rows. Display the root build path (
:) as “Root build”. Omit raw execution reasons, caching-disabled explanations and dependency navigation. Use a single Cache badge for Not cacheable or the observed cache result (hit, local hit, miss, error), falling back to Cacheable or Unknown cacheability when no result is available; omit a separate Remote lookup field. Reuse VCS branch/commit links. -
GitLab CI connections in Integrations take only an instance URL and runner token. GitLab and Buildkite cards share
runner_integrations_visible?, derived from the account runners feature flag. Disconnect replaces Connect in the card header after connecting; show the instance URL only in its editable field. Each job selects an account-owned profile through its pipeline tags. Never repopulate token inputs; job detail views load account-scoped metadata without execution payloads. -
GitLab disconnect disables the connection immediately and leaves upstream settlement to background polling; the disabled connection renders a pending notice and a disabled Disconnect action.
-
Runner job detail omits the whole Insights card unless at least one build or test run matches the runner job; candidate account projects alone do not justify an empty card. GitLab jobs link to their GitLab instance and omit the structured Steps card, which currently receives data only from GitHub completion webhooks; GitLab execution output remains available in Logs.
-
BuildTimelineLoaderowns lazy metric bootstrapping, build identity, versioning, tab reentry and forced refresh for Xcode, Gradle and Bazel. It cancels superseded bootstrap tasks and rejects stale/inactive-tab hook requests. Step metadata stays out of LiveView state: every source supplies an authorized HTTP URL tobuild_timeline_section, which shares loading/error UI. Xcode keeps cancellable server navigation/log tasks; Gradle and Bazel navigate downloaded steps locally, with Bazel logs loaded separately when available. -
Gradle and Bazel detail tabs follow Xcode: Overview, Timeline, then cache and source-specific tabs. Gradle machine metrics appear only in Timeline; legacy
tab=machine-metricslinks open Timeline without eagerly loading samples on other tabs. -
Humanize display counts with
format_number/2(10,000+ uses K/M/B/T), including table cells and dropdown values. Keep chart series, sort keys, filters, and pagination inputs numeric. -
GitLab edit forms submit the connection identifier as
_idand remap it to the context’sid; never usename="id"on an input because it shadows the form DOM property used by LiveView. -
Automation match previews use one stable async key and a 500ms condition-change debounce. Keep condition validation consistent across the summary, preview, and save path, including required event selections for event-driven monitors; an unchecked explicit save cancels pending existing-match actions.
-
Only expose Timeline when the selected build has recorded steps or aligned machine samples. Shared
BuildTimelineLoader.select_tab/3falls back to Overview for unavailable direct links; Xcode processing refreshes recheck availability. Bazel requires a published profile; retained summary spans alone do not qualify. Availability checks use scoped existence/scalar queries, never full step downloads.