refactor(nouser): labels de Mónada con 2 componentes del path
Resuelve la fricción visual de monorepos donde múltiples Mónadas
quedaban con label "src" (ambiguo). Nueva función label_from_path
toma los últimos hasta 2 componentes normales del path:
$ nouser scan crates/core
[01K..] brahman-admin/src card=5
[01K..] brahman-handshake/src card=6
[01K..] ente-brain/src card=11
[01K..] ente-kernel/src card=4
Tests añadidos: label_from_root_only_one_component,
label_from_deep_path_takes_last_two. Tests existentes actualizados
con los nuevos labels (proj/src en lugar de src).
22 tests en nouser-core (era 20, +2).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,22 @@ ratio/diff ver `git show <sha>`.
|
||||
|
||||
## 2026-05-08
|
||||
|
||||
### refactor(nouser): labels de Mónada con 2 componentes del path
|
||||
Resuelve la fricción visual de monorepos donde múltiples Mónadas se
|
||||
llamaban "src". Nueva función `label_from_path` toma los últimos hasta
|
||||
2 componentes normales del path y los une con `/`.
|
||||
|
||||
$ nouser scan crates/core
|
||||
[01K..] brahman-admin/src card=5
|
||||
[01K..] brahman-handshake/src card=6
|
||||
[01K..] ente-brain/src card=11
|
||||
[01K..] ente-kernel/src card=4
|
||||
...
|
||||
|
||||
Tests añadidos: `label_from_root_only_one_component`,
|
||||
`label_from_deep_path_takes_last_two`. Tests existentes actualizados
|
||||
con los nuevos labels.
|
||||
|
||||
### feat(nouser): Phase D-2 — proveedor Nous real (LLM) detrás de feature flag
|
||||
Cierra el ciclo del módulo Nous: existe un proveedor que produce
|
||||
embeddings reales con un modelo LLM, mientras que `cargo build` sin
|
||||
|
||||
@@ -46,11 +46,7 @@ pub fn by_directory(files: &[FileEntry], min_files: usize) -> Vec<MonadManifest>
|
||||
}
|
||||
|
||||
fn build_monad(parent: &std::path::Path, group: &[&FileEntry]) -> MonadManifest {
|
||||
let label = parent
|
||||
.file_name()
|
||||
.and_then(|s| s.to_str())
|
||||
.unwrap_or("unnamed")
|
||||
.to_string();
|
||||
let label = label_from_path(parent);
|
||||
|
||||
let keywords = top_extensions(group, 5);
|
||||
let lens = pick_lens(group);
|
||||
@@ -75,6 +71,27 @@ fn build_monad(parent: &std::path::Path, group: &[&FileEntry]) -> MonadManifest
|
||||
m
|
||||
}
|
||||
|
||||
/// Construye un label legible tomando los últimos hasta 2 componentes
|
||||
/// del path. Esto desambigua `src/` repetidos en monorepos: en lugar
|
||||
/// de 5 Mónadas con label "src", quedan "ente-zero/src", "ente-brain/src",
|
||||
/// etc. Para directorios shallow (root o un nivel), cae al
|
||||
/// `file_name()` simple.
|
||||
fn label_from_path(p: &std::path::Path) -> String {
|
||||
let normals: Vec<&str> = p
|
||||
.components()
|
||||
.filter_map(|c| match c {
|
||||
std::path::Component::Normal(s) => s.to_str(),
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
if normals.is_empty() {
|
||||
return "unnamed".to_string();
|
||||
}
|
||||
let take = normals.len().min(2);
|
||||
let start = normals.len() - take;
|
||||
normals[start..].join("/")
|
||||
}
|
||||
|
||||
fn build_summary(parent: &std::path::Path, group: &[&FileEntry], keywords: &[String]) -> String {
|
||||
let path_str = parent.display();
|
||||
let n = group.len();
|
||||
@@ -173,8 +190,10 @@ mod tests {
|
||||
let monads = by_directory(&files, 3);
|
||||
assert_eq!(monads.len(), 2);
|
||||
let labels: std::collections::BTreeSet<_> = monads.iter().map(|m| &m.label).collect();
|
||||
assert!(labels.iter().any(|l| l.as_str() == "src"));
|
||||
assert!(labels.iter().any(|l| l.as_str() == "docs"));
|
||||
// Phase B: labels usan los últimos 2 componentes del path para
|
||||
// desambiguar (proj/src vs proj/docs en lugar de src vs docs).
|
||||
assert!(labels.iter().any(|l| l.as_str() == "proj/src"));
|
||||
assert!(labels.iter().any(|l| l.as_str() == "proj/docs"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -188,7 +207,20 @@ mod tests {
|
||||
// min=3 → /proj/single solo no se promueve, /proj/sub sí.
|
||||
let monads = by_directory(&files, 3);
|
||||
assert_eq!(monads.len(), 1);
|
||||
assert_eq!(monads[0].label, "sub");
|
||||
assert_eq!(monads[0].label, "proj/sub");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn label_from_root_only_one_component() {
|
||||
// Un solo componente normal en el path → no hay "padre" útil.
|
||||
let p = std::path::Path::new("/onlyone");
|
||||
assert_eq!(label_from_path(p), "onlyone");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn label_from_deep_path_takes_last_two() {
|
||||
let p = std::path::Path::new("/a/b/c/d/e");
|
||||
assert_eq!(label_from_path(p), "d/e");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user