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
1 change: 1 addition & 0 deletions .codies-memory
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
wishful
57 changes: 0 additions & 57 deletions .github/workflows/claude-code-review.yml

This file was deleted.

50 changes: 0 additions & 50 deletions .github/workflows/claude.yml

This file was deleted.

4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ node_modules/
docs-site/node_modules/
docs-site/.astro/
docs-site/dist/
.bmad/
.claude/
.memsearch/
.pyro/
15 changes: 15 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,21 @@ Key properties:
- **Safety‑checked**: generated code is parsed and checked for obviously dangerous constructs.
- **Cache‑backed**: generated modules live as `.py` files and can be edited or committed.

### Active Product Direction: Code Search Workbench

The current serious direction is not "one-shot helper generation." It is bounded
code search: target artifact + mutation space + fitness function + budget +
accept/rollback. Before extending `evolve`, `context`, CLI, demos, or the
dashboard, read:

- `docs/specs/001-wishful-evolve/implementation-plan.md`
- `docs/specs/002-wishful-context/implementation-plan.md`
- `docs/specs/003-wishful-code-search-workbench/concept-plan.md`

The key product primitive is "function with lineage": import address, current
source, context, variants, scores, failures, winner, evidence scope, and
accept/rollback state.

---

## Repository Layout
Expand Down
75 changes: 73 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<a href="https://badge.fury.io/py/wishful"><img src="https://badge.fury.io/py/wishful.svg" alt="PyPI version"></a>
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.12+-blue.svg" alt="Python 3.12+"></a>
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
<a href="https://github.com/pyros-projects/wishful"><img src="https://img.shields.io/badge/tests-112%20passed-brightgreen.svg" alt="Tests"></a>
<a href="https://github.com/pyros-projects/wishful"><img src="https://img.shields.io/badge/coverage-80%25-green.svg" alt="Coverage"></a>
<a href="https://github.com/pyros-projects/wishful"><img src="https://img.shields.io/badge/tests-154%20passed-brightgreen.svg" alt="Tests"></a>
<a href="https://github.com/pyros-projects/wishful"><img src="https://img.shields.io/badge/coverage-78%25-green.svg" alt="Coverage"></a>
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/badge/code%20style-ruff-000000.svg" alt="Code style: ruff"></a>
</p>

Expand Down Expand Up @@ -246,6 +246,77 @@ It's turtles all the way down. 🐢

---

## 🧬 Evolve: Improve a Function Over Generations

`explore()` tries several fresh variants. `evolve()` goes one step further: it
keeps a history of prior attempts, scores, and failures, then passes that
history back into the next mutation prompt.

```python
import wishful


def normalize_scores(values):
values = [float(value) for value in values]
if not values:
return []
minimum = min(values)
maximum = max(values)
if maximum == minimum:
return [0.0 for _ in values]
return [(value - minimum) / (maximum - minimum) for value in values]


normalize_scores.__wishful_source__ = """
def normalize_scores(values):
values = [float(value) for value in values]
if not values:
return []
minimum = min(values)
maximum = max(values)
if maximum == minimum:
return [0.0 for _ in values]
return [(value - minimum) / (maximum - minimum) for value in values]
""".strip()


def is_correct(fn):
return (
fn([10, 20, 30]) == [0.0, 0.5, 1.0]
and fn([2, 2, 2]) == [0.0, 0.0, 0.0]
)


def score(fn):
return 1_000.0 - len(fn.__wishful_source__) if is_correct(fn) else 0.0


evolved = wishful.evolve(
normalize_scores,
fitness=score,
test=is_correct,
generations=3,
variants=4,
mutation_prompt="Keep behavior identical but make the code concise.",
)

print(evolved.__wishful_evolution__)
```

The returned function carries:

- `__wishful_source__`: the winning source code
- `__wishful_evolution__`: original score, final score, improvement, generation
summaries, and every attempted variant

Try the deterministic offline demo:

```bash
WISHFUL_FAKE_LLM=1 uv run python examples/14_evolve.py
```

---

## 🗄️ Cache Ops: Because Sometimes Wishes Need Revising

```python
Expand Down
Loading
Loading