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>
141 lines
4.3 KiB
Markdown
141 lines
4.3 KiB
Markdown
# 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::<HashSet<_>>();
|
|
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
|