Summary
The Python Processes panel's empty state has three coupled defects:
- It shows a Refresh button in the empty welcome view, where it makes no
sense.
- The list should be reactive (Signals-driven, centralised state) so a manual
Refresh button is unnecessary at all; while it isn't, the refresh affordance
should sit next to the process list, not float in the empty state.
- The message "No Python processes running" is a lie — the list is empty
because processes are being hidden / the fetch didn't populate, not because
zero Python processes exist. (Note the status bar in the repro: TMC:
Disconnected.)
1 — Hide the Refresh button in the empty state (do this now)
The welcome view renders a [Refresh] action
(package.json:84-87,
basilisk.refreshProcesses registered at
process-explorer.ts:406). But the
panel already auto-refreshes on a timer and the welcome copy itself says "The
list refreshes automatically" — so a manual Refresh in the empty state is
redundant and self-contradictory. Hide it here for now; it only makes sense
once there are processes to refresh.
2 — The list isn't reactive; it's timer-polled
The panel is refreshed by a 2-second setInterval, not by the centralised store
signals:
- process-explorer.ts:442-468
— wireVisibilityRefresh() runs setInterval(() => provider.refresh(), 2000)
while visible (DEFAULT_REFRESH_MS = 2000).
This is the opposite of the Modules panel, which refreshes off the store's
analysisRevision signal via an effect ([EXTACT-REACTIVE-STATE], #58). Per the
project principle (panels must be reactive via Signals; all state centralised),
the process list should update without a manual button. Until it is genuinely
reactive, the refresh control belongs inline next to the process list (a
view-title or item action on the populated state), never as a lone button in the
empty view.
3 — "No Python processes running" is misleading
fetchProcesses() swallows any LSP error into an empty list and marks the fetch
done, so an errored or not-yet-loaded state renders identically to a genuinely
empty one:
So when the LSP is disconnected / still starting / the feature is gated, the panel
claims there are no processes rather than admitting it couldn't load them.
This is the same trust-breaking false-negative as #144 ("No Python files found"
during startup): the empty message must distinguish loading / couldn't load /
unavailable from genuinely zero processes, and only assert the latter once a
fetch has actually succeeded.
A static viewsWelcome can't express those states — drive the empty/loading/error
copy from centralised store state (a basilisk.processesState context key gating
multiple viewsWelcome entries, or a Signals-driven treeView.message / leading
tree item), so it's never stale and never lies.
Notes
Spec / cross-references
Acceptance criteria
Summary
The Python Processes panel's empty state has three coupled defects:
sense.
Refresh button is unnecessary at all; while it isn't, the refresh affordance
should sit next to the process list, not float in the empty state.
because processes are being hidden / the fetch didn't populate, not because
zero Python processes exist. (Note the status bar in the repro: TMC:
Disconnected.)
1 — Hide the Refresh button in the empty state (do this now)
The welcome view renders a
[Refresh]action(package.json:84-87,
basilisk.refreshProcessesregistered atprocess-explorer.ts:406). But the
panel already auto-refreshes on a timer and the welcome copy itself says "The
list refreshes automatically" — so a manual Refresh in the empty state is
redundant and self-contradictory. Hide it here for now; it only makes sense
once there are processes to refresh.
2 — The list isn't reactive; it's timer-polled
The panel is refreshed by a 2-second
setInterval, not by the centralised storesignals:
—
wireVisibilityRefresh()runssetInterval(() => provider.refresh(), 2000)while visible (
DEFAULT_REFRESH_MS = 2000).This is the opposite of the Modules panel, which refreshes off the store's
analysisRevisionsignal via aneffect([EXTACT-REACTIVE-STATE], #58). Per theproject principle (panels must be reactive via Signals; all state centralised),
the process list should update without a manual button. Until it is genuinely
reactive, the refresh control belongs inline next to the process list (a
view-title or item action on the populated state), never as a lone button in the
empty view.
3 — "No Python processes running" is misleading
fetchProcesses()swallows any LSP error into an empty list and marks the fetchdone, so an errored or not-yet-loaded state renders identically to a genuinely
empty one:
— empty
processes→ empty tree → the welcome's "No Python processes running".— on fetch failure:
this.processes = []; this.fetched = true;(error logged,but the UI asserts the definitive negative).
So when the LSP is disconnected / still starting / the feature is gated, the panel
claims there are no processes rather than admitting it couldn't load them.
This is the same trust-breaking false-negative as #144 ("No Python files found"
during startup): the empty message must distinguish loading / couldn't load /
unavailable from genuinely zero processes, and only assert the latter once a
fetch has actually succeeded.
A static
viewsWelcomecan't express those states — drive the empty/loading/errorcopy from centralised store state (a
basilisk.processesStatecontext key gatingmultiple
viewsWelcomeentries, or a Signals-driventreeView.message/ leadingtree item), so it's never stale and never lies.
Notes
main. The repro's welcome ("No Python processesrunning. The list refreshes automatically." + three buttons: Run & Profile CPU,
Run & Track Memory, Refresh) does not match the current tree's
viewsWelcome(package.json:84-87,which has different copy and buttons). Reconcile the committed welcome with the
running build (same note as "Run & Track Memory (Current File)" dead-ends: toast says "take a snapshot", but stopping produces no chart/trace/report #146).
([PROFILE-UI-GATE]; view
when: basilisk.hasWorkspace && basilisk.profilingEnabled, package.json:67-71),so this is not shipped-user-facing yet — but the empty/loading honesty must be
fixed before the gate opens.
Spec / cross-references
[PROFILE-PROCESSES-PANEL],[PROFILE-UI-GATE]—docs/specs/LSP-PROFILING-SPEC.md.[EXTACT-REACTIVE-STATE](Type Health / Module Explorer panels are not reactive — require manual refresh (centralize state in store via Preact signals) #58) — the reactive-via-Signals pattern this panelshould follow.
Acceptance criteria
all) lives next to the populated process list.
state rather than an ad-hoc panel-local timer.
succeeded and the count is truly zero; loading / disconnected / unavailable
states say so honestly.
viewsWelcomematches the running entry point; an e2e testcross-references the spec ID.