Skip to content

refactor(cognitive,nexits): declare Branch, Switch, Loop, Catch, ElseIf and Exit #1697

Closed

Description

@dekobon

Objective

Declare Branch, Switch, Loop, Catch, ElseIf and Exit per language and route cognitive's nesting and increment arms, cyclomatic's statement arms and nexits through them. Zero drift.

Umbrella: R00: #1690 · Planning ID: R07: #1697
Completion prerequisites: R05: #1695, R06: #1696

Status (2026-10-31): implemented on branch refactor/1697-control-flow-roles (20 commits over origin/main 96a45849, tip fa3f316f); every checkbox below is met on the tree and the evidence is summarised in the completion comment. Merge prerequisite outside the tree: the output submodule commit af5c6222 (#1720's 33 Rust snapshots) is on the submodule's local main and not yet pushed. Two behaviour changes ride on the branch as their own commits after the zero-drift migration: #1720 (Rust type-syntax for) and #1602 (Elixir keyword sections).

Status (2026-10-26): both prerequisites are merged to main (PR #1717, e2fd7193). The plan below predates R06's DSL; the briefing comment of this date lists what landed since, the consumer shape this inherits, and the traps the last two packages paid for — read it before planning.

Why this exists, and why after R05: #1695 and R06: #1696

Lesson 19's founding cases are all in this family — C/C++ ternary and range-for uncounted by cognitive (#172, #173), Java enhanced-for (#178), Python match scoring zero for both cyclomatic and cognitive (#212) — and each fix was an audit table built by hand across twenty languages. ElseIf is the largest hand-written per-language predicate in the tree (grammar-dispatch.md §4: three macros, three hand-written impls, one constant false for Elixir that lesson 10 calls a stub). Exit already has a per-language macro, impl_exit_match_kinds! in src/metrics/nexits.rs, which cognitive's jump arm restates.

It needs R05: #1695 because cognitive's nesting expression includes owns_Ternary and its boolean-sequence arm reads pays_ShortCircuit, which R05: #1695 declares. It needs R06: #1696 because the nesting expression includes owns_Closure (a lambda body resets nesting — #1103's shared function-boundary rule). Cyclomatic's keyword-vs-statement distinction (If the token vs IfStatement the node, #284) is an owners/payers split, and ElseIf is a subtraction in cognitive (an else if pays the increment but not the nesting), expressible only once Branch is a row.

Implementation steps

  • Branch (if-like owners) and a separate Switch role (the switch-like container kinds): standard cyclomatic's policy expression omits owns_Switch because CaseArm pays; modified cyclomatic and cognitive's nesting include it. The declaration says what a switch is; the root expressions say who counts it. (Switch is added to R01: #1691's inventory under this package's name; R01: #1691 lists it from the start.) Loop (every for spelling: classic, range, enhanced, for…of, foreach, do-while, Tcl foreach/dict for, iRules), Catch, ElseIf (§4's three strategies become three row forms — parent_clause, prev_sibling, clause; Elixir declares absent with the reason, or a text_gated_by row if cond/else can be told apart — decided here), Exit (return, throw, yield, co_return, exit; Bash return/exit commands by text).
  • Cognitive: nesting reads owns_Branch ∪ owns_Switch ∪ owns_Loop ∪ owns_Ternary ∪ owns_Catch ∪ owns_Closure, minus ElseIf (cognitive/cpp.rs nests on SwitchStatement today; the expression keeps it); compute_booleans reads pays_ShortCircuit; the js_cognitive! body shrinks to the walk.
  • Cyclomatic: impl_cyclomatic_c_family! / _js_family! / _java_like! take their decision set from the rows and collapse to one macro that differs only in the policy expression.
  • nexits: impl_exit_match_kinds! becomes owns_Exit.
  • Delete the replaced lists inside the consumer boundary; bypass gate clean.

Tests and edge cases

  • tests/parity/{cognitive,cyclomatic,exit}_cross_language_parity.rs unchanged and passing.
  • ElseIf per language: an if / else if / else chain, a genuinely nested if inside an else block, and the language's own clause shape (elif, elsif, elseif, else_clause > if) — the predicate must distinguish the first from the second.
  • Zero drift; both snapshot forms; plain run; bench-scaling on the nested-if probe since ElseIf consults the chain; chain-audit.

Acceptance criteria

  • Every (language, Branch|Switch|Loop|Catch|ElseIf|Exit) pair has rows or absent(reason).
  • rg -o 'impl_is_else_if_(\w+)!' finds no invocation; §4's table in grammar-dispatch.md points at the row forms.
  • The three cyclomatic macros are one.

Verification and completion evidence

  • Corpus diff per language; bench-scaling exponents; chain-audit; BCA_GATE: line.

Activity

  1. added
    refactorCode maintainability / tech-debt cleanup (no behaviour change)
    on Oct 23, 2026
  2. dekobon commented on Oct 23, 2026

    @dekobon
    OwnerAuthor

    Tracking is ready

    The body now links the master issue and the work packages it references. Native parent and blocked-by relationships match the listed completion prerequisites. Implementation and acceptance checkboxes remain open; prerequisite closure and the R04: #1694 go decision govern execution order.

  3. dekobon commented on Oct 26, 2026

    @dekobon
    OwnerAuthor

    Briefing for planning — what landed since this was written (PR #1717, e2fd7193 on main)

    The plan above is still right in outline; it was written against the pre-R06 DSL and consumer shape. Everything below is what the body does not know. 132 pending R07 cells remain across the 25 tables (six roles × 22 languages, the rest absent).

    DSL surface now available (big-code-analysis-ast/src/roles/mod.rs)

    • Owner attributes: gated_by f / text_gated_by f / holds_payer (R05), plus callable, callable_when f, opens K, opens_by f (R06). Every gate is a named fn(&Node, &[u8], Ancestors) -> bool in roles/<lang>.rs; a gate the Python reader cannot see by name is not a gate.
    • Emitted per row: OWNERS, PAYERS, EXCLUDED, WRAPS, CALLABLE, TEXT_GATED, and owns / owns_kind / owns_via / pays_at_leaf[_kind] / pays_at_wrapper / pays_at_token_kind / is_callable[_kind] / lists_kind / project. owns_kind(kind, …) is the form every cognitive arm uses — one kind_id() read per node, bound once at the top of compute; a guard that re-reads it is the regression refactor(getter): declare Modifier, DeclKeyword and Primitive through role tables #1693 / refactor(checker,getter): declare FuncOpener, Closure, Container and opens_space; migrate entry-point callers #1696 removed.
    • lists_kind(kind) is the only byte-less emission (the kind table, gates aside). The byte-less Checker spellings forward with Ancestors::known(&[]), never Ancestors::unknown(); Tcl's string gate reads "no parent" as a script body, so the known-empty chain is a per-site decision, not a default. ruby_byte_less_spellings_stay_the_kind_table is the pin to copy where a row's gate reads the chain.
    • TEXT_GATED per row; nargs::tests::byte_less_spellings_read_only_rows_without_a_text_gate and nom's twin pin the rows the byte-less is_func / is_closure readers depend on. An Exit or Branch row that reads bytes must not be read by a byte-less spelling.
    • Shared fragments ..c_family_x!() / ..js_family_x!() / ..tcl_family_x!() splice into owns / pays; per-dialect gate macros (cpp_family_gates!, js_family_binding_gates!, tcl_family_string_gates!) emit the named gate fns.
    • utils/role_tables.py must learn every new attribute keyword — it parses the DSL for the three gates, and python_reader_agrees_with_the_compiled_tables holds it to the compiled constants. The dsl_gates proof table in roles/mod.rs's tests declares each attribute in every position it can sit; a @scan terminal that reads a word the fold consumes must sit above the fold rules, or it is reachable only when the word comes first and no production row need spell the losing order (astra finding on refactor(roles): declare every language's space tree, calls and string literals as role rows #1717; comment at the arms).

    Consumer shape R07 inherits

    • Cognitive (src/metrics/cognitive/<lang>.rs) already reads ternary / short_circuit / null_safe / func_opener / closure as _ if row::owns_kind(kind, …) guard arms after the kind arms. R07 converts the remaining kind arms — IfStatement, the loops, SwitchStatement, CatchClause, Else, the IfStatement if !Self::is_else_if(…) gate — the same way. enter_function_boundary(…, stops) takes func_opener::CALLABLE (or OWNERS for Java / Groovy / Kotlin, deliberately; C# keeps its own list because CALLABLE is gates-aside) and is not R07's, but every new arm sits beside it.
    • nexits.rs: impl_exit_match_kinds! is 6 of the 10 remaining .role-bypass-baseline.txt lines (the other 4 are Elixir's byte-less kind table, enhancement(elixir): add text-aware dispatch for def/defp/defstruct metrics #275). R07's Exit row clears them; --update is remove-only, so a swap cannot hide.
    • Elixir: defmodule / def are Call nodes told apart by text, through one elixir_declaration read shared by FuncOpener and Container (pinned by a counter). cognitive/elixir.rs's elixir_section gates keyword-form else: / rescue: / catch: on an owner list — that list is open bug fix(cognitive/elixir): keyword sections gated on an owner list, block sections not #1602, and R07's Branch / Catch rows are where it is fixed or explicitly deferred; say which in the plan.
    • The three cyclomatic macros the plan collapses: impl_cyclomatic_c_family! is a known cause-2 rustfmt-bail entry ($ternary $(| $short_circuit)+ is not parseable Rust) — the rewrite is the chance to retire that baseline line, and .claude/rules/formatting.md says what not to try.

    Traps the last two packages paid for

    1. A chain handed to a row must be the queried node's own (lesson 103). Ancestors::of_children(body) is the way to ask a row about a body's children; build it inside the arm that has decided the node is a body, never before the kind test — ahead of it, it ran for every node and a 64k-deep expression cost 3–6 s per metric.
    2. ElseIf consults the chain, and impl_is_else_if_{parent_clause,prev_sibling,clause}! in checker.rs are three strategies (grammar-dispatch §4: parent is else_clause; previous sibling is else; the clause node is the else-if), with Go / PHP / Python hand-written and Elixir a constant false. The row wants one gated_by per strategy, each a named fn; Ancestors::previous_sibling is the chain-fed sibling read, and the byte-less forwarding needs the known-empty-chain decision per language.
    3. Nest every cognitive fixture under an if so a reset of the enclosing nesting is observable: every flat lambda fixture in the tree passed with nesting.conditional = 0 injected into the arm until the audit-tests pass rewrote them (python_lambda_contributes_lambda_nesting is the corrected shape). R07's Branch / Loop / Catch arms want the same: a fixture where the arm's own increment and the nesting it inherits are both non-zero, with the alternatives named in the expected: comment.
    4. Perturb the fixture as well as the row: owners_covered in roles/call_string_tests.rs iterates the defensive alias list separately and requires each to be declared — a dropped defensive alias was invisible until then. The space-tree tests pin every row answer per kind string in a hand-written table (roles/space_tree_tests.rs); the R07 twin should do the same for the six roles, and each else if strategy needs its three shapes (chain, nested if in else, the language's own clause).
    5. Zero-drift oracle: ~/bca-evidence/1696/ has the drivers (oracle3.py, recovery_oracle.py, perturb.py), the verbatim-oracle source, the base binaries and 27,024 baseline records at 7425561f. R07 re-bases on e2fd7193: rebuild bca and verbatim-oracle there, recapture, then compare per slice. The recovery sweep's cut set must include keyword boundaries (lesson 102). Keep everything under ~/bca-evidence/1697/, not /tmp (AGENTS.md, "Oracle evidence lives under a durable path").
    6. Bench on an idle host only. cognitive/nested-fn, nom/nested-arrow and npa/java-deep-expression are the depth probes nearest R07's paths; three unrelated probes tripped at load average 21–29 and cleared at idle. Add the probe this plan already names for the ElseIf chain climb on a deep else if ladder, and falsify it with the climb reinstated.
    7. Self-scan: roles/mod.rs is baselined at sloc 1430 / ploc 688 against 1300 / 550; cognitive/kotlin.rs and cognitive/rust.rs halstead.effort sit just over 50 k from the *_kind spelling. Every DSL addition and every converted arm needs make self-scan-write-baseline-headroom in the commit that moved it (AGENTS.md, baseline-refresh discipline; split commits need the rebase --exec form).

    Process that worked on R06 / R08

    Per-language-family story commits (Java → JS family → kind-only → C++ / ObjC → C# → Kotlin / Groovy / Ruby → Python / Elixir), each BCA_GATE: pass; a completion-review commit; then simplify-rust → audit-tests → rust-optimize → five parallel reviews (the review checklist, performance / recursion, least-reviewed code, acceptance criteria against the issues, astra) → astra on the fixes, twice. Squash the cleanup passes into one commit before the PR and keep the story commits. For scale: the review passes found 11 test gaps, 2 pre-existing performance defects on touched paths, and 1 DSL reachability bug that the story commits' own gates did not — budget for them.

  4. dekobon commented on Oct 31, 2026

    @dekobon
    OwnerAuthor

    Completion — R07 implemented on refactor/1697-control-flow-roles

    Tip fa3f316f, 20 commits over origin/main (96a45849); the branch base was e2fd7193, and the story commits were rebased with identical per-commit diffs. Every checkbox in the body is ticked against the tree; this comment is the evidence. Full records live under ~/bca-evidence/1697/ on the author's host (README.md indexes them; reviews/ holds every checkpoint; acceptance-report.md is the independent 53-row audit).

    What landed

    Commit Scope
    8df4fccc Phase 0: two ElseIf scaling probes, oracle/recovery/perturbation drivers, #1720 filed from the keyword-outside-owner measurement
    8fa309d6 Java + Perl pilot: impl_cyclomatic_rows! shape fixed (per-tier term lists, extra/constraints, build-time cross-tier disjointness on LEAF_KINDS); ElseIf as a pays [] split row
    71de2cce cfcbb0a4 fed874e1 JS family, C family + ObjC, nine kind-list languages (Groovy, C#, Kotlin, Go, Bash, Lua, PHP, Ruby, iRules)
    712aae61 95033bdc bd80d267 3901ab84 C2a remediation: family fragments, paying_roles!(…, control_flow), shared else_if_parent_clause_gate! / else_if_prev_sibling_gate! emitters, compare-chain prefilters (slice_contains 14–28 → 0 per Halstead body), the test-lang-gates macro-inheritance rule
    c96cc8fb efc6b283 277db30f 5a: Python (ternary if declined by the payer gate; Elif the one ElseIf payer any grammar has; sole-if-under-else gate read off the chain before scanning) and Rust (count_try, let … else pays itself); keyword_payers_outside_owners pins
    dce25219 c83e9dec 5b: Tcl + Elixir through TclCommandWord / ElixirCallTarget, cached per visited node on FoldCache (Ancestors::classified); elixir_declaration a projection of the same read; impl_is_else_if_clause! deleted
    9b2de0b8 f0632335 R07 close: grammar-dispatch.md §4 on the rows, DSL docs, baseline refresh
    86cb2034 #1720 (behaviour): Rust type-syntax for — impl … for, HRTB, for<'a> fn, and impl for<'a> Fn(…) (the fourth parent, found in review) — no longer a decision; Halstead untouched; 33 output-submodule snapshots, 387 spaces
    bb8fc577 #1602 (behaviour): Elixir else: / rescue: / catch: score for any Call riding a do:; two per-list / per-argument memos; two width probes
    9a05080e Phase 3 (squashed): simplify-rust / review / audit-tests fixes, impl_else_if_from_row! with a compile-time !TEXT_GATED pin, a third Elixir memo for a quadratic inherited from main, parse_elixir fuzz target + 15 R07 recovery seeds on the existing targets, WMC scope in the #1720 entry, gate fix for hand-written(…) macro invokers
    fa3f316f post-rebase: npm/ruby.rs bypass exemptions name the rows main's dbbf3536 tables restate

    Acceptance criteria

    • Every (language, role) pair has rows or absent: rg 'pending R07' roles/ → 0; census 287 → 157 lines (all remaining pending are R09). Absent with reasons: Rust Catch; Perl Switch; Elixir ElseIf; Lua Switch; Bash/Go/Lua/Kotlin/… Catch/Guard as stated on each row; Ccomment/Preproc all six.
    • rg -o 'impl_is_else_if_(\w+)!' → nothing; impl_exit_match_kinds!, impl_cyclomatic_{c_family,js_family,java_like}! deleted; grammar-dispatch.md §4 re-derived: parent-clause (C, Cpp, Mozcpp, Objc, Rust, JS×4; PHP two-word by its own gate), prev-sibling (C#, Groovy, Java, Kotlin), Go parent-is-if, dedicated clause (Bash, iRules, Lua, Perl, Ruby, Tcl; PHP one-word), Python sole-statement, Elixir absent.
    • One cyclomatic macro: impl_cyclomatic_rows! for 19 languages; Python/Rust/Tcl/Elixir hand-written reading rows (ternary decline + loop/try else; count_try; per-handler try and CaseArm∩Loop on Command; per-word tier table).
    • Parity suites tests/parity/* untouched (git diff --stat empty), 31/31 passing.
    • ElseIf per language: roles/control_flow_tests.rs — 22 walk-order row tables + 19 is_else_if_* tests covering chain / nested / clause shapes; else_if_chain_scores_below_its_nested_twin_in_every_language through the metric.
    • Bypass baseline 10 → 4 (the four remaining are Elixir's enhancement(elixir): add text-aware dispatch for def/defp/defstruct metrics #275 byte-less kind table); coverage baseline 6,561 → 6,303 (remove-only); make role-bypass / role-census / role-coverage OK.

    Zero drift, then exactly two changes

    Oracle (bca CLI: metrics under a 7-variant option matrix, ops, dump, find, count, plus the library's verbatim export) over the integration corpora + a fixture per language, 24,652 files / 345,128 outputs:

    Capture vs Differing
    every migration slice (C1 … 5b) base 0
    whole corpus at perffix (end of C2a) base 0 / 345,128
    5a slice (Python + Rust) base 0 / 46,746
    5b slice (Tcl + Elixir + iRules) base 0 / 126 (no corpus population; fixture roots)
    Phase 3 simplify pass each slice's predecessor 0 (elixir 70, tcl+irules 84, php+ruby+perl 154)
    whole corpus at the tip base 207 / 345,128 — 201 Rust (#1720: 397 spaces, cyclomatic ↓ and MI ↑ only) + 6 Elixir (#1602: the R07 fixture, cognitive only). Nothing else.
    post-rebase, populations main touched pre-rebase tip 20 / 184,562 — four C++ files, npm/npa fields only (main's own #7b6ec276/#310cca8e)

    Recovery sweeps (every fixture cut at each line/offset/operator/word boundary, both binaries): C1 … C5a 0 differing; 5b 11,688 inputs, 0. One drift caught in flight and kept: C#'s catch token stranded under recovery when read at its clause.

    Perturbation sweeps: 26 (5a) + 16 (5b) + 23 (audit-tests) production mutations, each caught by the named test (expect populated); the one uncaught (Tcl try paying flat 1 vs per-handler) is unreachable at the pin (one on error, no trap) and documented rather than pinned on invalid input.

    Performance

    • make bench-scaling: 93/93 probes within bound at the tip (bench/scaling-1602-final.log). New probes: cognitive/else-if-ladder 0.94, cognitive/wide-if-siblings 0.79, cognitive/python-wide-if-siblings 1.00, cognitive/elixir-keyword-sections 1.02, cognitive/elixir-rejected-keyword-list 1.20 (1.92 / 1.68 / 1.67 with their memos removed — each discriminates).
    • make chain-audit: rc 0 at Phase 0, 5a and Phase 3.
    • Interleaved criterion A/B (8 rounds): C1 pilot no consistent direction; 5b Tcl/Elixir probes 0.80–1.03 median head/base with controls at 0.95–0.99 (bench/c5b-README.md). Deterministic evidence instead: IR check — every impl_cyclomatic_rows! body folds to one switch i16 with kind_id the only miss-path call (ir/tip-5be8a8c3/); call_keyword_reads / command_name_reads counters pin one text read per call / command per visit (4→1 Tcl, 9–12→1 Elixir).
    • Cost audit at Phase 3: every added gate is a chain read, an own-children read, or a cached sibling read, asked ≤1× per node per metric; no regression.

    Gates

    make pre-commit → BCA_GATE: pass (gate=pre-commit) at every commit; check-test-lang-gates-compare COMPARE_REF=origin/main → no test lost a build; single-feature -p builds green with differing filtered-out counts (ast: rust 289 / tcl 274 / elixir 263 / go 254; root: rust 601 / tcl 475 / elixir 527 / go 463 / python 597 / none 345); make fuzz-check builds all targets, seeds replay, parse_elixir 2,000 runs clean.

    Patch coverage (plan §6.7, coverage/README.md): 99.73 % (1,117 / 1,120 changed executable lines) against a floor of max(base 97.65 %, head 98.94 %) = 98.94 %, same toolchain and CI commands on both revisions; the three missed lines were a non-owner early return (now tested) and two is_enabled() continues a single-feature leg reaches.

    Reviews

    C0, C1, C2a, five-agent round, C2 (5b: astra + cost audit), C3a ×2 (#1720 found abstract_type; #1602 found a pre-existing quadratic), C3b, Phase 3 skill passes (simplify-rust ×3 agents, rust-optimize, review, audit-tests) + four parallel reviews (astra, cost, acceptance, least-reviewed), C4 on the squash. All findings fixed and re-reviewed; dispositions in reviews/.

    Open before merge

    1. Push the output submodule commit af5c6222 to dekobon/big-code-analysis-output main (parent gitlink already recorded in 86cb2034) — awaiting authorisation.
    2. Open the PR.
  5. dekobon commented on Oct 31, 2026

    @dekobon
    OwnerAuthor

    Evidence record (supersedes the ~/bca-evidence/1697/ path citations above)

    Per the temp-file tiers rule that landed in #1733, a claim cites what reproduces it, not a path on one host. The numbers in the completion comment stand; this is how each was produced, so they can be re-measured.

    Revisions. Branch base e2fd7193; branch tip after the second rebase 7af369d4 (25 commits over origin/main 95f5008f). Output-submodule commit for #1720: af5c6222. Toolchain rustc 1.99.0, cargo-llvm-cov 0.9.1, cargo-nextest 0.9.146.

    Zero-drift oracle. Two release binaries per comparison — bca from cargo build --release -p big-code-analysis-cli, and a verbatim-export oracle (a 60-line binary crate depending on the root with features = ["all-languages"] that prints Ast::analyze's FuncSpace tree as JSON lines). Driven over tests/repositories/ (the integration corpora: serde, DeepSpeech, pdf.js) plus one hand-written fixture per language, with metrics -O json under seven option variants (--exclude-tests × --cyclomatic-count-try=false, --metrics cyclomatic|cognitive|nexits), ops, dump, find call|string, count; outputs compared byte-for-byte after normalising the fixture-root path. 24,652 files, 345,128 outputs. Results: 0 differing at the migration's last commit vs e2fd7193; 207 at the pre-rebase tip (201 Rust = #1720, cyclomatic and MI only, 397 spaces by position; 6 Elixir = #1602, cognitive only, the R07 fixture); at 7af369d4 vs e2fd7193, 247 — the same 207 plus 40 C++/Mozcpp outputs on four DeepSpeech headers whose only changed fields are class_npm_sum / coa / class_methods / total_methods / class_coa / total, i.e. main's own 7b6ec276 (fix(npa/cpp)) brought in by the rebase.

    Recovery sweep. Every fixture cut at each line, byte offset, operator and word boundary, both binaries, fail-closed on a non-zero exit: 14,508 inputs at 5a, 11,688 at 5b, 0 differing.

    Perturbation sweeps. Production mutations applied from an in-memory backup and restored, full --lib suite per mutation: 26 (5a) + 16 (5b) + 23 + 21 (two audit-tests rounds), each caught by the named test; the one uncaught (Tcl try paying flat 1 vs per handler) is unreachable at the pin (one on error, no trap) and documented in cyclomatic/tcl.rs rather than pinned on invalid input.

    Performance. make bench-scaling 96/96 at 7af369d4; the five R07 probes' perturbed exponents are recorded in their rationale strings in big-code-analysis-bench/src/shapes.rs. IR check: cargo rustc --release -p big-code-analysis -- --emit=llvm-ir, demangle, count switch i16 / icmp eq i16 / call in each Cyclomatic::compute body — every impl_cyclomatic_rows! body is one switch with kind_id the only miss-path call (Java 1 / 0 / 1, C 1 / 0 / 1, Perl 1 / 0 / 2); identical at 5be8a8c3 and b140cf5c. make chain-audit rc 0.

    Coverage. cargo llvm-cov clean --workspace; cargo llvm-cov --no-report nextest --all-features --workspace --locked; cargo llvm-cov report --workspace --json on e2fd7193 and 11bbd049, codecov.yml ignores applied to both: project 97.65 % → 98.94 % lines; patch 1,117 / 1,120 = 99.73 % against the 98.94 % floor.

    Tier-1 follow-ups (drivers and fixtures with no permanent home yet, to be filed with the PR): the oracle / compare / recovery / perturbation drivers, coverage_diff.py, the IR check script, and the 21 per-language R07 fixtures.

  6. dekobon commented on Oct 31, 2026

    @dekobon
    OwnerAuthor

    History restructured for review

    The branch's 27 chronological commits (preserved locally as backup/1697-27-commits) carried three generations of the else-if design and ten review-pass commits that reshaped the two behaviour fixes after they landed — a reviewer walking them would review code that no longer exists. Rebased onto origin/main 0a9b6ebd and rewritten as four final-shape commits, each one reviewable on its own:

    # Commit What Gitlink
    1 3e0609b2 fix(utils): the test-lang-gates derivation reads a macro from its invokers (standalone; applies on main) main's 9076c554
    2 f673cbef refactor(roles,…): the six control-flow roles declared and read everywhere — the zero-drift migration 9076c554
    3 357c1ffb fix(cyclomatic/rust): #1720, with its snapshots af5c6222
    4 4cb989c2 fix(cognitive/elixir): #1602 af5c6222

    The final tree is byte-identical to the 27-commit tip except one CHANGELOG sentence that cross-referenced the fixes from the refactor entry (each entry now stands alone).

    Zero drift re-established on commit 2's tree, which had never existed as a commit before: whole-corpus oracle (oracle.py / compare.py as recorded above, --jobs 8) at f673cbef vs base e2fd7193 — 984 raw differences of 345,128; 944 are the fixture-root path rename, the 40 that survive normalisation are the cpp/mozcpp NPA fields of main's 7b6ec276; R07's own drift 0. And f673cbef vs the previous tip (7af369d4's capture): 207 differing — rust 201 / 33 files, fields cyclomatic.{sum,average,modified.*} and mi.{sei,visual_studio,original} only; elixir 6 / r07.ex, cognitive only — i.e. tip − refactor = exactly #1720 + #1602.

    Per-commit make pre-commit in a fresh worktree: commit 1 BCA_GATE: pass; commits 2–4 recorded on the PR.

  7. dekobon commented on Nov 1, 2026

    @dekobon
    OwnerAuthor

    PR open: #1741. Final chain on origin/main 0a9b6ebd: b7bb9024 (gate fix) → 4e401612 (refactor, zero drift) → 6c639f71 (#1720) → f53f55c7 (#1602); output-submodule af5c6222 pushed to dekobon/big-code-analysis-output main. Each commit BCA_GATE: pass in a fresh worktree; check-test-lang-gates-compare OK against main.

  8. added a commit that references this issue on Nov 1, 2026
    363d0e7
  9. dekobon commented on Nov 1, 2026

    @dekobon
    OwnerAuthor

    Working-cache records (attached before the cache was cleared)

    The regenerable evidence under the working cache (corpus captures, coverage profiles, per-checkpoint binaries, bench logs, IR dumps — ~134 GB) is deleted; every number it supported is recorded in the evidence-record comment above with the command and revisions that regenerate it. What was not regenerable and had no tree home is zipped here (98 files, 2.6 MB uncompressed):

    Still in the cache for R10 / R11, as their steps say: oracle.py, compare.py, recovery_oracle.py, perturb.py, coverage_diff.py, ir_check.sh, snapdiff.py, verbatim-oracle-src/ (source only), fixtures-r07/, fixtures-c5b/, fixtures-0e/.

    Attached in the next comment: bca-1697-records.zip (429 KB, 98 files).

  10. dekobon commented on Nov 1, 2026

    @dekobon
    OwnerAuthor
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

    refactorCode maintainability / tech-debt cleanup (no behaviour change)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions