Harness composition¶
Harness names an algorithm port; the consolidation archive is the
leaderboard; select_harness routes a new domain to the port the recorded
evidence says wins there. This is the composition layer: the ports themselves
(evolve() with different Policies / aggregator_factory — RRSI,
solver-challenger self-play, population islands, metasearch) never change, and
nothing before this chose between them or remembered which one won where.
The pieces¶
| Piece | What it is |
|---|---|
Harness(name, run) |
A named (tasks, repo_path) -> EvolutionResult callable. The caller binds everything the port needs into the closure, so a harness is a black box that turns a task set into a measured result. |
record_harness(store, *, harness_name, config, result, run_id) |
Writes the outcome to the archive under artifact_id="harness:<name>" with the domain's config — one ordinary ConsolidationRecord, atomic and idempotent. |
harness_score(store, name, config) |
The best measured reward for that harness on that config fingerprint, None when there is no evidence. |
harness_leaderboard(store, config) |
name -> {rewards, best} over the archive, per domain or aggregated. |
select_harness(store, harnesses, config, *, default) |
The harness with the highest recorded reward for the config; round-robin (or default) when no evidence exists — a harness with no runs on a domain can never beat one that was measured there. |
compose_run(store, tasks, harnesses, config, *, mode, repo_dir) |
Runs the selected harness (mode="best") or every harness (mode="all" — the leaderboard's training mode), each on a fresh ledger repo, records the outcomes, and returns a HarnessReport (per-harness reward / time-to-quality, the winner, and the selection reason). |
The loop¶
- Measure.
compose_run(..., mode="all")runs every harness on a task set and records each outcome for the domain's config fingerprint. - Route.
select_harnessreads the archive: same-config evidence first, best measured reward wins. A tie goes to the harness listed first; no evidence falls back to round-robin rather than a guess — the reason string says which way the choice went, so it can be logged. - Re-measure.
compose_run(..., mode="best")runs only the chosen harness, records the rerun, and the next route on the same domain sees the updated evidence — the composition learns which algorithm wins where, from measured runs, without touching any port.
Domain separation¶
config_fingerprint is the archive's existing domain key, and select_harness
uses it exactly as seed_from_archive does: a harness that wins on arithmetic
is never mistaken for one that wins on code, and evidence on one domain never
leaks into the choice on another.
Example¶
Two deterministic harnesses on the same arithmetic domain, one shallow
(rounds=4), one deep (rounds=8):
from agentdescent import ConsolidationStore, compose_run, harness
store = ConsolidationStore("~/.agentdescent/archive")
quick = harness("quick", lambda tasks, repo: evolve(tasks, reward, run=run,
propose=propose, strategy=SingleSlot("cap:0"), rounds=4,
repo_path=repo))
deep = harness("deep", lambda tasks, repo: evolve(tasks, reward, run=run,
propose=propose, strategy=SingleSlot("cap:0"), rounds=8,
repo_path=repo))
report, winner = compose_run(store, tasks, [quick, deep],
{"dataset": "cap", "scorer": "exact"}, mode="all")
print(report.winner, report.reason)
# the next compose_run(mode="best") on the same domain runs only the winner