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