What is an EvolutionEvent?
An EvolutionEvent is an immutable audit log entry that records every evolution cycle. Events form a tree structure via parent_id, enabling:
Complete Audit Trail : Every change is traceable
Evolution Trees : Visualize branching and lineage
Outcome Tracking : Success/failure rates over time
Rollback Support : Trace back to any historical state
Event Structure
Unique identifier (e.g., evt_1770477654236)
ID of the parent event (forms evolution tree). null for root events.
Evolution intent: repair, optimize, or innovate
Signals that triggered this evolution cycle
IDs of Genes applied in this cycle
ID of the Mutation that gated this evolution
Personality configuration at the time of evolution
Actual impact: { files: number, lines: number }
Result: { status: "success" | "failed", score: number }
ID of the Capsule created (only present if status=success)
Environment metadata (node version, platform, OS, etc.)
ID of the ValidationReport
Detailed metadata: selector decision, constraints, validation results, etc.
Real Event Examples
Example 1: Failed Innovation Event
This event attempted innovation but violated constraints:
{
"type" : "EvolutionEvent" ,
"schema_version" : "1.5.0" ,
"id" : "evt_1770477201173" ,
"parent" : "evt_1770476523037" ,
"intent" : "innovate" ,
"signals" : [
"user_missing" ,
"user_feature_request"
],
"genes_used" : [
"gene_gep_innovate_from_opportunity"
],
"mutation_id" : "mut_1770476534173" ,
"personality_state" : {
"type" : "PersonalityState" ,
"rigor" : 0.7 ,
"creativity" : 0.35 ,
"verbosity" : 0.25 ,
"risk_tolerance" : 0.4 ,
"obedience" : 0.9
},
"blast_radius" : {
"files" : 1 ,
"lines" : 2
},
"outcome" : {
"status" : "failed" ,
"score" : 0.2
},
"capsule_id" : null ,
"env_fingerprint" : {
"node_version" : "v22.22.0" ,
"platform" : "linux" ,
"arch" : "x64" ,
"os_release" : "6.1.0-42-cloud-amd64" ,
"evolver_version" : "1.7.0" ,
"cwd" : "/home/crishaocredits/.openclaw/workspace" ,
"captured_at" : "2026-02-07T15:13:21.123Z"
},
"validation_report_id" : "vr_1770477201172" ,
"meta" : {
"at" : "2026-02-07T15:13:21.173Z" ,
"signal_key" : "user_feature_request|user_missing" ,
"selector" : {
"selected" : "gene_gep_innovate_from_opportunity" ,
"reason" : [
"signals match gene.signals_match" ,
"signals: user_missing, user_feature_request" ,
"memory_graph: memory_prefer:gene_gep_innovate_from_opportunity | gene_prior:0.667"
],
"alternatives" : []
},
"constraints_ok" : false ,
"constraint_violations" : [
"forbidden_path touched: assets/gep/events.jsonl"
],
"validation_ok" : true
}
}
Validation Passed : All commands succeeded (validation_ok: true)Constraint Violation : Attempted to modify assets/gep/events.jsonl, which is forbiddenLow Score : outcome.score = 0.2 reflects constraint violationNo Capsule : Failed events don’t create Capsules (capsule_id: null)Parent Reference : parent: "evt_1770476523037" links to previous event in tree
Example 2: Successful Repair Event
This event successfully repaired a shell compatibility error:
{
"type" : "EvolutionEvent" ,
"schema_version" : "1.5.0" ,
"id" : "evt_1770477654236" ,
"parent" : "evt_1770477201173" ,
"intent" : "repair" ,
"signals" : [
"log_error" ,
"errsig:**TOOLRESULT**: { \" status \" : \" error \" , \" tool \" : \" exec \" , \" error \" : \" error: unknown command 'process' \\ n \\ nCommand exited with code 1 \" }" ,
"user_missing" ,
"windows_shell_incompatible" ,
"perf_bottleneck"
],
"genes_used" : [
"gene_gep_repair_from_errors"
],
"mutation_id" : "mut_1770477615603" ,
"personality_state" : {
"type" : "PersonalityState" ,
"rigor" : 0.7 ,
"creativity" : 0.35 ,
"verbosity" : 0.25 ,
"risk_tolerance" : 0.4 ,
"obedience" : 0.9
},
"blast_radius" : {
"files" : 1 ,
"lines" : 2
},
"outcome" : {
"status" : "success" ,
"score" : 0.85
},
"capsule_id" : "capsule_1770477654236" ,
"env_fingerprint" : {
"node_version" : "v22.22.0" ,
"platform" : "linux" ,
"arch" : "x64" ,
"os_release" : "6.1.0-42-cloud-amd64" ,
"evolver_version" : "1.7.0" ,
"cwd" : "/home/crishaocredits/.openclaw/workspace" ,
"captured_at" : "2026-02-07T15:20:54.155Z"
},
"validation_report_id" : "vr_1770477654235" ,
"meta" : {
"at" : "2026-02-07T15:20:54.236Z" ,
"signal_key" : "errsig_norm:870c3a82|log_error|perf_bottleneck|user_missing|windows_shell_incompatible" ,
"selector" : {
"selected" : "gene_gep_repair_from_errors" ,
"reason" : [
"signals match gene.signals_match" ,
"signals: log_error, errsig:**TOOLRESULT**: { \" status \" : \" error \" , \" tool \" : \" exec \" , \" error \" : \" error: unknown command 'process' \\ n \\ nCommand exited with code 1 \" }, user_missing, windows_shell_incompatible, perf_bottleneck" ,
"memory_graph: memory_prefer:gene_gep_repair_from_errors | gene_prior:0.500"
],
"alternatives" : [
"gene_gep_innovate_from_opportunity"
]
},
"constraints_ok" : true ,
"validation_ok" : true
}
}
Parent Event : evt_1770477201173 (the failed innovation attempt)Intent Switch : Changed from innovate to repair due to error signalsGene Selection : Repair Gene chosen over innovation GeneSuccess : Both validation and constraints passedCapsule Created : capsule_1770477654236 captures this solution
Tree Structure via parent_id
Building Evolution Trees
Events form a directed acyclic graph (DAG) via parent_id:
evt_1770476523037 (root)
└── evt_1770477201173 (failed innovate)
├── evt_1770477654236 (success repair, 1 file/2 lines)
└── evt_1770478341769 (success repair, 2 files/44 lines)
Querying Event History
From src/gep/assetStore.js:
function readAllEvents () {
try {
const raw = fs . readFileSync ( 'assets/gep/events.jsonl' , 'utf8' );
return raw . split ( ' \n ' )
. map ( l => l . trim ())
. filter ( Boolean )
. map ( l => {
try { return JSON . parse ( l ); }
catch { return null ; }
})
. filter ( Boolean );
} catch { return []; }
}
function getLastEventId () {
const events = readAllEvents ();
if ( events . length === 0 ) return null ;
const last = events [ events . length - 1 ];
return last . id || null ;
}
Computing Success Streaks
Capsule success streaks are computed by walking the event tree:
// From src/gep/a2a.js
function computeCapsuleSuccessStreak ( capsuleId , events ) {
let streak = 0 ;
for ( let i = events . length - 1 ; i >= 0 ; i -- ) {
const ev = events [ i ];
if ( ! ev || ev . type !== 'EvolutionEvent' ) continue ;
if ( String ( ev . capsule_id ) !== String ( capsuleId )) continue ;
const status = ev . outcome ?. status || 'unknown' ;
if ( status === 'success' ) streak ++ ;
else break ; // streak broken by failure
}
return streak ;
}
Validation Reports
ValidationReport Structure
Each event references a ValidationReport:
{
"type" : "ValidationReport" ,
"schema_version" : "1.5.0" ,
"id" : "vr_1770477654235" ,
"gene_id" : "gene_gep_repair_from_errors" ,
"env_fingerprint" : {
"node_version" : "v22.22.0" ,
"platform" : "linux" ,
"arch" : "x64" ,
"os_release" : "6.1.0-42-cloud-amd64" ,
"evolver_version" : "1.7.0"
},
"env_fingerprint_key" : "b98472b2ef785976" ,
"commands" : [
{
"command" : "node scripts/validate-modules.js ./src/evolve ./src/gep/solidify" ,
"ok" : true ,
"stdout" : "ok \n " ,
"stderr" : ""
},
{
"command" : "node scripts/validate-modules.js ./src/gep/selector ./src/gep/memoryGraph" ,
"ok" : true ,
"stdout" : "ok \n " ,
"stderr" : ""
}
],
"overall_ok" : true ,
"duration_ms" : 80 ,
"created_at" : "2026-02-07T15:20:54.236Z" ,
"asset_id" : "sha256:404345b559ec9a29d30444c3d66ff8f346d87017b7dea1d965ae35f029c8d5c6"
}
Selector Decision
The meta.selector object records why a particular Gene/Capsule was chosen:
"selector" : {
"selected" : "gene_gep_repair_from_errors" ,
"reason" : [
"signals match gene.signals_match" ,
"signals: log_error, exception, failed" ,
"memory_graph: memory_prefer:gene_gep_repair_from_errors | gene_prior:0.500"
],
"alternatives" : [ "gene_gep_innovate_from_opportunity" ]
}
Signal Key
The meta.signal_key is a normalized, sorted concatenation of all signals:
"signal_key" : "errsig_norm:870c3a82|log_error|perf_bottleneck|user_missing|windows_shell_incompatible"
This key is used for:
Deduplication : Prevent identical signal patterns from triggering multiple times
Memory Graph : Track success rates per signal combination
Capsule Matching : Find Capsules that handled similar signal patterns
Personality State
Each event captures the personality configuration:
"personality_state" : {
"type" : "PersonalityState" ,
"rigor" : 0.7 ,
"creativity" : 0.35 ,
"verbosity" : 0.25 ,
"risk_tolerance" : 0.4 ,
"obedience" : 0.9
}
Parameters :
rigor: Strictness of validation (0.0-1.0)
creativity: Willingness to try new approaches (0.0-1.0)
verbosity: Output detail level (0.0-1.0)
risk_tolerance: Acceptance of larger blast radius (0.0-1.0)
obedience: Follow Gene strategy exactly vs. adapt (0.0-1.0)
Querying Event History
Find Events by Intent
const events = readAllEvents ();
const repairEvents = events . filter ( e => e . intent === 'repair' );
const successRate = repairEvents . filter ( e => e . outcome . status === 'success' ). length / repairEvents . length ;
Find Events by Gene
const geneEvents = events . filter ( e => e . genes_used . includes ( 'gene_gep_repair_from_errors' ));
const avgBlastRadius = geneEvents . reduce (( sum , e ) => sum + e . blast_radius . files , 0 ) / geneEvents . length ;
Build Evolution Tree
function buildTree ( events ) {
const nodes = new Map ();
events . forEach ( e => nodes . set ( e . id , { ... e , children: [] }));
events . forEach ( e => {
if ( e . parent ) {
const parent = nodes . get ( e . parent );
if ( parent ) parent . children . push ( nodes . get ( e . id ));
}
});
return Array . from ( nodes . values ()). filter ( n => ! n . parent );
}
Find Latest Event
// From src/gep/assetStore.js
function getLastEventId () {
try {
const raw = fs . readFileSync ( 'assets/gep/events.jsonl' , 'utf8' );
const lines = raw . split ( ' \n ' ). map ( l => l . trim ()). filter ( Boolean );
if ( lines . length === 0 ) return null ;
const last = JSON . parse ( lines [ lines . length - 1 ]);
return last ?. id || null ;
} catch { return null ; }
}
JSONL (JSON Lines)
Events are stored in assets/gep/events.jsonl with one JSON object per line:
{ "type" : "ValidationReport" , "id" : "vr_1770477201172" , ... }
{ "type" : "EvolutionEvent" , "id" : "evt_1770477201173" , "parent" : "evt_1770476523037" , ... }
{ "type" : "ValidationReport" , "id" : "vr_1770477654235" , ... }
{ "type" : "EvolutionEvent" , "id" : "evt_1770477654236" , "parent" : "evt_1770477201173" , ... }
Why JSONL? :
Append-Only : Fast writes, no parsing entire file
Immutable : Each line is a separate record
Crash-Resistant : Partial writes don’t corrupt entire log
Stream-Friendly : Can process line-by-line for large logs
Forbidden Modifications
The events.jsonl file is strictly forbidden from modification by Genes:
"constraints" : {
"forbidden_paths" : [
".git" ,
"node_modules" ,
"assets/gep/events.jsonl"
]
}
This ensures the audit trail remains immutable and tamper-proof.
Event Lifecycle
Signal Extraction
Parse logs, errors, and user instructions to extract signals
Gene/Capsule Selection
Selector chooses best match based on signals and history
Mutation Gating
Create Mutation object to gate the evolution cycle
Apply Changes
Execute Gene strategy or apply Capsule solution
Validation
Run validation commands; rollback on failure
Constraint Check
Verify blast radius and forbidden paths
Solidify
Append EvolutionEvent + ValidationReport to events.jsonl
Capsule Creation
If successful, create Capsule and append to capsules.json
Next Steps
A2A Protocol Learn how events and capsules are shared between agents
Hub Integration Query hub for solutions before local evolution