Overview
Signals are actionable patterns extracted from logs, transcripts, and memory that trigger evolution. They serve as the bridge between raw runtime observations and structured evolution decisions.
Signal Types
Signals fall into three broad categories:
Defensive Errors, missing resources, stability issues
Opportunity Feature requests, capability gaps, performance bottlenecks
Meta Stagnation, repair loops, drift detection
The extractSignals() function scans multiple data sources to build a comprehensive signal list:
// From src/gep/signals.js:137
function extractSignals ({ recentSessionTranscript , todayLog , memorySnippet , userSnippet , recentEvents }) {
var signals = [];
var corpus = [
String ( recentSessionTranscript || '' ),
String ( todayLog || '' ),
String ( memorySnippet || '' ),
String ( userSnippet || '' ),
]. join ( ' \n ' );
var lower = corpus . toLowerCase ();
// Analyze recent evolution history for de-duplication
var history = analyzeRecentHistory ( recentEvents || []);
// Extract signals...
}
Defensive Signals
These signals indicate errors or missing resources that need immediate repair.
Error Detection
// From src/gep/signals.js:154
var errorHit = / \[ error \] | error: | exception: | iserror":true | "status": \s * "error" | "status": \s * "failed" | 错误 \s * [ :: ] | 异常 \s * [ :: ] | 报错 \s * [ :: ] | 失败 \s * [ :: ] / . test ( lower );
if ( errorHit ) signals . push ( 'log_error' );
The regex prioritizes structured error markers to avoid false positives on “fail”/“failed” in normal text.
Error Signature
For more reproducible error tracking, the system extracts an error signature :
// From src/gep/signals.js:158
try {
var lines = corpus . split ( ' \n ' ). map ( l => String ( l || '' ). trim ()). filter ( Boolean );
var errLine = lines . find ( l =>
/ \b ( typeerror | referenceerror | syntaxerror ) \b \s * : | error \s * : | exception \s * : | \[ error | 错误 \s * [ :: ] | 异常 \s * [ :: ] | 报错 \s * [ :: ] | 失败 \s * [ :: ] / i . test ( l )
) || null ;
if ( errLine ) {
var clipped = errLine . replace ( / \s + / g , ' ' ). slice ( 0 , 260 );
signals . push ( 'errsig:' + clipped );
}
} catch ( e ) {}
Recurring Error Detection
When the same error appears 3+ times, it’s flagged as recurring :
// From src/gep/signals.js:188
try {
var errorCounts = {};
var errPatterns = corpus . match ( / (?: LLM error | "error" | "status": \s * "error" ) [ ^ } ] {0,200} / gi ) || [];
for ( var ep = 0 ; ep < errPatterns . length ; ep ++ ) {
var key = errPatterns [ ep ]. replace ( / \s + / g , ' ' ). slice ( 0 , 100 );
errorCounts [ key ] = ( errorCounts [ key ] || 0 ) + 1 ;
}
var recurringErrors = Object . entries ( errorCounts ). filter ( e => e [ 1 ] >= 3 );
if ( recurringErrors . length > 0 ) {
signals . push ( 'recurring_error' );
var topErr = recurringErrors . sort (( a , b ) => b [ 1 ] - a [ 1 ])[ 0 ];
signals . push ( 'recurring_errsig(' + topErr [ 1 ] + 'x):' + topErr [ 0 ]. slice ( 0 , 150 ));
}
} catch ( e ) {}
Missing Resources
// From src/gep/signals.js:174
if ( lower . includes ( 'memory.md missing' )) signals . push ( 'memory_missing' );
if ( lower . includes ( 'user.md missing' )) signals . push ( 'user_missing' );
if ( lower . includes ( 'key missing' )) signals . push ( 'integration_key_missing' );
if ( lower . includes ( 'no session logs found' )) signals . push ( 'session_logs_missing' );
Opportunity Signals
These signals indicate chances to innovate rather than just fix errors.
Feature Requests
Supports 4 languages (EN, ZH-CN, ZH-TW, JA) with snippet extraction :
// From src/gep/signals.js:212
var featureRequestSnippet = '' ;
var featEn = corpus . match ( / \b ( add | implement | create | build | make | develop | write | design ) \b [ ^ .?!\n ] {3,120} \b ( feature | function | module | capability | tool | support | endpoint | command | option | mode ) \b / i );
if ( featEn ) featureRequestSnippet = featEn [ 0 ]. replace ( / \s + / g , ' ' ). trim (). slice ( 0 , 200 );
// Chinese detection
if ( ! featureRequestSnippet && /加个 | 实现一下 | 做个 | 想要 \s * 一个 | 需要 \s * 一个/ . test ( corpus )) {
var featZh = corpus . match ( / . {0,100} ( 加个 | 实现一下 | 做个 | 想要 \s * 一个 | 需要 \s * 一个 ) . {0,100} / );
if ( featZh ) featureRequestSnippet = featZh [ 0 ]. replace ( / \s + / g , ' ' ). trim (). slice ( 0 , 200 );
}
if ( featureRequestSnippet ) {
signals . push ( 'user_feature_request:' + featureRequestSnippet );
}
English : “add”, “implement”, “create”, “build”, “make”, “I want”, “I need”
Chinese (Simplified) : 加个, 实现一下, 做个, 想要一个, 需要一个
Chinese (Traditional) : 加個, 實現一下, 做個, 想要一個
Japanese : 追加, 実装, 作って, 機能を, が欲しい
Improvement Suggestions
// From src/gep/signals.js:246
if ( ! errorHit ) { // Only detect improvements when there's no error
var impEn = corpus . match ( / . {0,80} \b ( should be | could be better | improve | enhance | upgrade | refactor | clean up | simplify | streamline ) \b . {0,80} / i );
if ( impEn ) improvementSnippet = impEn [ 0 ]. replace ( / \s + / g , ' ' ). trim (). slice ( 0 , 200 );
if ( improvementSnippet ) {
signals . push ( 'user_improvement_suggestion:' + improvementSnippet );
}
}
// From src/gep/signals.js:271
if ( / \b ( slow | timeout | timed ? \s * out | latency | bottleneck | took too long | performance issue | high cpu | high memory | oom | out of memory ) \b / i . test ( lower )) {
signals . push ( 'perf_bottleneck' );
}
Capability Gaps
// From src/gep/signals.js:276
if ( / \b ( not supported | cannot | doesn' ? t support | no way to | missing feature | unsupported | not available | not implemented | no support for ) \b / i . test ( lower )) {
if ( ! signals . includes ( 'memory_missing' ) && ! signals . includes ( 'user_missing' )) {
signals . push ( 'capability_gap' );
}
}
Signal De-duplication
To prevent repair loops , the system analyzes recent evolution history and suppresses over-processed signals.
History Analysis
// From src/gep/signals.js:28
function analyzeRecentHistory ( recentEvents ) {
var recent = recentEvents . slice ( - 10 );
var tail = recent . slice ( - 8 );
// Count signal frequency in last 8 events
var signalFreq = {};
for ( var j = 0 ; j < tail . length ; j ++ ) {
var sigs = Array . isArray ( tail [ j ]. signals ) ? tail [ j ]. signals : [];
for ( var k = 0 ; k < sigs . length ; k ++ ) {
var s = String ( sigs [ k ]);
var key = s . startsWith ( 'errsig:' ) ? 'errsig'
: s . startsWith ( 'recurring_errsig' ) ? 'recurring_errsig'
: s . startsWith ( 'user_feature_request:' ) ? 'user_feature_request'
: s ;
signalFreq [ key ] = ( signalFreq [ key ] || 0 ) + 1 ;
}
}
// Suppress signals that appeared in 3+ of the last 8 events
var suppressedSignals = new Set ();
for ( var [ sig , count ] of Object . entries ( signalFreq )) {
if ( count >= 3 ) suppressedSignals . add ( sig );
}
return { suppressedSignals , recentIntents , consecutiveRepairCount , ... };
}
Suppression Logic
// From src/gep/signals.js:322
if ( history . suppressedSignals . size > 0 ) {
var beforeDedup = signals . length ;
signals = signals . filter ( s => {
var key = s . startsWith ( 'errsig:' ) ? 'errsig'
: s . startsWith ( 'recurring_errsig' ) ? 'recurring_errsig'
: s . startsWith ( 'user_feature_request:' ) ? 'user_feature_request'
: s ;
return ! history . suppressedSignals . has ( key );
});
if ( beforeDedup > 0 && signals . length === 0 ) {
// All signals suppressed = stable but stuck in loop
signals . push ( 'evolution_stagnation_detected' );
signals . push ( 'stable_success_plateau' );
}
}
If all signals are suppressed , the system injects evolution_stagnation_detected to force a strategy change.
Repair Loop Detection
When 3+ consecutive repairs fail, the system forces innovation intent :
// From src/gep/signals.js:342
if ( history . consecutiveRepairCount >= 3 ) {
// Remove repair-only signals
signals = signals . filter ( s =>
s !== 'log_error' && ! s . startsWith ( 'errsig:' ) && ! s . startsWith ( 'recurring_errsig' )
);
if ( signals . length === 0 ) {
signals . push ( 'repair_loop_detected' );
signals . push ( 'stable_success_plateau' );
}
signals . push ( 'force_innovation_after_repair_loop' );
}
Empty Cycle Detection
When 50%+ of last 8 cycles produced zero code changes , the evolver is spinning idle:
// From src/gep/signals.js:356
if ( history . emptyCycleCount >= 4 ) {
signals = signals . filter ( s =>
s !== 'log_error' && ! s . startsWith ( 'errsig:' )
);
if ( ! signals . includes ( 'empty_cycle_loop_detected' ))
signals . push ( 'empty_cycle_loop_detected' );
if ( ! signals . includes ( 'stable_success_plateau' ))
signals . push ( 'stable_success_plateau' );
}
Saturation & Graceful Degradation
When consecutive empty cycles pile up, the system switches to steady-state mode :
// From src/gep/signals.js:370
if ( history . consecutiveEmptyCycles >= 5 ) {
if ( ! signals . includes ( 'force_steady_state' ))
signals . push ( 'force_steady_state' );
if ( ! signals . includes ( 'evolution_saturation' ))
signals . push ( 'evolution_saturation' );
} else if ( history . consecutiveEmptyCycles >= 3 ) {
if ( ! signals . includes ( 'evolution_saturation' ))
signals . push ( 'evolution_saturation' );
}
This addresses the Echo-MingXuan failure : Cycle #55 hit “no committable changes” and load spiked to 1.30 because there was no degradation strategy.
Failure Streak Awareness
After 5+ consecutive failures, the system bans the dominant gene to force strategy change:
// From src/gep/signals.js:382
if ( history . consecutiveFailureCount >= 3 ) {
signals . push ( 'consecutive_failure_streak_' + history . consecutiveFailureCount );
if ( history . consecutiveFailureCount >= 5 ) {
signals . push ( 'failure_loop_detected' );
var topGene = null ;
var topGeneCount = 0 ;
for ( var [ gene , count ] of Object . entries ( history . geneFreq )) {
if ( count > topGeneCount ) {
topGeneCount = count ;
topGene = gene ;
}
}
if ( topGene ) signals . push ( 'ban_gene:' + topGene );
}
}
High tool usage can indicate inefficient automation or manual loops:
// From src/gep/signals.js:284
var toolUsage = {};
var toolMatches = corpus . match ( / \[ TOOL: \s * ( [ \w- ] + ) \] / g ) || [];
for ( var i = 0 ; i < toolMatches . length ; i ++ ) {
var toolName = toolMatches [ i ]. match ( / \[ TOOL: \s * ( [ \w- ] + ) \] / )[ 1 ];
toolUsage [ toolName ] = ( toolUsage [ toolName ] || 0 ) + 1 ;
}
Object . keys ( toolUsage ). forEach ( tool => {
if ( toolUsage [ tool ] >= 10 ) {
signals . push ( 'high_tool_usage:' + tool );
}
if ( tool === 'exec' && toolUsage [ tool ] >= 5 ) {
signals . push ( 'repeated_tool_usage:exec' );
}
});
Signal Prioritization
Cosmetic signals are removed when actionable signals exist:
// From src/gep/signals.js:312
var actionable = signals . filter ( s =>
s !== 'user_missing' &&
s !== 'memory_missing' &&
s !== 'session_logs_missing'
);
if ( actionable . length > 0 ) {
signals = actionable ;
}
Default Fallback
// From src/gep/signals.js:410
if ( signals . length === 0 ) {
signals . push ( 'stable_success_plateau' );
}
return Array . from ( new Set ( signals ));
Example Signal Flow
Next Steps
Evolution Cycle See how signals trigger the evolution cycle
Mutations Learn how signals map to mutation categories