430 lines
14 KiB
Markdown
430 lines
14 KiB
Markdown
# 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
|