Cross-cutting infrastructure that every v1.1 phase depends on. Lands as
a numbered phase before any user-visible feature so Phases 12–19 stay
mechanical.
5 pieces:
- `config.rs` — `Config` + `WikiConfig` + `DiagnosticConfig` + `LinkSeverity`.
Serde-deserialised from `initialization_options`. v1.0 single-wiki
shape (`wiki_root` + `file_extension` + `syntax`) desugars to one-entry
`wikis = [...]` per P16. `~/...` expansion without pulling in `dirs`.
Fallbacks: workspace_folders[0] → deprecated root_uri → empty list.
- `wiki.rs` — `Wiki` aggregate (id + WikiConfig + Arc<RwLock<Index>>).
`build_wikis(&[WikiConfig])` materialises the list; `resolve_uri_to_wiki`
picks the longest-prefix root match so nested wikis route correctly.
Single-entry today, multi-entry once Phase 18 lands.
- `edits.rs` — `WorkspaceEditBuilder` + `text_edit_replace/insert/delete`
+ `op_rename/delete/create`. Handles the UTF-8/UTF-16 conversion at the
span boundary so each Phase 13+ command stays a 3-liner. Builder picks
`documentChanges` when file ops are present (LSP requires it), `changes`
map otherwise (works for LSP 3.15- clients). File ops precede content
edits in the output so created/renamed files exist when edits apply.
`DeleteFile` is built without `annotation_id` — lsp-types 0.94.x ships
it that way; later versions added the field.
- `Backend` refactor — `index: Arc<RwLock<WorkspaceIndex>>` replaced by
`wikis: Arc<RwLock<Vec<Wiki>>>` + `config: Arc<RwLock<Config>>`. New
`wiki(id)` / `default_wiki()` / `wiki_for_uri(uri)` helpers. Every v1.0
handler (definition, references, hover, completion, workspace/symbol,
update_document) goes through `wiki_for_uri`. `initialize` builds wikis
from `Config::from_init_params`; `initialized` spawns one indexer task
per wiki with the existing `window/workDoneProgress` wrapper. New
`did_change_configuration` handler re-applies settings (rebuild
semantics revisited in Phase 18). The old `workspace_root_from_params`
helper is gone.
- `read_or_open` + `DocSnapshot` (scaffolded, `#[allow(dead_code)]` until
Phase 13's `workspace/rename` consumes it). Returns the live document
when held in the documents map, otherwise async-reads from disk and
re-parses so cross-document operations get accurate text and spans
instead of trusting stale `WorkspaceIndex` data.
- `collect_diagnostics` composable collector. Same `ErrorNode` walk
today; takes `Option<&WorkspaceIndex>` + `page_name` + `&DiagnosticConfig`
so Phase 15 can drop a link-health source in without further refactor.
`ast_diagnostics` kept as a thin wrapper for the v1.0 test surface.
New deps: `serde` + `serde_json` (already transitive through tower-lsp;
elevated to direct deps for clarity and stability). `tokio` gains the
`fs` feature for `read_or_open`'s async disk read.
Tests (19 new in `phase11_plumbing.rs`):
- Edits: UTF-8 passthrough + UTF-16 conversion (`héllo`), insert/delete
shape, builder mode selection, file-op accumulation, `op_create` round-trip
- Config: defaults, v1.0 desugar, explicit list overrides legacy, empty
JSON, invalid JSON preserves prior state
- Wiki: sequential id assignment, longest-prefix resolution, no-match,
`Wiki::contains`
- Diagnostics: error-node composition, link-health stub returns empty in
Phase 11
All 172 v1.0 tests still pass — backward compatible.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>