turbo-editors/turbo-corepublic Fork 0
v1.0.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

2026-09-18-first-launch-lsp.md · 34 lines · 3.2 KBmarkdown Blame HistoryRaw
🛟 Updated. 28d5985 k33g 13h ago1# Handoff — 2026-09-18 — first launch: LSP dead until save + relaunch → fixed
2
3## State
4
5The user reported that on turbo-go's first launch the LSP does not work, and that saving, quitting and relaunching fixes it. Diagnosed by reading the code, confirmed by the user (the window had started **Untitled**), and **fixed in this session** through a full `/methodical-dev` cycle. Not committed.
6
7The defect: a buffer that gains its path through Save As was never announced to the language server. `Language.DidOpen` skips path `""` (an Untitled window has nothing to announce), `afterSave` sent only `didSave`, and `announceOpenDocuments` runs once (`a.announced`) — and a server ignores `didChange`/`didSave` for a document it was never told is open, so every LSP feature stayed dead in that window until a restart reopened the file under its name.
8
9The fix, all in `app`:
10
11- `app/language.go` — the `documents` map is keyed by absolute path (`pathKey`, the renamed `diagnosticKey`), so `Knows` does not depend on how a path is spelt. Without this, the next change would re-announce a document opened relative and saved absolute.
12- `app/actions_file.go``announceSaved`, called from `afterSave` so both save paths get it: `didOpen` for a path the server does not `Knows`, `didSave` otherwise. And `save` remembers the buffer's path before `SaveAs` rewrites it; `renamed` (absolute comparison) triggers `DidClose` of the old document on a genuine rename, so no ghost document stays open on the server.
13
14Tests: 5 new (one in `app/diagnostics_test.go`, four in the new `app/save_test.go`), each verified by breaking the code it covers. Suite green, `-race` green on `app`. Quality run #30 PASS 0/0/0, complexity 2308. Docs EN + FR: `reference/app.md` (a `Knows` row, a paragraph on what saving sends), `how-to/talk-to-a-language-server.md` (a "file created inside the editor" variant), plus `app/README.md`.
15
16## In flight
17
18Nothing half-written. The tree also still carries the **uncommitted Windows terminal work of 2026-09-17** (disjoint files — see that day's handoff); this session's change sits on top of it on `main`.
19
20## Next steps
21
221. Commit (the user does this, or asks for it): the fix, its tests, the docs, and `.memory/`.
232. Drive it once against a real gopls: start turbo-go, type into an Untitled window, save as `x.go`, complete — the one verification the fake server cannot give.
243. Tag and release turbo-core, then re-pin the six editors so they inherit the fix.
25
26## Open questions / blockers
27
28- The user's report ("la 1ère fois") may also have had a second ingredient: gopls's very first run on a machine populates its caches and answers empty completions while loading, even once `LSP: ready` shows. Unmeasured; worth remembering if a report comes back after this fix ships.
29
30## Watch out for
31
32- Do not move the announcement into `Buffer.SaveAs`: it would put the language server underneath the text type. Rejected on purpose.
33- Autosave never renames (it rewrites the buffer's own path), which is why `DidClose` lives in `save` alone. If autosave ever learns to rename, that assumption breaks.
34- `waitForMethod` in the app tests polls up to 2 s; a test asserting a notification was *not* sent must wait for a later one first (see `TestSaveAsToTheSamePathClosesNothing`), or it asserts on a race.