claude-code-generator 0.1.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 (145) hide show
  1. {claude_code_generator-0.1.0/src/claude_code_generator.egg-info → claude_code_generator-0.2.1}/PKG-INFO +23 -7
  2. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/README.md +22 -6
  3. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/pyproject.toml +5 -1
  4. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1/src/claude_code_generator.egg-info}/PKG-INFO +23 -7
  5. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/claude_code_generator.egg-info/SOURCES.txt +38 -1
  6. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/__init__.py +1 -1
  7. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/cli.py +2 -0
  8. claude_code_generator-0.2.1/src/code_generator/commands/_detect.py +59 -0
  9. claude_code_generator-0.2.1/src/code_generator/commands/_dispatch.py +278 -0
  10. claude_code_generator-0.2.1/src/code_generator/commands/_resume.py +73 -0
  11. claude_code_generator-0.2.1/src/code_generator/commands/generate.py +126 -0
  12. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/commands/init.py +1 -3
  13. claude_code_generator-0.2.1/src/code_generator/commands/optimize.py +158 -0
  14. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/commands/review.py +18 -28
  15. claude_code_generator-0.2.1/src/code_generator/commands/status.py +192 -0
  16. claude_code_generator-0.2.1/src/code_generator/effort.py +164 -0
  17. claude_code_generator-0.2.1/src/code_generator/gh/__init__.py +51 -0
  18. claude_code_generator-0.2.1/src/code_generator/gh/core.py +111 -0
  19. claude_code_generator-0.2.1/src/code_generator/gh/issues.py +66 -0
  20. claude_code_generator-0.2.1/src/code_generator/gh/labels.py +102 -0
  21. claude_code_generator-0.2.1/src/code_generator/gh/milestones.py +89 -0
  22. claude_code_generator-0.2.1/src/code_generator/git_ops.py +213 -0
  23. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/logging_setup.py +61 -0
  24. claude_code_generator-0.2.1/src/code_generator/orchestrator/_comments.py +72 -0
  25. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/orchestrator/cycle_loop.py +239 -123
  26. claude_code_generator-0.2.1/src/code_generator/orchestrator/phase0_complexity.py +315 -0
  27. claude_code_generator-0.2.1/src/code_generator/orchestrator/phase1_plan.py +252 -0
  28. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/orchestrator/phase2_review.py +54 -35
  29. claude_code_generator-0.2.1/src/code_generator/orchestrator/phase3_4_implement.py +306 -0
  30. claude_code_generator-0.2.1/src/code_generator/orchestrator/phase5_closure.py +246 -0
  31. claude_code_generator-0.2.1/src/code_generator/orchestrator/phase6_test.py +117 -0
  32. claude_code_generator-0.2.1/src/code_generator/orchestrator/phase7_commit.py +336 -0
  33. claude_code_generator-0.2.1/src/code_generator/prompts/__init__.py +146 -0
  34. claude_code_generator-0.2.1/src/code_generator/prompts/prompt-optimize-requirements.md +70 -0
  35. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-0-complexity.md +64 -4
  36. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-1-planning.md +14 -5
  37. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-2-issue-review.md +5 -1
  38. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-3-implementation.md +8 -4
  39. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-5-final-review.md +25 -1
  40. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-7-commit.md +53 -6
  41. claude_code_generator-0.2.1/src/code_generator/requirements_structure.py +78 -0
  42. claude_code_generator-0.2.1/src/code_generator/runner/__init__.py +52 -0
  43. claude_code_generator-0.2.1/src/code_generator/runner/message_parsing.py +162 -0
  44. claude_code_generator-0.2.1/src/code_generator/runner/options.py +41 -0
  45. claude_code_generator-0.2.1/src/code_generator/runner/protocol.py +60 -0
  46. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/runner/rate_limit.py +70 -6
  47. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/runner/retry.py +5 -9
  48. claude_code_generator-0.2.1/src/code_generator/runner/sdk_runner.py +211 -0
  49. claude_code_generator-0.2.1/src/code_generator/runner/subprocess_runner.py +334 -0
  50. claude_code_generator-0.2.1/src/code_generator/runner/types.py +166 -0
  51. claude_code_generator-0.2.1/src/code_generator/runner/utils.py +16 -0
  52. claude_code_generator-0.2.1/src/code_generator/state.py +364 -0
  53. claude_code_generator-0.2.1/tests/test_comments.py +342 -0
  54. claude_code_generator-0.2.1/tests/test_commit_message.py +138 -0
  55. claude_code_generator-0.2.1/tests/test_cycle_loop.py +1476 -0
  56. claude_code_generator-0.2.1/tests/test_cycle_loop_multicycle.py +903 -0
  57. claude_code_generator-0.2.1/tests/test_delta_planning.py +493 -0
  58. claude_code_generator-0.2.1/tests/test_detect.py +259 -0
  59. claude_code_generator-0.2.1/tests/test_effort.py +274 -0
  60. claude_code_generator-0.2.1/tests/test_generate.py +419 -0
  61. claude_code_generator-0.2.1/tests/test_generate_resume.py +1339 -0
  62. claude_code_generator-0.2.1/tests/test_gh.py +347 -0
  63. claude_code_generator-0.2.1/tests/test_gh_labels.py +150 -0
  64. claude_code_generator-0.2.1/tests/test_gh_milestones.py +158 -0
  65. claude_code_generator-0.2.1/tests/test_gh_submodules.py +223 -0
  66. claude_code_generator-0.2.1/tests/test_git_ops.py +506 -0
  67. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_init.py +4 -12
  68. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_logging_setup.py +1 -3
  69. claude_code_generator-0.2.1/tests/test_message_parsing.py +432 -0
  70. claude_code_generator-0.2.1/tests/test_optimize.py +621 -0
  71. claude_code_generator-0.2.1/tests/test_options.py +95 -0
  72. claude_code_generator-0.2.1/tests/test_phase0.py +401 -0
  73. claude_code_generator-0.2.1/tests/test_phase1.py +687 -0
  74. claude_code_generator-0.2.1/tests/test_phase2.py +506 -0
  75. claude_code_generator-0.2.1/tests/test_phase3_4.py +1080 -0
  76. claude_code_generator-0.2.1/tests/test_phase5.py +787 -0
  77. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_phase6.py +95 -0
  78. claude_code_generator-0.2.1/tests/test_phase7.py +1036 -0
  79. claude_code_generator-0.2.1/tests/test_phase_token_logging.py +742 -0
  80. claude_code_generator-0.2.1/tests/test_prompts.py +433 -0
  81. claude_code_generator-0.2.1/tests/test_rate_limit.py +871 -0
  82. claude_code_generator-0.2.1/tests/test_requirements_structure.py +290 -0
  83. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_retry.py +75 -0
  84. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_review.py +3 -9
  85. claude_code_generator-0.2.1/tests/test_runner_protocol.py +208 -0
  86. claude_code_generator-0.2.1/tests/test_runner_protocol_annotations.py +214 -0
  87. claude_code_generator-0.2.1/tests/test_runner_types.py +311 -0
  88. claude_code_generator-0.2.1/tests/test_runner_utils.py +104 -0
  89. claude_code_generator-0.2.1/tests/test_sdk_runner.py +902 -0
  90. claude_code_generator-0.2.1/tests/test_state.py +1154 -0
  91. claude_code_generator-0.2.1/tests/test_status.py +541 -0
  92. claude_code_generator-0.2.1/tests/test_subprocess_runner.py +1147 -0
  93. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_version.py +11 -0
  94. claude_code_generator-0.1.0/src/code_generator/commands/generate.py +0 -252
  95. claude_code_generator-0.1.0/src/code_generator/commands/status.py +0 -83
  96. claude_code_generator-0.1.0/src/code_generator/gh.py +0 -331
  97. claude_code_generator-0.1.0/src/code_generator/orchestrator/phase0_complexity.py +0 -159
  98. claude_code_generator-0.1.0/src/code_generator/orchestrator/phase1_plan.py +0 -170
  99. claude_code_generator-0.1.0/src/code_generator/orchestrator/phase3_4_implement.py +0 -164
  100. claude_code_generator-0.1.0/src/code_generator/orchestrator/phase5_closure.py +0 -154
  101. claude_code_generator-0.1.0/src/code_generator/orchestrator/phase6_test.py +0 -98
  102. claude_code_generator-0.1.0/src/code_generator/orchestrator/phase7_commit.py +0 -167
  103. claude_code_generator-0.1.0/src/code_generator/prompts/__init__.py +0 -86
  104. claude_code_generator-0.1.0/src/code_generator/runner/__init__.py +0 -26
  105. claude_code_generator-0.1.0/src/code_generator/runner/sdk_runner.py +0 -267
  106. claude_code_generator-0.1.0/src/code_generator/runner/subprocess_runner.py +0 -200
  107. claude_code_generator-0.1.0/src/code_generator/state.py +0 -178
  108. claude_code_generator-0.1.0/tests/test_cycle_loop.py +0 -573
  109. claude_code_generator-0.1.0/tests/test_generate.py +0 -180
  110. claude_code_generator-0.1.0/tests/test_generate_resume.py +0 -436
  111. claude_code_generator-0.1.0/tests/test_gh.py +0 -365
  112. claude_code_generator-0.1.0/tests/test_phase0.py +0 -175
  113. claude_code_generator-0.1.0/tests/test_phase1.py +0 -223
  114. claude_code_generator-0.1.0/tests/test_phase2.py +0 -224
  115. claude_code_generator-0.1.0/tests/test_phase3_4.py +0 -229
  116. claude_code_generator-0.1.0/tests/test_phase5.py +0 -200
  117. claude_code_generator-0.1.0/tests/test_phase7.py +0 -257
  118. claude_code_generator-0.1.0/tests/test_prompts.py +0 -185
  119. claude_code_generator-0.1.0/tests/test_rate_limit.py +0 -260
  120. claude_code_generator-0.1.0/tests/test_sdk_runner.py +0 -285
  121. claude_code_generator-0.1.0/tests/test_state.py +0 -224
  122. claude_code_generator-0.1.0/tests/test_status.py +0 -106
  123. claude_code_generator-0.1.0/tests/test_subprocess_runner.py +0 -213
  124. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/LICENSE +0 -0
  125. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/setup.cfg +0 -0
  126. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
  127. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
  128. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/claude_code_generator.egg-info/requires.txt +0 -0
  129. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/claude_code_generator.egg-info/top_level.txt +0 -0
  130. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/agents.py +0 -0
  131. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/commands/__init__.py +0 -0
  132. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/env.py +0 -0
  133. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/orchestrator/__init__.py +0 -0
  134. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
  135. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/prompts/prompt-review.md +0 -0
  136. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/__init__.py +0 -0
  137. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/angular.md +0 -0
  138. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/base.md +0 -0
  139. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/fastapi.md +0 -0
  140. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/finance.md +0 -0
  141. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/fullstack.md +0 -0
  142. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/nestjs.md +0 -0
  143. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/src/code_generator/templates/python-cli.md +0 -0
  144. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_agents.py +0 -0
  145. {claude_code_generator-0.1.0 → claude_code_generator-0.2.1}/tests/test_env.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.1.0
