Changelog

All notable changes to the Rosett-AI are documented in this file.

Format follows Keep a Changelog.

[Unreleased]

[1.2.0] - 2026-04-14

Added

  • Integration test: scope isolation — Verifies project-scope compile writes to <project>/.claude/rules/ and does not modify global rules (WP#1490)
  • Integration test: BehaviourCompiler production mode — Verifies BehaviourCompiler works without engine gems or stub registrations (WP#1491)
  • Integration test: end-to-end compile — Full pipeline test from YAML source to compiled output for each builtin engine (claude, agents_md), including scope isolation (WP#1492)
  • Integration test: engine registration — Verifies builtin backends resolve via Backend.for() without plugin registry, and that unknown engines raise CompileError (WP#1492)

Fixed

  • Project-scope compile wrote to global rulesresolve_target_dir always returned ~/.claude/rules/ regardless of compile scope. Split into resolve_target_dir (explicit output_dir) and default_target_dir (scope-based routing). Project scope now writes to <project_root>/.claude/rules/ (WP#1490)
  • BehaviourCompiler failed without engine gemBehaviourCompiler queried the plugin registry directly for the claude engine, which fails when no engine gem is installed. Now uses Backend.for('claude') which checks BUILTIN_BACKENDS first, matching the Thor compile task resolution path (WP#1491)

[1.1.0] - 2026-04-01

Added

  • Doctor check: stale ~/.rosett-ai/ directory — New stale_home_nncc diagnostic warns when .rosett-ai/ exists at $HOME level, which causes scope resolution confusion by shadowing XDG-path behaviour files (WP#1123)
  • Commit hook behaviour — OpenProject work package integration via branch naming conventions (<type>/<id>-<subject>) and overcommit CommitMsg hook for automatic OP#<id> injection
  • XDG auto-migration — Automatic migration of behaviour files from legacy ~/.claude/conf/ to XDG-compliant ~/.config/rosett-ai/conf/ path
  • Duplicate rule ID detection — Compiler now warns when rule IDs collide across behaviour files
  • Hook command validation — Shell injection prevention in hook command configuration
  • Context-aware CLI — rosett-ai now detects project context via .rosett-ai/ directory marker, routing content commands (design, behaviour, compile, validate) to project-local configuration (ADR-011)
  • Command visibility filtering — Internal commands (build, release, documentation, dbus, desktop) are hidden outside the rosett-ai repository
  • rai init --project — New flag creates .rosett-ai/ project structure with config.yml, conf/behaviour/, and conf/design/
  • RosettAi::ProjectContext — New class for project root detection with .rosett-ai/ directory walking
  • Project config schema — JSON Schema for .rosett-ai/config.yml validation
  • Test Kitchen integration tests — InSpec profiles for context-aware CLI verification in Docker
  • Engine .deb packaging — Reusable packaging/build-engine-deb.sh for building per-engine Debian packages (ADR-010)
  • Wrapper templatepackaging/wrapper.sh.template with build-time @@RUBY_ABI@@/@@RUBY_ARCH@@ substitution
  • Gemfile.dev — Developer-only Gemfile for cross-repo engine testing (gitignored)
  • Pluggable plugin architecture — Contract modules for engine, GUI, and MCP plugins (lib/rosett_ai/plugins/)
  • Dynamic plugin registryRosettAi::Plugins::Registry with Gem.find_files discovery for external gems
  • Base config compilerRosettAi::Engines::BaseConfigCompiler template method pattern for engine config compilation
  • Engine contractRosettAi::Plugins::EngineContract defining backend, detector, executor, config compiler interfaces
  • GUI contractRosettAi::Plugins::GuiContract defining toolkit, application, D-Bus interface methods
  • MCP contractRosettAi::Plugins::McpContract defining server, tool, and resource interfaces
  • Engine-aware CLI--engine option on config compile with cascade lookup (config → autodetect → prompt)
  • Plugins subcommandbin/raictl engines plugins shows registered external engine gems
  • External Claude engine gemrosett-ai-engine-claude referenced via path in Gemfile (:engines group)
  • Engine stub infrastructurespec/support/stub_engines.rb provides test doubles for all 11 engine gems, enabling core-only rspec runs without engine gems installed
  • All 10 engine gemsrosett-ai-engine-{claude,generic,agents-md,ollama,gpt-neox,goose,aider,cursor,copilot,windsurf} extracted as separate gems
  • RosettAiEngine namespace — Engine gems use RosettAiEngine::<Name> to avoid Zeitwerk autoload root conflicts
  • Self-registration pattern — Each engine gem registers via Gem.find_files('rosett_ai_engine/*/register.rb')
  • ACME example enginerosett-ai-engine-acme reference implementation demonstrating how to build a third-party engine plugin
  • RAI_ENGINE_PATH — Custom engine discovery via colon-separated directory list for development/testing
  • Embedded gem fallback — Version-agnostic plugin discovery under /opt/rosett-ai/embedded/ for .deb runtime
  • target_profile_path contract method — Engines expose their target profile path via EngineContract, enabling plugin-aware TargetProfile.load
  • doc/REFERENCE.md — Comprehensive configuration reference (hierarchy, env vars, CLI options, file locations)
  • YARD Rake taskrake yard generates API documentation to doc/api/
  • Test Kitchen rai-commands suite — 13 InSpec control files for comprehensive CLI command verification
  • acme backend in target schema — Added to target_schema.json enum for completeness

Fixed

  • Duplicate rule ID warnings scoped per-file — Compiler now only warns about duplicate rule IDs within a single behaviour file, not across files. Rule IDs are scoped by behaviour name (WP#1130)
  • Removed dead compiler cache codeRosettAi::Cache::CompilerCache and RosettAi::Cache::Manifest were implemented but never wired into the compilation pipeline. Removed until cache is properly integrated (WP#768)
  • Pre-push hook segfault on GTK4 specs — Switched pre-push RSpec from full suite to core-only (RspecCore) hook that excludes desktop/dbus specs matching CI's --exclude-pattern, preventing Ruby segfault in gobject-introspection gem (WP#1122)
  • Wrapper breaks project context (RC1).deb wrapper cd /opt/rosett-ai/app made ProjectContext resolve to the rosett-ai internal tree instead of the user's project. Now preserves RAI_ORIGINAL_PWD before cd
  • Engine discovery fails on ABI mismatch (RC2) — Embedded Ruby 3.3.0 could not find engine gems installed under 3.3.10 GEM_PATH. Added version-agnostic fallback scan of /opt/rosett-ai/embedded/lib/ruby/gems/*/
  • Target profiles not found after extraction (RC3)TargetProfile.load now checks the plugin registry first (engine's target_profile_path) before falling back to file-based lookup
  • Missing engine produces unhelpful error (RC4)config compile and compile now show actionable install hints (apt install rosett-ai-engine-<name>) instead of empty "Available:" lists
  • init --project crash on missing enginerun_compile now rescues CompileError gracefully and suggests running rai compile after installing an engine
  • Build failure at install_gems — Removed engine path: references from core Gemfile that broke staging tree bundle install (Issue #build-001)
  • Embedded Ruby wrong prefix — Addressed via wrapper template LD_LIBRARY_PATH/RUBYLIB fix; CI no longer pre-seeds from Docker image's /usr/local/ Ruby (Issue 002)
  • Wrapper missing LD_LIBRARY_PATH/RUBYLIB — Wrapper template now sets LD_LIBRARY_PATH, RUBYLIB, GEM_HOME with correct embedded paths, eliminating chicken-and-egg ruby subprocess (Issue 001)
  • CI smoke test false positive — Removed apt-get install ruby from smoke test; added prefix and RUNPATH verification assertions (Issue 003)
  • Bundler env leakage — Added all BUNDLER_ORIG_* variables to BUNDLER_ENV_VARS constant for defense-in-depth cleanup

Breaking

  • Global behaviours relocated — Global behaviour files now live at ~/.config/rosett-ai/conf/ (XDG-compliant) instead of ~/.claude/conf/. Auto-migration runs on first compile.

Fixed

  • 38 audit bugs — Comprehensive audit campaign fixing remote contamination, XDG migration, worktree issues, and CI divergence (Epic WP#726)
  • CVE-2026-33946 — Updated mcp gem to patched version
  • Compile scope coexistence — Global and project behaviours now merge correctly in project scope (Issue 005, WP#711/712)
  • Global scope source resolution — Compile task now uses XDG-compliant path for global behaviour source (WP#943)

Changed

  • Engine registry delegationRosettAi::Engines::Registry now delegates entirely to RosettAi::Plugins::Registry (no hardcoded maps)
  • Backend resolutionRosettAi::Compiler::Backend.for resolves exclusively via plugin registry
  • BehaviourCompiler — Resolves Claude backend via plugin registry instead of direct require
  • Deprecated aliasesRosettAi::Config::* and RosettAi::Compiler::Backends::* are constant aliases to RosettAiEngine::*
  • ARCHITECTURE.md — Updated to reflect external gem plugin discovery model
  • CONTRIBUTING.md — Rewritten engine guide for RosettAiEngine:: gem-based plugins
  • ENGINES.md — Updated diagrams and registry docs for fully external approach

Removed

  • Built-in engine codelib/rosett_ai/engines/{claude,generic,...}/, conf/engines/, spec/rosett_ai/engines/{...}/ removed from core (now in separate gems)

[1.0.0] - 2026-03-05

Core-only release. Desktop components (D-Bus service, GTK4 app) available via the rosett-ai-gtk4 package. See ADR-009 for rationale.

Changed

  • render() signaturerender(category, data)render(data) with data['category'] set by caller (Finding #10)
  • Marker standardization — All engines use <!-- rosett-ai-{engine}-managed --> format (Finding #7)
  • Capability warnings — Grouped by feature type instead of per-file (Finding #9)
  • GTK4 engine list — Dynamic via D-Bus ListEngines() instead of hardcoded (Finding #4)
  • README tagline — Updated to list all 10 engines (Findings #5+6)
  • Core-only gemspecruby-dbus and i3ipc moved to :desktop Bundler group (ADR-009)
  • Zeitwerk conditional ignore — Desktop/D-Bus modules excluded when ruby-dbus unavailable
  • Desktop CLI graceful degradationdbus and desktop commands print install hint when desktop gems missing

Added

  • Operations design domainoperations added as 13th domain in design schema
  • Monitoring/observability design docconf/design/monitoring_observability.yml (structured telemetry, provider interface)
  • Usage optimization design docconf/design/usage_optimization.yml (startup targets, compile caching, profiling)
  • SimpleCov thresholds — Minimum 88% overall, 25% per file (baseline enforcement)
  • Test fixtures — Design doc fixtures (valid, invalid, operations), config fixtures (minimal, full)
  • Mutant expanded subjectsRosettAi::Engines* and RosettAi::Quorum* added to mutation testing
  • CI validation includesdesign-docs.yml and tooling-docs.yml now included in pipeline
  • Core-only rspec CI jobtest:rspec:core excluding desktop/dbus specs
  • Package smoke testbuild:package:smoke_test installs .deb and verifies CLI
  • ADR-009 — Core-only v1.0.0 release decision record
  • Security scan hardening — Explicit allow_failure: false on all 4 security scan CI jobs
  • AI provenancedoc/AI_PROVENANCE.md documenting AI-assisted development practices
  • Cursor enginelib/rosett_ai/engines/cursor/ backend + detector for Cursor by Anysphere (Engine Phase 4)
  • Copilot enginelib/rosett_ai/engines/copilot/ backend + detector for GitHub Copilot (Engine Phase 4)
  • Windsurf enginelib/rosett_ai/engines/windsurf/ backend + detector for Windsurf by Codeium (Engine Phase 4)
  • Goose executorlib/rosett_ai/engines/goose/executor.rb CLI subprocess executor via Open3.capture3 (Engine Phase 4)
  • Aider executorlib/rosett_ai/engines/aider/executor.rb CLI subprocess executor via Open3.capture3 (Engine Phase 4)
  • CLI executor typeapi_type: cli in engine manifests for subprocess-based executors (Engine Phase 4)
  • ExecutorResolver CLI supportbinary: kwarg branch for CLI-type engine executors
  • Goose enginelib/rosett_ai/engines/goose/ backend for Goose by Block (Engine Phase 3)
  • Aider enginelib/rosett_ai/engines/aider/ backend for Aider (Engine Phase 3)
  • Ollama/GPT-NeoX target profilesconf/engines/{ollama,gpt_neox}/target.yml for compilation (Finding #1)
  • D-Bus ListEngines method — Returns [name, display_name] tuples from Registry (Finding #4)
  • Executor API key guard — Raises AdoptError with --local hint when API key is nil (Finding #2)
  • Bullet-list local analysisLocalAnalysisCollector parses bullet rules from AGENTS.md format (Finding #3)
  • check_summarizedCapabilityChecker groups warnings by feature type (Finding #9)

Fixed

  • RuleAdopter::GENERATED_MARKER updated to match new marker format
  • BACKENDS hash includes all 10 engines (was missing aider, goose, gpt_neox, ollama, cursor, copilot, windsurf)
  • target_schema.json backend enum includes all 10 engines
  • engine_manifest_schema.json api_type enum includes cli for subprocess executors

Added

  • Quorum module (Backfill — multi-engine adopt analysis)

    • lib/rosett_ai/quorum/dispatcher.rb — Thread-based parallel dispatch to N engines
    • lib/rosett_ai/quorum/collector.rb — normalize per-engine responses to common format
    • lib/rosett_ai/quorum/comparator.rb — aggregate cross-engine findings, promote consensus
    • lib/rosett_ai/quorum/strategies/adopt.rb — adopt-specific orchestration
    • --quorum flag on bin/raictl adopt --api for multi-engine analysis
  • Capability checker (Backfill — compile-time capability gap warnings)

    • lib/rosett_ai/compiler/capability_checker.rb — check source YAML vs engine manifest
    • Warns when sensitive content targets engines without sensitive_filtering
    • --strict mode raises CompileError on capability gaps
    • All 5 engine manifests updated with sensitive_filtering and rule_metadata keys
  • Executor normalization (Backfill — uniform analyze interface)

    • lib/rosett_ai/adopter/executor_resolver.rb — manifest-driven executor kwargs
    • analyze(prompt) method added to Ollama and GPT-NeoX executors
    • All executors return {findings, overall_status, summary} JSON contract
  • D-Bus stop command (Backfill — bin/raictl dbus stop)

    • Shutdown method on be.neatnerds.rosettai.Manager interface
    • bin/raictl dbus stop sends shutdown signal via session bus
  • StatusNotifierItem (Backfill — system tray icon)

    • lib/rosett_ai/dbus/status_notifier_interface.rborg.kde.StatusNotifierItem
    • Properties: Id, Category, Status, Title, IconName, ToolTip
    • Signals: NewStatus, NewTitle
    • Graceful degradation if no SNI host available
  • GTK4 preference callbacks (Backfill — instant-apply via D-Bus)

    • Preference changes applied immediately via DbusClient#set_config
    • SetConfig(key, value) method on Manager interface
    • RaiConfig#update for persistent config changes with validation
    • Callbacks: verbose, strict, engine selection, auto-switch
  • GTK4 application hardening (Desktop Phase 2b — crash-proof architecture)

    • safe_action() wrapper pattern — all event handlers wrapped, app never crashes
    • safe_callback() wrapper for preferences dialog callbacks
    • lib/rosett_ai/desktop/gui_logger.rb — structured JSON Lines logging for GUI debugging
    • RAI_GUI_LOG=1 environment variable enables logging to stderr
    • RAI_GUI_LOG_FILE and RAI_GUI_LOG_LEVEL for file output and level control
    • D-Bus client returns safe defaults (SAFE_STATUS, SAFE_FOCUS, SAFE_COMPILE_RESULT)
    • defined? checks for libadwaita version compatibility (PreferencesDialog vs PreferencesWindow)
    • Error dialogs via Adw::MessageDialog instead of crashes
    • Thread-safe logging with Mutex
  • Ollama and GPT-NeoX engines (Engine Phase 2 — local quorum capability)

    • lib/rosett_ai/engines/ollama/ — backend, detector, executor for Ollama
    • lib/rosett_ai/engines/gpt_neox/ — backend, detector, executor for GPT-NeoX on vLLM
    • conf/engines/ollama/manifest.yml — Ollama capability declaration
    • conf/engines/gpt_neox/manifest.yml — GPT-NeoX capability declaration
    • Ollama detection: binary in PATH + localhost:11434
    • GPT-NeoX detection: VLLM_ENDPOINT env var or config
  • GTK4/Adwaita desktop application (Desktop Phase 2)

    • lib/rosett_ai/desktop/gtk4_app.rb — main GTK4 app following GNOME HIG
    • lib/rosett_ai/desktop/gtk4_preferences.rb — preferences dialog with instant-apply
    • lib/rosett_ai/desktop/dbus_client.rb — D-Bus client for GUI apps
    • bin/raictl desktop gtk4 CLI subcommand
    • Service status display, compile rules action, preferences pages
    • Adwaita widgets: HeaderBar, ToastOverlay, PreferencesGroup, ActionRow, SwitchRow, ComboRow
    • About window with license, version, and links
  • D-Bus service foundation (Desktop Phase 1)

    • lib/rosett_ai/dbus/service.rbbe.neatnerds.rosettai session bus service
    • lib/rosett_ai/dbus/manager_interface.rb — Compile, SwitchContext, GetStatus methods
    • lib/rosett_ai/dbus/focus_monitor_interface.rb — GetCurrentFocus, FocusChanged signal
    • lib/rosett_ai/dbus/compositor_detector.rb — GNOME, KDE, i3, Hyprland, X11 detection
    • lib/rosett_ai/dbus/focus_adapters/ — 5 compositor-specific focus adapters
    • bin/raictl dbus start CLI subcommand
  • AGENTS.md engine (Engine Phase 1 — first vendor-neutral engine)

    • lib/rosett_ai/engines/agents_md/backend.rb — compiles behaviour YAML to AGENTS.md format
    • lib/rosett_ai/engines/agents_md/detector.rb — detects existing AGENTS.md in project root
    • conf/engines/agents_md/manifest.yml — engine capability declaration
    • conf/engines/agents_md/target.yml — target profile for AGENTS.md output
    • --engine agents_md flag on bin/raictl compile for AGENTS.md output
    • Bullet-list rule rendering, priority-sorted, no rule IDs or metadata comments
    • "Instructions" section header (idiomatic for AGENTS.md format)
    • Distinct managed marker (<!-- agents_md-managed -->) for file ownership detection
  • XDG config, engine detection, and CLI flags (Phase 0c — engine-agnostic architecture)

    • lib/rosett_ai/rai_config.rb — runtime config loader (~/.config/rosett-ai/config.yml)
    • conf/schemas/rai_config_schema.json — rai config validation
    • conf/schemas/engine_manifest_schema.json — engine manifest validation
    • lib/rosett_ai/engines/detector.rb — base engine detector (manifest-driven)
    • lib/rosett_ai/engines/claude/detector.rb — Claude engine detector
    • lib/rosett_ai/thor/tasks/engines.rbengines list|detect|status CLI subcommand
    • lib/rosett_ai/init/config_file_writer.rb — default config writer for rai init
    • --engine flag on bin/raictl compile (replaces --target)
    • --strict flag on bin/raictl compile (warnings as errors)
    • --api flag on bin/raictl adopt (opt-in remote analysis)
    • Engine manifest validation in Registry via json_schemer
    • Engine detection during rai init --global
    • RosettAi.rai_config singleton accessor with reset_config! support

Changed

  • bin/raictl adopt defaults to local-only analysis (was remote)
  • --target flag deprecated in favour of --engine (emits warning)
  • RuleAdopter accepts engine: parameter for dynamic executor resolution
  • conf/engines/claude/manifest.yml sets detector: true

  • Engine directory structure (Phase 0b — engine-agnostic architecture)

    • lib/rosett_ai/engines/claude/ — Backend, ConfigCompiler, KeyMap, ScopeRouter, DomainTransformer, Executor (extracted from RuleAdopter)
    • lib/rosett_ai/engines/generic/ — Backend
    • lib/rosett_ai/engines/registry.rb — static engine discovery
    • conf/engines/claude/manifest.yml — capability declaration
    • conf/engines/generic/manifest.yml — capability declaration
    • Backward-compatible aliases for all moved classes (deprecated, remove in v1.1.0)

Changed

  • Renamed from "NeatNerds Claude Companion" to "Rosett-AI"
  • Version bump to 1.0.0 marking engine-agnostic architecture pivot (ADR-007)
  • CLI descriptions updated to reflect multi-engine support
  • Gemspec description reworded for engine-agnostic positioning
  • Moved anthropic gem from core gemspec to Gemfile :engines group (lazy-loaded)
  • Moved conf/claude_code/*.yml to conf/engines/claude/config/
  • Moved conf/targets/*.yml to conf/engines/<name>/target.yml
  • Moved conf/schemas/claude_code_config_schema.json to conf/engines/claude/schemas/config_schema.json
  • TargetProfile.load searches conf/engines/<name>/target.yml first, falls back to legacy path
  • PathResolver#claude_code_config_dir points to conf/engines/claude/config
  • RuleAdopter#analyze delegates to RosettAi::Engines::Claude::Executor
  • Documentation::Translator lazy-loads anthropic gem inside call_api

Added

  • Claude Code configuration compiler (P2 — claude_code_configuration.yml, all 17 acceptance criteria)
    • RosettAi::Config::Compiler — YAML-to-JSON compilation pipeline for Claude Code settings
    • RosettAi::Config::KeyMap — explicit snake_case→camelCase mapping table (not algorithmic)
    • RosettAi::Config::ScopeRouter — scope-to-target-path routing (managed/user/project/local)
    • RosettAi::Config::SecretResolver — deterministic ${secret:backend:key} parser (NO regex)
    • RosettAi::Config::CompileResult — structured result value object per scope compilation
    • conf/schemas/claude_code_config_schema.json — JSON Schema draft 2020-12 with scope-conditional validation
    • conf/claude_code/{managed,user,project,local}.yml — four populated scope configuration files
    • bin/raictl config compile — new CLI subcommand with --verbose, --simulate, --scope options
    • Secret backends: env (ENV.fetch), file (0600 perms, 64 KiB cap), path (traversal rejection)
    • Version compatibility checking via Gem::Requirement (advisory warnings only)
    • Context env-target fields compile to env key within JSON (merged with explicit env entries)
    • Network/API validate-only fields emit warnings when env vars are unset
    • Idempotent compilation — no unnecessary writes when source is unchanged
    • PathResolver extended with 5 new methods for settings target paths
  • Architecture packaging declarations (P2 — architecture.yml criterion 8)
    • VariantConfig loader validating conf/packaging/<variant>.yml against JSON Schema
    • Dynamic "current" version keyword resolving to RosettAi::VERSION at load time
    • conf/packaging/core.yml, gtk4.yml, qt6.yml variant configurations
    • conf/schemas/packaging_schema.json with name pattern and version constraint validation
    • --variant option on bin/raictl build package (default: core)
    • Non-core variants fail early if adapter file doesn't exist yet (P3)
  • Compiler multi-target pipeline (P2 — compiler.yml, all 9 acceptance criteria)
    • Strategy-pattern CompilationPipeline with pluggable Backend instances
    • ClaudeBackend — Claude Code markdown with HTML metadata and priority annotations
    • GenericBackend — plain markdown without Claude-specific formatting
    • CompiledOutput Struct value object replacing raw Hash returns
    • TargetProfile loader validating conf/targets/<name>.yml against JSON Schema
    • LocaleCompiler compiling ruby-i18n YAML to gettext (.pot/.po) and Qt Linguist (.ts)
    • --target claude|generic flag for target selection on bin/raictl compile
    • --locales flag for locale compilation on bin/raictl compile
    • conf/targets/claude.yml and conf/targets/generic.yml target profiles
    • conf/schemas/target_schema.json with strict enum validation
    • locales/en.yml English locale source file
    • Performance benchmark: 100 files compile in ~0.4s (criterion: < 5s)
  • PathResolver (ADR-002) — centralised path resolution for all Claude Code and rosett-ai directories, replacing hardcoded paths in 6 library files
    • RosettAi::PathResolver class with instance methods (Pathname return type)
    • RosettAi.paths module accessor with memoisation and reset support
    • XDG-compliant rai_config_dir respecting XDG_CONFIG_HOME
    • engine: keyword on constructor for future ADR-006 multi-engine support
  • Testing infrastructure (P1 — testing.yml, all 9 acceptance criteria)
    • Mutation testing via mutant-rspec with .mutant.yml (usage: opensource)
    • Property-based testing via Rantly for security-critical code (YamlLoader)
    • factory_bot factories for Behaviour and Rule domain objects
    • Shared examples defining UI interface contract for future implementations
    • Test fixtures: valid, invalid, malicious (YAML bomb, ANSI injection), and Unicode (NFC/NFD/CJK/RTL)
    • AI-generated test review checklist (11-point, doc/ai_test_review_checklist.md)
    • Mutant CI job on merge requests (test:mutant), blocks merge on score drop
  • Debian packaging via fpm + ruby-build, replacing Omnibus
    • bin/raictl build package produces self-contained .deb with embedded Ruby
    • Proper APT lifecycle: postinst (symlink + conffile), prerm, postrm (purge)
    • Multi-architecture support (amd64, arm64)
  • bin/raictl init command with --global / --local / --no-compile flags
  • bin/raictl tooling validate-ci-yaml for GitLab CI YAML validation
  • GitLab CI retry policy (max 2) for transient infrastructure failures
  • i18n/locale support scaffolding in CI pipeline
  • Release management (P5 — release_management.yml, all 10 acceptance criteria)
    • bin/raictl release prepare LEVEL — bumps version, runs 5 verification gates (rspec, rubocop, reek, bundler-audit, ruby-audit), generates CHANGELOG, creates release commit
    • bin/raictl release tag — creates annotated git tag with CHANGELOG excerpt
    • bin/raictl release status — shows version, last tag, unreleased commit count
    • cliff.toml — git-cliff conventional commit to Keep a Changelog mapping
    • GitLab CI release:publish job creates GitLab release on vX.Y.Z tag push
  • Documentation tooling (P5 — documentation.yml, all 10 acceptance criteria)
    • doc/man/rai.1.ronn — complete ronn-ng man page source (NAME through LICENSE)
    • rake man:build generates man/man1/rai.1 from ronn source
    • Build task :install_man stage gzips and installs man page to /usr/share/man/man1/
    • .yardopts for YARD API documentation generation
    • INSTALL.md — end-user installation guide (.deb, APT repo, verification, uninstall)
    • CI code_quality:doc_consistency job verifies Ruby version and doc file presence
    • ronn-ng (~> 0.10) and yard (~> 0.9) added as development dependencies
  • CONTRIBUTING.md — developer expansion guide covering how to add translations, AI engines, configuration sections, CLI subcommands, design documents, UI adapters, and CI jobs

Changed

  • claude_code_configuration.yml design document status changed from draft to approved (all 17 acceptance criteria met; completes P2 tier)
  • architecture.yml design document status changed from draft to approved (all 8 acceptance criteria met; unblocks P3 work)
  • Build task uses VariantConfig for package name, description, and dependencies instead of hardcoded values (backward compatible via --variant core default)
  • BehaviourCompiler refactored to thin wrapper around CompilationPipeline, preserving original 3-argument constructor for backward compatibility
  • Compile Thor task uses CompilationPipeline with target-aware backend instead of hardcoded BehaviourCompiler
  • compiler.yml design document status changed from draft to approved
  • SecretsResolver no longer owns path constants (SECRETS_DIR, SECRETS_FILE removed); delegates to RosettAi.paths for all path resolution
  • BehaviourCompiler lockfile output uses RosettAi.paths.rules_display_path instead of hardcoded tilde strings
  • Init, Backup, Compile, Adopt specs use instance_double(RosettAi::PathResolver) instead of stub_const or allow(File).to receive(:expand_path) stubs
  • Mutant coverage raised from 80% to 97.83% (543/555 killed, 12 equivalent survivors)
  • SimpleCov thresholds raised from 50/40 to 90/80 (overall/per-file)
  • SimpleCov coverage groups reorganized: Compilers, Validators, Adopter, Backup, Thor Tasks
  • Added rubocop-factory_bot plugin to .rubocop.yml
  • Replaced Omnibus (11 config files, 30-60 min builds, 100MB+ packages) with fpm (~650 LOC, <5 min builds, ~38MB packages)
  • Rewrote lib/rosett_ai/thor/tasks/init.rb to delegate to DirectoryBuilder and FileCopier
  • Simplified lib/rosett_ai/thor/tasks/tooling.rb from ~420 LOC to a focused CI validator
  • Refactored build task: extracted BuildContext Struct for mutable state, status_text helper
  • CI build job renamed from omnibus.yml to package.yml

Removed

  • Entire omnibus/ directory (Gemfile, Rakefile, config/, package-scripts/)
  • Orphaned lib/rosett_ai/tooling/ module (detector, display_helpers, package_manager, settings_manager, tool_registry)
  • Corresponding specs for removed tooling code

Fixed

  • Thor [WARNING] Attempted to create command messages during test runs
  • fpm --config-files packaging error (conffile now ships at /etc/rosett-ai/)
  • Gitleaks false positives on test fixtures and CI variables