From 736d9c9a80592e2d0ef6c634debe94896869a9cf Mon Sep 17 00:00:00 2001 From: Taylor Eernisse Date: Sat, 7 Feb 2026 21:35:16 -0500 Subject: [PATCH] docs: rewrite robot-mode-design to reflect implemented features Comprehensive update to the robot mode design document bringing it in sync with the actual implementation after the elapsed_ms, --fields, and error actions features landed. Major additions: - Response envelope section documenting compact JSON with elapsed_ms timing - Error actions table mapping each error code to executable recovery commands - Field selection section with presets (minimal) and per-entity available fields - Expanded exit codes table (14-20) covering Ollama, embedding, ambiguity errors - Updated command examples to use current CLI syntax (lore issues vs lore list issues) - Added -J shorthand and --fields to global flags table - Best practices section with --fields minimal for token efficiency (~60% reduction) Removed outdated sections that no longer match the implementation. Co-Authored-By: Claude Opus 4.6 --- docs/robot-mode-design.md | 327 ++++++++++++++++---------------------- 1 file changed, 136 insertions(+), 191 deletions(-) diff --git a/docs/robot-mode-design.md b/docs/robot-mode-design.md index 792cbc3..4c7e9a7 100644 --- a/docs/robot-mode-design.md +++ b/docs/robot-mode-design.md @@ -2,19 +2,22 @@ ## Overview -Robot mode optimizes the `lore` CLI for AI agent consumption with structured JSON output, meaningful exit codes, and token-efficient responses. +Robot mode optimizes the `lore` CLI for AI agent consumption with compact JSON output, structured errors with machine-actionable recovery steps, meaningful exit codes, response timing metadata, field selection for token efficiency, and TTY auto-detection. ## Activation ```bash # Explicit flag -lore --robot list issues +lore --robot issues -n 5 -# Auto-detection (when stdout is not a TTY) -lore list issues | jq . +# JSON shorthand +lore -J issues -n 5 # Environment variable -LORE_ROBOT=true lore list issues +LORE_ROBOT=1 lore issues + +# Auto-detection (when stdout is not a TTY) +lore issues | jq . ``` ## Global Flags @@ -22,218 +25,160 @@ LORE_ROBOT=true lore list issues | Flag | Description | |------|-------------| | `--robot` | Force JSON output, structured errors | -| `--quiet` | Suppress progress/spinners (implied by --robot) | +| `-J` / `--json` | Shorthand for `--robot` | +| `--quiet` | Suppress progress/spinners (implied by `--robot`) | +| `--fields ` | Select output fields for list commands | -## Exit Codes +## Response Envelope -| Code | ErrorCode | Meaning | -|------|-----------|---------| -| 0 | - | Success | -| 1 | INTERNAL_ERROR | Unknown/internal error | -| 2 | CONFIG_NOT_FOUND | Config file missing | -| 3 | CONFIG_INVALID | Config file malformed | -| 4 | TOKEN_NOT_SET | GitLab token not configured | -| 5 | GITLAB_AUTH_FAILED | Authentication failed | -| 6 | GITLAB_NOT_FOUND | Resource not found | -| 7 | GITLAB_RATE_LIMITED | Rate limited | -| 8 | GITLAB_NETWORK_ERROR | Network/connection error | -| 9 | DB_LOCKED | Database locked by another process | -| 10 | DB_ERROR | Database error | -| 11 | MIGRATION_FAILED | Migration failed | -| 12 | IO_ERROR | File I/O error | -| 13 | TRANSFORM_ERROR | Data transformation error | +All commands return a consistent JSON envelope to stdout: + +```json +{"ok":true,"data":{...},"meta":{"elapsed_ms":42}} +``` + +Key properties: +- **Compact JSON**: Single-line output (no pretty-printing) for efficient parsing +- **Uniform envelope**: Every command wraps its data in `{"ok":true,"data":{...},"meta":{...}}` +- **Timing metadata**: `meta.elapsed_ms` is present on every response (wall-clock milliseconds) ## Error Output Format -When `--robot` is active, errors are JSON on stderr: +Errors are JSON on stderr with structured fields for programmatic handling: ```json { "error": { "code": "CONFIG_NOT_FOUND", - "message": "Config file not found at ~/.config/lore/config.toml", - "suggestion": "Run 'lore init' to create configuration" + "message": "Config file not found at ~/.config/lore/config.json. Run \"lore init\" first.", + "suggestion": "Run 'lore init' to set up your GitLab connection.", + "actions": ["lore init"] } } ``` -## Success Output Format +| Field | Type | Description | +|-------|------|-------------| +| `code` | string | Machine-readable error code (e.g., `CONFIG_NOT_FOUND`) | +| `message` | string | Human-readable error description | +| `suggestion` | string? | Recovery guidance (omitted when not applicable) | +| `actions` | string[]? | Executable shell commands for recovery (omitted when empty) | -All commands return consistent JSON structure: +### Error Actions by Code -```json -{ - "ok": true, - "data": { ... }, - "meta": { - "count": 50, - "total": 1234, - "elapsed_ms": 45 - } -} +| Error Code | Actions | +|------------|---------| +| `CONFIG_NOT_FOUND` | `["lore init"]` | +| `CONFIG_INVALID` | `["lore init --force"]` | +| `GITLAB_AUTH_FAILED` | `["export GITLAB_TOKEN=glpat-xxx", "lore auth"]` | +| `TOKEN_NOT_SET` | `["export GITLAB_TOKEN=glpat-xxx"]` | +| `OLLAMA_UNAVAILABLE` | `["ollama serve"]` | +| `OLLAMA_MODEL_NOT_FOUND` | `["ollama pull nomic-embed-text"]` | +| `DB_LOCKED` | `["lore ingest --force"]` | +| `EMBEDDING_FAILED` | `["lore embed --retry-failed"]` | +| `MIGRATION_FAILED` | `["lore migrate"]` | +| `GITLAB_NETWORK_ERROR` | `["lore doctor"]` | + +## Exit Codes + +| Code | ErrorCode | Meaning | +|------|-----------|---------| +| 0 | -- | Success | +| 1 | `INTERNAL_ERROR` | Unknown/internal error | +| 2 | -- | Usage error (invalid flags or arguments) | +| 3 | `CONFIG_INVALID` | Config file malformed | +| 4 | `TOKEN_NOT_SET` | GitLab token not configured | +| 5 | `GITLAB_AUTH_FAILED` | Authentication failed | +| 6 | `GITLAB_NOT_FOUND` | Resource not found | +| 7 | `GITLAB_RATE_LIMITED` | Rate limited | +| 8 | `GITLAB_NETWORK_ERROR` | Network/connection error | +| 9 | `DB_LOCKED` | Database locked by another process | +| 10 | `DB_ERROR` | Database error | +| 11 | `MIGRATION_FAILED` | Migration failed | +| 12 | `IO_ERROR` | File I/O error | +| 13 | `TRANSFORM_ERROR` | Data transformation error | +| 14 | `OLLAMA_UNAVAILABLE` | Ollama not running | +| 15 | `OLLAMA_MODEL_NOT_FOUND` | Ollama model not installed | +| 16 | `EMBEDDING_FAILED` | Embedding generation failed | +| 17 | `NOT_FOUND` | Entity does not exist locally | +| 18 | `AMBIGUOUS` | Multiple projects match (use `-p`) | +| 19 | -- | Health check failed | +| 20 | `CONFIG_NOT_FOUND` | Config file missing | + +## Field Selection + +The `--fields` flag on `issues` and `mrs` list commands controls which fields appear in each item of the response array: + +```bash +# Preset: ~60% fewer tokens +lore -J issues --fields minimal + +# Custom field list +lore -J mrs --fields iid,title,state,draft,target_branch ``` -## Command-Specific Output +### Presets -### lore list issues --robot +| Preset | Expands to | +|--------|------------| +| `minimal` | `iid`, `title`, `state`, `updated_at_iso` | -```json -{ - "ok": true, - "data": { - "issues": [ - { - "iid": 123, - "project": "group/project", - "title": "Bug in login", - "state": "opened", - "author": "username", - "assignees": ["user1"], - "labels": ["bug", "priority::high"], - "discussions": { "total": 5, "unresolved": 2 }, - "updated_at": "2024-01-15T10:30:00Z", - "web_url": "https://..." - } - ] - }, - "meta": { "showing": 50, "total": 234 } -} +### Available Fields + +**Issues**: `iid`, `title`, `state`, `author_username`, `labels`, `assignees`, `discussion_count`, `unresolved_count`, `created_at_iso`, `updated_at_iso`, `web_url`, `project_path` + +**MRs**: `iid`, `title`, `state`, `author_username`, `labels`, `draft`, `target_branch`, `source_branch`, `discussion_count`, `unresolved_count`, `created_at_iso`, `updated_at_iso`, `web_url`, `project_path`, `reviewers` + +Field selection applies only to list output, not to show (single-entity) output which returns full detail. + +## Command Response Schemas + +Every command in `lore robot-docs` includes a `response_schema` field describing the shape of its JSON response. This enables agents to understand response structures without trial-and-error. + +```bash +# Get schema for a specific command +lore robot-docs | jq '.data.commands.issues.response_schema' + +# Get all schemas +lore robot-docs | jq '[.data.commands | to_entries[] | select(.value.response_schema) | {(.key): .value.response_schema}] | add' ``` -### lore show issue 123 --robot +## Clap Error Handling + +Parse errors from the argument parser emit structured JSON to stderr with semantic error codes: + +| Code | Meaning | +|------|---------| +| `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 | +| `HELP_REQUESTED` | Help or version flag used | +| `PARSE_ERROR` | General parse error | + +Unknown commands include a fuzzy suggestion when a close match exists: ```json -{ - "ok": true, - "data": { - "issue": { - "iid": 123, - "project": "group/project", - "title": "Bug in login", - "description": "Full markdown...", - "state": "opened", - "author": "username", - "created_at": "2024-01-10T08:00:00Z", - "updated_at": "2024-01-15T10:30:00Z", - "discussions": [ - { - "id": "abc123", - "resolved": false, - "notes": [ - { - "author": "user1", - "body": "Comment text...", - "created_at": "2024-01-11T09:00:00Z", - "system": false - } - ] - } - ] - } - } -} +{"error":{"code":"UNKNOWN_COMMAND","message":"...","suggestion":"Did you mean 'lore issues'? Run 'lore robot-docs' for all commands"}} ``` -### lore ingest --type issues --robot +## Agent Self-Discovery -```json -{ - "ok": true, - "data": { - "resource_type": "issues", - "projects": [ - { - "path": "group/project", - "issues_synced": 45, - "discussions_synced": 123 - } - ], - "totals": { - "issues": 45, - "discussions": 123 - } - }, - "meta": { "elapsed_ms": 3400 } -} +`lore robot-docs` provides a complete manifest for agent bootstrapping: + +```bash +lore robot-docs # Pretty-printed (human-readable) +lore --robot robot-docs # Compact (for parsing) ``` -### lore count issues --robot - -```json -{ - "ok": true, - "data": { - "entity": "issues", - "count": 1234, - "breakdown": { - "opened": 456, - "closed": 778 - } - } -} -``` - -### lore doctor --robot - -```json -{ - "ok": true, - "data": { - "success": true, - "checks": { - "config": { "status": "ok", "path": "~/.config/lore/config.toml" }, - "database": { "status": "ok", "version": 6 }, - "gitlab": { "status": "ok", "user": "username" }, - "projects": [ - { "path": "group/project", "status": "ok" } - ] - } - } -} -``` - -### lore sync-status --robot - -```json -{ - "ok": true, - "data": { - "last_sync": { - "status": "completed", - "resource_type": "issues", - "started_at": "2024-01-15T10:00:00Z", - "completed_at": "2024-01-15T10:00:45Z", - "duration_ms": 45000 - }, - "cursors": [ - { - "project": "group/project", - "resource_type": "issues", - "cursor": "2024-01-15T10:00:00Z" - } - ] - } -} -``` - -## Implementation Plan - -### Phase 1: Core Infrastructure -1. Add `--robot` global flag to Cli struct -2. Create `RobotOutput` trait for consistent JSON serialization -3. Add exit code mapping from ErrorCode -4. Implement TTY detection with `atty` crate - -### Phase 2: Command Updates -1. Update all commands to check robot mode -2. Add JSON output variants for commands missing them (count, ingest, sync-status) -3. Suppress progress bars in robot mode - -### Phase 3: Error Handling -1. Update main.rs error handler for robot mode -2. Add suggestion field to GiError variants -3. Emit structured JSON errors to stderr - -### Phase 4: Documentation -1. Update AGENTS.md with robot mode commands -2. Add --robot examples to help text +The manifest includes: +- All commands with flags, examples, and response schemas +- Deprecated command aliases (e.g., `list issues` -> `issues`) +- Exit codes with meanings +- Clap error codes +- Suggested workflows (first setup, daily sync, search, pre-flight) +- Activation methods (flags, env vars, TTY auto-detection)