rpr-cli 0.1.20__tar.gz → 0.1.22__tar.gz

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 (222) hide show
  1. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/PKG-INFO +1 -1
  2. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/all.instructions.md +8 -8
  3. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/frontend.instructions.md +1 -1
  4. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/rust-engine.instructions.md +4 -4
  5. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/setup-guide.instructions.md +8 -9
  6. {rpr_cli-0.1.20/src/rpr/scaffolds → rpr_cli-0.1.22/Sample-dot-github}/instructions/tooling-setup.instructions.md +1 -1
  7. rpr_cli-0.1.22/src/rpr/__init__.py +1 -0
  8. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/instructions.py +19 -2
  9. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/packages.py +71 -77
  10. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/api.py +16 -21
  11. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/domain.py +28 -29
  12. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/engine.py +4 -4
  13. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/storybook.py +31 -18
  14. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/ui.py +37 -12
  15. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/init.py +52 -42
  16. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/sync.py +7 -3
  17. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/context.py +30 -0
  18. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/dependencies.py +32 -8
  19. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/dependency_manifest_data.py +0 -9
  20. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/base.py +4 -2
  21. rpr_cli-0.1.22/src/rpr/generators/github.py +35 -0
  22. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/container.md +1 -1
  23. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/settings.md +1 -1
  24. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/all.instructions.md +8 -8
  25. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/domain.instructions.md +5 -5
  26. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/frontend.instructions.md +1 -1
  27. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/rust-engine.instructions.md +4 -4
  28. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/setup-guide.instructions.md +19 -20
  29. {rpr_cli-0.1.20/Sample-dot-github → rpr_cli-0.1.22/src/rpr/scaffolds}/instructions/tooling-setup.instructions.md +1 -1
  30. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/domain_container.md +1 -1
  31. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/domain_settings.md +1 -1
  32. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/dto_util.md +1 -1
  33. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/encrypted_column.md +1 -1
  34. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/mapper_util.md +1 -1
  35. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/special_files/partial_update.md +1 -1
  36. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/templates/registry.py +8 -8
  37. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/workspace.py +6 -36
  38. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_add.py +4 -3
  39. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_check.py +42 -75
  40. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_api.py +14 -11
  41. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_domain.py +41 -22
  42. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_engine.py +17 -15
  43. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_storybook.py +49 -30
  44. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_generate_ui.py +32 -60
  45. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_init.py +58 -35
  46. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_sync.py +17 -4
  47. rpr_cli-0.1.20/src/rpr/__init__.py +0 -1
  48. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/.github/agents/story.agent.md +0 -0
  49. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/.github/workflows/publish-pypi.yml +0 -0
  50. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/.gitignore +0 -0
  51. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/CLAUDE.md +0 -0
  52. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/GEMINI.md +0 -0
  53. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/LICENSE +0 -0
  54. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/README.md +0 -0
  55. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/api.instructions.md +0 -0
  56. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/domain.instructions.md +0 -0
  57. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/instructions/tooling.instructions.md +0 -0
  58. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/README.md +0 -0
  59. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/api/main.py +0 -0
  60. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/domain/base-repo.md +0 -0
  61. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/domain/base_entity.md +0 -0
  62. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/frontend/api.service.ts +0 -0
  63. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/Sample-dot-github/scaffolds/frontend/useStateNavigation.ts +0 -0
  64. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/changelogs/mui_v9.txt +0 -0
  65. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/code-map.md +0 -0
  66. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/nx_uv_setup.md +0 -0
  67. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/patch_output.py +0 -0
  68. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/pyproject.toml +0 -0
  69. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/Cargo.lock +0 -0
  70. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/Cargo.toml +0 -0
  71. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/pyproject.toml +0 -0
  72. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/rpr_parser.pyi +0 -0
  73. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/config/container.rs +0 -0
  74. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/config/mod.rs +0 -0
  75. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/config/settings.rs +0 -0
  76. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/graph.rs +0 -0
  77. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/lib.rs +0 -0
  78. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/dtos/mod.rs +0 -0
  79. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/entities/mod.rs +0 -0
  80. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/entities/users.rs +0 -0
  81. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/models/mod.rs +0 -0
  82. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/parse.rs +0 -0
  83. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/repos/base.rs +0 -0
  84. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/repos/mod.rs +0 -0
  85. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/repos/users.rs +0 -0
  86. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/resolve.rs +0 -0
  87. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/src/walker.rs +0 -0
  88. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/rpr-parser/uv.lock +0 -0
  89. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/special_files.md +0 -0
  90. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/__init__.py +0 -0
  91. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/approval.py +0 -0
  92. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/bootstrap.py +0 -0
  93. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/client.py +0 -0
  94. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/control.py +0 -0
  95. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/mock.py +0 -0
  96. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/runtime.py +0 -0
  97. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/session.py +0 -0
  98. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/__init__.py +0 -0
  99. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/base.py +0 -0
  100. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/mutating.py +0 -0
  101. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/readonly.py +0 -0
  102. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/agent/tools/registry.py +0 -0
  103. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/__init__.py +0 -0
  104. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/catalog.py +0 -0
  105. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/chat_service.py +0 -0
  106. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/checks.py +0 -0
  107. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/cli_adapter.py +0 -0
  108. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/completer.py +0 -0
  109. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/conversation_service.py +0 -0
  110. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/prompt_service.py +0 -0
  111. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/selector.py +0 -0
  112. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/application/shell.py +0 -0
  113. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/__init__.py +0 -0
  114. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/base.py +0 -0
  115. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/checks/workspace.py +0 -0
  116. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/cli.py +0 -0
  117. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/__init__.py +0 -0
  118. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/add.py +0 -0
  119. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/chat.py +0 -0
  120. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/check.py +0 -0
  121. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/generate/__init__.py +0 -0
  122. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/map.py +0 -0
  123. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/refresh.py +0 -0
  124. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/commands/settings.py +0 -0
  125. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/__init__.py +0 -0
  126. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/claude.py +0 -0
  127. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/copilot.py +0 -0
  128. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/cursor.py +0 -0
  129. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/generators/gemini.py +0 -0
  130. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/manifest_refresh.py +0 -0
  131. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/__init__.py +0 -0
  132. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/architecture.py +0 -0
  133. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/chains.py +0 -0
  134. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/classifier.py +0 -0
  135. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/coverage.py +0 -0
  136. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/dependencies.py +0 -0
  137. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/extractor.py +0 -0
  138. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/graph.py +0 -0
  139. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/output.py +0 -0
  140. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/responsibility.py +0 -0
  141. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/topology.py +0 -0
  142. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/map/walker.py +0 -0
  143. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/base_entity.md +0 -0
  144. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/domain/base_repo.md +0 -0
  145. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/api.instructions.md +0 -0
  146. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/instructions/tooling.instructions.md +0 -0
  147. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/js_special_files/fetch.service.md +0 -0
  148. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/scaffolds/js_special_files/sticky-navigation.md +0 -0
  149. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/templates/__init__.py +0 -0
  150. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/__init__.py +0 -0
  151. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/console.py +0 -0
  152. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/markdown.py +0 -0
  153. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/prompt_session.py +0 -0
  154. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/renderers.py +0 -0
  155. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/src/rpr/ui/theme.py +0 -0
  156. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/README.md +0 -0
  157. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/00-bootstrap-cli.md +0 -0
  158. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/01-rpr-init.md +0 -0
  159. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/02-rpr-generate-domain.md +0 -0
  160. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/03-rpr-generate-api.md +0 -0
  161. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/04-rpr-generate-ui.md +0 -0
  162. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/05-rpr-generate-engine.md +0 -0
  163. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/06-rpr-generate-storybook.md +0 -0
  164. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/07-rpr-sync-rules.md +0 -0
  165. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/08-rpr-add-template.md +0 -0
  166. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/09-rpr-check.md +0 -0
  167. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/10-rpr-domain-config.md +0 -0
  168. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/18-rpr-terminal-ui-foundation.md +0 -0
  169. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/19-rpr-markdown-rendering.md +0 -0
  170. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/20-rpr-chat-repl.md +0 -0
  171. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/21-rpr-agent-tool-loop.md +0 -0
  172. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/22-rpr-chat-tui.md +0 -0
  173. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/23-rpr-chat-unified-command-shell.md +0 -0
  174. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/24-rpr-async-chat-runtime-and-services.md +0 -0
  175. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/25-rpr-prompt-service-and-conversation-lifecycle.md +0 -0
  176. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/26-rpr-shared-command-catalog.md +0 -0
  177. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/27-rpr-slash-command-selection-panel.md +0 -0
  178. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/28-rpr-chat-cancellable-and-multiline-input.md +0 -0
  179. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/chat/29-rpr-file-context-selection.md +0 -0
  180. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/11-rpr-map-command.md +0 -0
  181. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/12-rpr-map-file-walker.md +0 -0
  182. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/13-rpr-map-rust-engine.md +0 -0
  183. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/13a-rpr-map-gitignore.md +0 -0
  184. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/14-rpr-map-graph-builder.md +0 -0
  185. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/15-rpr-map-analysis-bridge.md +0 -0
  186. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/16-rpr-map-layer-classifier.md +0 -0
  187. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17-rpr-map-output.md +0 -0
  188. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17a-rpr-map-directory-topology.md +0 -0
  189. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17b-rpr-map-architecture-assessment.md +0 -0
  190. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17c-rpr-map-representative-chains.md +0 -0
  191. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/completed/map/17d-rpr-map-multi-resolution-output.md +0 -0
  192. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/map/30-rpr-map-directory-view-and-cycle-detection.md +0 -0
  193. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/map/31-rpr-map-coupling-hotspots-and-verdict-reasoning.md +0 -0
  194. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/stories/map/32-rpr-map-dependencies-responsibilities-and-test-coverage.md +0 -0
  195. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/__init__.py +0 -0
  196. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_architecture.py +0 -0
  197. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_architecture_unwrapped.py +0 -0
  198. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_catalog.py +0 -0
  199. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_chat.py +0 -0
  200. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_chat_service.py +0 -0
  201. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_completer.py +0 -0
  202. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_context.py +0 -0
  203. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map.py +0 -0
  204. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_chains.py +0 -0
  205. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_classifier.py +0 -0
  206. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_coverage.py +0 -0
  207. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_dependencies.py +0 -0
  208. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_extractor.py +0 -0
  209. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_graph.py +0 -0
  210. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_output.py +0 -0
  211. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_responsibility.py +0 -0
  212. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_topology.py +0 -0
  213. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_map_walker.py +0 -0
  214. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_packaging.py +0 -0
  215. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_prompt_session.py +0 -0
  216. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_refresh.py +0 -0
  217. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_rpr_parser_stub.py +0 -0
  218. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_selector.py +0 -0
  219. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_settings.py +0 -0
  220. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/tests/test_ui.py +0 -0
  221. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/update_output.py +0 -0
  222. {rpr_cli-0.1.20 → rpr_cli-0.1.22}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rpr-cli
