Skip to content

Commit 8cc90e0

Browse files
committed
fix: exclude templates/archive from L1 extraction, fix people_notes count
Skip files under templates and archive folders in extract_active_projects to prevent template files (e.g. 05-Templates/Project.md) from leaking into active_projects. Adds path_is_in_excluded_folder helper that strips PARA numeric prefixes before matching. Also fixes people_notes count in run_detect_json: adds a depth-2 fallback scan for People/ subfolders when the profile doesn't detect a top-level people folder (e.g. 03-Resources/People/).
1 parent 29d0797 commit 8cc90e0

File tree

2 files changed

+65
-5
lines changed

2 files changed

+65
-5
lines changed

src/identity.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pub fn extract_l1_facts(store: &Store, profile: &VaultProfile) -> Result<L1Summa
2727

2828
// ── Active projects ─────────────────────────────────────────
2929
for file in &all_files {
30+
if path_is_in_excluded_folder(&file.path) {
31+
continue;
32+
}
3033
if file.tags.iter().any(|t| t.eq_ignore_ascii_case("project")) {
3134
let name = file_stem(&file.path);
3235
store.upsert_identity_fact(1, "active_project", &name, Some(&file.path))?;
@@ -231,6 +234,26 @@ fn file_stem(path: &str) -> String {
231234
.unwrap_or_else(|| path.to_string())
232235
}
233236

237+
/// Return true if the path is inside a templates or archive folder and should be
238+
/// excluded from L1 extraction. Matches any path component named "templates",
239+
/// "template", "archive", or "archives" (case-insensitive), as well as PARA-style
240+
/// numbered variants (e.g. "05-Templates", "04-Archive").
241+
fn path_is_in_excluded_folder(path: &str) -> bool {
242+
for component in path.split('/') {
243+
let stripped = component
244+
.trim_start_matches(|c: char| c.is_ascii_digit())
245+
.trim_start_matches(['-', '_', ' ']);
246+
let lower = stripped.to_ascii_lowercase();
247+
if matches!(
248+
lower.as_str(),
249+
"templates" | "template" | "archive" | "archives"
250+
) {
251+
return true;
252+
}
253+
}
254+
false
255+
}
256+
234257
/// Check whether a file path belongs to a given folder (case-insensitive prefix match).
235258
fn path_is_in_folder(path: &str, folder: &str) -> bool {
236259
let normalized = folder.trim_end_matches('/');

src/onboarding.rs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -686,15 +686,52 @@ fn count_daily_notes(vault_path: &Path, folders: &FolderMap) -> usize {
686686
}
687687

688688
/// Count markdown files in the people folder (if detected).
689+
/// Falls back to scanning common nested paths (e.g. `*/People/`) when the
690+
/// profile doesn't report a top-level people folder.
689691
fn count_people_notes(vault_path: &Path, folders: &FolderMap) -> usize {
690-
let Some(ref people) = folders.people else {
692+
// 1. Use profile-detected folder if available.
693+
if let Some(ref people) = folders.people {
694+
let people_dir = vault_path.join(people);
695+
if people_dir.is_dir() {
696+
return count_md_files_in_dir(&people_dir);
697+
}
698+
}
699+
700+
// 2. Fallback: walk one level of subdirectories looking for a "People" subfolder.
701+
let Ok(entries) = std::fs::read_dir(vault_path) else {
691702
return 0;
692703
};
693-
let people_dir = vault_path.join(people);
694-
if !people_dir.is_dir() {
695-
return 0;
704+
for entry in entries.filter_map(|e| e.ok()) {
705+
let Ok(ft) = entry.file_type() else { continue };
706+
if !ft.is_dir() {
707+
continue;
708+
}
709+
if entry.file_name().to_string_lossy().starts_with('.') {
710+
continue;
711+
}
712+
let subdir = entry.path();
713+
let Ok(inner) = std::fs::read_dir(&subdir) else {
714+
continue;
715+
};
716+
for inner_entry in inner.filter_map(|e| e.ok()) {
717+
let Ok(ift) = inner_entry.file_type() else {
718+
continue;
719+
};
720+
if !ift.is_dir() {
721+
continue;
722+
}
723+
let name = inner_entry.file_name();
724+
let name_lower = name.to_string_lossy().to_ascii_lowercase();
725+
if name_lower == "people" {
726+
let count = count_md_files_in_dir(&inner_entry.path());
727+
if count > 0 {
728+
return count;
729+
}
730+
}
731+
}
696732
}
697-
count_md_files_in_dir(&people_dir)
733+
734+
0
698735
}
699736

700737
/// Count `.md` files directly in a directory (non-recursive).

0 commit comments

Comments
 (0)