scaffold-ca-python 0.2.0__tar.gz → 0.2.1__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 (370) hide show
  1. scaffold_ca_python-0.2.1/.release-please-manifest.json +3 -0
  2. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/memory/constitution.md +25 -2
  3. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/CHANGELOG.md +7 -0
  4. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/PKG-INFO +1 -1
  5. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/pyproject.toml +7 -1
  6. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/checklists/requirements.md +35 -0
  7. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/contracts/cli-behavior.md +49 -0
  8. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/contracts/factory-extension.md +46 -0
  9. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/data-model.md +112 -0
  10. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/plan.md +189 -0
  11. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/quickstart.md +93 -0
  12. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/research.md +167 -0
  13. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/spec.md +241 -0
  14. scaffold_ca_python-0.2.1/specs/022-solid-code-cleanup/tasks.md +573 -0
  15. scaffold_ca_python-0.2.1/specs/023-error-hints/spec.md +25 -0
  16. scaffold_ca_python-0.2.1/specs/024-typed-template-contexts/spec.md +31 -0
  17. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/_entry_point_rules.py +53 -0
  18. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/_shared.py +109 -0
  19. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/add_mcp_tool.py +200 -0
  20. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/delete_module.py +110 -0
  21. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_driven_adapter.py +124 -0
  22. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_entry_point.py +249 -0
  23. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_helper.py +78 -0
  24. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_model.py +77 -0
  25. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_pipeline.py +114 -0
  26. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_project.py +159 -0
  27. scaffold_ca_python-0.2.1/src/scaffold_ca_python/commands/generate_use_case.py +83 -0
  28. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/commands/update_project.py +19 -32
  29. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/commands/validate_structure.py +8 -12
  30. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/file_writer.py +55 -70
  31. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/mcp_tool_spec.py +1 -1
  32. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/module_builder.py +13 -6
  33. scaffold_ca_python-0.2.1/src/scaffold_ca_python/core/module_locator.py +45 -0
  34. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/name_utils.py +1 -6
  35. scaffold_ca_python-0.2.1/src/scaffold_ca_python/core/openapi_routes.py +34 -0
  36. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/project_detector.py +14 -9
  37. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/structure_validator.py +66 -59
  38. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/template_renderer.py +1 -9
  39. scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/driven_adapters/__init__.py +14 -0
  40. scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/driven_adapters/base.py +23 -0
  41. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/driven_adapters/da_generic.py +3 -3
  42. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/driven_adapters/da_rest_consumer.py +4 -3
  43. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/driven_adapters/da_secrets.py +4 -3
  44. scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/entry_points/__init__.py +16 -0
  45. scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/entry_points/base.py +63 -0
  46. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/entry_points/ep_agent.py +13 -4
  47. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/entry_points/ep_generic.py +13 -4
  48. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/entry_points/ep_mcp.py +15 -8
  49. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/entry_points/ep_restapi.py +34 -6
  50. scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/pipelines/__init__.py +20 -0
  51. scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/pipelines/pipeline_factory.py +27 -0
  52. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/simple/delete_module_factory.py +10 -11
  53. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/simple/helper_factory.py +1 -1
  54. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/simple/model_factory.py +1 -1
  55. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/simple/use_case_factory.py +1 -1
  56. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/models/context.py +1 -1
  57. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/models/layer.py +1 -1
  58. scaffold_ca_python-0.2.1/src/scaffold_ca_python/models/options.py +53 -0
  59. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/models/violation.py +1 -1
  60. scaffold_ca_python-0.2.1/src/scaffold_ca_python/templates/project/package_init.py.jinja2 +1 -0
  61. scaffold_ca_python-0.2.1/tests/commands/test_behavior_contract.py +198 -0
  62. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_pipeline.py +46 -0
  63. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_project.py +32 -0
  64. scaffold_ca_python-0.2.1/tests/commands/test_shared.py +129 -0
  65. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_file_writer.py +36 -1
  66. scaffold_ca_python-0.2.1/tests/core/test_module_locator.py +62 -0
  67. scaffold_ca_python-0.2.1/tests/core/test_openapi_routes.py +53 -0
  68. scaffold_ca_python-0.2.1/tests/core/test_project_context.py +98 -0
  69. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_pyproject_writer.py +1 -1
  70. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/entry_points/test_ep_mcp.py +2 -2
  71. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/entry_points/test_ep_restapi.py +1 -3
  72. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/test_dry_run_parity.py +4 -3
  73. scaffold_ca_python-0.2.1/tests/factory/test_extensibility.py +94 -0
  74. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/test_module_builder.py +87 -0
  75. scaffold_ca_python-0.2.1/tests/factory/test_registry.py +114 -0
  76. scaffold_ca_python-0.2.1/tests/models/test_options.py +65 -0
  77. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_project_templates.py +17 -0
  78. scaffold_ca_python-0.2.1/tests/test_source_hygiene.py +34 -0
  79. scaffold_ca_python-0.2.0/.release-please-manifest.json +0 -3
  80. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/delete_module.py +0 -201
  81. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_driven_adapter.py +0 -187
  82. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_entry_point.py +0 -593
  83. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_helper.py +0 -135
  84. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_model.py +0 -134
  85. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_pipeline.py +0 -158
  86. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_project.py +0 -189
  87. scaffold_ca_python-0.2.0/src/scaffold_ca_python/commands/generate_use_case.py +0 -138
  88. scaffold_ca_python-0.2.0/tests/factory/test_extensibility.py +0 -46
  89. scaffold_ca_python-0.2.0/tests/factory/test_registry.py +0 -54
  90. scaffold_ca_python-0.2.0/tests/templates/__init__.py +0 -0
  91. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/copilot-instructions.md +0 -0
  92. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/issue_template.md +0 -0
  93. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/pull_request_template.md +0 -0
  94. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-analyze/SKILL.md +0 -0
  95. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-checklist/SKILL.md +0 -0
  96. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-clarify/SKILL.md +0 -0
  97. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-constitution/SKILL.md +0 -0
  98. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-converge/SKILL.md +0 -0
  99. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-implement/SKILL.md +0 -0
  100. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-plan/SKILL.md +0 -0
  101. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-specify/SKILL.md +0 -0
  102. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-tasks/SKILL.md +0 -0
  103. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/skills/speckit-taskstoissues/SKILL.md +0 -0
  104. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/workflows/build.yml +0 -0
  105. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/workflows/dependency-review.yml +0 -0
  106. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/workflows/publish.yml +0 -0
  107. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/workflows/release-please.yml +0 -0
  108. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/workflows/scorecards-analysis.yml +0 -0
  109. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.github/workflows/secret-scanner.yml +0 -0
  110. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.gitignore +0 -0
  111. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.pre-commit-config.yaml +0 -0
  112. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.python-version +0 -0
  113. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/.gitignore +0 -0
  114. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/init-options.json +0 -0
  115. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/integration.json +0 -0
  116. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/integrations/copilot.manifest.json +0 -0
  117. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/integrations/speckit.manifest.json +0 -0
  118. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  119. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/common.sh +0 -0
  120. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/create-new-feature.sh +0 -0
  121. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/resolve-template.sh +0 -0
  122. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/setup-plan.sh +0 -0
  123. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/setup-tasks.sh +0 -0
  124. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/scripts/bash/update-agent-context.sh +0 -0
  125. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/templates/agent-file-template.md +0 -0
  126. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/templates/checklist-template.md +0 -0
  127. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/templates/constitution-template.md +0 -0
  128. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/templates/plan-template.md +0 -0
  129. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/templates/spec-template.md +0 -0
  130. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/.specify/templates/tasks-template.md +0 -0
  131. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/LICENSE +0 -0
  132. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/README.md +0 -0
  133. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/SECURITY.md +0 -0
  134. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/release-please-config.json +0 -0
  135. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/checklists/requirements.md +0 -0
  136. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/ca.md +0 -0
  137. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/dm.md +0 -0
  138. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/gda.md +0 -0
  139. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/gep.md +0 -0
  140. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/gh.md +0 -0
  141. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/gm.md +0 -0
  142. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/gpipe.md +0 -0
  143. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/guc.md +0 -0
  144. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/up.md +0 -0
  145. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/contracts/vs.md +0 -0
  146. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/data-model.md +0 -0
  147. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/plan.md +0 -0
  148. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/quickstart.md +0 -0
  149. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/research.md +0 -0
  150. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/spec.md +0 -0
  151. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/004-scaffold-ca-python-cli/tasks.md +0 -0
  152. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/006-ca-scaffold-enhancements/checklists/requirements.md +0 -0
  153. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/006-ca-scaffold-enhancements/plan.md +0 -0
  154. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/006-ca-scaffold-enhancements/spec.md +0 -0
  155. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/006-ca-scaffold-enhancements/tasks.md +0 -0
  156. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/checklists/requirements.md +0 -0
  157. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/contracts/clean-architecture.md +0 -0
  158. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/contracts/gda.md +0 -0
  159. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/contracts/gep.md +0 -0
  160. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/contracts/gpipe.md +0 -0
  161. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/data-model.md +0 -0
  162. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/plan.md +0 -0
  163. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/quickstart.md +0 -0
  164. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/research.md +0 -0
  165. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/spec.md +0 -0
  166. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/007-cli-usability-enhancements/tasks.md +0 -0
  167. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/checklists/requirements.md +0 -0
  168. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/contracts/gep.md +0 -0
  169. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/data-model.md +0 -0
  170. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/plan.md +0 -0
  171. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/quickstart.md +0 -0
  172. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/research.md +0 -0
  173. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/spec.md +0 -0
  174. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/008-fastapi-entrypoint-baseline/tasks.md +0 -0
  175. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/checklists/requirements.md +0 -0
  176. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/contracts/gep-restapi.md +0 -0
  177. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/data-model.md +0 -0
  178. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/plan.md +0 -0
  179. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/quickstart.md +0 -0
  180. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/research.md +0 -0
  181. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/spec.md +0 -0
  182. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/009-app-factory-split/tasks.md +0 -0
  183. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/011-fix-restapi-cleanup/data-model.md +0 -0
  184. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/011-fix-restapi-cleanup/plan.md +0 -0
  185. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/011-fix-restapi-cleanup/quickstart.md +0 -0
  186. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/011-fix-restapi-cleanup/research.md +0 -0
  187. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/011-fix-restapi-cleanup/spec.md +0 -0
  188. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/011-fix-restapi-cleanup/tasks.md +0 -0
  189. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/checklists/requirements.md +0 -0
  190. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/data-model.md +0 -0
  191. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/plan.md +0 -0
  192. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/quickstart.md +0 -0
  193. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/research.md +0 -0
  194. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/spec.md +0 -0
  195. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/012-fix-restapi-test-templates/tasks.md +0 -0
  196. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/checklists/requirements.md +0 -0
  197. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/data-model.md +0 -0
  198. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/plan.md +0 -0
  199. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/quickstart.md +0 -0
  200. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/research.md +0 -0
  201. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/spec.md +0 -0
  202. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/014-tests-in-src/tasks.md +0 -0
  203. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/checklists/requirements.md +0 -0
  204. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/data-model.md +0 -0
  205. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/plan.md +0 -0
  206. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/quickstart.md +0 -0
  207. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/research.md +0 -0
  208. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/spec.md +0 -0
  209. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/015-factory-builder-refactor/tasks.md +0 -0
  210. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/016-dedup-command-aliases/checklists/requirements.md +0 -0
  211. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/016-dedup-command-aliases/data-model.md +0 -0
  212. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/016-dedup-command-aliases/plan.md +0 -0
  213. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/016-dedup-command-aliases/research.md +0 -0
  214. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/016-dedup-command-aliases/spec.md +0 -0
  215. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/016-dedup-command-aliases/tasks.md +0 -0
  216. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/checklists/requirements.md +0 -0
  217. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/contracts/name-validation.md +0 -0
  218. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/data-model.md +0 -0
  219. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/plan.md +0 -0
  220. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/research.md +0 -0
  221. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/spec.md +0 -0
  222. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/017-pep8-naming-validation/tasks.md +0 -0
  223. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/019-mcp-entry-point-restructure/contracts/gep-mcp.md +0 -0
  224. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/019-mcp-entry-point-restructure/data-model.md +0 -0
  225. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/019-mcp-entry-point-restructure/plan.md +0 -0
  226. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/019-mcp-entry-point-restructure/research.md +0 -0
  227. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/019-mcp-entry-point-restructure/spec.md +0 -0
  228. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/019-mcp-entry-point-restructure/tasks.md +0 -0
  229. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/checklists/requirements.md +0 -0
  230. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/contracts/readme-outline.md +0 -0
  231. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/data-model.md +0 -0
  232. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/plan.md +0 -0
  233. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/quickstart.md +0 -0
  234. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/research.md +0 -0
  235. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/spec.md +0 -0
  236. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/020-pypi-publish-readme/tasks.md +0 -0
  237. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/checklists/requirements.md +0 -0
  238. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/contracts/gep-add-tool.md +0 -0
  239. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/data-model.md +0 -0
  240. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/plan.md +0 -0
  241. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/quickstart.md +0 -0
  242. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/research.md +0 -0
  243. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/spec.md +0 -0
  244. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/specs/021-mcp-add-tool/tasks.md +0 -0
  245. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/__init__.py +0 -0
  246. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/cli.py +0 -0
  247. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/commands/__init__.py +0 -0
  248. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/__init__.py +0 -0
  249. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/core/pyproject_writer.py +0 -0
  250. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/factory/__init__.py +0 -0
  251. {scaffold_ca_python-0.2.0/src/scaffold_ca_python/factory/driven_adapters → scaffold_ca_python-0.2.1/src/scaffold_ca_python/factory/simple}/__init__.py +0 -0
  252. {scaffold_ca_python-0.2.0/src/scaffold_ca_python/factory/entry_points → scaffold_ca_python-0.2.1/src/scaffold_ca_python/models}/__init__.py +0 -0
  253. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/models/file_operation.py +0 -0
  254. {scaffold_ca_python-0.2.0/src/scaffold_ca_python/factory/simple → scaffold_ca_python-0.2.1/src/scaffold_ca_python/templates}/__init__.py +0 -0
  255. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/generic/__init__.py.jinja2 +0 -0
  256. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/generic/adapter.py.jinja2 +0 -0
  257. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/generic/test_adapter.py.jinja2 +0 -0
  258. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/rest_consumer/__init__.py.jinja2 +0 -0
  259. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/rest_consumer/rest_consumer.py.jinja2 +0 -0
  260. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/rest_consumer/test_rest_consumer.py.jinja2 +0 -0
  261. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/secrets/__init__.py.jinja2 +0 -0
  262. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/secrets/secrets_adapter.py.jinja2 +0 -0
  263. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/driven_adapter/secrets/test_secrets_adapter.py.jinja2 +0 -0
  264. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/agent/__init__.py.jinja2 +0 -0
  265. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/agent/agent.py.jinja2 +0 -0
  266. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/agent/card.py.jinja2 +0 -0
  267. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/agent/entrypoint_main.py.jinja2 +0 -0
  268. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/agent/test_agent.py.jinja2 +0 -0
  269. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/generic/__init__.py.jinja2 +0 -0
  270. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/generic/entrypoint_main.py.jinja2 +0 -0
  271. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/generic/handler.py.jinja2 +0 -0
  272. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/generic/test_handler.py.jinja2 +0 -0
  273. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/__init__.py.jinja2 +0 -0
  274. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/app.py.jinja2 +0 -0
  275. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/prompts.py.jinja2 +0 -0
  276. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/resources.py.jinja2 +0 -0
  277. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/server.py.jinja2 +0 -0
  278. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/test_app.py.jinja2 +0 -0
  279. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/test_prompts.py.jinja2 +0 -0
  280. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/test_resources.py.jinja2 +0 -0
  281. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/test_tool_stub.py.jinja2 +0 -0
  282. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/test_tools.py.jinja2 +0 -0
  283. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/tool_stub.py.jinja2 +0 -0
  284. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/mcp/tools.py.jinja2 +0 -0
  285. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/__init__.py.jinja2 +0 -0
  286. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/app.py.jinja2 +0 -0
  287. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/exception_handler.py.jinja2 +0 -0
  288. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/health.py.jinja2 +0 -0
  289. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/rest_controller.py.jinja2 +0 -0
  290. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/server.py.jinja2 +0 -0
  291. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/test_app.py.jinja2 +0 -0
  292. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/test_exception_handler.py.jinja2 +0 -0
  293. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/test_rest_controller.py.jinja2 +0 -0
  294. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/entry_point/restapi/test_server.py.jinja2 +0 -0
  295. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/helper/__init__.py.jinja2 +0 -0
  296. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/helper/helper.py.jinja2 +0 -0
  297. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/helper/test_helper.py.jinja2 +0 -0
  298. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/model/model.py.jinja2 +0 -0
  299. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/model/test_model.py.jinja2 +0 -0
  300. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/pipeline/azure/azure_pipelines.yml.jinja2 +0 -0
  301. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/pipeline/github/ci.yml.jinja2 +0 -0
  302. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/README.jinja2 +0 -0
  303. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/application/config/__init__.py.jinja2 +0 -0
  304. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/application/config/config.py.jinja2 +0 -0
  305. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/application/config/container.py.jinja2 +0 -0
  306. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/application/config/driven_adapters_container.py.jinja2 +0 -0
  307. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/application/config/resource_container.py.jinja2 +0 -0
  308. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/application/config/usecases_container.py.jinja2 +0 -0
  309. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/dockerfile.jinja2 +0 -0
  310. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/dockerignore.jinja2 +0 -0
  311. /scaffold_ca_python-0.2.0/src/scaffold_ca_python/models/__init__.py → /scaffold_ca_python-0.2.1/src/scaffold_ca_python/templates/project/empty.jinja2 +0 -0
  312. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/gitignore.jinja2 +0 -0
  313. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/layer_init.jinja2 +0 -0
  314. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/main.py.jinja2 +0 -0
  315. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/mypy_ini.jinja2 +0 -0
  316. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/pyproject_toml.jinja2 +0 -0
  317. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/project/python_version.jinja2 +0 -0
  318. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/use_case/test_use_case.py.jinja2 +0 -0
  319. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/src/scaffold_ca_python/templates/use_case/use_case.py.jinja2 +0 -0
  320. {scaffold_ca_python-0.2.0/src/scaffold_ca_python/templates → scaffold_ca_python-0.2.1/tests}/__init__.py +0 -0
  321. {scaffold_ca_python-0.2.0/tests → scaffold_ca_python-0.2.1/tests/commands}/__init__.py +0 -0
  322. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_cli.py +0 -0
  323. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_delete_module.py +0 -0
  324. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_dry_run_checksum.py +0 -0
  325. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_driven_adapter.py +0 -0
  326. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_entry_point.py +0 -0
  327. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_helper.py +0 -0
  328. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_model.py +0 -0
  329. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_generate_use_case.py +0 -0
  330. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_performance.py +0 -0
  331. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_update_project.py +0 -0
  332. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_validate_structure.py +0 -0
  333. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/commands/test_workflow.py +0 -0
  334. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/conftest.py +0 -0
  335. {scaffold_ca_python-0.2.0/tests/commands → scaffold_ca_python-0.2.1/tests/core}/__init__.py +0 -0
  336. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_mcp_tool_spec.py +0 -0
  337. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_name_utils.py +0 -0
  338. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_project_detector.py +0 -0
  339. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_structure_validator.py +0 -0
  340. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/core/test_template_renderer.py +0 -0
  341. {scaffold_ca_python-0.2.0/tests/core → scaffold_ca_python-0.2.1/tests/factory}/__init__.py +0 -0
  342. {scaffold_ca_python-0.2.0/tests/factory → scaffold_ca_python-0.2.1/tests/factory/driven_adapters}/__init__.py +0 -0
  343. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/driven_adapters/test_da_generic.py +0 -0
  344. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/driven_adapters/test_da_rest_consumer.py +0 -0
  345. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/driven_adapters/test_da_secrets.py +0 -0
  346. {scaffold_ca_python-0.2.0/tests/factory/driven_adapters → scaffold_ca_python-0.2.1/tests/factory/entry_points}/__init__.py +0 -0
  347. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/entry_points/test_ep_agent.py +0 -0
  348. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/entry_points/test_ep_generic.py +0 -0
  349. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/fixtures/dry_run_baseline.json +0 -0
  350. {scaffold_ca_python-0.2.0/tests/factory/entry_points → scaffold_ca_python-0.2.1/tests/factory/simple}/__init__.py +0 -0
  351. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/simple/test_delete_module_factory.py +0 -0
  352. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/simple/test_helper_factory.py +0 -0
  353. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/simple/test_model_factory.py +0 -0
  354. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/factory/simple/test_use_case_factory.py +0 -0
  355. {scaffold_ca_python-0.2.0/tests/factory/simple → scaffold_ca_python-0.2.1/tests/models}/__init__.py +0 -0
  356. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/models/test_context.py +0 -0
  357. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/models/test_file_operation.py +0 -0
  358. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/models/test_layer.py +0 -0
  359. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/models/test_violation.py +0 -0
  360. {scaffold_ca_python-0.2.0/tests/models → scaffold_ca_python-0.2.1/tests/templates}/__init__.py +0 -0
  361. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_di_config_templates.py +0 -0
  362. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_docker_templates.py +0 -0
  363. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_driven_adapter_templates.py +0 -0
  364. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_entry_point_templates.py +0 -0
  365. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_entrypoint_main_templates.py +0 -0
  366. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_helper_templates.py +0 -0
  367. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_model_templates.py +0 -0
  368. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_pipeline_templates.py +0 -0
  369. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/tests/templates/test_use_case_templates.py +0 -0
  370. {scaffold_ca_python-0.2.0 → scaffold_ca_python-0.2.1}/uv.lock +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.2.1"