3
- Version: 0.1.20
3
+ Version: 0.1.22
4
4
  Summary: RPR CLI -- React Python Rust monorepo scaffolding orchestrator
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -24,14 +24,14 @@ This project uses an NX + UV monorepo with a domain-driven design approach. Appl
24
24
 
25
25
  ## Layout
26
26
 
27
- | Path | Purpose |
28
- | ------------------------------- | ------------------------------------------------------------------------ |
29
- | `apps/{name}-web` | Thin frontend application shell |
30
- | `apps/{name}-api` | FastAPI application |
31
- | `packages/node/{name}-ui` | Reusable UI package with components, hooks, services, and state |
32
- | `packages/node/sb` | Storybook package |
33
- | `packages/python/domain` | Python domain package containing the `src/{name_underscore}_domain` code |
34
- | `packages/python/{name}-engine` | Rust engine package exposed to Python |
27
+ | Path | Purpose |
28
+ | ------------------------------------------ | ------------------------------------------------------------------------ |
29
+ | `apps/{name_kebab}-web` | Thin frontend application shell |
30
+ | `apps/{name_underscore}_api` | FastAPI application |
31
+ | `packages/node/{name_kebab}-ui` | Reusable UI package with components, hooks, services, and state |
32
+ | `packages/node/sb` | Storybook package |
33
+ | `packages/python/domain` | Python domain package containing the `src/{name_underscore}_domain` code |
34
+ | `packages/python/{name_underscore}_engine` | Rust engine package exposed to Python |
35
35
 
