Skip to content

branch has no stated contract: handler keywords, the syntax words of one conditional, and goto count as decisions in some languages and not in others #2822

Closed

Description

@squid-protocol

Part of #2812 (Phase 3; the branch row of standards/signal_contracts.py is draft). Found by the Phase 0 cause triage on 2026-09-06: keyword-rosetta's string-literal-selective-shielding ledger entry had been excusing 12 red branch cells by cross-product, and when its signal was narrowed to what a danger-only literal can actually move, five of those cells had no explanation at all. Each turned out to be documented in the language's manifest notes and never filed.

What the corpus reads

Planted: 3 decisions per language (if / else / a loop), plus 2 safety constructs. 38 languages read branch 3. These do not:

language reads what the extra hit is shape
cpp 4 catch in a.cpp — branch includes catch, dual with safety's try/catch A · handler keyword
ruby 4 rescue in a.rb — same dual A
csharp 4 goto — dual with high_risk_execution (fortran's GOTO shape, fortran-goto-dual-branch-highrisk) C · goto dual
swift 4 guard … else — the guard and its own else clause B · syntax words of one conditional
sqlite 5 one CASE expression — CASE/WHEN/THEN/ELSE/END all count B
ada 4 end if (ada-end-if-branch-inflation) B
shell 5 [ … ] test brackets (shell-test-brackets-in-branch) B
livecode, powershell, tcl, makefile 4–5 then/end if, trap/continue, trap (batch4-dual-keyword-overlaps) A / B

27 of the 46 branch rules name catch, rescue, except or goto; most languages simply plant their safety construct with a token their branch rule does not happen to match. The rules disagree, and the schema comment ("Includes: if, else, switch, for, while, catch, try …") says the handler keywords should count — which 38 languages contradict.

The contract question

One sentence, in the #2730 shape: branch matches a statement that chooses between control-flow paths at runtime. The three corollaries the audit above needs:

  1. A handler is not a decision. catch/rescue/except/finally/ensure mark where control arrives after a throw; the decision was made by the throw. They are safety's (count contract corollary 4: a token owned by another rule is not a second signal). Retire them from every branch rule and from the schema comment.
  2. One conditional is one hit. else, elsif, end if, then, WHEN/THEN/END, a guard's own else — the continuation and closing words of a construct already counted. Anchor on the opening keyword only. (ada, sqlite, swift, shell, livecode.)
  3. An unconditional transfer is not a decision — already decided for assembly's jmp/call/ret (assembly/agc_assembly: branch counts unconditional transfers — 23 of 25 hits are call/ret/jmp, not decisions (#2545's shape) #2764/fix(core-engine): assembly + agc_assembly branch counts decisions, not unconditional transfers (#2764) #2779) and for return (kotlin: branch rule counts 'return' — inconsistent with java/swift/c siblings #2545/fix(standards): stop counting bare return as branch in 6 languages (closes #2545) #2634); goto is the same shape (csharp, fortran, cpp's rule).

typescript has the mirror finding on safety (3 against a plant of 2): unknown ×2 and never — type keywords counted as runtime guards. It rides here because it is the same corollary-4 question from the other side, and the two rules must be audited together.

Consumers

branch feeds _calc_cog_load (cognitive load), control_flow_ratio, the cascading-flux proximity weight (spatial_correlation.py Block 6 — a handler within 150 chars of a write currently triples it in the weighted view) and the Silencer Region pairs. Corpus: risk_cognitive_load is 80% in band; the eight cells above are its low-hanging residue.

Method

The rule-contract-audit skill (worked example: #2765 / docs/state_mutation_rule_contract.md). Expect most languages to narrow by one token, the corpus cells above to land on 3 without a re-plant, and risk_cognitive_load to tighten. Corpus side: the ledger entries branch-counts-non-decision-keywords and typescript-type-keywords-count-as-safety (keyword-rosetta, Phase 0 triage PR) record the cells and cite this issue; retire them with the fix.

Activity

  1. added
    enhancementNew feature, sensor, or structural signature
    metricsHeuristics, risk exposures, and topological math updates
    core-engineModifications to the central physics and parsing engine
    on Sep 6, 2026
  2. squid-protocol commented on Sep 6, 2026

    @squid-protocol
    OwnerAuthor

    Another instance for this contract, measured while auditing #2806 — cobol's branch counts a bare out-of-line PERFORM <paragraph>, which is an unconditional call, not a conditional or a loop:

    "branch": re.compile(
        r"\b(IF|ELSE|EVALUATE|WHEN|PERFORM|UNTIL|VARYING|TIMES|DEPENDING\s+ON|...)\b", re.I)

    PERFORM is in the alternation unconditionally, so it counts three different constructs as one: PERFORM UNTIL <cond> (a loop — a branch), PERFORM 5 TIMES (a loop — but TIMES already counts it, a dual), and PERFORM SOME-PARA / PERFORM A THRU B (COBOL's procedure call — not a branch at all; it is the language's invocation form, which is why it is also the missing half of the #2806 census for COBOL).

    Measured on the language-crucible data/cobol (570 files): 21,549 branch hits, 2,191 of them (10%) a bare PERFORM <para> or PERFORM A THRU B on its own statement.

    Related consequence worth recording here rather than acting on: keyword-rosetta's data/cobol/main.cbl has the same plant gap #2806 found in abap/m4/makefile/objective-c — its DISPATCH-PARA displays a banner and calls nothing. Planting the canonical PERFORM PROBE-IO. PERFORM PROBE-RISK. moves raw_state_unreferenced 2.75 → 2.25 (both in band) at the cost of moving the gated branch cell 3 → 5 on this defect, so #2806's corpus PR deliberately left it unplanted and recorded it in docs/unreferenced_by_name_contract.md. Once branch stops counting a bare PERFORM, the cobol plant becomes free and should land with it.

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

    core-engineModifications to the central physics and parsing engineenhancementNew feature, sensor, or structural signaturemetricsHeuristics, risk exposures, and topological math updates

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions