Skip to content

refactor(#478): caller-neutral VariableBar activation port - #555

Merged
BorisTyshkevich merged 3 commits into
mainfrom
refactor/variable-bar-port-478
Jul 29, 2026
Merged

refactor(#478): caller-neutral VariableBar activation port#555
BorisTyshkevich merged 3 commits into
mainfrom
refactor/variable-bar-port-478

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

What & why

Closes #478. VariableBarApp is shared by Dashboard and detached Data, but its activation port was named after Workbench persistence (state.filterActive, params.saveFilterActive) — leaking one caller's storage model into a shared UI contract. Dashboard uses those members for an in-memory draft map with no persistence at all.

Renames only the shared port to caller-neutral names — state.activeByName, params.saveActive — and gives both callers explicit adapters:

  • Dashboard (src/ui/dashboard.ts) aliases its local draftActive map; saveActive is a no-op because the draft is never persisted.
  • Detached Data (src/ui/results.ts) builds an explicit adapter aliasing app.state.filterActive and routing saveActive to app.params.saveFilterActive(), replacing the previous app as VariableBarApp same-shape cast.

Every persisted name and storage key is unchanged — AppState.filterActive, WorkbenchParameterSession.saveFilterActive, effectiveFilterActive, asb:filterActive. No storage migration. Behaviour is identical; this is a naming/seam refactor.

The aliasing invariant is now falsifiable

The variable bar mutates the activation map in place, so an adapter that copied instead of aliased would break activation silently. tests/unit/results.test.ts gains a test that captures the object reference before expandDataPane builds the bar, edits a field, then asserts app.state.filterActive === activeRef (same identity — a copy would fail), that the write landed on that real object, and that saveFilterActive() was called.

tests/e2e/time-range.html's hand-built variableBarApp fixture was updated to match the renamed port — an App-shape change has to reach the e2e fixtures, not just the specs.

Checklist

  • npm test passes (the per-file coverage gate is non-negotiable)
  • Tests added/updated in the same change as the code
  • npm run build succeeds (single-file dist/sql.html)
  • Layers kept honest: pure logic in src/core/, network in src/net/ (injected fetch), DOM in src/ui/
  • No new runtime dependency
  • README / CHANGELOG.md ([Unreleased]) updated if behavior or the deployed surface changed
  • Reconciled affected tracked work (roadmap Roadmap to 1.0.0 #68, the issue body, ADR/CHANGELOG) if this change reshaped it

🤖 Generated with Claude Code

https://claude.ai/code/session_01GiubaoqEuBzAyo5C4P8Vqr

BorisTyshkevich and others added 3 commits July 29, 2026 16:39
…tral names

`VariableBarApp` is shared by Dashboard and detached Data, but its activation
port was named after Workbench persistence (state.filterActive,
params.saveFilterActive), leaking one caller's storage model into a shared UI
contract. Rename the shared port to state.activeByName / params.saveActive;
every persisted name and storage key (AppState.filterActive,
WorkbenchParameterSession.saveFilterActive, effectiveFilterActive,
asb:filterActive) is unchanged, with no storage migration.

Both callers now build an explicit adapter instead of a same-shape cast:
Dashboard aliases its local in-memory draft map with a no-op saveActive;
detached Data aliases the real AppState.filterActive object and routes
saveActive to app.params.saveFilterActive(). A new results.test.ts case
proves the alias by identity (app.state.filterActive === activeRef after a
bar-driven edit), not just behavior.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiubaoqEuBzAyo5C4P8Vqr
Review nit: the comment still pointed at the `as VariableBarApp` cast this
change removed. Describe the explicit adapter that replaced it instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiubaoqEuBzAyo5C4P8Vqr
@BorisTyshkevich
BorisTyshkevich merged commit 8814478 into main Jul 29, 2026
8 checks passed
lesandie pushed a commit to lesandie/altinity-sql-browser that referenced this pull request Aug 2, 2026
… read, not a snapshot

The VariableBarApp adapters built by results.ts (detached Data, Altinity#555) and
dashboard.ts (pre-Altinity#555) copied varRecent into state as a plain data
property, captured once at adapter-construction time. Unlike activeByName,
varRecent is replaced wholesale on every record/clear
(workbench-parameter-session.ts), so the copy went stale immediately:
Clear recent persisted but an open dropdown kept listing cleared values,
and a re-run's newly recorded value never showed until the pane reopened.

VariableBarApp now exposes getVarRecent(): RecentMap, a live-read callback
both adapters implement over their own varRecent reference, read at call
time. Updated the single consumer in variable-bar.ts, both production
adapters, the port's doc comment, and every other port construction
(variable-bar.test.ts's asBarApp, tests/e2e/time-range.html).

Added behavioural regression tests (wholesale-replacement-then-reopen, and
Clear-recent through a production-like clearVarRecent) in
variable-bar.test.ts, results.test.ts, and dashboard.test.ts — each
verified to fail against the reverted snapshot form before being restored.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GiubaoqEuBzAyo5C4P8Vqr
@BorisTyshkevich
BorisTyshkevich deleted the refactor/variable-bar-port-478 branch August 6, 2026 15:28
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.

Rename shared VariableBar activation port to caller-neutral names

1 participant