36
36
  ## Instructions, Templates, and Scaffolds
37
37
 
@@ -11,7 +11,7 @@ Use React for UI composition, TanStack Query for server-state workflows, TanStac
11
11
 
12
12
  - Use functional components.
13
13
  - Extract reusable behavior into hooks instead of duplicating component logic.
14
- - Import the generated shared UI package through the app-scoped package name `@{name}/ui`, such as `@testapp/ui`, not `@repo/{name}-ui`.
14
+ - Import the generated shared UI package through the app-scoped package name `@{name_kebab}/ui`, such as `@testapp/ui`, not `@repo/{name_kebab}-ui`.
15
15
  - Prefer a shared base API service at `src/services/base/api.service.ts` when the UI package needs centralized fetch behavior.
16
16
  - Prefer a shared `useStateNavigation` hook at `src/hooks/useStateNavigation.ts` when UI state should persist in the URL.
17
17
  - Reuse existing components, hooks, and service patterns before introducing a new abstraction.
@@ -1,5 +1,5 @@
1
1
  ---
2
- applyTo: "packages/python/*-engine/**"
2
+ applyTo: "packages/python/*_engine/**"
3
3
  description: "Rust + PyO3 engine build, lint, and Python bindings"
4
4
  ---
5
5
 
@@ -9,9 +9,9 @@ Use Rust for performance-sensitive code that needs a Python-facing API. This pac
9
9
 
10
10
  ## Structure
11
11
 
12
- - Package root: `packages/python/{name}-engine`
13
- - Rust source: `packages/python/{name}-engine/src/lib.rs`
14
- - Python build metadata: `packages/python/{name}-engine/pyproject.toml`
12
+ - Package root: `packages/python/{name_underscore}_engine`
13
+ - Rust source: `packages/python/{name_underscore}_engine/src/lib.rs`
14
+ - Python build metadata: `packages/python/{name_underscore}_engine/pyproject.toml`
15
15
  - Type stubs: keep a `.pyi` file next to the package root for editor support
16
16
 
17
17
  ## Build and Tooling
@@ -24,18 +24,17 @@ Use this guidance when validating or changing the monorepo setup against the RPR
24
24
  ## Naming And Layout
25
25
 
26
26
  - Use kebab-case for project roots and Nx project names.
27
- - Keep the frontend app at `apps/{name}-web`.
28
- - Keep the FastAPI app at `apps/{name}-api`.
29
- - Keep the reusable React library at `packages/node/{name}-ui`.
27
+ - Keep the frontend app at `apps/{name_kebab}-web`.
28
+ - Keep the FastAPI app at `apps/{name_underscore}_api`.
29
+ - Keep the reusable React library at `packages/node/{name_kebab}-ui`.
30
30
  - Keep the dedicated Storybook host at `packages/node/sb`.
31
31
  - Keep the Python domain package at `packages/python/domain`.
32
32
  - Keep the domain import package at `packages/python/domain/src/{name_underscore}_domain` so imports read as `from {name_underscore}_domain ...`.
33
- - Keep optional Rust engine packages at `packages/python/{name}-engine` unless the product contract changes.
33
+ - Keep optional Rust engine packages at `packages/python/{name_underscore}_engine` unless the product contract changes.
34
34
 
35
35
  ## Python Naming Rule
36
36
 
37
- - Use kebab-case for filesystem roots such as `apps/{name}-api`.
38
- - Use snake_case for the import package inside `src/`, for example `apps/{name}-api/src/{name}_api`.
37
+ - Use snake_case for Python filesystem roots and import packages, for example `apps/{name_underscore}_api/src/{name_underscore}_api`.
39
38
  - Apply the same rule to the domain package: keep the root directory `packages/python/domain`, but keep the import package at `src/{name_underscore}_domain`.
40
39
  - Keep the Python package name in `pyproject.toml` kebab-case.
41
40
  - Add a `tests/` directory for generated Python apps and libraries.
@@ -45,8 +44,8 @@ Use this guidance when validating or changing the monorepo setup against the RPR
45
44
  - Generate React app and library projects in a way that preserves the expected Nx command surface.
46
45
  - The web app should expose at least `serve`, `build`, `lint`, `test`, and `typecheck` when those capabilities exist in the generated project.
47
46
  - The UI library should expose at least `build`, `lint`, `test`, and `typecheck`.
48
- - Use app-scoped Node package names: `packages/node/{name}-ui` publishes as `@{name}/ui`, `apps/{name}-web` publishes as `@{name}/web`, and Storybook publishes as `@{name}/sb`.
49
- - Import the shared UI package through `@{name}/ui`, for example `import { AppThemeProvider } from "@testapp/ui"` for a `TestApp` workspace.
47
+ - Use app-scoped Node package names: `packages/node/{name_kebab}-ui` publishes as `@{name_kebab}/ui`, `apps/{name_kebab}-web` publishes as `@{name_kebab}/web`, and Storybook publishes as `@{name_kebab}/sb`.
48
+ - Import the shared UI package through `@{name_kebab}/ui`, for example `import { AppThemeProvider } from "@testapp/ui"` for a `TestApp` workspace.
50
49
  - Link local Node workspace packages with relative `file:` dependency specs instead of `workspace:*`, because npm must be able to install the generated workspace without unsupported protocol errors.
51
50
  - Keep Storybook as a dedicated host project at `packages/node/sb`; do not silently repurpose the UI library as the Storybook project.
52
51
 
@@ -84,7 +83,7 @@ npx nx run domain:migrate -- downgrade -1
84
83
  - Project roots and import package names follow the kebab-case and snake_case rules.
85
84
  - Python projects have both `src/` and `tests/`.
86
85
  - The domain import package remains `src/{name_underscore}_domain`.
87
- - Node imports use app-scoped package names such as `@{name}/ui`, not stale `@repo/*` aliases.
86
+ - Node imports use app-scoped package names such as `@{name_kebab}/ui`, not stale `@repo/*` aliases.
88
87
  - Storybook remains hosted in `packages/node/sb`.
89
88
  - Workspace members and workspace dependency sources are complete.
90
89
  - Generated instructions, checks, and scaffolds refer to the current contract rather than stale paths.
@@ -1,5 +1,5 @@
1
1
  ---
2
- applyTo: "pyproject.toml,nx.json,.pre-commit-config.yaml,package.json,apps/*/project.json,packages/**/project.json,apps/*/eslint.config.mjs,packages/**/eslint.config.mjs,packages/python/*-engine/Cargo.toml"
2
+ applyTo: "pyproject.toml,nx.json,.pre-commit-config.yaml,package.json,apps/*/project.json,packages/**/project.json,apps/*/eslint.config.mjs,packages/**/eslint.config.mjs,packages/python/*_engine/Cargo.toml"
3
3
  description: "Use when setting up or modifying Ruff, TypeScript linting, ESLint, Prettier, cargo fmt, Clippy, or pre-commit in an RPR workspace"
4
4
  ---
5
5
 
@@ -0,0 +1 @@
1
+ __version__ = "0.1.22"
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
 
5
5
  from rpr.checks.base import CheckResult
6
- from rpr.generators.base import SyncConfig, interpolate
6
+ from rpr.generators.base import interpolate
7
7
  from rpr.templates.registry import TEMPLATES
8
8
 
9
9
 
@@ -25,6 +25,23 @@ def check_instructions(
25
25
  )
26
26
  )
27
27
 
28
+ # GitHub / VS Code workspace instructions
29
+ github_instructions = project_dir / ".github" / "instructions"
30
+ github_ok = github_instructions.exists() and any(
31
+ github_instructions.glob("*.instructions.md")
32
+ )
33
+ results.append(
34
+ CheckResult(
35
+ group="AI Instructions & Templates",
36
+ area="GitHub workspace instructions",
37
+ status=github_ok,
38
+ path=str(github_instructions)
39
+ if github_ok
40
+ else ".github/instructions/*.instructions.md missing",
41
+ suggestion="rpr sync rules --target github",
42
+ )
43
+ )
44
+
28
45
  # Copilot instructions
29
46
  copilot_file = project_dir / ".github" / "copilot-instructions.md"
