Skip to content

MIRA v2026.06.25

Latest

Choose a tag to compare

@taylorsatula taylorsatula released this 25 Jun 06:11

MIRA v2026.06.25

Major feature additions, infrastructure migration, deployment hardening, and dead code removal. Net effect: +2208 lines added, -1575 removed across 75 files.

New Features

Retrieval-Backed Tool Result Compaction

Oversized tool results (>2000 chars) are now compacted in Valkey while PostgreSQL retains the original. The system works as follows:

  • After each turn commits, a ToolResultHistoryCommittedEvent triggers async compaction for oversized string tool results
  • Each result gets a session-scoped retrieval ID (tr_{session_prefix}_{message_id_hex}) stored in message metadata
  • An LLM produces a compact version; JSON-aware compaction selects array fields (keeps subset of indices) or text fields (summarizes prose within JSON objects)
  • A conditional cache patch via compare-and-set replaces the cached copy only if it still matches the original
  • In the API response, compacted messages get an ephemeral breadcrumb: [Exact original tool result available via continuum_tool.get_tool_result(...)]
  • If the assistant needs the full result, it calls continuum_tool.get_tool_result(tool_result_id) which queries PostgreSQL directly
  • Retrieved results carry tool_result_retrieved=True and are never re-compacted
  • URL preservation validation ensures summaries cannot invent or change URLs from the original

AsyncWorkBarrier provides bounded cross-turn coordination: the chat endpoint waits up to 30 seconds (configurable via async_work_barrier_timeout_seconds) for background compaction before loading the next turn's continuum, preventing stale data races.

Schema changes: messages.tool_call_id and messages.is_error moved from metadata into dedicated columns with proper indexes.

Portrait & LoRA Refinement (Preview-Before-Save)

Both portrait and user model (LoRA) now support a preview-before-save refinement workflow. Users provide free-text instructions, receive a proposed revision, then accept or decline.

  • Preview stored in Valkey with 10-minute TTL under opaque preview_id
  • Single-consume semantics prevent double-accept; user ID embedded in key prevents cross-user theft
  • Portrait: plain prose refinement via PortraitDomainHandler (actions: get, refine, accept, decline)
  • LoRA: same workflow plus critic validation loop (up to 3 attempts). Circuit breaker presents last candidate if all fail since the user initiated the request
  • Cache invalidation after accept clears the relevant WorkingMemory caches

Peanut Gallery "Initiative" Action Type

A new action type catches cases where MIRA is technically correct but conversationally passive — acting as a respondent instead of an interlocutor. Triggers on passivity patterns including literal-only answering, serial interrogation, option dumping without prioritization, explanation without action, missed value-add opportunities, situational blindness toward frustrated users, and premature closure. Never carries critical severity. Priority order: concern > coaching > initiative > noop.

One-Time Credential Dump

After installation, all credentials (Vault root token, unseal key, API keys) are written once to ~/Desktop/MIRA_credentials.txt with prominent warnings. File is chmod 600 restricted. Instructions tell the user to save securely and delete. For offline mode, notes that no external API keys were configured.

Infrastructure Changes

Local LLM: Ollama → llama.cpp Migration

Complete replacement of Ollama with llama.cpp for local/offline deployments:

  • llama.cpp built from source with CUDA support during deployment
  • Two-model architecture: Qwopus3.6-27B-v2-MTP-Q5_K_M (port 3090) + Qwen3.5-9B-UD-Q3_K_XL (port 3092)
  • VRAM target: dual RTX 3090 / 48GB total, tensor split 12,12
  • Pre-configured pair for dual RTX 3090 plus custom GGUF option for different hardware
  • Schema column renamed: adapter_namedialect_name across conversation_llm table
  • Default conversation LLM changed from gemma to primary; usage pricing tiers pruned
  • phoneafriend internal LLMs remain remote even in offline mode (fail gracefully if air-gapped)
  • OpenAI dialect gets _is_local_endpoint() detection and cache_checkpoint injection

Centralized Prompt Loader

