claude-code-generator 0.2.2__tar.gz → 0.2.4__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 (115) hide show
  1. {claude_code_generator-0.2.2/src/claude_code_generator.egg-info → claude_code_generator-0.2.4}/PKG-INFO +1 -1
  2. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/pyproject.toml +1 -1
  3. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4/src/claude_code_generator.egg-info}/PKG-INFO +1 -1
  4. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/__init__.py +1 -1
  5. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase2_review.py +13 -0
  6. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase5_closure.py +1 -1
  7. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/state.py +2 -0
  8. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase2.py +74 -0
  9. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/LICENSE +0 -0
  10. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/README.md +0 -0
  11. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/setup.cfg +0 -0
  12. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/claude_code_generator.egg-info/SOURCES.txt +0 -0
  13. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
  14. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
  15. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/claude_code_generator.egg-info/requires.txt +0 -0
  16. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/claude_code_generator.egg-info/top_level.txt +0 -0
  17. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/agents.py +0 -0
  18. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/cli.py +0 -0
  19. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/__init__.py +0 -0
  20. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/_detect.py +0 -0
  21. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/_dispatch.py +0 -0
  22. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/_resume.py +0 -0
  23. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/generate.py +0 -0
  24. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/init.py +0 -0
  25. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/optimize.py +0 -0
  26. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/review.py +0 -0
  27. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/commands/status.py +0 -0
  28. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/effort.py +0 -0
  29. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/env.py +0 -0
  30. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/gh/__init__.py +0 -0
  31. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/gh/core.py +0 -0
  32. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/gh/issues.py +0 -0
  33. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/gh/labels.py +0 -0
  34. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/gh/milestones.py +0 -0
  35. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/git_ops.py +0 -0
  36. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/logging_setup.py +0 -0
  37. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/__init__.py +0 -0
  38. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/_comments.py +0 -0
  39. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/cycle_loop.py +0 -0
  40. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase0_complexity.py +0 -0
  41. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase1_plan.py +0 -0
  42. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase3_4_implement.py +0 -0
  43. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase6_test.py +0 -0
  44. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/orchestrator/phase7_commit.py +0 -0
  45. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/__init__.py +0 -0
  46. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-optimize-requirements.md +0 -0
  47. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-0-complexity.md +0 -0
  48. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-1-planning.md +0 -0
  49. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-2-issue-review.md +0 -0
  50. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-3-implementation.md +0 -0
  51. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-5-final-review.md +0 -0
  52. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
  53. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-phase-7-commit.md +0 -0
  54. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/prompts/prompt-review.md +0 -0
  55. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/requirements_structure.py +0 -0
  56. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/__init__.py +0 -0
  57. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/message_parsing.py +0 -0
  58. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/options.py +0 -0
  59. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/protocol.py +0 -0
  60. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/rate_limit.py +0 -0
  61. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/retry.py +0 -0
  62. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/sdk_runner.py +0 -0
  63. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/subprocess_runner.py +0 -0
  64. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/types.py +0 -0
  65. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/runner/utils.py +0 -0
  66. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/__init__.py +0 -0
  67. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/angular.md +0 -0
  68. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/base.md +0 -0
  69. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/fastapi.md +0 -0
  70. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/finance.md +0 -0
  71. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/fullstack.md +0 -0
  72. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/nestjs.md +0 -0
  73. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/src/code_generator/templates/python-cli.md +0 -0
  74. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_agents.py +0 -0
  75. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_comments.py +0 -0
  76. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_commit_message.py +0 -0
  77. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_cycle_loop.py +0 -0
  78. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_cycle_loop_multicycle.py +0 -0
  79. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_delta_planning.py +0 -0
  80. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_detect.py +0 -0
  81. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_effort.py +0 -0
  82. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_env.py +0 -0
  83. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_generate.py +0 -0
  84. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_generate_resume.py +0 -0
  85. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_gh.py +0 -0
  86. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_gh_labels.py +0 -0
  87. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_gh_milestones.py +0 -0
  88. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_gh_submodules.py +0 -0
  89. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_git_ops.py +0 -0
  90. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_init.py +0 -0
  91. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_logging_setup.py +0 -0
  92. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_message_parsing.py +0 -0
  93. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_optimize.py +0 -0
  94. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_options.py +0 -0
  95. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase0.py +0 -0
  96. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase1.py +0 -0
  97. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase3_4.py +0 -0
  98. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase5.py +0 -0
  99. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase6.py +0 -0
  100. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase7.py +0 -0
  101. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_phase_token_logging.py +0 -0
  102. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_prompts.py +0 -0
  103. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_rate_limit.py +0 -0
  104. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_requirements_structure.py +0 -0
  105. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_retry.py +0 -0
  106. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_review.py +0 -0
  107. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_runner_protocol.py +0 -0
  108. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_runner_protocol_annotations.py +0 -0
  109. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_runner_types.py +0 -0
  110. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_runner_utils.py +0 -0
  111. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_sdk_runner.py +0 -0
  112. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_state.py +0 -0
  113. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_status.py +0 -0
  114. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/tests/test_subprocess_runner.py +0 -0
  115. {claude_code_generator-0.2.2 → claude_code_generator-0.2.4}/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.2.2
3
+ Version: 0.2.4
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "claude-code-generator"
7
- version = "0.2.2"
7
+ version = "0.2.4"
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.2.2
3
+ Version: 0.2.4
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
@@ -1,3 +1,3 @@
1
1
  """code-generator: orchestrator CLI for end-to-end project generation."""
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.2.4"
@@ -63,6 +63,14 @@ async def run(
63
63
  if issue.status != "open":
64
64
  continue
65
65
 
66
+ # Skip issues already reviewed in a prior run. Phase 2 never closes
67
+ # the issue (only Phase 3/4 does), so status alone cannot tell us
68
+ # whether the review already ran. Without this check, --continue
69
+ # re-reviews every open issue from scratch on every resume.
70
+ if issue.reviewed:
71
+ logger.info("Phase 2: issue #%d already reviewed — skipping.", issue.number)
72
+ continue
73
+
66
74
  logger.info("Phase 2: reviewing issue #%d (agent=%s).", issue.number, issue.agent)
67
75
 
68
76
  comments_section = fetch_formatted_comments(issue.number, logger)
@@ -137,6 +145,11 @@ async def run(
137
145
  phase_total += issue_usage
138
146
 
139
147
  if reviewed:
148
+ # Persist the per-issue reviewed flag immediately so a crash (or
149
+ # --continue after a rate-limit pause) does not re-review work
150
+ # that already succeeded.
151
+ issue.reviewed = True
152
+ save_state(state_path, state)
140
153
  logger.info("Phase 2: issue #%d reviewed.", issue.number)
141
154
 
142
155
  target = cycle if cycle is not None else state
@@ -191,7 +191,7 @@ async def run(
191
191
  effort=effort_level,
192
192
  allowed_tools=["Read", "Bash", "Glob", "Grep"],
193
193
  cwd=str(project_dir),
194
- max_turns=30,
194
+ max_turns=80,
195
195
  )
196
196
 
197
197
  result = await rate_limit.main_loop(
@@ -27,6 +27,7 @@ class IssueState:
27
27
  status: Literal["open", "closed"]
28
28
  agent: str
29
29
  labels: list[str] = field(default_factory=list)
30
+ reviewed: bool = False
30
31
 
31
32
 
32
33
  @dataclass
@@ -112,6 +113,7 @@ def _issue_from_dict(d: dict) -> IssueState: # type: ignore[type-arg]
112
113
  status=d["status"],
113
114
  agent=d["agent"],
114
115
  labels=d.get("labels", []),
116
+ reviewed=d.get("reviewed", False),
115
117
  )
116
118
 
117
119
 
@@ -504,3 +504,77 @@ class TestPhase2TokenAccumulation:
504
504
 
505
505
  assert cycle.token_usage.get("phase2") == issue_usage
506
506
  assert "phase2" not in st.token_usage
507
+
508
+ @pytest.mark.asyncio
509
+ async def test_skips_already_reviewed_issues(self, tmp_path: Path) -> None:
510
+ """Issues with reviewed=True from a prior --continue run must be skipped."""
511
+ state_dir = tmp_path / ".code-generator"
512
+ state_dir.mkdir(parents=True, exist_ok=True)
513
+ st = _state.load_state(state_dir / "missing.json")
514
+ st.issues = [
515
+ _state.IssueState(number=1, status="open", agent="python-pro", reviewed=True),
516
+ _state.IssueState(number=2, status="open", agent="python-pro", reviewed=False),
517
+ _state.IssueState(number=3, status="open", agent="python-pro", reviewed=True),
518
+ ]
519
+ _state.save_state(state_dir / "state.json", st)
520
+
521
+ reviewed_numbers: list[int] = []
522
+
523
+ async def fake_with_backoff(factory, *, breaker, **kw):
524
+ await factory()
525
+
526
+ async def fake_main_loop(runner, prompt, options, *, state_path, logger, **kw):
527
+ return _make_run_result()
528
+
529
+ with (
530
+ patch.object(phase2_review.rate_limit, "main_loop", side_effect=fake_main_loop),
531
+ patch.object(phase2_review.retry, "with_backoff", side_effect=fake_with_backoff),
532
+ patch.object(phase2_review.gh, "view_issue", return_value={"comments": []}),
533
+ patch.object(phase2_review, "load_prompt", side_effect=lambda *a, **k: "prompt"),
534
+ patch.object(
535
+ phase2_review,
536
+ "fetch_formatted_comments",
537
+ side_effect=lambda n, logger: reviewed_numbers.append(n) or "",
538
+ ),
539
+ ):
540
+ await phase2_review.run(
541
+ st,
542
+ None,
543
+ tmp_path,
544
+ runner_module=MagicMock(),
545
+ logger=logging.getLogger("test"),
546
+ )
547
+
548
+ # Only issue #2 is actually reviewed; #1 and #3 are skipped.
549
+ assert reviewed_numbers == [2]
550
+ # Issue #2 is now marked reviewed; #1 and #3 stay reviewed.
551
+ assert all(i.reviewed for i in st.issues)
552
+
553
+ @pytest.mark.asyncio
554
+ async def test_successful_review_persists_reviewed_flag(self, tmp_path: Path) -> None:
555
+ """A successful Phase 2 review must persist reviewed=True to state.json."""
556
+ state = _make_state_with_issues(tmp_path, [42])
557
+ state_path = tmp_path / ".code-generator" / "state.json"
558
+
559
+ async def fake_with_backoff(factory, *, breaker, **kw):
560
+ await factory()
561
+
562
+ async def fake_main_loop(runner, prompt, options, *, state_path, logger, **kw):
563
+ return _make_run_result()
564
+
565
+ with (
566
+ patch.object(phase2_review.rate_limit, "main_loop", side_effect=fake_main_loop),
567
+ patch.object(phase2_review.retry, "with_backoff", side_effect=fake_with_backoff),
568
+ patch.object(phase2_review.gh, "view_issue", return_value={"comments": []}),
569
+ ):
570
+ await phase2_review.run(
571
+ state,
572
+ None,
573
+ tmp_path,
574
+ runner_module=MagicMock(),
575
+ logger=logging.getLogger("test"),
576
+ )
577
+
578
+ # Reloaded state must show reviewed=True so a subsequent --continue skips it.
579
+ reloaded = _state.load_state(state_path)
580
+ assert reloaded.issues[0].reviewed is True