# Plan: `lore init --refresh`

**Created:** 2026-03-02
**Status:** Complete

## Problem

When new repos are added to the config file, `lore sync` doesn't pick them up because project discovery only happens during `lore init`. Currently, users must use `--force` to overwrite their config, which is awkward.

## Solution

Add `--refresh` flag to `lore init` that reads the existing config and updates the database to match, without overwriting the config file.

---

## Implementation Plan

### 1. CLI Changes (`src/cli/mod.rs`)

Add to init subcommand:
- `--refresh` flag (conflicts with `--force`)
- Ensure `--robot` / `-J` propagates to init

### 2. Update `InitOptions` struct

```rust
pub struct InitOptions {
    pub config_path: Option<String>,
    pub force: bool,
    pub non_interactive: bool,
    pub refresh: bool,       // NEW
    pub robot_mode: bool,    // NEW
}
```

### 3. New `RefreshResult` struct

```rust
pub struct RefreshResult {
    pub user: UserInfo,
    pub projects_registered: Vec<ProjectInfo>,
    pub projects_failed: Vec<ProjectFailure>,  // path + error message
    pub orphans_found: Vec<String>,            // paths in DB but not config
    pub orphans_deleted: Vec<String>,          // if user said yes
}

pub struct ProjectFailure {
    pub path: String,
    pub error: String,
}
```

### 4. Main logic: `run_init_refresh()` (new function)

```
1. Load config via Config::load()
2. Resolve token, call get_current_user() → validate auth
3. For each project in config.projects:
   - Call client.get_project(path)
   - On success: collect for DB upsert
   - On failure: collect in projects_failed
4. Query DB for all existing projects
5. Compute orphans = DB projects - config projects
6. If orphans exist:
   - Robot mode: include in output, no prompt, no delete
   - Interactive: prompt "Delete N orphan projects? [y/N]"
     - Default N → skip deletion
     - Y → delete from DB
7. Upsert validated projects into DB
8. Return RefreshResult
```

### 5. Improve existing init error message

In `run_init()`, when config exists and neither `--refresh` nor `--force`:

**Current:**
> Config file exists at ~/.config/lore/config.json. Use --force to overwrite.

**New:**
> Config already exists at ~/.config/lore/config.json.
> - Use `--refresh` to register new projects from config
> - Use `--force` to overwrite the config file

### 6. Robot mode output

```json
{
  "ok": true,
  "data": {
    "mode": "refresh",
    "user": { "username": "...", "name": "..." },
    "projects_registered": [...],
    "projects_failed": [...],
    "orphans_found": ["old/project"],
    "orphans_deleted": []
  },
  "meta": { "elapsed_ms": 123 }
}
```

### 7. Human output

```
  ✓ Authenticated as @username (Full Name)

  Projects
    ✓ group/project-a          registered
    ✓ group/project-b          registered
    ✗ group/nonexistent        not found

  Orphans
    • old/removed-project

  Delete 1 orphan project from database? [y/N]: n

  Registered 2 projects (1 failed, 1 orphan kept)
```

---

## Files to Touch

1. **`src/cli/mod.rs`** — add `--refresh` and `--robot` to init subcommand args
2. **`src/cli/commands/init.rs`** — add `RefreshResult`, `run_init_refresh()`, update error message
3. **`src/main.rs`** (or CLI dispatch) — route `--refresh` to new function

---

## Acceptance Criteria

- [x] `lore init --refresh` reads existing config and registers projects
- [x] Validates GitLab auth before processing
- [x] Orphan projects prompt with default N (interactive mode)
- [x] Robot mode outputs JSON, no prompts, includes orphans in output
- [x] Existing `lore init` (no flags) suggests `--refresh` when config exists
- [x] `--refresh` and `--force` are mutually exclusive
