Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"name": "agentdescent",
"source": "./integrations/claude-code",
"description": "Evolve skills, agents, prompts, code and plugins against examples with a parallel, merge-based optimiser.",
"version": "0.5.0"
"version": "0.5.1"
}
]
}
46 changes: 42 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,44 @@ All notable changes to AgentDescent are documented here. The format follows

## [Unreleased]

## [0.5.1] — 2026-10-10

### Release summary

- Agent-first editorial website and plugin quickstart, modular-framework
explanations, unified documentation styling, and an illustrative in-browser
workflow that makes no model calls or file changes. The optional one-command
setup installs current main and connects supported agent CLIs on PATH; it
is not a pinned-release installer.
- Token budgets, cost-aware selection, graceful budget degradation and optional
diminishing-returns stopping; checkpointed search state survives a restart.
- Sparse verifier auditing and calibration, opt-in priority-ordered audit drain,
and replay-aware sampling and proposals that can use settled evidence.
- Policy-slot evolution, the EvoX Genesis port with skill extraction and read-only
investigation, and the porous-molecule tree-search example. Research examples
remain in the source repository rather than the installed wheel.
- More reliable first runs: actionable spec/dataset errors, policy-slot scaffolds,
fail-fast host installation and a clean installed-wheel CLI/MCP smoke gate.

### Upgrade notes

- Python >= 3.9 remains supported; the MCP extra requires Python >= 3.10.
NumPy >= 1.20 is now an installed dependency for prediction-powered auditing.
- Use `ThreeLayerVerifier.full_eval` and `full_eval_matches_counts`. The old
`oracle_eval` and `oracle_shares_full_set` aliases remain available; using
`oracle_eval` emits a `DeprecationWarning`. Removal is planned for 0.7.
- Checkpointing, replay weighting and audit draining remain opt-in. Token-budget
enforcement depends on usage reported by the model adapter; it is not a
provider-side hard spending limit.

The detailed changes below cover the merged commits since 0.5.0. They do not
include the open multi-head, multi-artifact, asynchronous trajectory-resume,
value-directed evaluation or Genesis blind-mode proposals.

### Fixed

- Interactive demo restarts no longer interleave with an older approval run,
and the displayed artifact stays tied to the run that produced it.
- Keep the interactive demo reachable from the documentation navigation drawer
on mobile, where the desktop header links are hidden.
- Prevent Material admonition styles from exposing the mobile menu on desktop
Expand Down Expand Up @@ -969,10 +1005,10 @@ All notable changes to AgentDescent are documented here. The format follows
the scorer is biased. Reading it as ground truth is what let the docs claim the
loop audits itself against something outside itself, which it does not.

Both old names still work, once, with a `DeprecationWarning`, and are removed
in 0.7. `VerifierProtocol` declares `full_eval`; the engine reads a custom
Both old names still work; the `oracle_eval` compatibility path emits a
`DeprecationWarning`. Both aliases are scheduled for removal in 0.7. `VerifierProtocol` declares `full_eval`; the engine reads a custom
verifier through `verifier.full_eval_of` / `verifier.shares_eval_counts`, which
accept either spelling -- so a verifier written against the pre-0.6 page keeps
accept either spelling -- so a verifier written against the pre-0.5.1 page keeps
running instead of raising `AttributeError` in the middle of a merge. The
`oracle_budget` argument, `VerifierBudget.oracle_calls_*` and the
`oracle-rejected` merge outcome keep their names: they are the public spelling
Expand Down Expand Up @@ -4336,7 +4372,9 @@ First public release on PyPI as **`agentdescent`**.
discrete-space `Aggregator`, staleness policies, DP/TP/PP parallelism, layered
governance, and the provider-agnostic `agentdescent.agents` completion layer.

[Unreleased]: https://github.com/Birfy/agentdescent/compare/v0.4.6...HEAD
[Unreleased]: https://github.com/Birfy/agentdescent/compare/v0.5.1...HEAD
[0.5.1]: https://github.com/Birfy/agentdescent/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/Birfy/agentdescent/compare/v0.4.6...v0.5.0
[0.4.6]: https://github.com/Birfy/agentdescent/compare/v0.4.5...v0.4.6
[0.4.5]: https://github.com/Birfy/agentdescent/compare/v0.4.2...v0.4.5
[0.4.2]: https://github.com/Birfy/agentdescent/compare/v0.4.1...v0.4.2
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ are very welcome.
```bash
git clone https://github.com/Birfy/agentdescent
cd agentdescent
pip install -e ".[dev]" # core engine has zero runtime deps; [dev] adds pytest
pip install -e ".[dev]" # installs NumPy plus the pytest/PyYAML/Markdown development tools
```

