Rules specific to the RAG-indexing plugin (scanner, watchers, embedders,
CodeIndexManager, the git-index service). The repo-root
AGENTS.md applies in full — in particular the rules that
span this plugin and core (Tree-Sitter Language Registration, Indexer Policy
Single-Source-of-Truth, Headless Hosts Run The
Extension) stay there. The sibling CLAUDE.md is a symlink to this file.
-
GitIgnore Oracle Rule: The indexer's scanner, file-watcher, and service-factory MUST accept
IIgnoreFilter(fromgit-ignore-filter.ts) rather than the npmIgnoretype. AtCodeIndexManager._recreateServices(), preferGitIgnoreFilter.create(workspacePath)— which runsgit ls-files -z --cached --others --exclude-standard, honouring nested.gitignore,.git/info/exclude,core.excludesfile, and negation patterns — over a flat root-onlyignore().add()parse. Fall back to the flat parse only whencreate()returnsnull. A**/.gitignorewatcher (_ensureGitIgnoreWatcher, debounced 500 ms) refreshes on rule changes. Do NOT reintroduceimport { Ignore } from "ignore"in the indexer. -
Sole-Indexer Rule: Exactly ONE host writes a given code index. Every other host sharing that index is provisioned search-only —
searchOnly: trueplus the sharedindexKeyin this plugin's config (ordinary layered.shofer/plugin config) — andCodeIndexManagerhonours the flag in both entry points:initialize()step 7 andstartIndexing(). A search-only host that scanned would duplicate embedding work and race the indexing host as a second writer into one collection. Never "fix" a host that isn't indexing by enabling indexing on it. -
Index Identity Rule: The Qdrant collection name and the local cache filename are both hashed from the index key resolved by
CodeIndexManager._resolveIndexKeyPath()(src/manager.ts), which prefers the controller-assignedindexKeyover the local path. Do NOT derive index identity from the host's workspace path: hosts sharing an index would miss each other when they mount it at different paths, and unrelated hosts would collide when they merely share a path — every deployed executor pod runs--workspace /home/node/workspace, so path-derived identity silently maps different content onto one collection. Adding a new consumer of the collection/cache name means routing it through_resolveIndexKeyPath, not re-deriving fromworkspacePath. -
Per-Provider Concurrency Lane Rule: External-API concurrency limiters (embedder providers in
src/engine/embedders/) MUST be keyed by(provider, endpoint)at module scope and shared across everyIEmbedderinstance — not per-instance. Otherwise each window creates its ownIEmbedderand an N-instance reindex storm bypasses per-instance limits and trips the provider's rate limit (Ollama withOLLAMA_LANE = 1is the canonical victim; cloud defaults to4). The lane lives in a module-scopedMap<string, PQueue>and MUST forwardAbortSignalso a cancelled task doesn't hold the slot. -
Submodule-Aware Git Scanning Rule: Any code that walks files by consulting git (
GitIgnoreFilter, and the git-history orchestrator/watcher undersrc/git-index-service/) MUST descend into submodules declared in.gitmodules: read.gitmodulesonce per scan root, recurse with the submodule path as the newcwd, and union the results. Otherwise files inside nested repos are invisible to the indexer and git-history watcher.