drydock-cli 3.1.6__tar.gz → 3.1.8__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 (192) hide show
  1. {drydock_cli-3.1.6/drydock_cli.egg-info → drydock_cli-3.1.8}/PKG-INFO +56 -1
  2. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/README.md +55 -0
  3. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/providers.py +11 -0
  4. drydock_cli-3.1.8/drydock/ratchet.py +587 -0
  5. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tui/app.py +161 -12
  6. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tui/widgets.py +100 -8
  7. {drydock_cli-3.1.6 → drydock_cli-3.1.8/drydock_cli.egg-info}/PKG-INFO +56 -1
  8. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock_cli.egg-info/SOURCES.txt +2 -0
  9. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/pyproject.toml +1 -1
  10. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_doccanvas.py +45 -0
  11. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_events.py +1 -1
  12. drydock_cli-3.1.8/tests/test_ratchet.py +379 -0
  13. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_task_state.py +1 -1
  14. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tui.py +79 -0
  15. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_verification_gate.py +3 -3
  16. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/LICENSE +0 -0
  17. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/NOTICE +0 -0
  18. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/__init__.py +0 -0
  19. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/__main__.py +0 -0
  20. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/advisor.py +0 -0
  21. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/agent.py +0 -0
  22. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/bash_safety.py +0 -0
  23. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/budget.py +0 -0
  24. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/__init__.py +0 -0
  25. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/document-canvas.md +0 -0
  26. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/fiar-assess.md +0 -0
  27. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/fiar-cap.md +0 -0
  28. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/fiar-evidence.md +0 -0
  29. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/fiar-readiness.md +0 -0
  30. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/ml-data.md +0 -0
  31. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/ml-debug.md +0 -0
  32. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/ml-finetune.md +0 -0
  33. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/ml-metrics.md +0 -0
  34. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/ml-rl.md +0 -0
  35. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/ml-train.md +0 -0
  36. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/nist-ai-rmf.md +0 -0
  37. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/nist-csf.md +0 -0
  38. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/rmf-categorize.md +0 -0
  39. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/rmf-control.md +0 -0
  40. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/rmf-poam.md +0 -0
  41. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/rmf-review.md +0 -0
  42. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/stig-assess.md +0 -0
  43. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/builtin_skills/stig-remediate.md +0 -0
  44. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/cci.py +0 -0
  45. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/cli.py +0 -0
  46. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/compaction.py +0 -0
  47. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/config.py +0 -0
  48. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/detect.py +0 -0
  49. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/doccanvas.py +0 -0
  50. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/events.py +0 -0
  51. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/extract.py +0 -0
  52. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/fiar.py +0 -0
  53. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/gittools.py +0 -0
  54. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/graphrag.py +0 -0
  55. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/guards.py +0 -0
  56. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/loop_detect.py +0 -0
  57. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/mcp.py +0 -0
  58. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/phases.py +0 -0
  59. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/poam.py +0 -0
  60. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/progress.py +0 -0
  61. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/recipes.py +0 -0
  62. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/recovery.py +0 -0
  63. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/resume.py +0 -0
  64. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/rmf.py +0 -0
  65. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/rmf_graph.py +0 -0
  66. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/skills.py +0 -0
  67. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/stig.py +0 -0
  68. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/subagents.py +0 -0
  69. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/suggest.py +0 -0
  70. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/task_state.py +0 -0
  71. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tool_policy.py +0 -0
  72. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tool_registry.py +0 -0
  73. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tool_result.py +0 -0
  74. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tool_select.py +0 -0
  75. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tool_validate.py +0 -0
  76. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tools/__init__.py +0 -0
  77. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/trajectory.py +0 -0
  78. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tui/__init__.py +0 -0
  79. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tui/approval.py +0 -0
  80. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tui/messages.py +0 -0
  81. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/tuning.py +0 -0
  82. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/verification.py +0 -0
  83. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock/web.py +0 -0
  84. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock_cli.egg-info/dependency_links.txt +0 -0
  85. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock_cli.egg-info/entry_points.txt +0 -0
  86. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock_cli.egg-info/requires.txt +0 -0
  87. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/drydock_cli.egg-info/top_level.txt +0 -0
  88. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/setup.cfg +0 -0
  89. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_advisor.py +0 -0
  90. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_approval.py +0 -0
  91. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_back_command.py +0 -0
  92. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_background.py +0 -0
  93. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_binary_output.py +0 -0
  94. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_crossplatform.py +0 -0
  95. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_output_bounding.py +0 -0
  96. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_process_group.py +0 -0
  97. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_safety.py +0 -0
  98. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_sanitize.py +0 -0
  99. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_shell.py +0 -0
  100. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_stdin.py +0 -0
  101. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_stop_partial.py +0 -0
  102. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_timeout_network.py +0 -0
  103. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_bash_timeout_param.py +0 -0
  104. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_budget.py +0 -0
  105. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_cci.py +0 -0
  106. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_cli_agents.py +0 -0
  107. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_compact_command.py +0 -0
  108. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_compaction.py +0 -0
  109. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_config.py +0 -0
  110. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_config_migration.py +0 -0
  111. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_context_limit_config.py +0 -0
  112. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_context_limit_issue25.py +0 -0
  113. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_criteria_coverage.py +0 -0
  114. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_cycling_detection.py +0 -0
  115. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_degenerate_argument.py +0 -0
  116. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_detect.py +0 -0
  117. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_dispatch.py +0 -0
  118. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_e2e_connected.py +0 -0
  119. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_edit_replace_all.py +0 -0
  120. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_effort_governor.py +0 -0
  121. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_empty_response.py +0 -0
  122. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_extract.py +0 -0
  123. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_failure_loop.py +0 -0
  124. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_fiar.py +0 -0
  125. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_first_run_setup.py +0 -0
  126. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_gittools.py +0 -0
  127. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_glob_edit_edges.py +0 -0
  128. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_graphify_example.py +0 -0
  129. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_graphrag.py +0 -0
  130. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_graphrag_quoted_path.py +0 -0
  131. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_graphrag_sqlite.py +0 -0
  132. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_grep_and_read_robust.py +0 -0
  133. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_guards_and_tools.py +0 -0
  134. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_hallucinated_tools.py +0 -0
  135. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_leaked_tool_call.py +0 -0
  136. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_loop_detect.py +0 -0
  137. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_mcp.py +0 -0
  138. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_model_registry.py +0 -0
  139. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_oneshot_unreachable.py +0 -0
  140. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_overthink_interrupt.py +0 -0
  141. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_phases.py +0 -0
  142. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_plan_autocontinue.py +0 -0
  143. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_poam.py +0 -0
  144. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_progress.py +0 -0
  145. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_providers_unreachable.py +0 -0
  146. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_read_index.py +0 -0
  147. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_recipes.py +0 -0
  148. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_recovery.py +0 -0
  149. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_recovery_config.py +0 -0
  150. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_recovery_integration.py +0 -0
  151. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_repeated_outcome.py +0 -0
  152. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_repetition_interrupt.py +0 -0
  153. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_resume_events.py +0 -0
  154. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_resume_restore.py +0 -0
  155. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_resume_snapshot.py +0 -0
  156. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_rmf.py +0 -0
  157. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_rmf_graph.py +0 -0
  158. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_rmf_stig_graph.py +0 -0
  159. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_rolling_plan.py +0 -0
  160. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_runaway_repetition.py +0 -0
  161. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_screenshot.py +0 -0
  162. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_server_probe.py +0 -0
  163. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_skills.py +0 -0
  164. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_sqlite_events.py +0 -0
  165. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_stall_retry.py +0 -0
  166. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_stig.py +0 -0
  167. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_stop.py +0 -0
  168. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_streaming_newlines.py +0 -0
  169. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_subagent.py +0 -0
  170. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_subagents.py +0 -0
  171. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_suggest.py +0 -0
  172. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_system_prompt_help.py +0 -0
  173. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_timeline.py +0 -0
  174. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_todo.py +0 -0
  175. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_arg_coercion.py +0 -0
  176. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_arg_coercion_more.py +0 -0
  177. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_arg_parsing.py +0 -0
  178. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_canonical.py +0 -0
  179. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_policy.py +0 -0
  180. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_result.py +0 -0
  181. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_select.py +0 -0
  182. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tool_validate.py +0 -0
  183. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tools_undo.py +0 -0
  184. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_trajectory.py +0 -0
  185. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_tuning.py +0 -0
  186. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_viewimage.py +0 -0
  187. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_vision_input.py +0 -0
  188. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_web_tools.py +0 -0
  189. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_windows_shell.py +0 -0
  190. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_worker_subagent.py +0 -0
  191. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/tests/test_write_content_coerce.py +0 -0
  192. {drydock_cli-3.1.6 → drydock_cli-3.1.8}/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.6
