## What changed
This PR moves the shared VS Code development workflow to the repository
root.
It adds repo-level `.vscode/launch.json` and `.vscode/tasks.json` so
contributors can debug `clice` and the VS Code extension from the root
workspace with relative paths.
The checked-in tasks are intentionally limited to extension-side `pnpm`
workflows such as installing dependencies and running the extension
watcher. They do not build the `clice` executable or unit tests.
It also updates `.gitignore` to allow only those two shared VS Code
config files to be committed, while continuing to ignore other local
`.vscode` files.
Finally, it removes the duplicate `editors/vscode/.vscode` folder so
there is a single supported VS Code setup in the repo.
## Why
The previous setup split VS Code configs between local-only root files
and tracked configs under `editors/vscode/.vscode`, which made the
development/debug flow less consistent.
Keeping only extension-side tasks avoids baking a specific native build
workflow into committed editor config while still making extension
development usable out of the box.
## Developer impact
Contributors can now open the repository root in VS Code and use the
checked-in launch/tasks configs directly.
The extension debug configs only disable competing C/C++ language
extensions (`clangd` and `cpptools`) instead of disabling every
extension.
All committed paths remain relative to `${workspaceFolder}`.
## Validation
- Ran `python3 -m json.tool .vscode/launch.json`
- Ran `python3 -m json.tool .vscode/tasks.json`
## 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>