drydock-cli 3.1.38__tar.gz → 3.1.39__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 (221) hide show
  1. {drydock_cli-3.1.38/drydock_cli.egg-info → drydock_cli-3.1.39}/PKG-INFO +1 -1
  2. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/ratchet.py +29 -9
  3. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/swarm.py +5 -5
  4. {drydock_cli-3.1.38 → drydock_cli-3.1.39/drydock_cli.egg-info}/PKG-INFO +1 -1
  5. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/pyproject.toml +1 -1
  6. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_swarm.py +14 -0
  7. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/LICENSE +0 -0
  8. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/NOTICE +0 -0
  9. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/README.md +0 -0
  10. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/__init__.py +0 -0
  11. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/__main__.py +0 -0
  12. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/advisor.py +0 -0
  13. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/agent.py +0 -0
  14. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/asr.py +0 -0
  15. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/bash_safety.py +0 -0
  16. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/bottleneck.py +0 -0
  17. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/budget.py +0 -0
  18. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/__init__.py +0 -0
  19. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/document-canvas.md +0 -0
  20. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/ml-data.md +0 -0
  21. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/ml-debug.md +0 -0
  22. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/ml-finetune.md +0 -0
  23. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/ml-metrics.md +0 -0
  24. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/ml-rl.md +0 -0
  25. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/ml-train.md +0 -0
  26. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/nist-ai-rmf.md +0 -0
  27. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/nist-csf.md +0 -0
  28. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/rmf-categorize.md +0 -0
  29. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/rmf-control.md +0 -0
  30. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/rmf-poam.md +0 -0
  31. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/rmf-review.md +0 -0
  32. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/stig-assess.md +0 -0
  33. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/builtin_skills/stig-remediate.md +0 -0
  34. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/capacity.py +0 -0
  35. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/cci.py +0 -0
  36. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/cli.py +0 -0
  37. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/comms/__init__.py +0 -0
  38. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/comms/attention.py +0 -0
  39. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/comms/channels.py +0 -0
  40. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/comms/events.py +0 -0
  41. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/compaction.py +0 -0
  42. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/config.py +0 -0
  43. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/detect.py +0 -0
  44. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/doccanvas.py +0 -0
  45. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/eratchet.py +0 -0
  46. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/events.py +0 -0
  47. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/extract.py +0 -0
  48. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/gittools.py +0 -0
  49. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/graphrag.py +0 -0
  50. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/groundtruth.py +0 -0
  51. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/guards.py +0 -0
  52. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/jobs.py +0 -0
  53. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/loop_detect.py +0 -0
  54. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/mcp.py +0 -0
  55. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/mission.py +0 -0
  56. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/mission_cli.py +0 -0
  57. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/mission_run.py +0 -0
  58. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/pdfredbox.py +0 -0
  59. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/phases.py +0 -0
  60. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/poam.py +0 -0
  61. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/predictions.py +0 -0
  62. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/progress.py +0 -0
  63. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/providers.py +0 -0
  64. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/recipes.py +0 -0
  65. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/recovery.py +0 -0
  66. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/resume.py +0 -0
  67. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/rmf.py +0 -0
  68. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/rmf_graph.py +0 -0
  69. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/skills.py +0 -0
  70. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/stig.py +0 -0
  71. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/subagents.py +0 -0
  72. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/suggest.py +0 -0
  73. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/task_state.py +0 -0
  74. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tool_policy.py +0 -0
  75. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tool_registry.py +0 -0
  76. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tool_result.py +0 -0
  77. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tool_select.py +0 -0
  78. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tool_validate.py +0 -0
  79. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tools/__init__.py +0 -0
  80. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/trajectory.py +0 -0
  81. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tui/__init__.py +0 -0
  82. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tui/app.py +0 -0
  83. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tui/approval.py +0 -0
  84. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tui/messages.py +0 -0
  85. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tui/widgets.py +0 -0
  86. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/tuning.py +0 -0
  87. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/verification.py +0 -0
  88. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock/web.py +0 -0
  89. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock_cli.egg-info/SOURCES.txt +0 -0
  90. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock_cli.egg-info/dependency_links.txt +0 -0
  91. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock_cli.egg-info/entry_points.txt +0 -0
  92. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock_cli.egg-info/requires.txt +0 -0
  93. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/drydock_cli.egg-info/top_level.txt +0 -0
  94. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/setup.cfg +0 -0
  95. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_advisor.py +0 -0
  96. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_approval.py +0 -0
  97. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_asr.py +0 -0
  98. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_back_command.py +0 -0
  99. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_background.py +0 -0
  100. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_binary_output.py +0 -0
  101. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_crossplatform.py +0 -0
  102. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_output_bounding.py +0 -0
  103. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_process_group.py +0 -0
  104. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_safety.py +0 -0
  105. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_sanitize.py +0 -0
  106. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_shell.py +0 -0
  107. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_stdin.py +0 -0
  108. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_stop_partial.py +0 -0
  109. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_timeout_network.py +0 -0
  110. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bash_timeout_param.py +0 -0
  111. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_bottleneck.py +0 -0
  112. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_budget.py +0 -0
  113. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_capacity.py +0 -0
  114. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_cci.py +0 -0
  115. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_cli_agents.py +0 -0
  116. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_comms.py +0 -0
  117. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_compact_command.py +0 -0
  118. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_compaction.py +0 -0
  119. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_config.py +0 -0
  120. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_config_migration.py +0 -0
  121. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_context_limit_config.py +0 -0
  122. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_context_limit_issue25.py +0 -0
  123. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_criteria_coverage.py +0 -0
  124. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_cycling_detection.py +0 -0
  125. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_declared_deps.py +0 -0
  126. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_degenerate_argument.py +0 -0
  127. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_detect.py +0 -0
  128. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_dispatch.py +0 -0
  129. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_doccanvas.py +0 -0
  130. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_e2e_connected.py +0 -0
  131. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_edit_replace_all.py +0 -0
  132. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_edit_thrash_and_compaction.py +0 -0
  133. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_effort_governor.py +0 -0
  134. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_empty_response.py +0 -0
  135. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_eratchet.py +0 -0
  136. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_events.py +0 -0
  137. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_extract.py +0 -0
  138. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_failure_loop.py +0 -0
  139. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_first_run_setup.py +0 -0
  140. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_gittools.py +0 -0
  141. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_glob_edit_edges.py +0 -0
  142. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_graphify_example.py +0 -0
  143. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_graphrag.py +0 -0
  144. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_graphrag_quoted_path.py +0 -0
  145. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_graphrag_sqlite.py +0 -0
  146. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_grep_and_read_robust.py +0 -0
  147. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_groundtruth_predictions.py +0 -0
  148. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_guards_and_tools.py +0 -0
  149. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_hallucinated_tools.py +0 -0
  150. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_jobs.py +0 -0
  151. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_knowledge_tool_available.py +0 -0
  152. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_leaked_tool_call.py +0 -0
  153. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_loop_detect.py +0 -0
  154. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_main_api_key.py +0 -0
  155. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_mcp.py +0 -0
  156. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_mission.py +0 -0
  157. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_mission_cli.py +0 -0
  158. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_mission_run.py +0 -0
  159. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_model_registry.py +0 -0
  160. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_oneshot_unreachable.py +0 -0
  161. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_overthink_interrupt.py +0 -0
  162. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_pdfredbox.py +0 -0
  163. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_phases.py +0 -0
  164. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_plan_autocontinue.py +0 -0
  165. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_poam.py +0 -0
  166. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_progress.py +0 -0
  167. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_providers_unreachable.py +0 -0
  168. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_ratchet.py +0 -0
  169. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_ratchet_offer.py +0 -0
  170. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_read_index.py +0 -0
  171. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_recipes.py +0 -0
  172. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_recovery.py +0 -0
  173. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_recovery_config.py +0 -0
  174. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_recovery_integration.py +0 -0
  175. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_repeated_outcome.py +0 -0
  176. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_repetition_interrupt.py +0 -0
  177. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_resume_events.py +0 -0
  178. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_resume_restore.py +0 -0
  179. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_resume_snapshot.py +0 -0
  180. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_rmf.py +0 -0
  181. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_rmf_graph.py +0 -0
  182. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_rmf_stig_graph.py +0 -0
  183. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_rolling_plan.py +0 -0
  184. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_runaway_repetition.py +0 -0
  185. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_screenshot.py +0 -0
  186. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_server_probe.py +0 -0
  187. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_skills.py +0 -0
  188. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_sqlite_events.py +0 -0
  189. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_stall_retry.py +0 -0
  190. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_stig.py +0 -0
  191. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_stop.py +0 -0
  192. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_streaming_newlines.py +0 -0
  193. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_subagent.py +0 -0
  194. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_subagents.py +0 -0
  195. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_suggest.py +0 -0
  196. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_system_prompt_help.py +0 -0
  197. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_task_state.py +0 -0
  198. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_text_only_model.py +0 -0
  199. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_timeline.py +0 -0
  200. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_todo.py +0 -0
  201. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_arg_coercion.py +0 -0
  202. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_arg_coercion_more.py +0 -0
  203. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_arg_parsing.py +0 -0
  204. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_canonical.py +0 -0
  205. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_policy.py +0 -0
  206. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_result.py +0 -0
  207. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_select.py +0 -0
  208. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tool_validate.py +0 -0
  209. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tools_undo.py +0 -0
  210. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_trajectory.py +0 -0
  211. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_truncated_turn.py +0 -0
  212. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tui.py +0 -0
  213. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_tuning.py +0 -0
  214. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_verification_gate.py +0 -0
  215. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_viewimage.py +0 -0
  216. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_vision_input.py +0 -0
  217. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_web_tools.py +0 -0
  218. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_windows_shell.py +0 -0
  219. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_worker_subagent.py +0 -0
  220. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_write_content_coerce.py +0 -0
  221. {drydock_cli-3.1.38 → drydock_cli-3.1.39}/tests/test_xccdf.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.1.38
