Walks from `start` upward looking for an initialised repo marker (`.tracedecay/tracedecay.db`) or a profile-storage enrollment marker (`.tracedecay/enrollment.json`). Returns the first ancestor directory (inclusive) that contains an initialised `TraceDecay` project, or `None` if the filesystem root is reached without finding one. # Canonical project-root resolution order This walk-up is the hea
(start: &Path)
| 672 | /// wins, then the shallowest registered descendant; ties are reported as |
| 673 | /// ambiguous and require an explicit path. |
| 674 | pub fn discover_project_root(start: &Path) -> Option<PathBuf> { |
| 675 | let mut dir = start.to_path_buf(); |
| 676 | let worktree_root = crate::worktree::git_worktree_root(start); |
| 677 | loop { |
| 678 | if has_project_database(&dir) |
| 679 | || crate::storage::has_enrollment_marker(&dir) |
| 680 | || crate::storage::resolve_layout_for_current_profile(&dir).is_ok_and(|layout| { |
| 681 | layout.storage_mode == crate::storage::StorageMode::ProfileSharded |
| 682 | && layout.graph_db_path.exists() |
| 683 | }) |
| 684 | { |
| 685 | return Some(dir); |
| 686 | } |
| 687 | if worktree_root |
| 688 | .as_ref() |
| 689 | .is_some_and(|root| paths_same(&dir, root)) |
| 690 | { |
| 691 | return None; |
| 692 | } |
| 693 | if !dir.pop() { |
| 694 | return None; |
| 695 | } |
| 696 | } |
| 697 | } |
| 698 | |
| 699 | /// Like [`resolve_path`], but when `path` is `None` it walks up from `cwd` |
| 700 | /// to find the nearest initialised `TraceDecay` project before falling back to |