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,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ci_pipeline
|
|
3
|
+
domain: ci
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
status: implemented
|
|
6
|
+
priority: 1
|
|
7
|
+
author: hugo
|
|
8
|
+
created_at: "2026-02-18"
|
|
9
|
+
modified_at: "2026-03-17"
|
|
10
|
+
modified_by: claude
|
|
11
|
+
depends_on:
|
|
12
|
+
- security
|
|
13
|
+
- testing
|
|
14
|
+
- styles
|
|
15
|
+
|
|
16
|
+
intent: |
|
|
17
|
+
Define the CI/CD pipeline that enforces security and testing constraints on
|
|
18
|
+
every code change. Without enforcement gates, security rules are suggestions,
|
|
19
|
+
not constraints. This pipeline must be in place before feature development
|
|
20
|
+
begins. It is the mechanism that ensures the security and testing design
|
|
21
|
+
documents are not just documentation but are actively enforced on every
|
|
22
|
+
commit and merge request.
|
|
23
|
+
|
|
24
|
+
constraints:
|
|
25
|
+
- No code merges to main without passing all CI stages
|
|
26
|
+
- Security audit stage (bundler-audit, ruby_audit) must run first and block on any finding
|
|
27
|
+
- Static analysis (rubocop, reek) must block on any violation — no warnings-only mode
|
|
28
|
+
- Test stage must produce JUnit XML artifacts for GitLab integration
|
|
29
|
+
- Mutation testing runs on merge requests only (too slow for every push)
|
|
30
|
+
- Mutation testing must block merge if score drops below threshold
|
|
31
|
+
- Mutation testing timeout is 30 minutes maximum
|
|
32
|
+
- Coverage reports must be preserved as CI artifacts
|
|
33
|
+
- Pipeline must complete in under 15 minutes for push events (excluding mutation testing)
|
|
34
|
+
- No allow_failure on security or test stages
|
|
35
|
+
|
|
36
|
+
acceptance_criteria:
|
|
37
|
+
- GitLab CI YAML is valid and passes rai validate-ci-yaml
|
|
38
|
+
- Pipeline has distinct stages in order — audit, lint, test, mutation, build
|
|
39
|
+
- bundler-audit check exits non-zero on known CVEs
|
|
40
|
+
- ruby_audit check exits non-zero on Ruby stdlib CVEs
|
|
41
|
+
- rubocop exits non-zero on any violation
|
|
42
|
+
- reek exits non-zero on any code smell above configured threshold
|
|
43
|
+
- flay exits non-zero on structural duplication above threshold
|
|
44
|
+
- flog exits non-zero on complexity above threshold (deferred — see ADR-001, covered by RuboCop Metrics cops)
|
|
45
|
+
- rspec produces JUnit XML report and coverage/ artifacts
|
|
46
|
+
- mutant runs only on merge_request_event and blocks merge on score drop
|
|
47
|
+
- Build stage produces .deb package artifact
|
|
48
|
+
- Pipeline duration is under 15 minutes for push events
|
|
49
|
+
|
|
50
|
+
examples:
|
|
51
|
+
- scenario: "Developer pushes a commit with YAML.load in new code"
|
|
52
|
+
expected: |
|
|
53
|
+
Lint stage fails: RuboCop flags YAML.load as security violation.
|
|
54
|
+
Pipeline stops. Developer must fix to YAML.safe_load before re-pushing.
|
|
55
|
+
not: "Pipeline passes with a warning. Code merges with unsafe YAML parsing."
|
|
56
|
+
- scenario: "A gem dependency has a new CVE published"
|
|
57
|
+
expected: |
|
|
58
|
+
Next CI run fails at audit stage. bundler-audit reports the CVE with
|
|
59
|
+
advisory URL. Pipeline blocks. Developer updates gem or adds justified
|
|
60
|
+
exception to .bundler-audit.yml.
|
|
61
|
+
not: "CVE is silently ignored. Pipeline passes with vulnerable dependency."
|
|
62
|
+
- scenario: "Merge request adds new Compiler class with AI-generated tests"
|
|
63
|
+
expected: |
|
|
64
|
+
Push stages pass (audit, lint, unit test). Mutation stage runs on changed
|
|
65
|
+
files. If mutant score >= 85%, MR is mergeable. If score < 85%, MR is
|
|
66
|
+
blocked with mutation report showing surviving mutations.
|
|
67
|
+
not: "Mutation testing is skipped. MR merges without test quality validation."
|
|
68
|
+
- scenario: "Developer adds a new feature but forgets to write tests"
|
|
69
|
+
expected: |
|
|
70
|
+
SimpleCov minimum_coverage_by_file (80%) fails for the new file.
|
|
71
|
+
Pipeline blocks at test stage.
|
|
72
|
+
not: "Untested code merges. Coverage drops silently."
|
|
73
|
+
|
|
74
|
+
anti_patterns:
|
|
75
|
+
- Using allow_failure on security or test stages
|
|
76
|
+
- Skipping stages with CI variables or manual overrides
|
|
77
|
+
- Running mutation testing on every push (too slow, blocks development)
|
|
78
|
+
- Not preserving test artifacts (coverage reports, JUnit XML)
|
|
79
|
+
- Hardcoding credentials or tokens in CI configuration
|
|
80
|
+
- Using --no-verify or equivalent to bypass pre-commit hooks
|
|
81
|
+
- Ignoring bundler-audit advisories without documented justification
|
|
82
|
+
|
|
83
|
+
preferences:
|
|
84
|
+
language: ruby
|
|
85
|
+
patterns:
|
|
86
|
+
- fail_fast_pipeline
|
|
87
|
+
- artifacts_for_debugging
|
|
88
|
+
- merge_request_gates
|
|
89
|
+
gems:
|
|
90
|
+
- bundler-audit
|
|
91
|
+
- ruby_audit
|
|
92
|
+
- rubocop
|
|
93
|
+
- rubocop-performance
|
|
94
|
+
- rubocop-rspec
|
|
95
|
+
- reek
|
|
96
|
+
- flay
|
|
97
|
+
- rspec
|
|
98
|
+
- simplecov
|
|
99
|
+
- mutant-rspec
|
|
100
|
+
- rspec-junit-formatter
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claude_code_configuration
|
|
3
|
+
domain: core
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
status: implemented
|
|
6
|
+
priority: 2
|
|
7
|
+
author: hugo
|
|
8
|
+
created_at: "2026-02-20"
|
|
9
|
+
modified_at: "2026-03-17"
|
|
10
|
+
modified_by: claude
|
|
11
|
+
depends_on:
|
|
12
|
+
- security
|
|
13
|
+
- architecture
|
|
14
|
+
- compiler
|
|
15
|
+
- engine_architecture
|
|
16
|
+
|
|
17
|
+
intent: |
|
|
18
|
+
Define a YAML-based authoritative configuration format for AI tool
|
|
19
|
+
settings that compiles to native format via the engine-plugin pattern.
|
|
20
|
+
Core provides the compilation framework (BaseConfigCompiler, SecretResolver,
|
|
21
|
+
MaskingSecretResolver, CompileResult) and CLI commands (rai config compile,
|
|
22
|
+
raictl config show). Each engine provides the domain-specific transformation
|
|
23
|
+
logic: scope routing, key mapping, version compatibility checks, and
|
|
24
|
+
format-specific output.
|
|
25
|
+
|
|
26
|
+
For Claude Code, the rosett-ai-engine-claude gem implements ConfigCompiler,
|
|
27
|
+
DomainTransformer, ScopeRouter, and KeyMap to compile scope YAML files
|
|
28
|
+
into Claude Code's native JSON settings across all four scopes (managed,
|
|
29
|
+
user, project, local). Other engines may implement config_compiler_class
|
|
30
|
+
to compile their own tool-specific settings.
|
|
31
|
+
|
|
32
|
+
The goal is a single source of truth (scope-specific YAML files maintained
|
|
33
|
+
by the engine) that eliminates manual JSON editing, enforces schema
|
|
34
|
+
validation, supports version compatibility assertions, and handles
|
|
35
|
+
secrets resolution without exposing sensitive values in source.
|
|
36
|
+
|
|
37
|
+
constraints:
|
|
38
|
+
- All YAML files MUST be parseable with YAML.safe_load — no custom tags,
|
|
39
|
+
no permitted_classes, no extensions to the safe deserialisation surface
|
|
40
|
+
- Secret references use string convention "${secret:backend:key}" resolved
|
|
41
|
+
by deterministic string parser — never regex — to eliminate ReDoS vectors
|
|
42
|
+
- Secret resolution is single-pass only — resolved values are never
|
|
43
|
+
re-scanned for further references (prevents recursive injection)
|
|
44
|
+
- The secrets resolver MUST fail loudly (raise, never return nil) when a
|
|
45
|
+
referenced secret is missing or inaccessible
|
|
46
|
+
- File-backend secrets MUST validate 0600 permissions and reject files
|
|
47
|
+
owned by other users (prevent symlink/race attacks)
|
|
48
|
+
- File-backend secrets MUST enforce a size cap (64 KiB) to prevent
|
|
49
|
+
resource exhaustion from reading device files or oversized inputs
|
|
50
|
+
- Path-backend secrets MUST reject path traversal (no ".." components)
|
|
51
|
+
and validate against a whitelist of allowed directories
|
|
52
|
+
- Each YAML scope file compiles to exactly one native target — the
|
|
53
|
+
mapping is 1:1, never 1:many or many:1
|
|
54
|
+
- Configuration compilation follows the engine-plugin pattern — core
|
|
55
|
+
provides the abstract framework (BaseConfigCompiler), the engine
|
|
56
|
+
provides domain-specific transformation via config_compiler_class
|
|
57
|
+
- Core MUST NOT contain any engine-specific key mappings, scope routes,
|
|
58
|
+
or domain transformation logic — these belong in the engine gem
|
|
59
|
+
- No design or implementation in this document may contradict the security
|
|
60
|
+
design document (conf/design/security.yml)
|
|
61
|
+
|
|
62
|
+
acceptance_criteria:
|
|
63
|
+
# Core framework criteria
|
|
64
|
+
- rai config compile delegates to the active engine's config_compiler_class
|
|
65
|
+
via the plugin registry (RosettAi::Plugins::Registry)
|
|
66
|
+
- BaseConfigCompiler provides schema validation, SHA256 diffing, file I/O,
|
|
67
|
+
and compile result tracking that all engines inherit
|
|
68
|
+
- SecretResolver resolves ${secret:env:*}, ${secret:file:*}, and
|
|
69
|
+
${secret:path:*} references using deterministic string parsing (no regex)
|
|
70
|
+
- MaskingSecretResolver replaces all ${secret:*} values with "***" without
|
|
71
|
+
resolving actual secrets, used by rai config show
|
|
72
|
+
- The --simulate flag shows a diff of what would change in each target
|
|
73
|
+
file without writing anything
|
|
74
|
+
- The --verbose flag shows processing details during compilation
|
|
75
|
+
- CompileResult struct tracks scope, paths, json_data, warnings, action,
|
|
76
|
+
and diff for each compiled file
|
|
77
|
+
- Missing secrets cause compilation to abort with a clear error message
|
|
78
|
+
naming the missing reference and the file where it was declared
|
|
79
|
+
- No regex is used anywhere in the secrets resolution path
|
|
80
|
+
# Engine-side criteria (satisfied by rosett-ai-engine-claude)
|
|
81
|
+
- Engine provides ConfigCompiler, DomainTransformer, ScopeRouter, and
|
|
82
|
+
KeyMap classes that handle Claude Code-specific compilation
|
|
83
|
+
- Engine's ScopeRouter maps scope names to target file paths (managed,
|
|
84
|
+
user, project, local)
|
|
85
|
+
- Engine's DomainTransformer converts YAML domains to JSON using an
|
|
86
|
+
explicit KeyMap (snake_case to camelCase, not algorithmic)
|
|
87
|
+
- Engine checks version compatibility constraints against the installed
|
|
88
|
+
Claude Code version at compile time (warnings, not errors)
|
|
89
|
+
- RSpec tests exist for the compiler, schema validation, and secrets
|
|
90
|
+
resolver with mutant-verified kill rates
|
|
91
|
+
|
|
92
|
+
examples:
|
|
93
|
+
- scenario: User compiles their personal configuration
|
|
94
|
+
expected: >
|
|
95
|
+
"bin/raictl config compile" resolves the active engine via the plugin
|
|
96
|
+
registry, delegates to the engine's ConfigCompiler, resolves any
|
|
97
|
+
secret references, and writes the native settings file.
|
|
98
|
+
not: >
|
|
99
|
+
The compiler silently overwrites settings without showing what
|
|
100
|
+
changed, or leaves secret reference strings unresolved in the output
|
|
101
|
+
|
|
102
|
+
- scenario: A secret reference points to an unset environment variable
|
|
103
|
+
expected: >
|
|
104
|
+
Compilation aborts with "Error: secret 'env:ANTHROPIC_API_KEY'
|
|
105
|
+
could not be resolved — environment variable ANTHROPIC_API_KEY
|
|
106
|
+
is not set"
|
|
107
|
+
not: >
|
|
108
|
+
The compiler writes a file containing the literal string
|
|
109
|
+
"${secret:env:ANTHROPIC_API_KEY}" or a null/empty value
|
|
110
|
+
|
|
111
|
+
- scenario: No engine provides a config_compiler_class
|
|
112
|
+
expected: >
|
|
113
|
+
"bin/raictl config compile" raises an error explaining that the
|
|
114
|
+
active engine does not support configuration compilation
|
|
115
|
+
not: >
|
|
116
|
+
The command silently does nothing or crashes with a NoMethodError
|
|
117
|
+
|
|
118
|
+
- scenario: A crafted input attempts ReDoS via nested secret patterns
|
|
119
|
+
expected: >
|
|
120
|
+
The deterministic string parser processes it in O(n) time.
|
|
121
|
+
"${secret:env:${secret:env:NESTED}}" is treated as a literal string
|
|
122
|
+
because it does not match the exact prefix/suffix pattern
|
|
123
|
+
not: >
|
|
124
|
+
The parser enters catastrophic backtracking or hangs
|
|
125
|
+
|
|
126
|
+
- scenario: User runs config compile --simulate
|
|
127
|
+
expected: >
|
|
128
|
+
A diff is shown for each target file (additions in green, removals
|
|
129
|
+
in red) without writing any files to disk
|
|
130
|
+
not: >
|
|
131
|
+
Files are modified during simulation, or no output is shown
|
|
132
|
+
|
|
133
|
+
anti_patterns:
|
|
134
|
+
- Using regex for secret reference detection or resolution — use
|
|
135
|
+
deterministic string parsing (start_with?/end_with?/split) only
|
|
136
|
+
- Storing actual secret values in YAML source files, even temporarily
|
|
137
|
+
- Using YAML custom tags (!secret, !vault, etc.) which require
|
|
138
|
+
permitted_classes and widen the safe_load deserialisation surface
|
|
139
|
+
- Putting engine-specific key mappings or scope routes in core — these
|
|
140
|
+
belong in the engine gem
|
|
141
|
+
- Recursively resolving secret references (resolved values must never
|
|
142
|
+
be re-scanned for further ${secret:...} patterns)
|
|
143
|
+
- Silently ignoring missing secrets (returning nil or empty string)
|
|
144
|
+
- Writing compiled files when the source YAML has not changed
|
|
145
|
+
(wasteful I/O and misleading timestamps)
|
|
146
|
+
|
|
147
|
+
preferences:
|
|
148
|
+
language: ruby
|
|
149
|
+
testing: rspec with factory_bot and mutant-rspec
|
|
150
|
+
gems:
|
|
151
|
+
- psych
|
|
152
|
+
- json_schemer
|
|
153
|
+
- diffy
|
|
154
|
+
patterns:
|
|
155
|
+
- compiler_pattern
|
|
156
|
+
- resolver_pattern
|
|
157
|
+
- engine_plugin_delegation
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: compiler
|
|
3
|
+
domain: compiler
|
|
4
|
+
version: 2.0.0
|
|
5
|
+
status: draft
|
|
6
|
+
priority: 2
|
|
7
|
+
author: hugo
|
|
8
|
+
created_at: "2026-02-18"
|
|
9
|
+
modified_at: "2026-03-23"
|
|
10
|
+
modified_by: claude
|
|
11
|
+
depends_on:
|
|
12
|
+
- security
|
|
13
|
+
- architecture
|
|
14
|
+
- scope_hierarchy
|
|
15
|
+
|
|
16
|
+
intent: |
|
|
17
|
+
Define the compilation pipeline that transforms source documents (behaviours,
|
|
18
|
+
design specs, locale files) into target-specific output formats. This is the
|
|
19
|
+
core product capability of Rosett-AI: author once in the richest format, compile
|
|
20
|
+
down per AI target. The compiler must be pluggable to support new AI models
|
|
21
|
+
without code changes, and must enforce security constraints during all file
|
|
22
|
+
operations (safe YAML parsing, path validation, permission setting).
|
|
23
|
+
|
|
24
|
+
Compilation is scope-aware: the compiler resolves source directories from the
|
|
25
|
+
active scope hierarchy (global, local, project) before operating. Source files
|
|
26
|
+
are discovered from scope-appropriate directories, merged according to the
|
|
27
|
+
configured merge strategies, and written to scope-appropriate output locations
|
|
28
|
+
as declared by each engine's target profile. CLI flags (--global, --local,
|
|
29
|
+
--project) allow users to force a specific scope; without flags, the scope is
|
|
30
|
+
auto-detected from the user's working directory. See scope_hierarchy.yml for
|
|
31
|
+
the full scope specification.
|
|
32
|
+
|
|
33
|
+
constraints:
|
|
34
|
+
- All YAML parsing must use YAML.safe_load with explicit permitted_classes
|
|
35
|
+
- All output file writes must validate target path is within allowed directories
|
|
36
|
+
- All output files must be written with explicit permissions (0644)
|
|
37
|
+
- Compiler backends are pluggable via conf/targets/ profiles
|
|
38
|
+
- Source documents (conf/behaviour/, conf/design/) are never modified by compilation —
|
|
39
|
+
the sole exception is `rai retrofit`, which writes to source directories as a
|
|
40
|
+
controlled reverse-compilation operation (see retrofit.yml)
|
|
41
|
+
- Compilation must be idempotent (running twice produces identical output)
|
|
42
|
+
- Dry-run mode (--simulate) must never write to disk
|
|
43
|
+
- Verbose mode must never expose secrets or API keys in output
|
|
44
|
+
- Compilation errors must identify the source file and line/field that caused the error
|
|
45
|
+
- Locale compilation must produce platform-native formats (gettext, Qt Linguist)
|
|
46
|
+
- Compilation is scope-aware — source directories are resolved from the active
|
|
47
|
+
scope hierarchy (see scope_hierarchy.yml)
|
|
48
|
+
- CLI flags --global, --local, --project select a specific scope; without flags,
|
|
49
|
+
scope is auto-detected from the working directory
|
|
50
|
+
- "Each engine's target profile declares output directories: an absolute path
|
|
51
|
+
for global output and a relative path for scoped (local/project) output.
|
|
52
|
+
The compiler resolves the relative path against the active scope directory"
|
|
53
|
+
- Output target directory is never hardcoded — it is resolved from the engine's
|
|
54
|
+
target profile and the active scope
|
|
55
|
+
|
|
56
|
+
acceptance_criteria:
|
|
57
|
+
- bin/raictl compile produces output files in scope-resolved output directories
|
|
58
|
+
(e.g. ~/.claude/rules/ for global scope, <project>/.claude/rules/ for project scope)
|
|
59
|
+
- bin/raictl compile --engine claude produces CLAUDE.md-compatible markdown rules
|
|
60
|
+
- bin/raictl compile --engine generic produces lowest-common-denominator markdown
|
|
61
|
+
- bin/raictl compile --simulate --verbose shows scope-resolved source directories,
|
|
62
|
+
target output paths, and diffs — without writing any files
|
|
63
|
+
- bin/raictl compile --vendor writes a lockfile recording compiled state
|
|
64
|
+
- bin/raictl compile --locales compiles ruby-i18n YAML to gettext and Qt formats
|
|
65
|
+
- Adding a new target profile in conf/targets/ requires no code changes
|
|
66
|
+
- Invalid source documents produce clear error messages identifying the problem
|
|
67
|
+
- Compilation of 100 behaviour files completes in under 5 seconds
|
|
68
|
+
- bin/raictl compile --global compiles only global-scope sources to global output
|
|
69
|
+
- bin/raictl compile --local compiles merged global+local sources to local output
|
|
70
|
+
- bin/raictl compile --project compiles merged global+local+project sources to project output
|
|
71
|
+
- bin/raictl compile (no flag) auto-detects scope from working directory
|
|
72
|
+
- Compiler resolves source directory from the active scope before reading any files
|
|
73
|
+
- "Each engine's target profile declares output directories (global absolute,
|
|
74
|
+
scoped relative) — see scope_hierarchy.yml and engine_architecture.yml"
|
|
75
|
+
|
|
76
|
+
examples:
|
|
77
|
+
- scenario: "User runs bin/raictl compile from a project directory"
|
|
78
|
+
expected: |
|
|
79
|
+
Resolves scope from working directory: discovers project, local (if present),
|
|
80
|
+
and global source directories. Merges sources per scope hierarchy. Compiles
|
|
81
|
+
to project-scope output directory (e.g. <project>/.claude/rules/).
|
|
82
|
+
Sets 0644 permissions. Reports count of compiled rules and active scope.
|
|
83
|
+
not: "Ignores working directory. Always compiles from rosett-ai's own conf/."
|
|
84
|
+
- scenario: "User runs bin/raictl compile --engine mistral"
|
|
85
|
+
expected: |
|
|
86
|
+
Reads conf/targets/mistral.yml for model capabilities. Compiles behaviours
|
|
87
|
+
to flat markdown format (no YAML in prompt). Truncates or chunks if output
|
|
88
|
+
exceeds max_context. Writes to configured output location.
|
|
89
|
+
not: "Uses Claude-specific formatting for Mistral. Ignores context window limits."
|
|
90
|
+
- scenario: "A behaviour file has invalid YAML syntax"
|
|
91
|
+
expected: |
|
|
92
|
+
Compilation stops for that file. Error message includes filename and
|
|
93
|
+
parse error details. Other valid files still compile. Exit code is non-zero.
|
|
94
|
+
not: "YAML.load is used and succeeds despite syntax issues. Error is swallowed."
|
|
95
|
+
- scenario: "User runs bin/raictl compile --simulate --verbose"
|
|
96
|
+
expected: |
|
|
97
|
+
Shows scope resolution: 'Scope: project (~/projects/acme-api/.rosett-ai/)'.
|
|
98
|
+
Shows source directories per scope. Shows diff of what would change
|
|
99
|
+
on disk at scope-resolved output paths. Zero files written. Exit code 0.
|
|
100
|
+
not: "Actually writes files despite --simulate flag. Omits scope information."
|
|
101
|
+
- scenario: "User runs bin/raictl compile --global"
|
|
102
|
+
expected: |
|
|
103
|
+
Compiles only global-scope sources (~/.config/rosett-ai/conf/) to global
|
|
104
|
+
output directories. Local and project scopes are ignored even if
|
|
105
|
+
.rosett-ai/ markers exist in the current directory tree.
|
|
106
|
+
not: "Merges all scopes. Project-specific rules appear in global output."
|
|
107
|
+
|
|
108
|
+
anti_patterns:
|
|
109
|
+
- Using YAML.load instead of YAML.safe_load during compilation
|
|
110
|
+
- Writing output to arbitrary paths without validation
|
|
111
|
+
- Modifying source documents during compilation
|
|
112
|
+
- Hardcoding AI model assumptions instead of reading target profiles
|
|
113
|
+
- Silently skipping invalid source documents without error reporting
|
|
114
|
+
- Non-idempotent compilation (different output on repeated runs with same input)
|
|
115
|
+
- Hardcoding output directory (e.g. ~/.claude/rules/) instead of resolving from scope
|
|
116
|
+
- Assuming a single fixed source directory for all invocations
|
|
117
|
+
- Ignoring --global/--local/--project flags
|
|
118
|
+
|
|
119
|
+
preferences:
|
|
120
|
+
language: ruby
|
|
121
|
+
patterns:
|
|
122
|
+
- strategy_pattern_for_target_backends
|
|
123
|
+
- pipeline_pattern_for_compilation_stages
|
|
124
|
+
- value_objects_for_compiled_output
|
|
125
|
+
testing: rspec with file-based fixtures for input/output validation
|
|
126
|
+
gems:
|
|
127
|
+
- json_schemer
|
|
128
|
+
- diffy
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: comply
|
|
3
|
+
domain: security
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
status: implemented
|
|
6
|
+
priority: 2
|
|
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
|
+
- licensing_system
|
|
14
|
+
- policy_management
|
|
15
|
+
- error_handling
|
|
16
|
+
- engine_architecture
|
|
17
|
+
#
|
|
18
|
+
intent: |
|
|
19
|
+
Automate compliance checks for EU CRA and NIS2 directives, GPL-3.0
|
|
20
|
+
licensing requirements, and organisational policy adherence. Surface
|
|
21
|
+
compliance gaps before release rather than after deployment by providing
|
|
22
|
+
CRA vulnerability disclosure verification, SBOM generation, SPDX header
|
|
23
|
+
checks, and dependency license auditing through a single `rai comply`
|
|
24
|
+
command with machine-readable output for CI integration.
|
|
25
|
+
|
|
26
|
+
SBOM generation is a core capability: `rai comply --sbom` produces a
|
|
27
|
+
CycloneDX JSON document from Gemfile.lock and system metadata using the
|
|
28
|
+
syft CLI (when available) or a built-in Ruby fallback that parses
|
|
29
|
+
Gemfile.lock directly. The SBOM includes component name, version, PURL,
|
|
30
|
+
license SPDX identifier, and supplier. SPDX-format output is also
|
|
31
|
+
supported via `--sbom-format spdx` for organisations that mandate SPDX
|
|
32
|
+
over CycloneDX. SBOM output is written to a configurable path (default
|
|
33
|
+
`sbom.cdx.json` or `sbom.spdx.json` in the project root).
|
|
34
|
+
|
|
35
|
+
Comply is the compliance verification layer. It runs checks against
|
|
36
|
+
declarative rules. Policy management (policy_management.yml) defines
|
|
37
|
+
what policies apply to a project. Comply verifies that the project
|
|
38
|
+
meets those policies and produces an auditable report.
|
|
39
|
+
#
|
|
40
|
+
constraints:
|
|
41
|
+
- "CRA checks must not require network access by default — offline SBOM
|
|
42
|
+
analysis"
|
|
43
|
+
- "License audit must detect GPL-incompatible dependencies in the full
|
|
44
|
+
dependency tree"
|
|
45
|
+
- "SPDX header verification must support Ruby, YAML, JSON, Bash, and
|
|
46
|
+
Markdown files"
|
|
47
|
+
- "Output must be machine-readable (JSON/YAML) for CI integration and
|
|
48
|
+
TTY-aware (formatted table when interactive, structured data when piped)"
|
|
49
|
+
- "Must not store or transmit any proprietary compliance data"
|
|
50
|
+
- "Compliance rules must be declarative YAML, not hardcoded"
|
|
51
|
+
- "SBOM generation must work offline using Gemfile.lock as primary source —
|
|
52
|
+
syft CLI is optional (used when available for richer metadata)"
|
|
53
|
+
- "SBOM output must conform to CycloneDX 1.5 JSON schema or SPDX 2.3 JSON
|
|
54
|
+
schema depending on --sbom-format flag"
|
|
55
|
+
- "SBOM must include PURL (Package URL) identifiers for all components"
|
|
56
|
+
- "Exit code must distinguish pass (0), warning (1), and failure (2)
|
|
57
|
+
for CI pipelines"
|
|
58
|
+
- "This design governs compliance verification (checking adherence).
|
|
59
|
+
Policy definition and governance is handled by policy_management.yml.
|
|
60
|
+
Licensing system mechanics are handled by licensing_system.yml"
|
|
61
|
+
#
|
|
62
|
+
acceptance_criteria:
|
|
63
|
+
- "`rai comply` runs all compliance checks and produces a summary report"
|
|
64
|
+
- "`rai comply --cra` checks CRA-specific requirements (SBOM, vulnerability
|
|
65
|
+
policy)"
|
|
66
|
+
- "`rai comply --license` audits dependency licenses against GPL-3.0
|
|
67
|
+
compatibility"
|
|
68
|
+
- "`rai comply --headers` verifies SPDX headers on all source files"
|
|
69
|
+
- "`rai comply --format json` outputs machine-readable results"
|
|
70
|
+
- "CI pipeline can gate releases on compliance check exit code"
|
|
71
|
+
- "Compliance rules are loaded from conf/compliance/*.yml"
|
|
72
|
+
- "`rai comply --sbom` generates a CycloneDX 1.5 JSON SBOM from Gemfile.lock"
|
|
73
|
+
- "`rai comply --sbom --sbom-format spdx` generates an SPDX 2.3 JSON SBOM"
|
|
74
|
+
- "SBOM includes component name, version, PURL, license SPDX ID, and supplier"
|
|
75
|
+
- "SBOM generation works offline without syft (Ruby fallback parser)"
|
|
76
|
+
- "TTY-aware summary shows pass/warn/fail counts in colour when
|
|
77
|
+
interactive, plain counts when piped"
|
|
78
|
+
- "Exit code 0 on all pass, 1 on warnings only, 2 on any failure"
|
|
79
|
+
#
|
|
80
|
+
examples:
|
|
81
|
+
- scenario: "Developer runs `rai comply` before tagging a release"
|
|
82
|
+
expected: |
|
|
83
|
+
All checks pass; SBOM is current; all files have SPDX headers.
|
|
84
|
+
Summary: 12 checks passed, 0 warnings, 0 failures.
|
|
85
|
+
not: "Missing headers silently ignored or only warned about"
|
|
86
|
+
- scenario: "A new gem dependency has an AGPL-3.0 license"
|
|
87
|
+
expected: |
|
|
88
|
+
License audit flags it as potentially GPL-incompatible and explains
|
|
89
|
+
why: 'AGPL-3.0 imposes network copyleft obligations that may conflict
|
|
90
|
+
with GPL-3.0-only. Review and add to allowlist or replace dependency.'
|
|
91
|
+
not: "Silent acceptance of incompatible licenses"
|
|
92
|
+
- scenario: "Running in CI without internet access"
|
|
93
|
+
expected: |
|
|
94
|
+
Offline checks complete successfully using cached SBOM data.
|
|
95
|
+
Network-dependent checks (e.g. NVD lookup) are skipped with warning.
|
|
96
|
+
not: "Failure because NVD or other remote service is unreachable"
|
|
97
|
+
- scenario: "Developer generates SBOM for CRA compliance"
|
|
98
|
+
expected: |
|
|
99
|
+
`rai comply --sbom` produces sbom.cdx.json in CycloneDX 1.5 format.
|
|
100
|
+
Each component includes name, version, PURL, and license. Output
|
|
101
|
+
validates against the CycloneDX JSON schema.
|
|
102
|
+
not: |
|
|
103
|
+
SBOM generation requires internet access. Missing gems are silently
|
|
104
|
+
omitted. Output is an invalid CycloneDX document.
|
|
105
|
+
- scenario: "Compliance report in CI pipeline"
|
|
106
|
+
expected: |
|
|
107
|
+
`rai comply --format json` outputs structured results parseable by
|
|
108
|
+
CI tools. Exit code 2 triggers pipeline failure. Report includes
|
|
109
|
+
each check's name, status, and resolution guidance.
|
|
110
|
+
not: "Human-readable text output that CI cannot parse."
|
|
111
|
+
#
|
|
112
|
+
anti_patterns:
|
|
113
|
+
- "Hardcoding compliance rules in Ruby — use declarative YAML configs"
|
|
114
|
+
- "Requiring internet access for basic compliance checks"
|
|
115
|
+
- "Treating warnings as informational-only — they must have a clear
|
|
116
|
+
resolution path"
|
|
117
|
+
- "Mixing legal advice into tool output — report facts, not interpretations"
|
|
118
|
+
- "Coupling compliance checks to a specific engine's config format"
|
|
119
|
+
#
|
|
120
|
+
gui_notes: |
|
|
121
|
+
Document interactions (cross-references):
|
|
122
|
+
|
|
123
|
+
1. policy_management.yml: policies define what applies; comply verifies
|
|
124
|
+
adherence and produces reports.
|
|
125
|
+
|
|
126
|
+
2. licensing_system.yml: licensing mechanics (key management, activation).
|
|
127
|
+
Comply checks license compatibility of dependencies.
|
|
128
|
+
|
|
129
|
+
3. security.yml: comply enforces security-adjacent requirements (SPDX
|
|
130
|
+
headers, vulnerability disclosure).
|
|
131
|
+
|
|
132
|
+
4. error_handling.yml: exit codes and structured error messages follow
|
|
133
|
+
the error hierarchy.
|
|
134
|
+
|
|
135
|
+
5. engine_architecture.yml: compliance rules may reference engine
|
|
136
|
+
capabilities or engine-specific outputs.
|
|
137
|
+
|
|
138
|
+
6. distribution.yml: comply gates release publishing — CI runs comply
|
|
139
|
+
before deploy:publish.
|
|
140
|
+
#
|
|
141
|
+
preferences:
|
|
142
|
+
language: ruby
|
|
143
|
+
patterns:
|
|
144
|
+
- "Command pattern for individual check types"
|
|
145
|
+
- "Declarative YAML for compliance rule definitions"
|
|
146
|
+
- "Array-form system() for any shell-out to SBOM tools"
|
|
147
|
+
- "TTY-aware output (TtyHelper)"
|
|
148
|
+
testing: rspec with compliance rule fixtures, license compatibility
|
|
149
|
+
scenarios, SPDX header detection, and CI output format tests
|
|
150
|
+
gems:
|
|
151
|
+
- license_finder
|
|
152
|
+
- json_schemer
|
|
153
|
+
- thor
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: content_packs
|
|
3
|
+
domain: licensing
|
|
4
|
+
version: 1.1.0
|
|
5
|
+
status: implemented
|
|
6
|
+
priority: 4
|
|
7
|
+
author: hugo
|
|
8
|
+
created_at: "2026-02-18"
|
|
9
|
+
modified_at: "2026-03-17"
|
|
10
|
+
modified_by: claude
|
|
11
|
+
depends_on:
|
|
12
|
+
- security
|
|
13
|
+
- licensing_system
|
|
14
|
+
- compiler
|
|
15
|
+
|
|
16
|
+
intent: |
|
|
17
|
+
Define the premium content pack system that delivers curated behaviours,
|
|
18
|
+
design patterns, and AI target profiles to licensed users. Content packs
|
|
19
|
+
are signed tarballs of YAML files with manifests, downloaded from a content
|
|
20
|
+
server and cached locally. The system must work offline after initial
|
|
21
|
+
download. Content packs are licensed under the NeatNerds Content License
|
|
22
|
+
(separate from GPL-3.0), and are data consumed by the software, not
|
|
23
|
+
derivative works of it.
|
|
24
|
+
|
|
25
|
+
constraints:
|
|
26
|
+
- Content packs are signed with the same Ed25519 key pair used for license keys
|
|
27
|
+
- Content pack signatures must be verified before installation
|
|
28
|
+
- Content is stored locally in ~/.config/rosett-ai/premium/ after download
|
|
29
|
+
- Content packs must work offline after initial download
|
|
30
|
+
- Content pack manifests are YAML validated against schema
|
|
31
|
+
- Tier entitlement is checked before download (not after)
|
|
32
|
+
- Content packs are YAML files — no executable code in packs
|
|
33
|
+
- Content pack installation must not modify core rosett-ai files or configuration
|
|
34
|
+
- All content pack YAML must be parsed with YAML.safe_load
|
|
35
|
+
|
|
36
|
+
acceptance_criteria:
|
|
37
|
+
- bin/raictl content list shows available packs for current license tier
|
|
38
|
+
- bin/raictl content list --available shows packs at all tiers (with tier labels)
|
|
39
|
+
- bin/raictl content install security_pack downloads, verifies, and installs pack
|
|
40
|
+
- bin/raictl content update re-downloads all installed packs (subscriber tier)
|
|
41
|
+
- Signature verification rejects tampered content packs
|
|
42
|
+
- Installed packs work without internet after download
|
|
43
|
+
- Content pack manifest schema exists in conf/schemas/
|
|
44
|
+
- bin/raictl compile integrates premium behaviours alongside core behaviours
|
|
45
|
+
|
|
46
|
+
examples:
|
|
47
|
+
- scenario: "Supporter installs the security_behaviours content pack"
|
|
48
|
+
expected: |
|
|
49
|
+
License tier verified (supporter >= supporter). Pack downloaded from
|
|
50
|
+
content server. Ed25519 signature verified. Tarball extracted to
|
|
51
|
+
~/.config/rosett-ai/premium/security_behaviours/. Manifest validated.
|
|
52
|
+
'Installed security_behaviours v2.1.0 (4 behaviours, 2 designs).'
|
|
53
|
+
not: "Pack installed without signature check. Arbitrary code executed from pack."
|
|
54
|
+
- scenario: "Community user tries to install a supporter-tier pack"
|
|
55
|
+
expected: |
|
|
56
|
+
'security_behaviours requires Supporter tier. Your tier: Community.
|
|
57
|
+
Visit https://neatnerds.be/rosett-ai/pricing for upgrade options.'
|
|
58
|
+
not: "Pack downloads but fails silently. Error message is unclear about tier."
|
|
59
|
+
- scenario: "Content pack tarball has been tampered with"
|
|
60
|
+
expected: "Ed25519 signature verification fails. 'Content pack signature invalid. Pack not installed.'"
|
|
61
|
+
not: "Tampered pack is installed. YAML with unexpected content is loaded."
|
|
62
|
+
- scenario: "Subscriber runs bin/raictl content update while offline"
|
|
63
|
+
expected: "Graceful failure: 'Cannot reach content server. Existing content packs unchanged.'"
|
|
64
|
+
not: "Crash. Existing content deleted. Error without explanation."
|
|
65
|
+
|
|
66
|
+
anti_patterns:
|
|
67
|
+
- Including executable code (Ruby, shell) in content packs
|
|
68
|
+
- Installing packs without signature verification
|
|
69
|
+
- Requiring internet on every rosett-ai run to validate content
|
|
70
|
+
- Deleting local content when server is unreachable
|
|
71
|
+
- Mixing premium content with core rosett-ai files
|
|
72
|
+
- Using YAML.load to parse content pack files
|
|
73
|
+
|
|
74
|
+
preferences:
|
|
75
|
+
language: ruby
|
|
76
|
+
gems:
|
|
77
|
+
- faraday
|
|
78
|
+
- ed25519
|
|
79
|
+
- minitar
|
|
80
|
+
patterns:
|
|
81
|
+
- offline_first_caching
|
|
82
|
+
- signed_content_distribution
|
|
83
|
+
- schema_validated_manifests
|
|
84
|
+
testing: rspec with fixtures for valid, tampered, and unsigned packs
|