3
+ Version: 3.1.39
4
4
  Summary: Drydock — a local, provider-agnostic terminal coding agent for local LLMs
5
5
  Author: Frank Bobe III
6
6
  License-Expression: Apache-2.0
@@ -87,6 +87,30 @@ class VerifyResult:
87
87
  return self.total > 0 and self.passed >= self.total
88
88
 
89
89
 
90
+ def run_shell_bounded(command: str, cwd: str | None, timeout: float) -> tuple[str, int, bool]:
91
+ """Run a shell command with a timeout that actually holds: the command runs in its
92
+ own process group and the whole group is killed on timeout. (subprocess.run with
93
+ shell=True only kills /bin/sh; a hung child — e.g. pytest stuck in an infinite loop —
94
+ keeps the output pipes open and the call blocks far past the timeout.)
95
+ Returns (combined output, returncode, timed_out)."""
96
+ import signal
97
+
98
+ proc = subprocess.Popen(command, shell=True, cwd=cwd, stdout=subprocess.PIPE,
99
+ stderr=subprocess.PIPE, text=True, start_new_session=True)
100
+ try:
101
+ out, err = proc.communicate(timeout=timeout)
102
+ timed_out = False
103
+ except subprocess.TimeoutExpired:
104
+ try:
105
+ os.killpg(proc.pid, signal.SIGKILL)
106
+ except (ProcessLookupError, PermissionError):
107
+ proc.kill()
108
+ out, err = proc.communicate()
109
+ timed_out = True
110
+ text = (out or "") + ("\n" + err if err else "")
111
+ return text, (124 if timed_out else proc.returncode), timed_out
112
+
113
+
90
114
  @dataclass
