## Summary Add LSP trace recording and replay-based smoke testing infrastructure. ### clice changes (`src/clice.cc`) - Add `--log-level` CLI option with validation (rejects unknown levels instead of silently defaulting to off) - Add `--record <path>` CLI option that wraps the transport with `RecordingTransport` to capture client→server messages as timestamped JSONL - Works in both pipe and socket modes - Fix exit code: `loop.run()` returns non-zero after `uv_stop()`, explicitly return 0 after clean shutdown ### Compile logging (`src/compile/compilation.cpp`) - Print compile commands at debug log level ### Replay script (`tests/replay.py`) - Timestamp-based pacing: sleeps between messages based on recorded intervals, faithful to original editor session - Automatic workspace path rewriting: infers repo root from script location, rewrites absolute paths in trace so CI replay works without extra arguments - Handles server→client requests (workDoneProgress/create, registerCapability, etc.) with default responses - Waits for all pending responses before sending shutdown/exit - Detects server exit mid-replay and fails pending futures immediately instead of hanging - Reports PASS/FAIL/SKIP with stderr tail on failure ### CI & config - Add `smoke-test` pixi task and CI workflow step (runs after integration tests) - `.gitattributes`: mark `tests/smoke/*.jsonl` as `linguist-generated binary` to suppress diffs - Add sample trace file `tests/smoke/session.jsonl` ### VSCode extension - Add restart command (`clice.restart`) - Support `CLICE_MODE` env var to override mode setting (for debug launch configs) - Split launch configs into socket/pipe variants with `--disable-extensions` ## Test plan - [x] `python tests/replay.py tests/smoke/session.jsonl --clice ./build/RelWithDebInfo/bin/clice` passes locally - [ ] CI smoke test passes on Linux/macOS/Windows 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
29 lines
12 KiB
JSON
Generated
29 lines
12 KiB
JSON
Generated
{"ts":16,"msg":"{\"jsonrpc\":\"2.0\",\"id\":0,\"method\":\"initialize\",\"params\":{\"processId\":2611893,\"clientInfo\":{\"name\":\"Visual Studio Code\",\"version\":\"1.114.0\"},\"locale\":\"en\",\"rootPath\":\"/home/ykiko/C++/clice/tests/data/hello_world\",\"rootUri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world\",\"capabilities\":{\"workspace\":{\"applyEdit\":true,\"workspaceEdit\":{\"documentChanges\":true,\"resourceOperations\":[\"create\",\"rename\",\"delete\"],\"failureHandling\":\"textOnlyTransactional\",\"normalizesLineEndings\":true,\"changeAnnotationSupport\":{\"groupsOnLabel\":true}},\"configuration\":true,\"didChangeWatchedFiles\":{\"dynamicRegistration\":true,\"relativePatternSupport\":true},\"symbol\":{\"dynamicRegistration\":true,\"symbolKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},\"tagSupport\":{\"valueSet\":[1]},\"resolveSupport\":{\"properties\":[\"location.range\"]}},\"codeLens\":{\"refreshSupport\":true},\"executeCommand\":{\"dynamicRegistration\":true},\"didChangeConfiguration\":{\"dynamicRegistration\":true},\"workspaceFolders\":true,\"foldingRange\":{\"refreshSupport\":true},\"semanticTokens\":{\"refreshSupport\":true},\"fileOperations\":{\"dynamicRegistration\":true,\"didCreate\":true,\"didRename\":true,\"didDelete\":true,\"willCreate\":true,\"willRename\":true,\"willDelete\":true},\"inlineValue\":{\"refreshSupport\":true},\"inlayHint\":{\"refreshSupport\":true},\"diagnostics\":{\"refreshSupport\":true}},\"textDocument\":{\"publishDiagnostics\":{\"relatedInformation\":true,\"versionSupport\":false,\"tagSupport\":{\"valueSet\":[1,2]},\"codeDescriptionSupport\":true,\"dataSupport\":true},\"synchronization\":{\"dynamicRegistration\":true,\"willSave\":true,\"willSaveWaitUntil\":true,\"didSave\":true},\"completion\":{\"dynamicRegistration\":true,\"contextSupport\":true,\"completionItem\":{\"snippetSupport\":true,\"commitCharactersSupport\":true,\"documentationFormat\":[\"markdown\",\"plaintext\"],\"deprecatedSupport\":true,\"preselectSupport\":true,\"tagSupport\":{\"valueSet\":[1]},\"insertReplaceSupport\":true,\"resolveSupport\":{\"properties\":[\"documentation\",\"detail\",\"additionalTextEdits\"]},\"insertTextModeSupport\":{\"valueSet\":[1,2]},\"labelDetailsSupport\":true},\"insertTextMode\":2,\"completionItemKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]},\"completionList\":{\"itemDefaults\":[\"commitCharacters\",\"editRange\",\"insertTextFormat\",\"insertTextMode\",\"data\"]}},\"hover\":{\"dynamicRegistration\":true,\"contentFormat\":[\"markdown\",\"plaintext\"]},\"signatureHelp\":{\"dynamicRegistration\":true,\"signatureInformation\":{\"documentationFormat\":[\"markdown\",\"plaintext\"],\"parameterInformation\":{\"labelOffsetSupport\":true},\"activeParameterSupport\":true},\"contextSupport\":true},\"definition\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"references\":{\"dynamicRegistration\":true},\"documentHighlight\":{\"dynamicRegistration\":true},\"documentSymbol\":{\"dynamicRegistration\":true,\"symbolKind\":{\"valueSet\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},\"hierarchicalDocumentSymbolSupport\":true,\"tagSupport\":{\"valueSet\":[1]},\"labelSupport\":true},\"codeAction\":{\"dynamicRegistration\":true,\"isPreferredSupport\":true,\"disabledSupport\":true,\"dataSupport\":true,\"resolveSupport\":{\"properties\":[\"edit\"]},\"codeActionLiteralSupport\":{\"codeActionKind\":{\"valueSet\":[\"\",\"quickfix\",\"refactor\",\"refactor.extract\",\"refactor.inline\",\"refactor.rewrite\",\"source\",\"source.organizeImports\"]}},\"honorsChangeAnnotations\":true},\"codeLens\":{\"dynamicRegistration\":true},\"formatting\":{\"dynamicRegistration\":true},\"rangeFormatting\":{\"dynamicRegistration\":true,\"rangesSupport\":true},\"onTypeFormatting\":{\"dynamicRegistration\":true},\"rename\":{\"dynamicRegistration\":true,\"prepareSupport\":true,\"prepareSupportDefaultBehavior\":1,\"honorsChangeAnnotations\":true},\"documentLink\":{\"dynamicRegistration\":true,\"tooltipSupport\":true},\"typeDefinition\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"implementation\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"colorProvider\":{\"dynamicRegistration\":true},\"foldingRange\":{\"dynamicRegistration\":true,\"rangeLimit\":5000,\"lineFoldingOnly\":true,\"foldingRangeKind\":{\"valueSet\":[\"comment\",\"imports\",\"region\"]},\"foldingRange\":{\"collapsedText\":false}},\"declaration\":{\"dynamicRegistration\":true,\"linkSupport\":true},\"selectionRange\":{\"dynamicRegistration\":true},\"callHierarchy\":{\"dynamicRegistration\":true},\"semanticTokens\":{\"dynamicRegistration\":true,\"tokenTypes\":[\"namespace\",\"type\",\"class\",\"enum\",\"interface\",\"struct\",\"typeParameter\",\"parameter\",\"variable\",\"property\",\"enumMember\",\"event\",\"function\",\"method\",\"macro\",\"keyword\",\"modifier\",\"comment\",\"string\",\"number\",\"regexp\",\"operator\",\"decorator\"],\"tokenModifiers\":[\"declaration\",\"definition\",\"readonly\",\"static\",\"deprecated\",\"abstract\",\"async\",\"modification\",\"documentation\",\"defaultLibrary\"],\"formats\":[\"relative\"],\"requests\":{\"range\":true,\"full\":{\"delta\":true}},\"multilineTokenSupport\":false,\"overlappingTokenSupport\":false,\"serverCancelSupport\":true,\"augmentsSyntaxTokens\":true},\"linkedEditingRange\":{\"dynamicRegistration\":true},\"typeHierarchy\":{\"dynamicRegistration\":true},\"inlineValue\":{\"dynamicRegistration\":true},\"inlayHint\":{\"dynamicRegistration\":true,\"resolveSupport\":{\"properties\":[\"tooltip\",\"textEdits\",\"label.tooltip\",\"label.location\",\"label.command\"]}},\"diagnostic\":{\"dynamicRegistration\":true,\"relatedDocumentSupport\":false}},\"window\":{\"showMessage\":{\"messageActionItem\":{\"additionalPropertiesSupport\":true}},\"showDocument\":{\"support\":true},\"workDoneProgress\":true},\"general\":{\"staleRequestSupport\":{\"cancel\":true,\"retryOnContentModified\":[\"textDocument/semanticTokens/full\",\"textDocument/semanticTokens/range\",\"textDocument/semanticTokens/full/delta\"]},\"regularExpressions\":{\"engine\":\"ECMAScript\",\"version\":\"ES2020\"},\"markdown\":{\"parser\":\"marked\",\"version\":\"1.1.0\"},\"positionEncodings\":[\"utf-16\"]},\"notebookDocument\":{\"synchronization\":{\"dynamicRegistration\":true,\"executionSummarySupport\":true}}},\"trace\":\"off\",\"workspaceFolders\":[{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world\",\"name\":\"hello_world\"}]}}"}
|
|
{"ts":69,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"initialized\",\"params\":{}}"}
|
|
{"ts":90,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"textDocument/didOpen\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\",\"languageId\":\"cpp\",\"version\":1,\"text\":\"int add(int a, int b) {\\n return a + b;\\n}\\n\\nint main() {\\n int result = add(1, 2);\\n return result;\\n}\\n\"}}}"}
|
|
{"ts":307,"msg":"{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"textDocument/codeAction\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":7,\"character\":1},\"end\":{\"line\":7,\"character\":1}},\"context\":{\"diagnostics\":[],\"triggerKind\":2}}}"}
|
|
{"ts":358,"msg":"{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"textDocument/documentLink\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":358,"msg":"{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"textDocument/inlayHint\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":0,\"character\":0},\"end\":{\"line\":8,\"character\":0}}}}"}
|
|
{"ts":562,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"$/setTrace\",\"params\":{\"value\":\"off\"}}"}
|
|
{"ts":689,"msg":"{\"jsonrpc\":\"2.0\",\"id\":4,\"method\":\"textDocument/codeAction\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":7,\"character\":1},\"end\":{\"line\":7,\"character\":1}},\"context\":{\"diagnostics\":[],\"triggerKind\":2}}}"}
|
|
{"ts":690,"msg":"{\"jsonrpc\":\"2.0\",\"id\":5,\"method\":\"textDocument/documentSymbol\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":690,"msg":"{\"jsonrpc\":\"2.0\",\"id\":6,\"method\":\"textDocument/codeAction\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":7,\"character\":1},\"end\":{\"line\":7,\"character\":1}},\"context\":{\"diagnostics\":[],\"triggerKind\":2}}}"}
|
|
{"ts":690,"msg":"{\"jsonrpc\":\"2.0\",\"id\":7,\"method\":\"textDocument/semanticTokens/full\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":691,"msg":"{\"jsonrpc\":\"2.0\",\"id\":8,\"method\":\"textDocument/documentLink\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":691,"msg":"{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"textDocument/foldingRange\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":722,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"$/cancelRequest\",\"params\":{\"id\":4}}"}
|
|
{"ts":1367,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"$/setTrace\",\"params\":{\"value\":\"off\"}}"}
|
|
{"ts":1368,"msg":"{\"jsonrpc\":\"2.0\",\"id\":10,\"method\":\"textDocument/codeAction\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":7,\"character\":1},\"end\":{\"line\":7,\"character\":1}},\"context\":{\"diagnostics\":[],\"triggerKind\":2}}}"}
|
|
{"ts":1550,"msg":"{\"jsonrpc\":\"2.0\",\"id\":11,\"method\":\"textDocument/codeAction\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":7,\"character\":1},\"end\":{\"line\":7,\"character\":1}},\"context\":{\"diagnostics\":[],\"triggerKind\":2}}}"}
|
|
{"ts":1550,"msg":"{\"jsonrpc\":\"2.0\",\"id\":12,\"method\":\"textDocument/documentLink\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":1689,"msg":"{\"jsonrpc\":\"2.0\",\"id\":13,\"method\":\"textDocument/documentSymbol\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":1690,"msg":"{\"jsonrpc\":\"2.0\",\"id\":14,\"method\":\"textDocument/inlayHint\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"range\":{\"start\":{\"line\":0,\"character\":0},\"end\":{\"line\":8,\"character\":0}}}}"}
|
|
{"ts":2041,"msg":"{\"jsonrpc\":\"2.0\",\"id\":15,\"method\":\"textDocument/semanticTokens/full\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"}}}"}
|
|
{"ts":4457,"msg":"{\"jsonrpc\":\"2.0\",\"id\":16,\"method\":\"textDocument/hover\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"position\":{\"line\":5,\"character\":17}}}"}
|
|
{"ts":6653,"msg":"{\"jsonrpc\":\"2.0\",\"id\":17,\"method\":\"textDocument/hover\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"position\":{\"line\":5,\"character\":6}}}"}
|
|
{"ts":6653,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"$/cancelRequest\",\"params\":{\"id\":17}}"}
|
|
{"ts":6965,"msg":"{\"jsonrpc\":\"2.0\",\"id\":18,\"method\":\"textDocument/hover\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"position\":{\"line\":4,\"character\":6}}}"}
|
|
{"ts":9281,"msg":"{\"jsonrpc\":\"2.0\",\"id\":19,\"method\":\"textDocument/hover\",\"params\":{\"textDocument\":{\"uri\":\"file:///home/ykiko/C%2B%2B/clice/tests/data/hello_world/main.cpp\"},\"position\":{\"line\":6,\"character\":12}}}"}
|
|
{"ts":13769,"msg":"{\"jsonrpc\":\"2.0\",\"id\":20,\"method\":\"shutdown\"}"}
|
|
{"ts":13813,"msg":"{\"jsonrpc\":\"2.0\",\"method\":\"exit\"}"}
|