anatomy / moduleshillclimb

Overview

What a climber exchanges: one subpackage each under src/hillclimb/modules/, each with its contract in a base.py.

What a climber exchanges, one subpackage each under src/hillclimb/modules/, each with its contract in a base.py. Implementations import only hillclimb.sdk.

modulewhat it decidesbundledcontract
Policieswhat to try nextgreedy, openevolve, gepamodules/policies/base.py
Operatorshow one attempt is made: the draft, debug, improve, ensemble scaffoldsdraft, debug, improve, ensemblemodules/operators/base.py
Tunerswhich parameter values to tryrandom, optunamodules/tuners/base.py
Similarityhow alike two solutions are; drives the similarity map and reference viewssolution-card, api-calls, code-tokensmodules/similarity/base.py
Memorywhether a search reads and writes the cross-search memory: the YAML under hillclimb/knowledge/ — cards, claims, credit, consolidation, papers, skillsfiles, nonemodules/memory/
Knowledge graphhow that memory is indexed and traversed: build folds the files into a graph, retrieve picks the claims a search is shown, query answers hillclimb knowledge queryknowledge-graphmodules/memory/base.py

A climber is a directory with a climber.yaml naming a search policy (or a whole loop), the operators it may use, their prompts and a tuner. Three are bundled: greedy (debug failing tips, draft a few branches, improve the best), openevolve (MAP-Elites over hillclimb's operators) and gepa (reflective Pareto search, brings its own loop). A one-file climber is a .py with one policy class. A search snapshots its climber, so editing the live copy never changes a running search, and hillclimb climber check replays recorded journals through an edited climber before an agent hour is spent on it.

src/hillclimb/climbers/gepa/climber.yaml
name: gepa
description: Reflective Pareto search; brings its own SearchLoop. Experimental.
loop: hillclimb.integrations.gepa.loop:GepaLoop
params:
  max_metric_calls: 50
operators:
  - hillclimb.integrations.gepa.operator:GepaReflectOperator
memory: files
tuner: random
holdout_timing: after    # gepa's state never meets a holdout value, not even a failed hidden split