30
47
  results.append(
@@ -52,7 +69,7 @@ def check_instructions(
52
69
  )
53
70
 
54
71
  # Templates (only if domain package exists for Python, or UI library for JS)
55
- has_domain = any(project_dir.glob("packages/python/domain"))
72
+ has_domain = any(project_dir.glob("packages/python/*_domain"))
56
73
  has_ui = any(project_dir.glob("packages/node/*-ui"))
57
74
 
58
75
  template_ids = [
@@ -8,39 +8,41 @@ from rpr.checks.base import CheckResult
8
8
  from rpr.dependencies import (
9
9
  DOMAIN_RUNTIME_DEPENDENCIES,
10
10
  MATURIN_SPEC,
11
- ROOT_STORYBOOK_DEV_DEPENDENCIES,
12
- STORYBOOK_DEV_DEPENDENCIES,
13
- UI_LIBRARY_DEPENDENCIES,
14
- UI_LIBRARY_DEV_DEPENDENCIES,
15
- WEB_APP_DEV_DEPENDENCIES,
16
11
  api_runtime_dependencies,
17
12
  dependency_names,
18
- mapping_dependency_names,
19
- storybook_package_dependencies,
20
- web_app_dependencies,
13
+ node_project_name,
14
+ npm_package_name,
15
+ python_project_name,
21
16
  )
22
17
 
23
18
 
24
19
  def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckResult]:
25
20
  results: list[CheckResult] = []
26
21
  name = variables.get("name", "<name>")
27
- name_underscore = variables.get("name_underscore", name.replace("-", "_"))
22
+ name_underscore = variables.get("name_underscore", name.replace("-", "_")).lower()
23
+ domain_name = python_project_name(name, "domain")
24
+ api_name = python_project_name(name, "api")
25
+ ui_name = node_project_name(name, "ui")
26
+ web_name = node_project_name(name, "web")
28
27
 
29
28
  pyproject = project_dir / "pyproject.toml"
30
29
  workspace_members: set[str] = set()
31
30
  if pyproject.exists():
32
31
  try:
33
32
  data = tomllib.loads(pyproject.read_text())
34
- members = data.get("tool", {}).get("uv", {}).get("workspace", {}).get(
35
- "members", []
33
+ members = (
34
+ data.get("tool", {})
35
+ .get("uv", {})
36
+ .get("workspace", {})
37
+ .get("members", [])
36
38
  )
37
39
  if isinstance(members, list):
38
40
  workspace_members = set(members)
39
- except (OSError, tomllib.TOMLDecodeError):
41
+ except OSError, tomllib.TOMLDecodeError:
40
42
  workspace_members = set()
41
43
 
42
44
  # Domain package
43
- domain_dir = project_dir / "packages" / "python" / "domain"
45
+ domain_dir = project_dir / "packages" / "python" / domain_name
44
46
  results.append(
45
47
  CheckResult(
46
48
  group="Generated Packages & Apps",
@@ -48,7 +50,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
48
50
  status=domain_dir.exists(),
49
51
  path=str(domain_dir)
50
52
  if domain_dir.exists()
51
- else "packages/python/domain/ missing",
53
+ else f"packages/python/{domain_name}/ missing",
52
54
  suggestion=f"rpr generate domain {name}",
53
55
  )
54
56
  )
@@ -57,7 +59,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
57
59
  _check_python_layout(
58
60
  area="Domain layout",
59
61
  project_dir=domain_dir,
60
- src_package=domain_dir / "src" / f"{name_underscore}_domain",
62
+ src_package=domain_dir / "src" / domain_name,
61
63
  suggestion=f"rpr generate domain {name}",
62
64
  )
63
65
  )
@@ -73,7 +75,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
73
75
  _check_project_name(
74
76
  area="Domain project name",
75
77
  project_json=domain_dir / "project.json",
76
- expected_name="domain",
78
+ expected_name=domain_name,
77
79
  suggestion=f"rpr generate domain {name}",
78
80
  )
79
81
  )
@@ -96,22 +98,22 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
96
98
  CheckResult(
97
99
  group="Generated Packages & Apps",
98
100
  area="Domain workspace member",
99
- status="packages/python/domain" in workspace_members,
100
- path="packages/python/domain"
101
- if "packages/python/domain" in workspace_members
102
- else "packages/python/domain missing from [tool.uv.workspace].members",
101
+ status=f"packages/python/{domain_name}" in workspace_members,
102
+ path=f"packages/python/{domain_name}"
103
+ if f"packages/python/{domain_name}" in workspace_members
104
+ else f"packages/python/{domain_name} missing from [tool.uv.workspace].members",
103
105
  suggestion=f"rpr generate domain {name}",
104
106
  )
105
107
  )
106
108
 
107
109
  # API app
108
- api_dir = project_dir / "apps" / f"{name}-api"
110
+ api_dir = project_dir / "apps" / api_name
109
111
  results.append(
110
112
  CheckResult(
111
113
  group="Generated Packages & Apps",
112
114
  area="API app",
113
115
  status=api_dir.exists(),
114
- path=str(api_dir) if api_dir.exists() else f"apps/{name}-api/ missing",
116
+ path=str(api_dir) if api_dir.exists() else f"apps/{api_name}/ missing",
115
117
  suggestion=f"rpr generate api {name}",
116
118
  )
117
119
  )
@@ -120,7 +122,7 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
120
122
  _check_python_layout(
121
123
  area="API layout",
122
124
  project_dir=api_dir,
123
- src_package=api_dir / "src" / f"{name_underscore}_api",
125
+ src_package=api_dir / "src" / api_name,
124
126
  suggestion=f"rpr generate api {name}",
125
127
  )
126
128
  )
@@ -138,23 +140,23 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
138
140
  pyproject=api_dir / "pyproject.toml",
139
141
  required_dependencies=set(api_runtime_dependencies(name)),
140
142
  suggestion=f"rpr generate api {name}",
141
- required_sources={f"{name}-domain": {"workspace": True}},
143
+ required_sources={domain_name: {"workspace": True}},
142
144
  )
