### Added

- **Git diff endpoint** — new `GET /api/workspaces/:id/git/diff?path=<relative-path>` route that returns structured diff data for a file: hunks with line-level changes (added/removed/context), addition/deletion counts, language, and change status. Returns `diffAvailable: false` with a reason when Git is unavailable, the file is unchanged, binary, or outside the workspace.
- **`getGitFileDiff()` service** — new function in `gitStatus.ts` that handles path validation, Git availability checks, tracked file diffs (`git diff HEAD`), synthetic diffs for untracked files (whole file shown as added), binary detection, and deleted file support. Uses workspace path resolution consistent with file preview.
- **`parseUnifiedDiff()` parser** — new pure function that parses unified diff output (`git diff HEAD`) into structured hunks with tracked old/new line numbers. Handles file headers, hunk headers (including single-line and zero-count variants), added/removed/context lines, and binary detection.
- **`getLanguageForPath()` helper** — exported from `filePreview.ts` for reuse by the diff endpoint to include language detection in the response.
- **SDK types** — added `GitFileDiffResponse`, `GitDiffHunk`, `GitDiffChange`, and `GitFileDiffUnavailableReason` to `@jean2/sdk` shared types, plus `gitDiff()` REST method and `GitDiffFileResponse` response type.
- **`clearGitCache` browse parameter** — the browse endpoint (`GET /api/workspaces/:id/files`) now accepts `?clearGitCache=1` to clear the server-side Git status cache before fetching, ensuring fresh data on explicit user refresh. The SDK `browse()` method supports `clearGitCache` in `BrowseOptions`.
- **Server tests** — added 8 targeted tests for `parseUnifiedDiff` covering empty input, single/multiple hunks, line number tracking, single-line hunk headers, new-file patterns, file header ignoring, no-newline markers, and whitespace-only input.

### Changed

- **Reduced streaming persistence overhead** — assistant text and reasoning parts are no longer written to SQLite on every streamed delta. Streaming content is now kept live in memory and checkpointed to the database at a throttled interval, with a guaranteed final flush on completion, interruption, errors, and tool-call boundaries.
- **Deferred FTS work during active streams** — periodic streaming checkpoints now skip FTS synchronization. Search indexing still happens on final persisted state, avoiding repeated FTS rebuilds while the model is still generating.

### Fixed

- **Server responsiveness during fast streams** — mitigated event-loop stalls caused by per-token synchronous SQLite writes and repeated FTS updates in sessions where models stream quickly or produce many deltas.
- **Streaming durability at lifecycle boundaries** — pending text/reasoning content is flushed before stream completion, interruption handling, error handling, and tool execution transitions so persisted messages remain complete without requiring per-token writes.
- **Windows path handling in tool execution and file preview** — replaced `path.startsWith('/')` checks with `path.isAbsolute()` so Windows absolute paths (e.g., `C:\\Users\\...`) are correctly resolved instead of being incorrectly joined with the workspace path.
- **Server freezes during heavy shell commands** — replaced synchronous shell command execution with async `Bun.spawn()` and concurrent stdout/stderr reads so long-running builds and compilers no longer block the server event loop.
- **Shell command cancellation and timeouts** — tool executor timeouts and external aborts now propagate through `ctx.abortSignal`, allowing shell subprocesses to be killed instead of continuing in the background after interruption.
- **Visible console windows on Windows shell commands** — Windows shell execution now uses a hidden PowerShell `Start-Process` wrapper around `cmd.exe` with stdout/stderr redirection, preventing child build tools such as Node, Bun, Java, Gradle, or Maven from opening visible console windows while preserving command output.
