Skip to content

Stop overlays from rendering fixture data on missing dependencies - #366

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-5596-overlay-fixtures
Aug 7, 2026
Merged

Stop overlays from rendering fixture data on missing dependencies#366
TheGreatAxios merged 2 commits into
mainfrom
cl-5596-overlay-fixtures

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

residuals.ts held demo/fixture rows (settings, help, plugins, resume, mentions, a fake child-session transcript) that were exported from index.ts and compiled into the production bundle. shell.ts's overlay openers used them as read-site defaults (items: opts?.items ?? makeSettingsItems()), so a caller that omitted items rendered fabricated content indistinguishably from real data. Two call sites did exactly that in production: openSettingsSurface when its settings dependency was missing, and openHelpOverlay(shell) on every call.

Fix

  • OpenResidualListOpts.items is now required — the overlay openers (openSettingsOverlay, openMentionsOverlay) no longer have a fixture to fall back to; TypeScript enforces that every caller supplies real data.
  • openHelpOverlay always renders the shell's real keybinding catalog (SHELL_SHORTCUTS) — it never took a host dependency, so there was nothing to be missing; the read-site-default shape it copied from the others is gone.
  • openSettingsSurface now calls deps.notify(...) when its settings dependency is missing, matching the pattern already used by openPermissionsSurface / openPluginsSurface / openHooksSurface / openMcpSurface — an honest message instead of a painted overlay.
  • The observe fixture fallback (onObserveRequest ? onObserveRequest() : makeObserveFixture()) is gone; a missing host handler now leaves observe closed with the existing "no subagent session to observe" status line.
  • residuals.ts is reduced to genuinely production logic: ResidualCatalogEntry, ResidualListPayload, ObserveSession, residualListFromCatalog, residualIdFromSelection. All fixture generators moved into demo.ts, which is not exported from index.ts and never ships.

/resume and /plugins

  • /plugins: real plugin administration already exists — openPluginsSurface in command-surfaces.ts is wired to deps.plugins and is discoverable via the registry-backed /plugins slash command (which already shadows the palette's residual plugins entry via preferRegistry). The residual palette entry was pure duplication of a path that only ever rendered the fixture, so I removed it (DEFAULT_PALETTE_COMMANDS, PaletteActionId, and the runPaletteAction case).
  • /settings: same story — the registry-backed /settings command already routes through openSettingsSurface with real data, and the residual palette entry always shadowed itself in production. Removed for the same reason.
  • /resume: I searched for a real in-session resume data source and found none. pick-session.ts / list-modal.ts implement a real resume flow, but only as a pre-launch picker before the shell starts — there is no wiring to list or resume sessions from inside a running shell (ShellOverlayHooks.onResume was never set by any production caller). This matches the operator report cited in the issue ("not sure what this is"). Since there's nothing real to wire it to, I removed it from the palette rather than leave an overlay that can only ever show fake sessions.
  • /mentions: this one does have a real backing implementation (openAtMentionSuggestions, which reads the live @-token under the cursor via the injectable MentionSuggestionSource). The palette's residual "mentions" action was bypassing it and opening the fixture list directly; it now delegates to the real function, so the palette action either shows the same suggestions as typing @ or honestly does nothing when there's no @ token to complete.

Validation

  • bun run typecheck, bun run build, bun run test all pass (3985 tests, 0 fail).
  • Added overlay-fixture-fallback.test.ts as a red/green test: it opens settings with no settings dependency and asserts none of the old fixture strings appear — committed failing first, confirmed red, then made to pass by the fix.
  • Rewrote wave7.test.ts and overlay-paint.test.ts to pass real items into the now-required-items openers instead of relying on the fixture fallback; updated observe-live.test.ts's "falls back to the fixture" test to assert the honest empty state instead.
  • Ran the interactive demo (bun src/tui-opentui/demo.ts) in a real TTY via tmux and captured frames: h (help) renders the actual SHELL_SHORTCUTS catalog (verified against SHELL_SHORTCUTS.map(...) in the frame), and the demo's own settings overlay (now sourced from a local DEMO_SETTINGS_ITEMS in demo.ts, not the production module) still renders correctly.
  • Net diff: 9 files changed, 198 insertions(+), 346 deletions(-) — net-negative as required.

Judgment calls / other notes

  • Left ShellOverlayHooks (onSettings, onPlugins, onResume, onMentions) and the "resume"/"plugins" PrimaryOverlayKind values alone — they're generic accept-dispatch plumbing and the "resume" kind is still legitimately used by list-modal.ts's pre-launch picker. Out of scope for this fix.
  • Two other agents are concurrently touching shell.ts (palette/overlay-geometry and model-surface branches); rebased onto origin/main before opening this PR and resolved one small conflict in palette.ts where upstream had already dropped the category field from PaletteCommand.

Settings, plugins, resume, and mentions all read-site-defaulted to
hardcoded rows from residuals.ts whenever a caller omitted items,
indistinguishable from real content. Settings now surfaces an honest
message when its dependency is missing; help always renders the
shell's real keybinding catalog; the overlay openers require items
from their caller instead of silently substituting a fixture.

The in-shell /plugins and /settings palette entries duplicated slash
commands already wired to real data and are dropped. /resume had no
backing session source in-session (resume only exists as a pre-launch
picker) and is dropped rather than left pointing at fake sessions.
/mentions now drives the real @-mention path instead of opening a
fixture list. The observe fixture fallback is removed; a missing host
handler now leaves observe closed with an honest status line, matching
the existing empty-state message. Fixture data used only by the
interactive demo now lives in demo.ts, outside the production module
graph.
@linear-code

linear-code Bot commented Aug 7, 2026

Copy link
Copy Markdown

CL-5596

@TheGreatAxios
TheGreatAxios merged commit e143db0 into main Aug 7, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant