Commit Graph

13 Commits

Author SHA1 Message Date
Peter Steinberger 8fe2c1b83c perf(ui): consolidate Control UI boot chunk graph for HTTP/1.1 gateways (#128514)
* perf(ui): consolidate Control UI boot chunk graph for HTTP/1.1 gateways

The Control UI boot flow (app shell + sidebar + chat route) lazily loaded
~124 automatic chunks in one burst after the gateway handshake, which the
gateway's HTTP/1.1 transport serializes into ~24 six-connection round-trips
on high-latency links (Tailscale, remote gateways).

Add a measured boot-module manifest (ui/config/control-ui-boot-modules.json,
regenerated via pnpm ui:boot-manifest:gen) and a control-ui-boot codeSplitting
group that merges exactly that module set into a handful of chunks with
recursive dependency inclusion. Lazy islands (locales, ghostty-web, novnc,
non-default routes) keep their own chunks; stale manifest entries degrade
gracefully back to automatic chunking.

Measured on the built dist with the mocked gateway (chat route, 3 runs):
unique boot JS requests 140 -> 45, raw boot JS 3751 -> 3717 KiB, chat
composer interactive at simulated 50 ms RTT ~1600 ms -> ~575 ms.

Largest-CSS budget rises 45 -> 47 KiB for the merged boot CSS; startup JS
gzip baseline ratchets down (345049 -> 339214 B) as consolidation shrinks
the startup graph.

* chore(ui): refresh boot module manifest after rebase onto current main

* fix(ui): stop the pending lazy shell action replay loop starving boot

When a pending lazy shell action (command palette open, panel toggle)
replayed while the shell was still splash-gated, the dispatched event had
no rendered element to consume it and re-entered requestLazyElement in a
microtask cycle: request -> load -> replay -> dispatch -> request. The
cycle starved tasks (Gateway WebSocket messages included), so the boot
never finished and the recovery e2e froze on the splash screen.

Gate replay on the element actually being rendered: the controller skips
the action after load until the host's render root contains the tag, and
restorePendingLazyAction skips dispatch while a defined element is still
render-gated. The host retries after every completed update, so the replay
fires on the update that first renders the element. Regression test fails
on the pre-fix controller.

* fix(ui): re-anchor the scope-upgrade details popover before opening

wa-popover resolves its `for` target once per property change and never
re-resolves a missing or replaced anchor. The trigger with the shared id
can render after the popover's first update (the header trigger ships with
the lazy chat chunk), leaving the opened popover permanently invisible:
active popup with a native [popover] part stuck at UA display:none because
showPopover() never ran without an anchor. Re-arm the watcher when opening
while the anchor is missing or disconnected.

* test(ui): compare settled layouts in device-scope stability assertions

The 0.5px no-move assertions sampled geometry that later reflowed when the
details surface's first render fetched glyph subsets, reporting sub-pixel
drift the open never caused. Burn in the one-time open per context and
sample the baseline adjacent to the click.

* fix(ui): map the keyboard shortcuts dialog in lazy replay gating

Current main added the keyboard-shortcuts lazy shell event; the replay
gate's exhaustive event-to-element record needs its entry.