3
+ Version: 3.1.8
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
@@ -112,6 +112,12 @@ A full agentic CLI harness — every tool below is clean-room and dependency-fre
112
112
  - **Cross-platform** — runs natively on Linux, macOS, and **Windows via PowerShell/cmd**
113
113
  (no WSL or Git-Bash required); `/shell` shows which shell your commands run in.
114
114
  - **Loops** — `/loop <count> <prompt>` runs a prompt iteratively (Esc stops).
115
+ - **Ratchet** — `/ratchet <goal>` keeps solving across rounds, snapshotting the
116
+ workspace whenever more tests pass and rolling back regressions, until it goes
117
+ green. The verifier auto-detects (pytest/cargo/go/npm/make); `--verify "<cmd>"`
118
+ overrides. Progress can't slip backward. **`--effort low|medium|high|xhigh|max`**
119
+ is one dial from a cheap plain pawl (low) to full evolutionary search — fan-out
120
+ and crossover of partial solutions — for the hardest tasks (high+).
115
121
 
116
122
  ## Slash commands
117
123
 
@@ -129,6 +135,7 @@ Typed into the prompt. The agent also knows these, so you can just **ask it**
129
135
  | `/skills new <name> <prompt>` | Create a reusable `/<name>` skill (use `$ARGS` for input) |
