# Handoff — 2026-09-18 — first launch: LSP dead until save + relaunch → fixed ## State The 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. The 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. The fix, all in `app`: - `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. - `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. Tests: 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`. ## In flight Nothing 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`. ## Next steps 1. Commit (the user does this, or asks for it): the fix, its tests, the docs, and `.memory/`. 2. 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. 3. Tag and release turbo-core, then re-pin the six editors so they inherit the fix. ## Open questions / blockers - 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. ## Watch out for - Do not move the announcement into `Buffer.SaveAs`: it would put the language server underneath the text type. Rejected on purpose. - 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. - `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.