feat(explain): implement lore explain command for auto-generating issue/MR narratives

Adds the full explain command with 7 output sections: entity summary, description,
key decisions (heuristic event-note correlation), activity summary, open threads,
related entities (closing MRs, cross-references), and timeline excerpt (reuses
existing pipeline). Supports --sections filtering, --since time scoping,
--no-timeline, --max-decisions, and robot mode JSON output.

Closes: bd-2i3z, bd-a3j8, bd-wb0b, bd-3q5e, bd-nj7f, bd-9lbr
This commit is contained in:
teernisse
2026-03-10 14:24:35 -04:00
parent 16cc58b17f
commit 32134ea933
8 changed files with 2052 additions and 24 deletions

View File

@@ -277,6 +277,44 @@ pub enum Commands {
/// Trace why code was introduced: file -> MR -> issue -> discussion
Trace(TraceArgs),
/// Auto-generate a structured narrative of an issue or MR
#[command(after_help = "\x1b[1mExamples:\x1b[0m
lore explain issues 42 # Narrative for issue #42
lore explain mrs 99 -p group/repo # Narrative for MR !99 in specific project
lore -J explain issues 42 # JSON output for automation
lore explain issues 42 --sections key_decisions,open_threads # Specific sections only
lore explain issues 42 --since 30d # Narrative scoped to last 30 days
lore explain issues 42 --no-timeline # Skip timeline (faster)")]
Explain {
/// Entity type: "issues" or "mrs" (singular forms also accepted)
#[arg(value_parser = ["issues", "mrs", "issue", "mr"])]
entity_type: String,
/// Entity IID
iid: i64,
/// Scope to project (fuzzy match)
#[arg(short, long)]
project: Option<String>,
/// Select specific sections (comma-separated)
/// Valid: entity, description, key_decisions, activity, open_threads, related, timeline
#[arg(long, value_delimiter = ',', help_heading = "Output")]
sections: Option<Vec<String>>,
/// Skip timeline excerpt (faster execution)
#[arg(long, help_heading = "Output")]
no_timeline: bool,
/// Maximum key decisions to include
#[arg(long, default_value = "10", help_heading = "Output")]
max_decisions: usize,
/// Time scope for events/notes (e.g. 7d, 2w, 1m, or YYYY-MM-DD)
#[arg(long, help_heading = "Filters")]
since: Option<String>,
},
/// Detect discussion divergence from original intent
#[command(after_help = "\x1b[1mExamples:\x1b[0m
lore drift issues 42 # Check drift on issue #42