claude-code-generator 0.6.1__tar.gz → 0.6.2__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 (274) hide show
  1. {claude_code_generator-0.6.1/src/claude_code_generator.egg-info → claude_code_generator-0.6.2}/PKG-INFO +1 -1
  2. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/pyproject.toml +1 -1
  3. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2/src/claude_code_generator.egg-info}/PKG-INFO +1 -1
  4. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/claude_code_generator.egg-info/SOURCES.txt +1 -0
  5. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/__init__.py +1 -1
  6. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase6_5_verify.py +80 -6
  7. claude_code_generator-0.6.2/tests/test_phase6_5_port_isolation.py +87 -0
  8. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/LICENSE +0 -0
  9. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/README.md +0 -0
  10. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/setup.cfg +0 -0
  11. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/claude_code_generator.egg-info/dependency_links.txt +0 -0
  12. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/claude_code_generator.egg-info/entry_points.txt +0 -0
  13. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/claude_code_generator.egg-info/requires.txt +0 -0
  14. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/claude_code_generator.egg-info/top_level.txt +0 -0
  15. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/agents.py +0 -0
  16. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/archive_run.py +0 -0
  17. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/changelog.py +0 -0
  18. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/checklist.py +0 -0
  19. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/cli.py +0 -0
  20. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/__init__.py +0 -0
  21. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/_bench_io.py +0 -0
  22. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/_crash_recovery.py +0 -0
  23. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/_detect.py +0 -0
  24. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/_dispatch.py +0 -0
  25. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/_resume.py +0 -0
  26. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/_validators.py +0 -0
  27. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/bench.py +0 -0
  28. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/bench_compare.py +0 -0
  29. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/bench_export.py +0 -0
  30. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/generate.py +0 -0
  31. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/init.py +0 -0
  32. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/optimize.py +0 -0
  33. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/review.py +0 -0
  34. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/commands/status.py +0 -0
  35. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/effort.py +0 -0
  36. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/env.py +0 -0
  37. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/exceptions.py +0 -0
  38. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/gh/__init__.py +0 -0
  39. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/gh/actions.py +0 -0
  40. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/gh/core.py +0 -0
  41. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/gh/issues.py +0 -0
  42. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/gh/labels.py +0 -0
  43. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/gh/milestones.py +0 -0
  44. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/git_ops.py +0 -0
  45. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/logging_setup.py +0 -0
  46. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/manifest.py +0 -0
  47. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/memory.py +0 -0
  48. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/__init__.py +0 -0
  49. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/_cache_warmup.py +0 -0
  50. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/_client_lifecycle.py +0 -0
  51. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/_comments.py +0 -0
  52. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/_memory_writers.py +0 -0
  53. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/_phase5_precommit.py +0 -0
  54. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/agent_spec.py +0 -0
  55. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/criteria_oracle.py +0 -0
  56. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/cycle_loop.py +0 -0
  57. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/cycle_prompts.py +0 -0
  58. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/deviation_detector.py +0 -0
  59. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/failure_report.py +0 -0
  60. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/ollama_budget.py +0 -0
  61. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase0_complexity.py +0 -0
  62. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase1_plan.py +0 -0
  63. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase2_review.py +0 -0
  64. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase3_4_implement.py +0 -0
  65. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase5_closure.py +0 -0
  66. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase65_budget.py +0 -0
  67. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase6_test.py +0 -0
  68. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase7_commit.py +0 -0
  69. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase8_ci_classifier.py +0 -0
  70. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase8_finalization.py +0 -0
  71. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase8_local_verify.py +0 -0
  72. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase8_repair_loop.py +0 -0
  73. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/phase8_workflow_gen.py +0 -0
  74. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/scenario_builder.py +0 -0
  75. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/sica.py +0 -0
  76. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/tier_selector.py +0 -0
  77. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/tier_t3.py +0 -0
  78. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/tier_t4.py +0 -0
  79. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/orchestrator/vigil.py +0 -0
  80. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/preflight.py +0 -0
  81. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/__init__.py +0 -0
  82. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/hashes.py +0 -0
  83. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-cycle-specializer.md +0 -0
  84. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-optimize-requirements.md +0 -0
  85. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-0-complexity.md +0 -0
  86. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-1-planning.md +0 -0
  87. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-2-batch-review.md +0 -0
  88. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-3-implementation.md +0 -0
  89. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-5-final-review.md +0 -0
  90. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-6-5-verify.md +0 -0
  91. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-6-test.md +0 -0
  92. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-7-commit.md +0 -0
  93. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-8-finalization.md +0 -0
  94. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-phase-8-repair.md +0 -0
  95. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/prompts/prompt-review.md +0 -0
  96. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/repo_info.py +0 -0
  97. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/requirements_structure.py +0 -0
  98. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/__init__.py +0 -0
  99. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/_telemetry.py +0 -0
  100. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/batch.py +0 -0
  101. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/cache_breakpoints.py +0 -0
  102. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/codex_runner.py +0 -0
  103. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/compaction_pause.py +0 -0
  104. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/fake_runner.py +0 -0
  105. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/gemini_runner.py +0 -0
  106. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/mcp.py +0 -0
  107. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/memory_tool.py +0 -0
  108. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/message_parsing.py +0 -0
  109. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/options.py +0 -0
  110. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/phase_telemetry.py +0 -0
  111. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/protocol.py +0 -0
  112. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/rate_limit.py +0 -0
  113. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/retry.py +0 -0
  114. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/sdk_runner.py +0 -0
  115. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/soft_reset.py +0 -0
  116. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/state_guard.py +0 -0
  117. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/subprocess_runner.py +0 -0
  118. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/types.py +0 -0
  119. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/runner/utils.py +0 -0
  120. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/semver.py +0 -0
  121. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/state.py +0 -0
  122. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/state_retention.py +0 -0
  123. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/surface_scanner.py +0 -0
  124. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/__init__.py +0 -0
  125. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/angular.md +0 -0
  126. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/base.md +0 -0
  127. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/fastapi.md +0 -0
  128. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/finance.md +0 -0
  129. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/fullstack.md +0 -0
  130. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/nestjs.md +0 -0
  131. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/src/code_generator/templates/python-cli.md +0 -0
  132. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_agent_spec.py +0 -0
  133. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_agents.py +0 -0
  134. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_archive_run.py +0 -0
  135. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_bench.py +0 -0
  136. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_bench_compare.py +0 -0
  137. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_bench_export.py +0 -0
  138. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_bench_fixture.py +0 -0
  139. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_bench_regression.py +0 -0
  140. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cache_breakpoints.py +0 -0
  141. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cache_ttl_ordering.py +0 -0
  142. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cache_warmup.py +0 -0
  143. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_changelog.py +0 -0
  144. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_checklist.py +0 -0
  145. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_claude_md.py +0 -0
  146. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cli_io_logging.py +0 -0
  147. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_client_lifecycle.py +0 -0
  148. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_codex_preflight.py +0 -0
  149. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_codex_runner.py +0 -0
  150. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_comments.py +0 -0
  151. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_commit_message.py +0 -0
  152. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_compaction_pause_handler.py +0 -0
  153. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_crash_recovery.py +0 -0
  154. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_criteria_oracle.py +0 -0
  155. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cycle_loop.py +0 -0
  156. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cycle_loop_multicycle.py +0 -0
  157. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cycle_loop_phase6_5.py +0 -0
  158. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cycle_loop_phase8.py +0 -0
  159. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cycle_ollama_model.py +0 -0
  160. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_cycle_prompts.py +0 -0
  161. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_delta_planning.py +0 -0
  162. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_dependencies.py +0 -0
  163. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_detect.py +0 -0
  164. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_deviation_detector.py +0 -0
  165. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_dispatch_graph_report.py +0 -0
  166. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_docs_no_default_max_turns.py +0 -0
  167. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_docs_ollama_model_guide.py +0 -0
  168. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_docs_ollama_pro.py +0 -0
  169. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_effective_model_routing.py +0 -0
  170. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_effort.py +0 -0
  171. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_effort_routing_consistency.py +0 -0
  172. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_env.py +0 -0
  173. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_failure_report.py +0 -0
  174. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gemini_preflight.py +0 -0
  175. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gemini_runner.py +0 -0
  176. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_generate.py +0 -0
  177. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_generate_ollama.py +0 -0
  178. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_generate_resume.py +0 -0
  179. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh.py +0 -0
  180. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh_actions.py +0 -0
  181. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh_issues_create.py +0 -0
  182. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh_labels.py +0 -0
  183. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh_milestones.py +0 -0
  184. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh_repo_threading.py +0 -0
  185. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_gh_submodules.py +0 -0
  186. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_git_ops.py +0 -0
  187. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_git_ops_phase8.py +0 -0
  188. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_init.py +0 -0
  189. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_logging_setup.py +0 -0
  190. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_manifest.py +0 -0
  191. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_max_turns_cli_flag.py +0 -0
  192. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_mcp.py +0 -0
  193. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_memory.py +0 -0
  194. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_memory_tool.py +0 -0
  195. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_memory_writers.py +0 -0
  196. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_message_parsing.py +0 -0
  197. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_no_max_turns_in_call_sites.py +0 -0
  198. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_no_max_turns_literal.py +0 -0
  199. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_non_goals_grep_guard.py +0 -0
  200. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_ollama_budget.py +0 -0
  201. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_ollama_hardening.py +0 -0
  202. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_ollama_rate_limit.py +0 -0
  203. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_optimize.py +0 -0
  204. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_options.py +0 -0
  205. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase0.py +0 -0
  206. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase1.py +0 -0
  207. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase2.py +0 -0
  208. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase2_cache_regression.py +0 -0
  209. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase2_multicycle_token_reduction.py +0 -0
  210. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase2_token_reduction.py +0 -0
  211. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase3_4.py +0 -0
  212. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase5.py +0 -0
  213. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase5_precommit.py +0 -0
  214. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6.py +0 -0
  215. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase65_budget.py +0 -0
  216. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_integration.py +0 -0
  217. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_integration_cycle2.py +0 -0
  218. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_prompt.py +0 -0
  219. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_prompt_snapshot.py +0 -0
  220. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_run.py +0 -0
  221. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_state.py +0 -0
  222. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase6_5_tiers.py +0 -0
  223. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase7.py +0 -0
  224. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_access_control.py +0 -0
  225. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_changelog.py +0 -0
  226. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_ci_classifier.py +0 -0
  227. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_finalization.py +0 -0
  228. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_local_verify.py +0 -0
  229. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_prompt_snapshots.py +0 -0
  230. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_prompts.py +0 -0
  231. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_repair_loop.py +0 -0
  232. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_repair_sota.py +0 -0
  233. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_semver.py +0 -0
  234. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_state.py +0 -0
  235. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_status.py +0 -0
  236. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_surface_scanner.py +0 -0
  237. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_trigger.py +0 -0
  238. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase8_workflow_gen.py +0 -0
  239. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase_mcp_regression.py +0 -0
  240. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase_telemetry.py +0 -0
  241. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_phase_token_logging.py +0 -0
  242. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_preflight.py +0 -0
  243. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_preflight_ollama.py +0 -0
  244. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_prompt_drift.py +0 -0
  245. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_prompt_prefix_snapshots.py +0 -0
  246. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_prompt_prefix_stability.py +0 -0
  247. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_prompts.py +0 -0
  248. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_rate_limit.py +0 -0
  249. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_repo_info.py +0 -0
  250. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_requirements_structure.py +0 -0
  251. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_resume.py +0 -0
  252. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_retry.py +0 -0
  253. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_review.py +0 -0
  254. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_runner_protocol.py +0 -0
  255. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_runner_protocol_annotations.py +0 -0
  256. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_runner_types.py +0 -0
  257. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_runner_utils.py +0 -0
  258. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_scenario_builder.py +0 -0
  259. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_sdk_runner.py +0 -0
  260. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_sdk_runner_shared.py +0 -0
  261. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_session_mode.py +0 -0
  262. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_sica.py +0 -0
  263. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_state.py +0 -0
  264. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_state_guard.py +0 -0
  265. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_state_retention.py +0 -0
  266. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_status.py +0 -0
  267. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_subprocess_runner.py +0 -0
  268. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_telemetry.py +0 -0
  269. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_tier_selector.py +0 -0
  270. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_tier_t3.py +0 -0
  271. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_tier_t3_pass_rate.py +0 -0
  272. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_tier_t4.py +0 -0
  273. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_version.py +0 -0
  274. {claude_code_generator-0.6.1 → claude_code_generator-0.6.2}/tests/test_vigil.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-code-generator
