First Phase 4 lane lands. Measures corrections-to-competence curves
across 17 concepts (10 public + 7 holdouts disjoint). Per-concept
curriculum is a 4-hop chain of "is" corrections; probe asks the
chain head after each cumulative-correction count; score is the
count of chain-tail tokens visible in the probe surface.
Phase 4 framework discipline ("Plot, do not threshold" per
docs/capability_roadmap.md): the lane reports quantitative curves
and one structural gate (replay_determinism >= 0.95), not the
binary pass/fail thresholds of Phases 1-3.
Results:
split concepts first_hit saturation rate replay
public/v1 10 1.0 4.0 1.0 1.0
holdouts/v1 7 1.0 4.0 1.0 1.0
Every concept's curve: [0, 1, 2, 3, 4]. One correction -> one new
chain hop -> one new token visible in surface. Perfectly linear
sample efficiency on chain curricula; no diminishing returns; no
plateau; no spurious confabulation at k=0.
What the linearity says about CORE:
- The reviewed-teaching loop integrates each typed correction
into the proposition-graph substrate.
- The typed inference operator (transitive_walk, ADR-0018) surfaces
the chain endpoint on the next probe.
- The result is one-shot learning per correction on chain shapes -
visible by construction, not inferred from training statistics.
- Replay determinism = 1.0 across all snapshots means the curve
is the deterministic function of (concept, k), not a sampled
estimate of a stochastic process. Frontier systems cannot
publish this curve at all because their per-snapshot output is
not reproducible.
Lane contents:
contract.md - specifies the curve discipline, anti-overfitting
rules (disjoint concept sets, one-new-token-per-correction
invariant), and reporting structure.
runner.py - parallel sweep across snapshots, two-run replay
check per snapshot, per-concept curve aggregation.
dev/cases.jsonl (2 concepts) - smoke set.
public/v1/cases.jsonl (10 concepts) - wisdom, light, truth,
creation, meaning, reason, principle, identity, memory, question.
holdouts/v1/cases.jsonl (7 concepts) - being, spirit, distinction,
correction, verification, explanation, procedure.
baselines/v1_structural_zero.json - frontier baseline by
construction (per-snapshot reproducibility absent).
gaps.md - findings + v2 contract refinements (branching curricula,
distractor corrections, OOD probes, mixed-relation chains, CI
reporting).
CLI suites smoke / teaching all pass; no regression. PROGRESS.md
updated.
Phase 4 status: 1 of 3 lanes lands as v1 complete with a clean
result. Remaining lanes: long-context-cost (vault scaling 10^3-10^6)
and multi-agent-composition (two-instance cooperation with replay
preserved per agent).
191 lines
6.5 KiB
Python
191 lines
6.5 KiB
Python
"""sample-efficiency eval lane runner — Phase 4 (quantitative curve).
|
|
|
|
For each concept:
|
|
1. Sweep k = 0..len(curriculum). For each k, run a fresh pipeline,
|
|
teach the first k corrections, then probe.
|
|
2. Record cumulative token-hit count, vault hits, trace hash.
|
|
3. Repeat once for replay-determinism check.
|
|
|
|
Output is a per-concept curve plus aggregate efficiency statistics.
|
|
|
|
Conforms to the framework interface: run_lane(cases, config=None) -> report.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from dataclasses import dataclass, field
|
|
from typing import Any
|
|
|
|
from chat.runtime import ChatRuntime
|
|
from core.cognition.pipeline import CognitiveTurnPipeline
|
|
from core.config import RuntimeConfig
|
|
from evals.parallel import run_cases_parallel
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class LaneReport:
|
|
metrics: dict[str, Any] = field(default_factory=dict)
|
|
case_details: list[dict[str, Any]] = field(default_factory=list)
|
|
|
|
|
|
_TOKEN_BOUND = re.compile(r"\b([a-z][a-z'\-]*)\b")
|
|
|
|
|
|
def _tokens(text: str) -> set[str]:
|
|
return set(_TOKEN_BOUND.findall((text or "").lower()))
|
|
|
|
|
|
def _count_hits(text: str, expected: list[str]) -> int:
|
|
if not text:
|
|
return 0
|
|
toks = _tokens(text)
|
|
return sum(1 for tok in expected if tok.lower() in toks)
|
|
|
|
|
|
def _run_snapshot(
|
|
curriculum: list[str],
|
|
k: int,
|
|
probe: str,
|
|
seed: str,
|
|
) -> dict[str, Any]:
|
|
"""Teach first k corrections on a fresh pipeline, then probe.
|
|
|
|
The seed prompt (a question about the concept, e.g. "What is wisdom?")
|
|
runs first so that subsequent corrections have a prior_surface to bind
|
|
to — the teaching loop drops corrections that arrive on turn 0.
|
|
"""
|
|
runtime = ChatRuntime()
|
|
pipeline = CognitiveTurnPipeline(runtime)
|
|
try:
|
|
pipeline.run(seed, max_tokens=8)
|
|
except ValueError:
|
|
pass
|
|
for premise in curriculum[:k]:
|
|
try:
|
|
pipeline.run(premise, max_tokens=8)
|
|
except ValueError:
|
|
continue
|
|
try:
|
|
r = pipeline.run(probe, max_tokens=8)
|
|
except ValueError:
|
|
return {
|
|
"surface_blob": "",
|
|
"vault_hits": 0,
|
|
"trace_hash": "",
|
|
}
|
|
blob = " ".join([r.surface or "", r.articulation_surface or "", r.walk_surface or ""])
|
|
return {
|
|
"surface_blob": blob,
|
|
"vault_hits": int(r.vault_hits),
|
|
"trace_hash": r.trace_hash,
|
|
}
|
|
|
|
|
|
def _run_case(case: dict[str, Any]) -> dict[str, Any]:
|
|
concept: str = case["concept"]
|
|
curriculum: list[str] = list(case.get("curriculum", []))
|
|
probe: str = case["probe"]
|
|
expected_tokens: list[str] = list(case.get("expected_tokens", []))
|
|
seed: str = case.get("seed") or probe
|
|
|
|
n = len(curriculum)
|
|
n_expected = len(expected_tokens)
|
|
snapshots: list[dict[str, Any]] = []
|
|
replay_matches = 0
|
|
replay_total = 0
|
|
|
|
for k in range(n + 1):
|
|
first = _run_snapshot(curriculum, k, probe, seed)
|
|
second = _run_snapshot(curriculum, k, probe, seed)
|
|
replay_total += 1
|
|
if first["trace_hash"] and first["trace_hash"] == second["trace_hash"]:
|
|
replay_matches += 1
|
|
hits = _count_hits(first["surface_blob"], expected_tokens)
|
|
snapshots.append({
|
|
"k": k,
|
|
"cumulative_token_hit_count": hits,
|
|
"fraction": (hits / n_expected) if n_expected else 0.0,
|
|
"vault_hits": first["vault_hits"],
|
|
"trace_hash": first["trace_hash"],
|
|
"trace_hash_replay": second["trace_hash"],
|
|
"replay_match": first["trace_hash"] == second["trace_hash"],
|
|
})
|
|
|
|
# Curve summary statistics.
|
|
corrections_to_first_hit: int | None = None
|
|
corrections_to_saturation: int | None = None
|
|
for snap in snapshots:
|
|
if corrections_to_first_hit is None and snap["cumulative_token_hit_count"] >= 1:
|
|
corrections_to_first_hit = snap["k"]
|
|
if (
|
|
corrections_to_saturation is None
|
|
and n_expected > 0
|
|
and snap["cumulative_token_hit_count"] >= n_expected
|
|
):
|
|
corrections_to_saturation = snap["k"]
|
|
|
|
final_hits = snapshots[-1]["cumulative_token_hit_count"] if snapshots else 0
|
|
saturation_score = (final_hits / n_expected) if n_expected else 0.0
|
|
replay_rate = (replay_matches / replay_total) if replay_total else 0.0
|
|
|
|
return {
|
|
"concept": concept,
|
|
"curriculum_length": n,
|
|
"expected_token_count": n_expected,
|
|
"snapshots": snapshots,
|
|
"corrections_to_first_hit": corrections_to_first_hit,
|
|
"corrections_to_saturation": corrections_to_saturation,
|
|
"saturation_score": round(saturation_score, 4),
|
|
"replay_determinism": round(replay_rate, 4),
|
|
"passed": replay_rate >= 0.95,
|
|
}
|
|
|
|
|
|
def run_lane(
|
|
cases: list[dict[str, Any]],
|
|
*,
|
|
config: RuntimeConfig | None = None,
|
|
workers: int | None = None,
|
|
) -> LaneReport:
|
|
if not cases:
|
|
return LaneReport(metrics={}, case_details=[])
|
|
_ = config
|
|
|
|
case_details = run_cases_parallel(cases, _run_case, workers=workers)
|
|
total = len(case_details)
|
|
|
|
hit_concepts = [d for d in case_details if d["corrections_to_first_hit"] is not None]
|
|
sat_concepts = [d for d in case_details if d["corrections_to_saturation"] is not None]
|
|
|
|
def _mean(vals: list[int]) -> float | None:
|
|
if not vals:
|
|
return None
|
|
return round(sum(vals) / len(vals), 4)
|
|
|
|
mean_first_hit = _mean([d["corrections_to_first_hit"] for d in hit_concepts])
|
|
mean_saturation = _mean([d["corrections_to_saturation"] for d in sat_concepts])
|
|
saturation_rate = round(len(sat_concepts) / total, 4) if total else 0.0
|
|
hit_rate = round(len(hit_concepts) / total, 4) if total else 0.0
|
|
mean_saturation_score = (
|
|
round(sum(d["saturation_score"] for d in case_details) / total, 4) if total else 0.0
|
|
)
|
|
replay_rate = (
|
|
round(sum(d["replay_determinism"] for d in case_details) / total, 4) if total else 0.0
|
|
)
|
|
|
|
metrics: dict[str, Any] = {
|
|
"mean_corrections_to_first_hit": mean_first_hit,
|
|
"mean_corrections_to_saturation": mean_saturation,
|
|
"first_hit_rate": hit_rate,
|
|
"saturation_rate": saturation_rate,
|
|
"mean_saturation_score": mean_saturation_score,
|
|
"replay_determinism": replay_rate,
|
|
"concept_count": total,
|
|
# Phase 4 discipline: quantitative, not pass/fail beyond the structural
|
|
# replay-determinism gate. overall_pass is reported but is the gate
|
|
# only on reproducibility, not on the curve itself.
|
|
"overall_pass": replay_rate >= 0.95,
|
|
}
|
|
|
|
return LaneReport(metrics=metrics, case_details=case_details)
|