91
115
  class Verifier:
92
116
  """Runs a shell command and scores it. The command is the ground truth the
@@ -99,15 +123,11 @@ class Verifier:
99
123
 
100
124
  def run(self) -> VerifyResult:
101
125
  try:
102
- proc = subprocess.run(
103
- self.command, shell=True, cwd=self.cwd,
104
- capture_output=True, text=True, timeout=self.timeout,
105
- )
106
- out = (proc.stdout or "") + ("\n" + proc.stderr if proc.stderr else "")
107
- rc = proc.returncode
108
- except subprocess.TimeoutExpired as e:
109
- out = (e.output or "") + "\n[verifier timed out]"
110
- rc = 124
126
+ out, rc, timed_out = run_shell_bounded(self.command, self.cwd, self.timeout)
127
+ except OSError as e:
128
+ out, rc, timed_out = f"[verifier failed to start: {e}]", 127, False
129
+ if timed_out:
130
+ out += "\n[verifier timed out]"
111
131
  p, t = score_output(out, self.mode, rc)
112
132
  return VerifyResult(p, t, rc, out)
113
133
 
@@ -589,21 +589,21 @@ VerifyFn = Callable[["Candidate"], "tuple[int, int]"]
589
589
 
590
590
 
591
591
  def make_shell_verifier(verify_cmd: str, fitness: str = "auto",
592
- timeout: int = 1800) -> VerifyFn:
592
+ timeout: int = 600) -> VerifyFn:
593
593
  """A verifier that runs `verify_cmd` in the candidate's worktree and scores the output
