Darwin-style evolution of the forge's own components β mutation operators, evaluators, safety guards, and meta-strategies evolve through self-modification.
Navigation Β· Overview Β· Project Lineage Β· Self-Referential Approach Β· Architecture Β· Quick Start Β· Modules Β· Safety Β· Research
The Self-Referential Forge is the third generation of evolutionary optimization at NullLabTests. Where its predecessors evolved prompts and then agent blueprints, this forge evolves its own source code β a Darwin-style self-referential loop where the genetic operators, evaluators, safety guards, and meta-strategies are themselves subject to mutation, selection, and inheritance.
| Feature | Impact |
|---|---|
| 𧬠Self-Modifying Operators | Mutation operators rewrite the forge's own Python AST β inserting, deleting, and restructuring code at runtime |
| π Second-Order Evolution | The meta-evolver tracks which self-mutations improve evolution quality and adjusts selection pressure accordingly |
| π‘οΈ Safety-Guarded Mutation | Every self-modification passes through a safety validator that blocks dangerous patterns (eval, exec, destructive I/O) |
| π Self-Evaluation | Forge components are scored on syntax validity, code complexity, safety compliance, modular cohesion, and style consistency |
| ποΈ Immutable Archive | Every evolution snapshot is gzip-compressed and stored, enabling full rollback and trajectory analysis |
| ποΈ Human-in-the-Loop | Optional manual approval gate for every self-mutation |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 𧬠Forge Source Code (the entire forge package) β
β βββ forge/orchestrator.py β
β βββ forge/self_modifier.py βββ MUTATION TARGET β
β βββ evaluators/evaluator.py βββ MUTATION TARGET β
β βββ safety/safety_validator.py βββ MUTATION TARGET β
β βββ meta_evolution/*.py βββ MUTATION TARGET β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π§ SelfModifier applies genetic operators β
β βββ insert_code β inject logging/branching β
β βββ rewrite_function β replace body with pass β
β βββ add_parameter β add optional param to function β
β βββ swap_condition β negate if-condition β
β βββ duplicate_component β clone class/func β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π‘οΈ SafetyValidator checks mutation β
β βββ Blocks: eval, exec, os.system, destructives β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π SelfEvaluator scores the mutated component β
β βββ syntax_validity (AST parse) β
β βββ code_complexity (node count, depth) β
β βββ safety_compliance (dangerous patterns) β
β βββ modular_cohesion (imports, structure) β
β βββ style_consistency (indent, type hints) β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π§ MetaEvolver updates operator weights β
β βββ Positive delta β reinforce operator β
β βββ Negative delta β penalize operator β
β βββ Stagnation β novelty boost β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ποΈ Archivist snapshots the state to disk β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β self_referential_forge β
β (THIS PROJECT) β
β Evolves the forge's own source code β mutation operators, β
β evaluators, safety guards, and meta-strategies evolve through β
β self-modification. Second-order evolution loop with AST-level β
β mutations and safety-guarded self-modification. β
β β
β 𧬠Self-modifying operators π Second-order meta-evolution β
β π‘οΈ Safety-guarded mutation π Self-evaluation (6 dimensions) β
β ποΈ Immutable archive ποΈ Human-in-the-loop optional β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β²
β evolves from Β· self-referential fork
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β grounded_agent_forge β
β Evolves full agent blueprints (prompt + tools + memory + planning β
β + self-eval) in Docker sandbox with multi-objective fitness, β
β meta-evolution, and task specialization. β
β β
β ποΈ Agent-level evolution π¦ Docker sandboxed execution β
β π― 8+ fitness dimensions π Self-tuning meta-evolution β
β π Real-time dashboard π§© Task specialization β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β²
β builds on Β· evolves from
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β grounded_evolution β
β Evolves text prompts with execution-grounded validation via AST β
β parse, pytest, and flake8. Two-loop system: lexical + grounded. β
β β
β π 203 evolution cycles π Best score: 39/80 β
β π¬ 7 benchmark tasks π 127 mutations + 76 crossovers β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Capability | grounded_evolution | grounded_agent_forge | π self_referential_forge |
|---|---|---|---|
| Evolves text prompts | β | β | β |
| Evolves agent blueprints | β | β | β |
| Evolves its own source code | β | β | β |
| AST-level self-mutation | β | β | β |
| Safety-guarded modification | β | β | β |
| Docker sandbox execution | β | β | β |
| Multi-objective fitness | β | β (8 dims) | β (6 dims) |
| Self-evaluation of components | β | β | β |
| Second-order meta-evolution | β | β | β |
| Novelty-driven exploration | β | β | β |
| Immutable archive / rollback | β | β | β |
| Human-in-the-loop mutations | β | β | β |
| Real-time dashboard | β | β | β |
| Auto-commit on improvement | β | β | β |
This project was built using DeepSeek V4 as the primary coding model.
The Self-Referential Forge applies Darwinian principles β variation, selection, and inheritance β not to biological organisms or even to generated prompts, but to the forge's own implementation code.
Variation: Each evolution cycle selects a champion component (the highest-fitness piece of forge source) and applies a random genetic operator: inserting code, rewriting function bodies, adding parameters, negating conditions, or duplicating components. These operators work directly on the Python AST.
Selection: The mutated component is scored across six fitness dimensions β syntax validity (does it parse?), code complexity (is it non-trivial?), safety compliance (no dangerous patterns?), modular cohesion (well-structured?), style consistency (clean code?), and test survival (do tests still pass?). The weighted sum determines the component's fitness.
Inheritance: High-fitness components remain in the population and serve as parents for future mutations. Low-fitness variants are pruned. The meta-evolver tracks which operators consistently produce fitness gains and adjusts selection weights accordingly β a second-order evolution where the evolution strategy itself evolves.
Traditional evolutionary computation evolves solutions within a fixed framework (a genetic algorithm with hardcoded operators, fixed evaluation functions, static safety constraints). The self-referential forge removes these boundaries: the operators are mutatable, the evaluator is improvable, the safety rules are refinable.
This creates a system that can theoretically discover novel evolutionary strategies that a human designer would never have considered. The safety validator acts as the crucial guardrail β preventing the system from evolving destructive capabilities while still allowing creative exploration of the design space.
self_referential_forge/
β
βββ forge/ # βοΈ Core evolution modules
β βββ __init__.py # Package exports
β βββ __main__.py # CLI entry point
β βββ orchestrator.py # Self-referential evolution loop
β βββ self_modifier.py # AST-level code mutation engine
β
βββ meta_evolution/ # π§ Strategy adaptation
β βββ __init__.py
β βββ meta_evolver.py # Operator weight tuning + novelty
β
βββ evaluators/ # π Self-evaluation
β βββ __init__.py
β βββ evaluator.py # 6-dimension fitness scoring
β
βββ safety/ # π‘οΈ Tiered safety architecture
β βββ __init__.py # Exports SafetyValidator, SafetyTier, etc.
β βββ policy.py # Tier definitions, operatorβtier mappings
β βββ audit.py # Hash-chained, tamper-evident audit log
β βββ sandbox.py # Fork-test-promote sandbox lifecycle
β βββ safety_validator.py # Unified facade coordinating all safety
β
βββ archive/ # ποΈ State persistence
β βββ __init__.py
β βββ archivist.py # Compressed snapshot management
β
βββ benchmarks/ # π Internal quality benchmarks
β βββ __init__.py
β βββ benchmark_suite.py # 5 evolution quality metrics
β
βββ dashboard/ # π Real-time web dashboard
β βββ main.py # FastAPI + auto-refreshing UI
β
βββ self_modification/ # π Alternative import path
β βββ __init__.py # (re-exports from forge.self_modifier)
β
βββ run_forge.sh # π Production shell wrapper
βββ pyproject.toml # π¦ Project metadata
βββ README.md # π This file
βββ .env.example # π Environment template
- Python 3.11+
- pip (package installer)
# Navigate to the self-referential forge
cd grounded_agent_forge/self_referential_forge
# Create virtual environment (optional but recommended)
python -m venv .venv && source .venv/bin/activate
# Install the forge
pip install -e .
# Configure environment (optional)
cp .env.example .env# Infinite self-referential evolution (default)
bash run_forge.sh
# Run for 50 cycles
bash run_forge.sh --cycles 50
# Launch with the real-time dashboard
bash run_forge.sh --dashboard
# Require manual approval for each mutation
bash run_forge.sh --human-approval
# All together
bash run_forge.sh --cycles 100 --dashboard --human-approval --verboseYou can also run directly via Python:
python -m forge # Infinite evolution
python -m forge --cycles 50 # 50 cycles
python -m forge --dashboard # + dashboard
python -m forge --verbose # Debug logging
python -m forge --help # Show all options# Option A: Launch alongside the forge
python -m forge --dashboard
# Option B: Launch separately
uvicorn dashboard.main:app --host 0.0.0.0 --port 8000
# Open β http://localhost:8000The central loop that drives self-modification:
- Validates the forge environment on startup
- Selects champion components via tournament selection
- Delegates mutation to
SelfModifierwith safety gates - Evaluates fitness via
SelfEvaluator - Updates meta-evolution strategy via
MetaEvolver - Snapshots state via
Archivist - Supports human-in-the-loop approval gating
- Handles auto-commit for persistent improvement tracking
Five genetic operators that mutate the forge's own Python source by rewriting the AST:
| Operator | Description |
|---|---|
insert_code |
Injects a randomized logging or branching statement into a function body |
rewrite_function |
Replaces a random function body with pass (simplification operator) |
add_parameter |
Adds an optional _extra_* parameter to a random function |
swap_condition |
Negates a random if-condition (e.g., if x: β if not x:) |
duplicate_component |
Clones a random class or function definition |
Tracks operator performance and adjusts the evolution strategy:
- Weighted random operator selection based on historical success
- Fitness delta observation reinforces/penalizes operators
- Novelty boost triggers when stagnation is detected, amplifying low-weight operators
- Mutation rate dynamically adjusted based on recent delta
| Dimension | Weight | What It Measures |
|---|---|---|
| π― Syntax Validity | 25% | Does the source parse as valid Python AST? |
| βοΈ Code Complexity | 15% | Node count, function/class density, nesting depth |
| π‘οΈ Safety Compliance | 25% | Absence of eval, exec, os.system, pickle, etc. |
| π§© Modular Cohesion | 15% | Import ordering, structural separation, if __name__ |
| π§ͺ Test Survival | 10% | Do existing tests still pass? (neutral if no tests) |
| π Style Consistency | 10% | Line length, indentation discipline, type hints |
Prevents the forge from evolving dangerous capabilities:
- 9 dangerous patterns flagged: eval, exec, import, compile, os.system, subprocess, shutil.rmtree, git push, Docker destructive operations
- 4 critical patterns flagged: os.remove, shutil.rmtree, Path.unlink
- File boundary validation: ensures mutations stay within the forge directory
- Extension whitelist: only
.py,.toml,.md,.json, etc. - Directory blacklist:
.git,__pycache__,node_modules,.venv - Max file size: 100KB per source file
- Strict mode: disallows os/subprocess/shutil imports in mutated code
- Gzip-compressed JSON snapshots per generation
- Configurable max snapshot count (default: 100)
- Full rollback capability to any generation
- In-memory history with fitness trajectory access
- Auto-loads existing snapshots on init
Self-modifying code demands a defense-in-depth approach. The safety system is built on four independent layers, each designed to be a complete barrier:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SELF-MODIFICATION SAFETY STACK β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββ TIER 3: BLOCKED (never allowed) βββββββββββββββββββββββββββββββ β
β β eval(), exec(), compile(), __import__() β β
β β os.system(), subprocess.*, shutil.rmtree() β β
β β Path.unlink(), gc.collect() β β
β β Modifications to safety/ or archive/ modules β β
β β Writes to .git/, __pycache__/, .venv/ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β² β
β ββ TIER 2: HUMAN APPROVAL ββββββββββββββββββββββββββββββββββββββββ β
β β swap_condition operator β β
β β Bare except: or broad except Exception: β β
β β File write operations (open with w/wb/a mode) β β
β β try: blocks (heuristic) β β
β β ββ Human must type 'y' at interactive prompt β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β² β
β ββ TIER 1: DRY RUN (sandbox required) βββββββββββββββββββββββββββββ β
β β rewrite_function operator β β
β β add_parameter operator β β
β β duplicate_component operator β β
β β ββ Fails if: syntax error, AST violation, test failure β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β² β
β ββ TIER 0: AUTOMATED (no gate) ββββββββββββββββββββββββββββββββββββ β
β β insert_code operator (logging/branching injection) β β
β β ββ Still checked: syntax validity + dangerous pattern scan β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β CROSS-CUTTING: SANDOX + AUDIT β β
β β β β
β β ββββββββββββββββββββ ββββββββββββββββββββββ β β
β β β SANDBOX β β AUDIT LOG β β β
β β β fork β test β β β hash-chained JSONL β β β
β β β promote/rollback β β tamper-evident β β β
β β ββββββββββββββββββββ ββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Every mutation operator maps to a safety tier. The policy defines what is allowed at each tier:
| Tier | Name | Gate | Operators |
|---|---|---|---|
| 0 | AUTOMATED |
None | insert_code |
| 1 | DRY_RUN |
Sandbox tests must pass | rewrite_function, add_parameter, duplicate_component |
| 2 | HUMAN_APPROVAL |
Interactive prompt | swap_condition |
| 3 | BLOCKED |
Never allowed | eval, exec, os.system, subprocess, etc. |
The policy also enforces:
- Blocked AST nodes:
Exec,Eval,Call(when used dangerously) - Blocked imports: os, subprocess, shutil, signal, ctypes, socket, multiprocessing
- Protected modules: The
safety/andarchive/packages are immune to mutation - Path restrictions: Only
.py,.toml,.md,.json, etc. files within the forge root
Every Tier 1+ mutation must pass through the fork-test-promote lifecycle:
BEFORE AFTER (if tests pass)
β β²
βΌ β
βββββββββββββββββββββββββββββββββββββββββββ
β 1. FORK: Copy source to temp sandbox β
β 2. MUTATE: Apply operator to sandbox β
β 3. VALIDATE: β
β ββ Syntax check (ast.parse) β
β ββ AST safety scan (blocked nodes) β
β ββ Dangerous pattern scan (regex) β
β ββ Unit test execution (pytest) β
β 4. PROMOTE: Write to live file β
β OR β
β ROLLBACK: Restore original source β
βββββββββββββββββββββββββββββββββββββββββββ
Every mutation β whether approved or rejected β is recorded in an append-only, hash-chained audit log. Each entry contains:
| Field | Description |
|---|---|
timestamp |
Unix timestamp of the mutation |
mutation_id |
Unique UUID for the mutation |
operator |
Name of the mutation operator |
tier |
Safety tier at which it was assessed |
component_path |
Relative path to the mutated component |
source_hash_before |
SHA-256 of source before mutation |
source_hash_after |
SHA-256 of source after mutation |
safety_verdict |
approved, rejected, or rolled_back |
safety_violations |
List of violations (if rejected) |
human_approver |
Who approved (if Tier 2) |
sandbox_result |
passed, failed, or skipped |
prev_hash |
SHA-256 of the previous entry |
entry_hash |
SHA-256 of this entry |
The prev_hash β entry_hash chain provides tamper evidence: modifying an entry changes its hash, breaking the chain for all subsequent entries. The chain can be verified at any time:
from safety import AuditLog
audit = AuditLog()
chain_ok, issues = audit.verify_chain()Before any mutation cycle begins, the safety validator performs a full environment scan:
- All forge source files must parse as valid Python
- No blocked modules are imported in forge source
- The forge root directory is writable and accessible
- The audit log chain is intact from the previous run
| Scenario | Mechanism |
|---|---|
| Tier 2 operator selected | Interactive prompt: Approve this self-modification? [y/N] |
--human-approval flag |
Every mutation, regardless of tier, requires approval |
| Consecutive safety failures | Forge halts after max_consecutive_failures (default: 5) |
| Audit chain violation | Error logged immediately upon detection |
| Mechanism | Trigger | Scope |
|---|---|---|
| Git revert | Auto-commit before each mutation; git revert on failure |
Full file |
| Archive restore | Snapshots every generation; rollback_to(N) |
Full state |
| Sandbox rollback | Mutation fails sandbox tests | Single file |
| Safety violation | Dangerous pattern detected | Mutation cancelled (no write) |
| Attack | Defense |
|---|---|
Mutation inserts eval() |
Blocked at Tier 3 β never allowed |
Mutation imports os to delete files |
Blocked at Tier 3 β blocked import |
| Mutation modifies safety code | Blocked β protected module |
| Mutation writes outside forge root | Blocked β path sandboxing |
| Operator tries to escape tier | Blocked β operatorβtier mapping is immutable policy |
| Audit log is tampered | Detected β hash chain breaks on next verification |
| Sandbox test is skipped | Impossible β Tier 1+ requires sandbox pass before promote |
- Always use
--human-approvalfor unattended runs - Review
.env.exampleand setHUMAN_APPROVAL=true - Verify the audit log chain before each session
- Run in a dedicated directory or container
- Ensure git is initialized for rollback capability
- Set
META_PATHto a persistent, backed-up location - Review
safety/policy.pybefore adding new operators - Never disable safety (
--safety-off) in production
| Research Direction | Description |
|---|---|
| 𧬠Self-Referential Evolution | Can a system improve its own evolutionary algorithm by mutating its own source code? |
| π Second-Order Adaptation | Does tracking operator-level fitness deltas lead to more efficient evolution than fixed-operator GAs? |
| π‘οΈ Safe Self-Modification | Can safety guardrails be designed that are robust enough to allow creative exploration while preventing destructive outcomes? |
| π Self-Evaluation Accuracy | Do AST-level fitness metrics (syntax, complexity, safety) correlate with actual evolution quality? |
| ποΈ Evolutionary Memory | Does maintaining an immutable archive of all mutations improve the system's ability to roll back from local optima? |
- β A claim of AGI, sentience, or consciousness
- β An unconstrained recursive self-improvement system
- β A production-ready code generator
β It is a well-scoped experimental platform for studying how genetic algorithms can safely modify their own implementation β with strong guardrails, immutable history, and full human oversight.
MIT β see LICENSE.
| Contribution | Link |
|---|---|
| 𧬠Predecessor | grounded_agent_forge β full agent blueprint evolution platform |
| π Inspiration | grounded_evolution β execution-grounded prompt evolution with 203 evolution cycles |
| π€ Primary Coding Model | DeepSeek V4 β used as the primary AI coding model for this entire project |