# Appendices --- ## A. Robot Output Envelope All robot-mode responses follow this structure: ```json { "ok": true, "data": { /* command-specific */ }, "meta": { "elapsed_ms": 42 } } ``` Errors (to stderr): ```json { "error": { "code": "CONFIG_NOT_FOUND", "message": "Configuration file not found", "suggestion": "Run 'lore init'", "actions": ["lore init"] } } ``` The `actions` array contains copy-paste shell commands for automated recovery. Omitted when empty. --- ## B. Exit Codes | Code | Meaning | Retryable | |---|---|---| | 0 | Success | N/A | | 1 | Internal error / not implemented | Maybe | | 2 | Usage error (invalid flags or arguments) | No (fix syntax) | | 3 | Config invalid | No (fix config) | | 4 | Token not set | No (set token) | | 5 | GitLab auth failed | Maybe (token expired?) | | 6 | Resource not found (HTTP 404) | No | | 7 | Rate limited | Yes (wait) | | 8 | Network error | Yes (retry) | | 9 | Database locked | Yes (wait) | | 10 | Database error | Maybe | | 11 | Migration failed | No (investigate) | | 12 | I/O error | Maybe | | 13 | Transform error | No (bug) | | 14 | Ollama unavailable | Yes (start Ollama) | | 15 | Ollama model not found | No (pull model) | | 16 | Embedding failed | Yes (retry) | | 17 | Not found (entity does not exist) | No | | 18 | Ambiguous match (use `-p` to specify project) | No (be specific) | | 19 | Health check failed | Yes (fix issues first) | | 20 | Config not found | No (run init) | --- ## C. Field Selection Presets The `--fields` flag supports both presets and custom field lists: ```bash lore -J issues --fields minimal # Preset lore -J mrs --fields iid,title,state,draft # Custom comma-separated ``` | Command | Minimal Preset Fields | |---|---| | `issues` (list) | `iid`, `title`, `state`, `updated_at_iso` | | `mrs` (list) | `iid`, `title`, `state`, `updated_at_iso` | | `notes` (list) | `id`, `author_username`, `body`, `created_at_iso` | | `search` | `document_id`, `title`, `source_type`, `score` | | `timeline` | `timestamp`, `type`, `entity_iid`, `detail` | | `who expert` | `username`, `score` | | `who workload` | `iid`, `title`, `state` | | `who reviews` | `name`, `count`, `percentage` | | `who active` | `entity_type`, `iid`, `title`, `participants` | | `who overlap` | `username`, `touch_count` | | `me` (items) | `iid`, `title`, `attention_state`, `updated_at_iso` | | `me` (activity) | `timestamp_iso`, `event_type`, `entity_iid`, `actor` | --- ## D. Configuration Precedence 1. CLI flags (highest priority) 2. Environment variables (`LORE_ROBOT`, `GITLAB_TOKEN`, `LORE_CONFIG_PATH`) 3. Config file (`~/.config/lore/config.json`) 4. Built-in defaults (lowest priority) --- ## E. Time Parsing All commands accepting `--since`, `--until`, `--as-of` support: | Format | Example | Meaning | |---|---|---| | Relative days | `7d` | 7 days ago | | Relative weeks | `2w` | 2 weeks ago | | Relative months | `1m`, `6m` | 1/6 months ago | | Absolute date | `2026-01-15` | Specific date | Internally converted to Unix milliseconds for DB queries. --- ## F. Database Schema (28 migrations) ### Primary Entity Tables | Table | Key Columns | Notes | |---|---|---| | `projects` | `gitlab_project_id`, `path_with_namespace`, `web_url` | No `name` or `last_seen_at` | | `issues` | `iid`, `title`, `state`, `author_username`, 5 status columns | Status columns nullable (migration 021) | | `merge_requests` | `iid`, `title`, `state`, `draft`, `source_branch`, `target_branch` | `last_seen_at INTEGER NOT NULL` | | `discussions` | `gitlab_discussion_id` (text), `issue_id`/`merge_request_id` | One FK must be set | | `notes` | `gitlab_id`, `author_username`, `body`, DiffNote position columns | `type` column for DiffNote/DiscussionNote | ### Relationship Tables | Table | Purpose | |---|---| | `issue_labels`, `mr_labels` | Label junction (DELETE+INSERT for stale removal) | | `issue_assignees`, `mr_assignees` | Assignee junction | | `mr_reviewers` | Reviewer junction | | `entity_references` | Cross-refs: closes, mentioned, related (with `source_method`) | | `mr_file_changes` | File diffs: old_path, new_path, change_type | ### Event Tables | Table | Constraint | |---|---| | `resource_state_events` | CHECK: exactly one of issue_id/merge_request_id NOT NULL | | `resource_label_events` | Same CHECK constraint; `label_name` nullable (migration 012) | | `resource_milestone_events` | Same CHECK constraint; `milestone_title` nullable | ### Document/Search Pipeline | Table | Purpose | |---|---| | `documents` | Unified searchable content (source_type: issue/merge_request/discussion) | | `documents_fts` | FTS5 virtual table for text search | | `documents_fts_docsize` | FTS5 shadow B-tree (19x faster for COUNT) | | `document_labels` | Fast label filtering (indexed exact-match) | | `document_paths` | File path association for DiffNote filtering | | `embeddings` | vec0 virtual table; rowid = document_id * 1000 + chunk_index | | `embedding_metadata` | Chunk provenance + staleness tracking (document_hash) | | `dirty_sources` | Documents needing regeneration (with backoff via next_attempt_at) | ### Infrastructure | Table | Purpose | |---|---| | `sync_runs` | Sync history with metrics | | `sync_cursors` | Per-resource sync position (updated_at cursor + tie_breaker_id) | | `app_locks` | Crash-safe single-flight lock | | `raw_payloads` | Raw JSON storage for debugging | | `pending_discussion_fetches` | Dependent discussion fetch queue | | `pending_dependent_fetches` | Job queue for resource_events, mr_closes, mr_diffs | | `schema_version` | Migration tracking | --- ## G. Glossary | Term | Definition | |---|---| | **IID** | Issue/MR number within a project (not globally unique) | | **FTS5** | SQLite full-text search extension (BM25 ranking) | | **vec0** | SQLite extension for vector similarity search | | **RRF** | Reciprocal Rank Fusion — combines FTS and vector rankings | | **DiffNote** | Comment attached to a specific line in a merge request diff | | **Entity reference** | Cross-reference between issues/MRs (closes, mentioned, related) | | **Rename chain** | BFS traversal of mr_file_changes to follow file renames | | **Attention state** | Computed field on `me` items: needs_attention, not_started, stale, etc. | | **Surgical sync** | Fetching specific entities by IID instead of full incremental sync |