link add on a project without a config file disables every language: the file it creates carries an explicit empty enabled list #585

Closed
opened 2026-11-13 13:30:35 +01:00 by buildagent · 2 comments
Member

Found by the release lead while linking a worktree, 2026-11-13; reproduced on the released v0.41.52 (7fc7fb20) in a scratch project.

Reproduction

mkdir -p p/src other/src; printf 'pub fn a() {}\n' > p/src/lib.rs; (cd p && git init -q .)
code-index --root p index             # first start: rust enabled automatically
code-index --root p languages list    # enabled: rust; enabled_source: .code-index/languages.toml (an automatic start's decision)
code-index --root p link add other ../other
code-index --root p languages list    # enabled: (none); enabled_source: .code-index.toml (an explicit decision; it always wins)

p had no .code-index.toml. link add creates one from the full template, and the template contains [languages] enabled = []. An enabled key in .code-index.toml is an explicit decision that wins over the automatic one, so every language of the project becomes NOT INDEXED. The command printed only "added link …". The next one-shot query answered project_not_available.

On a real checkout this took all seven languages (1,106 source files) out of the index with one link add.

Expected

  • A command that creates .code-index.toml for another purpose must not record a language decision. The file it writes carries no enabled key (or the automatic decision is carried over as what it is), and languages list shows the same enabled set before and after.
  • The same check for every other command that can create the file as a side effect; init and languages enable are the two that are meant to decide.
  • If a command does change which languages are indexed, it says so in its output.

Also seen in the same step

  • link add <name> <path> for a path that is a worktree of the same repository records relationship = "dependency" and warns that the roots are nested. A linked worktree of the same repository then takes part in name fan-out and returns every hit twice. The relationship should be worktree when the target is a worktree of the primary's repository (or the command should say which value to pass).
  • link remove prints "withdrew the approval for link:" and nothing about the entry it removed from the file.

Acceptance

  • Test that can fail: a project whose languages were enabled by an automatic start keeps the same languages list output after link add and after link remove; mutation run.
  • A registry-style test over every code path that writes .code-index.toml: none but the two deciding commands can produce an enabled key.
Found by the release lead while linking a worktree, 2026-11-13; reproduced on the released v0.41.52 (`7fc7fb20`) in a scratch project. ## Reproduction ``` mkdir -p p/src other/src; printf 'pub fn a() {}\n' > p/src/lib.rs; (cd p && git init -q .) code-index --root p index # first start: rust enabled automatically code-index --root p languages list # enabled: rust; enabled_source: .code-index/languages.toml (an automatic start's decision) code-index --root p link add other ../other code-index --root p languages list # enabled: (none); enabled_source: .code-index.toml (an explicit decision; it always wins) ``` `p` had no `.code-index.toml`. `link add` creates one from the full template, and the template contains `[languages] enabled = []`. An `enabled` key in `.code-index.toml` is an explicit decision that wins over the automatic one, so every language of the project becomes `NOT INDEXED`. The command printed only "added link …". The next one-shot query answered `project_not_available`. On a real checkout this took all seven languages (1,106 source files) out of the index with one `link add`. ## Expected - A command that creates `.code-index.toml` for another purpose must not record a language decision. The file it writes carries no `enabled` key (or the automatic decision is carried over as what it is), and `languages list` shows the same enabled set before and after. - The same check for every other command that can create the file as a side effect; `init` and `languages enable` are the two that are meant to decide. - If a command does change which languages are indexed, it says so in its output. ## Also seen in the same step - `link add <name> <path>` for a path that is a worktree of the same repository records `relationship = "dependency"` and warns that the roots are nested. A linked worktree of the same repository then takes part in name fan-out and returns every hit twice. The relationship should be `worktree` when the target is a worktree of the primary's repository (or the command should say which value to pass). - `link remove` prints "withdrew the approval for link:<name>" and nothing about the entry it removed from the file. ## Acceptance - Test that can fail: a project whose languages were enabled by an automatic start keeps the same `languages list` output after `link add` and after `link remove`; mutation run. - A registry-style test over every code path that writes `.code-index.toml`: none but the two deciding commands can produce an `enabled` key.
Author
Member

Fixed on the next-train branch (lane r35, merged locally as 2d8ba04d; not released yet).

Cause. link add seeds a missing .code-index.toml from the shared template, and the template contained enabled = [].

