drydock-cli 3.0.65__tar.gz → 3.0.66__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 (91) hide show
  1. {drydock_cli-3.0.65/drydock_cli.egg-info → drydock_cli-3.0.66}/PKG-INFO +1 -1
  2. drydock_cli-3.0.66/drydock/builtin_skills/stig-assess.md +24 -0
  3. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tui/app.py +38 -0
  4. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tui/widgets.py +2 -1
  5. {drydock_cli-3.0.65 → drydock_cli-3.0.66/drydock_cli.egg-info}/PKG-INFO +1 -1
  6. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock_cli.egg-info/SOURCES.txt +1 -0
  7. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/pyproject.toml +1 -1
  8. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_skills.py +1 -1
  9. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/LICENSE +0 -0
  10. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/NOTICE +0 -0
  11. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/README.md +0 -0
  12. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/__init__.py +0 -0
  13. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/__main__.py +0 -0
  14. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/agent.py +0 -0
  15. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/bash_safety.py +0 -0
  16. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/builtin_skills/__init__.py +0 -0
  17. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/builtin_skills/rmf-categorize.md +0 -0
  18. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/builtin_skills/rmf-control.md +0 -0
  19. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/builtin_skills/rmf-poam.md +0 -0
  20. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/builtin_skills/rmf-review.md +0 -0
  21. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/cli.py +0 -0
  22. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/compaction.py +0 -0
  23. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/config.py +0 -0
  24. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/detect.py +0 -0
  25. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/extract.py +0 -0
  26. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/gittools.py +0 -0
  27. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/graphrag.py +0 -0
  28. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/guards.py +0 -0
  29. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/loop_detect.py +0 -0
  30. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/mcp.py +0 -0
  31. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/providers.py +0 -0
  32. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/rmf.py +0 -0
  33. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/rmf_graph.py +0 -0
  34. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/skills.py +0 -0
  35. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/stig.py +0 -0
  36. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tool_registry.py +0 -0
  37. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tools/__init__.py +0 -0
  38. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tui/__init__.py +0 -0
  39. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tui/approval.py +0 -0
  40. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tui/messages.py +0 -0
  41. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/tuning.py +0 -0
  42. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock/web.py +0 -0
  43. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock_cli.egg-info/dependency_links.txt +0 -0
  44. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock_cli.egg-info/entry_points.txt +0 -0
  45. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock_cli.egg-info/requires.txt +0 -0
  46. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/drydock_cli.egg-info/top_level.txt +0 -0
  47. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/setup.cfg +0 -0
  48. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_approval.py +0 -0
  49. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_back_command.py +0 -0
  50. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_bash_output_bounding.py +0 -0
  51. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_bash_process_group.py +0 -0
  52. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_bash_safety.py +0 -0
  53. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_bash_timeout_network.py +0 -0
  54. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_cli_agents.py +0 -0
  55. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_compact_command.py +0 -0
  56. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_compaction.py +0 -0
  57. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_config.py +0 -0
  58. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_config_migration.py +0 -0
  59. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_context_limit_config.py +0 -0
  60. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_detect.py +0 -0
  61. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_dispatch.py +0 -0
  62. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_empty_response.py +0 -0
  63. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_extract.py +0 -0
  64. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_failure_loop.py +0 -0
  65. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_first_run_setup.py +0 -0
  66. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_gittools.py +0 -0
  67. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_graphrag.py +0 -0
  68. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_guards_and_tools.py +0 -0
  69. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_hallucinated_tools.py +0 -0
  70. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_leaked_tool_call.py +0 -0
  71. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_loop_detect.py +0 -0
  72. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_mcp.py +0 -0
  73. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_oneshot_unreachable.py +0 -0
  74. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_plan_autocontinue.py +0 -0
  75. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_providers_unreachable.py +0 -0
  76. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_read_index.py +0 -0
  77. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_rmf.py +0 -0
  78. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_rmf_graph.py +0 -0
  79. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_runaway_repetition.py +0 -0
  80. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_stig.py +0 -0
  81. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_stop.py +0 -0
  82. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_streaming_newlines.py +0 -0
  83. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_subagent.py +0 -0
  84. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_system_prompt_help.py +0 -0
  85. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_todo.py +0 -0
  86. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_tool_arg_parsing.py +0 -0
  87. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_tools_undo.py +0 -0
  88. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_tui.py +0 -0
  89. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_tuning.py +0 -0
  90. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_vision_input.py +0 -0
  91. {drydock_cli-3.0.65 → drydock_cli-3.0.66}/tests/test_web_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.0.65
3
+ Version: 3.0.66
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
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: stig-assess
3
+ description: Assess the next un-reviewed STIG rule against system evidence
4
+ ---
5
+ Assess STIG rules in the checklist at: $ARGS
6
+
7
+ Do exactly ONE rule per run (loop it — /loop N /stig-assess <path> — for the
8
+ whole checklist):
9
+
10
+ 1. Call StigRules with that path and status=not_reviewed. If none remain, say the
11
+ checklist is fully assessed and STOP without calling other tools.
12
+ 2. Take the FIRST not_reviewed rule. Call StigRule (path + rule_id) to read its
13
+ Check Content and Fix Text.
14
+ 3. You MUST gather fresh evidence before deciding — do NOT guess. Read the exact
15
+ configuration file the Check Content names (Read tool) or run its check command
16
+ (Bash). Quote the specific line(s) you found. Reason step by step about whether
17
+ that evidence satisfies the Check Content.
18
+ 4. Call StigSet (path + rule_id) with:
19
+ - status = not_a_finding ONLY if the evidence clearly shows compliance;
20
+ open if the evidence shows non-compliance;
21
+ not_applicable if the rule does not apply to this system;
22
+ - finding_details = the exact evidence you observed and why it does/doesn't
23
+ comply (quote the config line).
24
+ Give a one-line summary: rule id, the evidence line, and the status you set.
@@ -496,6 +496,7 @@ class DrydockApp(App):
496
496
  " /loop /loop <count> <prompt> — repeat a prompt (Esc stops)\n"
