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.
- checksums.yaml +7 -0
- data/.ai-provenance.yml +119 -0
- data/.debride_whitelist +186 -0
- data/.fasterer.yml +29 -0
- data/.mdl_style.rb +10 -0
- data/.mdlrc +3 -0
- data/.mutant.yml +49 -0
- data/.namespace-allowlist +42 -0
- data/.reek.yml +1040 -0
- data/.rosett-ai/config.yml +3 -0
- data/.rspec +5 -0
- data/.rubocop.yml +380 -0
- data/.ruby-version +1 -0
- data/.yamllint +51 -0
- data/.yardopts +12 -0
- data/AI-DISCLOSURE.md +48 -0
- data/CHANGELOG.md +519 -0
- data/CLAUDE.md +141 -0
- data/CONTRIBUTING.md +734 -0
- data/INSTALL.md +154 -0
- data/LICENSE +674 -0
- data/LICENSE.md +675 -0
- data/QUICKSTART.md +73 -0
- data/README.md +366 -0
- data/Rakefile +200 -0
- data/SECURITY.md +114 -0
- data/bin/rai +1 -0
- data/cliff.toml +52 -0
- data/conf/adopt_redactions.yml +8 -0
- data/conf/behaviour/.gitkeep +0 -0
- data/conf/compliance/cra_rules.yml +25 -0
- data/conf/compliance/license_rules.yml +20 -0
- data/conf/design/aaif_alignment.yml +181 -0
- data/conf/design/ab_testing.yml +172 -0
- data/conf/design/accessibility.yml +84 -0
- data/conf/design/ai_authorship.yml +210 -0
- data/conf/design/ai_provenance.yml +224 -0
- data/conf/design/ai_tool_configuration.yml +207 -0
- data/conf/design/architecture.yml +139 -0
- data/conf/design/autocompletion.yml +115 -0
- data/conf/design/backward_compatibility.yml +112 -0
- data/conf/design/behaviour_composition.yml +246 -0
- data/conf/design/build_rake_extraction.yml +57 -0
- data/conf/design/ci_pipeline.yml +100 -0
- data/conf/design/claude_code_configuration.yml +157 -0
- data/conf/design/compiler.yml +128 -0
- data/conf/design/comply.yml +153 -0
- data/conf/design/content_packs.yml +84 -0
- data/conf/design/desktop_integration.yml +289 -0
- data/conf/design/distribution.yml +216 -0
- data/conf/design/doctor.yml +184 -0
- data/conf/design/documentation.yml +152 -0
- data/conf/design/engine_architecture.yml +257 -0
- data/conf/design/error_handling.yml +103 -0
- data/conf/design/feature_flags.yml +142 -0
- data/conf/design/git_hooks.yml +165 -0
- data/conf/design/gui_plugins.yml +475 -0
- data/conf/design/i18n.yml +84 -0
- data/conf/design/integration_testing.yml +56 -0
- data/conf/design/licensing_system.yml +88 -0
- data/conf/design/lifecycle_management.yml +208 -0
- data/conf/design/mcp_integration.yml +207 -0
- data/conf/design/mcp_settings.yml +126 -0
- data/conf/design/migration.yml +56 -0
- data/conf/design/monitoring_observability.yml +194 -0
- data/conf/design/namespace_cleanup.yml +145 -0
- data/conf/design/plugin_test_segregation.yml +145 -0
- data/conf/design/policy_management.yml +229 -0
- data/conf/design/project_management.yml +183 -0
- data/conf/design/rai_mcp_asset_discovery.yml +164 -0
- data/conf/design/rai_mcp_server.yml +605 -0
- data/conf/design/release_management.yml +117 -0
- data/conf/design/retrofit.yml +199 -0
- data/conf/design/retrospective_analyzer.yml +79 -0
- data/conf/design/scope_hierarchy.yml +352 -0
- data/conf/design/security.yml +115 -0
- data/conf/design/session_retrospective.yml +85 -0
- data/conf/design/smart_ui_feedback.yml +89 -0
- data/conf/design/structured_logging.yml +148 -0
- data/conf/design/styles.yml +123 -0
- data/conf/design/test_peer_review.yml +89 -0
- data/conf/design/testing.yml +136 -0
- data/conf/design/threat_model.yml +108 -0
- data/conf/design/ui_framework.yml +111 -0
- data/conf/design/usage_optimization.yml +122 -0
- data/conf/design/version_management.yml +60 -0
- data/conf/design/workflow.yml +227 -0
- data/conf/mcp/server_defaults.yml +42 -0
- data/conf/mcp/trust.yml +21 -0
- data/conf/packaging/core.yml +12 -0
- data/conf/packaging/gtk4.yml +11 -0
- data/conf/packaging/qt6.yml +11 -0
- data/conf/policy/default_deny_list.yml +197 -0
- data/conf/review/cli-command-audit.yml +857 -0
- data/conf/review/design-docs.yml +1064 -0
- data/conf/review/design-questionnaire.yml +153 -0
- data/conf/review/questionnaire.yml +146 -0
- data/conf/review/rosett-ai-core.yml +2919 -0
- data/conf/schemas/ai_config_schema.json +73 -0
- data/conf/schemas/behaviour_schema.json +132 -0
- data/conf/schemas/compliance_rule_schema.json +63 -0
- data/conf/schemas/content_pack_manifest_schema.json +51 -0
- data/conf/schemas/design_schema.json +210 -0
- data/conf/schemas/engine_manifest_schema.json +144 -0
- data/conf/schemas/lockfile_schema.json +74 -0
- data/conf/schemas/mcp_server_schema.json +48 -0
- data/conf/schemas/packaging_schema.json +70 -0
- data/conf/schemas/policy_schema.json +85 -0
- data/conf/schemas/provenance_schema.json +84 -0
- data/conf/schemas/rai_config_schema.json +56 -0
- data/conf/schemas/rai_project_schema.json +20 -0
- data/conf/schemas/scope_hierarchy_schema.json +49 -0
- data/conf/schemas/target_schema.json +67 -0
- data/conf/schemas/tooling_schema.json +65 -0
- data/conf/schemas/workflow_schema.json +112 -0
- data/conf/targets/agents_md.yml +17 -0
- data/conf/targets/claude.yml +12 -0
- data/conf/tooling/tools.yml +58 -0
- data/dist/rosett-ai-mcp.service +48 -0
- data/dist/rosett-ai-mcp.yml.default +45 -0
- data/doc/AAIF_POSITIONING.md +58 -0
- data/doc/ADOPT.md +224 -0
- data/doc/AI_PROVENANCE.md +139 -0
- data/doc/ARCHITECTURE.md +920 -0
- data/doc/BEHAVIOUR.md +409 -0
- data/doc/BUILD.md +138 -0
- data/doc/CI_CD_RECIPES.md +171 -0
- data/doc/CLAUDE_SESSIONS_MOVED.md +16 -0
- data/doc/COMMAND_ANALYSIS.md +229 -0
- data/doc/CONFIGURATION.md +281 -0
- data/doc/DESIGN_AUDIT.md +235 -0
- data/doc/DESIGN_PEER_REVIEW.md +771 -0
- data/doc/DESKTOP.md +447 -0
- data/doc/ENGINES.md +567 -0
- data/doc/ENGINE_DEVELOPMENT_GUIDE.md +417 -0
- data/doc/FEATURE_AUDIT.md +218 -0
- data/doc/IMPLEMENTATION_PLAN.md +669 -0
- data/doc/INCIDENT_REPORT_2026-02-02.md +251 -0
- data/doc/MIGRATION_GUIDE.md +88 -0
- data/doc/PACKAGING.md +232 -0
- data/doc/PROJECT_DASHBOARD.md +153 -0
- data/doc/PULP_DEPLOYMENT.md +164 -0
- data/doc/QUALITY_FIX_SUMMARY.md +110 -0
- data/doc/QUICK_START.md +162 -0
- data/doc/REEK_CONFIGURATION.md +166 -0
- data/doc/REFERENCE.md +253 -0
- data/doc/REFERENCES.md +324 -0
- data/doc/SECURITY_REVIEW_CHECKLIST.md +72 -0
- data/doc/SESSION_2026-02-28_GTK4_HARDENING.md +359 -0
- data/doc/SETUP.md +202 -0
- data/doc/TEST_PEER_REVIEW.md +152 -0
- data/doc/THREAT_MODEL.md +230 -0
- data/doc/USAGE.md +545 -0
- data/doc/USER_MANUAL.md +585 -0
- data/doc/ai_test_review_checklist.md +110 -0
- data/doc/changes/2026-02-18-packaging-fpm.md +155 -0
- data/doc/changes/2026-02-19-testing-infrastructure.md +221 -0
- data/doc/changes/2026-02-20-security-implementation.md +281 -0
- data/doc/changes/2026-02-20-styles-implementation.md +220 -0
- data/doc/changes/2026-02-21-architecture-completion.md +95 -0
- data/doc/changes/2026-02-21-architecture-ui-layer.md +253 -0
- data/doc/changes/2026-02-21-cc-config-implementation.md +108 -0
- data/doc/changes/2026-02-21-ci-pipeline-implementation.md +214 -0
- data/doc/changes/2026-02-21-compiler-multi-target-pipeline.md +241 -0
- data/doc/changes/2026-02-21-config-design-show-commands.md +61 -0
- data/doc/changes/2026-02-21-design-implementation-overview.md +455 -0
- data/doc/changes/2026-02-21-lifecycle-management.md +196 -0
- data/doc/changes/2026-02-21-path-resolver.md +128 -0
- data/doc/changes/2026-02-24-ci-tmpdir-mutant-fetch.md +45 -0
- data/doc/changes/2026-03-01-ci-bundler-strategy.md +120 -0
- data/doc/changes/2026-03-20-security-hardening-phase2.md +163 -0
- data/doc/context/SESSION-HANDOFF.md +69 -0
- data/doc/context/ai-engine-usage-trends-2026.md +80 -0
- data/doc/context/plan-pluggable-engines.md +590 -0
- data/doc/decisions/001-flog-deferred.md +32 -0
- data/doc/decisions/002-path-resolution-strategy.md +158 -0
- data/doc/decisions/003-ui-adapter-selection.md +193 -0
- data/doc/decisions/004-design-document-validation.md +179 -0
- data/doc/decisions/005-package-splitting-strategy.md +200 -0
- data/doc/decisions/006-multi-engine-architecture.md +147 -0
- data/doc/decisions/007-engine-agnostic-pivot.md +219 -0
- data/doc/decisions/008-ci-bundler-strategy.md +129 -0
- data/doc/decisions/009-core-only-v1-release.md +60 -0
- data/doc/decisions/010-engine-debian-packaging.md +66 -0
- data/doc/decisions/011-context-aware-cli.md +71 -0
- data/doc/dependency_decisions.yml +247 -0
- data/doc/issues/001-wrapper-missing-environment-variables.md +197 -0
- data/doc/issues/002-embedded-ruby-wrong-prefix.md +217 -0
- data/doc/issues/003-smoke-test-false-positive.md +127 -0
- data/doc/issues/004-market-research-design-updates.md +109 -0
- data/doc/issues/005-compile-scope-coexistence.md +161 -0
- data/doc/locales/.gitkeep +0 -0
- data/doc/man/rai.1.ronn +505 -0
- data/doc/operations/packaging.md +133 -0
- data/doc/operations/rosett-ai-release.md +65 -0
- data/doc/reference/error-catalog.md +107 -0
- data/doc/reference/rosett-ai-technical-reference.pdf +0 -0
- data/doc/reference/src/Pictures/cover.jpg +0 -0
- data/doc/reference/src/Pictures/head1.jpg +0 -0
- data/doc/reference/src/Pictures/head2.jpg +0 -0
- data/doc/reference/src/Pictures/head3.jpg +0 -0
- data/doc/reference/src/Pictures/head4.jpg +0 -0
- data/doc/reference/src/Pictures/head5.jpg +0 -0
- data/doc/reference/src/Pictures/head6.jpg +0 -0
- data/doc/reference/src/Pictures/head7.jpg +0 -0
- data/doc/reference/src/Pictures/head8.jpg +0 -0
- data/doc/reference/src/StyleInd.ist +4 -0
- data/doc/reference/src/bibliography.bib +79 -0
- data/doc/reference/src/main.tex +1288 -0
- data/doc/reference/src/structure.tex +303 -0
- data/doc/rosett-ai-bookmarks.html +301 -0
- data/kitchen.yml +46 -0
- data/lib/rosett_ai/adopter/executor_resolver.rb +77 -0
- data/lib/rosett_ai/adopter/local_analysis_collector.rb +154 -0
- data/lib/rosett_ai/adopter/rule_adopter.rb +254 -0
- data/lib/rosett_ai/ai_config/config_compiler.rb +111 -0
- data/lib/rosett_ai/ai_config/context_window.rb +55 -0
- data/lib/rosett_ai/ai_config/cost_controls.rb +44 -0
- data/lib/rosett_ai/ai_config/fallback_chain.rb +64 -0
- data/lib/rosett_ai/ai_config/model_router.rb +121 -0
- data/lib/rosett_ai/ai_config/validator.rb +45 -0
- data/lib/rosett_ai/authorship/attribution_compiler.rb +99 -0
- data/lib/rosett_ai/authorship/disclosure_policy.rb +81 -0
- data/lib/rosett_ai/authorship/review_validator.rb +39 -0
- data/lib/rosett_ai/authorship/trailer_generator.rb +88 -0
- data/lib/rosett_ai/backup/compressor.rb +180 -0
- data/lib/rosett_ai/backup/destination.rb +91 -0
- data/lib/rosett_ai/behaviour/manager.rb +156 -0
- data/lib/rosett_ai/compiler/backend.rb +86 -0
- data/lib/rosett_ai/compiler/backends/agents_md_backend.rb +80 -0
- data/lib/rosett_ai/compiler/backends/claude_backend.rb +88 -0
- data/lib/rosett_ai/compiler/backends/generic_backend.rb +15 -0
- data/lib/rosett_ai/compiler/behaviour_compiler.rb +40 -0
- data/lib/rosett_ai/compiler/capability_checker.rb +104 -0
- data/lib/rosett_ai/compiler/compilation_pipeline.rb +361 -0
- data/lib/rosett_ai/compiler/compiled_output.rb +39 -0
- data/lib/rosett_ai/compiler/locale_compiler.rb +250 -0
- data/lib/rosett_ai/compiler/target_profile.rb +112 -0
- data/lib/rosett_ai/completion/generator.rb +101 -0
- data/lib/rosett_ai/completion/shells/bash_generator.rb +126 -0
- data/lib/rosett_ai/completion/shells/fish_generator.rb +78 -0
- data/lib/rosett_ai/completion/shells/zsh_generator.rb +126 -0
- data/lib/rosett_ai/comply/checkers/cra_checker.rb +102 -0
- data/lib/rosett_ai/comply/checkers/license_checker.rb +85 -0
- data/lib/rosett_ai/comply/checkers/spdx_header_checker.rb +98 -0
- data/lib/rosett_ai/comply/reporter.rb +113 -0
- data/lib/rosett_ai/comply/runner.rb +50 -0
- data/lib/rosett_ai/composition/circular_dependency_detector.rb +56 -0
- data/lib/rosett_ai/composition/composer.rb +158 -0
- data/lib/rosett_ai/composition/composition_result.rb +64 -0
- data/lib/rosett_ai/composition/conflict_detector.rb +53 -0
- data/lib/rosett_ai/composition/lockfile.rb +103 -0
- data/lib/rosett_ai/composition/merge_strategy.rb +131 -0
- data/lib/rosett_ai/composition/priority_sorter.rb +29 -0
- data/lib/rosett_ai/composition/scope_resolver.rb +55 -0
- data/lib/rosett_ai/config/compile_result.rb +37 -0
- data/lib/rosett_ai/config/compiler.rb +13 -0
- data/lib/rosett_ai/config/domain_transformer.rb +13 -0
- data/lib/rosett_ai/config/key_map.rb +13 -0
- data/lib/rosett_ai/config/masking_secret_resolver.rb +40 -0
- data/lib/rosett_ai/config/scope_router.rb +13 -0
- data/lib/rosett_ai/config/secret_resolver.rb +125 -0
- data/lib/rosett_ai/configuration.rb +119 -0
- data/lib/rosett_ai/content/content_client.rb +60 -0
- data/lib/rosett_ai/content/pack_installer.rb +117 -0
- data/lib/rosett_ai/content/pack_manifest.rb +50 -0
- data/lib/rosett_ai/content/pack_registry.rb +68 -0
- data/lib/rosett_ai/content_packs/manager.rb +50 -0
- data/lib/rosett_ai/dbus/compositor_detector.rb +77 -0
- data/lib/rosett_ai/dbus/focus_adapters/base.rb +59 -0
- data/lib/rosett_ai/dbus/focus_adapters/gnome_adapter.rb +172 -0
- data/lib/rosett_ai/dbus/focus_adapters/hyprland_adapter.rb +77 -0
- data/lib/rosett_ai/dbus/focus_adapters/i3_adapter.rb +65 -0
- data/lib/rosett_ai/dbus/focus_adapters/kwin_adapter.rb +103 -0
- data/lib/rosett_ai/dbus/focus_adapters/x11_adapter.rb +105 -0
- data/lib/rosett_ai/dbus/focus_monitor_interface.rb +103 -0
- data/lib/rosett_ai/dbus/manager_interface.rb +213 -0
- data/lib/rosett_ai/dbus/plugin_manager_interface.rb +169 -0
- data/lib/rosett_ai/dbus/rate_limiter.rb +89 -0
- data/lib/rosett_ai/dbus/service.rb +121 -0
- data/lib/rosett_ai/dbus/status_notifier_interface.rb +79 -0
- data/lib/rosett_ai/deprecation.rb +79 -0
- data/lib/rosett_ai/desktop/dbus_client.rb +259 -0
- data/lib/rosett_ai/desktop/gtk4_app.rb +371 -0
- data/lib/rosett_ai/desktop/gtk4_preferences.rb +331 -0
- data/lib/rosett_ai/desktop/gui_logger.rb +236 -0
- data/lib/rosett_ai/doctor/check.rb +92 -0
- data/lib/rosett_ai/doctor/checks/cache_health_check.rb +50 -0
- data/lib/rosett_ai/doctor/checks/dbus_availability_check.rb +39 -0
- data/lib/rosett_ai/doctor/checks/engine_detection_check.rb +46 -0
- data/lib/rosett_ai/doctor/checks/file_permission_check.rb +44 -0
- data/lib/rosett_ai/doctor/checks/gem_dependency_check.rb +55 -0
- data/lib/rosett_ai/doctor/checks/ruby_version_check.rb +50 -0
- data/lib/rosett_ai/doctor/checks/stale_config_nncc_check.rb +57 -0
- data/lib/rosett_ai/doctor/checks/stale_home_nncc_check.rb +59 -0
- data/lib/rosett_ai/doctor.rb +81 -0
- data/lib/rosett_ai/documentation/reference_compiler.rb +122 -0
- data/lib/rosett_ai/documentation/translator.rb +62 -0
- data/lib/rosett_ai/engines/base_config_compiler.rb +203 -0
- data/lib/rosett_ai/engines/detector.rb +63 -0
- data/lib/rosett_ai/engines/registry.rb +50 -0
- data/lib/rosett_ai/error_handler.rb +139 -0
- data/lib/rosett_ai/exit_codes.rb +76 -0
- data/lib/rosett_ai/feature_flags.rb +102 -0
- data/lib/rosett_ai/formatting.rb +33 -0
- data/lib/rosett_ai/gem_consistency_checker.rb +199 -0
- data/lib/rosett_ai/git_hooks/chain_detector.rb +86 -0
- data/lib/rosett_ai/git_hooks/installer.rb +175 -0
- data/lib/rosett_ai/git_hooks/script_generator.rb +125 -0
- data/lib/rosett_ai/gitlab/validators/supplementary_gitlab_ci_yaml_validator.rb +79 -0
- data/lib/rosett_ai/i18n/locale_resolver.rb +46 -0
- data/lib/rosett_ai/i18n/utf8_checker.rb +32 -0
- data/lib/rosett_ai/init/config_file_writer.rb +24 -0
- data/lib/rosett_ai/init/directory_builder.rb +38 -0
- data/lib/rosett_ai/init/file_copier.rb +95 -0
- data/lib/rosett_ai/init/global_initializer.rb +28 -0
- data/lib/rosett_ai/init/local_initializer.rb +27 -0
- data/lib/rosett_ai/init/mcp_registrar.rb +109 -0
- data/lib/rosett_ai/init/project_initializer.rb +38 -0
- data/lib/rosett_ai/licensing/license_key.rb +139 -0
- data/lib/rosett_ai/licensing/license_store.rb +64 -0
- data/lib/rosett_ai/licensing/license_validator.rb +60 -0
- data/lib/rosett_ai/licensing/tier.rb +42 -0
- data/lib/rosett_ai/mcp/admin/auditor.rb +88 -0
- data/lib/rosett_ai/mcp/admin/health_checker.rb +81 -0
- data/lib/rosett_ai/mcp/admin/registry.rb +100 -0
- data/lib/rosett_ai/mcp/admin/schema_validator.rb +63 -0
- data/lib/rosett_ai/mcp/enforcement/.gitkeep +0 -0
- data/lib/rosett_ai/mcp/enforcement/hook_generator.rb +197 -0
- data/lib/rosett_ai/mcp/enforcement/validator.rb +215 -0
- data/lib/rosett_ai/mcp/governance.rb +160 -0
- data/lib/rosett_ai/mcp/http_security_config.rb +158 -0
- data/lib/rosett_ai/mcp/instructions.rb +266 -0
- data/lib/rosett_ai/mcp/key_hasher.rb +66 -0
- data/lib/rosett_ai/mcp/keyfile.rb +221 -0
- data/lib/rosett_ai/mcp/middleware/authentication.rb +146 -0
- data/lib/rosett_ai/mcp/middleware/content_type.rb +56 -0
- data/lib/rosett_ai/mcp/middleware/cors.rb +83 -0
- data/lib/rosett_ai/mcp/middleware/origin_validation.rb +73 -0
- data/lib/rosett_ai/mcp/middleware/rate_limit.rb +106 -0
- data/lib/rosett_ai/mcp/middleware/request_size.rb +51 -0
- data/lib/rosett_ai/mcp/plugins.rb +143 -0
- data/lib/rosett_ai/mcp/prompts/compilation_prompt.rb +40 -0
- data/lib/rosett_ai/mcp/prompts/compliance_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/prompts/diagnostics_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/prompts/validation_prompt.rb +41 -0
- data/lib/rosett_ai/mcp/resources/behaviour_resource.rb +127 -0
- data/lib/rosett_ai/mcp/resources/config_resource.rb +72 -0
- data/lib/rosett_ai/mcp/resources/design_resource.rb +58 -0
- data/lib/rosett_ai/mcp/resources/hooks_resource.rb +74 -0
- data/lib/rosett_ai/mcp/resources/provenance_resource.rb +51 -0
- data/lib/rosett_ai/mcp/resources/rules_resource.rb +60 -0
- data/lib/rosett_ai/mcp/resources/schema_resource.rb +72 -0
- data/lib/rosett_ai/mcp/response_helper.rb +46 -0
- data/lib/rosett_ai/mcp/security_logger.rb +60 -0
- data/lib/rosett_ai/mcp/server.rb +212 -0
- data/lib/rosett_ai/mcp/settings/server_installer.rb +112 -0
- data/lib/rosett_ai/mcp/settings/trust_manager.rb +142 -0
- data/lib/rosett_ai/mcp/tools/adopt_tool.rb +70 -0
- data/lib/rosett_ai/mcp/tools/backup_tool.rb +64 -0
- data/lib/rosett_ai/mcp/tools/behaviour_display_tool.rb +72 -0
- data/lib/rosett_ai/mcp/tools/behaviour_list_tool.rb +56 -0
- data/lib/rosett_ai/mcp/tools/behaviour_manage_tool.rb +114 -0
- data/lib/rosett_ai/mcp/tools/behaviour_show_tool.rb +62 -0
- data/lib/rosett_ai/mcp/tools/compile_status_tool.rb +122 -0
- data/lib/rosett_ai/mcp/tools/compile_tool.rb +191 -0
- data/lib/rosett_ai/mcp/tools/comply_tool.rb +79 -0
- data/lib/rosett_ai/mcp/tools/config_compile_tool.rb +71 -0
- data/lib/rosett_ai/mcp/tools/config_status_tool.rb +79 -0
- data/lib/rosett_ai/mcp/tools/content_tool.rb +78 -0
- data/lib/rosett_ai/mcp/tools/context_query_tool.rb +156 -0
- data/lib/rosett_ai/mcp/tools/design_list_tool.rb +57 -0
- data/lib/rosett_ai/mcp/tools/design_show_tool.rb +69 -0
- data/lib/rosett_ai/mcp/tools/doctor_tool.rb +62 -0
- data/lib/rosett_ai/mcp/tools/documentation_status_tool.rb +45 -0
- data/lib/rosett_ai/mcp/tools/engines_tool.rb +84 -0
- data/lib/rosett_ai/mcp/tools/hook_install_tool.rb +190 -0
- data/lib/rosett_ai/mcp/tools/hook_preview_tool.rb +173 -0
- data/lib/rosett_ai/mcp/tools/hooks_status_tool.rb +84 -0
- data/lib/rosett_ai/mcp/tools/init_tool.rb +87 -0
- data/lib/rosett_ai/mcp/tools/license_status_tool.rb +44 -0
- data/lib/rosett_ai/mcp/tools/project_tool.rb +117 -0
- data/lib/rosett_ai/mcp/tools/provenance_tool.rb +97 -0
- data/lib/rosett_ai/mcp/tools/provenance_write_tool.rb +40 -0
- data/lib/rosett_ai/mcp/tools/retrofit_tool.rb +81 -0
- data/lib/rosett_ai/mcp/tools/rule_search_tool.rb +163 -0
- data/lib/rosett_ai/mcp/tools/schema_get_tool.rb +94 -0
- data/lib/rosett_ai/mcp/tools/tooling_tool.rb +86 -0
- data/lib/rosett_ai/mcp/tools/validate_tool.rb +105 -0
- data/lib/rosett_ai/mcp/tools/workflow_execute_tool.rb +74 -0
- data/lib/rosett_ai/mcp/tools/workflow_tool.rb +78 -0
- data/lib/rosett_ai/migration/detector.rb +117 -0
- data/lib/rosett_ai/migration/nncc_config_migrator.rb +94 -0
- data/lib/rosett_ai/migration/nncc_project_migrator.rb +90 -0
- data/lib/rosett_ai/migration/xdg_migrator.rb +123 -0
- data/lib/rosett_ai/package_manager/apt.rb +108 -0
- data/lib/rosett_ai/package_manager/base.rb +68 -0
- data/lib/rosett_ai/package_manager/gem_backend.rb +90 -0
- data/lib/rosett_ai/packaging/variant_config.rb +92 -0
- data/lib/rosett_ai/path_resolver.rb +115 -0
- data/lib/rosett_ai/plugins/contract.rb +43 -0
- data/lib/rosett_ai/plugins/engine_contract.rb +60 -0
- data/lib/rosett_ai/plugins/gui_contract.rb +74 -0
- data/lib/rosett_ai/plugins/mcp_contract.rb +48 -0
- data/lib/rosett_ai/plugins/registry.rb +150 -0
- data/lib/rosett_ai/policy/auditor.rb +41 -0
- data/lib/rosett_ai/policy/deny_list.rb +71 -0
- data/lib/rosett_ai/policy/opt_out_scanner.rb +37 -0
- data/lib/rosett_ai/policy/policy_compiler.rb +84 -0
- data/lib/rosett_ai/policy/protected_files.rb +47 -0
- data/lib/rosett_ai/policy/tier_hierarchy.rb +48 -0
- data/lib/rosett_ai/policy/validator.rb +35 -0
- data/lib/rosett_ai/profiler.rb +79 -0
- data/lib/rosett_ai/project/drift_detector.rb +126 -0
- data/lib/rosett_ai/project/manager.rb +115 -0
- data/lib/rosett_ai/project/sync_manager.rb +138 -0
- data/lib/rosett_ai/project/template_applier.rb +105 -0
- data/lib/rosett_ai/project_context.rb +82 -0
- data/lib/rosett_ai/provenance/entry.rb +63 -0
- data/lib/rosett_ai/provenance/file_source.rb +32 -0
- data/lib/rosett_ai/provenance/source.rb +62 -0
- data/lib/rosett_ai/provenance/store.rb +153 -0
- data/lib/rosett_ai/provenance/tracker.rb +62 -0
- data/lib/rosett_ai/provenance/trailer_generator.rb +43 -0
- data/lib/rosett_ai/provenance/validator.rb +45 -0
- data/lib/rosett_ai/quorum/collector.rb +59 -0
- data/lib/rosett_ai/quorum/comparator.rb +81 -0
- data/lib/rosett_ai/quorum/dispatcher.rb +57 -0
- data/lib/rosett_ai/quorum/strategies/adopt.rb +56 -0
- data/lib/rosett_ai/rai_config.rb +107 -0
- data/lib/rosett_ai/retrofit/base_parser.rb +66 -0
- data/lib/rosett_ai/retrofit/engine.rb +171 -0
- data/lib/rosett_ai/retrofit/parsers/agents_md_parser.rb +50 -0
- data/lib/rosett_ai/retrofit/parsers/claude_parser.rb +69 -0
- data/lib/rosett_ai/retrofit/parsers/cursor_parser.rb +82 -0
- data/lib/rosett_ai/retrofit/round_trip_validator.rb +65 -0
- data/lib/rosett_ai/retrofit/scanner.rb +47 -0
- data/lib/rosett_ai/retrofit/secret_detector.rb +87 -0
- data/lib/rosett_ai/secrets_resolver.rb +71 -0
- data/lib/rosett_ai/smart_feedback/suggester.rb +83 -0
- data/lib/rosett_ai/smart_feedback/thor_middleware.rb +84 -0
- data/lib/rosett_ai/structured_logger.rb +110 -0
- data/lib/rosett_ai/telemetry/json_lines_writer.rb +50 -0
- data/lib/rosett_ai/telemetry/log_rotator.rb +67 -0
- data/lib/rosett_ai/telemetry/provider.rb +26 -0
- data/lib/rosett_ai/telemetry/reporter.rb +144 -0
- data/lib/rosett_ai/telemetry.rb +47 -0
- data/lib/rosett_ai/text_sanitizer.rb +62 -0
- data/lib/rosett_ai/thor/cli.rb +269 -0
- data/lib/rosett_ai/thor/tasks/adopt.rb +250 -0
- data/lib/rosett_ai/thor/tasks/backup.rb +420 -0
- data/lib/rosett_ai/thor/tasks/behaviour.rb +474 -0
- data/lib/rosett_ai/thor/tasks/build.rb +1162 -0
- data/lib/rosett_ai/thor/tasks/compile.rb +415 -0
- data/lib/rosett_ai/thor/tasks/completion.rb +123 -0
- data/lib/rosett_ai/thor/tasks/comply.rb +82 -0
- data/lib/rosett_ai/thor/tasks/config.rb +265 -0
- data/lib/rosett_ai/thor/tasks/content.rb +193 -0
- data/lib/rosett_ai/thor/tasks/dbus.rb +321 -0
- data/lib/rosett_ai/thor/tasks/design.rb +258 -0
- data/lib/rosett_ai/thor/tasks/desktop.rb +129 -0
- data/lib/rosett_ai/thor/tasks/doctor.rb +127 -0
- data/lib/rosett_ai/thor/tasks/documentation.rb +321 -0
- data/lib/rosett_ai/thor/tasks/engines.rb +167 -0
- data/lib/rosett_ai/thor/tasks/hooks.rb +219 -0
- data/lib/rosett_ai/thor/tasks/init.rb +259 -0
- data/lib/rosett_ai/thor/tasks/license.rb +120 -0
- data/lib/rosett_ai/thor/tasks/mcp.rb +535 -0
- data/lib/rosett_ai/thor/tasks/migrate.rb +121 -0
- data/lib/rosett_ai/thor/tasks/plugins.rb +157 -0
- data/lib/rosett_ai/thor/tasks/project.rb +260 -0
- data/lib/rosett_ai/thor/tasks/provenance.rb +195 -0
- data/lib/rosett_ai/thor/tasks/release.rb +314 -0
- data/lib/rosett_ai/thor/tasks/retrofit.rb +90 -0
- data/lib/rosett_ai/thor/tasks/tooling.rb +308 -0
- data/lib/rosett_ai/thor/tasks/validate.rb +108 -0
- data/lib/rosett_ai/thor/tasks/workflow.rb +196 -0
- data/lib/rosett_ai/tooling/ci_yaml_validator.rb +37 -0
- data/lib/rosett_ai/tooling/version_checker.rb +35 -0
- data/lib/rosett_ai/ui/accessible_tui.rb +61 -0
- data/lib/rosett_ai/ui/base.rb +46 -0
- data/lib/rosett_ai/ui/gtk4.rb +98 -0
- data/lib/rosett_ai/ui/kde.rb +40 -0
- data/lib/rosett_ai/ui/qt6.rb +40 -0
- data/lib/rosett_ai/ui/registry.rb +60 -0
- data/lib/rosett_ai/ui/tty_helper.rb +74 -0
- data/lib/rosett_ai/ui/tui.rb +59 -0
- data/lib/rosett_ai/validators/behaviour_validator.rb +20 -0
- data/lib/rosett_ai/validators/design_validator.rb +17 -0
- data/lib/rosett_ai/validators/schema_validator.rb +84 -0
- data/lib/rosett_ai/validators/tooling_validator.rb +17 -0
- data/lib/rosett_ai/version.rb +8 -0
- data/lib/rosett_ai/version_consistency_checker.rb +129 -0
- data/lib/rosett_ai/workflow/audit_log.rb +86 -0
- data/lib/rosett_ai/workflow/engine.rb +142 -0
- data/lib/rosett_ai/workflow/manager.rb +82 -0
- data/lib/rosett_ai/workflow/schema_validator.rb +71 -0
- data/lib/rosett_ai/workflow/step_runner.rb +61 -0
- data/lib/rosett_ai/workflow/steps/prompt_step.rb +62 -0
- data/lib/rosett_ai/workflow/steps/rai_step.rb +74 -0
- data/lib/rosett_ai/workflow/steps/shell_step.rb +53 -0
- data/lib/rosett_ai/yaml_loader.rb +78 -0
- data/lib/rosett_ai.rb +221 -0
- data/lib/rubocop/cop/rosett_ai/shell_interpolation.rb +54 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_const_get.rb +60 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_send.rb +50 -0
- data/lib/rubocop/cop/rosett_ai/unsafe_yaml_load.rb +40 -0
- data/lib/rubocop/rosett_ai.rb +9 -0
- data/lib/scripts/generated/docker_hub_tags.rb +126 -0
- data/locales/.gitkeep +0 -0
- data/locales/ar.yml +579 -0
- data/locales/en.yml +571 -0
- data/locales/fr.yml +567 -0
- data/packaging/build-engine-deb.sh +81 -0
- data/packaging/scripts/postinst +17 -0
- data/packaging/scripts/postrm +19 -0
- data/packaging/scripts/prerm +10 -0
- data/packaging/wrapper.sh.template +38 -0
- data/rosett-ai.gemspec +63 -0
- data/rules/.gitkeep +0 -0
- data/scripts/publish/pulp_upload.sh +123 -0
- data/settings.json +29 -0
- data/share/applications/be.neatnerds.rosettai.desktop +29 -0
- data/share/dbus-1/interfaces/be.neatnerds.rosettai.xml +103 -0
- data/share/dbus-1/services/be.neatnerds.rosettai.service +3 -0
- data/share/templates/behaviour/criticalthinking.yml +69 -0
- 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
|