3
+ }
@@ -34,6 +34,19 @@ None — all placeholders resolved.
34
34
 
35
35
  ---
36
36
 
37
+ ### Amendment v2.1.0 (2026-10-22) — MINOR
38
+ **Type**: MINOR — new governance clause (materially expanded guidance).
39
+
40
+ **Changes**:
41
+ - Governance: added "Pre-existing violations" clause. A feature MAY keep a violation that
42
+ already existed on `main` if the plan documents it as pre-existing debt in Complexity
43
+ Tracking and names a numbered follow-up feature whose spec directory exists before merge.
44
+ New code introduced by a feature MUST still comply with every principle.
45
+
46
+ **Templates updated**: None. First applied by `specs/022-solid-code-cleanup/plan.md`.
47
+
48
+ ---
49
+
37
50
  ### Amendment v2.0.3 (2026-04-10) — PATCH
38
51
  **Type**: PATCH — branch naming exception; no semantic change to other governance rules.
39
52
 
@@ -75,7 +88,7 @@ or artifact structure was affected.
75
88
 
76
89
  # scaffold-ca-python Constitution
77
90
 
78
- **Version**: 2.0.3 | **Ratified**: 2026-03-25 | **Last amended**: 2026-04-10
91
+ **Version**: 2.1.0 | **Ratified**: 2026-03-25 | **Last amended**: 2026-10-22
79
92
 
