--- plan: true title: "GitLab TODOs Integration" status: proposed iteration: 1 target_iterations: 3 beads_revision: 1 related_plans: [] created: 2026-02-23 updated: 2026-02-23 --- # GitLab TODOs Integration ## Summary Add GitLab TODO support to lore. Todos are fetched during sync, stored locally, and surfaced through: 1. A new `--todos` section in `lore me` 2. Enrichment of the activity feed in `lore me` 3. A standalone `lore todos` command **Scope:** Read-only. No mark-as-done operations. --- ## Design Decisions (from interview) | Decision | Choice | |----------|--------| | Write operations | **Read-only** — no mark-as-done | | Storage | **Persist locally** in SQLite | | Integration | Three-way: activity enrichment + `--todos` flag + `lore todos` | | Action types | Core only: assigned, mentioned, directly_addressed, approval_required, build_failed, unmergeable | | Niche actions | Skip display (but store): merge_train_removed, member_access_requested, marked | | Project filter | **Always account-wide** — `--project` does NOT filter todos | | Sync timing | During normal `lore sync` | | Non-synced projects | Include with `[external]` indicator | | Attention state | **Separate signal** — todos don't boost attention | | Summary header | Include pending todo count | | Grouping | By action type: Assignments \| Mentions \| Approvals \| Build Issues | | History | **Pending only** — done todos not tracked | | `lore todos` filters | **None** — show all pending, simple | | Robot mode | Yes, standard envelope | | Target types | All GitLab supports (Issue, MR, Epic, Commit, etc.) | --- ## Out of Scope - Write operations (mark as done) - Done todo history tracking - Filters on `lore todos` command - Todo-based attention state boosting - Notification settings API integration (deferred to separate plan) --- ## Acceptance Criteria ### AC-1: Database Schema - [ ] **AC-1.1:** Create `todos` table with columns: - `id` INTEGER PRIMARY KEY - `gitlab_todo_id` INTEGER NOT NULL UNIQUE - `project_id` INTEGER REFERENCES projects(id) ON DELETE SET NULL (nullable for non-synced) - `target_type` TEXT NOT NULL (Issue, MergeRequest, Commit, Epic, etc.) - `target_id` INTEGER (GitLab ID of target entity) - `target_iid` INTEGER (IID for issues/MRs, nullable) - `target_url` TEXT NOT NULL - `target_title` TEXT - `action_name` TEXT NOT NULL (assigned, mentioned, etc.) - `author_id` INTEGER - `author_username` TEXT - `body` TEXT (the todo message/snippet) - `state` TEXT NOT NULL (pending) - `created_at` INTEGER NOT NULL (epoch ms) - `updated_at` INTEGER NOT NULL (epoch ms) - `synced_at` INTEGER NOT NULL (epoch ms) - `project_path` TEXT (for display even if project not synced) - [ ] **AC-1.2:** Create index `idx_todos_state_action` on `(state, action_name)` - [ ] **AC-1.3:** Create index `idx_todos_target` on `(target_type, target_id)` - [ ] **AC-1.4:** Create index `idx_todos_created` on `(created_at DESC)` - [ ] **AC-1.5:** Migration increments schema version ### AC-2: GitLab API Client - [ ] **AC-2.1:** Add `fetch_todos()` method to GitLab client - [ ] **AC-2.2:** Fetch only `state=pending` todos - [ ] **AC-2.3:** Handle pagination (use existing pagination pattern) - [ ] **AC-2.4:** Parse all target types GitLab returns - [ ] **AC-2.5:** Extract project path from `target_url` for non-synced projects ### AC-3: Sync Pipeline - [ ] **AC-3.1:** Add todos sync step to `lore sync` pipeline - [ ] **AC-3.2:** Sync todos AFTER issues/MRs (ordering consistency) - [ ] **AC-3.3:** Snapshot semantics: fetch all pending, upsert, delete missing (= marked done elsewhere) - [ ] **AC-3.4:** Track `synced_at` timestamp - [ ] **AC-3.5:** Log todo sync stats: fetched, inserted, updated, deleted - [ ] **AC-3.6:** Add `--no-todos` flag to skip todo sync ### AC-4: Action Type Handling - [ ] **AC-4.1:** Store ALL action types from GitLab - [ ] **AC-4.2:** Display only core actions: - `assigned` — assigned to issue/MR - `mentioned` — @mentioned in comment - `directly_addressed` — @mentioned at start of comment - `approval_required` — approval needed on MR - `build_failed` — CI failed on your MR - `unmergeable` — merge conflicts on your MR - [ ] **AC-4.3:** Skip display (but store) niche actions: `merge_train_removed`, `member_access_requested`, `marked` ### AC-5: `lore todos` Command - [ ] **AC-5.1:** New subcommand `lore todos` (alias: `todo`) - [ ] **AC-5.2:** Display all pending todos, no filters - [ ] **AC-5.3:** Group by action type: Assignments | Mentions | Approvals | Build Issues - [ ] **AC-5.4:** Per-todo display: target title, project path, author, age, action - [ ] **AC-5.5:** Flag non-synced project todos with `[external]` indicator - [ ] **AC-5.6:** Human-readable output with colors/icons - [ ] **AC-5.7:** Robot mode: standard `{ok, data, meta}` envelope ### AC-6: `lore me --todos` Section - [ ] **AC-6.1:** Add `--todos` flag to `MeArgs` - [ ] **AC-6.2:** When no section flags: show todos in full dashboard - [ ] **AC-6.3:** When `--todos` flag only: show only todos section - [ ] **AC-6.4:** Todos section grouped by action type - [ ] **AC-6.5:** Todos NOT filtered by `--project` (always account-wide) - [ ] **AC-6.6:** Robot mode includes `todos` array in dashboard response ### AC-7: `lore me` Summary Header - [ ] **AC-7.1:** Add `pending_todo_count` to `MeSummary` struct - [ ] **AC-7.2:** Display todo count in summary line (human mode) - [ ] **AC-7.3:** Include `pending_todo_count` in robot mode summary ### AC-8: Activity Feed Enrichment - [ ] **AC-8.1:** Todos with local issue/MR target appear in activity feed - [ ] **AC-8.2:** New `ActivityEventType::Todo` variant - [ ] **AC-8.3:** Todo events show: action type, author, target in summary - [ ] **AC-8.4:** Sorted chronologically with other activity events - [ ] **AC-8.5:** Respect `--since` filter on todo `created_at` ### AC-9: Non-Synced Project Handling - [ ] **AC-9.1:** Store todos even if target project not in config - [ ] **AC-9.2:** Display `[external]` indicator for non-synced project todos - [ ] **AC-9.3:** Show project path (extracted from target URL) - [ ] **AC-9.4:** Graceful fallback when target title unavailable ### AC-10: Attention State - [ ] **AC-10.1:** Attention state calculation remains note-based (unchanged) - [ ] **AC-10.2:** Todos are separate signal, do not affect attention state - [ ] **AC-10.3:** Document this design decision in code comments ### AC-11: Robot Mode Schema - [ ] **AC-11.1:** `lore todos --robot` returns: ```json { "ok": true, "data": { "todos": [{ "id": 123, "gitlab_todo_id": 456, "action": "mentioned", "target_type": "Issue", "target_iid": 42, "target_title": "Fix login bug", "target_url": "https://...", "project_path": "group/repo", "author_username": "jdoe", "body": "Hey @you, can you look at this?", "created_at_iso": "2026-02-20T10:00:00Z", "is_external": false }], "counts": { "total": 8, "assigned": 2, "mentioned": 5, "approval_required": 1, "build_failed": 0, "unmergeable": 0 } }, "meta": {"elapsed_ms": 42} } ``` - [ ] **AC-11.2:** `lore me --robot` includes `todos` and `pending_todo_count` in response - [ ] **AC-11.3:** Support `--fields minimal` for token efficiency ### AC-12: Documentation - [ ] **AC-12.1:** Update CLAUDE.md with `lore todos` command reference - [ ] **AC-12.2:** Update `lore robot-docs` manifest with todos schema - [ ] **AC-12.3:** Add todos to CLI help output ### AC-13: Quality Gates - [ ] **AC-13.1:** `cargo check --all-targets` passes - [ ] **AC-13.2:** `cargo clippy --all-targets -- -D warnings` passes - [ ] **AC-13.3:** `cargo fmt --check` passes - [ ] **AC-13.4:** `cargo test` passes with new tests --- ## Technical Notes ### GitLab API Endpoint ``` GET /api/v4/todos?state=pending ``` Response fields: id, project, author, action_name, target_type, target, target_url, body, state, created_at, updated_at ### Sync Deletion Strategy Snapshot semantics: a todo disappearing from API response means it was marked done elsewhere. Delete from local DB to stay in sync. ### Project Path Extraction For non-synced projects, extract path from `target_url`: ``` https://gitlab.com/group/subgroup/repo/-/issues/42 ^^^^^^^^^^^^^^^^^ extract this ``` ### Action Type Grouping | Group | Actions | |-------|---------| | Assignments | `assigned` | | Mentions | `mentioned`, `directly_addressed` | | Approvals | `approval_required` | | Build Issues | `build_failed`, `unmergeable` | --- ## Rollout Slices ### Slice A: Schema + Client - Migration 028 - `GitLabTodo` type - `fetch_todos()` client method - Unit tests for deserialization ### Slice B: Sync Integration - `src/ingestion/todos.rs` - Integrate into `lore sync` - `--no-todos` flag - Sync stats ### Slice C: `lore todos` Command - CLI args + dispatch - Human + robot rendering - Autocorrect aliases ### Slice D: `lore me` Integration - `--todos` flag - Summary count - Activity feed enrichment ### Slice E: Polish - Edge case tests - Documentation updates - `robot-docs` manifest --- ## References - [GitLab To-Do List API](https://docs.gitlab.com/api/todos/) - [GitLab User Todos](https://docs.gitlab.com/user/todos/)