Skip to content

fix: eleven adversarial-review findings (seed skipping, manifest corruption, nan p-values, and more) - #100

Merged
sebasmos merged 4 commits into
mainfrom
fix/review-findings
Jul 20, 2026
Merged

fix: eleven adversarial-review findings (seed skipping, manifest corruption, nan p-values, and more)#100
sebasmos merged 4 commits into
mainfrom
fix/review-findings

Conversation

@sebasmos

Copy link
Copy Markdown
Member

What

Fixes eleven defects found by an adversarial review of the integrated codebase (find, then independently verify each finding). Every fix carries a regression test in tests/test_review_fixes.py. All offline; no data or keys needed to review.

High severity

  • blackboard: seed_turn now counts member slots only, so a pre_hook (real-time referee) injection can no longer silently skip the planted seed, which un-matched baseline/intervention pairs and would have fabricated the referee's measured effect.
  • data: options are serialized as a JSON array; an option containing a literal | no longer splits and silently shifts answer_index onto the wrong ground truth (legacy pipe manifests still parse).
  • analysis: lineage_overlap_test short-circuits an undefined statistic to a nan p-value; it previously reported the smallest possible p-value (1/(n+1)) when the observed overlap was nan.

Medium

  • data: Case.meta now round-trips through the manifest (new meta column); the CheXpert support-devices flag, the natural-cue signal, previously vanished on disk.
  • cli: benchmaxxing datasets listed nothing; it now lists the five registered adapters.
  • stats: multiple_comparison refuses non-finite p-values (a single nan silently destroyed every BH rejection in the family).
  • analysis: _resolve_metric always uses the guarded overlap implementations, so undefined cases stay nan instead of reading as a valid 0.0.
  • transcript: numpy-scalar answers are canonicalized; the dump no longer crashes and committed round-trips.

Low

  • analysis: _invoke gains a complete() branch, so gateway backends drive the solo lane as the docstring promises.
  • blind_metric: latch_rate matches per turn; a multi-word decoy term no longer matches across the boundary between two adjacent turns.
  • stats: fisher_exact docstring corrected to the sample (unconditional) odds ratio.

Suite: 222 passed, ruff clean. Note: ten further review candidates could not be independently verified before capacity ran out; they are lower-confidence and can be triaged separately.

- blackboard: seed_turn now counts MEMBER slots only, so a pre_hook (referee) injection can
  no longer silently skip the planted seed and un-match baseline/intervention pairs
- data: options serialized as JSON (a literal '|' in an option no longer corrupts
  answer_index; legacy pipe manifests still parse); Case.meta round-trips through a new
  manifest column (the CheXpert support-devices natural-cue flag survives disk)
- cli: 'benchmaxxing datasets' now lists the five registered adapters (it always printed
  none: it read a never-imported attribute)
- analysis: _invoke gains a complete() branch so gateway backends drive the solo lane as
  documented; lineage_overlap_test short-circuits an undefined statistic to a nan p-value
  (it reported the smallest possible p); _resolve_metric always uses the guarded overlap
  implementations so undefined cases stay nan
- stats: multiple_comparison refuses non-finite p-values (a nan silently destroyed every BH
  rejection); fisher_exact docstring corrected to the sample (unconditional) odds ratio
- blind_metric: latch_rate matches per turn (a multi-word decoy no longer matches across
  the boundary between two adjacent turns)
- transcript: numpy-scalar answers/committed values are canonicalized (dump no longer
  crashes; committed map round-trips)

Suite: 222 passed locally on this branch, ruff clean.
sebasmos referenced this pull request Jul 20, 2026
getattr(datasets, 'registry') returned None since the submodule was never imported, so the command always printed the empty-registry message. Use registry.names() directly.

@maximinl maximinl left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These fixes generally look well targeted, and the regression coverage is helpful. One part may be worth tightening: the new complete() branch in analysis._invoke sends a structured text payload to the gateway as str(payload). That produces a Python dictionary representation rather than the MCQ prompt format a model expects, while the regression test only checks that no TypeError occurs. A small semantic test that captures the prompt passed to complete() — or an explicit formatter/adapter boundary — would give more confidence that direct gateway support produces meaningful evaluations rather than merely running without an exception.

sebasmos added 2 commits July 20, 2026 11:29
…e solo lane

Per @maximinl: analysis._invoke's complete() branch sent str(payload) (a Python dict repr),
so a gateway backend ran without a TypeError but never saw a real question. Add
_payload_to_prompt() to render a text twin payload into a lettered MCQ prompt, and a semantic
test that captures the prompt the backend receives and asserts it contains the question and
options (not a dict repr).
@sebasmos

Copy link
Copy Markdown
Member Author

