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,220 @@
1
+ # Implement styles.yml design document (P1)
2
+
3
+ **Branch**: `design_implementation`
4
+ **Date**: 2026-02-19 to 2026-02-21
5
+ **Design doc**: `conf/design/styles.yml` v1.0.0
6
+ **Commits**: ff3d81e, bf9f15e (partial)
7
+
8
+ ## Motivation
9
+
10
+ Style enforcement eliminates bikeshedding, ensures consistency across human
11
+ and AI contributors, and makes code review focus on logic rather than
12
+ formatting. The styles design document codifies all conventions into automated
13
+ enforcement — pre-commit hooks block violations locally, and the CI pipeline
14
+ blocks them in merge requests. Style rules are not optional guidelines; they
15
+ are enforced gates.
16
+
17
+ This depends on security (tooling must be present) and testing (enforcement
18
+ must be verifiable). It is the third P1 domain.
19
+
20
+ ## Acceptance criteria
21
+
22
+ All 10 acceptance criteria from `styles.yml` are satisfied:
23
+
24
+ | # | Criterion | Evidence |
25
+ |---|-----------|----------|
26
+ | 1 | `.rubocop.yml` with all conventions, zero violations on main | `.rubocop.yml` with custom cops, Style/Copyright, all Metrics exclusions documented |
27
+ | 2 | `.yamllint` with project YAML formatting rules | Pre-existing `.yamllint` configuration |
28
+ | 3 | `.reek.yml` with code smell detection thresholds | `.reek.yml` with documented exclusions per `doc/REEK_CONFIGURATION.md` |
29
+ | 4 | `.overcommit.yml` enforces rubocop, yamllint, reek, json, bundler-audit, trailing whitespace | All hooks enabled with `on_warn: fail` |
30
+ | 5 | Commit message format enforced by CommitMsg hooks | Overcommit CommitMsg hook enforces Conventional Commits pattern |
31
+ | 6 | mdl configured and enforced for all .md files | `.mdlrc` + `.mdl_style.rb` + Mdl overcommit hook |
32
+ | 7 | `bundle exec rubocop` exits zero on entire codebase | Verified: 0 offenses |
33
+ | 8 | `bundle exec reek` exits zero on entire codebase | Verified: 0 warnings |
34
+ | 9 | yamllint exits zero on all YAML files | Verified: pre-existing enforcement |
35
+ | 10 | Flay configured + RuboCop Metrics cops enforced | Flay in overcommit (mass 16), CyclomaticComplexity (10), PerceivedComplexity (10), AbcSize (25) |
36
+
37
+ ## Changes by area
38
+
39
+ ### RuboCop configuration
40
+
41
+ **Commit**: bf9f15e
42
+
43
+ Key additions to `.rubocop.yml`:
44
+
45
+ | Setting | Value | Purpose |
46
+ |---------|-------|---------|
47
+ | `require: ./lib/rubocop/rosett_ai` | — | Load custom security cops |
48
+ | `RosettAi/UnsafeYamlLoad` | Severity: error | Block unsafe YAML.load |
49
+ | `RosettAi/ShellInterpolation` | Severity: error | Block shell injection |
50
+ | `Style/Copyright` | `SPDX-License-Identifier: GPL-3.0-only` | Enforce SPDX headers |
51
+ | `plugins: rubocop-factory_bot` | — | Test factory linting |
52
+ | `Metrics/AbcSize` | Max: 25 with documented exclusions | Complexity gate |
53
+ | `Metrics/CyclomaticComplexity` | Max: 10 | Complexity gate |
54
+ | `Metrics/PerceivedComplexity` | Max: 10 | Complexity gate |
55
+
56
+ All Metrics exclusions now include inline comments explaining why the exclusion
57
+ is justified (e.g., "Thor tasks orchestrate multi-stage workflows").
58
+
59
+ ### Reek configuration
60
+
61
+ **Commits**: 7423856, 46aa519, bf9f15e, 1d0bfb9, 6a8b27e
62
+
63
+ The `.reek.yml` was expanded with documented exclusions. Each exclusion has a
64
+ rationale recorded in `doc/REEK_CONFIGURATION.md`. Key patterns:
65
+
66
+ - `TooManyStatements`: excluded for Thor task methods (multi-stage workflows)
67
+ - `UtilityFunction`: excluded for module_function patterns (TextSanitizer, YamlLoader)
68
+ - `NilCheck`: excluded where nil guard is intentional API design
69
+ - `ControlParameter`: excluded for Registry.resolve optional name parameter
70
+
71
+ ### YAML linting
72
+
73
+ Pre-existing `.yamllint` configuration was already in place. No changes needed.
74
+
75
+ ### Markdown linting
76
+
77
+ **Commit**: bf9f15e
78
+
79
+ New files:
80
+
81
+ **`.mdlrc`**:
82
+
83
+ ```text
84
+ style '.mdl_style.rb'
85
+ ignore_front_matter true
86
+ ```
87
+
88
+ **`.mdl_style.rb`**:
89
+
90
+ ```ruby
91
+ all
92
+ rule 'MD013', line_length: 240, ignore_code_blocks: true, tables: false
93
+ rule 'MD029', style: :ordered
94
+ exclude_rule 'MD033' # Inline HTML — needed for anchors and complex tables
95
+ rule 'MD007', indent: 2
96
+ exclude_rule 'MD024' # Multiple headings with same content — changelogs repeat headings
97
+ ```
98
+
99
+ ### Overcommit hooks
100
+
101
+ **Commits**: 7423856, bf9f15e
102
+
103
+ Full pre-commit hook configuration (all set to `on_warn: fail`):
104
+
105
+ | Hook | Purpose |
106
+ |------|---------|
107
+ | RuboCop | Ruby style + security cops |
108
+ | Reek | Code smell detection |
109
+ | BundlerAudit | Gem CVE scanning |
110
+ | RubyAudit | Ruby stdlib CVE scanning |
111
+ | YamlSyntax | YAML validity |
112
+ | JsonSyntax | JSON validity |
113
+ | TrailingWhitespace | Whitespace hygiene |
114
+ | Mdl | Markdown lint (excludes LICENSE.md, vendor/, tmp/) |
115
+ | Flay | Structural duplication (mass threshold 16) |
116
+ | MergeConflicts | Unresolved conflict markers |
117
+ | BrokenSymlinks | Dead symlinks |
118
+
119
+ CommitMsg hooks enforce Conventional Commits format.
120
+
121
+ ### Conventional Commits
122
+
123
+ Enforced by overcommit CommitMsg hook. Format:
124
+
125
+ ```text
126
+ type(scope): description
127
+ ```
128
+
129
+ Types: `feat`, `fix`, `test`, `docs`, `refactor`, `style`, `chore`, `ci`.
130
+ All 12 commits on this branch follow the convention.
131
+
132
+ ### SPDX headers
133
+
134
+ **Commit**: bf9f15e
135
+
136
+ `Style/Copyright` cop enforces SPDX headers on all Ruby source files:
137
+
138
+ ```ruby
139
+ # SPDX-License-Identifier: GPL-3.0-only
140
+ # Copyright (C) 2026 Hugo Antonio Sepulveda Manriquez / NeatNerds
141
+ ```
142
+
143
+ 87 files received SPDX headers (all `.rb` files in `lib/` and `spec/`, plus
144
+ `Rakefile` and `bin/raictl`). Excluded: `Gemfile` and `.mdl_style.rb` (not
145
+ project source code).
146
+
147
+ ### LICENSE.md
148
+
149
+ **Commit**: bf9f15e
150
+
151
+ Full GPL-3.0-only license text (675 lines) added as `LICENSE.md`. Excluded
152
+ from mdl linting (pre-formatted legal text).
153
+
154
+ ## Pre-commit enforcement flow
155
+
156
+ ```mermaid
157
+ flowchart LR
158
+ subgraph LOCAL["Local (overcommit)"]
159
+ GC[git commit] --> PRE[Pre-commit hooks]
160
+ PRE --> RC[RuboCop]
161
+ PRE --> RK[Reek]
162
+ PRE --> BA[bundler-audit]
163
+ PRE --> RA[ruby-audit]
164
+ PRE --> FL[Flay]
165
+ PRE --> MDL2[mdl]
166
+ PRE --> YS[YamlSyntax]
167
+ PRE --> JS[JsonSyntax]
168
+ PRE --> TW[TrailingWhitespace]
169
+ end
170
+
171
+ subgraph MSG["Commit Message"]
172
+ CM[CommitMsg hook] --> CC{Conventional<br/>Commits?}
173
+ CC -->|no| REJECT[Reject]
174
+ CC -->|yes| PASS2[Accept]
175
+ end
176
+
177
+ subgraph REMOTE["CI Pipeline"]
178
+ PUSH[git push] --> VAL[validate stage]
179
+ VAL --> CQ[code_quality stage]
180
+ CQ --> SS[security_scan stage]
181
+ SS --> TEST[test stage]
182
+ TEST --> BUILD[build stage]
183
+ end
184
+
185
+ PRE -->|all pass| CM
186
+ PASS2 --> PUSH
187
+
188
+ style REJECT fill:#8b0000,color:#fff
189
+ ```
190
+
191
+ ## Files created
192
+
193
+ | File | Purpose |
194
+ |------|---------|
195
+ | `.mdlrc` | Markdownlint configuration |
196
+ | `.mdl_style.rb` | Custom markdownlint style rules |
197
+ | `LICENSE.md` | GPL-3.0-only full license text (675 lines) |
198
+
199
+ ## Files modified
200
+
201
+ | File | Change |
202
+ |------|--------|
203
+ | `.rubocop.yml` | Custom cops, Style/Copyright, factory_bot plugin, documented exclusions |
204
+ | `.reek.yml` | New exclusions with documented rationale for new classes |
205
+ | `.overcommit.yml` | Added RubyAudit, Mdl, Flay hooks |
206
+ | `Gemfile` | Added ruby_audit, flog, mdl dependencies |
207
+ | `rosett-ai.gemspec` | Updated gem metadata |
208
+ | 87 `.rb` files | SPDX-License-Identifier headers added |
209
+ | `doc/REEK_CONFIGURATION.md` | Updated with new exclusion rationale |
210
+
211
+ ## Verification
212
+
213
+ - [x] `bundle exec rubocop` — 0 offenses (all cops active)
214
+ - [x] `bundle exec reek lib/` — 0 warnings
215
+ - [x] `bundle exec mdl doc/` — 0 violations
216
+ - [x] `yamllint .` — 0 errors
217
+ - [x] All 12 commits follow Conventional Commits format
218
+ - [x] All Ruby source files have SPDX headers
219
+ - [x] Flay runs via overcommit (mass threshold 16)
220
+ - [x] Pre-commit hooks block violations (`on_warn: fail`)
@@ -0,0 +1,95 @@
1
+ # Architecture Completion — Criterion 8 (Package Dependencies)
2
+
3
+ **Date**: 2026-02-21
4
+ **Branch**: `design_implementation`
5
+ **Design document**: `conf/design/architecture.yml` (status: draft -> approved)
6
+
7
+ ## Summary
8
+
9
+ Implements the final acceptance criterion for the architecture design document:
10
+ "Package dependencies are correctly declared (rosett-ai-gtk4 depends on rosett-ai)".
11
+
12
+ This completes all 8 architecture criteria and changes the document status
13
+ from `draft` to `approved`, unblocking all P3 work (ui_framework,
14
+ accessibility, i18n).
15
+
16
+ ## Implementation
17
+
18
+ ### Data-driven variant packaging declarations
19
+
20
+ Three variant configuration files in `conf/packaging/` define the Debian
21
+ package metadata and dependencies for each rosett-ai package:
22
+
23
+ | File | Package | Depends on rosett-ai? |
24
+ |------|---------|-----------------|
25
+ | `core.yml` | `rosett-ai` | No (is the core) |
26
+ | `gtk4.yml` | `rosett-ai-gtk4` | Yes |
27
+ | `qt6.yml` | `rosett-ai-qt6` | Yes |
28
+
29
+ ### Dynamic version resolution
30
+
31
+ Variant configs use `"current"` as a version keyword for the rosett-ai dependency:
32
+
33
+ ```yaml
34
+ package_dependencies:
35
+ - name: rosett-ai
36
+ version: "current" # Resolved to ">= 0.1.0" at build time
37
+ ```
38
+
39
+ `VariantConfig#fpm_depends` resolves `"current"` to `">= #{RosettAi::VERSION}"`
40
+ at load time. This satisfies the `lifecycle_management.yml` atomic update
41
+ constraint — changing `lib/rosett_ai/version.rb` automatically updates all
42
+ variant dependency constraints with no manual intervention.
43
+
44
+ ### JSON Schema validation
45
+
46
+ `conf/schemas/packaging_schema.json` validates all variant configs with:
47
+
48
+ - Required fields: `name`, `variant`, `description`
49
+ - Variant enum: `["core", "gtk4", "qt6", "kde"]`
50
+ - Package name pattern: `^rosett-ai(-[a-z0-9]+)?$`
51
+ - Version constraint pattern accepting `"current"` or Debian-style constraints
52
+
53
+ ### Build task integration
54
+
55
+ `bin/raictl build package` accepts `--variant` option (default: `core`):
56
+
57
+ - `--variant core` — produces identical output to previous behavior
58
+ - `--variant gtk4` — would produce `rosett-ai-gtk4` package with rosett-ai dependency
59
+ - Non-core variants fail early if adapter file doesn't exist (P3 work)
60
+
61
+ ## Files
62
+
63
+ | Action | File |
64
+ |--------|------|
65
+ | New | `conf/packaging/core.yml` |
66
+ | New | `conf/packaging/gtk4.yml` |
67
+ | New | `conf/packaging/qt6.yml` |
68
+ | New | `conf/schemas/packaging_schema.json` |
69
+ | New | `lib/rosett_ai/packaging/variant_config.rb` |
70
+ | New | `spec/rosett_ai/packaging/variant_config_spec.rb` |
71
+ | Modified | `lib/rosett_ai/thor/tasks/build.rb` |
72
+ | Modified | `spec/rosett_ai/thor/tasks/build_package_spec.rb` |
73
+ | Modified | `spec/spec_helper.rb` |
74
+ | Modified | `conf/design/architecture.yml` |
75
+
76
+ ## System dependency lifecycle
77
+
78
+ System dependencies (`libc6`, `libgtk-4-1`, `qt6-base`) are Debian package
79
+ names. The upgrade procedure follows `lifecycle_management.yml`:
80
+
81
+ 1. **Trigger**: Debian release changes available package versions
82
+ 2. **Research**: `apt-cache show <package>` in target distribution
83
+ 3. **Scope**: grep variant configs for the dependency name
84
+ 4. **Execute**: update the variant config YAML
85
+ 5. **Verify**: full suite (rspec, rubocop, reek) + schema validation
86
+ 6. **Commit**: reference the Debian release or security advisory
87
+
88
+ ## Verification
89
+
90
+ ```bash
91
+ bundle exec rspec spec/rosett_ai/packaging/
92
+ bundle exec rspec spec/rosett_ai/thor/tasks/build_package_spec.rb
93
+ bundle exec rspec
94
+ bundle exec rubocop && bundle exec reek
95
+ ```
@@ -0,0 +1,253 @@
1
+ # Implement architecture.yml UI layer (partial P2)
2
+
3
+ **Branch**: `design_implementation`
4
+ **Date**: 2026-02-21
5
+ **Design doc**: `conf/design/architecture.yml` v1.0.0
6
+ **Commits**: 1d0bfb9, 6a8b27e
7
+
8
+ ## Motivation
9
+
10
+ The architecture design document defines rosett-ai as a TUI-first, pluggable
11
+ application with optional GUI layers delivered as separate Debian packages.
12
+ All UI variants share the same backend logic in `lib/rosett_ai/`. The abstract UI
13
+ interface (`lib/rosett_ai/ui/base.rb`) defines the contract that all implementations
14
+ must fulfil.
15
+
16
+ This implementation addresses the UI layer portion of the architecture document:
17
+ the abstract interface, the plugin registry, the default TUI adapter, and
18
+ accessibility methods (screen reader detection, text direction, live-region
19
+ announcements). The remaining architecture criteria (package separation, GTK4/Qt6
20
+ adapters, full headless verification) are deferred to the P3 ui_framework phase.
21
+
22
+ ## Acceptance criteria
23
+
24
+ 2 of 8 acceptance criteria from `architecture.yml` are addressed in this
25
+ implementation. The remainder are deferred with rationale:
26
+
27
+ | # | Criterion | Status | Evidence / Deferral reason |
28
+ |---|-----------|--------|----------------------------|
29
+ | 1 | bin/raictl runs without errors on headless server | Deferred | Requires full integration testing on headless CI runner |
30
+ | 2 | Installing rosett-ai-gtk4 adds GTK4 option without modifying core | Deferred | P3 — no GUI packages built yet |
31
+ | 3 | lib/rosett_ai/ui/base.rb defines abstract interface | Met | 7 abstract methods, RTL_LOCALES, accessibility |
32
+ | 4 | lib/rosett_ai/ui/registry.rb discovers installed UI plugins | Met | register, resolve, available, registered?, reset! |
33
+ | 5 | All business logic in lib/rosett_ai/ (not TUI or GUI code) | Deferred | Requires full codebase audit; TUI adapter delegates only |
34
+ | 6 | Design docs validated against design_schema.json | Deferred | Schema validation exists but is separate concern |
35
+ | 7 | Behaviour docs validated against behaviour_schema.json | Deferred | Already in place (BehaviourValidator) |
36
+ | 8 | Package dependencies correctly declared | Deferred | P4 — packaging for GUI variants not started |
37
+
38
+ ## Changes by area
39
+
40
+ ### RosettAi::Ui::Base abstract interface
41
+
42
+ **File**: `lib/rosett_ai/ui/base.rb` (47 lines)
43
+
44
+ Defines 7 methods that all UI adapters must implement. The first 5 raise
45
+ `NotImplementedError` (abstract pattern). The last 2 provide default
46
+ implementations shared across all adapters:
47
+
48
+ | Method | Signature | Purpose |
49
+ |--------|-----------|---------|
50
+ | `render` | `(content)` | Display content to user |
51
+ | `display_table` | `(headers, rows)` | Render tabular data |
52
+ | `prompt_user` | `(question, choices: nil)` | Interactive input |
53
+ | `show_spinner` | `(message, &block)` | Progress indication |
54
+ | `announce` | `(message)` | Screen reader live-region announcement |
55
+ | `accessible?` | `()` | Detect assistive technology (Orca, BRLTTY) |
56
+ | `text_direction` | `(locale = nil)` | RTL/LTR based on locale |
57
+
58
+ **Accessibility methods** (added in 6a8b27e):
59
+
60
+ `accessible?` checks environment variables set by screen readers:
61
+
62
+ ```ruby
63
+ def accessible?
64
+ ENV.key?('ORCA_RUNNING') || ENV.key?('BRLTTY_TTY')
65
+ end
66
+ ```
67
+
68
+ `text_direction` returns `:rtl` for Arabic, Hebrew, Farsi, and Urdu locales:
69
+
70
+ ```ruby
71
+ RTL_LOCALES = ['ar', 'he', 'fa', 'ur'].freeze
72
+
73
+ def text_direction(locale = nil)
74
+ lang = locale || ENV.fetch('LANG', 'en')[0, 2]
75
+ RTL_LOCALES.include?(lang) ? :rtl : :ltr
76
+ end
77
+ ```
78
+
79
+ `announce` provides a hook for screen reader live-region announcements.
80
+ The Base class raises NotImplementedError; Tui implements it via `warn`.
81
+
82
+ ### RosettAi::Ui::Registry plugin discovery
83
+
84
+ **File**: `lib/rosett_ai/ui/registry.rb` (55 lines)
85
+
86
+ Class-level registry that manages UI adapter plugins:
87
+
88
+ | Method | Purpose |
89
+ |--------|---------|
90
+ | `register(name, adapter_class)` | Register an adapter (called at require time) |
91
+ | `resolve(name = nil)` | Instantiate an adapter by name (defaults to `:tui`) |
92
+ | `available` | List registered adapter names |
93
+ | `registered?(name)` | Check if an adapter is registered |
94
+ | `reset!` | Clear registry (for testing) |
95
+
96
+ The `default_adapter` private method prefers `:tui` if registered, then falls
97
+ back to the first registered adapter, then raises if none are registered.
98
+
99
+ Plugin registration happens at the bottom of each adapter file:
100
+
101
+ ```ruby
102
+ # lib/rosett_ai/ui/tui.rb
103
+ Registry.register(:tui, Tui)
104
+ ```
105
+
106
+ Future GUI adapters will follow the same pattern:
107
+
108
+ ```ruby
109
+ # lib/rosett_ai/ui/gtk4.rb (future)
110
+ Registry.register(:gtk4, Gtk4)
111
+ ```
112
+
113
+ ### RosettAi::Ui::Tui default adapter
114
+
115
+ **File**: `lib/rosett_ai/ui/tui.rb` (53 lines)
116
+
117
+ The default terminal adapter delegates to TTY gems:
118
+
119
+ | Method | Implementation |
120
+ |--------|---------------|
121
+ | `render` | `$stdout.puts(content)` |
122
+ | `display_table` | `Terminal::Table.new` |
123
+ | `prompt_user` | `TTY::Prompt.new.select` / `.ask` |
124
+ | `show_spinner` | `TTY::Spinner.new` with auto_spin |
125
+ | `announce` | `warn(message)` (stderr for screen reader compatibility) |
126
+
127
+ Dependencies: `rainbow`, `terminal-table`, `tty-prompt`, `tty-spinner`.
128
+
129
+ ### Shared examples update
130
+
131
+ **File**: `spec/support/shared_examples/ui_implementation.rb`
132
+
133
+ The interface contract grew from 4 to 7 method checks:
134
+
135
+ | Version | Methods checked |
136
+ |---------|----------------|
137
+ | Initial (5f352e6) | render, display_table, prompt_user, show_spinner |
138
+ | Final (6a8b27e) | render, display_table, prompt_user, show_spinner, announce, accessible?, text_direction |
139
+
140
+ ## UI plugin class diagram
141
+
142
+ ```mermaid
143
+ classDiagram
144
+ class Base {
145
+ +render(content)
146
+ +display_table(headers, rows)
147
+ +prompt_user(question, choices)
148
+ +show_spinner(message, block)
149
+ +announce(message)
150
+ +accessible?() bool
151
+ +text_direction(locale) symbol
152
+ -RTL_LOCALES : Array
153
+ }
154
+
155
+ class Tui {
156
+ +render(content)
157
+ +display_table(headers, rows)
158
+ +prompt_user(question, choices)
159
+ +show_spinner(message, block)
160
+ +announce(message)
161
+ }
162
+
163
+ class Gtk4 {
164
+ <<future>>
165
+ +render(content)
166
+ +display_table(headers, rows)
167
+ +prompt_user(question, choices)
168
+ +show_spinner(message, block)
169
+ +announce(message)
170
+ }
171
+
172
+ class Qt6 {
173
+ <<future>>
174
+ +render(content)
175
+ +display_table(headers, rows)
176
+ +prompt_user(question, choices)
177
+ +show_spinner(message, block)
178
+ +announce(message)
179
+ }
180
+
181
+ class Registry {
182
+ -adapters : Hash
183
+ +register(name, klass)$
184
+ +resolve(name)$ Base
185
+ +available()$ Array
186
+ +registered?(name)$ bool
187
+ +reset!()$
188
+ }
189
+
190
+ Base <|-- Tui
191
+ Base <|-- Gtk4
192
+ Base <|-- Qt6
193
+ Registry --> Base : instantiates
194
+ ```
195
+
196
+ ## Registry discovery flow
197
+
198
+ ```mermaid
199
+ sequenceDiagram
200
+ participant APP as Application
201
+ participant REQ as require
202
+ participant REG as Registry
203
+ participant TUI as Tui adapter
204
+
205
+ APP->>REQ: require 'rosett_ai/ui/tui'
206
+ REQ->>REG: Registry.register(:tui, Tui)
207
+ REG-->>REQ: stored in @adapters
208
+
209
+ Note over APP: Later, at runtime...
210
+
211
+ APP->>REG: Registry.resolve(:tui)
212
+ REG->>REG: lookup @adapters[:tui]
213
+ REG->>TUI: Tui.new
214
+ TUI-->>APP: adapter instance
215
+
216
+ Note over APP: Or with default...
217
+
218
+ APP->>REG: Registry.resolve
219
+ REG->>REG: default_adapter -> :tui
220
+ REG->>TUI: Tui.new
221
+ TUI-->>APP: adapter instance
222
+ ```
223
+
224
+ ## Files created
225
+
226
+ | File | Purpose |
227
+ |------|---------|
228
+ | `lib/rosett_ai/ui/base.rb` | Abstract UI interface (7 methods + RTL_LOCALES) |
229
+ | `lib/rosett_ai/ui/registry.rb` | Plugin discovery and adapter management |
230
+ | `lib/rosett_ai/ui/tui.rb` | Terminal UI adapter using TTY gems |
231
+ | `spec/rosett_ai/ui/base_spec.rb` | Base interface tests (85 lines) |
232
+ | `spec/rosett_ai/ui/registry_spec.rb` | Registry tests (70 lines) |
233
+ | `spec/rosett_ai/ui/tui_spec.rb` | TUI adapter tests (48 lines) |
234
+
235
+ ## Files modified
236
+
237
+ | File | Change |
238
+ |------|--------|
239
+ | `spec/support/shared_examples/ui_implementation.rb` | 4 to 7 method checks (added announce, accessible?, text_direction) |
240
+ | `.reek.yml` | Exclusions for Ui::Registry (ControlParameter), Ui::Tui (UtilityFunction) |
241
+ | `conf/design/architecture.yml` | Minor status update |
242
+ | `lib/rubocop/cop/rosett-ai/shell_interpolation.rb` | Added on_xstr handler for backtick detection |
243
+
244
+ ## Verification
245
+
246
+ - [x] `bundle exec rspec spec/rosett_ai/ui/` — 42 examples, 0 failures
247
+ - [x] `bundle exec rubocop lib/rosett_ai/ui/` — 0 offenses
248
+ - [x] `bundle exec reek lib/rosett_ai/ui/` — 0 warnings
249
+ - [x] Shared examples pass for Tui adapter (all 7 interface methods)
250
+ - [x] Registry.resolve defaults to :tui when no name given
251
+ - [x] Registry.resolve raises for unknown adapter names
252
+ - [x] accessible? detects ORCA_RUNNING and BRLTTY_TTY environment variables
253
+ - [x] text_direction returns :rtl for ar, he, fa, ur; :ltr for others
@@ -0,0 +1,108 @@
1
+ # Claude Code Configuration Compiler Implementation
2
+
3
+ **Date**: 2026-02-21
4
+ **Branch**: `design_implementation`
5
+ **Design doc**: `conf/design/claude_code_configuration.yml` (P2, draft → approved)
6
+
7
+ ## Summary
8
+
9
+ Implements the Claude Code configuration compiler — the final P2 design
10
+ document. This delivers a YAML-to-JSON compilation pipeline that transforms
11
+ `conf/claude_code/*.yml` scope files into native Claude Code settings JSON
12
+ files. The compiler handles key remapping, secret resolution, env-key
13
+ merging, scope routing, and validate-only field checking.
14
+
15
+ ## Architecture
16
+
17
+ ```text
18
+ conf/claude_code/ Source YAML (4 scope files)
19
+ ├── managed.yml → /etc/claude-code/managed-settings.json
20
+ ├── user.yml → ~/.claude/settings.json
21
+ ├── project.yml → .claude/settings.json
22
+ └── local.yml → .claude/settings.local.json
23
+
24
+ lib/rosett_ai/config/
25
+ ├── compiler.rb Main orchestrator
26
+ ├── domain_transformer.rb Domain key mapping + env routing
27
+ ├── key_map.rb Explicit snake_case → camelCase mapping
28
+ ├── scope_router.rb Scope → target path resolution
29
+ ├── secret_resolver.rb ${secret:backend:key} parser (NO regex)
30
+ └── compile_result.rb Structured result per scope
31
+ ```
32
+
33
+ ## New files (19)
34
+
35
+ | Category | Files |
36
+ |----------|-------|
37
+ | Library | `lib/rosett_ai/config/{compiler,domain_transformer,key_map,scope_router,secret_resolver,compile_result}.rb` |
38
+ | Thor task | `lib/rosett_ai/thor/tasks/config.rb` |
39
+ | Schema | `conf/schemas/claude_code_config_schema.json` |
40
+ | Scope configs | `conf/claude_code/{managed,user,project,local}.yml` |
41
+ | Specs | `spec/rosett_ai/config/{compiler,key_map,scope_router,secret_resolver,compile_result}_spec.rb` |
42
+ | Spec | `spec/rosett_ai/thor/tasks/config_spec.rb` |
43
+ | Docs | `doc/changes/2026-02-21-cc-config-implementation.md` |
44
+
45
+ ## Modified files (9)
46
+
47
+ | File | Change |
48
+ |------|--------|
49
+ | `lib/rosett_ai/path_resolver.rb` | +5 methods for settings target paths |
50
+ | `lib/rosett_ai/thor/cli.rb` | Register `config` subcommand |
51
+ | `spec/rosett_ai/path_resolver_spec.rb` | Tests for new PathResolver methods |
52
+ | `spec/spec_helper.rb` | Copy claude_code_config_schema.json in test env |
53
+ | `spec/rosett_ai/thor/tasks/validate_spec.rb` | Add claude_code_config to internal schemas |
54
+ | `.reek.yml` | Exclusions for Config::Compiler, SecretResolver, Thor task |
55
+ | `conf/design/claude_code_configuration.yml` | status: draft → approved |
56
+ | `CHANGELOG.md` | CC config compiler entries |
57
+ | `doc/changes/2026-02-21-design-implementation-overview.md` | CC config status update |
58
+
59
+ ## Key design decisions
60
+
61
+ 1. **Explicit KeyMap, not algorithmic conversion** — Claude Code has irregular
62
+ keys (e.g., `auto_allow_bash` → `autoAllowBashIfSandboxed`). The compiler
63
+ uses a hardcoded table and raises `KeyMapError` on missing mappings.
64
+
65
+ 2. **NO regex in SecretResolver** — deterministic string parsing only
66
+ (`start_with?`/`end_with?`/`split`). Eliminates ReDoS vectors.
67
+
68
+ 3. **Single-pass secret resolution** — resolved values are never re-scanned,
69
+ preventing recursive injection attacks.
70
+
71
+ 4. **Three-target routing** — fields compile to `:json` (settings JSON),
72
+ `:env` (env key within JSON), or `:validate_only` (checked but not written).
73
+
74
+ 5. **handlers → hooks rename** — YAML uses `handlers` for hook definitions,
75
+ compiled JSON uses `hooks` (matching Claude Code's native format).
76
+
77
+ 6. **MCP filter key transformation** — `server_name` → `serverName` etc.
78
+ for managed-scope allowlist/denylist objects.
79
+
80
+ ## Acceptance criteria met (17/17)
81
+
82
+ | # | Criterion | Evidence |
83
+ |---|-----------|----------|
84
+ | 1 | JSON Schema exists | `conf/schemas/claude_code_config_schema.json` |
85
+ | 2 | Schema enforces scope enum | `"enum": ["managed", "user", "project", "local"]` |
86
+ | 3 | Compile reads YAML → JSON | `Config::Compiler#compile` + Thor task |
87
+ | 4 | user.yml → settings.json | `ScopeRouter` + compiler specs |
88
+ | 5 | project.yml → .claude/settings.json | ScopeRouter routing |
89
+ | 6 | local.yml → settings.local.json | ScopeRouter routing |
90
+ | 7 | managed.yml → /etc/... | ScopeRouter routing |
91
+ | 8 | Secret references resolved | `SecretResolver#resolve_all` |
92
+ | 9 | Secrets never logged | Single-pass, no display |
93
+ | 10 | Missing secrets abort | `SecretError` raised |
94
+ | 11 | Compatibility checked | `check_compatibility` method |
95
+ | 12 | Warnings don't block | Advisory only |
96
+ | 13 | --simulate shows diff | Hand-rolled unified diff |
97
+ | 14 | Schema errors show path | `data_pointer` in error messages |
98
+ | 15 | Idempotent | Checksum comparison |
99
+ | 16 | RSpec tests | Full spec coverage |
100
+ | 17 | No regex in secrets | Deterministic string parsing |
101
+
102
+ ## P2 completion
103
+
104
+ With this implementation, all three P2 design documents are now approved:
105
+
106
+ - `architecture.yml` — 8/8 criteria (implemented earlier)
107
+ - `compiler.yml` — 9/9 criteria (implemented earlier)
108
+ - `claude_code_configuration.yml` — 17/17 criteria (this change)