claude-code-generator 0.4.11__tar.gz → 0.4.12__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.
- {claude_code_generator-0.4.11/src/claude_code_generator.egg-info → claude_code_generator-0.4.12}/PKG-INFO +1 -1
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/pyproject.toml +1 -1
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12/src/claude_code_generator.egg-info}/PKG-INFO +1 -1
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/__init__.py +1 -1
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase1_plan.py +95 -21
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase1.py +97 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/LICENSE +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/README.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/setup.cfg +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/claude_code_generator.egg-info/SOURCES.txt +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/claude_code_generator.egg-info/requires.txt +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/claude_code_generator.egg-info/top_level.txt +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/agents.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/cli.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/__init__.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_bench_io.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_crash_recovery.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_detect.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_dispatch.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_resume.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_validators.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/bench.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/bench_compare.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/bench_export.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/generate.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/init.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/optimize.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/review.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/status.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/effort.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/env.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/__init__.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/core.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/issues.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/labels.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/milestones.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/git_ops.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/logging_setup.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/memory.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/__init__.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/_client_lifecycle.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/_comments.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/_memory_writers.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/_phase5_precommit.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/cycle_loop.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/cycle_prompts.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/ollama_budget.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase0_complexity.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase2_review.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase3_4_implement.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase5_closure.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase6_test.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/orchestrator/phase7_commit.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/preflight.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/__init__.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/hashes.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-cycle-specializer.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-optimize-requirements.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-0-complexity.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-1-planning.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-2-batch-review.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-2-issue-review.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-3-implementation.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-5-final-review.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-phase-7-commit.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/prompt-review.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/repo_info.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/repomap.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/requirements_structure.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/__init__.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/_telemetry.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/batch.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/fake_runner.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/mcp.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/message_parsing.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/options.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/protocol.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/rate_limit.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/retry.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/sdk_runner.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/soft_reset.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/state_guard.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/subprocess_runner.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/types.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/utils.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/state.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/state_retention.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/__init__.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/angular.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/base.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/fastapi.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/finance.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/fullstack.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/nestjs.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/python-cli.md +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_agents.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_bench.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_bench_compare.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_bench_export.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_bench_fixture.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_bench_regression.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_changelog.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_claude_md.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_client_lifecycle.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_comments.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_commit_message.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_crash_recovery.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_cycle_loop.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_cycle_loop_multicycle.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_cycle_ollama_model.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_cycle_prompts.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_delta_planning.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_dependencies.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_detect.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_docs_no_default_max_turns.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_docs_ollama_model_guide.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_docs_ollama_pro.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_effective_model_routing.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_effort.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_env.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_generate.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_generate_ollama.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_generate_resume.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_gh.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_gh_labels.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_gh_milestones.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_gh_repo_threading.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_gh_submodules.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_git_ops.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_init.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_logging_setup.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_max_turns_cli_flag.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_mcp.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_memory.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_memory_writers.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_message_parsing.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_no_max_turns_in_call_sites.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_no_max_turns_literal.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_non_goals_grep_guard.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_ollama_budget.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_ollama_rate_limit.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_optimize.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_options.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase0.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase2.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase2_batch.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase3_4.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase5.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase5_precommit.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase6.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase7.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase_mcp_regression.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase_token_logging.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_preflight.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_preflight_ollama.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_prompt_drift.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_prompt_prefix_snapshots.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_prompt_prefix_stability.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_prompts.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_rate_limit.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_repo_info.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_repomap.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_requirements_structure.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_retry.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_review.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_runner_protocol.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_runner_protocol_annotations.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_runner_types.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_runner_utils.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_sdk_runner.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_sdk_runner_shared.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_session_mode.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_state.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_state_guard.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_state_retention.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_status.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_subprocess_runner.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_telemetry.py +0 -0
- {claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_version.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "claude-code-generator"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.12"
|
|
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" }
|
|
@@ -116,6 +116,47 @@ _PHASE1_DEFAULT_MODEL = "claude-opus-4-7"
|
|
|
116
116
|
# CLAUDE.md invariant #8; overridden via ``effective_model`` on Ollama — #219.
|
|
117
117
|
|
|
118
118
|
|
|
119
|
+
_PHASE1_MAX_ATTEMPTS = 3
|
|
120
|
+
"""Max planning attempts before surfacing ``Phase1NoIssuesError`` (0.4.12).
|
|
121
|
+
|
|
122
|
+
Weak open models on the Ollama codepath often respond with prose describing
|
|
123
|
+
the plan instead of invoking ``gh issue create`` via the Bash tool. A single
|
|
124
|
+
stricter re-prompt is usually enough to unblock them without operator
|
|
125
|
+
intervention.
|
|
126
|
+
"""
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
_PHASE1_RETRY_NUDGE = (
|
|
130
|
+
"Your previous attempt finished without creating any GitHub issues. "
|
|
131
|
+
"This is a CRITICAL failure. You MUST use the Bash tool to invoke "
|
|
132
|
+
"`gh issue create` for each issue right now. Do NOT output markdown "
|
|
133
|
+
"or prose describing the plan — every planned issue must become a "
|
|
134
|
+
"real GitHub issue via `gh issue create ... --milestone "
|
|
135
|
+
'"{MILESTONE}" --assignee @me --label "..."`. Once you have called '
|
|
136
|
+
"`gh issue create` for every planned issue, print a one-line summary "
|
|
137
|
+
"per issue and stop.\n\n"
|
|
138
|
+
"The original instructions follow.\n\n"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _accumulate_usage(
|
|
143
|
+
total: _state.TokenUsage | None,
|
|
144
|
+
delta: _state.TokenUsage,
|
|
145
|
+
) -> _state.TokenUsage:
|
|
146
|
+
"""Sum two TokenUsage records field-by-field across Phase 1 attempts."""
|
|
147
|
+
from code_generator.runner.types import TokenUsage
|
|
148
|
+
|
|
149
|
+
if total is None:
|
|
150
|
+
return delta
|
|
151
|
+
return TokenUsage(
|
|
152
|
+
input=total.input + delta.input,
|
|
153
|
+
output=total.output + delta.output,
|
|
154
|
+
cache_read=total.cache_read + delta.cache_read,
|
|
155
|
+
cache_write=total.cache_write + delta.cache_write,
|
|
156
|
+
num_turns=total.num_turns + delta.num_turns,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
119
160
|
def _load_specialized_prompt(
|
|
120
161
|
project_dir: Path,
|
|
121
162
|
state: State,
|
|
@@ -249,28 +290,56 @@ async def run(
|
|
|
249
290
|
**max_turns_kwargs(max_turns),
|
|
250
291
|
)
|
|
251
292
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
293
|
+
# Up to _PHASE1_MAX_ATTEMPTS attempts: the first with the normal
|
|
294
|
+
# prompt, subsequent attempts prefixed with a stricter nudge that
|
|
295
|
+
# tells the model to use the Bash tool to call ``gh issue create``
|
|
296
|
+
# right now. Weak open models on the Ollama codepath commonly
|
|
297
|
+
# respond with prose on the first turn; the nudge recovers most
|
|
298
|
+
# of those cases without operator intervention (0.4.12).
|
|
299
|
+
issue_states: list[_state.IssueState] = []
|
|
300
|
+
total_usage = result = None # type: ignore[assignment]
|
|
301
|
+
attempt_prompt = prompt
|
|
302
|
+
effective_model_name = effective_model or _PHASE1_DEFAULT_MODEL
|
|
303
|
+
for attempt in range(1, _PHASE1_MAX_ATTEMPTS + 1):
|
|
304
|
+
result = await rate_limit.main_loop(
|
|
305
|
+
runner_module,
|
|
306
|
+
attempt_prompt,
|
|
307
|
+
options,
|
|
308
|
+
state_path=state_path,
|
|
309
|
+
logger=logger,
|
|
310
|
+
)
|
|
311
|
+
total_usage = _accumulate_usage(total_usage, result.usage)
|
|
259
312
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
313
|
+
raw_issues = gh.list_issues(
|
|
314
|
+
repo,
|
|
315
|
+
milestone=milestone_title,
|
|
316
|
+
state="all",
|
|
317
|
+
)
|
|
318
|
+
issue_states = _build_issue_states(raw_issues)
|
|
319
|
+
if issue_states:
|
|
320
|
+
break
|
|
321
|
+
|
|
322
|
+
if attempt >= _PHASE1_MAX_ATTEMPTS:
|
|
323
|
+
break
|
|
324
|
+
|
|
325
|
+
logger.warning(
|
|
326
|
+
"Phase 1 attempt %d/%d: model returned without creating any "
|
|
327
|
+
"GitHub issues. Re-prompting with a stricter nudge.",
|
|
328
|
+
attempt,
|
|
329
|
+
_PHASE1_MAX_ATTEMPTS,
|
|
330
|
+
)
|
|
331
|
+
nudge = _PHASE1_RETRY_NUDGE.replace("{MILESTONE}", milestone_title or "")
|
|
332
|
+
attempt_prompt = nudge + prompt
|
|
267
333
|
|
|
268
334
|
if not issue_states:
|
|
269
335
|
raise Phase1NoIssuesError(
|
|
270
|
-
"Phase 1 finished without creating any GitHub issues
|
|
271
|
-
"
|
|
272
|
-
"
|
|
273
|
-
"
|
|
336
|
+
f"Phase 1 finished without creating any GitHub issues after "
|
|
337
|
+
f"{_PHASE1_MAX_ATTEMPTS} attempts (model={effective_model_name!r}). "
|
|
338
|
+
"The model likely responded with prose instead of invoking "
|
|
339
|
+
"`gh issue create` via the Bash tool. Inspect "
|
|
340
|
+
".code-generator/logs/phase1.log for the tool-call trace, "
|
|
341
|
+
"try a stronger model, or simplify the cycle scope in "
|
|
342
|
+
"requirements.md and re-run."
|
|
274
343
|
)
|
|
275
344
|
|
|
276
345
|
target = cycle if cycle is not None else state
|
|
@@ -278,12 +347,17 @@ async def run(
|
|
|
278
347
|
cycle.issues = issue_states
|
|
279
348
|
else:
|
|
280
349
|
state.issues = issue_states
|
|
281
|
-
|
|
350
|
+
# Persist the accumulated usage across all attempts (not just the last).
|
|
351
|
+
target.token_usage["phase1"] = total_usage if total_usage is not None else result.usage
|
|
282
352
|
if hasattr(target, "cache_telemetry"):
|
|
283
|
-
accumulate_telemetry(
|
|
353
|
+
accumulate_telemetry(
|
|
354
|
+
target.cache_telemetry,
|
|
355
|
+
target.token_usage["phase1"],
|
|
356
|
+
result.wall_seconds,
|
|
357
|
+
)
|
|
284
358
|
|
|
285
359
|
_state.save_state(state_path, state)
|
|
286
|
-
log_phase_usage(logger, 1,
|
|
360
|
+
log_phase_usage(logger, 1, target.token_usage["phase1"])
|
|
287
361
|
logger.info("Phase 1: %d issues created.", len(issue_states))
|
|
288
362
|
|
|
289
363
|
except Exception:
|
|
@@ -414,9 +414,71 @@ class TestBuildIssueStates:
|
|
|
414
414
|
class TestPhase1NoIssuesError:
|
|
415
415
|
@pytest.mark.asyncio
|
|
416
416
|
async def test_raises_when_list_issues_returns_empty(self, tmp_path: Path) -> None:
|
|
417
|
+
"""Three consecutive empty listings → Phase1NoIssuesError with model name."""
|
|
417
418
|
state = _make_state(tmp_path)
|
|
419
|
+
call_count = 0
|
|
418
420
|
|
|
419
421
|
async def fake_main_loop(runner, prompt, options, *, state_path, logger, **kw):
|
|
422
|
+
nonlocal call_count
|
|
423
|
+
call_count += 1
|
|
424
|
+
return _make_run_result()
|
|
425
|
+
|
|
426
|
+
with (
|
|
427
|
+
patch.object(phase1_plan.rate_limit, "main_loop", side_effect=fake_main_loop),
|
|
428
|
+
patch.object(phase1_plan.gh, "ensure_standard_labels"),
|
|
429
|
+
patch.object(phase1_plan.gh, "list_issues", return_value=[]),
|
|
430
|
+
):
|
|
431
|
+
with pytest.raises(phase1_plan.Phase1NoIssuesError, match="3 attempts"):
|
|
432
|
+
await phase1_plan.run(
|
|
433
|
+
state,
|
|
434
|
+
None,
|
|
435
|
+
tmp_path,
|
|
436
|
+
runner_module=MagicMock(),
|
|
437
|
+
logger=logging.getLogger("test"),
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
assert call_count == phase1_plan._PHASE1_MAX_ATTEMPTS
|
|
441
|
+
|
|
442
|
+
@pytest.mark.asyncio
|
|
443
|
+
async def test_retry_succeeds_after_first_empty_attempt(self, tmp_path: Path) -> None:
|
|
444
|
+
"""If the first attempt created 0 issues but the second populates them, no raise."""
|
|
445
|
+
state = _make_state(tmp_path)
|
|
446
|
+
call_count = 0
|
|
447
|
+
# First call → empty list; second call → real issues.
|
|
448
|
+
listings = [[], _raw_issues([1, 2])]
|
|
449
|
+
|
|
450
|
+
async def fake_main_loop(runner, prompt, options, *, state_path, logger, **kw):
|
|
451
|
+
nonlocal call_count
|
|
452
|
+
call_count += 1
|
|
453
|
+
return _make_run_result()
|
|
454
|
+
|
|
455
|
+
def fake_list_issues(*_a, **_kw):
|
|
456
|
+
return listings[min(call_count - 1, len(listings) - 1)]
|
|
457
|
+
|
|
458
|
+
with (
|
|
459
|
+
patch.object(phase1_plan.rate_limit, "main_loop", side_effect=fake_main_loop),
|
|
460
|
+
patch.object(phase1_plan.gh, "ensure_standard_labels"),
|
|
461
|
+
patch.object(phase1_plan.gh, "list_issues", side_effect=fake_list_issues),
|
|
462
|
+
):
|
|
463
|
+
await phase1_plan.run(
|
|
464
|
+
state,
|
|
465
|
+
None,
|
|
466
|
+
tmp_path,
|
|
467
|
+
runner_module=MagicMock(),
|
|
468
|
+
logger=logging.getLogger("test"),
|
|
469
|
+
)
|
|
470
|
+
|
|
471
|
+
assert call_count == 2
|
|
472
|
+
assert len(state.issues) == 2
|
|
473
|
+
|
|
474
|
+
@pytest.mark.asyncio
|
|
475
|
+
async def test_retry_prompt_includes_strict_nudge(self, tmp_path: Path) -> None:
|
|
476
|
+
"""Second attempt's prompt must be prefixed with the stricter nudge."""
|
|
477
|
+
state = _make_state(tmp_path)
|
|
478
|
+
captured_prompts: list[str] = []
|
|
479
|
+
|
|
480
|
+
async def fake_main_loop(runner, prompt, options, *, state_path, logger, **kw):
|
|
481
|
+
captured_prompts.append(prompt)
|
|
420
482
|
return _make_run_result()
|
|
421
483
|
|
|
422
484
|
with (
|
|
@@ -433,6 +495,41 @@ class TestPhase1NoIssuesError:
|
|
|
433
495
|
logger=logging.getLogger("test"),
|
|
434
496
|
)
|
|
435
497
|
|
|
498
|
+
assert len(captured_prompts) == phase1_plan._PHASE1_MAX_ATTEMPTS
|
|
499
|
+
# First prompt is the plain Phase 1 prompt.
|
|
500
|
+
assert (
|
|
501
|
+
"Your previous attempt finished without creating any GitHub issues"
|
|
502
|
+
not in (captured_prompts[0])
|
|
503
|
+
)
|
|
504
|
+
# Subsequent prompts carry the stricter nudge prefix.
|
|
505
|
+
for retry_prompt in captured_prompts[1:]:
|
|
506
|
+
assert retry_prompt.startswith(
|
|
507
|
+
"Your previous attempt finished without creating any GitHub issues"
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
@pytest.mark.asyncio
|
|
511
|
+
async def test_error_message_names_effective_model(self, tmp_path: Path) -> None:
|
|
512
|
+
"""Ollama path: final error text must reference the operator-supplied tag."""
|
|
513
|
+
state = _make_state(tmp_path)
|
|
514
|
+
|
|
515
|
+
async def fake_main_loop(runner, prompt, options, *, state_path, logger, **kw):
|
|
516
|
+
return _make_run_result()
|
|
517
|
+
|
|
518
|
+
with (
|
|
519
|
+
patch.object(phase1_plan.rate_limit, "main_loop", side_effect=fake_main_loop),
|
|
520
|
+
patch.object(phase1_plan.gh, "ensure_standard_labels"),
|
|
521
|
+
patch.object(phase1_plan.gh, "list_issues", return_value=[]),
|
|
522
|
+
):
|
|
523
|
+
with pytest.raises(phase1_plan.Phase1NoIssuesError, match="glm-5.1:cloud"):
|
|
524
|
+
await phase1_plan.run(
|
|
525
|
+
state,
|
|
526
|
+
None,
|
|
527
|
+
tmp_path,
|
|
528
|
+
runner_module=MagicMock(),
|
|
529
|
+
logger=logging.getLogger("test"),
|
|
530
|
+
effective_model="glm-5.1:cloud",
|
|
531
|
+
)
|
|
532
|
+
|
|
436
533
|
|
|
437
534
|
# ---------------------------------------------------------------------------
|
|
438
535
|
# Phase 1 idempotency — AC from issue #134
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_detect.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/_resume.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/bench.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/init.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/review.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/commands/status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/issues.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/labels.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/gh/milestones.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/logging_setup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/preflight.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/__init__.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/prompts/hashes.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/repo_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/batch.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/mcp.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/options.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/protocol.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/retry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/types.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/runner/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/state_retention.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/base.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/src/code_generator/templates/nestjs.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_bench_regression.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_client_lifecycle.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_cycle_loop_multicycle.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_cycle_ollama_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_docs_ollama_model_guide.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_effective_model_routing.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_gh_repo_threading.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_max_turns_cli_flag.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_no_max_turns_literal.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_non_goals_grep_guard.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_ollama_rate_limit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase5_precommit.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase_mcp_regression.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_phase_token_logging.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_preflight_ollama.py
RENAMED
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_prompt_prefix_snapshots.py
RENAMED
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_prompt_prefix_stability.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_requirements_structure.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_sdk_runner_shared.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_generator-0.4.11 → claude_code_generator-0.4.12}/tests/test_subprocess_runner.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|