rosett-ai 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ai-provenance.yml +119 -0
- data/.debride_whitelist +186 -0
- data/.fasterer.yml +29 -0
- data/.mdl_style.rb +10 -0
- data/.mdlrc +3 -0
- data/.mutant.yml +49 -0
- data/.namespace-allowlist +42 -0
- data/.reek.yml +1040 -0
- data/.rosett-ai/config.yml +3 -0
- data/.rspec +5 -0
- data/.rubocop.yml +380 -0
- data/.ruby-version +1 -0
- data/.yamllint +51 -0
- data/.yardopts +12 -0
- data/AI-DISCLOSURE.md +48 -0
- data/CHANGELOG.md +519 -0
- data/CLAUDE.md +141 -0
- data/CONTRIBUTING.md +734 -0
- data/INSTALL.md +154 -0
- data/LICENSE +674 -0
- data/LICENSE.md +675 -0
- data/QUICKSTART.md +73 -0
- data/README.md +366 -0
- data/Rakefile +200 -0
- data/SECURITY.md +114 -0
- data/bin/rai +1 -0
- data/cliff.toml +52 -0
- data/conf/adopt_redactions.yml +8 -0
- data/conf/behaviour/.gitkeep +0 -0
- data/conf/compliance/cra_rules.yml +25 -0
- data/conf/compliance/license_rules.yml +20 -0
- data/conf/design/aaif_alignment.yml +181 -0
- data/conf/design/ab_testing.yml +172 -0
- data/conf/design/accessibility.yml +84 -0
- data/conf/design/ai_authorship.yml +210 -0
- data/conf/design/ai_provenance.yml +224 -0
- data/conf/design/ai_tool_configuration.yml +207 -0
- data/conf/design/architecture.yml +139 -0
- data/conf/design/autocompletion.yml +115 -0
- data/conf/design/backward_compatibility.yml +112 -0
- data/conf/design/behaviour_composition.yml +246 -0
- data/conf/design/build_rake_extraction.yml +57 -0
- data/conf/design/ci_pipeline.yml +100 -0
- data/conf/design/claude_code_configuration.yml +157 -0
- data/conf/design/compiler.yml +128 -0
- data/conf/design/comply.yml +153 -0
- data/conf/design/content_packs.yml +84 -0
- data/conf/design/desktop_integration.yml +289 -0
- data/conf/design/distribution.yml +216 -0
- data/conf/design/doctor.yml +184 -0
- data/conf/design/documentation.yml +152 -0
- data/conf/design/engine_architecture.yml +257 -0
- data/conf/design/error_handling.yml +103 -0
- data/conf/design/feature_flags.yml +142 -0
- data/conf/design/git_hooks.yml +165 -0
- data/conf/design/gui_plugins.yml +475 -0
- data/conf/design/i18n.yml +84 -0
- data/conf/design/integration_testing.yml +56 -0
- data/conf/design/licensing_system.yml +88 -0
- data/conf/design/lifecycle_management.yml +208 -0
- data/conf/design/mcp_integration.yml +207 -0
- data/conf/design/mcp_settings.yml +126 -0
- data/conf/design/migration.yml +56 -0
- data/conf/design/monitoring_observability.yml +194 -0
- data/conf/design/namespace_cleanup.yml +145 -0
- data/conf/design/plugin_test_segregation.yml +145 -0
- data/conf/design/policy_management.yml +229 -0
- data/conf/design/project_management.yml +183 -0
- data/conf/design/rai_mcp_asset_discovery.yml +164 -0
- data/conf/design/rai_mcp_server.yml +605 -0
- data/conf/design/release_management.yml +117 -0
- data/conf/design/retrofit.yml +199 -0
- data/conf/design/retrospective_analyzer.yml +79 -0
- data/conf/design/scope_hierarchy.yml +352 -0
- data/conf/design/security.yml +115 -0
- data/conf/design/session_retrospective.yml +85 -0
- data/conf/design/smart_ui_feedback.yml +89 -0
- data/conf/design/structured_logging.yml +148 -0
- data/conf/design/styles.yml +123 -0
- data/conf/design/test_peer_review.yml +89 -0
- data/conf/design/testing.yml +136 -0
- data/conf/design/threat_model.yml +108 -0
- data/conf/design/ui_framework.yml +111 -0
- data/conf/design/usage_optimization.yml +122 -0
- data/conf/design/version_management.yml +60 -0
- data/conf/design/workflow.yml +227 -0
- data/conf/mcp/server_defaults.yml +42 -0
- data/conf/mcp/trust.yml +21 -0
- data/conf/packaging/core.yml +12 -0
- data/conf/packaging/gtk4.yml +11 -0
- data/conf/packaging/qt6.yml +11 -0
- data/conf/policy/default_deny_list.yml +197 -0
- data/conf/review/cli-command-audit.yml +857 -0
- data/conf/review/design-docs.yml +1064 -0
- data/conf/review/design-questionnaire.yml +153 -0
- data/conf/review/questionnaire.yml +146 -0
- data/conf/review/rosett-ai-core.yml +2919 -0
- data/conf/schemas/ai_config_schema.json +73 -0
- data/conf/schemas/behaviour_schema.json +132 -0
- data/conf/schemas/compliance_rule_schema.json +63 -0
- data/conf/schemas/content_pack_manifest_schema.json +51 -0
- data/conf/schemas/design_schema.json +210 -0
- data/conf/schemas/engine_manifest_schema.json +144 -0
- data/conf/schemas/lockfile_schema.json +74 -0
- data/conf/schemas/mcp_server_schema.json +48 -0
- data/conf/schemas/packaging_schema.json +70 -0
- data/conf/schemas/policy_schema.json +85 -0
- data/conf/schemas/provenance_schema.json +84 -0
- data/conf/schemas/rai_config_schema.json +56 -0
- data/conf/schemas/rai_project_schema.json +20 -0
- data/conf/schemas/scope_hierarchy_schema.json +49 -0
- data/conf/schemas/target_schema.json +67 -0
- data/conf/schemas/tooling_schema.json +65 -0
- data/conf/schemas/workflow_schema.json +112 -0
- data/conf/targets/agents_md.yml +17 -0
- data/conf/targets/claude.yml +12 -0
- data/conf/tooling/tools.yml +58 -0
- data/dist/rosett-ai-mcp.service +48 -0
- data/dist/rosett-ai-mcp.yml.default +45 -0
- data/doc/AAIF_POSITIONING.md +58 -0
- data/doc/ADOPT.md +224 -0
- data/doc/AI_PROVENANCE.md +139 -0
- data/doc/ARCHITECTURE.md +920 -0
- data/doc/BEHAVIOUR.md +409 -0
- data/doc/BUILD.md +138 -0
- data/doc/CI_CD_RECIPES.md +171 -0
- data/doc/CLAUDE_SESSIONS_MOVED.md +16 -0
- data/doc/COMMAND_ANALYSIS.md +229 -0
- data/doc/CONFIGURATION.md +281 -0
- data/doc/DESIGN_AUDIT.md +235 -0
- data/doc/DESIGN_PEER_REVIEW.md +771 -0
- data/doc/DESKTOP.md +447 -0
- data/doc/ENGINES.md +567 -0
- data/doc/ENGINE_DEVELOPMENT_GUIDE.md +417 -0
- data/doc/FEATURE_AUDIT.md +218 -0
- data/doc/IMPLEMENTATION_PLAN.md +669 -0
- data/doc/INCIDENT_REPORT_2026-02-02.md +251 -0
- data/doc/MIGRATION_GUIDE.md +88 -0
- data/doc/PACKAGING.md +232 -0
- data/doc/PROJECT_DASHBOARD.md +153 -0
- data/doc/PULP_DEPLOYMENT.md +164 -0
- data/doc/QUALITY_FIX_SUMMARY.md +110 -0
- data/doc/QUICK_START.md +162 -0
- data/doc/REEK_CONFIGURATION.md +166 -0
- data/doc/REFERENCE.md +253 -0
- data/doc/REFERENCES.md +324 -0
- data/doc/SECURITY_REVIEW_CHECKLIST.md +72 -0
- data/doc/SESSION_2026-02-28_GTK4_HARDENING.md +359 -0
- data/doc/SETUP.md +202 -0
- data/doc/TEST_PEER_REVIEW.md +152 -0
- data/doc/THREAT_MODEL.md +230 -0
- data/doc/USAGE.md +545 -0
- data/doc/USER_MANUAL.md +585 -0
- data/doc/ai_test_review_checklist.md +110 -0
- data/doc/changes/2026-02-18-packaging-fpm.md +155 -0
- data/doc/changes/2026-02-19-testing-infrastructure.md +221 -0
- data/doc/changes/2026-02-20-security-implementation.md +281 -0
- data/doc/changes/2026-02-20-styles-implementation.md +220 -0
- data/doc/changes/2026-02-21-architecture-completion.md +95 -0
- data/doc/changes/2026-02-21-architecture-ui-layer.md +253 -0
- data/doc/changes/2026-02-21-cc-config-implementation.md +108 -0
- data/doc/changes/2026-02-21-ci-pipeline-implementation.md +214 -0
- data/doc/changes/2026-02-21-compiler-multi-target-pipeline.md +241 -0
- data/doc/changes/2026-02-21-config-design-show-commands.md +61 -0
- data/doc/changes/2026-02-21-design-implementation-overview.md +455 -0
- data/doc/changes/2026-02-21-lifecycle-management.md +196 -0
- data/doc/changes/2026-02-21-path-resolver.md +128 -0
- data/doc/changes/2026-02-24-ci-tmpdir-mutant-fetch.md +45 -0
- data/doc/changes/2026-03-01-ci-bundler-strategy.md +120 -0
- data/doc/changes/2026-03-20-security-hardening-phase2.md +163 -0
- data/doc/context/SESSION-HANDOFF.md +69 -0
- data/doc/context/ai-engine-usage-trends-2026.md +80 -0
- data/doc/context/plan-pluggable-engines.md +590 -0
- data/doc/decisions/001-flog-deferred.md +32 -0
- data/doc/decisions/002-path-resolution-strategy.md +158 -0
- data/doc/decisions/003-ui-adapter-selection.md +193 -0
- data/doc/decisions/004-design-document-validation.md +179 -0
- data/doc/decisions/005-package-splitting-strategy.md +200 -0
- data/doc/decisions/006-multi-engine-architecture.md +147 -0
- data/doc/decisions/007-engine-agnostic-pivot.md +219 -0
- data/doc/decisions/008-ci-bundler-strategy.md +129 -0
- data/doc/decisions/009-core-only-v1-release.md +60 -0
- data/doc/decisions/010-engine-debian-packaging.md +66 -0
- data/doc/decisions/011-context-aware-cli.md +71 -0
- data/doc/dependency_decisions.yml +247 -0
- data/doc/issues/001-wrapper-missing-environment-variables.md +197 -0
- data/doc/issues/002-embedded-ruby-wrong-prefix.md +217 -0
- data/doc/issues/003-smoke-test-false-positive.md +127 -0
- data/doc/issues/004-market-research-design-updates.md +109 -0
- data/doc/issues/005-compile-scope-coexistence.md +161 -0
- data/doc/locales/.gitkeep +0 -0
- data/doc/man/rai.1.ronn +505 -0
- data/doc/operations/packaging.md +133 -0
- data/doc/operations/rosett-ai-release.md +65 -0
- data/doc/reference/error-catalog.md +107 -0
- data/doc/reference/rosett-ai-technical-reference.pdf +0 -0
- data/doc/reference/src/Pictures/cover.jpg +0 -0
- data/doc/reference/src/Pictures/head1.jpg +0 -0
- data/doc/reference/src/Pictures/head2.jpg +0 -0
- data/doc/reference/src/Pictures/head3.jpg +0 -0
- data/doc/reference/src/Pictures/head4.jpg +0 -0
- data/doc/reference/src/Pictures/head5.jpg +0 -0
- data/doc/reference/src/Pictures/head6.jpg +0 -0
- data/doc/reference/src/Pictures/head7.jpg +0 -0
- data/doc/reference/src/Pictures/head8.jpg +0 -0
- data/doc/reference/src/StyleInd.ist +4 -0
- data/doc/reference/src/bibliography.bib +79 -0
- data/doc/reference/src/main.tex +1288 -0
- data/doc/reference/src/structure.tex +303 -0
- data/doc/rosett-ai-bookmarks.html +301 -0
- data/kitchen.yml +46 -0
- data/lib/rosett_ai/adopter/executor_resolver.rb +77 -0
- data/lib/rosett_ai/adopter/local_analysis_collector.rb +154 -0
- data/lib/rosett_ai/adopter/rule_adopter.rb +254 -0
- data/lib/rosett_ai/ai_config/config_compiler.rb +111 -0
- data/lib/rosett_ai/ai_config/context_window.rb +55 -0
- data/lib/rosett_ai/ai_config/cost_controls.rb +44 -0
- data/lib/rosett_ai/ai_config/fallback_chain.rb +64 -0
- data/lib/rosett_ai/ai_config/model_router.rb +121 -0
- data/lib/rosett_ai/ai_config/validator.rb +45 -0
- data/lib/rosett_ai/authorship/attribution_compiler.rb +99 -0
- data/lib/rosett_ai/authorship/disclosure_policy.rb +81 -0
- data/lib/rosett_ai/authorship/review_validator.rb +39 -0
- data/lib/rosett_ai/authorship/trailer_generator.rb +88 -0
- data/lib/rosett_ai/backup/compressor.rb +180 -0
- data/lib/rosett_ai/backup/destination.rb +91 -0
- data/lib/rosett_ai/behaviour/manager.rb +156 -0
- data/lib/rosett_ai/compiler/backend.rb +86 -0
- data/lib/rosett_ai/compiler/backends/agents_md_backend.rb +80 -0
- data/lib/rosett_ai/compiler/backends/claude_backend.rb +88 -0
- data/lib/rosett_ai/compiler/backends/generic_backend.rb +15 -0
- data/lib/rosett_ai/compiler/behaviour_compiler.rb +40 -0
- data/lib/rosett_ai/compiler/capability_checker.rb +104 -0
- data/lib/rosett_ai/compiler/compilation_pipeline.rb +361 -0
- data/lib/rosett_ai/compiler/compiled_output.rb +39 -0
- data/lib/rosett_ai/compiler/locale_compiler.rb +250 -0
- data/lib/rosett_ai/compiler/target_profile.rb +112 -0
- data/lib/rosett_ai/completion/generator.rb +101 -0
- data/lib/rosett_ai/completion/shells/bash_generator.rb +126 -0
- data/lib/rosett_ai/completion/shells/fish_generator.rb +78 -0
- data/lib/rosett_ai/completion/shells/zsh_generator.rb +126 -0
- data/lib/rosett_ai/comply/checkers/cra_checker.rb +102 -0
- data/lib/rosett_ai/comply/checkers/license_checker.rb +85 -0
- data/lib/rosett_ai/comply/checkers/spdx_header_checker.rb +98 -0
- data/lib/rosett_ai/comply/reporter.rb +113 -0
- data/lib/rosett_ai/comply/runner.rb +50 -0
- data/lib/rosett_ai/composition/circular_dependency_detector.rb +56 -0
- data/lib/rosett_ai/composition/composer.rb +158 -0
- data/lib/rosett_ai/composition/composition_result.rb +64 -0
- data/lib/rosett_ai/composition/conflict_detector.rb +53 -0
- data/lib/rosett_ai/composition/lockfile.rb +103 -0
- data/lib/rosett_ai/composition/merge_strategy.rb +131 -0
- data/lib/rosett_ai/composition/priority_sorter.rb +29 -0
- data/lib/rosett_ai/composition/scope_resolver.rb +55 -0
- data/lib/rosett_ai/config/compile_result.rb +37 -0
- data/lib/rosett_ai/config/compiler.rb +13 -0
- data/lib/rosett_ai/config/domain_transformer.rb +13 -0
- data/lib/rosett_ai/config/key_map.rb +13 -0
- data/lib/rosett_ai/config/masking_secret_resolver.rb +40 -0
- data/lib/rosett_ai/config/scope_router.rb +13 -0
- data/lib/rosett_ai/config/secret_resolver.rb +125 -0
- data/lib/rosett_ai/configuration.rb +119 -0
- data/lib/rosett_ai/content/content_client.rb +60 -0
- data/lib/rosett_ai/content/pack_installer.rb +117 -0
- data/lib/rosett_ai/content/pack_manifest.rb +50 -0
- data/lib/rosett_ai/content/pack_registry.rb +68 -0
- data/lib/rosett_ai/content_packs/manager.rb +50 -0
- data/lib/rosett_ai/dbus/compositor_detector.rb +77 -0
- data/lib/rosett_ai/dbus/focus_adapters/base.rb +59 -0
- data/lib/rosett_ai/dbus/focus_adapters/gnome_adapter.rb +172 -0
- data/lib/rosett_ai/dbus/focus_adapters/hyprland_adapter.rb +77 -0
- data/lib/rosett_ai/dbus/focus_adapters/i3_adapter.rb +65 -0
- data/lib/rosett_ai/dbus/focus_adapters/kwin_adapter.rb +103 -0
- data/lib/rosett_ai/dbus/focus_adapters/x11_adapter.rb +105 -0
- data/lib/rosett_ai/dbus/focus_monitor_interface.rb +103 -0
- data/lib/rosett_ai/dbus/manager_interface.rb +213 -0
- data/lib/rosett_ai/dbus/plugin_manager_interface.rb +169 -0
- data/lib/rosett_ai/dbus/rate_limiter.rb +89 -0
- data/lib/rosett_ai/dbus/service.rb +121 -0
- data/lib/rosett_ai/dbus/status_notifier_interface.rb +79 -0
- data/lib/rosett_ai/deprecation.rb +79 -0
- data/lib/rosett_ai/desktop/dbus_client.rb +259 -0
- data/lib/rosett_ai/desktop/gtk4_app.rb +371 -0
- data/lib/rosett_ai/desktop/gtk4_preferences.rb +331 -0
- data/lib/rosett_ai/desktop/gui_logger.rb +236 -0
- data/lib/rosett_ai/doctor/check.rb +92 -0
- data/lib/rosett_ai/doctor/checks/cache_health_check.rb +50 -0
- data/lib/rosett_ai/doctor/checks/dbus_availability_check.rb +39 -0
- data/lib/rosett_ai/doctor/checks/engine_detection_check.rb +46 -0
- data/lib/rosett_ai/doctor/checks/file_permission_check.rb +44 -0
- data/lib/rosett_ai/doctor/checks/gem_dependency_check.rb +55 -0
- data/lib/rosett_ai/doctor/checks/ruby_version_check.rb +50 -0
- data/lib/rosett_ai/doctor/checks/stale_config_nncc_check.rb +57 -0
- data/lib/rosett_ai/doctor/checks/stale_home_nncc_check.rb +59 -0
- data/lib/rosett_ai/doctor.rb +81 -0
- data/lib/rosett_ai/documentation/reference_compiler.rb +122 -0
- data/lib/rosett_ai/documentation/translator.rb +62 -0
- data/lib/rosett_ai/engines/base_config_compiler.rb +203 -0
- data/lib/rosett_ai/engines/detector.rb +63 -0
- data/lib/rosett_ai/engines/registry.rb +50 -0
- data/lib/rosett_ai/error_handler.rb +139 -0
- data/lib/rosett_ai/exit_codes.rb +76 -0
- data/lib/rosett_ai/feature_flags.rb +102 -0
- data/lib/rosett_ai/formatting.rb +33 -0
- data/lib/rosett_ai/gem_consistency_checker.rb +199 -0
- data/lib/rosett_ai/git_hooks/chain_detector.rb +86 -0
- data/lib/rosett_ai/git_hooks/installer.rb +175 -0
- data/lib/rosett_ai/git_hooks/script_generator.rb +125 -0
- data/lib/rosett_ai/gitlab/validators/supplementary_gitlab_ci_yaml_validator.rb +79 -0
- data/lib/rosett_ai/i18n/locale_resolver.rb +46 -0
- data/lib/rosett_ai/i18n/utf8_checker.rb +32 -0
- data/lib/rosett_ai/init/config_file_writer.rb +24 -0
- data/lib/rosett_ai/init/directory_builder.rb +38 -0
- data/lib/rosett_ai/init/file_copier.rb +95 -0
- data/lib/rosett_ai/init/global_initializer.rb +28 -0
- data/lib/rosett_ai/init/local_initializer.rb +27 -0
- data/lib/rosett_ai/init/mcp_registrar.rb +109 -0
- data/lib/rosett_ai/init/project_initializer.rb +38 -0
- data/lib/rosett_ai/licensing/license_key.rb +139 -0
- data/lib/rosett_ai/licensing/license_store.rb +64 -0
- data/lib/rosett_ai/licensing/license_validator.rb +60 -0
- data/lib/rosett_ai/licensing/tier.rb +42 -0
- data/lib/rosett_ai/mcp/admin/auditor.rb +88 -0
- data/lib/rosett_ai/mcp/admin/health_checker.rb +81 -0
- data/lib/rosett_ai/mcp/admin/registry.rb +100 -0
- data/lib/rosett_ai/mcp/admin/schema_validator.rb +63 -0
- data/lib/rosett_ai/mcp/enforcement/.gitkeep +0 -0
- data/lib/rosett_ai/mcp/enforcement/hook_generator.rb +197 -0
- data/lib/rosett_ai/mcp/enforcement/validator.rb +215 -0
- data/lib/rosett_ai/mcp/governance.rb +160 -0
- data/lib/rosett_ai/mcp/http_security_config.rb +158 -0
- data/lib/rosett_ai/mcp/instructions.rb +266 -0
- data/lib/rosett_ai/mcp/key_hasher.rb +66 -0
- data/lib/rosett_ai/mcp/keyfile.rb +221 -0
- data/lib/rosett_ai/mcp/middleware/authentication.rb +146 -0
- data/lib/rosett_ai/mcp/middleware/content_type.rb +56 -0
- data/lib/rosett_ai/mcp/middleware/cors.rb +83 -0
- data/lib/rosett_ai/mcp/middleware/origin_validation.rb +73 -0
- data/lib/rosett_ai/mcp/middleware/rate_limit.rb +106 -0
- data/lib/rosett_ai/mcp/middleware/request_size.rb +51 -0
- data/lib/rosett_ai/mcp/plugins.rb +143 -0
- data/lib/rosett_ai/mcp/prompts/compilation_prompt.rb +40 -0
- data/lib/rosett_ai/mcp/prompts/compliance_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/prompts/diagnostics_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/prompts/validation_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/resources/behaviour_resource.rb +127 -0
- data/lib/rosett_ai/mcp/resources/config_resource.rb +72 -0
- data/lib/rosett_ai/mcp/resources/design_resource.rb +58 -0
- data/lib/rosett_ai/mcp/resources/hooks_resource.rb +74 -0
- data/lib/rosett_ai/mcp/resources/provenance_resource.rb +51 -0
- data/lib/rosett_ai/mcp/resources/rules_resource.rb +60 -0
- data/lib/rosett_ai/mcp/resources/schema_resource.rb +72 -0
- data/lib/rosett_ai/mcp/response_helper.rb +46 -0
- data/lib/rosett_ai/mcp/security_logger.rb +60 -0
- data/lib/rosett_ai/mcp/server.rb +212 -0
- data/lib/rosett_ai/mcp/settings/server_installer.rb +112 -0
- data/lib/rosett_ai/mcp/settings/trust_manager.rb +142 -0
- data/lib/rosett_ai/mcp/tools/adopt_tool.rb +70 -0
- data/lib/rosett_ai/mcp/tools/backup_tool.rb +64 -0
- data/lib/rosett_ai/mcp/tools/behaviour_display_tool.rb +72 -0
- data/lib/rosett_ai/mcp/tools/behaviour_list_tool.rb +56 -0
- data/lib/rosett_ai/mcp/tools/behaviour_manage_tool.rb +114 -0
- data/lib/rosett_ai/mcp/tools/behaviour_show_tool.rb +62 -0
- data/lib/rosett_ai/mcp/tools/compile_status_tool.rb +122 -0
- data/lib/rosett_ai/mcp/tools/compile_tool.rb +191 -0
- data/lib/rosett_ai/mcp/tools/comply_tool.rb +79 -0
- data/lib/rosett_ai/mcp/tools/config_compile_tool.rb +71 -0
- data/lib/rosett_ai/mcp/tools/config_status_tool.rb +79 -0
- data/lib/rosett_ai/mcp/tools/content_tool.rb +78 -0
- data/lib/rosett_ai/mcp/tools/context_query_tool.rb +156 -0
- data/lib/rosett_ai/mcp/tools/design_list_tool.rb +57 -0
- data/lib/rosett_ai/mcp/tools/design_show_tool.rb +69 -0
- data/lib/rosett_ai/mcp/tools/doctor_tool.rb +62 -0
- data/lib/rosett_ai/mcp/tools/documentation_status_tool.rb +45 -0
- data/lib/rosett_ai/mcp/tools/engines_tool.rb +84 -0
- data/lib/rosett_ai/mcp/tools/hook_install_tool.rb +190 -0
- data/lib/rosett_ai/mcp/tools/hook_preview_tool.rb +173 -0
- data/lib/rosett_ai/mcp/tools/hooks_status_tool.rb +84 -0
- data/lib/rosett_ai/mcp/tools/init_tool.rb +87 -0
- data/lib/rosett_ai/mcp/tools/license_status_tool.rb +44 -0
- data/lib/rosett_ai/mcp/tools/project_tool.rb +117 -0
- data/lib/rosett_ai/mcp/tools/provenance_tool.rb +97 -0
- data/lib/rosett_ai/mcp/tools/provenance_write_tool.rb +40 -0
- data/lib/rosett_ai/mcp/tools/retrofit_tool.rb +81 -0
- data/lib/rosett_ai/mcp/tools/rule_search_tool.rb +163 -0
- data/lib/rosett_ai/mcp/tools/schema_get_tool.rb +94 -0
- data/lib/rosett_ai/mcp/tools/tooling_tool.rb +86 -0
- data/lib/rosett_ai/mcp/tools/validate_tool.rb +105 -0
- data/lib/rosett_ai/mcp/tools/workflow_execute_tool.rb +74 -0
- data/lib/rosett_ai/mcp/tools/workflow_tool.rb +78 -0
- data/lib/rosett_ai/migration/detector.rb +117 -0
- data/lib/rosett_ai/migration/nncc_config_migrator.rb +94 -0
- data/lib/rosett_ai/migration/nncc_project_migrator.rb +90 -0
- data/lib/rosett_ai/migration/xdg_migrator.rb +123 -0
- data/lib/rosett_ai/package_manager/apt.rb +108 -0
- data/lib/rosett_ai/package_manager/base.rb +68 -0
- data/lib/rosett_ai/package_manager/gem_backend.rb +90 -0
- data/lib/rosett_ai/packaging/variant_config.rb +92 -0
- data/lib/rosett_ai/path_resolver.rb +115 -0
- data/lib/rosett_ai/plugins/contract.rb +43 -0
- data/lib/rosett_ai/plugins/engine_contract.rb +60 -0
- data/lib/rosett_ai/plugins/gui_contract.rb +74 -0
- data/lib/rosett_ai/plugins/mcp_contract.rb +48 -0
- data/lib/rosett_ai/plugins/registry.rb +150 -0
- data/lib/rosett_ai/policy/auditor.rb +41 -0
- data/lib/rosett_ai/policy/deny_list.rb +71 -0
- data/lib/rosett_ai/policy/opt_out_scanner.rb +37 -0
- data/lib/rosett_ai/policy/policy_compiler.rb +84 -0
- data/lib/rosett_ai/policy/protected_files.rb +47 -0
- data/lib/rosett_ai/policy/tier_hierarchy.rb +48 -0
- data/lib/rosett_ai/policy/validator.rb +35 -0
- data/lib/rosett_ai/profiler.rb +79 -0
- data/lib/rosett_ai/project/drift_detector.rb +126 -0
- data/lib/rosett_ai/project/manager.rb +115 -0
- data/lib/rosett_ai/project/sync_manager.rb +138 -0
- data/lib/rosett_ai/project/template_applier.rb +105 -0
- data/lib/rosett_ai/project_context.rb +82 -0
- data/lib/rosett_ai/provenance/entry.rb +63 -0
- data/lib/rosett_ai/provenance/file_source.rb +32 -0
- data/lib/rosett_ai/provenance/source.rb +62 -0
- data/lib/rosett_ai/provenance/store.rb +153 -0
- data/lib/rosett_ai/provenance/tracker.rb +62 -0
- data/lib/rosett_ai/provenance/trailer_generator.rb +43 -0
- data/lib/rosett_ai/provenance/validator.rb +45 -0
- data/lib/rosett_ai/quorum/collector.rb +59 -0
- data/lib/rosett_ai/quorum/comparator.rb +81 -0
- data/lib/rosett_ai/quorum/dispatcher.rb +57 -0
- data/lib/rosett_ai/quorum/strategies/adopt.rb +56 -0
- data/lib/rosett_ai/rai_config.rb +107 -0
- data/lib/rosett_ai/retrofit/base_parser.rb +66 -0
- data/lib/rosett_ai/retrofit/engine.rb +171 -0
- data/lib/rosett_ai/retrofit/parsers/agents_md_parser.rb +50 -0
- data/lib/rosett_ai/retrofit/parsers/claude_parser.rb +69 -0
- data/lib/rosett_ai/retrofit/parsers/cursor_parser.rb +82 -0
- data/lib/rosett_ai/retrofit/round_trip_validator.rb +65 -0
- data/lib/rosett_ai/retrofit/scanner.rb +47 -0
- data/lib/rosett_ai/retrofit/secret_detector.rb +87 -0
- data/lib/rosett_ai/secrets_resolver.rb +71 -0
- data/lib/rosett_ai/smart_feedback/suggester.rb +83 -0
- data/lib/rosett_ai/smart_feedback/thor_middleware.rb +84 -0
- data/lib/rosett_ai/structured_logger.rb +110 -0
- data/lib/rosett_ai/telemetry/json_lines_writer.rb +50 -0
- data/lib/rosett_ai/telemetry/log_rotator.rb +67 -0
- data/lib/rosett_ai/telemetry/provider.rb +26 -0
- data/lib/rosett_ai/telemetry/reporter.rb +144 -0
- data/lib/rosett_ai/telemetry.rb +47 -0
- data/lib/rosett_ai/text_sanitizer.rb +62 -0
- data/lib/rosett_ai/thor/cli.rb +269 -0
- data/lib/rosett_ai/thor/tasks/adopt.rb +250 -0
- data/lib/rosett_ai/thor/tasks/backup.rb +420 -0
- data/lib/rosett_ai/thor/tasks/behaviour.rb +474 -0
- data/lib/rosett_ai/thor/tasks/build.rb +1162 -0
- data/lib/rosett_ai/thor/tasks/compile.rb +415 -0
- data/lib/rosett_ai/thor/tasks/completion.rb +123 -0
- data/lib/rosett_ai/thor/tasks/comply.rb +82 -0
- data/lib/rosett_ai/thor/tasks/config.rb +265 -0
- data/lib/rosett_ai/thor/tasks/content.rb +193 -0
- data/lib/rosett_ai/thor/tasks/dbus.rb +321 -0
- data/lib/rosett_ai/thor/tasks/design.rb +258 -0
- data/lib/rosett_ai/thor/tasks/desktop.rb +129 -0
- data/lib/rosett_ai/thor/tasks/doctor.rb +127 -0
- data/lib/rosett_ai/thor/tasks/documentation.rb +321 -0
- data/lib/rosett_ai/thor/tasks/engines.rb +167 -0
- data/lib/rosett_ai/thor/tasks/hooks.rb +219 -0
- data/lib/rosett_ai/thor/tasks/init.rb +259 -0
- data/lib/rosett_ai/thor/tasks/license.rb +120 -0
- data/lib/rosett_ai/thor/tasks/mcp.rb +535 -0
- data/lib/rosett_ai/thor/tasks/migrate.rb +121 -0
- data/lib/rosett_ai/thor/tasks/plugins.rb +157 -0
- data/lib/rosett_ai/thor/tasks/project.rb +260 -0
- data/lib/rosett_ai/thor/tasks/provenance.rb +195 -0
- data/lib/rosett_ai/thor/tasks/release.rb +314 -0
- data/lib/rosett_ai/thor/tasks/retrofit.rb +90 -0
- data/lib/rosett_ai/thor/tasks/tooling.rb +308 -0
- data/lib/rosett_ai/thor/tasks/validate.rb +108 -0
- data/lib/rosett_ai/thor/tasks/workflow.rb +196 -0
- data/lib/rosett_ai/tooling/ci_yaml_validator.rb +37 -0
- data/lib/rosett_ai/tooling/version_checker.rb +35 -0
- data/lib/rosett_ai/ui/accessible_tui.rb +61 -0
- data/lib/rosett_ai/ui/base.rb +46 -0
- data/lib/rosett_ai/ui/gtk4.rb +98 -0
- data/lib/rosett_ai/ui/kde.rb +40 -0
- data/lib/rosett_ai/ui/qt6.rb +40 -0
- data/lib/rosett_ai/ui/registry.rb +60 -0
- data/lib/rosett_ai/ui/tty_helper.rb +74 -0
- data/lib/rosett_ai/ui/tui.rb +59 -0
- data/lib/rosett_ai/validators/behaviour_validator.rb +20 -0
- data/lib/rosett_ai/validators/design_validator.rb +17 -0
- data/lib/rosett_ai/validators/schema_validator.rb +84 -0
- data/lib/rosett_ai/validators/tooling_validator.rb +17 -0
- data/lib/rosett_ai/version.rb +8 -0
- data/lib/rosett_ai/version_consistency_checker.rb +129 -0
- data/lib/rosett_ai/workflow/audit_log.rb +86 -0
- data/lib/rosett_ai/workflow/engine.rb +142 -0
- data/lib/rosett_ai/workflow/manager.rb +82 -0
- data/lib/rosett_ai/workflow/schema_validator.rb +71 -0
- data/lib/rosett_ai/workflow/step_runner.rb +61 -0
- data/lib/rosett_ai/workflow/steps/prompt_step.rb +62 -0
- data/lib/rosett_ai/workflow/steps/rai_step.rb +74 -0
- data/lib/rosett_ai/workflow/steps/shell_step.rb +53 -0
- data/lib/rosett_ai/yaml_loader.rb +78 -0
- data/lib/rosett_ai.rb +221 -0
- data/lib/rubocop/cop/rosett_ai/shell_interpolation.rb +54 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_const_get.rb +60 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_send.rb +50 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_yaml_load.rb +40 -0
- data/lib/rubocop/rosett_ai.rb +9 -0
- data/lib/scripts/generated/docker_hub_tags.rb +126 -0
- data/locales/.gitkeep +0 -0
- data/locales/ar.yml +579 -0
- data/locales/en.yml +571 -0
- data/locales/fr.yml +567 -0
- data/packaging/build-engine-deb.sh +81 -0
- data/packaging/scripts/postinst +17 -0
- data/packaging/scripts/postrm +19 -0
- data/packaging/scripts/prerm +10 -0
- data/packaging/wrapper.sh.template +38 -0
- data/rosett-ai.gemspec +63 -0
- data/rules/.gitkeep +0 -0
- data/scripts/publish/pulp_upload.sh +123 -0
- data/settings.json +29 -0
- data/share/applications/be.neatnerds.rosettai.desktop +29 -0
- data/share/dbus-1/interfaces/be.neatnerds.rosettai.xml +103 -0
- data/share/dbus-1/services/be.neatnerds.rosettai.service +3 -0
- data/share/templates/behaviour/criticalthinking.yml +69 -0
- metadata +810 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# ADR-002: Path Resolution Strategy
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted (2026-02-21)
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
raictl manages two distinct path domains:
|
|
10
|
+
|
|
11
|
+
1. **Claude Code's directory** (`~/.claude/`) — rules, settings, CLAUDE.md.
|
|
12
|
+
This path is Anthropic's convention, established by Claude Code itself.
|
|
13
|
+
We do not own or control this convention.
|
|
14
|
+
|
|
15
|
+
2. **rosett-ai's own configuration** (`~/.config/rosett-ai/`) — secrets, license keys,
|
|
16
|
+
content packs. This path is already established in our design documents
|
|
17
|
+
(`security.yml`, `licensing_system.yml`, `content_packs.yml`) and
|
|
18
|
+
implemented in `SecretsResolver`.
|
|
19
|
+
|
|
20
|
+
Currently, 6 Thor task files contain hardcoded `~/.claude` paths:
|
|
21
|
+
|
|
22
|
+
| File | Hardcoded path |
|
|
23
|
+
|------|---------------|
|
|
24
|
+
| `lib/rosett_ai/thor/tasks/init.rb` | `File.expand_path('~/.claude')` |
|
|
25
|
+
| `lib/rosett_ai/thor/tasks/backup.rb` | `File.expand_path('~/.claude')` |
|
|
26
|
+
| `lib/rosett_ai/thor/tasks/compile.rb` | `File.expand_path('~/.claude/rules')` |
|
|
27
|
+
| `lib/rosett_ai/thor/tasks/adopt.rb` | `File.expand_path('~/.claude/rules')` |
|
|
28
|
+
| `lib/rosett_ai/compiler/behaviour_compiler.rb` | `~/.claude/rules/` (string literal) |
|
|
29
|
+
| `lib/rosett_ai/thor/tasks/backup.rb` | `File.join(Dir.pwd, '.claude')` (local) |
|
|
30
|
+
|
|
31
|
+
The `architecture.yml` design document lists "hardcoded paths instead of
|
|
32
|
+
XDG-compliant directory resolution" as an anti-pattern (line 64).
|
|
33
|
+
|
|
34
|
+
### XDG Base Directory Specification
|
|
35
|
+
|
|
36
|
+
The [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir/latest/)
|
|
37
|
+
from freedesktop.org defines standard locations for user files:
|
|
38
|
+
|
|
39
|
+
| Variable | Default | Purpose |
|
|
40
|
+
|----------|---------|---------|
|
|
41
|
+
| `XDG_CONFIG_HOME` | `~/.config` | User-specific configuration |
|
|
42
|
+
| `XDG_DATA_HOME` | `~/.local/share` | User-specific data files |
|
|
43
|
+
| `XDG_CACHE_HOME` | `~/.cache` | Non-essential cached data |
|
|
44
|
+
| `XDG_STATE_HOME` | `~/.local/state` | User-specific state data |
|
|
45
|
+
|
|
46
|
+
Desktop environment compliance:
|
|
47
|
+
|
|
48
|
+
| DE | XDG compliant | Notes |
|
|
49
|
+
|----|--------------|-------|
|
|
50
|
+
| GNOME | Yes | freedesktop.org founding member |
|
|
51
|
+
| KDE Plasma | Yes | KDE UserBase documented |
|
|
52
|
+
| XFCE | Yes | Adopted spec |
|
|
53
|
+
| MATE | Yes | GNOME 2 fork, inherited |
|
|
54
|
+
| Cinnamon | Yes | GNOME fork, inherited |
|
|
55
|
+
| Headless/TTY | N/A | No DE; apps read env vars or use defaults |
|
|
56
|
+
| Tiling WMs | N/A | Apps decide individually |
|
|
57
|
+
|
|
58
|
+
Ruby ecosystem: RubyGems 3.0+ follows XDG. Pry follows XDG. Bundler supports
|
|
59
|
+
it with environment variables.
|
|
60
|
+
|
|
61
|
+
Sources:
|
|
62
|
+
[ArchWiki XDG Base Directory](https://wiki.archlinux.org/title/XDG_Base_Directory),
|
|
63
|
+
[freedesktop.org spec](https://specifications.freedesktop.org/basedir/latest/),
|
|
64
|
+
[KDE XDG Hierarchy](https://userbase.kde.org/KDE_System_Administration/XDG_Filesystem_Hierarchy).
|
|
65
|
+
|
|
66
|
+
## Options
|
|
67
|
+
|
|
68
|
+
### Option A: PathResolver (centralise, keep ~/.claude)
|
|
69
|
+
|
|
70
|
+
Create a single `RosettAi::PathResolver` module that owns all path constants.
|
|
71
|
+
Claude Code paths stay at `~/.claude` (respecting upstream convention). rosett-ai's
|
|
72
|
+
own config uses `XDG_CONFIG_HOME/rosett-ai` (defaults to `~/.config/rosett-ai`). All
|
|
73
|
+
hardcoded paths in Thor tasks are replaced with `PathResolver.rules_dir`,
|
|
74
|
+
`PathResolver.global_dir`, etc.
|
|
75
|
+
|
|
76
|
+
Pros:
|
|
77
|
+
|
|
78
|
+
- Single source of truth — one file to update if conventions change
|
|
79
|
+
- Testable: specs override PathResolver methods, no filesystem coupling
|
|
80
|
+
- DE-agnostic: works on any desktop environment or headless
|
|
81
|
+
- Consistent with existing design docs (SecretsResolver already uses
|
|
82
|
+
`~/.config/rosett-ai/`)
|
|
83
|
+
- Respects both upstream convention (Claude Code) and XDG (rosett-ai data)
|
|
84
|
+
|
|
85
|
+
Cons:
|
|
86
|
+
|
|
87
|
+
- Still "hardcodes" `~/.claude`, just centralised in one place
|
|
88
|
+
- New dependency for all path-using code
|
|
89
|
+
|
|
90
|
+
### Option B: Full XDG everywhere
|
|
91
|
+
|
|
92
|
+
Move both Claude Code AND rai config under XDG directories. Claude Code rules
|
|
93
|
+
would move to something like `~/.local/share/rosett-ai/claude/rules`.
|
|
94
|
+
|
|
95
|
+
Pros:
|
|
96
|
+
|
|
97
|
+
- Maximum standards compliance with freedesktop.org
|
|
98
|
+
|
|
99
|
+
Cons:
|
|
100
|
+
|
|
101
|
+
- Breaking change: Claude Code expects `~/.claude/`
|
|
102
|
+
- Users must reconfigure or symlink existing `~/.claude`
|
|
103
|
+
- Fights upstream convention for no practical gain
|
|
104
|
+
- Claude Code itself does not follow XDG
|
|
105
|
+
|
|
106
|
+
### Option C: Status quo + ADR (no code change)
|
|
107
|
+
|
|
108
|
+
Document why we keep `~/.claude` and stop there.
|
|
109
|
+
|
|
110
|
+
Pros:
|
|
111
|
+
|
|
112
|
+
- No code changes needed
|
|
113
|
+
|
|
114
|
+
Cons:
|
|
115
|
+
|
|
116
|
+
- Hardcoded paths remain scattered across 6+ files
|
|
117
|
+
- Every new feature adds more hardcoded paths
|
|
118
|
+
- Testing remains coupled to filesystem (cannot mock paths)
|
|
119
|
+
- Future refactor scope grows with each commit
|
|
120
|
+
- Path changes require grep-and-replace with risk of partial updates
|
|
121
|
+
- architecture.yml anti-pattern stays unresolved
|
|
122
|
+
|
|
123
|
+
## Decision
|
|
124
|
+
|
|
125
|
+
**Option A: PathResolver** — centralise all paths in `RosettAi::PathResolver` with
|
|
126
|
+
dual-domain separation.
|
|
127
|
+
|
|
128
|
+
Rationale:
|
|
129
|
+
|
|
130
|
+
- We do not own `~/.claude` — Anthropic does. Changing it would break the
|
|
131
|
+
Claude Code integration that rosett-ai exists to manage.
|
|
132
|
+
- We already use `~/.config/rosett-ai` for our own data (secrets, future license
|
|
133
|
+
keys, content packs). This is XDG-compliant.
|
|
134
|
+
- Centralising eliminates the scattered-hardcoding anti-pattern without
|
|
135
|
+
fighting upstream conventions.
|
|
136
|
+
- Testability: specs can override `PathResolver.global_dir` or inject a
|
|
137
|
+
mock, removing filesystem coupling from unit tests.
|
|
138
|
+
- If Claude Code ever changes its directory convention, one file changes
|
|
139
|
+
instead of 6+.
|
|
140
|
+
|
|
141
|
+
## Consequences
|
|
142
|
+
|
|
143
|
+
- New file: `lib/rosett_ai/path_resolver.rb` with instance methods (future-proofed
|
|
144
|
+
for ADR-006 multi-engine via `engine:` keyword)
|
|
145
|
+
- All 6 Thor task files + compiler updated to use `RosettAi.paths.*`
|
|
146
|
+
- `~/.config/rosett-ai/` created by `bin/raictl init --global` alongside `~/.claude/`
|
|
147
|
+
- `XDG_CONFIG_HOME` respected for rosett-ai data (non-default setups work)
|
|
148
|
+
- `SecretsResolver` updated to use `RosettAi.paths.rai_config_dir` instead of
|
|
149
|
+
its own hardcoded `File.join(Dir.home, '.config', 'rosett-ai')`
|
|
150
|
+
- `SECRETS_DIR` and `SECRETS_FILE` constants removed from SecretsResolver
|
|
151
|
+
- Lockfile output uses `rules_display_path` (tilde form) for portability
|
|
152
|
+
- Specs use `instance_double(RosettAi::PathResolver)` instead of `stub_const` or
|
|
153
|
+
`allow(File).to receive(:expand_path)` — cleaner, no filesystem coupling
|
|
154
|
+
- Future: if Claude Code changes conventions, one file to update
|
|
155
|
+
|
|
156
|
+
## Implementation
|
|
157
|
+
|
|
158
|
+
Implemented in Phase 3 (2026-02-21). See `doc/changes/2026-02-21-path-resolver.md`.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# ADR-003: UI Adapter Selection Mechanism
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted (2026-02-21) -- implementation deferred to P3
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The `RosettAi::Ui::Registry` pattern is implemented. UI adapters register
|
|
10
|
+
themselves at require time (`Registry.register(:tui, Tui)`), and
|
|
11
|
+
`Registry.resolve(name)` instantiates the requested adapter. Currently only
|
|
12
|
+
the TUI adapter exists and it is selected automatically as the default.
|
|
13
|
+
|
|
14
|
+
When GUI packages (`rosett-ai-gtk4`, `rosett-ai-qt6`) are introduced (P3), users will
|
|
15
|
+
need a mechanism to select which adapter to use. The `architecture.yml` design
|
|
16
|
+
document gives the example `bin/raictl --ui gtk4`, and the `ui_framework.yml`
|
|
17
|
+
document states TUI is the default with GUI packages as separate Debian
|
|
18
|
+
packages.
|
|
19
|
+
|
|
20
|
+
The selection mechanism must be decided now (P2) so the architecture is ready
|
|
21
|
+
for P3 implementation.
|
|
22
|
+
|
|
23
|
+
### Existing precedent
|
|
24
|
+
|
|
25
|
+
raictl already uses an ordered resolution pattern in `SecretsResolver`:
|
|
26
|
+
ENV variable > secrets file > raise error. This pattern is understood and
|
|
27
|
+
tested.
|
|
28
|
+
|
|
29
|
+
### Multi-engine constraint
|
|
30
|
+
|
|
31
|
+
ADR-006 establishes that rosett-ai should be engine-agnostic. The UI adapter
|
|
32
|
+
selection must therefore not depend on any engine-specific configuration
|
|
33
|
+
file (e.g. Claude Code's `settings.json`). The UI adapter is an rosett-ai
|
|
34
|
+
concern and must be resolved from rosett-ai's own configuration.
|
|
35
|
+
|
|
36
|
+
## Options
|
|
37
|
+
|
|
38
|
+
### Option A: Global CLI flag only
|
|
39
|
+
|
|
40
|
+
Add `--ui NAME` as a `class_option` on `Thor::CLI` (inherited by all
|
|
41
|
+
subcommands). Selection happens via `Registry.resolve(options[:ui])`.
|
|
42
|
+
|
|
43
|
+
Pros:
|
|
44
|
+
|
|
45
|
+
- Explicit, visible in help output
|
|
46
|
+
- No configuration infrastructure needed
|
|
47
|
+
|
|
48
|
+
Cons:
|
|
49
|
+
|
|
50
|
+
- Must be passed every invocation
|
|
51
|
+
- No way to set a persistent default
|
|
52
|
+
|
|
53
|
+
### Option B: Config file setting only
|
|
54
|
+
|
|
55
|
+
Add `preferred_ui: gtk4` to rosett-ai's own configuration. Read at startup.
|
|
56
|
+
|
|
57
|
+
Pros:
|
|
58
|
+
|
|
59
|
+
- Set once, works always
|
|
60
|
+
- Aligns with rosett-ai's own config infrastructure
|
|
61
|
+
|
|
62
|
+
Cons:
|
|
63
|
+
|
|
64
|
+
- No quick override for one-off invocations
|
|
65
|
+
|
|
66
|
+
### Option C: Environment variable only
|
|
67
|
+
|
|
68
|
+
Read `RAI_UI` environment variable. Default to `tui` if unset.
|
|
69
|
+
|
|
70
|
+
Pros:
|
|
71
|
+
|
|
72
|
+
- Simple, shell-profile level persistence
|
|
73
|
+
- No code infrastructure needed
|
|
74
|
+
|
|
75
|
+
Cons:
|
|
76
|
+
|
|
77
|
+
- Less discoverable than CLI flag
|
|
78
|
+
- Not visible in `--help` output
|
|
79
|
+
|
|
80
|
+
### Option D: Cascade precedence (revised)
|
|
81
|
+
|
|
82
|
+
Resolution order:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
1. --ui NAME CLI flag override (highest priority)
|
|
86
|
+
2. RAI_UI Environment variable (session-level)
|
|
87
|
+
3. rai config Ordered adapter list (first available wins)
|
|
88
|
+
4. DE auto-detection Detect runtime desktop environment
|
|
89
|
+
5. :tui Always-available fallback (lowest priority)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Each layer is consulted in order. The first layer that produces a result
|
|
93
|
+
wins. Layers 3-5 check adapter availability via `Registry.available?`
|
|
94
|
+
before selecting — an adapter whose package is not installed is skipped.
|
|
95
|
+
|
|
96
|
+
Layer 3 -- rai config adapter list:
|
|
97
|
+
|
|
98
|
+
The rai configuration file (`~/.config/rosett-ai/`) contains an ordered
|
|
99
|
+
array of preferred adapters. The first adapter in the list whose package
|
|
100
|
+
is installed wins:
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
ui:
|
|
104
|
+
adapters:
|
|
105
|
+
- gtk4
|
|
106
|
+
- qt6
|
|
107
|
+
- tui
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Array position is priority — no explicit priority numbers needed. This
|
|
111
|
+
is simpler and YAML arrays are inherently ordered. If per-project
|
|
112
|
+
overrides with cross-source merging are needed in the future, explicit
|
|
113
|
+
priority numbers can be added without breaking the simple form.
|
|
114
|
+
|
|
115
|
+
Layer 4 -- Desktop environment auto-detection:
|
|
116
|
+
|
|
117
|
+
When no explicit preference is configured, rosett-ai detects the running
|
|
118
|
+
desktop environment at runtime via XDG environment variables and selects
|
|
119
|
+
a matching adapter if its package is installed:
|
|
120
|
+
|
|
121
|
+
| Env var | Value | Adapter |
|
|
122
|
+
|---------|-------|---------|
|
|
123
|
+
| `XDG_CURRENT_DESKTOP` | `GNOME` | gtk4 |
|
|
124
|
+
| `XDG_CURRENT_DESKTOP` | `KDE` | qt6 |
|
|
125
|
+
| `XDG_CURRENT_DESKTOP` | `XFCE` | gtk4 (GTK-based) |
|
|
126
|
+
| `XDG_CURRENT_DESKTOP` | `MATE` | gtk4 (GTK-based) |
|
|
127
|
+
| `XDG_CURRENT_DESKTOP` | `Cinnamon` | gtk4 (GTK-based) |
|
|
128
|
+
| `XDG_SESSION_TYPE` | `tty` | tui |
|
|
129
|
+
| Unset / empty | -- | tui |
|
|
130
|
+
|
|
131
|
+
Note: `XDG_CURRENT_DESKTOP` can be colon-separated (e.g. `ubuntu:GNOME`).
|
|
132
|
+
The detection logic must handle this by checking each component.
|
|
133
|
+
|
|
134
|
+
Auto-detection only suggests adapters whose packages are installed. If
|
|
135
|
+
`XDG_CURRENT_DESKTOP=GNOME` but `rosett-ai-gtk4` is not installed, detection
|
|
136
|
+
falls through to TUI.
|
|
137
|
+
|
|
138
|
+
Pros:
|
|
139
|
+
|
|
140
|
+
- Most flexible — covers all use cases
|
|
141
|
+
- Follows principle of least surprise
|
|
142
|
+
- Consistent with existing `SecretsResolver` precedence pattern
|
|
143
|
+
- Users can set-and-forget via env or config
|
|
144
|
+
- Power users can override per-invocation
|
|
145
|
+
- Zero-config experience: install rosett-ai + rosett-ai-gtk4 on GNOME, it just works
|
|
146
|
+
- Users can switch desktop environments without reconfiguring rosett-ai
|
|
147
|
+
- Engine-agnostic: no dependency on any AI engine's config format
|
|
148
|
+
|
|
149
|
+
Cons:
|
|
150
|
+
|
|
151
|
+
- 5 levels to test
|
|
152
|
+
- Debug confusion if user forgets they set an env var or config
|
|
153
|
+
|
|
154
|
+
The debug confusion is mitigated by the `rai config show` command (see
|
|
155
|
+
Consequences below).
|
|
156
|
+
|
|
157
|
+
## Decision
|
|
158
|
+
|
|
159
|
+
**Option D: Cascade precedence (revised)** — because:
|
|
160
|
+
|
|
161
|
+
- Consistent with the existing resolution pattern in `SecretsResolver`
|
|
162
|
+
(ENV > file > raise). Adding a CLI flag as highest priority and
|
|
163
|
+
auto-detection as a smart fallback is a natural extension.
|
|
164
|
+
- Every use case is covered: one-off override (flag), session default
|
|
165
|
+
(env), persistent preference (config), smart default (DE detection),
|
|
166
|
+
and guaranteed fallback (TUI).
|
|
167
|
+
- Engine-agnostic: the cascade uses rosett-ai's own configuration, not any
|
|
168
|
+
engine-specific settings file. This aligns with ADR-006.
|
|
169
|
+
- When `rosett-ai-gtk4` is installed on a GNOME desktop, it works out of the
|
|
170
|
+
box with zero configuration via auto-detection. The user can still
|
|
171
|
+
override with `--ui tui` for a headless session.
|
|
172
|
+
- The cascade is simple to explain: "flag wins, then env, then config
|
|
173
|
+
list, then desktop detection, then TUI".
|
|
174
|
+
|
|
175
|
+
## Consequences
|
|
176
|
+
|
|
177
|
+
Implementation is deferred to P3 (ui_framework), but the architecture is
|
|
178
|
+
documented now:
|
|
179
|
+
|
|
180
|
+
- New `class_option :ui` on `Thor::CLI` (type: string, default: nil)
|
|
181
|
+
- Resolution logic in a `resolve_ui_adapter` method that implements the
|
|
182
|
+
5-level cascade
|
|
183
|
+
- `Registry.resolve` called once at CLI startup with the resolved name
|
|
184
|
+
- `Registry.available?(name)` used at layers 3-5 to skip missing adapters
|
|
185
|
+
- Adapter instance available to tasks that produce output
|
|
186
|
+
- `RAI_UI` documented in `bin/raictl --help` and `doc/USAGE.md`
|
|
187
|
+
- New CLI commands for configuration transparency (P3):
|
|
188
|
+
- `bin/raictl config show` — display full rai configuration
|
|
189
|
+
- `bin/raictl config show ui` — display UI configuration with active
|
|
190
|
+
adapter and resolution source (e.g. "gtk4 (from: DE auto-detection)")
|
|
191
|
+
- Desktop environment detection via `XDG_CURRENT_DESKTOP` and
|
|
192
|
+
`XDG_SESSION_TYPE`, with colon-separated value handling
|
|
193
|
+
- P2 code does not need the flag yet — TUI is the only adapter
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# ADR-004: Design Document Validation
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
|
|
5
|
+
Accepted (2026-02-21)
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
The `architecture.yml` design document (criterion 6) requires that
|
|
10
|
+
`conf/design/` documents are validated against `conf/schemas/design_schema.json`.
|
|
11
|
+
|
|
12
|
+
The schema already exists (206 lines, comprehensive) and covers all required
|
|
13
|
+
fields: name, domain, version, status, intent, constraints, acceptance_criteria,
|
|
14
|
+
plus optional sections for examples, anti_patterns, preferences, assets,
|
|
15
|
+
tui_layout, gui_notes, interactions, and accessibility.
|
|
16
|
+
|
|
17
|
+
There are currently 13 design documents in `conf/design/`. No validation
|
|
18
|
+
infrastructure exists for them.
|
|
19
|
+
|
|
20
|
+
### Existing pattern
|
|
21
|
+
|
|
22
|
+
`RosettAi::Validators::BehaviourValidator` validates behaviour configuration files
|
|
23
|
+
against `conf/schemas/behaviour_schema.json`. It uses JSONSchemer, provides a
|
|
24
|
+
`valid?`/`validate`/`errors` API, and is wired into the CLI via
|
|
25
|
+
`bin/raictl behaviour validate [NAME]`. This is a proven, tested pattern.
|
|
26
|
+
|
|
27
|
+
### Current schema inventory
|
|
28
|
+
|
|
29
|
+
Three schemas exist in `conf/schemas/`, but only one has a validator:
|
|
30
|
+
|
|
31
|
+
| Schema file | Validator class | CLI command | CI job |
|
|
32
|
+
|-------------|----------------|-------------|--------|
|
|
33
|
+
| `behaviour_schema.json` | `BehaviourValidator` | `behaviour validate` | Yes |
|
|
34
|
+
| `design_schema.json` | *(none)* | *(none)* | *(none)* |
|
|
35
|
+
| `tooling_schema.json` | *(none)* | *(none)* | *(none)* |
|
|
36
|
+
|
|
37
|
+
This ADR addresses all three — not just design documents.
|
|
38
|
+
|
|
39
|
+
### Code duplication concern
|
|
40
|
+
|
|
41
|
+
`BehaviourValidator` is 80 lines. Creating a `DesignValidator` and a
|
|
42
|
+
`ToolingValidator` with the same logic but different schema paths would be
|
|
43
|
+
near-duplicates. With further validators coming in P2 (compiler, CC
|
|
44
|
+
configuration), duplication becomes a maintenance burden.
|
|
45
|
+
|
|
46
|
+
## Options
|
|
47
|
+
|
|
48
|
+
### Option A: Dedicated validator class per schema
|
|
49
|
+
|
|
50
|
+
Mirror `BehaviourValidator` exactly for each schema — same interface,
|
|
51
|
+
different schema path.
|
|
52
|
+
|
|
53
|
+
```ruby
|
|
54
|
+
class DesignValidator
|
|
55
|
+
SCHEMA_PATH = 'conf/schemas/design_schema.json'
|
|
56
|
+
# ... identical logic to BehaviourValidator
|
|
57
|
+
end
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Pros:
|
|
61
|
+
|
|
62
|
+
- Consistent pattern, easy to understand
|
|
63
|
+
- No refactoring of existing code
|
|
64
|
+
|
|
65
|
+
Cons:
|
|
66
|
+
|
|
67
|
+
- Near-duplicate of `BehaviourValidator` (same logic, different constant)
|
|
68
|
+
- Each future validator adds another copy
|
|
69
|
+
- Bug fixes must be applied to all copies
|
|
70
|
+
|
|
71
|
+
### Option B: Generic SchemaValidator with schema parameter
|
|
72
|
+
|
|
73
|
+
Extract the shared logic into `RosettAi::Validators::SchemaValidator`. Accept
|
|
74
|
+
the schema filename in the constructor. All validators become thin wrappers.
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
class SchemaValidator
|
|
78
|
+
def initialize(schema:)
|
|
79
|
+
@schema_path = RosettAi.root.join('conf', 'schemas', schema)
|
|
80
|
+
# ... shared logic
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Thin wrappers
|
|
85
|
+
class BehaviourValidator < SchemaValidator
|
|
86
|
+
def initialize = super(schema: 'behaviour_schema.json')
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
class DesignValidator < SchemaValidator
|
|
90
|
+
def initialize = super(schema: 'design_schema.json')
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
class ToolingValidator < SchemaValidator
|
|
94
|
+
def initialize = super(schema: 'tooling_schema.json')
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Pros:
|
|
99
|
+
|
|
100
|
+
- DRY: shared validation logic in one place
|
|
101
|
+
- Extensible: future validators reuse the same base
|
|
102
|
+
- Existing API stays identical (`valid?`, `validate`, `errors`)
|
|
103
|
+
- Bug fixes apply once
|
|
104
|
+
|
|
105
|
+
Cons:
|
|
106
|
+
|
|
107
|
+
- Refactor touches `BehaviourValidator` (existing tests must still pass)
|
|
108
|
+
- Slightly more abstract (one level of inheritance)
|
|
109
|
+
|
|
110
|
+
### Option C: Validation in compile step only
|
|
111
|
+
|
|
112
|
+
Validate documents only when the compiler reads them. No standalone command.
|
|
113
|
+
|
|
114
|
+
Pros:
|
|
115
|
+
|
|
116
|
+
- No new CLI command needed
|
|
117
|
+
- Validation happens where it matters
|
|
118
|
+
|
|
119
|
+
Cons:
|
|
120
|
+
|
|
121
|
+
- Errors only surface during compilation, not during authoring
|
|
122
|
+
- No way to validate documents without a compile cycle
|
|
123
|
+
- CI cannot validate documents independently of compilation
|
|
124
|
+
|
|
125
|
+
## Decision
|
|
126
|
+
|
|
127
|
+
**Option B: Generic SchemaValidator** — because:
|
|
128
|
+
|
|
129
|
+
- DRY is justified: 3 validators today (behaviour, design, tooling), with
|
|
130
|
+
compiler and CC configuration confirmed for P2. This is not premature
|
|
131
|
+
abstraction — multiple consumers already exist.
|
|
132
|
+
- The existing `BehaviourValidator` API (`valid?`, `validate`, `errors`)
|
|
133
|
+
does not change. Existing tests continue to pass.
|
|
134
|
+
- Future validators become one-line subclasses.
|
|
135
|
+
- CI can validate each document category independently.
|
|
136
|
+
|
|
137
|
+
## Acceptance criteria
|
|
138
|
+
|
|
139
|
+
1. `SchemaValidator` base class has its own spec covering the full API
|
|
140
|
+
(`valid?`, `validate`, `errors`, error reset, missing file, bad YAML,
|
|
141
|
+
missing schema, invalid JSON schema)
|
|
142
|
+
2. Every subclass has its own spec proving correct schema wiring and
|
|
143
|
+
successful validation of all real documents in its category
|
|
144
|
+
3. For every `conf/schemas/*_schema.json` file, a corresponding validator
|
|
145
|
+
class exists in `lib/rosett_ai/validators/`, with a spec and a CI job
|
|
146
|
+
4. For every validator class in `lib/rosett_ai/validators/`, a corresponding
|
|
147
|
+
schema file exists in `conf/schemas/` (no orphan validators)
|
|
148
|
+
5. Existing `BehaviourValidator` spec passes unchanged after the refactor
|
|
149
|
+
|
|
150
|
+
## Consequences
|
|
151
|
+
|
|
152
|
+
- Extract: `BehaviourValidator` logic moves to `SchemaValidator` base class
|
|
153
|
+
- `BehaviourValidator` becomes a thin wrapper inheriting from `SchemaValidator`
|
|
154
|
+
- New: `DesignValidator` wrapper inheriting from `SchemaValidator`
|
|
155
|
+
- New: `ToolingValidator` wrapper inheriting from `SchemaValidator`
|
|
156
|
+
- New CLI: `bin/raictl design validate [NAME]` — validates design docs
|
|
157
|
+
- New CLI: `bin/raictl tooling validate [NAME]` — validates tooling docs
|
|
158
|
+
- New CI jobs in validate stage for design and tooling documents
|
|
159
|
+
- Existing `BehaviourValidator` tests pass unchanged (same API)
|
|
160
|
+
- Future P2 validators (compiler, CC config) inherit from `SchemaValidator`
|
|
161
|
+
- Acceptance criteria 3-4 can be enforced by a CI check that compares
|
|
162
|
+
schema files against validator classes, ensuring neither side drifts
|
|
163
|
+
|
|
164
|
+
### File changes
|
|
165
|
+
|
|
166
|
+
| Action | File |
|
|
167
|
+
|--------|------|
|
|
168
|
+
| New | `lib/rosett_ai/validators/schema_validator.rb` |
|
|
169
|
+
| Refactor | `lib/rosett_ai/validators/behaviour_validator.rb` (inherits SchemaValidator) |
|
|
170
|
+
| New | `lib/rosett_ai/validators/design_validator.rb` |
|
|
171
|
+
| New | `lib/rosett_ai/validators/tooling_validator.rb` |
|
|
172
|
+
| New | `lib/rosett_ai/thor/tasks/design.rb` |
|
|
173
|
+
| Modify | `lib/rosett_ai/thor/tasks/tooling.rb` (add validate subcommand) |
|
|
174
|
+
| New | `.gitlab-ci-files/validate/design-docs.yml` |
|
|
175
|
+
| New | `.gitlab-ci-files/validate/tooling-docs.yml` |
|
|
176
|
+
| Modify | `lib/rosett_ai/thor/cli.rb` (add design subcommand) |
|
|
177
|
+
| New | `spec/rosett_ai/validators/schema_validator_spec.rb` |
|
|
178
|
+
| New | `spec/rosett_ai/validators/design_validator_spec.rb` |
|
|
179
|
+
| New | `spec/rosett_ai/validators/tooling_validator_spec.rb` |
|