feat(cli): add --timings flag and enrich error tracking fields

Add -t/--timings flag to the sync subcommand, allowing users to opt
into a per-stage timing breakdown after the sync summary. Wire the flag
through main.rs into print_sync() which passes it to the new
should_print_timings() gate.

Enrich the data structures that flow through the sync pipeline so
downstream renderers have full error visibility:

- ProjectSummary gains status_errors (issue-side status enrichment
  failures per project)
- ProjectStatusEnrichment gains path (project path for sub-row display)
- SyncResult gains documents_errored and embedding_failed so the
  summary can surface doc-gen and embed failures separately
- Autocorrect table updated with --timings for fuzzy flag matching
This commit is contained in:
teernisse
2026-02-16 09:43:13 -05:00
parent a570327a6b
commit c8b47bf8f8
4 changed files with 13 additions and 2 deletions

View File

@@ -126,6 +126,7 @@ const COMMAND_FLAGS: &[(&str, &[&str])] = &[
"--no-file-changes",
"--dry-run",
"--no-dry-run",
"--timings",
],
),
(

View File

@@ -59,12 +59,14 @@ pub struct ProjectSummary {
pub events_failed: usize,
pub statuses_enriched: usize,
pub statuses_seen: usize,
pub status_errors: usize,
pub mr_diffs_fetched: usize,
pub mr_diffs_failed: usize,
}
/// Per-project status enrichment result, collected during ingestion.
pub struct ProjectStatusEnrichment {
pub path: String,
pub mode: String,
pub reason: Option<String>,
pub seen: usize,
@@ -664,6 +666,7 @@ async fn run_ingest_inner(
total
.status_enrichment_projects
.push(ProjectStatusEnrichment {
path: path.clone(),
mode: result.status_enrichment_mode.clone(),
reason: result.status_unsupported_reason.clone(),
seen: result.statuses_seen,
@@ -682,6 +685,8 @@ async fn run_ingest_inner(
events_failed: result.resource_events_failed,
statuses_enriched: result.statuses_enriched,
statuses_seen: result.statuses_seen,
status_errors: result.partial_error_count
+ usize::from(result.status_enrichment_error.is_some()),
mr_diffs_fetched: 0,
mr_diffs_failed: 0,
});
@@ -716,6 +721,7 @@ async fn run_ingest_inner(
events_failed: result.resource_events_failed,
statuses_enriched: 0,
statuses_seen: 0,
status_errors: 0,
mr_diffs_fetched: result.mr_diffs_fetched,
mr_diffs_failed: result.mr_diffs_failed,
});

View File

@@ -789,6 +789,10 @@ pub struct SyncArgs {
#[arg(long = "no-dry-run", hide = true, overrides_with = "dry_run")]
pub no_dry_run: bool,
/// Show detailed timing breakdown for sync stages
#[arg(short = 't', long = "timings")]
pub timings: bool,
}
#[derive(Parser)]

View File

@@ -2099,7 +2099,7 @@ async fn handle_sync_cmd(
"{}",
Theme::warning().render("Interrupted by Ctrl+C. Partial results:")
);
print_sync(&result, elapsed, Some(metrics));
print_sync(&result, elapsed, Some(metrics), args.timings);
if released > 0 {
eprintln!(
"{}",
@@ -2122,7 +2122,7 @@ async fn handle_sync_cmd(
if robot_mode {
print_sync_json(&result, elapsed.as_millis() as u64, Some(metrics));
} else {
print_sync(&result, elapsed, Some(metrics));
print_sync(&result, elapsed, Some(metrics), args.timings);
}
Ok(())
}