claude-code-generator 0.5.2__tar.gz → 0.5.3__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 (179) hide show
  1. {claude_code_generator-0.5.2/src/claude_code_generator.egg-info → claude_code_generator-0.5.3}/PKG-INFO +15 -4
  2. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/README.md +14 -3
  3. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/pyproject.toml +1 -1
  4. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3/src/claude_code_generator.egg-info}/PKG-INFO +15 -4
  5. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/__init__.py +1 -1
  6. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/_dispatch.py +36 -50
  7. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_dispatch_graph_report.py +53 -51
  8. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/LICENSE +0 -0
  9. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/setup.cfg +0 -0
  10. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/SOURCES.txt +0 -0
  11. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
  12. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
  13. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/requires.txt +0 -0
  14. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/top_level.txt +0 -0
  15. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/agents.py +0 -0
  16. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/cli.py +0 -0
  17. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/__init__.py +0 -0
  18. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/_bench_io.py +0 -0
  19. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/_crash_recovery.py +0 -0
  20. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/_detect.py +0 -0
  21. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/_resume.py +0 -0
  22. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/_validators.py +0 -0
  23. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/bench.py +0 -0
  24. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/bench_compare.py +0 -0
  25. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/bench_export.py +0 -0
  26. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/generate.py +0 -0
  27. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/init.py +0 -0
  28. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/optimize.py +0 -0
  29. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/review.py +0 -0
  30. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/commands/status.py +0 -0
  31. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/effort.py +0 -0
  32. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/env.py +0 -0
  33. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/gh/__init__.py +0 -0
  34. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/gh/core.py +0 -0
  35. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/gh/issues.py +0 -0
  36. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/gh/labels.py +0 -0
  37. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/gh/milestones.py +0 -0
  38. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/git_ops.py +0 -0
  39. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/logging_setup.py +0 -0
  40. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/memory.py +0 -0
  41. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/__init__.py +0 -0
  42. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_client_lifecycle.py +0 -0
  43. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_comments.py +0 -0
  44. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_memory_writers.py +0 -0
  45. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_phase5_precommit.py +0 -0
  46. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/cycle_loop.py +0 -0
  47. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/cycle_prompts.py +0 -0
  48. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/ollama_budget.py +0 -0
  49. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase0_complexity.py +0 -0
  50. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase1_plan.py +0 -0
  51. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase2_review.py +0 -0
  52. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase3_4_implement.py +0 -0
  53. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase5_closure.py +0 -0
  54. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase6_test.py +0 -0
  55. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase7_commit.py +0 -0
  56. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/preflight.py +0 -0
  57. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/__init__.py +0 -0
  58. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/hashes.py +0 -0
  59. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-cycle-specializer.md +0 -0
  60. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-optimize-requirements.md +0 -0
  61. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-0-complexity.md +0 -0
  62. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-1-planning.md +0 -0
  63. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-2-batch-review.md +0 -0
  64. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-3-implementation.md +0 -0
  65. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-5-final-review.md +0 -0
  66. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
  67. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-7-commit.md +0 -0
  68. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-review.md +0 -0
  69. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/repo_info.py +0 -0
  70. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/requirements_structure.py +0 -0
  71. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/__init__.py +0 -0
  72. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/_telemetry.py +0 -0
  73. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/batch.py +0 -0
  74. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/fake_runner.py +0 -0
  75. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/mcp.py +0 -0
  76. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/message_parsing.py +0 -0
  77. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/options.py +0 -0
  78. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/protocol.py +0 -0
  79. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/rate_limit.py +0 -0
  80. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/retry.py +0 -0
  81. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/sdk_runner.py +0 -0
  82. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/soft_reset.py +0 -0
  83. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/state_guard.py +0 -0
  84. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/subprocess_runner.py +0 -0
  85. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/types.py +0 -0
  86. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/runner/utils.py +0 -0
  87. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/state.py +0 -0
  88. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/state_retention.py +0 -0
  89. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/__init__.py +0 -0
  90. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/angular.md +0 -0
  91. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/base.md +0 -0
  92. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/fastapi.md +0 -0
  93. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/finance.md +0 -0
  94. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/fullstack.md +0 -0
  95. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/nestjs.md +0 -0
  96. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/src/code_generator/templates/python-cli.md +0 -0
  97. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_agents.py +0 -0
  98. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_bench.py +0 -0
  99. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_bench_compare.py +0 -0
  100. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_bench_export.py +0 -0
  101. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_bench_fixture.py +0 -0
  102. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_bench_regression.py +0 -0
  103. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_changelog.py +0 -0
  104. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_claude_md.py +0 -0
  105. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_client_lifecycle.py +0 -0
  106. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_comments.py +0 -0
  107. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_commit_message.py +0 -0
  108. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_crash_recovery.py +0 -0
  109. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_cycle_loop.py +0 -0
  110. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_cycle_loop_multicycle.py +0 -0
  111. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_cycle_ollama_model.py +0 -0
  112. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_cycle_prompts.py +0 -0
  113. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_delta_planning.py +0 -0
  114. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_dependencies.py +0 -0
  115. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_detect.py +0 -0
  116. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_docs_no_default_max_turns.py +0 -0
  117. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_docs_ollama_model_guide.py +0 -0
  118. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_docs_ollama_pro.py +0 -0
  119. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_effective_model_routing.py +0 -0
  120. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_effort.py +0 -0
  121. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_env.py +0 -0
  122. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_generate.py +0 -0
  123. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_generate_ollama.py +0 -0
  124. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_generate_resume.py +0 -0
  125. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_gh.py +0 -0
  126. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_gh_labels.py +0 -0
  127. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_gh_milestones.py +0 -0
  128. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_gh_repo_threading.py +0 -0
  129. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_gh_submodules.py +0 -0
  130. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_git_ops.py +0 -0
  131. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_init.py +0 -0
  132. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_logging_setup.py +0 -0
  133. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_max_turns_cli_flag.py +0 -0
  134. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_mcp.py +0 -0
  135. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_memory.py +0 -0
  136. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_memory_writers.py +0 -0
  137. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_message_parsing.py +0 -0
  138. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_no_max_turns_in_call_sites.py +0 -0
  139. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_no_max_turns_literal.py +0 -0
  140. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_non_goals_grep_guard.py +0 -0
  141. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_ollama_budget.py +0 -0
  142. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_ollama_rate_limit.py +0 -0
  143. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_optimize.py +0 -0
  144. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_options.py +0 -0
  145. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase0.py +0 -0
  146. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase1.py +0 -0
  147. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase2.py +0 -0
  148. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase3_4.py +0 -0
  149. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase5.py +0 -0
  150. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase5_precommit.py +0 -0
  151. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase6.py +0 -0
  152. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase7.py +0 -0
  153. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase_mcp_regression.py +0 -0
  154. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_phase_token_logging.py +0 -0
  155. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_preflight.py +0 -0
  156. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_preflight_ollama.py +0 -0
  157. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_prompt_drift.py +0 -0
  158. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_prompt_prefix_snapshots.py +0 -0
  159. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_prompt_prefix_stability.py +0 -0
  160. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_prompts.py +0 -0
  161. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_rate_limit.py +0 -0
  162. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_repo_info.py +0 -0
  163. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_requirements_structure.py +0 -0
  164. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_retry.py +0 -0
  165. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_review.py +0 -0
  166. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_runner_protocol.py +0 -0
  167. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_runner_protocol_annotations.py +0 -0
  168. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_runner_types.py +0 -0
  169. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_runner_utils.py +0 -0
  170. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_sdk_runner.py +0 -0
  171. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_sdk_runner_shared.py +0 -0
  172. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_session_mode.py +0 -0
  173. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_state.py +0 -0
  174. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_state_guard.py +0 -0
  175. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_state_retention.py +0 -0
  176. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_status.py +0 -0
  177. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_subprocess_runner.py +0 -0
  178. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_telemetry.py +0 -0
  179. {claude_code_generator-0.5.2 → claude_code_generator-0.5.3}/tests/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.5.2
