agentleFS
dvcdsysdvcdsys/code-index/skills/cix-workspace/SKILL.md

cix-workspace

Skill31 starsChanged 2 months agoMITView on GitHub

Cross-project research workflow for cix workspaces. Load the `cix-workspace` skill explicitly when a request spans multiple repos and you want the full workflow guidance (which repos? what code? what changes?) plus the trust rules for interpreting workspace search responses. Bundles the cix-workspace-investigator sub-agent for parallel per-repo fan-out. Do not auto-trigger.

  • In this repositoryOne other file it gives its agents.

The file

Show its rules and text

We split this skill into the rules it gives an agent

30 rules. About 0 are common, 13 are distinctive, and 17 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈13

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Agent rule: use the default server (no flag) unless the user names a specific server, or the primary project's workspace isn't on the …

    line 62
  2. Very specific:

    Never guess an alias — run cix config show to see the configured names.

    line 64
  3. Very specific:

    If you're not sure, run cix ws once to see whether the primary project is even part of a workspace.

    line 84
  4. Very specific:

    If cix ws doesn't list the workspace your task is about, it may live on a different server — re-run with --server <alias> (the alias from …

    line 102
  5. Very specific:

    If the workspace shows stale_fts_repos in any search response later, trust the dense ranking less — see the troubleshooting section.

    line 107
  6. Distinctive:

    Run workspace search with a short, term-rich query, not the full user sentence:

    line 112
  7. Very specific:

    A. Quick scan (≤ 2 repos to investigate): use single-project search directly via the CLI, scoped with -n to the project.

    line 161
  8. Distinctive:

    Run them concurrently (one message, multiple Agent tool calls).

    line 200
  9. Distinctive:

    Don't ask if the answer is obvious from the chunks.

    line 235
  10. Very specific:

    If bm25_score >> dense_score for a project: it's relevant because of literal token overlap (product name appears in code).

    line 254
  11. Very specific:

    If dense_score >> bm25_score: it's relevant because of semantic similarity (handler shape matches the query intent) but the literal term …

    line 257
  12. Distinctive:

    If both are near zero: you're seeing the project because nothing else cleared the gate either.

    line 261
  13. Very specific:

    When projects[] shows the target at rank 1 with a clear lead (project_score ≥ 1.5× the next), switch to per-project search: cix search -n …

    line 301
  14. Very specific:

    Default workspace min_score is 0.4.

    line 312
  15. Distinctive:

    If two query words are each domain-overloaded (e.g.

    line 321
  16. Distinctive:

    If you think top-1 is wrong:

    line 342
  17. Distinctive:

    Only after scanning, reformulate.

    line 346
  18. Very specific:

    When dropping from workspace to per-project search with a natural- language query (e.g.

    line 352
  19. Distinctive:

    When you have 3+ relevant repos, fan out.

    line 404
  20. Very specific:

    Use the dedicated cix-workspace-investigator sub-agent, which ships with this skill.

    line 408
  21. Distinctive:

    your: call, per spawn. The sub-agent follows your instructions.

    line 413
  22. Very specific:

    Pass the server alias too: If the workspace is on a non-default server, the sub-agent's cix search -n <project> calls must carry the *same* …

    line 442
  23. Distinctive:

    Run all sub-agents in one message with multiple Agent calls so they execute in parallel.

    line 526
  24. Very specific:

    Verify that projects with bm25_score = 0 aren't masquerading as relevant.

    line 567
  25. Distinctive:

    After reindex, BM25 populates incrementally per-file as chunks are written.

    line 597
  26. Very specific:

    Every workspace repo is still indexing.

    line 612
  27. Distinctive:

    When the user's task plausibly spans more than one repo:

    line 717
  28. Very specific:

    Read projects[] → that's your scope (Q1 answered).

    line 724
  29. Distinctive:

    Ask the user to confirm the scope and plan before implementing.

    line 731
  30. Very specific:

    If bm25_score is 0 across the board, the FTS index is stale — fix it before trusting the result.

    line 733

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

cix workspace — Cross-Project Research Workflow

You usually work inside one repo — your primary project — the directory the user opened you in. Most tasks are fully contained there and cix search / cix definitions / cix references are the right tools.

But some tasks are not contained. A request like "wire feature X through the platform" can touch a half-dozen repos in different languages, layers, and shapes — a service, a shared library, the infra manifests, an API spec. Reading the primary repo alone gives you 1/N of the picture. Worse, you don't know which N repos are actually involved until you look.

cix workspace is the tool for that. It searches every repo in a named workspace at once and tells you:

  1. Which repos are actually relevant to this request.
  2. Which code in those repos is the entry point.
  3. What changes need to land in each, and in what order.

Those three questions are the goal of using this skill. Don't jump to implementation before you can answer all three with evidence.

Prerequisite: a populated workspace. This skill assumes the workspace already exists and its repos are indexed. If it doesn't, create and populate one first (owner/admin): cix ws create "<name>", then cix ws "<name>" add <project> for each already-indexed repo — or clone new GitHub repos in via the dashboard. cix ws lists what's available; the main cix skill has the full management verb reference.


First: which server hosts the workspace?

The cix CLI can be configured with several named servers (a local box, a remote corporate backend, …). Each server hosts its own set of workspaces and projects — a workspace named platform on one server is unrelated to anything on another. Every cix command targets the default server unless you pass the global --server <alias> flag (or set CIX_SERVER).

cix config show     # lists configured servers; * marks the default

A workspace and all its repos live on exactly one server. So before you run the workflow, decide which server you're on, then be consistent: pass the same --server <alias> to every command in the flow — cix ws, workspace search, per-project drill-down, and the sub-agent fan-out. Mixing servers mid-workflow (orient on server A, drill down on the default) silently returns empty or wrong-repo results, because the project simply doesn't exist on the other server.

Agent rule: use the default server (no flag) unless the user names a specific server, or the primary project's workspace isn't on the default. Never guess an alias — run cix config show to see the configured names. Once you know the alias, thread it through the whole workflow. The examples below omit --server for readability; add it to every command when the target workspace is on a non-default server.


When to reach for workspace search

Signal in the user's requestWhat to do
Names a product / acronym you don't fully recognize from primary repoWorkspace search the acronym, see where it lives
"Add X to the Y flow", "wire Z into A"Workspace search Y or Z — likely cross-cutting
"Across services", "between repos", "end-to-end"Workspace search the feature
Talks about an event / topic / contract / API endpointWorkspace search the event name
References infra / deployment alongside codeWorkspace search — infra repo is probably in the workspace too
"How do I change X in production / staging"Workspace search BUT look past top-1 — the answer is usually a manifests/config/contract repo even when a code repo ranks higher (rule 7 below)
Plain bugfix entirely inside one fileDon't workspace search. cix search is enough
User points at a specific symbol / file pathDon't. cix definitions <name> or just Read the path

If you're not sure, run cix ws once to see whether the primary project is even part of a workspace. If it isn't, this skill doesn't apply.


The workflow

The goal-driven loop. Don't shortcut it. Each step is fast.

Step 0 — orient

cix config show              # which servers exist? which is default?
cix ws                       # list workspaces on the (default) server
cix ws <name>                # describe — confirm repos are indexed (✓ count)

If cix ws doesn't list the workspace your task is about, it may live on a different server — re-run with --server <alias> (the alias from cix config show) and keep that flag on every later command. Lock in the server here, before searching.

If the workspace shows stale_fts_repos in any search response later, trust the dense ranking less — see the troubleshooting section.

Step 1 — answer "which repos?"

Run workspace search with a short, term-rich query, not the full user sentence:

# GOOD — short, term-rich (a product acronym + an action verb)
cix ws platform search "rate-limit middleware"

# BAD — full sentence dilutes BM25 with stopwords ("add", "to", "a")
cix ws platform search "Add a rate limit to every API endpoint"

Why short: the hybrid algorithm fuses BM25 (literal token match) with dense (semantic). BM25 carries the project-gating signal — repos that share zero vocabulary with the query drop out. Common words ("add", "flow", "for") match everywhere and dilute that signal.

Read the response:

  • projects[] is the answer to Q1. Sorted by project_score (candidacy). Each entry has bm25_score (literal-token overlap) and dense_score (semantic similarity).
  • Projects below the per-query relative threshold are already filtered out — you only see the survivors.
  • Top entry's project_score is your reference. Entries at 60-100% of top are core relevant. Entries at 40-60% are secondary. Below 40% would have been dropped server-side.

Always include the primary project even if workspace search ranks it low — the user's task is rooted there. The workspace's other repos are dependencies / consumers / providers / counter-parties.

Step 2 — answer "what code is relevant?"

Now switch from workspace search to per-project search. Workspace search is a scoping tool: it tells you which repos are in play and shows a teaser of chunks, but that teaser is capped (round-robin, ~5 chunks per repo) and is NOT where you read the code. Once you know the target repos, drill into each one with single-project search (cix search -n <project_path>) or a cix-workspace-investigator sub-agent — that is where the real, file-grouped depth comes from. Don't try to answer the task from the workspace chunk panel alone.

For each repo from step 1, look at the chunks panel. The chunk list is interleaved by rank across surviving projects so each repo's top hit appears early. Use these chunks as starting points for a deeper read, not as the full answer.

For repos other than the primary, you have two options:

A. Quick scan (≤ 2 repos to investigate): use single-project search directly via the CLI, scoped with -n to the project. Pass the project_path from the workspace-search projects[] panel verbatim:

# Search inside one specific project (-n = exact project ID from cix list /
# the workspace projects[] panel). --server keeps it on the same backend
# the workspace lives on — REQUIRED when that's not the default server.
cix search "rate limit middleware handler" -n <project_path> --min-score 0
cix search "rate limit middleware handler" -n <project_path> --server corporate --min-score 0

The per-project default min_score is 0.2 — light floor that keeps abstract NL queries non-empty. For drill-down on a natural- language question ("how does X work end-to-end"), pass --min-score 0 explicitly to be safe. For strict code-symbol matching, pass 0.4+.

Workspace repos are external (server-cloned), so once search points you at a file you can read the actual source — not just the capped chunk teaser — straight from the server's checkout:

cix tree internal/api -n <project_path>              # browse the tree (one level)
cix file internal/api/handler.go -n <project_path>   # whole file
cix file internal/api/handler.go --lines 80:140 -n <project_path>

Prefer the CLI over a raw curl … /api/v1/projects/{hash}/search: the CLI resolves the right server (and its key) from your config, so you can't accidentally point $CIX_URL/$CIX_KEY at a different server than the workspace. If you do hand-roll curl, make sure the URL + key belong to the server that hosts this workspace.

B. Fan-out to sub-agents (≥ 3 repos, or you need a thorough read): spawn one cix-workspace-investigator sub-agent per relevant repo, in parallel. See the dedicated Sub-agent fan-out pattern section below for the four-part prompt template, including how to pass seed chunks with your interpretive commentary.

Run them concurrently (one message, multiple Agent tool calls). When they report back, you have N independent reads to synthesize, not N sequential rabbit-holes.

Step 3 — answer "what changes?"

This is your job, not a sub-agent's. Sub-agents report findings; you write the plan.

For each relevant repo:

  • What needs to change (specific file:line, or a new file).
  • Why (which step of the data flow this implements).
  • Order constraints (e.g. "shared-models migration must deploy before backend reads new field").
  • Tests that prove it works.

Confirm with the user before any of this lands. The plan is the deliverable of this skill; the implementation is a separate step.

Throughout — ask, don't guess

Trigger a clarifying question when:

  • Top-2 projects are at near-equal project_score and have different labels — the request might fit either repo, ask which.
  • bm25_score is 0 across all projects → either the FTS index is stale (see troubleshooting) OR the user's term doesn't exist literally in any repo. Ask the user for the term that would appear in code ("we call it Order in code, not Trade").
  • A sub-agent reports it can't find a clear entry point — surface that uncertainty back to the user, don't paper over it.
  • The implementation plan needs a deploy-order assumption — confirm who owns each repo and what their cycle looks like.

Don't ask if the answer is obvious from the chunks. The bar is "I have two plausible interpretations and the wrong one costs the user real time."


Reading the projects panel — what the numbers mean

project-a@main   0.500   5 hits   bm25 0.421   dense 0.556
project-b@main   0.412   5 hits   bm25 0.318   dense 0.498
project-c@main   0.288   3 hits   bm25 0.155   dense 0.362
  • project_score (first column): the α-blended candidacy in [0, 1]. Top = strongest signal across both retrieval modes.
  • bm25_score and dense_score: the raw per-mode signals. The algorithm normalizes these per query before blending — useful for diagnosis, not for sorting.
  • If bm25_score >> dense_score for a project: it's relevant because of literal token overlap (product name appears in code). Trust the surface area but verify semantic relevance manually.
  • If dense_score >> bm25_score: it's relevant because of semantic similarity (handler shape matches the query intent) but the literal term isn't there. Common when the user's term is a product nickname not used in code.
  • If both are near zero: you're seeing the project because nothing else cleared the gate either. Treat with skepticism.

Trust rules — making sense of the response

These ten rules were derived from a calibration eval (113 synthetic queries + 5 real engineering tasks against a mixed-domain workspace). Apply them before acting on workspace-search output. Numbers below are empirical, not vibes.

Rule 1 — chunk.score >= 0.4 is the trust threshold

Chunks with score < 0.4 are noise about 75% of the time (rank-inversion and weak-signal FPs from the relative project gate). Skim them only when the higher-scored chunks don't answer the question. With the default min_score=0.4 you usually won't see them at all; if you passed min_score=0 (intentional broad sweep), apply this rule yourself.

Rule 2 — chunk.score == 0 is a BM25-only hit, not low confidence

The chunk's project matched the literal query tokens via FTS5 but the embedding side didn't surface it. These are valuable when the query carries project-specific identifiers (CamelCase symbols, file names, acronyms). Discount them when the query is a generic English word (error, data, config) — common-word BM25 hits are noise.

Rule 3 — Top-1 of projects[] is correct ~70% of the time in real tasks

The synthetic eval measured 91% on single-target queries; real engineering tasks hit ~70% because real queries often span layers (see rule 7). When the top-1 project doesn't match your task's intent, scan ranks 2–5 before reformulating — the right repo is usually there. The projects[] panel is the answer to "where do the words live", not "where should the change happen".

Rule 4 — Drop down to single-project search for depth

When projects[] shows the target at rank 1 with a clear lead (project_score ≥ 1.5× the next), switch to per-project search: cix search -n <project_path> "<query>" (add --server <alias> when the workspace is on a non-default server). You get file-grouped, deeper results without the cross-project round-robin cap of 5 chunks per repo. -n takes the exact project_path from projects[] (e.g. github.com/owner/repo@branch) — that is the correct, working way to target one project; don't use -p (a filesystem path) for a remote repo.

Rule 5 — min_score=0 for intentional cross-project sweeps

Default workspace min_score is 0.4. For queries that should legitimately span many repos ("authentication", "configuration loading", "Kafka consumers"), pass min_score=0 explicitly. Expect projects[] to list 5–8 entries — that's the feature, not a bug. Ignore rule 1 in this mode: many real positives sit below 0.4 in genuine cross-cutting queries.

Rule 6 — Add a 3rd disambiguating token, carefully

If two query words are each domain-overloaded (e.g. "client SDK" could be the generated API client, the shared library, or a model type), add a third word. Prefer meta-tokens (endpoint, route, handler, manifest, migration, config file) over tech-stack guesses (grpc, kafka, terraform) — wrong stack guesses actively rotate the ranking away from the right answer. If unsure of the stack, run the query without a disambiguator first, read the top-1 project's language/path patterns, then refine.

Rule 7 — "Change X in production" → manifests repo, not code repo

For tasks framed as deploying / configuring / overriding a feature, the answer usually lives in a manifests / config / contract repo (K8s overlays, Helm charts, OpenAPI specs, environment-specific yaml). Workspace search ranks by token frequency, so the code repo typically wins. Look at projects[] for repos with manifests, config, platform, deploy, contract, openapi, infra in their names — those are often the right targets even at rank 3–5.

Rule 8 — When top-1 doesn't fit, scan first, reformulate second

If you think top-1 is wrong:

  1. First, scan ranks 2–5. The right project is there ~80% of the time when the layer mismatch caused rule 3 to fail.
  2. Only after scanning, reformulate. Reformulating before scanning wastes a round-trip and risks the new query introducing fresh layer confusion.

Rule 9 — For per-project NL drill-down, pass min_score=0 explicitly

When dropping from workspace to per-project search with a natural- language query (e.g. "how does X work"), pass min_score=0 to be safe. The per-project default min_score=0.2 is lighter than it used to be (0.4) and usually fine, but abstract semantic queries can score in the 0.2–0.3 range that the default still rejects.

Rule 10 — Words ≠ change location (the intent-vs-tokens watchword)

Workspace search ranks projects by where the words live. Your task is usually about where the change should happen. These coincide ~70% of the time, not 91%. When in doubt: read the chunks in ranks 2–5 before committing to a target repo.

Quick example — when rules 7 and 10 save you

User: "Change the database timeout for the staging environment of the order service."

Workspace search ranks the order-service code repo at #1 (it's where the word "database" appears most). But the change needs to land in the environment-platform manifests repo at rank #4. If you stopped at top-1 you'd edit the wrong file. Rules 7 and 10 remind you to scan further.


Primary project nuance

You are typically cd'd into a single repo. That's the primary project. The user's task is framed from that repo — they're extending it, integrating with something it depends on, or wiring up something that consumes it.

Patterns:

  • The change centers on primary, others are consumers/providers. Most common. Primary gets the bulk of the implementation; the other repos get small adapter changes (new field consumption, new webhook subscriber, new client method).
  • The change is in another repo, primary just calls it. Less common but real. Primary's role is the integration test or the feature-flag flip; the heavy lifting is elsewhere.
  • The change is genuinely distributed. Migrations, schema changes rolling through many services, protocol bumps. Each repo gets a coordinated change with deploy-order constraints.

Workspace search tells you which pattern you're in. Don't assume.


Sub-agent fan-out pattern

When you have 3+ relevant repos, fan out. Sub-agents run with isolated context — the main session stays clean (no per-repo code chunks bloating it) and the investigations run in parallel.

Use the dedicated cix-workspace-investigator sub-agent, which ships with this skill. It's a thin, read-only shell around cix search / cix def / cix refs / Read / Grep with three hard rules baked in: stay inside the assigned project, no edits, no recursion. The methodology — what to look for, what to report, in what format — is your call, per spawn. The sub-agent follows your instructions; it doesn't second-guess them.

The four parts of a good per-spawn prompt

You'll write one prompt per repo. A good one has four parts:

1. The user's task, verbatim

Sub-agents have zero prior context. Paste the original user request even if it feels redundant — your interpretation might be wrong, and the user's wording is the ground truth the sub-agent should reason from.

2. The project identifier you're assigning

Pass it in the exact form cix list shows. Two shapes are possible:

  • Local working tree: /Users/.../some-repo. The repo exists on disk; the sub-agent can use Read/Grep on top of cix.
  • Remote-only: github.com/<org>/<repo>@<branch>. The repo is not on disk — it's a GitHub-attached project indexed only by the cix server. The sub-agent must rely entirely on cix search/def/refs (passing -n <project_name>) and the chunks they return.

Workspace search output gives you the identifier as project_path on each entry in projects[]. Paste that string verbatim into the sub-agent prompt, and tell the sub-agent explicitly which shape it is so it doesn't waste calls grepping a tree that isn't there. One repo per spawn.

Pass the server alias too. If the workspace is on a non-default server, the sub-agent's cix search -n <project> calls must carry the same --server <alias> — otherwise they hit the default server, where the project doesn't exist, and come back empty. State it plainly in the prompt: "This project lives on server corporate; add --server corporate to every cix call." If you're on the default server, say so (or omit it) so the sub-agent doesn't invent a flag.

3. Seed chunks with your commentary

This is the part most often done badly. Don't just paste raw chunk pointers and hope the sub-agent figures out what matters. You saw the workspace search response; you have hunches about which chunks are real entry points and which are noise; pass that down.

For each chunk you cite, add one short line of interpretation. For the response as a whole, flag suspicious signals:

  • Which chunk looks like the most likely entry point and why
  • Which chunks look like test fixtures / dead code / wrong-layer the sub-agent should de-prioritize
  • Numeric signals that need a second opinion: score=0 (BM25-only literal — verify the token isn't a false friend), score < 0.4 (low confidence, possible rank-inversion), bm25_score high + dense_score near zero (literal-only match — concept may not actually live here)
  • Whether you suspect this repo is wrong-layer (rule 7) — tell the sub-agent to confirm relevance before diving into the chunks

Example "good chunk block":

Seed chunks from workspace search:
- `internal/gateway/server.go:412-418` (score 0.55) — looks like the
  HTTP handler entry point for the rate-limit feature; confirm it
  invokes the limiter middleware rather than just returning 429.
- `internal/gateway/middleware.go:89-93` (score 0.49) — middleware
  registration site. Verify whether rate-limit is wired here or
  elsewhere.
- `tests/integration/rate_limit_test.go` (score 0.41) — integration
  test. Useful for understanding the expected shape, but not where
  the change lands. Skim only.
- `pkg/shared/util.go:1-30` (score 0) — BM25-only hit, "limit"
  appears in a comment. Almost certainly noise; skip unless you need
  shared utilities.

Panel-level notes:
- Server: this project is on `corporate` — pass `--server corporate` on
  every cix call (it does NOT exist on the default server).
- Workspace ranked this project #1 with a clear lead (project_score
  1.000 vs next 0.860). High confidence this is the right repo.
- bm25_score=8.5, dense_score=0.54 — strong on both signals, not a
  wrong-layer concern.

4. Explicit deliverable

Tell the sub-agent exactly what to return and in what shape. Each task has different needs:

  • "Confirm whether this repo is in scope. Yes / no / partial + one sentence why."
  • "Find the entry point for the rate-limit middleware. Report file:line of the entry and a five-step trace through the call graph."
  • "List every file that would need to change to add a new audit-log event type. No code, just file path + one-line per-file reason."

Vague deliverables ("investigate this repo") → vague answers.

Anti-patterns to avoid

  • "Investigate this repo for rate-limit" — no deliverable. The sub-agent guesses scope and you can't verify the result.
  • Three paragraphs of context with nested questions — sub-agent answers the wrong question. Pick one deliverable per spawn.
  • "Read all the auth code" — unbounded. Either fails or returns a wall of text.
  • Pasting raw chunks without interpretation — you saw the response, you have hunches about what matters. Sub-agent doesn't. Skipping commentary throws away the most valuable thing you can pass down.

Mechanics

Run all sub-agents in one message with multiple Agent calls so they execute in parallel. Wait for completion. Synthesize their reports yourself — sub-agents don't see each other's work; you do. Surface inconsistencies (e.g. two repos disagree on which event format is canonical) back to the user.

Model inheritance. cix-workspace-investigator declares model: inherit in its frontmatter, so each spawn runs on the same model as the main session. You don't need to pass model: on Agent calls. If you do pass it, you'll override inheritance — only do that intentionally (e.g. forcing a smaller/faster model for a trivially-bounded look-up).


Worked example — why this skill exists

A representative failure mode that motivated the hybrid algorithm:

The naïve approach: running workspace search with a full natural- language sentence ("Add feature X to product Y"). The pre-hybrid implementation was pure-dense — it returned the N nearest vectors regardless of how far away "nearest" actually was. Every repo in the workspace surfaced, including repos that contained zero literal mentions of either the feature name or the product code. Confidently reporting all of them as "relevant" wasted time on completely unrelated repos.

The structural failure:

  1. Pure-dense fan-out cannot tell "no signal" apart from "weak signal" — a vector search always returns the K nearest vectors.
  2. Long natural-language queries dilute the few tokens that carry the actual gating signal.
  3. Without a sparse-retrieval channel, an acronym or unique identifier query has nothing to lock onto.

What this skill teaches instead:

  1. Query with just the high-precision term first — the product acronym, the feature name, the unique symbol. Everything else is noise.
  2. Verify that projects with bm25_score = 0 aren't masquerading as relevant. After the hybrid landed, repos with no literal matches AND only marginal dense similarity drop out automatically via the project gate.
  3. Confirm with the user before treating "this repo surfaced in search" as "this repo is in scope for the change".

The lesson encoded in this skill:

  • Step 1: query the term, not the sentence.
  • Step 1: trust the project gate; if a repo dropped out, it dropped out for a reason.
  • Step 2: read the surface area from projects[] first, then read the chunks as starting points.
  • Step 3: never assume "in search results" == "in scope". Verify.

Troubleshooting

bm25_score is 0.000 on every project

The workspace was indexed before the FTS5 mirror existed and the sparse half of the hybrid is empty. Hybrid degrades to pure-dense fan-out — the same algorithm that produces the false-positive failure mode described in the worked example above.

The response includes stale_fts_repos listing the affected project_paths. Fix: reindex each project (dashboard → project card → reindex button, or POST /api/v1/projects/{hash}/reindex). After reindex, BM25 populates incrementally per-file as chunks are written.

Until reindex completes, don't trust the project gating — the algorithm is producing the old failure mode. Verify project relevance by literal grep on the term.

status: "empty" despite obviously-relevant repos in the workspace

Either:

  • The query terms don't appear literally in any repo AND the dense similarity is below threshold for everything (project-gate dropped everyone). Re-phrase with the term the code actually uses, or lower min_score.
  • Every workspace repo is still indexing. Check pending_repos in the response.

status: "partial_failure"

At least one repo errored out (failed_repos array names them). Common cause: a missing or corrupt vector collection. The remaining repos still returned results. Surface to the user; don't silently treat as complete.

Top-2 projects are at near-equal candidacy

The algorithm isn't confident which repo is more relevant. Possible causes:

  • The feature genuinely lives in both. Ask the user which they intended as primary scope.
  • The query is too broad — both repos match generic vocabulary. Re-query with a more specific term.
  • One repo is a fork or duplicate. Confirm with cix ws <name> describe.

One project absolutely dominates everything else

Could be legit (the user's task is mostly contained in one repo and that repo is just very dense with relevant content). Or could be a single repo accidentally matching the user's stopwords across many files. Spot-check: is the project's bm25_score driven by the high-IDF term (the product name) or by common words?

Top-1 is wrong-layer (rule 7 / rule 10 in action)

The top-1 project contains the words but isn't where the change should land. Classic example: "deploy X to staging" → workspace ranks the code repo for X at #1, but the staging overlay lives in a manifests repo at rank #4. Or: "add API endpoint Y" → ranks the backend implementation at #1, but the OpenAPI contract repo at #3 must be updated first.

Fix: scan ranks 2–5 explicitly. Look for projects whose names hint at a different layer (*-platform, *-manifests, *-contracts, *-config, *-infra, openapi*). If you see one, that's probably your real target.

Disambiguator backfired — the query lost its grip

You added a 3rd word to discriminate between two overloaded terms, and the response is worse — top projects all have mediocre scores and the right repo isn't among them anymore. This usually happens when the added token belongs to a different stack than your target (e.g. you guessed a transport / framework / library that the canonical repo doesn't use), so the extra token rotates the ranking toward unrelated repos.

Fix: strip the guessed-stack token. Try a meta-token instead (endpoint, route, handler, manifest, migration). Or: run the 2-word query as-is, scan the top-1 project's path patterns and language to see what stack it actually uses, then refine.


Quick command reference

# Servers (run first if more than one backend is configured)
cix config show                 # list servers; * marks the default
cix ws --server corporate       # any command takes the global --server <alias>
# (CIX_SERVER=corporate also selects it; --server wins over the env var)

# List workspaces
cix ws
cix ws list --json

# Describe one workspace (always do this before searching)
cix ws platform
cix ws platform describe --json

# List repos attached to a workspace
cix ws platform list
cix ws platform repos --verbose

# Search a workspace
cix ws platform search "rate-limit middleware"
cix ws platform search "JWT validation" --top-projects 8 --top-chunks 30
cix ws platform search "audit logging" --json

Flags:

  • --top-projects N — surface up to N projects in the panel (default 10, max 50). Increase for very broad explorations.
  • --top-chunks K — return up to K chunks total (default 20, max 200). Round-robin interleaved across surviving projects.
  • --min-score F — drop dense hits below cosine F before scoring. Default 0.4 (symmetric with per-project search default). Pass 0 explicitly for intentional cross-project sweeps that need long-tail recall — broad concepts like "authentication" or "Kafka consumers" that legitimately live in many repos. Higher values (0.5+) for queries you want laser-focused.
  • --json — raw machine-readable response.

TL;DR

When the user's task plausibly spans more than one repo:

  1. cix config show → if more than one server, decide which one hosts the workspace and thread the same --server <alias> through every command below (default server → no flag needed).
  2. cix ws → find the workspace, then cix ws <name> describe it.
  3. Workspace search with a short, term-rich query.
  4. Read projects[] → that's your scope (Q1 answered).
  5. For each repo in scope, either single-project search (cix search -n <project_path>) or spawn a cix-workspace-investigator sub-agent — in parallel, with seed chunks, the server alias, AND your interpretive commentary on what to trust.
  6. Synthesize the sub-agent reports → plan changes per repo, with order constraints (Q2 + Q3 answered).
  7. Ask the user to confirm the scope and plan before implementing.

If bm25_score is 0 across the board, the FTS index is stale — fix it before trusting the result.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.