130
136
  | `/<name>` | Run a skill |
131
137
  | `/loop <count> <prompt>` | Repeat a prompt N times (Esc stops) |
138
+ | `/ratchet <goal>` | Solve across rounds, snapshotting on verifier gains, rolling back regressions. `--effort low..max` scales plain-pawl→evolutionary; verifier auto-detects (`--verify "<cmd>"` to override; `--rounds N`, `--fitness auto\|exitcode\|<regex>`) |
132
139
  | `/mcp` | List connected MCP servers + their tools |
133
140
  | `/rmf bootstrap [families]` | Ingest the NIST SP 800-53 catalog (RMF automation) |
134
141
  | `/rmf-control` · `/rmf-categorize` · `/rmf-review` · `/rmf-poam` | Bundled RMF skills |
@@ -367,6 +374,54 @@ docker run -it --add-host=host.docker.internal:host-gateway \
367
374
  `-v "$PWD:/work"` mounts your project so the agent can read/edit it. Tags:
368
375
  `fbobe3/drydock:latest` and `fbobe3/drydock:<version>` (e.g. `:3.0.135`).
369
376
 
377
+ ### Serving Gemma-4-31B
378
+
379
+ Drydock is provider-agnostic, but its primary target is dense **Gemma-4-31B**.
380
+ Two proven ways to serve it on a 2×GPU box, both exposing an OpenAI-compatible
381
+ API on `:8000` as model `gemma4`:
382
+
383
+ **llama.cpp** — QAT GGUF, flexible concurrency (more slots if you need them):
384
+
385
+ ```
386
+ llama-server -m gemma-4-31B-it-qat-UD-Q4_K_XL.gguf \
387
+ -c 65536 -np 2 --host 0.0.0.0 --port 8000 --alias gemma4
388
+ ```
389
+
390
+ **vLLM** — w4a16 QAT, ~2× faster per request, 128K context:
391
+
392
+ ```
393
+ docker run -d --name vllm-prod --gpus all --ipc=host --restart unless-stopped \
394
+ -v /data3/Models:/models -p 8000:8000 \
395
+ -e NCCL_P2P_DISABLE=1 \
396
+ vllm/vllm-openai:v0.26.0 \
397
+ --model /models/gemma-4-31B-it-qat-w4a16-ct \
398
+ --served-model-name gemma4 \
399
+ --tensor-parallel-size 2 \
400
+ --max-model-len 131072 \
401
+ --max-num-seqs 2 \
402
+ --gpu-memory-utilization 0.97 \
403
+ --kv-cache-dtype fp8 \
404
+ --tool-call-parser gemma4 \
405
+ --enable-auto-tool-choice
406
+ ```
407
+
408
+ Point drydock at either with
409
+ `--provider vllm --base-url http://<host>:8000/v1 --model gemma4`.
410
+
411
+ **vLLM-on-Gemma-4 notes** (drydock handles these for you as of **3.1.7**):
412
+
413
+ - **`skip_special_tokens: false`** is sent on every request — without it, a turn
414
+ truncated at `max_tokens` (tool-call / reasoning tails) comes back with *empty*
415
+ content, which looks like a refusal. If `finish_reason == "length"`, retry with
416
+ a larger `max_tokens` (≥ 2000 for reasoning-heavy calls).
417
+ - **Reasoning is off by default.** Enable per-request via
418
+ `chat_template_kwargs.enable_thinking`; the vLLM reasoning parser is disabled,
419
+ so `<|channel>thought …` markers arrive inside `content` (stripped client-side).
420
+ - **`--max-num-seqs 2`** caps concurrency at 2 — the cost of fitting 128K context
421
+ into the VRAM. Use llama.cpp if you need more concurrent sessions than context.
422
+ - Tool-calling is the standard OpenAI format; `/props` is llama.cpp-only (vLLM
423
+ 404s it — drydock falls back to `/v1/models` for the context length).
424
+
370
425
  ## Using it
