claude-code-generator 0.5.1__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.1/src/claude_code_generator.egg-info → claude_code_generator-0.5.3}/PKG-INFO +15 -4
  2. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/README.md +14 -3
  3. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/pyproject.toml +1 -1
  4. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3/src/claude_code_generator.egg-info}/PKG-INFO +15 -4
  5. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/__init__.py +1 -1
  6. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/_dispatch.py +36 -42
  7. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_dispatch_graph_report.py +53 -45
  8. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/LICENSE +0 -0
  9. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/setup.cfg +0 -0
  10. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/SOURCES.txt +0 -0
  11. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
  12. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
  13. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/requires.txt +0 -0
  14. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/claude_code_generator.egg-info/top_level.txt +0 -0
  15. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/agents.py +0 -0
  16. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/cli.py +0 -0
  17. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/__init__.py +0 -0
  18. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/_bench_io.py +0 -0
  19. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/_crash_recovery.py +0 -0
  20. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/_detect.py +0 -0
  21. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/_resume.py +0 -0
  22. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/_validators.py +0 -0
  23. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/bench.py +0 -0
  24. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/bench_compare.py +0 -0
  25. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/bench_export.py +0 -0
  26. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/generate.py +0 -0
  27. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/init.py +0 -0
  28. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/optimize.py +0 -0
  29. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/review.py +0 -0
  30. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/commands/status.py +0 -0
  31. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/effort.py +0 -0
  32. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/env.py +0 -0
  33. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/gh/__init__.py +0 -0
  34. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/gh/core.py +0 -0
  35. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/gh/issues.py +0 -0
  36. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/gh/labels.py +0 -0
  37. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/gh/milestones.py +0 -0
  38. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/git_ops.py +0 -0
  39. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/logging_setup.py +0 -0
  40. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/memory.py +0 -0
  41. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/__init__.py +0 -0
  42. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_client_lifecycle.py +0 -0
  43. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_comments.py +0 -0
  44. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_memory_writers.py +0 -0
  45. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/_phase5_precommit.py +0 -0
  46. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/cycle_loop.py +0 -0
  47. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/cycle_prompts.py +0 -0
  48. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/ollama_budget.py +0 -0
  49. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase0_complexity.py +0 -0
  50. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase1_plan.py +0 -0
  51. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase2_review.py +0 -0
  52. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase3_4_implement.py +0 -0
  53. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase5_closure.py +0 -0
  54. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase6_test.py +0 -0
  55. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/orchestrator/phase7_commit.py +0 -0
  56. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/preflight.py +0 -0
  57. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/__init__.py +0 -0
  58. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/hashes.py +0 -0
  59. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-cycle-specializer.md +0 -0
  60. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-optimize-requirements.md +0 -0
  61. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-0-complexity.md +0 -0
  62. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-1-planning.md +0 -0
  63. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-2-batch-review.md +0 -0
  64. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-3-implementation.md +0 -0
  65. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-5-final-review.md +0 -0
  66. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
  67. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-phase-7-commit.md +0 -0
  68. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/prompts/prompt-review.md +0 -0
  69. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/repo_info.py +0 -0
  70. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/requirements_structure.py +0 -0
  71. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/__init__.py +0 -0
  72. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/_telemetry.py +0 -0
  73. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/batch.py +0 -0
  74. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/fake_runner.py +0 -0
  75. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/mcp.py +0 -0
  76. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/message_parsing.py +0 -0
  77. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/options.py +0 -0
  78. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/protocol.py +0 -0
  79. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/rate_limit.py +0 -0
  80. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/retry.py +0 -0
  81. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/sdk_runner.py +0 -0
  82. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/soft_reset.py +0 -0
  83. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/state_guard.py +0 -0
  84. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/subprocess_runner.py +0 -0
  85. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/types.py +0 -0
  86. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/runner/utils.py +0 -0
  87. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/state.py +0 -0
  88. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/state_retention.py +0 -0
  89. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/__init__.py +0 -0
  90. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/angular.md +0 -0
  91. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/base.md +0 -0
  92. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/fastapi.md +0 -0
  93. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/finance.md +0 -0
  94. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/fullstack.md +0 -0
  95. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/nestjs.md +0 -0
  96. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/src/code_generator/templates/python-cli.md +0 -0
  97. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_agents.py +0 -0
  98. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_bench.py +0 -0
  99. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_bench_compare.py +0 -0
  100. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_bench_export.py +0 -0
  101. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_bench_fixture.py +0 -0
  102. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_bench_regression.py +0 -0
  103. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_changelog.py +0 -0
  104. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_claude_md.py +0 -0
  105. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_client_lifecycle.py +0 -0
  106. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_comments.py +0 -0
  107. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_commit_message.py +0 -0
  108. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_crash_recovery.py +0 -0
  109. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_cycle_loop.py +0 -0
  110. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_cycle_loop_multicycle.py +0 -0
  111. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_cycle_ollama_model.py +0 -0
  112. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_cycle_prompts.py +0 -0
  113. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_delta_planning.py +0 -0
  114. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_dependencies.py +0 -0
  115. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_detect.py +0 -0
  116. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_docs_no_default_max_turns.py +0 -0
  117. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_docs_ollama_model_guide.py +0 -0
  118. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_docs_ollama_pro.py +0 -0
  119. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_effective_model_routing.py +0 -0
  120. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_effort.py +0 -0
  121. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_env.py +0 -0
  122. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_generate.py +0 -0
  123. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_generate_ollama.py +0 -0
  124. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_generate_resume.py +0 -0
  125. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_gh.py +0 -0
  126. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_gh_labels.py +0 -0
  127. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_gh_milestones.py +0 -0
  128. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_gh_repo_threading.py +0 -0
  129. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_gh_submodules.py +0 -0
  130. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_git_ops.py +0 -0
  131. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_init.py +0 -0
  132. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_logging_setup.py +0 -0
  133. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_max_turns_cli_flag.py +0 -0
  134. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_mcp.py +0 -0
  135. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_memory.py +0 -0
  136. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_memory_writers.py +0 -0
  137. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_message_parsing.py +0 -0
  138. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_no_max_turns_in_call_sites.py +0 -0
  139. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_no_max_turns_literal.py +0 -0
  140. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_non_goals_grep_guard.py +0 -0
  141. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_ollama_budget.py +0 -0
  142. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_ollama_rate_limit.py +0 -0
  143. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_optimize.py +0 -0
  144. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_options.py +0 -0
  145. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase0.py +0 -0
  146. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase1.py +0 -0
  147. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase2.py +0 -0
  148. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase3_4.py +0 -0
  149. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase5.py +0 -0
  150. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase5_precommit.py +0 -0
  151. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase6.py +0 -0
  152. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase7.py +0 -0
  153. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase_mcp_regression.py +0 -0
  154. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_phase_token_logging.py +0 -0
  155. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_preflight.py +0 -0
  156. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_preflight_ollama.py +0 -0
  157. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_prompt_drift.py +0 -0
  158. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_prompt_prefix_snapshots.py +0 -0
  159. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_prompt_prefix_stability.py +0 -0
  160. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_prompts.py +0 -0
  161. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_rate_limit.py +0 -0
  162. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_repo_info.py +0 -0
  163. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_requirements_structure.py +0 -0
  164. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_retry.py +0 -0
  165. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_review.py +0 -0
  166. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_runner_protocol.py +0 -0
  167. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_runner_protocol_annotations.py +0 -0
  168. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_runner_types.py +0 -0
  169. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_runner_utils.py +0 -0
  170. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_sdk_runner.py +0 -0
  171. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_sdk_runner_shared.py +0 -0
  172. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_session_mode.py +0 -0
  173. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_state.py +0 -0
  174. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_state_guard.py +0 -0
  175. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_state_retention.py +0 -0
  176. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_status.py +0 -0
  177. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_subprocess_runner.py +0 -0
  178. {claude_code_generator-0.5.1 → claude_code_generator-0.5.3}/tests/test_telemetry.py +0 -0
  179. {claude_code_generator-0.5.1 → 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.1
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.1"
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.1
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.1"
3
+ __version__ = "0.5.3"
@@ -37,26 +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 ``--update`` flag *requires* an existing ``graph.json`` to
44
- merge into ("re-extract only changed files, merge into existing graph").
45
- On a virgin project tree it fails with exit 1. We detect that case by
46
- looking for ``graphify-out/graph.json`` and skipping ``--update`` on the
47
- first run.
48
-
49
- Args:
50
- project_dir: Project root directory.
51
-
52
- Returns:
53
- The argv list to pass to ``subprocess.run``.
54
- """
55
- graph_json = project_dir / "graphify-out" / "graph.json"
56
- base = ["graphify", str(project_dir), "--no-viz"]
57
- if graph_json.exists():
58
- base.append("--update")
59
- 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
+ )
60
46
 
61
47
 
62
48
  def _decode_stderr(stderr: bytes | str | None) -> str:
@@ -69,35 +55,37 @@ def _decode_stderr(stderr: bytes | str | None) -> str:
69
55
 
70
56
 
71
57
  def _compute_and_persist_graph_report(project_dir: Path, log: logging.Logger) -> None:
72
- """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``.
73
65
 
74
- Invokes the ``graphify`` CLI to (re)build ``graphify-out/GRAPH_REPORT.md``
75
- and copies the resulting markdown into
76
- ``.code-generator/memories/cycle-repo-map.md`` so Phases 0, 1, 2 can read
77
- it via :func:`code_generator.memory.read_cycle_repomap`.
66
+ Strategy:
78
67
 
79
- 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.
80
72
 
81
- - **First run** (no ``graphify-out/graph.json``): full build via
82
- ``graphify <path> --no-viz``. ``--update`` is *not* added because it
83
- requires a prior graph to merge into passing it on a virgin tree
84
- makes graphify exit 1.
85
- - **Incremental** (graph.json exists): ``graphify <path> --update
86
- --no-viz``. Graphify's SHA256-keyed cache in ``graphify-out/cache/``
87
- 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.
88
78
 
89
79
  Falls back to :data:`code_generator.memory.REPOMAP_FALLBACK` on any
90
80
  failure (binary missing, timeout, non-zero exit, missing report file).
91
81
  Stderr from graphify is captured and logged at WARN level on failure so
92
82
  the user can diagnose without re-running by hand.
93
83
 
94
- Auth: graphify inherits the parent process env (Claude Code OAuth
95
- subscription). Do **not** strip ``ANTHROPIC_*`` here graphify is a
96
- user-facing dev tool that piggybacks on whichever assistant invoked it.
97
- The startup ``env.assert_safe_environment()`` check (CLAUDE.md
98
- non-negotiable #1) already guarantees no API-key vars are present in the
99
- process environment when the orchestrator runs on the Anthropic Max
100
- 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.
101
89
 
102
90
  Args:
103
91
  project_dir: Project root directory (graphify writes ``graphify-out/``
@@ -106,6 +94,7 @@ def _compute_and_persist_graph_report(project_dir: Path, log: logging.Logger) ->
106
94
  """
107
95
  memories_dir = project_dir / ".code-generator" / "memories"
108
96
  report_path = project_dir / "graphify-out" / "GRAPH_REPORT.md"
97
+ graph_json = project_dir / "graphify-out" / "graph.json"
109
98
 
110
99
  if shutil.which("graphify") is None:
111
100
  log.warning(
@@ -115,9 +104,14 @@ def _compute_and_persist_graph_report(project_dir: Path, log: logging.Logger) ->
115
104
  _memory.write_memory_file(memories_dir, "cycle-repo-map.md", _memory.REPOMAP_FALLBACK)
116
105
  return
117
106
 
118
- 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", "."]
119
113
  try:
120
- log.info("graph-report: building (cmd=%s)", " ".join(cmd))
114
+ log.info("graph-report: refreshing (cmd=%s)", " ".join(cmd))
121
115
  subprocess.run( # noqa: S603
122
116
  cmd,
123
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,40 +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"
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"
65
71
  )
66
- assert _read_persisted(tmp_path) == "# fresh report\n"
67
72
 
68
- def test_incremental_run_uses_update_flag(
73
+ def test_seeded_graph_runs_update_subcommand(
69
74
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
70
75
  ) -> None:
71
- """When graph.json already exists, the run uses `--update --no-viz`."""
76
+ """When graph.json exists, run `graphify update .` (AST-only refresh)."""
72
77
  report_dir = tmp_path / "graphify-out"
73
78
  report_dir.mkdir(parents=True)
74
79
  (report_dir / "graph.json").write_text("{}", encoding="utf-8")
@@ -87,9 +92,9 @@ class TestGraphReportBuild:
87
92
 
88
93
  _dispatch._compute_and_persist_graph_report(tmp_path, _logger())
89
94
 
90
- assert len(commands_seen) == 1
91
- assert "--update" in commands_seen[0]
92
- assert "--no-viz" in commands_seen[0]
95
+ assert commands_seen == [["graphify", "update", "."]], (
96
+ f"expected `graphify update .`; got {commands_seen}"
97
+ )
93
98
  assert _read_persisted(tmp_path) == "# updated report\n"
94
99
 
95
100
  def test_binary_missing_writes_fallback(
@@ -114,7 +119,8 @@ class TestGraphReportBuild:
114
119
  def test_timeout_writes_fallback(
115
120
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
116
121
  ) -> None:
117
- """A `TimeoutExpired` from the build subprocess writes the fallback."""
122
+ """A `TimeoutExpired` from the update subprocess writes the fallback."""
123
+ _seed_graph(tmp_path)
118
124
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
119
125
 
120
126
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
@@ -129,7 +135,8 @@ class TestGraphReportBuild:
129
135
  def test_called_process_error_writes_fallback(
130
136
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
131
137
  ) -> None:
132
- """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)
133
140
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
134
141
 
135
142
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
@@ -145,9 +152,10 @@ class TestGraphReportBuild:
145
152
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture
146
153
  ) -> None:
147
154
  """On non-zero exit, graphify's stderr must appear in the log warning."""
155
+ _seed_graph(tmp_path)
148
156
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
149
157
 
150
- stderr_msg = b"Error: graph.json not found, cannot --update"
158
+ stderr_msg = b"Error: corrupted graph.json"
151
159
 
152
160
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
153
161
  raise subprocess.CalledProcessError(returncode=1, cmd=cmd, stderr=stderr_msg)
@@ -158,7 +166,7 @@ class TestGraphReportBuild:
158
166
  _dispatch._compute_and_persist_graph_report(tmp_path, _logger())
159
167
 
160
168
  warnings = [r.getMessage() for r in caplog.records if r.levelname == "WARNING"]
161
- assert any("graph.json not found" in w for w in warnings), (
169
+ assert any("corrupted graph.json" in w for w in warnings), (
162
170
  f"stderr from graphify must be in the log warning. Got: {warnings}"
163
171
  )
164
172
 
@@ -166,10 +174,14 @@ class TestGraphReportBuild:
166
174
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
167
175
  ) -> None:
168
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
+
169
181
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
170
182
 
171
183
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]:
172
- # Exit 0 but never create the report file.
184
+ # Exit 0 but don't (re)create the report file.
173
185
  return subprocess.CompletedProcess(args=cmd, returncode=0, stdout=b"", stderr=b"")
174
186
 
175
187
  monkeypatch.setattr(_dispatch.subprocess, "run", _fake_run)
@@ -181,20 +193,15 @@ class TestGraphReportBuild:
181
193
  def test_no_env_argument_passed_to_subprocess(
182
194
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
183
195
  ) -> None:
184
- """Graphify must inherit the parent env (no `env=` arg) for OAuth.
185
-
186
- Documented in the function's docstring: stripping ANTHROPIC_* would
187
- break graphify's LLM extraction. The startup env-safety check
188
- guarantees no API-key vars are in the process env on the Max path.
189
- """
196
+ """Graphify must inherit the parent env (no `env=` arg)."""
197
+ graphify_out = _seed_graph(tmp_path)
190
198
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
191
199
 
192
200
  captured_kwargs: dict[str, object] = {}
193
201
 
194
202
  def _fake_run(cmd: list[str], **kwargs: object) -> subprocess.CompletedProcess[bytes]:
195
203
  captured_kwargs.update(kwargs)
196
- (tmp_path / "graphify-out").mkdir(parents=True, exist_ok=True)
197
- (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")
198
205
  return subprocess.CompletedProcess(args=cmd, returncode=0, stdout=b"", stderr=b"")
199
206
 
200
207
  monkeypatch.setattr(_dispatch.subprocess, "run", _fake_run)
@@ -209,6 +216,7 @@ class TestGraphReportBuild:
209
216
  self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
210
217
  ) -> None:
211
218
  """An OSError from subprocess.run (e.g., permission denied) writes fallback."""
219
+ _seed_graph(tmp_path)
212
220
  monkeypatch.setattr(_dispatch.shutil, "which", lambda _name: "/usr/bin/graphify")
213
221
 
214
222
  def _fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[bytes]: