rosett-ai 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (527) hide show
  1. checksums.yaml +7 -0
  2. data/.ai-provenance.yml +119 -0
  3. data/.debride_whitelist +186 -0
  4. data/.fasterer.yml +29 -0
  5. data/.mdl_style.rb +10 -0
  6. data/.mdlrc +3 -0
  7. data/.mutant.yml +49 -0
  8. data/.namespace-allowlist +42 -0
  9. data/.reek.yml +1040 -0
  10. data/.rosett-ai/config.yml +3 -0
  11. data/.rspec +5 -0
  12. data/.rubocop.yml +380 -0
  13. data/.ruby-version +1 -0
  14. data/.yamllint +51 -0
  15. data/.yardopts +12 -0
  16. data/AI-DISCLOSURE.md +48 -0
  17. data/CHANGELOG.md +519 -0
  18. data/CLAUDE.md +141 -0
  19. data/CONTRIBUTING.md +734 -0
  20. data/INSTALL.md +154 -0
  21. data/LICENSE +674 -0
  22. data/LICENSE.md +675 -0
  23. data/QUICKSTART.md +73 -0
  24. data/README.md +366 -0
  25. data/Rakefile +200 -0
  26. data/SECURITY.md +114 -0
  27. data/bin/rai +1 -0
  28. data/cliff.toml +52 -0
  29. data/conf/adopt_redactions.yml +8 -0
  30. data/conf/behaviour/.gitkeep +0 -0
  31. data/conf/compliance/cra_rules.yml +25 -0
  32. data/conf/compliance/license_rules.yml +20 -0
  33. data/conf/design/aaif_alignment.yml +181 -0
  34. data/conf/design/ab_testing.yml +172 -0
  35. data/conf/design/accessibility.yml +84 -0
  36. data/conf/design/ai_authorship.yml +210 -0
  37. data/conf/design/ai_provenance.yml +224 -0
  38. data/conf/design/ai_tool_configuration.yml +207 -0
  39. data/conf/design/architecture.yml +139 -0
  40. data/conf/design/autocompletion.yml +115 -0
  41. data/conf/design/backward_compatibility.yml +112 -0
  42. data/conf/design/behaviour_composition.yml +246 -0
  43. data/conf/design/build_rake_extraction.yml +57 -0
  44. data/conf/design/ci_pipeline.yml +100 -0
  45. data/conf/design/claude_code_configuration.yml +157 -0
  46. data/conf/design/compiler.yml +128 -0
  47. data/conf/design/comply.yml +153 -0
  48. data/conf/design/content_packs.yml +84 -0
  49. data/conf/design/desktop_integration.yml +289 -0
  50. data/conf/design/distribution.yml +216 -0
  51. data/conf/design/doctor.yml +184 -0
  52. data/conf/design/documentation.yml +152 -0
  53. data/conf/design/engine_architecture.yml +257 -0
  54. data/conf/design/error_handling.yml +103 -0
  55. data/conf/design/feature_flags.yml +142 -0
  56. data/conf/design/git_hooks.yml +165 -0
  57. data/conf/design/gui_plugins.yml +475 -0
  58. data/conf/design/i18n.yml +84 -0
  59. data/conf/design/integration_testing.yml +56 -0
  60. data/conf/design/licensing_system.yml +88 -0
  61. data/conf/design/lifecycle_management.yml +208 -0
  62. data/conf/design/mcp_integration.yml +207 -0
  63. data/conf/design/mcp_settings.yml +126 -0
  64. data/conf/design/migration.yml +56 -0
  65. data/conf/design/monitoring_observability.yml +194 -0
  66. data/conf/design/namespace_cleanup.yml +145 -0
  67. data/conf/design/plugin_test_segregation.yml +145 -0
  68. data/conf/design/policy_management.yml +229 -0
  69. data/conf/design/project_management.yml +183 -0
  70. data/conf/design/rai_mcp_asset_discovery.yml +164 -0
  71. data/conf/design/rai_mcp_server.yml +605 -0
  72. data/conf/design/release_management.yml +117 -0
  73. data/conf/design/retrofit.yml +199 -0
  74. data/conf/design/retrospective_analyzer.yml +79 -0
  75. data/conf/design/scope_hierarchy.yml +352 -0
  76. data/conf/design/security.yml +115 -0
  77. data/conf/design/session_retrospective.yml +85 -0
  78. data/conf/design/smart_ui_feedback.yml +89 -0
  79. data/conf/design/structured_logging.yml +148 -0
  80. data/conf/design/styles.yml +123 -0
  81. data/conf/design/test_peer_review.yml +89 -0
  82. data/conf/design/testing.yml +136 -0
  83. data/conf/design/threat_model.yml +108 -0
  84. data/conf/design/ui_framework.yml +111 -0
  85. data/conf/design/usage_optimization.yml +122 -0
  86. data/conf/design/version_management.yml +60 -0
  87. data/conf/design/workflow.yml +227 -0
  88. data/conf/mcp/server_defaults.yml +42 -0
  89. data/conf/mcp/trust.yml +21 -0
  90. data/conf/packaging/core.yml +12 -0
  91. data/conf/packaging/gtk4.yml +11 -0
  92. data/conf/packaging/qt6.yml +11 -0
  93. data/conf/policy/default_deny_list.yml +197 -0
  94. data/conf/review/cli-command-audit.yml +857 -0
  95. data/conf/review/design-docs.yml +1064 -0
  96. data/conf/review/design-questionnaire.yml +153 -0
  97. data/conf/review/questionnaire.yml +146 -0
  98. data/conf/review/rosett-ai-core.yml +2919 -0
  99. data/conf/schemas/ai_config_schema.json +73 -0
  100. data/conf/schemas/behaviour_schema.json +132 -0
  101. data/conf/schemas/compliance_rule_schema.json +63 -0
  102. data/conf/schemas/content_pack_manifest_schema.json +51 -0
  103. data/conf/schemas/design_schema.json +210 -0
  104. data/conf/schemas/engine_manifest_schema.json +144 -0
  105. data/conf/schemas/lockfile_schema.json +74 -0
  106. data/conf/schemas/mcp_server_schema.json +48 -0
  107. data/conf/schemas/packaging_schema.json +70 -0
  108. data/conf/schemas/policy_schema.json +85 -0
  109. data/conf/schemas/provenance_schema.json +84 -0
  110. data/conf/schemas/rai_config_schema.json +56 -0
  111. data/conf/schemas/rai_project_schema.json +20 -0
  112. data/conf/schemas/scope_hierarchy_schema.json +49 -0
  113. data/conf/schemas/target_schema.json +67 -0
  114. data/conf/schemas/tooling_schema.json +65 -0
  115. data/conf/schemas/workflow_schema.json +112 -0
  116. data/conf/targets/agents_md.yml +17 -0
  117. data/conf/targets/claude.yml +12 -0
  118. data/conf/tooling/tools.yml +58 -0
  119. data/dist/rosett-ai-mcp.service +48 -0
  120. data/dist/rosett-ai-mcp.yml.default +45 -0
  121. data/doc/AAIF_POSITIONING.md +58 -0
  122. data/doc/ADOPT.md +224 -0
  123. data/doc/AI_PROVENANCE.md +139 -0
  124. data/doc/ARCHITECTURE.md +920 -0
  125. data/doc/BEHAVIOUR.md +409 -0
  126. data/doc/BUILD.md +138 -0
  127. data/doc/CI_CD_RECIPES.md +171 -0
  128. data/doc/CLAUDE_SESSIONS_MOVED.md +16 -0
  129. data/doc/COMMAND_ANALYSIS.md +229 -0
  130. data/doc/CONFIGURATION.md +281 -0
  131. data/doc/DESIGN_AUDIT.md +235 -0
  132. data/doc/DESIGN_PEER_REVIEW.md +771 -0
  133. data/doc/DESKTOP.md +447 -0
  134. data/doc/ENGINES.md +567 -0
  135. data/doc/ENGINE_DEVELOPMENT_GUIDE.md +417 -0
  136. data/doc/FEATURE_AUDIT.md +218 -0
  137. data/doc/IMPLEMENTATION_PLAN.md +669 -0
  138. data/doc/INCIDENT_REPORT_2026-02-02.md +251 -0
  139. data/doc/MIGRATION_GUIDE.md +88 -0
  140. data/doc/PACKAGING.md +232 -0
  141. data/doc/PROJECT_DASHBOARD.md +153 -0
  142. data/doc/PULP_DEPLOYMENT.md +164 -0
  143. data/doc/QUALITY_FIX_SUMMARY.md +110 -0
  144. data/doc/QUICK_START.md +162 -0
  145. data/doc/REEK_CONFIGURATION.md +166 -0
  146. data/doc/REFERENCE.md +253 -0
  147. data/doc/REFERENCES.md +324 -0
  148. data/doc/SECURITY_REVIEW_CHECKLIST.md +72 -0
  149. data/doc/SESSION_2026-02-28_GTK4_HARDENING.md +359 -0
  150. data/doc/SETUP.md +202 -0
  151. data/doc/TEST_PEER_REVIEW.md +152 -0
  152. data/doc/THREAT_MODEL.md +230 -0
  153. data/doc/USAGE.md +545 -0
  154. data/doc/USER_MANUAL.md +585 -0
  155. data/doc/ai_test_review_checklist.md +110 -0
  156. data/doc/changes/2026-02-18-packaging-fpm.md +155 -0
  157. data/doc/changes/2026-02-19-testing-infrastructure.md +221 -0
  158. data/doc/changes/2026-02-20-security-implementation.md +281 -0
  159. data/doc/changes/2026-02-20-styles-implementation.md +220 -0
  160. data/doc/changes/2026-02-21-architecture-completion.md +95 -0
  161. data/doc/changes/2026-02-21-architecture-ui-layer.md +253 -0
  162. data/doc/changes/2026-02-21-cc-config-implementation.md +108 -0
  163. data/doc/changes/2026-02-21-ci-pipeline-implementation.md +214 -0
  164. data/doc/changes/2026-02-21-compiler-multi-target-pipeline.md +241 -0
  165. data/doc/changes/2026-02-21-config-design-show-commands.md +61 -0
  166. data/doc/changes/2026-02-21-design-implementation-overview.md +455 -0
  167. data/doc/changes/2026-02-21-lifecycle-management.md +196 -0
  168. data/doc/changes/2026-02-21-path-resolver.md +128 -0
  169. data/doc/changes/2026-02-24-ci-tmpdir-mutant-fetch.md +45 -0
  170. data/doc/changes/2026-03-01-ci-bundler-strategy.md +120 -0
  171. data/doc/changes/2026-03-20-security-hardening-phase2.md +163 -0
  172. data/doc/context/SESSION-HANDOFF.md +69 -0
  173. data/doc/context/ai-engine-usage-trends-2026.md +80 -0
  174. data/doc/context/plan-pluggable-engines.md +590 -0
  175. data/doc/decisions/001-flog-deferred.md +32 -0
  176. data/doc/decisions/002-path-resolution-strategy.md +158 -0
  177. data/doc/decisions/003-ui-adapter-selection.md +193 -0
  178. data/doc/decisions/004-design-document-validation.md +179 -0
  179. data/doc/decisions/005-package-splitting-strategy.md +200 -0
  180. data/doc/decisions/006-multi-engine-architecture.md +147 -0
  181. data/doc/decisions/007-engine-agnostic-pivot.md +219 -0
  182. data/doc/decisions/008-ci-bundler-strategy.md +129 -0
  183. data/doc/decisions/009-core-only-v1-release.md +60 -0
  184. data/doc/decisions/010-engine-debian-packaging.md +66 -0
  185. data/doc/decisions/011-context-aware-cli.md +71 -0
  186. data/doc/dependency_decisions.yml +247 -0
  187. data/doc/issues/001-wrapper-missing-environment-variables.md +197 -0
  188. data/doc/issues/002-embedded-ruby-wrong-prefix.md +217 -0
  189. data/doc/issues/003-smoke-test-false-positive.md +127 -0
  190. data/doc/issues/004-market-research-design-updates.md +109 -0
  191. data/doc/issues/005-compile-scope-coexistence.md +161 -0
  192. data/doc/locales/.gitkeep +0 -0
  193. data/doc/man/rai.1.ronn +505 -0
  194. data/doc/operations/packaging.md +133 -0
  195. data/doc/operations/rosett-ai-release.md +65 -0
  196. data/doc/reference/error-catalog.md +107 -0
  197. data/doc/reference/rosett-ai-technical-reference.pdf +0 -0
  198. data/doc/reference/src/Pictures/cover.jpg +0 -0
  199. data/doc/reference/src/Pictures/head1.jpg +0 -0
  200. data/doc/reference/src/Pictures/head2.jpg +0 -0
  201. data/doc/reference/src/Pictures/head3.jpg +0 -0
  202. data/doc/reference/src/Pictures/head4.jpg +0 -0
  203. data/doc/reference/src/Pictures/head5.jpg +0 -0
  204. data/doc/reference/src/Pictures/head6.jpg +0 -0
  205. data/doc/reference/src/Pictures/head7.jpg +0 -0
  206. data/doc/reference/src/Pictures/head8.jpg +0 -0
  207. data/doc/reference/src/StyleInd.ist +4 -0
  208. data/doc/reference/src/bibliography.bib +79 -0
  209. data/doc/reference/src/main.tex +1288 -0
  210. data/doc/reference/src/structure.tex +303 -0
  211. data/doc/rosett-ai-bookmarks.html +301 -0
  212. data/kitchen.yml +46 -0
  213. data/lib/rosett_ai/adopter/executor_resolver.rb +77 -0
  214. data/lib/rosett_ai/adopter/local_analysis_collector.rb +154 -0
  215. data/lib/rosett_ai/adopter/rule_adopter.rb +254 -0
  216. data/lib/rosett_ai/ai_config/config_compiler.rb +111 -0
  217. data/lib/rosett_ai/ai_config/context_window.rb +55 -0
  218. data/lib/rosett_ai/ai_config/cost_controls.rb +44 -0
  219. data/lib/rosett_ai/ai_config/fallback_chain.rb +64 -0
  220. data/lib/rosett_ai/ai_config/model_router.rb +121 -0
  221. data/lib/rosett_ai/ai_config/validator.rb +45 -0
  222. data/lib/rosett_ai/authorship/attribution_compiler.rb +99 -0
  223. data/lib/rosett_ai/authorship/disclosure_policy.rb +81 -0
  224. data/lib/rosett_ai/authorship/review_validator.rb +39 -0
  225. data/lib/rosett_ai/authorship/trailer_generator.rb +88 -0
  226. data/lib/rosett_ai/backup/compressor.rb +180 -0
  227. data/lib/rosett_ai/backup/destination.rb +91 -0
  228. data/lib/rosett_ai/behaviour/manager.rb +156 -0
  229. data/lib/rosett_ai/compiler/backend.rb +86 -0
  230. data/lib/rosett_ai/compiler/backends/agents_md_backend.rb +80 -0
  231. data/lib/rosett_ai/compiler/backends/claude_backend.rb +88 -0
  232. data/lib/rosett_ai/compiler/backends/generic_backend.rb +15 -0
  233. data/lib/rosett_ai/compiler/behaviour_compiler.rb +40 -0
  234. data/lib/rosett_ai/compiler/capability_checker.rb +104 -0
  235. data/lib/rosett_ai/compiler/compilation_pipeline.rb +361 -0
  236. data/lib/rosett_ai/compiler/compiled_output.rb +39 -0
  237. data/lib/rosett_ai/compiler/locale_compiler.rb +250 -0
  238. data/lib/rosett_ai/compiler/target_profile.rb +112 -0
  239. data/lib/rosett_ai/completion/generator.rb +101 -0
  240. data/lib/rosett_ai/completion/shells/bash_generator.rb +126 -0
  241. data/lib/rosett_ai/completion/shells/fish_generator.rb +78 -0
  242. data/lib/rosett_ai/completion/shells/zsh_generator.rb +126 -0
  243. data/lib/rosett_ai/comply/checkers/cra_checker.rb +102 -0
  244. data/lib/rosett_ai/comply/checkers/license_checker.rb +85 -0
  245. data/lib/rosett_ai/comply/checkers/spdx_header_checker.rb +98 -0
  246. data/lib/rosett_ai/comply/reporter.rb +113 -0
  247. data/lib/rosett_ai/comply/runner.rb +50 -0
  248. data/lib/rosett_ai/composition/circular_dependency_detector.rb +56 -0
  249. data/lib/rosett_ai/composition/composer.rb +158 -0
  250. data/lib/rosett_ai/composition/composition_result.rb +64 -0
  251. data/lib/rosett_ai/composition/conflict_detector.rb +53 -0
  252. data/lib/rosett_ai/composition/lockfile.rb +103 -0
  253. data/lib/rosett_ai/composition/merge_strategy.rb +131 -0
  254. data/lib/rosett_ai/composition/priority_sorter.rb +29 -0
  255. data/lib/rosett_ai/composition/scope_resolver.rb +55 -0
  256. data/lib/rosett_ai/config/compile_result.rb +37 -0
  257. data/lib/rosett_ai/config/compiler.rb +13 -0
  258. data/lib/rosett_ai/config/domain_transformer.rb +13 -0
  259. data/lib/rosett_ai/config/key_map.rb +13 -0
  260. data/lib/rosett_ai/config/masking_secret_resolver.rb +40 -0
  261. data/lib/rosett_ai/config/scope_router.rb +13 -0
  262. data/lib/rosett_ai/config/secret_resolver.rb +125 -0
  263. data/lib/rosett_ai/configuration.rb +119 -0
  264. data/lib/rosett_ai/content/content_client.rb +60 -0
  265. data/lib/rosett_ai/content/pack_installer.rb +117 -0
  266. data/lib/rosett_ai/content/pack_manifest.rb +50 -0
  267. data/lib/rosett_ai/content/pack_registry.rb +68 -0
  268. data/lib/rosett_ai/content_packs/manager.rb +50 -0
  269. data/lib/rosett_ai/dbus/compositor_detector.rb +77 -0
  270. data/lib/rosett_ai/dbus/focus_adapters/base.rb +59 -0
  271. data/lib/rosett_ai/dbus/focus_adapters/gnome_adapter.rb +172 -0
  272. data/lib/rosett_ai/dbus/focus_adapters/hyprland_adapter.rb +77 -0
  273. data/lib/rosett_ai/dbus/focus_adapters/i3_adapter.rb +65 -0
  274. data/lib/rosett_ai/dbus/focus_adapters/kwin_adapter.rb +103 -0
  275. data/lib/rosett_ai/dbus/focus_adapters/x11_adapter.rb +105 -0
  276. data/lib/rosett_ai/dbus/focus_monitor_interface.rb +103 -0
  277. data/lib/rosett_ai/dbus/manager_interface.rb +213 -0
  278. data/lib/rosett_ai/dbus/plugin_manager_interface.rb +169 -0
  279. data/lib/rosett_ai/dbus/rate_limiter.rb +89 -0
  280. data/lib/rosett_ai/dbus/service.rb +121 -0
  281. data/lib/rosett_ai/dbus/status_notifier_interface.rb +79 -0
  282. data/lib/rosett_ai/deprecation.rb +79 -0
  283. data/lib/rosett_ai/desktop/dbus_client.rb +259 -0
  284. data/lib/rosett_ai/desktop/gtk4_app.rb +371 -0
  285. data/lib/rosett_ai/desktop/gtk4_preferences.rb +331 -0
  286. data/lib/rosett_ai/desktop/gui_logger.rb +236 -0
  287. data/lib/rosett_ai/doctor/check.rb +92 -0
  288. data/lib/rosett_ai/doctor/checks/cache_health_check.rb +50 -0
  289. data/lib/rosett_ai/doctor/checks/dbus_availability_check.rb +39 -0
  290. data/lib/rosett_ai/doctor/checks/engine_detection_check.rb +46 -0
  291. data/lib/rosett_ai/doctor/checks/file_permission_check.rb +44 -0
  292. data/lib/rosett_ai/doctor/checks/gem_dependency_check.rb +55 -0
  293. data/lib/rosett_ai/doctor/checks/ruby_version_check.rb +50 -0
  294. data/lib/rosett_ai/doctor/checks/stale_config_nncc_check.rb +57 -0
  295. data/lib/rosett_ai/doctor/checks/stale_home_nncc_check.rb +59 -0
  296. data/lib/rosett_ai/doctor.rb +81 -0
  297. data/lib/rosett_ai/documentation/reference_compiler.rb +122 -0
  298. data/lib/rosett_ai/documentation/translator.rb +62 -0
  299. data/lib/rosett_ai/engines/base_config_compiler.rb +203 -0
  300. data/lib/rosett_ai/engines/detector.rb +63 -0
  301. data/lib/rosett_ai/engines/registry.rb +50 -0
  302. data/lib/rosett_ai/error_handler.rb +139 -0
  303. data/lib/rosett_ai/exit_codes.rb +76 -0
  304. data/lib/rosett_ai/feature_flags.rb +102 -0
  305. data/lib/rosett_ai/formatting.rb +33 -0
  306. data/lib/rosett_ai/gem_consistency_checker.rb +199 -0
  307. data/lib/rosett_ai/git_hooks/chain_detector.rb +86 -0
  308. data/lib/rosett_ai/git_hooks/installer.rb +175 -0
  309. data/lib/rosett_ai/git_hooks/script_generator.rb +125 -0
  310. data/lib/rosett_ai/gitlab/validators/supplementary_gitlab_ci_yaml_validator.rb +79 -0
  311. data/lib/rosett_ai/i18n/locale_resolver.rb +46 -0
  312. data/lib/rosett_ai/i18n/utf8_checker.rb +32 -0
  313. data/lib/rosett_ai/init/config_file_writer.rb +24 -0
  314. data/lib/rosett_ai/init/directory_builder.rb +38 -0
  315. data/lib/rosett_ai/init/file_copier.rb +95 -0
  316. data/lib/rosett_ai/init/global_initializer.rb +28 -0
  317. data/lib/rosett_ai/init/local_initializer.rb +27 -0
  318. data/lib/rosett_ai/init/mcp_registrar.rb +109 -0
  319. data/lib/rosett_ai/init/project_initializer.rb +38 -0
  320. data/lib/rosett_ai/licensing/license_key.rb +139 -0
  321. data/lib/rosett_ai/licensing/license_store.rb +64 -0
  322. data/lib/rosett_ai/licensing/license_validator.rb +60 -0
  323. data/lib/rosett_ai/licensing/tier.rb +42 -0
  324. data/lib/rosett_ai/mcp/admin/auditor.rb +88 -0
  325. data/lib/rosett_ai/mcp/admin/health_checker.rb +81 -0
  326. data/lib/rosett_ai/mcp/admin/registry.rb +100 -0
  327. data/lib/rosett_ai/mcp/admin/schema_validator.rb +63 -0
  328. data/lib/rosett_ai/mcp/enforcement/.gitkeep +0 -0
  329. data/lib/rosett_ai/mcp/enforcement/hook_generator.rb +197 -0
  330. data/lib/rosett_ai/mcp/enforcement/validator.rb +215 -0
  331. data/lib/rosett_ai/mcp/governance.rb +160 -0
  332. data/lib/rosett_ai/mcp/http_security_config.rb +158 -0
  333. data/lib/rosett_ai/mcp/instructions.rb +266 -0
  334. data/lib/rosett_ai/mcp/key_hasher.rb +66 -0
  335. data/lib/rosett_ai/mcp/keyfile.rb +221 -0
  336. data/lib/rosett_ai/mcp/middleware/authentication.rb +146 -0
  337. data/lib/rosett_ai/mcp/middleware/content_type.rb +56 -0
  338. data/lib/rosett_ai/mcp/middleware/cors.rb +83 -0
  339. data/lib/rosett_ai/mcp/middleware/origin_validation.rb +73 -0
  340. data/lib/rosett_ai/mcp/middleware/rate_limit.rb +106 -0
  341. data/lib/rosett_ai/mcp/middleware/request_size.rb +51 -0
  342. data/lib/rosett_ai/mcp/plugins.rb +143 -0
  343. data/lib/rosett_ai/mcp/prompts/compilation_prompt.rb +40 -0
  344. data/lib/rosett_ai/mcp/prompts/compliance_prompt.rb +41 -0
  345. data/lib/rosett_ai/mcp/prompts/diagnostics_prompt.rb +41 -0
  346. data/lib/rosett_ai/mcp/prompts/validation_prompt.rb +41 -0
  347. data/lib/rosett_ai/mcp/resources/behaviour_resource.rb +127 -0
  348. data/lib/rosett_ai/mcp/resources/config_resource.rb +72 -0
  349. data/lib/rosett_ai/mcp/resources/design_resource.rb +58 -0
  350. data/lib/rosett_ai/mcp/resources/hooks_resource.rb +74 -0
  351. data/lib/rosett_ai/mcp/resources/provenance_resource.rb +51 -0
  352. data/lib/rosett_ai/mcp/resources/rules_resource.rb +60 -0
  353. data/lib/rosett_ai/mcp/resources/schema_resource.rb +72 -0
  354. data/lib/rosett_ai/mcp/response_helper.rb +46 -0
  355. data/lib/rosett_ai/mcp/security_logger.rb +60 -0
  356. data/lib/rosett_ai/mcp/server.rb +212 -0
  357. data/lib/rosett_ai/mcp/settings/server_installer.rb +112 -0
  358. data/lib/rosett_ai/mcp/settings/trust_manager.rb +142 -0
  359. data/lib/rosett_ai/mcp/tools/adopt_tool.rb +70 -0
  360. data/lib/rosett_ai/mcp/tools/backup_tool.rb +64 -0
  361. data/lib/rosett_ai/mcp/tools/behaviour_display_tool.rb +72 -0
  362. data/lib/rosett_ai/mcp/tools/behaviour_list_tool.rb +56 -0
  363. data/lib/rosett_ai/mcp/tools/behaviour_manage_tool.rb +114 -0
  364. data/lib/rosett_ai/mcp/tools/behaviour_show_tool.rb +62 -0
  365. data/lib/rosett_ai/mcp/tools/compile_status_tool.rb +122 -0
  366. data/lib/rosett_ai/mcp/tools/compile_tool.rb +191 -0
  367. data/lib/rosett_ai/mcp/tools/comply_tool.rb +79 -0
  368. data/lib/rosett_ai/mcp/tools/config_compile_tool.rb +71 -0
  369. data/lib/rosett_ai/mcp/tools/config_status_tool.rb +79 -0
  370. data/lib/rosett_ai/mcp/tools/content_tool.rb +78 -0
  371. data/lib/rosett_ai/mcp/tools/context_query_tool.rb +156 -0
  372. data/lib/rosett_ai/mcp/tools/design_list_tool.rb +57 -0
  373. data/lib/rosett_ai/mcp/tools/design_show_tool.rb +69 -0
  374. data/lib/rosett_ai/mcp/tools/doctor_tool.rb +62 -0
  375. data/lib/rosett_ai/mcp/tools/documentation_status_tool.rb +45 -0
  376. data/lib/rosett_ai/mcp/tools/engines_tool.rb +84 -0
  377. data/lib/rosett_ai/mcp/tools/hook_install_tool.rb +190 -0
  378. data/lib/rosett_ai/mcp/tools/hook_preview_tool.rb +173 -0
  379. data/lib/rosett_ai/mcp/tools/hooks_status_tool.rb +84 -0
  380. data/lib/rosett_ai/mcp/tools/init_tool.rb +87 -0
  381. data/lib/rosett_ai/mcp/tools/license_status_tool.rb +44 -0
  382. data/lib/rosett_ai/mcp/tools/project_tool.rb +117 -0
  383. data/lib/rosett_ai/mcp/tools/provenance_tool.rb +97 -0
  384. data/lib/rosett_ai/mcp/tools/provenance_write_tool.rb +40 -0
  385. data/lib/rosett_ai/mcp/tools/retrofit_tool.rb +81 -0
  386. data/lib/rosett_ai/mcp/tools/rule_search_tool.rb +163 -0
  387. data/lib/rosett_ai/mcp/tools/schema_get_tool.rb +94 -0
  388. data/lib/rosett_ai/mcp/tools/tooling_tool.rb +86 -0
  389. data/lib/rosett_ai/mcp/tools/validate_tool.rb +105 -0
  390. data/lib/rosett_ai/mcp/tools/workflow_execute_tool.rb +74 -0
  391. data/lib/rosett_ai/mcp/tools/workflow_tool.rb +78 -0
  392. data/lib/rosett_ai/migration/detector.rb +117 -0
  393. data/lib/rosett_ai/migration/nncc_config_migrator.rb +94 -0
  394. data/lib/rosett_ai/migration/nncc_project_migrator.rb +90 -0
  395. data/lib/rosett_ai/migration/xdg_migrator.rb +123 -0
  396. data/lib/rosett_ai/package_manager/apt.rb +108 -0
  397. data/lib/rosett_ai/package_manager/base.rb +68 -0
  398. data/lib/rosett_ai/package_manager/gem_backend.rb +90 -0
  399. data/lib/rosett_ai/packaging/variant_config.rb +92 -0
  400. data/lib/rosett_ai/path_resolver.rb +115 -0
  401. data/lib/rosett_ai/plugins/contract.rb +43 -0
  402. data/lib/rosett_ai/plugins/engine_contract.rb +60 -0
  403. data/lib/rosett_ai/plugins/gui_contract.rb +74 -0
  404. data/lib/rosett_ai/plugins/mcp_contract.rb +48 -0
  405. data/lib/rosett_ai/plugins/registry.rb +150 -0
  406. data/lib/rosett_ai/policy/auditor.rb +41 -0
  407. data/lib/rosett_ai/policy/deny_list.rb +71 -0
  408. data/lib/rosett_ai/policy/opt_out_scanner.rb +37 -0
  409. data/lib/rosett_ai/policy/policy_compiler.rb +84 -0
  410. data/lib/rosett_ai/policy/protected_files.rb +47 -0
  411. data/lib/rosett_ai/policy/tier_hierarchy.rb +48 -0
  412. data/lib/rosett_ai/policy/validator.rb +35 -0
  413. data/lib/rosett_ai/profiler.rb +79 -0
  414. data/lib/rosett_ai/project/drift_detector.rb +126 -0
  415. data/lib/rosett_ai/project/manager.rb +115 -0
  416. data/lib/rosett_ai/project/sync_manager.rb +138 -0
  417. data/lib/rosett_ai/project/template_applier.rb +105 -0
  418. data/lib/rosett_ai/project_context.rb +82 -0
  419. data/lib/rosett_ai/provenance/entry.rb +63 -0
  420. data/lib/rosett_ai/provenance/file_source.rb +32 -0
  421. data/lib/rosett_ai/provenance/source.rb +62 -0
  422. data/lib/rosett_ai/provenance/store.rb +153 -0
  423. data/lib/rosett_ai/provenance/tracker.rb +62 -0
  424. data/lib/rosett_ai/provenance/trailer_generator.rb +43 -0
  425. data/lib/rosett_ai/provenance/validator.rb +45 -0
  426. data/lib/rosett_ai/quorum/collector.rb +59 -0
  427. data/lib/rosett_ai/quorum/comparator.rb +81 -0
  428. data/lib/rosett_ai/quorum/dispatcher.rb +57 -0
  429. data/lib/rosett_ai/quorum/strategies/adopt.rb +56 -0
  430. data/lib/rosett_ai/rai_config.rb +107 -0
  431. data/lib/rosett_ai/retrofit/base_parser.rb +66 -0
  432. data/lib/rosett_ai/retrofit/engine.rb +171 -0
  433. data/lib/rosett_ai/retrofit/parsers/agents_md_parser.rb +50 -0
  434. data/lib/rosett_ai/retrofit/parsers/claude_parser.rb +69 -0
  435. data/lib/rosett_ai/retrofit/parsers/cursor_parser.rb +82 -0
  436. data/lib/rosett_ai/retrofit/round_trip_validator.rb +65 -0
  437. data/lib/rosett_ai/retrofit/scanner.rb +47 -0
  438. data/lib/rosett_ai/retrofit/secret_detector.rb +87 -0
  439. data/lib/rosett_ai/secrets_resolver.rb +71 -0
  440. data/lib/rosett_ai/smart_feedback/suggester.rb +83 -0
  441. data/lib/rosett_ai/smart_feedback/thor_middleware.rb +84 -0
  442. data/lib/rosett_ai/structured_logger.rb +110 -0
  443. data/lib/rosett_ai/telemetry/json_lines_writer.rb +50 -0
  444. data/lib/rosett_ai/telemetry/log_rotator.rb +67 -0
  445. data/lib/rosett_ai/telemetry/provider.rb +26 -0
  446. data/lib/rosett_ai/telemetry/reporter.rb +144 -0
  447. data/lib/rosett_ai/telemetry.rb +47 -0
  448. data/lib/rosett_ai/text_sanitizer.rb +62 -0
  449. data/lib/rosett_ai/thor/cli.rb +269 -0
  450. data/lib/rosett_ai/thor/tasks/adopt.rb +250 -0
  451. data/lib/rosett_ai/thor/tasks/backup.rb +420 -0
  452. data/lib/rosett_ai/thor/tasks/behaviour.rb +474 -0
  453. data/lib/rosett_ai/thor/tasks/build.rb +1162 -0
  454. data/lib/rosett_ai/thor/tasks/compile.rb +415 -0
  455. data/lib/rosett_ai/thor/tasks/completion.rb +123 -0
  456. data/lib/rosett_ai/thor/tasks/comply.rb +82 -0
  457. data/lib/rosett_ai/thor/tasks/config.rb +265 -0
  458. data/lib/rosett_ai/thor/tasks/content.rb +193 -0
  459. data/lib/rosett_ai/thor/tasks/dbus.rb +321 -0
  460. data/lib/rosett_ai/thor/tasks/design.rb +258 -0
  461. data/lib/rosett_ai/thor/tasks/desktop.rb +129 -0
  462. data/lib/rosett_ai/thor/tasks/doctor.rb +127 -0
  463. data/lib/rosett_ai/thor/tasks/documentation.rb +321 -0
  464. data/lib/rosett_ai/thor/tasks/engines.rb +167 -0
  465. data/lib/rosett_ai/thor/tasks/hooks.rb +219 -0
  466. data/lib/rosett_ai/thor/tasks/init.rb +259 -0
  467. data/lib/rosett_ai/thor/tasks/license.rb +120 -0
  468. data/lib/rosett_ai/thor/tasks/mcp.rb +535 -0
  469. data/lib/rosett_ai/thor/tasks/migrate.rb +121 -0
  470. data/lib/rosett_ai/thor/tasks/plugins.rb +157 -0
  471. data/lib/rosett_ai/thor/tasks/project.rb +260 -0
  472. data/lib/rosett_ai/thor/tasks/provenance.rb +195 -0
  473. data/lib/rosett_ai/thor/tasks/release.rb +314 -0
  474. data/lib/rosett_ai/thor/tasks/retrofit.rb +90 -0
  475. data/lib/rosett_ai/thor/tasks/tooling.rb +308 -0
  476. data/lib/rosett_ai/thor/tasks/validate.rb +108 -0
  477. data/lib/rosett_ai/thor/tasks/workflow.rb +196 -0
  478. data/lib/rosett_ai/tooling/ci_yaml_validator.rb +37 -0
  479. data/lib/rosett_ai/tooling/version_checker.rb +35 -0
  480. data/lib/rosett_ai/ui/accessible_tui.rb +61 -0
  481. data/lib/rosett_ai/ui/base.rb +46 -0
  482. data/lib/rosett_ai/ui/gtk4.rb +98 -0
  483. data/lib/rosett_ai/ui/kde.rb +40 -0
  484. data/lib/rosett_ai/ui/qt6.rb +40 -0
  485. data/lib/rosett_ai/ui/registry.rb +60 -0
  486. data/lib/rosett_ai/ui/tty_helper.rb +74 -0
  487. data/lib/rosett_ai/ui/tui.rb +59 -0
  488. data/lib/rosett_ai/validators/behaviour_validator.rb +20 -0
  489. data/lib/rosett_ai/validators/design_validator.rb +17 -0
  490. data/lib/rosett_ai/validators/schema_validator.rb +84 -0
  491. data/lib/rosett_ai/validators/tooling_validator.rb +17 -0
  492. data/lib/rosett_ai/version.rb +8 -0
  493. data/lib/rosett_ai/version_consistency_checker.rb +129 -0
  494. data/lib/rosett_ai/workflow/audit_log.rb +86 -0
  495. data/lib/rosett_ai/workflow/engine.rb +142 -0
  496. data/lib/rosett_ai/workflow/manager.rb +82 -0
  497. data/lib/rosett_ai/workflow/schema_validator.rb +71 -0
  498. data/lib/rosett_ai/workflow/step_runner.rb +61 -0
  499. data/lib/rosett_ai/workflow/steps/prompt_step.rb +62 -0
  500. data/lib/rosett_ai/workflow/steps/rai_step.rb +74 -0
  501. data/lib/rosett_ai/workflow/steps/shell_step.rb +53 -0
  502. data/lib/rosett_ai/yaml_loader.rb +78 -0
  503. data/lib/rosett_ai.rb +221 -0
  504. data/lib/rubocop/cop/rosett_ai/shell_interpolation.rb +54 -0
  505. data/lib/rubocop/cop/rosett_ai/unsafe_const_get.rb +60 -0
  506. data/lib/rubocop/cop/rosett_ai/unsafe_send.rb +50 -0
  507. data/lib/rubocop/cop/rosett_ai/unsafe_yaml_load.rb +40 -0
  508. data/lib/rubocop/rosett_ai.rb +9 -0
  509. data/lib/scripts/generated/docker_hub_tags.rb +126 -0
  510. data/locales/.gitkeep +0 -0
  511. data/locales/ar.yml +579 -0
  512. data/locales/en.yml +571 -0
  513. data/locales/fr.yml +567 -0
  514. data/packaging/build-engine-deb.sh +81 -0
  515. data/packaging/scripts/postinst +17 -0
  516. data/packaging/scripts/postrm +19 -0
  517. data/packaging/scripts/prerm +10 -0
  518. data/packaging/wrapper.sh.template +38 -0
  519. data/rosett-ai.gemspec +63 -0
  520. data/rules/.gitkeep +0 -0
  521. data/scripts/publish/pulp_upload.sh +123 -0
  522. data/settings.json +29 -0
  523. data/share/applications/be.neatnerds.rosettai.desktop +29 -0
  524. data/share/dbus-1/interfaces/be.neatnerds.rosettai.xml +103 -0
  525. data/share/dbus-1/services/be.neatnerds.rosettai.service +3 -0
  526. data/share/templates/behaviour/criticalthinking.yml +69 -0
  527. metadata +810 -0
