kvb-check-efficiency measures a change against its base: tokens.py counts skill text tokens and listing words, measure.py runs one command in a base worktree and the working tree (one run per side, the mean of five over 100, an estimate marked ~ when other processes load the CPU). kvb-check-speed reads wall time from the same run and is not relevant for skills. kvb-check-score prints fix, break, efficiency, speed and the product score with emojis plus a gate line: below 90/5 it reports, over 100 it requires asking the operator before the commit. Every skill that reported confidence and break risk now shows the score block; the 90/5 bar adds efficiency and speed at most 100. Commit blocks and the commit call's approval prompt name worktree, branch, diff stat and the score values, also for merges. 24 descriptions were shortened to keep the skill listing within its budget. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.7 KiB
name, description
| name | description |
|---|---|
| kvb-code-no-defaults | Forbid defaults for parameters, settings and environment lookups; demand explicit values. Apply AUTOMATICALLY whenever code, config, templates or infrastructure are written, edited or reviewed. |
A default is a guess written where the caller's intent is least known: it turns a missing value into a plausible wrong answer, and two callers read the same call differently (one means "use the default", the other forgot). Never write a substantive default: require the value; when it is absent, fail at once and loudly, naming the missing thing.
The rule
- Every parameter, option, setting, environment lookup, column and template variable MUST be supplied explicitly by its caller.
- A missing value MUST abort at the earliest moment (argument parsing, config load, container start), never at the point of use and never by proceeding with a substitute.
- The error MUST name the missing key and where to set it.
- Genuine optionality MUST be an explicit named case the call site handles:
None/nullin a visible branch is fine, a fallback baked into the accessor is not.
Free and justified defaults
false, null (None, nil, undefined), "" and an empty list or map
MAY be defaults without justification: they denote absence, not a guessed
value. ${VAR:-}, d.get(k), a ?? null and def f(a=None) are fine.
Every other default (a number, a non-empty string, list or map, an enum member, a path, a timeout) MUST carry a comment on or directly above it, in the project's exception-comment form if it has one, saying why that value is right for every caller that omits it; no comment, no default. The comment names the assumption so a reviewer can disagree.
"Sensible", "standard", "usual", "conventional", "every other project does it", "obvious" and "keeps the signature short" justify nothing: they assert someone else chose. A valid justification names why this value is right for a caller who says nothing. The operator asking for a specific default, in this conversation, for this value, settles it without a comment.
Detect
Before presenting a diff or a review, run
${CLAUDE_SKILL_DIR}/scripts/defaults.py --repo <dir> (--staged: index
only; --file <path>: a whole untracked file). Each hit prints file:line,
language, construct and replacement; exit 1 means hits. Judge each:
- Real default: rewrite it as the replacement, at the value's true owner.
- Justified: a
justified?hit stays only if its comment meets the bar above. - False positive: a
candidate(??,||, Pythonor) that is logic, or no default at all; report why.
Check by hand what the script cannot see: Go fields left to zero values (a
constructor validating every field), defaults in a Helm values.yaml (none;
fail on the missing input), Docker ENV placeholders for config
(${VAR:?VAR is required}), Java overloads filling an optional parameter
(required constructor arguments), and any other value-resolution fallback
(?:, getOrElse, fallback, a dataclass field).
How to apply
- Before writing any parameter, ask what happens if the caller omits it; anything but "it fails and says so" gets rewritten.
- Pushing a default one layer up is no fix: a caller passing an invented constant only moved the guess. Require the value at its true owner (operator, inventory, deployment config).
- Removing an existing default is a behaviour change, never a silent drive-by: name it and let the operator decide whether it lands in this change or its own.
Penalty
An unjustified default you wrote: report it with file and count, no excuses; lower the bundle's confidence numbers; write the date and the construct to persistent agent memory so the calibration survives the session.