# SPEC.md Revisions - First-Time User Experience

> **Note:** The project was renamed from "gitlab-inbox" to "gitlore" and the CLI from "gi" to "lore". References to "gi" in this document should be read as "lore".

**Date:** 2026-01-21
**Purpose:** Document all changes adding installation, setup, and user flow documentation to SPEC.md

---

## Summary of Changes

| Change | Location | Description |
|--------|----------|-------------|
| 1. Quick Start | After Executive Summary | Prerequisites, installation, first-run walkthrough |
| 2. `gi init` Command | Checkpoint 0 | Interactive setup wizard with GitLab validation |
| 3. CLI Command Reference | Before Future Work | Unified table of all commands |
| 4. Error Handling | After CLI Reference | Common errors with recovery guidance |
| 5. Database Management | After Error Handling | Location, backup, reset, migrations |
| 6. Empty State Handling | Checkpoint 4 scope | Behavior when no data indexed |
| 7. Resolved Decisions | Resolved Decisions table | New decisions from this revision |

---

## Change 1: Quick Start Section

**Location:** Insert after line 6 (after Executive Summary), before Discovery Summary

```diff
 A self-hosted tool to extract, index, and semantically search 2+ years of GitLab data (issues, MRs, and discussion threads) from 2 main repositories (~50-100K documents including threaded discussions). The MVP delivers semantic search as a foundational capability that enables future specialized views (file history, personal tracking, person context). Discussion threads are preserved as first-class entities to maintain conversational context essential for decision traceability.

 ---

+## Quick Start
+
+### Prerequisites
+
+| Requirement | Version | Notes |
+|-------------|---------|-------|
+| Node.js | 20+ | LTS recommended |
+| npm | 10+ | Comes with Node.js |
+| Ollama | Latest | Optional for semantic search; lexical search works without it |
+
+### Installation
+
+```bash
+# Clone and install
+git clone https://github.com/your-org/gitlab-inbox.git
+cd gitlab-inbox
+npm install
+npm run build
+npm link  # Makes `gi` available globally
+```
+
+### First Run
+
+1. **Set your GitLab token** (create at GitLab > Settings > Access Tokens with `read_api` scope):
+   ```bash
+   export GITLAB_TOKEN="glpat-xxxxxxxxxxxxxxxxxxxx"
+   ```
+
+2. **Run the setup wizard:**
+   ```bash
+   gi init
+   ```
+   This creates `gi.config.json` with your GitLab URL and project paths.
+
+3. **Verify your environment:**
+   ```bash
+   gi doctor
+   ```
+   All checks should pass (Ollama warning is OK if you only need lexical search).
+
+4. **Sync your data:**
+   ```bash
+   gi sync
+   ```
+   Initial sync takes 10-20 minutes depending on repo size and rate limits.
+
+5. **Search:**
+   ```bash
+   gi search "authentication redesign"
+   ```
+
+### Troubleshooting First Run
+
+| Symptom | Solution |
+|---------|----------|
+| `Config file not found` | Run `gi init` first |
+| `GITLAB_TOKEN not set` | Export the environment variable |
+| `401 Unauthorized` | Check token has `read_api` scope |
+| `Project not found: group/project` | Verify project path in GitLab URL |
+| `Ollama connection refused` | Start Ollama or use `--mode=lexical` for search |
+
+---
+
 ## Discovery Summary
```

---

## Change 2: `gi init` Command in Checkpoint 0

**Location:** Insert in Checkpoint 0 Manual CLI Smoke Tests table and Scope section

### 2a: Add to Manual CLI Smoke Tests table (after line 193)

```diff
 | `GITLAB_TOKEN=invalid gi auth-test` | Error message | Non-zero exit code, clear error about auth failure |
+| `gi init` | Interactive prompts | Creates valid gi.config.json |
+| `gi init` (config exists) | Confirmation prompt | Warns before overwriting |
+| `gi --help` | Command list | Shows all available commands |
+| `gi version` | Version number | Shows installed version |
```

### 2b: Add Automated Tests for init (after line 185)

```diff
 tests/integration/app-lock.test.ts
   ✓ acquires lock successfully
   ✓ updates heartbeat during operation
   ✓ detects stale lock and recovers
   ✓ refuses concurrent acquisition
+
+tests/integration/init.test.ts
+  ✓ creates config file with valid structure
+  ✓ validates GitLab URL format
+  ✓ validates GitLab connection before writing config
+  ✓ validates each project path exists in GitLab
+  ✓ fails if token not set
+  ✓ fails if GitLab auth fails
+  ✓ fails if any project path not found
+  ✓ prompts before overwriting existing config
+  ✓ respects --force to skip confirmation
```

### 2c: Add to Checkpoint 0 Scope (after line 209)

