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.
Files changed (527) hide show
  1. checksums.yaml +7 -0
  2. data/.ai-provenance.yml +119 -0
  3. data/.debride_whitelist +186 -0
  4. data/.fasterer.yml +29 -0
  5. data/.mdl_style.rb +10 -0
  6. data/.mdlrc +3 -0
  7. data/.mutant.yml +49 -0
  8. data/.namespace-allowlist +42 -0
  9. data/.reek.yml +1040 -0
  10. data/.rosett-ai/config.yml +3 -0
  11. data/.rspec +5 -0
  12. data/.rubocop.yml +380 -0
  13. data/.ruby-version +1 -0
  14. data/.yamllint +51 -0
  15. data/.yardopts +12 -0
  16. data/AI-DISCLOSURE.md +48 -0
  17. data/CHANGELOG.md +519 -0
  18. data/CLAUDE.md +141 -0
  19. data/CONTRIBUTING.md +734 -0
  20. data/INSTALL.md +154 -0
  21. data/LICENSE +674 -0
  22. data/LICENSE.md +675 -0
  23. data/QUICKSTART.md +73 -0
  24. data/README.md +366 -0
  25. data/Rakefile +200 -0
  26. data/SECURITY.md +114 -0
  27. data/bin/rai +1 -0
  28. data/cliff.toml +52 -0
  29. data/conf/adopt_redactions.yml +8 -0
  30. data/conf/behaviour/.gitkeep +0 -0
  31. data/conf/compliance/cra_rules.yml +25 -0
  32. data/conf/compliance/license_rules.yml +20 -0
  33. data/conf/design/aaif_alignment.yml +181 -0
  34. data/conf/design/ab_testing.yml +172 -0
  35. data/conf/design/accessibility.yml +84 -0
  36. data/conf/design/ai_authorship.yml +210 -0
  37. data/conf/design/ai_provenance.yml +224 -0
  38. data/conf/design/ai_tool_configuration.yml +207 -0
  39. data/conf/design/architecture.yml +139 -0
  40. data/conf/design/autocompletion.yml +115 -0
  41. data/conf/design/backward_compatibility.yml +112 -0
  42. data/conf/design/behaviour_composition.yml +246 -0
  43. data/conf/design/build_rake_extraction.yml +57 -0
  44. data/conf/design/ci_pipeline.yml +100 -0
  45. data/conf/design/claude_code_configuration.yml +157 -0
  46. data/conf/design/compiler.yml +128 -0
  47. data/conf/design/comply.yml +153 -0
  48. data/conf/design/content_packs.yml +84 -0
  49. data/conf/design/desktop_integration.yml +289 -0
  50. data/conf/design/distribution.yml +216 -0
  51. data/conf/design/doctor.yml +184 -0
  52. data/conf/design/documentation.yml +152 -0
  53. data/conf/design/engine_architecture.yml +257 -0
  54. data/conf/design/error_handling.yml +103 -0
  55. data/conf/design/feature_flags.yml +142 -0
  56. data/conf/design/git_hooks.yml +165 -0
  57. data/conf/design/gui_plugins.yml +475 -0
  58. data/conf/design/i18n.yml +84 -0
  59. data/conf/design/integration_testing.yml +56 -0
  60. data/conf/design/licensing_system.yml +88 -0
  61. data/conf/design/lifecycle_management.yml +208 -0
  62. data/conf/design/mcp_integration.yml +207 -0
  63. data/conf/design/mcp_settings.yml +126 -0
  64. data/conf/design/migration.yml +56 -0
  65. data/conf/design/monitoring_observability.yml +194 -0
  66. data/conf/design/namespace_cleanup.yml +145 -0
  67. data/conf/design/plugin_test_segregation.yml +145 -0
  68. data/conf/design/policy_management.yml +229 -0
  69. data/conf/design/project_management.yml +183 -0
  70. data/conf/design/rai_mcp_asset_discovery.yml +164 -0
  71. data/conf/design/rai_mcp_server.yml +605 -0
  72. data/conf/design/release_management.yml +117 -0
  73. data/conf/design/retrofit.yml +199 -0
  74. data/conf/design/retrospective_analyzer.yml +79 -0
  75. data/conf/design/scope_hierarchy.yml +352 -0
  76. data/conf/design/security.yml +115 -0
  77. data/conf/design/session_retrospective.yml +85 -0
  78. data/conf/design/smart_ui_feedback.yml +89 -0
  79. data/conf/design/structured_logging.yml +148 -0
  80. data/conf/design/styles.yml +123 -0
  81. data/conf/design/test_peer_review.yml +89 -0
  82. data/conf/design/testing.yml +136 -0
  83. data/conf/design/threat_model.yml +108 -0
  84. data/conf/design/ui_framework.yml +111 -0
  85. data/conf/design/usage_optimization.yml +122 -0
  86. data/conf/design/version_management.yml +60 -0
  87. data/conf/design/workflow.yml +227 -0
  88. data/conf/mcp/server_defaults.yml +42 -0
  89. data/conf/mcp/trust.yml +21 -0
  90. data/conf/packaging/core.yml +12 -0
  91. data/conf/packaging/gtk4.yml +11 -0
  92. data/conf/packaging/qt6.yml +11 -0
  93. data/conf/policy/default_deny_list.yml +197 -0
  94. data/conf/review/cli-command-audit.yml +857 -0
  95. data/conf/review/design-docs.yml +1064 -0
  96. data/conf/review/design-questionnaire.yml +153 -0
  97. data/conf/review/questionnaire.yml +146 -0
  98. data/conf/review/rosett-ai-core.yml +2919 -0
  99. data/conf/schemas/ai_config_schema.json +73 -0
  100. data/conf/schemas/behaviour_schema.json +132 -0
  101. data/conf/schemas/compliance_rule_schema.json +63 -0
  102. data/conf/schemas/content_pack_manifest_schema.json +51 -0
  103. data/conf/schemas/design_schema.json +210 -0
  104. data/conf/schemas/engine_manifest_schema.json +144 -0
  105. data/conf/schemas/lockfile_schema.json +74 -0
  106. data/conf/schemas/mcp_server_schema.json +48 -0
  107. data/conf/schemas/packaging_schema.json +70 -0
  108. data/conf/schemas/policy_schema.json +85 -0
  109. data/conf/schemas/provenance_schema.json +84 -0
  110. data/conf/schemas/rai_config_schema.json +56 -0
  111. data/conf/schemas/rai_project_schema.json +20 -0
  112. data/conf/schemas/scope_hierarchy_schema.json +49 -0
  113. data/conf/schemas/target_schema.json +67 -0
  114. data/conf/schemas/tooling_schema.json +65 -0
  115. data/conf/schemas/workflow_schema.json +112 -0
  116. data/conf/targets/agents_md.yml +17 -0
  117. data/conf/targets/claude.yml +12 -0
  118. data/conf/tooling/tools.yml +58 -0
  119. data/dist/rosett-ai-mcp.service +48 -0
  120. data/dist/rosett-ai-mcp.yml.default +45 -0
  121. data/doc/AAIF_POSITIONING.md +58 -0
  122. data/doc/ADOPT.md +224 -0
  123. data/doc/AI_PROVENANCE.md +139 -0
  124. data/doc/ARCHITECTURE.md +920 -0
  125. data/doc/BEHAVIOUR.md +409 -0
  126. data/doc/BUILD.md +138 -0
  127. data/doc/CI_CD_RECIPES.md +171 -0
  128. data/doc/CLAUDE_SESSIONS_MOVED.md +16 -0
  129. data/doc/COMMAND_ANALYSIS.md +229 -0
  130. data/doc/CONFIGURATION.md +281 -0
  131. data/doc/DESIGN_AUDIT.md +235 -0
  132. data/doc/DESIGN_PEER_REVIEW.md +771 -0
  133. data/doc/DESKTOP.md +447 -0
  134. data/doc/ENGINES.md +567 -0
  135. data/doc/ENGINE_DEVELOPMENT_GUIDE.md +417 -0
  136. data/doc/FEATURE_AUDIT.md +218 -0
  137. data/doc/IMPLEMENTATION_PLAN.md +669 -0
  138. data/doc/INCIDENT_REPORT_2026-02-02.md +251 -0
  139. data/doc/MIGRATION_GUIDE.md +88 -0
  140. data/doc/PACKAGING.md +232 -0
  141. data/doc/PROJECT_DASHBOARD.md +153 -0
  142. data/doc/PULP_DEPLOYMENT.md +164 -0
  143. data/doc/QUALITY_FIX_SUMMARY.md +110 -0
  144. data/doc/QUICK_START.md +162 -0
  145. data/doc/REEK_CONFIGURATION.md +166 -0
  146. data/doc/REFERENCE.md +253 -0
  147. data/doc/REFERENCES.md +324 -0
  148. data/doc/SECURITY_REVIEW_CHECKLIST.md +72 -0
  149. data/doc/SESSION_2026-02-28_GTK4_HARDENING.md +359 -0
  150. data/doc/SETUP.md +202 -0
  151. data/doc/TEST_PEER_REVIEW.md +152 -0
  152. data/doc/THREAT_MODEL.md +230 -0
  153. data/doc/USAGE.md +545 -0
  154. data/doc/USER_MANUAL.md +585 -0
  155. data/doc/ai_test_review_checklist.md +110 -0
  156. data/doc/changes/2026-02-18-packaging-fpm.md +155 -0
  157. data/doc/changes/2026-02-19-testing-infrastructure.md +221 -0
  158. data/doc/changes/2026-02-20-security-implementation.md +281 -0
  159. data/doc/changes/2026-02-20-styles-implementation.md +220 -0
  160. data/doc/changes/2026-02-21-architecture-completion.md +95 -0
  161. data/doc/changes/2026-02-21-architecture-ui-layer.md +253 -0
  162. data/doc/changes/2026-02-21-cc-config-implementation.md +108 -0
  163. data/doc/changes/2026-02-21-ci-pipeline-implementation.md +214 -0
  164. data/doc/changes/2026-02-21-compiler-multi-target-pipeline.md +241 -0
  165. data/doc/changes/2026-02-21-config-design-show-commands.md +61 -0
  166. data/doc/changes/2026-02-21-design-implementation-overview.md +455 -0
  167. data/doc/changes/2026-02-21-lifecycle-management.md +196 -0
  168. data/doc/changes/2026-02-21-path-resolver.md +128 -0
  169. data/doc/changes/2026-02-24-ci-tmpdir-mutant-fetch.md +45 -0
  170. data/doc/changes/2026-03-01-ci-bundler-strategy.md +120 -0
  171. data/doc/changes/2026-03-20-security-hardening-phase2.md +163 -0
  172. data/doc/context/SESSION-HANDOFF.md +69 -0
  173. data/doc/context/ai-engine-usage-trends-2026.md +80 -0
  174. data/doc/context/plan-pluggable-engines.md +590 -0
  175. data/doc/decisions/001-flog-deferred.md +32 -0
  176. data/doc/decisions/002-path-resolution-strategy.md +158 -0
  177. data/doc/decisions/003-ui-adapter-selection.md +193 -0
  178. data/doc/decisions/004-design-document-validation.md +179 -0
  179. data/doc/decisions/005-package-splitting-strategy.md +200 -0
  180. data/doc/decisions/006-multi-engine-architecture.md +147 -0
  181. data/doc/decisions/007-engine-agnostic-pivot.md +219 -0
  182. data/doc/decisions/008-ci-bundler-strategy.md +129 -0
  183. data/doc/decisions/009-core-only-v1-release.md +60 -0
  184. data/doc/decisions/010-engine-debian-packaging.md +66 -0
  185. data/doc/decisions/011-context-aware-cli.md +71 -0
  186. data/doc/dependency_decisions.yml +247 -0
  187. data/doc/issues/001-wrapper-missing-environment-variables.md +197 -0
  188. data/doc/issues/002-embedded-ruby-wrong-prefix.md +217 -0
  189. data/doc/issues/003-smoke-test-false-positive.md +127 -0
  190. data/doc/issues/004-market-research-design-updates.md +109 -0
  191. data/doc/issues/005-compile-scope-coexistence.md +161 -0
  192. data/doc/locales/.gitkeep +0 -0
  193. data/doc/man/rai.1.ronn +505 -0
  194. data/doc/operations/packaging.md +133 -0
  195. data/doc/operations/rosett-ai-release.md +65 -0
  196. data/doc/reference/error-catalog.md +107 -0
  197. data/doc/reference/rosett-ai-technical-reference.pdf +0 -0
  198. data/doc/reference/src/Pictures/cover.jpg +0 -0
  199. data/doc/reference/src/Pictures/head1.jpg +0 -0
  200. data/doc/reference/src/Pictures/head2.jpg +0 -0
  201. data/doc/reference/src/Pictures/head3.jpg +0 -0
  202. data/doc/reference/src/Pictures/head4.jpg +0 -0
  203. data/doc/reference/src/Pictures/head5.jpg +0 -0
  204. data/doc/reference/src/Pictures/head6.jpg +0 -0
  205. data/doc/reference/src/Pictures/head7.jpg +0 -0
  206. data/doc/reference/src/Pictures/head8.jpg +0 -0
  207. data/doc/reference/src/StyleInd.ist +4 -0
  208. data/doc/reference/src/bibliography.bib +79 -0
  209. data/doc/reference/src/main.tex +1288 -0
  210. data/doc/reference/src/structure.tex +303 -0
  211. data/doc/rosett-ai-bookmarks.html +301 -0
  212. data/kitchen.yml +46 -0
  213. data/lib/rosett_ai/adopter/executor_resolver.rb +77 -0
  214. data/lib/rosett_ai/adopter/local_analysis_collector.rb +154 -0
  215. data/lib/rosett_ai/adopter/rule_adopter.rb +254 -0
  216. data/lib/rosett_ai/ai_config/config_compiler.rb +111 -0
  217. data/lib/rosett_ai/ai_config/context_window.rb +55 -0
  218. data/lib/rosett_ai/ai_config/cost_controls.rb +44 -0
  219. data/lib/rosett_ai/ai_config/fallback_chain.rb +64 -0
  220. data/lib/rosett_ai/ai_config/model_router.rb +121 -0
  221. data/lib/rosett_ai/ai_config/validator.rb +45 -0
  222. data/lib/rosett_ai/authorship/attribution_compiler.rb +99 -0
  223. data/lib/rosett_ai/authorship/disclosure_policy.rb +81 -0
  224. data/lib/rosett_ai/authorship/review_validator.rb +39 -0
  225. data/lib/rosett_ai/authorship/trailer_generator.rb +88 -0
  226. data/lib/rosett_ai/backup/compressor.rb +180 -0
  227. data/lib/rosett_ai/backup/destination.rb +91 -0
  228. data/lib/rosett_ai/behaviour/manager.rb +156 -0
  229. data/lib/rosett_ai/compiler/backend.rb +86 -0
  230. data/lib/rosett_ai/compiler/backends/agents_md_backend.rb +80 -0
  231. data/lib/rosett_ai/compiler/backends/claude_backend.rb +88 -0
  232. data/lib/rosett_ai/compiler/backends/generic_backend.rb +15 -0
  233. data/lib/rosett_ai/compiler/behaviour_compiler.rb +40 -0
  234. data/lib/rosett_ai/compiler/capability_checker.rb +104 -0
  235. data/lib/rosett_ai/compiler/compilation_pipeline.rb +361 -0
  236. data/lib/rosett_ai/compiler/compiled_output.rb +39 -0
  237. data/lib/rosett_ai/compiler/locale_compiler.rb +250 -0
  238. data/lib/rosett_ai/compiler/target_profile.rb +112 -0
  239. data/lib/rosett_ai/completion/generator.rb +101 -0
  240. data/lib/rosett_ai/completion/shells/bash_generator.rb +126 -0
  241. data/lib/rosett_ai/completion/shells/fish_generator.rb +78 -0
  242. data/lib/rosett_ai/completion/shells/zsh_generator.rb +126 -0
  243. data/lib/rosett_ai/comply/checkers/cra_checker.rb +102 -0
  244. data/lib/rosett_ai/comply/checkers/license_checker.rb +85 -0
  245. data/lib/rosett_ai/comply/checkers/spdx_header_checker.rb +98 -0
  246. data/lib/rosett_ai/comply/reporter.rb +113 -0
  247. data/lib/rosett_ai/comply/runner.rb +50 -0
  248. data/lib/rosett_ai/composition/circular_dependency_detector.rb +56 -0
  249. data/lib/rosett_ai/composition/composer.rb +158 -0
  250. data/lib/rosett_ai/composition/composition_result.rb +64 -0
  251. data/lib/rosett_ai/composition/conflict_detector.rb +53 -0
  252. data/lib/rosett_ai/composition/lockfile.rb +103 -0
  253. data/lib/rosett_ai/composition/merge_strategy.rb +131 -0
  254. data/lib/rosett_ai/composition/priority_sorter.rb +29 -0
  255. data/lib/rosett_ai/composition/scope_resolver.rb +55 -0
  256. data/lib/rosett_ai/config/compile_result.rb +37 -0
  257. data/lib/rosett_ai/config/compiler.rb +13 -0
  258. data/lib/rosett_ai/config/domain_transformer.rb +13 -0
  259. data/lib/rosett_ai/config/key_map.rb +13 -0
  260. data/lib/rosett_ai/config/masking_secret_resolver.rb +40 -0
  261. data/lib/rosett_ai/config/scope_router.rb +13 -0
  262. data/lib/rosett_ai/config/secret_resolver.rb +125 -0
  263. data/lib/rosett_ai/configuration.rb +119 -0
  264. data/lib/rosett_ai/content/content_client.rb +60 -0
  265. data/lib/rosett_ai/content/pack_installer.rb +117 -0
  266. data/lib/rosett_ai/content/pack_manifest.rb +50 -0
  267. data/lib/rosett_ai/content/pack_registry.rb +68 -0
  268. data/lib/rosett_ai/content_packs/manager.rb +50 -0
  269. data/lib/rosett_ai/dbus/compositor_detector.rb +77 -0
  270. data/lib/rosett_ai/dbus/focus_adapters/base.rb +59 -0
  271. data/lib/rosett_ai/dbus/focus_adapters/gnome_adapter.rb +172 -0
  272. data/lib/rosett_ai/dbus/focus_adapters/hyprland_adapter.rb +77 -0
  273. data/lib/rosett_ai/dbus/focus_adapters/i3_adapter.rb +65 -0
  274. data/lib/rosett_ai/dbus/focus_adapters/kwin_adapter.rb +103 -0
  275. data/lib/rosett_ai/dbus/focus_adapters/x11_adapter.rb +105 -0
  276. data/lib/rosett_ai/dbus/focus_monitor_interface.rb +103 -0
  277. data/lib/rosett_ai/dbus/manager_interface.rb +213 -0
  278. data/lib/rosett_ai/dbus/plugin_manager_interface.rb +169 -0
  279. data/lib/rosett_ai/dbus/rate_limiter.rb +89 -0
  280. data/lib/rosett_ai/dbus/service.rb +121 -0
  281. data/lib/rosett_ai/dbus/status_notifier_interface.rb +79 -0
  282. data/lib/rosett_ai/deprecation.rb +79 -0
  283. data/lib/rosett_ai/desktop/dbus_client.rb +259 -0
  284. data/lib/rosett_ai/desktop/gtk4_app.rb +371 -0
  285. data/lib/rosett_ai/desktop/gtk4_preferences.rb +331 -0
  286. data/lib/rosett_ai/desktop/gui_logger.rb +236 -0
  287. data/lib/rosett_ai/doctor/check.rb +92 -0
  288. data/lib/rosett_ai/doctor/checks/cache_health_check.rb +50 -0
  289. data/lib/rosett_ai/doctor/checks/dbus_availability_check.rb +39 -0
  290. data/lib/rosett_ai/doctor/checks/engine_detection_check.rb +46 -0
  291. data/lib/rosett_ai/doctor/checks/file_permission_check.rb +44 -0
  292. data/lib/rosett_ai/doctor/checks/gem_dependency_check.rb +55 -0
  293. data/lib/rosett_ai/doctor/checks/ruby_version_check.rb +50 -0
  294. data/lib/rosett_ai/doctor/checks/stale_config_nncc_check.rb +57 -0
  295. data/lib/rosett_ai/doctor/checks/stale_home_nncc_check.rb +59 -0
  296. data/lib/rosett_ai/doctor.rb +81 -0
  297. data/lib/rosett_ai/documentation/reference_compiler.rb +122 -0
  298. data/lib/rosett_ai/documentation/translator.rb +62 -0
  299. data/lib/rosett_ai/engines/base_config_compiler.rb +203 -0
  300. data/lib/rosett_ai/engines/detector.rb +63 -0
  301. data/lib/rosett_ai/engines/registry.rb +50 -0
  302. data/lib/rosett_ai/error_handler.rb +139 -0
  303. data/lib/rosett_ai/exit_codes.rb +76 -0
  304. data/lib/rosett_ai/feature_flags.rb +102 -0
  305. data/lib/rosett_ai/formatting.rb +33 -0
  306. data/lib/rosett_ai/gem_consistency_checker.rb +199 -0
  307. data/lib/rosett_ai/git_hooks/chain_detector.rb +86 -0
  308. data/lib/rosett_ai/git_hooks/installer.rb +175 -0
  309. data/lib/rosett_ai/git_hooks/script_generator.rb +125 -0
  310. data/lib/rosett_ai/gitlab/validators/supplementary_gitlab_ci_yaml_validator.rb +79 -0
  311. data/lib/rosett_ai/i18n/locale_resolver.rb +46 -0
  312. data/lib/rosett_ai/i18n/utf8_checker.rb +32 -0
  313. data/lib/rosett_ai/init/config_file_writer.rb +24 -0
  314. data/lib/rosett_ai/init/directory_builder.rb +38 -0
  315. data/lib/rosett_ai/init/file_copier.rb +95 -0
  316. data/lib/rosett_ai/init/global_initializer.rb +28 -0
  317. data/lib/rosett_ai/init/local_initializer.rb +27 -0
  318. data/lib/rosett_ai/init/mcp_registrar.rb +109 -0
  319. data/lib/rosett_ai/init/project_initializer.rb +38 -0
  320. data/lib/rosett_ai/licensing/license_key.rb +139 -0
  321. data/lib/rosett_ai/licensing/license_store.rb +64 -0
  322. data/lib/rosett_ai/licensing/license_validator.rb +60 -0
  323. data/lib/rosett_ai/licensing/tier.rb +42 -0
  324. data/lib/rosett_ai/mcp/admin/auditor.rb +88 -0
  325. data/lib/rosett_ai/mcp/admin/health_checker.rb +81 -0
  326. data/lib/rosett_ai/mcp/admin/registry.rb +100 -0
  327. data/lib/rosett_ai/mcp/admin/schema_validator.rb +63 -0
  328. data/lib/rosett_ai/mcp/enforcement/.gitkeep +0 -0
  329. data/lib/rosett_ai/mcp/enforcement/hook_generator.rb +197 -0
  330. data/lib/rosett_ai/mcp/enforcement/validator.rb +215 -0
  331. data/lib/rosett_ai/mcp/governance.rb +160 -0
  332. data/lib/rosett_ai/mcp/http_security_config.rb +158 -0
  333. data/lib/rosett_ai/mcp/instructions.rb +266 -0
  334. data/lib/rosett_ai/mcp/key_hasher.rb +66 -0
  335. data/lib/rosett_ai/mcp/keyfile.rb +221 -0
  336. data/lib/rosett_ai/mcp/middleware/authentication.rb +146 -0
  337. data/lib/rosett_ai/mcp/middleware/content_type.rb +56 -0
  338. data/lib/rosett_ai/mcp/middleware/cors.rb +83 -0
  339. data/lib/rosett_ai/mcp/middleware/origin_validation.rb +73 -0
  340. data/lib/rosett_ai/mcp/middleware/rate_limit.rb +106 -0
  341. data/lib/rosett_ai/mcp/middleware/request_size.rb +51 -0
  342. data/lib/rosett_ai/mcp/plugins.rb +143 -0
  343. data/lib/rosett_ai/mcp/prompts/compilation_prompt.rb +40 -0
  344. data/lib/rosett_ai/mcp/prompts/compliance_prompt.rb +41 -0
  345. data/lib/rosett_ai/mcp/prompts/diagnostics_prompt.rb +41 -0
  346. data/lib/rosett_ai/mcp/prompts/validation_prompt.rb +41 -0
  347. data/lib/rosett_ai/mcp/resources/behaviour_resource.rb +127 -0
  348. data/lib/rosett_ai/mcp/resources/config_resource.rb +72 -0
  349. data/lib/rosett_ai/mcp/resources/design_resource.rb +58 -0
  350. data/lib/rosett_ai/mcp/resources/hooks_resource.rb +74 -0
  351. data/lib/rosett_ai/mcp/resources/provenance_resource.rb +51 -0
  352. data/lib/rosett_ai/mcp/resources/rules_resource.rb +60 -0
  353. data/lib/rosett_ai/mcp/resources/schema_resource.rb +72 -0
  354. data/lib/rosett_ai/mcp/response_helper.rb +46 -0
  355. data/lib/rosett_ai/mcp/security_logger.rb +60 -0
  356. data/lib/rosett_ai/mcp/server.rb +212 -0
  357. data/lib/rosett_ai/mcp/settings/server_installer.rb +112 -0
  358. data/lib/rosett_ai/mcp/settings/trust_manager.rb +142 -0
  359. data/lib/rosett_ai/mcp/tools/adopt_tool.rb +70 -0
  360. data/lib/rosett_ai/mcp/tools/backup_tool.rb +64 -0
  361. data/lib/rosett_ai/mcp/tools/behaviour_display_tool.rb +72 -0
  362. data/lib/rosett_ai/mcp/tools/behaviour_list_tool.rb +56 -0
  363. data/lib/rosett_ai/mcp/tools/behaviour_manage_tool.rb +114 -0
  364. data/lib/rosett_ai/mcp/tools/behaviour_show_tool.rb +62 -0
  365. data/lib/rosett_ai/mcp/tools/compile_status_tool.rb +122 -0
  366. data/lib/rosett_ai/mcp/tools/compile_tool.rb +191 -0
  367. data/lib/rosett_ai/mcp/tools/comply_tool.rb +79 -0
  368. data/lib/rosett_ai/mcp/tools/config_compile_tool.rb +71 -0
  369. data/lib/rosett_ai/mcp/tools/config_status_tool.rb +79 -0
  370. data/lib/rosett_ai/mcp/tools/content_tool.rb +78 -0
  371. data/lib/rosett_ai/mcp/tools/context_query_tool.rb +156 -0
  372. data/lib/rosett_ai/mcp/tools/design_list_tool.rb +57 -0
  373. data/lib/rosett_ai/mcp/tools/design_show_tool.rb +69 -0
  374. data/lib/rosett_ai/mcp/tools/doctor_tool.rb +62 -0
  375. data/lib/rosett_ai/mcp/tools/documentation_status_tool.rb +45 -0
  376. data/lib/rosett_ai/mcp/tools/engines_tool.rb +84 -0
  377. data/lib/rosett_ai/mcp/tools/hook_install_tool.rb +190 -0
  378. data/lib/rosett_ai/mcp/tools/hook_preview_tool.rb +173 -0
  379. data/lib/rosett_ai/mcp/tools/hooks_status_tool.rb +84 -0
  380. data/lib/rosett_ai/mcp/tools/init_tool.rb +87 -0
  381. data/lib/rosett_ai/mcp/tools/license_status_tool.rb +44 -0
  382. data/lib/rosett_ai/mcp/tools/project_tool.rb +117 -0
  383. data/lib/rosett_ai/mcp/tools/provenance_tool.rb +97 -0
  384. data/lib/rosett_ai/mcp/tools/provenance_write_tool.rb +40 -0
  385. data/lib/rosett_ai/mcp/tools/retrofit_tool.rb +81 -0
  386. data/lib/rosett_ai/mcp/tools/rule_search_tool.rb +163 -0
  387. data/lib/rosett_ai/mcp/tools/schema_get_tool.rb +94 -0
  388. data/lib/rosett_ai/mcp/tools/tooling_tool.rb +86 -0
  389. data/lib/rosett_ai/mcp/tools/validate_tool.rb +105 -0
  390. data/lib/rosett_ai/mcp/tools/workflow_execute_tool.rb +74 -0
  391. data/lib/rosett_ai/mcp/tools/workflow_tool.rb +78 -0
  392. data/lib/rosett_ai/migration/detector.rb +117 -0
  393. data/lib/rosett_ai/migration/nncc_config_migrator.rb +94 -0
  394. data/lib/rosett_ai/migration/nncc_project_migrator.rb +90 -0
  395. data/lib/rosett_ai/migration/xdg_migrator.rb +123 -0
  396. data/lib/rosett_ai/package_manager/apt.rb +108 -0
  397. data/lib/rosett_ai/package_manager/base.rb +68 -0
  398. data/lib/rosett_ai/package_manager/gem_backend.rb +90 -0
  399. data/lib/rosett_ai/packaging/variant_config.rb +92 -0
  400. data/lib/rosett_ai/path_resolver.rb +115 -0
  401. data/lib/rosett_ai/plugins/contract.rb +43 -0
  402. data/lib/rosett_ai/plugins/engine_contract.rb +60 -0
  403. data/lib/rosett_ai/plugins/gui_contract.rb +74 -0
  404. data/lib/rosett_ai/plugins/mcp_contract.rb +48 -0
  405. data/lib/rosett_ai/plugins/registry.rb +150 -0
  406. data/lib/rosett_ai/policy/auditor.rb +41 -0
  407. data/lib/rosett_ai/policy/deny_list.rb +71 -0
  408. data/lib/rosett_ai/policy/opt_out_scanner.rb +37 -0
  409. data/lib/rosett_ai/policy/policy_compiler.rb +84 -0
  410. data/lib/rosett_ai/policy/protected_files.rb +47 -0
  411. data/lib/rosett_ai/policy/tier_hierarchy.rb +48 -0
  412. data/lib/rosett_ai/policy/validator.rb +35 -0
  413. data/lib/rosett_ai/profiler.rb +79 -0
  414. data/lib/rosett_ai/project/drift_detector.rb +126 -0
  415. data/lib/rosett_ai/project/manager.rb +115 -0
  416. data/lib/rosett_ai/project/sync_manager.rb +138 -0
  417. data/lib/rosett_ai/project/template_applier.rb +105 -0
  418. data/lib/rosett_ai/project_context.rb +82 -0
  419. data/lib/rosett_ai/provenance/entry.rb +63 -0
  420. data/lib/rosett_ai/provenance/file_source.rb +32 -0
  421. data/lib/rosett_ai/provenance/source.rb +62 -0
  422. data/lib/rosett_ai/provenance/store.rb +153 -0
  423. data/lib/rosett_ai/provenance/tracker.rb +62 -0
  424. data/lib/rosett_ai/provenance/trailer_generator.rb +43 -0
  425. data/lib/rosett_ai/provenance/validator.rb +45 -0
  426. data/lib/rosett_ai/quorum/collector.rb +59 -0
  427. data/lib/rosett_ai/quorum/comparator.rb +81 -0
  428. data/lib/rosett_ai/quorum/dispatcher.rb +57 -0
  429. data/lib/rosett_ai/quorum/strategies/adopt.rb +56 -0
  430. data/lib/rosett_ai/rai_config.rb +107 -0
  431. data/lib/rosett_ai/retrofit/base_parser.rb +66 -0
  432. data/lib/rosett_ai/retrofit/engine.rb +171 -0
  433. data/lib/rosett_ai/retrofit/parsers/agents_md_parser.rb +50 -0
  434. data/lib/rosett_ai/retrofit/parsers/claude_parser.rb +69 -0
  435. data/lib/rosett_ai/retrofit/parsers/cursor_parser.rb +82 -0
  436. data/lib/rosett_ai/retrofit/round_trip_validator.rb +65 -0
  437. data/lib/rosett_ai/retrofit/scanner.rb +47 -0
  438. data/lib/rosett_ai/retrofit/secret_detector.rb +87 -0
  439. data/lib/rosett_ai/secrets_resolver.rb +71 -0
  440. data/lib/rosett_ai/smart_feedback/suggester.rb +83 -0
  441. data/lib/rosett_ai/smart_feedback/thor_middleware.rb +84 -0
  442. data/lib/rosett_ai/structured_logger.rb +110 -0
  443. data/lib/rosett_ai/telemetry/json_lines_writer.rb +50 -0
  444. data/lib/rosett_ai/telemetry/log_rotator.rb +67 -0
  445. data/lib/rosett_ai/telemetry/provider.rb +26 -0
  446. data/lib/rosett_ai/telemetry/reporter.rb +144 -0
  447. data/lib/rosett_ai/telemetry.rb +47 -0
  448. data/lib/rosett_ai/text_sanitizer.rb +62 -0
  449. data/lib/rosett_ai/thor/cli.rb +269 -0
  450. data/lib/rosett_ai/thor/tasks/adopt.rb +250 -0
  451. data/lib/rosett_ai/thor/tasks/backup.rb +420 -0
  452. data/lib/rosett_ai/thor/tasks/behaviour.rb +474 -0
  453. data/lib/rosett_ai/thor/tasks/build.rb +1162 -0
  454. data/lib/rosett_ai/thor/tasks/compile.rb +415 -0
  455. data/lib/rosett_ai/thor/tasks/completion.rb +123 -0
  456. data/lib/rosett_ai/thor/tasks/comply.rb +82 -0
  457. data/lib/rosett_ai/thor/tasks/config.rb +265 -0
  458. data/lib/rosett_ai/thor/tasks/content.rb +193 -0
  459. data/lib/rosett_ai/thor/tasks/dbus.rb +321 -0
  460. data/lib/rosett_ai/thor/tasks/design.rb +258 -0
  461. data/lib/rosett_ai/thor/tasks/desktop.rb +129 -0
  462. data/lib/rosett_ai/thor/tasks/doctor.rb +127 -0
  463. data/lib/rosett_ai/thor/tasks/documentation.rb +321 -0
  464. data/lib/rosett_ai/thor/tasks/engines.rb +167 -0
  465. data/lib/rosett_ai/thor/tasks/hooks.rb +219 -0
  466. data/lib/rosett_ai/thor/tasks/init.rb +259 -0
  467. data/lib/rosett_ai/thor/tasks/license.rb +120 -0
  468. data/lib/rosett_ai/thor/tasks/mcp.rb +535 -0
  469. data/lib/rosett_ai/thor/tasks/migrate.rb +121 -0
  470. data/lib/rosett_ai/thor/tasks/plugins.rb +157 -0
  471. data/lib/rosett_ai/thor/tasks/project.rb +260 -0
  472. data/lib/rosett_ai/thor/tasks/provenance.rb +195 -0
  473. data/lib/rosett_ai/thor/tasks/release.rb +314 -0
  474. data/lib/rosett_ai/thor/tasks/retrofit.rb +90 -0
  475. data/lib/rosett_ai/thor/tasks/tooling.rb +308 -0
  476. data/lib/rosett_ai/thor/tasks/validate.rb +108 -0
  477. data/lib/rosett_ai/thor/tasks/workflow.rb +196 -0
  478. data/lib/rosett_ai/tooling/ci_yaml_validator.rb +37 -0
  479. data/lib/rosett_ai/tooling/version_checker.rb +35 -0
  480. data/lib/rosett_ai/ui/accessible_tui.rb +61 -0
  481. data/lib/rosett_ai/ui/base.rb +46 -0
  482. data/lib/rosett_ai/ui/gtk4.rb +98 -0
  483. data/lib/rosett_ai/ui/kde.rb +40 -0
  484. data/lib/rosett_ai/ui/qt6.rb +40 -0
  485. data/lib/rosett_ai/ui/registry.rb +60 -0
  486. data/lib/rosett_ai/ui/tty_helper.rb +74 -0
  487. data/lib/rosett_ai/ui/tui.rb +59 -0
  488. data/lib/rosett_ai/validators/behaviour_validator.rb +20 -0
  489. data/lib/rosett_ai/validators/design_validator.rb +17 -0
  490. data/lib/rosett_ai/validators/schema_validator.rb +84 -0
  491. data/lib/rosett_ai/validators/tooling_validator.rb +17 -0
  492. data/lib/rosett_ai/version.rb +8 -0
  493. data/lib/rosett_ai/version_consistency_checker.rb +129 -0
  494. data/lib/rosett_ai/workflow/audit_log.rb +86 -0
  495. data/lib/rosett_ai/workflow/engine.rb +142 -0
  496. data/lib/rosett_ai/workflow/manager.rb +82 -0
  497. data/lib/rosett_ai/workflow/schema_validator.rb +71 -0
  498. data/lib/rosett_ai/workflow/step_runner.rb +61 -0
  499. data/lib/rosett_ai/workflow/steps/prompt_step.rb +62 -0
  500. data/lib/rosett_ai/workflow/steps/rai_step.rb +74 -0
  501. data/lib/rosett_ai/workflow/steps/shell_step.rb +53 -0
  502. data/lib/rosett_ai/yaml_loader.rb +78 -0
  503. data/lib/rosett_ai.rb +221 -0
  504. data/lib/rubocop/cop/rosett_ai/shell_interpolation.rb +54 -0
  505. data/lib/rubocop/cop/rosett_ai/unsafe_const_get.rb +60 -0
  506. data/lib/rubocop/cop/rosett_ai/unsafe_send.rb +50 -0
  507. data/lib/rubocop/cop/rosett_ai/unsafe_yaml_load.rb +40 -0
  508. data/lib/rubocop/rosett_ai.rb +9 -0
  509. data/lib/scripts/generated/docker_hub_tags.rb +126 -0
  510. data/locales/.gitkeep +0 -0
  511. data/locales/ar.yml +579 -0
  512. data/locales/en.yml +571 -0
  513. data/locales/fr.yml +567 -0
  514. data/packaging/build-engine-deb.sh +81 -0
  515. data/packaging/scripts/postinst +17 -0
  516. data/packaging/scripts/postrm +19 -0
  517. data/packaging/scripts/prerm +10 -0
  518. data/packaging/wrapper.sh.template +38 -0
  519. data/rosett-ai.gemspec +63 -0
  520. data/rules/.gitkeep +0 -0
  521. data/scripts/publish/pulp_upload.sh +123 -0
  522. data/settings.json +29 -0
  523. data/share/applications/be.neatnerds.rosettai.desktop +29 -0
  524. data/share/dbus-1/interfaces/be.neatnerds.rosettai.xml +103 -0
  525. data/share/dbus-1/services/be.neatnerds.rosettai.service +3 -0
  526. data/share/templates/behaviour/criticalthinking.yml +69 -0
  527. metadata +810 -0
