From 8b5b65a76e6e81b20b3a1e8329936acbc01821a2 Mon Sep 17 00:00:00 2001 From: darthghandi Date: Thu, 2 Jul 2026 15:56:58 -0600 Subject: [PATCH 1/6] docs: design clangd safe defaults --- .../2026-07-02-clangd-safe-defaults-design.md | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md diff --git a/docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md b/docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md new file mode 100644 index 00000000..1d2698b1 --- /dev/null +++ b/docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md @@ -0,0 +1,71 @@ +# Clangd Safe Defaults Design + +## Context + +Issue https://github.com/zzet/gortex/issues/220 reports high CPU during semantic enrichment when Gortex auto-registers `clangd` and launches it with `--background-index --header-insertion=never`. On a large C/C++ repository with a broad `.clang-tidy`, clangd can run expensive clang-tidy matchers, crash, reconnect, and repeat substantial enrichment work. + +The immediate user-facing problem is that Gortex's default clangd launch does more work than semantic graph enrichment needs. Crash-loop policy is separate follow-up work tracked in https://github.com/zzet/gortex/issues/222. + +## Scope + +Change only the built-in `clangd` LSP default arguments used by semantic enrichment. + +Do not add a new config option. Do not change reconnect behavior. Do not alter `.gortex.yaml` provider override semantics. + +## Proposed Default + +The built-in `clangd` spec should launch with: + +```text +--background-index=false +--clang-tidy=false +--header-insertion=never +-j=1 +``` + +`--clang-tidy=false` prevents repo `.clang-tidy` checks from running during enrichment. `--background-index=false` prevents clangd from building and maintaining a project-wide background index when Gortex only needs request-driven semantic evidence. `-j=1` limits clangd's internal worker concurrency for the enrichment subprocess. + +## Architecture + +Keep the existing registry/config architecture: + +- `internal/semantic/lsp/registry.go` remains the source of built-in LSP server specs. +- `internal/serverstack/shared_server.go` continues to auto-register available LSP specs. +- `SpecWithOverrides` continues to let `.gortex.yaml` replace built-in command, args, and env values. + +Users who want clang-tidy diagnostics or background indexing can opt back in with a repo-local provider override. + +## Data Flow + +Semantic enrichment will still discover C/C++ nodes, ask the LSP router for the `clangd` provider, and lazy-spawn clangd only when there is work to confirm or enrich. + +The only behavior change is the argv used when clangd is spawned from the built-in spec. Foreground LSP requests for definition, references, implementations, and hover remain available. + +## Error Handling + +This design does not change reconnect or crash handling. If an LSP server exits, the existing reconnect path continues to behave as it does today. + +Repeated-exit suppression is intentionally deferred to issue https://github.com/zzet/gortex/issues/222 so this fix stays narrow and easy to review. + +## Testing + +Use TDD for implementation: + +1. Add a failing registry test that asserts the built-in `clangd` spec has exactly the safe default args. +2. Run the focused test and confirm it fails before the implementation change. +3. Change the `clangd` built-in args. +4. Re-run the focused test and relevant package tests. + +The focused test belongs near the existing registry tests in `internal/semantic/lsp/registry_test.go`. It should verify the built-in spec, not a config override copy, so a future accidental reintroduction of `--background-index` or clang-tidy diagnostics fails quickly. + +## Documentation + +Update `docs/lsp.md` so the documented clangd command matches the new defaults. Include a short note that Gortex disables clang-tidy and background indexing by default for enrichment because it needs graph signal, not lint diagnostics or a persistent project index. + +## Non-Goals + +- No generic LSP crash-loop guard. +- No new semantic config key. +- No changes to C/C++ file selection. +- No changes to clangd availability detection. +- No changes to user-provided `semantic.providers` overrides. From 2828f3e2ffcdd1aed2062b77e2f857372d77c830 Mon Sep 17 00:00:00 2001 From: darthghandi Date: Thu, 2 Jul 2026 16:04:40 -0600 Subject: [PATCH 2/6] docs: plan clangd safe defaults --- .../plans/2026-07-02-clangd-safe-defaults.md | 232 ++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md diff --git a/docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md b/docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md new file mode 100644 index 00000000..cb87f807 --- /dev/null +++ b/docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md @@ -0,0 +1,232 @@ +# Clangd Safe Defaults Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Make Gortex's built-in clangd semantic-enrichment launch safe by default by disabling clang-tidy, disabling background indexing, and limiting clangd worker concurrency. + +**Architecture:** Keep the existing LSP registry and provider override architecture. Pin the built-in clangd args with a focused registry test, update only the clangd spec defaults, and document the new default command and rationale. + +**Tech Stack:** Go, standard `testing` package, Gortex LSP registry, Markdown docs. + +--- + +## File Structure + +- Modify: `internal/semantic/lsp/registry_test.go` + - Add a focused unit test that asserts the built-in `clangd` spec has the exact safe default args. +- Modify: `internal/semantic/lsp/registry.go` + - Change only the built-in `clangd` `Args` slice and its adjacent explanatory comment. +- Modify: `docs/lsp.md` + - Update the clangd command table row and add a short note explaining why clang-tidy and background indexing are off by default for enrichment. + +### Task 1: Pin clangd safe default args with a failing test + +**Files:** +- Modify: `internal/semantic/lsp/registry_test.go` + +- [ ] **Step 1: Write the failing test** + +Add this test after `TestPyreflyAndTsgoSpecs` and before `TestSpecWithOverrides`: + +```go +// TestClangdSpecUsesSafeEnrichmentDefaults pins clangd's built-in +// enrichment argv. Gortex needs request-driven graph signal from +// clangd, not repo clang-tidy diagnostics or a persistent background +// project index. +func TestClangdSpecUsesSafeEnrichmentDefaults(t *testing.T) { + clangd := SpecByName("clangd") + if clangd == nil { + t.Fatal("clangd spec not registered") + } + + want := []string{ + "--background-index=false", + "--clang-tidy=false", + "--header-insertion=never", + "-j=1", + } + if got := clangd.Args; !slices.Equal(got, want) { + t.Fatalf("clangd args = %v, want %v", got, want) + } +} +``` + +Also add the `slices` import to the import block: + +```go +import ( + "slices" + "strings" + "testing" + + "github.com/zzet/gortex/internal/semantic" +) +``` + +- [ ] **Step 2: Run the focused test to verify it fails** + +Run: + +```bash +go test ./internal/semantic/lsp -run TestClangdSpecUsesSafeEnrichmentDefaults -count=1 +``` + +Expected: FAIL. The failure should show the current args are: + +```text +[--background-index --header-insertion=never] +``` + +- [ ] **Step 3: Commit the failing test** + +Run: + +```bash +git add internal/semantic/lsp/registry_test.go +git commit -m "test: pin clangd safe enrichment defaults" +``` + +Expected: commit succeeds with only the failing test change. + +### Task 2: Change clangd built-in args + +**Files:** +- Modify: `internal/semantic/lsp/registry.go` + +- [ ] **Step 1: Update the clangd spec comment and args** + +Replace the current clangd comment and `Args` value with: + +```go + { + Name: "clangd", + Command: "clangd", + // Gortex uses clangd for request-driven graph evidence during + // enrichment, not lint diagnostics or a persistent project index. + // Keep clang-tidy and background indexing off by default so broad + // repo .clang-tidy configs and large C++ trees do not dominate CPU + // or crash-loop the enrichment subprocess. Users can opt back in via + // a semantic.providers override in .gortex.yaml. + Args: []string{ + "--background-index=false", + "--clang-tidy=false", + "--header-insertion=never", + "-j=1", + }, +``` + +Leave the existing `Languages`, `Extensions`, `LanguageIDs`, `Priority`, `Daemon`, and `MaxParallel` values unchanged. + +- [ ] **Step 2: Run the focused test to verify it passes** + +Run: + +```bash +go test ./internal/semantic/lsp -run TestClangdSpecUsesSafeEnrichmentDefaults -count=1 +``` + +Expected: PASS. + +- [ ] **Step 3: Commit the implementation** + +Run: + +```bash +git add internal/semantic/lsp/registry.go +git commit -m "fix(lsp): use safe clangd enrichment defaults" +``` + +Expected: commit succeeds with only the registry implementation change. + +### Task 3: Update LSP documentation + +**Files:** +- Modify: `docs/lsp.md` + +- [ ] **Step 1: Update the clangd command table row** + +Change the `clangd` row in the server registry table from: + +```markdown +| `clangd` | `clangd --background-index` | c, c++, objc, objc++ | 5 | +``` + +to: + +```markdown +| `clangd` | `clangd --background-index=false --clang-tidy=false --header-insertion=never -j=1` | c, c++, objc, objc++ | 5 | +``` + +- [ ] **Step 2: Add a short note below the fallback list** + +After the fallback list ending with: + +```markdown +- `phpactor` → falls back to `intelephense --stdio`. +``` + +add: + +```markdown +The built-in `clangd` spec disables background indexing and clang-tidy by +default because semantic enrichment needs request-driven graph evidence, +not lint diagnostics or a persistent project index. Repositories that want +those clangd features can override the `clangd` provider args in +`.gortex.yaml`. +``` + +- [ ] **Step 3: Commit the docs update** + +Run: + +```bash +git add docs/lsp.md +git commit -m "docs: document clangd safe defaults" +``` + +Expected: commit succeeds with only the documentation change. + +### Task 4: Verify and prepare final summary + +**Files:** +- No file edits expected. + +- [ ] **Step 1: Run the relevant package tests** + +Run: + +```bash +go test ./internal/semantic/lsp -count=1 +``` + +Expected: PASS. + +- [ ] **Step 2: Run the broader required test command if time permits** + +Run: + +```bash +go test -race ./... +``` + +Expected: PASS. If this is too slow or fails for an unrelated pre-existing issue, capture the failing package and error for the final summary. + +- [ ] **Step 3: Inspect git history and working tree** + +Run: + +```bash +git status --short --branch +git log --oneline -n 5 +``` + +Expected: branch is `fix/issue-220-clangd-tidy-high-cpu`; working tree is clean except any intentional plan/spec files; recent commits include the design, test, implementation, and docs commits. + +- [ ] **Step 4: Final response** + +Summarize: + +- The clangd default args now disable background indexing and clang-tidy and use `-j=1`. +- The focused registry test pins those args. +- `docs/lsp.md` documents the new default and opt-in override path. +- Verification commands run and their outcomes. From 00d5bfb7de0fbbb35b912426147bc8dbed5ba551 Mon Sep 17 00:00:00 2001 From: darthghandi Date: Thu, 2 Jul 2026 16:06:12 -0600 Subject: [PATCH 3/6] test: pin clangd safe enrichment defaults --- internal/semantic/lsp/registry_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/internal/semantic/lsp/registry_test.go b/internal/semantic/lsp/registry_test.go index 0c8d7c61..0f2ee2e0 100644 --- a/internal/semantic/lsp/registry_test.go +++ b/internal/semantic/lsp/registry_test.go @@ -1,6 +1,7 @@ package lsp import ( + "slices" "strings" "testing" @@ -179,6 +180,27 @@ func TestPyreflyAndTsgoSpecs(t *testing.T) { } } +// TestClangdSpecUsesSafeEnrichmentDefaults pins clangd's built-in +// enrichment argv. Gortex needs request-driven graph signal from +// clangd, not repo clang-tidy diagnostics or a persistent background +// project index. +func TestClangdSpecUsesSafeEnrichmentDefaults(t *testing.T) { + clangd := SpecByName("clangd") + if clangd == nil { + t.Fatal("clangd spec not registered") + } + + want := []string{ + "--background-index=false", + "--clang-tidy=false", + "--header-insertion=never", + "-j=1", + } + if got := clangd.Args; !slices.Equal(got, want) { + t.Fatalf("clangd args = %v, want %v", got, want) + } +} + // TestSpecWithOverrides verifies .gortex.yaml command / args / env // overrides are applied to a copy without mutating the built-in spec — // the path by which jdtls gets a pinned JRE and launcher args. From cb97d2fbe012f0396e602b5ffd6a74b901752a2e Mon Sep 17 00:00:00 2001 From: darthghandi Date: Thu, 2 Jul 2026 16:06:36 -0600 Subject: [PATCH 4/6] fix(lsp): use safe clangd enrichment defaults --- internal/semantic/lsp/registry.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/internal/semantic/lsp/registry.go b/internal/semantic/lsp/registry.go index 58240f83..fb9d89ad 100644 --- a/internal/semantic/lsp/registry.go +++ b/internal/semantic/lsp/registry.go @@ -319,11 +319,18 @@ var Servers = []ServerSpec{ { Name: "clangd", Command: "clangd", - // `--background-index` keeps a project-wide symbol index hot in - // the daemon, which is essential for type-hierarchy precision in - // large C++ trees. `--header-insertion=never` avoids tactical - // edits when we only want graph signal. - Args: []string{"--background-index", "--header-insertion=never"}, + // Gortex uses clangd for request-driven graph evidence during + // enrichment, not lint diagnostics or a persistent project index. + // Keep clang-tidy and background indexing off by default so broad + // repo .clang-tidy configs and large C++ trees do not dominate CPU + // or crash-loop the enrichment subprocess. Users can opt back in via + // a semantic.providers override in .gortex.yaml. + Args: []string{ + "--background-index=false", + "--clang-tidy=false", + "--header-insertion=never", + "-j=1", + }, Languages: []string{"c", "cpp", "objc", "objcpp"}, Extensions: []string{ ".c", ".h", From 747036b84caf0b2dfd07a39f11e4bd7f47b69b57 Mon Sep 17 00:00:00 2001 From: darthghandi Date: Thu, 2 Jul 2026 16:06:55 -0600 Subject: [PATCH 5/6] docs: document clangd safe defaults --- docs/lsp.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/lsp.md b/docs/lsp.md index 34630d9b..4845d8c7 100644 --- a/docs/lsp.md +++ b/docs/lsp.md @@ -27,7 +27,7 @@ Sixteen servers ship in the registry today | `typescript-language-server` | `typescript-language-server` | typescript, javascript | 5 | | `pyright` | `pyright-langserver` | python | 5 | | `rust-analyzer` | `rust-analyzer` | rust | 5 | -| `clangd` | `clangd --background-index` | c, c++, objc, objc++ | 5 | +| `clangd` | `clangd --background-index=false --clang-tidy=false --header-insertion=never -j=1` | c, c++, objc, objc++ | 5 | | `jdtls` | `jdtls` | java | 6 | | `kotlin-language-server` | `kotlin-language-server` | kotlin | 6 | | `omnisharp` | `omnisharp -lsp` | csharp | 5 | @@ -47,6 +47,12 @@ binary on `PATH`: - `ruby-lsp` → falls back to `solargraph stdio`. - `phpactor` → falls back to `intelephense --stdio`. +The built-in `clangd` spec disables background indexing and clang-tidy by +default because semantic enrichment needs request-driven graph evidence, +not lint diagnostics or a persistent project index. Repositories that want +those clangd features can override the `clangd` provider args in +`.gortex.yaml`. + Lower priority numbers win when more than one provider serves the same language. `gopls` is `3` so it beats SCIP-based providers (`5`) for Go; `jdtls` is `6` so it's lower-priority than the SCIP-java path that From 297253e4abf3e55fac65ccf90b9059c48a09d9cc Mon Sep 17 00:00:00 2001 From: darthghandi Date: Thu, 2 Jul 2026 18:55:04 -0600 Subject: [PATCH 6/6] Remove specs Remove the superpowers directory and the plans and specs --- .../plans/2026-07-02-clangd-safe-defaults.md | 232 ------------------ .../2026-07-02-clangd-safe-defaults-design.md | 71 ------ 2 files changed, 303 deletions(-) delete mode 100644 docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md delete mode 100644 docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md diff --git a/docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md b/docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md deleted file mode 100644 index cb87f807..00000000 --- a/docs/superpowers/plans/2026-07-02-clangd-safe-defaults.md +++ /dev/null @@ -1,232 +0,0 @@ -# Clangd Safe Defaults Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -**Goal:** Make Gortex's built-in clangd semantic-enrichment launch safe by default by disabling clang-tidy, disabling background indexing, and limiting clangd worker concurrency. - -**Architecture:** Keep the existing LSP registry and provider override architecture. Pin the built-in clangd args with a focused registry test, update only the clangd spec defaults, and document the new default command and rationale. - -**Tech Stack:** Go, standard `testing` package, Gortex LSP registry, Markdown docs. - ---- - -## File Structure - -- Modify: `internal/semantic/lsp/registry_test.go` - - Add a focused unit test that asserts the built-in `clangd` spec has the exact safe default args. -- Modify: `internal/semantic/lsp/registry.go` - - Change only the built-in `clangd` `Args` slice and its adjacent explanatory comment. -- Modify: `docs/lsp.md` - - Update the clangd command table row and add a short note explaining why clang-tidy and background indexing are off by default for enrichment. - -### Task 1: Pin clangd safe default args with a failing test - -**Files:** -- Modify: `internal/semantic/lsp/registry_test.go` - -- [ ] **Step 1: Write the failing test** - -Add this test after `TestPyreflyAndTsgoSpecs` and before `TestSpecWithOverrides`: - -```go -// TestClangdSpecUsesSafeEnrichmentDefaults pins clangd's built-in -// enrichment argv. Gortex needs request-driven graph signal from -// clangd, not repo clang-tidy diagnostics or a persistent background -// project index. -func TestClangdSpecUsesSafeEnrichmentDefaults(t *testing.T) { - clangd := SpecByName("clangd") - if clangd == nil { - t.Fatal("clangd spec not registered") - } - - want := []string{ - "--background-index=false", - "--clang-tidy=false", - "--header-insertion=never", - "-j=1", - } - if got := clangd.Args; !slices.Equal(got, want) { - t.Fatalf("clangd args = %v, want %v", got, want) - } -} -``` - -Also add the `slices` import to the import block: - -```go -import ( - "slices" - "strings" - "testing" - - "github.com/zzet/gortex/internal/semantic" -) -``` - -- [ ] **Step 2: Run the focused test to verify it fails** - -Run: - -```bash -go test ./internal/semantic/lsp -run TestClangdSpecUsesSafeEnrichmentDefaults -count=1 -``` - -Expected: FAIL. The failure should show the current args are: - -```text -[--background-index --header-insertion=never] -``` - -- [ ] **Step 3: Commit the failing test** - -Run: - -```bash -git add internal/semantic/lsp/registry_test.go -git commit -m "test: pin clangd safe enrichment defaults" -``` - -Expected: commit succeeds with only the failing test change. - -### Task 2: Change clangd built-in args - -**Files:** -- Modify: `internal/semantic/lsp/registry.go` - -- [ ] **Step 1: Update the clangd spec comment and args** - -Replace the current clangd comment and `Args` value with: - -```go - { - Name: "clangd", - Command: "clangd", - // Gortex uses clangd for request-driven graph evidence during - // enrichment, not lint diagnostics or a persistent project index. - // Keep clang-tidy and background indexing off by default so broad - // repo .clang-tidy configs and large C++ trees do not dominate CPU - // or crash-loop the enrichment subprocess. Users can opt back in via - // a semantic.providers override in .gortex.yaml. - Args: []string{ - "--background-index=false", - "--clang-tidy=false", - "--header-insertion=never", - "-j=1", - }, -``` - -Leave the existing `Languages`, `Extensions`, `LanguageIDs`, `Priority`, `Daemon`, and `MaxParallel` values unchanged. - -- [ ] **Step 2: Run the focused test to verify it passes** - -Run: - -```bash -go test ./internal/semantic/lsp -run TestClangdSpecUsesSafeEnrichmentDefaults -count=1 -``` - -Expected: PASS. - -- [ ] **Step 3: Commit the implementation** - -Run: - -```bash -git add internal/semantic/lsp/registry.go -git commit -m "fix(lsp): use safe clangd enrichment defaults" -``` - -Expected: commit succeeds with only the registry implementation change. - -### Task 3: Update LSP documentation - -**Files:** -- Modify: `docs/lsp.md` - -- [ ] **Step 1: Update the clangd command table row** - -Change the `clangd` row in the server registry table from: - -```markdown -| `clangd` | `clangd --background-index` | c, c++, objc, objc++ | 5 | -``` - -to: - -```markdown -| `clangd` | `clangd --background-index=false --clang-tidy=false --header-insertion=never -j=1` | c, c++, objc, objc++ | 5 | -``` - -- [ ] **Step 2: Add a short note below the fallback list** - -After the fallback list ending with: - -```markdown -- `phpactor` → falls back to `intelephense --stdio`. -``` - -add: - -```markdown -The built-in `clangd` spec disables background indexing and clang-tidy by -default because semantic enrichment needs request-driven graph evidence, -not lint diagnostics or a persistent project index. Repositories that want -those clangd features can override the `clangd` provider args in -`.gortex.yaml`. -``` - -- [ ] **Step 3: Commit the docs update** - -Run: - -```bash -git add docs/lsp.md -git commit -m "docs: document clangd safe defaults" -``` - -Expected: commit succeeds with only the documentation change. - -### Task 4: Verify and prepare final summary - -**Files:** -- No file edits expected. - -- [ ] **Step 1: Run the relevant package tests** - -Run: - -```bash -go test ./internal/semantic/lsp -count=1 -``` - -Expected: PASS. - -- [ ] **Step 2: Run the broader required test command if time permits** - -Run: - -```bash -go test -race ./... -``` - -Expected: PASS. If this is too slow or fails for an unrelated pre-existing issue, capture the failing package and error for the final summary. - -- [ ] **Step 3: Inspect git history and working tree** - -Run: - -```bash -git status --short --branch -git log --oneline -n 5 -``` - -Expected: branch is `fix/issue-220-clangd-tidy-high-cpu`; working tree is clean except any intentional plan/spec files; recent commits include the design, test, implementation, and docs commits. - -- [ ] **Step 4: Final response** - -Summarize: - -- The clangd default args now disable background indexing and clang-tidy and use `-j=1`. -- The focused registry test pins those args. -- `docs/lsp.md` documents the new default and opt-in override path. -- Verification commands run and their outcomes. diff --git a/docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md b/docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md deleted file mode 100644 index 1d2698b1..00000000 --- a/docs/superpowers/specs/2026-07-02-clangd-safe-defaults-design.md +++ /dev/null @@ -1,71 +0,0 @@ -# Clangd Safe Defaults Design - -## Context - -Issue https://github.com/zzet/gortex/issues/220 reports high CPU during semantic enrichment when Gortex auto-registers `clangd` and launches it with `--background-index --header-insertion=never`. On a large C/C++ repository with a broad `.clang-tidy`, clangd can run expensive clang-tidy matchers, crash, reconnect, and repeat substantial enrichment work. - -The immediate user-facing problem is that Gortex's default clangd launch does more work than semantic graph enrichment needs. Crash-loop policy is separate follow-up work tracked in https://github.com/zzet/gortex/issues/222. - -## Scope - -Change only the built-in `clangd` LSP default arguments used by semantic enrichment. - -Do not add a new config option. Do not change reconnect behavior. Do not alter `.gortex.yaml` provider override semantics. - -## Proposed Default - -The built-in `clangd` spec should launch with: - -```text ---background-index=false ---clang-tidy=false ---header-insertion=never --j=1 -``` - -`--clang-tidy=false` prevents repo `.clang-tidy` checks from running during enrichment. `--background-index=false` prevents clangd from building and maintaining a project-wide background index when Gortex only needs request-driven semantic evidence. `-j=1` limits clangd's internal worker concurrency for the enrichment subprocess. - -## Architecture - -Keep the existing registry/config architecture: - -- `internal/semantic/lsp/registry.go` remains the source of built-in LSP server specs. -- `internal/serverstack/shared_server.go` continues to auto-register available LSP specs. -- `SpecWithOverrides` continues to let `.gortex.yaml` replace built-in command, args, and env values. - -Users who want clang-tidy diagnostics or background indexing can opt back in with a repo-local provider override. - -## Data Flow - -Semantic enrichment will still discover C/C++ nodes, ask the LSP router for the `clangd` provider, and lazy-spawn clangd only when there is work to confirm or enrich. - -The only behavior change is the argv used when clangd is spawned from the built-in spec. Foreground LSP requests for definition, references, implementations, and hover remain available. - -## Error Handling - -This design does not change reconnect or crash handling. If an LSP server exits, the existing reconnect path continues to behave as it does today. - -Repeated-exit suppression is intentionally deferred to issue https://github.com/zzet/gortex/issues/222 so this fix stays narrow and easy to review. - -## Testing - -Use TDD for implementation: - -1. Add a failing registry test that asserts the built-in `clangd` spec has exactly the safe default args. -2. Run the focused test and confirm it fails before the implementation change. -3. Change the `clangd` built-in args. -4. Re-run the focused test and relevant package tests. - -The focused test belongs near the existing registry tests in `internal/semantic/lsp/registry_test.go`. It should verify the built-in spec, not a config override copy, so a future accidental reintroduction of `--background-index` or clang-tidy diagnostics fails quickly. - -## Documentation - -Update `docs/lsp.md` so the documented clangd command matches the new defaults. Include a short note that Gortex disables clang-tidy and background indexing by default for enrichment because it needs graph signal, not lint diagnostics or a persistent project index. - -## Non-Goals - -- No generic LSP crash-loop guard. -- No new semantic config key. -- No changes to C/C++ file selection. -- No changes to clangd availability detection. -- No changes to user-provided `semantic.providers` overrides.