Python ≥ 3.9 is required.
Expand Down Expand Up @@ -38,7 +38,7 @@ The suite is **offline and deterministic** (no network, no model API):
pytest -q
```

CI runs the same suite on Python 3.9 / 3.11 / 3.12 for every push and PR. Please
CI runs the same suite on Python 3.9 / 3.10 / 3.11 / 3.12 for every push and PR. Please
add or update tests for any behavior change — the reference domain
(`agentdescent/domains/router.py`) and the example stubs let you test the full
parallel/async loop without an API key.
Expand Down
37 changes: 20 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# AgentDescent

**[Website & interactive demo](https://birfy.github.io/agentdescent/)** ·
[Get started](https://birfy.github.io/agentdescent/install/) ·
[Documentation](https://birfy.github.io/agentdescent/docs/)

> **Gradient descent — but the parameters are agents.** A parallel, asynchronous
> framework for self-evolving agents (skills, prompts, harnesses) where **diffs
> are the gradients** and **the aggregator is the optimizer**.
Expand Down Expand Up @@ -63,38 +67,37 @@ The figure is the paper's, rendered from its TikZ source by
[`tools/gen_architecture_figure.py`](tools/gen_architecture_figure.py) so it
cannot drift from what the paper shows.

## Try the offline demo from current `main`
## Install and run the offline demo

These instructions target **0.5.1**. Once that version is published:

```bash
pip install "agentdescent>=0.5.1"
agentdescent demo
```

The packaged `agentdescent demo` command shown here is on the unreleased
`main` branch. Install that checkout before running it:
Before publication, or when developing from source, install your checkout:

```bash
git clone --branch main https://github.com/Birfy/agentdescent && cd agentdescent
git clone https://github.com/Birfy/agentdescent && cd agentdescent
pip install -e .
agentdescent demo
```

The library supports Python ≥ 3.9 and installs NumPy for its
prediction-powered audit estimator. The packaged demo runs the offline
evolution loop without a model API key. On current unreleased `main`, it ends
with output like:
evolution loop without a model API key and ends with output like:

```
held-out reward: 1.000 outcomes: {'committed': 1}
what it learned: rules.md -> 'COLUMN: amount'
```

For the published stable v0.5.0 installation, run:

```bash
pip install agentdescent
```

Its documented offline example uses `python -m examples.run_demo`; those
examples are outside the wheel, so clone the repo and follow
[install and first run](docs/install.md). The library includes
[`evolve()`](docs/evolution.md), [`DirectoryStrategy`](docs/directory-evolution.md),
and its algorithm ports.
Research examples are outside the wheel. To run the
`python -m examples.run_demo` comparison, clone the repo and follow
[install and first run](docs/install.md).
The library includes [`evolve()`](docs/evolution.md),
[`DirectoryStrategy`](docs/directory-evolution.md), and its algorithm ports.

## Quickstart — a dataset to an evolved skill

Expand Down
2 changes: 1 addition & 1 deletion agentdescent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
shard_round_robin,
)

__version__ = "0.5.0"
__version__ = "0.5.1"

__all__ = [
"Contract",
Expand Down
4 changes: 2 additions & 2 deletions agentdescent/aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"spot-check" arrow, which reads as advisory when it holds a veto.

Note what this stage does *not* do. It re-reads the caller's own scorer over the
whole held-out set (``full_eval``, called ``oracle_eval`` until 0.6), so it can
whole held-out set (``full_eval``, called ``oracle_eval`` until 0.5.1), so it can
catch a verdict that rested on too few tasks and cannot catch one that rested on a
biased scorer -- the outcome name outlived the rename and overstates the check.
:mod:`agentdescent.audit` is the second source.
Expand Down Expand Up @@ -1055,7 +1055,7 @@ def _audit(self, artifact, artifact_id, best_state, best_diff,
#
# Read through the two helpers rather than by attribute: a verifier
# is whatever the caller handed us, including one written against the
# pre-0.6 `oracle_eval` / `oracle_shares_full_set` names. Reading the
# pre-0.5.1 `oracle_eval` / `oracle_shares_full_set` names. Reading the
# new name directly would have made an old custom verifier fail here,
# mid-merge, several minutes into a run.
if shares_eval_counts(self.verifier):
Expand Down
2 changes: 1 addition & 1 deletion agentdescent/policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ class VerifierProtocol(Protocol):
Not three. `docs/verifier.md` said three for a while, and a verifier written
from that page fails in the middle of a merge rather than at startup.

``full_eval`` was ``oracle_eval`` until 0.6. The engine still reads the old
``full_eval`` was ``oracle_eval`` until 0.5.1. The engine still reads the old
name, once, with a `DeprecationWarning`
(:func:`~agentdescent.verifier.full_eval_of`), so an implementation written
against the old page keeps working until 0.7. The rename is a correction:
Expand Down
18 changes: 9 additions & 9 deletions agentdescent/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

.. note:: **The expensive layer is not a second opinion.**

``full_eval`` was called ``oracle_eval`` until 0.6, and the old name claimed
``full_eval`` was called ``oracle_eval`` until 0.5.1, and the old name claimed
more than the code delivers. Every layer here calls the one ``eval_fn`` the
caller supplied; they differ in **how many tasks** they score, not in *who is
scoring*. So the expensive layer bounds the sampling error of a measurement
Expand Down Expand Up @@ -123,7 +123,7 @@ class ThreeLayerVerifier:
#: itself declares over the value it inherited from here.
full_eval_matches_counts = True

#: Pre-0.6 name for :attr:`full_eval_matches_counts`. Read through
#: Pre-0.5.1 name for :attr:`full_eval_matches_counts`. Read through
#: :func:`shares_eval_counts`, which prefers the new one, so a custom
#: verifier that set either keeps working.
oracle_shares_full_set = True
Expand Down Expand Up @@ -219,7 +219,7 @@ def eval_counts(self, artifact: Evolvable,
def full_eval(self, artifact: Evolvable) -> float:
"""``eval_fn`` on the **whole** held-out set. Consumes audit budget.

Called ``oracle_eval`` until 0.6, and the rename is a correction rather
Called ``oracle_eval`` until 0.5.1, and the rename is a correction rather
than a tidy-up. The name promised an *independent source of truth* and
the method delivers the same ``eval_fn`` the cheap layers call, differing
only in **how many tasks** it looks at -- so it can shrink the variance of
Expand Down Expand Up @@ -264,18 +264,18 @@ def oracle_eval(self, artifact: Evolvable) -> float:
return self.full_eval(artifact)


# -- reading a verifier that may predate the 0.6 rename ----------------------
# -- reading a verifier that may predate the 0.5.1 rename ----------------------
#
# `VerifierProtocol` is structural, so a verifier is whatever a caller hands the
# engine -- including one written against the pre-0.6 page and carrying only the
# engine -- including one written against the pre-0.5.1 page and carrying only the
# old names. These two read either spelling, so the rename costs a warning
# rather than an `AttributeError` in the middle of somebody's merge.


def full_eval_of(verifier: Any) -> Callable[[Evolvable], float]:
"""The verifier's whole-held-out-set scorer, under whichever name it has.

Prefers ``full_eval``; falls back to a pre-0.6 ``oracle_eval`` and says so
Prefers ``full_eval``; falls back to a pre-0.5.1 ``oracle_eval`` and says so
once per verifier class, naming the class so the warning points at the file
that has to change.
"""
Expand All @@ -290,7 +290,7 @@ def full_eval_of(verifier: Any) -> Callable[[Evolvable], float]:
"full_eval")
warnings.warn(
f"{type(verifier).__name__} defines oracle_eval but not full_eval. The "
"method was renamed in 0.6 -- oracle_eval is read for now and dropped "
"method was renamed in 0.5.1 -- oracle_eval is read for now and dropped "
"in 0.7. Rename it; the behaviour is unchanged.",
DeprecationWarning, stacklevel=2)
return legacy
Expand All @@ -303,13 +303,13 @@ def shares_eval_counts(verifier: Any) -> bool:
buying the same sweep twice -- and, more importantly, instead of routing a
commit decision through a call that degrades to a sub-sample once the budget
is gone. Reads :attr:`~ThreeLayerVerifier.full_eval_matches_counts`, then the
pre-0.6 ``oracle_shares_full_set``.
pre-0.5.1 ``oracle_shares_full_set``.
"""
# A *declaration* beats an inherited default. `ThreeLayerVerifier` sets
# `full_eval_matches_counts = True` as a statement about how that class is
# written, and a subclass inherits it -- so the escape hatch the attribute's
# docstring offers ("simply does not define it") does not exist for a
# subclass, and one that set the pre-0.6 `oracle_shares_full_set = False`
# subclass, and one that set the pre-0.5.1 `oracle_shares_full_set = False`
# was ignored. Its independent expensive layer then went uncalled and the
# gate degraded to the cheap measurement it existed to cross-check, with no
# warning.
Expand Down
2 changes: 1 addition & 1 deletion docs/design-directory-evolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ result.write_to(path, backup=True) # 装回,先备份

两个反直觉的点,都已对代码核实:

1. **审计门是免费的。** `full_eval`(0.6 前叫 `oracle_eval`)和 `eval_counts` 调同一个 `eval_fn`、同一个
1. **审计门是免费的。** `full_eval`(0.5.1 前叫 `oracle_eval`)和 `eval_counts` 调同一个 `eval_fn`、同一个
held-out 集,而 `_EvalCache` 按 `(render(), task.id)` 记忆化
([evolution.py:531](https://github.com/Birfy/agentdescent/blob/main/agentdescent/evolution.py#L531)),所以 L1 的强制审计只消耗
`oracle_budget` 计数器,不产生任何额外 agent 调用。**演化 agent 目录/代码
Expand Down
Loading
Loading