fix(desktop): workspace scoping + returning-user org recovery + signal drill-down - #1
Open
Bennettxai wants to merge 2 commits into
Open
fix(desktop): workspace scoping + returning-user org recovery + signal drill-down#1Bennettxai wants to merge 2 commits into
Bennettxai wants to merge 2 commits into
Conversation
The desktop shell showed empty modules (nodes, graph, timeline, heatmap) for any real workspace. Two root causes, both the same class of bug: the active workspace scope was dropped before hitting the engine, so requests fell back to the empty "default" compatibility workspace. 1. workspace store: bootstrap()/refreshWorkspaces() called listWorkspaces(orgId), but that function's first arg is `tenant`, not organization. An org id is not a tenant id (every workspace shares tenant "default" but belongs to a specific organization), so selecting a real org (e.g. operatoros) sent ?tenant=operatoros and matched zero workspaces, emptying the whole UI. listWorkspaces now takes an options object and filters by ?organization. bootstrap() also now prefers a real organization over the "default" compatibility org on first load. 2. knowledge graph + node files: loadGraph() and getNodeFiles() called /api/workspace, /api/optimal/graph and /api/optimal/nodes/:slug/files with no workspace param, so they always read the empty default workspace. Node slugs are not globally unique across workspaces, so the scope is mandatory. Both now thread the active workspace through every call, and the /graph route remounts on workspace switch. Verified against a live engine: all 5 workspaces now populate nodes, graph, activity/timeline/heatmap and search. svelte-check: 0 errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…x signal drill-down Follow-up to the workspace-scoping fix, addressing "every module is empty" for returning users. 1. Stuck on the compat "default" org. Before organizations were first-class, the app auto-selected and persisted the "default" org. The previous fix only re-selected when the saved org was *invalid*, but "default" is valid, so returning users stayed parked on the empty compatibility org and every data module (nodes, graph, timeline, heatmap, activity) rendered empty. bootstrap() now also upgrades away from "default" to a real org when one exists, so a returning user self-heals on next load. Verified live: restoring the old default/default localStorage state now recovers to OperatorOS + a populated workspace and renders the node tree. 2. Signal drill-down returned "signal not found". /api/signals/:id is keyed by the context id and is workspace-scoped, but the node-files payload dropped the id it already SELECTs (the UI fell back to parsing the filename, which never matches) and getSignal() omitted the workspace. optimal_node_files now returns `id`; getSignal(id, workspace) passes the scope; the workspace page uses the file's real id. svelte-check 0 errors; engine recompiles clean (the running release must be rebuilt for the node-files id to appear). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
In the desktop shell, the data modules (nodes, graph, timeline, heatmap, activity) rendered empty for a real workspace, and returning users saw every module empty. The signal drill-down also errored with "signal not found."
Root causes (all: the active scope was dropped before reaching the engine)
Org id used as tenant id.
bootstrap()/refreshWorkspaces()calledlistWorkspaces(orgId), but that arg istenant. Selecting a real org (operatoros) sent?tenant=operatoros, matched zero workspaces, and blanked the UI.Graph + node files unscoped.
loadGraph()andgetNodeFiles()hit/api/workspace,/api/optimal/graph,/api/optimal/nodes/:slug/fileswith no workspace param, always reading the emptydefaultworkspace. Node slugs are not globally unique, so scope is mandatory.Returning users stuck on the compat
defaultorg. Before organizations were first-class, the app auto-selected and persisted thedefaultorg. Fix fix(desktop): workspace scoping + returning-user org recovery + signal drill-down #1's re-selection only triggered when the saved org was invalid;defaultis valid, so returning users stayed parked on the empty compatibility org and saw every module empty. This was the reported "nothing works."Signal drill-down 404.
/api/signals/:idis keyed by the context id and workspace-scoped, but the node-files payload dropped theidit already SELECTs (the UI parsed the filename instead, which never matches) andgetSignal()omitted the workspace.Fix
listWorkspaces()takes an options object and filters by?organization; addedorganization_idto theWorkspacetype.bootstrap()prefers a real organization, and now also upgrades away from the emptydefaultorg when a real one exists, so returning users self-heal on next load.loadGraph(workspace)andgetNodeFiles(slug, workspace)thread the active workspace through every/api/workspaceand/api/optimal/*call; the/graphroute remounts on workspace switch.optimal_node_filesnow returns each signal'sid;getSignal(id, workspace)passes the scope; the Nodes page drills in with the real id.Verification (live engine on :4200)
svelte-check: 0 errors (4 pre-existing warnings). Enginemix compile: clean.default/defaultlocalStorage state now recovers to OperatorOS + a populated workspace and renders the node tree./graphrenders 262 nodes / 420 edges for a populated workspace (was 0).id(fix #4) to appear; the change compiles and the/api/signals/:id?workspace=contract is verified manually.Out of scope / follow-ups
memoryandwikiare empty by data-state (no promoted facts, no curated wiki pages), not a bug.+layout.sveltecreateWorkspace({ tenant: $activeOrgId })has the same org-vs-tenant mixup on the write path and noorganizationfield. Left for a separate pass.🤖 Generated with Claude Code