rosett-ai 1.3.3 → 1.5.9
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 +398 -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 +87 -4
- 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
|
@@ -22,6 +22,10 @@ module RosettAi
|
|
|
22
22
|
:stage_timings, :completed_stages,
|
|
23
23
|
:failed_stage, :failure_reason, :summary_printed
|
|
24
24
|
) do
|
|
25
|
+
# Create a new build context with a unique ID and log file.
|
|
26
|
+
#
|
|
27
|
+
# @param log_dir [Pathname] directory for build log files
|
|
28
|
+
# @return [BuildContext]
|
|
25
29
|
def self.create(log_dir)
|
|
26
30
|
id = SecureRandom.uuid
|
|
27
31
|
log_path = log_dir.join("build-#{id}.log")
|
|
@@ -60,6 +64,7 @@ module RosettAi
|
|
|
60
64
|
|
|
61
65
|
default_task :create
|
|
62
66
|
|
|
67
|
+
# @return [String] Target installation directory for packages.
|
|
63
68
|
INSTALL_DIR = '/opt/rosett-ai'
|
|
64
69
|
|
|
65
70
|
# Files/directories excluded when syncing app source into the staging tree
|
|
@@ -68,9 +73,12 @@ module RosettAi
|
|
|
68
73
|
'.git', '.gitignore',
|
|
69
74
|
# Bundler / gem build artifacts
|
|
70
75
|
'.bundle', '.binstubs', 'vendor/bundle', '*.gem',
|
|
71
|
-
'Gemfile.dev', 'Gemfile.dev.lock',
|
|
76
|
+
'Gemfile.dev', 'Gemfile.dev.lock',
|
|
77
|
+
'Gemfile.integration', 'Gemfile.integration.lock',
|
|
72
78
|
# CI/CD
|
|
73
79
|
'.gitlab-ci*',
|
|
80
|
+
# CI artifacts — never ship test/lint output
|
|
81
|
+
'rspec-report.xml', 'rubocop-report.json',
|
|
74
82
|
# Build & packaging
|
|
75
83
|
'coverage', 'tmp', 'pkg', 'spec', 'test', 'packaging',
|
|
76
84
|
# Dev tool configs
|
|
@@ -79,8 +87,24 @@ module RosettAi
|
|
|
79
87
|
'.overcommit.yml', '.git-hooks',
|
|
80
88
|
'.mdlrc', '.mdl_style.rb', '.yamllint', '.yardopts',
|
|
81
89
|
'.project', '.rosett-ai',
|
|
90
|
+
# Dev-only documentation (not needed at runtime)
|
|
91
|
+
'doc/api', 'doc/reference', 'doc/context', 'doc/issues',
|
|
92
|
+
'doc/decisions', 'doc/changes',
|
|
93
|
+
# Security advisories — internal, never ship publicly
|
|
94
|
+
'doc/security',
|
|
95
|
+
# Design docs — carry internal WP refs, not runtime-required
|
|
96
|
+
'conf/design',
|
|
97
|
+
# Behaviour rules — user-authored, must never ship in packages (sec_001/rule_073)
|
|
98
|
+
'conf/behaviour',
|
|
99
|
+
# Peer review configs (dev-only)
|
|
100
|
+
'conf/review',
|
|
82
101
|
# AI assistant state — never ship in package
|
|
83
102
|
'.claude', 'doc/claude-sessions',
|
|
103
|
+
# AI provenance file — dev-only provenance tracking, not runtime-required
|
|
104
|
+
'.ai-provenance.yml',
|
|
105
|
+
# Internal audit, operations, signing, and rule-audit documents
|
|
106
|
+
'doc/audits', 'doc/operations', 'doc/signing',
|
|
107
|
+
'doc/rules-audit-*.md',
|
|
84
108
|
'cliff.toml', 'kitchen.yml', 'Rakefile'
|
|
85
109
|
].freeze
|
|
86
110
|
|
|
@@ -89,7 +113,7 @@ module RosettAi
|
|
|
89
113
|
:validate, :clean, :prepare, :compile_ruby,
|
|
90
114
|
:sync_app, :install_gems, :clean_build_artifacts,
|
|
91
115
|
:install_wrapper,
|
|
92
|
-
:install_config, :install_man, :install_build_info, :package
|
|
116
|
+
:install_config, :install_systemd, :install_man, :install_build_info, :rewrite_shebangs, :package
|
|
93
117
|
].freeze
|
|
94
118
|
|
|
95
119
|
# Bundler/RubyGems environment variables that must be stripped
|
|
@@ -162,6 +186,9 @@ module RosettAi
|
|
|
162
186
|
default: 'core',
|
|
163
187
|
desc: 'Package variant (core, gtk4, qt6)'
|
|
164
188
|
|
|
189
|
+
# Build a .deb package for the specified variant.
|
|
190
|
+
#
|
|
191
|
+
# @return [void]
|
|
165
192
|
def create
|
|
166
193
|
unless RosettAi.context.rai_internal?
|
|
167
194
|
raise ::Thor::Error,
|
|
@@ -181,8 +208,10 @@ module RosettAi
|
|
|
181
208
|
run_stage(:clean_build_artifacts) { clean_build_artifacts! }
|
|
182
209
|
run_stage(:install_wrapper) { install_wrapper! }
|
|
183
210
|
run_stage(:install_config) { install_default_config! }
|
|
211
|
+
run_stage(:install_systemd) { install_systemd_unit! }
|
|
184
212
|
run_stage(:install_man) { install_man_pages! }
|
|
185
213
|
run_stage(:install_build_info) { install_build_info! }
|
|
214
|
+
run_stage(:rewrite_shebangs) { rewrite_shebangs! }
|
|
186
215
|
run_stage(:package) { build_package! }
|
|
187
216
|
|
|
188
217
|
print_build_summary(:success)
|
|
@@ -295,7 +324,7 @@ module RosettAi
|
|
|
295
324
|
end
|
|
296
325
|
|
|
297
326
|
def check_ronn_available!
|
|
298
|
-
ronn_source = project_root.join('doc', 'man', '
|
|
327
|
+
ronn_source = project_root.join('doc', 'man', 'raictl.1.ronn')
|
|
299
328
|
return unless ronn_source.exist?
|
|
300
329
|
|
|
301
330
|
begin
|
|
@@ -560,10 +589,25 @@ module RosettAi
|
|
|
560
589
|
log_verbose("Installed conffile to #{etc_dir.join('settings.json')}")
|
|
561
590
|
end
|
|
562
591
|
|
|
592
|
+
# -- systemd -----------------------------------------------------------
|
|
593
|
+
|
|
594
|
+
def install_systemd_unit!
|
|
595
|
+
systemd_src = packaging_dir.join('lib', 'systemd')
|
|
596
|
+
return log_verbose('No systemd unit source found — skipping') unless systemd_src.directory?
|
|
597
|
+
|
|
598
|
+
systemd_dest = staging_install.join('lib', 'systemd')
|
|
599
|
+
FileUtils.mkdir_p(systemd_dest)
|
|
600
|
+
|
|
601
|
+
Dir.glob(systemd_src.join('*').to_s).each do |src_path|
|
|
602
|
+
FileUtils.cp_r(src_path, systemd_dest)
|
|
603
|
+
log_verbose("Installed #{File.basename(src_path)} to #{systemd_dest}")
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
|
|
563
607
|
# -- man pages ---------------------------------------------------------
|
|
564
608
|
|
|
565
609
|
def install_man_pages!
|
|
566
|
-
ronn_source = project_root.join('doc', 'man', '
|
|
610
|
+
ronn_source = project_root.join('doc', 'man', 'raictl.1.ronn')
|
|
567
611
|
return log_verbose('No man page source found — skipping') unless ronn_source.exist?
|
|
568
612
|
|
|
569
613
|
man_dir = staging_dir.join('usr', 'share', 'man', 'man1')
|
|
@@ -590,6 +634,39 @@ module RosettAi
|
|
|
590
634
|
log_verbose("Installed build info to #{dest}")
|
|
591
635
|
end
|
|
592
636
|
|
|
637
|
+
# -- shebang rewrite ---------------------------------------------------
|
|
638
|
+
|
|
639
|
+
# ruby-build compiles with the staging prefix as --prefix, so scripts
|
|
640
|
+
# in embedded/bin/ (gem, bundle, rake, irb, …) carry the build-time
|
|
641
|
+
# staging path in their shebang. Rewrite all ruby-shebang scripts to
|
|
642
|
+
# the runtime path AFTER gem installation (which still needs the
|
|
643
|
+
# staging shebang to run bundle) and BEFORE packaging.
|
|
644
|
+
def rewrite_shebangs!
|
|
645
|
+
spinner = build_spinner('Rewriting embedded bin shebangs...')
|
|
646
|
+
bin_dir = staging_embedded.join('bin')
|
|
647
|
+
count = count_shebang_rewrites(bin_dir, '#!/opt/rosett-ai/embedded/bin/ruby')
|
|
648
|
+
log_verbose("Rewrote #{count} shebang(s) in #{bin_dir}")
|
|
649
|
+
spinner.success(Rainbow(" done (#{count} scripts)").green)
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
def count_shebang_rewrites(bin_dir, target)
|
|
653
|
+
return 0 unless bin_dir.directory?
|
|
654
|
+
|
|
655
|
+
bin_dir.each_child.count { |path| !path.directory? && rewrite_ruby_shebang!(path, target) }
|
|
656
|
+
end
|
|
657
|
+
|
|
658
|
+
def rewrite_ruby_shebang!(path, target)
|
|
659
|
+
content = path.binread
|
|
660
|
+
return unless content.start_with?('#!')
|
|
661
|
+
|
|
662
|
+
nl = content.index("\n") || content.length
|
|
663
|
+
first_line = content[0, nl]
|
|
664
|
+
return unless first_line.include?('ruby') && first_line.strip != target
|
|
665
|
+
|
|
666
|
+
path.binwrite("#{target}#{content[nl..]}")
|
|
667
|
+
true
|
|
668
|
+
end
|
|
669
|
+
|
|
593
670
|
def build_info_content
|
|
594
671
|
<<~INFO
|
|
595
672
|
version=#{RosettAi::VERSION}
|
|
@@ -741,8 +818,10 @@ module RosettAi
|
|
|
741
818
|
install_gems: 'Install gems (deployment)',
|
|
742
819
|
install_wrapper: 'Install wrapper script',
|
|
743
820
|
install_config: 'Install default config',
|
|
821
|
+
install_systemd: 'Install systemd unit',
|
|
744
822
|
install_man: 'Install man pages',
|
|
745
823
|
install_build_info: 'Install build info',
|
|
824
|
+
rewrite_shebangs: 'Rewrite embedded bin shebangs',
|
|
746
825
|
package: 'Build .deb with fpm'
|
|
747
826
|
}.fetch(stage, stage.to_s)
|
|
748
827
|
end
|
|
@@ -848,6 +927,7 @@ module RosettAi
|
|
|
848
927
|
|
|
849
928
|
default_task :create
|
|
850
929
|
|
|
930
|
+
# @return [String] Base installation path for engine plugins.
|
|
851
931
|
INSTALL_BASE = '/opt/rosett-ai/embedded/lib/ruby/gems'
|
|
852
932
|
|
|
853
933
|
desc 'create', 'Build a .deb package for an rosett-ai engine plugin'
|
|
@@ -885,6 +965,9 @@ module RosettAi
|
|
|
885
965
|
default: 1,
|
|
886
966
|
desc: 'Package build iteration (release number)'
|
|
887
967
|
|
|
968
|
+
# Build a .deb package for an engine plugin.
|
|
969
|
+
#
|
|
970
|
+
# @return [void]
|
|
888
971
|
def create
|
|
889
972
|
resolve_engine_dir!
|
|
890
973
|
detect_gemspec!
|
|
@@ -30,6 +30,7 @@ module RosettAi
|
|
|
30
30
|
--simulate: Dry run with diffs, no file writes
|
|
31
31
|
--vendor: Write compile.lock.yml lockfile
|
|
32
32
|
--engine NAME: Compile for specific engine
|
|
33
|
+
--scope SCOPE: Compile scope (global/project/auto)
|
|
33
34
|
--strict: Treat warnings as errors
|
|
34
35
|
--locales: Compile locale files to gettext/Qt formats
|
|
35
36
|
|
|
@@ -39,6 +40,8 @@ module RosettAi
|
|
|
39
40
|
|
|
40
41
|
raictl compile
|
|
41
42
|
raictl compile --verbose --simulate
|
|
43
|
+
raictl compile --scope global
|
|
44
|
+
raictl compile --scope project
|
|
42
45
|
raictl compile --engine generic --strict
|
|
43
46
|
raictl compile --vendor
|
|
44
47
|
raictl compile --locales
|
|
@@ -73,11 +76,18 @@ module RosettAi
|
|
|
73
76
|
type: :boolean,
|
|
74
77
|
default: false,
|
|
75
78
|
desc: 'Treat warnings as errors'
|
|
79
|
+
method_option :scope,
|
|
80
|
+
type: :string,
|
|
81
|
+
default: 'auto',
|
|
82
|
+
enum: ['global', 'project', 'auto'],
|
|
83
|
+
desc: 'Compile scope: global (~/.claude/rules/), project (.claude/rules/), or auto-detect'
|
|
76
84
|
method_option :locales,
|
|
77
85
|
type: :boolean,
|
|
78
86
|
default: false,
|
|
79
87
|
desc: 'Compile locale files to gettext and Qt formats'
|
|
80
88
|
|
|
89
|
+
# Generate the compiled output.
|
|
90
|
+
# @return [void]
|
|
81
91
|
def generate
|
|
82
92
|
if options[:locales]
|
|
83
93
|
compile_locales
|
|
@@ -153,8 +163,17 @@ module RosettAi
|
|
|
153
163
|
end
|
|
154
164
|
|
|
155
165
|
def detect_compile_scope
|
|
156
|
-
|
|
157
|
-
|
|
166
|
+
case options[:scope]
|
|
167
|
+
when 'global'
|
|
168
|
+
:global
|
|
169
|
+
when 'project'
|
|
170
|
+
raise RosettAi::CompileError, t('compile.scope_project_no_project') unless RosettAi.context.project?
|
|
171
|
+
|
|
172
|
+
:project
|
|
173
|
+
else # 'auto'
|
|
174
|
+
ctx = RosettAi.context
|
|
175
|
+
ctx.project? && !ctx.rai_internal? ? :project : :global
|
|
176
|
+
end
|
|
158
177
|
end
|
|
159
178
|
|
|
160
179
|
def check_xdg_migration
|
|
@@ -236,30 +255,18 @@ module RosettAi
|
|
|
236
255
|
RosettAi.paths.rules_dir
|
|
237
256
|
end
|
|
238
257
|
|
|
239
|
-
# Resolves the target directory for a compiled output
|
|
240
|
-
# declared scope. Falls back to the pipeline's target_dir when no
|
|
241
|
-
# scope is declared or the behaviour's scope matches the pipeline's.
|
|
258
|
+
# Resolves the target directory for a compiled output.
|
|
242
259
|
#
|
|
243
|
-
#
|
|
244
|
-
#
|
|
245
|
-
#
|
|
246
|
-
#
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if RosettAi.context.project?
|
|
254
|
-
RosettAi.context.project_root.join('.claude', 'rules')
|
|
255
|
-
else
|
|
256
|
-
compiler.target_dir
|
|
257
|
-
end
|
|
258
|
-
when 'global', 'personal'
|
|
259
|
-
RosettAi.paths.rules_dir
|
|
260
|
-
else
|
|
261
|
-
compiler.target_dir
|
|
262
|
-
end
|
|
260
|
+
# Always returns the pipeline's target_dir to prevent cross-directory
|
|
261
|
+
# writes. The pipeline scope (global vs project) already determines
|
|
262
|
+
# the correct output directory. Per-file scope metadata is preserved
|
|
263
|
+
# in lockfile output but does not affect write location.
|
|
264
|
+
#
|
|
265
|
+
# Previously, per-file scope: global/personal routed to
|
|
266
|
+
# ~/.claude/rules/ even during project-scope compilation, causing
|
|
267
|
+
# Claude Code to load duplicate rules from both directories.
|
|
268
|
+
def resolve_scoped_target_dir(compiler, _info)
|
|
269
|
+
compiler.target_dir
|
|
263
270
|
end
|
|
264
271
|
|
|
265
272
|
def compile_locales
|
|
@@ -296,10 +303,17 @@ module RosettAi
|
|
|
296
303
|
|
|
297
304
|
compiled.each do |filename, info|
|
|
298
305
|
target_dir = resolve_scoped_target_dir(compiler, info)
|
|
299
|
-
target_path = target_dir.join(filename)
|
|
300
306
|
content = info[:content]
|
|
301
307
|
new_checksum = compiler.checksum(content)
|
|
302
308
|
|
|
309
|
+
if deduplicate_against_global?(compiler, target_dir, filename, new_checksum)
|
|
310
|
+
cleanup_stale_project_copy(target_dir, filename) unless options[:simulate]
|
|
311
|
+
results[:skipped] << filename
|
|
312
|
+
log_verbose(t('compile.deduplicated_detail', filename: filename))
|
|
313
|
+
next
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
target_path = target_dir.join(filename)
|
|
303
317
|
ctx = CompileFileContext.new(
|
|
304
318
|
target_path: target_path, content: content, checksum: new_checksum, filename: filename
|
|
305
319
|
)
|
|
@@ -313,6 +327,32 @@ module RosettAi
|
|
|
313
327
|
results
|
|
314
328
|
end
|
|
315
329
|
|
|
330
|
+
# Checks whether a file should be deduplicated against the global
|
|
331
|
+
# rules directory. In project scope, if a compiled file is identical
|
|
332
|
+
# to its global counterpart in ~/.claude/rules/, writing it to the
|
|
333
|
+
# project .claude/rules/ would cause Claude Code to load it twice.
|
|
334
|
+
#
|
|
335
|
+
# @return [Boolean] true if the file should be skipped
|
|
336
|
+
def deduplicate_against_global?(compiler, target_dir, filename, checksum)
|
|
337
|
+
return false unless compiler.scope == :project
|
|
338
|
+
|
|
339
|
+
global_dir = RosettAi.paths.rules_dir
|
|
340
|
+
return false if target_dir.to_s == global_dir.to_s
|
|
341
|
+
|
|
342
|
+
global_file = global_dir.join(filename)
|
|
343
|
+
return false unless global_file.exist?
|
|
344
|
+
|
|
345
|
+
global_checksum = compiler.checksum(File.read(global_file, encoding: 'utf-8'))
|
|
346
|
+
checksum == global_checksum
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
# Removes a stale project-scope copy that was previously compiled
|
|
350
|
+
# but is now deduplicated against the global version.
|
|
351
|
+
def cleanup_stale_project_copy(target_dir, filename)
|
|
352
|
+
stale_path = target_dir.join(filename)
|
|
353
|
+
File.delete(stale_path) if stale_path.exist?
|
|
354
|
+
end
|
|
355
|
+
|
|
316
356
|
def handle_simulate(compiler, ctx, results)
|
|
317
357
|
if File.exist?(ctx.target_path)
|
|
318
358
|
diff_output = compiler.diff(ctx.target_path, ctx.content)
|
|
@@ -366,7 +406,7 @@ module RosettAi
|
|
|
366
406
|
def remove_orphans(compiler, compiled)
|
|
367
407
|
# Guard: when compile produced no output (e.g. empty project conf/),
|
|
368
408
|
# every managed file in target_dir would appear orphaned. Removing
|
|
369
|
-
# them would silently destroy all compiled rules.
|
|
409
|
+
# them would silently destroy all compiled rules.
|
|
370
410
|
return if compiled.empty?
|
|
371
411
|
|
|
372
412
|
orphans = compiler.orphaned_files(compiled.keys)
|
|
@@ -389,11 +429,15 @@ module RosettAi
|
|
|
389
429
|
end
|
|
390
430
|
|
|
391
431
|
def print_summary(results)
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
432
|
+
label_map = {
|
|
433
|
+
created: t('compile.created'),
|
|
434
|
+
updated: t('compile.updated'),
|
|
435
|
+
unchanged: t('compile.unchanged', filename: ''),
|
|
436
|
+
skipped: t('compile.deduplicated')
|
|
437
|
+
}
|
|
438
|
+
rows = label_map.filter_map do |key, label|
|
|
439
|
+
[label, results[key].size] unless results[key].empty?
|
|
440
|
+
end
|
|
397
441
|
return if rows.empty?
|
|
398
442
|
|
|
399
443
|
puts
|
|
@@ -15,6 +15,7 @@ module RosettAi
|
|
|
15
15
|
# @author hugo
|
|
16
16
|
# @author claude
|
|
17
17
|
class Completion < ::Thor
|
|
18
|
+
# @return [Hash] Shell-specific completion installation paths.
|
|
18
19
|
INSTALL_PATHS = {
|
|
19
20
|
'bash' => '/usr/share/bash-completion/completions/rai',
|
|
20
21
|
'zsh' => '/usr/share/zsh/vendor-completions/_rai',
|
|
@@ -29,6 +30,8 @@ module RosettAi
|
|
|
29
30
|
|
|
30
31
|
Related: completion zsh, completion fish, completion install
|
|
31
32
|
LONGDESC
|
|
33
|
+
# Generate bash shell completion script.
|
|
34
|
+
# @return [void]
|
|
32
35
|
def bash
|
|
33
36
|
output_completion('bash')
|
|
34
37
|
end
|
|
@@ -41,6 +44,8 @@ module RosettAi
|
|
|
41
44
|
|
|
42
45
|
Related: completion bash, completion fish, completion install
|
|
43
46
|
LONGDESC
|
|
47
|
+
# Generate zsh shell completion script.
|
|
48
|
+
# @return [void]
|
|
44
49
|
def zsh
|
|
45
50
|
output_completion('zsh')
|
|
46
51
|
end
|
|
@@ -53,6 +58,8 @@ module RosettAi
|
|
|
53
58
|
|
|
54
59
|
Related: completion bash, completion zsh, completion install
|
|
55
60
|
LONGDESC
|
|
61
|
+
# Generate fish shell completion script.
|
|
62
|
+
# @return [void]
|
|
56
63
|
def fish
|
|
57
64
|
output_completion('fish')
|
|
58
65
|
end
|
|
@@ -78,6 +85,8 @@ module RosettAi
|
|
|
78
85
|
LONGDESC
|
|
79
86
|
method_option :shell, type: :string, default: nil,
|
|
80
87
|
desc: 'Shell to install for (auto-detected from $SHELL)'
|
|
88
|
+
# Install the component.
|
|
89
|
+
# @return [void]
|
|
81
90
|
def install
|
|
82
91
|
shell = detect_shell
|
|
83
92
|
generator = RosettAi::Completion::Generator.new
|
|
@@ -46,6 +46,8 @@ module RosettAi
|
|
|
46
46
|
desc: 'Run SPDX header checks only'
|
|
47
47
|
method_option :format, type: :string, enum: ['table', 'json'], default: 'table',
|
|
48
48
|
desc: 'Output format'
|
|
49
|
+
# Run the check and return results.
|
|
50
|
+
# @return [Hash]
|
|
49
51
|
def check
|
|
50
52
|
checks = selected_checks
|
|
51
53
|
results = RosettAi::Comply::Runner.new(
|
|
@@ -11,7 +11,7 @@ module RosettAi
|
|
|
11
11
|
module Thor
|
|
12
12
|
module Tasks
|
|
13
13
|
# Thor task for compiling engine configuration YAML to settings JSON.
|
|
14
|
-
class Config < ::Thor
|
|
14
|
+
class Config < ::Thor # rubocop:disable Metrics/ClassLength
|
|
15
15
|
default_task :compile
|
|
16
16
|
|
|
17
17
|
desc 'show SCOPE', 'Display compiled configuration for a scope with secrets masked'
|
|
@@ -36,6 +36,10 @@ module RosettAi
|
|
|
36
36
|
method_option :engine, type: :string, default: nil,
|
|
37
37
|
desc: 'Engine name (default: configured default)'
|
|
38
38
|
|
|
39
|
+
# Display detailed information for the named item.
|
|
40
|
+
#
|
|
41
|
+
# @param scope [Object] the scope
|
|
42
|
+
# @return [void]
|
|
39
43
|
def show(scope)
|
|
40
44
|
scope = RosettAi::TextSanitizer.normalize_nfc(scope)
|
|
41
45
|
compiler = resolve_config_compiler(simulate: true, masking: true)
|
|
@@ -58,6 +62,12 @@ module RosettAi
|
|
|
58
62
|
--simulate: Dry run without writing files
|
|
59
63
|
--scope NAME: Compile only one scope (managed, user, project, local)
|
|
60
64
|
--engine NAME: Compile for specific engine
|
|
65
|
+
--strict: Replace target entirely — do not preserve uncategorized entries
|
|
66
|
+
|
|
67
|
+
The default (non-strict) compile MERGES with the existing target file,
|
|
68
|
+
preserving any entries not present in the source YAML scopes and emitting
|
|
69
|
+
a warning for each. Use --strict to restore the old replace-all behaviour.
|
|
70
|
+
Run `raictl backfill-user-yml` to capture preserved entries into source.
|
|
61
71
|
|
|
62
72
|
Exit codes: 1 if any scope fails to compile
|
|
63
73
|
|
|
@@ -66,8 +76,9 @@ module RosettAi
|
|
|
66
76
|
raictl config compile
|
|
67
77
|
raictl config compile --verbose --simulate
|
|
68
78
|
raictl config compile --scope managed --engine claude
|
|
79
|
+
raictl config compile --strict
|
|
69
80
|
|
|
70
|
-
Related commands: raictl config show, rai compile
|
|
81
|
+
Related commands: raictl config show, raictl backfill-user-yml, rai compile
|
|
71
82
|
LONGDESC
|
|
72
83
|
method_option :verbose, type: :boolean, default: false,
|
|
73
84
|
desc: 'Show detailed output'
|
|
@@ -77,9 +88,13 @@ module RosettAi
|
|
|
77
88
|
desc: 'Compile specific scope only (managed, user, project, local)'
|
|
78
89
|
method_option :engine, type: :string, default: nil,
|
|
79
90
|
desc: 'Engine name (default: configured default)'
|
|
91
|
+
method_option :strict, type: :boolean, default: false,
|
|
92
|
+
desc: 'Replace target entirely — do not preserve uncategorized entries'
|
|
80
93
|
|
|
94
|
+
# Compile the configuration.
|
|
95
|
+
# @return [void]
|
|
81
96
|
def compile
|
|
82
|
-
compiler = resolve_config_compiler(simulate: options[:simulate])
|
|
97
|
+
compiler = resolve_config_compiler(simulate: options[:simulate], strict: options[:strict])
|
|
83
98
|
|
|
84
99
|
results = if options[:scope]
|
|
85
100
|
scope_path = find_scope_file(options[:scope], compiler)
|
|
@@ -110,7 +125,7 @@ module RosettAi
|
|
|
110
125
|
options[:engine] || RosettAi.rai_config.default_engine
|
|
111
126
|
end
|
|
112
127
|
|
|
113
|
-
def resolve_config_compiler(simulate: false, masking: false)
|
|
128
|
+
def resolve_config_compiler(simulate: false, masking: false, strict: false)
|
|
114
129
|
engine_name = resolve_engine_name
|
|
115
130
|
|
|
116
131
|
unless RosettAi::Plugins::Registry.registered?(:engine, engine_name)
|
|
@@ -128,7 +143,8 @@ module RosettAi
|
|
|
128
143
|
end
|
|
129
144
|
|
|
130
145
|
secret_resolver = masking ? RosettAi::Config::MaskingSecretResolver.new : nil
|
|
131
|
-
plugin.config_compiler_class.new(simulate: simulate, secret_resolver: secret_resolver
|
|
146
|
+
plugin.config_compiler_class.new(simulate: simulate, secret_resolver: secret_resolver,
|
|
147
|
+
strict: strict)
|
|
132
148
|
end
|
|
133
149
|
|
|
134
150
|
def engine_hint(available, engine_name)
|
|
@@ -32,6 +32,8 @@ module RosettAi
|
|
|
32
32
|
LONGDESC
|
|
33
33
|
method_option :available, type: :boolean, default: false,
|
|
34
34
|
desc: 'Show all available packs with tier labels'
|
|
35
|
+
# List available items.
|
|
36
|
+
# @return [void]
|
|
35
37
|
def list
|
|
36
38
|
if options[:available]
|
|
37
39
|
list_available
|
|
@@ -53,6 +55,10 @@ module RosettAi
|
|
|
53
55
|
|
|
54
56
|
Related commands: raictl content list --available, rai license status
|
|
55
57
|
LONGDESC
|
|
58
|
+
# Install the component.
|
|
59
|
+
#
|
|
60
|
+
# @param pack_name [Object] the pack name
|
|
61
|
+
# @return [void]
|
|
56
62
|
def install(pack_name)
|
|
57
63
|
result = validate_license!
|
|
58
64
|
tier = result[:tier]
|
|
@@ -85,6 +91,8 @@ module RosettAi
|
|
|
85
91
|
|
|
86
92
|
Related commands: raictl content list, rai license status
|
|
87
93
|
LONGDESC
|
|
94
|
+
# Update to the latest version.
|
|
95
|
+
# @return [void]
|
|
88
96
|
def update
|
|
89
97
|
validate_license!
|
|
90
98
|
registry = RosettAi::Content::PackRegistry.new
|
|
@@ -21,14 +21,19 @@ module RosettAi
|
|
|
21
21
|
# @author hugo
|
|
22
22
|
# @author claude
|
|
23
23
|
class DBus < ::Thor
|
|
24
|
+
# @return [Integer] Exit code for successful D-Bus operation.
|
|
24
25
|
EXIT_SUCCESS = 0
|
|
26
|
+
# @return [Integer] Exit code for D-Bus connection failure.
|
|
25
27
|
EXIT_DBUS_FAILURE = 1
|
|
28
|
+
# @return [Integer] Exit code for missing D-Bus dependency.
|
|
26
29
|
EXIT_MISSING_DEPENDENCY = 5
|
|
27
30
|
|
|
31
|
+
# @return [Array] Environment variables checked for compositor detection.
|
|
28
32
|
ENV_VARS = [
|
|
29
33
|
'SWAYSOCK', 'I3SOCK', 'HYPRLAND_INSTANCE_SIGNATURE', 'DISPLAY', 'WAYLAND_DISPLAY', 'XDG_RUNTIME_DIR', 'XDG_SESSION_TYPE'
|
|
30
34
|
].freeze
|
|
31
35
|
|
|
36
|
+
# @return [Hash] Maps compositor names to focus adapter classes.
|
|
32
37
|
ADAPTER_MAP = {
|
|
33
38
|
sway: 'I3Adapter (i3ipc)',
|
|
34
39
|
i3: 'I3Adapter (i3ipc)',
|
|
@@ -54,6 +59,8 @@ module RosettAi
|
|
|
54
59
|
|
|
55
60
|
Related commands: raictl dbus start, rai dbus detect
|
|
56
61
|
LONGDESC
|
|
62
|
+
# Return the current status.
|
|
63
|
+
# @return [String]
|
|
57
64
|
def status
|
|
58
65
|
require_desktop_gems!
|
|
59
66
|
check_dbus_availability
|
|
@@ -90,6 +97,8 @@ module RosettAi
|
|
|
90
97
|
default: false,
|
|
91
98
|
aliases: '-d',
|
|
92
99
|
desc: 'Run as daemon (background)'
|
|
100
|
+
# Start the adapter or service.
|
|
101
|
+
# @return [void]
|
|
93
102
|
def start
|
|
94
103
|
require_desktop_gems!
|
|
95
104
|
check_dbus_availability
|
|
@@ -121,6 +130,8 @@ module RosettAi
|
|
|
121
130
|
|
|
122
131
|
Related commands: raictl dbus start, rai dbus status
|
|
123
132
|
LONGDESC
|
|
133
|
+
# Stop the adapter or service.
|
|
134
|
+
# @return [void]
|
|
124
135
|
def stop
|
|
125
136
|
require_desktop_gems!
|
|
126
137
|
unless service_running?
|
|
@@ -145,6 +156,8 @@ module RosettAi
|
|
|
145
156
|
|
|
146
157
|
Related commands: raictl dbus status, rai dbus start
|
|
147
158
|
LONGDESC
|
|
159
|
+
# Detect available engines on the system.
|
|
160
|
+
# @return [Array<Hash>]
|
|
148
161
|
def detect
|
|
149
162
|
require_desktop_gems!
|
|
150
163
|
compositor = RosettAi::DBus::CompositorDetector.detect
|
|
@@ -29,6 +29,8 @@ module RosettAi
|
|
|
29
29
|
|
|
30
30
|
Related commands: raictl desktop status, rai dbus start
|
|
31
31
|
LONGDESC
|
|
32
|
+
# Launch the GTK4 desktop application.
|
|
33
|
+
# @return [void]
|
|
32
34
|
def gtk4
|
|
33
35
|
require_desktop_gems!
|
|
34
36
|
unless RosettAi::Desktop::Gtk4App.available?
|
|
@@ -52,6 +54,8 @@ module RosettAi
|
|
|
52
54
|
|
|
53
55
|
Related commands: raictl desktop gtk4, rai dbus status
|
|
54
56
|
LONGDESC
|
|
57
|
+
# Return the current status.
|
|
58
|
+
# @return [String]
|
|
55
59
|
def status
|
|
56
60
|
require_desktop_gems!
|
|
57
61
|
gtk4_available = RosettAi::Desktop::Gtk4App.available?
|
|
@@ -33,6 +33,8 @@ module RosettAi
|
|
|
33
33
|
method_option :check, type: :string, desc: 'Run only the named check'
|
|
34
34
|
method_option :format, type: :string, enum: ['table', 'json'], default: 'table',
|
|
35
35
|
desc: 'Output format'
|
|
36
|
+
# Return the current status.
|
|
37
|
+
# @return [String]
|
|
36
38
|
def status
|
|
37
39
|
validate_check_name!(options[:check]) if options[:check]
|
|
38
40
|
results = RosettAi::Doctor.run_all(only: options[:check])
|
|
@@ -13,6 +13,7 @@ module RosettAi
|
|
|
13
13
|
module Tasks
|
|
14
14
|
# Documentation management tasks
|
|
15
15
|
class Documentation < ::Thor
|
|
16
|
+
# @return [Hash] Terminal color codes for documentation types.
|
|
16
17
|
TYPE_COLORS = {
|
|
17
18
|
lib: :cyan, behaviour: :magenta, dependency: :yellow, reference: :blue
|
|
18
19
|
}.freeze
|
|
@@ -53,6 +54,8 @@ module RosettAi
|
|
|
53
54
|
default: false,
|
|
54
55
|
desc: 'Skip LaTeX reference document compilation'
|
|
55
56
|
|
|
57
|
+
# Update to the latest version.
|
|
58
|
+
# @return [void]
|
|
56
59
|
def update
|
|
57
60
|
changes = scan_with_spinner
|
|
58
61
|
return puts Paint[t('no_updates'), :yellow] if changes.empty?
|
|
@@ -76,6 +79,8 @@ module RosettAi
|
|
|
76
79
|
|
|
77
80
|
Related commands: update, translate
|
|
78
81
|
LONGDESC
|
|
82
|
+
# Return the current status.
|
|
83
|
+
# @return [String]
|
|
79
84
|
def status
|
|
80
85
|
display_status_header
|
|
81
86
|
display_doc_files
|
|
@@ -107,6 +112,8 @@ module RosettAi
|
|
|
107
112
|
required: true,
|
|
108
113
|
desc: 'Target locale'
|
|
109
114
|
|
|
115
|
+
# Translate documentation to the target locale.
|
|
116
|
+
# @return [void]
|
|
110
117
|
def translate(source_file = nil)
|
|
111
118
|
files = source_file ? [source_file] : Dir.glob(RosettAi.root.join('doc', '*.md'))
|
|
112
119
|
|