Skip to content

test(core-engine): the raw/adjusted api split is not a sum (#2729) - #2747

Merged
squid-protocol merged 1 commit into
mainfrom
fix/2729-raw-adjusted-invariant
Sep 5, 2026
Merged

test(core-engine): the raw/adjusted api split is not a sum (#2729)#2747
squid-protocol merged 1 commit into
mainfrom
fix/2729-raw-adjusted-invariant

Conversation

@squid-protocol

Copy link
Copy Markdown
Owner

Part of #2729 — the last piece of its own "Engine/test surface" half.
Test-only; no production code is touched.

What #2729 asked for here

Engine/test surface: make the split explicit. […] so api asserts what the rule found and
the conversion is asserted separately (as arch_api - raw_arch_api, or not at all).

The gate half landed corpus-side in keyword-rosetta#53 (verify_language.py reads raw_arch_api
as api and pins the conversion separately as api_orphan_credit). #2731/#2734 added the engine
tests for the conversion itself, at both layers that own it — test_detector.py's
api_declared_orphans tests and test_galaxyscope.py's Contextual-Baseline-Fix tests.

One thing was left behind: the recorder test was still documenting the pre-#2731 arithmetic as
an engine invariant.

The stale assertion

test_raw_columns_persist_pre_adjustment_values ended with:

assert row["arch_api"] == row["raw_arch_api"] + row["raw_state_slop_orphans"], (
    "Contextual Baseline Fix invariant broken: adjusted api must equal raw api + raw orphans"
)

Two problems:

  1. It never proved that. Both sides are literals fed into the fixture (hit_vector=[5, 0],
    raw_pre_adjustment={"api": 2, "orphaned_logic": 3}). The test passes on its own arithmetic,
    not on the engine's.
  2. It is false in general since fix(core-engine): the api rule's own declarations are not new orphan surface (#2731) #2734. The conversion credits
    orphans - api_declared_orphans, so a file whose api rule already declared some of its orphans
    records an adjusted value below that sum — and total overlap (every public function uncalled:
    the library case, and every file in the keyword-rosetta corpus) makes it raw_arch_api exactly.

So the message a reader takes from the only recorder-level statement of the contract is the double
count #2731 removed, written down as an expectation. The fixture happens to be the no-overlap case,
which is why 2 + 3 == 5 holds in it — nothing was catching that.

What replaces it

  • The same test now asserts what the raw columns are actually for: the credit is recoverable as
    adjusted - raw, without assuming what it equals. That is the identical subtraction
    keyword-rosetta's gate reads as api_orphan_credit.
  • New test_raw_columns_recover_a_partial_conversion_credit covers the shape the sum-based
    assertion excluded by construction — 4 declared, 3 orphans, 2 of them already public → adjusted
    5, credit 1 — and asserts arch_api != raw_arch_api + raw_state_slop_orphans on purpose, so
    a regression back to the pre-arch_api counts a declared-public, uncalled function twice: 3 functions record api 6 #2731 arithmetic fails here rather than only in the corpus.
  • The section header now says which layer owns which number, so the next reader does not re-derive
    the conversion from the recorder's columns: galaxyscope.py owns the adjusted value,
    detector.py owns api_declared_orphans, these tests own the round-trip.

Verification

Full suite 7626 passed serially (CI's mode), ruff and mypy clean against their baselines. A
test-only change cannot move the golden masters, the tri-comparison baselines or the tree-sitter
baselines, and none of them moved.

Cross-repo

Companion: squid-protocol/keyword-rosetta#57, the corpus re-bless that restores #2729's stated
close criteria (verify_language.py 46/46, bias_report.py --gate exit 0). Neither PR depends on
the other — this one changes no observable count, so it carries no rosetta:rebless-owed label and
its rosetta-audit classifies the outstanding drift as pre-existing until #57 merges.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WfeHRWra1d6Z5uSReFajSq

#2729's fix shape asks for the split between the api rule's own count and the
Contextual Baseline Fix's converted orphans to be explicit in the engine/test
surface, because `api` in the risk equations is not the `api` rule. The gate
half landed corpus-side (keyword-rosetta reads `raw_arch_api` as `api` and
pins the conversion separately as `api_orphan_credit`), and #2731/#2734 added
the detector and galaxyscope tests for the conversion itself. This is the last
piece: the recorder test was still documenting the pre-#2731 arithmetic as an
engine invariant.

`test_raw_columns_persist_pre_adjustment_values` asserted
`arch_api == raw_arch_api + raw_state_slop_orphans` and called it "the
Contextual Baseline Fix invariant". It never proved that -- both numbers are
fed in as literals -- and since #2734 it is false in general: the conversion
credits `orphans - api_declared_orphans`, so a file whose api rule already
declared some of its orphans records an adjusted value BELOW that sum, and
total overlap (every public function uncalled -- the library case, and every
file in the keyword-rosetta corpus) makes it `raw_arch_api` exactly. A reader
would take the assertion as the engine's contract, and it is the double count
#2731 removed, written down as an expectation.

Replaced with what the raw columns are actually for: the credit is recoverable
as `adjusted - raw` without assuming what it equals -- the same subtraction
keyword-rosetta's gate reads. Added `test_raw_columns_recover_a_partial_
conversion_credit` for the shape the sum-based assertion excluded by
construction (4 declared + 3 orphans, 2 already public -> adjusted 5, credit
1), which fails against the old sum on purpose.

Header comment now says which layer owns which number, so the next reader does
not re-derive the conversion from the recorder's columns: galaxyscope.py owns
the adjusted value, detector.py owns `api_declared_orphans`, and these tests
own the round-trip only.

No production code touched; no golden-master, tri-comparison or tree-sitter
movement is possible from a test-only change. Full suite 7626 passed.

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

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

🐦‍⬛ Muninn Security Scan

✅ No security issues found.

🐦‍⬛ Powered by Muninn · Skald Lab

@squid-protocol
squid-protocol merged commit 0e521e8 into main Sep 5, 2026
28 checks passed
@squid-protocol
squid-protocol deleted the fix/2729-raw-adjusted-invariant branch September 5, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant