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,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Middleware
|
|
9
|
+
# Rack middleware that enforces maximum request body size.
|
|
10
|
+
#
|
|
11
|
+
# Returns 413 Payload Too Large for oversized requests.
|
|
12
|
+
# Default limit: 1 MB.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class RequestSize
|
|
17
|
+
DEFAULT_MAX_SIZE = 1_048_576 # 1 MB
|
|
18
|
+
|
|
19
|
+
# @param app [#call] the next Rack application
|
|
20
|
+
# @param max_size [Integer] maximum request body size in bytes
|
|
21
|
+
def initialize(app, max_size: DEFAULT_MAX_SIZE)
|
|
22
|
+
@app = app
|
|
23
|
+
@max_size = max_size
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @param env [Hash] Rack environment
|
|
27
|
+
# @return [Array] Rack response triplet
|
|
28
|
+
def call(env)
|
|
29
|
+
content_length = env['CONTENT_LENGTH'].to_i
|
|
30
|
+
return payload_too_large(content_length) if content_length > @max_size
|
|
31
|
+
|
|
32
|
+
@app.call(env)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def payload_too_large(size)
|
|
38
|
+
body = JSON.generate(
|
|
39
|
+
jsonrpc: '2.0',
|
|
40
|
+
error: {
|
|
41
|
+
code: -32_600,
|
|
42
|
+
message: "Payload too large (#{size} bytes, max #{@max_size})"
|
|
43
|
+
},
|
|
44
|
+
id: nil
|
|
45
|
+
)
|
|
46
|
+
[413, { 'content-type' => 'application/json' }, [body]]
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
# Plugin auto-discovery and loading for MCP server.
|
|
9
|
+
#
|
|
10
|
+
# Discovers installed gems named `rosett-ai-mcp-*` and loads them
|
|
11
|
+
# as MCP server plugins. Convention: gem `rosett-ai-mcp-foo` defines
|
|
12
|
+
# `RosettAiMcp::Plugins::Foo` with a `.register(server)` method.
|
|
13
|
+
#
|
|
14
|
+
# Governance (built-in tools) is always loaded first.
|
|
15
|
+
#
|
|
16
|
+
# @author hugo
|
|
17
|
+
# @author claude
|
|
18
|
+
module Plugins
|
|
19
|
+
PLUGIN_MUTEX = Mutex.new
|
|
20
|
+
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
# Register a plugin class by name.
|
|
24
|
+
#
|
|
25
|
+
# @param name [Symbol] plugin name
|
|
26
|
+
# @param plugin_class [Class] plugin class with .register(server)
|
|
27
|
+
# @return [void]
|
|
28
|
+
def register(name, plugin_class)
|
|
29
|
+
PLUGIN_MUTEX.synchronize { plugin_registry[name.to_sym] = plugin_class }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Check if a plugin is available (registered or gem installed).
|
|
33
|
+
#
|
|
34
|
+
# @param name [Symbol, String] plugin name
|
|
35
|
+
# @return [Boolean]
|
|
36
|
+
def available?(name)
|
|
37
|
+
PLUGIN_MUTEX.synchronize { plugin_registry.key?(name.to_sym) } || gem_available?(name)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Load all discovered plugins and register with server.
|
|
41
|
+
#
|
|
42
|
+
# @param server [MCP::Server] the MCP server instance
|
|
43
|
+
# @param plugin_names [Array<String>] explicit plugins to load
|
|
44
|
+
# @return [Array<Symbol>] loaded plugin names
|
|
45
|
+
def load_all(server, plugin_names = [])
|
|
46
|
+
discovered = discover_plugin_gems
|
|
47
|
+
all_plugins = (discovered + plugin_names.map(&:to_sym)).uniq
|
|
48
|
+
loaded = []
|
|
49
|
+
|
|
50
|
+
all_plugins.each do |name|
|
|
51
|
+
loaded << name if load_plugin(server, name)
|
|
52
|
+
end
|
|
53
|
+
loaded
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Load a single plugin by name.
|
|
57
|
+
#
|
|
58
|
+
# @param server [MCP::Server] the MCP server instance
|
|
59
|
+
# @param name [Symbol, String] plugin name
|
|
60
|
+
# @return [Boolean] true if loaded successfully
|
|
61
|
+
def load_plugin(server, name)
|
|
62
|
+
sym = name.to_sym
|
|
63
|
+
plugin_class = PLUGIN_MUTEX.synchronize { plugin_registry[sym] }
|
|
64
|
+
|
|
65
|
+
if plugin_class
|
|
66
|
+
plugin_class.register(server)
|
|
67
|
+
return true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
require_and_register_gem(server, sym)
|
|
71
|
+
rescue StandardError, LoadError => e
|
|
72
|
+
warn "[rai-mcp] Plugin load failed for #{name}: #{e.message}"
|
|
73
|
+
false
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Discover installed gems named rosett-ai-mcp-*.
|
|
77
|
+
#
|
|
78
|
+
# @return [Array<Symbol>] discovered plugin names
|
|
79
|
+
def discover_plugin_gems
|
|
80
|
+
discovered = []
|
|
81
|
+
Gem::Specification.each do |spec|
|
|
82
|
+
next unless spec.name.start_with?('rosett-ai-mcp-') && spec.name != 'rosett-ai-mcp'
|
|
83
|
+
|
|
84
|
+
plugin_name = spec.name.sub('rosett-ai-mcp-', '')
|
|
85
|
+
discovered << plugin_name.to_sym
|
|
86
|
+
end
|
|
87
|
+
discovered
|
|
88
|
+
rescue StandardError
|
|
89
|
+
[]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Read-only access to the plugin registry.
|
|
93
|
+
#
|
|
94
|
+
# @return [Hash] registered plugins
|
|
95
|
+
def registry
|
|
96
|
+
PLUGIN_MUTEX.synchronize { plugin_registry.dup }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Reset the registry (for testing).
|
|
100
|
+
#
|
|
101
|
+
# @return [void]
|
|
102
|
+
def reset!
|
|
103
|
+
PLUGIN_MUTEX.synchronize { plugin_registry.clear }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Thread-safe access to the plugin store.
|
|
107
|
+
#
|
|
108
|
+
# @return [Hash] mutable registry hash
|
|
109
|
+
def plugin_registry
|
|
110
|
+
@plugin_registry ||= {} # rubocop:disable ThreadSafety/ClassInstanceVariable
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Allowlist prefix for plugin constant resolution.
|
|
114
|
+
PLUGIN_NAMESPACE = 'RosettAiMcp::Plugins::'
|
|
115
|
+
|
|
116
|
+
class << self
|
|
117
|
+
private
|
|
118
|
+
|
|
119
|
+
def gem_available?(name)
|
|
120
|
+
Gem::Specification.find_by_name("rosett-ai-mcp-#{name}")
|
|
121
|
+
true
|
|
122
|
+
rescue Gem::MissingSpecError
|
|
123
|
+
false
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def require_and_register_gem(server, name) # rubocop:disable Naming/PredicateMethod
|
|
127
|
+
gem_name = "rosett-ai-mcp-#{name}"
|
|
128
|
+
require gem_name.tr('-', '_')
|
|
129
|
+
|
|
130
|
+
plugin_class_name = name.to_s.split(/[-_]/).map(&:capitalize).join
|
|
131
|
+
qualified_name = "#{PLUGIN_NAMESPACE}#{plugin_class_name}"
|
|
132
|
+
|
|
133
|
+
# Safe constant resolution via Object.const_get with validated name
|
|
134
|
+
raise ArgumentError, "Invalid plugin name: #{name}" unless plugin_class_name.match?(/\A[A-Z][a-zA-Z0-9]*\z/)
|
|
135
|
+
|
|
136
|
+
plugin_module = Object.const_get(qualified_name) # rubocop:disable RosettAi/UnsafeConstGet
|
|
137
|
+
plugin_module.register(server)
|
|
138
|
+
true
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Prompts
|
|
9
|
+
# MCP prompt: compilation workflow.
|
|
10
|
+
#
|
|
11
|
+
# Provides a structured prompt for AI agents to compile
|
|
12
|
+
# rai behaviours and review the output.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class CompilationPrompt
|
|
17
|
+
PROMPT_NAME = 'rai_compilation_workflow'
|
|
18
|
+
DESCRIPTION = 'Compile rai behaviours and review output'
|
|
19
|
+
|
|
20
|
+
# Generates the compilation prompt messages.
|
|
21
|
+
#
|
|
22
|
+
# @param engine [String] target engine (default 'claude')
|
|
23
|
+
# @return [Array<Hash>] MCP prompt messages
|
|
24
|
+
def call(engine: 'claude')
|
|
25
|
+
[
|
|
26
|
+
{
|
|
27
|
+
role: 'user',
|
|
28
|
+
content: {
|
|
29
|
+
type: 'text',
|
|
30
|
+
text: "Please compile rai behaviours for the '#{engine}' engine. " \
|
|
31
|
+
'First run nncc_compile with simulate=true to preview changes, ' \
|
|
32
|
+
'then review the diffs before confirming compilation.'
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Prompts
|
|
9
|
+
# MCP prompt: compliance workflow.
|
|
10
|
+
#
|
|
11
|
+
# Provides a structured prompt for AI agents to run compliance
|
|
12
|
+
# checks and interpret the results.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class CompliancePrompt
|
|
17
|
+
PROMPT_NAME = 'rai_compliance_workflow'
|
|
18
|
+
DESCRIPTION = 'Run compliance checks and interpret results'
|
|
19
|
+
|
|
20
|
+
# Generates the compliance prompt messages.
|
|
21
|
+
#
|
|
22
|
+
# @param scope [String, nil] optional scope ('cra', 'license', 'headers')
|
|
23
|
+
# @return [Array<Hash>] MCP prompt messages
|
|
24
|
+
def call(scope: nil)
|
|
25
|
+
scope_text = scope ? " focusing on #{scope} checks" : ''
|
|
26
|
+
[
|
|
27
|
+
{
|
|
28
|
+
role: 'user',
|
|
29
|
+
content: {
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: "Please run rosett-ai compliance checks#{scope_text}. " \
|
|
32
|
+
'Use the Rosett-AI_comply tool to check for violations, then ' \
|
|
33
|
+
'review any findings and suggest remediation steps.'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Prompts
|
|
9
|
+
# MCP prompt: diagnostics workflow.
|
|
10
|
+
#
|
|
11
|
+
# Provides a structured prompt for AI agents to run diagnostics
|
|
12
|
+
# and troubleshoot issues.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class DiagnosticsPrompt
|
|
17
|
+
PROMPT_NAME = 'rai_diagnostics_workflow'
|
|
18
|
+
DESCRIPTION = 'Run diagnostics and troubleshoot issues'
|
|
19
|
+
|
|
20
|
+
# Generates the diagnostics prompt messages.
|
|
21
|
+
#
|
|
22
|
+
# @param check [String, nil] specific check to focus on
|
|
23
|
+
# @return [Array<Hash>] MCP prompt messages
|
|
24
|
+
def call(check: nil)
|
|
25
|
+
check_text = check ? " specifically the '#{check}' check" : ''
|
|
26
|
+
[
|
|
27
|
+
{
|
|
28
|
+
role: 'user',
|
|
29
|
+
content: {
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: "Please run rosett-ai diagnostics#{check_text}. " \
|
|
32
|
+
'Use the Rosett-AI_doctor tool to check system health, then ' \
|
|
33
|
+
'review any failures and suggest troubleshooting steps.'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Prompts
|
|
9
|
+
# MCP prompt: validation workflow.
|
|
10
|
+
#
|
|
11
|
+
# Provides a structured prompt for AI agents to validate
|
|
12
|
+
# rai configuration and suggest fixes for any issues found.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class ValidationPrompt
|
|
17
|
+
PROMPT_NAME = 'rai_validation_workflow'
|
|
18
|
+
DESCRIPTION = 'Validate rai configuration and suggest fixes'
|
|
19
|
+
|
|
20
|
+
# Generates the validation prompt messages.
|
|
21
|
+
#
|
|
22
|
+
# @param scope [String, nil] optional scope filter
|
|
23
|
+
# @return [Array<Hash>] MCP prompt messages
|
|
24
|
+
def call(scope: nil)
|
|
25
|
+
scope_text = scope ? " for scope '#{scope}'" : ''
|
|
26
|
+
[
|
|
27
|
+
{
|
|
28
|
+
role: 'user',
|
|
29
|
+
content: {
|
|
30
|
+
type: 'text',
|
|
31
|
+
text: "Please validate all rai configuration files#{scope_text}. " \
|
|
32
|
+
'Use the Rosett-AI_validate tool to check for errors, then review ' \
|
|
33
|
+
'any issues found and suggest specific fixes.'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Resources
|
|
9
|
+
# MCP resource provider for rai behaviour files.
|
|
10
|
+
#
|
|
11
|
+
# Exposes behaviour YAML files as MCP resources with 3-tier lookup:
|
|
12
|
+
# project > XDG user > packaged. Supports tier query parameter
|
|
13
|
+
# to request a specific tier.
|
|
14
|
+
#
|
|
15
|
+
# URIs: rosett-ai://behaviour/{name}
|
|
16
|
+
# rosett-ai://behaviour/{name}?tier=xdg
|
|
17
|
+
#
|
|
18
|
+
# @author hugo
|
|
19
|
+
# @author claude
|
|
20
|
+
class BehaviourResource
|
|
21
|
+
URI_PREFIX = 'rosett-ai://behaviour/'
|
|
22
|
+
|
|
23
|
+
TIER_DIRS = {
|
|
24
|
+
'project' => -> { RosettAi.conf_root.join('conf', 'behaviour') },
|
|
25
|
+
'xdg' => -> { RosettAi.paths.rai_conf_dir.join('behaviour') },
|
|
26
|
+
'packaged' => -> { RosettAi.paths.packaged_conf_dir.join('behaviour') }
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
# Lists all available behaviour resources across all tiers.
|
|
30
|
+
#
|
|
31
|
+
# @return [Array<Hash>] resource entries with :uri, :name, :description
|
|
32
|
+
def list
|
|
33
|
+
names = Set.new
|
|
34
|
+
tier_dirs.each_value do |dir|
|
|
35
|
+
next unless dir.directory?
|
|
36
|
+
|
|
37
|
+
dir.glob('*.yml').each { |path| names << path.basename('.yml').to_s }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
names.sort.map { |name| resource_entry(name) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Reads a specific behaviour resource via 3-tier lookup.
|
|
44
|
+
#
|
|
45
|
+
# @param name [String] behaviour name, optionally with ?tier= query
|
|
46
|
+
# @return [Hash, nil] resource content with :uri, :content, :mime_type
|
|
47
|
+
def read(name)
|
|
48
|
+
base_name, tier = parse_name_and_tier(name)
|
|
49
|
+
path = tier ? find_in_tier(base_name, tier) : find_first(base_name)
|
|
50
|
+
return nil unless path&.exist?
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
uri: "#{URI_PREFIX}#{base_name}",
|
|
54
|
+
content: File.read(path),
|
|
55
|
+
mime_type: 'application/x-yaml',
|
|
56
|
+
tier: tier || detected_tier(path)
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
# @return [Hash{String => Pathname}]
|
|
63
|
+
def tier_dirs
|
|
64
|
+
TIER_DIRS.transform_values(&:call)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# @param raw [String] e.g. "criticalthinking?tier=xdg"
|
|
68
|
+
# @return [Array(String, String)] [base_name, tier]
|
|
69
|
+
def parse_name_and_tier(raw)
|
|
70
|
+
if raw.include?('?')
|
|
71
|
+
base, query = raw.split('?', 2)
|
|
72
|
+
tier = query[/tier=(\w+)/, 1]
|
|
73
|
+
[base, tier]
|
|
74
|
+
else
|
|
75
|
+
[raw, nil]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @param name [String]
|
|
80
|
+
# @param tier [String]
|
|
81
|
+
# @return [Pathname, nil]
|
|
82
|
+
def find_in_tier(name, tier)
|
|
83
|
+
dir = tier_dirs[tier]
|
|
84
|
+
return nil unless dir&.directory?
|
|
85
|
+
|
|
86
|
+
path = dir.join("#{name}.yml")
|
|
87
|
+
path.exist? ? path : nil
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# First-wins lookup: project > xdg > packaged.
|
|
91
|
+
#
|
|
92
|
+
# @param name [String]
|
|
93
|
+
# @return [Pathname, nil]
|
|
94
|
+
def find_first(name)
|
|
95
|
+
tier_dirs.each_value do |dir|
|
|
96
|
+
next unless dir.directory?
|
|
97
|
+
|
|
98
|
+
path = dir.join("#{name}.yml")
|
|
99
|
+
return path if path.exist?
|
|
100
|
+
end
|
|
101
|
+
nil
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @param path [Pathname]
|
|
105
|
+
# @return [String]
|
|
106
|
+
def detected_tier(path)
|
|
107
|
+
path_str = path.to_s
|
|
108
|
+
tier_dirs.each do |tier, dir|
|
|
109
|
+
return tier if path_str.start_with?(dir.to_s)
|
|
110
|
+
end
|
|
111
|
+
'unknown'
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @param name [String]
|
|
115
|
+
# @return [Hash]
|
|
116
|
+
def resource_entry(name)
|
|
117
|
+
{
|
|
118
|
+
uri: "#{URI_PREFIX}#{name}",
|
|
119
|
+
name: name,
|
|
120
|
+
description: "Behaviour configuration: #{name}",
|
|
121
|
+
mime_type: 'application/x-yaml'
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Resources
|
|
9
|
+
# MCP resource provider for compiled configuration.
|
|
10
|
+
#
|
|
11
|
+
# Exposes compiled configuration scopes as MCP resources.
|
|
12
|
+
#
|
|
13
|
+
# @author hugo
|
|
14
|
+
# @author claude
|
|
15
|
+
class ConfigResource
|
|
16
|
+
URI_PREFIX = 'rosett-ai://config/'
|
|
17
|
+
SCOPES = ['managed', 'user', 'project', 'local'].freeze
|
|
18
|
+
|
|
19
|
+
# Lists available config resources.
|
|
20
|
+
#
|
|
21
|
+
# @return [Array<Hash>] resource entries
|
|
22
|
+
def list
|
|
23
|
+
SCOPES.filter_map do |scope|
|
|
24
|
+
path = scope_path(scope)
|
|
25
|
+
next unless path&.exist?
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
uri: "#{URI_PREFIX}#{scope}",
|
|
29
|
+
name: "config-#{scope}",
|
|
30
|
+
description: "Compiled configuration: #{scope} scope",
|
|
31
|
+
mime_type: 'application/json'
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Reads a specific config scope.
|
|
37
|
+
#
|
|
38
|
+
# @param scope [String] scope name (managed, user, project, local)
|
|
39
|
+
# @return [Hash, nil] resource content
|
|
40
|
+
def read(scope)
|
|
41
|
+
return nil unless SCOPES.include?(scope)
|
|
42
|
+
|
|
43
|
+
path = scope_path(scope)
|
|
44
|
+
return nil unless path&.exist?
|
|
45
|
+
|
|
46
|
+
{
|
|
47
|
+
uri: "#{URI_PREFIX}#{scope}",
|
|
48
|
+
content: File.read(path),
|
|
49
|
+
mime_type: 'application/json'
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# @param scope [String]
|
|
56
|
+
# @return [Pathname, nil]
|
|
57
|
+
def scope_path(scope)
|
|
58
|
+
case scope
|
|
59
|
+
when 'managed'
|
|
60
|
+
Pathname.new(File.expand_path('~/.claude/settings.json'))
|
|
61
|
+
when 'user'
|
|
62
|
+
Pathname.new(File.expand_path('~/.claude/settings.local.json'))
|
|
63
|
+
when 'project'
|
|
64
|
+
RosettAi.root.join('.claude', 'settings.json')
|
|
65
|
+
when 'local'
|
|
66
|
+
RosettAi.root.join('.claude', 'settings.local.json')
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Resources
|
|
9
|
+
# MCP resource provider for rai design documents.
|
|
10
|
+
#
|
|
11
|
+
# Exposes design YAML files as MCP resources with
|
|
12
|
+
# URIs in the format rosett-ai://design/{name}.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class DesignResource
|
|
17
|
+
URI_PREFIX = 'rosett-ai://design/'
|
|
18
|
+
|
|
19
|
+
# Lists all available design resources.
|
|
20
|
+
#
|
|
21
|
+
# @return [Array<Hash>] resource entries with :uri, :name, :description
|
|
22
|
+
def list
|
|
23
|
+
dir = RosettAi.root.join('conf', 'design')
|
|
24
|
+
return [] unless dir.directory?
|
|
25
|
+
|
|
26
|
+
dir.glob('*.yml').map { |path| resource_entry(path) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Reads a specific design resource.
|
|
30
|
+
#
|
|
31
|
+
# @param name [String] design name (without .yml)
|
|
32
|
+
# @return [Hash, nil] resource content with :uri, :content, :mime_type
|
|
33
|
+
def read(name)
|
|
34
|
+
path = RosettAi.root.join('conf', 'design', "#{name}.yml")
|
|
35
|
+
return nil unless path.exist?
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
uri: "#{URI_PREFIX}#{name}",
|
|
39
|
+
content: File.read(path),
|
|
40
|
+
mime_type: 'application/x-yaml'
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def resource_entry(path)
|
|
47
|
+
name = path.basename('.yml').to_s
|
|
48
|
+
{
|
|
49
|
+
uri: "#{URI_PREFIX}#{name}",
|
|
50
|
+
name: name,
|
|
51
|
+
description: "Design document: #{name}",
|
|
52
|
+
mime_type: 'application/x-yaml'
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
4
|
+
# Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
|
|
5
|
+
|
|
6
|
+
module RosettAi
|
|
7
|
+
module Mcp
|
|
8
|
+
module Resources
|
|
9
|
+
# MCP resource provider for installed hook scripts.
|
|
10
|
+
#
|
|
11
|
+
# Exposes installed rai enforcement hooks as MCP resources
|
|
12
|
+
# with URIs in the format rosett-ai://hooks/{scope}.
|
|
13
|
+
#
|
|
14
|
+
# @author hugo
|
|
15
|
+
# @author claude
|
|
16
|
+
class HooksResource
|
|
17
|
+
URI_PREFIX = 'rosett-ai://hooks/'
|
|
18
|
+
|
|
19
|
+
SCOPES = {
|
|
20
|
+
'global' => -> { RosettAi.paths.global_dir.join('hooks') },
|
|
21
|
+
'project' => -> { RosettAi.context.project_root.join('.claude', 'hooks') }
|
|
22
|
+
}.freeze
|
|
23
|
+
|
|
24
|
+
# Lists available hook resources.
|
|
25
|
+
#
|
|
26
|
+
# @return [Array<Hash>] resource entries
|
|
27
|
+
def list
|
|
28
|
+
SCOPES.filter_map do |scope, dir_factory|
|
|
29
|
+
dir = safe_dir(dir_factory)
|
|
30
|
+
next unless dir&.directory? && dir.glob('*.rb').any?
|
|
31
|
+
|
|
32
|
+
{
|
|
33
|
+
uri: "#{URI_PREFIX}#{scope}",
|
|
34
|
+
name: "hooks-#{scope}",
|
|
35
|
+
description: "Installed hooks: #{scope} scope",
|
|
36
|
+
mime_type: 'text/x-ruby'
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Reads hooks for a specific scope.
|
|
42
|
+
#
|
|
43
|
+
# @param scope [String] 'global' or 'project'
|
|
44
|
+
# @return [Hash, nil] resource content
|
|
45
|
+
def read(scope)
|
|
46
|
+
dir_factory = SCOPES[scope]
|
|
47
|
+
return nil unless dir_factory
|
|
48
|
+
|
|
49
|
+
dir = safe_dir(dir_factory)
|
|
50
|
+
return nil unless dir&.directory?
|
|
51
|
+
|
|
52
|
+
scripts = dir.glob('*.rb').map { |path| File.read(path) }
|
|
53
|
+
return nil if scripts.empty?
|
|
54
|
+
|
|
55
|
+
{
|
|
56
|
+
uri: "#{URI_PREFIX}#{scope}",
|
|
57
|
+
content: scripts.join("\n\n# --- next hook ---\n\n"),
|
|
58
|
+
mime_type: 'text/x-ruby'
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
# @param factory [Proc]
|
|
65
|
+
# @return [Pathname, nil]
|
|
66
|
+
def safe_dir(factory)
|
|
67
|
+
factory.call
|
|
68
|
+
rescue StandardError
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|