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,128 @@
|
|
|
1
|
+
# Implement ADR-002 PathResolver (Phase 3)
|
|
2
|
+
|
|
3
|
+
**Branch**: `design_implementation`
|
|
4
|
+
**Date**: 2026-02-21
|
|
5
|
+
**ADR**: `doc/decisions/002-path-resolution-strategy.md`
|
|
6
|
+
**Design docs affected**: `architecture.yml` (anti-pattern elimination)
|
|
7
|
+
|
|
8
|
+
## Motivation
|
|
9
|
+
|
|
10
|
+
Six library files contained hardcoded `~/.claude` paths and two files contained
|
|
11
|
+
hardcoded `~/.config/rosett-ai` paths. The `architecture.yml` design document lists
|
|
12
|
+
"hardcoded paths instead of XDG-compliant directory resolution" as an
|
|
13
|
+
anti-pattern. ADR-002 was accepted to centralise all path resolution in a single
|
|
14
|
+
class.
|
|
15
|
+
|
|
16
|
+
## Design decisions
|
|
17
|
+
|
|
18
|
+
| Decision | Choice | Rationale |
|
|
19
|
+
|----------|--------|-----------|
|
|
20
|
+
| Class vs module | Class with instance methods | Future-proofed for ADR-006 multi-engine (pass `engine:` keyword) |
|
|
21
|
+
| Return type | `Pathname` everywhere | Consistent API, chainable `.join()`, type-safe |
|
|
22
|
+
| Display strings | Tilde form (`~/.claude/rules`) | Lockfile portability across machines |
|
|
23
|
+
| Singleton accessor | `RosettAi.paths` on module | Clean call sites, single point to swap for multi-engine |
|
|
24
|
+
|
|
25
|
+
## Changes by area
|
|
26
|
+
|
|
27
|
+
### RosettAi::PathResolver (new)
|
|
28
|
+
|
|
29
|
+
**File**: `lib/rosett_ai/path_resolver.rb` (36 lines)
|
|
30
|
+
|
|
31
|
+
Centralises all filesystem path resolution into a single class:
|
|
32
|
+
|
|
33
|
+
| Method | Returns | Domain |
|
|
34
|
+
|--------|---------|--------|
|
|
35
|
+
| `global_dir` | `Pathname(~/.claude)` | Claude Code |
|
|
36
|
+
| `rules_dir` | `Pathname(~/.claude/rules)` | Claude Code |
|
|
37
|
+
| `local_dir` | `Pathname(./claude)` | Claude Code |
|
|
38
|
+
| `project_claude_md` | `Pathname(./CLAUDE.md)` | Claude Code |
|
|
39
|
+
| `rai_config_dir` | `Pathname($XDG_CONFIG_HOME/rosett-ai)` | rosett-ai (XDG) |
|
|
40
|
+
| `secrets_file` | `Pathname(rai_config_dir/secrets.yml)` | rosett-ai (XDG) |
|
|
41
|
+
| `rules_display_path` | `'~/.claude/rules'` (String) | Lockfile display |
|
|
42
|
+
|
|
43
|
+
Constructor accepts `engine:` keyword (defaults to `:claude`) for future
|
|
44
|
+
multi-engine support per ADR-006.
|
|
45
|
+
|
|
46
|
+
### RosettAi module accessor
|
|
47
|
+
|
|
48
|
+
**File**: `lib/rosett_ai.rb`
|
|
49
|
+
|
|
50
|
+
Added `RosettAi.paths` memoized accessor and updated `RosettAi.reset_config!` to clear
|
|
51
|
+
the paths instance alongside the config instance.
|
|
52
|
+
|
|
53
|
+
### Thor task refactoring (4 files)
|
|
54
|
+
|
|
55
|
+
| File | Old | New |
|
|
56
|
+
|------|-----|-----|
|
|
57
|
+
| `compile.rb:70` | `Pathname.new(File.expand_path('~/.claude/rules'))` | `RosettAi.paths.rules_dir` |
|
|
58
|
+
| `adopt.rb:64` | `Pathname.new(File.expand_path('~/.claude/rules'))` | `RosettAi.paths.rules_dir` |
|
|
59
|
+
| `init.rb:49` | `File.expand_path('~/.claude')` | `RosettAi.paths.global_dir.to_s` |
|
|
60
|
+
| `init.rb:59` | `File.join(Dir.pwd, '.claude')` | `RosettAi.paths.local_dir.to_s` |
|
|
61
|
+
| `backup.rb:96` | `File.expand_path('~/.claude')` | `RosettAi.paths.global_dir.to_s` |
|
|
62
|
+
| `backup.rb:107` | `File.join(Dir.pwd, '.claude')` | `RosettAi.paths.local_dir.to_s` |
|
|
63
|
+
| `backup.rb:117` | `File.join(Dir.pwd, 'CLAUDE.md')` | `RosettAi.paths.project_claude_md.to_s` |
|
|
64
|
+
|
|
65
|
+
### BehaviourCompiler lockfile paths
|
|
66
|
+
|
|
67
|
+
**File**: `lib/rosett_ai/compiler/behaviour_compiler.rb`
|
|
68
|
+
|
|
69
|
+
| Line | Old | New |
|
|
70
|
+
|------|-----|-----|
|
|
71
|
+
| 143 | `"~/.claude/rules/#{filename}"` | `"#{RosettAi.paths.rules_display_path}/#{filename}"` |
|
|
72
|
+
| 155 | `'~/.claude/rules'` | `RosettAi.paths.rules_display_path` |
|
|
73
|
+
|
|
74
|
+
### SecretsResolver constant elimination
|
|
75
|
+
|
|
76
|
+
**File**: `lib/rosett_ai/secrets_resolver.rb`
|
|
77
|
+
|
|
78
|
+
Removed `SECRETS_DIR` and `SECRETS_FILE` constants. All path references now go
|
|
79
|
+
through `RosettAi.paths.secrets_file` and `RosettAi.paths.rai_config_dir`. The
|
|
80
|
+
`raise_missing` error message dynamically includes the secrets file path.
|
|
81
|
+
|
|
82
|
+
### Spec updates
|
|
83
|
+
|
|
84
|
+
| File | Change |
|
|
85
|
+
|------|--------|
|
|
86
|
+
| `spec/rosett_ai/secrets_resolver_spec.rb` | `stub_const` replaced with `instance_double(RosettAi::PathResolver)` |
|
|
87
|
+
| `spec/rosett_ai/thor/tasks/init_spec.rb` | `stub_home` uses PathResolver `instance_double` |
|
|
88
|
+
| `spec/rosett_ai/thor/tasks/backup_spec.rb` | `stub_home` uses PathResolver `instance_double` |
|
|
89
|
+
|
|
90
|
+
### Configuration
|
|
91
|
+
|
|
92
|
+
| File | Change |
|
|
93
|
+
|------|--------|
|
|
94
|
+
| `.mutant.yml` | Added `RosettAi::PathResolver` and `RosettAi::SecretsResolver` to subjects |
|
|
95
|
+
|
|
96
|
+
## Files inventory
|
|
97
|
+
|
|
98
|
+
| Action | File |
|
|
99
|
+
|--------|------|
|
|
100
|
+
| New | `lib/rosett_ai/path_resolver.rb` |
|
|
101
|
+
| New | `spec/rosett_ai/path_resolver_spec.rb` |
|
|
102
|
+
| Modified | `lib/rosett_ai.rb` |
|
|
103
|
+
| Modified | `lib/rosett_ai/thor/tasks/compile.rb` |
|
|
104
|
+
| Modified | `lib/rosett_ai/thor/tasks/adopt.rb` |
|
|
105
|
+
| Modified | `lib/rosett_ai/thor/tasks/init.rb` |
|
|
106
|
+
| Modified | `lib/rosett_ai/thor/tasks/backup.rb` |
|
|
107
|
+
| Modified | `lib/rosett_ai/compiler/behaviour_compiler.rb` |
|
|
108
|
+
| Modified | `lib/rosett_ai/secrets_resolver.rb` |
|
|
109
|
+
| Modified | `spec/rosett_ai/secrets_resolver_spec.rb` |
|
|
110
|
+
| Modified | `spec/rosett_ai/thor/tasks/init_spec.rb` |
|
|
111
|
+
| Modified | `spec/rosett_ai/thor/tasks/backup_spec.rb` |
|
|
112
|
+
| Modified | `.mutant.yml` |
|
|
113
|
+
| Modified | `doc/decisions/002-path-resolution-strategy.md` |
|
|
114
|
+
|
|
115
|
+
## Verification
|
|
116
|
+
|
|
117
|
+
- [x] `bundle exec rspec spec/rosett_ai/path_resolver_spec.rb` — 22 examples, 0 failures
|
|
118
|
+
- [x] `bundle exec rspec spec/rosett_ai/secrets_resolver_spec.rb` — 18 examples, 0 failures
|
|
119
|
+
- [x] `bundle exec rspec spec/rosett_ai/thor/tasks/init_spec.rb` — 9 examples, 0 failures
|
|
120
|
+
- [x] `bundle exec rspec spec/rosett_ai/thor/tasks/backup_spec.rb` — 21 examples, 0 failures
|
|
121
|
+
- [x] `bundle exec rspec spec/rosett_ai/thor/tasks/compile_spec.rb` — 11 examples, 0 failures
|
|
122
|
+
- [x] `bundle exec rspec spec/rosett_ai/thor/tasks/adopt_spec.rb` — 14 examples, 0 failures
|
|
123
|
+
- [x] `bundle exec rspec` — 501 examples, 0 failures
|
|
124
|
+
- [x] `bundle exec rubocop` — 81 files, 0 offenses
|
|
125
|
+
- [x] `bundle exec reek` — 0 warnings
|
|
126
|
+
- [x] `bin/raictl compile --simulate --verbose` — CLI smoke test passes
|
|
127
|
+
- [x] No hardcoded `~/.claude` paths remain outside PathResolver and display strings
|
|
128
|
+
- [x] No hardcoded `~/.config/rosett-ai` paths remain outside PathResolver
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Fix CI pipeline: TMPDIR world-writable warnings and mutant git fetch
|
|
2
|
+
|
|
3
|
+
**Date**: 2026-02-24
|
|
4
|
+
**Branch**: `design_implementation`
|
|
5
|
+
**Related jobs**: `test:rspec`, `test:mutant`
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
|
|
9
|
+
Two CI pipeline failures resolved in a single change:
|
|
10
|
+
|
|
11
|
+
1. **TMPDIR world-writable warnings** — Ruby's `Dir.tmpdir` emits warnings
|
|
12
|
+
when `/tmp` is world-writable (standard in Docker containers). RSpec and
|
|
13
|
+
other Ruby tools surfaced these as test output noise or failures.
|
|
14
|
+
|
|
15
|
+
2. **Mutant git fetch permission denied** — The `.base` template sets the
|
|
16
|
+
git remote to SSH (`git@...`) via a deploy key, but `test:mutant` was the
|
|
17
|
+
only job that performed an explicit `git fetch` after setup. The deploy key
|
|
18
|
+
lacked the necessary read access for this operation.
|
|
19
|
+
|
|
20
|
+
## Changes
|
|
21
|
+
|
|
22
|
+
### `.gitlab-ci-files/global/defaults.yml`
|
|
23
|
+
|
|
24
|
+
- Added `export TMPDIR=$(mktemp -d)` as the first line of `.base`
|
|
25
|
+
`before_script` — covers all jobs extending `.base`, `.ruby_base`, and
|
|
26
|
+
`.security_base`
|
|
27
|
+
- Added the same to `.minimal_base` `before_script` for consistency
|
|
28
|
+
- `mktemp -d` creates a directory with `0700` permissions, eliminating
|
|
29
|
+
the world-writable path warnings
|
|
30
|
+
|
|
31
|
+
### `.gitlab-ci-files/test/mutant.yml`
|
|
32
|
+
|
|
33
|
+
- Added `git remote set-url origin "${CI_REPOSITORY_URL}"` before
|
|
34
|
+
`git fetch` in the `test:mutant` job script
|
|
35
|
+
- `CI_REPOSITORY_URL` is a predefined GitLab CI variable containing the
|
|
36
|
+
HTTPS URL with the ephemeral CI job token, providing guaranteed read
|
|
37
|
+
access to the project without depending on the SSH deploy key
|
|
38
|
+
|
|
39
|
+
## Rationale
|
|
40
|
+
|
|
41
|
+
- The TMPDIR fix is applied at the `.base` template level so every job
|
|
42
|
+
inherits it automatically — no per-job configuration needed
|
|
43
|
+
- Using `CI_REPOSITORY_URL` for mutant's fetch is preferred over fixing
|
|
44
|
+
the deploy key because it uses GitLab's built-in authentication and
|
|
45
|
+
requires no infrastructure changes
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# CI Bundler Strategy and RuboCop Compliance
|
|
2
|
+
|
|
3
|
+
**Branch**: `docs/update-implementation-plan`
|
|
4
|
+
**Date**: 2026-03-01
|
|
5
|
+
**ADR**: `doc/decisions/008-ci-bundler-strategy.md`
|
|
6
|
+
**Commits**: 17430f6 (desktop exclusion), 75f7c14 (rubocop fixes + frozen bundle)
|
|
7
|
+
|
|
8
|
+
## Motivation
|
|
9
|
+
|
|
10
|
+
Three CI jobs (`validate:ci_yaml`, `validate:schemas`,
|
|
11
|
+
`validate:version_consistency`) failed in the pipeline because `bundle install`
|
|
12
|
+
attempted to build the `gobject-introspection` native extension. This gem is a
|
|
13
|
+
transitive dependency of the `:desktop` Bundler group (`adwaita -> gtk4 -> ...
|
|
14
|
+
-> gobject-introspection`) and requires `libgirepository1.0-dev`, which is not
|
|
15
|
+
present in the `ruby:3.3.10-bookworm` Docker image.
|
|
16
|
+
|
|
17
|
+
Additionally, `quality:rubocop` reported 15 new offenses from cops introduced
|
|
18
|
+
in RuboCop 1.85.0. CI resolved this version because `Gemfile.lock` was not
|
|
19
|
+
tracked, allowing Bundler to resolve `~> 1.82` to the latest available release.
|
|
20
|
+
Local development used 1.84.2 (from the local lockfile), masking the offenses.
|
|
21
|
+
|
|
22
|
+
## Root cause analysis
|
|
23
|
+
|
|
24
|
+
| Symptom | Root cause |
|
|
25
|
+
|---------|------------|
|
|
26
|
+
| `gobject-introspection` build failure | `:desktop` group installed in CI where no job needs GTK4 |
|
|
27
|
+
| 15 new rubocop offenses in CI only | `Gemfile.lock` untracked; CI resolved rubocop 1.85.0 vs local 1.84.2 |
|
|
28
|
+
| Offenses not caught by pre-commit hook | Overcommit `RuboCop` hook only lints changed files |
|
|
29
|
+
|
|
30
|
+
## Changes
|
|
31
|
+
|
|
32
|
+
### 1. Exclude `:desktop` Bundler group in CI
|
|
33
|
+
|
|
34
|
+
**File**: `.gitlab-ci-files/global/defaults.yml`
|
|
35
|
+
|
|
36
|
+
Added to `.ruby_base` before_script:
|
|
37
|
+
|
|
38
|
+
```yaml
|
|
39
|
+
- bundle config set --local without 'desktop'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This prevents the GTK4 dependency chain from being resolved in CI. No CI job
|
|
43
|
+
requires desktop gems.
|
|
44
|
+
|
|
45
|
+
### 2. Track `Gemfile.lock` and freeze CI installs
|
|
46
|
+
|
|
47
|
+
**Files**: `.gitignore`, `Gemfile.lock`, `.gitlab-ci-files/global/defaults.yml`
|
|
48
|
+
|
|
49
|
+
- Removed `Gemfile.lock` from `.gitignore`
|
|
50
|
+
- Committed `Gemfile.lock` with rubocop 1.85.0 pinned
|
|
51
|
+
- Added `bundle config set --local frozen true` to `.ruby_base`
|
|
52
|
+
|
|
53
|
+
CI now fails immediately if the lockfile diverges from the Gemfile, preventing
|
|
54
|
+
silent version drift.
|
|
55
|
+
|
|
56
|
+
### 3. Fix all 15 rubocop 1.85.0 offenses
|
|
57
|
+
|
|
58
|
+
**Files**: 7 source files updated
|
|
59
|
+
|
|
60
|
+
| Cop | Count | Fix |
|
|
61
|
+
|-----|-------|-----|
|
|
62
|
+
| `Style/RedundantStructKeywordInit` | 4 | Removed redundant `keyword_init: true` |
|
|
63
|
+
| `Style/ReduceToHash` | 10 | Replaced `each_with_object({})` with `to_h { ... }` |
|
|
64
|
+
| `Style/FileOpen` | 1 | Inline-disabled (intentional persistent handle with explicit cleanup) |
|
|
65
|
+
|
|
66
|
+
### 4. Replace overcommit RuboCop with full-project RubocopAll
|
|
67
|
+
|
|
68
|
+
**Files**: `.overcommit.yml`, `.git-hooks/pre_commit/rubocop_all.rb`
|
|
69
|
+
|
|
70
|
+
Disabled the built-in `RuboCop` hook (which only lints changed files) and
|
|
71
|
+
replaced it with a custom `RubocopAll` hook that scans all project files on
|
|
72
|
+
every commit. This catches offenses from new cops or config changes regardless
|
|
73
|
+
of what files are in the commit.
|
|
74
|
+
|
|
75
|
+
## `.ruby_base` template (after changes)
|
|
76
|
+
|
|
77
|
+
```yaml
|
|
78
|
+
.ruby_base:
|
|
79
|
+
image: 'ruby:${RUBY_VERSION}-${DEBIAN_RELEASE}'
|
|
80
|
+
extends: .base
|
|
81
|
+
before_script:
|
|
82
|
+
- !reference [.base, before_script]
|
|
83
|
+
- ruby --version
|
|
84
|
+
- gem install bundler --no-document
|
|
85
|
+
- bundle config set --local path "$BUNDLE_PATH"
|
|
86
|
+
- bundle config set --local jobs "$BUNDLE_JOBS"
|
|
87
|
+
- bundle config set --local without 'desktop'
|
|
88
|
+
- bundle config set --local frozen true
|
|
89
|
+
- bundle install
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Verification
|
|
93
|
+
|
|
94
|
+
- [x] `bundle exec rubocop` -- 0 offenses (245 files, rubocop 1.85.0)
|
|
95
|
+
- [x] `bundle exec rspec` -- 1005 examples, 0 failures
|
|
96
|
+
- [x] Overcommit `RubocopAll` hook passes (full-project scan)
|
|
97
|
+
- [x] All pre-commit and commit-msg hooks pass
|
|
98
|
+
|
|
99
|
+
## Files created
|
|
100
|
+
|
|
101
|
+
| File | Purpose |
|
|
102
|
+
|------|---------|
|
|
103
|
+
| `doc/decisions/008-ci-bundler-strategy.md` | ADR documenting decisions |
|
|
104
|
+
| `doc/changes/2026-03-01-ci-bundler-strategy.md` | This change document |
|
|
105
|
+
| `.git-hooks/pre_commit/rubocop_all.rb` | Custom overcommit hook |
|
|
106
|
+
|
|
107
|
+
## Files modified
|
|
108
|
+
|
|
109
|
+
| File | Change |
|
|
110
|
+
|------|--------|
|
|
111
|
+
| `.gitlab-ci-files/global/defaults.yml` | Added `without 'desktop'` and `frozen true` |
|
|
112
|
+
| `.gitignore` | Removed `Gemfile.lock` entry |
|
|
113
|
+
| `.overcommit.yml` | Disabled `RuboCop`, added `RubocopAll` |
|
|
114
|
+
| `lib/rosett_ai/compiler/compiled_output.rb` | Removed redundant `keyword_init: true` |
|
|
115
|
+
| `lib/rosett_ai/config/compile_result.rb` | Removed redundant `keyword_init: true` |
|
|
116
|
+
| `lib/rosett_ai/desktop/gui_logger.rb` | Inline-disabled `Style/FileOpen` |
|
|
117
|
+
| `lib/rosett_ai/thor/tasks/build.rb` | Removed `keyword_init: true`, replaced `each_with_object` |
|
|
118
|
+
| `lib/rosett_ai/thor/tasks/compile.rb` | Removed redundant `keyword_init: true` |
|
|
119
|
+
| `spec/rosett_ai/yaml_loader_property_spec.rb` | Replaced `each_with_object` with `to_h` |
|
|
120
|
+
| `spec/rosett_ai/yaml_loader_spec.rb` | Replaced `each_with_object` with `to_h` (7 instances) |
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Security Hardening Phase 2
|
|
2
|
+
|
|
3
|
+
**Branch**: `security/hardening-phase2`
|
|
4
|
+
**Date**: 2026-03-20
|
|
5
|
+
**Authors**: hugo, claude
|
|
6
|
+
|
|
7
|
+
## Motivation
|
|
8
|
+
|
|
9
|
+
Following the initial security implementation (v1.1.0), this phase addresses
|
|
10
|
+
remaining gaps identified in the security review:
|
|
11
|
+
|
|
12
|
+
1. Supply chain integrity via Gemfile.lock checksums
|
|
13
|
+
2. Advisory cops for dynamic dispatch patterns
|
|
14
|
+
3. Thread safety analysis
|
|
15
|
+
4. Enhanced content pack path traversal protection
|
|
16
|
+
5. D-Bus rate limiting for DoS prevention
|
|
17
|
+
|
|
18
|
+
## Changes
|
|
19
|
+
|
|
20
|
+
### 1. Gemfile.lock Checksums
|
|
21
|
+
|
|
22
|
+
Added SHA-256 checksums to all gems in Gemfile.lock:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bundle lock --add-checksums
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This ensures that gem integrity is verified on every `bundle install`, protecting
|
|
29
|
+
against supply chain attacks where a compromised RubyGems registry could serve
|
|
30
|
+
tampered gem versions.
|
|
31
|
+
|
|
32
|
+
### 2. Advisory Custom Cops
|
|
33
|
+
|
|
34
|
+
Two new RuboCop cops added with severity `warning` (advisory, not blocking):
|
|
35
|
+
|
|
36
|
+
#### RosettAi/UnsafeConstGet
|
|
37
|
+
|
|
38
|
+
Flags `Object.const_get` and `constantize` with non-literal arguments:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
# flagged
|
|
42
|
+
Object.const_get(user_input)
|
|
43
|
+
class_name.constantize
|
|
44
|
+
|
|
45
|
+
# allowed
|
|
46
|
+
Object.const_get(:MyClass)
|
|
47
|
+
REGISTRY.fetch(name) # use frozen allowlist
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Exclusions**: RuboCop cop files (use `on_send` AST pattern)
|
|
51
|
+
|
|
52
|
+
#### RosettAi/UnsafeSend
|
|
53
|
+
|
|
54
|
+
Flags `send`, `public_send`, `__send__` with non-literal method names:
|
|
55
|
+
|
|
56
|
+
```ruby
|
|
57
|
+
# flagged
|
|
58
|
+
object.send(method_name)
|
|
59
|
+
|
|
60
|
+
# allowed
|
|
61
|
+
object.send(:known_method)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Exclusions**: GTK4 desktop code, Thor tasks (validated dispatch patterns)
|
|
65
|
+
|
|
66
|
+
### 3. Thread Safety Analysis
|
|
67
|
+
|
|
68
|
+
Added `rubocop-thread_safety` gem and enabled cops:
|
|
69
|
+
|
|
70
|
+
- `ThreadSafety/InstanceVariableInClassMethod`
|
|
71
|
+
- `ThreadSafety/ClassAndModuleAttributes`
|
|
72
|
+
- `ThreadSafety/MutableClassInstanceVariable`
|
|
73
|
+
|
|
74
|
+
This catches potential thread safety issues, especially relevant for the D-Bus
|
|
75
|
+
service which uses threads for shutdown handling.
|
|
76
|
+
|
|
77
|
+
### 4. Enhanced Content Pack Security
|
|
78
|
+
|
|
79
|
+
Strengthened `PackInstaller#reject_traversal!` to reject:
|
|
80
|
+
|
|
81
|
+
| Attack Vector | Check |
|
|
82
|
+
|---------------|-------|
|
|
83
|
+
| Parent traversal | `..` in path |
|
|
84
|
+
| Absolute paths | Starts with `/` |
|
|
85
|
+
| Home expansion | Starts with `~` |
|
|
86
|
+
| Null byte injection | Contains `\x00` |
|
|
87
|
+
|
|
88
|
+
Added canonical path verification in `extract_entry`:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
canonical_target = File.expand_path(target)
|
|
92
|
+
canonical_dest = File.expand_path(dest_dir)
|
|
93
|
+
unless canonical_target.start_with?(canonical_dest + '/')
|
|
94
|
+
raise RosettAi::ContentError, "Path escape rejected"
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 5. D-Bus Rate Limiting
|
|
99
|
+
|
|
100
|
+
Added `RosettAi::DBus::RateLimiter` using token bucket algorithm:
|
|
101
|
+
|
|
102
|
+
| Operation | Rate | Burst |
|
|
103
|
+
|-----------|------|-------|
|
|
104
|
+
| Default | 10 req/s | 20 |
|
|
105
|
+
| Compile | 2 req/s | 5 |
|
|
106
|
+
| Config | 5 req/s | 10 |
|
|
107
|
+
|
|
108
|
+
Rate limiting is applied to all ManagerInterface methods:
|
|
109
|
+
|
|
110
|
+
- `Compile`
|
|
111
|
+
- `SwitchContext`
|
|
112
|
+
- `GetStatus`
|
|
113
|
+
- `SetConfig`
|
|
114
|
+
- `ListEngines`
|
|
115
|
+
|
|
116
|
+
Exceeded limits raise D-Bus `LimitsExceeded` error.
|
|
117
|
+
|
|
118
|
+
## Files Created
|
|
119
|
+
|
|
120
|
+
| File | Purpose |
|
|
121
|
+
|------|---------|
|
|
122
|
+
| `lib/rubocop/cop/rosett-ai/unsafe_const_get.rb` | Advisory cop for const_get |
|
|
123
|
+
| `lib/rubocop/cop/rosett-ai/unsafe_send.rb` | Advisory cop for send |
|
|
124
|
+
| `lib/rosett_ai/dbus/rate_limiter.rb` | Token bucket rate limiter |
|
|
125
|
+
| `spec/rubocop/cop/rosett-ai/unsafe_const_get_spec.rb` | Cop tests |
|
|
126
|
+
| `spec/rubocop/cop/rosett-ai/unsafe_send_spec.rb` | Cop tests |
|
|
127
|
+
| `spec/rosett_ai/dbus/rate_limiter_spec.rb` | Rate limiter tests |
|
|
128
|
+
|
|
129
|
+
## Files Modified
|
|
130
|
+
|
|
131
|
+
| File | Change |
|
|
132
|
+
|------|--------|
|
|
133
|
+
| `Gemfile` | Added rubocop-thread_safety |
|
|
134
|
+
| `Gemfile.lock` | Added checksums, new gem |
|
|
135
|
+
| `.rubocop.yml` | Thread safety plugin, new cop configuration |
|
|
136
|
+
| `lib/rosett_ai/content/pack_installer.rb` | Enhanced path traversal checks |
|
|
137
|
+
| `lib/rosett_ai/dbus/manager_interface.rb` | Rate limiting integration |
|
|
138
|
+
| `spec/rosett_ai/content/pack_installer_spec.rb` | New path traversal tests |
|
|
139
|
+
| `.claude/SECURITY_REVIEW.md` | Updated gap status |
|
|
140
|
+
|
|
141
|
+
## Verification
|
|
142
|
+
|
|
143
|
+
- [ ] `bundle exec rubocop` — 0 offenses
|
|
144
|
+
- [ ] `bundle exec rspec` — all tests pass
|
|
145
|
+
- [ ] `overcommit -r` — all hooks pass
|
|
146
|
+
- [ ] `bundle exec bundler-audit check` — 0 vulnerabilities
|
|
147
|
+
- [ ] `bundle exec ruby-audit check` — 0 vulnerabilities
|
|
148
|
+
- [ ] Test-kitchen integration tests pass
|
|
149
|
+
|
|
150
|
+
## Security Impact
|
|
151
|
+
|
|
152
|
+
| Threat | Mitigation |
|
|
153
|
+
|--------|------------|
|
|
154
|
+
| Supply chain attack | Gemfile.lock checksums |
|
|
155
|
+
| Arbitrary class instantiation | UnsafeConstGet cop (advisory) |
|
|
156
|
+
| Arbitrary method execution | UnsafeSend cop (advisory) |
|
|
157
|
+
| Thread safety bugs | rubocop-thread_safety |
|
|
158
|
+
| Content pack zip slip | Enhanced path validation |
|
|
159
|
+
| D-Bus DoS | Token bucket rate limiting |
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
Generated by security hardening session on 2026-03-20
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Session Handoff — Pluggable Engine Architecture
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-03-07
|
|
4
|
+
**Status:** All phases COMPLETE — merged via MR
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Current State Summary
|
|
9
|
+
|
|
10
|
+
### Pluggable Engine Architecture — COMPLETE
|
|
11
|
+
|
|
12
|
+
All 6 phases of the pluggable engine architecture have been implemented:
|
|
13
|
+
|
|
14
|
+
| Phase | Description | Status | Branch |
|
|
15
|
+
|-------|-------------|--------|--------|
|
|
16
|
+
| 1 | Plugin contracts + dynamic registry | Done | `feature/pluggable-engines` |
|
|
17
|
+
| 2a | Extract Claude engine to separate gem | Done | `feature/pluggable-engines` |
|
|
18
|
+
| 2b | Extract remaining 9 engines to gems | Done | `feature/pluggable-engines` |
|
|
19
|
+
| 2c | Remove built-in engine code from core | Done | `feature/pluggable-engines` |
|
|
20
|
+
| 3 | ACME example engine plugin | Done | `feature/acme-example-engine` |
|
|
21
|
+
| 5-6 | Design doc + documentation updates | Done | `feature/acme-example-engine` |
|
|
22
|
+
|
|
23
|
+
### Quality Gates (all pass)
|
|
24
|
+
|
|
25
|
+
| Repository | RSpec | RuboCop | Reek | bundler-audit |
|
|
26
|
+
|-----------|-------|---------|------|---------------|
|
|
27
|
+
| rosett-ai core | 1285/0 (28 pending) | 224 files, 0 | 0 | 0 |
|
|
28
|
+
| rosett-ai-engine-claude | 123/0 | 21 files, 0 | 0 | 0 |
|
|
29
|
+
| rosett-ai-engine-generic | 21/0 | 10 files, 0 | 0 | 0 |
|
|
30
|
+
| rosett-ai-engine-agents-md | 29/0 | 12 files, 0 | 0 | 0 |
|
|
31
|
+
| rosett-ai-engine-acme | 27/0 | 12 files, 0 | 0 | 0 |
|
|
32
|
+
| rosett-ai-engine-ollama | 39/0 | 14 files, 0 | 0 | 0 |
|
|
33
|
+
| rosett-ai-engine-gpt-neox | 40/0 | 14 files, 0 | 0 | 0 |
|
|
34
|
+
| rosett-ai-engine-goose | 46/0 | 14 files, 0 | 0 | 0 |
|
|
35
|
+
| rosett-ai-engine-aider | 46/0 | 14 files, 0 | 0 | 0 |
|
|
36
|
+
| rosett-ai-engine-cursor | 29/0 | 12 files, 0 | 0 | 0 |
|
|
37
|
+
| rosett-ai-engine-copilot | 29/0 | 12 files, 0 | 0 | 0 |
|
|
38
|
+
| rosett-ai-engine-windsurf | 29/0 | 12 files, 0 | 0 | 0 |
|
|
39
|
+
| **Total** | **1743/0** | **0 offenses** | **0** | **0** |
|
|
40
|
+
|
|
41
|
+
### External Gem Repositories
|
|
42
|
+
|
|
43
|
+
| Gem | Location | Specs | Components |
|
|
44
|
+
|-----|----------|-------|------------|
|
|
45
|
+
| rosett-ai-engine-claude | `rosett-ai-engine-claude/` | 123 | backend, detector, executor, config_compiler, key_map, scope_router, domain_transformer |
|
|
46
|
+
| rosett-ai-engine-generic | `rosett-ai-engine-generic/` | 21 | backend |
|
|
47
|
+
| rosett-ai-engine-agents-md | `rosett-ai-engine-agents-md/` | 29 | backend, detector |
|
|
48
|
+
| rosett-ai-engine-acme | `rosett-ai-engine-acme/` | 27 | backend, detector (example) |
|
|
49
|
+
| rosett-ai-engine-ollama | `rosett-ai-engine-ollama/` | 39 | backend, detector, executor |
|
|
50
|
+
| rosett-ai-engine-gpt-neox | `rosett-ai-engine-gpt-neox/` | 40 | backend, detector, executor |
|
|
51
|
+
| rosett-ai-engine-goose | `rosett-ai-engine-goose/` | 46 | backend, detector, executor |
|
|
52
|
+
| rosett-ai-engine-aider | `rosett-ai-engine-aider/` | 46 | backend, detector, executor |
|
|
53
|
+
| rosett-ai-engine-cursor | `rosett-ai-engine-cursor/` | 29 | backend, detector |
|
|
54
|
+
| rosett-ai-engine-copilot | `rosett-ai-engine-copilot/` | 29 | backend, detector |
|
|
55
|
+
| rosett-ai-engine-windsurf | `rosett-ai-engine-windsurf/` | 29 | backend, detector |
|
|
56
|
+
|
|
57
|
+
### Key Architecture Decisions
|
|
58
|
+
|
|
59
|
+
- **Plugin types**: engine, gui, mcp (each with own contract module)
|
|
60
|
+
- **Discovery**: `Gem.find_files('nncc_{engine,gui,mcp}/*/register.rb')`
|
|
61
|
+
- **Namespace**: `RosettAiEngine::<Name>` in `lib/rosett_ai_engine/<name>/` (avoids Zeitwerk conflicts)
|
|
62
|
+
- **Base classes in core**: `RosettAi::Compiler::Backend`, `RosettAi::Engines::Detector`, `RosettAi::Engines::BaseConfigCompiler`
|
|
63
|
+
- **Self-registration**: Each gem's `register.rb` calls `RosettAi::Plugins::Registry.register(:engine, ...)`
|
|
64
|
+
- **Deprecated aliases**: `RosettAi::Config::*` and `RosettAi::Compiler::Backends::*` point to `RosettAiEngine::*`
|
|
65
|
+
- **GPL-3.0-only** on all repositories
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
*Last updated: 2026-03-07*
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# AI Engine Usage Trends — Market Research (2026)
|
|
2
|
+
|
|
3
|
+
Compiled: 2026-03-22
|
|
4
|
+
Context: NLnet grant research, validates ADR-006/ADR-007 multi-engine architecture
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
Industry data confirms that multi-engine usage and engine switching are standard practice,
|
|
9
|
+
not edge cases. rosett-ai's engine-agnostic architecture (ADR-007) is validated by market
|
|
10
|
+
reality. The problem rosett-ai solves — portable human intent across AI engines — is now
|
|
11
|
+
recognized industry-wide as "the new cloud vendor lock-in."
|
|
12
|
+
|
|
13
|
+
## Key Statistics
|
|
14
|
+
|
|
15
|
+
| Metric | Value | Source |
|
|
16
|
+
|--------|-------|--------|
|
|
17
|
+
| Developers using 3+ AI tools | 59% | Panto (2026) |
|
|
18
|
+
| Developers using 5+ AI tools | 20% | Panto (2026) |
|
|
19
|
+
| ChatGPT adoption | 82% | Stack Overflow (2025) |
|
|
20
|
+
| GitHub Copilot adoption | 68% | Stack Overflow (2025) |
|
|
21
|
+
| Daily AI tool usage | 51% | Stack Overflow (2025) |
|
|
22
|
+
| Developers using/planning AI tools | 84% | Stack Overflow (2025) |
|
|
23
|
+
| Positive sentiment (declining) | 60% (was 70%+) | Stack Overflow (2025) |
|
|
24
|
+
| Confidence in AI code quality (6+ tools) | 28% | Panto (2026) |
|
|
25
|
+
|
|
26
|
+
## Engine Migration Is Constant
|
|
27
|
+
|
|
28
|
+
- **Claude Code**: zero to #1 most-used tool in 8 months (launched May 2025)
|
|
29
|
+
- **Claude Code**: 46% "most loved" vs Cursor 19% vs Copilot 9%
|
|
30
|
+
- **When switching**: ALL project configuration and context is lost
|
|
31
|
+
- **Configuration portability**: does not exist between any two engines
|
|
32
|
+
- Developers must "re-explain project conventions from scratch every session"
|
|
33
|
+
|
|
34
|
+
### Implication for rosett-ai
|
|
35
|
+
The human intent declarations in `conf/behaviour/*.yml`, `conf/design/*.yml`, and
|
|
36
|
+
`conf/tooling/*.yml` survive engine migrations. A team that switches from Cursor to
|
|
37
|
+
Claude Code runs `rai compile` and retains all governance. This is the core value
|
|
38
|
+
proposition — validated by the data showing constant migration.
|
|
39
|
+
|
|
40
|
+
## Vendor Lock-In Is a Recognized Strategic Risk
|
|
41
|
+
|
|
42
|
+
- Framed as "the new cloud vendor lock-in of the AI era"
|
|
43
|
+
- Each tool has proprietary config: CLAUDE.md, .cursorrules, .windsurfrules
|
|
44
|
+
- AGENTS.md emerged (2025) as standardization attempt (OpenAI, Google, Cursor, Factory)
|
|
45
|
+
- rosett-ai already supports AGENTS.md as a compilation target (ADR-007)
|
|
46
|
+
|
|
47
|
+
### Implication for rosett-ai
|
|
48
|
+
raictl is positioned ahead of the standardization curve. While AGENTS.md addresses format
|
|
49
|
+
convergence for a subset of tools, rosett-ai treats ALL engines as compilation targets —
|
|
50
|
+
including those that will never adopt AGENTS.md (Copilot, Ollama, GPT-NeoX).
|
|
51
|
+
|
|
52
|
+
## Multi-Agent Trend (2026)
|
|
53
|
+
|
|
54
|
+
- Gartner: 1,445% surge in multi-agent system inquiries (Q1 2024 → Q2 2025)
|
|
55
|
+
- Trend: specialized teams of AI agents, not single assistants
|
|
56
|
+
- GitHub Agent HQ (Feb 2026): run Claude, Codex, Copilot simultaneously
|
|
57
|
+
- xAI Grok Build: up to 8 agents working simultaneously on different codebase parts
|
|
58
|
+
|
|
59
|
+
### Implication for rosett-ai
|
|
60
|
+
Validates the planned quorum proofing feature — parallel execution across engines for
|
|
61
|
+
cross-validation. Also validates the need for consistent governance across agents that
|
|
62
|
+
may be working simultaneously on the same codebase.
|
|
63
|
+
|
|
64
|
+
## Sources
|
|
65
|
+
|
|
66
|
+
- [AI Coding Statistics & Trends 2026 — Panto](https://www.getpanto.ai/blog/ai-coding-assistant-statistics)
|
|
67
|
+
- [Stack Overflow 2025 Developer Survey](https://survey.stackoverflow.co/2025/)
|
|
68
|
+
- [Stack Overflow Blog — Developers Remain Willing but Reluctant](https://stackoverflow.blog/2025/12/29/developers-remain-willing-but-reluctant-to-use-ai-the-2025-developer-survey-results-are-here/)
|
|
69
|
+
- [Breaking Free from AI Vendor Lock-In — Medium](https://medium.com/@alexzanfir/breaking-free-from-ai-vendor-lock-in-the-case-for-system-agnostic-development-568fea21b3c8)
|
|
70
|
+
- [AI Vendor Lock-In Trap 2025 — Fusion](https://tryfusion.ai/blog/the-2025-ai-vendor-lock-in-trap-and-how-to-build-your-exit)
|
|
71
|
+
- [AI Vendor Lock-In Strategic Risk — Kellton](https://www.kellton.com/kellton-tech-blog/why-vendor-lock-in-is-riskier-in-genai-era-and-how-to-avoid-it)
|
|
72
|
+
- [AI Vendor Lock-In — CTO Magazine](https://ctomagazine.com/ai-vendor-lock-in-cto-strategy/)
|
|
73
|
+
- [DEV Community — AI Coding Assistants Comparison 2025](https://dev.to/_d7eb1c1703182e3ce1782/best-ai-coding-assistants-2025-claude-vs-copilot-vs-cursor-honest-comparison-4oh8)
|
|
74
|
+
- [DEV Community — Claude Code vs Cursor vs Copilot 2026](https://dev.to/alexcloudstar/claude-code-vs-cursor-vs-github-copilot-the-2026-ai-coding-tool-showdown-53n4)
|
|
75
|
+
- [Agentic Coding 2026 — Multi-Agent Teams](https://aiautomationglobal.com/blog/agentic-coding-revolution-multi-agent-teams-2026)
|
|
76
|
+
- [State of AI Coding Agents 2026 — Medium](https://medium.com/@dave-patten/the-state-of-ai-coding-agents-2026-from-pair-programming-to-autonomous-ai-teams-b11f2b39232a)
|
|
77
|
+
|
|
78
|
+
## Action Items
|
|
79
|
+
|
|
80
|
+
See `doc/issues/004-market-research-design-updates.md` for follow-up tasks.
|