@@ -0,0 +1,1288 @@
1
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
+ % NeatNerds Code Companion -- Technical Reference
3
+ % Comprehensive reference for all design documents, architectural decisions,
4
+ % schemas, and configuration settings.
5
+ %
6
+ % Owner: Hugo Antonio Sepulveda Manriquez (hugo@neatnerds.be)
7
+ %
8
+ % Based on the template: Clustering the Interstellar Medium
9
+ % https://www.overleaf.com/articles/clustering-the-interstellar-medium/mtthgyyfrdkn
10
+ % Licensed under the LaTeX Project Public License 1.3c
11
+ %
12
+ % Chapter heading images should have a 2:1 width:height ratio.
13
+ %
14
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
15
+
16
+ %------------------------------------------------------------------------------
17
+ % PACKAGES AND OTHER DOCUMENT CONFIGURATIONS
18
+ %------------------------------------------------------------------------------
19
+
20
+ \documentclass[11pt,fleqn]{book}
21
+
22
+ \usepackage[top=3cm,bottom=3cm,left=3cm,right=3cm,headsep=10pt,a4paper]{geometry}
23
+
24
+ \usepackage{xcolor}
25
+ \definecolor{ocre}{RGB}{52,177,201}
26
+
27
+ % Font Settings
28
+ \usepackage{avant}
29
+ \usepackage{mathptmx}
30
+
31
+ \usepackage{microtype}
32
+ \usepackage[utf8]{inputenc}
33
+ \usepackage[T1]{fontenc}
34
+
35
+ % Bibliography
36
+ \usepackage[style=alphabetic,sorting=nyt,sortcites=true,autopunct=true,
37
+ autolang=hyphen,hyperref=true,abbreviate=false,backref=true,backend=biber]{
38
+ biblatex}
39
+ \addbibresource{bibliography.bib}
40
+ \defbibheading{bibempty}{}
41
+
42
+ \input{structure}
43
+
44
+ \begin{document}
45
+
46
+ %------------------------------------------------------------------------------
47
+ % TITLE PAGE
48
+ %------------------------------------------------------------------------------
49
+
50
+ \begingroup
51
+ \thispagestyle{empty}
52
+ \AddToShipoutPicture*{\put(0,0){\includegraphics[scale=1.25]{cover}}}
53
+ \centering
54
+ \vspace*{5cm}
55
+ \par\normalfont\fontsize{35}{35}\sffamily\selectfont
56
+ \textbf{\textcolor{white}{NeatNerds Code Companion}}\\[0.5cm]
57
+ {\LARGE \textcolor{white}{Technical Reference \& Design Specification}}\par
58
+ \vspace*{1.5cm}
59
+ {\Large \textcolor{white}{Version 1.0.0}}\par
60
+ \vspace*{0.5cm}
61
+ {\large \textcolor{white}{Hugo Antonio Sepulveda Manriquez}}\par
62
+ \endgroup
63
+
64
+ %------------------------------------------------------------------------------
65
+ % COPYRIGHT PAGE
66
+ %------------------------------------------------------------------------------
67
+
68
+ \newpage
69
+ ~\vfill
70
+ \thispagestyle{empty}
71
+
72
+ \noindent \textsc{NeatNerds -- Antwerp, Belgium}\\
73
+
74
+ \noindent \textsc{https://gitlab.neatnerds.be/neatnerds/nncc}\\
75
+
76
+ \noindent Licensed under the GNU General Public License v3.0 only
77
+ (GPL-3.0-only).\\
78
+ This is free software: you are free to change and redistribute it under
79
+ the terms of the GPL-3.0-only license.\cite{gpl3}\\
80
+
81
+ \noindent \textit{First edition, February 2026}
82
+
83
+ %------------------------------------------------------------------------------
84
+ % TABLE OF CONTENTS
85
+ %------------------------------------------------------------------------------
86
+
87
+ \chapterimage{head1.jpg}
88
+
89
+ \pagestyle{empty}
90
+
91
+ \tableofcontents
92
+
93
+ \pagestyle{fancy}
94
+
95
+ \cleardoublepage
96
+
97
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98
+ % CHAPTER 1: PROJECT OVERVIEW
99
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
100
+
101
+ \chapterimage{head2.jpg}
102
+ \chapter{Project Overview}\label{ch:overview}
103
+
104
+ \section{Introduction}\index{Introduction}
105
+
106
+ The \textbf{NeatNerds Code Companion} (\texttt{nncc}) is a Ruby-based
107
+ configuration management tool for AI-assisted development workflows. It provides a
108
+ structured, schema-validated approach to managing AI assistant configurations,
109
+ compiling them into target-specific output formats (Claude Code, Cursor, AGENTS.md,
110
+ and more), and enforcing security and quality standards throughout the
111
+ development lifecycle.
112
+
113
+ \begin{constraintbox}
114
+ \textbf{Core Principle:} Author once, compile to many. A single set of YAML
115
+ source files is compiled into configurations for Claude, Mistral, GPT-NeoX,
116
+ or any generic AI assistant target.
117
+ \end{constraintbox}
118
+
119
+ \section{Project Identity}\index{Project Identity}
120
+
121
+ \begin{longtable}{ll}
122
+ \toprule
123
+ \textbf{Field} & \textbf{Value} \\
124
+ \midrule
125
+ Project Name & nncc \\
126
+ Full Name & NeatNerds Code Companion \\
127
+ Author & Hugo Antonio Sepulveda Manriquez \\
128
+ Contact & hugo@neatnerds.be \\
129
+ License & GPL-3.0-only \\
130
+ Ruby Version & 3.3.10 (via rbenv) \\
131
+ Repository & gitlab.neatnerds.be/neatnerds/nncc \\
132
+ Version & 0.1.0 \\
133
+ \bottomrule
134
+ \end{longtable}
135
+
136
+ \section{Architecture at a Glance}\index{Architecture}
137
+
138
+ The system follows a layered architecture with clear extension points:
139
+
140
+ \begin{lstlisting}[language={},caption={Layer architecture}]
141
+ CLI Layer lib/nncc/thor/tasks/*.rb Thor subcommands
142
+ Library Layer lib/nncc/**/*.rb Domain logic
143
+ Config Layer conf/**/*.yml YAML configurations
144
+ Schema Layer conf/schemas/*.json JSON Schema validation
145
+ Compiler Layer lib/nncc/compiler/backends/ AI target backends
146
+ UI Layer lib/nncc/ui/ Pluggable display adapters
147
+ i18n Layer locales/*.yml Translation files
148
+ \end{lstlisting}
149
+
150
+ \section{Implementation Priority}\index{Priority}
151
+
152
+ Design documents are implemented in strict priority order, with security
153
+ and quality gates established before any feature code:
154
+
155
+ \begin{longtable}{clp{9cm}}
156
+ \toprule
157
+ \textbf{Priority} & \textbf{Tier} & \textbf{Documents} \\
158
+ \midrule
159
+ P1 & Foundation & security, testing, styles, ci\_pipeline \\
160
+ P2 & Structure & architecture, compiler, claude\_code\_configuration \\
161
+ P3 & Interface & ui\_framework, accessibility, i18n \\
162
+ P4 & Business & licensing\_system, content\_packs \\
163
+ P5 & Operations & release\_management, documentation, distribution \\
164
+ \bottomrule
165
+ \end{longtable}
166
+
167
+ \begin{criterionbox}
168
+ \textbf{Rule:} Guardrails before features. Validation before implementation.
169
+ No feature code merges until P1 gates exist.
170
+ \end{criterionbox}
171
+
172
+ \section{Key Decisions}\index{Key Decisions}
173
+
174
+ \begin{itemize}
175
+ \item \textbf{GPL-3.0-only} -- open-core model: software is free, premium
176
+ content is paid
177
+ \item \textbf{TUI-first} with pluggable GUI: \texttt{nncc},
178
+ \texttt{nncc-gtk4}, \texttt{nncc-qt6}, \texttt{nncc-kde}
179
+ \item \textbf{Multi-target AI} -- author once, compile to
180
+ Claude/Mistral/GPT-NeoX/generic
181
+ \item \textbf{Mutant} as independent test quality validator (three-party model)
182
+ \item \textbf{Ed25519-signed JWT}\cite{ed25519,jwt} license keys,
183
+ offline-verifiable
184
+ \item \textbf{EN 301 549}\cite{en301549} (EU) accessibility compliance
185
+ \item \textbf{UTF-8 everywhere}, Linux/Debian only initially
186
+ \end{itemize}
187
+
188
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189
+ % CHAPTER 2: P1 FOUNDATION
190
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
191
+
192
+ \chapterimage{head3.jpg}
193
+ \chapter{P1 -- Foundation}\label{ch:p1}
194
+
195
+ Priority 1 establishes the security, testing, style, and CI foundations
196
+ that all subsequent work depends on.
197
+
198
+ \section{Security}\index{Security}
199
+
200
+ \subsection{Intent}
201
+
202
+ Define and enforce security boundaries for every operation \texttt{nncc}
203
+ performs. Security is not a feature -- it is a constraint that applies to
204
+ every line of code, every file operation, and every external interaction.
205
+
206
+ \subsection{Core Constraints}
207
+
208
+ \begin{constraintbox}
209
+ \begin{enumerate}
210
+ \item \textbf{YAML.safe\_load only} -- never \texttt{YAML.load}
211
+ (arbitrary code execution risk)
212
+ \item \textbf{Array-form system()} -- never string interpolation
213
+ in shell commands (injection risk)
214
+ \item \textbf{File writes to whitelisted directories only} -- prevent
215
+ path traversal
216
+ \item \textbf{Secrets at 0600 permissions} -- never logged, never in
217
+ version control
218
+ \item \textbf{All external input validated before use} -- schema
219
+ validation for YAML, JSON Schema for configs
220
+ \end{enumerate}
221
+ \end{constraintbox}
222
+
223
+ \subsection{Secret Management}
224
+
225
+ Secrets are referenced using a DSL convention:
226
+
227
+ \begin{lstlisting}[language=yaml,caption={Secret reference DSL}]
228
+ api:
229
+ key: "${secret:env:ANTHROPIC_API_KEY}"
230
+ auth_token: "${secret:file:~/.config/nncc/token}"
231
+ \end{lstlisting}
232
+
233
+ The \texttt{SecretsResolver} class resolves these references at runtime
234
+ from environment variables, files, or system keyrings. The reference
235
+ string itself is never a secret -- it is a pointer.
236
+
237
+ \subsection{Input Validation}
238
+
239
+ Every YAML file loaded by \texttt{nncc} is validated against its JSON
240
+ Schema before any data is used. The validation chain:
241
+
242
+ \begin{enumerate}
243
+ \item \texttt{YAML.safe\_load} -- parse safely
244
+ \item \texttt{JSONSchemer.schema} -- validate against schema
245
+ \item Domain-specific checks -- e.g., permission patterns, version
246
+ constraints
247
+ \end{enumerate}
248
+
249
+ \subsection{File Permission Model}
250
+
251
+ \begin{longtable}{lll}
252
+ \toprule
253
+ \textbf{File Type} & \textbf{Mode} & \textbf{Rationale} \\
254
+ \midrule
255
+ License keys & 0600 & Contains subscription identity \\
256
+ Configuration & 0644 & Readable, owner-writable \\
257
+ Executables & 0755 & Standard Unix convention \\
258
+ Directories & 0755 & Standard traversal \\
259
+ Secret dirs & 0700 & Owner-only access \\
260
+ \bottomrule
261
+ \end{longtable}
262
+
263
+ \begin{antipatternbox}
264
+ \textbf{Anti-patterns:}
265
+ \begin{itemize}
266
+ \item Using \texttt{YAML.load} with untrusted input
267
+ \item Building shell commands with string interpolation
268
+ \item Writing files outside the whitelisted directories
269
+ \item Logging secret values, even at debug level
270
+ \item Storing secrets in YAML configuration files
271
+ \end{itemize}
272
+ \end{antipatternbox}
273
+
274
+ \section{Testing}\index{Testing}
275
+
276
+ \subsection{Intent}
277
+
278
+ Ensure every component has meaningful, fast tests that catch regressions
279
+ early. The testing strategy uses a three-party model: RSpec for
280
+ specifications, SimpleCov for coverage measurement, and Mutant as an
281
+ independent test quality validator.
282
+
283
+ \subsection{Testing Pyramid}
284
+
285
+ \begin{longtable}{lp{5cm}p{5cm}}
286
+ \toprule
287
+ \textbf{Level} & \textbf{Scope} & \textbf{Tools} \\
288
+ \midrule
289
+ Unit & Individual classes/methods & RSpec + factory\_bot \\
290
+ Integration & Module interactions & RSpec + tmpdir isolation \\
291
+ Mutation & Test quality validation & Mutant (mutant-rspec) \\
292
+ Security & Vulnerability scanning & bundler-audit, ruby-audit \\
293
+ Style & Code consistency & RuboCop, Reek \\
294
+ \bottomrule
295
+ \end{longtable}
296
+
297
+ \subsection{Constraints}
298
+
299
+ \begin{constraintbox}
300
+ \begin{itemize}
301
+ \item RSpec suite must pass with 0 failures before any commit
302
+ \item Coverage target: 90\%+ line coverage (SimpleCov)
303
+ \item Mutation testing validates test effectiveness -- tests that
304
+ do not detect mutations are insufficient
305
+ \item All specs run in isolation -- no shared mutable state, no
306
+ filesystem leaks
307
+ \item Test fixtures use \texttt{factory\_bot} -- never hand-crafted
308
+ hashes
309
+ \end{itemize}
310
+ \end{constraintbox}
311
+
312
+ \section{Styles}\index{Styles}
313
+
314
+ \subsection{Intent}
315
+
316
+ Enforce consistent code style across all Ruby source files. Style rules
317
+ are not aesthetic preferences -- they are communication standards that
318
+ reduce cognitive load during code review.
319
+
320
+ \subsection{Tool Configuration}
321
+
322
+ \begin{longtable}{lll}
323
+ \toprule
324
+ \textbf{Tool} & \textbf{Config} & \textbf{Standard} \\
325
+ \midrule
326
+ RuboCop & .rubocop.yml & 0 offenses required \\
327
+ Reek & .reek.yml & 0 warnings (or justified exclusions) \\
328
+ Flay & (Rakefile) & Duplication monitoring \\
329
+ \bottomrule
330
+ \end{longtable}
331
+
332
+ \subsection{Key Style Rules}
333
+
334
+ \begin{itemize}
335
+ \item \textbf{Frozen string literals} -- every Ruby file starts with
336
+ \texttt{\# frozen\_string\_literal: true}
337
+ \item \textbf{SPDX headers} -- every Ruby file includes
338
+ \texttt{\# SPDX-License-Identifier: GPL-3.0-only}
339
+ \item \textbf{UTF-8 encoding} -- no Latin-1, no BOM markers
340
+ \item \textbf{2-space indentation} -- Ruby community standard
341
+ \item \textbf{No trailing whitespace} -- enforced by pre-commit hooks
342
+ \end{itemize}
343
+
344
+ \section{CI Pipeline}\index{CI Pipeline}
345
+
346
+ \subsection{Intent}
347
+
348
+ Automate all verification steps so that no broken code reaches the main
349
+ branch. The CI pipeline mirrors the pre-commit hook chain but runs in an
350
+ isolated, reproducible environment.
351
+
352
+ \subsection{Pipeline Stages}
353
+
354
+ \begin{longtable}{llp{7cm}}
355
+ \toprule
356
+ \textbf{Stage} & \textbf{Job} & \textbf{Description} \\
357
+ \midrule
358
+ validate & yaml\_lint & YAML syntax validation \\
359
+ code\_quality & rubocop & Style enforcement (0 offenses) \\
360
+ code\_quality & reek & Code smell detection \\
361
+ code\_quality & flay & Duplication detection \\
362
+ security\_scan & bundler\_audit & Gem CVE scanning \\
363
+ security\_scan & ruby\_audit & Ruby CVE scanning \\
364
+ security\_scan & gitleaks & Secret detection \\
365
+ test & rspec & Full test suite \\
366
+ build & package & Debian package build \\
367
+ \bottomrule
368
+ \end{longtable}
369
+
370
+ \begin{criterionbox}
371
+ \textbf{CI Rule:} All stages must pass before merge. There are no
372
+ ``allowed failures'' in the pipeline.
373
+ \end{criterionbox}
374
+
375
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
376
+ % CHAPTER 3: P2 STRUCTURE
377
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
378
+
379
+ \chapterimage{head4.jpg}
380
+ \chapter{P2 -- Structure}\label{ch:p2}
381
+
382
+ Priority 2 builds the core structural components: the modular architecture,
383
+ the multi-target compiler, and the Claude Code configuration management
384
+ system.
385
+
386
+ \section{Architecture}\index{Architecture}
387
+
388
+ \subsection{Intent}
389
+
390
+ Define the modular structure that allows \texttt{nncc} to grow without
391
+ becoming a monolith. Each module has a single responsibility, clear
392
+ interfaces, and minimal coupling.
393
+
394
+ \subsection{Module Map}
395
+
396
+ \begin{longtable}{lp{9cm}}
397
+ \toprule
398
+ \textbf{Module} & \textbf{Responsibility} \\
399
+ \midrule
400
+ \texttt{Nncc::Thor} & CLI interface (Thor subcommands) \\
401
+ \texttt{Nncc::Compiler} & Multi-target compilation pipeline \\
402
+ \texttt{Nncc::Config} & Claude Code configuration management \\
403
+ \texttt{Nncc::Security} & Secret resolution, input validation \\
404
+ \texttt{Nncc::Ui} & Pluggable UI adapters (TUI/GUI) \\
405
+ \texttt{Nncc::Licensing} & Ed25519 JWT license validation \\
406
+ \texttt{Nncc::I18n} & Locale resolution and string externalization \\
407
+ \texttt{Nncc::ContentPack} & Premium content pack management \\
408
+ \bottomrule
409
+ \end{longtable}
410
+
411
+ \subsection{Path Resolution}
412
+
413
+ All filesystem paths are resolved through \texttt{Nncc::PathResolver},
414
+ ensuring consistent path computation regardless of the current working
415
+ directory. Key paths:
416
+
417
+ \begin{lstlisting}[language=ruby,caption={Path resolution}]
418
+ Nncc.paths.root # Project root
419
+ Nncc.paths.conf_dir # conf/
420
+ Nncc.paths.rules_dir # ~/.claude/rules/
421
+ Nncc.paths.license_file # ~/.config/nncc/license.key
422
+ Nncc.paths.premium_content_dir # ~/.local/share/nncc/content/
423
+ \end{lstlisting}
424
+
425
+ \begin{decisionbox}
426
+ \textbf{ADR-001: PathResolver centralisation.} All path computation goes
427
+ through a single resolver class to prevent path drift between modules.
428
+ Each method returns a \texttt{Pathname} object for safe path manipulation.
429
+ \end{decisionbox}
430
+
431
+ \section{Compiler}\index{Compiler}
432
+
433
+ \subsection{Intent}
434
+
435
+ Transform YAML source configurations into target-specific output formats.
436
+ The compiler uses a strategy pattern where each AI target has a
437
+ \texttt{Backend} class and a \texttt{TargetProfile} YAML configuration.
438
+
439
+ \subsection{Compilation Pipeline}
440
+
441
+ The \texttt{CompilationPipeline} class orchestrates the full flow:
442
+
443
+ \begin{enumerate}
444
+ \item \textbf{Discovery} -- scan \texttt{conf/} for categories that
445
+ have matching schemas
446
+ \item \textbf{Loading} -- parse YAML with \texttt{YAML.safe\_load}
447
+ \item \textbf{Validation} -- verify against JSON Schema
448
+ \item \textbf{Rendering} -- delegate to the backend for format-specific
449
+ output
450
+ \item \textbf{Checksumming} -- SHA-256 digest for change detection
451
+ \item \textbf{Orphan cleanup} -- remove managed files that no longer
452
+ have sources
453
+ \end{enumerate}
454
+
455
+ \subsection{Backend Architecture}
456
+
457
+ \begin{lstlisting}[language=ruby,caption={Backend registration}]
458
+ BACKENDS = {
459
+ 'claude' => 'Nncc::Compiler::Backends::ClaudeBackend',
460
+ 'generic' => 'Nncc::Compiler::Backends::GenericBackend'
461
+ }.freeze
462
+ \end{lstlisting}
463
+
464
+ Each backend implements:
465
+ \begin{itemize}
466
+ \item \texttt{render(category, data)} -- produce output string
467
+ \item \texttt{generated\_marker} -- identify managed files
468
+ \item \texttt{file\_extension} -- output format (\texttt{.md} for markdown)
469
+ \end{itemize}
470
+
471
+ \subsection{Target Profiles}
472
+
473
+ \begin{lstlisting}[language=yaml,caption={Claude target profile}]
474
+ name: claude
475
+ description: Claude Code (Anthropic) target
476
+ backend: claude
477
+ engine_version: ">=1.0.0"
478
+ output_format: markdown
479
+ output_dir: null
480
+ max_context_window: 200000
481
+ rendering:
482
+ include_source_metadata: true
483
+ include_priority_annotations: true
484
+ include_generated_marker: true
485
+ \end{lstlisting}
486
+
487
+ \begin{decisionbox}
488
+ \textbf{ADR-005: Multi-engine architecture.} Adding a new AI target
489
+ requires only a YAML profile and a Ruby backend class. No changes to
490
+ the compilation pipeline, CLI, or test infrastructure.
491
+ \end{decisionbox}
492
+
493
+ \section{Claude Code Configuration}\index{Claude Code Configuration}
494
+
495
+ \subsection{Intent}
496
+
497
+ Manage Claude Code settings across four scopes: user, project, local,
498
+ and managed. Each scope compiles to a specific JSON file that Claude Code
499
+ reads at runtime.
500
+
501
+ \subsection{Scope Hierarchy}
502
+
503
+ \begin{longtable}{llp{6cm}}
504
+ \toprule
505
+ \textbf{Scope} & \textbf{Output Path} & \textbf{Purpose} \\
506
+ \midrule
507
+ managed & /etc/claude-code/managed-settings.json & Enterprise policies \\
508
+ user & \textasciitilde/.claude/settings.json & User defaults \\
509
+ project & .claude/settings.json & Project-specific \\
510
+ local & .claude/settings.local.json & Local overrides (gitignored) \\
511
+ \bottomrule
512
+ \end{longtable}
513
+
514
+ \subsection{Key Mapping}
515
+
516
+ YAML source files use \texttt{snake\_case} keys which are transformed
517
+ to \texttt{camelCase} for the JSON output that Claude Code expects.
518
+ The \texttt{KeyMap} class handles this transformation:
519
+
520
+ \begin{lstlisting}[language=ruby,caption={Key mapping example}]
521
+ # YAML source
522
+ auto_allow_bash: true
523
+ max_output_tokens: 32000
524
+
525
+ # JSON output
526
+ "autoAllowBash": true,
527
+ "maxOutputTokens": 32000
528
+ \end{lstlisting}
529
+
530
+ \subsection{Permission Model}
531
+
532
+ Permissions are structured as allow/deny/ask lists with glob patterns:
533
+
534
+ \begin{lstlisting}[language=yaml,caption={Permission configuration}]
535
+ permissions:
536
+ default_mode: acceptEdits
537
+ allow:
538
+ - "Bash(bundle *)"
539
+ - "Bash(bin/nncc *)"
540
+ - "Bash(rbenv *)"
541
+ deny:
542
+ - "Read(./.env)"
543
+ - "Read(~/.ssh/**/*)"
544
+ - "Read(~/.gnupg/**/*)"
545
+ ask:
546
+ - "Bash(git push *)"
547
+ \end{lstlisting}
548
+
549
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
550
+ % CHAPTER 4: P3 INTERFACE
551
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
552
+
553
+ \chapterimage{head5.jpg}
554
+ \chapter{P3 -- Interface}\label{ch:p3}
555
+
556
+ Priority 3 implements the user-facing interface layer: pluggable UI
557
+ adapters, accessibility compliance, and internationalization.
558
+
559
+ \section{UI Framework}\index{UI Framework}
560
+
561
+ \subsection{Intent}
562
+
563
+ Provide a pluggable display layer that decouples domain logic from
564
+ presentation. The default is a terminal UI (TUI); GUI adapters are
565
+ optional extensions distributed as separate Debian packages.
566
+
567
+ \subsection{Adapter Registry}
568
+
569
+ The \texttt{Nncc::Ui::Registry} class manages adapter discovery
570
+ and resolution:
571
+
572
+ \begin{lstlisting}[language=ruby,caption={UI adapter registration}]
573
+ Registry.register(:tui, Tui)
574
+ Registry.register(:accessible_tui, AccessibleTui)
575
+ Registry.register(:gtk4, Gtk4)
576
+ Registry.register(:qt6, Qt6)
577
+ Registry.register(:kde, Kde)
578
+ \end{lstlisting}
579
+
580
+ \subsection{Package Variants}
581
+
582
+ \begin{longtable}{llp{6cm}}
583
+ \toprule
584
+ \textbf{Package} & \textbf{Adapter} & \textbf{System Dependencies} \\
585
+ \midrule
586
+ nncc & tui & ruby, libncurses \\
587
+ nncc-gtk4 & gtk4 & nncc, libgtk-4-dev, ruby-gnome \\
588
+ nncc-qt6 & qt6 & nncc (placeholder -- bindings pending) \\
589
+ nncc-kde & kde & nncc-qt6 (placeholder -- bindings pending) \\
590
+ \bottomrule
591
+ \end{longtable}
592
+
593
+ \begin{decisionbox}
594
+ \textbf{ADR-002: UI adapter registry.} Adding a new GUI adapter
595
+ requires only a Ruby class implementing the \texttt{Base} interface
596
+ and a packaging variant YAML. The CLI \texttt{--ui} flag selects
597
+ the adapter at runtime.
598
+ \end{decisionbox}
599
+
600
+ \subsection{Base Interface}
601
+
602
+ Every UI adapter must implement five methods:
603
+
604
+ \begin{longtable}{lp{6.5cm}}
605
+ \toprule
606
+ \textbf{Method} & \textbf{Purpose} \\
607
+ \midrule
608
+ \texttt{render(content)} & Display text to the user \\
609
+ \texttt{display\_table(h, rows)} & Display tabular data \\
610
+ \texttt{prompt\_user(q, choices:)} & Interactive input \\
611
+ \texttt{show\_spinner(msg, \&blk)} & Progress indication \\
612
+ \texttt{announce(message)} & Accessibility announcement \\
613
+ \bottomrule
614
+ \end{longtable}
615
+
616
+ \section{Accessibility}\index{Accessibility}
617
+
618
+ \subsection{Intent}
619
+
620
+ Ensure \texttt{nncc} is usable by people with disabilities, in compliance
621
+ with EN 301 549 (EU accessibility standard)\cite{en301549}. This is not
622
+ optional -- it is a legal requirement for publicly-funded ICT in the EU.
623
+
624
+ \subsection{Implementation}
625
+
626
+ The \texttt{AccessibleTui} adapter provides:
627
+
628
+ \begin{itemize}
629
+ \item \textbf{Linear output} -- no box-drawing characters, no
630
+ decorative ANSI escapes
631
+ \item \textbf{NO\_COLOR support} -- respects the \texttt{NO\_COLOR}
632
+ environment variable
633
+ \item \textbf{Screen reader compatibility} -- tested with Orca and BRLTTY
634
+ \item \textbf{Auto-detection} -- switches to accessible mode when
635
+ \texttt{ORCA\_RUNNING} or \texttt{BRLTTY\_TTY} is set
636
+ \item \textbf{Announcement priorities} -- \texttt{:polite} and
637
+ \texttt{:assertive} levels for screen reader output
638
+ \item \textbf{RTL support} -- detects RTL locales (Arabic, Hebrew)
639
+ and adjusts text direction
640
+ \end{itemize}
641
+
642
+ \begin{constraintbox}
643
+ \textbf{Accessibility constraint:} Every UI adapter must pass the
644
+ shared example \texttt{it\_behaves\_like 'a UI implementation'}
645
+ which verifies all five interface methods are implemented.
646
+ \end{constraintbox}
647
+
648
+ \section{Internationalization}\index{Internationalization}
649
+
650
+ \subsection{Intent}
651
+
652
+ Externalize all user-facing strings so that \texttt{nncc} can be used
653
+ in any language. The i18n system uses ruby-i18n with YAML source files.
654
+
655
+ \subsection{Locale Resolution}
656
+
657
+ The \texttt{LocaleResolver} determines the active locale through a
658
+ priority chain:
659
+
660
+ \begin{enumerate}
661
+ \item \texttt{--locale} CLI flag (highest priority)
662
+ \item \texttt{NNCC\_LOCALE} environment variable
663
+ \item \texttt{LANG} environment variable
664
+ \item English fallback (lowest priority)
665
+ \end{enumerate}
666
+
667
+ \subsection{Translation Structure}
668
+
669
+ \begin{lstlisting}[language=yaml,caption={Locale file structure}]
670
+ en:
671
+ nncc:
672
+ meta:
673
+ direction: ltr
674
+ language_name: "English"
675
+ cli:
676
+ version: "nncc Version %{version}"
677
+ compile:
678
+ compiling: "Compiling %{category}..."
679
+ success: "Compiled %{count} files"
680
+ \end{lstlisting}
681
+
682
+ \subsection{UTF-8 Enforcement}
683
+
684
+ A \texttt{TextSanitizer} module enforces UTF-8 throughout:
685
+
686
+ \begin{itemize}
687
+ \item \texttt{normalize\_nfc(text)} -- Unicode NFC normalization
688
+ \item \texttt{strip\_ansi(text)} -- remove ANSI escape sequences
689
+ \item \texttt{valid\_utf8?(text)} -- encoding validation
690
+ \end{itemize}
691
+
692
+ \subsection{Locale Compilation}
693
+
694
+ The \texttt{LocaleCompiler} transforms YAML locale files into
695
+ distribution formats:
696
+
697
+ \begin{longtable}{llp{5cm}}
698
+ \toprule
699
+ \textbf{Format} & \textbf{Extension} & \textbf{Use Case} \\
700
+ \midrule
701
+ Gettext & .pot/.po & GNU toolchain integration \\
702
+ Qt Linguist & .ts & Qt6 GUI adapter \\
703
+ \bottomrule
704
+ \end{longtable}
705
+
706
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707
+ % CHAPTER 5: P4 BUSINESS
708
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
709
+
710
+ \chapterimage{head6.jpg}
711
+ \chapter{P4 -- Business}\label{ch:p4}
712
+
713
+ Priority 4 implements the business model: an open-core licensing system
714
+ where the software is free (GPL-3.0) and premium content packs are paid.
715
+
716
+ \section{Licensing System}\index{Licensing}
717
+
718
+ \subsection{Intent}
719
+
720
+ Enable a sustainable open-source business model. The licensing system
721
+ controls access to premium content packs -- it NEVER restricts software
722
+ functionality. This distinction is critical for GPL-3.0 compliance.
723
+
724
+ \begin{criterionbox}
725
+ \textbf{GPL-3.0 compliance rule:} License tiers gate content pack
726
+ \emph{downloads}, not software features. A community user has full
727
+ access to all \texttt{nncc} functionality -- they simply do not have
728
+ access to premium behaviour and design packs.
729
+ \end{criterionbox}
730
+
731
+ \subsection{License Key Format}
732
+
733
+ License keys are Ed25519-signed JWTs\cite{jwt,ed25519} with an
734
+ \texttt{NNCC-} prefix:
735
+
736
+ \begin{lstlisting}[language={},caption={License key structure}]
737
+ NNCC-eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...
738
+ \end{lstlisting}
739
+
740
+ JWT claims include:
741
+ \begin{longtable}{llp{5cm}}
742
+ \toprule
743
+ \textbf{Claim} & \textbf{Type} & \textbf{Description} \\
744
+ \midrule
745
+ tier & string & community, supporter, subscriber, enterprise \\
746
+ exp & integer & Expiry timestamp (Unix epoch) \\
747
+ perpetual & boolean & Perpetual license flag \\
748
+ sub & string & Subscriber identifier \\
749
+ \bottomrule
750
+ \end{longtable}
751
+
752
+ \subsection{Tier Hierarchy}
753
+
754
+ \begin{longtable}{clp{6cm}}
755
+ \toprule
756
+ \textbf{Level} & \textbf{Tier} & \textbf{Access} \\
757
+ \midrule
758
+ 0 & Community & Free software, no premium content \\
759
+ 1 & Supporter & Basic premium packs \\
760
+ 2 & Subscriber & All premium packs + updates \\
761
+ 3 & Enterprise & All packs + priority support \\
762
+ \bottomrule
763
+ \end{longtable}
764
+
765
+ \subsection{Grace Periods}
766
+
767
+ \begin{longtable}{lll}
768
+ \toprule
769
+ \textbf{Period} & \textbf{Duration} & \textbf{Behaviour} \\
770
+ \midrule
771
+ Active & Until expiry & Full access \\
772
+ Grace & 14 days post-expiry & Access with warning \\
773
+ Offline & 30 days & Verify without network \\
774
+ Expired & After grace & Content frozen at last version \\
775
+ \bottomrule
776
+ \end{longtable}
777
+
778
+ \subsection{Storage Security}
779
+
780
+ The \texttt{LicenseStore} class persists the license key at
781
+ \texttt{\textasciitilde/.config/nncc/license.key} with:
782
+
783
+ \begin{itemize}
784
+ \item File mode \texttt{0600} (owner read/write only)
785
+ \item Directory mode \texttt{0700} (owner access only)
786
+ \item UID verification (must match current process)
787
+ \end{itemize}
788
+
789
+ \begin{antipatternbox}
790
+ \textbf{Anti-patterns:}
791
+ \begin{itemize}
792
+ \item Restricting software features based on license tier (GPL violation)
793
+ \item Storing license keys in YAML config files (wrong permissions)
794
+ \item Logging license key contents
795
+ \item Phone-home license validation (must work offline)
796
+ \end{itemize}
797
+ \end{antipatternbox}
798
+
799
+ \section{Content Packs}\index{Content Packs}
800
+
801
+ \subsection{Intent}
802
+
803
+ Distribute premium behaviour and design packs to licensed users. Content
804
+ packs are the revenue mechanism that sustains the open-source project.
805
+
806
+ \subsection{Pack Structure}
807
+
808
+ \begin{lstlisting}[language=yaml,caption={Content pack manifest}]
809
+ name: enterprise_security
810
+ version: 1.0.0
811
+ tier_required: subscriber
812
+ description: "Advanced security behaviours for enterprise"
813
+ author: "NeatNerds"
814
+ contents:
815
+ behaviours:
816
+ - advanced_audit.yml
817
+ - compliance_reporting.yml
818
+ designs:
819
+ - soc2_compliance.yml
820
+ \end{lstlisting}
821
+
822
+ \subsection{Installation Path}
823
+
824
+ Premium content is installed to
825
+ \texttt{\textasciitilde/.local/share/nncc/content/<pack\_name>/}
826
+ and discovered automatically by the compilation pipeline.
827
+
828
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
829
+ % CHAPTER 6: P5 OPERATIONS
830
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
831
+
832
+ \chapterimage{head7.jpg}
833
+ \chapter{P5 -- Operations}\label{ch:p5}
834
+
835
+ Priority 5 covers operational concerns: release management, documentation
836
+ generation, and package distribution.
837
+
838
+ \section{Release Management}\index{Release Management}
839
+
840
+ \subsection{Intent}
841
+
842
+ Define a repeatable, automated process for releasing \texttt{nncc}
843
+ versions. The release process eliminates manual version edits, manual
844
+ CHANGELOG writing, and manual tag creation -- all sources of
845
+ inconsistency and human error.
846
+
847
+ \subsection{Release Workflow}
848
+
849
+ \begin{enumerate}
850
+ \item \texttt{bin/nncc release prepare LEVEL} --
851
+ bumps version, generates CHANGELOG, creates release commit
852
+ \item Developer reviews the commit
853
+ \item \texttt{bin/nncc release tag} -- creates annotated tag
854
+ \item \texttt{git push origin branch --tags} -- triggers CI release
855
+ \end{enumerate}
856
+
857
+ \subsection{Constraints}
858
+
859
+ \begin{constraintbox}
860
+ \begin{itemize}
861
+ \item Version follows Semantic Versioning 2.0.0\cite{semver}
862
+ \item CHANGELOG follows Keep a Changelog 1.1.0\cite{keepachangelog}
863
+ \item Full verification suite must pass before any release commit
864
+ \item Version source of truth: \texttt{lib/nncc/version.rb}
865
+ \item Tags are annotated (not lightweight) with pattern \texttt{vX.Y.Z}
866
+ \item Release commits use \texttt{chore(release):} prefix
867
+ \item Auto-push is forbidden -- push is always explicit
868
+ \end{itemize}
869
+ \end{constraintbox}
870
+
871
+ \subsection{git-cliff Configuration}
872
+
873
+ CHANGELOG generation uses git-cliff\cite{gitcliff} with conventional
874
+ commit parsing:
875
+
876
+ \begin{lstlisting}[language={},caption={Conventional commit mapping}]
877
+ feat -> Added
878
+ fix -> Fixed
879
+ refactor -> Changed
880
+ perf -> Changed
881
+ docs -> Documentation
882
+ chore -> Other
883
+ \end{lstlisting}
884
+
885
+ \begin{antipatternbox}
886
+ \textbf{Anti-patterns:}
887
+ \begin{itemize}
888
+ \item Auto-pushing to remote as part of the release process
889
+ \item Editing CHANGELOG manually when automation exists
890
+ \item Using lightweight git tags
891
+ \item Coupling version bump and tag creation into one command
892
+ \end{itemize}
893
+ \end{antipatternbox}
894
+
895
+ \section{Documentation}\index{Documentation}
896
+
897
+ \subsection{Intent}
898
+
899
+ Provide end users with complete documentation for installing, configuring,
900
+ and using \texttt{nncc}. Three documentation tiers:
901
+
902
+ \begin{longtable}{llp{6cm}}
903
+ \toprule
904
+ \textbf{Tier} & \textbf{Format} & \textbf{Audience} \\
905
+ \midrule
906
+ Man pages & ronn-ng (roff) & End users (\texttt{man nncc}) \\
907
+ API docs & YARD (HTML) & Contributors \\
908
+ Guides & Markdown & All (INSTALL.md, SETUP.md) \\
909
+ \bottomrule
910
+ \end{longtable}
911
+
912
+ \subsection{Man Page Structure}
913
+
914
+ \begin{lstlisting}[language={},caption={Man page sections}]
915
+ NAME - nncc -- NeatNerds Code Companion
916
+ SYNOPSIS - nncc [OPTIONS] COMMAND [ARGS]
917
+ DESCRIPTION - Overview of what nncc does
918
+ COMMANDS - All CLI subcommands
919
+ OPTIONS - Global flags (--accessible, --locale, --ui)
920
+ FILES - Configuration file locations
921
+ EXIT STATUS - Return codes and meanings
922
+ ENVIRONMENT - Relevant environment variables
923
+ SEE ALSO - Related commands and resources
924
+ \end{lstlisting}
925
+
926
+ \subsection{Documentation Consistency}
927
+
928
+ A CI job verifies documentation consistency:
929
+ \begin{itemize}
930
+ \item Ruby version in \texttt{doc/SETUP.md} matches \texttt{.ruby-version}
931
+ \item Subcommands in man page match CLI \texttt{--help} output
932
+ \item No stale version references in documentation files
933
+ \end{itemize}
934
+
935
+ \section{Distribution}\index{Distribution}
936
+
937
+ \subsection{Intent}
938
+
939
+ Deliver \texttt{nncc} Debian packages to end users through a managed
940
+ APT repository. The distribution system uses Pulp\cite{pulp} as the
941
+ repository management platform.
942
+
943
+ \subsection{Packaging}
944
+
945
+ The \texttt{bin/nncc build package} command creates Debian packages
946
+ using fpm (Effing Package Management):
947
+
948
+ \begin{longtable}{lp{8cm}}
949
+ \toprule
950
+ \textbf{Stage} & \textbf{Description} \\
951
+ \midrule
952
+ verify & Pre-flight checks (Ruby version, fpm, dpkg) \\
953
+ clean & Reset staging directory \\
954
+ stage\_ruby & Install gems to staging (--deployment) \\
955
+ install\_bin & Copy executables \\
956
+ install\_lib & Copy library files \\
957
+ install\_conf & Copy configuration and schemas \\
958
+ install\_locales & Copy translation files \\
959
+ install\_man & Generate and install man pages \\
960
+ fpm & Build .deb package \\
961
+ verify\_deb & Validate package with dpkg-deb \\
962
+ \bottomrule
963
+ \end{longtable}
964
+
965
+ \subsection{Repository Architecture}
966
+
967
+ \begin{lstlisting}[language={},caption={Pulp repository layout}]
968
+ Distribution:
969
+ nncc-stable -> latest releases
970
+ nncc-testing -> release candidates
971
+ nncc-nightly -> CI builds (auto-pruned)
972
+
973
+ Signing:
974
+ GPG Ed25519 or RSA-4096
975
+ SHA256+ digest only
976
+
977
+ Phases:
978
+ Phase 1: pulp_deb (Debian/Ubuntu)
979
+ Phase 2: pulp_rpm (RHEL/Fedora) -- future
980
+ Phase 3: pulp_file (generic tarballs) -- future
981
+ \end{lstlisting}
982
+
983
+ \begin{decisionbox}
984
+ \textbf{ADR: Pulp over aptly.} The distribution system uses
985
+ Pulp instead of aptly because Pulp supports multi-format repositories
986
+ (deb + rpm + file) through a plugin architecture, provides a REST API
987
+ for CI integration, and runs in OCI containers for reproducibility.
988
+ \end{decisionbox}
989
+
990
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991
+ % CHAPTER 7: LIFECYCLE MANAGEMENT
992
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
993
+
994
+ \chapterimage{head8.jpg}
995
+ \chapter{Lifecycle Management}\label{ch:lifecycle}
996
+
997
+ \section{Intent}\index{Lifecycle Management}
998
+
999
+ Define repeatable, auditable processes for upgrading software components
1000
+ (Ruby runtime, gems, system libraries, build tools) across the project.
1001
+ Upgrades are security-critical operations -- a missed CVE fix is a
1002
+ vulnerability, a botched upgrade is downtime.
1003
+
1004
+ \section{Upgrade Methodology}\index{Upgrade Methodology}
1005
+
1006
+ The lifecycle management methodology consists of six phases:
1007
+
1008
+ \subsection{Phase 1: Discovery}
1009
+
1010
+ \begin{itemize}
1011
+ \item Run security audit tools (\texttt{ruby-audit}, \texttt{bundler-audit})
1012
+ \item Record each CVE identifier, severity, and affected component
1013
+ \item Determine the minimum version that resolves all identified CVEs
1014
+ \end{itemize}
1015
+
1016
+ \subsection{Phase 2: Research}
1017
+
1018
+ \begin{itemize}
1019
+ \item Check official release pages for the target version
1020
+ \item Check version manager availability (\texttt{rbenv install --list})
1021
+ \item Read release notes for breaking changes or new deprecations
1022
+ \item Verify target version satisfies gemspec/dependency constraints
1023
+ \end{itemize}
1024
+
1025
+ \subsection{Phase 3: Scope}
1026
+
1027
+ \begin{itemize}
1028
+ \item Grep the entire codebase for all version references
1029
+ \item Categorize findings: config, docs, specs, build scripts
1030
+ \item Note any version-dependent logic in source code
1031
+ \end{itemize}
1032
+
1033
+ \subsection{Phase 4: Execute}
1034
+
1035
+ \begin{itemize}
1036
+ \item Install the new version
1037
+ \item Update version pins
1038
+ \item Reinstall dependencies
1039
+ \item Update all version references identified in scope phase
1040
+ \end{itemize}
1041
+
1042
+ \subsection{Phase 5: Verify}
1043
+
1044
+ \begin{longtable}{ll}
1045
+ \toprule
1046
+ \textbf{Check} & \textbf{Expected Result} \\
1047
+ \midrule
1048
+ ruby-audit & 0 vulnerabilities \\
1049
+ bundler-audit & 0 vulnerabilities \\
1050
+ RuboCop & 0 offenses \\
1051
+ Reek & 0 warnings \\
1052
+ RSpec & 0 failures \\
1053
+ Grep & No stale version references \\
1054
+ \bottomrule
1055
+ \end{longtable}
1056
+
1057
+ \subsection{Phase 6: Commit}
1058
+
1059
+ \begin{itemize}
1060
+ \item Stage only upgrade-related files
1061
+ \item Write commit message referencing CVEs or upgrade rationale
1062
+ \item Let pre-commit hooks run (never \texttt{--no-verify})
1063
+ \end{itemize}
1064
+
1065
+ \section{Reference Execution}\index{Reference Execution}
1066
+
1067
+ The methodology was derived from the Ruby 3.3.8 to 3.3.10 upgrade % rai:no-version-check
1068
+ (2026-02-19), triggered by \texttt{ruby-audit} flagging three CVEs:
1069
+
1070
+ \begin{longtable}{lp{8cm}}
1071
+ \toprule
1072
+ \textbf{CVE} & \textbf{Description} \\
1073
+ \midrule
1074
+ CVE-2025-24294 & resolv library denial of service \\
1075
+ CVE-2025-58767 & REXML denial of service \\
1076
+ CVE-2025-61594 & URI credential leak \\
1077
+ \bottomrule
1078
+ \end{longtable}
1079
+
1080
+ Verification results after upgrade:
1081
+ \begin{itemize}
1082
+ \item ruby-audit: 0 vulnerabilities
1083
+ \item RuboCop: 44 files, 0 offenses
1084
+ \item Reek: 0 warnings
1085
+ \item Flay: 199 total score (unchanged)
1086
+ \item RSpec: 277 examples, 0 failures
1087
+ \item Coverage: 92.92\%
1088
+ \end{itemize}
1089
+
1090
+ \begin{antipatternbox}
1091
+ \textbf{Anti-patterns:}
1092
+ \begin{itemize}
1093
+ \item Upgrading without checking official release notes
1094
+ \item Partial version reference updates
1095
+ \item Running \texttt{bundle update} without targeting specific gems
1096
+ \item Skipping verification because ``it is just a patch version''
1097
+ \item Bypassing pre-commit hooks with \texttt{--no-verify}
1098
+ \item Mixing unrelated changes into an upgrade commit
1099
+ \end{itemize}
1100
+ \end{antipatternbox}
1101
+
1102
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1103
+ % CHAPTER 8: SCHEMA REFERENCE
1104
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1105
+
1106
+ \chapterimage{head1.jpg}
1107
+ \chapter{Schema Reference}\label{ch:schemas}
1108
+
1109
+ All YAML configuration files are validated against JSON
1110
+ Schemas\cite{jsonschema} before use. This chapter documents each schema.
1111
+
1112
+ \section{Design Document Schema}\index{Design Schema}
1113
+
1114
+ Validates the structure of design documents in \texttt{conf/design/}.
1115
+
1116
+ \begin{longtable}{llp{5cm}}
1117
+ \toprule
1118
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1119
+ \midrule
1120
+ name & string & Unique identifier (pattern: \texttt{[\^{}a-z0-9\_]}) \\
1121
+ domain & enum & core, ui, security, testing, styles, i18n, accessibility,
1122
+ licensing, ci, compiler, release, documentation \\
1123
+ version & string & Semantic version (X.Y.Z) \\
1124
+ status & enum & draft, review, approved, deprecated \\
1125
+ priority & integer & 1--6 (P1=highest) \\
1126
+ author & string & Creator \\
1127
+ created\_at & date & ISO 8601 date \\
1128
+ modified\_at & date & Last modification date \\
1129
+ modified\_by & string & Last modifier \\
1130
+ depends\_on & array & List of dependency document names \\
1131
+ intent & string & Purpose and rationale \\
1132
+ constraints & array & Hard boundaries \\
1133
+ acceptance\_criteria & array & Testable done conditions \\
1134
+ examples & array & Usage scenarios \\
1135
+ anti\_patterns & array & What to avoid \\
1136
+ preferences & object & Implementation preferences \\
1137
+ \bottomrule
1138
+ \end{longtable}
1139
+
1140
+ \section{Behaviour Schema}\index{Behaviour Schema}
1141
+
1142
+ Validates behaviour configuration files in \texttt{conf/behaviour/}.
1143
+
1144
+ \begin{longtable}{llp{5cm}}
1145
+ \toprule
1146
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1147
+ \midrule
1148
+ name & string & Unique identifier (1--100 chars) \\
1149
+ description & string & Human-readable explanation \\
1150
+ version & string & Semantic version \\
1151
+ author & string & Creator \\
1152
+ created\_at & date & Creation date \\
1153
+ modified\_at & date & Last modification \\
1154
+ modified\_by & string & Last modifier \\
1155
+ sensitive & boolean & Exclude from API analysis \\
1156
+ used\_in & array & Projects using this behaviour \\
1157
+ rules & array & Operational rules (min 1) \\
1158
+ \bottomrule
1159
+ \end{longtable}
1160
+
1161
+ \subsection{Rule Schema}
1162
+
1163
+ Each rule within a behaviour has:
1164
+
1165
+ \begin{longtable}{llp{5cm}}
1166
+ \toprule
1167
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1168
+ \midrule
1169
+ id & string & Unique rule identifier \\
1170
+ description & string & What this rule instructs \\
1171
+ priority & integer & 1--100 (90--100 critical, 70--89 high,
1172
+ 50--69 medium, 30--49 low, 1--29 minimal) \\
1173
+ enabled & boolean & Whether rule is active \\
1174
+ \bottomrule
1175
+ \end{longtable}
1176
+
1177
+ \section{Claude Code Config Schema}\index{CC Config Schema}
1178
+
1179
+ Validates Claude Code configuration files in \texttt{conf/claude\_code/}.
1180
+ This is the most complex schema, covering all Claude Code settings.
1181
+
1182
+ \subsection{Top-Level Sections}
1183
+
1184
+ \begin{longtable}{lp{8cm}}
1185
+ \toprule
1186
+ \textbf{Section} & \textbf{Description} \\
1187
+ \midrule
1188
+ model & Default model, available models, effort level \\
1189
+ permissions & Allow/deny/ask lists with glob patterns \\
1190
+ sandbox & Network restrictions, command filtering \\
1191
+ context & Token limits, compaction threshold \\
1192
+ display & Language, progress bar, spinner configuration \\
1193
+ hooks & Pre/post tool-use event handlers \\
1194
+ mcp & Model Context Protocol server policies \\
1195
+ attribution & Commit and PR attribution strings \\
1196
+ api & API key helpers, provider configuration \\
1197
+ system & Auto-updates, cleanup, team mate mode \\
1198
+ env & Pass-through environment variables \\
1199
+ \bottomrule
1200
+ \end{longtable}
1201
+
1202
+ \section{Target Profile Schema}\index{Target Schema}
1203
+
1204
+ Validates compiler target profiles in \texttt{conf/targets/}.
1205
+
1206
+ \begin{longtable}{llp{5cm}}
1207
+ \toprule
1208
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1209
+ \midrule
1210
+ name & string & Target identifier \\
1211
+ backend & enum & claude, generic \\
1212
+ output\_format & enum & markdown, json, yaml \\
1213
+ output\_dir & string/null & Override output directory \\
1214
+ max\_context\_window & integer/null & Max tokens \\
1215
+ rendering & object & Source metadata, priority annotations, marker \\
1216
+ \bottomrule
1217
+ \end{longtable}
1218
+
1219
+ \section{Content Pack Manifest Schema}\index{Content Pack Schema}
1220
+
1221
+ Validates premium content pack manifests.
1222
+
1223
+ \begin{longtable}{llp{5cm}}
1224
+ \toprule
1225
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1226
+ \midrule
1227
+ name & string & Pack identifier (lowercase, underscores) \\
1228
+ version & string & Semantic version \\
1229
+ tier\_required & enum & supporter, subscriber, enterprise \\
1230
+ description & string & Human-readable description \\
1231
+ author & string & Pack author \\
1232
+ contents & object & behaviours and designs arrays \\
1233
+ \bottomrule
1234
+ \end{longtable}
1235
+
1236
+ \section{Packaging Schema}\index{Packaging Schema}
1237
+
1238
+ Validates Debian packaging variant configurations.
1239
+
1240
+ \begin{longtable}{llp{5cm}}
1241
+ \toprule
1242
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1243
+ \midrule
1244
+ name & string & Debian package name (nncc*) \\
1245
+ variant & enum & core, gtk4, qt6, kde \\
1246
+ description & string & Package description \\
1247
+ ui\_adapter & enum & tui, gtk4, qt6, kde \\
1248
+ system\_dependencies & array & Debian package names \\
1249
+ package\_dependencies & array & nncc packages with versions \\
1250
+ \bottomrule
1251
+ \end{longtable}
1252
+
1253
+ \section{Tooling Schema}\index{Tooling Schema}
1254
+
1255
+ Validates the tool registry for external CLI tool management.
1256
+
1257
+ \begin{longtable}{llp{5cm}}
1258
+ \toprule
1259
+ \textbf{Field} & \textbf{Type} & \textbf{Description} \\
1260
+ \midrule
1261
+ tools & object & Map of tool names to configs \\
1262
+ \quad description & string & Tool description \\
1263
+ \quad permission\_pattern & string & Claude Code pattern \\
1264
+ \quad category & enum & json, yaml, search, text, system, network \\
1265
+ \quad packages & object & Package manager to package name map \\
1266
+ \bottomrule
1267
+ \end{longtable}
1268
+
1269
+ %------------------------------------------------------------------------------
1270
+ % BIBLIOGRAPHY
1271
+ %------------------------------------------------------------------------------
1272
+
1273
+ \chapter*{Bibliography}
1274
+ \addcontentsline{toc}{chapter}{\textcolor{ocre}{Bibliography}}
1275
+
1276
+ \printbibliography[heading=bibempty]
1277
+
1278
+ %------------------------------------------------------------------------------
1279
+ % INDEX
1280
+ %------------------------------------------------------------------------------
1281
+
1282
+ \cleardoublepage
1283
+ \phantomsection
1284
+ \setlength{\columnsep}{0.75cm}
1285
+ \addcontentsline{toc}{chapter}{\textcolor{ocre}{Index}}
1286
+ \printindex
1287
+
1288
+ \end{document}