3
+ Version: 0.2.1
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
@@ -31,7 +31,7 @@ Dynamic: license-file
31
31
 
32
32
  # code-generator
33
33
 
34
- A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Three commands — `init`, `generate`, `review` — plus `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
34
+ A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Five commands — `init`, `optimize`, `generate`, `review`, `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
35
35
 
36
36
  > **Max subscription only.** This tool uses **exclusively** the Claude Max subscription. It strips every environment variable that could route a call through the API and aborts on startup if any are still present. There is no path to API credit billing — see [Safety constraints](#safety-constraints) below.
37
37
 
@@ -68,6 +68,20 @@ code-generator init --template fastapi
68
68
  $EDITOR .code-generator/requirements.md
69
69
  ```
70
70
 
71
+ ### `code-generator optimize [--dry-run] [--force]`
72
+
73
+ Pre-flight rewrite of `.code-generator/requirements.md` into the canonical structure the orchestrator expects: `# Title` → `## Description` → `## Tech Stack` → `## Goals` → `## Scope` (numbered `### N.` subsections with per-section `Acceptance criteria` checklists) → `## Non-goals` → `## Constraints` → `## Global acceptance criteria`.
74
+
75
+ Runs a single Opus 4.6 session with a dedicated prompt, preserves the original intent verbatim when ambiguous (never invents new scope), and writes the rewrite back to disk atomically. The pre-optimize original is saved to `.code-generator/requirements.backup-<UTC-timestamp>.md` so you can always `diff` and recover. The command is stateless — it never reads or writes `state.json` and never calls `gh`.
76
+
77
+ Short-circuits and exits 0 if the file is already canonical. Use `--force` to re-optimize anyway. Use `--dry-run` to print the proposed rewrite to stdout without touching the file or creating a backup.
78
+
79
+ ```bash
80
+ code-generator optimize --dry-run # preview
81
+ code-generator optimize # commit the rewrite
82
+ code-generator generate # then run the pipeline
83
+ ```
84
+
71
85
  ### `code-generator generate [flags]`
72
86
 
73
87
  Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0→7 phase pipeline:
@@ -80,7 +94,9 @@ Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0
80
94
  | 3-4 | Implementation, fresh SDK session per issue (TDD) | Sonnet 4.6 |
81
95
  | 5 | Closure + cross-module review | Opus 4.6 |
82
96
  | 6 | Test suite, max 3 retries on failure | Sonnet 4.6 |
83
- | 7 | Commit message + git add/commit/push | Haiku 4.5 |
97
+ | 7 | Commit message + git add/commit/push | Opus 4.6 |
98
+
99
+ Every phase logs a completion summary with token counts (`in`, `cache_read`, `cache_write`, `out`) and persists them to `state.json`.
84
100
 
85
101
  Flags:
86
102
 
@@ -102,7 +118,7 @@ Run a standalone Opus 4.6 review of the current codebase against the design prin
102
118
 
103
119
  ### `code-generator status`
104
120
 
105
- Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), and the last error.
121
+ Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), per-cycle token consumption columns (`in | cache_read | cache_write | out`), wall-clock elapsed time, and any `last_error` highlighted in red.
106
122
 
