Skip to content

Joining an existing workspace leaves already-indexed nodes on their old workspace_id, and the fail-closed scope filter turns that into count: 0 for the whole repo #673

Description

@chenroth-island

Describe the bug

BackfillWorkspaceSlugs (internal/indexer/workspace_resolve.go) stamps WorkspaceID/ProjectID from config "whenever those fields are empty" — written to close the upgrade gap where old snapshots had "". It has no path for a field that is non-empty but stale.

A repo tracked on its own gets workspace_id = <repo name>. When it later joins a workspace the declaration moves — gortex workspace list shows the new one — but existing nodes keep the old key; only newly written nodes get the new one. filterTextMatchesByResolvedScope (tools_search_text.go) then fail-closes, dropping any match it cannot attribute to an in-scope node, so every query against that repo returns count: 0 with no error.

To Reproduce

  1. gortex track <repo> on its own and let it index — it self-keys workspace_id = <repo name>.
  2. gortex workspace set-all shared --global --yes, then restart the daemon.
  3. Any search text for a string you know is in that repo returns count: 0. grep finds it.
  4. Confirm the cause:
select repo_prefix, workspace_id, count(*) from nodes group by 1,2;
-- repo_prefix = <repo>, workspace_id = <repo>   -- never 'shared'

Expected behavior

Joining a workspace re-stamps existing nodes, or the query reports that it could not attribute them. A repo silently answering zero while workspace list shows it correctly configured is indistinguishable from "this string isn't in the codebase".

Environment:

  • OS: macOS 26.5.1 (25F80)
  • Go version: 1.26.5
  • Gortex version: v0.63.7+0988412

Additional context

(Repo names anonymized.) On a five-repo store the split tracks exactly when each repo was tracked relative to the workspace:

repo-ts    | repo-ts    | 818190   <- stale, returns 0
repo-ts    | shared     |  91850
repo-cs    | repo-cs    | 540733   <- stale, returns 0
repo-cs    | shared     |     43
repo-go    | shared     | 537315   ok, tracked after the workspace existed
repo-infra | shared     | 104203   ok
repo-agent | shared     |  66574   ok

The three clean repos return hits; the two stale ones return zero. The store is intact throughout — symbol_fts joins 100% to nodes, and the graph holds nodes under the exact stamped path the trigram match carries, so this is purely the scope filter. UPDATE nodes SET workspace_id='shared', project_id='shared' over the two stale repos restored exact grep parity immediately.

One secondary fix worth taking regardless: the scope_note says "0 results within the active scope (repo:X) — widen with repo:"*"", which points at scope narrowing rather than the attribution failure that actually happened — and repo:"*" is inert for both text and symbols. project:<workspace> as a top-level arg does work, and is the fastest way to confirm this diagnosis.

Related from the other direction: #663 derives the workspace id from the folder name and collides across branches. Same root cause — the id comes from a mutable name and is never reconciled — opposite symptom.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions