Skip to content

feat(eval): iSOTA provider-neutral tournament harness - #1185

Merged
mdheller merged 2 commits into
mainfrom
feat/isota-tournament-harness
Aug 1, 2026
Merged

feat(eval): iSOTA provider-neutral tournament harness#1185
mdheller merged 2 commits into
mainfrom
feat/isota-tournament-harness

Conversation

@mdheller

@mdheller mdheller commented Aug 1, 2026

Copy link
Copy Markdown
Member

Operationalizes the Provider Eval Seed Strategy and feeds the Intelligence-Superiority Bench (iSOTA). Binds to the existing eval fabric — does not rebuild it: the tournament outcome is emitted as records conforming to schemas/eval/{metric-definition,model-candidate,benchmark-contract,metric-fact}.schema.json.

What it does

tools/isota_tournament.py runs the Stage 0→4 tournament — governance gate → provider-seed smoke (Corpus A) → Sherlock task, weighted heaviest (Corpus B) → adversarial/stress (Corpus C) → promote — over an EvalItem corpus, and emits spec-valid MetricDefinition + ModelCandidate + BenchmarkContract. Winners' composites become internal_reproduced MetricFacts that the existing dashboard-bff GET /v1/intelligence-superiority already serves.

Two load-bearing invariants (tested, teeth both ways)

  • Provider-neutralprovider_id is a passthrough label and enters no scoring term. Permuting provider labels changes no verdict; a score change does (control is not vacuous).
  • No laundering (the eval-fabric honesty rule) — internal_reproduced means we measured it. Illustrative seed scores are the mechanism's input and are never emitted as data: no ModelCandidate carries a score, and a provisional/seed run emits ZERO reproduced facts and no accepted/rejected status. Only a real-results run (--results) emits internal_reproduced facts.
  • Plus fail-closed Stage 0 governance gate, proven both ways.

Firing the control

A path-scoped workflow (.github/workflows/isota-tournament.yml) runs the producer + tests on any change to the harness, corpus, eval schemas, or tests — so this control actually fires (a never-fired control is worse than none). make validate-isota-tournament for local parity.

Verification (local)

  • python tools/isota_tournament.py → 1 def / 5 candidates / 5 contracts / 0 facts (provisional), all schema-valid; mechanism: 3 would-promote, 2 gated at Stage 0.
  • pytest tests/platform_stubs/test_isota_tournament.py7 passed.

Provenance

EvalItem schema vendored from SourceOS-Linux/sourceos-spec#238 (merged). No app/deploy/image touched — pure tools + schema + test + workflow. Next: the Vue cockpit port; and applying the harness with real run results to populate iSOTA.

… corpora to the eval fabric)

Operationalizes the Provider Eval Seed Strategy and feeds the Intelligence-
Superiority Bench (iSOTA). Binds to the existing eval fabric -- does not rebuild
it: the tournament OUTCOME is emitted as records conforming to
schemas/eval/{metric-definition,model-candidate,benchmark-contract,metric-fact}.

- tools/isota_tournament.py: Stage 0->4 tournament (governance gate -> smoke ->
  Sherlock (weighted) -> adversarial -> promote) over three corpora (A provider
  seed / B Sherlock task / C adversarial). Provider-neutral: provider_id is a
  passthrough label, no scoring term. Emits spec-valid MetricDefinition +
  ModelCandidate + BenchmarkContract; MetricFacts only from REAL run results.
- tools/isota_corpus_seed.json: seed EvalItem corpus (A/B/C).
- schemas/eval/vendored/EvalItem.schema.json: vendored from sourceos-spec #238.
- tests/platform_stubs/test_isota_tournament.py: 7 tests, teeth both ways --
  spec-first validation; provider-label permutation changes no verdict but a
  score change does; Stage 0 fail-closed both ways; and NO LAUNDERING: a
  provisional/seed run emits ZERO internal_reproduced facts and no accepted/
  rejected status (illustrative scores are never emitted as data).
- .github/workflows/isota-tournament.yml: path-scoped workflow so the control
  actually fires; + `make validate-isota-tournament` for local parity.
Copilot AI review requested due to automatic review settings August 1, 2026 01:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

--results mode currently drives accepted/rejected status off illustrative seed scores (and can emit facts for Stage-0-gated candidates), which breaks the stated no-laundering + fail-closed invariants.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

Adds a new provider-neutral iSOTA “tournament harness” that produces eval-fabric records (MetricDefinition / ModelCandidate / BenchmarkContract / MetricFact) and validates them against in-repo schemas, with a seed corpus + invariant tests and a path-scoped CI workflow to ensure the control runs when relevant files change.

Changes:

  • Introduces tools/isota_tournament.py to build and schema-validate an iSOTA tournament bundle (provisional vs --results modes).
  • Adds a seed EvalItem corpus and vendors the EvalItem JSON schema for in-repo validation.
  • Adds invariant/conformance tests plus local (make validate-isota-tournament) and CI workflow wiring.
