What is wrong
Every symbol-taking verb accepts the two :: spellings ripwire prints about itself: the canonical id
path::scope::name that every map row carries in id=, and the Scope::name that --edit-check
prints as sym=. --callers, --callees, --impact and --expand all resolve them. --uses
resolves them too — and then answers count="0", with no rows and no disclosure, for symbols that
plainly have call sites. A zero that reads as "defined, and nothing uses it" is exactly the
misreading CLAUDE.md non-negotiable 3 exists to prevent, and the callers answer's own next=
pointer sends the reader straight into it.
The evidence
On the test/declinefix fixture, three spellings of one symbol:
--callers=cpp/pair/one.cpp::One::ctwin count="1" next="--uses=cpp/pair/one.cpp::One::ctwin"
--uses=cpp/pair/one.cpp::One::ctwin defs="1" external="0" count="0" (no rows)
--uses=cpp/pair/one.cpp:ctwin count="1" <u role="call" p="cpp/pair/user.cpp:3" …/>
On this repository itself, --callers=NoteIndex::empty counts 816 callers and
--uses=NoteIndex::empty counts 0.
The cause is one comparison: resolveUsesSelector in src/verbs_navigate.h keeps the whole ::
spelling as the site match key, and collectUseSites compares that key against reference names,
which are always bare. The same zero reaches --safe-delete's uses=, --verify="uses(…)" and
unused(…), which share the scan, and the MCP uses verb, which carries its own copy of the
comparison. It was characterized across 16 selectors in C++, Python and Rust.
test/usesselectorcheck.sh already pins the gap. On a build of main it is ALL PASS, 57 checks
with 12 of them labelled KNOWN GAP; each asserts today's wrong answer and names its FIXED
expectation in a comment beside it. Against a wrapper faking the naive "strip the scope" fix, 12
arms go red — nine read MOVED, and the two precision controls and the wrong-scope control fail.
Size
Good first issue, though not a trivial one. The root cause is a single comparison in a single
function, and fixing it there reaches all three CLI verbs at once; there is no new gate file to
write, because the arms to flip already exist and every code pointer is verified. What keeps it from
being tiny: the MCP twin holds its own copy of the comparison and needs a decision, the --uses
legend has 25 bytes of budget left, and --help plus the generated docs/COMMANDS.md move with the
change.
Where to start
prompts/help-wanted/uses-qualified-selector.md is a self-contained prompt for a coding agent. It
carries the reproduction, the characterization table, file:line pointers with their symbols, the fix
shape and its edges, the honesty rules that apply, the acceptance criteria and the traps. Like every
prompt in prompts/, it ends by writing a plan and stopping — a maintainer agrees the plan
before any code is written.
Acceptance is flipping every KNOWN GAP arm in test/usesselectorcheck.sh to its FIXED line, red
against a build of main and green on the fix, with every control unchanged.
A sibling kit, prompts/help-wanted/next-uses-bare-name.md, changes the callers answer's next= on
a declined call and names this bound :: case as a separate, older gap. The two touch different
code, read the same fixture, and can land in either order; neither should absorb the other.
Comment here to claim it.
What is wrong
Every symbol-taking verb accepts the two
::spellings ripwire prints about itself: the canonical idpath::scope::namethat every map row carries inid=, and theScope::namethat--edit-checkprints as
sym=.--callers,--callees,--impactand--expandall resolve them.--usesresolves them too — and then answers
count="0", with no rows and no disclosure, for symbols thatplainly have call sites. A zero that reads as "defined, and nothing uses it" is exactly the
misreading
CLAUDE.mdnon-negotiable 3 exists to prevent, and the callers answer's ownnext=pointer sends the reader straight into it.
The evidence
On the
test/declinefixfixture, three spellings of one symbol:On this repository itself,
--callers=NoteIndex::emptycounts 816 callers and--uses=NoteIndex::emptycounts 0.The cause is one comparison:
resolveUsesSelectorinsrc/verbs_navigate.hkeeps the whole::spelling as the site match key, and
collectUseSitescompares that key against reference names,which are always bare. The same zero reaches
--safe-delete'suses=,--verify="uses(…)"andunused(…), which share the scan, and the MCPusesverb, which carries its own copy of thecomparison. It was characterized across 16 selectors in C++, Python and Rust.
test/usesselectorcheck.shalready pins the gap. On a build ofmainit is ALL PASS, 57 checkswith 12 of them labelled KNOWN GAP; each asserts today's wrong answer and names its FIXED
expectation in a comment beside it. Against a wrapper faking the naive "strip the scope" fix, 12
arms go red — nine read MOVED, and the two precision controls and the wrong-scope control fail.
Size
Good first issue, though not a trivial one. The root cause is a single comparison in a single
function, and fixing it there reaches all three CLI verbs at once; there is no new gate file to
write, because the arms to flip already exist and every code pointer is verified. What keeps it from
being tiny: the MCP twin holds its own copy of the comparison and needs a decision, the
--useslegend has 25 bytes of budget left, and
--helpplus the generateddocs/COMMANDS.mdmove with thechange.
Where to start
prompts/help-wanted/uses-qualified-selector.mdis a self-contained prompt for a coding agent. Itcarries the reproduction, the characterization table, file:line pointers with their symbols, the fix
shape and its edges, the honesty rules that apply, the acceptance criteria and the traps. Like every
prompt in
prompts/, it ends by writing a plan and stopping — a maintainer agrees the planbefore any code is written.
Acceptance is flipping every KNOWN GAP arm in
test/usesselectorcheck.shto its FIXED line, redagainst a build of
mainand green on the fix, with every control unchanged.A sibling kit,
prompts/help-wanted/next-uses-bare-name.md, changes the callers answer'snext=ona declined call and names this bound
::case as a separate, older gap. The two touch differentcode, read the same fixture, and can land in either order; neither should absorb the other.
Comment here to claim it.