feat(cli): generalize applicability tag + honest R-expectancy refusal prose (fieldtest 0108 F8)

--metrics now tags the four generalizable names (expectancy_r,
net_expectancy_r, sqn, sqn_normalized) via check_r_metric as the
predicate — the registry's own R-expectancy rule, no fourth roster
site (#190). The GeneralizeNonRMetric refusal names the real rule
with the roster pointer instead of mislabeling R-denominated-but-
unranked metrics (max_r_drawdown is a drawdown in R, not a 'pip
metric').

RED-first (tdd-author handoff): the extended --metrics pins and the
flipped prose pins (unit + seam) observed failing on the old output.

Gates: workspace 1026/0, clippy -D warnings clean.

closes #207
This commit is contained in:
2026-07-04 02:14:58 +02:00
parent 38ffe50b57
commit 891c40d64b
3 changed files with 51 additions and 12 deletions
+9 -2
View File
@@ -82,7 +82,10 @@ fn print_metric_roster() {
for name in aura_research::metric_vocabulary() {
let rankable = aura_campaign::RANKABLE_METRICS.contains(name);
let gate = aura_campaign::PER_MEMBER_METRICS.contains(name);
let tag = match (rankable, gate) {
// The generalize applicability is the registry's own R-expectancy
// predicate — no fourth roster site (#190/#207).
let generalize = aura_registry::check_r_metric(name).is_ok();
let base = match (rankable, gate) {
(true, true) => "rankable | gate",
(false, true) => "gate",
// Unreachable today (the rankable roster is a subset of the
@@ -90,7 +93,11 @@ fn print_metric_roster() {
(true, false) => "rankable",
(false, false) => "annotation",
};
println!("{name:<24} {tag}");
if generalize {
println!("{name:<24} {base} | generalize");
} else {
println!("{name:<24} {base}");
}
}
}