feature/release 2026 29 06#134
Merged
Merged
Conversation
ar7casper
commented
Jul 5, 2026
Contributor
- fix(parsers/python): match imports by module components in both directions
- feat(context): gate local-only suppression on trust_boundaries, not just app type
- fix(cli): add zig to the --language choices for parse and scan
- fix(go-parser): key generic-type methods on base type, not "unknown"
- build(parsers/go): stop tracking the compiled go_parser binary
- fix(reachability): anchor user-input entry-point patterns with word boundary
- fix(parsers): CM-A is_test_file anchored to path components, not substring (BUG-NEW 2,22)
- fix(parsers/zig): u13 call_graph_builder — local-type/builtin/const-alias (BUG-NEW 3,17,41)
- fix(parsers/zig): u14 function_extractor — fn-name/test-classification/container-methods (BUG-NEW 16,26,37)
- fix(parsers/c): u1 call_graph_builder — builtin-leak same-file pre-check (BUG-NEW 13)
- fix(parsers/c): u2 function_extractor — ctor/dtor/struct/union/lambda/operator/template/ns (BUG-NEW 14,15,32,33,35,39,40)
- fix(parsers/c): u3 unit_generator — carry is_inline into the unit (BUG-NEW 29)
- fix(parsers/php): u5 call_graph_builder — variable-fn + parent::/self::/static:: + <?php-tag root cause (BUG-NEW 20,52)
- fix(parsers/c): land deferred [51] member-dispatch + [30] virtual/inherited dispatch
- fix(parsers/ruby): u10 call_graph_builder — parenless/crossfile-class/builtin/method-object/substring-import (BUG-NEW 1,8,11,31,49)
- fix(parsers/php): u6 function_extractor — nested-fn/attribute-start_line/enum/braceless-ns (BUG-NEW 7,25,36,54)
- fix(parsers/php): u7 unit_generator — namespace key-drift + is_static (BUG-NEW 43,28)
- fix(parsers/ruby): u11 function_extractor — nested/singleton/define_method/alias/private/nested-class (BUG-NEW 6,18,24,42,44,50)
- fix(parsers/ruby): guard alias resolution to single unconditional binding (BUG-NEW 31)
- fix(reachability): u12 entry_point_detector — seed silent binary main (BUG-NEW 4)
- fix(parsers/go): u4 BUG-5 — normalize call_graph.json func records to snake_case (BUG-NEW 5)
- fix(parsers/go): [5] re-verify — complete the snake-case normalization schema
- fix(parsers/go): u4 callgraph — func-value alias edge + top-level call routing (BUG-NEW 19)
- feat(reachability): opt-in library-mode seeds the public API surface
- fix(parsers/python): u9 function_extractor — 6 finder bugs (BUG-NEW 9,21,23,34,45,48)
- fix(parsers/python): u8 call_graph_builder — builtin-leak/alias/import-overresolve/inherited-self (BUG-NEW 10,12,27,46)
- fix(parsers/python): [34] re-verify — token-aware property classification (cached_property)
- fix(parsers/python): guard alias resolution to single unconditional binding (BUG-NEW 12)
- fix(parsers/python): resolve self/cls-aliased method calls in the call graph
- fix(parsers/go): classify entry points by signature, not return type or bare next(
- fix(parsers/js): extract module-level block-scoped functions
- fix(parsers/c): resolve static-inline functions in included headers
- fix(parsers/php): keep both same-name defs from conditional/guarded branches
- feat(reachability): warn on silent library blackout across all parsers
- fix(parsers/c): stop same-(file,name) functions collapsing to one func_id
- fix(parsers/python): extract block-scoped def/class units
- fix(parsers/ruby): keep both same-name defs from conditional branches
- feat(reachability): extend opt-in library-mode to all parsers + CLI
- fix(zig,php parsers): attribute generic-container & anonymous-class methods correctly
- docs(zig,php parsers): surface grammar-alignment prerequisite in regression tests
- fix(parsers/php): resolve $this->/self:: calls into used traits
- fix(parsers/c): guard macro-alias resolution against cyclic #defines
- fix(parser_adapter): restore --fresh dataset deletion silently dropped by the feat(reachability): opt-in library-mode seeds the public API surface #117 merge
…tions
`_resolve_import` Strategy 2 bound an imported function to a file whose dotted
module path string-`endswith` the imported module (either direction). That crosses
component boundaries: `from utils import helper` matched `extra_utils.py`
(`'extra_utils'.endswith('utils')`) — a false call-graph edge to the wrong module
that no Python layout can produce.
Fix: match by dotted COMPONENTS, in EITHER direction — the imported module is a
component-suffix of the file path (a repo-root prefix on the file, `src/pkg/auth.py`
for `from pkg.auth import ...`), OR the file path is a component-suffix of the
imported module (the repo-IS-the-package self-import, `auth.py` == `myapp/auth.py`
recorded shallow via relative_to(repo_path), for `from myapp.auth import ...`).
Both are real layouts and are KEPT; only the substring-crossing matches are dropped.
An adversarial review caught that an earlier forward-only version dropped the
reverse direction (repo-is-package self-imports) — a recall regression. Because the
reachability filter keeps only reachable units, a dropped real edge silently removes
attack surface; so an edge that COULD be real (e.g. `from pkg.auth import login` to a
top-level `auth.py`, structurally identical to a self-import) is kept, not forbidden.
Net: strictly fewer false edges than master, never fewer real ones.
Tests (tests/parsers/python/test_call_graph_import_resolution.py): 2 precision drops
(substring-crossing `extra_utils`/`utils`, `extra_auth`/`auth`) + 6 recall guards
(exact, repo-root-prefix, top-level, repo-is-package self-import, nested reverse-prefix,
relative). Full python suite: 12 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ust app type A data-processing library (parser, deserializer, codec) takes untrusted INPUT DATA — that data crossing into the code is the attack surface even with no network listener. The generator sets requires_remote_trigger=False for every library, so the Stage 1/2 prompts emitted 'only flag REMOTE attacker, not local users' and discarded exactly those bugs (tree-sitter: all parser memory-safety findings suppressed until requires_remote_trigger was hand-set). Add ApplicationContext.suppress_local_only(): suppress ONLY when no trust boundary is 'untrusted'. Reuses the already-captured trust_boundaries — no new field. Gate all 7 sites (6 live in prompts/, 1 display in context/). A genuine no-attack-surface library (all-trusted) is unchanged; an untrusted-input library is now analysed. Generator instruction reworded to set the flag from untrusted input, not blanket-false per type. Tests: 8 new (suppress_local_only unit + Stage 1 + Stage 2 present/absent).
The zig parser is dispatched by parse_repository (core/parser_adapter.py:126) and has a working test_pipeline, but 'zig' was missing from the parse/scan --language choices, so 'openant parse --language zig' errored with 'invalid choice'. Pre-existing gap (present on master); surfaced while verifying the library-mode work — zig library-mode is unreachable via the CLI without this. Verified: 'openant parse /tmp/zig-kf --language zig --level reachable --library-mode' now runs (9 -> 21 reachable functions under library-mode).
typeToString had no case for *ast.IndexExpr / *ast.IndexListExpr, so methods on generic types (func (s *Stack[T]) Push()) keyed under class "unknown". Distinct generic types' same-named methods then collided onto one unit id and the store silently overwrote one (data loss). Generic call sites (Gen[K,V](), obj.M[T]()) were likewise dropped from the call graph. - extractor.go: add IndexExpr/IndexListExpr cases to typeToString (bare base type) - callgraph.go: unwrap generic instantiation in analyzeCallExpr; reuse the Ident/SelectorExpr classification (fixes all generic call shapes + receiver) - extractor.go: add duplicateIDWarning() - stderr signal on funcID collision so a future class-key collapse fails loudly instead of silently overwriting Tests: 5 new (generic receiver keys, no-collision data-loss regression, generic calls, dup-guard). go test ./... green; independent + judge verified, no regression. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The binary is listed in .gitignore but was tracked since the initial commit, so it drifted stale on every source change (master's committed binary still emits "unknown.Push"). Untrack it so it stays ignored; CI builds it on every run (.github/workflows/test.yaml) and the dev pipeline rebuilds it when absent (parsers/go/test_pipeline.py). Compile on demand — no committed artifact. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oundary The FastAPI input pattern (Query|Body|Form|File|Header|Cookie)\s*\( and the ArgumentParser pattern lacked a leading \b, so any identifier ending in one of those words (setCookie(, PQsendQuery(, getHeader(, MyArgumentParser() matched as a user-input source and was seeded as a false remote-web entry point across C/Go/PHP/Python repos. Anchor both with \b; qualified forms like fastapi.Query( still match (the '.' provides the boundary). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…undaries Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…and scan Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s in both directions Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rns with word boundary Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tring (BUG-NEW 2,22) Local-only finder-fixes-54. 3 parametrized tests across 5 langs. is_test_file used unanchored 'pattern in path_lower' (zig worst: bare test/spec tokens), so real source whose name CONTAINS a token (latest/contest/attestation/inspector) was silently dropped from extraction (skip_tests=True is the pipeline default). Anchored to exact path DIRECTORY components + basename conventions across c/php/python/ruby/zig repository_scanner. JS/Go already anchored -> untouched (judge-confirmed). Decoys not excluded; real test files still excluded (recall preserved). Judge: AGREE / SHIP-AS-IS. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit d8c5f3fb0387c969a7e7c899a8d59e598c46a477)
…lias (BUG-NEW 3,17,41) Local-only finder-fixes-54 (base master 368b559). TDD; 5 tests in the new tests/parsers/zig/test_call_graph_builder_u*.py. Judge (vs prepared recommendation, independent re-derivation from raw): AGREE / SHIP-AS-IS. CM-B builtin pre-check scoped SAME-FILE (judge-confirmed: no global cross-file fallback; genuine-builtin non-link pinned by a negative test). Combined parser suite: 70 passed, 10 skipped. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 4294ffe24e0814bc2668f1f6c46c3874de56b01e)
…n/container-methods (BUG-NEW 16,26,37) Local-only finder-fixes-54. 7 new tests. [37] fixed grammar node-type keys (variable_declaration + struct/enum/union/opaque_declaration, members=function_declaration) so container methods extract as C.m; [16] first identifier as fn name; [26] anchored test classification. Cross-unit: the [37] fix changes the call-graph edge target to the now-correct qualified id m.zig:C.m -> updated 2 test_call_graph_builder_u13 assertions (judge-verified legitimate, not a weakening). Judge: AGREE / SHIP-AS-IS. (Follow-up: dead _extract_struct_methods left for a separate cleanup.) Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 1aae27a79420beb4ab1ad2f2c064124c221ec26d)
…eck (BUG-NEW 13) Local-only finder-fixes-54 (base master 368b559). TDD; 6 tests in the new tests/parsers/c/test_call_graph_builder_u*.py. Judge (vs prepared recommendation, independent re-derivation from raw): AGREE / SHIP-AS-IS. CM-B builtin pre-check scoped SAME-FILE (judge-confirmed: no global cross-file fallback; genuine-builtin non-link pinned by a negative test). Combined parser suite: 70 passed, 10 skipped. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit ef1a3f91f163547a7652132f65613bb1be56c973)
…/operator/template/ns (BUG-NEW 14,15,32,33,35,39,40) Local-only finder-fixes-54 (base 368b559). 8 tests. struct_specifier/union_specifier branches mirror class_specifier (closes [32] AND the [38] static-call dup — VERIFIED: Helper::compute resolves); ctor/dtor on unqualified leaf; lambda_expression; operator_name; template args in func_id (g<int>!=g); namespace-qualifier vs class-qualifier (namespaced free fn class_name=None). Judge+probe: AGREE / SHIP-AS-IS. Full parser suite 131 passed, 10 skipped. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit e360860ceac539a3d1df0f5068faf560e3e9c6c2)
…G-NEW 29) Local-only finder-fixes-54 (base master 368b559). The C extractor produces func_data['is_inline'] but create_unit dropped it from unit metadata (and the parallel generate_analyzer_output dropped 'isInline'). Carry it in both, matching the is_static/is_exported convention. Adds RF-1 field-contract guard tests/parsers/c/test_c_schema_completeness.py: an explicit producer-key -> dotted-unit-location MAP (+ snake->camel analyzer map) that round-trips each contracted field, so future drops fail automatically; plus a self-check pinning the drift-prone key in the map. 5 tests; c+php parser suites pass. Judge (vs prepared recommendation): AGREE / SHIP-AS-IS; RF-1 realized as the sound field-contract MAP (not a key-superset). Independent+judge concurred. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 5eece7512f6872d878039e4866a32d13d4311a86)
…::/static:: + <?php-tag root cause (BUG-NEW 20,52) Local-only finder-fixes-54. 6 tests. [20] resolve $f() via a single string-literal binding (multi/non-literal declines). [52] parent::/self::/static:: parse as relative_scope (was unhandled -> dropped); parent:: resolves via a class->parent index + cross-file _resolve_class_call (NOT _resolve_self_call, which is same-file/same-class — independent+judge confirmed via a shadow-method probe). DEEPER ROOT CAUSE fixed: extractor stores bodies without a <?php tag, so tree-sitter parsed them as inline HTML -> ZERO call nodes (masked ALL php edges); prepend <?php before re-parse (idempotent, offset-sound, no spurious 'php' edge — judge-verified necessary + in-scope). Judge+independent: AGREE / SHIP-AS-IS. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit fb4983428c0ebd0d38ab7eafcd4b84df37dc7c1d)
…erited dispatch Adds the local-decl type-inference machinery that was MISSING for these two deferred bugs (judge-confirmed last time they couldn't be a resolver tweak). 10 tests; full c suite 50 passed (no regression of the 9 committed c bugs). [51] member-dispatch (sound, same-file): preserve the receiver (_extract_call_name_and_receiver); new _extract_local_var_types (varname->type from declaration nodes incl. pointer/init/reference declarators); methods_by_class index; receiver-type-aware _resolve_member_call resolves w.compute()/w->compute() to Type::compute when the receiver's local-declared type defines it same-file — else FALLS BACK to base-name resolution (no false edge when type unknown). [30] virtual/inherited dispatch (static-declared-type FLOOR + inheritance walk): function_extractor now extracts base classes (_extract_base_classes walks base_class_clause -> class_bases index); _resolve_member_call does a cycle-guarded BFS UP the base chain, resolving to the first ancestor that defines the method. Base* b; b->compute() links ONLY Base::compute (the static type's method) — derived overrides are the DOCUMENTED non-goal (over-approximation = false edges). Override stops the walk; unknown/no-definer -> None. Precision negatives all pass (unknown receiver, free fn unchanged, two-class disambiguation, override-stops-walk, no-ancestor, inheritance cycle). Independent + judge verified SOUND from raw; no false edge introduced vs prior behavior. One pre-existing same-file same-name-cross-namespace mislink is unchanged by this fix (documented optional follow-up). go/python tree changes are separate (already committed). Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit e55be766db832831a716c3c97509f9af9d103d88)
…/builtin/method-object/substring-import (BUG-NEW 1,8,11,31,49) Local-only finder-fixes-54 (base master 368b559). TDD; 10 tests in the new tests/parsers/ruby/test_call_graph_builder_u*.py. Judge (vs prepared recommendation, independent re-derivation from raw): AGREE / SHIP-AS-IS. CM-B builtin pre-check scoped SAME-FILE (judge-confirmed: no global cross-file fallback; genuine-builtin non-link pinned by a negative test). Combined parser suite: 70 passed, 10 skipped. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 74153f98a94f9e8b95c39083d3d0eaf71ea7956e)
…ine/enum/braceless-ns (BUG-NEW 7,25,36,54) Local-only finder-fixes-54. 4 tests. enum_declaration branch (closes [36] AND the [53] dup — enum methods get class_name); recurse nested functions; start_line past attribute_list [25]; [54] braceless namespace metadata carried to following siblings (sibling-not-child of namespace_definition). Judge+probe: AGREE / SHIP-AS-IS. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 7efc40e3339f47c6203a11dbbe6b2776c15a6c5e)
… (BUG-NEW 43,28) Local-only finder-fixes-54 (base master 368b559). - [43] create_unit read func_data.get('namespace') but the extractor writes 'namespace_name' (canonical, emitted in 5 sites) -> unit namespace was always None. Aligned the CONSUMER to read 'namespace_name' (1 read + 2 emit sites; lower blast radius than renaming the producer; no other reader of either key). - [28] is_static produced but never carried into unit metadata -> carried it (create_unit + generate_analyzer_output). Adds RF-1 field-contract guard tests/parsers/php/test_php_schema_completeness.py (producer-key -> unit-reader MAP, encodes the namespace rename leg) + a membership self-check. 6 tests; php parser suite passes. Judge (vs prepared recommendation): AGREE / SHIP-AS-IS; consumer is the correct side for [43]. Independent+judge concurred. SURFACED (separate, out-of-scope, not fixed): php extractor never emits 'visibility' (_get_visibility uncalled) -> private methods report public — logged for a separate fix. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit f193401fa6c74764b274150f5a54ccb01dedc927)
…ethod/alias/private/nested-class (BUG-NEW 6,18,24,42,44,50) Local-only finder-fixes-54. 8 tests. recurse method bodies; is_singleton before initialize; define_method(:sym) registers sym [24] and alias node registers name [42] (DISTINCT AST nodes, judge-confirmed); private/ public/protected keyword-state visibility model [44]; compose Outer::Inner [50]. Judge: AGREE / SHIP-AS-IS. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 825c92d71c686234828215102da60eb584e0de7b)
…ding (BUG-NEW 31) Ruby hunk of the alias-guard (python hunk ships in the python PR). Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (BUG-NEW 4) Local-only finder-fixes-54. 5 tests; 33 passed (detector+reachability), no regress. ENTRY_POINT_TYPES omitted 'main', and _get_entry_point_reasons gated the unit-type signal solely on that set, so a silent main (no decorator/input pattern) accumulated zero reasons -> never seeded -> its callees fell out of the reachable set. Added 'main' to ENTRY_POINT_TYPES + a defensive name=='main' fallback. Language-agnostic; for Go this also requires the BUG-5 camelCase normalization (separate commit) so unitType is read. Judge: AGREE / SHIP-AS-IS. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 95a708fb2d2bdaff619d24c3883aafb3072b601b)
… snake_case (BUG-NEW 5) Local-only finder-fixes-54. 3 tests; 143 passed, 31 skipped, no regress. The Go binary emits camelCase FunctionInfo keys (unitType/startLine/filePath/...) while every Python consumer reads snake_case -> Go func records had unit_type=None, silently disabling ALL unit_type-based logic for Go (entry-point seeding, reachability, by-type stats). Root: the two normalization blocks in test_pipeline.py normalized the WRONG way (emitting camelCase, stale "detector expects camelCase" comment) while EntryPointDetector reads snake. Added a shared idempotent normalize_go_function_records() (camel->snake, already-snake passes through) at both call_graph.json build + reachability-filter boundaries. END-TO-END verified (real Go binary): a silent func main() now seeds reachability via unit_type:main and its helper is reachable (the [4]+[5] payoff). Deliberately NOT touched: the analyzer_output.json camelCase surface (consumed camelCase by repository_index.py/tools.py — a separate intentional contract). Consumer-check corrected the deep-investigation's "likely non-bug" verdict: [5] is a REAL bug on the call_graph surface. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit c33c35ab16e099b72a36464f26b98359cee79bc2)
…n schema Re-verification (independent + judge) of the shipped [5] go-camelCase fix. Confirmed correct on the call_graph.json surface (real bug; analyzer_output.json camelCase is a separate intentional contract, untouched). Gap closed: normalize_go_function_records omitted parameters/returns/is_async (present in Go FunctionInfo); added them with the isAsync->is_async fallback (defense-in-depth — no live consumer reads them yet, but the record now matches the snake-case shape). +2 unit tests (camel->snake full schema + idempotency, no Go toolchain needed). go parser suite: 9 passed. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 908384050b46c9c5afb2d59cc36cba406045c415)
…l routing (BUG-NEW 19) Local-only finder-fixes-54. go test ./... green (3 new go tests); binary rebuilt (go build -o go_parser .). [19] f := helper; f() dropped the edge — collectFuncValueAliases now tracks a SINGLE unconditional name:=<ident> binding and rewrites f() to its target before the builtins filter (reassigned/conditional/non-ident RHS -> dropped, no false edge). DEEPER bug found + fixed (the reported baseline 'direct helper() resolves' was FALSE): resolveCalls routed every call into the method branch via "" == callerInfo.ClassName, so top-level calls produced 0 edges, masking the alias bug — guarded the routing to require a non-empty class match. Scope widened by that one routing line (flagged for the judge). Method-value alias (m := obj.M) = the distinct BUG-044, correctly dropped (out of scope). Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 52440afa1887427c79efe64676477c010f0420bc)
A pure library exposes no main/route/CLI entry point, so the structural detector finds nothing and apply_reachability_filter drops EVERY unit — the library, and any vulnerable sink it contains, is never analysed (verified: a library whose public function calls a private eval() sink scans to 0 units). The public API IS the entry surface for a library. Adds an opt-in `library_mode` to apply_reachability_filter: when set, seed every public/exported function (`is_exported` when the parser provides it, else name-not-underscore) and let the existing forward BFS pull in their callees. The seed merge is union-only, so it can never demote a structurally-detected app entry point — turning the flag on for an app can only ADD reachable units. Default is False, so every existing caller is byte-identical. Threaded through parse_repository -> _parse_python (the Python parse path that applies this filter; other languages compute reachability in their own pipelines and are a follow-on). The CLI --library-mode flag is a thin follow-on passthrough. Tests (tests/test_library_mode_reachability.py): blackout-when-off, public-API-seeded-when-on (private callee reached via the edge), unreferenced- private-stays-out (precision), app-baseline-unchanged, app-mode-on-is-additive- only (adversarial: union can't subtract), and a parse_repository wiring guard. 6 passed; e2e confirmed False -> [] / True -> [public_api, _sink]. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…,21,23,34,45,48) Pilot unit of the local-only finder-fixes-54 batch (base GitHub master 368b559). TDD; 8 RED->GREEN tests in tests/parsers/python/test_function_extractor_u9.py (full python parser suite: 12 passed). Verified per-bug pytest summary inline. - [9] recurse into function bodies (_process_function_tree) — nested def extracted - [21] emit module-level name-bound lambdas (handler = lambda ...) - [23] start_line = first decorator line (was the def line; off-by-N for stacked) - [34] classify @x.setter/@x.deleter as 'property'; getter keeps canonical func_id C.x, setter -> qualified_name C.x.setter (role suffix), preserving func_id == path:qualified_name (the call_graph_builder reconstruction invariant) — order-independent + adds property_role metadata - [45] recurse into nested classes (_process_class_tree) — Outer.Inner.deep - [48] classify test by path COMPONENTS / basename conventions, not the bare substring 'test' (latest.py no longer mis-flagged) Reconciliation: a BLIND /bug-fix derivation initially used an order-based #N func_id suffix for [34]; an independent re-derivation + judge (vs the prepared fix-design recommendation) found it breaks the path:qualified_name invariant and is order-dependent. Replaced with the role-in-qualified_name scheme (judge: SHIP the other 5 as-is). _store_function residual collisions now disambiguate by source line (#L<line>), not emission order. Local-only; not pushed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 24510d1a071b131e8b48aa089d4dbe28c61aa50f)
This was referenced Jul 10, 2026
Closed
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.