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