File summaries
File Description
tools/isota_tournament.py New tournament producer + schema validation + CLI output bundle
tools/isota_corpus_seed.json Seed corpora (A/B/C) items used as tournament input
tests/platform_stubs/test_isota_tournament.py Spec conformance + invariants (neutrality, fail-closed, no-laundering)
schemas/eval/vendored/EvalItem.schema.json Vendored EvalItem schema used to validate the corpus
Makefile Adds validate-isota-tournament target for local parity
.github/workflows/isota-tournament.yml Path-scoped workflow to run producer + tests on relevant changes
Review details
  • Files reviewed: 6/6 changed files
  • Comments generated: 4
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment thread tools/isota_tournament.py Outdated
Comment on lines +155 to +157
# MetricFacts ONLY for real, measured results — never from seed scores.
if results is not None and cid in results:
r = results[cid]
Comment thread tools/isota_tournament.py
Comment on lines +117 to +123
cid, v = c["candidate_id"], verdicts[c["candidate_id"]]
# honesty: without real results, verdict does not set accepted/rejected.
if results is None:
status = "benchmark_candidate"
else:
status = "accepted" if v["promoted"] else "rejected"
gates = ["stage0_governance", "stage1_provider_seed_smoke", "stage2_sherlock_weighted",
Comment thread tools/isota_tournament.py
Comment on lines +224 to +225
corpus = json.loads(SEED_CORPUS.read_text())["items"]
results = json.loads(args.results.read_text()) if args.results else None
Comment thread tools/isota_tournament.py Outdated
Comment on lines +178 to +188
def validate_bundle(bundle: dict) -> None:
md, mc = _schema("metric-definition"), _schema("model-candidate")
bc, mf = _schema("benchmark-contract"), _schema("metric-fact")
for d in bundle["definitions"]:
jsonschema.validate(d, md)
for c in bundle["candidates"]:
jsonschema.validate(c, mc)
for k in bundle["contracts"]:
jsonschema.validate(k, bc)
for f in bundle["facts"]:
jsonschema.validate(f, mf)
…les, enforce format

Copilot's adversarial review found four real defects in the stated invariants; all fixed:

- No-laundering (line 123): emitted accepted/rejected status now comes ONLY from a
  real MEASURED result (--results) vs the promotion threshold — seed axis scores no
  longer set any emitted status. Added a test proving measured value (not seed score)
  drives the verdict.
- Fail-closed (line 157): a Stage-0-gated candidate yields NO MetricFact even when a
  result is supplied for it, and its status is rejected. Added a regression test.
- Spec-first corpus (line 225): main() now validates the seed corpus against the
  vendored EvalItem schema fail-fast.
- Format enforcement (line 188): validate via Draft202012Validator + FormatChecker so
  "format": date-time (MetricFact.ts) is actually checked; added rfc3339-validator to
  the workflow + make target so the check bites (verified: a bad ts now rejects).

9 tests pass; provider-neutral + fail-closed + no-laundering all proven both ways.
Copilot AI review requested due to automatic review settings August 1, 2026 01:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

The current output bundle includes seed-derived composite scores in verdicts, which undermines the stated “no laundering / seed scores are never emitted as data” invariant and should be reconciled before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (4)

tools/isota_tournament.py:102

  • build() always includes verdicts from run_tournament(), which currently contains a numeric composite and a reason string with the composite value derived from illustrative seed axis scores. That contradicts the “seed scores are never emitted as data” / no-laundering invariant (the provisional bundle written to disk still contains seed-derived scores). Consider redacting the composite (and numeric reason) when results is None so the provisional artifact doesn’t publish seed scores.
    ts = ts or datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
    verdicts = run_tournament(candidates)
    corpus_by = _corpus_summary(corpus)
    dataset_ref = "isota:corpus/A%d+B%d+C%d" % (corpus_by["A"], corpus_by["B"], corpus_by["C"])
    workloads = sorted({it["task_family"] for it in corpus})

tools/isota_tournament.py:68

  • The run_tournament() docstring describes a full Stage 0→4 pipeline (including stages 1–3), but the implementation only distinguishes Stage 0 (gated) vs Stage 4 (scored/promoted) and never reports intermediate stage outcomes. This mismatch can confuse consumers of stage_reached/reason; either implement intermediate stages or clarify the docstring to match current behavior.
    """The Stage 0->4 mechanism. Returns {candidate_id: verdict-dict}. Fail-closed at
    Stage 0: a candidate that does not clear the governance floor is rejected there and
    never scored. Promotion at Stage 4 is by composite threshold alone."""

tools/isota_tournament.py:212

  • In seed_candidates(), the parameter name gov_ok is misleading because it only controls the observability governance flag (the rest are hardcoded True). Renaming it to observability_ok would make it clear what the boolean actually represents and avoid accidental misuse.
    def cand(cid, name, provider, family, gov_ok, sc):
        gov = {"api": True, "rate": True, "auth": True, "cost": True, "observability": gov_ok}

schemas/eval/vendored/EvalItem.schema.json:14

  • The schema description says provider-sourced items “must name the provider”, but the provider property currently allows an empty string. Add minLength: 1 so the schema enforces the documented constraint.
    "provider": { "type": "string" },
  • Files reviewed: 6/6 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

@mdheller
mdheller merged commit 0b39024 into main Aug 1, 2026
75 checks passed
@mdheller
mdheller deleted the feat/isota-tournament-harness branch August 1, 2026 01:31
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