Repository navigation
Consolidate duplicated composables across both GUIs into the shared kit #14907
Description
Activity
- addedarea: frontend-unificationWave 4 · cluster B — Frontend unification & design systemWave 4 · cluster B — Frontend unification & design system
on Sep 1, 2026 Checked the candidate branch for this issue (`lane-gui-dedup`) before reviving it, per standing discipline (never revive without comparing each touched file's blob against current `origin/main` first).
Substantial progress already landed on main, via a different path than this branch:
- AC2 (one `useToast` in the kit, union behavior) — done. `libs/autobot-ui/src/composables/useToast.ts` exists; both `autobot-frontend/src/composables/useToast.ts` and `autobot-slm-frontend/src/composables/useToast.ts` are thin re-export shims citing this issue by number, each with a doc comment naming what capability diff the union preserved (Tier-C persistent-error handling from the main GUI's larger implementation, MAX_TOASTS=5 behavior from the SLM's).
- AC3 (eight shared Prometheus type names, domain logic per-app) — done. Both `usePrometheusMetrics.ts` files import the shared type names from `@autobot/ui`; domain-specific logic (main's `WorkflowMetrics`/`GithubMetrics`/`MultiModalMetrics`, SLM's `NodeMetricsDetailed`/`FleetMetricsDetailed`/`NPUFleetMetrics`) stays local, matching the issue's own explicit instruction not to merge those wholesale.
- AC6 (guard fails on a composable filename in both GUIs, absent from the kit) — done. `autobot-infrastructure/shared/scripts/hooks/pre-commit-no-cross-gui-duplicate` exists on main with its own test file.
`lane-gui-dedup` itself should NOT be revived — beyond being superseded on the above, its own residual diff (direct tip-to-tip against current main, not merge-base) carries two real regressions:
- `autobot-frontend/src/services/RedisServiceAPI.ts` — exists on the branch, absent from main entirely. Deliberately removed by `fa76c273cd`/`4b6c4e4c24` ("remove the unreachable user-GUI Redis client... tech-debt(frontend): move SettingsPanel's detailed system health and Redis service management into the SLM #16245, bug(frontend): RedisServiceControl calls /api/service-monitor/services/* and no mounted router serves those paths #16252"). Reviving the branch's touch resurrects dead code a landed cleanup removed.
- `autobot-slm-frontend/src/composables/usePrometheusMetrics.ts` — the branch's version is missing `meanOfKnown()`/`summariseGpus()` and the `GPUNodeStatus` import that main added later for fix(slm-frontend): monitoring hardcodes GPU as absent — "no GPU nodes in fleet" is asserted in a composable while the schema models nvidia-gpu and amd-gpu per node #15226 (real GPU-utilization aggregation — "an unmeasured fleet is unknown, not a fleet sitting at 0%"). The branch predates that feature; merging it would delete working logic.
Still genuinely open, verified directly against main, not assumed:
- AC1 (`useVncControls` promotion) — open, and worse than the issue's own text implies: the composable is triplicated, not duplicated — `autobot-frontend/src/composables/useVncControls.ts`, `autobot-slm-frontend/src/composables/useVncControls.ts`, and `autobot-plugins/vnc/src/composables/useVncControls.ts` all still exist locally, none promoted to the kit. Per the issue's own text this is the cleanest candidate (byte-identical, no reconciliation) — good next scoped piece of work.
- AC4 (WebSocket composable comparison) and AC5 (full behavioral sweep across all composables) — not verified either way in this pass; flagging as unchecked rather than assuming either status.
Not closing anything here — leaving the checklist as-is since AC1/AC4/AC5 are unverified-or-open. Recommend treating remaining scope as fresh work off current main rather than reviving `lane-gui-dedup`.
- added a commit that references this issue
on Sep 20, 2026 - linked a pull request that will close this issuechore(frontend): remove the two dead useVncControls shims #17180
on Sep 20, 2026 Follow-up to the earlier comment: AC1 ("`useVncControls` promoted to the kit; both GUIs import it; no local copies remain") named the wrong target package. The promotion happened, correctly, to `autobot-plugins/vnc` (a VNC-specific plugin, not `@autobot/ui`) via #12931/#12653/#12978 — that's the only reason this AC read as unmet for months. The two app-local files were already dead re-export shims with zero callers, not a live duplicate needing reconciliation.
Cleanup PR: #17180 — removes both shims plus the one regression test whose entire subject was the shim (a relative import a path-substring grep initially missed; a second, unscoped grep across both apps including tests and dynamic-import forms caught it before it could break the build). `docs/adr/008` updated so its file:line citation of the shims doesn't go stale.
AC1 can be ticked once #17180 lands.
- added a commit that references this issue
on Sep 20, 2026
Part of #14774. Discovery issue — the sweep below is partial; completing it is part of the work.
Problem
Composables are duplicated across the two GUIs with no shared home. Counts:
autobot-frontend/src/composablesautobot-slm-frontend/src/composableslibs/autobot-ui/src/composablesThe kit exports only
useFocusTrap/useFocusRestore/useInitialFocus/useBodyScrollLock/usePagination/useFormValidation. Everything else is per-app.Confirmed duplicates
Three composables exist under the same filename in both GUIs:
1.
useVncControls.ts— byte-identical. 21 lines, 824 bytes,cmpreports no difference. A verbatim copy. Cleanest possible promote-to-kit candidate.2.
useToast.ts— identical public contract, divergent implementations. Both export exactly the same eight symbols:ToastType·Toast·UseToastReturn·MAX_TOASTS·TOAST_DURATIONS·TOAST_INJECT_KEY·provideToast·useToastMain is 184 lines, the SLM 93. Same API contract, two implementations — the SLM's reads as a trimmed copy. Two implementations of one contract drift independently, and toast behaviour (max queue, durations, inject key) is exactly the kind of thing that should be identical across both GUIs.
3.
usePrometheusMetrics.ts— same name, overlapping types, genuinely different domains. Eight type names are declared in both files:GPUMetrics·NPUMetrics·ServiceHealth·ServicesSummary·PerformanceAlert·AlertsSummary·OptimizationRecommendation·UsePrometheusMetricsOptionsBut the surrounding logic differs legitimately — main carries
WorkflowMetrics,GithubMetrics,MultiModalMetrics; the SLM carriesNodeMetricsDetailed,FleetMetricsDetailed,NPUFleetMetrics,PerformanceOverview. This one should not be merged wholesale. The shared types are duplicated and belong in one place; the domain logic stays per-app.Unexamined, flagged
useWebSocket.ts,useGlobalWebSocket.ts,useCanvasWebSocket.ts(main) anduseSlmWebSocket.ts(SLM). Not compared — reconnect/backoff/auth handling is the likely overlap and the likely place for divergent bugs.useSlmApi,useAutobotApi,useApiKeyApi,useSecretsApi,useSsoApi,useMfaApi,useLlmConfigApi,useSlmUserApi; main has its own set includinguseSecretsAuditApi,useSecretsInfraApi. Whether they share request/auth/error handling is unchecked.Scope of this sweep — read before trusting it
This compared exact filename collisions between the two GUIs, plus a targeted concept list. It did not compare 229 composables against 30 behaviourally. Same-concept/different-name duplicates are the likeliest remaining category and are not covered here — a full pass is part of this issue, not a prerequisite for it.
Approach
useVncControlsto the kit — byte-identical, no reconciliation needed.useToastinto one kit implementation taking the union of both behaviours, not the smaller one. Diff the two bodies first and record what each does that the other does not.usePrometheusMetricstypes into one shared location. Leave both composables' domain logic in place — merging them would be a fork collapse of two genuinely different things.Risks / constraints
useToastbeing twice the size is a signal it does more, not that it is bloated.usePrometheusMetricsis a trap: the shared name and shared types make it look like one duplicate, but the domain logic is legitimately per-app. Types only.Acceptance criteria
useVncControlspromoted to the kit; both GUIs import it; no local copies remainuseToastin the kit, its behaviour the union of both prior versions, with the diff recorded in the PR