#[derive(Serialize)]
struct RobotDocsOutput {
    ok: bool,
    data: RobotDocsData,
}

#[derive(Serialize)]
struct RobotDocsData {
    name: String,
    version: String,
    description: String,
    activation: RobotDocsActivation,
    quick_start: serde_json::Value,
    commands: serde_json::Value,
    /// Deprecated command aliases (old -> new)
    aliases: serde_json::Value,
    /// Pre-clap error tolerance: what the CLI auto-corrects
    error_tolerance: serde_json::Value,
    exit_codes: serde_json::Value,
    /// Error codes emitted by clap parse failures
    clap_error_codes: serde_json::Value,
    error_format: String,
    workflows: serde_json::Value,
    config_notes: serde_json::Value,
}

#[derive(Serialize)]
struct RobotDocsActivation {
    flags: Vec<String>,
    env: String,
    auto: String,
}

fn handle_robot_docs(robot_mode: bool, brief: bool) -> Result<(), Box<dyn std::error::Error>> {
    let version = env!("CARGO_PKG_VERSION").to_string();

    let commands = serde_json::json!({
        "init": {
            "description": "Initialize configuration and database",
            "flags": ["--force", "--non-interactive", "--gitlab-url <URL>", "--token-env-var <VAR>", "--projects <paths>", "--default-project <path>"],
            "robot_flags": ["--gitlab-url", "--token-env-var", "--projects", "--default-project"],
            "example": "lore --robot init --gitlab-url https://gitlab.com --token-env-var GITLAB_TOKEN --projects group/project,other/repo --default-project group/project",
            "response_schema": {
                "ok": "bool",
                "data": {"config_path": "string", "data_dir": "string", "user": {"username": "string", "name": "string"}, "projects": "[{path:string, name:string}]", "default_project": "string?"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "health": {
            "description": "Quick pre-flight check: config, database, schema version",
            "flags": [],
            "example": "lore --robot health",
            "response_schema": {
                "ok": "bool",
                "data": {"healthy": "bool", "config_found": "bool", "db_found": "bool", "schema_current": "bool", "schema_version": "int"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "auth": {
            "description": "Verify GitLab authentication",
            "flags": [],
            "example": "lore --robot auth",
            "response_schema": {
                "ok": "bool",
                "data": {"authenticated": "bool", "username": "string", "name": "string", "gitlab_url": "string"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "doctor": {
            "description": "Full environment health check (config, auth, DB, Ollama)",
            "flags": [],
            "example": "lore --robot doctor",
            "response_schema": {
                "ok": "bool",
                "data": {"success": "bool", "checks": "{config:object, auth:object, database:object, ollama:object}"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "ingest": {
            "description": "Sync data from GitLab",
            "flags": ["--project <path>", "--force", "--no-force", "--full", "--no-full", "--dry-run", "--no-dry-run", "<entity: issues|mrs>"],
            "example": "lore --robot ingest issues --project group/repo",
            "response_schema": {
                "ok": "bool",
                "data": {"resource_type": "string", "projects_synced": "int", "issues_fetched?": "int", "mrs_fetched?": "int", "upserted": "int", "labels_created": "int", "discussions_fetched": "int", "notes_upserted": "int"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "sync": {
            "description": "Full sync pipeline: ingest -> generate-docs -> embed. Supports surgical per-IID mode.",
            "flags": ["--full", "--no-full", "--force", "--no-force", "--no-embed", "--no-docs", "--no-events", "--no-file-changes", "--no-status", "--dry-run", "--no-dry-run", "-t/--timings", "--lock", "--issue <IID>", "--mr <IID>", "-p/--project <path>", "--preflight-only"],
            "example": "lore --robot sync",
            "surgical_mode": {
                "description": "Sync specific issues or MRs by IID. Runs a scoped pipeline: preflight -> TOCTOU check -> ingest -> dependents -> docs -> embed.",
                "flags": ["--issue <IID> (repeatable)", "--mr <IID> (repeatable)", "-p/--project <path> (required)", "--preflight-only"],
                "examples": [
                    "lore --robot sync --issue 7 -p group/project",
                    "lore --robot sync --issue 7 --issue 42 --mr 10 -p group/project",
                    "lore --robot sync --issue 7 -p group/project --preflight-only"
                ],
                "constraints": ["--issue/--mr requires -p/--project (or defaultProject in config)", "--full and --issue/--mr are incompatible", "--preflight-only requires --issue or --mr", "Max 100 total targets"],
                "entity_result_outcomes": ["synced", "skipped_stale", "not_found", "preflight_failed", "error"]
            },
            "response_schema": {
                "normal": {
                    "ok": "bool",
                    "data": {"issues_updated": "int", "mrs_updated": "int", "documents_regenerated": "int", "documents_embedded": "int", "resource_events_synced": "int", "resource_events_failed": "int"},
                    "meta": {"elapsed_ms": "int", "stages?": "[{name:string, elapsed_ms:int, items_processed:int}]"}
                },
                "surgical": {
                    "ok": "bool",
                    "data": {"surgical_mode": "true", "surgical_iids": "{issues:[int], merge_requests:[int]}", "entity_results": "[{entity_type:string, iid:int, outcome:string, error?:string, toctou_reason?:string}]", "preflight_only?": "bool", "issues_updated": "int", "mrs_updated": "int", "documents_regenerated": "int", "documents_embedded": "int", "discussions_fetched": "int"},
                    "meta": {"elapsed_ms": "int"}
                }
            }
        },
        "issues": {
            "description": "List issues, or view detail with <IID>",
            "flags": ["<IID>", "-n/--limit", "--fields <list>", "-s/--state", "--status <name>", "-p/--project", "-a/--author", "-A/--assignee", "-l/--label", "-m/--milestone", "--since", "--due-before", "--has-due", "--no-has-due", "--sort", "--asc", "--no-asc", "-o/--open", "--no-open"],
            "example": "lore --robot issues --state opened --limit 10",
            "notes": {
                "status_filter": "--status filters by work item status NAME (case-insensitive). Valid values are in meta.available_statuses of any issues list response.",
                "status_name": "status_name is the board column label (e.g. 'In review', 'Blocked'). This is the canonical status identifier for filtering."
            },
            "response_schema": {
                "list": {
                    "ok": "bool",
                    "data": {"issues": "[{iid:int, title:string, state:string, author_username:string, labels:[string], assignees:[string], discussion_count:int, unresolved_count:int, created_at_iso:string, updated_at_iso:string, web_url:string?, project_path:string, status_name:string?}]", "total_count": "int", "showing": "int"},
                    "meta": {"elapsed_ms": "int", "available_statuses": "[string] — all distinct status names in the database, for use with --status filter"}
                },
                "detail": {
                    "ok": "bool",
                    "data": "IssueDetail (full entity with description, discussions, notes, events)",
                    "meta": {"elapsed_ms": "int"}
                }
            },
            "example_output": {"list": {"ok":true,"data":{"issues":[{"iid":3864,"title":"Switch Health Card","state":"opened","status_name":"In progress","labels":["customer:BNSF"],"assignees":["teernisse"],"discussion_count":12,"updated_at_iso":"2026-02-12T..."}],"total_count":1,"showing":1},"meta":{"elapsed_ms":42}}},
            "fields_presets": {"minimal": ["iid", "title", "state", "updated_at_iso"]}
        },
        "mrs": {
            "description": "List merge requests, or view detail with <IID>",
            "flags": ["<IID>", "-n/--limit", "--fields <list>", "-s/--state", "-p/--project", "-a/--author", "-A/--assignee", "-r/--reviewer", "-l/--label", "--since", "-d/--draft", "-D/--no-draft", "--target", "--source", "--sort", "--asc", "--no-asc", "-o/--open", "--no-open"],
            "example": "lore --robot mrs --state opened",
            "response_schema": {
                "list": {
                    "ok": "bool",
                    "data": {"mrs": "[{iid:int, title:string, state:string, author_username:string, labels:[string], draft:bool, target_branch:string, source_branch:string, discussion_count:int, unresolved_count:int, created_at_iso:string, updated_at_iso:string, web_url:string?, project_path:string, reviewers:[string]}]", "total_count": "int", "showing": "int"},
                    "meta": {"elapsed_ms": "int"}
                },
                "detail": {
                    "ok": "bool",
                    "data": "MrDetail (full entity with description, discussions, notes, events)",
                    "meta": {"elapsed_ms": "int"}
                }
            },
            "example_output": {"list": {"ok":true,"data":{"mrs":[{"iid":200,"title":"Add throw time chart","state":"opened","draft":false,"author_username":"teernisse","target_branch":"main","source_branch":"feat/throw-time","reviewers":["cseiber"],"discussion_count":5,"updated_at_iso":"2026-02-11T..."}],"total_count":1,"showing":1},"meta":{"elapsed_ms":38}}},
            "fields_presets": {"minimal": ["iid", "title", "state", "updated_at_iso"]}
        },
        "search": {
            "description": "Search indexed documents (lexical, hybrid, semantic)",
            "flags": ["<QUERY>", "--mode", "--type", "--author", "-p/--project", "--label", "--path", "--since", "--updated-since", "-n/--limit", "--fields <list>", "--explain", "--no-explain", "--fts-mode"],
            "example": "lore --robot search 'authentication bug' --mode hybrid --limit 10",
            "response_schema": {
                "ok": "bool",
                "data": {"results": "[{document_id:int, source_type:string, title:string, snippet:string, score:float, url:string?, author:string?, created_at:string?, updated_at:string?, project_path:string, labels:[string], paths:[string]}]", "total_results": "int", "query": "string", "mode": "string", "warnings": "[string]"},
                "meta": {"elapsed_ms": "int"}
            },
            "example_output": {"ok":true,"data":{"query":"throw time","mode":"hybrid","total_results":3,"results":[{"document_id":42,"source_type":"issue","title":"Switch Health Card","score":0.92,"snippet":"...throw time data from BNSF...","project_path":"vs/typescript-code"}],"warnings":[]},"meta":{"elapsed_ms":85}},
            "fields_presets": {"minimal": ["document_id", "title", "source_type", "score"]}
        },
        "count": {
            "description": "Count entities in local database",
            "flags": ["<entity: issues|mrs|discussions|notes|events>", "-f/--for <issue|mr>"],
            "example": "lore --robot count issues",
            "response_schema": {
                "ok": "bool",
                "data": {"entity": "string", "count": "int", "system_excluded?": "int", "breakdown?": {"opened": "int", "closed": "int", "merged?": "int", "locked?": "int"}},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "stats": {
            "description": "Show document and index statistics",
            "flags": ["--check", "--no-check", "--repair", "--dry-run", "--no-dry-run"],
            "example": "lore --robot stats",
            "response_schema": {
                "ok": "bool",
                "data": {"total_documents": "int", "indexed_documents": "int", "embedded_documents": "int", "stale_documents": "int", "integrity?": "object"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "status": {
            "description": "Show sync state (cursors, last sync times)",
            "flags": [],
            "example": "lore --robot status",
            "response_schema": {
                "ok": "bool",
                "data": {"projects": "[{path:string, issues_cursor:string?, mrs_cursor:string?, last_sync:string?}]"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "generate-docs": {
            "description": "Generate searchable documents from ingested data",
            "flags": ["--full", "-p/--project <path>"],
            "example": "lore --robot generate-docs --full",
            "response_schema": {
                "ok": "bool",
                "data": {"generated": "int", "updated": "int", "unchanged": "int", "deleted": "int"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "embed": {
            "description": "Generate vector embeddings for documents via Ollama",
            "flags": ["--full", "--no-full", "--retry-failed", "--no-retry-failed"],
            "example": "lore --robot embed",
            "response_schema": {
                "ok": "bool",
                "data": {"embedded": "int", "skipped": "int", "failed": "int", "total_chunks": "int"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "migrate": {
            "description": "Run pending database migrations",
            "flags": [],
            "example": "lore --robot migrate",
            "response_schema": {
                "ok": "bool",
                "data": {"before_version": "int", "after_version": "int", "migrated": "bool"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "version": {
            "description": "Show version information",
            "flags": [],
            "example": "lore --robot version",
            "response_schema": {
                "ok": "bool",
                "data": {"version": "string", "git_hash?": "string"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "completions": {
            "description": "Generate shell completions",
            "flags": ["<shell: bash|zsh|fish|powershell>"],
            "example": "lore completions bash > ~/.local/share/bash-completion/completions/lore"
        },
        "timeline": {
            "description": "Chronological timeline of events matching a keyword query or entity reference",
            "flags": ["<QUERY>", "-p/--project", "--since <duration>", "--depth <n>", "--no-mentions", "-n/--limit", "--fields <list>", "--max-seeds", "--max-entities", "--max-evidence"],
            "query_syntax": {
                "search": "Any text -> hybrid search seeding (FTS5 + vector)",
                "entity_direct": "issue:N, i:N, mr:N, m:N -> direct entity seeding (no search, no Ollama)"
            },
            "example": "lore --robot timeline issue:42",
            "response_schema": {
                "ok": "bool",
                "data": {"entities": "[{type:string, iid:int, title:string, project_path:string}]", "events": "[{timestamp:string, type:string, entity_type:string, entity_iid:int, detail:string}]", "total_events": "int"},
                "meta": {"elapsed_ms": "int", "search_mode": "string (hybrid|lexical|direct)"}
            },
            "fields_presets": {"minimal": ["timestamp", "type", "entity_iid", "detail"]}
        },
        "who": {
            "description": "People intelligence: experts, workload, active discussions, overlap, review patterns",
            "flags": ["<target>", "--path <path>", "--active", "--overlap <path>", "--reviews", "--since <duration>", "-p/--project", "-n/--limit", "--fields <list>", "--detail", "--no-detail", "--as-of <date>", "--explain-score", "--include-bots", "--include-closed", "--all-history"],
            "modes": {
                "expert": "lore who <file-path> -- Who knows about this area? (also: --path for root files)",
                "workload": "lore who <username> -- What is someone working on?",
                "reviews": "lore who <username> --reviews -- Review pattern analysis",
                "active": "lore who --active -- Active unresolved discussions",
                "overlap": "lore who --overlap <path> -- Who else is touching these files?"
            },
            "example": "lore --robot who src/features/auth/",
            "response_schema": {
                "ok": "bool",
                "data": {
                    "mode": "string",
                    "input": {"target": "string|null", "path": "string|null", "project": "string|null", "since": "string|null", "limit": "int"},
                    "resolved_input": {"mode": "string", "project_id": "int|null", "project_path": "string|null", "since_ms": "int", "since_iso": "string", "since_mode": "string (default|explicit|none)", "limit": "int"},
                    "...": "mode-specific fields"
                },
                "meta": {"elapsed_ms": "int"}
            },
            "example_output": {"expert": {"ok":true,"data":{"mode":"expert","result":{"experts":[{"username":"teernisse","score":42,"note_count":15,"diff_note_count":8}]}},"meta":{"elapsed_ms":65}}},
            "fields_presets": {
                "expert_minimal": ["username", "score"],
                "workload_minimal": ["entity_type", "iid", "title", "state"],
                "active_minimal": ["entity_type", "iid", "title", "participants"]
            }
        },
        "trace": {
            "description": "Trace why code was introduced: file -> MR -> issue -> discussion. Follows rename chains by default.",
            "flags": ["<path>", "-p/--project <path>", "--discussions", "--no-follow-renames", "-n/--limit <N>"],
            "example": "lore --robot trace src/main.rs -p group/repo",
            "response_schema": {
                "ok": "bool",
                "data": {"path": "string", "resolved_paths": "[string]", "trace_chains": "[{mr_iid:int, mr_title:string, mr_state:string, mr_author:string, change_type:string, merged_at_iso:string?, updated_at_iso:string, web_url:string?, issues:[{iid:int, title:string, state:string, reference_type:string, web_url:string?}], discussions:[{discussion_id:string, mr_iid:int, author_username:string, body_snippet:string, path:string, created_at_iso:string}]}]"},
                "meta": {"tier": "string (api_only)", "line_requested": "int?", "elapsed_ms": "int", "total_chains": "int", "renames_followed": "bool"}
            }
        },
        "file-history": {
            "description": "Show MRs that touched a file, with rename chain resolution and optional DiffNote discussions",
            "flags": ["<path>", "-p/--project <path>", "--discussions", "--no-follow-renames", "--merged", "-n/--limit <N>"],
            "example": "lore --robot file-history src/main.rs -p group/repo",
            "response_schema": {
                "ok": "bool",
                "data": {"path": "string", "rename_chain": "[string]?", "merge_requests": "[{iid:int, title:string, state:string, author_username:string, change_type:string, merged_at_iso:string?, updated_at_iso:string, merge_commit_sha:string?, web_url:string?}]", "discussions": "[{discussion_id:string, author_username:string, body_snippet:string, path:string, created_at_iso:string}]?"},
                "meta": {"elapsed_ms": "int", "total_mrs": "int", "renames_followed": "bool", "paths_searched": "int"}
            }
        },
        "drift": {
            "description": "Detect discussion divergence from original issue intent",
            "flags": ["<entity_type: issues>", "<IID>", "--threshold <0.0-1.0>", "-p/--project <path>"],
            "example": "lore --robot drift issues 42 --threshold 0.4",
            "response_schema": {
                "ok": "bool",
                "data": {"entity_type": "string", "iid": "int", "title": "string", "threshold": "float", "divergent_discussions": "[{discussion_id:string, similarity:float, snippet:string}]"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "explain": {
            "description": "Auto-generate a structured narrative of an issue or MR",
            "flags": ["<entity_type: issues|mrs>", "<IID>", "-p/--project <path>", "--sections <comma-list>", "--no-timeline", "--max-decisions <N>", "--since <period>"],
            "valid_sections": ["entity", "description", "key_decisions", "activity", "open_threads", "related", "timeline"],
            "example": "lore --robot explain issues 42 --sections key_decisions,activity --since 30d",
            "response_schema": {
                "ok": "bool",
                "data": {"entity": "{type:string, iid:int, title:string, state:string, author:string, assignees:[string], labels:[string], created_at:string, updated_at:string, url:string?, status_name:string?}", "description_excerpt": "string?", "key_decisions": "[{timestamp:string, actor:string, action:string, context_note:string}]?", "activity": "{state_changes:int, label_changes:int, notes:int, first_event:string?, last_event:string?}?", "open_threads": "[{discussion_id:string, started_by:string, started_at:string, note_count:int, last_note_at:string}]?", "related": "{closing_mrs:[{iid:int, title:string, state:string, web_url:string?}], related_issues:[{entity_type:string, iid:int, title:string?, reference_type:string}]}?", "timeline_excerpt": "[{timestamp:string, event_type:string, actor:string?, summary:string}]?"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "notes": {
            "description": "List notes from discussions with rich filtering",
            "flags": ["--limit/-n <N>", "--author/-a <username>", "--note-type <type>", "--contains <text>", "--for-issue <iid>", "--for-mr <iid>", "-p/--project <path>", "--since <period>", "--until <period>", "--path <filepath>", "--resolution <any|unresolved|resolved>", "--sort <created|updated>", "--asc", "--include-system", "--note-id <id>", "--gitlab-note-id <id>", "--discussion-id <id>", "--fields <list|minimal>", "--open"],
            "robot_flags": ["--format json", "--fields minimal"],
            "example": "lore --robot notes --author jdefting --since 1y --format json --fields minimal",
            "response_schema": {
                "ok": "bool",
                "data": {"notes": "[NoteListRowJson]", "total_count": "int", "showing": "int"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "cron": {
            "description": "Manage cron-based automatic syncing (Unix only)",
            "subcommands": {
                "install": {"flags": ["--interval <minutes>"], "default_interval": 8},
                "uninstall": {"flags": []},
                "status": {"flags": []}
            },
            "example": "lore --robot cron status",
            "response_schema": {
                "ok": "bool",
                "data": {"action": "string (install|uninstall|status)", "installed?": "bool", "interval_minutes?": "int", "entry?": "string", "log_path?": "string", "replaced?": "bool", "was_installed?": "bool", "last_run_iso?": "string"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "token": {
            "description": "Manage stored GitLab token",
            "subcommands": {
                "set": {"flags": ["--token <value>"], "note": "Reads from stdin if --token omitted in non-interactive mode"},
                "show": {"flags": ["--unmask"]}
            },
            "example": "lore --robot token show",
            "response_schema": {
                "ok": "bool",
                "data": {"action": "string (set|show)", "token_masked?": "string", "token?": "string", "valid?": "bool", "username?": "string"},
                "meta": {"elapsed_ms": "int"}
            }
        },
        "me": {
            "description": "Personal work dashboard: open issues, authored/reviewing MRs, @mentioned-in items, activity feed, and cursor-based since-last-check inbox with computed attention states",
            "flags": ["--issues", "--mrs", "--mentions", "--activity", "--since <period>", "-p/--project <path>", "--all", "--user <username>", "--fields <list|minimal>", "--reset-cursor"],
            "example": "lore --robot me",
            "response_schema": {
                "ok": "bool",
                "data": {
                    "username": "string",
                    "since_iso": "string?",
                    "summary": {"project_count": "int", "open_issue_count": "int", "authored_mr_count": "int", "reviewing_mr_count": "int", "mentioned_in_count": "int", "needs_attention_count": "int"},
                    "since_last_check": "{cursor_iso:string, total_event_count:int, groups:[{entity_type:string, entity_iid:int, entity_title:string, project:string, events:[{timestamp_iso:string, event_type:string, actor:string?, summary:string, body_preview:string?}]}]}?",
                    "open_issues": "[{project:string, iid:int, title:string, state:string, attention_state:string, attention_reason:string, status_name:string?, labels:[string], updated_at_iso:string, web_url:string?}]",
                    "open_mrs_authored": "[{project:string, iid:int, title:string, state:string, attention_state:string, attention_reason:string, draft:bool, detailed_merge_status:string?, author_username:string?, labels:[string], updated_at_iso:string, web_url:string?}]",
                    "reviewing_mrs": "[same as open_mrs_authored]",
                    "mentioned_in": "[{entity_type:string, project:string, iid:int, title:string, state:string, attention_state:string, attention_reason:string, updated_at_iso:string, web_url:string?}]",
                    "activity": "[{timestamp_iso:string, event_type:string, entity_type:string, entity_iid:int, project:string, actor:string?, is_own:bool, summary:string, body_preview:string?}]"
                },
                "meta": {"elapsed_ms": "int", "gitlab_base_url": "string (GitLab instance URL for constructing entity links: {base_url}/{project}/-/issues/{iid})"}
            },
            "fields_presets": {
                "me_items_minimal": ["iid", "title", "attention_state", "attention_reason", "updated_at_iso"],
                "me_mentions_minimal": ["entity_type", "iid", "title", "state", "attention_state", "attention_reason", "updated_at_iso"],
                "me_activity_minimal": ["timestamp_iso", "event_type", "entity_iid", "actor"]
            },
            "notes": {
                "attention_states": "needs_attention | not_started | awaiting_response | stale | not_ready",
                "event_types": "note | status_change | label_change | assign | unassign | review_request | milestone_change",
                "section_flags": "If none of --issues/--mrs/--mentions/--activity specified, all sections returned",
                "since_default": "1d for activity feed",
                "issue_filter": "Only In Progress / In Review status issues shown",
                "since_last_check": "Cursor-based inbox showing events since last run. Null on first run (no cursor yet). Groups events by entity (issue/MR). Sources: others' comments on your items, @mentions, assignment/review-request notes. Cursor auto-advances after each run. Use --reset-cursor to clear.",
                "cursor_persistence": "Stored per user in ~/.local/share/lore/me_cursor_<username>.json. --project filters display only for since-last-check; cursor still advances for all projects for that user.",
                "url_construction": "Use meta.gitlab_base_url + project + entity_type + iid to build links: {gitlab_base_url}/{project}/-/{issues|merge_requests}/{iid}"
            }
        },
        "robot-docs": {
            "description": "This command (agent self-discovery manifest)",
            "flags": ["--brief"],
            "example": "lore robot-docs --brief"
        }
    });

    let quick_start = serde_json::json!({
        "glab_equivalents": [
            { "glab": "glab issue list", "lore": "lore -J issues -n 50", "note": "Richer: includes labels, status, closing MRs, discussion counts" },
            { "glab": "glab issue view 123", "lore": "lore -J issues 123", "note": "Includes full discussions, work-item status, cross-references" },
            { "glab": "glab issue list -l bug", "lore": "lore -J issues --label bug", "note": "AND logic for multiple --label flags" },
            { "glab": "glab mr list", "lore": "lore -J mrs", "note": "Includes draft status, reviewers, discussion counts" },
            { "glab": "glab mr view 456", "lore": "lore -J mrs 456", "note": "Includes discussions, review threads, source/target branches" },
            { "glab": "glab mr list -s opened", "lore": "lore -J mrs -s opened", "note": "States: opened, merged, closed, locked, all" },
            { "glab": "glab api '/projects/:id/issues'", "lore": "lore -J issues -p project", "note": "Fuzzy project matching (suffix or substring)" }
        ],
        "lore_exclusive": [
            "search: FTS5 + vector hybrid search across all entities",
            "who: Expert/workload/reviews analysis per file path or person",
            "timeline: Chronological event reconstruction across entities",
            "trace: Code provenance chains (file -> MR -> issue -> discussion)",
            "file-history: MR history per file with rename resolution",
            "notes: Rich note listing with author, type, resolution, path, and discussion filters",
            "stats: Database statistics with document/note/discussion counts",
            "count: Entity counts with state breakdowns",
            "embed: Generate vector embeddings for semantic search via Ollama",
            "cron: Automated sync scheduling (Unix)",
            "token: Secure token management with masked display",
            "me: Personal work dashboard with attention states, activity feed, cursor-based since-last-check inbox, and needs-attention triage"
        ],
        "read_write_split": "lore = ALL reads (issues, MRs, search, who, timeline, intelligence). glab = ALL writes (create, update, approve, merge, CI/CD)."
    });

    // --brief: strip response_schema and example_output from every command (~60% smaller)
    let mut commands = commands;
    if brief {
        strip_schemas(&mut commands);
    }

    let exit_codes = serde_json::json!({
        "0": "Success",
        "1": "Internal error",
        "2": "Usage error (invalid flags or arguments)",
        "3": "Config invalid",
        "4": "Token not set",
        "5": "GitLab auth failed",
        "6": "Resource not found",
        "7": "Rate limited",
        "8": "Network error",
        "9": "Database locked",
        "10": "Database error",
        "11": "Migration failed",
        "12": "I/O error",
        "13": "Transform error",
        "14": "Ollama unavailable",
        "15": "Ollama model not found",
        "16": "Embedding failed",
        "17": "Not found",
        "18": "Ambiguous match",
        "19": "Health check failed",
        "20": "Config not found",
        "21": "Embeddings not built"
    });

    let workflows = serde_json::json!({
        "first_setup": [
            "lore --robot init --gitlab-url https://gitlab.com --token-env-var GITLAB_TOKEN --projects group/project",
            "lore --robot doctor",
            "lore --robot sync"
        ],
        "daily_sync": [
            "lore --robot sync"
        ],
        "search": [
            "lore --robot search 'query' --mode hybrid"
        ],
        "pre_flight": [
            "lore --robot health"
        ],
        "temporal_intelligence": [
            "lore --robot sync",
            "lore --robot timeline '<keyword>' --since 30d",
            "lore --robot timeline '<keyword>' --depth 2"
        ],
        "people_intelligence": [
            "lore --robot who src/path/to/feature/",
            "lore --robot who @username",
            "lore --robot who @username --reviews",
            "lore --robot who --active --since 7d",
            "lore --robot who --overlap src/path/",
            "lore --robot who --path README.md"
        ],
        "surgical_sync": [
            "lore --robot sync --issue 7 -p group/project",
            "lore --robot sync --issue 7 --mr 10 -p group/project",
            "lore --robot sync --issue 7 -p group/project --preflight-only"
        ],
        "personal_dashboard": [
            "lore --robot me",
            "lore --robot me --issues",
            "lore --robot me --activity --since 7d",
            "lore --robot me --project group/repo",
            "lore --robot me --fields minimal",
            "lore --robot me --reset-cursor"
        ]
    });

    // Phase 3: Deprecated command aliases
    let aliases = serde_json::json!({
        "deprecated_commands": {
            "list issues": "issues",
            "list mrs": "mrs",
            "show issue <IID>": "issues <IID>",
            "show mr <IID>": "mrs <IID>",
            "auth-test": "auth",
            "sync-status": "status"
        },
        "command_aliases": {
            "issue": "issues",
            "mr": "mrs",
            "merge-requests": "mrs",
            "merge-request": "mrs",
            "mergerequests": "mrs",
            "mergerequest": "mrs",
            "generate-docs": "generate-docs",
            "generatedocs": "generate-docs",
            "gendocs": "generate-docs",
            "gen-docs": "generate-docs",
            "robot-docs": "robot-docs",
            "robotdocs": "robot-docs"
        },
        "pre_clap_aliases": {
            "note": "Underscore/no-separator forms auto-corrected before parsing",
            "merge_requests": "mrs",
            "merge_request": "mrs",
            "mergerequests": "mrs",
            "mergerequest": "mrs",
            "generate_docs": "generate-docs",
            "generatedocs": "generate-docs",
            "gendocs": "generate-docs",
            "gen-docs": "generate-docs",
            "robot-docs": "robot-docs",
            "robotdocs": "robot-docs"
        },
        "prefix_matching": "Enabled via infer_subcommands. Unambiguous prefixes work: 'iss' -> issues, 'time' -> timeline, 'sea' -> search"
    });

    let error_tolerance = serde_json::json!({
        "note": "The CLI auto-corrects common mistakes before parsing. Corrections are applied silently with a teaching note on stderr.",
        "auto_corrections": [
            {"type": "single_dash_long_flag", "example": "-robot -> --robot", "mode": "all"},
            {"type": "case_normalization", "example": "--Robot -> --robot, --State -> --state", "mode": "all"},
            {"type": "flag_prefix", "example": "--proj -> --project (when unambiguous)", "mode": "all"},
            {"type": "fuzzy_flag", "example": "--projct -> --project", "mode": "all (threshold 0.9 in robot, 0.8 in human)"},
            {"type": "subcommand_alias", "example": "merge_requests -> mrs, robotdocs -> robot-docs", "mode": "all"},
            {"type": "subcommand_fuzzy", "example": "issuess -> issues, timline -> timeline, serach -> search", "mode": "all (threshold 0.85)"},
            {"type": "flag_as_subcommand", "example": "--robot-docs -> robot-docs, --generate-docs -> generate-docs", "mode": "all"},
            {"type": "value_normalization", "example": "--state Opened -> --state opened", "mode": "all"},
            {"type": "value_fuzzy", "example": "--state opend -> --state opened", "mode": "all"},
            {"type": "prefix_matching", "example": "lore iss -> lore issues, lore time -> lore timeline", "mode": "all (via clap infer_subcommands)"}
        ],
        "teaching_notes": "Auto-corrections emit a JSON warning on stderr: {\"warning\":{\"type\":\"ARG_CORRECTED\",\"corrections\":[...],\"teaching\":[...]}}"
    });

    // Phase 3: Clap error codes (emitted by handle_clap_error)
    let clap_error_codes = serde_json::json!({
        "UNKNOWN_COMMAND": "Unrecognized subcommand (includes fuzzy suggestion)",
        "UNKNOWN_FLAG": "Unrecognized command-line flag",
        "MISSING_REQUIRED": "Required argument not provided",
        "INVALID_VALUE": "Invalid value for argument",
        "TOO_MANY_VALUES": "Too many values provided",
        "TOO_FEW_VALUES": "Too few values provided",
        "ARGUMENT_CONFLICT": "Conflicting arguments",
        "MISSING_COMMAND": "No subcommand provided (in non-robot mode, shows help)",
        "HELP_REQUESTED": "Help or version flag used",
        "PARSE_ERROR": "General parse error"
    });

    let config_notes = serde_json::json!({
        "defaultProject": {
            "type": "string?",
            "description": "Fallback project path used when -p/--project is omitted. Must match a configured project path (exact or suffix). CLI -p always overrides.",
            "example": "group/project"
        }
    });

    let output = RobotDocsOutput {
        ok: true,
        data: RobotDocsData {
            name: "lore".to_string(),
            version,
            description: "Local GitLab data management with semantic search".to_string(),
            activation: RobotDocsActivation {
                flags: vec!["--robot".to_string(), "-J".to_string(), "--json".to_string()],
                env: "LORE_ROBOT=1".to_string(),
                auto: "Non-TTY stdout".to_string(),
            },
            quick_start,
            commands,
            aliases,
            error_tolerance,
            exit_codes,
            clap_error_codes,
            error_format: "stderr JSON: {\"error\":{\"code\":\"...\",\"message\":\"...\",\"suggestion\":\"...\",\"actions\":[\"...\"]}}".to_string(),
            workflows,
            config_notes,
        },
    };

    if robot_mode {
        println!("{}", serde_json::to_string(&output)?);
    } else {
        println!("{}", serde_json::to_string_pretty(&output)?);
    }

    Ok(())
}

fn handle_who(
    config_override: Option<&str>,
    mut args: WhoArgs,
    robot_mode: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    let start = std::time::Instant::now();
    let config = Config::load(config_override)?;
    if args.project.is_none() {
        args.project = config.default_project.clone();
    }
    let run = run_who(&config, &args)?;
    let elapsed_ms = start.elapsed().as_millis() as u64;

    if robot_mode {
        print_who_json(&run, &args, elapsed_ms);
    } else {
        print_who_human(&run.result, run.resolved_input.project_path.as_deref());
    }
    Ok(())
}

fn handle_me(
    config_override: Option<&str>,
    args: MeArgs,
    robot_mode: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    let config = Config::load(config_override)?;
    run_me(&config, &args, robot_mode)?;
    Ok(())
}

async fn handle_drift(
    config_override: Option<&str>,
    entity_type: &str,
    iid: i64,
    threshold: f32,
    project: Option<&str>,
    robot_mode: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    let start = std::time::Instant::now();
    let config = Config::load(config_override)?;
    let effective_project = config.effective_project(project);
    let response = run_drift(&config, entity_type, iid, threshold, effective_project).await?;
    let elapsed_ms = start.elapsed().as_millis() as u64;

    if robot_mode {
        print_drift_json(&response, elapsed_ms);
    } else {
        print_drift_human(&response);
    }
    Ok(())
}

async fn handle_related(
    config_override: Option<&str>,
    query_or_type: &str,
    iid: Option<i64>,
    limit: usize,
    project: Option<&str>,
    robot_mode: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    let start = std::time::Instant::now();
    let config = Config::load(config_override)?;
    let effective_project = config.effective_project(project);
    let response = run_related(&config, query_or_type, iid, limit, effective_project).await?;
    let elapsed_ms = start.elapsed().as_millis() as u64;

    if robot_mode {
        print_related_json(&response, elapsed_ms);
    } else {
        print_related_human(&response);
    }
    Ok(())
}

#[allow(clippy::too_many_arguments)]
async fn handle_list_compat(
    config_override: Option<&str>,
    entity: &str,
    limit: usize,
    project_filter: Option<&str>,
    state_filter: Option<&str>,
    author_filter: Option<&str>,
    assignee_filter: Option<&str>,
    label_filter: Option<&[String]>,
    milestone_filter: Option<&str>,
    since_filter: Option<&str>,
    due_before_filter: Option<&str>,
    has_due_date: bool,
    sort: &str,
    order: &str,
    open_browser: bool,
    json_output: bool,
    draft: bool,
    no_draft: bool,
    reviewer_filter: Option<&str>,
    target_branch_filter: Option<&str>,
    source_branch_filter: Option<&str>,
) -> Result<(), Box<dyn std::error::Error>> {
    let start = std::time::Instant::now();
    let config = Config::load(config_override)?;
    let project_filter = config.effective_project(project_filter);

    let state_normalized = state_filter.map(str::to_lowercase);
    match entity {
        "issues" => {
            let filters = ListFilters {
                limit,
                project: project_filter,
                state: state_normalized.as_deref(),
                author: author_filter,
                assignee: assignee_filter,
                labels: label_filter,
                milestone: milestone_filter,
                since: since_filter,
                due_before: due_before_filter,
                has_due_date,
                statuses: &[],
                sort,
                order,
            };

            let result = run_list_issues(&config, filters)?;

            if open_browser {
                open_issue_in_browser(&result);
            } else if json_output {
                print_list_issues_json(&result, start.elapsed().as_millis() as u64, None);
            } else {
                print_list_issues(&result);
            }

            Ok(())
        }
        "mrs" => {
            let filters = MrListFilters {
                limit,
                project: project_filter,
                state: state_normalized.as_deref(),
                author: author_filter,
                assignee: assignee_filter,
                reviewer: reviewer_filter,
                labels: label_filter,
                since: since_filter,
                draft,
                no_draft,
                target_branch: target_branch_filter,
                source_branch: source_branch_filter,
                sort,
                order,
            };

            let result = run_list_mrs(&config, filters)?;

            if open_browser {
                open_mr_in_browser(&result);
            } else if json_output {
                print_list_mrs_json(&result, start.elapsed().as_millis() as u64, None);
            } else {
                print_list_mrs(&result);
            }

            Ok(())
        }
        _ => {
            eprintln!(
                "{}",
                Theme::error().render(&format!("Unknown entity: {entity}"))
            );
            std::process::exit(1);
        }
    }
}