107
123
  ## Safety constraints
108
124
 
@@ -115,7 +131,7 @@ The tool enforces eight non-negotiables (see `CLAUDE.md` for the full list):
115
131
  5. **Wait-and-resume rate-limit handling.** Rate limits are not retried with exponential backoff — the tool sleeps until `resets_at + 60s` and resumes the same session. Backoff (10→20→40→80→120s) only applies to non-rate-limit transient errors.
116
132
  6. **Fresh SDK session per issue.** The implementation phase never reuses conversational context across issues — each issue is a `/clear`-equivalent fresh session.
117
133
  7. **Atomic state writes.** `.code-generator/state.json` is updated via `tmp → os.replace(tmp, STATE)` so a crash mid-write cannot corrupt it.
118
- 8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5; Sonnet 4.6 for phases 3/4/6; Haiku 4.5 for phase 7's commit message.
134
+ 8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5/7; Sonnet 4.6 for phases 3/4/6.
119
135
 
120
136
  ## Troubleshooting
121
137
 
@@ -151,9 +167,9 @@ src/code_generator/
151
167
  │ ├── phase3_4_implement.py # TDD loop, fresh session per issue
152
168
  │ ├── phase5_closure.py # closure + fix-issue feedback loop
153
169
  │ ├── phase6_test.py # test runner, max 3 retries
