baldart 3.8.2 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +61 -0
- package/README.md +6 -2
- package/VERSION +1 -1
- package/framework/.claude/agents/REGISTRY.md +1 -1
- package/framework/.claude/agents/codebase-architect.md +8 -0
- package/framework/.claude/skills/bug/SKILL.md +5 -1
- package/framework/.claude/skills/context-primer/SKILL.md +4 -0
- package/framework/.claude/skills/lsp-bootstrap/SKILL.md +113 -0
- package/framework/.claude/skills/new/SKILL.md +4 -4
- package/framework/.claude/skills/prd/SKILL.md +3 -1
- package/framework/.claude/skills/simplify/SKILL.md +6 -0
- package/framework/.claude/skills/worktree-manager/SKILL.md +91 -20
- package/framework/agents/code-search-protocol.md +126 -0
- package/framework/agents/index.md +2 -0
- package/framework/docs/LSP-LAYER.md +405 -0
- package/framework/docs/PROJECT-CONFIGURATION.md +17 -0
- package/framework/templates/baldart.config.template.yml +42 -0
- package/framework/templates/overlays/agents/codebase-architect.lsp-example.md +53 -0
- package/package.json +1 -1
- package/src/commands/configure.js +124 -1
- package/src/commands/doctor.js +55 -0
- package/src/commands/update.js +14 -5
- package/src/utils/lsp-adapters/go.js +29 -0
- package/src/utils/lsp-adapters/index.js +49 -0
- package/src/utils/lsp-adapters/python.js +42 -0
- package/src/utils/lsp-adapters/ruby.js +30 -0
- package/src/utils/lsp-adapters/rust.js +26 -0
- package/src/utils/lsp-adapters/typescript.js +54 -0
- package/src/utils/lsp-installer.js +118 -0
|
@@ -14,6 +14,7 @@ Route agents to the right module with minimal reading.
|
|
|
14
14
|
|
|
15
15
|
- **MANDATORY pre-read for any skill/agent that touches project-specific paths, identity, stack, or feature toggles** -> read `agents/project-context.md`. Skills consult `baldart.config.yml` + `.baldart/overlays/<skill>.md` instead of hard-coded paths; missing keys MUST be asked, never assumed.
|
|
16
16
|
- If needing to understand codebase structure, existing patterns, or architecture before planning -> MUST invoke `codebase-architect` agent (via Task tool) first; do not proceed without architectural understanding.
|
|
17
|
+
- If searching for a function/type/symbol (identifier-shaped query, not free text) and `features.has_lsp_layer: true` -> read `agents/code-search-protocol.md` and prefer LSP `find-references` / `go-to-definition` over Grep. Falls back to Grep when LSP is unavailable or the query is textual.
|
|
17
18
|
- If touching API endpoints or request/response shape -> read `agents/api-contracts.md` and `${paths.references_dir}/api/index.md` (then specific API module for your domain).
|
|
18
19
|
- If touching database schema or fields -> read `agents/data-model.md` and `${paths.references_dir}/data-model.md`.
|
|
19
20
|
- If touching UI pages/routes or flows -> read `${paths.references_dir}/ui/index.md` (then specific UI module for your domain).
|
|
@@ -57,6 +58,7 @@ When adding or updating agents, update REGISTRY.md — not this file.
|
|
|
57
58
|
- `agents/skills-mapping.md`
|
|
58
59
|
- `agents/llm-wiki-methodology.md` — LLM wiki overlay methodology + auto-learning loop (since v2.0.0)
|
|
59
60
|
- `agents/project-context.md` — Project context protocol: `baldart.config.yml` + overlays + missing-key handling (since v3.0.0)
|
|
61
|
+
- `agents/code-search-protocol.md` — Retrieval hierarchy for code search: RAG → LSP → Grep → Git (since v3.10.0, gated on `features.has_lsp_layer`)
|
|
60
62
|
|
|
61
63
|
## Where to Document (Decision Tree)
|
|
62
64
|
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
<!-- contamination-scan: skip
|
|
2
|
+
This guide uses literal example paths (tsconfig.json, pyproject.toml,
|
|
3
|
+
`src/components/...`, etc.) as pedagogical examples of what
|
|
4
|
+
`baldart configure` autodetects. They are not project leak. -->
|
|
5
|
+
# LSP Symbol-Search Layer
|
|
6
|
+
|
|
7
|
+
A complete operator + agent reference for the LSP retrieval tier introduced in
|
|
8
|
+
**v3.10.0**. Read this when:
|
|
9
|
+
|
|
10
|
+
- you are upgrading a consumer repo from pre-v3.10 and want to know what
|
|
11
|
+
changed and how to roll the new feature out,
|
|
12
|
+
- you are an AI agent asked to extend, debug, or modify the layer,
|
|
13
|
+
- a contributor wants to add a new language adapter or change the fallback
|
|
14
|
+
rules.
|
|
15
|
+
|
|
16
|
+
For the *runtime* protocol (RAG → LSP → Grep → Git, query-type
|
|
17
|
+
discrimination, budget) read [`framework/agents/code-search-protocol.md`](../agents/code-search-protocol.md).
|
|
18
|
+
This document covers the *plumbing*: how the layer is installed, configured,
|
|
19
|
+
verified, and wired into agents/skills.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 1. Why this exists
|
|
24
|
+
|
|
25
|
+
Pre-v3.10, every BALDART code-exploration flow ran:
|
|
26
|
+
|
|
27
|
+
> RAG hybrid → `git log` → **Grep** → read files.
|
|
28
|
+
|
|
29
|
+
Grep collapses semantically distinct symbols that share a name. A search for
|
|
30
|
+
`handleSubmit` in a medium repo dumps every form handler, every CLI utility,
|
|
31
|
+
every test helper into the model's context — Claude then burns turns opening
|
|
32
|
+
files to figure out which one is relevant. The signal is buried in the
|
|
33
|
+
textual noise.
|
|
34
|
+
|
|
35
|
+
LSP — Language Server Protocol — answers "give me every reference to *this*
|
|
36
|
+
symbol" by walking the type graph the compiler/interpreter already has. A
|
|
37
|
+
function named `handleSubmit` declared in `src/forms/Login.tsx` returns
|
|
38
|
+
exactly the callsites that resolve to *that* declaration; the CLI utility's
|
|
39
|
+
unrelated `handleSubmit` is filtered out before any file is read.
|
|
40
|
+
|
|
41
|
+
The layer is **opt-in** (some consumers don't want devDep churn, some target
|
|
42
|
+
languages we don't have an adapter for yet) and **degrades gracefully** (when
|
|
43
|
+
LSP is unavailable, agents silently fall back to the legacy RAG → Grep flow,
|
|
44
|
+
so existing behavior is preserved).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 2. The four moving parts
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
52
|
+
│ baldart.config.yml │
|
|
53
|
+
│ features.has_lsp_layer: true │
|
|
54
|
+
│ lsp.installed_servers: [typescript, python] │
|
|
55
|
+
│ lsp.auto_verify: true │
|
|
56
|
+
└──────────────┬──────────────────────────────────────────────────────┘
|
|
57
|
+
│ read by
|
|
58
|
+
▼
|
|
59
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
60
|
+
│ Plumbing layer (CLI, this repo) │
|
|
61
|
+
│ src/utils/lsp-adapters/<lang>.js ← per-language recipes │
|
|
62
|
+
│ src/utils/lsp-installer.js ← high-level install+verify │
|
|
63
|
+
│ src/commands/configure.js (prompt + install on opt-in) │
|
|
64
|
+
│ src/commands/doctor.js (verify + lsp-fix action) │
|
|
65
|
+
└──────────────┬──────────────────────────────────────────────────────┘
|
|
66
|
+
│ writes installed_servers; surfaces broken servers
|
|
67
|
+
▼
|
|
68
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
69
|
+
│ Protocol layer (framework/) │
|
|
70
|
+
│ framework/agents/code-search-protocol.md │
|
|
71
|
+
│ framework/agents/index.md (routing line) │
|
|
72
|
+
└──────────────┬──────────────────────────────────────────────────────┘
|
|
73
|
+
│ referenced by
|
|
74
|
+
▼
|
|
75
|
+
┌─────────────────────────────────────────────────────────────────────┐
|
|
76
|
+
│ Consumers (framework/.claude/) │
|
|
77
|
+
│ agents/codebase-architect.md (Investigation Protocol) │
|
|
78
|
+
│ agents/REGISTRY.md (capability declaration) │
|
|
79
|
+
│ skills/context-primer/SKILL.md (retrieval step 3) │
|
|
80
|
+
│ skills/bug/SKILL.md (Phase 0 step 3) │
|
|
81
|
+
│ skills/simplify/SKILL.md (deduplication step 3) │
|
|
82
|
+
│ skills/prd/SKILL.md, skills/new/SKILL.md (transitive note) │
|
|
83
|
+
│ skills/lsp-bootstrap/SKILL.md (/lsp-bootstrap) │
|
|
84
|
+
└─────────────────────────────────────────────────────────────────────┘
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Each layer is independently testable and individually replaceable. The
|
|
88
|
+
adapters never speak LSP themselves — they just describe *how to install*
|
|
89
|
+
the language server. Actual symbol resolution at runtime happens through
|
|
90
|
+
whatever Claude Code plugin / MCP server the consumer has loaded.
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 3. End-to-end lifecycle
|
|
95
|
+
|
|
96
|
+
### 3.1 First install in a brand-new repo
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npx baldart add # subtree pull + symlink reconcile
|
|
100
|
+
# → triggers configure interactively
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`configure` autodetects supported languages by probing for marker files:
|
|
104
|
+
|
|
105
|
+
| Language | Marker(s) | Adapter |
|
|
106
|
+
|------------|----------------------------------------------------------|----------------------------------|
|
|
107
|
+
| TypeScript | `tsconfig.json`, `jsconfig.json`, `package.json` w/ typescript | `lsp-adapters/typescript.js` |
|
|
108
|
+
| Python | `pyproject.toml`, `setup.py`, `setup.cfg`, `requirements.txt`, `Pipfile`, top-level `*.py` | `lsp-adapters/python.js` |
|
|
109
|
+
| Go | `go.mod` | `lsp-adapters/go.js` |
|
|
110
|
+
| Rust | `Cargo.toml` | `lsp-adapters/rust.js` |
|
|
111
|
+
| Ruby | `Gemfile`, `.ruby-version`, `config.ru` | `lsp-adapters/ruby.js` |
|
|
112
|
+
|
|
113
|
+
If any adapter fires, `features.has_lsp_layer` defaults to `true` in the
|
|
114
|
+
configure prompt (the user can still say no). The prompt copy is
|
|
115
|
+
*"Enable LSP symbol-search layer? (recommended for large codebases)"*.
|
|
116
|
+
|
|
117
|
+
When the user confirms, for each detected language:
|
|
118
|
+
|
|
119
|
+
- **npm-dev mode** (TS, Python via pyright): `npm install --save-dev <pkg>`
|
|
120
|
+
runs in-process. Success → added to `lsp.installed_servers`.
|
|
121
|
+
- **system mode** (Go, Rust, Ruby): the install command is *printed*, never
|
|
122
|
+
executed. The server name is recorded as pending in `installed_servers`;
|
|
123
|
+
`baldart doctor` re-verifies on the next run and flags the mismatch if the
|
|
124
|
+
user hasn't run the printed command yet.
|
|
125
|
+
|
|
126
|
+
### 3.2 Update from pre-v3.10
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
npx baldart update # subtree pull
|
|
130
|
+
# → schema-drift detector runs
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
`update.js:407–435` diffs `template.features` vs `cur.features`. It finds
|
|
134
|
+
`has_lsp_layer` missing and prints:
|
|
135
|
+
|
|
136
|
+
> ⚠ New config keys in this version: has_lsp_layer.
|
|
137
|
+
> Run `baldart configure` now to populate them? (y/N)
|
|
138
|
+
|
|
139
|
+
The user re-enters the configure flow above. **No silent default** — the
|
|
140
|
+
always-ask contract from `framework/agents/project-context.md` § 3 owns this.
|
|
141
|
+
|
|
142
|
+
### 3.3 Routine doctor run
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npx baldart # smart doctor (no-arg, default since v3.2.0)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`doctor.js` reads `config.lsp.installed_servers`. When
|
|
149
|
+
`lsp.auto_verify !== false`, it executes each adapter's `verifyCommand()`
|
|
150
|
+
(e.g. `npx --no-install typescript-language-server --version`). Output:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
· LSP layer 2 server(s) verified (typescript, python)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
If any server fails verify, the planner emits an `lsp-fix` action with
|
|
157
|
+
`autoOk: false` (so it asks before touching anything) and reinstalls only
|
|
158
|
+
the broken ones — with per-server confirmation, preserving any deliberate
|
|
159
|
+
uninstall the user may have done.
|
|
160
|
+
|
|
161
|
+
### 3.4 Standalone bootstrap
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
/lsp-bootstrap # inside Claude Code, when the layer is enabled
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The same install + verify flow exposed as a skill, useful when the user has
|
|
168
|
+
toggled `has_lsp_layer: true` manually in `baldart.config.yml` and now wants
|
|
169
|
+
to populate the layer without re-running the full configure prompt. The
|
|
170
|
+
skill refuses to run when the flag is `false` — opt-in is owned by configure.
|
|
171
|
+
|
|
172
|
+
### 3.5 Runtime behavior in a Claude Code session
|
|
173
|
+
|
|
174
|
+
When `codebase-architect` or one of the code-exploration skills (`bug`,
|
|
175
|
+
`prd`, `new`, `simplify`, `context-primer`) is invoked:
|
|
176
|
+
|
|
177
|
+
1. Read `baldart.config.yml`. If `features.has_lsp_layer !== true`, behave
|
|
178
|
+
exactly as v3.9.x (RAG → Grep → Git).
|
|
179
|
+
2. Otherwise: classify the query.
|
|
180
|
+
- Identifier-shaped (function name, type name, class, exported symbol) →
|
|
181
|
+
**LSP first** (`ToolSearch("LSP")` → `find-references` / `definition`).
|
|
182
|
+
- Free text / phrase / comment / path / regex → **Grep first**, LSP is
|
|
183
|
+
useless here.
|
|
184
|
+
- Mixed (e.g. "refactor function X used in 5 places") → RAG hybrid for
|
|
185
|
+
conceptual context, then LSP for the structural part.
|
|
186
|
+
3. Budget: max **3 LSP calls per task**. After 3 calls without convergence,
|
|
187
|
+
escalate to direct file reads — don't ping-pong references.
|
|
188
|
+
4. If LSP tool isn't loaded / plugin missing / timeout > 8s / zero
|
|
189
|
+
references for a symbol you know exists → **silent fallback to Grep**.
|
|
190
|
+
The user does not see an error mid-task; `baldart doctor` is the
|
|
191
|
+
self-heal channel.
|
|
192
|
+
|
|
193
|
+
The protocol document
|
|
194
|
+
[`framework/agents/code-search-protocol.md`](../agents/code-search-protocol.md)
|
|
195
|
+
is the authoritative runtime spec — this doc points at it rather than
|
|
196
|
+
duplicating its content.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 4. Field reference
|
|
201
|
+
|
|
202
|
+
### 4.1 `baldart.config.yml`
|
|
203
|
+
|
|
204
|
+
```yaml
|
|
205
|
+
features:
|
|
206
|
+
has_lsp_layer: true # gate
|
|
207
|
+
|
|
208
|
+
lsp:
|
|
209
|
+
installed_servers: # list of adapter names
|
|
210
|
+
- typescript
|
|
211
|
+
- python
|
|
212
|
+
auto_verify: true # doctor re-runs verifyCommand on each call
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Constraints:
|
|
216
|
+
|
|
217
|
+
- `has_lsp_layer` MUST be present and explicitly `true | false` once
|
|
218
|
+
configure has run (always-ask contract).
|
|
219
|
+
- `installed_servers` is **only meaningful when the flag is `true`**.
|
|
220
|
+
Configure resets it to `[]` if the flag flips to `false` (so the file
|
|
221
|
+
doesn't lie about pending installs).
|
|
222
|
+
- `auto_verify: false` is intended for noisy CI — agents still respect the
|
|
223
|
+
layer at runtime; only the doctor's verify probe is suppressed.
|
|
224
|
+
- Adapter names map 1:1 to filenames under `src/utils/lsp-adapters/`. An
|
|
225
|
+
unknown name in `installed_servers` produces a soft warning, never a hard
|
|
226
|
+
failure.
|
|
227
|
+
|
|
228
|
+
### 4.2 Adapter contract (`src/utils/lsp-adapters/<lang>.js`)
|
|
229
|
+
|
|
230
|
+
Every adapter is a class exporting:
|
|
231
|
+
|
|
232
|
+
| Member | Type | Purpose |
|
|
233
|
+
|----------------------|---------------------|------------------------------------------------------------|
|
|
234
|
+
| `name` | string getter | Stable id used in `installed_servers` (e.g. `"typescript"`)|
|
|
235
|
+
| `label` | string getter | Human-readable for prompts/diagnostics |
|
|
236
|
+
| `binary` | string getter | Executable name expected on PATH or in node_modules |
|
|
237
|
+
| `installMode` | `"npm-dev"` / `"system"` | How the installer treats this language |
|
|
238
|
+
| `npmPackage` | string (npm-dev only) | What goes after `npm install --save-dev` |
|
|
239
|
+
| `installCommand()` | string | The exact shell command (printed or executed) |
|
|
240
|
+
| `verifyCommand()` | string | A no-side-effect probe (e.g. `--version`) |
|
|
241
|
+
| `claudePluginId()` | string \| null | Reserved: id of a Claude Code code-intelligence plugin |
|
|
242
|
+
| `static detect(cwd)` | boolean | Pure: does the language live in this repo? |
|
|
243
|
+
|
|
244
|
+
The contract is enforced by convention, not by an interface check. When you
|
|
245
|
+
add a new adapter, mirror the shape of `typescript.js` exactly, then add it
|
|
246
|
+
to the REGISTRY in `lsp-adapters/index.js`.
|
|
247
|
+
|
|
248
|
+
### 4.3 Installer contract (`src/utils/lsp-installer.js`)
|
|
249
|
+
|
|
250
|
+
`LspInstaller` exposes:
|
|
251
|
+
|
|
252
|
+
- `detectLanguages()` → string[] — pure, no I/O beyond filesystem reads
|
|
253
|
+
- `recommend(langs?)` → entries with install metadata for UI consumption
|
|
254
|
+
- `installServers(names, { interactive=true, dryRun=false })` →
|
|
255
|
+
`{ installed, skipped, manual }` — returns rather than throws
|
|
256
|
+
- `verifyServers(names)` → `[{ name, ok, output|error }]` — never throws
|
|
257
|
+
|
|
258
|
+
All side-effecting methods are gated by `interactive` and a per-server
|
|
259
|
+
confirm; doctor passes `interactive: true` so the user retains veto power.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 5. Adding a new language
|
|
264
|
+
|
|
265
|
+
Worked example: adding **Java** support.
|
|
266
|
+
|
|
267
|
+
1. Pick the language server. For Java the de-facto choice is `jdtls`
|
|
268
|
+
(Eclipse JDT Language Server), installed via system means.
|
|
269
|
+
2. Create `src/utils/lsp-adapters/java.js`:
|
|
270
|
+
```js
|
|
271
|
+
const fs = require('fs');
|
|
272
|
+
const path = require('path');
|
|
273
|
+
|
|
274
|
+
class JavaAdapter {
|
|
275
|
+
constructor(cwd = process.cwd()) { this.cwd = cwd; }
|
|
276
|
+
get name() { return 'java'; }
|
|
277
|
+
get label() { return 'Java (jdtls)'; }
|
|
278
|
+
get binary() { return 'jdtls'; }
|
|
279
|
+
get installMode() { return 'system'; }
|
|
280
|
+
installCommand() { return 'brew install jdtls'; }
|
|
281
|
+
verifyCommand() { return 'jdtls --version'; }
|
|
282
|
+
claudePluginId() { return null; }
|
|
283
|
+
static detect(cwd = process.cwd()) {
|
|
284
|
+
return ['pom.xml', 'build.gradle', 'build.gradle.kts']
|
|
285
|
+
.some(m => fs.existsSync(path.join(cwd, m)));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
module.exports = JavaAdapter;
|
|
290
|
+
```
|
|
291
|
+
3. Register in `src/utils/lsp-adapters/index.js`:
|
|
292
|
+
```js
|
|
293
|
+
const JavaAdapter = require('./java');
|
|
294
|
+
// ...
|
|
295
|
+
const REGISTRY = {
|
|
296
|
+
// ...
|
|
297
|
+
java: JavaAdapter,
|
|
298
|
+
};
|
|
299
|
+
```
|
|
300
|
+
4. Smoke test:
|
|
301
|
+
```bash
|
|
302
|
+
node -e 'const r = require("./src/utils/lsp-adapters"); console.log(r.listAdapters())'
|
|
303
|
+
```
|
|
304
|
+
Should now include `java`.
|
|
305
|
+
5. No change required in `configure.js`, `doctor.js`, the protocol module,
|
|
306
|
+
or any agent/skill — they all iterate over the REGISTRY.
|
|
307
|
+
6. Update `CHANGELOG.md`, bump VERSION (PATCH if pure addition), document the
|
|
308
|
+
adapter in this file's § 3.1 marker table.
|
|
309
|
+
7. Optional: add a per-language quirk paragraph to
|
|
310
|
+
`framework/templates/overlays/agents/codebase-architect.lsp-example.md`
|
|
311
|
+
if Java has gotchas worth flagging to consumers (e.g. classpath setup,
|
|
312
|
+
multi-module Maven projects).
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 6. Troubleshooting
|
|
317
|
+
|
|
318
|
+
### 6.1 "Agents are still using Grep even though LSP is enabled"
|
|
319
|
+
|
|
320
|
+
Likely causes, in order of likelihood:
|
|
321
|
+
|
|
322
|
+
1. The query is free text, not a symbol. Re-read § 3.5 — Grep is correct
|
|
323
|
+
here, not a regression.
|
|
324
|
+
2. The Claude Code LSP plugin isn't loaded in this session. Check inside
|
|
325
|
+
Claude Code with `/plugin list`. Reload if necessary.
|
|
326
|
+
3. The language server binary isn't on PATH. Run `baldart doctor` — the
|
|
327
|
+
LSP line will say `n/m broken (typescript, ...)` and propose `lsp-fix`.
|
|
328
|
+
4. `features.has_lsp_layer` is `false` or missing in `baldart.config.yml`.
|
|
329
|
+
Run `baldart configure`.
|
|
330
|
+
|
|
331
|
+
### 6.2 "configure prompted me but didn't install anything"
|
|
332
|
+
|
|
333
|
+
The autodetector found no supported language markers. Either:
|
|
334
|
+
|
|
335
|
+
- You're in a polyglot repo where the supported language lives in a
|
|
336
|
+
subdirectory configure didn't probe. Add the marker file at the repo root
|
|
337
|
+
(e.g. a stub `tsconfig.json`) or extend the adapter's `detect()`.
|
|
338
|
+
- You're using a language we don't ship an adapter for. See § 5.
|
|
339
|
+
|
|
340
|
+
### 6.3 "doctor says my server is broken but it works in my editor"
|
|
341
|
+
|
|
342
|
+
`verifyCommand()` executes from the consumer cwd with a hard 8s timeout. If
|
|
343
|
+
the language server takes longer than that to print `--version` (rare, but
|
|
344
|
+
seen on first-run cold caches), the verify fails. Re-run `baldart doctor`
|
|
345
|
+
once warm. If still failing, run the exact `verifyCommand()` string in your
|
|
346
|
+
shell — the actual error will surface.
|
|
347
|
+
|
|
348
|
+
### 6.4 "I want to enable the layer but not have devDeps in package.json"
|
|
349
|
+
|
|
350
|
+
For TypeScript / Python you can override the adapter's `installMode` by
|
|
351
|
+
writing an overlay at `.baldart/overlays/agents/codebase-architect.md`
|
|
352
|
+
documenting your alternative install path (e.g. system pyright via uv), and
|
|
353
|
+
then manually setting `lsp.installed_servers: [python]` in the config. The
|
|
354
|
+
runtime layer doesn't care *how* the binary got there, only that it's
|
|
355
|
+
reachable. `baldart doctor` will continue to verify it.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## 7. Mental model for agents extending this layer
|
|
360
|
+
|
|
361
|
+
When you (an AI agent) are asked to modify the LSP layer, internalize these
|
|
362
|
+
invariants — they are the rules the existing code obeys, and breaking them
|
|
363
|
+
silently corrupts consumer installs:
|
|
364
|
+
|
|
365
|
+
1. **Opt-in is owned by configure.** No code path may flip
|
|
366
|
+
`features.has_lsp_layer` from `false` to `true` (or vice versa) without
|
|
367
|
+
going through `configure.js` or an explicit user-typed YAML edit. The
|
|
368
|
+
`lsp-bootstrap` skill and the doctor `lsp-fix` action both *refuse* to
|
|
369
|
+
change the gate; they only act when it's already on.
|
|
370
|
+
2. **`installed_servers` is descriptive, not normative.** It records what
|
|
371
|
+
BALDART knows about; it does not enforce. Removing a name from the list
|
|
372
|
+
doesn't uninstall the binary, and adding a name doesn't install one. The
|
|
373
|
+
single source of truth for "is it usable" is the verify probe.
|
|
374
|
+
3. **Fallback to Grep is silent.** Never abort an agent's task because LSP
|
|
375
|
+
failed. The user finds out about broken LSP through `baldart doctor`,
|
|
376
|
+
not by getting an error mid-bug-investigation.
|
|
377
|
+
4. **The adapter REGISTRY is the only place to enumerate languages.**
|
|
378
|
+
`configure.js`, `doctor.js`, the bootstrap skill, and the docs all
|
|
379
|
+
iterate the registry. Hard-coding a language anywhere else is a bug.
|
|
380
|
+
5. **Schema-change propagation rule** (from memory
|
|
381
|
+
`feedback_schema_change_propagation.md`): any new key under `lsp.*` or
|
|
382
|
+
`features.has_lsp_*` must land in the template, the configure prompt,
|
|
383
|
+
the update detector, the doctor diagnostic, the relevant skill(s), AND
|
|
384
|
+
the CHANGELOG. If you only add the template, you have introduced silent
|
|
385
|
+
drift between layers — the v3.9.0 pattern is the worked example to copy.
|
|
386
|
+
6. **No MCP server lives in this repo.** BALDART does not ship its own LSP
|
|
387
|
+
bridge. The runtime tools come from Claude Code's plugin ecosystem (or
|
|
388
|
+
a third-party MCP the user installs); BALDART's job is to make sure the
|
|
389
|
+
binaries are present and to instruct agents how to use them.
|
|
390
|
+
|
|
391
|
+
If a feature request seems to break one of these invariants, push back and
|
|
392
|
+
propose an alternative that preserves them — they were chosen deliberately
|
|
393
|
+
in the design review (see the approved plan in
|
|
394
|
+
`/Users/antoniobaldassarre/.claude/plans/` from 2026-05-23).
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 8. See also
|
|
399
|
+
|
|
400
|
+
- [`framework/agents/code-search-protocol.md`](../agents/code-search-protocol.md) — runtime protocol
|
|
401
|
+
- [`framework/agents/project-context.md`](../agents/project-context.md) — always-ask contract
|
|
402
|
+
- [`framework/docs/PROJECT-CONFIGURATION.md`](PROJECT-CONFIGURATION.md) § 4.5 + § 4.6 — config schema
|
|
403
|
+
- [`framework/.claude/skills/lsp-bootstrap/SKILL.md`](../.claude/skills/lsp-bootstrap/SKILL.md) — invokable skill
|
|
404
|
+
- [`framework/templates/overlays/agents/codebase-architect.lsp-example.md`](../templates/overlays/agents/codebase-architect.lsp-example.md) — starter overlay
|
|
405
|
+
- [`CHANGELOG.md`](../../CHANGELOG.md) — v3.10.0 entry
|
|
@@ -148,6 +148,23 @@ Every flag MUST be present as `true` or `false` once `baldart configure` has run
|
|
|
148
148
|
| `has_adrs` | ADR workflow. Architectural decisions get logged in `paths.adrs_dir`. |
|
|
149
149
|
| `has_prd_workflow` | PRD workflow (`paths.prd_dir`). `/prd` and `/prd-add` skills refuse to run without it. |
|
|
150
150
|
| `has_wiki_overlay` | LLM-wiki overlay (`paths.wiki_dir`). `/capture` skill refuses to run without it. |
|
|
151
|
+
| `has_lsp_layer` | LSP symbol-search layer (since v3.10.0). When `true`, `codebase-architect`, `context-primer`, `bug`, `prd`, `new`, and `simplify` prefer LSP `find-references` / `go-to-definition` over Grep for identifier queries. Wired by `framework/agents/code-search-protocol.md`. The flag also triggers `baldart configure` (and the `/lsp-bootstrap` skill) to install the matching language servers. |
|
|
152
|
+
|
|
153
|
+
### 4.6 `lsp` — installed language servers (since v3.10.0)
|
|
154
|
+
|
|
155
|
+
Populated by `baldart configure` and the `/lsp-bootstrap` skill when `features.has_lsp_layer: true`. Leave empty otherwise.
|
|
156
|
+
|
|
157
|
+
| Key | Meaning |
|
|
158
|
+
|---|---|
|
|
159
|
+
| `lsp.installed_servers` | List of language IDs (`typescript`, `python`, `go`, `rust`, `ruby`, …) whose server BALDART has recorded for this project. Identifiers map 1:1 to adapter files under `src/utils/lsp-adapters/`. |
|
|
160
|
+
| `lsp.auto_verify` | When `true` (default), `baldart doctor` re-verifies the binaries are reachable on every run. Disable on CI if the verify step is too noisy. |
|
|
161
|
+
|
|
162
|
+
**Install modes per adapter:**
|
|
163
|
+
|
|
164
|
+
- `typescript`, `python` — installed as npm devDeps (`npm install --save-dev typescript-language-server typescript` / `pyright`). Project-local, version-pinned.
|
|
165
|
+
- `go`, `rust`, `ruby` — installed via system tools (`go install …`, `rustup component add …`, `gem install …`). BALDART prints the command; the user runs it.
|
|
166
|
+
|
|
167
|
+
**Fallback contract.** When the LSP layer is enabled but a server is missing or broken, agents silently fall back to Grep — code search never fails because of LSP issues. `baldart doctor` surfaces the mismatch and offers reinstall.
|
|
151
168
|
|
|
152
169
|
## 5. The overlay system
|
|
153
170
|
|
|
@@ -112,6 +112,48 @@ features:
|
|
|
112
112
|
# LLM-wiki overlay (paths.wiki_dir + capture/wiki-curator loop).
|
|
113
113
|
has_wiki_overlay: false
|
|
114
114
|
|
|
115
|
+
# LSP symbol-search layer. When true, agents and skills that explore code
|
|
116
|
+
# (codebase-architect, context-primer, bug, prd, new, simplify) prefer
|
|
117
|
+
# language-server "find references / go to definition" over Grep for
|
|
118
|
+
# identifier queries, falling back to Grep only when LSP is unavailable
|
|
119
|
+
# or the query isn't a symbol. See framework/agents/code-search-protocol.md.
|
|
120
|
+
# `baldart configure` installs the relevant language servers when enabled.
|
|
121
|
+
has_lsp_layer: false
|
|
122
|
+
|
|
123
|
+
# ─── LSP ─────────────────────────────────────────────────────────────────
|
|
124
|
+
# State of the LSP layer for this project. Populated by `baldart configure`
|
|
125
|
+
# (and by `npx baldart lsp install` / the `/lsp-bootstrap` skill). Leave
|
|
126
|
+
# empty if `features.has_lsp_layer: false`.
|
|
127
|
+
lsp:
|
|
128
|
+
# Languages whose language server BALDART has installed/verified locally.
|
|
129
|
+
# Identifiers map to adapters under src/utils/lsp-adapters/
|
|
130
|
+
# (typescript, python, go, rust, ruby — extend as needed).
|
|
131
|
+
installed_servers: []
|
|
132
|
+
|
|
133
|
+
# When true, `baldart doctor` re-verifies the binaries are reachable on
|
|
134
|
+
# every run. Disable on CI if the verify step is too noisy.
|
|
135
|
+
auto_verify: true
|
|
136
|
+
|
|
137
|
+
# ─── GIT ─────────────────────────────────────────────────────────────────
|
|
138
|
+
# Controls how worktree-manager (`/mw`) integrates a worktree's feature
|
|
139
|
+
# branch back into `develop`.
|
|
140
|
+
git:
|
|
141
|
+
# How `/mw` lands the feature branch onto develop:
|
|
142
|
+
#
|
|
143
|
+
# pr (default) — push feature branch, open a PR via `gh pr create`,
|
|
144
|
+
# merge via `gh pr merge`. Required if `develop` is protected
|
|
145
|
+
# on origin (status checks, required reviews, merge queue).
|
|
146
|
+
#
|
|
147
|
+
# local-push — after rebasing the feature branch onto `origin/develop`,
|
|
148
|
+
# fast-forward push the feature branch directly to
|
|
149
|
+
# `origin/develop` (`git push origin <feat>:develop`).
|
|
150
|
+
# No PR, no `gh` dependency. FAILS hard if `develop` is
|
|
151
|
+
# protected on origin — switch back to `pr` in that case.
|
|
152
|
+
#
|
|
153
|
+
# Neither strategy ever touches the main repo's HEAD — both flows are
|
|
154
|
+
# worktree-isolated and respect the terminal-isolation rule.
|
|
155
|
+
merge_strategy: pr
|
|
156
|
+
|
|
115
157
|
# ─── TOOLS ───────────────────────────────────────────────────────────────
|
|
116
158
|
# Which AI CLI tools should the framework target on this machine?
|
|
117
159
|
# Each enabled tool gets its own per-item skill symlinks pointing at the
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
base_agent: codebase-architect
|
|
3
|
+
base_agent_version: 3.10.0
|
|
4
|
+
mode: extend
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
> **How to use this example**
|
|
8
|
+
>
|
|
9
|
+
> Copy this file to `.baldart/overlays/agents/codebase-architect.md` (drop the
|
|
10
|
+
> `.lsp-example`) when you want to add project-specific LSP guidance on top of
|
|
11
|
+
> the shipped `agents/code-search-protocol.md`. The framework regenerates
|
|
12
|
+
> `.claude/agents/codebase-architect.md` from base + overlay on every
|
|
13
|
+
> `npx baldart update`.
|
|
14
|
+
>
|
|
15
|
+
> Section markers (see `framework/templates/overlays/README.md`):
|
|
16
|
+
> - `## [OVERRIDE] <heading>` — replace the entire matching H2 from the base.
|
|
17
|
+
> - `## [APPEND] <heading>` — add content after the base section.
|
|
18
|
+
> - `## [PREPEND] <heading>` — add content before the base section.
|
|
19
|
+
> - `## <heading>` with no marker — appended at the end as a new custom section.
|
|
20
|
+
>
|
|
21
|
+
> Skip this overlay entirely if the shipped protocol is enough — the base
|
|
22
|
+
> agent already wires LSP correctly when `features.has_lsp_layer: true`.
|
|
23
|
+
|
|
24
|
+
## [APPEND] LSP Symbol Search
|
|
25
|
+
|
|
26
|
+
Project-specific tuning on top of `framework/agents/code-search-protocol.md`:
|
|
27
|
+
|
|
28
|
+
- **Preferred entry points.** For identifier-shaped lookups in this repo,
|
|
29
|
+
start with `find-references` on the symbol exported from
|
|
30
|
+
`src/<your-canonical-module>/index.ts` (or your equivalent). The export
|
|
31
|
+
surface is small enough that the references list converges in 1–2 calls.
|
|
32
|
+
- **Per-language quirks.**
|
|
33
|
+
- TypeScript: monorepo packages under `packages/<name>` need
|
|
34
|
+
`tsserver` workspaces enabled. If LSP returns zero references for a
|
|
35
|
+
symbol you know is used cross-package, fall back to Grep scoped to
|
|
36
|
+
`packages/*/src/`.
|
|
37
|
+
- Python: pyright honors `extraPaths` from `pyrightconfig.json` — if
|
|
38
|
+
you re-rooted sources, double-check the config before reporting "no
|
|
39
|
+
references found".
|
|
40
|
+
- **Don't chase generated code.** Skip LSP results pointing into `dist/`,
|
|
41
|
+
`.next/`, `coverage/`, or any path matching the project's `.gitignore` —
|
|
42
|
+
treat them as noise.
|
|
43
|
+
|
|
44
|
+
## Project-only conventions
|
|
45
|
+
|
|
46
|
+
Custom rules with no equivalent in the base — appended as a new H2:
|
|
47
|
+
|
|
48
|
+
- All `find-references` outputs over 50 callsites trigger a refactor
|
|
49
|
+
conversation with the maintainer before any rename / signature change
|
|
50
|
+
proceeds.
|
|
51
|
+
- When LSP is unavailable, write the reason (binary missing / plugin not
|
|
52
|
+
loaded / language not yet adopted) into the analysis output so reviewers
|
|
53
|
+
understand why Grep was used instead.
|