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,103 @@
1
+ ---
2
+ name: error_handling
3
+ domain: core
4
+ version: 0.1.0
5
+ status: implemented
6
+ priority: 1
7
+ author: hugo
8
+ created_at: "2026-03-15"
9
+ modified_at: "2026-03-16"
10
+ modified_by: claude
11
+ depends_on:
12
+ - security
13
+ - architecture
14
+ - i18n
15
+ #
16
+ intent: |
17
+ Establish a structured error hierarchy, standardised exit codes, and localised
18
+ error messages for Rosett-AI. Every error the user encounters must be actionable —
19
+ stating what went wrong, why, and how to fix it. This document prevents ad-hoc
20
+ error handling that leads to cryptic messages, swallowed exceptions, and
21
+ inconsistent exit codes across CLI commands.
22
+ #
23
+ constraints:
24
+ - All rosett-ai errors must inherit from RosettAi::Error (the base class)
25
+ - Each module defines exactly one error subclass (e.g. RosettAi::Compiler::CompilerError)
26
+ - Exit codes must follow a defined mapping — 0 success, 1 general error, 2 validation error, 3 configuration error, 4 permission error, 5 dependency error
27
+ - Error messages must include three parts — what failed, why it failed, and a suggested fix
28
+ - Error messages must be translatable via i18n keys (not hardcoded English strings)
29
+ - Never rescue StandardError or Exception at module boundaries — rescue only specific error classes
30
+ - Never swallow exceptions silently — all rescued exceptions must be logged or re-raised
31
+ - Stack traces are shown only in DEBUG log level — user-facing output shows structured messages only
32
+ - CLI commands must set Process.exit with the correct mapped exit code
33
+ - Error display must respect the current UI mode (TUI table, GUI dialog, plain text for pipes)
34
+ - Errors from YAML parsing must include the file path and line number when available
35
+ - Validation errors must be collected and reported as a batch (not fail-fast on first error)
36
+ #
37
+ acceptance_criteria:
38
+ - RosettAi::Error base class exists with message, code, and suggestion attributes
39
+ - Every module error class inherits from RosettAi::Error and is documented in error_handling.yml
40
+ - bin/raictl exits with documented exit code for each error category
41
+ - Error messages display what/why/fix structure in TUI and plain text modes
42
+ - All error message strings are i18n keys resolvable from locales/ directory
43
+ - bin/raictl validate reports all validation errors in a single run (batch mode)
44
+ - stack traces are suppressed unless RAI_LOG_LEVEL=DEBUG
45
+ - YAML parse errors include filename and line number in the error message
46
+ - RSpec tests verify exit codes for each CLI command error path
47
+ - No instance of rescue StandardError or rescue Exception exists outside the top-level CLI handler
48
+ #
49
+ examples:
50
+ - scenario: "User runs bin/raictl compile with a malformed behaviour YAML"
51
+ expected: |
52
+ Exit code 2. Message: "Validation failed: conf/behaviour/broken.yml:14 —
53
+ missing required field 'rules'. Fix: add a 'rules' array to the behaviour file."
54
+ not: |
55
+ Exit code 1. Message: "undefined method `[]' for nil:NilClass" or
56
+ silent failure with no output.
57
+ - scenario: "User runs bin/raictl adopt --api without an API key configured"
58
+ expected: |
59
+ Exit code 3. Message: "Configuration error: ANTHROPIC_API_KEY not found.
60
+ Set it via environment variable or system keyring. See: bin/raictl help adopt"
61
+ not: |
62
+ Exit code 1. Message: "HTTP 401 Unauthorized" with no context.
63
+ - scenario: "User runs bin/raictl compile and two behaviour files have errors"
64
+ expected: |
65
+ Both errors displayed in a table. Exit code 2.
66
+ "2 validation errors in 2 files. Fix errors and re-run bin/raictl compile."
67
+ not: |
68
+ First error displayed, second file not checked. User must fix-and-retry repeatedly.
69
+ - scenario: "Developer pipes bin/raictl validate output to another tool"
70
+ expected: |
71
+ Plain text output (no colours, no table borders). One error per line.
72
+ Exit code reflects worst error category.
73
+ not: |
74
+ ANSI escape codes in output corrupt downstream parsing.
75
+ - scenario: "A permission error occurs writing to ~/.claude/rules/"
76
+ expected: |
77
+ Exit code 4. Message: "Permission denied: cannot write to ~/.claude/rules/security.md.
78
+ Fix: check directory permissions (expected 0755) or run with appropriate user."
79
+ not: |
80
+ Exit code 1. Message: "Errno::EACCES: Permission denied @ rb_sysopen"
81
+ #
82
+ anti_patterns:
83
+ - Using puts for error output instead of structured error objects
84
+ - Rescuing StandardError as a catch-all at module boundaries
85
+ - Hardcoded English error messages without i18n keys
86
+ - Returning nil on failure instead of raising a typed error
87
+ - Using exit(1) for all error types instead of specific exit codes
88
+ - Displaying raw Ruby exception messages to end users
89
+ - Fail-fast validation that stops at the first error
90
+ - Swallowing exceptions in rescue blocks without logging
91
+ #
92
+ preferences:
93
+ language: ruby
94
+ patterns:
95
+ - error_hierarchy
96
+ - structured_error_messages
97
+ - batch_validation
98
+ - exit_code_mapping
99
+ testing: rspec with exit code verification and i18n key resolution tests
100
+ gems:
101
+ - i18n
102
+ - thor
103
+ - pastel
@@ -0,0 +1,142 @@
1
+ ---
2
+ name: feature_flags
3
+ domain: core
4
+ version: 0.1.0
5
+ status: implemented
6
+ priority: 3
7
+ author: hugo
8
+ created_at: "2026-03-16"
9
+ modified_at: "2026-03-16"
10
+ modified_by: claude
11
+ depends_on:
12
+ - architecture
13
+ - error_handling
14
+ - backward_compatibility
15
+ #
16
+ intent: |
17
+ Provide a lightweight, environment-variable-based feature gating mechanism
18
+ that allows experimental features to be developed on main without exposing
19
+ them to users by default. Setting `RAI_EXPERIMENTAL=workflow,mcp` enables
20
+ only the listed features; all others remain hidden. This prevents premature
21
+ exposure of incomplete features while allowing developers and testers to
22
+ exercise new code paths before a stable release.
23
+
24
+ Feature flags complement backward compatibility (backward_compatibility.yml):
25
+ deprecation warnings communicate removal of existing features, while feature
26
+ flags control visibility of new features before they are stable. Both serve
27
+ the same goal — protecting users from unexpected changes — but operate in
28
+ opposite directions (removal vs introduction).
29
+
30
+ This design intentionally avoids a database-backed, per-user, or remote
31
+ feature flag service. Flags are environment-only, process-scoped, and
32
+ resolved at startup. There is no runtime toggle, no A/B testing, and no
33
+ analytics integration. Complexity is kept minimal: a single module with
34
+ a class method interface.
35
+ #
36
+ constraints:
37
+ - "Feature flags are controlled exclusively via RAI_EXPERIMENTAL environment
38
+ variable — no config files, no CLI flags, no runtime API"
39
+ - "Format is comma-separated feature names: RAI_EXPERIMENTAL=workflow,mcp"
40
+ - "Unknown feature names emit a warning to stderr but do not cause an error"
41
+ - "Feature flag checks must be O(1) — flags are parsed once at startup into
42
+ a frozen Set"
43
+ - "When a gated command is invoked without its flag enabled, the error message
44
+ must name the required flag: 'rai workflow is experimental. Enable with:
45
+ RAI_EXPERIMENTAL=workflow'"
46
+ - "Feature flags must not affect the behaviour of stable (non-experimental)
47
+ commands"
48
+ - "All feature flag names must be snake_case, matching the design document
49
+ name they gate"
50
+ - "Feature flags are removed (replaced with unconditional code) when the
51
+ feature is promoted to stable in a release"
52
+ - "The list of known experimental features must be maintained in a single
53
+ constant (KNOWN_FLAGS) for discoverability"
54
+ - "This design governs feature visibility gating. Deprecation of existing
55
+ features is governed by backward_compatibility.yml. Configuration
56
+ compilation is governed by compiler.yml"
57
+ #
58
+ acceptance_criteria:
59
+ - "RosettAi::FeatureFlags.enabled?(:workflow) returns true when
60
+ RAI_EXPERIMENTAL includes 'workflow'"
61
+ - "RosettAi::FeatureFlags.enabled?(:workflow) returns false when
62
+ RAI_EXPERIMENTAL is unset or does not include 'workflow'"
63
+ - "Unknown flag names in RAI_EXPERIMENTAL emit a warning to stderr"
64
+ - "Gated CLI commands display an actionable error when invoked without
65
+ the required flag"
66
+ - "RosettAi::FeatureFlags.all_enabled returns the Set of currently active flags"
67
+ - "RosettAi::FeatureFlags::KNOWN_FLAGS contains all recognized flag names"
68
+ - "Stable commands are unaffected by RAI_EXPERIMENTAL values"
69
+ - "Flag parsing happens once at module load time, not on every check"
70
+ - "Exit code 1 when a gated command is invoked without its flag"
71
+ #
72
+ examples:
73
+ - scenario: "User runs `rai workflow run ci.yml` without the workflow flag"
74
+ expected: |
75
+ Error: "rai workflow is experimental and not enabled.
76
+ Enable with: RAI_EXPERIMENTAL=workflow bin/raictl workflow run ci.yml"
77
+ Exit code 1.
78
+ not: |
79
+ Command runs with unexpected behaviour. Error message does not mention
80
+ how to enable the feature. Exit code 0.
81
+ - scenario: "Developer enables workflow and mcp features"
82
+ expected: |
83
+ RAI_EXPERIMENTAL=workflow,mcp bin/raictl workflow run ci.yml succeeds.
84
+ bin/raictl mcp status succeeds. Other experimental features remain hidden.
85
+ not: "Enabling one feature enables all experimental features."
86
+ - scenario: "User sets RAI_EXPERIMENTAL=workflow,nonexistent"
87
+ expected: |
88
+ Warning on stderr: "Unknown experimental feature: nonexistent.
89
+ Known features: workflow, mcp, doctor, comply."
90
+ Workflow feature is enabled normally despite the unknown flag.
91
+ not: |
92
+ Error that prevents any command from running. Unknown flag silently
93
+ ignored without warning.
94
+ - scenario: "Feature is promoted to stable in v1.2.0"
95
+ expected: |
96
+ Feature flag guard is removed from the command. RAI_EXPERIMENTAL=workflow
97
+ has no effect (feature is always available). KNOWN_FLAGS no longer lists it.
98
+ CHANGELOG documents: "workflow command is now stable (no longer requires
99
+ RAI_EXPERIMENTAL)."
100
+ not: |
101
+ Flag guard remains in code. Users must set RAI_EXPERIMENTAL forever.
102
+ Promotion is not documented.
103
+ #
104
+ anti_patterns:
105
+ - "Database-backed or remote feature flag services (overkill for CLI tool)"
106
+ - "Per-user feature flags (rosett-ai is a single-user CLI)"
107
+ - "Runtime feature toggling (flags are resolved once at startup)"
108
+ - "Config file-based flags (environment variable is the only source)"
109
+ - "Enabling all experimental features with a single flag like 'all'
110
+ (explicit opt-in per feature prevents accidental exposure)"
111
+ - "Checking ENV on every call instead of parsing once into a frozen Set"
112
+ - "Using feature flags for A/B testing or analytics"
113
+ - "Leaving flag guards in code after a feature is promoted to stable"
114
+ #
115
+ gui_notes: |
116
+ Document interactions (cross-references):
117
+
118
+ 1. backward_compatibility.yml: deprecation warnings for existing features
119
+ and feature flags for new features are complementary mechanisms.
120
+
121
+ 2. error_handling.yml: gated command errors follow the structured error
122
+ hierarchy with what/why/fix pattern and exit code 1.
123
+
124
+ 3. architecture.yml: feature flags follow the minimal-dependency principle
125
+ (stdlib only, no external gems).
126
+
127
+ Module structure:
128
+
129
+ lib/rosett_ai/feature_flags.rb — Single module with class methods
130
+ KNOWN_FLAGS constant, .enabled?, .all_enabled,
131
+ .gate! (raises if feature not enabled)
132
+ #
133
+ preferences:
134
+ language: ruby
135
+ patterns:
136
+ - "Frozen Set for O(1) membership checks"
137
+ - "Module with class methods (no instances needed)"
138
+ - "Single constant for known flags (KNOWN_FLAGS)"
139
+ - "Parse-once at module load time"
140
+ testing: rspec with ENV stubbing for flag combinations, unknown flag
141
+ warnings, gated command errors, and promotion (flag removal) scenarios
142
+ gems: []
@@ -0,0 +1,165 @@
1
+ ---
2
+ name: git_hooks
3
+ domain: core
4
+ version: 0.1.0
5
+ status: implemented
6
+ priority: 3
7
+ author: hugo
8
+ created_at: "2026-03-16"
9
+ modified_at: "2026-03-16"
10
+ modified_by: claude
11
+ depends_on:
12
+ - architecture
13
+ - compiler
14
+ - security
15
+ - error_handling
16
+ - workflow
17
+ - monitoring_observability
18
+ #
19
+ intent: >-
20
+ Provide configurable, opt-in git hook integration that runs rai commands
21
+ at key points in the git lifecycle — keeping compiled output, validation
22
+ state, and configuration in sync with the working tree automatically. Hooks
23
+ are declared in the project's .rosett-ai/config.yml (not installed imperatively),
24
+ coexist with existing hook managers (overcommit, husky, lefthook), and
25
+ respect the user's choice to enable or disable them per project.
26
+ #
27
+ constraints:
28
+ - "Git hook integration must be opt-in — never installed automatically by
29
+ `rai init` without explicit user consent"
30
+ - "Hook definitions must be declarative YAML in the project root config
31
+ (.rosett-ai/config.yml, hooks section), not imperatively installed shell scripts"
32
+ - "All hook commands must use array-form execution — no string interpolation
33
+ or shell expansion"
34
+ - "Hooks must coexist with existing hook managers — rosett-ai writes to its own
35
+ hook script and chains to any pre-existing hook via the GIT_HOOK_CHAIN
36
+ convention"
37
+ - "Hook execution must be silent on success (exit 0, no stdout) and
38
+ informative on failure (structured error to stderr)"
39
+ - "Hook failures must never corrupt the git operation — pre-commit failures
40
+ block the commit, but post-checkout failures must not block checkout"
41
+ - "Hooks must respect RAI_SKIP_HOOKS=1 to allow emergency bypass without
42
+ removing the hook installation"
43
+ - "Hook installation must be reversible — `rai hooks uninstall` restores
44
+ the pre-rosett-ai hook state exactly"
45
+ - "Hooks must complete within a configurable timeout (default 30 seconds) to
46
+ prevent blocking interactive git workflows"
47
+ - "Hook scripts must be POSIX sh for portability — they invoke rosett-ai as an
48
+ external command, not as inline Ruby. This is the same infrastructure
49
+ exception as CI/packaging Bash scripts (per language purity rules)"
50
+ - "Hooks must log their execution to the Rosett-AI audit trail when
51
+ monitoring_observability is enabled"
52
+ - "The set of supported git hooks is limited to pre-commit, post-commit,
53
+ post-checkout, post-merge, and pre-push — no server-side hooks"
54
+ - "This design governs git hook integration (automated reactions to git
55
+ lifecycle events). Multi-step workflow orchestration (independent of git)
56
+ is governed by workflow.yml. A hook may trigger a workflow, but hooks
57
+ and workflows are independently defined"
58
+ #
59
+ acceptance_criteria:
60
+ - "`rai hooks install` reads .rosett-ai/config.yml and installs configured
61
+ hooks to .git/hooks/"
62
+ - "`rai hooks uninstall` removes rai hooks and restores any previous
63
+ hook scripts"
64
+ - "`rai hooks list` shows installed hooks with their configured commands
65
+ using TTY-aware output (table when interactive, plain text when piped)"
66
+ - "`rai hooks status` shows which hooks are installed and whether they
67
+ match the current config, using TTY-aware output"
68
+ - "pre-commit hook runs `rai validate` and blocks commit on failure"
69
+ - "post-checkout hook runs `rai compile` and reports if compilation changes
70
+ any output files"
71
+ - "post-merge hook runs `rai compile` to sync output with merged changes"
72
+ - "pre-push hook runs `rai validate --strict` and blocks push on failure"
73
+ - "RAI_SKIP_HOOKS=1 bypasses all rai hooks for the current git operation"
74
+ - "Hook timeout terminates the Rosett-AI process after the configured limit"
75
+ - "Existing hooks (overcommit, husky) continue to function when rai hooks
76
+ are installed alongside them"
77
+ - "Hook configuration changes in .rosett-ai/config.yml are detected by
78
+ `rai hooks status` as drift"
79
+ - "`rai hooks install` detects existing hooks (including symlinks from
80
+ overcommit/husky) and chains correctly without breaking them"
81
+ - "Exit code 0 on success, 1 on hook execution failure, 3 on missing
82
+ or invalid hook configuration, 5 on missing rosett-ai dependency"
83
+ - "Hooks are complementary to workflows — hooks automate git lifecycle
84
+ events, workflows orchestrate multi-step sequences independent of git"
85
+ #
86
+ examples:
87
+ - scenario: "Developer enables pre-commit validation in a project"
88
+ expected: |
89
+ .rosett-ai/config.yml contains `hooks: { pre_commit: ["validate"] }`.
90
+ `rai hooks install` writes .git/hooks/pre-commit that invokes
91
+ `rai validate`. Next `git commit` runs validation first.
92
+ not: |
93
+ Hook is installed globally affecting all repositories. Hook is a
94
+ raw shell script that must be manually maintained.
95
+ - scenario: "Developer switches branches with different behaviour configs"
96
+ expected: |
97
+ post-checkout hook runs `rai compile`. If compiled output changes,
98
+ a brief message is printed: "rosett-ai: recompiled 3 rules for branch
99
+ feature/x". If nothing changed, no output.
100
+ not: |
101
+ Stale compiled rules from the previous branch remain in place.
102
+ Developer must manually remember to run `rai compile`.
103
+ - scenario: "Project uses overcommit for linting and rosett-ai for config validation"
104
+ expected: |
105
+ Both hook managers coexist. rosett-ai's pre-commit script detects the
106
+ existing overcommit hook, chains to it after running rosett-ai's own
107
+ checks. Both run on every commit.
108
+ not: |
109
+ raictl overwrites overcommit's pre-commit hook. Linting stops working.
110
+ - scenario: "Hook takes too long during pre-commit"
111
+ expected: |
112
+ After 30 seconds (or configured timeout), the hook process is
113
+ terminated. Commit is blocked with message: "rosett-ai: pre-commit
114
+ timed out after 30s. Run `rai validate` manually or set
115
+ RAI_SKIP_HOOKS=1."
116
+ not: |
117
+ Developer waits indefinitely. Only option is Ctrl-C.
118
+ #
119
+ anti_patterns:
120
+ - "Installing hooks without explicit user opt-in"
121
+ - "Using string-form shell execution in hook scripts"
122
+ - "Overwriting existing hook managers instead of chaining"
123
+ - "Silent failures in post-checkout or post-merge hooks that hide errors"
124
+ - "Hooks that require network access and block offline git workflows"
125
+ - "Coupling hook logic to a specific hook manager's internal format"
126
+ - "Hardcoding hook commands instead of reading from declarative config"
127
+ - "Server-side hooks that run on remote repositories"
128
+ - "Assuming all hook managers use the same chaining mechanism — detect
129
+ symlinks, wrapper scripts, and direct hooks individually"
130
+ #
131
+ gui_notes: |
132
+ Document interactions (cross-references):
133
+
134
+ 1. workflow.yml: hooks may trigger workflows but are independently defined.
135
+ Hooks automate git lifecycle reactions; workflows orchestrate multi-step
136
+ sequences independent of git.
137
+
138
+ 2. compiler.yml: post-checkout and post-merge hooks invoke `rai compile`
139
+ to keep compiled output in sync with the working tree.
140
+
141
+ 3. security.yml: array-form execution for hook commands, no string
142
+ interpolation or shell expansion.
143
+
144
+ 4. error_handling.yml: hook failures emit structured errors to stderr
145
+ (what/why/fix format). Exit codes follow the error hierarchy.
146
+
147
+ 5. monitoring_observability.yml: hooks log execution to the telemetry
148
+ system when enabled.
149
+
150
+ 6. architecture.yml: hook configuration lives in .rosett-ai/config.yml, the
151
+ project root config managed by `rai init`.
152
+ #
153
+ preferences:
154
+ language: ruby
155
+ patterns:
156
+ - "Declarative hook configuration in YAML"
157
+ - "Hook chaining convention (GIT_HOOK_CHAIN)"
158
+ - "Timeout-wrapped execution"
159
+ - "POSIX sh hook scripts (infrastructure exception)"
160
+ - "TTY-aware output (TtyHelper)"
161
+ testing: rspec with git repository fixtures, hook chaining scenarios,
162
+ timeout handling, RAI_SKIP_HOOKS bypass, overcommit/husky coexistence,
163
+ and drift detection tests
164
+ gems:
165
+ - thor