Summary
tests/tools/tree_sitter_accuracy_audit.py's _get_node_name mis-reads two CSS at-rule node
shapes, making the tri-comparison audit disagree with GitGalaxy where GitGalaxy is actually
correct. Both surfaced during a tri-comparison-ledger-sweep pass on css. Same bug class as
#1313 (which fixed media_statement / supports_statement but left these two wrong).
Neither is a GitGalaxy engine defect — GitGalaxy's css func_start is correct in both cases.
Bug 1 — keyframes_statement name branch is dead code (precision)
if node.type == "keyframes_statement":
for child in node.children:
if child.type == "at_keyword": # never matches in this grammar version
return child.text.decode("utf8").lstrip("@")
return None # always taken
In the pinned tree-sitter-css grammar the at-keyword child of a keyframes_statement has node
type @keyframes (or @-webkit-keyframes), not at_keyword. The loop never matches, so
_get_node_name returns None for every @keyframes node and the walk drops it. Net effect:
tree-sitter reports 0 @keyframes across the entire corpus, even though its parse tree
contains the nodes and GitGalaxy's func_start matches @keyframes fine.
Ledger shape: css/function/existence/agree[gitgalaxy]_vs[ctags,tree_sitter] (5 occ) —
tailwindcss_atrules/theme.css:443,449,457,463 (nested in a Tailwind-v4 @theme block) and
gutenberg_css_modules/button.module.css:237 (top-level). All 5 are real @keyframes rules;
GitGalaxy is right, the audit reader was blind.
Bug 2 — bodyless @layer a, b; counted as a function (recall)
_get_node_name's at_rule branch returns "layer" for both:
@layer wp-ui-components { … } — block form, which GitGalaxy's func_start matches (its
(?=[^{]*\{) lookahead requires a block)
@layer wp-ui-utilities, wp-ui-components, …; — a bodyless cascade-layer ordering statement,
which GitGalaxy deliberately does not match
GitGalaxy's css func_start counts only block-bearing at-rules — the same
"body-bearing definitions only" convention this very audit tool already applies when it drops
C/C++ forward declarations (class Foo;). The bodyless @layer a, b; is the CSS analogue. The
audit should not credit it as a real function GitGalaxy missed.
Ledger shape: css/function/existence/agree[tree_sitter]_vs[ctags,gitgalaxy] (4 occ) —
gutenberg_css_modules/{button,card,tabs}.module.css:1 and tailwindcss_atrules/index.css:1.
(3 of the 4 are additionally obscured by rank/line occurrence-alignment fuzz — GitGalaxy's count
for the block form in those files is already correct.)
Fix
_get_node_name, keyframes_statement branch: accept child types @keyframes /
@-webkit-keyframes (keep at_keyword for forward-compat), fall back to "keyframes".
_get_node_name, at_rule branch: return None when the node has no block child.
at_rule / keyframes_statement appear in no other language's NODE_MAPS entry, so the change
is css-only. After the fix, GitGalaxy and tree-sitter agree on the function count in every one of
the 21 css corpus files (zero diffs), recall_audit.py css counted-misses goes 4 → 0, and css
Func Found / Func Precision both reach 100% with no asterisk.
Fixed in the same PR as this issue, alongside the two ledger verdicts and the
docs/language_status/css.md §9 capstone.
Summary
tests/tools/tree_sitter_accuracy_audit.py's_get_node_namemis-reads two CSS at-rule nodeshapes, making the tri-comparison audit disagree with GitGalaxy where GitGalaxy is actually
correct. Both surfaced during a
tri-comparison-ledger-sweeppass oncss. Same bug class as#1313 (which fixed
media_statement/supports_statementbut left these two wrong).Neither is a GitGalaxy engine defect — GitGalaxy's
cssfunc_startis correct in both cases.Bug 1 —
keyframes_statementname branch is dead code (precision)In the pinned
tree-sitter-cssgrammar the at-keyword child of akeyframes_statementhas nodetype
@keyframes(or@-webkit-keyframes), notat_keyword. The loop never matches, so_get_node_namereturnsNonefor every@keyframesnode and the walk drops it. Net effect:tree-sitter reports 0
@keyframesacross the entire corpus, even though its parse treecontains the nodes and GitGalaxy's
func_startmatches@keyframesfine.Ledger shape:
css/function/existence/agree[gitgalaxy]_vs[ctags,tree_sitter](5 occ) —tailwindcss_atrules/theme.css:443,449,457,463(nested in a Tailwind-v4@themeblock) andgutenberg_css_modules/button.module.css:237(top-level). All 5 are real@keyframesrules;GitGalaxy is right, the audit reader was blind.
Bug 2 — bodyless
@layer a, b;counted as a function (recall)_get_node_name'sat_rulebranch returns"layer"for both:@layer wp-ui-components { … }— block form, which GitGalaxy'sfunc_startmatches (its(?=[^{]*\{)lookahead requires a block)@layer wp-ui-utilities, wp-ui-components, …;— a bodyless cascade-layer ordering statement,which GitGalaxy deliberately does not match
GitGalaxy's
cssfunc_startcounts only block-bearing at-rules — the same"body-bearing definitions only" convention this very audit tool already applies when it drops
C/C++ forward declarations (
class Foo;). The bodyless@layer a, b;is the CSS analogue. Theaudit should not credit it as a real function GitGalaxy missed.
Ledger shape:
css/function/existence/agree[tree_sitter]_vs[ctags,gitgalaxy](4 occ) —gutenberg_css_modules/{button,card,tabs}.module.css:1andtailwindcss_atrules/index.css:1.(3 of the 4 are additionally obscured by rank/line occurrence-alignment fuzz — GitGalaxy's count
for the block form in those files is already correct.)
Fix
_get_node_name,keyframes_statementbranch: accept child types@keyframes/@-webkit-keyframes(keepat_keywordfor forward-compat), fall back to"keyframes"._get_node_name,at_rulebranch: returnNonewhen the node has noblockchild.at_rule/keyframes_statementappear in no other language'sNODE_MAPSentry, so the changeis css-only. After the fix, GitGalaxy and tree-sitter agree on the function count in every one of
the 21 css corpus files (zero diffs),
recall_audit.py csscounted-misses goes 4 → 0, and cssFunc Found / Func Precision both reach 100% with no asterisk.
Fixed in the same PR as this issue, alongside the two ledger verdicts and the
docs/language_status/css.md§9 capstone.