* chore(ui): refresh startup budget baseline after rebase onto current main
2026-08-24 03:55:37 -07:00
Peter Steinberger 41ed3c3460 fix(ui): buttons use the default cursor instead of the link hand (#126153)
* fix(ui): reserve pointer cursors for links

* test: align cursor and docs contracts
2026-08-18 21:40:52 -07:00
Peter Steinberger 84f342a87e refactor(webui): drop gateway-version fallbacks per version-lock decision (#124971)
* refactor(webui): drop gateway-version fallbacks per version-lock decision

* refactor(webui): drop chat.startup history fallbacks

* test(webui): advertise full method catalog in terminal e2e scenarios

* refactor(webui): enforce the build-identity handshake at connect

* docs(webui): state exempted skew paths fail visibly by design
2026-08-16 23:09:25 -07:00
Peter Steinberger 67a1cdda00 docs(ui): record stylesheet policy (tokens, breakpoint ladder, dead-CSS audit, no-layer decision) (#123185) 2026-08-13 15:00:03 -07:00
Peter Steinberger 7e78de747b refactor(ui): replace duplicated locale bundles with canonical translation memory (#117157)
* refactor(ui): generate locale bundles from canonical translation memory

* fix(ui): keep server-only locale config out of browser test helpers
2026-07-31 19:40:27 -07:00
Peter Steinberger 5a8db91459 fix(macos): keep polling gateway-executed wizard steps (#114383)
* fix(macos): keep polling gateway-executed wizard steps

* docs(ui): note the prebuilt control-UI bundle in live verification

* test(macos): fail fast when gateway progress polling stalls

* chore(i18n): refresh native source inventory anchors
2026-07-27 04:33:09 -04:00
Peter Steinberger 3807591ff4 build(lint): adopt stylelint for Control UI css templates and stylesheets (#113971) 2026-07-25 19:13:46 -07:00
Peter Steinberger 067635cb51 fix(ui): prevent generated locale rebase conflicts (#109393)
* ci(ui): make locale refresh bot-owned

* test(ui): keep locale gate coverage scoped

* fix(ci): preserve generated PR merge policy

* fix(ci): wait for generated PR head convergence

* fix(ci): retry transient guard API failures

* fix(ci): enforce locale isolation across CI events

* fix(ci): harden generated PR publication

* fix(ci): validate release gate merge tree

* fix(ci): allow trusted main locale output
2026-07-16 18:48:20 -07:00
Peter Steinberger ce919593bf fix(ui): unblock rebases with generated i18n conflicts (#109279)
* fix(ui): automate i18n conflict resolution

* fix(ui): preserve i18n cache merge intent

* fix(ui): restrict resolver to generated locales

* fix(ui): prune stale locales before baseline

* fix(ui): handle removed locale conflicts
2026-07-16 12:52:28 -07:00
Peter Steinberger 47d37804a8 improve(ui): catch i18n catalog drift locally (#107253)
* ci(ui): verify i18n catalogs locally

* fix(ui): preserve scoped i18n sync errors

* refactor(ui): share i18n raw-copy verifier

* test(ui): cover i18n lint gate

* fix(ui): route lint threads to oxlint
2026-07-14 01:12:36 -07:00
Peter Steinberger 1b1a41d87f refactor(ui): sidebar IA cleanup: Activity to Settings, Dreams into Agents Memory tab, single MCP mutation owner (#104604)
* refactor(ui): move dreams page modules to agents/memory (verbatim)

* refactor(ui): sidebar IA cleanup: Activity to Settings, Dreams into Agents Memory tab, single MCP mutation owner, Usage icon

Folds the per-agent Dreams page into the Agents page as a Memory panel and
deletes the dreams route; moves the session-scoped Activity page out of the
sidebar into Settings > System next to Logs; removes the MCP enable/disable
toggle from Settings > MCP so the Plugins page is the single mutation surface
for config.mcp.servers; gives Usage a coins icon so it no longer collides
with Overview.

Closes #104590

* docs: update Control UI docs for Activity/Memory/MCP sidebar changes

* fix(scripts): fail control-ui i18n sync closed on new untranslated keys without provider auth

An unauthenticated ui:i18n:sync silently recorded English fallbacks, which the
shipped-fallback CI gate then rejects; post-merge translation is owned by the
control-ui-locale-refresh workflow. Sync now errors on new untranslated keys
without a provider (OPENCLAW_CONTROL_UI_I18N_AUTH_OPTIONAL=1 opts back in),
and the ui AGENTS guide documents the commit-en.ts-only contributor flow.

* chore(ui): translate new sidebar keys, refresh i18n baseline, localize Memory tab expectation
2026-07-11 14:24:39 -07:00
Peter Steinberger 4feb4e6623 docs(ui): document i18n report usage 2026-05-14 10:27:12 +01:00
Vincent Koc 80730c53bd docs(agents): split scoped workflow guidance (#65241)
* docs(agents): add scoped workflow guides

* docs(agents): trim root guide duplication

* Update AGENTS.md

* docs(agents): restore root boundary context

* docs(agents): clarify plugin architecture direction
2026-04-12 09:09:50 +01:00