Skip to content

Commit 748c221

Browse files
committed
feat: show uncovered languages by default in ways language
Default view now emphasizes what's missing: lists all 47 uncovered languages alongside the 4 covered ones. Per-way detail table moves behind --audit flag. Covered (4/51): ar, de, es, ja + en Uncovered (47/51): bg, ca, cs, da, ...
1 parent 3ad6223 commit 748c221

2 files changed

Lines changed: 48 additions & 6 deletions

File tree

tools/ways-cli/src/cmd/language.rs

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::frontmatter;
1414
use crate::table::Table;
1515
use crate::util::home_dir;
1616

17-
pub fn run(filter_lang: Option<&str>, json_output: bool) -> Result<()> {
17+
pub fn run(filter_lang: Option<&str>, audit: bool, json_output: bool) -> Result<()> {
1818
let ways_dir = home_dir().join(".claude/hooks/ways");
1919
let xdg_way = xdg_cache_dir().join("claude-ways/user");
2020
let excluded = crate::util::load_excluded_segments();
@@ -71,19 +71,41 @@ pub fn run(filter_lang: Option<&str>, json_output: bool) -> Result<()> {
7171
println!("Multi corpus: {multi_corpus_count} ways");
7272
println!();
7373

74+
// Language coverage summary
75+
let all_supported = get_all_language_codes();
76+
let non_en: Vec<&str> = all_supported.iter()
77+
.filter(|c| *c != "en")
78+
.map(|s| s.as_str())
79+
.collect();
80+
7481
if !all_locales.is_empty() {
75-
println!("Language stubs found: {}", all_locales.iter().cloned().collect::<Vec<_>>().join(", "));
76-
println!();
82+
println!("Covered ({}/{}): {} + en",
83+
all_locales.len(), non_en.len(),
84+
all_locales.iter().cloned().collect::<Vec<_>>().join(", "),
85+
);
86+
}
87+
88+
let uncovered: Vec<String> = non_en.iter()
89+
.filter(|code| !all_locales.contains(**code))
90+
.map(|s| s.to_string())
91+
.collect();
92+
93+
if !uncovered.is_empty() {
94+
println!("Uncovered ({}/{}): {}",
95+
uncovered.len(), non_en.len(),
96+
uncovered.join(", "),
97+
);
7798
}
99+
println!();
78100

79101
// Summary counts
80102
let en_count = ways.iter().filter(|w| w.embed_model == "en").count();
81103
let multi_count = ways.iter().filter(|w| w.embed_model == "multilingual").count();
82104
println!("Ways: {} total ({} en, {} multilingual)", ways.len(), en_count, multi_count);
83105
println!();
84106

85-
// Per-way detail
86-
if !ways.is_empty() {
107+
// Per-way detail (only in audit mode)
108+
if audit && !ways.is_empty() {
87109
let mut t = Table::new(&["Way", "Model", "Locales"]);
88110
t.max_width(0, 45);
89111
for w in &ways {
@@ -97,6 +119,8 @@ pub fn run(filter_lang: Option<&str>, json_output: bool) -> Result<()> {
97119
t.add(vec![&w.id, &w.embed_model, &locales]);
98120
}
99121
t.print();
122+
} else if !audit {
123+
println!("Run `ways language --audit` for per-way detail.");
100124
}
101125

102126
// Warnings
@@ -266,6 +290,21 @@ fn line_count(path: &Path) -> usize {
266290
.unwrap_or(0)
267291
}
268292

293+
/// Get all language codes from languages.json, sorted.
294+
fn get_all_language_codes() -> Vec<String> {
295+
let parsed: serde_json::Value = match serde_json::from_str(agents::LANGUAGES_JSON) {
296+
Ok(v) => v,
297+
Err(_) => return Vec::new(),
298+
};
299+
let mut codes: Vec<String> = parsed
300+
.get("languages")
301+
.and_then(|v| v.as_object())
302+
.map(|m| m.keys().cloned().collect())
303+
.unwrap_or_default();
304+
codes.sort();
305+
codes
306+
}
307+
269308
fn xdg_cache_dir() -> PathBuf {
270309
std::env::var("XDG_CACHE_HOME")
271310
.map(PathBuf::from)

tools/ways-cli/src/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,9 @@ enum Commands {
137137
/// Filter to ways supporting this language (code or name)
138138
#[arg(long)]
139139
filter: Option<String>,
140+
/// Show full per-way coverage detail (default shows uncovered summary)
141+
#[arg(long)]
142+
audit: bool,
140143
/// Machine-readable JSON output
141144
#[arg(long)]
142145
json: bool,
@@ -423,7 +426,7 @@ fn main() -> Result<()> {
423426
Commands::Tree { path, jaccard } => cmd::tree::run(path, jaccard),
424427
Commands::Provenance { ways_dir } => cmd::provenance::run(ways_dir),
425428
Commands::Init { project } => cmd::init::run(project.as_deref()),
426-
Commands::Language { filter, json } => cmd::language::run(filter.as_deref(), json),
429+
Commands::Language { filter, audit, json } => cmd::language::run(filter.as_deref(), audit, json),
427430
Commands::Stats { days, project, json, global } => {
428431
cmd::stats::run(days, project.as_deref(), json, global)
429432
}

0 commit comments

Comments
 (0)