You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(py): accept the CLI's metric names in metrics= #1614
CLI.--metrics resolves names through metric_alias.rs: family names, the list-metrics bucket names (sloc, dloc, …) and dotted ids (cyclomatic.modified). Since PR feat(mi): stop charging documentation rows in MI #1609 it also takes the loc family name.
Python.metrics= takes only the 13 family names in METRIC_NAMES, which is how _native.pyi documents it.
This is not new.sloc already behaved this way on main, and PR #1609's dloc follows it. It is a parity gap rather than a bug.
Proposal. Resolve Python names with the same rules as the CLI, so a name copied from bca list-metrics, bca check --threshold or the CLI's --metrics works in Python. Keep METRIC_NAMES as the canonical family list and document the accepted aliases next to it. Then update:
_native.pyi and the stubtest allowlist, if needed;
the book's Python page.
Tests should cover a sub-metric, a dotted id, a family name and an unknown name, with its did-you-mean message.
Found during the whole-branch review of PR #1609 (#1597).
Resolution
Status: fixed (pending merge) Commit:02ac90b on fix/batch-2026-10-17 (rewritten onto the #1621 layer; the original 7630358 was superseded — see the "Resolution (rewritten)" comment) Root cause: the CLI and the Python bindings each resolved metric names their own way. Both now go through the public metric_catalog::resolve_selector. The SARIF threshold-name gap moved to #1618.
Root cause: the CLI resolved --metrics names in its own metric_alias module (family names, list-metrics row names, dotted ids). The Python bindings parsed metrics= with Metric::from_str, which takes only the 13 family names. There was no shared resolver to keep the two in step.
Changes:
Root crate: new public metric_catalog::resolve_selector, selector_names and UnknownSelectorError. Additive, and recorded in STABILITY.md. A selector maps to its Metric family, so "dloc" selects all of loc, exactly as --metrics dloc does. The did-you-mean algorithm moved from the CLI into a private src/suggestion.rs; the CLI reaches it through one #[doc(hidden)] re-export that STABILITY.md places outside the contract.
CLI: metric_for_name is a thin wrapper around resolve_selector. Its error text is byte-identical (16 cases compared before and after: --metrics, check --threshold, diff --metric, [thresholds.lang]).
Python: metrics= resolves through resolve_selector. The error keeps its unknown metric: <name> prefix, followed by the CLI's did-you-mean hint and name list.
Docs: _native.pyi, the book's Python metrics page and the bindings README. Also documented: cognitive, nargs and nexits pull in nom.
Tests: root resolver tests for families, row names, dotted ids, a close miss, ties, no match and case; the CLI error text pinned; Python tests for sloc/dloc/loc.dloc, a dotted id, the suggestion message, and the nom dependency. Six production perturbations, each failing its tests. The review tightened one assertion: the known-names list is now checked by list membership, because a substring check passed with loc missing, as loc sits inside dloc and sloc. Patch coverage is 99.55 % (220/221) against 98.22 % project; the one missed region was already missed in the CLI's copy of the moved code.
Premise check: all confirmed. The CLI computes whole families and never trims output to the named field, and Python now matches that.
Out of scope, filed separately:to_sarif(thresholds=) needs a scalar resolver (mi.original must not collapse to Mi). That is #1618.
The batch branch fix/batch-2026-10-17 was rewritten so these fixes sit on the shared value-semantics layer from #1621 (metric_catalog::Scale + Threshold). This issue's fix is now commit 02ac90ba on that branch; the earlier hash in the comments above is superseded and no longer on the branch (it survives on backup/batch-1017-before-rewrite locally). Behaviour, tests and reproducers are as described in the earlier resolution, with these deltas from the layer:
Replayed unchanged; git range-diff against the original shows only merge context in src/lib.rs / src/metric_catalog.rs and the regenerated .bca-baseline.toml.
Gate: BCA_GATE: pass (gate=pre-commit) on the commit and on the series tip 1a8023dd.
Activity
dekobon commentedon Oct 18, 2026
Fix summary
Root cause: the CLI resolved
--metricsnames in its ownmetric_aliasmodule (family names,list-metricsrow names, dotted ids). The Python bindings parsedmetrics=withMetric::from_str, which takes only the 13 family names. There was no shared resolver to keep the two in step.Changes:
metric_catalog::resolve_selector,selector_namesandUnknownSelectorError. Additive, and recorded in STABILITY.md. A selector maps to itsMetricfamily, so"dloc"selects all ofloc, exactly as--metrics dlocdoes. The did-you-mean algorithm moved from the CLI into a privatesrc/suggestion.rs; the CLI reaches it through one#[doc(hidden)]re-export that STABILITY.md places outside the contract.metric_for_nameis a thin wrapper aroundresolve_selector. Its error text is byte-identical (16 cases compared before and after:--metrics,check --threshold,diff --metric,[thresholds.lang]).metrics=resolves throughresolve_selector. The error keeps itsunknown metric: <name>prefix, followed by the CLI's did-you-mean hint and name list._native.pyi, the book's Python metrics page and the bindings README. Also documented:cognitive,nargsandnexitspull innom.Tests: root resolver tests for families, row names, dotted ids, a close miss, ties, no match and case; the CLI error text pinned; Python tests for
sloc/dloc/loc.dloc, a dotted id, the suggestion message, and thenomdependency. Six production perturbations, each failing its tests. The review tightened one assertion: the known-names list is now checked by list membership, because a substring check passed withlocmissing, aslocsits insidedlocandsloc. Patch coverage is 99.55 % (220/221) against 98.22 % project; the one missed region was already missed in the CLI's copy of the moved code.Premise check: all confirmed. The CLI computes whole families and never trims output to the named field, and Python now matches that.
Out of scope, filed separately:
to_sarif(thresholds=)needs a scalar resolver (mi.originalmust not collapse toMi). That is #1618.Commit: 7630358 on
fix/batch-2026-10-17.dekobon commentedon Oct 18, 2026
Resolution (rewritten)
The batch branch
fix/batch-2026-10-17was rewritten so these fixes sit on the shared value-semantics layer from #1621 (metric_catalog::Scale+Threshold). This issue's fix is now commit02ac90baon that branch; the earlier hash in the comments above is superseded and no longer on the branch (it survives onbackup/batch-1017-before-rewritelocally). Behaviour, tests and reproducers are as described in the earlier resolution, with these deltas from the layer:git range-diffagainst the original shows only merge context insrc/lib.rs/src/metric_catalog.rsand the regenerated.bca-baseline.toml.Gate:
BCA_GATE: pass (gate=pre-commit)on the commit and on the series tip1a8023dd.feat(py): accept CLI metric names in metrics=
docs(changelog): record the metric value-semantics layer
docs: align tier and limit wording with the gate
feat(py): accept CLI metric names in metrics=
feat(py): accept CLI metric names in metrics=
dekobon commentedon Oct 20, 2026
Pull request: #1650.