Change.

  • The template leaves enabled commented out. init writes its detected list explicitly; languages enable records an explicit list as before. A file without the key means the same as no file: the automatic decision in .code-index/languages.toml stays in force.
  • Every code path that writes the manifest is inventoried by a test (twelve call sites) and driven on a scratch project, once with an automatic decision and once with an explicit one. Only init and languages enable may produce the key; a new writer that is not registered in the test fails it.
  • link add without --relationship records worktree when the target is another checkout of the primary's Git repository, dependency otherwise; an explicit --relationship wins. The nested-roots warning no longer fires for nested checkouts, which the outer index does not walk anyway.
  • link remove prints the entry it removed (name, path, relationship, file).
  • README, docs/configuration.md, docs/operations.md and the template comments say the same.

The project_not_available answer in the report came from the empty language list: the primary's activation failed its gate because no language contributed anything. The linked project was not the cause. The refusal does not say that; left as it is here, it belongs to the refusal wording work in #521.

Checked by the lead: the production diff read through changed_symbols with hunks; the CLI suite, formatting and clippy pass; mutation "a new function that calls a manifest sink" fails the inventory test. The worker ran the other mutations (template key restored, inference removed, explicit relationship ignored, removal line) and reported each red. I replaced the worker's parser-based inventory with a line scan that finds the same twelve call sites, to keep a parser dependency out of the CLI crate.

Workaround on v0.41.52: after link add on a project that had no .code-index.toml, delete the line enabled = [] from the new file and check code-index languages list.

Fixed on the next-train branch (lane r35, merged locally as `2d8ba04d`; not released yet). **Cause.** `link add` seeds a missing `.code-index.toml` from the shared template, and the template contained `enabled = []`. **Change.** - The template leaves `enabled` commented out. `init` writes its detected list explicitly; `languages enable` records an explicit list as before. A file without the key means the same as no file: the automatic decision in `.code-index/languages.toml` stays in force. - Every code path that writes the manifest is inventoried by a test (twelve call sites) and driven on a scratch project, once with an automatic decision and once with an explicit one. Only `init` and `languages enable` may produce the key; a new writer that is not registered in the test fails it. - `link add` without `--relationship` records `worktree` when the target is another checkout of the primary's Git repository, `dependency` otherwise; an explicit `--relationship` wins. The nested-roots warning no longer fires for nested checkouts, which the outer index does not walk anyway. - `link remove` prints the entry it removed (name, path, relationship, file). - README, `docs/configuration.md`, `docs/operations.md` and the template comments say the same. **The `project_not_available` answer** in the report came from the empty language list: the primary's activation failed its gate because no language contributed anything. The linked project was not the cause. The refusal does not say that; left as it is here, it belongs to the refusal wording work in #521. **Checked by the lead:** the production diff read through `changed_symbols` with hunks; the CLI suite, formatting and clippy pass; mutation "a new function that calls a manifest sink" fails the inventory test. The worker ran the other mutations (template key restored, inference removed, explicit relationship ignored, removal line) and reported each red. I replaced the worker's parser-based inventory with a line scan that finds the same twelve call sites, to keep a parser dependency out of the CLI crate. Workaround on v0.41.52: after `link add` on a project that had no `.code-index.toml`, delete the line `enabled = []` from the new file and check `code-index languages list`.
Author
Member

Released in v0.41.53 (59b8bc3d); verified on the installed binaries.
link add no longer creates a configuration with enabled = [], so the automatic language decision is preserved. It infers relationship = "worktree" for another checkout of the same repository, and link remove prints the removed entry.

Verified on the installed release:

  • 585_precondition: no configuration file exists before link add. PASS: no .code-index.toml before link add
  • 585_no_enabled_key: the created file has no uncommented enabled key. PASS: no uncommented enabled key
  • 585_worktree_inferred: the same-repository checkout is recorded as a worktree. PASS: relationship = "worktree"
  • 585_languages_unchanged: the Rust language decision is unchanged. PASS: rust yes auto
  • 585_remove_prints: removal prints the removed link. PASS: removed link 'wt' (worktree)
Released in v0.41.53 (59b8bc3d); verified on the installed binaries. `link add` no longer creates a configuration with `enabled = []`, so the automatic language decision is preserved. It infers `relationship = "worktree"` for another checkout of the same repository, and `link remove` prints the removed entry. Verified on the installed release: - `585_precondition`: no configuration file exists before `link add`. PASS: no .code-index.toml before link add - `585_no_enabled_key`: the created file has no uncommented `enabled` key. PASS: no uncommented enabled key - `585_worktree_inferred`: the same-repository checkout is recorded as a worktree. PASS: relationship = "worktree" - `585_languages_unchanged`: the Rust language decision is unchanged. PASS: rust yes auto - `585_remove_prints`: removal prints the removed link. PASS: removed link 'wt' (worktree)
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.

Dependencies

No dependencies set

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