I4200 — A warm UI screen borrows what its sources answered and writes its page once, so a plan of any size is not copied per request
Make the warm request path of /ui copy nothing it already holds: read the intents, issues, waves and scope pairs through view::items (borrowed) instead of view::list (a deep copy) in ui/issues.rs, ui/idd.rs (screen, render, choice, wave_panel) and ui/intent.rs's inspector; move a screen's tree into its page in ui/shell.rs::page instead of cloning it; and escape text and attribute values straight into the page buffer in cockpit/html.rs instead of through a new String each.
READY wave 0 · p1 · implementation profile · runs alone
Part of M004 — Performance is executable evidence, and the hot path does no canonical work twice.
Ready. Every dependency is done, so majordomus plan start I4200 will be accepted.
Objective
Make the warm request path of /ui copy nothing it already holds: read the intents, issues, waves and scope pairs through view::items (borrowed) instead of view::list (a deep copy) in ui/issues.rs, ui/idd.rs (screen, render, choice, wave_panel) and ui/intent.rs's inspector; move a screen's tree into its page in ui/shell.rs::page instead of cloning it; and escape text and attribute values straight into the page buffer in cockpit/html.rs instead of through a new String each.
Why
Train 5's ui-checks step 'every warm screen of the UI is within its budget' failed on #2403: system.http.ui.idd warm p95 108.3 ms and system.http.ui.issues 106.6 ms against 100 ms, and both sat at 95-110% of the budget on every runner. The data comes from cached readings, so warm cost equalled cold cost: every request deep-copied the whole intents list (four times on /ui/idd), every issue of the plan, the whole waves answer with every scope pair of the plan (79% of /ui/idd's render once the first copies were gone), and then the screen's entire element tree again to place it in the page, which on /ui/issues is a ~970 KB page of 976 rows.
Current state
Measured on d078fb2309e, both builds made the same way here (debug, RUSTFLAGS=''), `majordomus bench <id> --transport system --profile ci`, warm p95: system.http.ui.idd 17.9 ms and system.http.ui.issues 35.8 ms. view::list is `items(answer, pointer).to_vec()`; shell::page took &View and did `.child(view.main.clone())`; cockpit::html::El::write called escape(), which returns a new String, for every text and every attribute value.
Desired state
Warm p95 on the same build: system.http.ui.idd 6.4 ms (-64%) and system.http.ui.issues 22.2 ms (-38%), with every screen's output unchanged byte for byte, so both screens sit well inside the 100 ms budget on CI's runners without raising it.
Scope
- .ai/repo/project/issues/I4200.yaml
- apps/majordomus-cli/src/ui/issues.rs
- apps/majordomus-cli/src/ui/idd.rs
- apps/majordomus-cli/src/ui/intent.rs
- apps/majordomus-cli/src/ui/shell.rs
- apps/majordomus-cli/src/ui/mod.rs
- apps/majordomus-cli/src/cockpit/html.rs
Out of scope
- Raising any warm budget
- Paginating /ui/issues, which would change what the screen shows
Dependencies
None. This issue is a root of the graph.
Acceptance criteria
- The ui and cockpit::html unit tests pass unchanged, so every screen renders the same bytes
- bench system.http.ui.idd and system.http.ui.issues warm p95 fall by at least a third against a build of the same commit without the change
- ui-checks' warm-budget step passes on CI without a rerun
Validation
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --lib -- cockpit::html ui::
- majordomus bench system.http.ui.idd --transport system --profile ci --no-write
- majordomus bench system.http.ui.issues --transport system --profile ci --no-write
Evidence required
- warm_screens_copy_nothing
- warm_budget_passes_on_ci
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
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/I4200.yaml. Read it back with majordomus plan show I4200.