Skip to content

Bring the recorded Genomic Intelligence fixtures to contract revision 16 - #99

Merged
bviggiano merged 3 commits into
evo-design:mainfrom
genomicintelligence:fix/gi-test-fixture-sequence-length
Sep 7, 2026
Merged

bviggiano merged 3 commits into
evo-design:mainfrom
genomicintelligence:fix/gi-test-fixture-sequence-length

Conversation

@boldakov

@boldakov boldakov commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

The recorded Genomic Intelligence response fixtures describe a data.input echo the service no longer returns. This brings them to the current published contract and adds the guards that would have caught the drift.

What changed upstream

data.input is an echo of the request. Two contract revisions have narrowed it:

  • Revision 13 (2026-09-03) dropped data.input.sequence_length. It held the 9,198 bp scored window, not the submission, so for any locus longer than one window it disagreed with meta.sequence_length — and reading it was a real defect found in review here.
  • Revision 16 (2026-09-06) dropped submitted_sequence_length and scored_window from the expression echo, and made every data.input a typed, closed object: additionalProperties: false, all fields required, covered by the consumer contract pins for the first time.

Recorded against the live service today:

task data.input
promoter, splice, enhancer, chromatin, annotation {sequence_name}
expression {sequence_name, description, tss_index}
find_genes_and_predict_expression {sequence_name, description}

The derived numbers live in meta, which is where they belong and where the published schema has always covered them: meta.sequence_length for the submission, meta.task_specific_counts.scored_window for the window.

What this PR does

No client change. parse_expression_data already reads meta.task_specific_counts with no echo fallback — that is what the first commits on this branch established. What was stale was the recorded bodies and the prose around them.

  • Recorded echoes updated to the shapes above.
  • Two new tests. A recorded fixture has nothing upstream keeping it honest: a stale one describes a service that no longer exists, and the client it exercises goes on passing. test_recorded_input_echoes_carry_no_derived_key sweeps all seven payloads for the three removed keys; test_the_recorded_expression_echo_matches_the_published_shape pins the two non-trivial shapes by set equality, so a re-added key fails too. Both verified red by reintroducing scored_window into the expression echo.
  • Comments and docstrings that still described the old echo, corrected.

One fixture is deliberately left wrong. test_parse_expression_takes_the_submitted_length_from_meta_not_the_echo keeps all three removed keys and makes them disagree with meta on purpose, so that a reader drifting back to the echo fails here rather than in a user's report. Its docstring now says so explicitly, because "make the fixture match the schema" is the obvious wrong move for the next person.

Verification

62 passed, 2 skipped on tests/sequence_scoring_tests/test_genomic_intelligence.py (the 2 skips are the --integration tests). The live integration test that distinguishes submitted length from scored window is unchanged and still asserts against meta.

Nothing here is a behaviour change for users of the tool; it is fixture and test accuracy.

boldakov and others added 3 commits September 4, 2026 22:40
…recorded shapes

The fixtures at the top of this file are labelled shapes recorded from the live
service, and they carried a data.input.sequence_length the service no longer
returns. It was removed from the echo on all seven predict operations on
2026-09-03 (contract revision 13): it meant the scored window on expression and
the submitted length everywhere else, duplicating meta.sequence_length on six
operations and contradicting it on the seventh. Keeping it in a fixture that
claims to be a recording invites the next reader to reach for it again, which
is the bug 9625541 and c85c15a removed from the tools.

No parser reads the echo, so no assertion moves: 57 passed, 9 skipped, same as
before.

The one place the key stays is the payload in
test_parse_expression_takes_the_submitted_length_from_meta_not_the_echo, which
exists to make meta and the echo disagree. That is still worth pinning --
data.input is additionalProperties: true and no contract pin covers it, so
nothing stops the key returning, and an older recorded body still has it. Its
docstring said the service carries the key today; it now says when it went and
why the test keeps it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Tc2vgq9BQP1YAPYABu8b9
…ld echo

Follow-on to the fixture commit, same key and same reason.

_GOOD_DATA is the minimal envelope the transport and envelope-shape tests hand
back, and its data.input carried a sequence_length of 400. Nothing reads it:
no tool in this package touches data.input at all, and every assertion on that
payload is an identity check against the dict itself. It is now
{"sequence_name": "demo"}, which is what the service echoes for that
submission, so the payload no longer offers a reader a field the API does not
send.

The comment in test_gi_expression_benchmark said, in the present tense, that
data.input carries a sequence_length of its own holding the window. That has
been false since contract revision 13 on 2026-09-03. The two assertions it
explains are still exactly right, and are still the only place the submitted
length and the scored window can be told apart, so only the tense and the
consequence move: a reader of the echo now gets None rather than the window.

60 passed, 9 skipped, unchanged. ruff check and ruff format clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Tc2vgq9BQP1YAPYABu8b9
…ision 16

Revision 13 dropped data.input.sequence_length, which is what this branch
started as. Revision 16 (2026-09-06) went further: it dropped
submitted_sequence_length and scored_window from the expression echo, and made
every data.input a typed, closed object -- additionalProperties: false, all
fields required, and covered by the consumer contract pins for the first time.

Recorded against live PROD today:

  promoter / splice / enhancer / chromatin / annotation  {sequence_name}
  expression                    {sequence_name, description, tss_index}
  find_genes_and_predict_expression        {sequence_name, description}

The client needed no change -- parse_expression_data already reads
meta.task_specific_counts.scored_window with no echo fallback, which is the
whole point of the earlier commits on this branch. What was stale was the
recorded bodies and the prose around them.

Two new tests, because a recorded fixture has nothing upstream keeping it
honest: a stale one describes a service that no longer exists and the client it
exercises goes on passing. test_recorded_input_echoes_carry_no_derived_key
sweeps all seven payloads for the three removed keys;
test_the_recorded_expression_echo_matches_the_published_shape pins the two
non-trivial shapes by set equality, so a re-added key fails too. Both verified
red by reintroducing scored_window into the expression echo.

Deliberately NOT touched: the adversarial payload in
test_parse_expression_takes_the_submitted_length_from_meta_not_the_echo, which
keeps all three removed keys and makes them disagree with meta on purpose. Its
value is that it does not match the current contract, and its docstring now
says so, because "fix the fixture to match the schema" is the obvious wrong
move for the next reader.
@boldakov boldakov changed the title Drop data.input.sequence_length from the recorded Genomic Intelligence fixtures Bring the recorded Genomic Intelligence fixtures to contract revision 16 Sep 6, 2026
@bviggiano
bviggiano merged commit ff5ba88 into evo-design:main Sep 7, 2026
5 checks passed
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.

2 participants