Skip to content

fix(#2409,#2410): livecode func_start -- Mode D routing + LiveCode Builder handlers - #2420

Merged
squid-protocol merged 2 commits into
mainfrom
fix/2409-2410-livecode-lcb-handlers
Aug 29, 2026
Merged

fix(#2409,#2410): livecode func_start -- Mode D routing + LiveCode Builder handlers#2420
squid-protocol merged 2 commits into
mainfrom
fix/2409-2410-livecode-lcb-handlers

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Fixes #2409, fixes #2410.

Problem

livecode extracted exactly one named function from ~900 real handlers across the 98-file
language-crucible corpus.

reality before
named functions ~934 handlers 1 (escape)
func_start raw signals 847 847 counted, 0 sliced into FunctionNodes
.lcb handlers 471 declarations (127 real defs) 0 detected

Two root causes, one PR (they're inseparable)

#2410 — no ScopeParsingRegistry entry → Mode B brace-slice fallthrough

LiveCode has no braces (end <name> terminators), so _slice_by_braces produced one
FunctionNode for the whole corpus. Added a mode_d entry:

  • Statement-anchored openers (on/command/function/getprop/setprop/handler +
    repeat/if/switch/try/unsafe), bare end closer, function_opener for nested
    handlers. Anchoring is required here (unlike other mode_d configs) because the bare end
    closer also spells end if/end repeat/end handler, and function is a LiveCode operator.
  • Anchoring makes next repeat / exit repeat / else if / else fall out for free.
  • A dedicated _slice_by_keywords guard handles if COND then <statement> one-liners (no
    end if), analogous to the Ruby/Elixir inline-modifier guard.
  • New livecode branch in _extract_semantic_name.

Same routing-only failure class as MATLAB #1266 / yacc #2351.

#2409.lcb handler syntax invisible to func_start/args

Added a second alternation arm for LiveCode Builder [public|private] handler <name>(...)
parenthesized, typed. foreign handler (344 FFI binding declarations — C-prototype shaped,
binds to "<builtin>", no body) and handler type <Name>() (function-pointer typedefs) are
excluded by construction (the design decision on #2409: parallel to a C header prototype not
being a definition).

Verification

Independent-scanner name-diff over the whole corpus (ground truth = every real handler
definition header, from a line scanner sharing no implementation with func_start):

934 real handler defs · 934 GG named functions · 0 false positives · 0 missed.
(.livecodescript ~815, .lcb 121 real handler defs.)

  • manual_verification.json: livecode function 1 → 934/934 (PRECISION record for handler
    existence, the chart's staleness anchor). Func Found / Func Precision panels go 0/N → 934/934** + GitGalaxy badge. gg_args_found 2 → 950.
  • Differential Scan (crucible_check.py, full ~80-repo corpus): every diff is livecode or
    its downstream ripple. livecode's one monster function splits into ~934 correctly-sized ones,
    so its global mass share drops ~18× and dominant_language corrects livecode → c.
    Zero unrelated-language diffs. Both golden masters re-blessed, re-verified PASS both modes.
  • ast_accuracy / ruff / mypy / dead-key: no change.

One limitation, filed separately (#2419)

Exactly 1 of the 934 (addExternalFromFile in the 2183-line
revsaveasandroidstandalone.livecodescript) over-extends its body because _apply_literal_shield
mis-reads /* / */ sitting inside that file's string literals ("Android/*", "*/R.java"),
blanking the handler's own end lines. A narrow shield edge, not a Mode D gap — every other
handler slices cleanly — and it does not affect the 934/934 handler-existence count. Its
own PR.

Tests

tests/core_engine/ + tests/extraction/ full: 6803 passed. New:
test_detector_mode_d_livecode_script_handlers, test_detector_mode_d_livecode_builder_handlers,
.lcb handler cases in test_livecode.py (func_start + args, incl. foreign handler /
handler type exclusions).

tri_comparison_chart.svg / tri_comparison_ledger.json are regenerated by the post-merge
tri-comparison-history.yml job, not here (language_standards.py/detector.py are
tri-comparison-audit.yml trigger paths, but that job only measures js/ts/zig and never
regenerates the chart).

🤖 Generated with Claude Code

https://claude.ai/code/session_019Zm1uVBpVEZJ9SB7bWFR8S

…ilder handlers

livecode extracted exactly ONE named function from ~900 real handlers
across the 98-file language-crucible corpus. Two root causes, one PR:

#2410 -- no ScopeParsingRegistry entry, so livecode fell through to Mode B
brace-slicing. LiveCode has no braces (`end <name>` terminators), so
`_slice_by_braces` produced 1 FunctionNode for the whole corpus despite
781 correct raw `func_start` signals. Added a `mode_d` entry with
statement-anchored openers (`on`/`command`/`function`/`getprop`/`setprop`/
`handler` + `repeat`/`if`/`switch`/`try`/`unsafe`), a bare `end` closer,
and a `function_opener` for nested-handler detection. Anchoring makes
`next repeat` / `exit repeat` / `else if` / `else` fall out for free; a
dedicated `_slice_by_keywords` guard handles `if COND then <statement>`
one-liners (no `end if`). Same routing-only failure class as MATLAB #1266
/ yacc #2351. Also added a `livecode` branch to `_extract_semantic_name`.

#2409 -- `func_start` / `args` only knew LiveCode Script's unparenthesized
`on|command|function|getprop|setprop <name>` form. Added a second
alternation arm for LiveCode Builder `.lcb` `[public|private] handler
<name>(...)` -- parenthesized, typed. `foreign handler` (344 FFI binding
declarations, C-prototype shaped, no body) and `handler type <Name>()`
(function-pointer typedefs) are excluded by construction, per the design
decision on #2409.

Verification (independent-scanner name-diff, whole corpus): 934 real
handler definitions, 934 GG named functions, ZERO false positives, ZERO
missed. `.livecodescript` ~815, `.lcb` 121 real `handler` defs.

manual_verification.json: livecode `function` 1 -> 934/934 (PRECISION
record for handler existence; chart's staleness anchor). Func Found /
Func Precision panels go from `0/N` to real; `934/934**` + GitGalaxy
badge. `gg_args_found` 2 -> 950.

Differential Scan (crucible_check.py, full ~80-repo corpus): every diff
is livecode or its downstream ripple -- livecode's one monster function
splits into ~934 correctly-sized ones, so its global mass share DROPS
~18x and `dominant_language` corrects `livecode` -> `c`. Zero
unrelated-language diffs. Both golden masters re-blessed, re-verified
PASS both modes. ast_accuracy / ruff / mypy / dead-key: no change.

One body-extent limitation filed as #2419 (does not affect the 934/934
existence count): exactly 1 handler over-extends its body because
`_apply_literal_shield` mis-reads `/*` / `*/` inside a LiveCode string
literal -- a narrow shield edge, its own PR.

tri_comparison_chart.svg / ledger.json are regenerated by the post-merge
tri-comparison-history.yml job, not here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Zm1uVBpVEZJ9SB7bWFR8S
@github-actions

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

@squid-protocol
squid-protocol merged commit db66ef7 into main Aug 29, 2026
30 checks passed
@squid-protocol
squid-protocol deleted the fix/2409-2410-livecode-lcb-handlers branch August 29, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant