### Added

- **Workspace additional paths** — workspaces now support `additionalPaths`: extra directories the agent has full access to without permission prompts. Paths are stored in a new `workspace_paths` DB table (`workspace_id`, `path`, `label`), threaded through the agent execution pipeline, and included in the system prompt so the LLM knows to use absolute paths for them.
- **`PATCH /api/workspaces/:id` extended** — now accepts `{ name?, additionalPaths? }`. Paths are validated to exist on disk before saving.
- **Path security updated** — `isPathWithinWorkspace`, `createPathHelpers`, and `getFilePreview` all check against the primary workspace path plus any additional paths.
- **Response format CRUD API** — new REST endpoints `GET/POST/PUT/DELETE /api/response-formats` with full create, read, update, delete support. Formats are stored in SQLite with JSON Schema definitions. Built-in formats no longer have delete protection — all formats are freely editable and deletable.
- **Structured output in messages** — when a response format is selected, the LLM's structured output is parsed from the stream result and attached to the final assistant message as `structuredOutput` (with `formatName`, `data`, `schema`). Stored in the `structured_output` column on the messages table.
- **Pinned assistant messages** — added persistent workspace-scoped pinned messages with a new `pinned_messages` SQLite table, FK cascade cleanup, uniqueness by workspace/message, and validation that only assistant messages can be pinned.
- **Pinned messages REST API** — added workspace endpoints to list, pin, and unpin pinned messages. Pinning is idempotent and list responses include session title, message timestamp, and preview text for sidebar rendering.

### Fixed
- **Newly created skills not discoverable** — the skills registry cached scan results permanently in memory with no TTL or invalidation. When the LLM created a new `.agents/skills/<name>/SKILL.md`, it remained invisible until server restart. Removed the cache entirely — skills are now scanned fresh from disk on each chat turn (a trivially cheap operation of one `readdir` + one `readFile` per skill folder).
- **Truncated tool results saved to malformed temp paths** — `truncateToolResult()` used `path.join(tmpdir(), 'jean2', '')` which produces a path without trailing separator, then string-concatenated the session ID directly, yielding paths like `/tmp/jean2abc123-...` instead of `/tmp/jean2/abc123-...`. The missing `/` meant `read-file` couldn't recognize the path as jean2-managed temp and unnecessarily prompted for permission. Now uses `path.join()` for both segments.

### Changed
- **Removed built-in format protection** — the DELETE endpoint no longer rejects `builtin-` prefixed IDs. All formats are treated equally.

## Workspace Memory

- **Added workspace memory** — new `packages/server/src/memory/` module with registry (file I/O for `.jean2/USER.md` and `.jean2/MEMORY.md`) and a built-in `memory` tool. The agent can persist compact user preferences and workspace facts across sessions via bullet-point markdown files in the workspace.
- **Added workspace settings** — new `settings` JSON column on the `workspaces` table with auto-migration for existing databases. `Workspace` SDK type now includes a `settings: WorkspaceSettings` field with `memory: { enabled, permissionRisk }` configuration.
- **Extended `PATCH /api/workspaces/:id`** — now accepts `{ settings }` with full validation: `memory.enabled` must be boolean, `memory.permissionRisk` must be a valid level (`none`, `low`, `medium`, `high`, `critical`).
- **Memory prompt injection** — when memory is enabled, `.jean2/USER.md` and `.jean2/MEMORY.md` are loaded and injected into the system prompt as `<user_memory>` and `<workspace_memory>` XML sections with usage counters (e.g., `usage="420/1500"`). Includes guidance text describing how to use the memory tool.
- **Memory tool** — built-in dynamic tool registered in `buildAiSdkTools()` only when the workspace has memory enabled. Supports `add`, `replace`, `remove` actions on `user` and `memory` targets. Enforces char limits (USER.md: 1500, MEMORY.md: 2500), rejects duplicates, requires unique matches for replace/remove. Permission level is configurable per-workspace.
- **Added SDK types** — `WorkspaceSettings`, `WorkspaceMemorySettings` exported from `@jean2/sdk`. SDK REST client `workspaces.update()` now accepts `settings` parameter.
