Ad-hoc project attach: project="<absolute dir>" indexes a foreign directory once, read-only, no state written into it (zero-fallback) #559

Open
opened 2026-11-09 12:29:11 +01:00 by buildagent · 2 comments
Member

Part of the zero-fallback epic (#555). Cause 2: code outside the configured projects is unreachable.

Observed

Checking a corpus copy (~/.cache/cosi-corpus/cs-dapper, a bind-diff staging dir) meant code-index query --root <dir> in the shell: cold 5–60 s, JSON on stdout, no reuse across calls. sed -n 225,235p won. Workers verifying binds in foreign checkouts did the same.

Proposal

project: "<absolute directory>" on any tool attaches that directory as an ad-hoc read-only project for the session:

  • indexed once by its own daemon (the existing per-root daemon, reused across calls and sessions);
  • never fanned out;
  • disclosed as relationship: ad_hoc with its root;
  • writes no state into the directory unless it is already a code-index project (see the #546 observation: state dirs appeared in corpus checkouts nobody indexed). Its index lives under the user cache, not in the foreign tree.

Optionally an explicit attach_project(path) for clients that want to pre-warm. The first call answers warming_up with a retry hint rather than blocking.

Acceptance

  • e2e: from a session rooted elsewhere, search_symbols(project="/tmp/x") warms then answers. A second call reuses the daemon. No .code-index/ is created inside /tmp/x.
  • The benchmark task "check a bind against source in a foreign checkout" needs zero shell calls.
Part of the zero-fallback epic (#555). Cause 2: **code outside the configured projects is unreachable.** ## Observed Checking a corpus copy (`~/.cache/cosi-corpus/cs-dapper`, a bind-diff staging dir) meant `code-index query --root <dir>` in the shell: cold 5–60 s, JSON on stdout, no reuse across calls. `sed -n 225,235p` won. Workers verifying binds in foreign checkouts did the same. ## Proposal `project: "<absolute directory>"` on any tool attaches that directory as an **ad-hoc read-only project** for the session: - indexed once by its own daemon (the existing per-root daemon, reused across calls and sessions); - never fanned out; - disclosed as `relationship: ad_hoc` with its root; - writes no state into the directory unless it is already a code-index project (see the #546 observation: state dirs appeared in corpus checkouts nobody indexed). Its index lives under the user cache, not in the foreign tree. Optionally an explicit `attach_project(path)` for clients that want to pre-warm. The first call answers `warming_up` with a retry hint rather than blocking. ## Acceptance - e2e: from a session rooted elsewhere, `search_symbols(project="/tmp/x")` warms then answers. A second call reuses the daemon. No `.code-index/` is created inside `/tmp/x`. - The benchmark task "check a bind against source in a foreign checkout" needs zero shell calls.
Author
Member

Second independent report (codex-531, #531 bind audit): the staged corpus sources under the bind-diff output (before/<repo>/source/) cannot be read or navigated through the MCP instrument. The worker had to use code-index query --root in the shell or plain reads. The measured fallback classifier (#556) puts these in its foreign class: the lead had 2 such fallbacks in the baseline session, and the #531 audit adds more.

Second independent report (codex-531, #531 bind audit): the staged corpus sources under the bind-diff output (`before/<repo>/source/`) cannot be read or navigated through the MCP instrument. The worker had to use `code-index query --root` in the shell or plain reads. The measured fallback classifier (#556) puts these in its `foreign` class: the lead had 2 such fallbacks in the baseline session, and the #531 audit adds more.
Author
Member

More field evidence from codex-531's #531 corpus audit (dogfood D5–D10, D13):

  • D5: reading a staged corpus copy returned path_outside_known_roots, which is exactly this issue.
  • D6: the workaround, a CLI code-index query --db per window, took 36 subprocess calls and 103 s to read 184 source windows. That is measurable, but expensive.
  • D7: a read-only query on an existing explicit DB entered automatic plugin enablement (plugin_mutation_busy) and then answered symbol_not_found. Concurrent read-only queries contend as plugin writers.
  • D9: a query against a copied audit DB failed with SQLite database disk image is malformed (the copy probably lacked its WAL). The original stays readable.
  • D10 / D13: query --no-daemon --db X warned that a registered daemon of a different build would answer, then fell back. With no code-index-mcp next to it, it also used a helper of a different build (answer_provenance.build).

For this issue's design: an ad-hoc or explicit-DB read must be read-only and snapshot-consistent (WAL included), must never trigger activation or plugin mutation, must never attach to a daemon of a different build or root, and must report only the build that actually answered.

More field evidence from codex-531's #531 corpus audit (dogfood D5–D10, D13): - **D5:** reading a staged corpus copy returned `path_outside_known_roots`, which is exactly this issue. - **D6:** the workaround, a CLI `code-index query --db` per window, took 36 subprocess calls and 103 s to read 184 source windows. That is measurable, but expensive. - **D7:** a read-only `query` on an existing explicit DB entered automatic plugin enablement (`plugin_mutation_busy`) and then answered `symbol_not_found`. Concurrent read-only queries contend as plugin writers. - **D9:** a query against a copied audit DB failed with SQLite `database disk image is malformed` (the copy probably lacked its WAL). The original stays readable. - **D10 / D13:** `query --no-daemon --db X` warned that a registered daemon of a different build would answer, then fell back. With no `code-index-mcp` next to it, it also used a helper of a different build (`answer_provenance.build`). For this issue's design: an ad-hoc or explicit-DB read must be read-only and snapshot-consistent (WAL included), must never trigger activation or plugin mutation, must never attach to a daemon of a different build or root, and must report only the build that actually answered.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
h-dv/code-index#559
No description provided.