594
594
  with drydock.ratchet.score_output — the same scorer the ratchet/eratchet use, so a
595
595
  candidate is judged by a real test run, never by the builder's self-report (§18/§20)."""
596
- from drydock.ratchet import score_output
596
+ from drydock.ratchet import run_shell_bounded, score_output
597
597
 
598
598
  def verify(cand: Candidate) -> tuple[int, int]:
599
599
  if not cand.worktree or not Path(cand.worktree).exists():
600
600
  return 0, 0
601
601
  try:
602
- r = subprocess.run(verify_cmd, cwd=cand.worktree, shell=True,
603
- capture_output=True, text=True, timeout=timeout)
602
+ out, rc, _ = run_shell_bounded(verify_cmd, cand.worktree, timeout)
604
603
  except (OSError, subprocess.SubprocessError):
605
604
  return 0, 1
606
- return score_output((r.stdout or "") + (r.stderr or ""), fitness, r.returncode)
605
+ # a hung candidate (killed at the timeout) scores whatever finished before the kill
606
+ return score_output(out, fitness, rc)
607
607
 
608
608
  return verify
609
609
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.1.38
3
+ Version: 3.1.39
4
4
  Summary: Drydock — a local, provider-agnostic terminal coding agent for local LLMs
5
5
  Author: Frank Bobe III
6
6
  License-Expression: Apache-2.0
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
  # PyPI distribution name is drydock-cli (the established install name, continued
8
8
  # from the retired v2 fork); the import package + CLI command stay `drydock`.
9
9
  name = "drydock-cli"
10
- version = "3.1.38"
10
+ version = "3.1.39"
11
11
  description = "Drydock — a local, provider-agnostic terminal coding agent for local LLMs"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.11"
@@ -496,3 +496,17 @@ def test_run_swarm_cancel_stops_queued_waves_and_verification(tmp_path):
496
496
  assert verified == [] # verification skipped on cancel
497
497
  assert "cancelled" in events and "judge" in events
498
498
  assert len([c for c in res.candidates if c.commit]) == 1
499
+
500
+
501
+ def test_shell_verifier_timeout_kills_hung_child(tmp_path):
502
+ import time
503
+
504
+ wt = tmp_path / "wt"
505
+ wt.mkdir()
506
+ cand = swarm.Candidate(id="c-1", agent="a", commit="x", worktree=str(wt))
507
+ # the shell spawns a child that outlives the shell's own kill and holds the pipes open
508
+ verify = swarm.make_shell_verifier("sleep 30 & sleep 30; echo done", timeout=1)
509
+ t0 = time.monotonic()
510
+ passed, _total = verify(cand)
511
+ assert time.monotonic() - t0 < 10
512
+ assert passed == 0
File without changes
File without changes
File without changes
File without changes