fix(ai): hide Translate / Find related / Suggest reply menu items when the AI flag is off (LC-686) #652
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/LC-686-ai-menu-gate"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
With the LC-679 AI feature flag off (its production default), the message action menu still showed Translate, Find related, and Suggest reply. Clicking one fails: the route 403s (correct) and the UI shows two confusing toasts - "AI request failed. Please try again." (live.js) and "Could not save. Please try again." (settings.js binds a global
htmx:responseErrorhandler). Catch me up and the composer writing-assistant are gated server-side and correctly vanish when the flag is off, so the menu was inconsistent.Root cause (CSS specificity, not a backend failure)
These three items are CSS-gated: they always render with a
lc-llm-only/lc-embeddings-onlyclass, hidden by default and revealed only under the[data-lc-llm]/[data-lc-embeddings]page-root attribute (which now folds in flag + role).The hide rule lost a specificity tie:
.lc-llm-only { display: none }/.lc-embeddings-only { display: none }- (0,1,0).lc-menu-item { display: flex }, defined later in the same file - also (0,1,0)Every item carries both classes (
class="lc-menu-item lc-llm-only"), so the later rule won the source-order tie and the item was always shown. The reveal rule[data-lc-llm] .lc-menu-item.lc-llm-only(0,3,0) only ever turned items on; nothing turned them off. Same cascade trap as LC-678.Fix
Scope the two hide rules to
.lc-menu-item.lc-llm-only/.lc-menu-item.lc-embeddings-only(0,2,0) - beats.lc-menu-item, while the reveal rule (0,3,0) still wins. Both classes are used only aslc-menu-item lc-<x>-onlyacross the templates, and the sibling.lc-read-aloudgate already uses this higher-specificity shape.Result: with the flag off the three items disappear exactly like Catch me up and the writing-assistant; reveal is unchanged for flag-on + configured + privileged viewers, including live-swapped WS message fragments (the rule is ancestor-based). The routes keep their 403 as server-side defense in depth (covered by the LC-679
routes_ai_gatetests).Scope
One file,
server/assets/main.css(+12/-4), served directly (no build step). No behavior change when the flag is on.🤖 Generated with Claude Code
https://claude.ai/code/session_01PBAyCesyqJkZ5JgixXf9Lf
With the LC-679 AI feature flag off (its production default), the message action menu still showed Translate, Find related, and Suggest reply. Clicking one 403s (the routes gate correctly) and the UI surfaced two confusing toasts ("AI request failed" from live.js and, via settings.js's global htmx:responseError handler, "Could not save"). Catch me up and the composer writing-assistant are gated server-side and correctly vanish when the flag is off, so the menu was inconsistent. Root cause is a CSS specificity tie, not a backend failure. These three items are CSS-gated: they always render with a lc-llm-only / lc-embeddings-only class and are meant to be hidden by default, revealed only under the [data-lc-llm] / [data-lc-embeddings] page-root attribute (which now folds in the flag + role). But the hide rule `.lc-llm-only { display: none }` is (0,1,0) and `.lc-menu-item { display: flex }`, defined later in the same file, is also (0,1,0); every item carries both classes, so the later rule won the source-order tie and the item was always shown. The reveal rule only ever turned items ON; nothing turned them OFF. Same cascade trap as LC-678. Fix: scope the two hide rules as `.lc-menu-item.lc-llm-only` / `.lc-menu-item.lc-embeddings-only` (0,2,0), which beats `.lc-menu-item` while the reveal rule (0,3,0) still wins. Both classes are used only as `lc-menu-item lc-<x>-only` across the templates, and the sibling `.lc-read-aloud` gate already uses this higher-specificity shape. Now the three items disappear when the flag is off, exactly like Catch me up and the writing-assistant, and reveal unchanged for flag-on + configured + privileged viewers (including live-swapped WS message fragments). The routes keep their 403 as server-side defense in depth (LC-679 routes_ai_gate tests). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PBAyCesyqJkZ5JgixXf9Lf