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,352 @@
1
+ ---
2
+ name: scope_hierarchy
3
+ domain: core
4
+ version: 1.0.0
5
+ status: implemented
6
+ priority: 2
7
+ author: hugo
8
+ created_at: "2026-03-23"
9
+ modified_at: "2026-04-14"
10
+ modified_by: claude opus-4.6
11
+ depends_on:
12
+ - architecture
13
+ - security
14
+ - error_handling
15
+ #
16
+ intent: |
17
+ Define the three-level scope hierarchy that makes rosett-ai directory-aware.
18
+ Currently, all commands (compile, validate, design) operate on rosett-ai's own
19
+ conf/ directory regardless of where the user invokes them. This design
20
+ introduces a Hiera-like scope model where configuration sources are
21
+ discovered based on the user's working directory, merged according to
22
+ configurable strategies, and compiled to scope-appropriate output locations.
23
+
24
+ The three scope levels are:
25
+
26
+ 1. Global (~/.config/rosett-ai/conf/) — user-wide defaults following XDG
27
+ Base Directory Specification. Applied everywhere unless overridden.
28
+
29
+ 2. Local (<group-dir>/.rosett-ai/conf/) — multi-project workspace defaults.
30
+ A local scope groups related projects (e.g. a monorepo or a team
31
+ workspace) under shared configuration. Detected by a .rosett-ai/ marker
32
+ directory that has child directories also containing .rosett-ai/ markers.
33
+
34
+ 3. Project (<project-dir>/.rosett-ai/conf/) — project-specific overrides.
35
+ The most specific scope. A project scope is a leaf .rosett-ai/ directory
36
+ (no children with their own .rosett-ai/ markers).
37
+
38
+ The merge order is global -> local -> project: each successive layer
39
+ overrides the previous one. Merge strategies are configurable per key.
40
+
41
+ Without this design, rosett-ai cannot serve users who work across multiple
42
+ projects with shared conventions. Every project must duplicate global
43
+ defaults, and there is no way to express workspace-level settings that
44
+ apply to a group of related projects. The scope hierarchy solves this
45
+ by making configuration inheritance explicit, configurable, and auditable.
46
+
47
+ This design is the authoritative specification for scope semantics.
48
+ All other design documents that reference scopes (compiler.yml,
49
+ behaviour_composition.yml, engine_architecture.yml, project_management.yml,
50
+ architecture.yml) defer to this document for scope definitions, detection
51
+ algorithm, and merge behaviour.
52
+ #
53
+ constraints:
54
+ - "Exactly three scope levels exist: global, local, project — no more, no fewer"
55
+ - "Global scope source directory is ~/.config/rosett-ai/conf/ (XDG_CONFIG_HOME/rosett-ai/conf/)"
56
+ - "Local scope source directory is <group-dir>/.rosett-ai/conf/ where <group-dir>
57
+ is detected by walking up from RAI_ORIGINAL_PWD"
58
+ - "Project scope source directory is <project-dir>/.rosett-ai/conf/ where
59
+ <project-dir> is the nearest directory containing a .rosett-ai/ marker"
60
+ - "Scope detection walks up from RAI_ORIGINAL_PWD (or Dir.pwd if unset),
61
+ finding the nearest .rosett-ai/ marker first"
62
+ - "A .rosett-ai/ directory is classified as local (workspace) if it has child
63
+ directories that also contain .rosett-ai/ markers; otherwise it is project"
64
+ - "Merge order is always global -> local -> project (lower scope wins)"
65
+ - "Merge strategies are configurable per key in .rosett-ai/config.yml under
66
+ a merge_strategies key"
67
+ - "Supported merge strategies: deep_merge (default for hashes), replace
68
+ (default for scalars), array_union (combine + deduplicate), first_found
69
+ (first non-nil from most-specific scope)"
70
+ - "Default merge strategy when unconfigured: replace for scalar values,
71
+ deep_merge for hash values, array_union for array values"
72
+ - "When no .rosett-ai/ marker is found in the directory tree, only the global
73
+ scope is active — this is not an error"
74
+ - "When no global config exists (~/.config/rosett-ai/ absent), commands work
75
+ with whatever scopes are available — global is not required"
76
+ - "At most one local scope and one project scope can be active at any time.
77
+ Nested workspaces (a .rosett-ai/ marker whose parent also has a .rosett-ai/ marker
78
+ with children) are resolved by nearest-wins: the deepest workspace-level
79
+ marker is selected as local, and any higher markers are ignored"
80
+ - "CLI flags --global, --local, --project select a scope level. These
81
+ flags are mutually exclusive — specifying more than one is an error
82
+ (exit 2). Each level includes all scopes above it: --global uses only
83
+ global sources; --local merges global+local; --project merges
84
+ global+local+project. Output is written to the selected level's output
85
+ directory. Without flags, scope is auto-detected from working directory"
86
+ - "Scope detection must not traverse above the filesystem root or into
87
+ unreadable directories"
88
+ - "All YAML files in scope source directories are parsed with YAML.safe_load
89
+ (per security.yml constraints)"
90
+ - "Scope resolution result must be deterministic for a given directory tree"
91
+ - "Each engine declares per-scope output directories in its target profile.
92
+ Global output uses an absolute path (e.g. ~/.claude/rules/). Local and
93
+ project outputs use a relative path (e.g. .claude/rules/) resolved against
94
+ the scope directory by the compiler"
95
+ - "Scope-related errors use the what/why/fix format from error_handling.yml"
96
+ #
97
+ acceptance_criteria:
98
+ - "ScopeResolver.resolve(working_dir) returns a ScopeResult with global,
99
+ local (optional), and project (optional) source directories"
100
+ - "When invoked from a project directory, all active scopes are discovered
101
+ and merged in order global -> local (if present) -> project"
102
+ - "When invoked from a directory with no .rosett-ai/ marker above it, only
103
+ the global scope is active and returned"
104
+ - "deep_merge strategy recursively merges hashes from all active scopes,
105
+ with lower (more-specific) scope keys winning on conflict"
106
+ - "replace strategy uses the value from the most-specific active scope,
107
+ ignoring all higher scopes"
108
+ - "array_union strategy combines arrays from all active scopes and
109
+ deduplicates entries, preserving order (most-specific scope first)"
110
+ - "first_found strategy returns the first non-nil value scanning from
111
+ project -> local -> global"
112
+ - "bin/raictl compile --global compiles only global-scope sources to
113
+ global output directories"
114
+ - "bin/raictl compile --local compiles merged global+local sources to
115
+ local output directories"
116
+ - "bin/raictl compile --project compiles merged global+local+project
117
+ sources to project output directories"
118
+ - "bin/raictl compile (no flag) auto-detects scope from working directory
119
+ and compiles to the appropriate output location"
120
+ - "bin/raictl compile --simulate --verbose shows scope-resolved source
121
+ directories and target output paths before showing diffs"
122
+ - "bin/raictl validate operates on sources from the auto-detected scope"
123
+ - "Merge strategy configuration in .rosett-ai/config.yml is validated against
124
+ scope_hierarchy_schema.json"
125
+ - "Scope detection terminates at filesystem root without error"
126
+ - "Exit code 0 on success, 2 on scope configuration error, 3 on missing
127
+ required scope (when --local or --project is used but no marker found)"
128
+ #
129
+ examples:
130
+ - scenario: "User runs bin/raictl compile from ~/projects/acme-api/"
131
+ expected: |
132
+ ScopeResolver finds:
133
+ project: ~/projects/acme-api/.rosett-ai/conf/
134
+ local: ~/projects/.rosett-ai/conf/ (if ~/projects/.rosett-ai/ exists and has children with .rosett-ai/)
135
+ global: ~/.config/rosett-ai/conf/
136
+ Merges global -> local -> project. Compiles to project-scope output
137
+ directories (e.g. ~/projects/acme-api/.claude/rules/ for Claude engine).
138
+ not: "Compiles from rosett-ai's own conf/ directory. Ignores working directory."
139
+ - scenario: "User runs bin/raictl compile --global"
140
+ expected: |
141
+ Only global scope sources (~/.config/rosett-ai/conf/) are compiled.
142
+ Output goes to global output directories (e.g. ~/.claude/rules/).
143
+ Local and project scopes are ignored even if .rosett-ai/ markers exist
144
+ in the current directory tree.
145
+ not: "All scopes are merged. Project-specific rules appear in global output."
146
+ - scenario: "User runs bin/raictl compile from /tmp (no .rosett-ai/ anywhere)"
147
+ expected: |
148
+ Only global scope is active. Compiles global sources to global output.
149
+ No warning about missing local/project scopes (this is normal).
150
+ not: "Error: no .rosett-ai/ found. Compilation refuses to run."
151
+ - scenario: "Two behaviours define the same key with different merge strategies"
152
+ expected: |
153
+ .rosett-ai/config.yml specifies:
154
+ merge_strategies:
155
+ editor_settings: deep_merge
156
+ allowed_tools: array_union
157
+ Global defines editor_settings: { theme: dark }.
158
+ Project defines editor_settings: { font_size: 14 }.
159
+ Merged result: { theme: dark, font_size: 14 }.
160
+ not: "Project replaces entire editor_settings hash."
161
+ - scenario: "User runs bin/raictl compile --project but no .rosett-ai/ exists"
162
+ expected: |
163
+ Error (exit 3): 'No project scope found: no .rosett-ai/ marker in directory
164
+ tree from /current/dir. Run `rai init --project` to create one, or
165
+ omit --project to use auto-detection.'
166
+ not: "Silent fallback to global scope. Compiles without indicating scope mismatch."
167
+ - scenario: "Local scope has a .rosett-ai/config.yml with merge_strategies"
168
+ expected: |
169
+ Merge strategies from local config apply to the local+project merge.
170
+ Global config may also declare merge_strategies; the most-specific
171
+ merge_strategies configuration wins (project > local > global).
172
+ not: "Only project-level merge_strategies are respected."
173
+ - scenario: "Engine declares per-scope output directories"
174
+ expected: |
175
+ Claude engine target profile contains:
176
+ output_dirs:
177
+ global: ~/.claude/rules/
178
+ scoped: .claude/rules/
179
+ Global output uses the absolute path. For local and project scopes,
180
+ the compiler resolves the relative path against the scope directory:
181
+ local: ~/projects/.claude/rules/
182
+ project: ~/projects/acme-api/.claude/rules/
183
+ not: "All output goes to ~/.claude/rules/ regardless of scope."
184
+ - scenario: "User runs bin/raictl validate from a project directory"
185
+ expected: |
186
+ Validates sources from all active scopes (global, local, project).
187
+ Reports validation results grouped by scope:
188
+ [global] conf/behaviour/security.yml: valid
189
+ [project] conf/behaviour/api_rules.yml: 2 errors
190
+ not: "Only validates rosett-ai's own conf/ directory."
191
+ #
192
+ anti_patterns:
193
+ - "Hardcoding source or output directories instead of resolving from scope"
194
+ - "Assuming a single fixed source directory for all commands"
195
+ - "Merging scopes in wrong order (project before global)"
196
+ - "Treating missing scopes as errors (only --local/--project flags require presence)"
197
+ - "Scope detection that follows symlinks across filesystem boundaries"
198
+ - "Merge strategies that silently drop data without user visibility"
199
+ - "Scope resolution that depends on environment variables other than
200
+ RAI_ORIGINAL_PWD and XDG_CONFIG_HOME"
201
+ - "Caching scope resolution results across commands (directory tree can change)"
202
+ #
203
+ gui_notes: |
204
+ Document interactions (cross-references):
205
+
206
+ 1. architecture.yml: scope hierarchy is an architectural principle.
207
+ Architecture declares scope-first as a constraint; this document
208
+ defines the full specification.
209
+
210
+ 2. compiler.yml: compilation is scope-aware. Compiler resolves source
211
+ directories from the active scope before operating.
212
+
213
+ 3. behaviour_composition.yml: composition uses the scope hierarchy for
214
+ layering behaviours. This document defines the scope model; composition
215
+ defines the merge and priority rules within that model.
216
+
217
+ 4. engine_architecture.yml: engines declare per-scope output directories
218
+ in their target profiles. This document defines the scope levels;
219
+ engines map each level to tool-native paths.
220
+
221
+ 5. project_management.yml: project lifecycle commands are scope-aware.
222
+ raictl init creates scope markers; rai project status reports scope.
223
+
224
+ 6. security.yml: all YAML parsing in scope directories uses YAML.safe_load.
225
+ Path traversal in scope detection must be validated.
226
+
227
+ 7. error_handling.yml: scope errors (missing marker, invalid config)
228
+ follow the what/why/fix format with dedicated exit codes.
229
+
230
+ Scope detection algorithm (pseudocode):
231
+
232
+ def resolve(start_dir):
233
+ global = XDG_CONFIG_HOME/rosett-ai/conf/ or ~/.config/rosett-ai/conf/
234
+ current = start_dir
235
+ markers = []
236
+
237
+ # Phase 1: collect all .rosett-ai/ markers from root to start_dir
238
+ while current != '/':
239
+ if current/.rosett-ai exists:
240
+ markers.prepend(current)
241
+ current = parent(current)
242
+
243
+ if markers.empty:
244
+ return ScopeResult(global: global, local: nil, project: nil)
245
+
246
+ # Phase 2: nearest marker (deepest) is the project candidate
247
+ project_candidate = markers.last
248
+
249
+ # Phase 3: scan remaining markers upward for a local (workspace) scope
250
+ # A marker is local if it has child directories that also contain
251
+ # .rosett-ai/ markers (i.e. it groups multiple projects)
252
+ local_candidate = nil
253
+ markers[0..-2].reverse_each do |dir|
254
+ if dir has child directories containing .rosett-ai/ markers:
255
+ local_candidate = dir
256
+ break
257
+ end
258
+ end
259
+
260
+ if local_candidate:
261
+ return ScopeResult(
262
+ global: global,
263
+ local: local_candidate/.rosett-ai/conf/,
264
+ project: project_candidate/.rosett-ai/conf/
265
+ )
266
+
267
+ # Single marker — check if it is local (workspace) or project (leaf)
268
+ if project_candidate has child directories containing .rosett-ai/ markers:
269
+ # User is at workspace level, not inside a child project
270
+ return ScopeResult(
271
+ global: global,
272
+ local: project_candidate/.rosett-ai/conf/,
273
+ project: nil
274
+ )
275
+ else:
276
+ return ScopeResult(
277
+ global: global,
278
+ local: nil,
279
+ project: project_candidate/.rosett-ai/conf/
280
+ )
281
+
282
+ Directory layout example:
283
+
284
+ ~/.config/rosett-ai/ # Global scope
285
+ └── conf/
286
+ └── behaviour/
287
+ └── security.yml # User-wide security defaults
288
+
289
+ ~/projects/ # Local scope (workspace)
290
+ ├── .rosett-ai/
291
+ │ ├── config.yml # merge_strategies, workspace settings
292
+ │ └── conf/
293
+ │ └── behaviour/
294
+ │ └── team_style.yml # Shared across projects in workspace
295
+ ├── acme-api/ # Project scope
296
+ │ ├── .rosett-ai/
297
+ │ │ ├── config.yml # project_name, default_engine
298
+ │ │ └── conf/
299
+ │ │ └── behaviour/
300
+ │ │ └── api_rules.yml # Project-specific rules
301
+ │ └── src/
302
+ └── acme-web/ # Another project in same workspace
303
+ ├── .rosett-ai/
304
+ │ └── conf/
305
+ │ └── behaviour/
306
+ │ └── web_rules.yml
307
+ └── src/
308
+ #
309
+ preferences:
310
+ language: ruby
311
+ patterns:
312
+ - "ScopeResolver with upward directory traversal"
313
+ - "ScopeResult value object (global, local, project)"
314
+ - "Strategy pattern for merge strategies"
315
+ - "XDG Base Directory compliance"
316
+ - "Marker-based scope detection (.rosett-ai/)"
317
+ - "Hiera-like configurable merge"
318
+ testing: rspec with directory tree fixtures, scope detection edge cases
319
+ (no markers, nested markers, symlinks), merge strategy property tests,
320
+ CLI flag override tests, and scope-aware compilation integration tests
321
+ gems:
322
+ - json_schemer
323
+ - thor
324
+
325
+ implementation_notes: |
326
+ v1.2.0 implementation diverged from the original 3-level design:
327
+
328
+ 1. ScopeResolver uses a 4-level model: global, organisation, project, local.
329
+ The "organisation" level was added to support multi-org workspaces.
330
+ SCOPE_ORDER = ['global', 'organisation', 'project', 'local'].
331
+
332
+ 2. ScopeResolver.resolve() returns a scope name string
333
+ ('global'/'organisation'/'project'/'local') for a given file path,
334
+ not a ScopeResult value object. The ScopeResult contract from the
335
+ design is not yet implemented.
336
+
337
+ 3. Workspace (local) detection via child-marker walking is not yet
338
+ implemented. ProjectContext.detect_project_root() walks upward
339
+ looking for .rosett-ai/ but treats all markers as "project".
340
+
341
+ 4. Merge strategies: first_wins (default), deep_merge, array_union
342
+ are implemented. "replace" and "first_found" from design are not.
343
+ Per-key merge strategy configuration from .rosett-ai/config.yml
344
+ is not yet implemented.
345
+
346
+ 5. CompilationPipeline accepts scope: :global or :project (no :local).
347
+ CLI flags --global/--local/--project not yet integrated.
348
+
349
+ 6. Per-scope output_dirs not in TargetProfile — uses single output_dir.
350
+
351
+ These are known gaps. The 4-level model is the intentional direction;
352
+ the design doc's 3-level model should be updated to match.
@@ -0,0 +1,115 @@
1
+ ---
2
+ name: security
3
+ domain: security
4
+ version: 1.2.0
5
+ status: implemented
6
+ priority: 1
7
+ author: hugo
8
+ created_at: "2026-02-18"
9
+ modified_at: "2026-03-17"
10
+ modified_by: claude
11
+ depends_on: []
12
+ #
13
+ intent: |
14
+ Establish security as the foundation layer of Rosett-AI. Every line of code written
15
+ after this document is adopted must follow these constraints. Retrofitting
16
+ security is 10x more expensive than building it in. This document defines hard
17
+ rules, required tooling, and safe coding patterns that apply to ALL code in
18
+ the project — core, TUI, GUI, compilers, and tests.
19
+ #
20
+ constraints:
21
+ - Never use YAML.load — always YAML.safe_load with explicit permitted_classes
22
+ - Never interpolate user input into system() calls — use array form exclusively
23
+ - Never write files outside whitelisted directories (~/.claude/, project .claude/, ~/.config/rosett-ai/)
24
+ - All file writes must set restrictive permissions (0644 for files, 0755 for directories)
25
+ - Secrets files must use 0600 permissions
26
+ - Never log, display, or include in error messages any secrets, API keys, or tokens
27
+ - All external input (YAML, JSON, CLI arguments, environment variables) must be validated before use
28
+ - Tempfiles must use Tempfile.new with restrictive permissions and must be cleaned up in ensure blocks
29
+ - No information conveyed by colour alone (accessibility and security overlap)
30
+ - Destructive operations require explicit user confirmation before execution
31
+ - All dependencies must be audited for known CVEs before release
32
+ - No eval, instance_eval, or class_eval on user-supplied input
33
+ - File paths must be validated with File.expand_path and checked against whitelists
34
+ - YAML input must be bounded — max file size (1 MB), max nesting depth (10), max key count (1000)
35
+ - All user-authored content must be stripped of ANSI escape sequences and control characters before display in TUI/GUI
36
+ - Identifiers and filenames from external input must be NFC-normalized (Unicode) at input boundaries
37
+ - Secrets resolution order is ENV variable > system keyring (libsecret/kwallet) > secrets file (0600) — never write secrets to disk by default
38
+ #
39
+ acceptance_criteria:
40
+ - bundler-audit runs in CI and blocks merge on any known CVE
41
+ - ruby_audit runs in CI and blocks merge on Ruby stdlib vulnerabilities
42
+ - RuboCop security cops are enabled and enforced (no violations allowed)
43
+ - No instance of YAML.load exists in codebase (only YAML.safe_load)
44
+ - No string-interpolated system() calls exist in codebase
45
+ - All file write operations use explicit permission setting
46
+ - CI pipeline rejects code that violates any security constraint
47
+ - Custom RuboCop cop flags unsafe patterns (YAML.load, interpolated system calls)
48
+ - YAML files exceeding 1 MB, 10 levels nesting, or 1000 keys are rejected with clear error
49
+ - TUI output containing ANSI escape sequences from YAML content is sanitized before rendering
50
+ - Filenames and identifiers are NFC-normalized (verified by test with NFD input producing NFC output)
51
+ - Secrets are never written to disk unless user explicitly configures a secrets file
52
+ #
53
+ examples:
54
+ - scenario: "Code reads a user-provided YAML config file"
55
+ expected: "Uses YAML.safe_load(content, permitted_classes: [Date, Time]) with explicit class allowlist"
56
+ not: "Uses YAML.load(content) which allows arbitrary object instantiation"
57
+ - scenario: "Code executes a git command with a user-provided branch name"
58
+ expected: "system('git', 'checkout', '--', branch_name) using array form"
59
+ not: "system(\"git checkout #{branch_name}\") which allows shell injection"
60
+ - scenario: "Code writes a compiled behaviour file to disk"
61
+ expected: "Validates output path is within ~/.claude/rules/, writes with File.open(path, 'w', 0644)"
62
+ not: "Writes to arbitrary path without validation or permission setting"
63
+ - scenario: "An API key is needed for the adopt command"
64
+ expected: "Resolved via ENV['ANTHROPIC_API_KEY'] > system keyring > secrets file (0600). Never displayed in output."
65
+ not: "Hardcoded in source, logged in verbose mode, written to disk unprompted, or stored in world-readable config"
66
+ - scenario: "bundler-audit finds a CVE in a dependency"
67
+ expected: "CI pipeline fails, merge is blocked, developer must update or justify exception"
68
+ not: "Warning is ignored, code merges with known vulnerability"
69
+ - scenario: "A behaviour YAML file contains ANSI escape codes in a rule description"
70
+ expected: |
71
+ Control characters and escape sequences are stripped before TUI rendering.
72
+ 'Rule description: clean text here' is displayed. Log warning in development mode.
73
+ not: "Terminal is cleared, title bar is changed, or garbled output is shown."
74
+ - scenario: "A 50 MB YAML file is provided as a behaviour config"
75
+ expected: "Rejected before parsing: 'File exceeds maximum size (1 MB): 50.0 MB'. No memory exhaustion."
76
+ not: "Parser attempts to load 50 MB into memory. Application hangs or crashes."
77
+ - scenario: "A filename contains Unicode NFD characters (e.g. e + combining acute)"
78
+ expected: "Filename is NFC-normalized at input boundary. Stored and compared as single precomposed character."
79
+ not: "Two visually identical filenames coexist. String comparisons fail silently."
80
+ - scenario: "User runs bin/raictl adopt and needs an API key"
81
+ expected: |
82
+ Checks ENV['ANTHROPIC_API_KEY'] first. If absent, checks system keyring.
83
+ If absent, checks ~/.config/rosett-ai/secrets.yml (0600). If no key found,
84
+ prompts user with instructions to set ENV variable.
85
+ not: "Prompts user to create a plaintext secrets file. Writes API key to disk unprompted."
86
+ #
87
+ anti_patterns:
88
+ - Using YAML.load for any reason (even when input seems trusted)
89
+ - String interpolation in shell commands (system, backticks, %x)
90
+ - Writing files without explicit permission bits
91
+ - Storing secrets in version-controlled files
92
+ - Silencing or skipping security audit failures in CI
93
+ - Using eval/instance_eval/class_eval on dynamic input
94
+ - Catching and swallowing exceptions without logging (hides security events)
95
+ - Trusting file paths from CLI arguments without canonicalization
96
+ - Rendering user-authored YAML content in TUI without stripping control characters
97
+ - Parsing unbounded YAML input without size or depth limits
98
+ - Writing secrets to disk as the default or first-choice storage method
99
+ - Comparing filenames or identifiers without Unicode normalization
100
+ #
101
+ preferences:
102
+ language: ruby
103
+ gems:
104
+ - bundler-audit
105
+ - ruby_audit
106
+ - rubocop
107
+ - rubocop-performance
108
+ - rubocop-rspec
109
+ - reek
110
+ - flay
111
+ patterns:
112
+ - input_validation_at_boundaries
113
+ - fail_fast_on_invalid_input
114
+ - principle_of_least_privilege
115
+ testing: rspec with security-focused fixtures
@@ -0,0 +1,85 @@
1
+ ---
2
+ name: session_retrospective
3
+ domain: operations
4
+ version: 1.0.0
5
+ status: draft
6
+ priority: 6
7
+ author: claude
8
+ created_at: '2026-03-24'
9
+ modified_at: '2026-03-24'
10
+ modified_by: claude
11
+ depends_on:
12
+ - testing
13
+ - ci_pipeline
14
+
15
+ intent: |
16
+ Define a repeatable methodology for AI session self-evaluation within the Rosett-AI
17
+ ecosystem. When Claude Code completes a multi-session campaign (coverage push,
18
+ feature branch, refactoring), it must produce a structured retrospective that
19
+ identifies what went well, what went poorly, and what concrete process changes
20
+ would prevent the same failures from recurring.
21
+
22
+ This document exists because the coverage push campaign (2026-03-20 through
23
+ 2026-03-24) demonstrated that unchecked agent delegation, insufficient API
24
+ verification, and poor resource management can waste significant human and
25
+ compute time. The retrospective methodology captures these lessons in a
26
+ machine-readable format that persists across sessions.
27
+
28
+ constraints:
29
+ - Retrospectives must be honest assessments, never self-congratulatory
30
+ - Each failure identified must include a root cause (not just a symptom)
31
+ - Retrospectives must result in actionable process changes, not vague intentions
32
+ - The retrospective format must be machine-parseable (YAML or structured markdown)
33
+ - Retrospectives must not require user prompting to be triggered at session boundaries
34
+ - Agent-introduced failures count against the orchestrator, not the agent
35
+
36
+ acceptance_criteria:
37
+ - A /retrospective skill exists that Claude Code can invoke at session end
38
+ - The skill produces a structured assessment covering successes, failures, and process changes
39
+ - Each failure includes root cause analysis and a specific preventive action
40
+ - The retrospective is written to persistent storage (auto memory or project docs)
41
+ - The methodology is documented in a behaviour file with enforceable rules
42
+
43
+ examples:
44
+ - scenario: Claude Code completes a coverage push across 3 sessions
45
+ expected: >-
46
+ Before closing the final session, Claude invokes /retrospective and produces
47
+ a structured assessment. The assessment identifies that 27 agent-introduced
48
+ test failures were caused by agents writing specs against imagined APIs,
49
+ and proposes a process change: always read the implementation before writing
50
+ tests.
51
+ not: >-
52
+ Claude says 'the session went well' without identifying specific failures
53
+ or their root causes.
54
+
55
+ - scenario: A session hits the context window limit mid-task
56
+ expected: >-
57
+ The retrospective notes the context exhaustion, identifies what consumed
58
+ the context (e.g. reading too many files in the main window instead of
59
+ delegating to agents), and proposes a mitigation (e.g. use Explore agents
60
+ for initial research, keep main window for orchestration).
61
+ not: >-
62
+ The retrospective blames context limits as an external constraint without
63
+ analysing whether the session's approach was context-efficient.
64
+
65
+ - scenario: Rate limits are hit due to over-parallelisation
66
+ expected: >-
67
+ The retrospective identifies the specific parallel operation pattern that
68
+ triggered rate limits, estimates the wasted time, and proposes a concurrency
69
+ cap or sequential fallback strategy.
70
+ not: >-
71
+ The retrospective omits the rate limit incident or treats it as unavoidable.
72
+
73
+ anti_patterns:
74
+ - Retrospectives that only list successes ('coverage went from X to Y')
75
+ - Root causes that blame external systems ('the API was slow')
76
+ - Process changes that are too vague to verify ('be more careful next time')
77
+ - Skipping the retrospective because the session 'went well'
78
+ - Writing the retrospective to ephemeral scratch space
79
+
80
+ preferences:
81
+ language: ruby
82
+ patterns:
83
+ - structured_logging
84
+ - yaml_first_configuration
85
+ testing: rspec with schema validation
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: smart_ui_feedback
3
+ domain: ui
4
+ version: 0.1.0
5
+ status: implemented
6
+ priority: 3
7
+ author: hugo
8
+ created_at: "2026-03-15"
9
+ modified_at: "2026-03-16"
10
+ modified_by: claude
11
+ depends_on:
12
+ - ui_framework
13
+ - architecture
14
+ - autocompletion
15
+ - error_handling
16
+ #
17
+ intent: >-
18
+ Transform generic Thor error messages into actionable suggestions using
19
+ edit distance (Levenshtein) matching. Provide "Did you mean?" feedback
20
+ for mistyped commands, subcommands, flags, and arguments — reducing
21
+ frustration, accelerating learning, and making the CLI feel responsive
22
+ and helpful across rosett-ai's 17+ subcommands and dozens of flags.
23
+ #
24
+ constraints:
25
+ - "Suggestions must use edit distance (Levenshtein), not substring matching"
26
+ - "Maximum 3 suggestions per error — more is noise"
27
+ - "Suggestion threshold: edit distance <= 2 for commands, <= 3 for flags"
28
+ - "Must not add measurable latency to valid command execution"
29
+ - "Must work for commands, subcommands, flags, and named arguments"
30
+ - "Suggestions must respect the current command context (not global)"
31
+ - "Must integrate with Thor's error handling, not replace it"
32
+ - "This design governs CLI typo suggestions only. Shell-level tab
33
+ completion is governed by autocompletion.yml"
34
+ #
35
+ acceptance_criteria:
36
+ - "`raictl complie` suggests `compile`"
37
+ - "`rai behaviour shw` suggests `show`"
38
+ - "`rai compile --verboes` suggests `--verbose`"
39
+ - "`raictl build package --varient` suggests `--variant`"
40
+ - "No suggestions shown when edit distance > threshold"
41
+ - "Valid commands execute without any suggestion overhead"
42
+ - "Suggestions are formatted consistently: 'Did you mean `X`?'"
43
+ - "Exit code 1 for unknown command with suggestion, 1 for unknown
44
+ command without suggestion (same exit code, different message)"
45
+ #
46
+ examples:
47
+ - scenario: "User types `raictl complie` (transposed letters)"
48
+ expected: |
49
+ Error: Unknown command 'complie'. Did you mean `compile`?
50
+ not: "Error: Could not find command 'complie'."
51
+ - scenario: "User types `raictl xyz` (no close match)"
52
+ expected: |
53
+ Error: Unknown command 'xyz'. Run `raictl help` for available commands.
54
+ not: "A list of all 17+ commands as suggestions"
55
+ - scenario: "User types `raictl build package --clean --verboes`"
56
+ expected: |
57
+ Error: Unknown option '--verboes'. Did you mean `--verbose`?
58
+ not: "Generic Thor error with no suggestion."
59
+ #
60
+ anti_patterns:
61
+ - "Suggesting commands from unrelated subcommand contexts"
62
+ - "Using substring matching instead of edit distance"
63
+ - "Showing more than 3 suggestions"
64
+ - "Adding latency to the happy path (valid commands)"
65
+ - "Reimplementing Thor's command routing"
66
+ #
67
+ gui_notes: |
68
+ Document interactions (cross-references):
69
+
70
+ 1. autocompletion.yml: tab completion prevents typos proactively;
71
+ smart_ui_feedback handles typos reactively. Both improve CLI UX
72
+ but operate at different points in the interaction.
73
+
74
+ 2. error_handling.yml: suggestions augment structured error messages.
75
+ The "Did you mean?" output follows the error hierarchy format.
76
+
77
+ 3. ui_framework.yml: smart feedback is a CLI-layer feature, not a
78
+ TUI widget. TUI input fields may have their own completion logic.
79
+ #
80
+ preferences:
81
+ language: ruby
82
+ patterns:
83
+ - "Levenshtein distance for fuzzy matching"
84
+ - "Thor error handler middleware"
85
+ - "Cached command registry for zero-latency lookup"
86
+ testing: rspec with typo fixtures, threshold boundary tests, and
87
+ context-aware suggestion scenarios
88
+ gems:
89
+ - thor