refactor(ui): harden Lit lifecycle boundaries#102745
Conversation
Dependency GuardThis PR changes dependency-related files. Maintainers should confirm these changes are intentional. Changed files:
Maintainer follow-up:
|
Dependency graph change authorizedThis PR includes dependency graph changes. A repository admin or member of
A later push changes the PR head SHA and requires a fresh security approval. |
|
Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 8:13 AM ET / 12:13 UTC. Summary Reproducibility: no. high-confidence live browser reproduction was established. Current-main source and the linked issue show the repeated lifecycle/subscription patterns the PR targets, but the observable races remain source-level rather than reproduced in a real UI session here. Review metrics: 1 noteworthy metric.
Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Keep the lifecycle-controller direction, but land it only after security/admin dependency approval for the exact head, fresh post-rebase CI, and redacted real Control UI proof for representative reconnect/route/chat behavior. Do we have a high-confidence way to reproduce the issue? No high-confidence live browser reproduction was established. Current-main source and the linked issue show the repeated lifecycle/subscription patterns the PR targets, but the observable races remain source-level rather than reproduced in a real UI session here. Is this the best way to solve the issue? Unclear as merge-ready: the controller/base-element approach matches the affected Lit lifecycle boundary, but the unapproved dependency graph change and missing real behavior proof keep this from being the final best fix yet. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against f786efddcd88. Label changesLabel changes:
Label justifications:
Evidence reviewedSecurity concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
80f79c9 to
e448b1a
Compare
|
Land-ready code/test proof for
Known proof gap: no single live browser scenario reproduces every intermittent lifecycle race; deterministic tests cover each ownership branch. Local Blacksmith Testbox was unavailable, so the exact-head broad proof is the hosted CI run above. |
|
/allow-dependencies-change Declare the existing production @lit/context import in the Control UI package. |
|
Merged via squash.
|
* refactor(ui): harden Lit lifecycle boundaries * fix(ui): clear ChatPage subscriptions before teardown * test(ui): satisfy lifecycle lint gates * chore: defer Lit lifecycle release note * fix(ui): sync raw-copy baseline * test(ui): avoid order-sensitive Sessions mock --------- Co-authored-by: Peter Steinberger <[email protected]>
Closes #102423
What Problem This Solves
Resolves a class of Control UI failures where retained elements could keep listening to a replaced application capability, or publish an obsolete async result after a disconnect, reconnect, provider replacement, route change, or detach. These races could leave stale lists, errors, loading locks, model overrides, task suggestions, token side effects, plugin polling, or navigation state visible in the current UI.
Why This Change Was Made
The Control UI now has shared light-DOM Lit bases for live locale updates and a
SubscriptionsControllerthat owns replaceable external sources. Page, capability, router, overlay, terminal, chat, modal, plugin, and session work is scoped to explicit source/connection generations; stale completions become inert and retired resources are released at the owning lifecycle boundary. All production Lit elements—including the newly added Sessions context menu—use the shared base, while upstream Talk, split-view, Codex Sessions, and Settings behavior remains intact.This is AI-assisted maintainer work. The implementation and every accepted review finding were inspected and corrected before submission.
User Impact
The Control UI remains deterministic across reconnects and in-place runtime replacement: language changes propagate without remounting, stale data and errors cannot overwrite current state, sensitive device-token responses cannot escape a retired request epoch, and chat/plugin/session surfaces cleanly release their old work.
Evidence
node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.test.ui.json ....oxfmt --check;git diff --checkpasses.check:changed; exact PR-head broad CI is pending because the local Blacksmith Testbox executable was unavailable.