mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
docs: add self-improving engine design plan
Designs a system where the engine debugs and improves itself, based on the pattern observed in the last session: 5 consecutive bug fixes all followed trace → read → identify → edit → test, using tools the engine already has access to. Three levels of self-improvement: - Level 1 (Prompt): edit prompts/*.md to prevent LLM mistakes. Auto-apply. - Level 2 (Config): adjust defaults/mappings. Branch + test + PR. - Level 3 (Code): Rust patches for engine bugs. Branch + test + clippy + PR. Architecture: Self-improvement Mission spawns a Reflection thread that reads traces, reads source, proposes fixes, validates via cargo test, and either auto-applies (Level 1) or creates a PR (Level 2-3). Includes: fix pattern database (seeded from our 8 debugging session fixes), feedback loop diagram, safety model, implementation phases (A through D), and what exists vs what's new. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
# Self-Improving Engine: Automated Debugging and Evolution
|
||||
|
||||
**Date:** 2026-03-23
|
||||
**Status:** Design
|
||||
**Context:** The last debugging session revealed a clear pattern: trace → human reads trace → human identifies root cause → human edits code → rebuild. Every step of this loop is something the engine can already do. This plan designs a system where the engine debugs and improves itself.
|
||||
|
||||
---
|
||||
|
||||
## The Pattern We Observed
|
||||
|
||||
5 consecutive fixes followed the same loop:
|
||||
|
||||
| Trace symptom | Root cause | Fix location | Fix type |
|
||||
|---|---|---|---|
|
||||
| `Tool web_search not found` | Hyphen/underscore mismatch | `effect_adapter.rs` | Code (name conversion) |
|
||||
| `TypeError: str indices must be integers` | JSON double-serialization | `effect_adapter.rs` | Code (parse before wrap) |
|
||||
| `NameError: result not defined` | No variable persistence | `loop_engine.rs` | Code (state dict) |
|
||||
| `byte index 80 is not a char boundary` | Unsafe UTF-8 slicing | `thread.rs`, `loop_engine.rs`, `scripting.rs` | Code (chars() not bytes) |
|
||||
| Model calls `web_fetch` (doesn't exist) | Wrong example in prompt | `codeact_preamble.md` | Prompt edit |
|
||||
|
||||
Each fix used the same tools the engine has access to: `read_file`, `apply_patch`, `shell` (cargo test), and file writing.
|
||||
|
||||
---
|
||||
|
||||
## Three Levels of Self-Improvement
|
||||
|
||||
### Level 1: Prompt Evolution (low risk)
|
||||
|
||||
The engine modifies its own prompt templates based on accumulated experience.
|
||||
|
||||
**What it changes:** `crates/ironclaw_engine/prompts/*.md` files
|
||||
|
||||
**Examples:**
|
||||
- Adds "NEVER call web_fetch — use http() or llm_context()" to rules section
|
||||
- Adds "freshness parameter: 'pd'=past day, 'pw'=past week, 'pm'=past month" to tool hints
|
||||
- Adds "Always access previous step data via state['tool_name']" after repeated NameErrors
|
||||
- Removes examples that reference nonexistent tools
|
||||
|
||||
**Safety:** Low risk. Prompt changes only affect LLM behavior, not engine logic. Easy to review diff. Easy to revert (git checkout).
|
||||
|
||||
**Trigger:** After every thread with issues detected by trace analysis.
|
||||
|
||||
**Validation:** None needed beyond human review of diff.
|
||||
|
||||
### Level 2: Configuration Tuning (medium risk)
|
||||
|
||||
The engine adjusts its own defaults and mappings.
|
||||
|
||||
**What it changes:**
|
||||
- `ThreadConfig` defaults (max_iterations, truncation limits, compaction thresholds)
|
||||
- Tool name alias mappings
|
||||
- Output truncation sizes
|
||||
- Resource limits
|
||||
|
||||
**Examples:**
|
||||
- After repeated `freshness` errors: add parameter hints to tool descriptions
|
||||
- After repeated truncation issues: adjust `OUTPUT_TRUNCATE_LEN`
|
||||
- After excessive step counts: lower `max_iterations` default
|
||||
|
||||
**Safety:** Medium risk. Config changes affect execution behavior. Should be bounded (e.g., max_iterations can go 30-100 but not 1 or 10000).
|
||||
|
||||
**Trigger:** After N threads with similar patterns (not on first occurrence).
|
||||
|
||||
**Validation:** Run existing test suite (`cargo test -p ironclaw_engine`). Only apply if tests pass.
|
||||
|
||||
### Level 3: Code Patching (high risk, high value)
|
||||
|
||||
The engine proposes Rust code changes to fix bugs it detects in itself.
|
||||
|
||||
**What it changes:** Any file in `crates/ironclaw_engine/` or `src/bridge/`
|
||||
|
||||
**Examples:**
|
||||
- Fix unsafe byte slicing (detected by panics in traces)
|
||||
- Add missing type conversions (detected by tool errors)
|
||||
- Fix missing match arms (detected by unhandled response types)
|
||||
- Add error recovery paths (detected by repeated failures)
|
||||
|
||||
**Safety:** High risk. Wrong patches can break the engine, introduce security issues, or cause data loss.
|
||||
|
||||
**Guardrails:**
|
||||
1. Always work in a git branch (`self-improve/{timestamp}`)
|
||||
2. Run full test suite (`cargo test -p ironclaw_engine`)
|
||||
3. Run clippy (`cargo clippy -p ironclaw_engine --all-targets -- -D warnings`)
|
||||
4. Never modify files outside `crates/ironclaw_engine/` and `src/bridge/` without human approval
|
||||
5. Max patch size: 50 lines changed
|
||||
6. Generate a PR (not direct commit) with trace evidence
|
||||
7. Human approves or rejects the PR
|
||||
|
||||
**Trigger:** After a pattern appears in 3+ traces.
|
||||
|
||||
**Validation:** Full test suite + clippy + human review.
|
||||
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
### Self-Improvement Mission
|
||||
|
||||
A `Mission` with `MissionCadence::OnEvent` that triggers after each thread completion:
|
||||
|
||||
```
|
||||
Thread completes
|
||||
→ Trace analysis (existing, automatic)
|
||||
→ If issues detected:
|
||||
→ Spawn self-improvement thread (ThreadType::Reflection)
|
||||
→ Thread has access to: shell, read_file, write_file, apply_patch
|
||||
→ Thread reads the trace JSON
|
||||
→ Thread reads relevant source files
|
||||
→ Thread proposes a fix
|
||||
→ Thread validates the fix (cargo test)
|
||||
→ Thread either:
|
||||
a) Applies prompt edit directly (Level 1)
|
||||
b) Creates a git branch + PR (Level 2-3)
|
||||
c) Logs the proposal for human review
|
||||
```
|
||||
|
||||
### The Self-Improvement Thread's Prompt
|
||||
|
||||
```
|
||||
You are a debugging agent analyzing execution traces from the IronClaw engine.
|
||||
|
||||
## Your task
|
||||
Read the trace file at {trace_path} and identify the root cause of any issues.
|
||||
Then propose and validate a fix.
|
||||
|
||||
## Available information
|
||||
- Trace JSON: full message history, events, tool results, issues detected
|
||||
- Source code: read any file in the codebase
|
||||
- Prompt templates: crates/ironclaw_engine/prompts/*.md
|
||||
- Bridge adapters: src/bridge/*.rs
|
||||
- Engine code: crates/ironclaw_engine/src/**/*.rs
|
||||
|
||||
## Fix levels
|
||||
1. PROMPT EDIT: Modify prompts/*.md to prevent LLM mistakes
|
||||
→ Apply directly, no approval needed
|
||||
2. CONFIG CHANGE: Adjust defaults in engine code
|
||||
→ Create git branch, run tests, propose PR
|
||||
3. CODE PATCH: Fix Rust code bugs
|
||||
→ Create git branch, run tests + clippy, propose PR
|
||||
|
||||
## Rules
|
||||
- Always read the relevant source file before proposing a change
|
||||
- Always run `cargo test -p ironclaw_engine` after making changes
|
||||
- Never modify more than 50 lines in a single patch
|
||||
- For Level 2-3: create a branch `self-improve/{issue}` and use git
|
||||
- Explain your reasoning: what the trace shows, why the fix works
|
||||
```
|
||||
|
||||
### Trace-to-Fix Pattern Database
|
||||
|
||||
Over time, the system builds a pattern database mapping trace symptoms to fix strategies:
|
||||
|
||||
| Trace pattern | Fix strategy | Location pattern |
|
||||
|---|---|---|
|
||||
| `Tool X not found` | Add name alias/conversion | `effect_adapter.rs` |
|
||||
| `TypeError: str indices must be integers` | Parse JSON before wrapping | Where tool output is converted |
|
||||
| `NameError: name 'X' not defined` | Add to state dict or prompt hint | `loop_engine.rs` or `prompts/*.md` |
|
||||
| `byte index N is not a char boundary` | Replace `[..N]` with `chars().take(N)` | Grep for `[..` in relevant files |
|
||||
| Model calls nonexistent tool | Fix prompt example or add alias | `prompts/*.md` or `effect_adapter.rs` |
|
||||
| Model ignores tool results | Improve output metadata format | `loop_engine.rs` output building |
|
||||
| Excessive steps (>5) for simple task | Add prompt rule or fix tool schema | `prompts/*.md` |
|
||||
|
||||
This database itself is a MemoryDoc that the self-improvement thread can read and extend.
|
||||
|
||||
### Feedback Loop
|
||||
|
||||
```
|
||||
┌──────────────────────────────────┐
|
||||
│ User Message │
|
||||
└──────────────┬───────────────────┘
|
||||
│
|
||||
┌──────────────▼───────────────────┐
|
||||
│ Thread Execution (CodeAct) │
|
||||
│ Using: evolved prompt + │
|
||||
│ learned rules + tool hints │
|
||||
└──────────────┬───────────────────┘
|
||||
│
|
||||
┌──────────────▼───────────────────┐
|
||||
│ Trace + Reflection │
|
||||
│ Produces: Lesson, Issue, │
|
||||
│ Spec, Rule, Playbook docs │
|
||||
└──────────────┬───────────────────┘
|
||||
│
|
||||
┌─────────▼─────────┐
|
||||
│ Issues detected? │
|
||||
└────┬──────────┬────┘
|
||||
│ yes │ no
|
||||
┌─────────▼────┐ └──→ done
|
||||
│ Self-Improve │
|
||||
│ Thread │
|
||||
├──────────────┤
|
||||
│ Read trace │
|
||||
│ Read source │
|
||||
│ Propose fix │
|
||||
│ Test fix │
|
||||
│ Apply/PR │
|
||||
└──────┬───────┘
|
||||
│
|
||||
┌────────────▼────────────┐
|
||||
│ Level 1: prompt edit │──→ Apply directly
|
||||
│ Level 2: config change │──→ Branch + test + PR
|
||||
│ Level 3: code patch │──→ Branch + test + clippy + PR
|
||||
└─────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase A: Prompt Self-Evolution (Level 1)
|
||||
|
||||
**Effort:** Small. Uses existing infrastructure.
|
||||
|
||||
1. After reflection, if any `Spec` or `Lesson` docs reference prompt issues, spawn a Level 1 self-improvement thread
|
||||
2. The thread reads `prompts/codeact_preamble.md` and the Lesson/Spec docs
|
||||
3. It proposes an edit using `apply_patch` or `write_file`
|
||||
4. No testing needed — prompt changes are safe
|
||||
5. Next thread uses the updated prompt (loaded at runtime, not compile time)
|
||||
|
||||
**Prerequisite:** Prompts must be loaded at runtime from workspace, not via `include_str!`. Change `build_codeact_system_prompt` to read from store/file with `include_str!` as fallback.
|
||||
|
||||
### Phase B: Fix Pattern Database (Level 1-2)
|
||||
|
||||
**Effort:** Medium.
|
||||
|
||||
1. Create a `MemoryDoc` of type `Playbook` that maps trace symptoms to fix strategies
|
||||
2. Seed it with the 8 patterns from our debugging session
|
||||
3. The self-improvement thread reads this playbook before analyzing a trace
|
||||
4. After successfully fixing an issue, it adds the new pattern to the playbook
|
||||
5. The playbook grows over time — the system gets better at fixing itself
|
||||
|
||||
### Phase C: Automated Code Patches (Level 3)
|
||||
|
||||
**Effort:** Large. Requires careful safety design.
|
||||
|
||||
1. Self-improvement thread creates a git branch
|
||||
2. Reads trace + source code + fix pattern database
|
||||
3. Proposes a Rust code change using `apply_patch`
|
||||
4. Runs `cargo test -p ironclaw_engine` and `cargo clippy`
|
||||
5. If tests pass: creates a PR with trace evidence + reasoning
|
||||
6. Human reviews and merges (or the system auto-merges after N successful self-fixes build trust)
|
||||
|
||||
### Phase D: Meta-Evaluation Loop
|
||||
|
||||
**Effort:** Large. This is the full autoresearch loop.
|
||||
|
||||
1. Periodically replay historical traces against the current code
|
||||
2. Compare: did the fix actually reduce the failure pattern?
|
||||
3. Score fixes by effectiveness
|
||||
4. Revert ineffective fixes
|
||||
5. Propose more targeted fixes for persistent issues
|
||||
|
||||
---
|
||||
|
||||
## Safety Model
|
||||
|
||||
| Level | What can change | Who approves | Revert mechanism |
|
||||
|---|---|---|---|
|
||||
| **1: Prompt** | `prompts/*.md` only | Auto (no approval) | `git checkout prompts/` |
|
||||
| **2: Config** | Engine defaults, constants | Auto if tests pass | `git revert` |
|
||||
| **3: Code** | Any `.rs` in engine/bridge | Human via PR review | `git revert` or PR rejection |
|
||||
|
||||
**Hard boundaries (never auto-modify):**
|
||||
- Security-sensitive code (safety layer, policy engine, leak detection)
|
||||
- Database schemas / migrations
|
||||
- Files outside `crates/ironclaw_engine/` and `src/bridge/` (without human approval)
|
||||
- Test files (never weaken tests to make a fix pass)
|
||||
|
||||
---
|
||||
|
||||
## What We Already Have vs What's New
|
||||
|
||||
| Component | Status | Used for |
|
||||
|---|---|---|
|
||||
| Trace recording | **Exists** | Input: execution data |
|
||||
| Retrospective analysis | **Exists** | Detection: find issues |
|
||||
| Reflection pipeline | **Exists** | Analysis: produce Lessons/Specs |
|
||||
| RetrievalEngine | **Exists** | Context: inject learnings |
|
||||
| CodeAct/Monty | **Exists** | Execution: write and run code |
|
||||
| Tools: shell, read_file, apply_patch | **Exists** | Mechanics: read/edit files, run tests |
|
||||
| Missions | **Exists** | Trigger: run after events |
|
||||
| Self-improvement thread prompt | **NEW** | Brain: tells the agent how to debug itself |
|
||||
| Fix pattern database | **NEW** | Knowledge: maps symptoms to strategies |
|
||||
| Runtime prompt loading | **NEW** | Prerequisite: prompts editable at runtime |
|
||||
| Git branch + PR creation | **NEW** | Safety: human review for code changes |
|
||||
| Trace replay for validation | **NEW** | Quality: verify fixes actually help |
|
||||
|
||||
---
|
||||
|
||||
## First Concrete Step
|
||||
|
||||
The smallest thing that creates a real self-improvement loop:
|
||||
|
||||
1. Move prompt loading from `include_str!` to runtime file read (with compiled fallback)
|
||||
2. After reflection produces a `Spec` doc about a prompt issue, spawn a thread that edits `prompts/codeact_preamble.md`
|
||||
3. The edit is a simple append to the "Important rules" section
|
||||
4. Next user message picks up the updated prompt
|
||||
|
||||
This is Level 1 prompt evolution with zero risk. One feature, one file change, immediate feedback loop.
|
||||
Reference in New Issue
Block a user