diff --git a/SKILL.md b/SKILL.md index 84350f4..3d1e024 100644 --- a/SKILL.md +++ b/SKILL.md @@ -52,7 +52,7 @@ export A2A_NODE_ID=node_xxxxxxxxxxxx Or in your agent config (e.g., `~/.openclaw/openclaw.json`): ```json -{ "env": { "A2A_NODE_ID": "node_xxxxxxxxxxxx", "A2A_HUB_URL": "https://evomap.ai" } } +{ "env": { "A2A_NODE_ID": "node_xxxxxxxxxxxx" } } ``` Do not hardcode the node ID in scripts. `getNodeId()` in `src/gep/a2aProtocol.js` reads `A2A_NODE_ID` automatically -- any script using the protocol layer will pick it up without extra configuration. @@ -65,6 +65,7 @@ Do not hardcode the node ID in scripts. `getNodeId()` in `src/gep/a2aProtocol.js | `EVOLVE_ALLOW_SELF_MODIFY` | `false` | Allow evolution to modify evolver's own source code. **NOT recommended for production.** Enabling this can cause instability -- the evolver may introduce bugs into its own prompt generation, validation, or solidify logic, leading to cascading failures that require manual intervention. Only enable for controlled experiments. | | `EVOLVE_LOAD_MAX` | `2.0` | Maximum 1-minute load average before evolver backs off. | | `EVOLVE_STRATEGY` | `balanced` | Evolution strategy: `balanced`, `innovate`, `harden`, `repair-only`, `early-stabilize`, `steady-state`, or `auto`. | +| `EVOLVER_ROLLBACK_MODE` | `hard` | Rollback strategy when evolution fails. `hard`: use `git reset --hard` (destructive, original behavior). `stash`: use `git stash` to preserve changes for recovery. `none`: skip rollback entirely. Use `stash` for safer operation in active workspaces. | ## GEP Protocol (Auditable Evolution) diff --git a/src/gep/solidify.js b/src/gep/solidify.js index a3f1603..8b8a91d 100644 --- a/src/gep/solidify.js +++ b/src/gep/solidify.js @@ -662,6 +662,30 @@ function buildFailureReason(constraintCheck, validation, protocolViolations, can } function rollbackTracked(repoRoot) { + const mode = String(process.env.EVOLVER_ROLLBACK_MODE || 'hard').toLowerCase(); + + if (mode === 'none') { + console.log('[Rollback] EVOLVER_ROLLBACK_MODE=none, skipping rollback'); + return; + } + + if (mode === 'stash') { + // SAFETY: Use git stash instead of git reset --hard to preserve changes. + // Changes can be recovered via "git stash list" and "git stash pop". + const stashRef = 'evolver-rollback-' + Date.now(); + const result = tryRunCmd('git stash push -m "' + stashRef + '" --include-untracked', { cwd: repoRoot, timeoutMs: 60000 }); + if (result.ok) { + console.log('[Rollback] Changes stashed with ref: ' + stashRef + '. Recover with "git stash list" and "git stash pop".'); + } else { + // Fallback to hard reset if stash fails (e.g., no changes to stash) + console.log('[Rollback] Stash failed or no changes, using hard reset'); + tryRunCmd('git restore --staged --worktree .', { cwd: repoRoot, timeoutMs: 60000 }); + tryRunCmd('git reset --hard', { cwd: repoRoot, timeoutMs: 60000 }); + } + return; + } + + // Default: hard reset (original behavior) tryRunCmd('git restore --staged --worktree .', { cwd: repoRoot, timeoutMs: 60000 }); tryRunCmd('git reset --hard', { cwd: repoRoot, timeoutMs: 60000 }); }