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 raiseCompileError(WP#1492)
Fixed
- Project-scope compile wrote to global rules —
resolve_target_diralways returned~/.claude/rules/regardless of compile scope. Split intoresolve_target_dir(explicit output_dir) anddefault_target_dir(scope-based routing). Project scope now writes to<project_root>/.claude/rules/(WP#1490) - BehaviourCompiler failed without engine gem —
BehaviourCompilerqueried the plugin registry directly for the claude engine, which fails when no engine gem is installed. Now usesBackend.for('claude')which checksBUILTIN_BACKENDSfirst, 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_nnccdiagnostic warns when.rosett-ai/exists at$HOMElevel, 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 automaticOP#<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 withconfig.yml,conf/behaviour/, andconf/design/RosettAi::ProjectContext— New class for project root detection with.rosett-ai/directory walking- Project config schema — JSON Schema for
.rosett-ai/config.ymlvalidation - Test Kitchen integration tests — InSpec profiles for context-aware CLI verification in Docker
- Engine .deb packaging — Reusable
packaging/build-engine-deb.shfor building per-engine Debian packages (ADR-010) - Wrapper template —
packaging/wrapper.sh.templatewith 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 registry —
RosettAi::Plugins::RegistrywithGem.find_filesdiscovery for external gems - Base config compiler —
RosettAi::Engines::BaseConfigCompilertemplate method pattern for engine config compilation - Engine contract —
RosettAi::Plugins::EngineContractdefining backend, detector, executor, config compiler interfaces - GUI contract —
RosettAi::Plugins::GuiContractdefining toolkit, application, D-Bus interface methods - MCP contract —
RosettAi::Plugins::McpContractdefining server, tool, and resource interfaces - Engine-aware CLI —
--engineoption onconfig compilewith cascade lookup (config → autodetect → prompt) - Plugins subcommand —
bin/raictl engines pluginsshows registered external engine gems - External Claude engine gem —
rosett-ai-engine-claudereferenced via path in Gemfile (:enginesgroup) - Engine stub infrastructure —
spec/support/stub_engines.rbprovides test doubles for all 11 engine gems, enabling core-onlyrspecruns without engine gems installed - All 10 engine gems —
rosett-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 engine —
rosett-ai-engine-acmereference 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.debruntime target_profile_pathcontract method — Engines expose their target profile path viaEngineContract, enabling plugin-awareTargetProfile.loaddoc/REFERENCE.md— Comprehensive configuration reference (hierarchy, env vars, CLI options, file locations)- YARD Rake task —
rake yardgenerates API documentation todoc/api/ - Test Kitchen
rai-commandssuite — 13 InSpec control files for comprehensive CLI command verification acmebackend in target schema — Added totarget_schema.jsonenum 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 code —
RosettAi::Cache::CompilerCacheandRosettAi::Cache::Manifestwere 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) —
.debwrappercd /opt/rosett-ai/appmadeProjectContextresolve to the rosett-ai internal tree instead of the user's project. Now preservesRAI_ORIGINAL_PWDbeforecd - 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.loadnow checks the plugin registry first (engine'starget_profile_path) before falling back to file-based lookup - Missing engine produces unhelpful error (RC4) —
config compileandcompilenow show actionable install hints (apt install rosett-ai-engine-<name>) instead of empty "Available:" lists init --projectcrash on missing engine —run_compilenow rescuesCompileErrorgracefully and suggests runningrai compileafter 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/RUBYLIBfix; 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_HOMEwith correct embedded paths, eliminating chicken-and-egg ruby subprocess (Issue 001) - CI smoke test false positive — Removed
apt-get install rubyfrom smoke test; added prefix and RUNPATH verification assertions (Issue 003) - Bundler env leakage — Added all
BUNDLER_ORIG_*variables toBUNDLER_ENV_VARSconstant 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 delegation —
RosettAi::Engines::Registrynow delegates entirely toRosettAi::Plugins::Registry(no hardcoded maps) - Backend resolution —
RosettAi::Compiler::Backend.forresolves exclusively via plugin registry - BehaviourCompiler — Resolves Claude backend via plugin registry instead of direct require
- Deprecated aliases —
RosettAi::Config::*andRosettAi::Compiler::Backends::*are constant aliases toRosettAiEngine::* - 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 code —
lib/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() signature —
render(category, data)→render(data)withdata['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 gemspec —
ruby-dbusandi3ipcmoved to:desktopBundler group (ADR-009) - Zeitwerk conditional ignore — Desktop/D-Bus modules excluded when
ruby-dbusunavailable - Desktop CLI graceful degradation —
dbusanddesktopcommands print install hint when desktop gems missing
Added
- Operations design domain —
operationsadded as 13th domain in design schema - Monitoring/observability design doc —
conf/design/monitoring_observability.yml(structured telemetry, provider interface) - Usage optimization design doc —
conf/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 subjects —
RosettAi::Engines*andRosettAi::Quorum*added to mutation testing - CI validation includes —
design-docs.ymlandtooling-docs.ymlnow included in pipeline - Core-only rspec CI job —
test:rspec:coreexcluding desktop/dbus specs - Package smoke test —
build:package:smoke_testinstalls .deb and verifies CLI - ADR-009 — Core-only v1.0.0 release decision record
- Security scan hardening — Explicit
allow_failure: falseon all 4 security scan CI jobs - AI provenance —
doc/AI_PROVENANCE.mddocumenting AI-assisted development practices - Cursor engine —
lib/rosett_ai/engines/cursor/backend + detector for Cursor by Anysphere (Engine Phase 4) - Copilot engine —
lib/rosett_ai/engines/copilot/backend + detector for GitHub Copilot (Engine Phase 4) - Windsurf engine —
lib/rosett_ai/engines/windsurf/backend + detector for Windsurf by Codeium (Engine Phase 4) - Goose executor —
lib/rosett_ai/engines/goose/executor.rbCLI subprocess executor viaOpen3.capture3(Engine Phase 4) - Aider executor —
lib/rosett_ai/engines/aider/executor.rbCLI subprocess executor viaOpen3.capture3(Engine Phase 4) - CLI executor type —
api_type: cliin engine manifests for subprocess-based executors (Engine Phase 4) - ExecutorResolver CLI support —
binary:kwarg branch for CLI-type engine executors - Goose engine —
lib/rosett_ai/engines/goose/backend for Goose by Block (Engine Phase 3) - Aider engine —
lib/rosett_ai/engines/aider/backend for Aider (Engine Phase 3) - Ollama/GPT-NeoX target profiles —
conf/engines/{ollama,gpt_neox}/target.ymlfor compilation (Finding #1) - D-Bus ListEngines method — Returns
[name, display_name]tuples from Registry (Finding #4) - Executor API key guard — Raises
AdoptErrorwith--localhint when API key is nil (Finding #2) - Bullet-list local analysis —
LocalAnalysisCollectorparses bullet rules from AGENTS.md format (Finding #3) - check_summarized —
CapabilityCheckergroups warnings by feature type (Finding #9)
Fixed
RuleAdopter::GENERATED_MARKERupdated to match new marker formatBACKENDShash includes all 10 engines (was missing aider, goose, gpt_neox, ollama, cursor, copilot, windsurf)target_schema.jsonbackend enum includes all 10 enginesengine_manifest_schema.jsonapi_type enum includesclifor subprocess executors
Added
Quorum module (Backfill — multi-engine adopt analysis)
lib/rosett_ai/quorum/dispatcher.rb— Thread-based parallel dispatch to N engineslib/rosett_ai/quorum/collector.rb— normalize per-engine responses to common formatlib/rosett_ai/quorum/comparator.rb— aggregate cross-engine findings, promote consensuslib/rosett_ai/quorum/strategies/adopt.rb— adopt-specific orchestration--quorumflag onbin/raictl adopt --apifor 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 --strictmode raisesCompileErroron capability gaps- All 5 engine manifests updated with
sensitive_filteringandrule_metadatakeys
Executor normalization (Backfill — uniform analyze interface)
lib/rosett_ai/adopter/executor_resolver.rb— manifest-driven executor kwargsanalyze(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)Shutdownmethod onbe.neatnerds.rosettai.Managerinterfacebin/raictl dbus stopsends shutdown signal via session bus
StatusNotifierItem (Backfill — system tray icon)
lib/rosett_ai/dbus/status_notifier_interface.rb—org.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 interfaceRaiConfig#updatefor persistent config changes with validation- Callbacks: verbose, strict, engine selection, auto-switch
- Preference changes applied immediately via
GTK4 application hardening (Desktop Phase 2b — crash-proof architecture)
safe_action()wrapper pattern — all event handlers wrapped, app never crashessafe_callback()wrapper for preferences dialog callbackslib/rosett_ai/desktop/gui_logger.rb— structured JSON Lines logging for GUI debuggingRAI_GUI_LOG=1environment variable enables logging to stderrRAI_GUI_LOG_FILEandRAI_GUI_LOG_LEVELfor 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::MessageDialoginstead 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 Ollamalib/rosett_ai/engines/gpt_neox/— backend, detector, executor for GPT-NeoX on vLLMconf/engines/ollama/manifest.yml— Ollama capability declarationconf/engines/gpt_neox/manifest.yml— GPT-NeoX capability declaration- Ollama detection: binary in PATH + localhost:11434
- GPT-NeoX detection:
VLLM_ENDPOINTenv var or config
GTK4/Adwaita desktop application (Desktop Phase 2)
lib/rosett_ai/desktop/gtk4_app.rb— main GTK4 app following GNOME HIGlib/rosett_ai/desktop/gtk4_preferences.rb— preferences dialog with instant-applylib/rosett_ai/desktop/dbus_client.rb— D-Bus client for GUI appsbin/raictl desktop gtk4CLI 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.rb—be.neatnerds.rosettaisession bus servicelib/rosett_ai/dbus/manager_interface.rb— Compile, SwitchContext, GetStatus methodslib/rosett_ai/dbus/focus_monitor_interface.rb— GetCurrentFocus, FocusChanged signallib/rosett_ai/dbus/compositor_detector.rb— GNOME, KDE, i3, Hyprland, X11 detectionlib/rosett_ai/dbus/focus_adapters/— 5 compositor-specific focus adaptersbin/raictl dbus startCLI 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 formatlib/rosett_ai/engines/agents_md/detector.rb— detects existing AGENTS.md in project rootconf/engines/agents_md/manifest.yml— engine capability declarationconf/engines/agents_md/target.yml— target profile for AGENTS.md output--engine agents_mdflag onbin/raictl compilefor 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 validationconf/schemas/engine_manifest_schema.json— engine manifest validationlib/rosett_ai/engines/detector.rb— base engine detector (manifest-driven)lib/rosett_ai/engines/claude/detector.rb— Claude engine detectorlib/rosett_ai/thor/tasks/engines.rb—engines list|detect|statusCLI subcommandlib/rosett_ai/init/config_file_writer.rb— default config writer forrai init--engineflag onbin/raictl compile(replaces--target)--strictflag onbin/raictl compile(warnings as errors)--apiflag onbin/raictl adopt(opt-in remote analysis)- Engine manifest validation in Registry via
json_schemer - Engine detection during
rai init --global RosettAi.rai_configsingleton accessor withreset_config!support
Changed
bin/raictl adoptdefaults to local-only analysis (was remote)--targetflag deprecated in favour of--engine(emits warning)RuleAdopteracceptsengine:parameter for dynamic executor resolutionconf/engines/claude/manifest.ymlsetsdetector: trueEngine 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/— Backendlib/rosett_ai/engines/registry.rb— static engine discoveryconf/engines/claude/manifest.yml— capability declarationconf/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
anthropicgem from core gemspec to Gemfile:enginesgroup (lazy-loaded) - Moved
conf/claude_code/*.ymltoconf/engines/claude/config/ - Moved
conf/targets/*.ymltoconf/engines/<name>/target.yml - Moved
conf/schemas/claude_code_config_schema.jsontoconf/engines/claude/schemas/config_schema.json TargetProfile.loadsearchesconf/engines/<name>/target.ymlfirst, falls back to legacy pathPathResolver#claude_code_config_dirpoints toconf/engines/claude/configRuleAdopter#analyzedelegates toRosettAi::Engines::Claude::ExecutorDocumentation::Translatorlazy-loadsanthropicgem insidecall_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 settingsRosettAi::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 compilationconf/schemas/claude_code_config_schema.json— JSON Schema draft 2020-12 with scope-conditional validationconf/claude_code/{managed,user,project,local}.yml— four populated scope configuration filesbin/raictl config compile— new CLI subcommand with--verbose,--simulate,--scopeoptions- 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
envkey 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)
VariantConfigloader validatingconf/packaging/<variant>.ymlagainst JSON Schema- Dynamic
"current"version keyword resolving toRosettAi::VERSIONat load time conf/packaging/core.yml,gtk4.yml,qt6.ymlvariant configurationsconf/schemas/packaging_schema.jsonwith name pattern and version constraint validation--variantoption onbin/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
CompilationPipelinewith pluggableBackendinstances ClaudeBackend— Claude Code markdown with HTML metadata and priority annotationsGenericBackend— plain markdown without Claude-specific formattingCompiledOutputStruct value object replacing raw Hash returnsTargetProfileloader validatingconf/targets/<name>.ymlagainst JSON SchemaLocaleCompilercompiling ruby-i18n YAML to gettext (.pot/.po) and Qt Linguist (.ts)--target claude|genericflag for target selection onbin/raictl compile--localesflag for locale compilation onbin/raictl compileconf/targets/claude.ymlandconf/targets/generic.ymltarget profilesconf/schemas/target_schema.jsonwith strict enum validationlocales/en.ymlEnglish locale source file- Performance benchmark: 100 files compile in ~0.4s (criterion: < 5s)
- Strategy-pattern
- PathResolver (ADR-002) — centralised path resolution for all Claude Code
and rosett-ai directories, replacing hardcoded paths in 6 library files
RosettAi::PathResolverclass with instance methods (Pathnamereturn type)RosettAi.pathsmodule accessor with memoisation and reset support- XDG-compliant
rai_config_dirrespectingXDG_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
- Mutation testing via mutant-rspec with
- Debian packaging via fpm + ruby-build, replacing Omnibus
bin/raictl build packageproduces self-contained.debwith embedded Ruby- Proper APT lifecycle: postinst (symlink + conffile), prerm, postrm (purge)
- Multi-architecture support (amd64, arm64)
bin/raictl initcommand with--global/--local/--no-compileflagsbin/raictl tooling validate-ci-yamlfor 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 commitbin/raictl release tag— creates annotated git tag with CHANGELOG excerptbin/raictl release status— shows version, last tag, unreleased commit countcliff.toml— git-cliff conventional commit to Keep a Changelog mapping- GitLab CI
release:publishjob creates GitLab release onvX.Y.Ztag 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:buildgeneratesman/man1/rai.1from ronn source- Build task
:install_manstage gzips and installs man page to/usr/share/man/man1/ .yardoptsfor YARD API documentation generationINSTALL.md— end-user installation guide (.deb, APT repo, verification, uninstall)- CI
code_quality:doc_consistencyjob verifies Ruby version and doc file presence ronn-ng(~> 0.10) andyard(~> 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.ymldesign document status changed fromdrafttoapproved(all 17 acceptance criteria met; completes P2 tier)architecture.ymldesign document status changed fromdrafttoapproved(all 8 acceptance criteria met; unblocks P3 work)- Build task uses
VariantConfigfor package name, description, and dependencies instead of hardcoded values (backward compatible via--variant coredefault) BehaviourCompilerrefactored to thin wrapper aroundCompilationPipeline, preserving original 3-argument constructor for backward compatibility- Compile Thor task uses
CompilationPipelinewith target-aware backend instead of hardcodedBehaviourCompiler compiler.ymldesign document status changed fromdrafttoapprovedSecretsResolverno longer owns path constants (SECRETS_DIR,SECRETS_FILEremoved); delegates toRosettAi.pathsfor all path resolutionBehaviourCompilerlockfile output usesRosettAi.paths.rules_display_pathinstead of hardcoded tilde strings- Init, Backup, Compile, Adopt specs use
instance_double(RosettAi::PathResolver)instead ofstub_constorallow(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_botplugin 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.rbto delegate toDirectoryBuilderandFileCopier - Simplified
lib/rosett_ai/thor/tasks/tooling.rbfrom ~420 LOC to a focused CI validator - Refactored build task: extracted
BuildContextStruct for mutable state,status_texthelper - CI build job renamed from
omnibus.ymltopackage.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 commandmessages during test runs - fpm
--config-filespackaging error (conffile now ships at/etc/rosett-ai/) - Gitleaks false positives on test fixtures and CI variables