```diff
 - Rate limit handling with exponential backoff + jitter
+- `gi init` command for guided setup:
+  - Prompts for GitLab base URL
+  - Prompts for project paths (comma-separated or multiple prompts)
+  - Prompts for token environment variable name (default: GITLAB_TOKEN)
+  - **Validates before writing config:**
+    - Token must be set in environment
+    - Tests auth with `GET /user` endpoint
+    - Validates each project path with `GET /projects/:path`
+    - Only writes config after all validations pass
+  - Generates `gi.config.json` with sensible defaults
+- `gi --help` shows all available commands
+- `gi <command> --help` shows command-specific help
+- `gi version` shows installed version
+- First-run detection: if no config exists, suggest `gi init`
```

---

## Change 3: CLI Command Reference Section

**Location:** Insert before "## Future Work (Post-MVP)" (before line 1174)

```diff
+## CLI Command Reference
+
+All commands support `--help` for detailed usage information.
+
+### Setup & Diagnostics
+
+| Command | CP | Description |
+|---------|-----|-------------|
+| `gi init` | 0 | Interactive setup wizard; creates gi.config.json |
+| `gi auth-test` | 0 | Verify GitLab authentication |
+| `gi doctor` | 0 | Check environment (GitLab, Ollama, DB) |
+| `gi doctor --json` | 0 | JSON output for scripting |
+| `gi version` | 0 | Show installed version |
+
+### Data Ingestion
+
+| Command | CP | Description |
+|---------|-----|-------------|
+| `gi ingest --type=issues` | 1 | Fetch issues from GitLab |
+| `gi ingest --type=merge_requests` | 2 | Fetch MRs and discussions |
+| `gi embed --all` | 3 | Generate embeddings for all documents |
+| `gi embed --retry-failed` | 3 | Retry failed embeddings |
+| `gi sync` | 5 | Full sync orchestration (ingest + docs + embed) |
+| `gi sync --full` | 5 | Force complete re-sync (reset cursors) |
+| `gi sync --force` | 5 | Override stale lock after operator review |
+| `gi sync --no-embed` | 5 | Sync without embedding (faster) |
+
+### Data Inspection
+
+| Command | CP | Description |
+|---------|-----|-------------|
+| `gi list issues [--limit=N] [--project=PATH]` | 1 | List issues |
+| `gi list mrs [--limit=N]` | 2 | List merge requests |
+| `gi count issues` | 1 | Count issues |
+| `gi count mrs` | 2 | Count merge requests |
+| `gi count discussions` | 2 | Count discussions |
+| `gi count notes` | 2 | Count notes |
+| `gi show issue <iid>` | 1 | Show issue details |
+| `gi show mr <iid>` | 2 | Show MR details with discussions |
+| `gi stats` | 3 | Embedding coverage statistics |
+| `gi stats --json` | 3 | JSON stats for scripting |
+| `gi sync-status` | 1 | Show cursor positions and last sync |
+
+### Search
+
+| Command | CP | Description |
+|---------|-----|-------------|
+| `gi search "query"` | 4 | Hybrid semantic + lexical search |
+| `gi search "query" --mode=lexical` | 3 | Lexical-only search (no Ollama required) |
+| `gi search "query" --type=issue\|mr\|discussion` | 4 | Filter by document type |
+| `gi search "query" --author=USERNAME` | 4 | Filter by author |
+| `gi search "query" --after=YYYY-MM-DD` | 4 | Filter by date |
+| `gi search "query" --label=NAME` | 4 | Filter by label (repeatable) |
+| `gi search "query" --project=PATH` | 4 | Filter by project |
+| `gi search "query" --path=FILE` | 4 | Filter by file path |
+| `gi search "query" --json` | 4 | JSON output for scripting |
+| `gi search "query" --explain` | 4 | Show ranking breakdown |
+
+### Database Management
+
+| Command | CP | Description |
+|---------|-----|-------------|
+| `gi backup` | 0 | Create timestamped database backup |
+| `gi reset --confirm` | 0 | Delete database and reset cursors |
+
+---
+
 ## Future Work (Post-MVP)
```

---

## Change 4: Error Handling Section

**Location:** Insert after CLI Command Reference, before Future Work