154
- │ ├── phase7_commit.py # Haiku commit message + push with rebase retry
170
+ │ ├── phase7_commit.py # Opus commit message + push with rebase retry
155
171
  │ └── cycle_loop.py # multi-cycle driver
156
- └── commands/ # init, status, generate, review (Typer commands)
172
+ └── commands/ # init, optimize, status, generate, review (Typer commands)
157
173
  ```
158
174
 
159
175
  ## Development
@@ -1,6 +1,6 @@
1
1
  # code-generator
2
2
 
3
- A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Three commands — `init`, `generate`, `review` — plus `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
3
+ A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Five commands — `init`, `optimize`, `generate`, `review`, `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
4
4
 
5
5
  > **Max subscription only.** This tool uses **exclusively** the Claude Max subscription. It strips every environment variable that could route a call through the API and aborts on startup if any are still present. There is no path to API credit billing — see [Safety constraints](#safety-constraints) below.
6
6
 
@@ -37,6 +37,20 @@ code-generator init --template fastapi
37
37
  $EDITOR .code-generator/requirements.md
38
38
  ```
39
39
 
40
+ ### `code-generator optimize [--dry-run] [--force]`
41
+
42
+ Pre-flight rewrite of `.code-generator/requirements.md` into the canonical structure the orchestrator expects: `# Title` → `## Description` → `## Tech Stack` → `## Goals` → `## Scope` (numbered `### N.` subsections with per-section `Acceptance criteria` checklists) → `## Non-goals` → `## Constraints` → `## Global acceptance criteria`.
43
+
44
+ Runs a single Opus 4.6 session with a dedicated prompt, preserves the original intent verbatim when ambiguous (never invents new scope), and writes the rewrite back to disk atomically. The pre-optimize original is saved to `.code-generator/requirements.backup-<UTC-timestamp>.md` so you can always `diff` and recover. The command is stateless — it never reads or writes `state.json` and never calls `gh`.
45
+
46
+ Short-circuits and exits 0 if the file is already canonical. Use `--force` to re-optimize anyway. Use `--dry-run` to print the proposed rewrite to stdout without touching the file or creating a backup.
47
+
48
+ ```bash
49
+ code-generator optimize --dry-run # preview
50
+ code-generator optimize # commit the rewrite
51
+ code-generator generate # then run the pipeline
52
+ ```
53
+
40
54
  ### `code-generator generate [flags]`
