# 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`: ```rust 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: ```rust 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`: ```rust fn should_show_project(events: &[TimelineEvent]) -> bool { let mut projects = events.iter().map(|e| &e.project_path).collect::>(); projects.len() > 1 } ``` Then conditionally format: ```rust 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: ```rust 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. ### 4. Update footer seed list `print_timeline_footer` (line 155-164) should also use the project-aware format: ```rust 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