3
- Version: 0.6.1
3
+ Version: 0.6.2
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.6.1"
7
+ version = "0.6.2"
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.6.1
3
+ Version: 0.6.2
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
@@ -212,6 +212,7 @@ tests/test_phase6.py
212
212
  tests/test_phase65_budget.py
213
213
  tests/test_phase6_5_integration.py
214
214
  tests/test_phase6_5_integration_cycle2.py
215
+ tests/test_phase6_5_port_isolation.py
215
216
  tests/test_phase6_5_prompt.py
216
217
  tests/test_phase6_5_prompt_snapshot.py
217
218
  tests/test_phase6_5_run.py
@@ -1,3 +1,3 @@
1
1
  """code-generator: orchestrator CLI for end-to-end project generation."""
2
2
 
3
- __version__ = "0.6.1"
3
+ __version__ = "0.6.2"
@@ -32,7 +32,7 @@ import socket
32
32
  import subprocess
33
33
  import sys
34
34
  import time
35
- from dataclasses import dataclass, field
35
+ from dataclasses import dataclass, field, replace
36
36
  from typing import TYPE_CHECKING, Any
37
37
 
38
38
  import httpx
@@ -348,6 +348,48 @@ def _spawn_child(entry_cmd: list[str], cwd: Path, env: Mapping[str, str]) -> sub
348
348
  )