497
497
  " /mcp list connected MCP servers and their tools\n"
498
498
  " /rmf RMF automation — /rmf bootstrap, then /rmf-control etc.\n"
499
+ " /stig summarize a .ckl/.cklb; assess via /stig-assess\n"
499
500
  " /clear reset the conversation\n"
500
501
  " /quit exit\n"
501
502
  "Type a task and press Enter. ↑/↓ recall history · Esc stops · Ctrl+O expands tools."
@@ -504,6 +505,8 @@ class DrydockApp(App):
504
505
  self._cmd_mcp()
505
506
  elif cmd == "/rmf":
506
507
  self._cmd_rmf(arg)
508
+ elif cmd == "/stig":
509
+ self._cmd_stig(arg)
507
510
  elif cmd == "/loop":
508
511
  self._cmd_loop(arg)
509
512
  elif cmd == "/skills":
@@ -513,6 +516,41 @@ class DrydockApp(App):
513
516
  else:
514
517
  self._mount(ErrorMessage(f"unknown command: {cmd} (try /help)"))
515
518
 
519
+ def _cmd_stig(self, arg: str) -> None:
520
+ """Summarize a STIG checklist (.ckl/.cklb): asset + status counts, or list
521
+ rules of a given status. Assess it with /stig-assess (loop for the whole
522
+ checklist)."""
523
+ from drydock import stig
524
+
525
+ parts = arg.split()
526
+ if not parts:
527
+ self._info("usage: /stig <path-to.ckl|.cklb> [status] "
528
+ "(status: open|not_a_finding|not_applicable|not_reviewed)\n"
529
+ "Assess it: /loop <n> /stig-assess <path>")
530
+ return
531
+ import os as _os
532
+ path = parts[0]
533
+ if not _os.path.isabs(path):
534
+ path = _os.path.join(self.config.get("cwd") or ".", path)
535
+ try:
536
+ cl = stig.load(path)
537
+ except Exception as e: # noqa: BLE001
538
+ self._mount(ErrorMessage(f"could not read checklist: {e}"))
539
+ return
540
+ host = cl.asset.get("HOST_NAME") or cl.asset.get("host_name") or "?"
541
+ c = cl.counts()
542
+ lines = [f"STIG checklist {path} (host: {host}, format: {cl.fmt})",
543
+ f" {len(cl.rules)} rules — " + " · ".join(f"{k}={v}" for k, v in c.items())]
544
+ if len(parts) > 1:
545
+ sf = stig.canonical_status(parts[1])
546
+ hits = [r for r in cl.rules if r.status == sf]
547
+ lines.append(f"\n{sf} ({len(hits)}):")
548
+ lines += [f" {r.group_id} ({r.severity}) — {r.title}" for r in hits[:50]]
549
+ else:
550
+ lines.append("Assess un-reviewed rules: /loop "
551
+ f"{c.get('not_reviewed', 0) or 1} /stig-assess {parts[0]}")
552
+ self._info("\n".join(lines))
553
+
516
554
  def _cmd_rmf(self, arg: str) -> None:
517
555
  """RMF automation: bootstrap the NIST 800-53 catalog into the knowledge
518
556
  base and surface the bundled RMF skills."""
@@ -153,7 +153,8 @@ class PromptHistory:
153
153
  # completes the prefix.
154
154
  SLASH_COMMANDS = [
155
155
  "/help", "/model", "/cwd", "/undo", "/back", "/stop", "/status",
156
- "/compact", "/graphrag", "/skills", "/loop", "/mcp", "/rmf", "/clear", "/quit",
156
+ "/compact", "/graphrag", "/skills", "/loop", "/mcp", "/rmf", "/stig",
157
+ "/clear", "/quit",
157
158
  ]
158
159
 
159
160
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: drydock-cli
3
- Version: 3.0.65
3
+ Version: 3.0.66
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
@@ -29,6 +29,7 @@ drydock/builtin_skills/rmf-categorize.md
29
29
  drydock/builtin_skills/rmf-control.md
30
30
  drydock/builtin_skills/rmf-poam.md
31
31
  drydock/builtin_skills/rmf-review.md
32
+ drydock/builtin_skills/stig-assess.md
32
33
  drydock/tools/__init__.py
33
34
  drydock/tui/__init__.py
34
35
  drydock/tui/app.py
@@ -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.0.65"
10
+ version = "3.0.66"
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"
@@ -55,7 +55,7 @@ def test_empty_body_skipped(tmp_path):
55
55
  def test_no_user_or_project_skills_yields_only_builtins(tmp_path):
56
56
  # With no user/project skills, only the bundled built-ins (RMF) are present.
57
57
  loaded = skills.load_skills(str(tmp_path))
58
- assert set(loaded) == {"rmf-control", "rmf-categorize", "rmf-review", "rmf-poam"}
58
+ assert set(loaded) == {"rmf-control", "rmf-categorize", "rmf-review", "rmf-poam", "stig-assess"}
59
59
 
60
60
 
61
61
  def test_create_skill_user_scope(tmp_path, monkeypatch):
File without changes
File without changes
File without changes
File without changes