rosett-ai 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ai-provenance.yml +119 -0
- data/.debride_whitelist +186 -0
- data/.fasterer.yml +29 -0
- data/.mdl_style.rb +10 -0
- data/.mdlrc +3 -0
- data/.mutant.yml +49 -0
- data/.namespace-allowlist +42 -0
- data/.reek.yml +1040 -0
- data/.rosett-ai/config.yml +3 -0
- data/.rspec +5 -0
- data/.rubocop.yml +380 -0
- data/.ruby-version +1 -0
- data/.yamllint +51 -0
- data/.yardopts +12 -0
- data/AI-DISCLOSURE.md +48 -0
- data/CHANGELOG.md +519 -0
- data/CLAUDE.md +141 -0
- data/CONTRIBUTING.md +734 -0
- data/INSTALL.md +154 -0
- data/LICENSE +674 -0
- data/LICENSE.md +675 -0
- data/QUICKSTART.md +73 -0
- data/README.md +366 -0
- data/Rakefile +200 -0
- data/SECURITY.md +114 -0
- data/bin/rai +1 -0
- data/cliff.toml +52 -0
- data/conf/adopt_redactions.yml +8 -0
- data/conf/behaviour/.gitkeep +0 -0
- data/conf/compliance/cra_rules.yml +25 -0
- data/conf/compliance/license_rules.yml +20 -0
- data/conf/design/aaif_alignment.yml +181 -0
- data/conf/design/ab_testing.yml +172 -0
- data/conf/design/accessibility.yml +84 -0
- data/conf/design/ai_authorship.yml +210 -0
- data/conf/design/ai_provenance.yml +224 -0
- data/conf/design/ai_tool_configuration.yml +207 -0
- data/conf/design/architecture.yml +139 -0
- data/conf/design/autocompletion.yml +115 -0
- data/conf/design/backward_compatibility.yml +112 -0
- data/conf/design/behaviour_composition.yml +246 -0
- data/conf/design/build_rake_extraction.yml +57 -0
- data/conf/design/ci_pipeline.yml +100 -0
- data/conf/design/claude_code_configuration.yml +157 -0
- data/conf/design/compiler.yml +128 -0
- data/conf/design/comply.yml +153 -0
- data/conf/design/content_packs.yml +84 -0
- data/conf/design/desktop_integration.yml +289 -0
- data/conf/design/distribution.yml +216 -0
- data/conf/design/doctor.yml +184 -0
- data/conf/design/documentation.yml +152 -0
- data/conf/design/engine_architecture.yml +257 -0
- data/conf/design/error_handling.yml +103 -0
- data/conf/design/feature_flags.yml +142 -0
- data/conf/design/git_hooks.yml +165 -0
- data/conf/design/gui_plugins.yml +475 -0
- data/conf/design/i18n.yml +84 -0
- data/conf/design/integration_testing.yml +56 -0
- data/conf/design/licensing_system.yml +88 -0
- data/conf/design/lifecycle_management.yml +208 -0
- data/conf/design/mcp_integration.yml +207 -0
- data/conf/design/mcp_settings.yml +126 -0
- data/conf/design/migration.yml +56 -0
- data/conf/design/monitoring_observability.yml +194 -0
- data/conf/design/namespace_cleanup.yml +145 -0
- data/conf/design/plugin_test_segregation.yml +145 -0
- data/conf/design/policy_management.yml +229 -0
- data/conf/design/project_management.yml +183 -0
- data/conf/design/rai_mcp_asset_discovery.yml +164 -0
- data/conf/design/rai_mcp_server.yml +605 -0
- data/conf/design/release_management.yml +117 -0
- data/conf/design/retrofit.yml +199 -0
- data/conf/design/retrospective_analyzer.yml +79 -0
- data/conf/design/scope_hierarchy.yml +352 -0
- data/conf/design/security.yml +115 -0
- data/conf/design/session_retrospective.yml +85 -0
- data/conf/design/smart_ui_feedback.yml +89 -0
- data/conf/design/structured_logging.yml +148 -0
- data/conf/design/styles.yml +123 -0
- data/conf/design/test_peer_review.yml +89 -0
- data/conf/design/testing.yml +136 -0
- data/conf/design/threat_model.yml +108 -0
- data/conf/design/ui_framework.yml +111 -0
- data/conf/design/usage_optimization.yml +122 -0
- data/conf/design/version_management.yml +60 -0
- data/conf/design/workflow.yml +227 -0
- data/conf/mcp/server_defaults.yml +42 -0
- data/conf/mcp/trust.yml +21 -0
- data/conf/packaging/core.yml +12 -0
- data/conf/packaging/gtk4.yml +11 -0
- data/conf/packaging/qt6.yml +11 -0
- data/conf/policy/default_deny_list.yml +197 -0
- data/conf/review/cli-command-audit.yml +857 -0
- data/conf/review/design-docs.yml +1064 -0
- data/conf/review/design-questionnaire.yml +153 -0
- data/conf/review/questionnaire.yml +146 -0
- data/conf/review/rosett-ai-core.yml +2919 -0
- data/conf/schemas/ai_config_schema.json +73 -0
- data/conf/schemas/behaviour_schema.json +132 -0
- data/conf/schemas/compliance_rule_schema.json +63 -0
- data/conf/schemas/content_pack_manifest_schema.json +51 -0
- data/conf/schemas/design_schema.json +210 -0
- data/conf/schemas/engine_manifest_schema.json +144 -0
- data/conf/schemas/lockfile_schema.json +74 -0
- data/conf/schemas/mcp_server_schema.json +48 -0
- data/conf/schemas/packaging_schema.json +70 -0
- data/conf/schemas/policy_schema.json +85 -0
- data/conf/schemas/provenance_schema.json +84 -0
- data/conf/schemas/rai_config_schema.json +56 -0
- data/conf/schemas/rai_project_schema.json +20 -0
- data/conf/schemas/scope_hierarchy_schema.json +49 -0
- data/conf/schemas/target_schema.json +67 -0
- data/conf/schemas/tooling_schema.json +65 -0
- data/conf/schemas/workflow_schema.json +112 -0
- data/conf/targets/agents_md.yml +17 -0
- data/conf/targets/claude.yml +12 -0
- data/conf/tooling/tools.yml +58 -0
- data/dist/rosett-ai-mcp.service +48 -0
- data/dist/rosett-ai-mcp.yml.default +45 -0
- data/doc/AAIF_POSITIONING.md +58 -0
- data/doc/ADOPT.md +224 -0
- data/doc/AI_PROVENANCE.md +139 -0
- data/doc/ARCHITECTURE.md +920 -0
- data/doc/BEHAVIOUR.md +409 -0
- data/doc/BUILD.md +138 -0
- data/doc/CI_CD_RECIPES.md +171 -0
- data/doc/CLAUDE_SESSIONS_MOVED.md +16 -0
- data/doc/COMMAND_ANALYSIS.md +229 -0
- data/doc/CONFIGURATION.md +281 -0
- data/doc/DESIGN_AUDIT.md +235 -0
- data/doc/DESIGN_PEER_REVIEW.md +771 -0
- data/doc/DESKTOP.md +447 -0
- data/doc/ENGINES.md +567 -0
- data/doc/ENGINE_DEVELOPMENT_GUIDE.md +417 -0
- data/doc/FEATURE_AUDIT.md +218 -0
- data/doc/IMPLEMENTATION_PLAN.md +669 -0
- data/doc/INCIDENT_REPORT_2026-02-02.md +251 -0
- data/doc/MIGRATION_GUIDE.md +88 -0
- data/doc/PACKAGING.md +232 -0
- data/doc/PROJECT_DASHBOARD.md +153 -0
- data/doc/PULP_DEPLOYMENT.md +164 -0
- data/doc/QUALITY_FIX_SUMMARY.md +110 -0
- data/doc/QUICK_START.md +162 -0
- data/doc/REEK_CONFIGURATION.md +166 -0
- data/doc/REFERENCE.md +253 -0
- data/doc/REFERENCES.md +324 -0
- data/doc/SECURITY_REVIEW_CHECKLIST.md +72 -0
- data/doc/SESSION_2026-02-28_GTK4_HARDENING.md +359 -0
- data/doc/SETUP.md +202 -0
- data/doc/TEST_PEER_REVIEW.md +152 -0
- data/doc/THREAT_MODEL.md +230 -0
- data/doc/USAGE.md +545 -0
- data/doc/USER_MANUAL.md +585 -0
- data/doc/ai_test_review_checklist.md +110 -0
- data/doc/changes/2026-02-18-packaging-fpm.md +155 -0
- data/doc/changes/2026-02-19-testing-infrastructure.md +221 -0
- data/doc/changes/2026-02-20-security-implementation.md +281 -0
- data/doc/changes/2026-02-20-styles-implementation.md +220 -0
- data/doc/changes/2026-02-21-architecture-completion.md +95 -0
- data/doc/changes/2026-02-21-architecture-ui-layer.md +253 -0
- data/doc/changes/2026-02-21-cc-config-implementation.md +108 -0
- data/doc/changes/2026-02-21-ci-pipeline-implementation.md +214 -0
- data/doc/changes/2026-02-21-compiler-multi-target-pipeline.md +241 -0
- data/doc/changes/2026-02-21-config-design-show-commands.md +61 -0
- data/doc/changes/2026-02-21-design-implementation-overview.md +455 -0
- data/doc/changes/2026-02-21-lifecycle-management.md +196 -0
- data/doc/changes/2026-02-21-path-resolver.md +128 -0
- data/doc/changes/2026-02-24-ci-tmpdir-mutant-fetch.md +45 -0
- data/doc/changes/2026-03-01-ci-bundler-strategy.md +120 -0
- data/doc/changes/2026-03-20-security-hardening-phase2.md +163 -0
- data/doc/context/SESSION-HANDOFF.md +69 -0
- data/doc/context/ai-engine-usage-trends-2026.md +80 -0
- data/doc/context/plan-pluggable-engines.md +590 -0
- data/doc/decisions/001-flog-deferred.md +32 -0
- data/doc/decisions/002-path-resolution-strategy.md +158 -0
- data/doc/decisions/003-ui-adapter-selection.md +193 -0
- data/doc/decisions/004-design-document-validation.md +179 -0
- data/doc/decisions/005-package-splitting-strategy.md +200 -0
- data/doc/decisions/006-multi-engine-architecture.md +147 -0
- data/doc/decisions/007-engine-agnostic-pivot.md +219 -0
- data/doc/decisions/008-ci-bundler-strategy.md +129 -0
- data/doc/decisions/009-core-only-v1-release.md +60 -0
- data/doc/decisions/010-engine-debian-packaging.md +66 -0
- data/doc/decisions/011-context-aware-cli.md +71 -0
- data/doc/dependency_decisions.yml +247 -0
- data/doc/issues/001-wrapper-missing-environment-variables.md +197 -0
- data/doc/issues/002-embedded-ruby-wrong-prefix.md +217 -0
- data/doc/issues/003-smoke-test-false-positive.md +127 -0
- data/doc/issues/004-market-research-design-updates.md +109 -0
- data/doc/issues/005-compile-scope-coexistence.md +161 -0
- data/doc/locales/.gitkeep +0 -0
- data/doc/man/rai.1.ronn +505 -0
- data/doc/operations/packaging.md +133 -0
- data/doc/operations/rosett-ai-release.md +65 -0
- data/doc/reference/error-catalog.md +107 -0
- data/doc/reference/rosett-ai-technical-reference.pdf +0 -0
- data/doc/reference/src/Pictures/cover.jpg +0 -0
- data/doc/reference/src/Pictures/head1.jpg +0 -0
- data/doc/reference/src/Pictures/head2.jpg +0 -0
- data/doc/reference/src/Pictures/head3.jpg +0 -0
- data/doc/reference/src/Pictures/head4.jpg +0 -0
- data/doc/reference/src/Pictures/head5.jpg +0 -0
- data/doc/reference/src/Pictures/head6.jpg +0 -0
- data/doc/reference/src/Pictures/head7.jpg +0 -0
- data/doc/reference/src/Pictures/head8.jpg +0 -0
- data/doc/reference/src/StyleInd.ist +4 -0
- data/doc/reference/src/bibliography.bib +79 -0
- data/doc/reference/src/main.tex +1288 -0
- data/doc/reference/src/structure.tex +303 -0
- data/doc/rosett-ai-bookmarks.html +301 -0
- data/kitchen.yml +46 -0
- data/lib/rosett_ai/adopter/executor_resolver.rb +77 -0
- data/lib/rosett_ai/adopter/local_analysis_collector.rb +154 -0
- data/lib/rosett_ai/adopter/rule_adopter.rb +254 -0
- data/lib/rosett_ai/ai_config/config_compiler.rb +111 -0
- data/lib/rosett_ai/ai_config/context_window.rb +55 -0
- data/lib/rosett_ai/ai_config/cost_controls.rb +44 -0
- data/lib/rosett_ai/ai_config/fallback_chain.rb +64 -0
- data/lib/rosett_ai/ai_config/model_router.rb +121 -0
- data/lib/rosett_ai/ai_config/validator.rb +45 -0
- data/lib/rosett_ai/authorship/attribution_compiler.rb +99 -0
- data/lib/rosett_ai/authorship/disclosure_policy.rb +81 -0
- data/lib/rosett_ai/authorship/review_validator.rb +39 -0
- data/lib/rosett_ai/authorship/trailer_generator.rb +88 -0
- data/lib/rosett_ai/backup/compressor.rb +180 -0
- data/lib/rosett_ai/backup/destination.rb +91 -0
- data/lib/rosett_ai/behaviour/manager.rb +156 -0
- data/lib/rosett_ai/compiler/backend.rb +86 -0
- data/lib/rosett_ai/compiler/backends/agents_md_backend.rb +80 -0
- data/lib/rosett_ai/compiler/backends/claude_backend.rb +88 -0
- data/lib/rosett_ai/compiler/backends/generic_backend.rb +15 -0
- data/lib/rosett_ai/compiler/behaviour_compiler.rb +40 -0
- data/lib/rosett_ai/compiler/capability_checker.rb +104 -0
- data/lib/rosett_ai/compiler/compilation_pipeline.rb +361 -0
- data/lib/rosett_ai/compiler/compiled_output.rb +39 -0
- data/lib/rosett_ai/compiler/locale_compiler.rb +250 -0
- data/lib/rosett_ai/compiler/target_profile.rb +112 -0
- data/lib/rosett_ai/completion/generator.rb +101 -0
- data/lib/rosett_ai/completion/shells/bash_generator.rb +126 -0
- data/lib/rosett_ai/completion/shells/fish_generator.rb +78 -0
- data/lib/rosett_ai/completion/shells/zsh_generator.rb +126 -0
- data/lib/rosett_ai/comply/checkers/cra_checker.rb +102 -0
- data/lib/rosett_ai/comply/checkers/license_checker.rb +85 -0
- data/lib/rosett_ai/comply/checkers/spdx_header_checker.rb +98 -0
- data/lib/rosett_ai/comply/reporter.rb +113 -0
- data/lib/rosett_ai/comply/runner.rb +50 -0
- data/lib/rosett_ai/composition/circular_dependency_detector.rb +56 -0
- data/lib/rosett_ai/composition/composer.rb +158 -0
- data/lib/rosett_ai/composition/composition_result.rb +64 -0
- data/lib/rosett_ai/composition/conflict_detector.rb +53 -0
- data/lib/rosett_ai/composition/lockfile.rb +103 -0
- data/lib/rosett_ai/composition/merge_strategy.rb +131 -0
- data/lib/rosett_ai/composition/priority_sorter.rb +29 -0
- data/lib/rosett_ai/composition/scope_resolver.rb +55 -0
- data/lib/rosett_ai/config/compile_result.rb +37 -0
- data/lib/rosett_ai/config/compiler.rb +13 -0
- data/lib/rosett_ai/config/domain_transformer.rb +13 -0
- data/lib/rosett_ai/config/key_map.rb +13 -0
- data/lib/rosett_ai/config/masking_secret_resolver.rb +40 -0
- data/lib/rosett_ai/config/scope_router.rb +13 -0
- data/lib/rosett_ai/config/secret_resolver.rb +125 -0
- data/lib/rosett_ai/configuration.rb +119 -0
- data/lib/rosett_ai/content/content_client.rb +60 -0
- data/lib/rosett_ai/content/pack_installer.rb +117 -0
- data/lib/rosett_ai/content/pack_manifest.rb +50 -0
- data/lib/rosett_ai/content/pack_registry.rb +68 -0
- data/lib/rosett_ai/content_packs/manager.rb +50 -0
- data/lib/rosett_ai/dbus/compositor_detector.rb +77 -0
- data/lib/rosett_ai/dbus/focus_adapters/base.rb +59 -0
- data/lib/rosett_ai/dbus/focus_adapters/gnome_adapter.rb +172 -0
- data/lib/rosett_ai/dbus/focus_adapters/hyprland_adapter.rb +77 -0
- data/lib/rosett_ai/dbus/focus_adapters/i3_adapter.rb +65 -0
- data/lib/rosett_ai/dbus/focus_adapters/kwin_adapter.rb +103 -0
- data/lib/rosett_ai/dbus/focus_adapters/x11_adapter.rb +105 -0
- data/lib/rosett_ai/dbus/focus_monitor_interface.rb +103 -0
- data/lib/rosett_ai/dbus/manager_interface.rb +213 -0
- data/lib/rosett_ai/dbus/plugin_manager_interface.rb +169 -0
- data/lib/rosett_ai/dbus/rate_limiter.rb +89 -0
- data/lib/rosett_ai/dbus/service.rb +121 -0
- data/lib/rosett_ai/dbus/status_notifier_interface.rb +79 -0
- data/lib/rosett_ai/deprecation.rb +79 -0
- data/lib/rosett_ai/desktop/dbus_client.rb +259 -0
- data/lib/rosett_ai/desktop/gtk4_app.rb +371 -0
- data/lib/rosett_ai/desktop/gtk4_preferences.rb +331 -0
- data/lib/rosett_ai/desktop/gui_logger.rb +236 -0
- data/lib/rosett_ai/doctor/check.rb +92 -0
- data/lib/rosett_ai/doctor/checks/cache_health_check.rb +50 -0
- data/lib/rosett_ai/doctor/checks/dbus_availability_check.rb +39 -0
- data/lib/rosett_ai/doctor/checks/engine_detection_check.rb +46 -0
- data/lib/rosett_ai/doctor/checks/file_permission_check.rb +44 -0
- data/lib/rosett_ai/doctor/checks/gem_dependency_check.rb +55 -0
- data/lib/rosett_ai/doctor/checks/ruby_version_check.rb +50 -0
- data/lib/rosett_ai/doctor/checks/stale_config_nncc_check.rb +57 -0
- data/lib/rosett_ai/doctor/checks/stale_home_nncc_check.rb +59 -0
- data/lib/rosett_ai/doctor.rb +81 -0
- data/lib/rosett_ai/documentation/reference_compiler.rb +122 -0
- data/lib/rosett_ai/documentation/translator.rb +62 -0
- data/lib/rosett_ai/engines/base_config_compiler.rb +203 -0
- data/lib/rosett_ai/engines/detector.rb +63 -0
- data/lib/rosett_ai/engines/registry.rb +50 -0
- data/lib/rosett_ai/error_handler.rb +139 -0
- data/lib/rosett_ai/exit_codes.rb +76 -0
- data/lib/rosett_ai/feature_flags.rb +102 -0
- data/lib/rosett_ai/formatting.rb +33 -0
- data/lib/rosett_ai/gem_consistency_checker.rb +199 -0
- data/lib/rosett_ai/git_hooks/chain_detector.rb +86 -0
- data/lib/rosett_ai/git_hooks/installer.rb +175 -0
- data/lib/rosett_ai/git_hooks/script_generator.rb +125 -0
- data/lib/rosett_ai/gitlab/validators/supplementary_gitlab_ci_yaml_validator.rb +79 -0
- data/lib/rosett_ai/i18n/locale_resolver.rb +46 -0
- data/lib/rosett_ai/i18n/utf8_checker.rb +32 -0
- data/lib/rosett_ai/init/config_file_writer.rb +24 -0
- data/lib/rosett_ai/init/directory_builder.rb +38 -0
- data/lib/rosett_ai/init/file_copier.rb +95 -0
- data/lib/rosett_ai/init/global_initializer.rb +28 -0
- data/lib/rosett_ai/init/local_initializer.rb +27 -0
- data/lib/rosett_ai/init/mcp_registrar.rb +109 -0
- data/lib/rosett_ai/init/project_initializer.rb +38 -0
- data/lib/rosett_ai/licensing/license_key.rb +139 -0
- data/lib/rosett_ai/licensing/license_store.rb +64 -0
- data/lib/rosett_ai/licensing/license_validator.rb +60 -0
- data/lib/rosett_ai/licensing/tier.rb +42 -0
- data/lib/rosett_ai/mcp/admin/auditor.rb +88 -0
- data/lib/rosett_ai/mcp/admin/health_checker.rb +81 -0
- data/lib/rosett_ai/mcp/admin/registry.rb +100 -0
- data/lib/rosett_ai/mcp/admin/schema_validator.rb +63 -0
- data/lib/rosett_ai/mcp/enforcement/.gitkeep +0 -0
- data/lib/rosett_ai/mcp/enforcement/hook_generator.rb +197 -0
- data/lib/rosett_ai/mcp/enforcement/validator.rb +215 -0
- data/lib/rosett_ai/mcp/governance.rb +160 -0
- data/lib/rosett_ai/mcp/http_security_config.rb +158 -0
- data/lib/rosett_ai/mcp/instructions.rb +266 -0
- data/lib/rosett_ai/mcp/key_hasher.rb +66 -0
- data/lib/rosett_ai/mcp/keyfile.rb +221 -0
- data/lib/rosett_ai/mcp/middleware/authentication.rb +146 -0
- data/lib/rosett_ai/mcp/middleware/content_type.rb +56 -0
- data/lib/rosett_ai/mcp/middleware/cors.rb +83 -0
- data/lib/rosett_ai/mcp/middleware/origin_validation.rb +73 -0
- data/lib/rosett_ai/mcp/middleware/rate_limit.rb +106 -0
- data/lib/rosett_ai/mcp/middleware/request_size.rb +51 -0
- data/lib/rosett_ai/mcp/plugins.rb +143 -0
- data/lib/rosett_ai/mcp/prompts/compilation_prompt.rb +40 -0
- data/lib/rosett_ai/mcp/prompts/compliance_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/prompts/diagnostics_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/prompts/validation_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/resources/behaviour_resource.rb +127 -0
- data/lib/rosett_ai/mcp/resources/config_resource.rb +72 -0
- data/lib/rosett_ai/mcp/resources/design_resource.rb +58 -0
- data/lib/rosett_ai/mcp/resources/hooks_resource.rb +74 -0
- data/lib/rosett_ai/mcp/resources/provenance_resource.rb +51 -0
- data/lib/rosett_ai/mcp/resources/rules_resource.rb +60 -0
- data/lib/rosett_ai/mcp/resources/schema_resource.rb +72 -0
- data/lib/rosett_ai/mcp/response_helper.rb +46 -0
- data/lib/rosett_ai/mcp/security_logger.rb +60 -0
- data/lib/rosett_ai/mcp/server.rb +212 -0
- data/lib/rosett_ai/mcp/settings/server_installer.rb +112 -0
- data/lib/rosett_ai/mcp/settings/trust_manager.rb +142 -0
- data/lib/rosett_ai/mcp/tools/adopt_tool.rb +70 -0
- data/lib/rosett_ai/mcp/tools/backup_tool.rb +64 -0
- data/lib/rosett_ai/mcp/tools/behaviour_display_tool.rb +72 -0
- data/lib/rosett_ai/mcp/tools/behaviour_list_tool.rb +56 -0
- data/lib/rosett_ai/mcp/tools/behaviour_manage_tool.rb +114 -0
- data/lib/rosett_ai/mcp/tools/behaviour_show_tool.rb +62 -0
- data/lib/rosett_ai/mcp/tools/compile_status_tool.rb +122 -0
- data/lib/rosett_ai/mcp/tools/compile_tool.rb +191 -0
- data/lib/rosett_ai/mcp/tools/comply_tool.rb +79 -0
- data/lib/rosett_ai/mcp/tools/config_compile_tool.rb +71 -0
- data/lib/rosett_ai/mcp/tools/config_status_tool.rb +79 -0
- data/lib/rosett_ai/mcp/tools/content_tool.rb +78 -0
- data/lib/rosett_ai/mcp/tools/context_query_tool.rb +156 -0
- data/lib/rosett_ai/mcp/tools/design_list_tool.rb +57 -0
- data/lib/rosett_ai/mcp/tools/design_show_tool.rb +69 -0
- data/lib/rosett_ai/mcp/tools/doctor_tool.rb +62 -0
- data/lib/rosett_ai/mcp/tools/documentation_status_tool.rb +45 -0
- data/lib/rosett_ai/mcp/tools/engines_tool.rb +84 -0
- data/lib/rosett_ai/mcp/tools/hook_install_tool.rb +190 -0
- data/lib/rosett_ai/mcp/tools/hook_preview_tool.rb +173 -0
- data/lib/rosett_ai/mcp/tools/hooks_status_tool.rb +84 -0
- data/lib/rosett_ai/mcp/tools/init_tool.rb +87 -0
- data/lib/rosett_ai/mcp/tools/license_status_tool.rb +44 -0
- data/lib/rosett_ai/mcp/tools/project_tool.rb +117 -0
- data/lib/rosett_ai/mcp/tools/provenance_tool.rb +97 -0
- data/lib/rosett_ai/mcp/tools/provenance_write_tool.rb +40 -0
- data/lib/rosett_ai/mcp/tools/retrofit_tool.rb +81 -0
- data/lib/rosett_ai/mcp/tools/rule_search_tool.rb +163 -0
- data/lib/rosett_ai/mcp/tools/schema_get_tool.rb +94 -0
- data/lib/rosett_ai/mcp/tools/tooling_tool.rb +86 -0
- data/lib/rosett_ai/mcp/tools/validate_tool.rb +105 -0
- data/lib/rosett_ai/mcp/tools/workflow_execute_tool.rb +74 -0
- data/lib/rosett_ai/mcp/tools/workflow_tool.rb +78 -0
- data/lib/rosett_ai/migration/detector.rb +117 -0
- data/lib/rosett_ai/migration/nncc_config_migrator.rb +94 -0
- data/lib/rosett_ai/migration/nncc_project_migrator.rb +90 -0
- data/lib/rosett_ai/migration/xdg_migrator.rb +123 -0
- data/lib/rosett_ai/package_manager/apt.rb +108 -0
- data/lib/rosett_ai/package_manager/base.rb +68 -0
- data/lib/rosett_ai/package_manager/gem_backend.rb +90 -0
- data/lib/rosett_ai/packaging/variant_config.rb +92 -0
- data/lib/rosett_ai/path_resolver.rb +115 -0
- data/lib/rosett_ai/plugins/contract.rb +43 -0
- data/lib/rosett_ai/plugins/engine_contract.rb +60 -0
- data/lib/rosett_ai/plugins/gui_contract.rb +74 -0
- data/lib/rosett_ai/plugins/mcp_contract.rb +48 -0
- data/lib/rosett_ai/plugins/registry.rb +150 -0
- data/lib/rosett_ai/policy/auditor.rb +41 -0
- data/lib/rosett_ai/policy/deny_list.rb +71 -0
- data/lib/rosett_ai/policy/opt_out_scanner.rb +37 -0
- data/lib/rosett_ai/policy/policy_compiler.rb +84 -0
- data/lib/rosett_ai/policy/protected_files.rb +47 -0
- data/lib/rosett_ai/policy/tier_hierarchy.rb +48 -0
- data/lib/rosett_ai/policy/validator.rb +35 -0
- data/lib/rosett_ai/profiler.rb +79 -0
- data/lib/rosett_ai/project/drift_detector.rb +126 -0
- data/lib/rosett_ai/project/manager.rb +115 -0
- data/lib/rosett_ai/project/sync_manager.rb +138 -0
- data/lib/rosett_ai/project/template_applier.rb +105 -0
- data/lib/rosett_ai/project_context.rb +82 -0
- data/lib/rosett_ai/provenance/entry.rb +63 -0
- data/lib/rosett_ai/provenance/file_source.rb +32 -0
- data/lib/rosett_ai/provenance/source.rb +62 -0
- data/lib/rosett_ai/provenance/store.rb +153 -0
- data/lib/rosett_ai/provenance/tracker.rb +62 -0
- data/lib/rosett_ai/provenance/trailer_generator.rb +43 -0
- data/lib/rosett_ai/provenance/validator.rb +45 -0
- data/lib/rosett_ai/quorum/collector.rb +59 -0
- data/lib/rosett_ai/quorum/comparator.rb +81 -0
- data/lib/rosett_ai/quorum/dispatcher.rb +57 -0
- data/lib/rosett_ai/quorum/strategies/adopt.rb +56 -0
- data/lib/rosett_ai/rai_config.rb +107 -0
- data/lib/rosett_ai/retrofit/base_parser.rb +66 -0
- data/lib/rosett_ai/retrofit/engine.rb +171 -0
- data/lib/rosett_ai/retrofit/parsers/agents_md_parser.rb +50 -0
- data/lib/rosett_ai/retrofit/parsers/claude_parser.rb +69 -0
- data/lib/rosett_ai/retrofit/parsers/cursor_parser.rb +82 -0
- data/lib/rosett_ai/retrofit/round_trip_validator.rb +65 -0
- data/lib/rosett_ai/retrofit/scanner.rb +47 -0
- data/lib/rosett_ai/retrofit/secret_detector.rb +87 -0
- data/lib/rosett_ai/secrets_resolver.rb +71 -0
- data/lib/rosett_ai/smart_feedback/suggester.rb +83 -0
- data/lib/rosett_ai/smart_feedback/thor_middleware.rb +84 -0
- data/lib/rosett_ai/structured_logger.rb +110 -0
- data/lib/rosett_ai/telemetry/json_lines_writer.rb +50 -0
- data/lib/rosett_ai/telemetry/log_rotator.rb +67 -0
- data/lib/rosett_ai/telemetry/provider.rb +26 -0
- data/lib/rosett_ai/telemetry/reporter.rb +144 -0
- data/lib/rosett_ai/telemetry.rb +47 -0
- data/lib/rosett_ai/text_sanitizer.rb +62 -0
- data/lib/rosett_ai/thor/cli.rb +269 -0
- data/lib/rosett_ai/thor/tasks/adopt.rb +250 -0
- data/lib/rosett_ai/thor/tasks/backup.rb +420 -0
- data/lib/rosett_ai/thor/tasks/behaviour.rb +474 -0
- data/lib/rosett_ai/thor/tasks/build.rb +1162 -0
- data/lib/rosett_ai/thor/tasks/compile.rb +415 -0
- data/lib/rosett_ai/thor/tasks/completion.rb +123 -0
- data/lib/rosett_ai/thor/tasks/comply.rb +82 -0
- data/lib/rosett_ai/thor/tasks/config.rb +265 -0
- data/lib/rosett_ai/thor/tasks/content.rb +193 -0
- data/lib/rosett_ai/thor/tasks/dbus.rb +321 -0
- data/lib/rosett_ai/thor/tasks/design.rb +258 -0
- data/lib/rosett_ai/thor/tasks/desktop.rb +129 -0
- data/lib/rosett_ai/thor/tasks/doctor.rb +127 -0
- data/lib/rosett_ai/thor/tasks/documentation.rb +321 -0
- data/lib/rosett_ai/thor/tasks/engines.rb +167 -0
- data/lib/rosett_ai/thor/tasks/hooks.rb +219 -0
- data/lib/rosett_ai/thor/tasks/init.rb +259 -0
- data/lib/rosett_ai/thor/tasks/license.rb +120 -0
- data/lib/rosett_ai/thor/tasks/mcp.rb +535 -0
- data/lib/rosett_ai/thor/tasks/migrate.rb +121 -0
- data/lib/rosett_ai/thor/tasks/plugins.rb +157 -0
- data/lib/rosett_ai/thor/tasks/project.rb +260 -0
- data/lib/rosett_ai/thor/tasks/provenance.rb +195 -0
- data/lib/rosett_ai/thor/tasks/release.rb +314 -0
- data/lib/rosett_ai/thor/tasks/retrofit.rb +90 -0
- data/lib/rosett_ai/thor/tasks/tooling.rb +308 -0
- data/lib/rosett_ai/thor/tasks/validate.rb +108 -0
- data/lib/rosett_ai/thor/tasks/workflow.rb +196 -0
- data/lib/rosett_ai/tooling/ci_yaml_validator.rb +37 -0
- data/lib/rosett_ai/tooling/version_checker.rb +35 -0
- data/lib/rosett_ai/ui/accessible_tui.rb +61 -0
- data/lib/rosett_ai/ui/base.rb +46 -0
- data/lib/rosett_ai/ui/gtk4.rb +98 -0
- data/lib/rosett_ai/ui/kde.rb +40 -0
- data/lib/rosett_ai/ui/qt6.rb +40 -0
- data/lib/rosett_ai/ui/registry.rb +60 -0
- data/lib/rosett_ai/ui/tty_helper.rb +74 -0
- data/lib/rosett_ai/ui/tui.rb +59 -0
- data/lib/rosett_ai/validators/behaviour_validator.rb +20 -0
- data/lib/rosett_ai/validators/design_validator.rb +17 -0
- data/lib/rosett_ai/validators/schema_validator.rb +84 -0
- data/lib/rosett_ai/validators/tooling_validator.rb +17 -0
- data/lib/rosett_ai/version.rb +8 -0
- data/lib/rosett_ai/version_consistency_checker.rb +129 -0
- data/lib/rosett_ai/workflow/audit_log.rb +86 -0
- data/lib/rosett_ai/workflow/engine.rb +142 -0
- data/lib/rosett_ai/workflow/manager.rb +82 -0
- data/lib/rosett_ai/workflow/schema_validator.rb +71 -0
- data/lib/rosett_ai/workflow/step_runner.rb +61 -0
- data/lib/rosett_ai/workflow/steps/prompt_step.rb +62 -0
- data/lib/rosett_ai/workflow/steps/rai_step.rb +74 -0
- data/lib/rosett_ai/workflow/steps/shell_step.rb +53 -0
- data/lib/rosett_ai/yaml_loader.rb +78 -0
- data/lib/rosett_ai.rb +221 -0
- data/lib/rubocop/cop/rosett_ai/shell_interpolation.rb +54 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_const_get.rb +60 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_send.rb +50 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_yaml_load.rb +40 -0
- data/lib/rubocop/rosett_ai.rb +9 -0
- data/lib/scripts/generated/docker_hub_tags.rb +126 -0
- data/locales/.gitkeep +0 -0
- data/locales/ar.yml +579 -0
- data/locales/en.yml +571 -0
- data/locales/fr.yml +567 -0
- data/packaging/build-engine-deb.sh +81 -0
- data/packaging/scripts/postinst +17 -0
- data/packaging/scripts/postrm +19 -0
- data/packaging/scripts/prerm +10 -0
- data/packaging/wrapper.sh.template +38 -0
- data/rosett-ai.gemspec +63 -0
- data/rules/.gitkeep +0 -0
- data/scripts/publish/pulp_upload.sh +123 -0
- data/settings.json +29 -0
- data/share/applications/be.neatnerds.rosettai.desktop +29 -0
- data/share/dbus-1/interfaces/be.neatnerds.rosettai.xml +103 -0
- data/share/dbus-1/services/be.neatnerds.rosettai.service +3 -0
- data/share/templates/behaviour/criticalthinking.yml +69 -0
- metadata +810 -0
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
# Contributing to rosett-ai
|
|
2
|
+
|
|
3
|
+
This guide explains how to extend the Rosett-AI. Each section
|
|
4
|
+
covers a specific expansion pattern with the exact files to create or modify.
|
|
5
|
+
|
|
6
|
+
## Development Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://gitlab.neatnerds.be/neatnerds/NeatNerds-AI/rosett-ai.git
|
|
10
|
+
cd rosett-ai
|
|
11
|
+
bundle install
|
|
12
|
+
overcommit --install
|
|
13
|
+
overcommit --sign # trust the hook signatures
|
|
14
|
+
bundle exec rspec # run tests
|
|
15
|
+
bundle exec rubocop # run linter
|
|
16
|
+
bundle exec reek # run code smell detector
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Bundler Groups and Dependencies
|
|
20
|
+
|
|
21
|
+
The core Gemfile defines four groups:
|
|
22
|
+
|
|
23
|
+
| Group | Purpose | Included locally | Included in CI |
|
|
24
|
+
|-------|---------|:---:|:---:|
|
|
25
|
+
| `:default` | Core runtime (gemspec) | Yes | Yes |
|
|
26
|
+
| `:desktop` | GTK4/Adwaita desktop UI | Yes | No |
|
|
27
|
+
| `:build` | Package building (fpm) | Yes | Yes |
|
|
28
|
+
| `:development, :test` | Linters, test tools | Yes | Yes |
|
|
29
|
+
|
|
30
|
+
Engine gems are **not** in the core Gemfile. For cross-repo engine development,
|
|
31
|
+
use `Gemfile.dev` (gitignored):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
BUNDLE_GEMFILE=Gemfile.dev bundle install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This loads all `rosett-ai-engine-*` gems from sibling directories. In production,
|
|
38
|
+
engine gems are installed as separate `.deb` packages (see ADR-010).
|
|
39
|
+
|
|
40
|
+
The `:desktop` group is excluded in CI (`bundle config without 'desktop'`)
|
|
41
|
+
because it requires system libraries (`libgirepository1.0-dev`, `libgtk-4-dev`)
|
|
42
|
+
that are not in the CI Docker image. No CI job needs GTK4 gems.
|
|
43
|
+
|
|
44
|
+
If you are developing desktop features locally, install the system dependencies
|
|
45
|
+
first:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
sudo apt-get install -y libgirepository1.0-dev libgtk-4-dev
|
|
49
|
+
bundle install # includes :desktop group by default
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If you do not need desktop features, you can exclude them locally too:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
bundle config set --local without 'desktop'
|
|
56
|
+
bundle install
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Updating dependencies
|
|
60
|
+
|
|
61
|
+
`Gemfile.lock` is tracked in git (see ADR-008). CI runs with `frozen: true`,
|
|
62
|
+
meaning it will reject any mismatch between `Gemfile` and `Gemfile.lock`.
|
|
63
|
+
|
|
64
|
+
To update a dependency:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bundle update <gem-name> # updates the lockfile
|
|
68
|
+
bundle exec rspec # verify tests pass
|
|
69
|
+
bundle exec rubocop # verify no new offenses
|
|
70
|
+
git add Gemfile.lock
|
|
71
|
+
git commit -m "chore(deps): update <gem-name> to X.Y.Z"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
To update all dependencies at once:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
bundle update
|
|
78
|
+
bundle exec rspec && bundle exec rubocop
|
|
79
|
+
git add Gemfile.lock
|
|
80
|
+
git commit -m "chore(deps): update all dependencies"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Pre-commit Hooks (Overcommit)
|
|
84
|
+
|
|
85
|
+
Overcommit runs quality gates on every commit. The key hooks:
|
|
86
|
+
|
|
87
|
+
| Hook | Scope | What it checks |
|
|
88
|
+
|------|-------|----------------|
|
|
89
|
+
| `RubocopAll` | All files | Ruby style and lint offenses (full project scan) |
|
|
90
|
+
| `Reek` | Changed files | Code smell detection |
|
|
91
|
+
| `Flay` | Changed files | Structural code duplication (mass threshold: 16) |
|
|
92
|
+
| `YamlLint` | Changed files | YAML syntax |
|
|
93
|
+
| `Mdl` | Changed files | Markdown style |
|
|
94
|
+
| `BundlerAudit` | Gemfile.lock | Known gem CVEs |
|
|
95
|
+
| `RubyAudit` | Ruby stdlib | Known Ruby CVEs |
|
|
96
|
+
| `CheckVersions` | Project-wide | Ruby version consistency across files |
|
|
97
|
+
|
|
98
|
+
`RubocopAll` is a custom hook (`.git-hooks/pre_commit/rubocop_all.rb`) that
|
|
99
|
+
scans all project files, not just changed files. This ensures new rubocop cops
|
|
100
|
+
(from version updates) catch offenses everywhere, not just in the commit diff.
|
|
101
|
+
See ADR-008 for the rationale.
|
|
102
|
+
|
|
103
|
+
If a hook fails, fix the issue and commit again. To run hooks manually:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
bundle exec overcommit --run # run all pre-commit hooks
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Architecture Overview
|
|
110
|
+
|
|
111
|
+
raictl follows a layered architecture with clear extension points:
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
CLI Layer lib/rosett_ai/thor/tasks/*.rb Thor subcommands
|
|
115
|
+
Library Layer lib/rosett_ai/**/*.rb Domain logic
|
|
116
|
+
Engine Layer lib/rosett_ai/engines/<name>/ AI engine backends & adapters
|
|
117
|
+
Config Layer conf/**/*.yml YAML configurations
|
|
118
|
+
Schema Layer conf/schemas/*.json JSON Schema validation
|
|
119
|
+
UI Layer lib/rosett_ai/ui/ Pluggable display adapters
|
|
120
|
+
i18n Layer locales/*.yml Translation files
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Adding a New Translation (Locale)
|
|
126
|
+
|
|
127
|
+
raictl uses ruby-i18n with YAML source files.
|
|
128
|
+
|
|
129
|
+
### Create the locale file
|
|
130
|
+
|
|
131
|
+
Create `locales/<code>.yml` (e.g., `locales/de.yml`). Copy the structure from
|
|
132
|
+
`locales/en.yml` and translate every string value. The top-level key must be
|
|
133
|
+
the locale code:
|
|
134
|
+
|
|
135
|
+
```yaml
|
|
136
|
+
de:
|
|
137
|
+
rosett_ai:
|
|
138
|
+
meta:
|
|
139
|
+
direction: ltr
|
|
140
|
+
language_name: "German"
|
|
141
|
+
language_name_native: "Deutsch"
|
|
142
|
+
cli:
|
|
143
|
+
version: "rosett-ai Version %{version}"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Translation rules
|
|
147
|
+
|
|
148
|
+
- Preserve all interpolation variables (`%{version}`, `%{count}`, etc.)
|
|
149
|
+
exactly as they appear in en.yml. Changing variable names will cause
|
|
150
|
+
runtime errors.
|
|
151
|
+
- For RTL languages (Arabic, Hebrew), set `meta.direction: rtl`. The
|
|
152
|
+
`AccessibleTui` adapter reads this to set text direction.
|
|
153
|
+
- For languages with plural rules (Arabic has 6 forms), use the ruby-i18n
|
|
154
|
+
plural keys (`zero`, `one`, `two`, `few`, `many`, `other`). See
|
|
155
|
+
`locales/ar.yml` for an example.
|
|
156
|
+
|
|
157
|
+
### Compile and test
|
|
158
|
+
|
|
159
|
+
Compile locale files (optional, for distribution):
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
bin/raictl compile --locales
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
This generates gettext `.pot`/`.po` and Qt Linguist `.ts` files.
|
|
166
|
+
|
|
167
|
+
Test: Run `bin/raictl version --locale de` to verify.
|
|
168
|
+
|
|
169
|
+
### Files to modify
|
|
170
|
+
|
|
171
|
+
| File | Action |
|
|
172
|
+
|------|--------|
|
|
173
|
+
| `locales/<code>.yml` | Create (copy en.yml structure) |
|
|
174
|
+
|
|
175
|
+
No code changes required — the locale is auto-discovered from the `locales/`
|
|
176
|
+
directory at load time.
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Adding a New AI Engine
|
|
181
|
+
|
|
182
|
+
Engines live under `lib/rosett_ai/engines/<name>/` with optional components.
|
|
183
|
+
Each engine has a manifest declaring its capabilities and a backend for
|
|
184
|
+
compilation. See the Claude and Generic engines for reference.
|
|
185
|
+
|
|
186
|
+
### Create the engine gem
|
|
187
|
+
|
|
188
|
+
Each engine is a separate gem. Use `rosett-ai-engine-acme` as a reference:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
mkdir -p rosett-ai-engine-mistral/{lib/rosett_ai_engine/mistral,spec/rosett_ai_engine/mistral,conf}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Create the manifest
|
|
195
|
+
|
|
196
|
+
Create `conf/manifest.yml`:
|
|
197
|
+
|
|
198
|
+
```yaml
|
|
199
|
+
---
|
|
200
|
+
name: mistral
|
|
201
|
+
display_name: "Mistral AI"
|
|
202
|
+
version: 1.0.0
|
|
203
|
+
components:
|
|
204
|
+
backend: true
|
|
205
|
+
config_compiler: false
|
|
206
|
+
executor: false
|
|
207
|
+
detector: false
|
|
208
|
+
scaffolder: false
|
|
209
|
+
detection: {}
|
|
210
|
+
execution: {}
|
|
211
|
+
capabilities:
|
|
212
|
+
compile: true
|
|
213
|
+
config: false
|
|
214
|
+
adopt_api: false
|
|
215
|
+
settings_json: false
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Create the backend class
|
|
219
|
+
|
|
220
|
+
Create `lib/rosett_ai_engine/mistral/backend.rb`:
|
|
221
|
+
|
|
222
|
+
```ruby
|
|
223
|
+
# frozen_string_literal: true
|
|
224
|
+
|
|
225
|
+
module RosettAiEngine
|
|
226
|
+
module Mistral
|
|
227
|
+
class Backend < RosettAi::Compiler::Backend
|
|
228
|
+
MARKER_PREFIX = '<!-- rosett-ai-mistral-managed'
|
|
229
|
+
|
|
230
|
+
def render(data)
|
|
231
|
+
# Return a string representing the compiled output.
|
|
232
|
+
# See RosettAiEngine::Generic::Backend or
|
|
233
|
+
# RosettAiEngine::Claude::Backend for reference.
|
|
234
|
+
lines = []
|
|
235
|
+
lines << "#{generated_marker} -->"
|
|
236
|
+
# ... build your format
|
|
237
|
+
lines.join("\n") + "\n"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def generated_marker
|
|
241
|
+
MARKER_PREFIX
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Create the engine module and self-registration
|
|
249
|
+
|
|
250
|
+
Create `lib/rosett_ai_engine/mistral/engine.rb`:
|
|
251
|
+
|
|
252
|
+
```ruby
|
|
253
|
+
# frozen_string_literal: true
|
|
254
|
+
|
|
255
|
+
require 'rosett_ai'
|
|
256
|
+
require_relative 'version'
|
|
257
|
+
require_relative 'backend'
|
|
258
|
+
|
|
259
|
+
module RosettAiEngine
|
|
260
|
+
module Mistral
|
|
261
|
+
module Engine
|
|
262
|
+
include RosettAi::Plugins::EngineContract
|
|
263
|
+
|
|
264
|
+
class << self
|
|
265
|
+
def engine_name = 'mistral'
|
|
266
|
+
def display_name = 'Mistral AI'
|
|
267
|
+
def version = VERSION
|
|
268
|
+
def backend_class = RosettAiEngine::Mistral::Backend
|
|
269
|
+
def detector_class = nil
|
|
270
|
+
def executor_class = nil
|
|
271
|
+
def config_compiler_class = nil
|
|
272
|
+
|
|
273
|
+
def manifest_path
|
|
274
|
+
Pathname.new(__dir__).join('..', '..', '..', 'conf', 'manifest.yml').expand_path
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Create `lib/rosett_ai_engine/mistral/register.rb`:
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
# frozen_string_literal: true
|
|
286
|
+
|
|
287
|
+
require_relative 'engine'
|
|
288
|
+
RosettAi::Plugins::Registry.register(:engine, 'mistral', RosettAiEngine::Mistral::Engine)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
The engine self-registers via `Gem.find_files('rosett_ai_engine/*/register.rb')`.
|
|
292
|
+
No core code changes needed — install the gem, and it appears automatically.
|
|
293
|
+
|
|
294
|
+
### CLI executor type
|
|
295
|
+
|
|
296
|
+
Some engines use CLI subprocess execution (`api_type: cli`) instead of an
|
|
297
|
+
HTTP API. These engines spawn a child process via `Open3.capture3` and
|
|
298
|
+
communicate through stdin/stdout.
|
|
299
|
+
|
|
300
|
+
In the engine manifest, set:
|
|
301
|
+
|
|
302
|
+
```yaml
|
|
303
|
+
execution:
|
|
304
|
+
api_type: cli
|
|
305
|
+
binary: mistral-cli
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Then create an executor at `lib/rosett_ai_engine/mistral/executor.rb` that
|
|
309
|
+
implements `#analyze(prompt)` using `Open3.capture3`. See
|
|
310
|
+
`rosett-ai-engine-goose` or `rosett-ai-engine-aider` for reference
|
|
311
|
+
for reference.
|
|
312
|
+
|
|
313
|
+
### Detector patterns
|
|
314
|
+
|
|
315
|
+
Engines can provide automatic detection via a detector class. The detector
|
|
316
|
+
checks for CLI binaries, config directories, or environment variables:
|
|
317
|
+
|
|
318
|
+
```ruby
|
|
319
|
+
module RosettAi
|
|
320
|
+
module Engines
|
|
321
|
+
module Mistral
|
|
322
|
+
class Detector < RosettAi::Engines::Detector
|
|
323
|
+
private
|
|
324
|
+
|
|
325
|
+
def detect_binary
|
|
326
|
+
system('which', 'mistral-cli', out: File::NULL, err: File::NULL)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def detect_config
|
|
330
|
+
File.directory?(File.expand_path('~/.mistral'))
|
|
331
|
+
end
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### Add tests and use
|
|
339
|
+
|
|
340
|
+
Add tests at `spec/rosett_ai/engines/mistral/backend_spec.rb`, then use
|
|
341
|
+
it with `bin/raictl compile --engine mistral`.
|
|
342
|
+
|
|
343
|
+
You can set your new engine as the default by editing `~/.config/rosett-ai/config.yml`:
|
|
344
|
+
|
|
345
|
+
```yaml
|
|
346
|
+
default_engine: mistral
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Files to modify
|
|
350
|
+
|
|
351
|
+
| File | Action |
|
|
352
|
+
|------|--------|
|
|
353
|
+
| `conf/engines/<name>/manifest.yml` | Create |
|
|
354
|
+
| `conf/engines/<name>/target.yml` | Create |
|
|
355
|
+
| `lib/rosett_ai/engines/<name>/backend.rb` | Create |
|
|
356
|
+
| `lib/rosett_ai/engines/registry.rb` | Add to `ENGINES` hash |
|
|
357
|
+
| `lib/rosett_ai/compiler/backend.rb` | Add to `BACKENDS` hash |
|
|
358
|
+
| `spec/rosett_ai/engines/<name>/backend_spec.rb` | Create |
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Adding a New Configuration Section (Claude Code Scope)
|
|
363
|
+
|
|
364
|
+
Claude Code settings are compiled from YAML scopes in `conf/engines/claude/config/`.
|
|
365
|
+
|
|
366
|
+
### Edit or create scope files
|
|
367
|
+
|
|
368
|
+
Edit the scope file (e.g., `conf/engines/claude/config/managed.yml`) to add new
|
|
369
|
+
configuration keys. The schema at `conf/engines/claude/schemas/config_schema.json`
|
|
370
|
+
defines which keys are valid per scope.
|
|
371
|
+
|
|
372
|
+
To add an entirely new scope, create `conf/engines/claude/config/<scope>.yml` and
|
|
373
|
+
register it in `lib/rosett_ai/engines/claude/scope_router.rb`.
|
|
374
|
+
|
|
375
|
+
### Key mappings and domains
|
|
376
|
+
|
|
377
|
+
- For new key mappings (snake\_case YAML to camelCase JSON), update
|
|
378
|
+
`lib/rosett_ai/engines/claude/key_map.rb` to add the mapping entry.
|
|
379
|
+
- For new domains (like `mcp`, `api`), update
|
|
380
|
+
`lib/rosett_ai/engines/claude/domain_transformer.rb` to handle transformation rules.
|
|
381
|
+
|
|
382
|
+
### Test
|
|
383
|
+
|
|
384
|
+
Run `bin/raictl config compile --simulate --verbose` to verify.
|
|
385
|
+
|
|
386
|
+
### Files to modify
|
|
387
|
+
|
|
388
|
+
| File | Action |
|
|
389
|
+
|------|--------|
|
|
390
|
+
| `conf/engines/claude/config/<scope>.yml` | Edit or create |
|
|
391
|
+
| `conf/engines/claude/schemas/config_schema.json` | Extend schema |
|
|
392
|
+
| `lib/rosett_ai/engines/claude/key_map.rb` | Add key mapping (if new keys) |
|
|
393
|
+
| `lib/rosett_ai/engines/claude/scope_router.rb` | Add scope route (if new scope) |
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## Adding a New CLI Subcommand
|
|
398
|
+
|
|
399
|
+
### Create the task file
|
|
400
|
+
|
|
401
|
+
Create `lib/rosett_ai/thor/tasks/<name>.rb`:
|
|
402
|
+
|
|
403
|
+
```ruby
|
|
404
|
+
# frozen_string_literal: true
|
|
405
|
+
|
|
406
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
407
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
408
|
+
|
|
409
|
+
require 'thor'
|
|
410
|
+
require 'rainbow'
|
|
411
|
+
|
|
412
|
+
module RosettAi
|
|
413
|
+
module Thor
|
|
414
|
+
module Tasks
|
|
415
|
+
class Example < ::Thor
|
|
416
|
+
desc 'execute', 'Run the example command'
|
|
417
|
+
def execute
|
|
418
|
+
puts t('success')
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
private
|
|
422
|
+
|
|
423
|
+
def t(key, **)
|
|
424
|
+
::I18n.t("rosett-ai.cli.example.#{key}", **)
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Register and configure
|
|
433
|
+
|
|
434
|
+
Register the subcommand in `lib/rosett_ai/thor/cli.rb`:
|
|
435
|
+
|
|
436
|
+
```ruby
|
|
437
|
+
desc 'example SUBCOMMAND', 'Example commands'
|
|
438
|
+
subcommand 'example', RosettAi::Thor::Tasks::Example
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Add the error class in `lib/rosett_ai.rb`:
|
|
442
|
+
|
|
443
|
+
```ruby
|
|
444
|
+
class ExampleError < Error; end
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
### i18n, tests, and documentation
|
|
448
|
+
|
|
449
|
+
- Add i18n strings to `locales/en.yml` and `locales/fr.yml` under
|
|
450
|
+
`rosett-ai.cli.example.*`.
|
|
451
|
+
- Add reek exclusions in `.reek.yml` — at minimum add the class to
|
|
452
|
+
`DuplicateMethodCall` if it uses `puts`/`Rainbow` for output.
|
|
453
|
+
- Add tests at `spec/rosett_ai/thor/tasks/example_spec.rb`.
|
|
454
|
+
- Update `CLAUDE.md` (CLI Usage section) and `doc/man/rai.1.ronn`
|
|
455
|
+
(COMMANDS section).
|
|
456
|
+
|
|
457
|
+
### Files to modify
|
|
458
|
+
|
|
459
|
+
| File | Action |
|
|
460
|
+
|------|--------|
|
|
461
|
+
| `lib/rosett_ai/thor/tasks/<name>.rb` | Create |
|
|
462
|
+
| `lib/rosett_ai/thor/cli.rb` | Register subcommand |
|
|
463
|
+
| `lib/rosett_ai.rb` | Add error class |
|
|
464
|
+
| `locales/en.yml` | Add i18n strings |
|
|
465
|
+
| `locales/fr.yml` | Add i18n strings |
|
|
466
|
+
| `.reek.yml` | Add exclusions |
|
|
467
|
+
| `spec/rosett_ai/thor/tasks/<name>_spec.rb` | Create |
|
|
468
|
+
| `CLAUDE.md` | Document command |
|
|
469
|
+
| `doc/man/rai.1.ronn` | Document command |
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## Adding a New Design Document
|
|
474
|
+
|
|
475
|
+
Design documents define implementation standards in `conf/design/`.
|
|
476
|
+
|
|
477
|
+
### Create the document
|
|
478
|
+
|
|
479
|
+
Create `conf/design/<name>.yml` with the required fields:
|
|
480
|
+
|
|
481
|
+
```yaml
|
|
482
|
+
name: my_feature
|
|
483
|
+
domain: core
|
|
484
|
+
version: 0.1.0
|
|
485
|
+
status: draft
|
|
486
|
+
priority: 5
|
|
487
|
+
author: your_name
|
|
488
|
+
created_at: "2026-01-01"
|
|
489
|
+
modified_at: "2026-01-01"
|
|
490
|
+
modified_by: your_name
|
|
491
|
+
depends_on: []
|
|
492
|
+
intent: |
|
|
493
|
+
Why this exists and what problem it solves.
|
|
494
|
+
constraints:
|
|
495
|
+
- Hard boundary that must not be crossed
|
|
496
|
+
acceptance_criteria:
|
|
497
|
+
- Testable statement defining done
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
Valid domains: `core`, `ui`, `security`, `testing`, `styles`, `i18n`,
|
|
501
|
+
`accessibility`, `licensing`, `ci`, `compiler`, `release`, `documentation`,
|
|
502
|
+
`operations`.
|
|
503
|
+
|
|
504
|
+
### Validate and approve
|
|
505
|
+
|
|
506
|
+
Run `bin/raictl design validate my_feature` to check the document against
|
|
507
|
+
the schema. If a new domain is needed, update `conf/schemas/design_schema.json`
|
|
508
|
+
to add it to the `domain` enum. Set status to `approved` once reviewed.
|
|
509
|
+
|
|
510
|
+
### Files to modify
|
|
511
|
+
|
|
512
|
+
| File | Action |
|
|
513
|
+
|------|--------|
|
|
514
|
+
| `conf/design/<name>.yml` | Create |
|
|
515
|
+
| `conf/schemas/design_schema.json` | Extend domain enum (if new domain) |
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Adding a New UI Adapter
|
|
520
|
+
|
|
521
|
+
The UI layer uses a registry pattern. TUI is the default; GUI adapters are
|
|
522
|
+
optional.
|
|
523
|
+
|
|
524
|
+
### Create the adapter
|
|
525
|
+
|
|
526
|
+
Create `lib/rosett_ai/ui/<name>.rb`:
|
|
527
|
+
|
|
528
|
+
```ruby
|
|
529
|
+
# frozen_string_literal: true
|
|
530
|
+
|
|
531
|
+
module RosettAi
|
|
532
|
+
module Ui
|
|
533
|
+
class MyAdapter < Base
|
|
534
|
+
def render(content)
|
|
535
|
+
# Render content string to the user
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def display_table(headers:, rows:, title: nil)
|
|
539
|
+
# Display tabular data
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def prompt_user(message, choices: [])
|
|
543
|
+
# Interactive prompt
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def show_spinner(message)
|
|
547
|
+
# Show spinner, yield, return result
|
|
548
|
+
yield
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
def announce(message, priority: :polite)
|
|
552
|
+
# Accessibility announcement
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### Register and test
|
|
560
|
+
|
|
561
|
+
Register in `lib/rosett_ai/ui/registry.rb`:
|
|
562
|
+
|
|
563
|
+
```ruby
|
|
564
|
+
register('myadapter', RosettAi::Ui::MyAdapter)
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
Add the `--ui` enum value in `lib/rosett_ai/thor/cli.rb`.
|
|
568
|
+
|
|
569
|
+
Add tests using the shared examples at
|
|
570
|
+
`spec/support/shared_examples/ui_implementation.rb`:
|
|
571
|
+
|
|
572
|
+
```ruby
|
|
573
|
+
RSpec.describe RosettAi::Ui::MyAdapter do
|
|
574
|
+
it_behaves_like 'a UI implementation'
|
|
575
|
+
end
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
If this adapter is a separate .deb package (like `rosett-ai-gtk4`), create a
|
|
579
|
+
packaging variant at `conf/packaging/<name>.yml`.
|
|
580
|
+
|
|
581
|
+
### Files to modify
|
|
582
|
+
|
|
583
|
+
| File | Action |
|
|
584
|
+
|------|--------|
|
|
585
|
+
| `lib/rosett_ai/ui/<name>.rb` | Create |
|
|
586
|
+
| `lib/rosett_ai/ui/registry.rb` | Register adapter |
|
|
587
|
+
| `lib/rosett_ai/thor/cli.rb` | Add to `--ui` enum |
|
|
588
|
+
| `spec/rosett_ai/ui/<name>_spec.rb` | Create |
|
|
589
|
+
| `conf/packaging/<name>.yml` | Create (if separate package) |
|
|
590
|
+
|
|
591
|
+
---
|
|
592
|
+
|
|
593
|
+
## Adding a New CI Job
|
|
594
|
+
|
|
595
|
+
CI jobs live in `.gitlab-ci-files/<stage>/` and are included from
|
|
596
|
+
`.gitlab-ci.yml`.
|
|
597
|
+
|
|
598
|
+
### Create the job file
|
|
599
|
+
|
|
600
|
+
Create `.gitlab-ci-files/<stage>/<name>.yml`:
|
|
601
|
+
|
|
602
|
+
```yaml
|
|
603
|
+
my_job:
|
|
604
|
+
stage: code_quality
|
|
605
|
+
extends:
|
|
606
|
+
- .ruby_base
|
|
607
|
+
script:
|
|
608
|
+
- echo "Running my check"
|
|
609
|
+
rules:
|
|
610
|
+
- if: $CI_MERGE_REQUEST_IID
|
|
611
|
+
when: on_success
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
Available stages: `validate`, `code_quality`, `security_scan`, `test`, `build`.
|
|
615
|
+
Stages are defined in `.gitlab-ci-files/global/stages.yml`.
|
|
616
|
+
|
|
617
|
+
### Include the job
|
|
618
|
+
|
|
619
|
+
Add the include to `.gitlab-ci.yml`:
|
|
620
|
+
|
|
621
|
+
```yaml
|
|
622
|
+
- local: '.gitlab-ci-files/<stage>/<name>.yml'
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
---
|
|
626
|
+
|
|
627
|
+
## Security Rules
|
|
628
|
+
|
|
629
|
+
All contributions must follow these rules (enforced by CI):
|
|
630
|
+
|
|
631
|
+
- **YAML.safe\_load only** — never `YAML.load`
|
|
632
|
+
- **Array-form system()** — never string interpolation in shell commands
|
|
633
|
+
- **File writes to whitelisted directories only**
|
|
634
|
+
- **Secrets: 0600 permissions, never logged**
|
|
635
|
+
- **All external input validated before use**
|
|
636
|
+
- **SPDX headers** on every Ruby source file:
|
|
637
|
+
`# SPDX-License-Identifier: GPL-3.0-only`
|
|
638
|
+
|
|
639
|
+
## Code Quality Gates
|
|
640
|
+
|
|
641
|
+
Every commit must pass:
|
|
642
|
+
|
|
643
|
+
- `bundle exec rspec` — all tests green
|
|
644
|
+
- `bundle exec rubocop` — zero offenses
|
|
645
|
+
- `bundle exec reek` — zero warnings (or excluded in `.reek.yml` with justification)
|
|
646
|
+
- `bundle exec bundler-audit check` — no known CVEs
|
|
647
|
+
- `bundle exec ruby-audit check` — no Ruby advisory violations
|
|
648
|
+
- Overcommit pre-commit hooks (YAML lint, trailing whitespace, JSON syntax, etc.)
|
|
649
|
+
|
|
650
|
+
## Branch Naming
|
|
651
|
+
|
|
652
|
+
All branches must follow the pattern `<type>/<id>-<subject>`:
|
|
653
|
+
|
|
654
|
+
- **type** --- a [Conventional Commits](https://www.conventionalcommits.org/)
|
|
655
|
+
type: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`,
|
|
656
|
+
`ci`, `build`, `revert`
|
|
657
|
+
- **id** --- the OpenProject work package number (omit if no WP exists)
|
|
658
|
+
- **subject** --- short kebab-case description
|
|
659
|
+
|
|
660
|
+
Examples:
|
|
661
|
+
|
|
662
|
+
```text
|
|
663
|
+
feat/857-belspo-registration
|
|
664
|
+
fix/712-compile-scope-bug
|
|
665
|
+
docs/1286-security-md
|
|
666
|
+
chore/update-deps
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
## Conventional Commits
|
|
670
|
+
|
|
671
|
+
All commit messages must follow
|
|
672
|
+
[Conventional Commits](https://www.conventionalcommits.org/) format:
|
|
673
|
+
|
|
674
|
+
```text
|
|
675
|
+
type(scope): description
|
|
676
|
+
|
|
677
|
+
Optional body explaining *why*, not *what*.
|
|
678
|
+
|
|
679
|
+
OP#<work-package-id>
|
|
680
|
+
|
|
681
|
+
Co-Authored-By: ... (if applicable)
|
|
682
|
+
Signed-off-by: ... (if applicable)
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
Valid types match the branch naming types above. The scope is optional
|
|
686
|
+
but encouraged (e.g. `fix(compile):`, `docs(security):`). The
|
|
687
|
+
`OP#<id>` trailer is injected automatically by the overcommit
|
|
688
|
+
`CommitMsg` hook when the branch follows the naming convention.
|
|
689
|
+
|
|
690
|
+
## AI Disclosure
|
|
691
|
+
|
|
692
|
+
When AI tools assist in writing code or documentation, contributors
|
|
693
|
+
must disclose the assistance:
|
|
694
|
+
|
|
695
|
+
1. **Co-Authored-By trailer** --- add to the commit message:
|
|
696
|
+
|
|
697
|
+
```text
|
|
698
|
+
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
Replace the model name and version with the actual tool used. This
|
|
702
|
+
trailer is required for any commit where AI generated or
|
|
703
|
+
substantially revised the content.
|
|
704
|
+
|
|
705
|
+
2. **Provenance file** --- for NeatNerds maintainers, run
|
|
706
|
+
`raictl provenance add` after each AI-assisted commit to append
|
|
707
|
+
an entry to `.ai-provenance.yml`. External contributors are not
|
|
708
|
+
required to update this file.
|
|
709
|
+
|
|
710
|
+
Contributions generated entirely by AI without human review will not
|
|
711
|
+
be accepted. The human contributor remains responsible for
|
|
712
|
+
correctness, security, and license compliance of all submitted code.
|
|
713
|
+
|
|
714
|
+
## Developer Certificate of Origin (DCO)
|
|
715
|
+
|
|
716
|
+
External contributors must sign off their commits to certify they
|
|
717
|
+
have the right to submit the work under the project's license:
|
|
718
|
+
|
|
719
|
+
```text
|
|
720
|
+
Signed-off-by: Your Name <your-email@example.com>
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
Use `git commit --signoff` (or `-s`) to add this trailer
|
|
724
|
+
automatically. By signing off, you agree to the
|
|
725
|
+
[Developer Certificate of Origin](https://developercertificate.org/)
|
|
726
|
+
(version 1.1).
|
|
727
|
+
|
|
728
|
+
NeatNerds maintainers are covered by their employment or contractor
|
|
729
|
+
agreement and do not need to sign off individually.
|
|
730
|
+
|
|
731
|
+
## License
|
|
732
|
+
|
|
733
|
+
raictl is licensed under GPL-3.0-only. All contributions must be compatible
|
|
734
|
+
with this license.
|