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
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,734 @@
1
+ # Contributing to rosett-ai
2
+
3
+ This guide explains how to extend the Rosett-AI. Each section
4
+ covers a specific expansion pattern with the exact files to create or modify.
5
+
6
+ ## Development Setup
7
+
8
+ ```bash
9
+ git clone https://gitlab.neatnerds.be/neatnerds/NeatNerds-AI/rosett-ai.git
10
+ cd rosett-ai
11
+ bundle install
12
+ overcommit --install
13
+ overcommit --sign # trust the hook signatures
14
+ bundle exec rspec # run tests
15
+ bundle exec rubocop # run linter
16
+ bundle exec reek # run code smell detector
17
+ ```
18
+
19
+ ## Bundler Groups and Dependencies
20
+
21
+ The core Gemfile defines four groups:
22
+
23
+ | Group | Purpose | Included locally | Included in CI |
24
+ |-------|---------|:---:|:---:|
25
+ | `:default` | Core runtime (gemspec) | Yes | Yes |
26
+ | `:desktop` | GTK4/Adwaita desktop UI | Yes | No |
27
+ | `:build` | Package building (fpm) | Yes | Yes |
28
+ | `:development, :test` | Linters, test tools | Yes | Yes |
29
+
30
+ Engine gems are **not** in the core Gemfile. For cross-repo engine development,
31
+ use `Gemfile.dev` (gitignored):
32
+
33
+ ```bash
34
+ BUNDLE_GEMFILE=Gemfile.dev bundle install
35
+ ```
36
+
37
+ This loads all `rosett-ai-engine-*` gems from sibling directories. In production,
38
+ engine gems are installed as separate `.deb` packages (see ADR-010).
39
+
40
+ The `:desktop` group is excluded in CI (`bundle config without 'desktop'`)
41
+ because it requires system libraries (`libgirepository1.0-dev`, `libgtk-4-dev`)
42
+ that are not in the CI Docker image. No CI job needs GTK4 gems.
43
+
44
+ If you are developing desktop features locally, install the system dependencies
45
+ first:
46
+
47
+ ```bash
48
+ sudo apt-get install -y libgirepository1.0-dev libgtk-4-dev
49
+ bundle install # includes :desktop group by default
50
+ ```
51
+
52
+ If you do not need desktop features, you can exclude them locally too:
53
+
54
+ ```bash
55
+ bundle config set --local without 'desktop'
56
+ bundle install
57
+ ```
58
+
59
+ ### Updating dependencies
60
+
61
+ `Gemfile.lock` is tracked in git (see ADR-008). CI runs with `frozen: true`,
62
+ meaning it will reject any mismatch between `Gemfile` and `Gemfile.lock`.
63
+
64
+ To update a dependency:
65
+
66
+ ```bash
67
+ bundle update <gem-name> # updates the lockfile
68
+ bundle exec rspec # verify tests pass
69
+ bundle exec rubocop # verify no new offenses
70
+ git add Gemfile.lock
71
+ git commit -m "chore(deps): update <gem-name> to X.Y.Z"
72
+ ```
73
+
74
+ To update all dependencies at once:
75
+
76
+ ```bash
77
+ bundle update
78
+ bundle exec rspec && bundle exec rubocop
79
+ git add Gemfile.lock
80
+ git commit -m "chore(deps): update all dependencies"
81
+ ```
82
+
83
+ ## Pre-commit Hooks (Overcommit)
84
+
85
+ Overcommit runs quality gates on every commit. The key hooks:
86
+
87
+ | Hook | Scope | What it checks |
88
+ |------|-------|----------------|
89
+ | `RubocopAll` | All files | Ruby style and lint offenses (full project scan) |
90
+ | `Reek` | Changed files | Code smell detection |
91
+ | `Flay` | Changed files | Structural code duplication (mass threshold: 16) |
92
+ | `YamlLint` | Changed files | YAML syntax |
93
+ | `Mdl` | Changed files | Markdown style |
94
+ | `BundlerAudit` | Gemfile.lock | Known gem CVEs |
95
+ | `RubyAudit` | Ruby stdlib | Known Ruby CVEs |
96
+ | `CheckVersions` | Project-wide | Ruby version consistency across files |
97
+
98
+ `RubocopAll` is a custom hook (`.git-hooks/pre_commit/rubocop_all.rb`) that
99
+ scans all project files, not just changed files. This ensures new rubocop cops
100
+ (from version updates) catch offenses everywhere, not just in the commit diff.
101
+ See ADR-008 for the rationale.
102
+
103
+ If a hook fails, fix the issue and commit again. To run hooks manually:
104
+
105
+ ```bash
106
+ bundle exec overcommit --run # run all pre-commit hooks
107
+ ```
108
+
109
+ ## Architecture Overview
110
+
111
+ raictl follows a layered architecture with clear extension points:
112
+
113
+ ```text
114
+ CLI Layer lib/rosett_ai/thor/tasks/*.rb Thor subcommands
115
+ Library Layer lib/rosett_ai/**/*.rb Domain logic
116
+ Engine Layer lib/rosett_ai/engines/<name>/ AI engine backends & adapters
117
+ Config Layer conf/**/*.yml YAML configurations
118
+ Schema Layer conf/schemas/*.json JSON Schema validation
119
+ UI Layer lib/rosett_ai/ui/ Pluggable display adapters
120
+ i18n Layer locales/*.yml Translation files
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Adding a New Translation (Locale)
126
+
127
+ raictl uses ruby-i18n with YAML source files.
128
+
129
+ ### Create the locale file
130
+
131
+ Create `locales/<code>.yml` (e.g., `locales/de.yml`). Copy the structure from
132
+ `locales/en.yml` and translate every string value. The top-level key must be
133
+ the locale code:
134
+
135
+ ```yaml
136
+ de:
137
+ rosett_ai:
138
+ meta:
139
+ direction: ltr
140
+ language_name: "German"
141
+ language_name_native: "Deutsch"
142
+ cli:
143
+ version: "rosett-ai Version %{version}"
144
+ ```
145
+
146
+ ### Translation rules
147
+
148
+ - Preserve all interpolation variables (`%{version}`, `%{count}`, etc.)
149
+ exactly as they appear in en.yml. Changing variable names will cause
150
+ runtime errors.
151
+ - For RTL languages (Arabic, Hebrew), set `meta.direction: rtl`. The
152
+ `AccessibleTui` adapter reads this to set text direction.
153
+ - For languages with plural rules (Arabic has 6 forms), use the ruby-i18n
154
+ plural keys (`zero`, `one`, `two`, `few`, `many`, `other`). See
155
+ `locales/ar.yml` for an example.
156
+
157
+ ### Compile and test
158
+
159
+ Compile locale files (optional, for distribution):
160
+
161
+ ```bash
162
+ bin/raictl compile --locales
163
+ ```
164
+
165
+ This generates gettext `.pot`/`.po` and Qt Linguist `.ts` files.
166
+
167
+ Test: Run `bin/raictl version --locale de` to verify.
168
+
169
+ ### Files to modify
170
+
171
+ | File | Action |
172
+ |------|--------|
173
+ | `locales/<code>.yml` | Create (copy en.yml structure) |
174
+
175
+ No code changes required — the locale is auto-discovered from the `locales/`
176
+ directory at load time.
177
+
178
+ ---
179
+
180
+ ## Adding a New AI Engine
181
+
182
+ Engines live under `lib/rosett_ai/engines/<name>/` with optional components.
183
+ Each engine has a manifest declaring its capabilities and a backend for
184
+ compilation. See the Claude and Generic engines for reference.
185
+
186
+ ### Create the engine gem
187
+
188
+ Each engine is a separate gem. Use `rosett-ai-engine-acme` as a reference:
189
+
190
+ ```bash
191
+ mkdir -p rosett-ai-engine-mistral/{lib/rosett_ai_engine/mistral,spec/rosett_ai_engine/mistral,conf}
192
+ ```
193
+
194
+ ### Create the manifest
195
+
196
+ Create `conf/manifest.yml`:
197
+
198
+ ```yaml
199
+ ---
200
+ name: mistral
201
+ display_name: "Mistral AI"
202
+ version: 1.0.0
203
+ components:
204
+ backend: true
205
+ config_compiler: false
206
+ executor: false
207
+ detector: false
208
+ scaffolder: false
209
+ detection: {}
210
+ execution: {}
211
+ capabilities:
212
+ compile: true
213
+ config: false
214
+ adopt_api: false
215
+ settings_json: false
216
+ ```
217
+
218
+ ### Create the backend class
219
+
220
+ Create `lib/rosett_ai_engine/mistral/backend.rb`:
221
+
222
+ ```ruby
223
+ # frozen_string_literal: true
224
+
225
+ module RosettAiEngine
226
+ module Mistral
227
+ class Backend < RosettAi::Compiler::Backend
228
+ MARKER_PREFIX = '<!-- rosett-ai-mistral-managed'
229
+
230
+ def render(data)
231
+ # Return a string representing the compiled output.
232
+ # See RosettAiEngine::Generic::Backend or
233
+ # RosettAiEngine::Claude::Backend for reference.
234
+ lines = []
235
+ lines << "#{generated_marker} -->"
236
+ # ... build your format
237
+ lines.join("\n") + "\n"
238
+ end
239
+
240
+ def generated_marker
241
+ MARKER_PREFIX
242
+ end
243
+ end
244
+ end
245
+ end
246
+ ```
247
+
248
+ ### Create the engine module and self-registration
249
+
250
+ Create `lib/rosett_ai_engine/mistral/engine.rb`:
251
+
252
+ ```ruby
253
+ # frozen_string_literal: true
254
+
255
+ require 'rosett_ai'
256
+ require_relative 'version'
257
+ require_relative 'backend'
258
+
259
+ module RosettAiEngine
260
+ module Mistral
261
+ module Engine
262
+ include RosettAi::Plugins::EngineContract
263
+
264
+ class << self
265
+ def engine_name = 'mistral'
266
+ def display_name = 'Mistral AI'
267
+ def version = VERSION
268
+ def backend_class = RosettAiEngine::Mistral::Backend
269
+ def detector_class = nil
270
+ def executor_class = nil
271
+ def config_compiler_class = nil
272
+
273
+ def manifest_path
274
+ Pathname.new(__dir__).join('..', '..', '..', 'conf', 'manifest.yml').expand_path
275
+ end
276
+ end
277
+ end
278
+ end
279
+ end
280
+ ```
281
+
282
+ Create `lib/rosett_ai_engine/mistral/register.rb`:
283
+
284
+ ```ruby
285
+ # frozen_string_literal: true
286
+
287
+ require_relative 'engine'
288
+ RosettAi::Plugins::Registry.register(:engine, 'mistral', RosettAiEngine::Mistral::Engine)
289
+ ```
290
+
291
+ The engine self-registers via `Gem.find_files('rosett_ai_engine/*/register.rb')`.
292
+ No core code changes needed — install the gem, and it appears automatically.
293
+
294
+ ### CLI executor type
295
+
296
+ Some engines use CLI subprocess execution (`api_type: cli`) instead of an
297
+ HTTP API. These engines spawn a child process via `Open3.capture3` and
298
+ communicate through stdin/stdout.
299
+
300
+ In the engine manifest, set:
301
+
302
+ ```yaml
303
+ execution:
304
+ api_type: cli
305
+ binary: mistral-cli
306
+ ```
307
+
308
+ Then create an executor at `lib/rosett_ai_engine/mistral/executor.rb` that
309
+ implements `#analyze(prompt)` using `Open3.capture3`. See
310
+ `rosett-ai-engine-goose` or `rosett-ai-engine-aider` for reference
311
+ for reference.
312
+
313
+ ### Detector patterns
314
+
315
+ Engines can provide automatic detection via a detector class. The detector
316
+ checks for CLI binaries, config directories, or environment variables:
317
+
318
+ ```ruby
319
+ module RosettAi
320
+ module Engines
321
+ module Mistral
322
+ class Detector < RosettAi::Engines::Detector
323
+ private
324
+
325
+ def detect_binary
326
+ system('which', 'mistral-cli', out: File::NULL, err: File::NULL)
327
+ end
328
+
329
+ def detect_config
330
+ File.directory?(File.expand_path('~/.mistral'))
331
+ end
332
+ end
333
+ end
334
+ end
335
+ end
336
+ ```
337
+
338
+ ### Add tests and use
339
+
340
+ Add tests at `spec/rosett_ai/engines/mistral/backend_spec.rb`, then use
341
+ it with `bin/raictl compile --engine mistral`.
342
+
343
+ You can set your new engine as the default by editing `~/.config/rosett-ai/config.yml`:
344
+
345
+ ```yaml
346
+ default_engine: mistral
347
+ ```
348
+
349
+ ### Files to modify
350
+
351
+ | File | Action |
352
+ |------|--------|
353
+ | `conf/engines/<name>/manifest.yml` | Create |
354
+ | `conf/engines/<name>/target.yml` | Create |
355
+ | `lib/rosett_ai/engines/<name>/backend.rb` | Create |
356
+ | `lib/rosett_ai/engines/registry.rb` | Add to `ENGINES` hash |
357
+ | `lib/rosett_ai/compiler/backend.rb` | Add to `BACKENDS` hash |
358
+ | `spec/rosett_ai/engines/<name>/backend_spec.rb` | Create |
359
+
360
+ ---
361
+
362
+ ## Adding a New Configuration Section (Claude Code Scope)
363
+
364
+ Claude Code settings are compiled from YAML scopes in `conf/engines/claude/config/`.
365
+
366
+ ### Edit or create scope files
367
+
368
+ Edit the scope file (e.g., `conf/engines/claude/config/managed.yml`) to add new
369
+ configuration keys. The schema at `conf/engines/claude/schemas/config_schema.json`
370
+ defines which keys are valid per scope.
371
+
372
+ To add an entirely new scope, create `conf/engines/claude/config/<scope>.yml` and
373
+ register it in `lib/rosett_ai/engines/claude/scope_router.rb`.
374
+
375
+ ### Key mappings and domains
376
+
377
+ - For new key mappings (snake\_case YAML to camelCase JSON), update
378
+ `lib/rosett_ai/engines/claude/key_map.rb` to add the mapping entry.
379
+ - For new domains (like `mcp`, `api`), update
380
+ `lib/rosett_ai/engines/claude/domain_transformer.rb` to handle transformation rules.
381
+
382
+ ### Test
383
+
384
+ Run `bin/raictl config compile --simulate --verbose` to verify.
385
+
386
+ ### Files to modify
387
+
388
+ | File | Action |
389
+ |------|--------|
390
+ | `conf/engines/claude/config/<scope>.yml` | Edit or create |
391
+ | `conf/engines/claude/schemas/config_schema.json` | Extend schema |
392
+ | `lib/rosett_ai/engines/claude/key_map.rb` | Add key mapping (if new keys) |
393
+ | `lib/rosett_ai/engines/claude/scope_router.rb` | Add scope route (if new scope) |
394
+
395
+ ---
396
+
397
+ ## Adding a New CLI Subcommand
398
+
399
+ ### Create the task file
400
+
401
+ Create `lib/rosett_ai/thor/tasks/<name>.rb`:
402
+
403
+ ```ruby
404
+ # frozen_string_literal: true
405
+
406
+ # SPDX-License-Identifier: GPL-3.0-only
407
+ # Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
408
+
409
+ require 'thor'
410
+ require 'rainbow'
411
+
412
+ module RosettAi
413
+ module Thor
414
+ module Tasks
415
+ class Example < ::Thor
416
+ desc 'execute', 'Run the example command'
417
+ def execute
418
+ puts t('success')
419
+ end
420
+
421
+ private
422
+
423
+ def t(key, **)
424
+ ::I18n.t("rosett-ai.cli.example.#{key}", **)
425
+ end
426
+ end
427
+ end
428
+ end
429
+ end
430
+ ```
431
+
432
+ ### Register and configure
433
+
434
+ Register the subcommand in `lib/rosett_ai/thor/cli.rb`:
435
+
436
+ ```ruby
437
+ desc 'example SUBCOMMAND', 'Example commands'
438
+ subcommand 'example', RosettAi::Thor::Tasks::Example
439
+ ```
440
+
441
+ Add the error class in `lib/rosett_ai.rb`:
442
+
443
+ ```ruby
444
+ class ExampleError < Error; end
445
+ ```
446
+
447
+ ### i18n, tests, and documentation
448
+
449
+ - Add i18n strings to `locales/en.yml` and `locales/fr.yml` under
450
+ `rosett-ai.cli.example.*`.
451
+ - Add reek exclusions in `.reek.yml` — at minimum add the class to
452
+ `DuplicateMethodCall` if it uses `puts`/`Rainbow` for output.
453
+ - Add tests at `spec/rosett_ai/thor/tasks/example_spec.rb`.
454
+ - Update `CLAUDE.md` (CLI Usage section) and `doc/man/rai.1.ronn`
455
+ (COMMANDS section).
456
+
457
+ ### Files to modify
458
+
459
+ | File | Action |
460
+ |------|--------|
461
+ | `lib/rosett_ai/thor/tasks/<name>.rb` | Create |
462
+ | `lib/rosett_ai/thor/cli.rb` | Register subcommand |
463
+ | `lib/rosett_ai.rb` | Add error class |
464
+ | `locales/en.yml` | Add i18n strings |
465
+ | `locales/fr.yml` | Add i18n strings |
466
+ | `.reek.yml` | Add exclusions |
467
+ | `spec/rosett_ai/thor/tasks/<name>_spec.rb` | Create |
468
+ | `CLAUDE.md` | Document command |
469
+ | `doc/man/rai.1.ronn` | Document command |
470
+
471
+ ---
472
+
473
+ ## Adding a New Design Document
474
+
475
+ Design documents define implementation standards in `conf/design/`.
476
+
477
+ ### Create the document
478
+
479
+ Create `conf/design/<name>.yml` with the required fields:
480
+
481
+ ```yaml
482
+ name: my_feature
483
+ domain: core
484
+ version: 0.1.0
485
+ status: draft
486
+ priority: 5
487
+ author: your_name
488
+ created_at: "2026-01-01"
489
+ modified_at: "2026-01-01"
490
+ modified_by: your_name
491
+ depends_on: []
492
+ intent: |
493
+ Why this exists and what problem it solves.
494
+ constraints:
495
+ - Hard boundary that must not be crossed
496
+ acceptance_criteria:
497
+ - Testable statement defining done
498
+ ```
499
+
500
+ Valid domains: `core`, `ui`, `security`, `testing`, `styles`, `i18n`,
501
+ `accessibility`, `licensing`, `ci`, `compiler`, `release`, `documentation`,
502
+ `operations`.
503
+
504
+ ### Validate and approve
505
+
506
+ Run `bin/raictl design validate my_feature` to check the document against
507
+ the schema. If a new domain is needed, update `conf/schemas/design_schema.json`
508
+ to add it to the `domain` enum. Set status to `approved` once reviewed.
509
+
510
+ ### Files to modify
511
+
512
+ | File | Action |
513
+ |------|--------|
514
+ | `conf/design/<name>.yml` | Create |
515
+ | `conf/schemas/design_schema.json` | Extend domain enum (if new domain) |
516
+
517
+ ---
518
+
519
+ ## Adding a New UI Adapter
520
+
521
+ The UI layer uses a registry pattern. TUI is the default; GUI adapters are
522
+ optional.
523
+
524
+ ### Create the adapter
525
+
526
+ Create `lib/rosett_ai/ui/<name>.rb`:
527
+
528
+ ```ruby
529
+ # frozen_string_literal: true
530
+
531
+ module RosettAi
532
+ module Ui
533
+ class MyAdapter < Base
534
+ def render(content)
535
+ # Render content string to the user
536
+ end
537
+
538
+ def display_table(headers:, rows:, title: nil)
539
+ # Display tabular data
540
+ end
541
+
542
+ def prompt_user(message, choices: [])
543
+ # Interactive prompt
544
+ end
545
+
546
+ def show_spinner(message)
547
+ # Show spinner, yield, return result
548
+ yield
549
+ end
550
+
551
+ def announce(message, priority: :polite)
552
+ # Accessibility announcement
553
+ end
554
+ end
555
+ end
556
+ end
557
+ ```
558
+
559
+ ### Register and test
560
+
561
+ Register in `lib/rosett_ai/ui/registry.rb`:
562
+
563
+ ```ruby
564
+ register('myadapter', RosettAi::Ui::MyAdapter)
565
+ ```
566
+
567
+ Add the `--ui` enum value in `lib/rosett_ai/thor/cli.rb`.
568
+
569
+ Add tests using the shared examples at
570
+ `spec/support/shared_examples/ui_implementation.rb`:
571
+
572
+ ```ruby
573
+ RSpec.describe RosettAi::Ui::MyAdapter do
574
+ it_behaves_like 'a UI implementation'
575
+ end
576
+ ```
577
+
578
+ If this adapter is a separate .deb package (like `rosett-ai-gtk4`), create a
579
+ packaging variant at `conf/packaging/<name>.yml`.
580
+
581
+ ### Files to modify
582
+
583
+ | File | Action |
584
+ |------|--------|
585
+ | `lib/rosett_ai/ui/<name>.rb` | Create |
586
+ | `lib/rosett_ai/ui/registry.rb` | Register adapter |
587
+ | `lib/rosett_ai/thor/cli.rb` | Add to `--ui` enum |
588
+ | `spec/rosett_ai/ui/<name>_spec.rb` | Create |
589
+ | `conf/packaging/<name>.yml` | Create (if separate package) |
590
+
591
+ ---
592
+
593
+ ## Adding a New CI Job
594
+
595
+ CI jobs live in `.gitlab-ci-files/<stage>/` and are included from
596
+ `.gitlab-ci.yml`.
597
+
598
+ ### Create the job file
599
+
600
+ Create `.gitlab-ci-files/<stage>/<name>.yml`:
601
+
602
+ ```yaml
603
+ my_job:
604
+ stage: code_quality
605
+ extends:
606
+ - .ruby_base
607
+ script:
608
+ - echo "Running my check"
609
+ rules:
610
+ - if: $CI_MERGE_REQUEST_IID
611
+ when: on_success
612
+ ```
613
+
614
+ Available stages: `validate`, `code_quality`, `security_scan`, `test`, `build`.
615
+ Stages are defined in `.gitlab-ci-files/global/stages.yml`.
616
+
617
+ ### Include the job
618
+
619
+ Add the include to `.gitlab-ci.yml`:
620
+
621
+ ```yaml
622
+ - local: '.gitlab-ci-files/<stage>/<name>.yml'
623
+ ```
624
+
625
+ ---
626
+
627
+ ## Security Rules
628
+
629
+ All contributions must follow these rules (enforced by CI):
630
+
631
+ - **YAML.safe\_load only** — never `YAML.load`
632
+ - **Array-form system()** — never string interpolation in shell commands
633
+ - **File writes to whitelisted directories only**
634
+ - **Secrets: 0600 permissions, never logged**
635
+ - **All external input validated before use**
636
+ - **SPDX headers** on every Ruby source file:
637
+ `# SPDX-License-Identifier: GPL-3.0-only`
638
+
639
+ ## Code Quality Gates
640
+
641
+ Every commit must pass:
642
+
643
+ - `bundle exec rspec` — all tests green
644
+ - `bundle exec rubocop` — zero offenses
645
+ - `bundle exec reek` — zero warnings (or excluded in `.reek.yml` with justification)
646
+ - `bundle exec bundler-audit check` — no known CVEs
647
+ - `bundle exec ruby-audit check` — no Ruby advisory violations
648
+ - Overcommit pre-commit hooks (YAML lint, trailing whitespace, JSON syntax, etc.)
649
+
650
+ ## Branch Naming
651
+
652
+ All branches must follow the pattern `<type>/<id>-<subject>`:
653
+
654
+ - **type** --- a [Conventional Commits](https://www.conventionalcommits.org/)
655
+ type: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`,
656
+ `ci`, `build`, `revert`
657
+ - **id** --- the OpenProject work package number (omit if no WP exists)
658
+ - **subject** --- short kebab-case description
659
+
660
+ Examples:
661
+
662
+ ```text
663
+ feat/857-belspo-registration
664
+ fix/712-compile-scope-bug
665
+ docs/1286-security-md
666
+ chore/update-deps
667
+ ```
668
+
669
+ ## Conventional Commits
670
+
671
+ All commit messages must follow
672
+ [Conventional Commits](https://www.conventionalcommits.org/) format:
673
+
674
+ ```text
675
+ type(scope): description
676
+
677
+ Optional body explaining *why*, not *what*.
678
+
679
+ OP#<work-package-id>
680
+
681
+ Co-Authored-By: ... (if applicable)
682
+ Signed-off-by: ... (if applicable)
683
+ ```
684
+
685
+ Valid types match the branch naming types above. The scope is optional
686
+ but encouraged (e.g. `fix(compile):`, `docs(security):`). The
687
+ `OP#<id>` trailer is injected automatically by the overcommit
688
+ `CommitMsg` hook when the branch follows the naming convention.
689
+
690
+ ## AI Disclosure
691
+
692
+ When AI tools assist in writing code or documentation, contributors
693
+ must disclose the assistance:
694
+
695
+ 1. **Co-Authored-By trailer** --- add to the commit message:
696
+
697
+ ```text
698
+ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
699
+ ```
700
+
701
+ Replace the model name and version with the actual tool used. This
702
+ trailer is required for any commit where AI generated or
703
+ substantially revised the content.
704
+
705
+ 2. **Provenance file** --- for NeatNerds maintainers, run
706
+ `raictl provenance add` after each AI-assisted commit to append
707
+ an entry to `.ai-provenance.yml`. External contributors are not
708
+ required to update this file.
709
+
710
+ Contributions generated entirely by AI without human review will not
711
+ be accepted. The human contributor remains responsible for
712
+ correctness, security, and license compliance of all submitted code.
713
+
714
+ ## Developer Certificate of Origin (DCO)
715
+
716
+ External contributors must sign off their commits to certify they
717
+ have the right to submit the work under the project's license:
718
+
719
+ ```text
720
+ Signed-off-by: Your Name <your-email@example.com>
721
+ ```
722
+
723
+ Use `git commit --signoff` (or `-s`) to add this trailer
724
+ automatically. By signing off, you agree to the
725
+ [Developer Certificate of Origin](https://developercertificate.org/)
726
+ (version 1.1).
727
+
728
+ NeatNerds maintainers are covered by their employment or contractor
729
+ agreement and do not need to sign off individually.
730
+
731
+ ## License
732
+
733
+ raictl is licensed under GPL-3.0-only. All contributions must be compatible
734
+ with this license.