core/evals/frontier_compare
Shay 8f1903e8e7
chore(evals): contracts + bench json + Lane B viewer + chart + audit + demo schema (#62)
* chore(evals, cli): contract standardization + bench --json stdout cleanliness

End-of-session shippability pass.  Three concrete fixes:

1. core/cli.py — bench --json no longer pollutes stdout
   Several bench paths call scripts.run_pulse.run_pulse which prints
   verbose [pulse] traces unconditionally to stdout, breaking jq /
   programmatic consumers of --json output.

   New _bench_stdout_guard() redirects stdout → stderr for the
   duration of the bench run when --json is set.  Operator still sees
   the pulse trace (on stderr), but --json consumers get a clean JSON
   document on stdout.  Applied to all four bench paths: cost,
   articulation, default suite, and --suite all.

   Verified: core bench --suite determinism --json now produces
   parseable JSON; human path still shows 1140 [pulse] lines.

2. evals/{frontier_compare,realizer_guard}/contract.md (new)
   core/contemplation/contract.md (new)

   Each new contract follows the established pattern (37 contracts
   already exist under evals/<lane>/contract.md):

     - What it measures
     - Why it matters (structural win)
     - How to run
     - How to read the output
     - Pass criteria table
     - When it has failed and why
     - Runner / module layout

   Coverage:
     - frontier_compare: both Lane A (CORE-only suites) and Lane B
       (cross-provider prompt_battery) with explicit guardrails
       against mixing — operator asks for the wrong lane combination,
       runner exits 2 with helpful error.
     - realizer_guard: C1/C2 articulation safety boundary — synthetic
       illegal candidates rejected directly by check_surface AND
       former-bug runtime prompts now produce legal articulations.
     - contemplation (ADR-0080): not under evals/ since it's runtime
       infrastructure that consumes eval reports — contract lives at
       core/contemplation/contract.md.  Documents the read-only +
       SPECULATIVE-only + deterministic-replay invariants and the
       shared DiscoveryCandidateSink plumbing convergence (ADR-0080).

3. evals/CLAIMS.md — Tier 2 rows added

   - frontier_compare Lane A: determinism.primary_score, max_versor_condition
   - frontier_compare Lane B: prompt_battery.primary_score (CORE adapter),
     cross-provider artifact persistence
   - realizer_guard: all_claims_supported
   - contemplation: SPECULATIVE-only invariant, deterministic replay,
     additive sink path, no pack mutation (all CI-pinned by tests)

Verification
------------
$ core test --suite smoke -q
67 passed in 27.22s    (no regression)

$ uv run pytest -q tests/test_contemplation_loop.py \
    tests/test_contemplation_pipeline_convergence.py \
    tests/test_frontier_compare_cross_provider.py
27 passed in 4.87s

$ core bench --suite determinism --json 2>/dev/null | jq .results[0].passed
true        (was: JSONDecodeError on prior [pulse] pollution)

* feat(evals/ui): report viewer renders Lane B cross-provider + pass-rate chart

Stop-hook caught that #62 only covered contracts — the 929-line
report_viewer.html was never audited against the new cross-provider
report shape from #61.  Two real gaps:

1. Lane-aware observation drawer
   The drawer hardcoded Lane A (CORE-native) fields: surface,
   grounding_source, anchor_lens_mode_label, versor_condition.
   Lane B (cross-provider) observations carry different fields:
   provider, model, elapsed_ms, error_type, error_message.

   Loading a cross-provider report rendered only the surface row
   with empty `grounding` — the provider + model + timing data
   was unreachable without expanding "Show raw JSON".

   Fix: detect Lane B (presence of `obs.provider`) and render the
   appropriate field set.  Lane A still renders identically (now
   also surfaces trace_hash + register_id when present, which were
   silently buried in the raw JSON before).

2. Pass-rate chart per suite
   The summary strip showed one aggregate Primary % across all
   suites, with no way to see WHICH suite is dragging the score.
   Multi-suite runs (e.g. --suite all) had to expand each panel
   individually to find the failing one.

   Fix: new .passrate-chart element below the summary strip,
   one horizontal bar per suite showing passed/total.  All-pass =
   solid green, all-fail = solid red, partial = green/red split
   at the pass fraction.  CSS only — no new dependencies.

3. SUITE_PREAMBLES gains the prompt_battery entry so the sidebar
   shows the "side-by-side surface evidence across providers"
   description when loading a Lane B report.

Verified
--------
- Brace/paren/div balance unchanged (308/308 / 380/380 / 54/54)
- One <script> tag pair preserved
- Generated a real Lane B report via
  `python -m evals.frontier_compare --provider core --suite prompt_battery`
  for visual confirmation

Out of scope (noted for future PR)
----------------------------------
Sampled 3 `core demo` targets:
- register-tour: clean schema (all_claims_supported, claims, grid)
- audit-tour: both scene_1_* keys AND an empty scenes:[] array — inconsistent
- anti-regression: no all_claims_supported key, uses all_gates_held instead

Demo schema standardization deserves its own PR — operator tooling
would benefit from a uniform top-level success field across demos.

* docs(evals) + chore(demos): systematic audit + uniform success field

Stop-hook caught two real gaps after the contract+UI PR:
- demos had divergent success-field names (all_gates_held vs
  learning_loop_closed vs claim_supported vs nested claims_supported)
- no systematic look at the 48 eval directories had been done

Both addressed concretely; remaining work captured in audit doc
rather than vaguely deferred.

1. Demo schema standardization — uniform all_claims_supported field
----------------------------------------------------------------------
All 9 ``core demo`` targets now emit a top-level
``all_claims_supported: bool`` field.  Existing per-demo fields
(``all_gates_held``, ``learning_loop_closed``, ``claim_supported``,
nested ``claims_supported``) are preserved for backwards compat —
the new field is an alias derived from the demo's existing success
signal, not a replacement.

Operator tooling and the CI gate can now target
``all_claims_supported`` without knowing each demo's idiomatic
field name.

Files touched:
- evals/anti_regression/run_demo.py — adds AND of all_gates_held +
  active_corpus_byte_identical
- evals/learning_loop/run_demo.py — adds AND of learning_loop_closed +
  active_corpus_byte_identical
- scripts/publish_pack_measurements.py — adds AND of the three
  entries in the nested claims_supported dict
- evals/long_context_cost/comparison_runner.py — adds alias for
  claim_supported (singular)

The 5 demos already using ``all_claims_supported`` (audit-tour,
register-tour, anchor-lens-tour, orthogonality-tour, articulation)
are unchanged.

Verified across all 9 demos:
  audit-tour              : True
  register-tour           : True
  anchor-lens-tour        : True
  orthogonality-tour      : True
  pack-measurements       : True   ← new alias
  anti-regression         : True   ← new alias
  learning-loop           : True   ← new alias
  articulation            : True
  long-context-comparison : True   ← new alias

2. docs/EVAL_AUDIT_2026-05-20.md — systematic 48-lane audit
------------------------------------------------------------
Replaces the "future PR" deferral with a concrete document.

Contains:
- Method (what was inspected for each lane).
- Summary (40/48 have contract.md; 18/48 have saved results;
  empty results/ ≠ broken — most lanes regenerate on demand).
- Cross-provider relevance triage:
    * 9 lanes are cross-provider-relevant and could benefit
      from the prompt_battery-style adapter pattern (cognition,
      english_fluency_ood, hebrew_fluency, koine_greek_fluency,
      grammatical_coverage, inference_closure, multi_step_reasoning,
      discourse_paragraph, foundational_*_ood, etc.).
    * 29 lanes are CORE-only by design (versor closure, anchor
      lens, identity divergence, provenance, etc.) — wiring
      providers would be category-erroneous.
- Demo schema standardization status (this PR closes that).
- UI/UX coverage matrix.
- 5 concrete follow-up items, each focused enough for a single
  PR, none requiring architectural change.

Regenerated reports
-------------------
evals/long_context_cost/results/comparison_v1.json and
evals/results/phase2_pack_measurements.json now contain the new
all_claims_supported field (auto-regenerated when validating the
schema change).

evals/frontier_compare/results/sample_core_promptbattery.json
added as a reference Lane B report so the new viewer always has
something to load on first open.
2026-05-20 13:53:13 -07:00
..
results chore(evals): contracts + bench json + Lane B viewer + chart + audit + demo schema (#62) 2026-05-20 13:53:13 -07:00
ui chore(evals): contracts + bench json + Lane B viewer + chart + audit + demo schema (#62) 2026-05-20 13:53:13 -07:00
__init__.py feat(evals): frontier comparison benchmark wave 1 (#52) 2026-05-20 06:27:32 -07:00
__main__.py feat(evals): wire ADR-0082 providers into frontier_compare runner (#61) 2026-05-20 13:22:37 -07:00
contract.md chore(evals): contracts + bench json + Lane B viewer + chart + audit + demo schema (#62) 2026-05-20 13:53:13 -07:00
cross_provider.py feat(evals): wire ADR-0082 providers into frontier_compare runner (#61) 2026-05-20 13:22:37 -07:00
model_registry.py chore(adr): rename ADR-0081 frontier provider adapters → ADR-0082 (#59) 2026-05-20 12:46:13 -07:00
providers.py chore(adr): rename ADR-0081 frontier provider adapters → ADR-0082 (#59) 2026-05-20 12:46:13 -07:00
README.md feat(evals): frontier comparison benchmark wave 1 (#52) 2026-05-20 06:27:32 -07:00
runner.py feat(evals): frontier comparison benchmark wave 1 (#52) 2026-05-20 06:27:32 -07:00

Frontier Compare Benchmarks — Wave 1

This directory contains CORE's first no-handicap benchmark wave for comparing the CORE architecture against frontier-model behavior without pretending the systems are the same kind of machine.

The guiding rule:

If a frontier LLM can solve it, let it solve it.
If CORE can solve something the LLM cannot structurally audit, CORE must prove it.
If both solve it, compare correctness, determinism, traceability, latency, cost, memory, and failure mode.

Wave 1 is deliberately local and CORE-native. It does not call external frontier APIs, does not require provider keys, and does not change runtime behavior. It creates the benchmark harness, report schema, recording UI, and first suites that measure the things CORE should already be able to defend:

  • deterministic replay
  • truth-lock / groundedness behavior
  • register vs anchor-lens axis discipline
  • compact machine-readable reports suitable for later head-to-head frontier runs
  • a static visual report viewer for clean recordings and demos

Provider adapters for GPT / Claude / Gemini / open-weight baselines are intentionally deferred to a later wave so this PR remains testable without secrets.


Why this exists

Most frontier benchmarks primarily measure final answer quality. That is necessary, but insufficient for CORE's architectural thesis. CORE must also be scored on properties a stochastic frontier model often cannot expose natively:

  • trace stability
  • explicit grounding source
  • refusal instead of fabrication when evidence is absent
  • stable proposition identity under presentation-register variation
  • substantive movement under anchor-lens engagement
  • versor closure health
  • cost / latency / memory class

This benchmark family does not handicap CORE or LLMs. It separates score axes so every model gets credit only for what it actually proves.


Suites in Wave 1

determinism

Runs the same prompts across fresh runtimes and checks whether the surface, grounding source, and key provenance fields remain stable.

Primary metric:

trace_hash_stability proxy = exact replay stability across surfaces + provenance fields

truth_lock

Runs a small closed-world prompt set covering known pack terms and unknown/OOV-like prompts. Scores whether CORE emits grounded pack/teaching surfaces when evidence exists and bounded disclosure/OOV behavior when it does not.

Primary metrics:

grounded_correct
correct_refusal_or_learning_invitation
fabrication_flags

axis_orthogonality

Runs the same prompt across register packs and anchor-lens packs. The register axis should preserve proposition identity / canonical surface where R6 says it must; the anchor-lens axis may move substantive proposition behavior where it engages.

Primary metrics:

register_canonical_stability
surface_variation_observed
anchor_lens_engagement_observed

Run

From the repository root:

CORE_BACKEND=numpy CORE_STRICT_MLX_ON_APPLE=0 \
uv run python -m evals.frontier_compare --suite all --json

Write a report:

CORE_BACKEND=numpy CORE_STRICT_MLX_ON_APPLE=0 \
uv run python -m evals.frontier_compare --suite all --json --report frontier_wave1.json

Human-readable table:

uv run python -m evals.frontier_compare --suite all

Recording UI

Wave 1 includes a zero-dependency static viewer:

evals/frontier_compare/ui/report_viewer.html

Use it for clean screen recordings, investor-safe internal demos, and rapid operator review.

Suggested recording flow:

CORE_BACKEND=numpy CORE_STRICT_MLX_ON_APPLE=0 \
uv run python -m evals.frontier_compare --suite all --json --report frontier_wave1.json

open evals/frontier_compare/ui/report_viewer.html

Then drag frontier_wave1.json into the page. The viewer renders:

  • executive score cards
  • suite pass/fail states
  • per-case prompts
  • failure reasons
  • expandable raw details

The viewer is intentionally static:

  • no build step
  • no framework dependency
  • no network calls
  • no report data leaves the browser

This keeps the benchmark presentation simple, pretty, durable, and easy to record without adding UI bloat to the runtime.


Report contract

The runner emits a stable JSON object:

{
  "benchmark_family": "frontier_compare_wave1",
  "model": "core",
  "mode": "native",
  "suites": [...],
  "summary": {
    "suite_count": 3,
    "case_count": 0,
    "passed": true,
    "primary_score": 1.0
  }
}

Each case records:

  • prompt/config identity
  • pass/fail
  • measured fields
  • failure reasons
  • elapsed milliseconds

No raw hidden state is emitted. The report is safe for internal benchmarking and can be sanitized for public progress summaries later.


Non-goals for Wave 1

  • No provider API calls.
  • No API key handling.
  • No leaderboard claims.
  • No SWE-bench clone.
  • No multimodal tasks.
  • No benchmark that depends on stochastic sampling.
  • No changes to ChatRuntime behavior.
  • No frontend framework or app server.

Next waves

Suggested next branches:

  1. feat/frontier-compare-provider-adapters — model adapter interface for frontier APIs and local baselines.
  2. feat/frontier-compare-reliability-surface — repeated-run / perturbation / failure-injection surface.
  3. feat/frontier-compare-long-horizon-state — 100+ turn state consistency sessions.
  4. feat/frontier-compare-curated-index — closed-corpus provenance benchmark.
  5. feat/frontier-compare-coding-microbench — generated private repo bug-fix benchmark.