Introduce a reusable GraphQL client (`src/gitlab/graphql.rs`) that handles
GitLab's GraphQL API with full error handling for auth failures, rate
limiting, and partial errors. Key capabilities:
- Adaptive page sizing (100 → 50 → 25 → 10) to handle GitLab GraphQL
complexity limits without hardcoding a single safe page size
- Paginated issue status fetching via the workItems GraphQL query
- Graceful detection of unsupported instances (missing GraphQL endpoint
or forbidden auth) so ingestion continues without status data
- Retry-After header parsing via the `httpdate` crate for rate limit
compliance
Also adds `WorkItemStatus` type to `gitlab::types` with name, category,
color, and icon_name fields (all optional except name) with comprehensive
deserialization tests covering all system statuses (TO_DO, IN_PROGRESS,
DONE, CANCELED) and edge cases (null category, unknown future values).
The `GitLabClient` gains a `graphql_client()` factory method for
ergonomic access from the ingestion pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bump version from 0.1.0 to 0.5.0 to reflect the maturity of the CLI
after months of development — robot mode, search pipeline, ingestion
orchestrator, who commands, timeline pipeline, and embedding support
are all implemented and stable.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes to the sync pipeline:
1. Atomic watermarks: wrap complete_job + update_watermark in a single
SQLite transaction so crash between them can't leave partial state.
2. Concurrent drain loops: prefetch HTTP requests via join_all (batch
size = dependent_concurrency), then write serially to DB. Reduces
~9K sequential requests from ~19 min to ~2.4 min.
3. Graceful shutdown: install Ctrl+C handler via ShutdownSignal
(Arc<AtomicBool>), thread through orchestrator/CLI, release locked
jobs on interrupt, record sync_run as "failed".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CLI help improvements (cli/mod.rs):
- Add descriptive help text to all global flags (-c, --robot, -J, etc.)
- Add descriptions to all subcommands (Issues, Mrs, Sync, etc.)
- Add --no-quiet flag for explicit quiet override
- Shell completions now shows installation instructions for each shell
- Optional subcommand: running bare 'lore' shows help in terminal mode,
robot-docs in robot mode
Structured clap error handling (main.rs):
- Early robot mode detection before parsing (env + args)
- JSON error output for parse failures in robot mode
- Semantic error codes: UNKNOWN_COMMAND, UNKNOWN_FLAG, MISSING_REQUIRED,
INVALID_VALUE, ARGUMENT_CONFLICT, etc.
- Fuzzy command suggestion using Jaro-Winkler similarity (>0.7 threshold)
- Help/version requests handled normally (exit 0, not error)
Robot-docs enhancements (main.rs):
- Document deprecated command aliases (list issues -> issues, etc.)
- Document clap error codes for programmatic error handling
- Include completions command in manifest
- Update flag documentation to show short forms (-n, -s, -p, etc.)
Dependencies:
- Add strsim 0.11 for Jaro-Winkler fuzzy matching
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The note_parser module requires regex for extracting "mentioned in" and
"closed by" patterns from GitLab system notes. The regex crate provides:
- LazyLock-compatible lazy compilation (Regex::new at first use)
- Named capture groups for clean field extraction
- Efficient iteration over all matches via captures_iter()
Version 1.x is the current stable release with good compile times.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduce the foundational observability layer for the sync pipeline:
- MetricsLayer: Custom tracing subscriber layer that captures span timing
and structured fields, materializing them into a hierarchical
Vec<StageTiming> tree for robot-mode performance data output
- logging: Dual-layer subscriber infrastructure with configurable stderr
verbosity (-v/-vv/-vvv) and always-on JSON file logging with daily
rotation and configurable retention (default 30 days)
- SyncRunRecorder: Compile-time enforced lifecycle recorder for sync_runs
table (start -> succeed|fail), with correlation IDs and aggregate counts
- LoggingConfig: New config section for log_dir, retention_days, and
file_logging toggle
- get_log_dir(): Path helper for log directory resolution
- is_permanent_api_error(): Distinguish retryable vs permanent API failures
(only 404 is truly permanent; 403/auth errors may be environmental)
Database changes:
- Migration 013: Add resource_events_synced_for_updated_at watermark columns
to issues and merge_requests tables for incremental resource event sync
- Migration 014: Enrich sync_runs with run_id correlation ID, aggregate
counts (total_items_processed, total_errors), and run_id index
- Wrap file-based migrations in savepoints for rollback safety
Dependencies: Add uuid (run_id generation), tracing-appender (file logging)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tracing-indicatif pulled in vt100, arrayvec, and its own indicatif
integration layer. Replace it with a minimal SuspendingWriter that
coordinates tracing output with progress bars via a global LazyLock
MultiProgress.
- Add src/cli/progress.rs: shared MultiProgress singleton via LazyLock
and a SuspendingWriter that suspends bars before writing log lines,
preventing interleaving/flicker
- Wire all progress bar creation through multi().add() in sync and
ingest commands
- Replace IndicatifLayer in main.rs with SuspendingWriter for
tracing-subscriber's fmt layer
- Remove tracing-indicatif from Cargo.toml (drops vt100 and arrayvec
transitive deps)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add clap_complete for shell completion generation and libc (unix-only)
for SIGPIPE handling. Create build.rs to embed the git commit hash at
compile time via cargo:rustc-env=GIT_HASH, enabling `lore version` to
display the short hash alongside the version number.
Co-Authored-By: Claude (us.anthropic.claude-opus-4-5-20251101-v1:0) <noreply@anthropic.com>
The embedding pipeline and retry queues need randomized exponential
backoff to prevent thundering herd effects when Ollama or GitLab
recover from transient failures. The rand crate (0.8) provides the
thread-safe RNG needed for jitter computation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Set up the GitLab Inbox (gi) CLI tool as a Rust 2024 edition project.
Dependencies organized by purpose:
- Database: rusqlite (bundled SQLite), sqlite-vec for vector search
- Serialization: serde/serde_json for GitLab API responses
- CLI: clap for argument parsing, dialoguer for interactive prompts,
comfy-table for formatted output, indicatif for progress bars
- HTTP: reqwest with tokio async runtime for GitLab API calls
- Async: async-stream and futures for paginated API iteration
- Utilities: thiserror for error types, chrono for timestamps,
flate2 for payload compression, sha2 for content hashing
- Logging: tracing with env-filter for structured debug output
Release profile optimized for small binary size (LTO, strip symbols).
Project structure follows standard Rust conventions with src/lib.rs
exposing modules and src/main.rs as CLI entry point.
Added .gitignore for Rust/Cargo artifacts and local database files.
Added AGENTS.md with TDD workflow guidance and beads issue tracking
integration instructions for AI-assisted development.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>