41
55
 
42
56
  Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0→7 phase pipeline:
@@ -49,7 +63,9 @@ Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0
49
63
  | 3-4 | Implementation, fresh SDK session per issue (TDD) | Sonnet 4.6 |
50
64
  | 5 | Closure + cross-module review | Opus 4.6 |
51
65
  | 6 | Test suite, max 3 retries on failure | Sonnet 4.6 |
52
- | 7 | Commit message + git add/commit/push | Haiku 4.5 |
66
+ | 7 | Commit message + git add/commit/push | Opus 4.6 |
67
+
68
+ Every phase logs a completion summary with token counts (`in`, `cache_read`, `cache_write`, `out`) and persists them to `state.json`.
53
69
 
54
70
  Flags:
55
71
 
@@ -71,7 +87,7 @@ Run a standalone Opus 4.6 review of the current codebase against the design prin
71
87
 
72
88
  ### `code-generator status`
73
89
 
74
- Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), and the last error.
90
+ Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), per-cycle token consumption columns (`in | cache_read | cache_write | out`), wall-clock elapsed time, and any `last_error` highlighted in red.
75
91
 
76
92
  ## Safety constraints
77
93
 
@@ -84,7 +100,7 @@ The tool enforces eight non-negotiables (see `CLAUDE.md` for the full list):
84
100
  5. **Wait-and-resume rate-limit handling.** Rate limits are not retried with exponential backoff — the tool sleeps until `resets_at + 60s` and resumes the same session. Backoff (10→20→40→80→120s) only applies to non-rate-limit transient errors.
85
101
  6. **Fresh SDK session per issue.** The implementation phase never reuses conversational context across issues — each issue is a `/clear`-equivalent fresh session.
86
102
  7. **Atomic state writes.** `.code-generator/state.json` is updated via `tmp → os.replace(tmp, STATE)` so a crash mid-write cannot corrupt it.
87
- 8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5; Sonnet 4.6 for phases 3/4/6; Haiku 4.5 for phase 7's commit message.
103
+ 8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5/7; Sonnet 4.6 for phases 3/4/6.
88
104
 
89
105
  ## Troubleshooting
90
106
 
@@ -120,9 +136,9 @@ src/code_generator/
120
136
  │ ├── phase3_4_implement.py # TDD loop, fresh session per issue
121
137
  │ ├── phase5_closure.py # closure + fix-issue feedback loop
122
138
  │ ├── phase6_test.py # test runner, max 3 retries
123
- │ ├── phase7_commit.py # Haiku commit message + push with rebase retry
139
+ │ ├── phase7_commit.py # Opus commit message + push with rebase retry
124
140
  │ └── cycle_loop.py # multi-cycle driver
125
- └── commands/ # init, status, generate, review (Typer commands)
141
+ └── commands/ # init, optimize, status, generate, review (Typer commands)
126
142
  ```
127
143
 
128
144
  ## Development
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "claude-code-generator"
7
- version = "0.1.0"
7
+ version = "0.2.1"
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" }
@@ -69,3 +69,7 @@ ignore = []
69
69
  [tool.pytest.ini_options]
70
70
  testpaths = ["tests"]
71
71
  asyncio_mode = "auto"
72
+
73
+ [tool.pyright]
74
+ # Test mocks intentionally use unused parameters to match the production interface signature.
75
+ reportUnusedParameter = "none"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.1.0
3
+ Version: 0.2.1
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
@@ -31,7 +31,7 @@ Dynamic: license-file
31
31
 
32
32
  # code-generator
33
33
 
34
- A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Three commands — `init`, `generate`, `review` — plus `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
34
+ A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Five commands — `init`, `optimize`, `generate`, `review`, `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
35
35
 
36
36
  > **Max subscription only.** This tool uses **exclusively** the Claude Max subscription. It strips every environment variable that could route a call through the API and aborts on startup if any are still present. There is no path to API credit billing — see [Safety constraints](#safety-constraints) below.
37
37
 
@@ -68,6 +68,20 @@ code-generator init --template fastapi
68
68
  $EDITOR .code-generator/requirements.md
69
69
  ```
