Bring your own optimizer
recension is a measurement-and-governance shell, not an optimizer. The mechanics of generating good candidate edits are well covered by projects like DSPy and GEPA. recension's contribution is everything around the edit: versioned artifacts with provenance, a held-out objective with a locked test split, significance and guard gates, leakage detection, a cost ledger, and a tamper-evident audit record.
Those two concerns compose. The Proposer protocol is the seam:
supply the candidate edits from any engine you like, and recension keeps owning the measurement and the
record. The artifact, evalset, and record abstractions do not change.
The Proposer protocol
A proposer does two things: turn observed failures into a short diagnosis, and turn that diagnosis into distinct candidate revisions.
class Proposer(Protocol):
def diagnose(self, model, artifact_text, failures, *, seed=None) -> str: ...
def propose(self, model, artifact_text, diagnosis, n, *, seed=None) -> list[str]: ...
The built-in DefaultProposer is the reflective
diagnose/propose loop recension ships with. To plug in your own engine, pass a custom proposer to the
optimizer.
Wrapping an external engine
CallableProposer adapts plain functions, so wrapping an
external optimizer is a few lines. Your function returns the candidate texts; recension scores them on
the held-out split, runs the significance and guard gates, checks for leakage, and writes the audit
record.
from recension import CallableProposer, ReflectiveOptimizer
def propose_with_my_engine(model, artifact_text, diagnosis, n, seed):
# Call DSPy, GEPA, or any optimizer here and return up to n revised artifact strings.
return my_engine.optimize(artifact_text, n=n)
optimizer = ReflectiveOptimizer(
artifact=artifact,
evalset=evalset,
objective=objective,
model=model,
proposer=CallableProposer(propose_with_my_engine),
)
record = optimizer.run() # recension owns measurement, leakage, and the record
For full control, implement the Proposer protocol directly as a class. Either way, the run produces
the same RunRecord: the governance guarantees hold no matter who
proposed the edits.