* fix: persist turns after approval and add agent-level tests
Port relevant changes from PR #112 that were not carried over to #237:
- Add persist_turn calls in process_approval for the response, error,
and auth-required paths. Previously, turns completed after tool
approval were never persisted to DB — if the process crashed after
approval the entire turn (user message + assistant response) was lost.
- Add agent-level unit tests: StaticLlmProvider mock, make_test_agent
helper, tests for auto-approval logic, destructive shell command
detection, and PendingApproval backward-compatible deserialization
(without deferred_tool_calls field).
- Remove unused _thread_state binding in process_approval.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: address 14 audit findings in src/agent/
Audit of the agent module found 2 High, 7 Medium, 3 Low, and 2 Nit
severity issues. This commit fixes all of them:
High:
- Remove 4 `.expect()` calls in session.rs (entry API, match, direct
indexing, if-let) to eliminate panic paths in production
- Add typed RoutineError enum replacing Result<_, String> across
routine.rs, routine_engine.rs, and callers in history/store.rs and
db/libsql/mod.rs
Medium:
- Sanitize routine names in path construction to prevent directory
traversal (routine_engine.rs)
- Log warnings for 5 silently-swallowed errors in scheduler.rs,
compaction.rs, and worker.rs
- Extract shared handle_auth_intercept helper to deduplicate auth
interception in thread_ops.rs
- Add session count warning threshold in session_manager.rs
- Make FullJob stub degradation visible via warn-level log and
prepended warning in output
Low:
- Restrict dead code visibility with #[cfg(test)] on 19 unused items
in submission.rs, task.rs, and undo.rs
- Narrow pub to pub(crate) on self_repair.rs builder methods
- Remove TaskStatus from mod.rs re-exports (test-only type)
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: address PR review comments
- Reorder persist_turn before persist_response_chain so the
conversation row exists before the metadata UPDATE runs
- Add persist_response_chain call to handle_auth_intercept so
auth-required paths preserve the response chain
- Harden sanitize_routine_name to use allowlist (alphanumeric,
dash, underscore) instead of denylist replacements
- Fix stale active_thread ID in get_or_create_thread: fall back
to create_thread() when the stored ID is missing from the map
- Persist turn on approval rejection so user messages survive
crashes after a tool is rejected
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
* feat: add libSQL/Turso database backend with full feature parity
Introduce a Database trait abstraction (~60 async methods) enabling
compile-time backend selection between PostgreSQL and libSQL/Turso.
Convert all modules from concrete Store to Arc<dyn Database>, add
LibSqlSecretsStore and LibSqlWasmToolStore implementations, wire
libsql stores throughout CLI and main entry points, and make the
setup wizard backend-agnostic.
Key changes:
- src/db/: Database trait, PostgresDatabase adapter, LibSqlBackend
with native SQLite-dialect SQL, and idempotent migration system
- src/secrets/store.rs: LibSqlSecretsStore (all 8 trait methods)
- src/tools/wasm/storage.rs: LibSqlWasmToolStore (all 7 trait methods)
- src/main.rs, cli/tool.rs, cli/mcp.rs: backend-conditional wiring
- src/setup/channels.rs: SecretsContext uses Arc<dyn SecretsStore>
- Feature-gate postgres-only tests and examples
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* feat: enable onboarding wizard for libSQL builds
Refactor the setup wizard to work with both postgres and libsql feature
flags. Previously the wizard was gated behind #[cfg(feature = "postgres")]
only, so libsql-only builds would print an error on `ironclaw onboard`.
- Add libsql fields to Settings (database_backend, libsql_path, libsql_url)
- Split wizard database/migration/secrets methods into feature-gated variants
- Add step_database_libsql() with local path and Turso remote replica prompts
- Update setup/mod.rs and main.rs feature gates to any(postgres, libsql)
- Extend check_onboard_needed() to detect libsql database presence
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: address PR review feedback for libSQL backend
- P0: Switch libsql_backend to connection-per-operation pattern to fix
shared Connection concurrency issue across tokio tasks
- P0: Wrap secrets store INSERT+SELECT in transaction to fix TOCTOU race
- P0: Document encryption-at-rest limitations and json_patch divergence
- P1: Fix get_opt_text removing .filter(|s| !s.is_empty()) that conflated
empty strings with NULL
- P1: Replace datetime('now') with fmt_ts(&Utc::now()) for consistent
RFC 3339 timestamps across all queries
- P2: Use explicit _rowid column in FTS5 triggers and joins for stability
across VACUUM operations
- P2: Add tracing::warn when embedding provided but vector search disabled
in hybrid_search
- Extract shared connect_from_config() helper to deduplicate DB connection
logic across main.rs, cli/config.rs, and cli/mcp.rs
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: add missing JobContext fields and resolve fmt/clippy warnings
Add total_tokens_used and max_tokens fields to JobContext in
libsql_backend.rs, apply cargo fmt, and fix clippy warnings.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: review fixes for libSQL backend (shared connections, panics, indexes)
- Replace .expect() with proper error propagation in 3 call sites
- Share Arc<Database> between backend and stores instead of single Connection
- Add connect-per-operation pattern to LibSqlSecretsStore and LibSqlWasmToolStore
- Wrap store() INSERT + SELECT-back in a transaction
- Add ~22 missing indexes for parity with PostgreSQL schema
- Add 18 leak_detection_patterns seed rows matching PostgreSQL V2 migration
- Fix super:: import to use crate:: style
- Gate mask_password_in_url behind #[cfg(feature = "postgres")]
- Rewrite secrets store init with or_else chain for runtime backend selection
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: Resolve clippy lints (collapsible_if, too_many_arguments)
Collapse nested if blocks into let_chains to satisfy clippy's
collapsible_if lint (CI uses -D warnings). Suppress too_many_arguments
on libsql_row_to_tool_at since refactoring the positional index
pattern would be a larger change.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Illia Polosukhin <[email protected]>
* Bump MSRV to 1.92 and add GCP deployment files
rig-core 0.30 uses let_chains (stabilized post-1.87), which breaks
builds on Rust 1.85. Bump rust-version in Cargo.toml and both
Dockerfiles to 1.92 (verified working).
Add cloud deployment scaffolding:
- Dockerfile: multi-stage build for the main agent container
- deploy/cloud-sql-proxy.service: systemd unit for Cloud SQL Auth Proxy
- deploy/ironclaw.service: systemd unit for the IronClaw container
- deploy/setup.sh: VM bootstrap script (Docker, proxy, services)
- deploy/env.example: reference environment configuration
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* Address review feedback: harden deploy scaffolding
- Add comment explaining GATEWAY_HOST=0.0.0.0 and when to use 127.0.0.1
- Document /opt/ironclaw ownership model (root-owned, Docker reads as root)
- Switch cloud-sql-proxy service from User=root to DynamicUser=yes
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: Resolve clippy lints (Rust 1.93) and fix CI test workflow
- Fix 97 collapsible_if warnings using let-chains syntax (auto-fixed)
- Fix ptr_arg: change &PathBuf to &Path in pairing store functions
- Fix suspicious_open_options: add .truncate(false) to OpenOptions
- Fix too_many_arguments: add clippy allow on execute_status
- Fix unnecessary_unwrap: use if-let in repository.rs hybrid_search
- Gate unused EchoTool with #[cfg(test)]
- Add PairingStore argument to ChannelStoreData::new() test call sites
- Add skip guard for bundled channel test when WASM artifacts unavailable
- Split CI test workflow to exclude PostgreSQL-dependent integration tests
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: Address review feedback from ilblackdragon
- Add root check to setup.sh (exits with error if not root)
- Add warning comment to env.example about placeholder passwords
- Dockerfile.worker already uses rust:1.92 (no change needed)
- PR #41 overlap noted; will rebase after #41 merges
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* fix: resolve 47 collapsible_if clippy warnings
Collapse nested if statements across the codebase to satisfy
clippy::collapsible_if on Rust 1.93.
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
- Add HeartbeatConfig for proactive periodic execution with channel notifications
- Add use_planning option to Worker for ActionPlan generation before tool execution
- Implement tool failure tracking in database (V3 migration)
- Add auto-repair via Builder for broken WASM tools in self_repair.rs
- Record tool failures in Worker for self-repair tracking
- Update .env.example with new configuration options
Co-Authored-By: Claude Opus 4.5 <[email protected]>