Summary
The clang-tidy-diff gate analyses changed lines only. That is a reasonable
policy for a repository adopting a large check set, but it has a consequence
nobody has measured: the public headers under include/morph/ carry a body of
findings the gate structurally cannot see, and each one is a trap for whoever
next edits the line it sits on — the gate goes red on a change that did not
introduce the finding.
101 distinct findings, across 17 headers, from six test translation units.
That is a lower bound, not a total: six TUs out of ~180, and the check set is
the repository's own .clang-tidy with WarningsAsErrors: "*" and
HeaderFilterRegex: "include/morph/.*".
Verification status
Reproduced, on cab05413 plus PR #579's branch (which touches only
completion.hpp, none of the files below), clang-tidy 22.1.8, against
build/clang-debug's compile_commands.json:
for f in tests/test_completion.cpp tests/test_bridge_local.cpp \
tests/test_remote_extra.cpp tests/test_wire_hardening.cpp \
tests/test_offline_queue.cpp tests/test_forms_layout.cpp; do
clang-tidy -p build/clang-debug --quiet "$f"
done
Deduplicated by normalised path + line + column (the same header reaches
clang-tidy through several ../ include chains, so a raw count double-counts):
distinct header findings: 101
files: 17
21 include/morph/util/quantity.hpp
18 include/morph/forms/forms.hpp
17 include/morph/detail/quantity_equation.hpp
7 include/morph/core/backend.hpp
7 include/morph/core/wire.hpp
6 include/morph/core/registry.hpp
5 include/morph/core/bridge.hpp
4 include/morph/journal/action_log.hpp
3 include/morph/offline/offline_queue.hpp
3 include/morph/session/session_auth.hpp
2 include/morph/util/rational.hpp
2 include/morph/core/remote.hpp
2 include/morph/core/timeout_scheduler.hpp
1 include/morph/attributes.hpp
1 include/morph/core/model.hpp
By check:
17 modernize-use-designated-initializers
14 readability-redundant-member-init
13 performance-unnecessary-value-param
11 cppcoreguidelines-avoid-do-while
7 cppcoreguidelines-macro-usage
6 bugprone-easily-swappable-parameters
4 misc-const-correctness
4 misc-no-recursion
Real output, three representative lines:
include/morph/core/wire.hpp:414:37: error: the parameter 'message' of type
'std::string' is copied for each invocation but only used as a const
reference; consider making it a const reference
[performance-unnecessary-value-param,-warnings-as-errors]
include/morph/core/backend.hpp:182:108: error: the parameter 'factory' of type
'std::function<std::unique_ptr<::morph::model::detail::IModelHolder>()>' is
copied for each invocation but only used as a const reference
[performance-unnecessary-value-param,-warnings-as-errors]
include/morph/core/detail/../wire.hpp:313:20: error: do not use array subscript
when the index is not an integer constant expression
[cppcoreguidelines-pro-bounds-constant-array-index,-warnings-as-errors]
The full deduplicated list is reproducible with the loop above; it is not pasted
here because it is 101 lines and will drift.
Not verified: whether any of the 101 is a defect rather than a style
finding. Spot-checking two:
wire.hpp:414 — makeErr(std::string message) is called with a string
literal at ~30 sites in remote.hpp and then passes message to
detail::sanitizeControlChars(std::string_view), which returns a fresh
string. The by-value std::string parameter is a wasted allocation on every
error reply. Small, real.
executor.hpp:211 — runTask(std::function<void()> task) is called only as
runTask(std::move(task)) from two sites, so the by-value parameter is a
move, not a copy. The finding is technically correct and practically inert.
That mix is the point: nobody has looked, and the gate is not built to make
anyone look.
Why this matters more than the count
The cost is not the 101 findings. It is that the gate's failure is displaced
from its cause. A contributor who reformats one line of backend.hpp, or
whose change makes clang-tidy re-analyse a region, gets a red clang-tidy-diff
naming a finding they did not introduce — and the cheapest way out is a
NOLINT, which is how a check set decays.
This is the same shape AGENTS.md's "Verify rather than assert" names: the gate
reports success while measuring only the sliver of the codebase that moved.
It measures exactly what it claims to and no more; the gap is that nobody
has stated what it does not cover.
What would change the verdict
Close this when either:
- the 101 (or whatever the full-tree number turns out to be) are fixed or
explicitly suppressed with a reason, so a full-tree clang-tidy run over
include/morph/ is clean and could be gated; or
- a deliberate decision is recorded that changed-lines-only is the policy and
latent header findings are accepted, in which case the trap should at least
be documented where a contributor hitting it will find it
(.clang-tidy's own header comment, or AGENTS.md's CI notes).
Re-open if the count grows without either.
Notes
Found while running the repository's own clang-tidy-diff as a pre-flight for
PR #579 (morph#553 / morph#565). Outside that PR's remit and deliberately not
folded into it. Nothing here is introduced by #579 — its own changed lines are
clean, and none of the 17 files above are in its diff except
include/morph/core/completion.hpp, which reports none.
Summary
The
clang-tidy-diffgate analyses changed lines only. That is a reasonablepolicy for a repository adopting a large check set, but it has a consequence
nobody has measured: the public headers under
include/morph/carry a body offindings the gate structurally cannot see, and each one is a trap for whoever
next edits the line it sits on — the gate goes red on a change that did not
introduce the finding.
101 distinct findings, across 17 headers, from six test translation units.
That is a lower bound, not a total: six TUs out of ~180, and the check set is
the repository's own
.clang-tidywithWarningsAsErrors: "*"andHeaderFilterRegex: "include/morph/.*".Verification status
Reproduced, on
cab05413plus PR #579's branch (which touches onlycompletion.hpp, none of the files below), clang-tidy 22.1.8, againstbuild/clang-debug'scompile_commands.json:Deduplicated by normalised path + line + column (the same header reaches
clang-tidy through several
../include chains, so a raw count double-counts):By check:
Real output, three representative lines:
The full deduplicated list is reproducible with the loop above; it is not pasted
here because it is 101 lines and will drift.
Not verified: whether any of the 101 is a defect rather than a style
finding. Spot-checking two:
wire.hpp:414—makeErr(std::string message)is called with a stringliteral at ~30 sites in
remote.hppand then passesmessagetodetail::sanitizeControlChars(std::string_view), which returns a freshstring. The by-value
std::stringparameter is a wasted allocation on everyerror reply. Small, real.
executor.hpp:211—runTask(std::function<void()> task)is called only asrunTask(std::move(task))from two sites, so the by-value parameter is amove, not a copy. The finding is technically correct and practically inert.
That mix is the point: nobody has looked, and the gate is not built to make
anyone look.
Why this matters more than the count
The cost is not the 101 findings. It is that the gate's failure is displaced
from its cause. A contributor who reformats one line of
backend.hpp, orwhose change makes clang-tidy re-analyse a region, gets a red
clang-tidy-diffnaming a finding they did not introduce — and the cheapest way out is a
NOLINT, which is how a check set decays.This is the same shape AGENTS.md's "Verify rather than assert" names: the gate
reports success while measuring only the sliver of the codebase that moved.
It measures exactly what it claims to and no more; the gap is that nobody
has stated what it does not cover.
What would change the verdict
Close this when either:
explicitly suppressed with a reason, so a full-tree
clang-tidyrun overinclude/morph/is clean and could be gated; orlatent header findings are accepted, in which case the trap should at least
be documented where a contributor hitting it will find it
(
.clang-tidy's own header comment, orAGENTS.md's CI notes).Re-open if the count grows without either.
Notes
Found while running the repository's own
clang-tidy-diffas a pre-flight forPR #579 (morph#553 / morph#565). Outside that PR's remit and deliberately not
folded into it. Nothing here is introduced by #579 — its own changed lines are
clean, and none of the 17 files above are in its diff except
include/morph/core/completion.hpp, which reports none.