349
349
 
350
350
 
351
+ def _alloc_free_port() -> int:
352
+ """Bind ``127.0.0.1:0`` to obtain an OS-assigned free TCP port, then
353
+ release it.
354
+
355
+ Phase 6.5 must not hardcode ``:8000`` — co-resident tooling (e.g. the
356
+ claude-mem plugin's ``chroma run``) squats well-known ports and returns
357
+ 404 to every health probe, burning the entire repair-retry budget on a
358
+ purely environmental collision. An ephemeral port makes that collision
359
+ structurally impossible.
360
+
361
+ There is a benign TOCTOU window between release here and the app binding
362
+ the port; :func:`_ensure_verify_port` closes it by re-checking (and
363
+ rerolling) immediately before each attempt.
364
+ """
365
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
366
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
367
+ sock.bind(("127.0.0.1", 0))
368
+ return int(sock.getsockname()[1])
369
+
370
+
371
+ def _ensure_verify_port(port: int, *, logger: logging.Logger) -> int:
372
+ """Pre-flight port guard (#2).
373
+
374
+ If *port* was claimed by a foreign listener between attempts (a plugin
375
+ rebinding, a leaked uvicorn from a prior run), reroll to a fresh free
376
+ port instead of letting the squatter fail a tier and consume a retry.
377
+ A genuine app bug still fails the tier on its own port; only
378
+ environmental collisions are absorbed here.
379
+ """
380
+ if not _port_open(port):
381
+ return port
382
+ new_port = _alloc_free_port()
383
+ logger.warning(
384
+ "Phase 6.5 verify port %d occupied by a foreign listener before the "
385
+ "attempt began; rerolled to %d so the retry budget is not spent on "
386
+ "an environmental port collision.",
387
+ port,
388
+ new_port,
389
+ )
390
+ return new_port
391
+
392
+
351
393
  def _port_open(port: int, host: str = "127.0.0.1", timeout_s: float = 0.25) -> bool:
352
394
  try:
353
395
  with socket.create_connection((host, port), timeout=timeout_s):
@@ -654,6 +696,10 @@ async def run(
654
696
  budget = Phase65BudgetTracker(wall_budget_s=wall_budget_s, turn_budget=turn_budget)
655
697
  budget.start()
656
698
 
699
+ # Ephemeral verification port (#1): allocate once so base_url stays
700
+ # stable across the retry loop; re-checked per attempt by the guard (#2).
701
+ verify_port = _alloc_free_port()
702
+
657
703
  for attempt in range(max_retries):
658
704
  budget.check(turns_consumed=attempt, logger=logger)
659
705
  progress = _begin_attempt(target, progress, attempt)
@@ -661,6 +707,7 @@ async def run(
661
707
  if attempt > 0:
662
708
  _soft_reset_for_repair(project_dir, attempt + 1)
663
709
 
710
+ verify_port = _ensure_verify_port(verify_port, logger=logger)
664
711
  outcome = _run_tiers(
665
712
  project_dir,
666
713
  state,
@@ -669,6 +716,7 @@ async def run(
669
716
  progress,
670
717
  attempt,
671
718
  target,
719
+ port=verify_port,
672
720
  logger=logger,
673
721
  detector=detector,
674
722
  )
@@ -722,6 +770,7 @@ def _run_tiers(
722
770
  attempt: int,
723
771
  target: Any,
724
772
  *,
773
+ port: int,
725
774
  logger: logging.Logger,
726
775
  detector: DeviationDetector | None = None,
727
776
  ) -> TierResult | None:
@@ -731,13 +780,27 @@ def _run_tiers(
731
780
  :func:`tier_selector.select_tiers` then iterates ``spec.tiers``,
732
781
  skipping any tier with ``enabled=False`` and recording the
733
782
  skip reason on ``Phase65Progress``.
783
+
784
+ *port* is the ephemeral free port allocated by :func:`run` (#1). It is
785
+ woven into ``base_url``, the subprocess env (``PORT`` / ``UVICORN_PORT``
786
+ / ``APP_PORT``), and the persisted spec so both the programmatic tier
787
+ runners and the SDK repair agent bind the same collision-free port.
734
788
  """
735
- env = build_agent_env()
789
+ base_url = f"http://127.0.0.1:{port}"
790
+ # The SDK repair agent does not inherit this env (its credentials are
791
+ # locked at shared-client open time); it learns the port from the
792
+ # persisted spec's base_url/T1.port instead. These vars steer the
793
+ # programmatic T0/T2 subprocesses and any app that honours $PORT.
794
+ env = {
795
+ **build_agent_env(),
796
+ "PORT": str(port),
797
+ "UVICORN_PORT": str(port),
798
+ "APP_PORT": str(port),
799
+ }
736
800
  requirements_path = project_dir / ".code-generator" / "requirements.md"
737
801
  endpoints = _load_endpoints(requirements_path)
738
- base_url = "http://127.0.0.1:8000"
739
802
 
740
- spec = _persist_spec_for_attempt(project_dir, requirements_path)
803
+ spec = _persist_spec_for_attempt(project_dir, requirements_path, port)
741
804
  _record_skips(target, progress, spec, attempt, logger=logger)
742
805
  save_state(state_path, state)
743
806
 
@@ -759,11 +822,15 @@ def _run_tiers(
759
822
  return None
760
823
 
761
824
 
762
- def _persist_spec_for_attempt(project_dir: Path, requirements_path: Path) -> AgentSpec:
825
+ def _persist_spec_for_attempt(project_dir: Path, requirements_path: Path, port: int) -> AgentSpec:
763
826
  """Build the ``AgentSpec`` for this run and atomically persist it.
764
827
 
765
828
  The spec is the single source of truth consumed by :func:`_run_tiers`
766
- and any later replay tooling.
829
+ *and* the SDK repair agent (the prompt instructs it to trust the spec's
830
+ declared ports). ``build_agent_spec`` stays pure and deterministic
831
+ (default ``:8000``); the ephemeral *port* (#1) is layered on here via
832
+ :func:`dataclasses.replace` so the agent boots the app on a
833
+ collision-free port instead of the well-known ``:8000``.
767
834
  """
768
835
  tiers = select_tiers(project_dir, requirements_path)
769
836
  requirements_text = (
@@ -771,6 +838,13 @@ def _persist_spec_for_attempt(project_dir: Path, requirements_path: Path) -> Age
771
838
  )
772
839
  flags = {tier.tier_id: tier.enabled for tier in tiers if tier.tier_id in {"T3", "T4"}}
773
840
  spec = build_agent_spec(project_dir, requirements_text, flags)
841
+ spec = replace(
842
+ spec,
843
+ base_url=f"http://127.0.0.1:{port}",
844
+ tiers=tuple(
845
+ replace(tier, port=port) if tier.port is not None else tier for tier in spec.tiers
846
+ ),
847
+ )
774
848
  persist_agent_spec(spec, project_dir / ".code-generator")
775
849
  return spec
776
850
 
@@ -0,0 +1,87 @@
1
+ """Phase 6.5 ephemeral-port isolation (#1) and pre-flight port guard (#2).
2
+
3
+ Regression cover for the well-known-port collision that exhausted the
4
+ repair-retry budget: a co-resident ``chroma run`` (claude-mem plugin)
5
+ squatting ``:8000`` returned 404 to every health probe, so attempts 1+2
6
+ failed environmentally and attempt 3's real fix landed after the budget
7
+ was already spent. The fix moves verification onto an OS-assigned free
8
+ port and rerolls if that port is squatted before an attempt starts.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import logging
14
+ import socket
15
+ from pathlib import Path
16
+
17
+ from code_generator.orchestrator.agent_spec import load_agent_spec
18
+ from code_generator.orchestrator.phase6_5_verify import (
19
+ _alloc_free_port,
20
+ _ensure_verify_port,
21
+ _persist_spec_for_attempt,
22
+ )
23
+
24
+ _LOGGER = logging.getLogger("test.phase6_5.port_isolation")
25
+
26
+
27
+ def _make_project(tmp_path: Path) -> Path:
28
+ project_dir = tmp_path / "project"
29
+ (project_dir / ".code-generator").mkdir(parents=True)
30
+ (project_dir / ".code-generator" / "requirements.md").write_text(
31
+ "# Demo\n\n## Tech Stack\n\nFastAPI\n", encoding="utf-8"
32
+ )
33
+ return project_dir
34
+
35
+
36
+ def test_alloc_free_port_returns_a_bindable_ephemeral_port() -> None:
37
+ port = _alloc_free_port()
38
+ assert 1024 < port < 65536
39
+ # Released back to the OS — re-bindable, proving it was genuinely free.
40
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
41
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
42
+ sock.bind(("127.0.0.1", port))
43
+
44
+
45
+ def test_persisted_spec_carries_ephemeral_port_not_8000(tmp_path: Path) -> None:
46
+ project_dir = _make_project(tmp_path)
47
+ port = _alloc_free_port()
48
+
49
+ _persist_spec_for_attempt(
50
+ project_dir, project_dir / ".code-generator" / "requirements.md", port
51
+ )
52
+
53
+ spec = load_agent_spec(project_dir / ".code-generator")
54
+ assert spec.base_url == f"http://127.0.0.1:{port}"
55
+ assert spec.base_url != "http://127.0.0.1:8000"
56
+ # Every tier that declares a port (T1) is rewritten to the free port —
57
+ # this is the field the SDK repair agent reads to boot the app.
58
+ ported = [t for t in spec.tiers if t.port is not None]
59
+ assert ported, "expected at least one tier with an explicit port (T1)"
60
+ assert all(t.port == port for t in ported)
61
+
62
+
63
+ def test_guard_passes_through_a_free_port() -> None:
64
+ port = _alloc_free_port()
65
+ assert _ensure_verify_port(port, logger=_LOGGER) == port
66
+
67
+
68
+ def test_guard_rerolls_when_port_is_squatted(caplog) -> None:
69
+ """A foreign listener on the chosen port → reroll, never reuse it.
70
+
71
+ This is the chroma-on-:8000 scenario in miniature: the guard must
72
+ hand back a *different*, free port so the squatter cannot fail a
73
+ tier and burn a retry.
74
+ """
75
+ squatter = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
76
+ squatter.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
77
+ squatter.bind(("127.0.0.1", 0))
78
+ squatter.listen(1)
79
+ squatted_port = squatter.getsockname()[1]
80
+ try:
81
+ with caplog.at_level(logging.WARNING):
82
+ rerolled = _ensure_verify_port(squatted_port, logger=_LOGGER)
83
+ assert rerolled != squatted_port
84
+ assert 1024 < rerolled < 65536
85
+ assert "rerolled" in caplog.text
86
+ finally:
87
+ squatter.close()