70
70
 
71
+ ### `code-generator optimize [--dry-run] [--force]`
72
+
73
+ Pre-flight rewrite of `.code-generator/requirements.md` into the canonical structure the orchestrator expects: `# Title` → `## Description` → `## Tech Stack` → `## Goals` → `## Scope` (numbered `### N.` subsections with per-section `Acceptance criteria` checklists) → `## Non-goals` → `## Constraints` → `## Global acceptance criteria`.
74
+
75
+ Runs a single Opus 4.6 session with a dedicated prompt, preserves the original intent verbatim when ambiguous (never invents new scope), and writes the rewrite back to disk atomically. The pre-optimize original is saved to `.code-generator/requirements.backup-<UTC-timestamp>.md` so you can always `diff` and recover. The command is stateless — it never reads or writes `state.json` and never calls `gh`.
76
+
77
+ Short-circuits and exits 0 if the file is already canonical. Use `--force` to re-optimize anyway. Use `--dry-run` to print the proposed rewrite to stdout without touching the file or creating a backup.
78
+
79
+ ```bash
80
+ code-generator optimize --dry-run # preview
81
+ code-generator optimize # commit the rewrite
82
+ code-generator generate # then run the pipeline
83
+ ```
84
+
71
85
  ### `code-generator generate [flags]`
72
86
 
73
87
  Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0→7 phase pipeline:
@@ -80,7 +94,9 @@ Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0
80
94
  | 3-4 | Implementation, fresh SDK session per issue (TDD) | Sonnet 4.6 |
81
95
  | 5 | Closure + cross-module review | Opus 4.6 |
82
96
  | 6 | Test suite, max 3 retries on failure | Sonnet 4.6 |
83
- | 7 | Commit message + git add/commit/push | Haiku 4.5 |
97
+ | 7 | Commit message + git add/commit/push | Opus 4.6 |
98
+
99
+ Every phase logs a completion summary with token counts (`in`, `cache_read`, `cache_write`, `out`) and persists them to `state.json`.
84
100
 
85
101
  Flags:
86
102
 
@@ -102,7 +118,7 @@ Run a standalone Opus 4.6 review of the current codebase against the design prin
102
118
 
103
119
  ### `code-generator status`
104
120
 
105
- Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), and the last error.
121
+ Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), per-cycle token consumption columns (`in | cache_read | cache_write | out`), wall-clock elapsed time, and any `last_error` highlighted in red.
106
122
 
107
123
  ## Safety constraints
108
124
 
@@ -115,7 +131,7 @@ The tool enforces eight non-negotiables (see `CLAUDE.md` for the full list):
115
131
  5. **Wait-and-resume rate-limit handling.** Rate limits are not retried with exponential backoff — the tool sleeps until `resets_at + 60s` and resumes the same session. Backoff (10→20→40→80→120s) only applies to non-rate-limit transient errors.
116
132
  6. **Fresh SDK session per issue.** The implementation phase never reuses conversational context across issues — each issue is a `/clear`-equivalent fresh session.
117
133
  7. **Atomic state writes.** `.code-generator/state.json` is updated via `tmp → os.replace(tmp, STATE)` so a crash mid-write cannot corrupt it.
118
- 8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5; Sonnet 4.6 for phases 3/4/6; Haiku 4.5 for phase 7's commit message.
134
+ 8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5/7; Sonnet 4.6 for phases 3/4/6.
119
135
 
120
136
  ## Troubleshooting
121
137
 
@@ -151,9 +167,9 @@ src/code_generator/
151
167
  │ ├── phase3_4_implement.py # TDD loop, fresh session per issue
152
168
  │ ├── phase5_closure.py # closure + fix-issue feedback loop
153
169
  │ ├── phase6_test.py # test runner, max 3 retries
