Files
gitlore/docs/issues/001-timeline-missing-project-in-entity-ref.md
Taylor Eernisse 4185abe05d docs: add feature ideas catalog, time-decay scoring plan, and timeline issue doc
Ideas catalog (docs/ideas/): 25 feature concept documents covering future
lore capabilities including bottleneck detection, churn analysis, expert
scoring, collaboration patterns, milestone risk, knowledge silos, and more.
Each doc includes motivation, implementation sketch, data requirements, and
dependencies on existing infrastructure. README.md provides an overview and
SYSTEM-PROPOSAL.md presents the unified analytics vision.

Plans (plans/): Time-decay expert scoring design with four rounds of review
feedback exploring decay functions, scoring algebra, and integration points
with the existing who-expert pipeline.

Issue doc (docs/issues/001): Documents the timeline pipeline bug where
EntityRef was missing project context, causing ambiguous cross-project
references during the EXPAND stage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 10:16:48 -05:00

4.3 KiB

001: Timeline human output omits project path from entity references

  • Severity: medium
  • Component: src/cli/commands/timeline.rs
  • Status: open

Problem

The lore timeline human-readable output renders entity references as bare #42 or !234 without the project path. When multiple projects are synced, this makes the output ambiguous — issue #42 in group/backend and #42 in group/frontend are indistinguishable.

Affected code

format_entity_ref at src/cli/commands/timeline.rs:201-207:

fn format_entity_ref(entity_type: &str, iid: i64) -> String {
    match entity_type {
        "issue" => format!("#{iid}"),
        "merge_request" => format!("!{iid}"),
        _ => format!("{entity_type}:{iid}"),
    }
}

This function is called in three places:

  1. Event lines (print_timeline_event, line 130) — each event row shows #42 with no project context
  2. Footer seed list (print_timeline_footer, line 161) — seed entities listed as #42, !234 with no project disambiguation
  3. Collect stage summaries (timeline_collect.rs:107) — the summary field itself bakes in "Issue #42 created: ..." without project

Current output (ambiguous)

2025-01-20  CREATED       #42      Issue #42 created: Login timeout bug        @alice
2025-01-21  LABEL+        #42      Label added: priority::high                 @dave
2025-01-22  CREATED       !234     MR !234 created: Refactor auth middleware   @alice
2025-01-25  MERGED        !234     MR !234 merged                              @bob

  Seed entities: #42, !234

When multiple projects are synced, a reader cannot tell which project #42 belongs to.

Robot mode is partially affected

The robot JSON output (EventJson, line 387-416) DOES include a project field per event, so programmatic consumers can disambiguate. However, the summary string field still bakes in bare #42 without project context, which is misleading if an agent uses the summary for display.

Proposed fix

1. Add project to format_entity_ref

Pass project_path into format_entity_ref and use GitLab's full reference format:

fn format_entity_ref(entity_type: &str, iid: i64, project_path: &str) -> String {
    match entity_type {
        "issue" => format!("{project_path}#{iid}"),
        "merge_request" => format!("{project_path}!{iid}"),
        _ => format!("{project_path}/{entity_type}:{iid}"),
    }
}

2. Smart elision for single-project timelines

When all events belong to the same project, the full path is visual noise. Detect this and fall back to bare #42 / !234:

fn should_show_project(events: &[TimelineEvent]) -> bool {
    let mut projects = events.iter().map(|e| &e.project_path).collect::<HashSet<_>>();
    projects.len() > 1
}

Then conditionally format:

let entity_ref = if show_project {
    format_entity_ref(&event.entity_type, event.entity_iid, &event.project_path)
} else {
    format_entity_ref_short(&event.entity_type, event.entity_iid)
};

3. Fix summary strings in collect stage

timeline_collect.rs:107 bakes the summary as "Issue #42 created: title". This should include the project when multi-project:

let prefix = if multi_project {
    format!("{type_label} {project_path}#{iid}")
} else {
    format!("{type_label} #{iid}")
};
summary = format!("{prefix} created: {title_str}");

Same pattern for the merge summary at lines 317 and 347.

print_timeline_footer (line 155-164) should also use the project-aware format:

result.seed_entities.iter()
    .map(|e| format_entity_ref(&e.entity_type, e.entity_iid, &e.project_path))

Expected output after fix

Single project (no change)

2025-01-20  CREATED       #42      Issue #42 created: Login timeout bug        @alice

Multi-project (project path added)

2025-01-20  CREATED   group/backend#42   Issue group/backend#42 created: Login timeout  @alice
2025-01-22  CREATED   group/frontend#42  Issue group/frontend#42 created: Broken layout @eve

Impact

  • Human output: ambiguous for multi-project users (the primary use case for gitlore)
  • Robot output: summary field misleading, but project field provides workaround
  • Timeline footer: seed entity list ambiguous
  • Collect-stage summaries: baked-in bare references propagate to both renderers