We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
Meta-Evolution: When AI Evolves AI
Exploring meta-evolution in Prismatic: how the platform's evolution system evolves itself, the role of genetic algorithms in quality improvement, and the philosophical implications of self-improving systems.
Tomas Korcak (korczis)
Prismatic Platform
Prismatic's auto-evolution system improves the platform's code. But what improves the evolution system itself? This is meta-evolution -- the process by which the improvement process improves. It sounds recursive because it is.
The Meta-Evolution Problem
The auto-evolution system has its own quality characteristics:
These characteristics can be measured, and if they can be measured, they can be optimized. The question is: who optimizes the optimizer?
Three Levels of Evolution
Prismatic operates at three evolutionary levels:
Level 1: Code Evolution -- the platform's code improves through mutation, evaluation, and selection. This is the base level described in our [Self-Evolving Architecture](/blog/self-evolving-architecture/) post.
Level 2: Process Evolution -- the evolution process itself improves. The scanner learns which patterns to look for. The mutator learns which transformations succeed. The evaluator refines its fitness function.
Level 3: Meta Evolution -- the framework for process evolution improves. New evaluation dimensions are added. New mutation strategies are developed. The architecture of the evolution system itself changes.
How Process Evolution Works
The evolution system tracks its own performance:
defmodule Prismatic.MetaEvolve.Tracker do
def track_mutation(mutation, result) do
:ets.insert(:evolution_history, {
mutation.type,
mutation.target,
result.accepted?,
result.fitness_delta,
DateTime.utc_now()
})
end
def mutation_success_rate(type, window_days \\ 30) do
cutoff = DateTime.add(DateTime.utc_now(), -window_days * 86400)
:evolution_history
|> :ets.match_object({type, :_, :_, :_, :"$1"})
|> Enum.filter(fn {_, _, _, _, ts} -> DateTime.compare(ts, cutoff) == :gt end)
|> then(fn entries ->
accepted = Enum.count(entries, fn {_, _, accepted?, _, _} -> accepted? end)
total = length(entries)
if total > 0, do: accepted / total, else: 0.0
end)
end
end
If a mutation type has a low success rate (e.g., documentation generation mutations are only accepted 60% of the time), the system can:
2. Adjust the evaluation -- perhaps the fitness function is too strict for this mutation type
3. Deprecate the mutation -- if it consistently produces low-value changes, stop attempting it
Fitness Function Evolution
The fitness function itself evolves. Initially, Prismatic's fitness function measured three dimensions:
Fitness = compilation_score 0.5 + test_score 0.3 + warning_count * 0.2
Over time, new dimensions were added based on observed failure modes:
Fitness = compilation * 0.20
+ tests * 0.20
+ doctrine * 0.20
+ documentation * 0.15
+ performance * 0.15
+ dependencies * 0.10
Each addition was itself a mutation at the meta level -- a change to the evolution system that was evaluated by its impact on overall platform quality.
The Philosophical Dimension
Meta-evolution raises interesting questions:
Convergence: Does the system converge to a fixed point where no further improvements are possible? In theory, yes -- but in practice, the environment changes (new dependencies, new requirements, new best practices), which creates new improvement opportunities.
Optimization target: What should a self-improving system optimize for? We chose a multi-dimensional fitness function rather than a single metric, because single-metric optimization leads to Goodhart's Law -- the metric improves but the underlying quality does not.
Guardrails: A self-improving system without guardrails could optimize itself into a local maximum that humans do not want. Our guardrails are explicit:
Transparency: Every meta-evolution change is committed to git with a detailed message. The system cannot evolve in ways that are invisible to human reviewers.
Practical Meta-Evolution Examples
Improved scanner accuracy: The scanner initially flagged too many false positives for "dead code." By tracking which flagged items were actually dead (vs. dynamically called or used in macros), the scanner learned to reduce false positives by 70%.
Better mutation ordering: Mutations were initially applied in random order. By tracking which mutation types tend to block other mutations (e.g., fixing a compilation error must happen before adding tests), the system learned to apply mutations in dependency order.
Adaptive thresholds: The fitness threshold for accepting a mutation was initially fixed at "no decrease." By analyzing the distribution of fitness changes, the system learned to accept small fitness decreases when they enable larger improvements in subsequent mutations.
Limits of Meta-Evolution
Meta-evolution is powerful but bounded:
The system is most effective for mechanical improvements: fixing anti-patterns, adding documentation, updating dependencies, and enforcing coding standards. Creative work remains human.
Conclusion
Meta-evolution is the natural extension of automated quality improvement. If you automate code improvement, you should also automate the improvement of the automation. Prismatic's three-level evolution system -- code, process, and meta -- ensures that quality improvement compounds over time rather than stagnating.
The key insight is that self-improvement requires self-measurement. Track the performance of your improvement process, and improvement opportunities emerge naturally.
Explore the [Evolution Module](/architecture/) for framework details or check the platform's current fitness with `mix health.score`.