Thanks @maximinl, you're right, str(payload) sent a dict repr, so the gateway branch ran without a TypeError but never saw a real question. Fixed in 434f059: added _payload_to_prompt() which renders a text twin payload into a lettered MCQ prompt, and a semantic test (test_gateway_backend_receives_a_real_mcq_prompt) that captures the exact prompt the backend receives and asserts it contains the question and options and is not a dict repr. Full suite 406 passing.

@sebasmos
sebasmos requested review from arshnoor08, azzy-chemE and dr-shrey and removed request for PeterLi-jpg, aaaaaashz, armaanvgrewal and azzy-chemE July 20, 2026 12:56

@felipeocampoos felipeocampoos left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed both commits and ran the suite locally on this branch.

Findings addressed (spot-checked each against its regression test):

  • blackboard.seed_turn now counts member slots only — verified test_seed_survives_pre_hook_injection covers the referee-injection-skips-seed case.
  • data.py options round-trip via JSON instead of '|'.join — legacy pipe manifests still parse (dedicated test), and Case.meta survives the manifest round trip.
  • cli.py datasets now correctly lists the 5 registered adapters.
  • analysis._invoke gained a complete() branch for gateway backends, and the second commit fixes the initial oversight (sending str(payload) / a dict repr instead of a real MCQ prompt) — good catch incorporating that review feedback with its own semantic test.
  • analysis.lineage_overlap_test / stats.multiple_comparison: nan-observed-statistic now short-circuits to nan p-value instead of reporting the smallest possible p; multiple_comparison now refuses non-finite input instead of letting a stray nan silently zero out every BH rejection. This one matters most — it's a correctness bug that could have made an insignificant result look significant.
  • blind_metric.latch_rate now matches per-turn instead of over the joined transcript, so a decoy term can't spuriously match across a turn boundary.
  • transcript.py numpy-scalar canonicalization fixes a real crash on dump_transcript for numpy answer types.

Verification:

  • ruff check benchmaxxing tests — clean.
  • pytest — 407 passed, 6 skipped (optional extras not installed: ruptures/torch), 1 failed (test_checksum_is_stable_and_matches_hashlib) — confirmed this failure is pre-existing on main too (Windows CRLF vs the literal-string hash fixture), not introduced by this PR.

Each of the 11 findings has its own named regression test, which makes this easy to verify in isolation. LGTM — approving.

@sebasmos
sebasmos merged commit 0850bea into main Jul 20, 2026
felipeocampoos pushed a commit that referenced this pull request Jul 22, 2026
Implements benchmaxxing/datasets/medmcqa.py mapping MedMCQA's JSON/JSONL rows
(question, opa..opd, cop, subject_name, topic_name) to the shared Case schema,
following the same pattern as the medqa adapter: opa..opd become an ordered
options tuple, cop maps directly to answer_index, and subject_name/topic_name
flow into Case.meta. Registers the adapter in registry.py, so `benchmaxxing
datasets` lists medmcqa alongside the existing five.

Tests cover the fixture round trip, directory resolution, limit, provided ids,
missing-data and out-of-range-cop errors, and the meta mapping (checked on the
Case object directly, since the manifest round trip does not yet preserve meta
on main -- that lands separately in PR #100).

Suite: 403 passed, 6 skipped, ruff clean (the one pre-existing failure,
test_checksum_is_stable_and_matches_hashlib, is a Windows CRLF issue on main,
unrelated to this change).
@sebasmos
sebasmos deleted the fix/review-findings branch July 24, 2026 00:13
sebasmos added a commit that referenced this pull request Aug 4, 2026
…e solo lane

Per @maximinl: analysis._invoke's complete() branch sent str(payload) (a Python dict repr),
so a gateway backend ran without a TypeError but never saw a real question. Add
_payload_to_prompt() to render a text twin payload into a lettered MCQ prompt, and a semantic
test that captures the prompt the backend receives and asserts it contains the question and
options (not a dict repr).
sebasmos added a commit that referenced this pull request Aug 4, 2026
fix: eleven adversarial-review findings (seed skipping, manifest corruption, nan p-values, and more)
sebasmos pushed a commit that referenced this pull request Aug 4, 2026
Implements benchmaxxing/datasets/medmcqa.py mapping MedMCQA's JSON/JSONL rows
(question, opa..opd, cop, subject_name, topic_name) to the shared Case schema,
following the same pattern as the medqa adapter: opa..opd become an ordered
options tuple, cop maps directly to answer_index, and subject_name/topic_name
flow into Case.meta. Registers the adapter in registry.py, so `benchmaxxing
datasets` lists medmcqa alongside the existing five.

Tests cover the fixture round trip, directory resolution, limit, provided ids,
missing-data and out-of-range-cop errors, and the meta mapping (checked on the
Case object directly, since the manifest round trip does not yet preserve meta
on main -- that lands separately in PR #100).

Suite: 403 passed, 6 skipped, ruff clean (the one pre-existing failure,
test_checksum_is_stable_and_matches_hashlib, is a Windows CRLF issue on main,
unrelated to this change).
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.

3 participants