143
145
  )
144
146
  results.append(
145
147
  CheckResult(
146
148
  group="Generated Packages & Apps",
147
149
  area="API workspace member",
148
- status=f"apps/{name}-api" in workspace_members,
149
- path=f"apps/{name}-api"
150
- if f"apps/{name}-api" in workspace_members
151
- else f"apps/{name}-api missing from [tool.uv.workspace].members",
150
+ status=f"apps/{api_name}" in workspace_members,
151
+ path=f"apps/{api_name}"
152
+ if f"apps/{api_name}" in workspace_members
153
+ else f"apps/{api_name} missing from [tool.uv.workspace].members",
152
154
  suggestion=f"rpr generate api {name}",
153
155
  )
154
156
  )
155
157
 
156
158
  # UI library
157
- ui_dir = project_dir / "packages" / "node" / f"{name}-ui"
159
+ ui_dir = project_dir / "packages" / "node" / ui_name
158
160
  results.append(
159
161
  CheckResult(
160
162
  group="Generated Packages & Apps",
@@ -179,22 +181,19 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
179
181
  _check_node_dependency_contract(
180
182
  area="UI install metadata",
181
183
  package_json=ui_dir / "package.json",
182
- required_dependencies=mapping_dependency_names(UI_LIBRARY_DEPENDENCIES),
183
- required_dev_dependencies=mapping_dependency_names(
184
- UI_LIBRARY_DEV_DEPENDENCIES
185
- ),
184
+ expected_name=f"@{npm_package_name(name)}/ui",
186
185
  suggestion=f"rpr generate ui {name}",
187
186
  )
188
187
  )
189
188
 
190
189
  # Web app
191
- web_dir = project_dir / "apps" / f"{name}-web"
190
+ web_dir = project_dir / "apps" / web_name
192
191
  results.append(
193
192
  CheckResult(
194
193
  group="Generated Packages & Apps",
195
194
  area="Web app",
196
195
  status=web_dir.exists(),
197
- path=str(web_dir) if web_dir.exists() else f"apps/{name}-web/ missing",
196
+ path=str(web_dir) if web_dir.exists() else f"apps/{web_name}/ missing",
198
197
  suggestion=f"rpr generate ui {name} --no-library",
199
198
  )
200
199
  )
@@ -209,14 +208,9 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
209
208
  )
210
209
  results.append(
211
210
  _check_node_dependency_contract(
212
- area="Web install metadata",
211
+ area="Web package metadata",
213
212
  package_json=web_dir / "package.json",
214
- required_dependencies=mapping_dependency_names(
215
- web_app_dependencies(f"{name}-ui")
216
- ),
217
- required_dev_dependencies=mapping_dependency_names(
218
- WEB_APP_DEV_DEPENDENCIES
219
- ),
213
+ expected_name=f"@{npm_package_name(name)}/web",
220
214
  suggestion=f"rpr generate ui {name} --no-library",
221
215
  )
222
216
  )
@@ -251,30 +245,15 @@ def check_packages(project_dir: Path, variables: dict[str, str]) -> list[CheckRe
251
245
  )
252
246
  results.append(
253
247
  _check_node_dependency_contract(
254
- area="Storybook host install metadata",
248
+ area="Storybook host package metadata",
255
249
  package_json=sb_dir / "package.json",
256
- required_dependencies=mapping_dependency_names(
257
- storybook_package_dependencies(f"{name}-ui")
258
- ),
259
- required_dev_dependencies=mapping_dependency_names(
260
- STORYBOOK_DEV_DEPENDENCIES
261
- ),
262
- suggestion="rpr generate storybook",
263
- )
264
- )
265
- results.append(
266
- _check_node_dependency_contract(
267
- area="Storybook root install metadata",
268
- package_json=project_dir / "package.json",
269
- required_dev_dependencies=mapping_dependency_names(
270
- ROOT_STORYBOOK_DEV_DEPENDENCIES
271
- ),
250
+ expected_name=f"@{npm_package_name(name)}/sb",
272
251
  suggestion="rpr generate storybook",
273
252
  )
274
253
  )
275
254
 
276
255
  # Engine
