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