rosett-ai 1.3.3 → 1.5.10
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 +4 -4
- data/CHANGELOG.md +413 -22
- data/README.md +56 -42
- data/bin/raictl +13 -0
- data/conf/adopt_redactions.yml +2 -0
- data/conf/compliance/cra_rules.yml +2 -0
- data/conf/compliance/license_rules.yml +2 -0
- data/conf/mcp/server_defaults.yml +2 -0
- data/conf/mcp/trust.yml +1 -0
- data/conf/packaging/core.yml +2 -0
- data/conf/packaging/gtk4.yml +2 -0
- data/conf/packaging/qt6.yml +2 -0
- data/conf/policy/default_deny_list.yml +2 -0
- data/conf/review/cli-command-audit.yml +2 -0
- data/conf/review/design-docs.yml +2 -0
- data/conf/review/design-questionnaire.yml +2 -0
- data/conf/review/questionnaire.yml +2 -0
- data/conf/review/rosett-ai-core.yml +2 -0
- data/conf/schemas/ai_config_schema.json +14 -2
- data/conf/schemas/autoqueue.schema.json +153 -0
- data/conf/schemas/behaviour_schema.json +31 -7
- data/conf/schemas/compliance_rule_schema.json +17 -4
- data/conf/schemas/content_pack_manifest_schema.json +23 -4
- data/conf/schemas/design_schema.json +177 -42
- data/conf/schemas/engine_manifest_schema.json +22 -5
- data/conf/schemas/lockfile_schema.json +26 -4
- data/conf/schemas/mcp_server_schema.json +50 -9
- data/conf/schemas/packaging_schema.json +23 -5
- data/conf/schemas/policy_schema.json +35 -9
- data/conf/schemas/provenance_schema.json +33 -5
- data/conf/schemas/rai_config_schema.json +6 -2
- data/conf/schemas/rai_project_schema.json +8 -2
- data/conf/schemas/scope_hierarchy_schema.json +22 -5
- data/conf/schemas/target_schema.json +33 -6
- data/conf/schemas/tooling_schema.json +53 -12
- data/conf/schemas/workflow_schema.json +39 -9
- data/conf/targets/agents_md.yml +1 -0
- data/conf/targets/claude.yml +2 -0
- data/conf/tooling/tools.yml +2 -0
- data/lib/rosett_ai/adopter/local_analysis_collector.rb +5 -0
- data/lib/rosett_ai/adopter/rule_adopter.rb +40 -0
- data/lib/rosett_ai/ai_config/context_window.rb +3 -0
- data/lib/rosett_ai/ai_config/cost_controls.rb +1 -0
- data/lib/rosett_ai/ai_config/fallback_chain.rb +1 -0
- data/lib/rosett_ai/ai_config/model_router.rb +1 -0
- data/lib/rosett_ai/ai_config/validator.rb +2 -0
- data/lib/rosett_ai/authorship/attribution_compiler.rb +1 -0
- data/lib/rosett_ai/authorship/disclosure_policy.rb +2 -0
- data/lib/rosett_ai/authorship/review_validator.rb +1 -0
- data/lib/rosett_ai/authorship/trailer_generator.rb +1 -0
- data/lib/rosett_ai/backup/compressor.rb +3 -0
- data/lib/rosett_ai/backup/destination.rb +1 -0
- data/lib/rosett_ai/behaviour/manager.rb +1 -0
- data/lib/rosett_ai/compiler/backend.rb +3 -0
- data/lib/rosett_ai/compiler/backends/agents_md_backend.rb +1 -0
- data/lib/rosett_ai/compiler/backends/claude_backend.rb +1 -0
- data/lib/rosett_ai/compiler/behaviour_compiler.rb +1 -0
- data/lib/rosett_ai/compiler/compilation_pipeline.rb +1 -7
- data/lib/rosett_ai/compiler/locale_compiler.rb +2 -0
- data/lib/rosett_ai/compiler/target_profile.rb +11 -0
- data/lib/rosett_ai/completion/generator.rb +2 -0
- data/lib/rosett_ai/completion/shells/zsh_generator.rb +1 -0
- data/lib/rosett_ai/comply/checkers/cra_checker.rb +1 -0
- data/lib/rosett_ai/comply/checkers/license_checker.rb +2 -0
- data/lib/rosett_ai/comply/checkers/spdx_header_checker.rb +4 -0
- data/lib/rosett_ai/comply/runner.rb +2 -0
- data/lib/rosett_ai/composition/composer.rb +1 -0
- data/lib/rosett_ai/composition/lockfile.rb +1 -0
- data/lib/rosett_ai/composition/merge_strategy.rb +1 -0
- data/lib/rosett_ai/config/masking_secret_resolver.rb +9 -0
- data/lib/rosett_ai/config/secret_resolver.rb +4 -0
- data/lib/rosett_ai/configuration.rb +4 -0
- data/lib/rosett_ai/content/content_client.rb +15 -0
- data/lib/rosett_ai/content/pack_installer.rb +1 -0
- data/lib/rosett_ai/content/pack_manifest.rb +21 -0
- data/lib/rosett_ai/content_packs/manager.rb +1 -0
- data/lib/rosett_ai/dbus/compositor_detector.rb +2 -0
- data/lib/rosett_ai/dbus/focus_adapters/base.rb +1 -0
- data/lib/rosett_ai/dbus/focus_adapters/gnome_adapter.rb +5 -0
- data/lib/rosett_ai/dbus/focus_adapters/hyprland_adapter.rb +4 -0
- data/lib/rosett_ai/dbus/focus_adapters/i3_adapter.rb +4 -0
- data/lib/rosett_ai/dbus/focus_adapters/kwin_adapter.rb +4 -0
- data/lib/rosett_ai/dbus/focus_adapters/x11_adapter.rb +4 -0
- data/lib/rosett_ai/dbus/focus_monitor_interface.rb +1 -0
- data/lib/rosett_ai/dbus/manager_interface.rb +1 -0
- data/lib/rosett_ai/dbus/plugin_manager_interface.rb +2 -0
- data/lib/rosett_ai/dbus/rate_limiter.rb +1 -0
- data/lib/rosett_ai/dbus/service.rb +3 -0
- data/lib/rosett_ai/dbus/status_notifier_interface.rb +14 -0
- data/lib/rosett_ai/desktop/dbus_client.rb +6 -0
- data/lib/rosett_ai/desktop/gtk4_app.rb +3 -0
- data/lib/rosett_ai/desktop/gtk4_preferences.rb +1 -0
- data/lib/rosett_ai/desktop/gui_logger.rb +2 -0
- data/lib/rosett_ai/doctor/check.rb +1 -1
- data/lib/rosett_ai/doctor/checks/cache_health_check.rb +1 -0
- data/lib/rosett_ai/doctor.rb +1 -0
- data/lib/rosett_ai/documentation/reference_compiler.rb +9 -0
- data/lib/rosett_ai/documentation/translator.rb +8 -0
- data/lib/rosett_ai/engines/base_config_compiler.rb +71 -1
- data/lib/rosett_ai/engines/detector.rb +5 -0
- data/lib/rosett_ai/engines/registry.rb +7 -0
- data/lib/rosett_ai/exit_codes.rb +6 -0
- data/lib/rosett_ai/formatting.rb +1 -0
- data/lib/rosett_ai/gem_consistency_checker.rb +6 -0
- data/lib/rosett_ai/git_hooks/chain_detector.rb +1 -0
- data/lib/rosett_ai/git_hooks/installer.rb +4 -0
- data/lib/rosett_ai/git_hooks/script_generator.rb +2 -0
- data/lib/rosett_ai/gitlab/validators/supplementary_gitlab_ci_yaml_validator.rb +6 -0
- data/lib/rosett_ai/i18n/utf8_checker.rb +1 -0
- data/lib/rosett_ai/init/config_file_writer.rb +4 -0
- data/lib/rosett_ai/init/directory_builder.rb +15 -0
- data/lib/rosett_ai/init/file_copier.rb +51 -0
- data/lib/rosett_ai/init/mcp_registrar.rb +1 -0
- data/lib/rosett_ai/init/project_initializer.rb +1 -0
- data/lib/rosett_ai/licensing/license_key.rb +4 -0
- data/lib/rosett_ai/licensing/license_store.rb +11 -0
- data/lib/rosett_ai/licensing/tier.rb +9 -0
- data/lib/rosett_ai/mcp/admin/auditor.rb +1 -0
- data/lib/rosett_ai/mcp/admin/health_checker.rb +1 -0
- data/lib/rosett_ai/mcp/admin/registry.rb +1 -0
- data/lib/rosett_ai/mcp/enforcement/hook_generator.rb +27 -4
- data/lib/rosett_ai/mcp/enforcement/validator.rb +24 -3
- data/lib/rosett_ai/mcp/governance.rb +9 -0
- data/lib/rosett_ai/mcp/http_security_config.rb +22 -0
- data/lib/rosett_ai/mcp/key_hasher.rb +4 -2
- data/lib/rosett_ai/mcp/keyfile.rb +4 -0
- data/lib/rosett_ai/mcp/middleware/cors.rb +4 -0
- data/lib/rosett_ai/mcp/middleware/origin_validation.rb +1 -0
- data/lib/rosett_ai/mcp/middleware/rate_limit.rb +3 -0
- data/lib/rosett_ai/mcp/plugins.rb +1 -0
- data/lib/rosett_ai/mcp/prompts/compilation_prompt.rb +2 -0
- data/lib/rosett_ai/mcp/prompts/compliance_prompt.rb +3 -0
- data/lib/rosett_ai/mcp/prompts/diagnostics_prompt.rb +2 -0
- data/lib/rosett_ai/mcp/prompts/validation_prompt.rb +2 -0
- data/lib/rosett_ai/mcp/resources/behaviour_resource.rb +2 -0
- data/lib/rosett_ai/mcp/resources/config_resource.rb +2 -0
- data/lib/rosett_ai/mcp/resources/design_resource.rb +1 -0
- data/lib/rosett_ai/mcp/resources/hooks_resource.rb +3 -0
- data/lib/rosett_ai/mcp/resources/provenance_resource.rb +2 -0
- data/lib/rosett_ai/mcp/resources/rules_resource.rb +1 -0
- data/lib/rosett_ai/mcp/resources/schema_resource.rb +1 -0
- data/lib/rosett_ai/mcp/server.rb +7 -1
- data/lib/rosett_ai/mcp/settings/trust_manager.rb +3 -0
- data/lib/rosett_ai/mcp/tools/adopt_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/backup_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/behaviour_display_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/behaviour_list_tool.rb +3 -0
- data/lib/rosett_ai/mcp/tools/behaviour_manage_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/behaviour_show_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/compile_status_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/compile_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/comply_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/config_compile_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/config_status_tool.rb +3 -0
- data/lib/rosett_ai/mcp/tools/content_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/context_query_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/design_list_tool.rb +3 -0
- data/lib/rosett_ai/mcp/tools/design_show_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/doctor_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/documentation_status_tool.rb +3 -0
- data/lib/rosett_ai/mcp/tools/engines_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/hook_install_tool.rb +7 -0
- data/lib/rosett_ai/mcp/tools/hook_preview_tool.rb +33 -8
- data/lib/rosett_ai/mcp/tools/hooks_status_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/init_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/license_status_tool.rb +3 -0
- data/lib/rosett_ai/mcp/tools/project_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/provenance_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/provenance_write_tool.rb +3 -0
- data/lib/rosett_ai/mcp/tools/retrofit_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/rule_search_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/schema_get_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/tooling_tool.rb +5 -0
- data/lib/rosett_ai/mcp/tools/validate_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/workflow_execute_tool.rb +4 -0
- data/lib/rosett_ai/mcp/tools/workflow_tool.rb +5 -0
- data/lib/rosett_ai/migration/detector.rb +1 -0
- data/lib/rosett_ai/migration/nncc_config_migrator.rb +2 -0
- data/lib/rosett_ai/migration/xdg_migrator.rb +3 -1
- data/lib/rosett_ai/package_manager/apt.rb +5 -0
- data/lib/rosett_ai/package_manager/base.rb +1 -0
- data/lib/rosett_ai/package_manager/gem_backend.rb +1 -0
- data/lib/rosett_ai/packaging/variant_config.rb +12 -0
- data/lib/rosett_ai/plugins/contract.rb +1 -0
- data/lib/rosett_ai/plugins/engine_contract.rb +2 -0
- data/lib/rosett_ai/plugins/gui_contract.rb +2 -0
- data/lib/rosett_ai/plugins/mcp_contract.rb +2 -0
- data/lib/rosett_ai/plugins/registry.rb +10 -0
- data/lib/rosett_ai/policy/auditor.rb +1 -0
- data/lib/rosett_ai/policy/opt_out_scanner.rb +1 -0
- data/lib/rosett_ai/policy/tier_hierarchy.rb +2 -0
- data/lib/rosett_ai/policy/validator.rb +1 -0
- data/lib/rosett_ai/profiler.rb +7 -0
- data/lib/rosett_ai/project/drift_detector.rb +1 -0
- data/lib/rosett_ai/project/manager.rb +1 -0
- data/lib/rosett_ai/project/template_applier.rb +1 -0
- data/lib/rosett_ai/provenance/entry.rb +2 -0
- data/lib/rosett_ai/provenance/source.rb +1 -0
- data/lib/rosett_ai/provenance/store.rb +3 -0
- data/lib/rosett_ai/provenance/validator.rb +1 -0
- data/lib/rosett_ai/quorum/collector.rb +1 -0
- data/lib/rosett_ai/quorum/comparator.rb +2 -0
- data/lib/rosett_ai/quorum/strategies/adopt.rb +1 -0
- data/lib/rosett_ai/rai_config.rb +9 -0
- data/lib/rosett_ai/retrofit/engine.rb +2 -0
- data/lib/rosett_ai/retrofit/parsers/agents_md_parser.rb +8 -0
- data/lib/rosett_ai/retrofit/parsers/claude_parser.rb +10 -0
- data/lib/rosett_ai/retrofit/parsers/cursor_parser.rb +9 -0
- data/lib/rosett_ai/retrofit/secret_detector.rb +3 -0
- data/lib/rosett_ai/secrets_resolver.rb +1 -0
- data/lib/rosett_ai/session_hooks/installer.rb +130 -0
- data/lib/rosett_ai/smart_feedback/suggester.rb +4 -0
- data/lib/rosett_ai/smart_feedback/thor_middleware.rb +7 -0
- data/lib/rosett_ai/structured_logger.rb +1 -0
- data/lib/rosett_ai/telemetry/log_rotator.rb +1 -0
- data/lib/rosett_ai/telemetry.rb +1 -0
- data/lib/rosett_ai/thor/cli.rb +9 -0
- data/lib/rosett_ai/thor/tasks/adopt.rb +2 -0
- data/lib/rosett_ai/thor/tasks/backfill_user_yml.rb +207 -0
- data/lib/rosett_ai/thor/tasks/backup.rb +6 -0
- data/lib/rosett_ai/thor/tasks/behaviour.rb +12 -0
- data/lib/rosett_ai/thor/tasks/build.rb +106 -21
- data/lib/rosett_ai/thor/tasks/compile.rb +76 -32
- data/lib/rosett_ai/thor/tasks/completion.rb +9 -0
- data/lib/rosett_ai/thor/tasks/comply.rb +2 -0
- data/lib/rosett_ai/thor/tasks/config.rb +21 -5
- data/lib/rosett_ai/thor/tasks/content.rb +8 -0
- data/lib/rosett_ai/thor/tasks/dbus.rb +13 -0
- data/lib/rosett_ai/thor/tasks/design.rb +2 -0
- data/lib/rosett_ai/thor/tasks/desktop.rb +4 -0
- data/lib/rosett_ai/thor/tasks/doctor.rb +2 -0
- data/lib/rosett_ai/thor/tasks/documentation.rb +7 -0
- data/lib/rosett_ai/thor/tasks/engines.rb +8 -0
- data/lib/rosett_ai/thor/tasks/hooks.rb +8 -0
- data/lib/rosett_ai/thor/tasks/init.rb +1 -0
- data/lib/rosett_ai/thor/tasks/license.rb +8 -0
- data/lib/rosett_ai/thor/tasks/mcp.rb +40 -0
- data/lib/rosett_ai/thor/tasks/migrate.rb +2 -0
- data/lib/rosett_ai/thor/tasks/plugins.rb +15 -0
- data/lib/rosett_ai/thor/tasks/project.rb +8 -0
- data/lib/rosett_ai/thor/tasks/provenance.rb +8 -0
- data/lib/rosett_ai/thor/tasks/release.rb +8 -0
- data/lib/rosett_ai/thor/tasks/retrofit.rb +4 -0
- data/lib/rosett_ai/thor/tasks/validate.rb +1 -0
- data/lib/rosett_ai/thor/tasks/workflow.rb +14 -0
- data/lib/rosett_ai/tooling/version_checker.rb +1 -0
- data/lib/rosett_ai/ui/accessible_tui.rb +18 -0
- data/lib/rosett_ai/ui/base.rb +3 -0
- data/lib/rosett_ai/ui/gtk4.rb +19 -0
- data/lib/rosett_ai/ui/kde.rb +1 -0
- data/lib/rosett_ai/ui/qt6.rb +1 -0
- data/lib/rosett_ai/ui/registry.rb +15 -0
- data/lib/rosett_ai/ui/tui.rb +22 -0
- data/lib/rosett_ai/validators/behaviour_validator.rb +1 -0
- data/lib/rosett_ai/validators/design_validator.rb +2 -0
- data/lib/rosett_ai/validators/schema_validator.rb +4 -0
- data/lib/rosett_ai/validators/tooling_validator.rb +1 -0
- data/lib/rosett_ai/version.rb +2 -1
- data/lib/rosett_ai/version_consistency_checker.rb +6 -0
- data/lib/rosett_ai/workflow/engine.rb +1 -0
- data/lib/rosett_ai/workflow/manager.rb +1 -0
- data/lib/rosett_ai/workflow/schema_validator.rb +2 -0
- data/lib/rosett_ai/workflow/step_runner.rb +1 -0
- data/lib/rosett_ai/workflow/steps/rai_step.rb +1 -0
- data/lib/rosett_ai/yaml_loader.rb +2 -0
- data/lib/rosett_ai.rb +2 -0
- data/lib/scripts/generated/docker_hub_tags.rb +2 -0
- data/locales/ar.yml +2 -0
- data/locales/en.yml +5 -0
- data/locales/fr.yml +2 -0
- metadata +9 -189
- data/.ai-provenance.yml +0 -119
- data/.debride_whitelist +0 -186
- data/.fasterer.yml +0 -29
- data/.mdl_style.rb +0 -10
- data/.mdlrc +0 -3
- data/.mutant.yml +0 -49
- data/.namespace-allowlist +0 -42
- data/.reek.yml +0 -1040
- data/.rosett-ai/config.yml +0 -3
- data/.rspec +0 -5
- data/.rubocop.yml +0 -380
- data/.ruby-version +0 -1
- data/.yamllint +0 -51
- data/.yardopts +0 -12
- data/AI-DISCLOSURE.md +0 -48
- data/CLAUDE.md +0 -141
- data/CONTRIBUTING.md +0 -734
- data/INSTALL.md +0 -154
- data/LICENSE.md +0 -675
- data/QUICKSTART.md +0 -73
- data/Rakefile +0 -200
- data/SECURITY.md +0 -114
- data/cliff.toml +0 -52
- data/conf/behaviour/.gitkeep +0 -0
- data/conf/design/aaif_alignment.yml +0 -181
- data/conf/design/ab_testing.yml +0 -172
- data/conf/design/accessibility.yml +0 -84
- data/conf/design/ai_authorship.yml +0 -210
- data/conf/design/ai_provenance.yml +0 -224
- data/conf/design/ai_tool_configuration.yml +0 -207
- data/conf/design/architecture.yml +0 -139
- data/conf/design/autocompletion.yml +0 -115
- data/conf/design/backward_compatibility.yml +0 -112
- data/conf/design/behaviour_composition.yml +0 -246
- data/conf/design/build_rake_extraction.yml +0 -57
- data/conf/design/ci_pipeline.yml +0 -100
- data/conf/design/claude_code_configuration.yml +0 -157
- data/conf/design/compiler.yml +0 -128
- data/conf/design/comply.yml +0 -153
- data/conf/design/content_packs.yml +0 -84
- data/conf/design/desktop_integration.yml +0 -289
- data/conf/design/distribution.yml +0 -216
- data/conf/design/doctor.yml +0 -184
- data/conf/design/documentation.yml +0 -152
- data/conf/design/engine_architecture.yml +0 -257
- data/conf/design/error_handling.yml +0 -103
- data/conf/design/feature_flags.yml +0 -142
- data/conf/design/git_hooks.yml +0 -165
- data/conf/design/gui_plugins.yml +0 -475
- data/conf/design/i18n.yml +0 -84
- data/conf/design/integration_testing.yml +0 -56
- data/conf/design/licensing_system.yml +0 -88
- data/conf/design/lifecycle_management.yml +0 -208
- data/conf/design/mcp_integration.yml +0 -207
- data/conf/design/mcp_settings.yml +0 -126
- data/conf/design/migration.yml +0 -56
- data/conf/design/monitoring_observability.yml +0 -194
- data/conf/design/namespace_cleanup.yml +0 -145
- data/conf/design/plugin_test_segregation.yml +0 -145
- data/conf/design/policy_management.yml +0 -229
- data/conf/design/project_management.yml +0 -183
- data/conf/design/rai_mcp_asset_discovery.yml +0 -164
- data/conf/design/rai_mcp_server.yml +0 -605
- data/conf/design/release_management.yml +0 -117
- data/conf/design/retrofit.yml +0 -199
- data/conf/design/retrospective_analyzer.yml +0 -79
- data/conf/design/scope_hierarchy.yml +0 -352
- data/conf/design/security.yml +0 -115
- data/conf/design/session_retrospective.yml +0 -85
- data/conf/design/smart_ui_feedback.yml +0 -89
- data/conf/design/structured_logging.yml +0 -148
- data/conf/design/styles.yml +0 -123
- data/conf/design/test_peer_review.yml +0 -89
- data/conf/design/testing.yml +0 -136
- data/conf/design/threat_model.yml +0 -108
- data/conf/design/ui_framework.yml +0 -111
- data/conf/design/usage_optimization.yml +0 -122
- data/conf/design/version_management.yml +0 -60
- data/conf/design/workflow.yml +0 -227
- data/doc/AAIF_POSITIONING.md +0 -58
- data/doc/ADOPT.md +0 -224
- data/doc/AI_PROVENANCE.md +0 -139
- data/doc/ARCHITECTURE.md +0 -920
- data/doc/BEHAVIOUR.md +0 -409
- data/doc/BUILD.md +0 -138
- data/doc/CI_CD_RECIPES.md +0 -171
- data/doc/CLAUDE_SESSIONS_MOVED.md +0 -16
- data/doc/COMMAND_ANALYSIS.md +0 -229
- data/doc/CONFIGURATION.md +0 -281
- data/doc/DESIGN_AUDIT.md +0 -235
- data/doc/DESIGN_PEER_REVIEW.md +0 -771
- data/doc/DESKTOP.md +0 -447
- data/doc/ENGINES.md +0 -567
- data/doc/ENGINE_DEVELOPMENT_GUIDE.md +0 -417
- data/doc/FEATURE_AUDIT.md +0 -218
- data/doc/IMPLEMENTATION_PLAN.md +0 -669
- data/doc/INCIDENT_REPORT_2026-02-02.md +0 -251
- data/doc/MIGRATION_GUIDE.md +0 -88
- data/doc/PACKAGING.md +0 -232
- data/doc/PROJECT_DASHBOARD.md +0 -153
- data/doc/PULP_DEPLOYMENT.md +0 -164
- data/doc/QUALITY_FIX_SUMMARY.md +0 -110
- data/doc/QUICK_START.md +0 -162
- data/doc/REEK_CONFIGURATION.md +0 -166
- data/doc/REFERENCE.md +0 -253
- data/doc/REFERENCES.md +0 -324
- data/doc/SECURITY_REVIEW_CHECKLIST.md +0 -72
- data/doc/SESSION_2026-02-28_GTK4_HARDENING.md +0 -359
- data/doc/SETUP.md +0 -202
- data/doc/TEST_PEER_REVIEW.md +0 -152
- data/doc/THREAT_MODEL.md +0 -230
- data/doc/USAGE.md +0 -545
- data/doc/USER_MANUAL.md +0 -585
- data/doc/ai_test_review_checklist.md +0 -110
- data/doc/changes/2026-02-18-packaging-fpm.md +0 -155
- data/doc/changes/2026-02-19-testing-infrastructure.md +0 -221
- data/doc/changes/2026-02-20-security-implementation.md +0 -281
- data/doc/changes/2026-02-20-styles-implementation.md +0 -220
- data/doc/changes/2026-02-21-architecture-completion.md +0 -95
- data/doc/changes/2026-02-21-architecture-ui-layer.md +0 -253
- data/doc/changes/2026-02-21-cc-config-implementation.md +0 -108
- data/doc/changes/2026-02-21-ci-pipeline-implementation.md +0 -214
- data/doc/changes/2026-02-21-compiler-multi-target-pipeline.md +0 -241
- data/doc/changes/2026-02-21-config-design-show-commands.md +0 -61
- data/doc/changes/2026-02-21-design-implementation-overview.md +0 -455
- data/doc/changes/2026-02-21-lifecycle-management.md +0 -196
- data/doc/changes/2026-02-21-path-resolver.md +0 -128
- data/doc/changes/2026-02-24-ci-tmpdir-mutant-fetch.md +0 -45
- data/doc/changes/2026-03-01-ci-bundler-strategy.md +0 -120
- data/doc/changes/2026-03-20-security-hardening-phase2.md +0 -163
- data/doc/context/SESSION-HANDOFF.md +0 -69
- data/doc/context/ai-engine-usage-trends-2026.md +0 -80
- data/doc/context/plan-pluggable-engines.md +0 -590
- data/doc/decisions/001-flog-deferred.md +0 -32
- data/doc/decisions/002-path-resolution-strategy.md +0 -158
- data/doc/decisions/003-ui-adapter-selection.md +0 -193
- data/doc/decisions/004-design-document-validation.md +0 -179
- data/doc/decisions/005-package-splitting-strategy.md +0 -200
- data/doc/decisions/006-multi-engine-architecture.md +0 -147
- data/doc/decisions/007-engine-agnostic-pivot.md +0 -219
- data/doc/decisions/008-ci-bundler-strategy.md +0 -129
- data/doc/decisions/009-core-only-v1-release.md +0 -60
- data/doc/decisions/010-engine-debian-packaging.md +0 -66
- data/doc/decisions/011-context-aware-cli.md +0 -71
- data/doc/dependency_decisions.yml +0 -247
- data/doc/issues/001-wrapper-missing-environment-variables.md +0 -197
- data/doc/issues/002-embedded-ruby-wrong-prefix.md +0 -217
- data/doc/issues/003-smoke-test-false-positive.md +0 -127
- data/doc/issues/004-market-research-design-updates.md +0 -109
- data/doc/issues/005-compile-scope-coexistence.md +0 -161
- data/doc/locales/.gitkeep +0 -0
- data/doc/man/rai.1.ronn +0 -505
- data/doc/operations/packaging.md +0 -133
- data/doc/operations/rosett-ai-release.md +0 -65
- data/doc/reference/error-catalog.md +0 -107
- 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 +0 -4
- data/doc/reference/src/bibliography.bib +0 -79
- data/doc/reference/src/main.tex +0 -1288
- data/doc/reference/src/structure.tex +0 -303
- data/doc/rosett-ai-bookmarks.html +0 -301
- data/kitchen.yml +0 -46
- data/lib/rosett_ai/mcp/enforcement/.gitkeep +0 -0
- data/locales/.gitkeep +0 -0
- data/packaging/build-engine-deb.sh +0 -81
- data/packaging/scripts/postinst +0 -17
- data/packaging/scripts/postrm +0 -19
- data/packaging/scripts/prerm +0 -10
- data/packaging/wrapper.sh.template +0 -38
- data/rosett-ai.gemspec +0 -63
- data/rules/.gitkeep +0 -0
- data/scripts/publish/pulp_upload.sh +0 -123
- data/settings.json +0 -29
|
@@ -15,6 +15,7 @@ module RosettAi
|
|
|
15
15
|
# Signals:
|
|
16
16
|
# FocusChanged(app_id: s, title: s) Emitted on active window change
|
|
17
17
|
class FocusMonitorInterface < ::DBus::Object
|
|
18
|
+
# @return [String] D-Bus interface name.
|
|
18
19
|
INTERFACE = 'be.neatnerds.rosettai.FocusMonitor'
|
|
19
20
|
|
|
20
21
|
dbus_interface INTERFACE do
|
|
@@ -23,6 +23,7 @@ module RosettAi
|
|
|
23
23
|
# - Rate limiting (10 req/s, burst 20) prevents DoS via rapid method calls
|
|
24
24
|
# - Compile operations have stricter limits (2 req/s, burst 5)
|
|
25
25
|
class ManagerInterface < ::DBus::Object
|
|
26
|
+
# @return [String] D-Bus interface name.
|
|
26
27
|
INTERFACE = 'be.neatnerds.rosettai.Manager'
|
|
27
28
|
|
|
28
29
|
# Rate limit configurations per operation type
|
|
@@ -21,8 +21,10 @@ module RosettAi
|
|
|
21
21
|
# @author hugo
|
|
22
22
|
# @author claude
|
|
23
23
|
class PluginManagerInterface < ::DBus::Object
|
|
24
|
+
# @return [String] D-Bus interface name.
|
|
24
25
|
INTERFACE = 'be.neatnerds.rosettai.PluginManager'
|
|
25
26
|
|
|
27
|
+
# @return [Array] Set of permitted type values.
|
|
26
28
|
VALID_TYPES = ['engine', 'gui', 'mcp'].freeze
|
|
27
29
|
|
|
28
30
|
dbus_interface INTERFACE do
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
require 'dbus'
|
|
7
7
|
|
|
8
8
|
module RosettAi
|
|
9
|
+
# D-Bus session service for desktop integration.
|
|
9
10
|
module DBus
|
|
10
11
|
# Main D-Bus session service for Rosett-AI.
|
|
11
12
|
#
|
|
@@ -16,7 +17,9 @@ module RosettAi
|
|
|
16
17
|
#
|
|
17
18
|
# The service is designed to gracefully degrade when D-Bus is unavailable.
|
|
18
19
|
class Service
|
|
20
|
+
# @return [String] D-Bus well-known bus name.
|
|
19
21
|
BUS_NAME = 'be.neatnerds.rosettai'
|
|
22
|
+
# @return [String] D-Bus object path.
|
|
20
23
|
OBJECT_PATH = '/be/neatnerds/rosett-ai'
|
|
21
24
|
|
|
22
25
|
attr_reader :bus, :main_loop, :manager, :focus_monitor, :status_notifier
|
|
@@ -15,10 +15,14 @@ module RosettAi
|
|
|
15
15
|
#
|
|
16
16
|
# Degrades gracefully if no StatusNotifierHost is available.
|
|
17
17
|
class StatusNotifierInterface < ::DBus::Object
|
|
18
|
+
# @return [String] D-Bus interface name.
|
|
18
19
|
INTERFACE = 'org.kde.StatusNotifierItem'
|
|
19
20
|
|
|
21
|
+
# @return [String] StatusNotifierItem category.
|
|
20
22
|
CATEGORY = 'ApplicationStatus'
|
|
23
|
+
# @return [String] StatusNotifierItem icon name.
|
|
21
24
|
ICON_NAME = 'rosett-ai-symbolic'
|
|
25
|
+
# @return [String] StatusNotifierItem application identifier.
|
|
22
26
|
APP_ID = 'be.neatnerds.rosettai'
|
|
23
27
|
|
|
24
28
|
dbus_interface INTERFACE do
|
|
@@ -46,10 +50,20 @@ module RosettAi
|
|
|
46
50
|
@current_status = 'Active'
|
|
47
51
|
end
|
|
48
52
|
|
|
53
|
+
# Return the unique identifier.
|
|
54
|
+
# @return [String]
|
|
49
55
|
def id = APP_ID
|
|
56
|
+
# Return the StatusNotifierItem category.
|
|
57
|
+
# @return [String]
|
|
50
58
|
def category = CATEGORY
|
|
59
|
+
# Return the current status.
|
|
60
|
+
# @return [String]
|
|
51
61
|
def status = @current_status
|
|
62
|
+
# Return the display title.
|
|
63
|
+
# @return [String]
|
|
52
64
|
def title = "rai #{RosettAi::VERSION}"
|
|
65
|
+
# Return the icon name for display.
|
|
66
|
+
# @return [String]
|
|
53
67
|
def icon_name = ICON_NAME
|
|
54
68
|
|
|
55
69
|
# ToolTip is a struct: (icon_name, icon_pixmap[], title, body)
|
|
@@ -18,14 +18,20 @@ module RosettAi
|
|
|
18
18
|
# Ruby Rosett-AI modules directly. This ensures the D-Bus service is
|
|
19
19
|
# the single source of truth.
|
|
20
20
|
class DbusClient
|
|
21
|
+
# @return [String] D-Bus well-known bus name.
|
|
21
22
|
BUS_NAME = 'be.neatnerds.rosettai'
|
|
23
|
+
# @return [String] D-Bus object path.
|
|
22
24
|
OBJECT_PATH = '/be/neatnerds/rosett-ai'
|
|
25
|
+
# @return [String] Manager iface constant.
|
|
23
26
|
MANAGER_IFACE = 'be.neatnerds.rosettai.Manager'
|
|
27
|
+
# @return [String] Focus iface constant.
|
|
24
28
|
FOCUS_IFACE = 'be.neatnerds.rosettai.FocusMonitor'
|
|
25
29
|
|
|
26
30
|
# Default safe return values
|
|
27
31
|
SAFE_STATUS = { 'error' => 'Service not available', 'version' => 'unknown' }.freeze
|
|
32
|
+
# @return [Array] Safe focus constant.
|
|
28
33
|
SAFE_FOCUS = ['', ''].freeze
|
|
34
|
+
# @return [String] Safe compile result constant.
|
|
29
35
|
SAFE_COMPILE_RESULT = 'Error: D-Bus service not available'
|
|
30
36
|
|
|
31
37
|
attr_reader :bus, :last_error
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
require_relative 'gui_logger'
|
|
7
7
|
|
|
8
8
|
module RosettAi
|
|
9
|
+
# Desktop GUI application and D-Bus client.
|
|
9
10
|
module Desktop
|
|
10
11
|
# Main GTK4/Adwaita application for rai desktop integration.
|
|
11
12
|
#
|
|
@@ -22,7 +23,9 @@ module RosettAi
|
|
|
22
23
|
# Follows GNOME HIG: single-window, instant-apply preferences,
|
|
23
24
|
# headerbar with title and buttons.
|
|
24
25
|
class Gtk4App
|
|
26
|
+
# @return [String] GTK application identifier.
|
|
25
27
|
APPLICATION_ID = 'be.neatnerds.rosettai'
|
|
28
|
+
# @return [String] Error message when the UI backend is not available.
|
|
26
29
|
UNAVAILABLE_MESSAGE = 'GTK4 app requires the adwaita gem. Install: gem install adwaita'
|
|
27
30
|
|
|
28
31
|
attr_reader :application, :dbus_client
|
|
@@ -66,6 +66,7 @@ module RosettAi
|
|
|
66
66
|
log_error('Failed to present preferences dialog', e)
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
+
# @return [Array] Engine names used when detection fails.
|
|
69
70
|
FALLBACK_ENGINES = [
|
|
70
71
|
{ name: 'claude', display_name: 'Claude' },
|
|
71
72
|
{ name: 'generic', display_name: 'Generic' },
|
|
@@ -30,7 +30,9 @@ module RosettAi
|
|
|
30
30
|
# RAI_GUI_LOG=1 RAI_GUI_LOG_FILE=/tmp/rosett-ai-gui.log bin/raictl desktop gtk4
|
|
31
31
|
#
|
|
32
32
|
class GuiLogger
|
|
33
|
+
# @return [Hash] Supported level values.
|
|
33
34
|
LEVELS = { debug: 0, info: 1, warn: 2, error: 3 }.freeze
|
|
35
|
+
# @return [Symbol] Default log level.
|
|
34
36
|
DEFAULT_LEVEL = :info
|
|
35
37
|
|
|
36
38
|
class << self
|
data/lib/rosett_ai/doctor.rb
CHANGED
|
@@ -16,8 +16,11 @@ module RosettAi
|
|
|
16
16
|
#
|
|
17
17
|
# Design reference: conf/design/documentation.yml
|
|
18
18
|
class ReferenceCompiler
|
|
19
|
+
# @return [Array] External tools required for documentation compilation.
|
|
19
20
|
REQUIRED_TOOLS = ['pdflatex', 'biber', 'makeindex'].freeze
|
|
21
|
+
# @return [String] Filename for compiled reference documentation.
|
|
20
22
|
OUTPUT_NAME = 'rosett-ai-technical-reference.pdf'
|
|
23
|
+
# @return [Array] Files produced during reference documentation build.
|
|
21
24
|
BUILD_ARTIFACTS = ['aux', 'bbl', 'bcf', 'blg', 'idx', 'ilg', 'ind',
|
|
22
25
|
'lof', 'log', 'lot', 'out', 'ptc', 'run.xml', 'toc'].freeze
|
|
23
26
|
|
|
@@ -29,6 +32,8 @@ module RosettAi
|
|
|
29
32
|
REQUIRED_TOOLS.all? { |tool| tool_on_path?(tool) }
|
|
30
33
|
end
|
|
31
34
|
|
|
35
|
+
# Return external tools required but not installed.
|
|
36
|
+
# @return [Array<String>]
|
|
32
37
|
def missing_tools
|
|
33
38
|
REQUIRED_TOOLS.reject { |tool| tool_on_path?(tool) }
|
|
34
39
|
end
|
|
@@ -56,10 +61,14 @@ module RosettAi
|
|
|
56
61
|
clean_artifacts!
|
|
57
62
|
end
|
|
58
63
|
|
|
64
|
+
# Return the compiled documentation output path.
|
|
65
|
+
# @return [Pathname]
|
|
59
66
|
def output_path
|
|
60
67
|
@root.join('doc', 'reference', OUTPUT_NAME)
|
|
61
68
|
end
|
|
62
69
|
|
|
70
|
+
# Return the man page source directory.
|
|
71
|
+
# @return [Pathname]
|
|
63
72
|
def source_dir
|
|
64
73
|
@root.join('doc', 'reference', 'src')
|
|
65
74
|
end
|
|
@@ -6,18 +6,26 @@
|
|
|
6
6
|
require 'fileutils'
|
|
7
7
|
|
|
8
8
|
module RosettAi
|
|
9
|
+
# Reference documentation compilation and translation.
|
|
9
10
|
module Documentation
|
|
10
11
|
# Produces draft translations of documentation files using the Claude API.
|
|
11
12
|
#
|
|
12
13
|
# Reads source documentation, sends to API with a translation prompt,
|
|
13
14
|
# and writes the result to doc/locales/{locale}/.
|
|
14
15
|
class Translator
|
|
16
|
+
# @return [String] AI model used for documentation translation.
|
|
15
17
|
MODEL = 'claude-sonnet-4-20250514'
|
|
16
18
|
|
|
17
19
|
def initialize(doc_dir: nil)
|
|
18
20
|
@doc_dir = doc_dir || RosettAi.root.join('doc')
|
|
19
21
|
end
|
|
20
22
|
|
|
23
|
+
# Translate documentation to the target locale.
|
|
24
|
+
#
|
|
25
|
+
# @param source_file [Object] the source file
|
|
26
|
+
# @param from [Object] the from
|
|
27
|
+
# @param to [Object] the to
|
|
28
|
+
# @return [void]
|
|
21
29
|
def translate(source_file, from:, to:)
|
|
22
30
|
content = File.read(source_file)
|
|
23
31
|
basename = File.basename(source_file)
|
|
@@ -15,6 +15,10 @@ module RosettAi
|
|
|
15
15
|
# file discovery, YAML loading, schema validation, checksum diffing,
|
|
16
16
|
# action determination, and result writing.
|
|
17
17
|
#
|
|
18
|
+
# By default, compiling a scope MERGES with the existing target file,
|
|
19
|
+
# preserving entries not covered by any source YAML. Pass strict: true
|
|
20
|
+
# to get the old replace-all behaviour.
|
|
21
|
+
#
|
|
18
22
|
# Subclasses must implement:
|
|
19
23
|
# - #config_dir → Pathname to scope YAML directory
|
|
20
24
|
# - #schema_path → Pathname to JSON Schema file
|
|
@@ -22,11 +26,16 @@ module RosettAi
|
|
|
22
26
|
# - #transform(data, scope) → [json_data, warnings]
|
|
23
27
|
# - #output_format → Symbol (:json, :yaml)
|
|
24
28
|
class BaseConfigCompiler
|
|
29
|
+
# @return [Array] YAML header keys preserved in compiled output.
|
|
25
30
|
HEADER_KEYS = ['name', 'scope', 'version', 'status', 'compatibility',
|
|
26
31
|
'author', 'created_at', 'modified_at', 'modified_by'].freeze
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
# @param simulate [Boolean] dry-run — compute diffs but do not write
|
|
34
|
+
# @param secret_resolver [#resolve_all] resolves secret placeholders
|
|
35
|
+
# @param strict [Boolean] replace target entirely (skip merge pass)
|
|
36
|
+
def initialize(simulate: false, secret_resolver: nil, strict: false)
|
|
29
37
|
@simulate = simulate
|
|
38
|
+
@strict = strict
|
|
30
39
|
@secret_resolver = secret_resolver || RosettAi::Config::SecretResolver.new
|
|
31
40
|
@schema = load_schema
|
|
32
41
|
end
|
|
@@ -50,6 +59,9 @@ module RosettAi
|
|
|
50
59
|
json_data = @secret_resolver.resolve_all(json_data)
|
|
51
60
|
|
|
52
61
|
target = scope_router.target_path(scope)
|
|
62
|
+
json_data, merge_warnings = merge_pass(target, json_data)
|
|
63
|
+
warnings.concat(merge_warnings)
|
|
64
|
+
|
|
53
65
|
action, diff = determine_action(target, json_data)
|
|
54
66
|
|
|
55
67
|
RosettAi::Config::CompileResult.new(
|
|
@@ -115,6 +127,24 @@ module RosettAi
|
|
|
115
127
|
[]
|
|
116
128
|
end
|
|
117
129
|
|
|
130
|
+
# Merge compiled JSON with the existing target file, preserving entries
|
|
131
|
+
# not produced by any source YAML scope. In strict mode, returns compiled
|
|
132
|
+
# data unchanged.
|
|
133
|
+
#
|
|
134
|
+
# @param target_path [Pathname, nil] path to existing settings file
|
|
135
|
+
# @param json_data [Hash] compiled output from transform + secret resolution
|
|
136
|
+
# @return [Array(Hash, Array<String>)] [merged_data, preserve_warnings]
|
|
137
|
+
def merge_pass(target_path, json_data)
|
|
138
|
+
return [json_data, []] if @strict
|
|
139
|
+
return [json_data, []] unless target_path&.exist?
|
|
140
|
+
|
|
141
|
+
existing = JSON.parse(File.read(target_path))
|
|
142
|
+
result = deep_merge_preserve(json_data, existing)
|
|
143
|
+
[result[:data], result[:warnings]]
|
|
144
|
+
rescue Errno::ENOENT, JSON::ParserError
|
|
145
|
+
[json_data, []]
|
|
146
|
+
end
|
|
147
|
+
|
|
118
148
|
private
|
|
119
149
|
|
|
120
150
|
def load_schema
|
|
@@ -198,6 +228,46 @@ module RosettAi
|
|
|
198
228
|
def extract_scope_from_path(path)
|
|
199
229
|
File.basename(path, '.yml')
|
|
200
230
|
end
|
|
231
|
+
|
|
232
|
+
# Recursively merge compiled data with existing, preserving keys/elements
|
|
233
|
+
# that are absent from compiled. Array merging appends existing-only elements.
|
|
234
|
+
#
|
|
235
|
+
# @param compiled [Hash] compiled json_data (source of truth for what was set)
|
|
236
|
+
# @param existing [Hash] parsed existing settings file
|
|
237
|
+
# @param path_prefix [String] dot-path prefix for warning messages
|
|
238
|
+
# @return [Hash] with keys :data (merged Hash) and :warnings (Array<String>)
|
|
239
|
+
def deep_merge_preserve(compiled, existing, path_prefix: '')
|
|
240
|
+
warnings = []
|
|
241
|
+
merged = compiled.dup
|
|
242
|
+
existing.each do |key, existing_val|
|
|
243
|
+
entry_path = path_prefix.empty? ? key.to_s : "#{path_prefix}.#{key}"
|
|
244
|
+
warnings.concat(merge_existing_entry(merged, compiled, key, existing_val, entry_path))
|
|
245
|
+
end
|
|
246
|
+
{ data: merged, warnings: warnings }
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def merge_existing_entry(merged, compiled, key, existing_val, entry_path)
|
|
250
|
+
unless compiled.key?(key)
|
|
251
|
+
merged[key] = existing_val
|
|
252
|
+
return [preserved_warning("#{entry_path}: #{existing_val.inspect}")]
|
|
253
|
+
end
|
|
254
|
+
compiled_val = compiled[key]
|
|
255
|
+
if compiled_val.is_a?(Array) && existing_val.is_a?(Array)
|
|
256
|
+
extra = existing_val - compiled_val
|
|
257
|
+
merged[key] = compiled_val + extra
|
|
258
|
+
return extra.map { |e| preserved_warning(e.inspect) }
|
|
259
|
+
elsif compiled_val.is_a?(Hash) && existing_val.is_a?(Hash)
|
|
260
|
+
sub = deep_merge_preserve(compiled_val, existing_val, path_prefix: entry_path)
|
|
261
|
+
merged[key] = sub[:data]
|
|
262
|
+
return sub[:warnings]
|
|
263
|
+
end
|
|
264
|
+
[] # scalar: compiled wins silently (merged already has compiled[key] from dup)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def preserved_warning(entry_label)
|
|
268
|
+
'Preserved entry from settings.json not in source scopes: ' \
|
|
269
|
+
"#{entry_label}. Consider running `raictl backfill-user-yml` to capture in source."
|
|
270
|
+
end
|
|
201
271
|
end
|
|
202
272
|
end
|
|
203
273
|
end
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
5
|
|
|
6
6
|
module RosettAi
|
|
7
|
+
# Engine plugin discovery, detection, and registry.
|
|
7
8
|
module Engines
|
|
8
9
|
# Base engine detector that reads manifest detection rules and probes the system.
|
|
9
10
|
#
|
|
@@ -17,6 +18,8 @@ module RosettAi
|
|
|
17
18
|
@manifest = Registry.manifest(@engine_name)
|
|
18
19
|
end
|
|
19
20
|
|
|
21
|
+
# Detect available engines on the system.
|
|
22
|
+
# @return [Array<Hash>]
|
|
20
23
|
def detect
|
|
21
24
|
checks = []
|
|
22
25
|
detection = @manifest['detection'] || {}
|
|
@@ -35,6 +38,8 @@ module RosettAi
|
|
|
35
38
|
|
|
36
39
|
protected
|
|
37
40
|
|
|
41
|
+
# Return custom engine detection check results.
|
|
42
|
+
# @return [Array<Hash>]
|
|
38
43
|
def custom_checks
|
|
39
44
|
[]
|
|
40
45
|
end
|
|
@@ -12,10 +12,17 @@ module RosettAi
|
|
|
12
12
|
# register.rb files, discovered by Gem.find_files.
|
|
13
13
|
class Registry
|
|
14
14
|
class << self
|
|
15
|
+
# List all available engine plugins.
|
|
16
|
+
#
|
|
17
|
+
# @return [Array<Hash>]
|
|
15
18
|
def available
|
|
16
19
|
RosettAi::Plugins::Registry.available(:engine)
|
|
17
20
|
end
|
|
18
21
|
|
|
22
|
+
# Return the Ruby module for the given engine name.
|
|
23
|
+
#
|
|
24
|
+
# @param name [String, Symbol] the engine name
|
|
25
|
+
# @return [Module, nil]
|
|
19
26
|
def engine_module(name)
|
|
20
27
|
RosettAi::Plugins::Registry.plugin_module(:engine, name.to_s)
|
|
21
28
|
end
|
data/lib/rosett_ai/exit_codes.rb
CHANGED
|
@@ -17,11 +17,17 @@ module RosettAi
|
|
|
17
17
|
# @author hugo
|
|
18
18
|
# @author claude
|
|
19
19
|
module ExitCodes
|
|
20
|
+
# @return [Integer] Success constant.
|
|
20
21
|
SUCCESS = 0
|
|
22
|
+
# @return [Integer] General constant.
|
|
21
23
|
GENERAL = 1
|
|
24
|
+
# @return [Integer] Validation constant.
|
|
22
25
|
VALIDATION = 2
|
|
26
|
+
# @return [Integer] Config constant.
|
|
23
27
|
CONFIG = 3
|
|
28
|
+
# @return [Integer] Permission constant.
|
|
24
29
|
PERMISSION = 4
|
|
30
|
+
# @return [Integer] Dependency constant.
|
|
25
31
|
DEPENDENCY = 5
|
|
26
32
|
|
|
27
33
|
# Maps each RosettAi error class to its exit code.
|
data/lib/rosett_ai/formatting.rb
CHANGED
|
@@ -7,6 +7,7 @@ module RosettAi
|
|
|
7
7
|
# Human-readable formatting for byte sizes and durations.
|
|
8
8
|
# Include in any class that needs to display file sizes or elapsed times.
|
|
9
9
|
module Formatting
|
|
10
|
+
# @return [Array] Human-readable byte size unit labels.
|
|
10
11
|
SIZE_UNITS = ['B', 'KB', 'MB', 'GB'].freeze
|
|
11
12
|
|
|
12
13
|
# Formats a byte count as a human-readable string (e.g. "2.0 KB").
|
|
@@ -13,11 +13,15 @@ module RosettAi
|
|
|
13
13
|
# against gemspec constraints, and scans project files for stale gem version
|
|
14
14
|
# references.
|
|
15
15
|
class GemConsistencyChecker
|
|
16
|
+
# @return [Array] Directory names excluded from consistency checking.
|
|
16
17
|
EXCLUDED_DIRS = ['vendor', 'tmp', 'coverage', '.git', '.bundle'].freeze
|
|
18
|
+
# @return [Array] Filenames excluded from consistency checking.
|
|
17
19
|
EXCLUDED_FILES = ['Gemfile.lock', 'Gemfile', 'rosett_ai.gemspec',
|
|
18
20
|
'spec/rosett_ai/gem_consistency_checker_spec.rb',
|
|
19
21
|
'spec/examples.txt'].freeze
|
|
22
|
+
# @return [Array] Filename prefixes excluded from consistency checking.
|
|
20
23
|
EXCLUDED_PREFIXES = ['doc/changes/', 'doc/claude-sessions/', 'conf/design/'].freeze
|
|
24
|
+
# @return [Array] File extensions excluded from consistency checking.
|
|
21
25
|
EXCLUDED_EXTENSIONS = ['.aux', '.toc', '.out', '.ptc', '.log', '.idx', '.ind',
|
|
22
26
|
'.ilg', '.bbl', '.blg', '.bcf', '.fls', '.json'].freeze
|
|
23
27
|
|
|
@@ -28,6 +32,8 @@ module RosettAi
|
|
|
28
32
|
@results = { gems: [], stale_references: [], consistent: true }
|
|
29
33
|
end
|
|
30
34
|
|
|
35
|
+
# Run the check and return results.
|
|
36
|
+
# @return [Hash]
|
|
31
37
|
def check
|
|
32
38
|
constraints = parse_gemspec_constraints
|
|
33
39
|
locked = parse_lockfile_versions
|
|
@@ -13,6 +13,7 @@ module RosettAi
|
|
|
13
13
|
# @author hugo
|
|
14
14
|
# @author claude
|
|
15
15
|
class ChainDetector
|
|
16
|
+
# @return [Hash] Recognized git hook manager names.
|
|
16
17
|
KNOWN_MANAGERS = {
|
|
17
18
|
'overcommit' => { marker: /overcommit/i, config: '.overcommit.yml' },
|
|
18
19
|
'husky' => { marker: /husky/i, config: '.husky' },
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
5
|
|
|
6
6
|
module RosettAi
|
|
7
|
+
# Git hook installation, generation, and chain detection.
|
|
7
8
|
module GitHooks
|
|
8
9
|
# Installs and uninstalls rosett-ai-managed git hooks in .git/hooks/.
|
|
9
10
|
#
|
|
@@ -14,9 +15,12 @@ module RosettAi
|
|
|
14
15
|
# @author hugo
|
|
15
16
|
# @author claude
|
|
16
17
|
class Installer
|
|
18
|
+
# @return [String] Marker identifying rai-managed hook scripts.
|
|
17
19
|
RAI_MARKER = '# rosett-ai-managed hook'
|
|
20
|
+
# @return [String] File extension appended to backup copies.
|
|
18
21
|
BACKUP_SUFFIX = '.rosett-ai-backup'
|
|
19
22
|
|
|
23
|
+
# @return [Array] Git hook types supported for installation.
|
|
20
24
|
SUPPORTED_HOOKS = [
|
|
21
25
|
'pre-commit', 'post-commit', 'post-checkout', 'post-merge', 'pre-push'
|
|
22
26
|
].freeze
|
|
@@ -15,7 +15,9 @@ module RosettAi
|
|
|
15
15
|
# @author hugo
|
|
16
16
|
# @author claude
|
|
17
17
|
module ScriptGenerator
|
|
18
|
+
# @return [String] File extension appended to backup copies.
|
|
18
19
|
BACKUP_SUFFIX = '.rosett-ai-backup'
|
|
20
|
+
# @return [Integer] Default timeout in seconds.
|
|
19
21
|
DEFAULT_TIMEOUT = 30
|
|
20
22
|
|
|
21
23
|
# Pattern matching shell metacharacters that indicate potential injection.
|
|
@@ -7,7 +7,9 @@ require 'yaml'
|
|
|
7
7
|
require 'pathname'
|
|
8
8
|
|
|
9
9
|
module RosettAi
|
|
10
|
+
# GitLab CI integration and validation.
|
|
10
11
|
module Gitlab
|
|
12
|
+
# GitLab CI YAML validation implementations.
|
|
11
13
|
module Validators
|
|
12
14
|
# Validates GitLab CI YAML files for syntax correctness.
|
|
13
15
|
#
|
|
@@ -17,7 +19,9 @@ module RosettAi
|
|
|
17
19
|
# (e.g. double-quoted strings misinterpreted as YAML scalars) while
|
|
18
20
|
# remaining compatible with GitLab-specific extensions.
|
|
19
21
|
class SupplementaryGitlabCiYamlValidator
|
|
22
|
+
# @return [String] Root CI configuration filename.
|
|
20
23
|
CI_ROOT_FILE = '.gitlab-ci.yml'
|
|
24
|
+
# @return [String] Directory for supplementary CI YAML files.
|
|
21
25
|
CI_FILES_DIR = '.gitlab-ci-files'
|
|
22
26
|
|
|
23
27
|
attr_reader :results
|
|
@@ -27,6 +31,8 @@ module RosettAi
|
|
|
27
31
|
@results = { valid: [], invalid: [] }
|
|
28
32
|
end
|
|
29
33
|
|
|
34
|
+
# Validate the input and return any errors.
|
|
35
|
+
# @return [Array<Hash>]
|
|
30
36
|
def validate
|
|
31
37
|
@results = { valid: [], invalid: [] }
|
|
32
38
|
|
|
@@ -8,6 +8,10 @@ module RosettAi
|
|
|
8
8
|
# Writes the default rai config file at ~/.config/rosett-ai/config.yml
|
|
9
9
|
# if it does not already exist.
|
|
10
10
|
class ConfigFileWriter
|
|
11
|
+
# Write the default configuration file to disk.
|
|
12
|
+
#
|
|
13
|
+
# @param config_dir [Object] the config dir
|
|
14
|
+
# @return [void]
|
|
11
15
|
def self.write_default(config_dir: nil)
|
|
12
16
|
dir = config_dir || RosettAi.paths.rai_config_dir
|
|
13
17
|
path = dir.join('config.yml')
|
|
@@ -9,20 +9,35 @@ module RosettAi
|
|
|
9
9
|
module Init
|
|
10
10
|
# Helper module for creating directories during initialization
|
|
11
11
|
module DirectoryBuilder
|
|
12
|
+
# @return [Array] Directory structure for global initialization.
|
|
12
13
|
GLOBAL_DIRS = ['rules', 'locales', 'conf', 'conf/behaviour', 'conf/schemas', 'doc', 'bin', 'lib',
|
|
13
14
|
'lib/rosett-ai'].freeze
|
|
15
|
+
# @return [Array] Directory structure for local initialization.
|
|
14
16
|
LOCAL_DIRS = ['rules', 'conf', 'conf/behaviour', 'conf/schemas'].freeze
|
|
15
17
|
|
|
16
18
|
module_function
|
|
17
19
|
|
|
20
|
+
# Create the global ~/.claude/ directory structure.
|
|
21
|
+
#
|
|
22
|
+
# @param base_dir [String] the base directory path
|
|
23
|
+
# @return [Array<String>] list of created directories
|
|
18
24
|
def create_global_structure(base_dir)
|
|
19
25
|
create_directories(base_dir, GLOBAL_DIRS)
|
|
20
26
|
end
|
|
21
27
|
|
|
28
|
+
# Create the project-local .claude/ directory structure.
|
|
29
|
+
#
|
|
30
|
+
# @param base_dir [String] the base directory path
|
|
31
|
+
# @return [Array<String>] list of created directories
|
|
22
32
|
def create_local_structure(base_dir)
|
|
23
33
|
create_directories(base_dir, LOCAL_DIRS)
|
|
24
34
|
end
|
|
25
35
|
|
|
36
|
+
# Create the specified subdirectories under the base directory.
|
|
37
|
+
#
|
|
38
|
+
# @param base_dir [String] the base directory path
|
|
39
|
+
# @param subdirs [Array<String>] subdirectory names to create
|
|
40
|
+
# @return [Array<String>] list of newly created directories
|
|
26
41
|
def create_directories(base_dir, subdirs)
|
|
27
42
|
created = []
|
|
28
43
|
([base_dir] + subdirs.map { |subdir| File.join(base_dir, subdir) }).each do |dir|
|