feat: add streamd lsp subcommand with LSP server

Implements a full Language Server Protocol server accessible via
`streamd lsp`. The server communicates over stdin/stdout and auto-
detects the workspace root from the LSP initialize request.

Features implemented:
- Passive mode when no .streamd.toml exists in workspace root
- Workspace-root-based config loading (bypasses R22/R23 global config)
- .streamd.toml file watcher (config reloads without restart)
- textDocument/completion with @ trigger, conditional suggestions
  (if_with relationships), and temporal date/time snippets (R16)
- textDocument/publishDiagnostics: R15 file-name format + R18
  timesheet violations (overlapping timecards, unclosed days)
- textDocument/documentSymbol: shard tree exposed as nested symbols
- textDocument/codeAction: "Mark task as done" quickfix for @Task
- workspace/symbol: cross-file shard search
- textDocument/references: find all @Marker occurrences
- textDocument/rename: rename @Marker across all files

Dependencies added: tower-lsp 0.20, tokio, dashmap, serde_json
This commit is contained in:
Konstantin Fickel 2026-04-13 21:37:38 +02:00
parent 77bf9c584b
commit 50c592a641
Signed by: kfickel
GPG key ID: A793722F9933C1A5
6 changed files with 1769 additions and 4 deletions

View file

@ -72,4 +72,7 @@ pub enum Commands {
#[arg(value_enum)]
shell: Shell,
},
/// Start LSP server (communicates over stdin/stdout)
Lsp,
}

1112
src/cli/commands/lsp.rs Normal file

File diff suppressed because it is too large Load diff

View file

@ -12,6 +12,7 @@ use crate::models::{LocalizedShard, RepositoryConfiguration};
pub mod completions;
pub mod daily;
pub mod edit;
pub mod lsp;
pub mod new;
pub mod timesheet;
pub mod todo;

View file

@ -22,6 +22,7 @@ fn main() -> miette::Result<()> {
Some(Commands::Completions { shell }) => {
streamd::cli::commands::completions::run(shell);
}
Some(Commands::Lsp) => streamd::cli::commands::lsp::run()?,
None => streamd::cli::commands::daily::run(None)?,
}