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
6 changes: 3 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
- [x] **Refresh ADR 0001 to reflect implemented Tier 1 safety state** _(done 2026-07-19)_
- Updated tier table, "Current state" block, operator guidance, and Section 6 to reflect that Tier 1 (tasks 2.13–2.15) is now implemented and default-on

- [ ] **Add a "How It Actually Works" tutorial**
- [x] **Add a "How It Actually Works" tutorial**
- Walk through a single evolution cycle step by step with real logs
- Lower the barrier for new contributors
Comment on lines +282 to 284

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not mark the tutorial complete before meeting its stated criteria.

The TODO requires a walkthrough “with real logs.” docs/tutorials/how_it_works.md contains snippets and example payloads, but no real CLI log transcript. Add a dry-run transcript or revise the TODO wording before updating the completion counts.

Also applies to: 311-312

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TODO.md` around lines 282 - 284, Do not mark the “How It Actually Works”
tutorial complete in TODO.md until docs/tutorials/how_it_works.md includes a
real CLI dry-run log transcript alongside its walkthrough and payload examples.
Add the transcript, or revise the TODO requirement to match the tutorial’s
actual content before updating any completion counts.

- [x] **Improve API reference** _(done 2026-07-31)_
Expand Down Expand Up @@ -308,8 +308,8 @@
| 🔴 P0 | 11 | 11 | Original 5 complete; all 6 critical bugs from 2026-07-22 whole-repo review fixed (PRs #74, #76-#79) |
| 🟠 P1 | 24 | 15 | Original safety/integration items done; +12 high-priority bugs from 2026-07-22 review; signal-handler init fix; safety.yaml created; monitoring dashboard auth+CORS fix |
| 🟡 P2 | 30 | 23 | Co-evolution loop gaps (8 items, 8 done) + existing P2 + 13 medium bugs from 2026-07-22 review + 4 latent collect->train bugs found closing the loop (1 fixed, 1 new HF-format gap resolved); provider_manager health-check await fix; workflow-agent private-API/event-loop fix; checkpoint save/restore test; trust_remote_code security fix |
| 🟢 P3 | 24 | 16 | Makefile, pre-commit, Docker, ADRs, ADR refresh, CHANGELOG complete; +11 hygiene items from 2026-07-22 review; Ollama provider retry/backoff fix; local_models TTL cache; workspace prompt file conventions |
| **Total** | **89** | **65** | |
| 🟢 P3 | 24 | 17 | Makefile, pre-commit, Docker, ADRs, ADR refresh, CHANGELOG complete; +11 hygiene items from 2026-07-22 review; Ollama provider retry/backoff fix; local_models TTL cache; workspace prompt file conventions; how-it-works tutorial |
| **Total** | **89** | **66** | |

> Update this table as you complete items. Recommended flow: P0 → P1 → P2 → P3.
>
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Welcome to the EVOSEAL documentation! This comprehensive guide will help you get
## User Guides

### Getting Started
- [How EVOSEAL Actually Works](tutorials/how_it_works.md) - Step-by-step walkthrough of an evolution cycle
- [Configuration Guide](guides/CONFIGURATION.md) - System configuration
- [Setup Guide](guides/SETUP.md) - Installation and setup
- [Deployment Guide](guides/DEPLOYMENT.md) - Production deployment
Expand Down
347 changes: 347 additions & 0 deletions docs/tutorials/how_it_works.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,347 @@
# How EVOSEAL Actually Works

A step-by-step walkthrough of a single evolution cycle — from code analysis
through self-modification — with real code references and example output.

**Who this is for:** Contributors who want to understand the runtime flow
before reading source, and operators who want to know what happens when they
run `evoseal start evolution` or `evoseal pipeline run`.

---

## The Big Picture

EVOSEAL alternates between two phases:

1. **Solve a task** — generate code variants, test them, pick the best.
2. **Improve the pipeline** — use the results to fine-tune the model or
adjust the pipeline itself.

A single cycle of Phase 1 is what `EvolutionPipeline.run_evolution_cycle()`
executes. Phase 2 is orchestrated by `ContinuousEvolutionService` and
`BidirectionalEvolutionManager` on a timer.

This tutorial covers **one Phase-1 cycle** end to end.

---

## Prerequisites

- EVOSEAL installed (`uv sync` from the repo root)
- API key configured in `.env` (or use `--dry-run` for mock responses)
- Submodules initialized if you want real DGM/OpenEvolve/SEAL integration
(`git submodule update --init --recursive`)

For a zero-cost walkthrough, use dry-run mode:

```bash
evoseal pipeline run --dry-run
```

---

## Entry Points

There are two ways to trigger a cycle:

| Entry point | What it does |
|---|---|
| `evoseal pipeline run` | Runs one or more evolution iterations synchronously via the CLI |
| `evoseal start evolution` | Starts `ContinuousEvolutionService`, a long-running daemon that runs cycles on a timer and also monitors training readiness |

Both converge on the same core: `EvolutionPipeline.run_evolution_cycle()`.

---

## Step 1: Initialization

When the pipeline starts, it sets up the safety infrastructure first:

```text
EvolutionPipeline.__init__
├── SafetyIntegration(config, repo_root=...) # checkpoint + rollback + regression detection
├── MetricsTracker() # records fitness scores per iteration
├── ImprovementValidator() # compares before/after metrics
├── BudgetTracker() # enforces token/spend limits
└── IntegrationOrchestrator() # manages DGM/OpenEvolve/SEAL adapters
```

The safety layer is initialized automatically — it gates every
self-modification. If you skip it, the pipeline will still run, but no
improvement will ever be validated (the validator needs metrics history to
compare against). Note that the checkpoint/rollback wrapping described in
Step 8 is a separate, optional safety variant (`run_evolution_cycle_with_safety`).

**Key file:** `evoseal/core/evolution_pipeline.py` — `__init__`

---

## Step 2: The Iteration Loop

`run_evolution_cycle(iterations=N)` runs N iterations. Each iteration is
one pass through the full analyze → generate → adapt → evaluate → validate
pipeline:

```python
# Illustrative — see evolution_pipeline.py for the actual code
for i in range(iterations):
iteration_result = await self._run_single_iteration(i + 1)
results.append(iteration_result)

