feat(cli): Add search, stats, embed, sync, health, and robot-docs commands
Extends the CLI with six new commands that complete the search pipeline: - lore search <QUERY>: Hybrid search with mode selection (lexical, hybrid, semantic), rich filtering (--type, --author, --project, --label, --path, --after, --updated-after), result limits, and optional explain mode showing RRF score breakdowns. Safe FTS mode sanitizes user input; raw mode passes through for power users. - lore stats: Document and index statistics with optional --check for integrity verification and --repair to fix inconsistencies (orphaned documents, missing FTS entries, stale dirty queue items). - lore embed: Generate vector embeddings via Ollama. Supports --retry-failed to re-attempt previously failed embeddings. - lore generate-docs: Drain the dirty queue to regenerate documents. --full seeds all entities for complete rebuild. --project scopes to a single project. - lore sync: Full pipeline orchestration (ingest issues + MRs, generate-docs, embed) with --no-embed and --no-docs flags for partial runs. Reports per-stage results and total elapsed time. - lore health: Quick pre-flight check (config exists, DB exists, schema current). Returns exit code 1 if unhealthy. Designed for agent pre-flight scripts. - lore robot-docs: Machine-readable command manifest for agent self-discovery. Returns all commands, flags, examples, exit codes, and recommended workflows as structured JSON. Also enhances lore init with --gitlab-url, --token-env-var, and --projects flags for fully non-interactive robot-mode initialization. Fixes init's force/non-interactive precedence logic and adds JSON output for robot mode. Updates all command files for the GiError -> LoreError rename. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ use serde::Serialize;
|
||||
|
||||
use crate::Config;
|
||||
use crate::core::db::create_connection;
|
||||
use crate::core::error::{GiError, Result};
|
||||
use crate::core::error::{LoreError, Result};
|
||||
use crate::core::paths::get_db_path;
|
||||
use crate::core::time::ms_to_iso;
|
||||
|
||||
@@ -188,11 +188,11 @@ fn find_issue(conn: &Connection, iid: i64, project_filter: Option<&str>) -> Resu
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
|
||||
match issues.len() {
|
||||
0 => Err(GiError::NotFound(format!("Issue #{} not found", iid))),
|
||||
0 => Err(LoreError::NotFound(format!("Issue #{} not found", iid))),
|
||||
1 => Ok(issues.into_iter().next().unwrap()),
|
||||
_ => {
|
||||
let projects: Vec<String> = issues.iter().map(|i| i.project_path.clone()).collect();
|
||||
Err(GiError::Ambiguous(format!(
|
||||
Err(LoreError::Ambiguous(format!(
|
||||
"Issue #{} exists in multiple projects: {}. Use --project to specify.",
|
||||
iid,
|
||||
projects.join(", ")
|
||||
@@ -386,11 +386,11 @@ fn find_mr(conn: &Connection, iid: i64, project_filter: Option<&str>) -> Result<
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
|
||||
match mrs.len() {
|
||||
0 => Err(GiError::NotFound(format!("MR !{} not found", iid))),
|
||||
0 => Err(LoreError::NotFound(format!("MR !{} not found", iid))),
|
||||
1 => Ok(mrs.into_iter().next().unwrap()),
|
||||
_ => {
|
||||
let projects: Vec<String> = mrs.iter().map(|m| m.project_path.clone()).collect();
|
||||
Err(GiError::Ambiguous(format!(
|
||||
Err(LoreError::Ambiguous(format!(
|
||||
"MR !{} exists in multiple projects: {}. Use --project to specify.",
|
||||
iid,
|
||||
projects.join(", ")
|
||||
|
||||
Reference in New Issue
Block a user