277
- engine_dir = next(project_dir.glob("packages/python/*-engine"), None)
256
+ engine_dir = next(project_dir.glob("packages/python/*_engine"), None)
278
257
  results.append(
279
258
  CheckResult(
280
259
  group="Generated Packages & Apps",
@@ -300,7 +279,7 @@ def _load_json(path: Path) -> dict[str, object] | None:
300
279
  return None
301
280
  try:
302
281
  data = json.loads(path.read_text())
303
- except (OSError, json.JSONDecodeError):
282
+ except OSError, json.JSONDecodeError:
304
283
  return None
305
284
  return data if isinstance(data, dict) else None
306
285
 
@@ -310,7 +289,7 @@ def _load_toml(path: Path) -> dict[str, object] | None:
310
289
  return None
311
290
  try:
312
291
  data = tomllib.loads(path.read_text())
313
- except (OSError, tomllib.TOMLDecodeError):
292
+ except OSError, tomllib.TOMLDecodeError:
314
293
  return None
315
294
  return data if isinstance(data, dict) else None
316
295
 
@@ -405,7 +384,9 @@ def _check_python_dependency_contract(
405
384
  suggestion=suggestion,
406
385
  )
407
386
 
408
- project = data.get("project", {}) if isinstance(data.get("project", {}), dict) else {}
387
+ project = (
388
+ data.get("project", {}) if isinstance(data.get("project", {}), dict) else {}
389
+ )
409
390
  dependencies = project.get("dependencies", []) if isinstance(project, dict) else []
410
391
  dependency_set = set(dependencies) if isinstance(dependencies, list) else set()
411
392
  missing_dependencies = sorted(required_dependencies.difference(dependency_set))
@@ -434,9 +415,7 @@ def _check_python_dependency_contract(
434
415
  group="Generated Packages & Apps",
435
416
  area=area,
436
417
  status=status,
437
- path=str(pyproject)
438
- if status
439
- else f"{pyproject} {'; '.join(details)}",
418
+ path=str(pyproject) if status else f"{pyproject} {'; '.join(details)}",
440
419
  suggestion=suggestion,
441
420
  )
442
421
 
@@ -446,6 +425,7 @@ def _check_node_dependency_contract(
446
425
  area: str,
447
426
  package_json: Path,
448
427
  suggestion: str,
428
+ expected_name: str | None = None,
449
429
  required_dependencies: set[str] | None = None,
450
430
  required_dev_dependencies: set[str] | None = None,
451
431
  ) -> CheckResult:
@@ -459,6 +439,15 @@ def _check_node_dependency_contract(
459
439
  suggestion=suggestion,
460
440
  )
461
441
 
442
+ if expected_name is not None and data.get("name") != expected_name:
443
+ return CheckResult(
444
+ group="Generated Packages & Apps",
445
+ area=area,
446
+ status=False,
447
+ path=f"{package_json} expected name '{expected_name}'",
448
+ suggestion=suggestion,
449
+ )
450
+
462
451
  dependencies = data.get("dependencies", {})
463
452
  dev_dependencies = data.get("devDependencies", {})
464
453
  dependency_keys = set(dependencies) if isinstance(dependencies, dict) else set()
@@ -486,9 +475,7 @@ def _check_node_dependency_contract(
486
475
  group="Generated Packages & Apps",
487
476
  area=area,
488
477
  status=status,
489
- path=str(package_json)
490
- if status
491
- else f"{package_json} {'; '.join(details)}",
478
+ path=str(package_json) if status else f"{package_json} {'; '.join(details)}",
492
479
  suggestion=suggestion,
493
480
  )
494
481
 
@@ -498,7 +485,11 @@ def _check_domain_migration_scaffold(
498
485
  ) -> CheckResult:
499
486
  project_json = domain_dir / "project.json"
500
487
  project = _load_json(project_json) or {}
501
- targets = project.get("targets", {}) if isinstance(project.get("targets", {}), dict) else {}
488
+ targets = (
489
+ project.get("targets", {})
490
+ if isinstance(project.get("targets", {}), dict)
491
+ else {}
492
+ )
502
493
  migrate_target = targets.get("migrate") if isinstance(targets, dict) else None
503
494
 
504
495
  alembic_ini = domain_dir / "alembic.ini"
@@ -521,16 +512,19 @@ def _check_domain_migration_scaffold(
521
512
  suggestion=f"rpr generate domain {name} --migrations",
522
513
  )
523
514
 
524
- options = migrate_target.get("options", {}) if isinstance(migrate_target, dict) else {}
515
+ options = (
516
+ migrate_target.get("options", {}) if isinstance(migrate_target, dict) else {}
517
+ )
525
518
  command_ok = isinstance(options, dict) and options.get("command") == (
526
- "uv run alembic -c packages/python/domain/alembic.ini"
519
+ f"uv run alembic -c packages/python/{name_underscore}_domain/alembic.ini"
527
520
  )
528
521
  cwd_ok = isinstance(options, dict) and options.get("cwd") == "."
529
522
  env_ok = False
530
523
  if env_py.exists():
531
524
  env_content = env_py.read_text()
532
525
  env_ok = (
533
- f"from {name_underscore}_domain.config.settings import Settings" in env_content
526
+ f"from {name_underscore}_domain.config.settings import Settings"
527
+ in env_content
534
528
  and f"import {name_underscore}_domain.entities" in env_content
535
529
  )
536
530
 
@@ -559,9 +553,7 @@ def _check_domain_migration_scaffold(
559
553
  )
560
554
 
561
555
 
562
- def _check_engine_install_metadata(
563
- *, engine_dir: Path, suggestion: str
564
- ) -> CheckResult:
556
+ def _check_engine_install_metadata(*, engine_dir: Path, suggestion: str) -> CheckResult:
565
557
  pyproject = engine_dir / "pyproject.toml"
566
558
  data = _load_toml(pyproject)
567
559
  if data is None:
@@ -574,7 +566,9 @@ def _check_engine_install_metadata(
574
566
  )
575
567
 
576
568
  build_system = data.get("build-system", {})
577
- requires = build_system.get("requires", []) if isinstance(build_system, dict) else []
569
+ requires = (
570
+ build_system.get("requires", []) if isinstance(build_system, dict) else []
571
+ )
578
572
  requires_set = set(requires) if isinstance(requires, list) else set()
579
573
  status = MATURIN_SPEC in requires_set
580
574
  return CheckResult(
@@ -10,6 +10,7 @@ from rich.console import Console
10
10
  from rpr.cli import generate_app
11
11
  from rpr.context import RunContext
12
12
  from rpr.dependencies import api_runtime_dependencies
13
+ from rpr.dependencies import python_project_name
13
14
  from rpr.workspace import add_workspace_member
14
15
 
15
16
  console = Console()
@@ -29,11 +30,10 @@ def api(
29
30
  name = typer.prompt("App name")
30
31
 
31
32
  ctx = RunContext(dry_run=dry_run, project_dir=Path.cwd())
32
- app_name = f"{name}-api"
33
- app_name_underscore = app_name.replace("-", "_")
34
- domain_underscore = f"{name}_domain".replace("-", "_")
33
+ app_name = python_project_name(name, "api")
34
+ domain_name = python_project_name(name, "domain")
35
35
  api_root = ctx.project_dir / "apps" / app_name
36
- src_root = api_root / "src" / app_name_underscore
36
+ src_root = api_root / "src" / app_name
37
37
  tests_root = api_root / "tests"
38
38
 
39
39
  console.print(f"\n[bold]Generating FastAPI app:[/] {app_name}\n")
@@ -41,14 +41,14 @@ def api(
41
41
  ctx.ensure_dir(src_root / "routes")
42
42
  ctx.ensure_dir(tests_root)
43
43
 
44
- _write_api_pyproject(ctx, api_root, name, app_name, app_name_underscore)
44
+ _write_api_pyproject(ctx, api_root, name, app_name, domain_name)
45
45
  _write_api_readme(ctx, api_root, name)
46
- _write_api_project_json(ctx, api_root, app_name, app_name_underscore)
47
- _write_main(ctx, src_root / "main.py", name, domain_underscore)
46
+ _write_api_project_json(ctx, api_root, app_name)
47
+ _write_main(ctx, src_root / "main.py", name, domain_name)
48
48
  _write_init_file(ctx, src_root / "__init__.py")
49
49
  _write_init_file(ctx, src_root / "routes" / "__init__.py")
50
50
  _write_health_route(ctx, src_root / "routes" / "health.py")
51
- _write_health_test(ctx, tests_root / "test_health.py", app_name_underscore)
51
+ _write_health_test(ctx, tests_root / "test_health.py", app_name)
52
52
 
53
53
  add_workspace_member(ctx, f"apps/{app_name}")
54
54
  ctx.preview_dependencies(
@@ -58,7 +58,8 @@ def api(
58
58
  )
59
59
 
60
60
  if not dry_run:
61
- ctx.run_command(["uv", "sync"], cwd=ctx.project_dir)
61
+ ctx.run_uv_command(["uv", "add", *api_runtime_dependencies(name)], cwd=api_root)
62
+ ctx.run_uv_command(["uv", "sync", "--all-packages"], cwd=ctx.project_dir)
62
63
 
63
64
  console.print(f"\n[bold green]Done![/] FastAPI app created at {api_root}")
64
65
  console.print(f" Run with: npx nx serve {app_name}")
@@ -69,7 +70,7 @@ def _write_init_file(ctx: RunContext, path: Path) -> None:
69
70
 
70
71
 
71
72
  def _write_api_pyproject(
72
- ctx: RunContext, api_root: Path, name: str, app_name: str, app_name_underscore: str
73
+ ctx: RunContext, api_root: Path, name: str, app_name: str, domain_name: str
73
74
  ) -> None:
74
75
  content = f"""[project]
75
76
  name = "{app_name}"
@@ -77,21 +78,17 @@ version = "0.1.0"
77
78
  description = "{name} API"
78
79
  readme = "README.md"
79
80
  requires-python = ">=3.12"
80
- dependencies = [
81
- "{api_runtime_dependencies(name)[0]}",
82
- "{api_runtime_dependencies(name)[1]}",
83
- "{api_runtime_dependencies(name)[2]}",
84
- ]
81
+ dependencies = []
85
82
 
86
83
  [build-system]
87
84
  requires = ["hatchling"]
88
85
  build-backend = "hatchling.build"
89
86
 
90
87
  [tool.hatch.build.targets.wheel]
91
- packages = ["src/{app_name_underscore}"]
88
+ packages = ["src/{app_name}"]
92
89
 
93
90
  [tool.uv.sources]
94
- {name}-domain = {{ workspace = true }}
91
+ {domain_name} = {{ workspace = true }}
95
92
 
96
93
  [tool.pytest.ini_options]
97
94
  testpaths = ["tests"]
@@ -107,9 +104,7 @@ FastAPI application generated by RPR.
107
104
  ctx.write_file(api_root / "README.md", content)
108
105
 
109
106
 
110
- def _write_api_project_json(
111
- ctx: RunContext, api_root: Path, app_name: str, app_name_underscore: str
112
- ) -> None:
107
+ def _write_api_project_json(ctx: RunContext, api_root: Path, app_name: str) -> None:
113
108
  project = {
114
109
  "name": app_name,
115
110
  "root": f"apps/{app_name}",
@@ -117,7 +112,7 @@ def _write_api_project_json(
117
112
  "serve": {
118
113
  "executor": "nx:run-commands",
119
114
  "options": {
120
- "command": f"uv run uvicorn {app_name_underscore}.main:app --reload --host 0.0.0.0 --port 8000",
115
+ "command": f"uv run uvicorn {app_name}.main:app --reload --host 0.0.0.0 --port 8000",
121
116
  "cwd": f"apps/{app_name}",
122
117
  },
123
118
  },