Acting on a codometer failure
A
run reports three different kinds of finding, and they call for
three different responses. Reading which one occurred, rather than reacting to
"the check failed," is most of this skill.
A breach
A metric went past a limit declared for it. The report names the metric, the
limit's value, and its severity:
- prints the breach and leaves the exit code alone. Nothing about
the run fails; it is advance notice that a number is moving in a direction
worth watching.
- exits , and only when the run asked for a gate
at all — a bare measuring the same breach reports nothing
wrong, because nothing asked it to gate.
The instinctive fix — raising the limit's — is not an option. The
limit exists to keep a promise about the codebase's shape; loosening it on the
same change that broke the promise erases the evidence the check existed to
produce, and the next breach starts from a codebase that is already worse.
Reduce what is actually being measured instead:
- A size breach: shrink the input's own output — trim a dependency, split a
bundle, delete dead code — rather than the number that reports it. The
skill covers declaring an input and pointing it at
compiled output correctly, which is a common reason a size looks larger than
the code that produced it: an input measuring more than it should.
- A convention-count breach (too many of something, or too few): the count is
usually accurate — the fix is in the code the counter is watching, not in
the counter's .
- A comment budget breach is a custom statistic like any other, gated by an
ordinary entry against its metric — but its
name a file and a line for each breaching block rather than only
a total, because the thing measured is one block rather than a
repository-wide count. Condense that block, or move the detail into
documentation that has room for it. Check which reader measured it before
trusting the count — shell, TOML, SQL, and HCL use a line scanner that reads
a comment marker inside a string literal as a comment, and Python's comments
go unmeasured entirely when the interpreter cannot be run. The
skill has both caveats in full.
- A comment budget a language is not covered by is not a breach at all —
it is simply not measured. If a repository added a language codometer can
parse comments in but nobody added a selector for it, that
language's blocks run with no budget until one is declared; this is never
something to diagnose as a false negative in the tool.
If the limit's number was simply wrong for what this metric should hold going
forward — not because of this change, but as a standing decision — that is a
deliberate edit to make and explain on its own, never a side effect of getting
one check to pass.
Staleness
compares a committed report against a fresh measurement and
fails when they disagree, whether or not any limit is involved. Two causes
produce this, and only one of them is a real regression:
- The code actually changed and the committed report was never
re-measured. Re-run with / to refresh it.
- The runtime changed. Compressed sizes are Node-version dependent — the
bundled zlib differs release to release — so a report written on one Node
version and checked on another reads as stale with zero code changes
involved. Check on the exact runtime the repository pins for everything
else before concluding the source moved.
A breach and staleness are reported as separate findings even when
they come from the same run; do not read one as a symptom of the other.
A run that failed outright
Distinct from both of the above: the run itself could not finish, collected
into
in the report rather than folded into any metric.
- A limit bound to nothing. The metric path names no measurement the run
actually took — misspelled, or naming an analysis its input never ran, or
genuinely ambiguous between two inputs. Fix the path in the configuration;
the skill covers how a metric path resolves and why an
ambiguous one is refused rather than guessed.
- An input matched no files while carrying a limit. Declaring a limit
against an input asserts its files exist, so an empty match means the glob
stopped matching or the build that should have produced those files never
ran — check the build step before touching the configuration. An input
nobody limited that matches nothing is unremarkable and reports no failure.
- The configuration itself was rejected before anything measured. A
missing , two entries of the same type, a custom statistic
naming none of //, or an entry
selecting a label the top-level array never declared each
fail the run at load time with the reason named. A configuration exporting a
function instead of a plain object is a quieter version of the same problem:
there is no config-as-function escape hatch any more, so it is not
recognized and falls back to an empty configuration — which then fails on
the missing rather than on anything naming the real cause. Fix the
configuration rather than the command line.
Every failure in one run is collected and reported together, so treat a report
naming three as three things to fix, not one flaky run to retry.
Before reaching for /
Remember that the two
flags and
are independent, with no
inferred relationship between them — the
skill has the full
flag table. Combining an
flag with
is refused
outright: nothing can be stale in a report the same run just wrote, so that
combination is a configuration mistake to fix, not a way to force a report
current.
is independent of
too — narrowing a
run to exactly the given globs does not change whether it gates or writes.
There is no
on
: a run always measures the process's
own working directory. The
subcommand is the one place
still exists, for listing what a directory's configuration
resolves to rather than for measuring it.