Skip to content

The api rule has no stated contract: 7 languages' own visibility idiom is invisible to it, and 5 others count any public token #2730

Description

@squid-protocol

Found by the corpus wave that closed the second half of #2729. Once the rosetta gate started asserting the api rule instead of the converted orphan count, every language's api rule had to be pointed at a real public surface in that language's own vocabulary — and seven of them cannot see the idiom their own language uses to make a function public.

What the wave measured

37 of 46 corpus languages now plant a public surface their api rule matches: pub (rust, zig), public (java, csharp, kotlin, php, groovy, swift, solidity), global (apex), export (cpp, javascript, typescript, shell, makefile), a capitalised name (go), a per-function export statement (scheme, tcl, powershell, ruby), a module header (haskell), or a file-level declaration where the language has no per-function concept (dockerfile EXPOSE, yaml on:, css @property, html id=, yacc %define, m4 AC_SUBST, cobol ENTRY, agc EQUALS).

Seven cannot, and the corpus records 0 rather than manufacture a construct nobody writes:

language how the language makes a function public what the api rule matches
abap FORM subroutines are public by default PUBLIC SECTION / REMOTE FUNCTION / EXPOSED / DEFINE VIEW — all need a CLASS, RFC metadata or a CDS definition
ada a subprogram declared in the package spec package X is — a spec, i.e. a separate .ads compilation unit
dart a top-level function whose name does not start with _ export / part of, annotations, and class|mixin|enum|extension|typedef declarations
matlab a function file is public by definition only a classdef methods block
objective-c a method declared in the @interface FOUNDATION_EXPORT / OBJC_EXPORT / extern / @property / IB*
ruby public :name (top-level defs are private on Object) module_function and Sinatra-style routes
shell export -f name ^[ \t]*export\s+NAME — variables only, -f never matches

Two more of the same family, found while planting: yaml's rule lists push\|pull_request\|workflow_dispatch\|issues as triggers but not workflow_call, which is the actual reusable-workflow API; perl's only rule-visible export form (@EXPORT_OK = qw(...)) also counts state_mutation, and use Exporter\|parent\|base also counts import.

Why this is one finding, not seven

The rules disagree about what "public surface" means, in both directions:

  • Too narrow (the table above): the language's own visibility idiom is invisible, so the metric reads 0 for a file that exposes everything it defines.
  • Too broad: java/csharp/php/kotlin count a bare \bpublic\b, so a public field, a public class and a public method are three api hits and a modifier anywhere in the code stream counts; go's third alternative ^[ \t]+\b[A-Z]\w+\b(?!\() counts any indented capitalised token, i.e. a reference to an exported name, not a declaration.

api feeds _calc_api_exposure and _calc_documentation, so both directions land in scored risk. On the corpus this reads as language bias with nothing wrong in the corpus: identical planted intent, api 0 in one language and 3 in its neighbour, purely from what the regex accepts.

Fix shape

Give the api rule a stated contract — a declaration that makes a named function or type visible outside this file — and audit all 46 against it, rather than fixing seven regexes one at a time. The narrow half is mostly a missing alternative (export\s+-f\s+NAME for shell, public\s+: for ruby, an @interface method line for objective-c, a top-level non-underscore Type name( for dart, workflow_call for yaml). The broad half needs the \bpublic\b alternatives anchored to a declaration the way go's first alternative already is.

Per corpus AGENTS.md rule 8 and #2669's paired-work rule, any rule change here is corpus-visible: it must land with the matching plant in keyword-rosetta, or it manufactures a fresh red cell. The corpus side is ledgered meanwhile as api-no-plantable-idiom (upstream-question, citing this issue).

Part of #2669. Siblings: #2729 (the gate half, done), #2727 (orphan census is name recurrence — which is why an export statement naming its own function zeroes api_orphan_credit in assembly/powershell/ruby/tcl).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginecore-engineModifications to the central physics and parsing enginemetricsHeuristics, risk exposures, and topological math updates

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions