# Development History Summary of the Claude Code sessions that built the engine v2, self-improvement system, and Python orchestrator. This helps new contributors understand *why* things were designed the way they are. ## Session 1: Engine v2 Foundation (2026-03-20 to 2026-03-22) Built the core engine crate (`crates/ironclaw_engine/`) from scratch in 6 phases: - **Phase 1**: Core types (Thread, Step, Capability, MemoryDoc, Project), trait definitions (LlmBackend, Store, EffectExecutor), thread state machine. 32 tests. - **Phase 2**: Execution engine (Tier 0) — CapabilityRegistry, LeaseManager, PolicyEngine, ThreadManager, ExecutionLoop with structured tool calls. 74 tests. - **Phase 3**: CodeAct executor (Tier 1) — Monty Python interpreter integration, RLM pattern (context-as-variables, FINAL(), llm_query(), output truncation, Step 0 orientation). 74 tests. - **Phase 4**: Memory and reflection — RetrievalEngine, reflection pipeline (Summary/Lesson/Issue/Spec/Playbook docs), context compaction, rlm_query() recursive sub-agents, budget controls. 78 tests. - **Phase 5**: Conversation surface — ConversationManager routing UI messages to threads. 85 tests. - **Phase 6**: Bridge adapters — LlmBridgeAdapter, EffectBridgeAdapter, HybridStore, EngineRouter. Parallel deployment via `ENGINE_V2=true`. 151 tests. **Key design decision**: The engine has zero dependency on the main ironclaw crate. All interaction goes through three traits (LlmBackend, Store, EffectExecutor) implemented by bridge adapters. ## Session 2: Debugging via Traces (2026-03-22 to 2026-03-23) Ran the engine end-to-end with real LLMs and discovered 8 bugs through trace analysis: 1. Tool name hyphens vs underscores (`web-search` vs `web_search`) 2. Double-serialization of JSON tool output 3. UTF-8 byte-index slicing panics on multi-byte characters 4. Code block detection missing in plain completion path 5. Missing system prompt on thread spawn 6. Empty messages sent to LLM 7. `web_fetch` example in prompt (nonexistent tool) 8. False positive `missing_tool_output` trace warning **Key insight**: Every fix followed the same loop (trace → human reads → human edits Rust → rebuild). This became the motivation for the self-improving engine design. ## Session 3: Mission System (2026-03-24) Built the Mission system for long-running goals that spawn threads over time: - `MissionManager` with create/pause/resume/complete lifecycle - `MissionCadence`: Cron, OnEvent, OnSystemEvent, Webhook, Manual - `build_meta_prompt()` — assembles mission goal + current focus + approach history + project docs + trigger payload - `process_mission_outcome()` — extracts next_focus and goal-achieved status from thread responses - Cron ticker (60s interval) - 7 E2E mission flow tests **Key design decision**: Missions evolve their strategy via `current_focus` and `approach_history`. Each thread gets a meta-prompt that includes what was tried before. ## Session 4: Review Fixes + Self-Improvement Foundation (2026-03-25, morning) Fixed 4 review comments (P1/P2 severity) in the engine v2 bridge: 1. **SSE events scoped to user** — `broadcast_for_user()` instead of `broadcast()` 2. **Per-user pending approvals** — HashMap keyed by user_id instead of global Option 3. **Reset tool-call limit counter** — reset before each thread, not monotonic 4. **Only auto-approve on "always"** — one-off "yes" no longer persists Then built the self-improvement foundation: - Runtime prompt overlay via MemoryDoc (prompt builder becomes async + Store-aware) - `fire_on_system_event()` — wires the previously-unimplemented OnSystemEvent cadence - `start_event_listener()` — subscribes to thread events, fires matching missions - `ensure_self_improvement_mission()` — creates the built-in self-improvement Mission - `process_self_improvement_output()` — saves prompt overlays and fix patterns - Seed fix pattern database with 8 known patterns ## Session 5: Autoresearch-Inspired Redesign (2026-03-25, afternoon) Studied [karpathy/autoresearch](https://github.com/karpathy/autoresearch) and redesigned the self-improvement approach: **Before**: Vague goal prompt, structured JSON output, reactive only. **After**: Concrete `program.md`-style prompt with exact loop steps, plain text + tool-use (agent uses tools directly like autoresearch), enriched trigger payload with actual error messages. Key takeaways applied from autoresearch: - The entire "research org" is a markdown prompt with an explicit loop - The agent uses tools directly (shell, grep, git) rather than emitting structured output - Results tracked in a simple append-only log - "NEVER STOP" — the agent is autonomous within constraints ## Session 6: Python Orchestrator (2026-03-25, evening) The pivotal architectural change. Motivated by the question: *"What if we move some part of the engine inside CodeAct itself?"* **The realization**: All the bugs from Session 2 were in the "glue" between the LLM and tools — output formatting, tool dispatch, state management, truncation. These functions are Python-natural. If they were Python, the self-improvement Mission could fix them without a Rust rebuild. **Research**: Verified that Monty supports nested VM execution (`rlm_query()` already does exactly this — suspends parent VM, runs child ExecutionLoop, resumes parent). No shared state, ~50KB per suspended VM. **Implementation** (4 commits): 1. **Host function module** (`executor/orchestrator.rs`) — 11 host functions exposed to Python via Monty suspension: `__llm_complete__`, `__execute_code_step__`, `__execute_action__`, `__check_signals__`, `__emit_event__`, `__add_message__`, `__save_checkpoint__`, `__transition_to__`, `__retrieve_docs__`, `__check_budget__`, `__get_actions__`. 2. **Default orchestrator** (`orchestrator/default.py`) — The v0 Python orchestrator that replicates the Rust loop logic. Helper functions (extract_final, format_output, signals_tool_intent) defined before run_loop for Monty scoping. 3. **Switchover** — Replaced the 900-line `ExecutionLoop::run()` with an 80-line bootstrap. Key debugging: Monty's `ExtFunctionResult::NotFound` (not `Error`) for user-defined functions, FINAL result propagation, step_count tracking via `__emit_event__("step_completed")`. 4. **Versioning + rollback** — Failure tracking via MemoryDoc, auto-rollback after 3 consecutive failures, `OrchestratorRollback` event. Self-improvement Mission goal updated with Level 1.5 orchestrator patch instructions. **Key debugging moment**: The orchestrator's helper functions (`extract_final`, `format_output`) were defined after `run_loop` in the Python file. Monty couldn't find them because the default `FunctionCall` handler returned `ExtFunctionResult::Error` instead of `ExtFunctionResult::NotFound`. The fix: return `NotFound` for unknown functions so Monty falls through to its own namespace resolution. Then move helpers above `run_loop` to avoid any ordering issues. **Final state**: 189 tests pass, zero clippy warnings. The Python orchestrator is the execution engine. The Rust layer is the kernel. ## Session 7: Integration Scaling Research (2026-03-26) Studied [Pica](https://github.com/withoneai/pica) (formerly IntegrationOS, 200+ third-party API integrations) to understand how to rapidly scale the number of available integrations in IronClaw. **Pica's architecture**: Integrations are MongoDB documents, not code. Each platform has a `ConnectionDefinition` (identity + auth schema) and N `ConnectionModelDefinition` records (one per API endpoint: URL, method, auth method, schemas, JS transform functions). A generic executor dispatches requests. OAuth definitions embed JavaScript compute functions executed by a TypeScript service. Adding a new platform = inserting documents, no code changes. **Analysis of IronClaw v1 tools**: Audited all 37 built-in tools. Only 3 (image_gen, image_analyze, image_edit) are HTTP API wrappers. The other 34 are local computation, filesystem, orchestration, or system management — none convertible to data-driven definitions. The value isn't converting existing tools; it's enabling hundreds of new integrations. **Key finding — deterministic executors don't solve the LLM problem**: Even with a Pica-style executor, each integration action must be registered as a tool in the LLM's context. At 200+ tools: - ~20,000 tokens always-on cost (tool definitions sent every request) - LLM tool selection accuracy degrades beyond ~20-30 tools - The LLM still constructs parameters and can get them wrong - Deterministic execution only helps *after* the LLM correctly selects the tool and params **The realization**: In engine v2, Capabilities already bundle actions + knowledge. For API integrations, a Capability's knowledge text teaches the LLM how to call the platform's API using the generic `http` action. This is superior to dedicated tools because: - Tool list stays small (just `http` + core actions) — high selection accuracy - Knowledge loaded on-demand per thread context — zero cost for unused integrations - ~350 tokens of knowledge covers 4+ API endpoints (the LLM generalizes) - Adding a new platform = writing markdown knowledge, no Rust code **Remaining gap**: OAuth token acquisition requires a dedicated `oauth_init` action (LLM can't do redirect flows). Capability knowledge instructs the LLM to call it before using the API. **Decision**: Use Capabilities as knowledge-bearing integration definitions. Write knowledge text for top 20 platforms. Build one `oauth_init` action. Skip the Pica-style deterministic executor — it solves the wrong problem for LLM agents. ## Architecture Evolution ``` Session 1-2: Rust loop (900 lines) → works but bugs in glue layer Session 3: + Missions (long-running goals, evolving strategy) Session 4: + Self-improvement Mission (fires on issues, fixes prompts) Session 5: + Autoresearch-style goal prompt (concrete, not vague) Session 6: Rust loop → Python orchestrator (self-modifiable) 900 lines Rust → 80 lines Rust bootstrap + 230 lines Python Session 7: Integration scaling: Capabilities as knowledge → http action (not Pica-style per-action tools — tool list bloat kills LLM accuracy) ``` ## Key Commits | Commit | Description | |--------|-------------| | `8be19a4` | Phase 1: Foundation types + traits | | `bf7dfb8` | Phase 2: Tier 0 execution engine | | `b59a0b9` | Phase 3: CodeAct (Monty + RLM) | | `4bc7ffd` | Phase 4: Memory + reflection + budgets | | `0827235` | Phase 5: Conversation surface | | `ac4ced0` | Phase 6: Bridge adapters (parallel deploy) | | `8180a417` | Self-improving engine via Mission system | | `cfe856da` | Python orchestrator module + host functions | | `63756039` | Switch ExecutionLoop to Python orchestrator | | `080317aa` | All 177 tests pass with orchestrator | | `46fd2b5d` | Versioning, auto-rollback, 189 tests |