if not iteration_result["should_continue"]:
break # stop early if no improvement found
```

**Key file:** `evoseal/core/evolution_pipeline.py` — `run_evolution_cycle`

---

## Step 3: Analyze the Current Version

```python
analysis = await self._analyze_current_version()
```

This step examines the current codebase state — what tests exist, what the
current fitness scores look like, and where the weakest points are. The
analysis result is a dict that feeds into the generation step.

In the current implementation, this step is a placeholder that returns `{}`
(the TODO for full analysis logic is noted in the source). The pipeline
still works because the generation step can operate without analysis context
when using OpenEvolve's built-in strategies.

**Key file:** `evoseal/core/evolution_pipeline.py` — `_analyze_current_version`

---

## Step 4: Generate Improvements

```python
improvements = await self._generate_improvements(analysis)
```

The pipeline method itself is a stub — it returns `[]` and delegates nothing
internally. The real generation logic is intended to live in integration
adapters (OpenEvolve via the integration orchestrator), but that wiring is
not yet implemented.

For reference, the `Controller` class (`evoseal/core/controller.py`) has its
own `run_generation()` method that implements a test/evaluate/select loop.
This is a **separate code path** — it is not called by `_generate_improvements`
and is not on the pipeline's execution path. It exists as an independent CLI
entry point and may be wired into the pipeline in the future:

```text
# Illustrative — see controller.py:run_generation for the real code
Controller.run_generation()
├── test_runner.run_tests(target) # run tests against the candidate
├── evaluator.evaluate(test_results) # score the candidate
└── select_candidates(eval_results) # pick top-k for the next generation
```

**Key file:** `evoseal/core/evolution_pipeline.py` — `_generate_improvements` (stub); `evoseal/core/controller.py` — `run_generation` (separate code path)

---

## Step 5: SEAL Adaptation

```python
adapted_improvements = await self._adapt_improvements(improvements)
```

The pipeline method itself is a passthrough — SEAL (Self-Adapting Language
Models) takes the raw improvements from OpenEvolve via the integration
adapter and adapts them, applying learned editing strategies to refine the
candidates. This is the "self-adapting" part of the system.

The adaptation strategies live in `evoseal/integration/seal/self_editor/strategies/`
and include code-style, documentation, and logic-focused strategies.

**Key file:** `evoseal/core/evolution_pipeline.py` — `_adapt_improvements`

---

## Step 6: Evaluate the New Version

```python
evaluation_result = await self._evaluate_version(adapted_improvements)
```

The pipeline method itself is a stub — the real evaluation happens through
the integration adapter. The adapted improvements are applied (or simulated,
in dry-run mode) and the result is scored. The evaluation runs the test
suite against the modified code and collects metrics: pass rate, fitness
score, runtime, etc.

The `SandboxedTestRunner` (`evoseal/core/testrunner.py`) runs tests in an
isolated environment:
- Strips API keys from the subprocess environment
- Makes `configs/safety.yaml` and `.env` read-only
- Enforces CPU time and memory limits
- Captures stdout/stderr for diagnostics

**Key file:** `evoseal/core/testrunner.py` — `SandboxedTestRunner`

---

## Step 7: Validate the Improvement

```python
is_improvement = await self._validate_improvement(evaluation_result)
```

This is the gate. The `ImprovementValidator` compares the current iteration's
metrics against the previous iteration's metrics. If the new version
regresses on any critical dimension, the improvement is rejected and the
cycle stops (`should_continue=False`).

```python
# Illustrative — see _validate_improvement for the real code
metrics = self.metrics_tracker.get_metrics_history(test_type)

if len(metrics) < 2:
return True # first iteration, nothing to compare against

result = self.validator.validate_improvement(baseline_id, comparison_id, test_type)
return result.passed
Comment on lines +194 to +207

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Clarify first-iteration validation.