80
93
  ## Core Principles
81
94
 
@@ -255,7 +268,17 @@ dependencies listed in Principle III, installed via `uv` at generation time.
255
268
  - **PATCH**: clarifications, wording improvements, or typo fixes with no semantic change.
256
269
  - All pull requests MUST include a Constitution Check section in their plan document
257
270
  verifying compliance with every applicable principle.
271
+ - **Pre-existing violations**: A feature MAY leave a violation of a principle in place only if
272
+ all of the following hold:
273
+ 1. The violation existed on `main` before the feature branch was created (it is not
274
+ introduced or worsened by the feature).
275
+ 2. The plan's Constitution Check marks the principle as "⚠️ pre-existing debt" and the
276
+ Complexity Tracking table records the violation, its measured extent, and why fixing it
277
+ is out of scope.
278
+ 3. A numbered follow-up feature (e.g. `023-error-hints`) is named in Complexity Tracking
279
+ and its spec directory is created before the feature is merged.
280
+ New code introduced by the feature MUST comply with every principle.
258
281
  - Compliance reviews MUST occur at the start of each new feature branch and before
259
282
  merging to `main`.
260
283
 
261
- **Version**: 2.0.3 | **Ratified**: 2026-03-25 | **Last Amended**: 2026-04-10
284
+ **Version**: 2.1.0 | **Ratified**: 2026-03-25 | **Last Amended**: 2026-10-22
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.1](https://github.com/bancolombia/scaffold-clean-architecture-py/compare/v0.2.0...v0.2.1) (2026-10-23)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **refactor:** simplify scaffolder internals and improve extensibility ([8cb0a96](https://github.com/bancolombia/scaffold-clean-architecture-py/commit/8cb0a967d8e00dc5f995e8178d537a3fe5bb7865))
9
+
3
10
  ## [0.2.0](https://github.com/bancolombia/scaffold-clean-architecture-py/compare/v0.1.4...v0.2.0) (2026-10-19)
4
11
 
5
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: scaffold-ca-python
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Scaffolder to generate Clean Architecture apps
5
5
  Project-URL: Homepage, https://github.com/bancolombia/scaffold-clean-architecture-py
6
6
  Project-URL: Repository, https://github.com/bancolombia/scaffold-clean-architecture-py
@@ -75,7 +75,13 @@ line-length = 120
75
75
  target-version = "py313"
76
76
 
77
77
  [tool.ruff.lint]
78
- select = ["E", "F", "I", "UP", "ANN"]
78
+ select = ["E", "F", "I", "UP", "ANN", "B", "SIM", "C90"]
79
+
80
+ [tool.ruff.lint.mccabe]
81
+ max-complexity = 10
82
+
83
+ # Temporary: removed by the end of feature 022.
84
+ [tool.ruff.lint.per-file-ignores]
79
85
 
80
86
  [tool.mypy]
81
87
  strict = true
@@ -0,0 +1,35 @@
1
+ # Specification Quality Checklist: SOLID refactor and comment cleanup
2
+
3
+ **Purpose**: Validate specification completeness and quality before proceeding to planning
4
+ **Created**: 2026-10-22
5
+ **Feature**: [spec.md](../spec.md)
6
+
7
+ ## Content Quality
8
+
9
+ - [x] No implementation details (languages, frameworks, APIs)
10
+ - [x] Focused on user value and business needs
11
+ - [x] Written for non-technical stakeholders
12
+ - [x] All mandatory sections completed
13
+
14
+ ## Requirement Completeness
15
+
16
+ - [x] No [NEEDS CLARIFICATION] markers remain
17
+ - [x] Requirements are testable and unambiguous
18
+ - [x] Success criteria are measurable
19
+ - [x] Success criteria are technology-agnostic (no implementation details)
20
+ - [x] All acceptance scenarios are defined
21
+ - [x] Edge cases are identified
22
+ - [x] Scope is clearly bounded
23
+ - [x] Dependencies and assumptions identified
24
+
25
+ ## Feature Readiness
26
+
27
+ - [x] All functional requirements have clear acceptance criteria
28
+ - [x] User scenarios cover primary flows
29
+ - [x] Feature meets measurable outcomes defined in Success Criteria
30
+ - [x] No implementation details leak into specification
31
+
32
+ ## Notes
33
+
34
+ - This feature is an internal refactor, so its "users" are the maintainers. The spec deliberately names quality tools (linter, cyclomatic complexity, Google-style docstrings) because they are the goal of the feature itself, not implementation details. They are accepted as an exception to "technology-agnostic".
35
+ - Concrete module names (`commands/`, `gep`, `gpipe`) are used only to bound the scope.
@@ -0,0 +1,49 @@
1
+ # Contract: observable CLI behavior
2
+
3
+ This refactor does **not** change the public interface. The contract is what the suite already verifies, plus the three explicit exceptions listed at the end.
4
+
5
+ ## Invariants
6
+
7
+ | Aspect | Contract | Verified by |
8
+ |---|---|---|
9
+ | Commands and aliases | `ca/clean-architecture`, `gm`, `guc`, `gda`, `gep`, `gh`, `gpipe`, `vs`, `dm`, `up`, with the same long names | `tests/commands/test_cli.py` |
10
+ | Flags and defaults | Same names, defaults, help panels and epilogs | `--help` snapshot in `test_cli.py` and per-command tests |
11
+ | Generated files | Byte-for-byte identical, including the files that now come from new templates (FR-004) | `tests/commands/test_dry_run_checksum.py`, `tests/templates/` |
12
+ | `--dry-run` | Same list of paths, no writes | `tests/factory/test_dry_run_parity.py` and per-command tests |
13
+ | Error messages | Same text and same `Hint:` (when present) | per-command tests (`strip_ansi`), `tests/commands/test_behavior_contract.py` |
14
+ | Exit codes | `0` success or help, `1` user error, `2` `uv` failure in `up` | per-command tests |
15
+ | `pyproject.toml` | Same injected dependencies, groups and `[project.scripts]` | `tests/core/test_pyproject_writer.py` and gep/gda tests |
16
+
17
+ ## Allowed changes (exhaustive)
18
+
19
+ ### C-1: unified project context (FR-010)
20
+
21
+ - **Before**: `gep` and `gep --add-tool` used `to_snake_case([project].name)`, with `"project"` as the default.
22
+ - **After**: every command uses `[tool.scaffold-ca-python].name`, falling back to the root directory name.
23
+ - **Impact**: it only changes for projects where `[project].name` was edited by hand and no longer matches the tool section.
24
+
25
+ ### C-2: `gpipe` conflict message (FR-016)
26
+
27
+ - **Before**:
28
+ ```
29
+ Error: '<display>' already exists at '<path>'. Use --force to overwrite.
30
+ Hint: Remove the existing file first or choose a different provider.
31
+ ```
32
+ - **After**:
33
+ ```
34
+ Error: '<display>' already exists at '<path>'.
35
+ Hint: Remove the existing file first or choose a different provider.
36
+ ```
37
+
38
+ ### C-3: TOML sections visible in the `gep` output (FR-021)
39
+
40
+ - **Before**: Rich interprets `[project.scripts]` as markup and drops it:
41
+ ```
42
+ Would update : my_app = "my_app.server:start_server"
43
+ ✓ Updated : my_app = "my_app.server:start_server"
44
+ ```
45
+ - **After**: `escape()` is applied, as is already done for `[project.dependencies]`:
46
+ ```
47
+ Would update [project.scripts]: my_app = "my_app.server:start_server"
48
+ ✓ Updated [project.scripts]: my_app = "my_app.server:start_server"
49
+ ```
@@ -0,0 +1,46 @@
1
+ # Contract: adding a new type without touching `commands/`
2
+
3
+ An internal contract for maintainers. `tests/factory/test_extensibility.py` verifies it.
4
+
5
+ ## Entry point
6
+
7
+ 1. Create `factory/entry_points/ep_<type>.py`:
8
+
9
+ ```python
10
+ class EntryPointFoo(EntryPointFactory):
11
+ subdir: ClassVar[str] = "foo"
12
+ supported_flags: ClassVar[frozenset[EntryPointFlag]] = frozenset({EntryPointFlag.ENABLE_KAFKA})
13
+ conflicts: ClassVar[tuple[EntryPointConflict, ...]] = ()
14
+
15
+ def build(self, builder: ModuleBuilder) -> None: ...
16
+ ```
17
+
18
+ 2. Register the factory with one line in `factory/entry_points/__init__.py`:
19
+
20
+ ```python
21
+ ENTRY_POINT_FACTORIES["foo"] = EntryPointFoo
22
+ ```
23
+
24
+ 3. Add its templates under `templates/entry_point/foo/` and their test under `tests/templates/`, as Constitution II requires.
25
+
26
+ With that, `gep --type foo` does the following with no further changes:
27
+
28
+ - validates flags with messages derived from the registered types (research R-02);
29
+ - applies the `conflicts` guards and the duplicate guard on `subdir`;
30
+ - shows `result_notes()`, which by default is the `main.py` replacement notice;
31
+ - registers the script if the factory called `builder.set_project_script(...)`.
32
+
33
+ ## Driven adapter
34
+
35
+ - Inherit from `DrivenAdapterFactory`.
36
+ - Declare `fixed_name`, or `None` when `--name` provides the name.
37
+ - Register it in `factory/driven_adapters/__init__.py`.
38
+
39
+ ## Pipeline
40
+
41
+ - Add a `PipelineFactory(output_path=…, template=…, display_name=…)` instance to `PIPELINE_PROVIDERS` in `factory/pipelines/__init__.py`.
42
+
43
+ ## Guarantees
44
+
45
+ - An unknown `--type` produces `Unknown type '<x>'. Allowed: <registry keys in order>.`. An unknown `--provider` produces `Unknown provider '<x>'. Allowed: <registry keys in order>.`.
46
+ - No module in `commands/` contains type literals (`"restapi"`, `"mcp"`, `"github"`…). The exception is `add_mcp_tool.py`, which is MCP-specific by definition: it validates `--type mcp`.
@@ -0,0 +1,112 @@
1
+ # Data Model: SOLID refactor and comment cleanup
2
+
3
+ Internal entities that the refactor introduces or modifies. There is no new persistence: the only persisted state is still the generated project and its `pyproject.toml`.
4
+
5
+ ## ProjectContext (modified: how it is loaded)
6
+
7
+ | Field | Type | Source |
8
+ |---|---|---|
9
+ | `name` | `str` (validated by `NAME_RE`) | `[tool.scaffold-ca-python].name`; if missing, the root directory name |
10
+ | `python_package` | `str` (computed) | `to_snake_case(name)` |
11
+ | `python_package_script` | `str` (computed) | `to_kebab_case(name)` |
12
+
13
+ - **Single loader**: `core.project_detector.load_project_context(root: Path) -> ProjectContext`.
14
+ - **FR-011 rule**: `python_package` stays in snake_case. The code `gep` generates does not change for projects created with the tool, because in those `[project].name == [tool.scaffold-ca-python].name`.
15
+ - **Behavior change (FR-010)**: `gep` and `--add-tool` stop reading `[project].name`.
16
+
17
+ ## EntryPointOptions (new, `models/options.py`)
18
+
19
+ Dataclass with `frozen=True, slots=True`. Groups the 12 parameters of `gep`.
20
+
21
+ | Field | Type | Default |
22
+ |---|---|---|
23
+ | `type_` | `str` | — |
24
+ | `swagger` | `str \| None` | `None` |
25
+ | `enable_kafka` | `bool` | `False` |
26
+ | `enable_mcp_client` | `bool` | `False` |
27
+ | `with_resources` | `bool` | `False` |
28
+ | `with_prompts` | `bool` | `False` |
29
+ | `add_tool` | `bool` | `False` |
30
+ | `name` | `str \| None` | `None` |
31
+ | `params` | `tuple[str, ...]` | `()` |
32
+ | `returns` | `str` | `"str"` |
33
+ | `description` | `str \| None` | `None` |
34
+ | `dry_run` | `bool` | `False` |
35
+
36
+ Methods:
37
+ - `creation_flags() -> list[str]`: returns the active creation flags, in the current order (`--swagger`, `--enable-kafka`, `--enable-mcp-client`, `--with-resources`, `--with-prompts`). The `--add-tool` guard uses it.
38
+ - `apply_to(builder, routes) -> None`: transfers the build parameters to the builder (see research R-05).
39
+
40
+ ## EntryPointFlag (new, enum in `factory/entry_points/base.py`)
41
+
42
+ | Member | Label in messages | Verb | Active when |
43
+ |---|---|---|---|
44
+ | `SWAGGER` | `--swagger` | `is` | `options.swagger` is truthy |
45
+ | `ENABLE_MCP_CLIENT` | `--enable-mcp-client` | `is` | `options.enable_mcp_client` |
46
+ | `MCP_PRIMITIVES` | `--with-resources and --with-prompts` | `are` | `with_resources or with_prompts` |
47
+ | `ENABLE_KAFKA` | `--enable-kafka` | `is` | `options.enable_kafka` |
48
+
49
+ The command evaluates the flags in table order. Research R-02 describes how the message is derived.
50
+
51
+ ## EntryPointConflict (new)
52
+
53
+ A named tuple `(label: str, subdir: str)`: a directory under `infrastructure/entry_points/` whose existence prevents creating the type.
54
+
55
+ ## EntryPointFactory (new, ABC implementing `ModuleFactory`)
56
+
57
+ | Member | Type | Default |
58
+ |---|---|---|
59
+ | `subdir` | `ClassVar[str]` | required |
60
+ | `supported_flags` | `ClassVar[frozenset[EntryPointFlag]]` | `frozenset()` |
61
+ | `conflicts` | `ClassVar[tuple[EntryPointConflict, ...]]` | `()` |
62
+ | `build(builder)` | abstract | — |
63
+ | `result_notes(project_root, pkg, type_key, *, dry_run)` | `list[str]` | `main.py` replacement notice |
64
+
65
+ Declared values, equivalent to the current logic:
66
+
67
+ | Type | subdir | supported_flags | conflicts | result_notes |
68
+ |---|---|---|---|---|
69
+ | `restapi` | `api/v1` | SWAGGER, ENABLE_MCP_CLIENT, ENABLE_KAFKA | `mcp_server`, `agent` | override: `main.py` deletion + `[project.scripts]` (escaped, C-3) |
70
+ | `mcp` | `mcp_server` | MCP_PRIMITIVES, ENABLE_KAFKA | `restapi`→`api` | default |
71
+ | `agent` | `agent` | ENABLE_MCP_CLIENT, ENABLE_KAFKA | `restapi`→`api` | default |
72
+ | `generic` | `generic` | ENABLE_MCP_CLIENT, ENABLE_KAFKA | — | default |
73
+
74
+ Note: today `--enable-kafka` and `--enable-mcp-client` are accepted without error by types that don't use them. Declaring them as supported keeps that behavior.
75
+
76
+ ## DrivenAdapterFactory (new, ABC)
77
+
78
+ | Member | Type | Meaning |
79
+ |---|---|---|
80
+ | `fixed_name` | `ClassVar[str \| None]` | when set, `--name` is ignored (`rest_consumer`, `secrets`) |
81
+ | `module_name(name: str \| None) -> str \| None` | method | returns `fixed_name or name`. When the result is `None`, the command fails with `"--name is required when --type is {type}."` |
82
+
83
+ The subdirectory is `to_snake_case(module_name)`.
84
+
85
+ ## PipelineFactory (new, `factory/pipelines/`)
86
+
87
+ | Field | Type | github | azure |
88
+ |---|---|---|---|
89
+ | `output_path` | relative `PurePosixPath` | `.github/workflows/ci.yml` | `azure-pipelines.yml` |
90
+ | `template` | `str` | `pipeline/github/ci.yml.jinja2` | `pipeline/azure/azure_pipelines.yml.jinja2` |
91
+ | `display_name` | `str` | `ci.yml` | `azure-pipelines.yml` |
92
+
93
+ `PIPELINE_PROVIDERS: dict[str, PipelineFactory]` keeps the `github, azure` order for the `Allowed: …` message. `build()` renders with the `ProjectContext` (a Pydantic model), so it complies with Constitution II.
94
+
95
+ ## ModuleBuilder (modified)
96
+
97
+ | Change | Detail |
98
+ |---|---|
99
+ | + `set_project_script(entry_fn: str = "start_server")` | replaces `add_param("scripts_entry"/"scripts_entry_fn")` |
100
+ | + `pending_project_script: str \| None` (property) | what tests and dry-run output read |
101
+ | `persist()` | applies dependencies, groups and the script; no longer reads magic keys from `_params` |
102
+ | `add_param`/`get_param` | kept for build flags (R-05) |
103
+
104
+ ## ModuleTarget (new, `core/module_locator.py`)
105
+
106
+ `find_module_targets(project_root, pkg, snake) -> list[tuple[Path, Path | None]]`. A single implementation, shared by `delete_module` (preview) and `DeleteModuleFactory` (deletion).
107
+
108
+ ## Internal utilities (stateless)
109
+
110
+ - `commands/_shared.py`: see research R-07.
111
+ - `commands/_entry_point_rules.py`: `check_flags()`, `check_conflicts()` (research R-02/R-03).
112
+ - New templates: `project/package_init.py.jinja2`, `project/empty.jinja2` (research R-13).
@@ -0,0 +1,189 @@
1
+ # Implementation Plan: SOLID refactor and comment cleanup of the scaffolder
2
+
3
+ **Branch**: `feature/022-solid-code-cleanup` | **Date**: 2026-10-22 | **Spec**: [spec.md](spec.md)
4
+
5
+ **Input**: Feature specification from `/specs/022-solid-code-cleanup/spec.md`
6
+
7
+ ## Summary
8
+
9
+ Internal refactor of `src/scaffold_ca_python/` with no change to the CLI's observable behavior, apart from the allowed changes C-1, C-2 and C-3. It has five parts.
10
+
11
+ 1. **Shared command utilities.** A common layer for the commands (`commands/_shared.py`) centralizes:
12
+ - errors with a resolution hint;
13
+ - project-root lookup;
14
+ - duplicate guards;
15
+ - the dry-run tree;
16
+ - the `--dry-run` option.
17
+ 2. **Single context loader.** `load_project_context` moves to `core/project_detector.py` and fixes the `gep` inconsistency.
18
+ 3. **Type knowledge lives in the factories.** Entry-point, driven-adapter and pipeline factories declare what is specific to their type through base classes with `ClassVar`s. The registries move into their `factory/` packages, so a new type does not touch `commands/`.
19
+ 4. **Complexity ≤ 10.** `_add_tool_impl`, `_generate_entry_point_impl`, `FileWriter._commit`, `StructureValidator.validate` and `DeleteModuleFactory.build` are split.
20
+ 5. **Comments, guardrails and output fixes.** Comments and docstrings are cleaned up (Google style, no Spec Kit IDs). Ruff `B`, `SIM` and `C90` are enabled. The `gpipe` hint (FR-016) and the `[project.scripts]` output (FR-021) are fixed.
21
+
22
+ ## Technical Context
23
+
24
+ **Language/Version**: Python 3.13.
25
+
26
+ **Primary Dependencies**: Typer (with `Annotated`), Rich, Jinja2, Pydantic v2, PyYAML. No dependencies are added.
27
+
28
+ **Storage**: local files (the generated project and its `pyproject.toml`).
29
+
30
+ **Testing**: pytest, pytest-cov (≥80% gate), pytest-benchmark and `typer.testing.CliRunner`. Baseline measured on 2026-10-22: **739 passed, 1 skipped, 96.50% coverage**.
31
+
32
+ **Target Platform**: cross-platform CLI (macOS, Linux, Windows) distributed through PyPI.
33
+
34
+ **Project Type**: CLI (single project, `src/` layout).
35
+
36
+ **Performance Goals**: no regression in `tests/commands/test_performance.py`.
37
+
38
+ **Constraints**:
39
+ - Output is byte-for-byte identical in generated files, messages and exit codes. The exceptions are:
40
+ - FR-010 (project context);
41
+ - FR-016 (`gpipe` message);
42
+ - FR-021 (`[project.scripts]` shown literally).
43
+ - Existing Jinja templates are not modified. Only two new ones are added (FR-004, research R-13).
44
+ - `mypy --strict` must pass.
45
+
46
+ **Scale/Scope**: about 4.4k LOC in 40 modules and 50 test files.
47
+
48
+ Violations measured today with `ruff --select B,SIM,C90` and `max-complexity=10`:
49
+ - **`src/`, 10 in total:**
50
+ - 6 × C901: `_add_tool_impl` 26, `_generate_entry_point_impl` 24, `_generate_driven_adapter_impl` 13, `StructureValidator.validate` 13, `FileWriter._commit` 12, `DeleteModuleFactory.build` 12.
51
+ - 2 × B904, 1 × B905 and 1 × SIM108.
52
+ - **`tests/`:** 2 × B017. No C90 violations.
53
+ - **B008:** does not appear, because Typer uses `Annotated`.
54
+
55
+ ## Constitution Check
56
+
57
+ *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* Constitution version: **2.1.0**.
58
+
59
+ | Principle | Assessment | Status |
60
+ |---|---|---|
61
+ | I. Clean Architecture in generated projects | Templates and generated output don't change. `vs` keeps its logic; only the complexity of `validate` is reduced. | ✅ |
62
+ | II. Template-driven generation | `generate_project` and `generate_pipeline` switch to `TemplateRenderer.render()` with packaged templates instead of `render_string(_tmpl())`. Two files of `ca` that don't come from a template today now do, with the same output (FR-004, R-13): the root package `__init__.py` (an f-string) and the empty `src/tests/__init__.py`. They use the new templates `project/package_init.py.jinja2` and `project/empty.jinja2`. Factories still pass template contexts as `dict`, which is pre-existing debt (see Complexity Tracking). No new code introduces `dict` contexts: the `render_into` helper was dropped. | ✅ / ⚠️ pre-existing debt (Governance v2.1.0) |
63
+ | III. Command parity and `--dry-run` | Commands, aliases and flags don't change, and the parity and checksum tests are kept. | ✅ |
64
+ | IV. Python idioms | Compliance improves: consistent `X \| None` typing, extended ruff rules and strict mypy with no new `type: ignore`. | ✅ |
65
+ | V. Test-first (NON-NEGOTIABLE) | Every story starts with red tests, among them the context regression (FR-020), extensibility with a fake factory, the new `gpipe` message, the `[project.scripts]` output (FR-021), `set_project_script` and the new templates. The pure refactor is covered by the existing suite, green before and after each step. | ✅ |
66
+ | VI. Developer Experience | FR-016 fixes an invalid hint (`--force`) and FR-021 makes `[project.scripts]` visible in the output. 38 of the 56 error messages in `commands/` have no `Hint:`. FR-003 keeps them unchanged; this is pre-existing debt. | ⚠️ pre-existing debt (Governance v2.1.0) |
67
+ | VII. Branches | `feature/022-solid-code-cleanup`, with the `feature/` prefix the repo uses. | ✅ |
68
+
69
+ **Result**: the gate passes. Two pre-existing violations are kept under the "Pre-existing violations" governance clause (v2.1.0):
70
+ - VI: missing resolution hints;
71
+ - II: template contexts passed as `dict`.
72
+
73
+ The feature does not introduce or worsen either one. The follow-up spec directories are created in T063 before merge.
74
+
75
+ **Post-design re-check (Phase 1)**: ✅. The design in [data-model.md](data-model.md) and [contracts/](contracts/):
76
+ - only adds base classes, `ClassVar`s and internal utilities;
77
+ - doesn't change existing templates or flags;
78
+ - changes the output only through C-1, C-2 and C-3.
79
+
80
+ The adapted tests only change imports or where a factory is registered (see research R-08).
81
+
82
+ ## Project Structure
83
+
84
+ ### Documentation (this feature)
85
+
86
+ ```text
87
+ specs/022-solid-code-cleanup/
88
+ ├── plan.md # This file
89
+ ├── research.md # Phase 0: design decisions
90
+ ├── data-model.md # Phase 1: internal entities (options, descriptors, context)
91
+ ├── quickstart.md # Phase 1: validation guide
92
+ ├── contracts/
93
+ │ ├── cli-behavior.md # Observable behavior contract (+ allowed changes C-1..C-3)
94
+ │ └── factory-extension.md # Contract for adding new types
95
+ ├── checklists/
96
+ │ └── requirements.md
97
+ └── tasks.md # Phase 2 (/speckit-tasks)
98
+ ```
99
+
100
+ ### Source Code (repository root)
101
+
102
+ ```text
103
+ src/scaffold_ca_python/
104
+ ├── cli.py # no functional changes
105
+ ├── commands/
106
+ │ ├── _shared.py # NEW: fail(), require_project_root(), validate_name_or_exit(),
107
+ │ │ # ensure_absent(), print_dry_run_tree(),
108
+ │ │ # print_pending_dependencies(), dry_run_option(), build_and_persist()
109
+ │ ├── _entry_point_rules.py # NEW: check_flags(), check_conflicts() (research R-02/R-03)
110
+ │ ├── generate_entry_point.py # orchestration only: options → validation → factory → presentation
111
+ │ ├── add_mcp_tool.py # NEW: --add-tool flow extracted from generate_entry_point
112
+ │ ├── generate_driven_adapter.py # no if/elif per type
113
+ │ ├── generate_pipeline.py # uses ModuleBuilder + PIPELINE_PROVIDERS, injectable renderer/writer
114
+ │ ├── generate_project.py # file table + injectable ModuleBuilder
115
+ │ ├── generate_model.py / generate_use_case.py / generate_helper.py / delete_module.py
116
+ │ │ # no single-entry _REGISTRY; use _shared
117
+ │ ├── update_project.py # _run_uv() removes the duplicated try/except
118
+ │ └── validate_structure.py
119
+ ├── core/
120
+ │ ├── project_detector.py # + load_project_context() (single definition)
121
+ │ ├── module_locator.py # NEW: find_module_targets() (shared by dm and its factory)
122
+ │ ├── openapi_routes.py # NEW: parse_routes() (formerly _parse_swagger in gep)
123
+ │ ├── module_builder.py # + set_project_script(); no magic keys in persist()
124
+ │ ├── file_writer.py # _commit split; zip(strict=True)
125
+ │ ├── structure_validator.py # validate split into _classify/_parse/_violations_in
126
+ │ └── mcp_tool_spec.py, pyproject_writer.py, template_renderer.py, name_utils.py # docstring cleanup
127
+ ├── factory/
128
+ │ ├── __init__.py # ModuleFactory (Protocol, unchanged)
129
+ │ ├── entry_points/
130
+ │ │ ├── __init__.py # ENTRY_POINT_FACTORIES (registry)
131
+ │ │ ├── base.py # NEW: EntryPointFactory, EntryPointConflict, EntryPointFlag
132
+ │ │ └── ep_restapi.py, ep_mcp.py, ep_agent.py, ep_generic.py # declare ClassVars
133
+ │ ├── driven_adapters/
134
+ │ │ ├── __init__.py # DRIVEN_ADAPTER_FACTORIES
135
+ │ │ ├── base.py # NEW: DrivenAdapterFactory
136
+ │ │ └── da_*.py
137
+ │ ├── pipelines/ # NEW
138
+ │ │ ├── __init__.py # PIPELINE_PROVIDERS
139
+ │ │ └── pipeline_factory.py # PipelineFactory (github, azure as descriptor instances)
140
+ │ └── simple/ # no structural changes; cleanup
141
+ ├── models/
142
+ │ ├── context.py # docstring cleanup
143
+ │ └── options.py # NEW: EntryPointOptions (frozen dataclass)
144
+ └── templates/project/
145
+ ├── package_init.py.jinja2 # NEW (R-13)
146
+ └── empty.jinja2 # NEW (R-13)
147
+
148
+ tests/ # same layout; new tests:
149
+ ├── commands/test_shared.py
150
+ ├── commands/test_behavior_contract.py # US1 safety net + C-3
151
+ ├── core/test_project_context.py # FR-010/FR-020 regression
152
+ ├── core/test_module_locator.py
153
+ ├── core/test_openapi_routes.py
154
+ ├── models/test_options.py
155
+ ├── test_source_hygiene.py # FR-015
156
+ └── factory/test_extensibility.py # extended: fake factory with a full descriptor
157
+ ```
158
+
159
+ **Structure Decision**: The single project with `src/` layout stays.
160
+ - **Registries:** type registries move from `commands/` to the `__init__.py` of each `factory/` package, so adding a type does not modify `commands/` (SC-005).
161
+ - **Shared logic:** command-shared logic lives in `commands/_shared.py` and not in `core/`, because it depends on Rich and Typer (it is presentation). `core/` stays independent of the CLI.
162
+ - **Template helpers:** the local `tpl()` helpers in the entry-point factories stay as they are. A shared `render_into()` helper was considered and dropped, because it would be new code that accepts `dict` contexts (Constitution II, Governance v2.1.0: new code must comply).
163
+
164
+ ## Suggested implementation order
165
+
166
+ Each step leaves the suite green and can be its own commit:
167
+
168
+ 1. **Guardrails first:** enable `B`, `SIM` and `C90` in `pyproject.toml`, with a temporary C901 `per-file-ignores` only for the affected modules. It is removed at the end. Fix B904, B905, SIM108 and B017.
169
+ 2. **Shared utilities:** create and test `commands/_shared.py`.
170
+ 3. **Story 1 (P1), safety net:** behavior-contract tests, green against the current code.
171
+ 4. **Story 2 (P1):** `EntryPointFactory` and `DrivenAdapterFactory`, registries in `factory/`, `set_project_script()` and `PipelineFactory`.
172
+ 5. **Story 3 (P2), TDD:** single `load_project_context` and its regression test.
173
+ 6. **Story 4 (P2):**
174
+ - split gep (`EntryPointOptions`, `add_mcp_tool.py`, `openapi_routes.py`), `FileWriter`, `StructureValidator`, and `delete_module` (with `module_locator`);
175
+ - `generate_project` switches to the file table, the new templates and an injectable builder.
176
+ 7. **Stories 5 and 6 (P3):**
177
+ - comment and docstring cleanup and dead code;
178
+ - the `gpipe` message (C-2) and the `[project.scripts]` output (C-3);
179
+ - remove the temporary `per-file-ignores`.
180
+ 8. **Final verification:** full suite, checksum, parity, generated-tree comparison ([quickstart.md](quickstart.md)), and the follow-up spec directories 023/024.
181
+
182
+ ## Complexity Tracking
183
+
184
+ Pre-existing violations kept under the Constitution v2.1.0 "Pre-existing violations" governance clause:
185
+
186
+ | Violation | Why Needed | Simpler Alternative Rejected Because |
187
+ |---|---|---|
188
+ | **VI**: 38 of 56 error messages in `commands/` have no `Hint:`. Examples: the `gep` flag validation, `Unknown type` and `--name is required…`. They are kept unchanged. | FR-003 requires the output to stay unchanged during the refactor. Adding hints would mix a UX change into the refactor. | Adding them here would invalidate the US1 safety net (T008–T010) and multiply the allowed changes. It will be resolved in follow-up feature **023-error-hints**. |
189
+ | **II**: factories pass `dict` contexts to templates. The dicts come from the already validated `ModuleContext.model_dump()`, plus `bool` flags. | Keep the output identical and the refactor scope bounded. | Typing every context with Pydantic touches all 11 factories and their templates. It will be resolved in follow-up feature **024-typed-template-contexts**. No new code in this feature adds `dict` contexts. |
@@ -0,0 +1,93 @@
1
+ # Quickstart: validating the 022 refactor
2
+
3
+ End-to-end validation guide. Design details are in [data-model.md](data-model.md) and [contracts/](contracts/).
4
+
5
+ ## Prerequisites
6
+
7
+ ```bash
8
+ export SSL_CERT_FILE=/etc/ssl/cert.pem # only if uv fails with a TLS error
9
+ uv sync
10
+ git switch feature/022-solid-code-cleanup
11
+ REPO=~/projects/ingsw/scaffold-clean-architecture-py
12
+ ```
13
+
14
+ ## 1. Reference tree (before the refactor)
15
+
16
+ Run once from `main`, before starting:
17
+
18
+ ```bash
19
+ gen_tree() { # $1 = output dir, $2 = sha file
20
+ mkdir -p "$1" && cd "$1"
21
+ uv run --project "$REPO" scaffold-ca-python ca --name demo-app
22
+ cd demo-app
23
+ for t in "gm --name order" "guc --name create_order" "gh --name clock" \
24
+ "gda --type rest-consumer" "gda --type generic --name cache" \
25
+ "gep --type mcp --with-resources" "gep --type mcp --add-tool --name ping --returns str" \
26
+ "gpipe --provider github"; do
27
+ uv run --project "$REPO" scaffold-ca-python $t
28
+ done
29
+ sed -i '' '/^created_at = /d' pyproject.toml # timestamp differs on every run
30
+ find . -type f -print0 | sort -z | xargs -0 shasum > "$2"
31
+ }
32
+ gen_tree /tmp/ref022 /tmp/ref022.sha
33
+ ```
34
+
35
+ Repeat for restapi in another directory, because restapi is incompatible with mcp. Use `ca --name demo-api`, then `gep --type restapi` and `gda --type secrets`, and save the hashes to `/tmp/ref022-restapi.sha`.
36
+
37
+ After the refactor, run the same thing in `/tmp/new022` and `/tmp/new022-restapi`, then compare:
38
+
39
+ ```bash
40
+ diff /tmp/ref022.sha /tmp/new022.sha
41
+ diff /tmp/ref022-restapi.sha /tmp/new022-restapi.sha
42
+ ```
43
+
44
+ **Expected**: no differences. This covers User Story 1 and SC-001.
45
+
46
+ ## 2. Suite and guardrails
47
+
48
+ ```bash
49
+ uv run ruff check src/ tests/
50
+ uv run ruff format --check src/ tests/
51
+ uv run mypy src/
52
+ uv run pytest
53
+ ```
54
+
55
+ **Expected**:
56
+ - Everything is green, with coverage ≥80% (baseline: 96.50%).
57
+ - The 739 existing tests pass, plus the new ones. Only the tests listed in research R-08 and those of C-1, C-2 and C-3 are adapted.
58
+
59
+ This covers SC-001, SC-002 and SC-007.
60
+
61
+ ## 3. Measurable criteria
62
+
63
+ ```bash
64
+ # SC-003: zero Spec Kit IDs in src/
65
+ grep -rnE '\b(T0[0-9]{2}|FR-[0-9]{3}|US-?[0-9]|R-[0-9]{2})\b|Phase [0-9]' src/ | grep '\.py:' | wc -l # → 0
66
+
67
+ # SC-004: single definitions
68
+ grep -rn "def load_project_context\|def _load_project_context" src/ | wc -l # → 1
69
+ grep -rn "No scaffold-ca-python project found" src/ | wc -l # → 1
70
+
71
+ # SC-005: no type literals in commands/ (except add_mcp_tool.py)
72
+ grep -nE '"(restapi|agent|generic|rest-consumer|secrets|github|azure)"' src/scaffold_ca_python/commands/*.py # → empty
73
+
74
+ # No temporary C901 ignores left
75
+ grep -n "C901" pyproject.toml # → empty
76
+
77
+ # FR-004: only the two new templates were added; nothing existing was modified
78
+ git diff --stat main -- src/scaffold_ca_python/templates
79
+ ```
80
+
81
+ ## 4. Allowed behavior changes
82
+
83
+ - **C-1 (FR-010)**: run `uv run pytest tests/core/test_project_context.py`. It uses a project whose `[project].name` differs from `[tool.scaffold-ca-python].name`; `gep` and `gm` must resolve the same package.
84
+ - **C-2 (FR-016)**: run `scaffold-ca-python gpipe --provider github` twice. The second error does not mention `--force`.
85
+ - **C-3 (FR-021)**: `scaffold-ca-python gep --type restapi --dry-run` shows `Would update [project.scripts]: <pkg> = "<pkg>.server:start_server"`.
86
+
87
+ ## 5. Extensibility
88
+
89
+ ```bash
90
+ uv run pytest tests/factory/test_extensibility.py -v
91
+ ```
92
+
93
+ **Expected**: the fake factory registered in `ENTRY_POINT_FACTORIES` generates its files, validates flags and shows its notes, and `commands/` was not modified.