371
426
 
372
427
  Type a task and press **Enter**. Drydock reads/writes/edits files and runs
@@ -88,6 +88,12 @@ A full agentic CLI harness — every tool below is clean-room and dependency-fre
88
88
  - **Cross-platform** — runs natively on Linux, macOS, and **Windows via PowerShell/cmd**
89
89
  (no WSL or Git-Bash required); `/shell` shows which shell your commands run in.
90
90
  - **Loops** — `/loop <count> <prompt>` runs a prompt iteratively (Esc stops).
91
+ - **Ratchet** — `/ratchet <goal>` keeps solving across rounds, snapshotting the
92
+ workspace whenever more tests pass and rolling back regressions, until it goes
93
+ green. The verifier auto-detects (pytest/cargo/go/npm/make); `--verify "<cmd>"`
94
+ overrides. Progress can't slip backward. **`--effort low|medium|high|xhigh|max`**
95
+ is one dial from a cheap plain pawl (low) to full evolutionary search — fan-out
96
+ and crossover of partial solutions — for the hardest tasks (high+).
91
97
 
92
98
  ## Slash commands
93
99
 
@@ -105,6 +111,7 @@ Typed into the prompt. The agent also knows these, so you can just **ask it**
105
111
  | `/skills new <name> <prompt>` | Create a reusable `/<name>` skill (use `$ARGS` for input) |
106
112
  | `/<name>` | Run a skill |
107
113
  | `/loop <count> <prompt>` | Repeat a prompt N times (Esc stops) |
114
+ | `/ratchet <goal>` | Solve across rounds, snapshotting on verifier gains, rolling back regressions. `--effort low..max` scales plain-pawl→evolutionary; verifier auto-detects (`--verify "<cmd>"` to override; `--rounds N`, `--fitness auto\|exitcode\|<regex>`) |
108
115
  | `/mcp` | List connected MCP servers + their tools |
109
116
  | `/rmf bootstrap [families]` | Ingest the NIST SP 800-53 catalog (RMF automation) |
110
117
  | `/rmf-control` · `/rmf-categorize` · `/rmf-review` · `/rmf-poam` | Bundled RMF skills |
@@ -343,6 +350,54 @@ docker run -it --add-host=host.docker.internal:host-gateway \
343
350
  `-v "$PWD:/work"` mounts your project so the agent can read/edit it. Tags:
344
351
  `fbobe3/drydock:latest` and `fbobe3/drydock:<version>` (e.g. `:3.0.135`).
