Repository navigation
orphaned_logic reports 100% dead code for five languages whose invocation model never names the callee — the family #2727 closed without covering #2806
Description
Activity
- addedbugUnintended behavior or logic failure in the engineUnintended behavior or logic failure in the enginemetricsHeuristics, risk exposures, and topological math updatesHeuristics, risk exposures, and topological math updatescore-engineModifications to the central physics and parsing engineModifications to the central physics and parsing engine
on Sep 6, 2026 Addressed in #2825 (+ corpus keyword-rosetta#82), with one correction to this issue's own premise that a future reader should see before the fix shape:
Four of the five languages here do name their callees. Measured on both corpora at engine main
87cfc933:abap—PERFORM probe_branchis an invocation by name, and the census sees it: real-world ABAP (language-crucible, abapGit) reads 8 unreferenced subroutines in 124, a 6% rate, entirely throughPERFORM.m4— bare-name macro expansion.makefile— a prerequisite (main.mk's one wired probe,$(call probe_branch), already cleared).objective-c— a selector send.
What those four had in common was keyword-rosetta, not the engine: every median language's
maindispatches its three probes (python'sentry()callsprobe_branch/probe_io/probe_risk), and in these fourmaindeclared adispatch/entryunit that invoked nothing at all —FORM dispatchwrote a banner,- (int)entry:returned its argument,m4_define(probe_dispatch, [$1])named no probe. Planting each language's own idiom moves all four from 3.25 to the median with no engine change. The "identical planted intent in every language" premise this issue reasoned from was false for exactly these cells.jcl is the real case, and shape (a) is what it got. Nothing in JCL references an EXEC step; the nameable unit is the PROC, which the
apirule counts and the slicer does not extract.jcl.pydeclaresinvocation_model: "positional"(a top-level language property — not a rule:language_lens.pycompiles every string value insiderulesinto a regex) and the census is not computed there. Worth adding to this issue's evidence: of the 42 crucible steps that did clear the flag, none were invoked — they collided with unrelated text (a step namedCREATEbeside inline SQL in aSYSIN DD *block,COBOLbeside the word inside a DSN,CRTABSrepeated seven times in one job). Both the 89% and the 11% were noise.Shape (c) landed as a full rename, not just a re-reading:
orphaned_logic→unreferenced_by_name,state_slop_orphans→state_unreferenced,raw_state_slop_orphans→raw_state_unreferenced, with an in-place column migration for existing databases. The contract, its six corollaries and the 46-language audit are indocs/unreferenced_by_name_contract.md.Shape (b) is still open for two languages, in the opposite direction: #2823 (haskell/scheme read 0.25/file because a module export list and a type signature clear the flag).
- added 5 commits that reference this issue
on Sep 6, 2026 - added 5 commits that reference this issue
on Sep 20, 2026 - added 6 commits that reference this issue
on Oct 1, 2026
orphaned_logicreports every function in the file as unused for five languages whose invocation model does not name the callee. #2727 fixed a different half of this metric and its closing comment says explicitly that it did not reach this one — but the issue is closed COMPLETED and the ledger entry still carriesdisposition: upstream-bug,still_reproduces: true, pointing at it.Measured 2026-09-06 on engine main
a59ecf6b/ corpus main2038a86. Ledger:orphan-detection-is-name-recurrence.The measurement
Baseline is 2.50 orphans/file — 13 probe functions across 4 files, 3 of them called from main. Five languages sit at 3.25, which is 13/4: every function orphaned.
cobol is the near-miss that proves the mechanism rather than an exception to it: 11 of its 13 paragraphs read orphaned, and the two that clear are
DISPATCH-PARAandPROBE-BRANCH— the only two paragraph names that appear a second time anywhere in the corpus, inmain.cbl'sALTER DISPATCH-PARA TO PROCEED TO PROBE-BRANCH.The nine copybook paragraphs, entered throughENTRY 'PROBE-X'alternate entry points, are named once each and all read dead.What #2727 fixed, and what it said it did not
#2727 replaced a whole-file token-frequency test with a span-scoped name-reference test.
_is_orphan(detector.py~L7086) now counts occurrences of the name outside[start_idx, end_idx), with a declaration discount when the span contains none, and #2777/#2774 have since corrected the boundary pattern and discounted_visibility_exportnames. That work is sound and this issue does not touch it.Its closing comment, verbatim:
It was then closed COMPLETED, and no successor was filed. This is that successor.
The point
The post-#2727 test is a correct name-reference test. The defect is one level up:
orphaned_logicis consumed as "this function is dead", and for these languages a function can be reached without anything naming it.PERFORMis optional, and the corpus's probes are entered throughENTRYalternate entry points, which name the paragraph inside a quoted literal rather than as a call.So the metric answers "does any other text name this function" and is read as "is this function unused", and for five of 46 languages those are different questions with opposite answers. Downstream it is not cosmetic:
orphaned_logicfeedsrisk_tech_debt(jcl 48.8 against a 38.7 median) and drives the orphan→api conversion thatapi-contextual-baseline-fixdocuments.Candidate shapes
(a) A per-language invocation model. A language declares whether its callable units are reached by name (
python,java,go) or positionally / by fall-through (jcl,cobol,makefile,m4). For the second grouporphaned_logicis not computed — the question is unanswerable without a real call graph, and a metric that cannot be answered should be absent, not maximal. Mirrors the_dependency_capturepattern: a per-language declaration in the registry, mechanically testable, no heuristics.(b) Teach the test the invocation forms. COBOL
PERFORM <name>andENTRY '<name>', Make prerequisites, m4 bare expansion. Narrower, and it makes the metric more right where it applies — but the JCL case has no form to teach, because JCL has no invocation-by-name syntax at all. So (b) cannot cover the family and would leave jcl exactly where it is.(c) Rename and re-scope.
orphaned_logicbecomesunreferenced_by_name, and the tech-debt formula stops treating it as dead code for languages where the name is not the call. Cheapest, honest, and it fixes the reading rather than the score.My reading is (a) plus (c): the concept is only meaningful where the language names its callees, and the five languages that do not should read n/a rather than 100%.
Corpus pairing
Under (a) the five languages'
raw_state_slop_orphansbecomes n/a and theirapi_orphan_creditre-blesses — noteapi-declared-orphans-are-not-new-surfaceandapi-contextual-baseline-fixboth depend on the current conversion, so this is a coordinated re-bless rather than a one-cell edit. Under (c) nothing in the corpus moves. No plant change under any shape.orphan-detection-is-name-recurrencenarrows to whichever shapes remain.rosetta:rebless-owedunder (a).Part of #2669. Successor to #2727 (closed); related #2754, #2768, #2774, #2777, #2731.