Lines 197-198 return True when fewer than two metrics exist. The first iteration therefore bypasses ImprovementValidator.validate_improvement at Line 200. Describe this as baseline establishment, or change the implementation if the first candidate must pass the validation gate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/tutorials/how_it_works.md` around lines 188 - 201, Clarify the
`_validate_improvement` documentation to describe the fewer-than-two-metrics
path as baseline establishment, explicitly noting that the first iteration
bypasses `ImprovementValidator.validate_improvement`; only change the
implementation if the intended contract requires first candidates to pass that
gate.

```

The `RegressionDetector` (`evoseal/core/regression_detector.py`) provides
configurable thresholds for what counts as a regression — not just raw
fitness, but also test pass rate, runtime, and memory usage.

**Key file:** `evoseal/core/evolution_pipeline.py` — `_validate_improvement`

---

## Step 8: Safety Wraparound (Optional)

The `run_evolution_cycle_with_safety` variant wraps each iteration with:

1. **Checkpoint** — snapshot the codebase before the iteration
2. **Run** — execute the iteration
3. **Detect regression** — compare metrics against the checkpoint
4. **Rollback** — if regression is detected, restore the checkpoint

```text
# Illustrative — see run_evolution_cycle_with_safety for the real code
CheckpointManager.create_checkpoint()
→ run iteration
→ RegressionDetector.check_for_regression()
→ if regression: RollbackManager.rollback_to_checkpoint()
```

This is the mechanism that prevents a bad self-modification from corrupting
the system. The safety config lives in `configs/safety.yaml`.

**Key file:** `evoseal/core/safety_integration.py` — `SafetyIntegration`

---

## Step 9: Results and Events

Each iteration produces a result dict:

```python
{
"iteration": 1,
"success": True,
"is_improvement": True,
"metrics": {"fitness": 0.85, "pass_rate": 0.92},
"should_continue": True,
"resilience_status": {...},
}
```

Events are published at every stage boundary via the `EventBus`
(`evoseal/core/events.py`):

| Event | When |
|---|---|
| `EVOLUTION_STARTED` | Cycle begins |
| `ITERATION_STARTED` | Each iteration begins |
| `PIPELINE_STAGE_STARTED` / `PIPELINE_STAGE_COMPLETED` | Each pipeline stage |
| `ITERATION_COMPLETED` / `ITERATION_FAILED` | Each iteration ends |
| `EVOLUTION_COMPLETED` | Cycle ends |
| `ERROR_OCCURRED` | On any unrecovered error |

These events feed the monitoring dashboard (`evoseal/services/monitoring_dashboard.py`)
via WebSocket.

---

## Step 10: Continuous Loop (Daemon Mode)

When started via `evoseal start evolution`, the
`ContinuousEvolutionService` wraps the above in a long-running loop:

```python
# Illustrative — see continuous_evolution_service.py for the real code
while not shutdown:
await _run_evolution_cycle() # Phase 1: evolve
await asyncio.sleep(evolution_interval)

if bidirectional_manager.should_train():
await bidirectional_manager.run_loop_cycle() # Phase 2: train + deploy
await asyncio.sleep(training_check_interval)
```

Phase 2 (the bidirectional loop) involves:
1. Collect evolution results into training data
2. Fine-tune the model (LoRA/QLoRA)
3. Validate the fine-tuned model
4. Deploy the improved model
5. The next evolution cycle uses the improved model

This is the "bidirectional co-evolution" — evolution improves the model,
and the improved model produces better evolution candidates.

**Key file:** `evoseal/services/continuous_evolution_service.py`

---

## Resilience and Error Recovery

Every pipeline stage is wrapped with the resilience manager:

```python
analysis = await resilience_manager.execute_with_resilience(
"pipeline", "analyze_version", self._analyze_current_version
)
```

This provides:
- **Circuit breakers** — if a component fails repeatedly, it's temporarily
disabled to prevent cascading failures
- **Retry with backoff** — transient failures are retried with exponential
delay
- **Error recovery** — `error_recovery_manager` attempts to recover from
known failure patterns before giving up

**Key file:** `evoseal/core/resilience.py`

---

## What's Still TODO

Several pieces of the pipeline are stubbed with `# TODO` comments:

- `_analyze_current_version()` returns `{}`
- `_generate_improvements()` returns `[]` (the real generation logic is intended for the OpenEvolve adapter — not yet wired; `Controller.run_generation` is a separate code path, not on the pipeline's execution path)
- `_adapt_improvements()` is a passthrough (the real SEAL strategy application lives in the integration adapter)
- `_evaluate_version()` returns `{"metrics": {}}` (the real evaluation lives in `SandboxedTestRunner`)

The pipeline methods are coordination points, not the actual implementations.
Generation and adaptation logic lives in the DGM/OpenEvolve/SEAL integration
adapters. Evaluation uses `SandboxedTestRunner`. The resilience manager wraps
these runtime components (see Steps 4-6 above).

---

## Further Reading

- [Bidirectional Evolution Architecture](../architecture/bidirectional_evolution.md)
- [Self-Improvement Walkthrough](../examples/self_improvement_walkthrough.md)
- [Safety Overview](../safety/index.md)
- [Configuration Guide](../guides/CONFIGURATION.md)
Loading