load_prompt() replaces ad-hoc open(Path(...)) calls across ~12 services. Guarantees UTF-8 encoding, path traversal protection, .txt enforcement, empty-file detection, optional-prompt support (required=False), and debug logging. System prompt loader hardened with path traversal protection and file extension checks.

Compaction Trigger Simplification

Removed _estimate_request_tokens() entirely. Uses previous turn's actual provider-reported token count directly against compaction_trigger_tokens (40000). Segment collapse invalidates cached baseline via SegmentCollapsedEvent subscription. Added model_validator ensuring trigger doesn't exceed provider input budget.

Vault Hardening

Deploy script now applies restrictive permissions to /opt/vault/ at install time (directory 700, files 600, scripts 700) instead of just warning the user to do it manually.

Deploy Script Fixes

  • Added missing cmake/git packages to Debian/Ubuntu apt install lists so llama.cpp build succeeds
  • Added nvcc detection before llama.cpp build; falls back to CPU-only when CUDA toolkit is unavailable
  • Fixed DISTRO check from ubuntu to debian to match actual distro detection logic
  • Rejects unsupported Fedora versions (< 41) upfront with clear error rather than failing mid-install with cryptic 404

Model Defaults Updated

  • Generic chat default: qwen/qwen3.5-397b-a17bz-ai/glm-5.2
  • Subcortical default: qwen/qwen3-32bqwen/qwen3.6-27b

Docker Install Option

README now includes Docker one-liner as a third install option alongside local install and VM provisioning.

System Prompt Overhaul

System prompt trimmed from 110 to 89 lines by removing motivational framing and prescribing emotional texture. Operational constraints restored in affirmative form: forage guidance, tool-call contract, sentence-content rule, structure-from-task rule, contrastive-negation discipline, conversation origination, and emotion-tag UI note. All additions avoid negative examples to prevent priming failure modes.

HUD Restructure (Synthetic Tool Call + Named Fields)

HUD notification center restructured from a single assistant prose block with <mira:hud> wrapper into a synthetic tool call/result pair. The model sees it as a tool interaction (system called "hud" tool, got structured data), eliminating the need for disclaimers like "not generated by you."

  • notification_center type changed from str to dict[str, str] mapping section names to XML content
  • Each trinket's output appears as a named field (datetime_section, active_reminders, inbox_status, etc.) serialized as JSON
  • Empty sections omitted entirely; whole HUD skipped when no data exists
  • Removed dead notification_parts variable from routing pipeline

Dead Code Removal (~400 lines)

  • ContinuumRepository: get_by_id(), load_messages_by_ids(), update_message_metadata(), get_messages_for_dates() — all unused
  • LinkingService: classify_relationship_sync(), _parse_classification_response(), llm_provider param — marked dead since Feb 2026
  • ContinuumPool.update_cache() — unused public method
  • MEMORY_GARDENER.md removed (unfinished design doc, subtractive OSS change)

Bug Fixes

  • Anthropic dialect: skip thinking blocks when no signature matches, preventing orphaned blocks without signatures
  • POST probe: accounts for reasoning text and tool calls; providers returning only reasoning or tool calls no longer fail. Max tokens increased 16→256. Resource cleanup added via PostgresClient.close_all_pools() in finally blocks
  • Prompt injection defense: exception type corrected from RuntimeError to ValueError for JSON parsing failures
  • Health endpoint: thread_health converted to async function
  • Inbox tool: handles None chars parameter without crashing
  • Prepopulate SQL: adds missing segment_turn_count field
  • Vault preload: added mira/services path so service config secrets are loaded at startup alongside api_keys/database/auth categories
  • Reminder tool: replaced if/elif dispatch chain with operation_map dict and inspect.signature-based kwarg filtering; schema-valid but per-operation-irrelevant params no longer crash methods that don't accept them

Chores

  • coerce_to_int extracted from continuum_tool into shared tools/repo utility
  • email-validator dependency added for Pydantic EmailStr validation
  • Web tool synthesis config supports environment variable overrides
  • Tool definitions sorted alphabetically for deterministic output
  • All CLAUDE.md files updated to reflect new architecture