Repository navigation
perl args: traditional subs have no formal signature -- ground truth only checked the declaration, and GitGalaxy's own shift/my@_ counting only saw the first statement #1519
Description
Summary
args_exact_match for perl measured 137/937 (14.6%) in docs/self_scan/tree_sitter_accuracy_history.csv -- second-worst score in the table, reading as "GitGalaxy's perl args regex is badly broken." As with shell (#1518), it wasn't: confirmed all ~800 mismatches were real=0 got=N, where traditional Perl subs (sub foo { my ($x,$y) = @_; ... }) have NO formal parameter list in the declaration at all -- args arrive via body-level idioms (my (...) = @_, my $x = shift, bare shift), and both the ground-truth measurement and GitGalaxy's own engine had real, fixable gaps in reading those idioms.
Root cause 1 (measurement): ground truth only checked the declaration
_get_param_count had no perl branch at all -- it checked for a formal parameters field, found nothing (traditional Perl has none), and returned 0 regardless of the body's real idiom.
Root cause 2 (engine): single match only ever saw the first arg-unpacking statement
Confirmed via bugzilla/Bug.pm::ValidateDependencies ($fields->{dependson} = shift; $fields->{blocked} = shift; my $id = shift || 0; -- three separate shift statements, real arity 3) and many subs mixing my $class = shift; (invocant) with a later my ($a, $b) = @_; (the rest) -- GitGalaxy's regex-based counting took one .search() per function and only ever counted the first matching statement.
Root cause 3 (engine, real false-positive): bare shift matched shift @other_array/shift(@other_array)
The old (\bshift\b) alternative matched the literal word "shift" anywhere, including calls that shift a COMPLETELY DIFFERENT array (shift @some_queue;), nothing to do with unpacking @_.
Root cause 4 (engine gap): my @statuses = @_; (bare array catch-all) wasn't recognized at all
Distinct from my ($x, $y) = @_ (fixed-size destructure) -- a parenless my @array = @_ catches ALL remaining args as a variadic "rest", extremely common after shifting off a fixed prefix (e.g. my $class = shift; my @statuses = @_;). The regex only recognized the parenthesized form.
Fix (implemented, see PR)
tests/tools/tree_sitter_accuracy_audit.py: new_count_perl_real_args, preferring a real Perl 5.20+ signature node if present, else recursively walking the sub's body (via tree-sitter's real parse, not descending into a nested sub's own body) summing everymy (...) = @_(including a bareundefplaceholder slot used to skip an unwanted positional arg, e.g.my ($a, undef, $c) = @_;-- confirmed viabugzilla/Bug.pm::_check_component, still a real consumed argument) and every bareshiftcall found anywhere in the body.gitgalaxy/core/detector.py: new opt-in_args_findall_sum_groupsrouting flag -- scans the whole block and SUMS every matching statement's contribution instead of taking the first.gitgalaxy/standards/language_standards.py: tightened theshiftalternative to excludeshift @other/shift(@other); added a new alternative for the baremy @array = @_catch-all idiom.
args_exact_match: 137/937 (14.6%) -> 769/937 (82.1%).
Known remaining gap (documented, not fixed)
A nested anonymous sub's own my (...) = @_ (a closure/callback defined inside another sub, e.g. bugzilla/Bug.pm::_cf_accessor) gets summed into the OUTER sub's count too, since GitGalaxy's flat regex scan has no real nested-block-boundary awareness the way the ground-truth walker (which explicitly stops at a nested sub boundary) does. Fixing this on the engine side would need real block-boundary detection within the text-scanning architecture -- noted as a real, if uncommon, source of overcounting rather than chased further here.
Why this isn't "GitGalaxy loses to tree-sitter here"
For this one specific signal (parameter count), in this one specific circumstance (no formal parameter-list syntax exists), a plain AST/tree-sitter-only tool has nothing to read at the declaration and can only ever report 0 -- correct, but useless for coupling/complexity scoring. GitGalaxy's body-aware regex is the more informative measurement here. Full writeup: docs/why_gitgalaxy_beats_ast_here.md.
This only affects extraction-pillar args-counting accuracy (epic #813) and the args_exact_match measurement (epic #1227/#1261), not risk scoring beyond the signal's own coupling number.
Activity
fix(shell,perl): args-counting for languages with no formal parameter…
fix(perl): shield-corruption and legacy-prototype fixes for tree-sitt…
squid-protocol commentedon Aug 15, 2026
This was already fixed by PR #1520 (
fix(shell,perl): args-counting for languages with no formal parameter-list syntax, merged 2026-08-14) -- that PR's own body said "Fixes #1518, #1519" but GitHub only linked #1518 via closing-issue-references, so this one never auto-closed despite being resolved.Independently re-verified against current main:
_count_perl_real_args(ground-truth counter intests/tools/tree_sitter_accuracy_audit.py),_args_findall_sum_groups(gitgalaxy/standards/language_standards.py), and the summing routing logic (gitgalaxy/core/detector.py) are all present and cover all 3 root causes described here (plus a 4th this issue didn't originally enumerate: the baremy @array = @_catch-all).args_exact_matchfor perl now measures 923/938 = 98.4%.Closing as already resolved.
test(perl): lock in args-summing behavior from PR #1520 (#1666)