154
- │ ├── phase7_commit.py # Haiku commit message + push with rebase retry
170
+ │ ├── phase7_commit.py # Opus commit message + push with rebase retry
155
171
  │ └── cycle_loop.py # multi-cycle driver
156
- └── commands/ # init, status, generate, review (Typer commands)
172
+ └── commands/ # init, optimize, status, generate, review (Typer commands)
157
173
  ```
158
174
 
159
175
  ## Development
@@ -10,16 +10,28 @@ src/claude_code_generator.egg-info/top_level.txt
10
10
  src/code_generator/__init__.py
11
11
  src/code_generator/agents.py
12
12
  src/code_generator/cli.py
13
+ src/code_generator/effort.py
13
14
  src/code_generator/env.py
14
- src/code_generator/gh.py
15
+ src/code_generator/git_ops.py
15
16
  src/code_generator/logging_setup.py
17
+ src/code_generator/requirements_structure.py
16
18
  src/code_generator/state.py
17
19
  src/code_generator/commands/__init__.py
20
+ src/code_generator/commands/_detect.py
21
+ src/code_generator/commands/_dispatch.py
22
+ src/code_generator/commands/_resume.py
18
23
  src/code_generator/commands/generate.py
19
24
  src/code_generator/commands/init.py
25
+ src/code_generator/commands/optimize.py
20
26
  src/code_generator/commands/review.py
21
27
  src/code_generator/commands/status.py
28
+ src/code_generator/gh/__init__.py
29
+ src/code_generator/gh/core.py
30
+ src/code_generator/gh/issues.py
31
+ src/code_generator/gh/labels.py
32
+ src/code_generator/gh/milestones.py
22
33
  src/code_generator/orchestrator/__init__.py
34
+ src/code_generator/orchestrator/_comments.py
23
35
  src/code_generator/orchestrator/cycle_loop.py
24
36
  src/code_generator/orchestrator/phase0_complexity.py
25
37
  src/code_generator/orchestrator/phase1_plan.py
@@ -29,6 +41,7 @@ src/code_generator/orchestrator/phase5_closure.py
29
41
  src/code_generator/orchestrator/phase6_test.py
30
42
  src/code_generator/orchestrator/phase7_commit.py
31
43
  src/code_generator/prompts/__init__.py
44
+ src/code_generator/prompts/prompt-optimize-requirements.md
32
45
  src/code_generator/prompts/prompt-phase-0-complexity.md
33
46
  src/code_generator/prompts/prompt-phase-1-planning.md
34
47
  src/code_generator/prompts/prompt-phase-2-issue-review.md
@@ -38,10 +51,15 @@ src/code_generator/prompts/prompt-phase-6-test.md
38
51
  src/code_generator/prompts/prompt-phase-7-commit.md
39
52
  src/code_generator/prompts/prompt-review.md
40
53
  src/code_generator/runner/__init__.py
54
+ src/code_generator/runner/message_parsing.py
55
+ src/code_generator/runner/options.py
56
+ src/code_generator/runner/protocol.py
41
57
  src/code_generator/runner/rate_limit.py
42
58
  src/code_generator/runner/retry.py
43
59
  src/code_generator/runner/sdk_runner.py
44
60
  src/code_generator/runner/subprocess_runner.py
61
+ src/code_generator/runner/types.py
62
+ src/code_generator/runner/utils.py
45
63
  src/code_generator/templates/__init__.py
46
64
  src/code_generator/templates/angular.md
47
65
  src/code_generator/templates/base.md
@@ -51,13 +69,26 @@ src/code_generator/templates/fullstack.md
51
69
  src/code_generator/templates/nestjs.md
52
70
  src/code_generator/templates/python-cli.md
53
71
  tests/test_agents.py
72
+ tests/test_comments.py
73
+ tests/test_commit_message.py
54
74
  tests/test_cycle_loop.py
75
+ tests/test_cycle_loop_multicycle.py
76
+ tests/test_delta_planning.py
77
+ tests/test_detect.py
78
+ tests/test_effort.py
55
79
  tests/test_env.py
56
80
  tests/test_generate.py
57
81
  tests/test_generate_resume.py
58
82
  tests/test_gh.py
83
+ tests/test_gh_labels.py
84
+ tests/test_gh_milestones.py
85
+ tests/test_gh_submodules.py
86
+ tests/test_git_ops.py
59
87
  tests/test_init.py
60
88
  tests/test_logging_setup.py
89
+ tests/test_message_parsing.py
90
+ tests/test_optimize.py
91
+ tests/test_options.py
61
92
  tests/test_phase0.py
62
93
  tests/test_phase1.py
63
94
  tests/test_phase2.py
@@ -65,10 +96,16 @@ tests/test_phase3_4.py
65
96
  tests/test_phase5.py
66
97
  tests/test_phase6.py
67
98
  tests/test_phase7.py
99
+ tests/test_phase_token_logging.py
68
100
  tests/test_prompts.py
69
101
  tests/test_rate_limit.py
102
+ tests/test_requirements_structure.py
70
103
  tests/test_retry.py
71
104
  tests/test_review.py
105
+ tests/test_runner_protocol.py
106
+ tests/test_runner_protocol_annotations.py
107
+ tests/test_runner_types.py
108
+ tests/test_runner_utils.py
72
109
  tests/test_sdk_runner.py
73
110
  tests/test_state.py
74
111
  tests/test_status.py
@@ -1,3 +1,3 @@
1
1
  """code-generator: orchestrator CLI for end-to-end project generation."""
2
2
 
3
- __version__ = "0.1.0"
3
+ __version__ = "0.2.1"
@@ -11,6 +11,7 @@ import typer
11
11
  import code_generator
12
12
  from code_generator.commands.generate import generate_command
13
13
  from code_generator.commands.init import init_command
14
+ from code_generator.commands.optimize import optimize_command
14
15
  from code_generator.commands.review import review_command
15
16
  from code_generator.commands.status import status_command
16
17
 
@@ -46,4 +47,5 @@ def root(
46
47
  app.command(name="init")(init_command)
47
48
  app.command(name="status")(status_command)
48
49
  app.command(name="generate")(generate_command)
50
+ app.command(name="optimize")(optimize_command)
49
51
  app.command(name="review")(review_command)
@@ -0,0 +1,59 @@
1
+ """Re-run detection for the generate command.
2
+
3
+ Compares the current requirements.md hash against the stored hash in state to
4
+ decide the correct execution path on startup.
5
+
6
+ The sole exported function is a pure function (no I/O) so it is trivially
7
+ unit-testable.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from typing import TYPE_CHECKING, Literal
13
+
14
+ if TYPE_CHECKING:
15
+ from code_generator import state as state_module
16
+
17
+ RunMode = Literal["first-run", "resume", "no-op", "delta"]
18
+
19
+ __all__ = ["RunMode", "detect_run_mode"]
20
+
21
+
22
+ def _run_is_complete(state: state_module.State) -> bool:
23
+ """Return True when the generation run is fully complete.
24
+
25
+ Single mode: complete when phase == 7 (final commit phase).
26
+ Multi-cycle mode: complete when every cycle has status "completed"
27
+ and at least one cycle exists.
28
+ """
29
+ if state.mode == "multi-cycle":
30
+ return len(state.cycles) > 0 and all(c.status == "completed" for c in state.cycles)
31
+ return state.phase == 7
32
+
33
+
34
+ def detect_run_mode(state: state_module.State, current_hash: str) -> RunMode:
35
+ """Determine how the generate command should proceed given existing state.
36
+
37
+ This is a pure function: it reads ``state`` and ``current_hash`` and
38
+ returns a decision literal. It never performs I/O.
39
+
40
+ Decision rules (evaluated in order):
41
+ 1. No stored hash → ``"first-run"`` (treat as a brand-new run)
42
+ 2. Hashes differ → ``"delta"`` (requirements changed)
43
+ 3. Run complete → ``"no-op"`` (nothing left to do)
44
+ 4. Otherwise → ``"resume"`` (same requirements, incomplete run)
45
+
46
+ Args:
47
+ state: Loaded root state (may have requirements_hash=None for old runs).
48
+ current_hash: SHA-256 hex digest of the current requirements.md.
49
+
50
+ Returns:
51
+ One of ``"first-run"``, ``"resume"``, ``"no-op"``, or ``"delta"``.
52
+ """
53
+ if state.requirements_hash is None:
54
+ return "first-run"
55
+ if state.requirements_hash != current_hash:
56
+ return "delta"
57
+ if _run_is_complete(state):
58
+ return "no-op"
59
+ return "resume"