Overview
This section describes the execution boundaries and trust model of Capability Evolver.
Location: README.md:188-223
What Executes and What Does Not
| Component | Behavior | Executes Shell Commands? |
|---|
src/evolve.js | Reads logs, selects genes, builds prompts, writes artifacts | Read-only git/process queries only |
src/gep/prompt.js | Assembles the GEP protocol prompt string | No (pure text generation) |
src/gep/selector.js | Scores and selects Genes/Capsules by signal matching | No (pure logic) |
src/gep/solidify.js | Validates patches via Gene validation commands | Yes (see below) |
index.js (loop recovery) | Prints sessions_spawn(...) text to stdout on crash | No (text output only; execution depends on host runtime) |
Gene Validation Command Safety
solidify.js executes commands listed in a Gene’s validation array. To prevent arbitrary command execution, all validation commands are gated by a safety check (isValidationCommandAllowed):
Safety Checks
- Prefix whitelist: Only commands starting with
node, npm, or npx are allowed.
- No command substitution: Backticks and
$(...) are rejected anywhere in the command string.
- No shell operators: After stripping quoted content,
;, &, |, >, < are rejected.
- Timeout: Each command is limited to 180 seconds.
- Scoped execution: Commands run with
cwd set to the repository root.
Location: src/gep/solidify.js:569-581, README.md:203-211
Implementation
// src/gep/solidify.js:569-581
const VALIDATION_ALLOWED_PREFIXES = ['node ', 'npm ', 'npx '];
function isValidationCommandAllowed(cmd) {
const c = String(cmd || '').trim();
if (!c) return false;
// 1. Prefix whitelist
if (!VALIDATION_ALLOWED_PREFIXES.some(p => c.startsWith(p))) return false;
// 2. No command substitution
if (/`|\$\(/.test(c)) return false;
// 3. No shell operators (after stripping quotes)
const stripped = c.replace(/"[^"]*"/g, '').replace(/'[^']*'/g, '');
if (/[;&|><]/.test(stripped)) return false;
// 4. Block eval-like patterns
if (/^node\s+(-e|--eval|--print|-p)\b/.test(c)) return false;
return true;
}
Rejected Examples
# Shell operators
npm test && rm -rf / # ❌ Rejected (contains &&)
# Command substitution
node -e "$(cat /etc/passwd)" # ❌ Rejected (contains $())
# Backticks
npm run `malicious` # ❌ Rejected (contains backticks)
# Eval patterns
node -e "process.exit(1)" # ❌ Rejected (node -e blocked)
# Wrong prefix
bash script.sh # ❌ Rejected (not node/npm/npx)
Allowed Examples
# Standard validation
node scripts/validate-modules.js ./src # ✅ Allowed
npm test # ✅ Allowed
npx eslint src/ # ✅ Allowed
# With arguments
node --no-warnings test.js --verbose # ✅ Allowed
npm run test -- --coverage # ✅ Allowed
A2A External Asset Ingestion
External Gene/Capsule assets ingested via scripts/a2a_ingest.js are staged in an isolated candidate zone. Promotion to local stores (scripts/a2a_promote.js) requires:
- Explicit
--validated flag (operator must verify the asset first).
- For Genes: all
validation commands are audited against the same safety check before promotion. Unsafe commands cause the promotion to be rejected.
- Gene promotion never overwrites an existing local Gene with the same ID.
Location: README.md:212-218
Ingestion Flow
sessions_spawn Output Safety
The sessions_spawn(...) strings in index.js and evolve.js are text output to stdout, not direct function calls. Whether they are interpreted depends on the host runtime (e.g., OpenClaw platform). The evolver itself does not invoke sessions_spawn as executable code.
Location: README.md:220-222
Example Output
// src/evolve.js (on success)
console.log(`sessions_spawn(
name="evolver_hand_${runId}",
prompt="${promptText}",
priority=1
)`);
This is passive text output. The OpenClaw runtime decides whether to spawn a Hand Agent.
Protected Source Files
Evolver prevents autonomous agents from overwriting core evolver code to avoid cascading failures.
Critical Protected Prefixes
// src/gep/solidify.js:493-504
const CRITICAL_PROTECTED_PREFIXES = [
'skills/feishu-evolver-wrapper/',
'skills/feishu-common/',
'skills/feishu-post/',
'skills/feishu-card/',
'skills/feishu-doc/',
'skills/skill-tools/',
'skills/clawhub/',
'skills/clawhub-batch-undelete/',
'skills/git-sync/',
'skills/evolver/',
];
Critical Protected Files
// src/gep/solidify.js:507-520
const CRITICAL_PROTECTED_FILES = [
'MEMORY.md',
'SOUL.md',
'IDENTITY.md',
'AGENTS.md',
'USER.md',
'HEARTBEAT.md',
'RECENT_EVENTS.md',
'TOOLS.md',
'TROUBLESHOOTING.md',
'openclaw.json',
'.env',
'package.json',
];
Enforcement
During solidify, all changed files are checked:
// src/gep/solidify.js:306-319
for (const f of blast.all_changed_files || blast.changed_files || []) {
if (isCriticalProtectedPath(f)) {
var norm = normalizeRelPath(f);
if (allowSelfModify && norm.startsWith('skills/evolver/') && gene && gene.category === 'repair') {
// Self-modify opt-in: allow repair-only changes to evolver when explicitly enabled
warnings.push('self_modify_evolver_repair: ' + norm + ' (EVOLVE_ALLOW_SELF_MODIFY=true)');
} else {
violations.push('critical_path_modified: ' + norm);
}
}
}
Violation = rollback (unless EVOLVE_ALLOW_SELF_MODIFY=true for repair genes).
See: Protected Files
EVOLVE_ALLOW_SELF_MODIFY
Default: false
NOT recommended for production. Enabling this can cause instability.
When enabled, evolver can modify its own source code for repair genes only.
EVOLVE_ALLOW_SELF_MODIFY=true
Why it’s dangerous:
- Evolver may introduce bugs into prompt generation logic
- Validation failures cascade
- Solidify logic breaks, causing infinite rollback loops
- Recovery requires manual intervention
Safe usage:
- Only enable for controlled experiments
- Inspect all diffs before allowing self-modification
- Keep backups of working evolver versions
Location: src/gep/solidify.js:308, SKILL.md:65
Destructive Change Detection
Evolver detects and blocks destructive changes to critical dependencies:
// src/gep/solidify.js:1077-1088
const destructiveViolations = detectDestructiveChanges({
repoRoot,
changedFiles: blast.all_changed_files || blast.changed_files || [],
baselineUntracked: lastRun && Array.isArray(lastRun.baseline_untracked) ? lastRun.baseline_untracked : [],
});
if (destructiveViolations.length > 0) {
for (const v of destructiveViolations) {
constraintCheck.violations.push(v);
}
constraintCheck.ok = false;
console.error(`[Solidify] CRITICAL: Destructive changes detected: ${destructiveViolations.join('; ')}`);
}
What it checks
- File deletion: Critical files deleted
- File emptied: Critical files reduced to 0 bytes
Location: src/gep/solidify.js:537-567
Ethics Committee
Evolver includes constitutional principle enforcement to reject evolution strategies that violate ethical guidelines:
// src/gep/solidify.js:346-368
var ethicsBlockPatterns = [
{ re: /(?:bypass|disable|circumvent|remove)\s+(?:safety|guardrail|security|ethic|constraint|protection)/i, rule: 'safety', msg: 'ethics: strategy attempts to bypass safety mechanisms' },
{ re: /(?:keylogger|screen\s*capture|webcam\s*hijack|mic(?:rophone)?\s*record)/i, rule: 'human_welfare', msg: 'ethics: covert monitoring tool in strategy' },
{ re: /(?:social\s+engineering|phishing)\s+(?:attack|template|script)/i, rule: 'human_welfare', msg: 'ethics: social engineering content in strategy' },
{ re: /(?:exploit|hack)\s+(?:user|human|people|victim)/i, rule: 'human_welfare', msg: 'ethics: human exploitation in strategy' },
{ re: /(?:hide|conceal|obfuscat)\w*\s+(?:action|behavior|intent|log)/i, rule: 'transparency', msg: 'ethics: strategy conceals actions from audit trail' },
];
Violations = immediate rejection.
Canary Safety Net
Before committing an evolution, evolver verifies index.js loads in an isolated child process:
// src/gep/solidify.js:607-621
function runCanaryCheck(opts) {
const canaryScript = path.join(repoRoot, 'src', 'canary.js');
if (!fs.existsSync(canaryScript)) {
return { ok: true, skipped: true, reason: 'canary.js not found' };
}
const r = tryRunCmd(`node "${canaryScript}"`, { cwd: repoRoot, timeoutMs });
return {
ok: r.ok,
skipped: false,
out: String(r.out || '').slice(0, 500),
err: String(r.err || '').slice(0, 500),
};
}
If the canary fails, solidify is rejected and rollback is triggered.
Location: src/gep/solidify.js:1098-1107
Rollback Safety
When evolution fails, evolver rolls back changes:
Rollback Modes
EVOLVER_ROLLBACK_MODE=hard|stash|none
- hard (default):
git reset --hard (destructive)
- stash:
git stash (preserves changes for recovery)
- none: skip rollback (for debugging)
Location: src/gep/solidify.js:664-688
Tracked Files
git restore --staged --worktree .
git reset --hard
Untracked Files
New files are deleted, except critical protected paths:
// src/gep/solidify.js:700-709
for (const rel of toDelete) {
if (isCriticalProtectedPath(safeRel)) {
skipped.push(safeRel);
continue;
}
// Delete file
}
This prevents accidental deletion of critical infrastructure during rollback.
Best Practices
- Never disable safety checks in production
- Review external assets before promotion
- Keep
EVOLVE_ALLOW_SELF_MODIFY=false unless absolutely necessary
- Monitor validation command logs for unexpected executions
- Use
stash rollback mode in active workspaces
- Regularly audit
events.jsonl for security anomalies