345
352
 
353
+ ### Serving Gemma-4-31B
354
+
355
+ Drydock is provider-agnostic, but its primary target is dense **Gemma-4-31B**.
356
+ Two proven ways to serve it on a 2×GPU box, both exposing an OpenAI-compatible
357
+ API on `:8000` as model `gemma4`:
358
+
359
+ **llama.cpp** — QAT GGUF, flexible concurrency (more slots if you need them):
360
+
361
+ ```
362
+ llama-server -m gemma-4-31B-it-qat-UD-Q4_K_XL.gguf \
363
+ -c 65536 -np 2 --host 0.0.0.0 --port 8000 --alias gemma4
364
+ ```
365
+
366
+ **vLLM** — w4a16 QAT, ~2× faster per request, 128K context:
367
+
368
+ ```
369
+ docker run -d --name vllm-prod --gpus all --ipc=host --restart unless-stopped \
370
+ -v /data3/Models:/models -p 8000:8000 \
371
+ -e NCCL_P2P_DISABLE=1 \
372
+ vllm/vllm-openai:v0.26.0 \
373
+ --model /models/gemma-4-31B-it-qat-w4a16-ct \
374
+ --served-model-name gemma4 \
375
+ --tensor-parallel-size 2 \
376
+ --max-model-len 131072 \
377
+ --max-num-seqs 2 \
378
+ --gpu-memory-utilization 0.97 \
379
+ --kv-cache-dtype fp8 \
380
+ --tool-call-parser gemma4 \
381
+ --enable-auto-tool-choice
382
+ ```
383
+
384
+ Point drydock at either with
385
+ `--provider vllm --base-url http://<host>:8000/v1 --model gemma4`.
386
+
387
+ **vLLM-on-Gemma-4 notes** (drydock handles these for you as of **3.1.7**):
388
+
389
+ - **`skip_special_tokens: false`** is sent on every request — without it, a turn
390
+ truncated at `max_tokens` (tool-call / reasoning tails) comes back with *empty*
391
+ content, which looks like a refusal. If `finish_reason == "length"`, retry with
392
+ a larger `max_tokens` (≥ 2000 for reasoning-heavy calls).
393
+ - **Reasoning is off by default.** Enable per-request via
394
+ `chat_template_kwargs.enable_thinking`; the vLLM reasoning parser is disabled,
395
+ so `<|channel>thought …` markers arrive inside `content` (stripped client-side).
396
+ - **`--max-num-seqs 2`** caps concurrency at 2 — the cost of fitting 128K context
397
+ into the VRAM. Use llama.cpp if you need more concurrent sessions than context.
398
+ - Tool-calling is the standard OpenAI format; `/props` is llama.cpp-only (vLLM
399
+ 404s it — drydock falls back to `/v1/models` for the context length).
400
+
346
401
  ## Using it
347
402
 
348
403
  Type a task and press **Enter**. Drydock reads/writes/edits files and runs
@@ -584,6 +584,17 @@ def stream(
584
584
  if config.get("temperature") is not None:
585
585
  kwargs["temperature"] = config["temperature"]
586
586
 
587
+ # vLLM-Gemma quirk: a turn truncated at max_tokens (esp. tool-call / reasoning
588
+ # turns, whose tail is special tokens) comes back with EMPTY content unless we
589
+ # send skip_special_tokens=false — and a checker-scored harness reads an empty
590
+ # turn as a FAILURE. Always send it for vLLM (harmless / ignored on llama.cpp),
591
+ # and floor an already-configured-but-tiny budget so reasoning turns don't
592
+ # truncate to nothing. We never impose a cap where none was set.
593
+ if provider == "vllm":
594
+ kwargs.setdefault("extra_body", {})["skip_special_tokens"] = False
595
+ if kwargs.get("max_tokens") and kwargs["max_tokens"] < 2000:
596
+ kwargs["max_tokens"] = 2000
597
+
587
598
  # Adaptive reasoning budget (harmony/gpt-oss style models accept this;
588
599
  # endpoints without the knob ignore the extra field). Set per turn by the
589
600
  # agent loop: high for planning, low for routine continuation.