fix(detector): anchor scheme define slices at the outer paren (#2933) - #2960
Merged
Conversation
Scheme (recursive_block_lisp) has no ScopeParsingRegistry entry and is in neither the Mode-A nor Mode-C tuple, so it falls through to Mode B (_slice_by_braces). Mode B anchored each function at match.start(), but scheme's func_start leads with `^[ \t\n]*\(` under re.M -- its newline- inclusive class swallows the blank/blanked-comment lines before `(define`, so the anchor landed at the top of that whitespace run: line 1 for the first form, shifted early for every later one. block hides this (it's .strip()ped), but start_line/end_line were counted from the bad anchor, which also poisoned #2908's is_documented header window. Advance start_idx to the outer `(` for the lisp family only. Same set of matches -> function COUNT is unchanged; only the line numbers move. This keeps scheme consistent with every other language's declaration-start anchor semantics and stays a single slicer-layer change (#2812 rule 4). Tests: multi-declaration start_line/end_line/loc guard, a `#\(`/`#\)` char-literal + string-paren balance guard, and an update to the #2908 scheme is_documented test (its "far comment" case had leaned on the anchor bug -- start_line always 1 -- so the gap now sits between the comment and the define to be genuinely outside the k=5 window). Slicer layer moves recorded line numbers -> golden-master + keyword-rosetta re-bless owed as follow-ups. Closes #2933 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rUcYDAzYYCgrLdHyKBT9G
Contributor
The #2933 slicer fix anchors scheme (recursive_block_lisp) `define` forms at their outer paren instead of match.start(), correcting start_line/ end_line for forms preceded by blank/comment lines. Both golden masters move on exactly 3 scheme/racket corpus files (schemify.rkt, io.ss, thread.rkt), and ONLY on `Start Line`/`End Line`: - schemify.rkt::schemify-linklet 33-1067 -> 83-1117 (50-line license header) - io.ss::extract-permission-mask 398-411 -> 400-413 - thread.rkt::do-make-thread 186-1318 -> 190-1322 LOC, branch/arg counts, control-flow ratio, impact, is_public/is_documented, function names and function COUNT are all unchanged; bless_scope.py reports 0 topological re-solve and no files newly parsed/excluded on both legs. Regenerated per-leg in isolated venvs (full-precision: all deps; zero-dep: PyYAML only) via tests/tools/update_golden_master.py against language-crucible @ v1.2.0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014rUcYDAzYYCgrLdHyKBT9G
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.
Summary
Scheme (
recursive_block_lisp) has noScopeParsingRegistryentry and is in neither the Mode-A nor Mode-C tuple, so it falls through to Mode B (_slice_by_braces). Mode B anchored each function atmatch.start(), but scheme'sfunc_startleads with^[ \t\n]*\(underre.M— its newline-inclusive class swallows the blank/blanked-comment lines before(define. The anchor therefore landed at the top of that whitespace run: line 1 for the first form, shifted early for every later one.blockhides this (it's.strip()ped), butstart_line/end_linewere counted from the bad anchor, which also poisoned #2908'sis_documentedheader window.Fix: for the lisp family only, advance
start_idxto the outer(of the form.end_idxwas already correct. Same set of matches → function count is unchanged; only line numbers move — keeping scheme consistent with every other language's declaration-start anchor semantics and staying a single slicer-layer change (#2812 rule 4).Measured before→after on a 3-
definefile:add1→4,mul6→9,square11→12 (each now lands on its real(defineline).Tests (
tests/core_engine/test_detector.py)test_detector_scheme_start_line_multi_declaration_2933— correctstart_line/end_line/locper define (verified to fail pre-fix).test_detector_scheme_start_line_char_literal_balance_2933—#\(/#\)char literals and a)inside a string don't derail the anchor or the balanced end.test_detector_is_documented_recursive_block_lisp_scheme(Epic: risk_documentation becomes a per-unit coverage ratio (Phase 4 score contract; child of #2812) #2908): its "far comment" case had leaned on the anchor bug (start_linealways 1), so the gap now sits between the comment and the define to be genuinely outside thek=5window; docstring refreshed.Verification
tests/core_engine/+tests/extraction/: 8316 passed, 4 skipped, 9 xfailed, 3 xpassed, 0 failed.tests/ruff_audit.py --ciwith pinnedruff==0.16.0: no new lint findings beyond baseline; format clean.Rebless owed (follow-ups, per #2812 rule 4)
This slicer-layer change moves recorded line numbers, so after merge:
scripts/update_golden_masters.sh); scope-check withbless_scope.py— expect scheme line columns only, no count change.main.Label:
rosetta:rebless-owedCloses #2933
🤖 Generated with Claude Code