@@ -0,0 +1,590 @@
1
+ # Pluggable Engine Architecture + Config Adapters
2
+
3
+ ## Context
4
+
5
+ raictl currently hardcodes 10 engines in two maps (`Registry.ENGINES` + `Backend.BACKENDS`). Every new engine or engine change requires modifying rosett-ai core. This is fragile — AI tools evolve rapidly and new ones emerge constantly.
6
+
7
+ This plan extracts engines into **separate repositories** as individual gems (`rosett-ai-engine-<name>`) with a pluggable discovery system. Each engine gem owns its backend, detector, executor, config compiler, manifests, schemas, and specs. rosett-ai core provides the CLI, compilation pipeline, registry, and base classes.
8
+
9
+ The pluggable architecture applies to **all plugin types** — not just engines. GUIs (desktop environments), MCP servers, and future plugin categories each get their own contract module, discovery mechanism, and separate repository. The naming convention `rosett-ai-<plugin-type>-<name>` covers:
10
+ - `rosett-ai-engine-<name>` — AI engine plugins (claude, goose, aider, cursor, etc.)
11
+ - `rosett-ai-gui-<name>` — Desktop GUI plugins (gtk4, qt6, etc.)
12
+ - `rosett-ai-mcp-<name>` — MCP server plugins
13
+ - Other future plugin types as needed
14
+
15
+ Config adapters for Goose, Aider, Cursor, Ollama, GPT-NeoX, and a new Mistral engine are built using this pluggable pattern.
16
+
17
+ ---
18
+
19
+ ## Plan A: Pluggable Architecture + Engine Extraction
20
+
21
+ **Branch**: `feature/pluggable-engines`
22
+
23
+ ### Phase 1: Plugin contracts + dynamic registry
24
+
25
+ #### 1a. Plugin contract modules
26
+
27
+ Create contract modules for each plugin type. Each contract defines the interface that plugin gems must implement.
28
+
29
+ **Engine contract** — `lib/rosett_ai/plugins/engine_contract.rb`:
30
+
31
+ ```ruby
32
+ module RosettAi::Plugins::EngineContract
33
+ def self.included(base)
34
+ base.extend(ClassMethods)
35
+ end
36
+
37
+ module ClassMethods
38
+ def plugin_type = :engine
39
+ def engine_name = raise NotImplementedError
40
+ def display_name = raise NotImplementedError
41
+ def backend_class = raise NotImplementedError
42
+ def detector_class = nil # optional
43
+ def executor_class = nil # optional
44
+ def config_compiler_class = nil # optional
45
+ def manifest_path = raise NotImplementedError
46
+ end
47
+ end
48
+ ```
49
+
50
+ **GUI contract** — `lib/rosett_ai/plugins/gui_contract.rb`:
51
+
52
+ ```ruby
53
+ module RosettAi::Plugins::GuiContract
54
+ def self.included(base)
55
+ base.extend(ClassMethods)
56
+ end
57
+
58
+ module ClassMethods
59
+ def plugin_type = :gui
60
+ def gui_name = raise NotImplementedError
61
+ def display_name = raise NotImplementedError
62
+ def toolkit = raise NotImplementedError # :gtk4, :qt6, etc.
63
+ def application_class = raise NotImplementedError
64
+ def dbus_interface_class = nil # optional D-Bus integration
65
+ end
66
+ end
67
+ ```
68
+
69
+ **MCP contract** — `lib/rosett_ai/plugins/mcp_contract.rb`:
70
+
71
+ ```ruby
72
+ module RosettAi::Plugins::McpContract
73
+ def self.included(base)
74
+ base.extend(ClassMethods)
75
+ end
76
+
77
+ module ClassMethods
78
+ def plugin_type = :mcp
79
+ def mcp_name = raise NotImplementedError
80
+ def display_name = raise NotImplementedError
81
+ def server_class = raise NotImplementedError
82
+ def tool_definitions = raise NotImplementedError # MCP tool schema
83
+ def resource_definitions = [] # optional MCP resources
84
+ end
85
+ end
86
+ ```
87
+
88
+ **Base contract** — `lib/rosett_ai/plugins/contract.rb` (shared interface for all plugin types):
89
+
90
+ ```ruby
91
+ module RosettAi::Plugins::Contract
92
+ def self.included(base)
93
+ base.extend(ClassMethods)
94
+ end
95
+
96
+ module ClassMethods
97
+ def plugin_type = raise NotImplementedError
98
+ def plugin_name = raise NotImplementedError
99
+ def display_name = raise NotImplementedError
100
+ def version = raise NotImplementedError
101
+ end
102
+ end
103
+ ```
104
+
105
+ #### 1b. Dynamic registry (multi-type)
106
+
107
+ Replace hardcoded `ENGINES` and `BACKENDS` maps with a multi-type registry supporting engines, GUIs, and MCPs:
108
+
109
+ ```ruby
110
+ module RosettAi::Plugins
111
+ class Registry
112
+ PLUGIN_TYPES = %i[engine gui mcp].freeze
113
+ @plugins = Hash.new { |h, k| h[k] = {} }
114
+
115
+ def self.register(type, name, plugin_module)
116
+ raise ArgumentError unless PLUGIN_TYPES.include?(type)
117
+ @plugins[type][name.to_s] = plugin_module
118
+ end
119
+
120
+ def self.available(type) = @plugins[type].keys
121
+ def self.plugin_module(type, name) = @plugins[type].fetch(name.to_s) { raise ... }
122
+
123
+ # Convenience aliases
124
+ def self.engines = @plugins[:engine]
125
+ def self.guis = @plugins[:gui]
126
+ def self.mcps = @plugins[:mcp]
127
+
128
+ # Discovery: find and load all installed plugin gems
129
+ def self.discover!
130
+ Gem.find_files('rosett_ai_engine/*/register.rb').each { |f| require f }
131
+ Gem.find_files('rosett_ai_gui/*/register.rb').each { |f| require f }
132
+ Gem.find_files('rosett_ai_mcp/*/register.rb').each { |f| require f }
133
+ end
134
+ end
135
+ end
136
+ ```
137
+
138
+ Refactor `Backend.for` to delegate to `Registry.plugin_module(:engine, name).backend_class` instead of the hardcoded `BACKENDS` map.
139
+
140
+ #### 1c. Base config compiler
141
+
142
+ Extract shared compilation pipeline from `RosettAi::Engines::Claude::ConfigCompiler` into `lib/rosett_ai/engines/base_config_compiler.rb`:
143
+ - `discover_scope_files`, `compile`, `compile_scope`, `write_results`
144
+ - Schema validation via json_schemer
145
+ - Secret resolution via shared `RosettAi::Config::SecretResolver`
146
+ - `CompileResult` return type (already shared)
147
+
148
+ Each engine overrides: `transform(data, scope)`, `output_format`, `scope_routes`, `schema_path`.
149
+
150
+ #### 1d. Engine-aware CLI
151
+
152
+ Update `lib/rosett_ai/thor/tasks/config.rb`:
153
+ - Add `--engine` option with cascade lookup: config → autodetect → prompt
154
+ - Cascade: configured default → autodetect (Claude preferred, then alphabetical) → ask user for binary/endpoint
155
+ - Resolve to engine's `config_compiler_class` via Registry
156
+ - Remove hardcoded `RosettAi::Config::Compiler` (Claude alias)
157
+
158
+ Update `bin/raictl config show` to also display **plugged engines** — list all registered engine gems with version, capabilities, and detection status.
159
+
160
+ **Files to create:**
161
+ - `lib/rosett_ai/plugins/contract.rb` (base contract)
162
+ - `lib/rosett_ai/plugins/engine_contract.rb`
163
+ - `lib/rosett_ai/plugins/gui_contract.rb`
164
+ - `lib/rosett_ai/plugins/mcp_contract.rb`
165
+ - `lib/rosett_ai/plugins/registry.rb`
166
+ - `lib/rosett_ai/engines/base_config_compiler.rb`
167
+ - `spec/rosett_ai/plugins/contract_spec.rb`
168
+ - `spec/rosett_ai/plugins/engine_contract_spec.rb`
169
+ - `spec/rosett_ai/plugins/gui_contract_spec.rb`
170
+ - `spec/rosett_ai/plugins/mcp_contract_spec.rb`
171
+ - `spec/rosett_ai/plugins/registry_spec.rb`
172
+ - `spec/rosett_ai/engines/base_config_compiler_spec.rb`
173
+
174
+ **Files to modify:**
175
+ - `lib/rosett_ai/engines/registry.rb` — delegate to `Plugins::Registry`, deprecation alias
176
+ - `lib/rosett_ai/compiler/backend.rb` — delegate to `Plugins::Registry`, remove `BACKENDS`
177
+ - `lib/rosett_ai/thor/tasks/config.rb` — `--engine` flag, cascade lookup, plugged engines display
178
+ - `lib/rosett_ai/thor/tasks/compile.rb` — use Registry for engine resolution
179
+ - `lib/rosett_ai/thor/tasks/engines.rb` — use dynamic Registry
180
+ - `spec/rosett_ai/engines/registry_spec.rb` — update
181
+ - `spec/rosett_ai/compiler/backend_spec.rb` — update
182
+ - `spec/rosett_ai/thor/tasks/config_spec.rb` — update
183
+
184
+ ---
185
+
186
+ ### Phase 2: Engine extraction to separate repositories
187
+
188
+ #### 2a. Repository structure
189
+
190
+ Each engine is a **separate git repository** at:
191
+ ```
192
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-engine-<name>/
193
+ ```
194
+
195
+ Plugin naming convention for all rosett-ai plugin types:
196
+ ```text
197
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-<plugin-type>-<name>/
198
+ ```
199
+
200
+ Examples:
201
+ ```text
202
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-engine-claude/
203
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-engine-goose/
204
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-gui-gtk4/
205
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-gui-qt6/
206
+ ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-mcp-server/
207
+ ```
208
+
209
+ #### 2b. Per-engine repository layout
210
+
211
+ ```text
212
+ rosett-ai-engine-claude/
213
+ ├── rosett-ai-engine-claude.gemspec
214
+ ├── .gitlab-ci.yml # Same quality gates as core
215
+ ├── .rubocop.yml
216
+ ├── .reek.yml
217
+ ├── .license_finder.yml # License compliance config
218
+ ├── .mutant.yml # Mutation testing config
219
+ ├── Gemfile
220
+ ├── CHANGELOG.md
221
+ ├── LICENSE # GPL-3.0-only (MANDATORY)
222
+ ├── lib/
223
+ │ └── rosett_ai_engine/
224
+ │ └── claude/
225
+ │ ├── register.rb # self-registration entry point
226
+ │ ├── engine.rb # includes EngineContract, declares components
227
+ │ ├── backend.rb
228
+ │ ├── detector.rb
229
+ │ ├── executor.rb
230
+ │ ├── config_compiler.rb
231
+ │ ├── key_map.rb
232
+ │ ├── scope_router.rb
233
+ │ └── domain_transformer.rb
234
+ ├── conf/
235
+ │ ├── manifest.yml
236
+ │ ├── target.yml
237
+ │ ├── config/
238
+ │ │ ├── managed.yml
239
+ │ │ ├── user.yml
240
+ │ │ ├── project.yml
241
+ │ │ └── local.yml
242
+ │ └── schemas/
243
+ │ └── config_schema.json
244
+ └── spec/
245
+ ├── spec_helper.rb
246
+ ├── backend_spec.rb
247
+ ├── config_compiler_spec.rb
248
+ ├── key_map_spec.rb
249
+ └── ...
250
+ ```
251
+
252
+ #### 2c. Quality gates per plugin repository
253
+
254
+ Each plugin repo MUST have the same CI quality gates as rosett-ai core:
255
+ - RSpec (all specs pass, SimpleCov coverage)
256
+ - RuboCop (zero offenses)
257
+ - Reek (zero smells)
258
+ - **Mutant** (mutation testing on critical subjects)
259
+ - bundler-audit + ruby-audit
260
+ - **license_finder** (license compliance — all deps must be GPL-3.0-compatible)
261
+ - Schema validation (manifest, config schemas)
262
+ - **GPL-3.0-only** license file in every repository
263
+
264
+ Generated `.gitlab-ci.yml` per plugin repo, reusing CI templates where possible.
265
+
266
+ #### 2d. Claude extraction first
267
+
268
+ Extract Claude engine first — this is the most complex engine (7 components) and must work flawlessly before extracting others. Steps:
269
+
270
+ 1. Create `~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-engine-claude/`
271
+ 2. Move `lib/rosett_ai/engines/claude/*.rb` → `lib/rosett_ai_engine/claude/`
272
+ 3. Move `conf/engines/claude/` → `conf/`
273
+ 4. Move `spec/rosett_ai/engines/claude/` → `spec/`
274
+ 5. Create gemspec, register.rb, engine.rb
275
+ 6. Set up CI pipeline with quality gates
276
+ 7. Verify all specs pass independently
277
+ 8. Update rosett-ai core Gemfile to reference via `path:` or git URL
278
+ 9. Verify full rosett-ai suite still passes
279
+
280
+ Then extract remaining engines in order: generic, agents_md, goose, aider, cursor, copilot, windsurf, ollama, gpt_neox.
281
+
282
+ #### 2e. GUI + MCP extraction
283
+
284
+ After engine extraction is validated, extract GUI and MCP plugins:
285
+
286
+ 1. `rosett-ai-gui-gtk4/` — extract `lib/rosett_ai/desktop/gtk4/` + D-Bus adapters into `lib/rosett_ai_gui/gtk4/`
287
+ 2. `rosett-ai-gui-qt6/` — placeholder for future KDE/Qt6 desktop (currently deferred)
288
+ 3. `rosett-ai-mcp-server/` — extract `lib/rosett_ai/mcp/` into `lib/rosett_ai_mcp/server/`
289
+
290
+ Each follows the same pattern: own repo, own gemspec, own CI, GPL-3.0-only, contract module inclusion, self-registration via `register.rb`.
291
+
292
+ #### 2f. Core cleanup
293
+
294
+ Remove from rosett-ai core after all extractions:
295
+ - `lib/rosett_ai/engines/` (except `registry.rb`, `detector.rb`, `base_config_compiler.rb`)
296
+ - `lib/rosett_ai/desktop/` (moved to gui plugins)
297
+ - `lib/rosett_ai/mcp/` (moved to mcp plugins)
298
+ - `conf/engines/` (except `conf/schemas/engine_manifest_schema.json`)
299
+ - Engine/GUI/MCP-specific specs
300
+
301
+ Retain in core:
302
+ - `lib/rosett_ai/plugins/` (contract modules + registry)
303
+ - `lib/rosett_ai/engines/base_config_compiler.rb`
304
+ - Shared modules: `CompileResult`, `SecretResolver`, `CapabilityChecker`
305
+
306
+ Update rosett-ai core Gemfile to reference all plugin gems.
307
+
308
+ ---
309
+
310
+ ### Phase 3: Example dummy plugins (ACME)
311
+
312
+ A true pluggable architecture must include example plugins so end users can understand the contract between core and plugin. ACME examples cover **all plugin types** to demonstrate each contract.
313
+
314
+ #### 3a. ACME example engine
315
+
316
+ Create `rosett-ai-engine-acme` — an inert example engine plugin:
317
+
318
+ **Placeholder organization**: ACME Corp (`acme-corp.tld`)
319
+ - Example users: alice, bob, goku, Haru Urara, Momonga
320
+ - Example roles: admin, developer, manager, analyst, hr, creator, student
321
+
322
+ The ACME engine:
323
+ - Includes `EngineContract` with all required methods
324
+ - Backend renders a no-op output (e.g., `# ACME engine — no output`)
325
+ - Detector always returns `detected: false`
326
+ - Config compiler demonstrates the full pipeline with example settings
327
+ - Has example config YAML with ACME-specific settings (using ACME users/roles)
328
+ - Has example manifest declaring capabilities
329
+ - **Tests exist and achieve minimal code coverage** (even though the engine is inert)
330
+ - Extensive inline comments explaining each contract method and what it does
331
+ - GPL-3.0-only license, mutant config, license_finder config
332
+
333
+ #### 3b. ACME example GUI (optional, deferred until GUI extraction)
334
+
335
+ Create `rosett-ai-gui-acme` — an inert example GUI plugin:
336
+ - Includes `GuiContract` with all required methods
337
+ - Application class returns immediately (no actual window)
338
+ - Demonstrates how a GUI plugin registers and interfaces with core
339
+
340
+ #### 3c. ACME example MCP (optional, deferred until MCP extraction)
341
+
342
+ Create `rosett-ai-mcp-acme` — an inert example MCP plugin:
343
+ - Includes `McpContract` with all required methods
344
+ - Server class responds with dummy tool definitions
345
+ - Demonstrates how an MCP plugin registers and interfaces with core
346
+
347
+ #### 3d. ACME documentation focus
348
+
349
+ The ACME plugins are **declarative and educational**:
350
+ - Every file has comments explaining why it exists and what it fulfills
351
+ - `README.md` walks through creating a plugin from scratch
352
+ - Shows how to register, how discovery works, how manifests are validated
353
+ - References the contract module and base classes in rosett-ai core
354
+ - Documents the differences between engine, GUI, and MCP contracts
355
+
356
+ ---
357
+
358
+ ### Phase 4: Config adapters (using pluggable pattern)
359
+
360
+ Each adapter follows the same pattern — engine gem adds `config_compiler.rb`, `key_map.rb`, scope YAML, and schema.
361
+
362
+ #### 4a. Goose config adapter
363
+
364
+ - **Output**: `~/.config/goose/config.yaml` (YAML)
365
+ - **Settings**: provider, model, temperature, max_tokens, mode, max_turns, security, planner
366
+ - **Scopes**: user only
367
+
368
+ #### 4b. Aider config adapter
369
+
370
+ - **Output**: `~/.aider.conf.yml` (user) + `./.aider.conf.yml` (project)
371
+ - **Settings**: model, weak-model, editor-model, edit-format, API keys (secret refs), auto-commits, lint-cmd, test-cmd, dark-mode, stream, cache-prompts, reasoning-effort
372
+ - **Scopes**: user + project
373
+
374
+ #### 4c. Cursor config adapter
375
+
376
+ - **Output**: `.cursor/settings.json` (JSON)
377
+ - **Settings**: API keys (secret refs), model selection, custom endpoints, MCP servers
378
+ - **Scopes**: project only
379
+
380
+ #### 4d. Ollama config adapter
381
+
382
+ - **Output**: Modelfile (text) + env var config
383
+ - **Settings**: FROM (model), PARAMETER temperature/top_k/top_p, SYSTEM prompt, OLLAMA_HOST
384
+ - **Scopes**: user only
385
+
386
+ #### 4e. GPT-NeoX (vLLM) config adapter
387
+
388
+ - **Output**: `config.yaml` for `vllm serve --config`
389
+ - **Settings**: model, host, port, gpu-memory-utilization, max-model-len
390
+ - **Scopes**: user only
391
+
392
+ #### 4f. Mistral engine (new)
393
+
394
+ Entirely new engine gem `rosett-ai-engine-mistral`:
395
+ - Backend: compile behaviour YAML to Mistral instruction format
396
+ - Detector: check `mistral` CLI binary or `MISTRAL_API_KEY` env var
397
+ - Config adapter: API key (secret ref), model, endpoint, temperature
398
+ - Manifest + target profile
399
+ - Scopes: user only
400
+
401
+ ---
402
+
403
+ ### Phase 5: Design document updates
404
+
405
+ #### 5a. Update existing design documents
406
+
407
+ All existing design documents in `conf/design/` must be updated to reflect the pluggable architecture:
408
+ - `engine_architecture.yml` — pluggable discovery, contract modules (engine + GUI + MCP), gem-based plugins
409
+ - `compiler.yml` — base config compiler, engine-aware pipeline
410
+ - `testing.yml` — per-plugin gem testing strategy (including mutant)
411
+ - `distribution.yml` — per-plugin gem packaging, license_finder requirement
412
+ - `architecture.yml` — updated system overview with multi-type plugin system
413
+ - `desktop_integration.yml` — GUI contract module, gui plugin extraction
414
+ - `mcp_integration.yml` — MCP contract module, mcp plugin extraction
415
+ - Others as applicable
416
+
417
+ #### 5b. Categorize design documents
418
+
419
+ Design documents should be categorized by topic and purpose:
420
+ - **Core architecture**: architecture, compiler, engine_architecture
421
+ - **Security & quality**: security, testing, ci_pipeline
422
+ - **Distribution**: distribution, release_management, version_management, lifecycle_management
423
+ - **User interface**: ui_framework, accessibility, desktop_integration, styles
424
+ - **Integrations**: mcp_integration, aaif_alignment, content_packs
425
+ - **Operations**: monitoring_observability, usage_optimization
426
+ - **Configuration**: claude_code_configuration, i18n
427
+ - **Business**: licensing_system, documentation
428
+
429
+ ---
430
+
431
+ ### Phase 6: Documentation
432
+
433
+ Documentation about the pluggable architecture is of **extreme importance**.
434
+
435
+ - Update `doc/ARCHITECTURE.md` — pluggable engine diagrams, gem discovery flow
436
+ - Update `doc/ENGINES.md` — per-engine config adapter docs, how plugins work
437
+ - Update `doc/man/rai.1.ronn` — `config compile --engine`, `config show` plugged engines
438
+ - Update `CONTRIBUTING.md` — "How to create an engine gem" guide (reference ACME example)
439
+ - Update `INSTALL.md` — how to install engine gems
440
+ - Update `CHANGELOG.md`
441
+ - Update `doc/IMPLEMENTATION_PLAN.md` — new phases, engine delivery matrix
442
+ - Full quality gate
443
+
444
+ ---
445
+
446
+ ## Key design decisions
447
+
448
+ | Decision | Rationale |
449
+ |----------|-----------|
450
+ | Separate git repositories per plugin | Engines, GUIs, MCPs, and future plugin types each get full independence, own CI, own versioning |
451
+ | `Gem.find_files('nncc_{engine,gui,mcp}/*/register.rb')` discovery | No config needed; install gem = available |
452
+ | Namespaced dirs (`rosett_ai_engine/`, `rosett_ai_gui/`, `rosett_ai_mcp/`) | **Default approach** — avoids Zeitwerk root dir overlap with core gem |
453
+ | Contract modules per plugin type | Engine, GUI, and MCP contracts define type-specific interfaces |
454
+ | Base contract shared across all types | Common `plugin_type`, `plugin_name`, `display_name`, `version` |
455
+ | Plugin gemspec `metadata['nncc_plugin_type']` | Enables `gem search` filtering by type |
456
+ | Base config compiler in core | Shared pipeline logic, engines only override transforms |
457
+ | `CompileResult` + `SecretResolver` stay in core | Shared across all plugins |
458
+ | ACME example plugin | Teaches the contract without requiring real AI tool knowledge |
459
+ | Claude extracted first | Most complex engine; validates the pattern |
460
+ | GPL-3.0-only on ALL repositories | Uniform licensing across core and all plugin repos |
461
+ | Mutant in every repo's CI | Mutation testing ensures real test coverage quality |
462
+ | license_finder in every repo | Ensures all dependencies are GPL-3.0-compatible |
463
+
464
+ ## Risk areas
465
+
466
+ | Risk | Mitigation |
467
+ |------|-----------|
468
+ | Zeitwerk root dir conflicts | **Namespacing is the default**: `rosett_ai_engine/`, `rosett_ai_gui/`, `rosett_ai_mcp/` — never overlap with core's `rosett-ai/` autoload root |
469
+ | Gem discovery order | Registry sorts alphabetically; Claude preferred via config default |
470
+ | Breaking existing specs | Claude extraction must be flawless before others |
471
+ | Deprecation aliases | Keep `RosettAi::Config::Compiler` etc. for one release cycle |
472
+ | CI complexity | Each plugin repo has own CI; core CI tests with all plugins installed |
473
+ | License compatibility | license_finder enforced in CI — blocks merges with incompatible deps |
474
+ | Contract drift across types | Base contract module ensures common interface; type-specific contracts extend it |
475
+ | GUI/MCP contracts not yet battle-tested | Engine contract validated first via Claude extraction; GUI/MCP contracts refined during extraction |
476
+
477
+ ---
478
+
479
+ ## Plan B: Building/Packaging Fixes (separate plan, after Plan A)
480
+
481
+ **Branch**: `fix/packaging-v1`
482
+
483
+ Addresses three documented issues at `doc/issues/`:
484
+
485
+ ### Issue 001: Wrapper script missing LD_LIBRARY_PATH and RUBYLIB
486
+
487
+ - **Severity**: Critical (application fails to launch)
488
+ - **Fix**: Update `packaging/wrapper.sh` to set `LD_LIBRARY_PATH`, `RUBYLIB`, and hardcode `GEM_HOME` (or use ERB template at build time to avoid chicken-and-egg `ruby -e` call)
489
+ - **Files**: `packaging/wrapper.sh` (or new `packaging/wrapper.sh.erb`), `lib/rosett_ai/thor/tasks/build.rb`
490
+
491
+ ### Issue 002: Embedded Ruby compiled with wrong --prefix
492
+
493
+ - **Severity**: High (makes Issue 001 workarounds necessary)
494
+ - **Root cause**: CI Docker pre-seeding copies `/usr/local/` Ruby (prefix `/usr/local`) to `/opt/rosett-ai/embedded/`; local builds use staging absolute path as prefix
495
+ - **Fix**: Option A+C — compile Ruby with `RUBY_CONFIGURE_OPTS="--prefix=/opt/rosett-ai/embedded"` in both CI and local builds; update `ruby_already_compiled?` to verify prefix
496
+ - **Files**: `.gitlab-ci-files/build/package.yml`, `lib/rosett_ai/thor/tasks/build.rb`
497
+
498
+ ### Issue 003: Smoke test may produce false positives
499
+
500
+ - **Severity**: Medium (test reliability)
501
+ - **Root cause**: Smoke test installs system Ruby (`apt-get install ruby`) before testing the package, masking missing deps
502
+ - **Fix**: Remove `apt-get install ruby` from smoke test; test package in isolation on clean `debian:bookworm`; add `readelf` and `RbConfig::CONFIG["prefix"]` assertions
503
+ - **Files**: `.gitlab-ci-files/build/package.yml`
504
+
505
+ ---
506
+
507
+ ## Plan C: Test Kitchen Integration (separate plan, after Plan A)
508
+
509
+ **Branch**: `feature/test-kitchen`
510
+
511
+ Imperative for fully testing the pluggable architecture in realistic deployment scenarios.
512
+
513
+ ### Overview
514
+
515
+ Implement test-kitchen for integration testing of rosett-ai packages and plugin architecture.
516
+
517
+ ### InSpec via neatspec
518
+
519
+ For compliance/verification profiles, use the **neatspec** project:
520
+ - Location: `~/git/Neatnerds/NNSD/InSpec/neatspec`
521
+ - Wraps `cinc-auditor` gem
522
+ - Provides reusable profiles, role-based compliance, hierarchical data management
523
+
524
+ ### Scope
525
+
526
+ - Kitchen configuration for testing .deb package installation on clean Debian
527
+ - Verify wrapper script, embedded Ruby prefix, and `$LOAD_PATH`
528
+ - Verify plugin discovery works with installed engine gems
529
+ - Verify `bin/raictl` commands work after package install
530
+ - neatspec profiles for rosett-ai compliance (file permissions, paths, service health)
531
+ - Design document for test-kitchen exists or will be created in `conf/design/`
532
+
533
+ ---
534
+
535
+ ## Verification (Plan A)
536
+
537
+ After Phase 1:
538
+ ```bash
539
+ bundle exec rspec spec/rosett_ai/plugins/registry_spec.rb
540
+ bundle exec rspec spec/rosett_ai/plugins/contract_spec.rb
541
+ bundle exec rspec spec/rosett_ai/plugins/engine_contract_spec.rb
542
+ bundle exec rspec spec/rosett_ai/plugins/gui_contract_spec.rb
543
+ bundle exec rspec spec/rosett_ai/plugins/mcp_contract_spec.rb
544
+ bundle exec rspec spec/rosett_ai/engines/base_config_compiler_spec.rb
545
+ ```
546
+
547
+ After Phase 2 (per engine repo):
548
+ ```bash
549
+ cd ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-engine-claude && bundle exec rspec
550
+ # ... repeat for each engine
551
+ bundle exec rspec # full suite from rosett-ai core
552
+ ```
553
+
554
+ After Phase 3:
555
+ ```bash
556
+ cd ~/git/Neatnerds/NNSD/NeatNerds-ai/rosett-ai-engine-acme && bundle exec rspec
557
+ ```
558
+
559
+ After Phase 4:
560
+ ```bash
561
+ bin/raictl config compile --engine goose --simulate --verbose
562
+ bin/raictl config compile --engine aider --simulate --verbose
563
+ bin/raictl config compile --engine cursor --simulate --verbose
564
+ bin/raictl config compile --engine ollama --simulate --verbose
565
+ bin/raictl config compile --engine gpt_neox --simulate --verbose
566
+ bin/raictl config compile --engine mistral --simulate --verbose
567
+ ```
568
+
569
+ Final (per-repo):
570
+ ```bash
571
+ bundle exec rspec # All specs pass
572
+ bundle exec rubocop # Clean
573
+ bundle exec reek # Clean
574
+ bundle exec mutant run # Mutation score tracked
575
+ bundle exec bundler-audit check # No vulns
576
+ bundle exec license_finder # All deps GPL-3.0-compatible
577
+ ```
578
+
579
+ Final (rosett-ai core with all plugins):
580
+ ```bash
581
+ bundle exec rspec # All specs pass (including plugin integration)
582
+ bundle exec rubocop # Clean
583
+ bundle exec reek # Clean
584
+ bundle exec mutant run # Mutation score tracked
585
+ bundle exec bundler-audit check # No vulns
586
+ bundle exec license_finder # All deps GPL-3.0-compatible
587
+ bin/raictl validate # All config valid
588
+ bin/raictl engines list # 12 engines (10 real + acme + mistral)
589
+ bin/raictl config show # Shows plugged engines + GUIs + MCPs
590
+ ```
@@ -0,0 +1,32 @@
1
+ # ADR-001: Flog Deferred from Lifecycle Verification Suite
2
+
3
+ ## Status
4
+
5
+ Accepted (2026-02-20)
6
+
7
+ ## Context
8
+
9
+ The lifecycle_management.yml design document (criterion 4) originally required
10
+ RuboCop, Reek, Flay, **and Flog** to run without regressions after every upgrade.
11
+
12
+ Flog measures method complexity using an ABC-based scoring algorithm. However,
13
+ RuboCop already enforces method complexity through two Metrics cops:
14
+
15
+ - `Metrics/CyclomaticComplexity` (default max: 7)
16
+ - `Metrics/PerceivedComplexity` (default max: 8)
17
+
18
+ These cops cover the same concern as Flog (identifying overly complex methods)
19
+ and are already enforced in CI and pre-commit hooks.
20
+
21
+ ## Decision
22
+
23
+ Defer Flog from the lifecycle verification suite. The complexity concern it
24
+ addresses is already covered by RuboCop Metrics cops that are active in the
25
+ project's CI pipeline and pre-commit configuration.
26
+
27
+ ## Consequences
28
+
29
+ - One fewer tool to install and run in the verification pipeline
30
+ - Complexity enforcement remains via RuboCop (already mandatory)
31
+ - If RuboCop Metrics cops are ever disabled or relaxed, revisit this decision
32
+ and consider re-introducing Flog as a standalone check