3
+ Version: 0.5.3
4
4
  Summary: Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file.
5
5
  Author: Silvio Baratto
6
6
  License: MIT
@@ -55,17 +55,28 @@ cd code-generator && pip install -e ".[dev]"
55
55
 
56
56
  ### Optional: codebase graph (graphify)
57
57
 
58
- Phases 0, 1, and 2 inject a knowledge-graph report from [graphify](https://github.com/safishamsi/graphify) for richer code orientation. When the binary is missing, the orchestrator falls back to a sentinel string and continues.
58
+ Phases 0, 1, and 2 inject a knowledge-graph report from [graphify](https://github.com/safishamsi/graphify) for richer code orientation. When the graph is missing, the orchestrator falls back to a sentinel string and continues — nothing breaks.
59
+
60
+ **Install the CLI** (required to use graphify at all):
59
61
 
60
62
  ```bash
61
63
  pipx install graphifyy # CLI binary is `graphify`
62
64
  ```
63
65
 
66
+ **Seed the graph (one-time, per project)**: graphify's full LLM-driven build runs through the `/graphify` slash-command inside an AI assistant — *not* through the shell binary. From inside Claude Code (or any other graphify-supported assistant) run:
67
+
68
+ ```
69
+ /graphify .
70
+ ```
71
+
72
+ This produces `graphify-out/graph.json` and `graphify-out/GRAPH_REPORT.md`.
73
+
74
+ **Subsequent code-generator runs** will automatically refresh the graph with `graphify update .` (AST-only, no LLM cost). Doc / paper / image changes still need a manual `/graphify .` re-run inside your assistant.
75
+
64
76
  Add to your project's `.gitignore`:
65
77
 
66
78
  ```
67
- graphify-out/manifest.json
68
- graphify-out/cost.json
79
+ graphify-out/
69
80
  ```
70
81
 
71
82
  ## Authentication
@@ -17,17 +17,28 @@ cd code-generator && pip install -e ".[dev]"
17
17
 
18
18
  ### Optional: codebase graph (graphify)
19
19
 
20
- Phases 0, 1, and 2 inject a knowledge-graph report from [graphify](https://github.com/safishamsi/graphify) for richer code orientation. When the binary is missing, the orchestrator falls back to a sentinel string and continues.
20
+ Phases 0, 1, and 2 inject a knowledge-graph report from [graphify](https://github.com/safishamsi/graphify) for richer code orientation. When the graph is missing, the orchestrator falls back to a sentinel string and continues — nothing breaks.
21
+
22
+ **Install the CLI** (required to use graphify at all):
21
23
 
22
24
  ```bash
23
25
  pipx install graphifyy # CLI binary is `graphify`
24
26
  ```
25
27
 
28
+ **Seed the graph (one-time, per project)**: graphify's full LLM-driven build runs through the `/graphify` slash-command inside an AI assistant — *not* through the shell binary. From inside Claude Code (or any other graphify-supported assistant) run:
29
+
30
+ ```
31
+ /graphify .
32
+ ```
33
+
34
+ This produces `graphify-out/graph.json` and `graphify-out/GRAPH_REPORT.md`.
35
+
36
+ **Subsequent code-generator runs** will automatically refresh the graph with `graphify update .` (AST-only, no LLM cost). Doc / paper / image changes still need a manual `/graphify .` re-run inside your assistant.
37
+
26
38
  Add to your project's `.gitignore`:
27
39
 
28
40
  ```
29
- graphify-out/manifest.json
30
- graphify-out/cost.json
41
+ graphify-out/
31
42
  ```
32
43
 
33
44
  ## Authentication
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "claude-code-generator"
7
- version = "0.5.2"
7
+ version = "0.5.3"
8
8
  description = "Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file."
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.5.2
3
+ Version: 0.5.3
4
4
  Summary: Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file.
5
5
  Author: Silvio Baratto
6
6
  License: MIT
@@ -55,17 +55,28 @@ cd code-generator && pip install -e ".[dev]"
55
55
 
56
56
  ### Optional: codebase graph (graphify)
57
57
 
58
- Phases 0, 1, and 2 inject a knowledge-graph report from [graphify](https://github.com/safishamsi/graphify) for richer code orientation. When the binary is missing, the orchestrator falls back to a sentinel string and continues.
58
+ Phases 0, 1, and 2 inject a knowledge-graph report from [graphify](https://github.com/safishamsi/graphify) for richer code orientation. When the graph is missing, the orchestrator falls back to a sentinel string and continues — nothing breaks.
59
+
60
+ **Install the CLI** (required to use graphify at all):
59
61
 
60
62
  ```bash
61
63
  pipx install graphifyy # CLI binary is `graphify`
62
64
  ```
63
65
 
66
+ **Seed the graph (one-time, per project)**: graphify's full LLM-driven build runs through the `/graphify` slash-command inside an AI assistant — *not* through the shell binary. From inside Claude Code (or any other graphify-supported assistant) run:
67
+
68
+ ```
69
+ /graphify .
70
+ ```
71
+
72
+ This produces `graphify-out/graph.json` and `graphify-out/GRAPH_REPORT.md`.
73
+
74
+ **Subsequent code-generator runs** will automatically refresh the graph with `graphify update .` (AST-only, no LLM cost). Doc / paper / image changes still need a manual `/graphify .` re-run inside your assistant.
75
+
64
76
  Add to your project's `.gitignore`:
65
77
 
66
78
  ```
67
- graphify-out/manifest.json
68
- graphify-out/cost.json
79
+ graphify-out/
69
80
  ```
70
81
 
71
82
  ## Authentication
@@ -1,3 +1,3 @@
1
1
  """code-generator: orchestrator CLI for end-to-end project generation."""
2
2
 
3
- __version__ = "0.5.2"
3
+ __version__ = "0.5.3"
@@ -37,34 +37,12 @@ __all__ = ["dispatch_async", "dispatch_orchestrator"]
37
37
  _GRAPHIFY_TIMEOUT = int(os.environ.get("CODE_GENERATOR_GRAPHIFY_TIMEOUT", "600"))
38
38
 
39
39
 
40
- def _graphify_command(project_dir: Path) -> list[str]:
41
- """Return the right graphify CLI invocation based on whether a prior graph exists.
42
-
43
- Graphify's CLI parser treats the first positional arg as a *subcommand*
44
- name (``install``, ``query``, ``update``, ...) and only falls through to
45
- "build the graph for this directory" when the arg looks like a relative
46
- path (``.``, ``./src``). Passing an absolute path like
47
- ``/Volumes/External SSD/optimizer`` makes graphify exit 1 with
48
- ``error: unknown command '<path>'``. We always pass ``.`` and rely on
49
- ``subprocess.run(cwd=project_dir)`` to anchor it.
50
-
51
- Graphify's ``--update`` flag *requires* an existing ``graph.json`` to
52
- merge into ("re-extract only changed files, merge into existing graph").
53
- On a virgin project tree it fails with exit 1. We detect that case by
54
- looking for ``graphify-out/graph.json`` and skipping ``--update`` on the
55
- first run.
56
-
57
- Args:
58
- project_dir: Project root directory.
59
-
60
- Returns:
61
- The argv list to pass to ``subprocess.run``.
62
- """
63
- graph_json = project_dir / "graphify-out" / "graph.json"
64
- base = ["graphify", ".", "--no-viz"]
65
- if graph_json.exists():
66
- base.append("--update")
67
- return base
40
+ _SETUP_HINT = (
41
+ "graph-report: graphify-out/graph.json not found run `/graphify .` once "
42
+ "inside Claude Code (or another graphify-compatible assistant) to seed the "
43
+ "knowledge graph. After that, code-generator will keep it fresh "
44
+ "automatically with `graphify update .`. Using fallback for now."
45
+ )
68
46
 
69
47
 
70
48
  def _decode_stderr(stderr: bytes | str | None) -> str:
@@ -77,35 +55,37 @@ def _decode_stderr(stderr: bytes | str | None) -> str:
77
55
 
78
56
 
79
57
  def _compute_and_persist_graph_report(project_dir: Path, log: logging.Logger) -> None:
80
- """Build the codebase graph via graphify and persist it to memories.
58
+ """Refresh the codebase graph via graphify and persist the report.
59
+
60
+ Graphify's shell CLI does **not** support a "build" subcommand — the full
61
+ LLM-driven build only happens through the ``/graphify`` slash-command
62
+ inside an AI assistant (Claude Code, Codex, Cursor, etc.). The shell
63
+ binary only supports maintenance subcommands like ``update``, ``watch``,
64
+ ``query``.
81
65
 
82
- Invokes the ``graphify`` CLI to (re)build ``graphify-out/GRAPH_REPORT.md``
83
- and copies the resulting markdown into
84
- ``.code-generator/memories/cycle-repo-map.md`` so Phases 0, 1, 2 can read
85
- it via :func:`code_generator.memory.read_cycle_repomap`.
66
+ Strategy:
86
67
 
87
- Two modes:
68
+ 1. If ``graphify-out/graph.json`` does **not** exist, the user has never
69
+ seeded the graph. Log a one-time setup hint, write the fallback
70
+ sentinel, and return — do not call subprocess. The user must run
71
+ ``/graphify .`` in their assistant once to seed it.
88
72
 
89
- - **First run** (no ``graphify-out/graph.json``): full build via
90
- ``graphify <path> --no-viz``. ``--update`` is *not* added because it
91
- requires a prior graph to merge into passing it on a virgin tree
92
- makes graphify exit 1.
93
- - **Incremental** (graph.json exists): ``graphify <path> --update
94
- --no-viz``. Graphify's SHA256-keyed cache in ``graphify-out/cache/``
95
- keeps subsequent runs cheap.
73
+ 2. If it exists, run ``graphify update .`` (cwd=project_dir). This is
74
+ AST-only re-extraction, no LLM cost, fast on cached files. It
75
+ refreshes ``graph.json`` and ``GRAPH_REPORT.md``. Doc / paper /
76
+ image changes are *not* picked up — for those the user must run
77
+ ``/graphify .`` again in their assistant.
96
78
 
97
79
  Falls back to :data:`code_generator.memory.REPOMAP_FALLBACK` on any
98
80
  failure (binary missing, timeout, non-zero exit, missing report file).
99
81
  Stderr from graphify is captured and logged at WARN level on failure so
100
82
  the user can diagnose without re-running by hand.
101
83
 
102
- Auth: graphify inherits the parent process env (Claude Code OAuth
103
- subscription). Do **not** strip ``ANTHROPIC_*`` here graphify is a
104
- user-facing dev tool that piggybacks on whichever assistant invoked it.
105
- The startup ``env.assert_safe_environment()`` check (CLAUDE.md
106
- non-negotiable #1) already guarantees no API-key vars are present in the
107
- process environment when the orchestrator runs on the Anthropic Max
108
- path, so passing the inherited env to graphify is safe.
84
+ Auth: graphify inherits the parent process env. ``graphify update`` is
85
+ AST-only and makes no LLM calls, so OAuth context is irrelevant on this
86
+ codepath but we still don't strip ``ANTHROPIC_*`` because the startup
87
+ ``env.assert_safe_environment()`` check (CLAUDE.md non-negotiable #1)
88
+ already guarantees those vars are absent on the Anthropic Max path.
109
89
 
110
90
  Args:
111
91
  project_dir: Project root directory (graphify writes ``graphify-out/``
@@ -114,6 +94,7 @@ def _compute_and_persist_graph_report(project_dir: Path, log: logging.Logger) ->
114
94
  """
115
95
  memories_dir = project_dir / ".code-generator" / "memories"
116
96
  report_path = project_dir / "graphify-out" / "GRAPH_REPORT.md"
97
+ graph_json = project_dir / "graphify-out" / "graph.json"
117
98
 
118
99
  if shutil.which("graphify") is None:
119
100
  log.warning(
@@ -123,9 +104,14 @@ def _compute_and_persist_graph_report(project_dir: Path, log: logging.Logger) ->
123
104
  _memory.write_memory_file(memories_dir, "cycle-repo-map.md", _memory.REPOMAP_FALLBACK)
124
105
  return
125
106
 
126
- cmd = _graphify_command(project_dir)
107
+ if not graph_json.exists():
108
+ log.info(_SETUP_HINT)
109
+ _memory.write_memory_file(memories_dir, "cycle-repo-map.md", _memory.REPOMAP_FALLBACK)
110
+ return
111
+
112
+ cmd = ["graphify", "update", "."]
127
113
  try:
128
- log.info("graph-report: building (cmd=%s)", " ".join(cmd))
114
+ log.info("graph-report: refreshing (cmd=%s)", " ".join(cmd))
129
115
  subprocess.run( # noqa: S603
130
116
  cmd,
131
117
  cwd=project_dir,
@@ -1,15 +1,14 @@
1
1
  """Tests for ``commands._dispatch._compute_and_persist_graph_report``.
2
2
 
3
- The helper shells out to the ``graphify`` CLI to (re)build
4
- ``graphify-out/GRAPH_REPORT.md`` and copies the result into
5
- ``.code-generator/memories/cycle-repo-map.md``.
6
-
7
- Two invocation modes:
8
- - **First run** (no ``graphify-out/graph.json``): ``graphify <path> --no-viz``
9
- - **Incremental** (graph.json exists): ``graphify <path> --update --no-viz``
10
-
11
- The ``--update`` flag merges into an existing graph and fails on a virgin
12
- tree, so we detect first-run via ``graph.json`` existence.
3
+ Graphify's shell CLI only supports maintenance — the full LLM-driven build
4
+ runs through the ``/graphify`` slash-command inside an AI assistant. Our
5
+ orchestrator therefore:
6
+
7
+ - writes the fallback sentinel and emits a one-time setup hint when
8
+ ``graphify-out/graph.json`` does not exist (user must seed via the
9
+ slash-command first);
10
+ - runs ``graphify update .`` (AST-only refresh, no LLM cost) when the
11
+ graph already exists.
13
12
  """
14
13
 
15
14
  from __future__ import annotations
@@ -35,46 +34,46 @@ def _read_persisted(project_dir: Path) -> str:
35
34
  return target.read_text(encoding="utf-8") if target.exists() else ""
36
35
 
37
36
 
37
+ def _seed_graph(project_dir: Path) -> Path:
38
+ """Pre-create ``graphify-out/graph.json`` so subprocess paths run."""
39
+ graphify_out = project_dir / "graphify-out"
40
+ graphify_out.mkdir(parents=True, exist_ok=True)
41
+ (graphify_out / "graph.json").write_text("{}", encoding="utf-8")
42
+ (graphify_out / "GRAPH_REPORT.md").write_text("# seed report\n", encoding="utf-8")
43
+ return graphify_out
44
+
45
+
38
46
  class TestGraphReportBuild:
39
47
  """Behaviour of _compute_and_persist_graph_report under each branch."""
40
48
 
41
- def test_first_run_uses_full_build_without_update_flag(
42
- self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
49
+ def test_no_graph_seed_writes_fallback_and_emits_setup_hint(
50
+ self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
43
51
  ) -> None:
44
- """First run (no graph.json) invokes `graphify <path> --no-viz` (no --update)."""
52
+ """When graph.json doesn't exist, write fallback + emit `/graphify .` hint, no subprocess."""
45
53
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
46
54
 
47
- commands_seen: list[list[str]] = []
55
+ called: list[object] = []
48
56
 
49
- def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
50
- commands_seen.append(cmd)
51
- report_dir = tmp_path / "graphify-out"
52
- report_dir.mkdir(parents=True, exist_ok=True)
53
- (report_dir / "GRAPH_REPORT.md").write_text("# fresh report\n", encoding="utf-8")
54
- return subprocess.CompletedProcess(args=cmd, returncode=0, stdout=b"", stderr=b"")
57
+ def _fake_run(*a: object, **k: object) -> subprocess.CompletedProcess[bytes]:
58
+ called.append(a)
59
+ raise AssertionError("subprocess.run must not be called when graph.json is missing")
55
60
 
56
61
  monkeypatch.setattr(_dispatch.subprocess, "run", _fake_run)
57
62
 
58
- _dispatch._compute_and_persist_graph_report(tmp_path, _logger())
63
+ with caplog.at_level("INFO"):
64
+ _dispatch._compute_and_persist_graph_report(tmp_path, _logger())
59
65
 
60
- assert len(commands_seen) == 1
61
- assert commands_seen[0][0] == "graphify"
62
- assert "--no-viz" in commands_seen[0]
63
- assert "--update" not in commands_seen[0], (
64
- "first run must not pass --update graphify exits 1 without an existing graph"
65
- )
66
- # Path arg must be relative '.', not absolute — graphify's CLI parser
67
- # rejects absolute paths as 'unknown command' (verified on graphify 0.5.x).
68
- assert "." in commands_seen[0], "must pass relative '.' so graphify accepts it"
69
- assert str(tmp_path) not in commands_seen[0], (
70
- "absolute path would trigger graphify's `unknown command` error"
66
+ assert called == []
67
+ assert _read_persisted(tmp_path) == REPOMAP_FALLBACK
68
+ messages = [r.getMessage() for r in caplog.records]
69
+ assert any("/graphify" in m for m in messages), (
70
+ "must emit a hint telling the user to seed via /graphify"
71
71
  )
72
- assert _read_persisted(tmp_path) == "# fresh report\n"
73
72
 
74
- def test_incremental_run_uses_update_flag(
73
+ def test_seeded_graph_runs_update_subcommand(
75
74
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
76
75
  ) -> None:
77
- """When graph.json already exists, the run uses `--update --no-viz`."""
76
+ """When graph.json exists, run `graphify update .` (AST-only refresh)."""
78
77
  report_dir = tmp_path / "graphify-out"
79
78
  report_dir.mkdir(parents=True)
80
79
  (report_dir / "graph.json").write_text("{}", encoding="utf-8")
@@ -93,9 +92,9 @@ class TestGraphReportBuild:
93
92
 
94
93
  _dispatch._compute_and_persist_graph_report(tmp_path, _logger())
95
94
 
96
- assert len(commands_seen) == 1
97
- assert "--update" in commands_seen[0]
98
- assert "--no-viz" in commands_seen[0]
95
+ assert commands_seen == [["graphify", "update", "."]], (
96
+ f"expected `graphify update .`; got {commands_seen}"
97
+ )
99
98
  assert _read_persisted(tmp_path) == "# updated report\n"
100
99
 
101
100
  def test_binary_missing_writes_fallback(
@@ -120,7 +119,8 @@ class TestGraphReportBuild:
120
119
  def test_timeout_writes_fallback(
121
120
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
122
121
  ) -> None:
123
- """A `TimeoutExpired` from the build subprocess writes the fallback."""
122
+ """A `TimeoutExpired` from the update subprocess writes the fallback."""
123
+ _seed_graph(tmp_path)
124
124
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
125
125
 
126
126
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
@@ -135,7 +135,8 @@ class TestGraphReportBuild:
135
135
  def test_called_process_error_writes_fallback(
136
136
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
137
137
  ) -> None:
138
- """Non-zero exit from the build subprocess writes the fallback."""
138
+ """Non-zero exit from the update subprocess writes the fallback."""
139
+ _seed_graph(tmp_path)
139
140
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
140
141
 
141
142
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
@@ -151,9 +152,10 @@ class TestGraphReportBuild:
151
152
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
152
153
  ) -> None:
153
154
  """On non-zero exit, graphify's stderr must appear in the log warning."""
155
+ _seed_graph(tmp_path)
154
156
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
155
157
 
156
- stderr_msg = b"Error: graph.json not found, cannot --update"
158
+ stderr_msg = b"Error: corrupted graph.json"
157
159
 
158
160
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
159
161
  raise subprocess.CalledProcessError(returncode=1, cmd=cmd, stderr=stderr_msg)
@@ -164,7 +166,7 @@ class TestGraphReportBuild:
164
166
  _dispatch._compute_and_persist_graph_report(tmp_path, _logger())
165
167
 
166
168
  warnings = [r.getMessage() for r in caplog.records if r.levelname == "WARNING"]
167
- assert any("graph.json not found" in w for w in warnings), (
169
+ assert any("corrupted graph.json" in w for w in warnings), (
168
170
  f"stderr from graphify must be in the log warning. Got: {warnings}"
169
171
  )
170
172
 
@@ -172,10 +174,14 @@ class TestGraphReportBuild:
172
174
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
173
175
  ) -> None:
174
176
  """If graphify exits 0 but the report file is missing, write fallback."""
177
+ graphify_out = _seed_graph(tmp_path)
178
+ # Remove the seed report so the read fails after success.
179
+ (graphify_out / "GRAPH_REPORT.md").unlink()
180
+
175
181
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
176
182
 
177
183
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
178
- # Exit 0 but never create the report file.
184
+ # Exit 0 but don't (re)create the report file.
179
185
  return subprocess.CompletedProcess(args=cmd, returncode=0, stdout=b"", stderr=b"")
180
186
 
181
187
  monkeypatch.setattr(_dispatch.subprocess, "run", _fake_run)
@@ -187,20 +193,15 @@ class TestGraphReportBuild:
187
193
  def test_no_env_argument_passed_to_subprocess(
188
194
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
189
195
  ) -> None:
190
- """Graphify must inherit the parent env (no `env=` arg) for OAuth.
191
-
192
- Documented in the function's docstring: stripping ANTHROPIC_* would
193
- break graphify's LLM extraction. The startup env-safety check
194
- guarantees no API-key vars are in the process env on the Max path.
195
- """
196
+ """Graphify must inherit the parent env (no `env=` arg)."""
197
+ graphify_out = _seed_graph(tmp_path)
196
198
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
197
199
 
198
200
  captured_kwargs: dict[str, object] = {}
199
201
 
200
202
  def _fake_run(cmd: list[str], **kwargs: object) -> subprocess.CompletedProcess[bytes]:
201
203
  captured_kwargs.update(kwargs)
202
- (tmp_path / "graphify-out").mkdir(parents=True, exist_ok=True)
203
- (tmp_path / "graphify-out" / "GRAPH_REPORT.md").write_text("ok\n", encoding="utf-8")
204
+ (graphify_out / "GRAPH_REPORT.md").write_text("ok\n", encoding="utf-8")
204
205
  return subprocess.CompletedProcess(args=cmd, returncode=0, stdout=b"", stderr=b"")
205
206
 
206
207
  monkeypatch.setattr(_dispatch.subprocess, "run", _fake_run)
@@ -215,6 +216,7 @@ class TestGraphReportBuild:
215
216
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
216
217
  ) -> None:
217
218
  """An OSError from subprocess.run (e.g., permission denied) writes fallback."""
219
+ _seed_graph(tmp_path)
218
220
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
219
221
 
220
222
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]: