Skip to content

I2486 — No screen waits for a source: a page shows the latest reading with its age, read again behind the reader

Take every handler, git call and file read off the path of a UI request: the executor keeps the latest reading of each source a page asked for, a screen is rendered from those readings at once, and a worker reads a source again behind the reader whenever the reading is not of the repository as it is now.

DONE wave 1 · p0 · implementation profile · runs alone

Part of development-runtime — The runtime has a development surface.

Objective

Take every handler, git call and file read off the path of a UI request: the executor keeps the latest reading of each source a page asked for, a screen is rendered from those readings at once, and a worker reads a source again behind the reader whenever the reading is not of the repository as it is now.

Why

The owner said on 2026-10-12 that the UI 'is tragically slow' and is to be solved 'architecturally'. Measured on the UI-performance batch's build (c66f49e406, debug, load 20): /ui 2.2-2.5 s on every request, because health.report (2.4 s, probes, not cacheable) is in its first paint; the first request after a start or a change 5.6-8.1 s for roadmap, evidence and governance, because a cache keyed by the repository's state is empty exactly then; /ui/panels/delivery 75.7 s. A page costs its slowest source and no cache changes that. ADR 0142 records the decision.

Current state

A screen asks its sources through ctx.execute and waits for all of them (ui/source.rs ask_all). A cached source answers at once while the repository stands still; an uncached one and the first read after any change run the handler on the request.

Desired state

capability::readings keeps, per source and input, what it last answered, when, how long it took and in which state of the repository. Context::read hands that over: at once when it is of the repository as it is now, with a worker reading it again behind the caller once it is older than a second; after at most 50 ms, marked stale and refreshing, when the repository has moved, and then every other source read lately is read again too; after waiting for the first reading when there is none, said as pending past a minute. One worker per source, four at once in all, above the executor's own cache and single flight. execute is unchanged and exact. ui::source asks for readings; an answer carries its standing (age, current/stale/pending, refreshing); a source line says a reading's age once it is older than five seconds and says when it predates the last change; a line whose reading is catching up carries data-catching-up and the page's script reads the screen again after 0.4 s, doubling to 6.4 s, until none is left. The first reader of the UI starts one background pass over SCREENS and PANELS. MAJORDOMUS_CAPABILITY_CACHE=off makes a reading run its handler; MAJORDOMUS_READING_PATIENCE_MS sets the patience, and wait makes every read exact.

Scope

  • apps/majordomus-cli/src/capability/readings.rs
  • apps/majordomus-cli/src/capability/executor.rs
  • apps/majordomus-cli/src/capability/handler.rs
  • apps/majordomus-cli/src/capability/mod.rs
  • apps/majordomus-cli/src/ui
  • apps/majordomus-cli/src/http/router.rs
  • apps/majordomus-cli/tests/executor.rs
  • share/ui/ui.js
  • docs/MAJORDOMUS_UI.md
  • docs/CLI.md
  • test/cases/1096_no_screen_waits_for_a_source.sh
  • .ai/repo/adrs/0142-no-screen-waits-for-a-source.md
  • .ai/repo/rules/project/no-screen-waits-for-a-source.v1.md
  • .ai/repo/project/issues/I2486.yaml

Dependencies

What waits on this

Acceptance criteria

  • A source slower than the caller's patience and never read is handed over as pending before its handler finishes, and a caller that then waits joins the same reading: one handler run
  • A source that has been read is handed over without its handler running on the caller's thread, however slow the handler is, and is read again behind the caller once the reading is older than a second
  • After the repository moved, a slow source is handed over as it was, marked stale and refreshing, within the patience; a caller that waits gets the current reading; a source read lately and not asked for is read again
  • A source that fails or panics is a reading that says so, with an age, and is read again
  • A screen whose source is catching up marks that source's line with data-catching-up and says how old the reading is; a screen whose sources are current does not
  • No screen under src/ui calls a handler: outside ui/source.rs and tests, nothing there calls execute
  • With MAJORDOMUS_READING_PATIENCE_MS=0, a served screen answers after a change of the repository without waiting for its sources, and shows the changed value once the readings have caught up

Validation

  • bin/majordomus plan validate
  • cargo test --test executor
  • cargo test --lib ui::
  • MJ_TEST_JOBS=2 bash test/run.sh 1096_no_screen_waits_for_a_source

Evidence required

  • readings_executor_tests
  • ui_standing_unit_tests
  • no_screen_waits_case_1096
  • ui_latency_before_after

Evidence

coverstypecommandresultat commit
readings_executor_teststestcargo test --manifest-path apps/majordomus-cli/Cargo.toml --test executortest result: ok. 17 passed; 0 failed, on a tree equal to master 3442ce68c5; six of them are the readings tests: pending, at once, stale on a move, failure and panic, bounded workers and priority3442ce6
ui_standing_unit_teststestcargo test --manifest-path apps/majordomus-cli/Cargo.toml --lib ui::source && cargo test --manifest-path apps/majordomus-cli/Cargo.toml --lib ui::viewui::source 8 passed, ui::view 17 passed, 0 failed, on a tree equal to master 3442ce68c5: a source line says a reading's age and whether it predates the change3442ce6
no_screen_waits_case_1096testbash test/run.sh 1096_no_screen_waits_for_a_sourceok 1096_no_screen_waits_for_a_source, on a tree equal to master 3442ce68c5: no file under src/ui calls execute, and a served screen after a commit says it is catching up and then shows the new commit3442ce6
ui_latency_before_aftermanualcurl timings against release builds serving one clone, base c66f49e406 against the change (pull request 1041)warm, every screen: 0.12-0.92 s before, 2-12 ms after; first request after a commit: roadmap, evidence and governance 1.2-4.2 s before, 55-140 ms after on a Linux host; /ui 1.2-1.55 s before, 3-162 ms after on a Mac at load 21, slowest single sample 330 ms. Measured on 2026-10-12, not repeated on 3442ce68c5; the Cockpit still computes on the request and is not part of this3442ce6

Timeline

started
2026-10-13T12:45:05Z
verified
2026-10-13T12:45:29Z
completed
2026-10-13T12:47:30Z

Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.

Canonical record: .ai/repo/project/issues/I2486.yaml. Read it back with majordomus plan show I2486.

Searches the titles and descriptions of every page this site publishes.