```diff
+## Error Handling
+
+Common errors and their resolutions:
+
+### Configuration Errors
+
+| Error | Cause | Resolution |
+|-------|-------|------------|
+| `Config file not found` | No gi.config.json | Run `gi init` to create configuration |
+| `Invalid config: missing baseUrl` | Malformed config | Re-run `gi init` or fix gi.config.json manually |
+| `Invalid config: no projects defined` | Empty projects array | Add at least one project path to config |
+
+### Authentication Errors
+
+| Error | Cause | Resolution |
+|-------|-------|------------|
+| `GITLAB_TOKEN environment variable not set` | Token not exported | `export GITLAB_TOKEN="glpat-xxx"` |
+| `401 Unauthorized` | Invalid or expired token | Generate new token with `read_api` scope |
+| `403 Forbidden` | Token lacks permissions | Ensure token has `read_api` scope |
+
+### GitLab API Errors
+
+| Error | Cause | Resolution |
+|-------|-------|------------|
+| `Project not found: group/project` | Invalid project path | Verify path matches GitLab URL (case-sensitive) |
+| `429 Too Many Requests` | Rate limited | Wait for Retry-After period; sync will auto-retry |
+| `Connection refused` | GitLab unreachable | Check GitLab URL and network connectivity |
+
+### Data Errors
+
+| Error | Cause | Resolution |
+|-------|-------|------------|
+| `No documents indexed` | Sync not run | Run `gi sync` first |
+| `No results found` | Query too specific | Try broader search terms |
+| `Database locked` | Concurrent access | Wait for other process; use `gi sync --force` if stale |
+
+### Embedding Errors
+
+| Error | Cause | Resolution |
+|-------|-------|------------|
+| `Ollama connection refused` | Ollama not running | Start Ollama or use `--mode=lexical` |
+| `Model not found: nomic-embed-text` | Model not pulled | Run `ollama pull nomic-embed-text` |
+| `Embedding failed for N documents` | Transient failures | Run `gi embed --retry-failed` |
+
+### Operational Behavior
+
+| Scenario | Behavior |
+|----------|----------|
+| **Ctrl+C during sync** | Graceful shutdown: finishes current page, commits cursor, exits cleanly. Resume with `gi sync`. |
+| **Disk full during write** | Fails with clear error. Cursor preserved at last successful commit. Free space and resume. |
+| **Stale lock detected** | Lock held > 10 minutes without heartbeat is considered stale. Next sync auto-recovers. |
+| **Network interruption** | Retries with exponential backoff. After max retries, sync fails but cursor is preserved. |
+
+---
+
 ## Future Work (Post-MVP)
```

---

## Change 5: Database Management Section

**Location:** Insert after Error Handling, before Future Work

```diff
+## Database Management
+
+### Database Location
+
+The SQLite database is stored at an XDG-compliant location:
+
+```
+~/.local/share/gi/data.db
+```
+
+This can be overridden in `gi.config.json`:
+
+```json
+{
+  "storage": {
+    "dbPath": "/custom/path/to/data.db"
+  }
+}
+```
+
+### Backup
+
+Create a timestamped backup of the database:
+
+```bash
+gi backup
+# Creates: ~/.local/share/gi/backups/data-2026-01-21T14-30-00.db
+```
+
+Backups are SQLite `.backup` command copies (safe even during active writes due to WAL mode).
+
+### Reset
+
+To completely reset the database and all sync cursors:
+
+```bash
+gi reset --confirm
+```
+
+This deletes:
+- The database file
+- All sync cursors
+- All embeddings
+
+You'll need to run `gi sync` again to repopulate.
+
+### Schema Migrations
+
+Database schema is version-tracked and migrations auto-apply on startup:
+
+1. On first run, schema is created at latest version
+2. On subsequent runs, pending migrations are applied automatically
+3. Migration version is stored in `schema_version` table
+4. Migrations are idempotent and reversible where possible
+
+**Manual migration check:**
+```bash
+gi doctor --json | jq '.checks.database'
+# Shows: { "status": "ok", "schemaVersion": 5, "pendingMigrations": 0 }
+```
+
+---
+
 ## Future Work (Post-MVP)
```

---

## Change 6: Empty State Handling in Checkpoint 4

**Location:** Add to Checkpoint 4 scope section (around line 885, after "Graceful degradation")

```diff
 - Graceful degradation: if Ollama is unreachable, fall back to FTS5-only search with warning
+- Empty state handling:
+  - No documents indexed: `No data indexed. Run 'gi sync' first.`
+  - Query returns no results: `No results found for "query".`
+  - Filters exclude all results: `No results match the specified filters.`
+  - Helpful hints shown in non-JSON mode (e.g., "Try broadening your search")
```

**Location:** Add to Manual CLI Smoke Tests table (after `gi search "xyznonexistent123"` row)

```diff
 | `gi search "xyznonexistent123"` | No results message | Graceful empty state |
+| `gi search "auth"` (no data synced) | No data message | Shows "Run gi sync first" |
```

---

## Change 7: Update Resolved Decisions Table

**Location:** Add new rows to Resolved Decisions table (around line 1280)

```diff
 | JSON output | **Stable documented schema** | Enables reliable agent/MCP consumption |
+| Database location | **XDG compliant: `~/.local/share/gi/`** | Standard location, user-configurable |
+| `gi init` validation | **Validate GitLab before writing config** | Fail fast, better UX |
+| Ctrl+C handling | **Graceful shutdown** | Finish page, commit cursor, exit cleanly |
+| Empty state UX | **Actionable messages** | Guide user to next step |
```

---

## Files Modified

| File | Action |
|------|--------|
| `SPEC.md` | 7 changes applied |
| `SPEC-REVISIONS-3.md` | Created (this file) |

---

## Verification Checklist

After applying changes:

- [ ] Quick Start section provides clear 5-step onboarding
- [ ] `gi init` fully specified with validation behavior
- [ ] All CLI commands documented in reference table
- [ ] Error scenarios have recovery guidance
- [ ] Database location and management documented
- [ ] Empty states have helpful messages
- [ ] Resolved Decisions updated with new choices
- [ ] No orphaned command references
