control-tower 6.0.0rc3__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 (481) hide show
  1. control_tower-6.0.0rc3/LICENSE +21 -0
  2. control_tower-6.0.0rc3/MANIFEST.in +2 -0
  3. control_tower-6.0.0rc3/PKG-INFO +88 -0
  4. control_tower-6.0.0rc3/README.md +35 -0
  5. control_tower-6.0.0rc3/pyproject.toml +229 -0
  6. control_tower-6.0.0rc3/setup.cfg +4 -0
  7. control_tower-6.0.0rc3/src/control_tower/__init__.py +3 -0
  8. control_tower-6.0.0rc3/src/control_tower/cli/__init__.py +3 -0
  9. control_tower-6.0.0rc3/src/control_tower/cli/base.py +215 -0
  10. control_tower-6.0.0rc3/src/control_tower/cli/cloud.py +132 -0
  11. control_tower-6.0.0rc3/src/control_tower/cli/completions/completion_callbacks.py +125 -0
  12. control_tower-6.0.0rc3/src/control_tower/cli/completions/completions_build.py +59 -0
  13. control_tower-6.0.0rc3/src/control_tower/cli/completions/completions_hooks.py +209 -0
  14. control_tower-6.0.0rc3/src/control_tower/cli/ct_cli_group.py +28 -0
  15. control_tower-6.0.0rc3/src/control_tower/cli/extras.py +89 -0
  16. control_tower-6.0.0rc3/src/control_tower/cli/login.py +77 -0
  17. control_tower-6.0.0rc3/src/control_tower/cli/main.py +44 -0
  18. control_tower-6.0.0rc3/src/control_tower/cli/mcp_meta.py +30 -0
  19. control_tower-6.0.0rc3/src/control_tower/cli/task_sets.py +133 -0
  20. control_tower-6.0.0rc3/src/control_tower/ct_runs/__init__.py +0 -0
  21. control_tower-6.0.0rc3/src/control_tower/ct_runs/claude_host.py +26 -0
  22. control_tower-6.0.0rc3/src/control_tower/ct_runs/dashboard.py +265 -0
  23. control_tower-6.0.0rc3/src/control_tower/ct_runs/dashboard_cli.py +19 -0
  24. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/__init__.py +0 -0
  25. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/README.md +80 -0
  26. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/__init__.py +0 -0
  27. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/cli.py +81 -0
  28. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/models.py +63 -0
  29. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/prompts/system.md +68 -0
  30. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/prompts/user.md +30 -0
  31. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/audit/task.py +278 -0
  32. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/generate/README.md +75 -0
  33. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/generate/cli.py +146 -0
  34. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/generate/prompts/system.md +62 -0
  35. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/generate/prompts/user.md +21 -0
  36. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/generate/task.py +361 -0
  37. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/shared/concurrency.py +72 -0
  38. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/shared/spec.md +79 -0
  39. control_tower-6.0.0rc3/src/control_tower/ct_runs/env_description/shared/spec_loader.py +24 -0
  40. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/README.md +59 -0
  41. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/cli.py +115 -0
  42. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/prompts/analyze.md +44 -0
  43. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/prompts/check_tasks.md +29 -0
  44. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/prompts/coverage.md +27 -0
  45. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/prompts/fix.md +14 -0
  46. control_tower-6.0.0rc3/src/control_tower/ct_runs/integration_test_quality/task.py +160 -0
  47. control_tower-6.0.0rc3/src/control_tower/ct_runs/pairing_analysis/README.md +30 -0
  48. control_tower-6.0.0rc3/src/control_tower/ct_runs/pairing_analysis/cli.py +82 -0
  49. control_tower-6.0.0rc3/src/control_tower/ct_runs/pairing_analysis/prompts/turn1.md +59 -0
  50. control_tower-6.0.0rc3/src/control_tower/ct_runs/pairing_analysis/prompts/turn2.md +43 -0
  51. control_tower-6.0.0rc3/src/control_tower/ct_runs/pairing_analysis/task.py +390 -0
  52. control_tower-6.0.0rc3/src/control_tower/ct_runs/prompts.py +28 -0
  53. control_tower-6.0.0rc3/src/control_tower/ct_runs/run_cli.py +16 -0
  54. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/base.py +216 -0
  55. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/_json.py +31 -0
  56. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/chroma.py +285 -0
  57. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/docker.py +366 -0
  58. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/elasticsearch.py +293 -0
  59. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/filesystem.py +155 -0
  60. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/generated_manifest.json +13 -0
  61. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/influxdb.py +549 -0
  62. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/listener.py +82 -0
  63. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/minio.py +360 -0
  64. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/mongo.py +338 -0
  65. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/openldap.py +241 -0
  66. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/postgres.py +317 -0
  67. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/process.py +134 -0
  68. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/rabbitmq.py +369 -0
  69. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/redis.py +291 -0
  70. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/sqlite.py +309 -0
  71. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/sshd.py +270 -0
  72. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/checks/vault.py +376 -0
  73. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/cli.py +560 -0
  74. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/compose_analyzer.py +182 -0
  75. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/detection.py +236 -0
  76. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/dockerfile_analyzer.py +377 -0
  77. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/llm_generator.py +448 -0
  78. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/runner.py +445 -0
  79. control_tower-6.0.0rc3/src/control_tower/ct_runs/scorer_idempotency/runtime_prober.py +378 -0
  80. control_tower-6.0.0rc3/src/control_tower/ct_runs/storage.py +74 -0
  81. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/compare_side_tasks/README.md +25 -0
  82. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/compare_side_tasks/cli.py +25 -0
  83. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/compare_side_tasks/task.py +126 -0
  84. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/README.md +77 -0
  85. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/audits/base.py +129 -0
  86. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/audits/goal.py +95 -0
  87. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/audits/sd.py +103 -0
  88. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/cli.py +207 -0
  89. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/heuristics/base.py +53 -0
  90. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/heuristics/goal.py +215 -0
  91. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/heuristics/sd.py +222 -0
  92. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/prompts/goal/system.md +109 -0
  93. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/prompts/goal/user.md +21 -0
  94. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/prompts/sd/system.md +311 -0
  95. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/prompts/sd/user.md +26 -0
  96. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/sd_audit_labels.json +98 -0
  97. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/doc_audit/task.py +227 -0
  98. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/failure_type_audit/cli.py +138 -0
  99. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/failure_type_audit/prompts/system.md +9 -0
  100. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/failure_type_audit/prompts/user.md +21 -0
  101. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/failure_type_audit/task.py +227 -0
  102. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/goal_completeness/README.md +56 -0
  103. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/goal_completeness/cli.py +125 -0
  104. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/goal_completeness/prompts/system.md +46 -0
  105. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/goal_completeness/prompts/user.md +60 -0
  106. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/goal_completeness/task.py +358 -0
  107. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/goal_completeness/viewer.py +142 -0
  108. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/reward_hacking/README.md +46 -0
  109. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/reward_hacking/cli.py +115 -0
  110. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/reward_hacking/prompts/system.md +71 -0
  111. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/reward_hacking/prompts/user.md +62 -0
  112. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/reward_hacking/task.py +388 -0
  113. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/reward_hacking/viewer.py +122 -0
  114. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/rt_alignment/README.md +45 -0
  115. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/rt_alignment/cli.py +119 -0
  116. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/rt_alignment/prompts/system.md +50 -0
  117. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/rt_alignment/prompts/user.md +57 -0
  118. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/rt_alignment/task.py +387 -0
  119. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/rt_alignment/viewer.py +128 -0
  120. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/side_task_review/README.md +47 -0
  121. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/side_task_review/cli.py +95 -0
  122. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/side_task_review/prompts/review.md +29 -0
  123. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/side_task_review/task.py +101 -0
  124. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/validate_cover/README.md +32 -0
  125. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/validate_cover/cli.py +97 -0
  126. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/validate_cover/task.py +94 -0
  127. control_tower-6.0.0rc3/src/control_tower/ct_runs/task_analysis/validate_cover/validate_cover_prompt.md +35 -0
  128. control_tower-6.0.0rc3/src/control_tower/ct_runs/timing_report/__init__.py +17 -0
  129. control_tower-6.0.0rc3/src/control_tower/ct_runs/timing_report/cli.py +71 -0
  130. control_tower-6.0.0rc3/src/control_tower/ct_runs/timing_report/report.py +327 -0
  131. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability/README.md +49 -0
  132. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability/cli.py +125 -0
  133. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability/prompts/system.md +29 -0
  134. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability/prompts/user.md +72 -0
  135. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability/task.py +402 -0
  136. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability/viewer.py +159 -0
  137. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability_verified/README.md +52 -0
  138. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability_verified/cli.py +143 -0
  139. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability_verified/prompts/system.md +36 -0
  140. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability_verified/prompts/user.md +63 -0
  141. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability_verified/task.py +762 -0
  142. control_tower-6.0.0rc3/src/control_tower/ct_runs/traj_analysis/submit_guessability_verified/viewer.py +186 -0
  143. control_tower-6.0.0rc3/src/control_tower/datasets/__init__.py +0 -0
  144. control_tower-6.0.0rc3/src/control_tower/datasets/check.py +88 -0
  145. control_tower-6.0.0rc3/src/control_tower/datasets/cli.py +532 -0
  146. control_tower-6.0.0rc3/src/control_tower/datasets/external.py +648 -0
  147. control_tower-6.0.0rc3/src/control_tower/datasets/importers/__init__.py +42 -0
  148. control_tower-6.0.0rc3/src/control_tower/datasets/importers/eval_log.py +570 -0
  149. control_tower-6.0.0rc3/src/control_tower/datasets/importers/monitoring_bench.py +643 -0
  150. control_tower-6.0.0rc3/src/control_tower/datasets/importers/mythos_5_incident.py +243 -0
  151. control_tower-6.0.0rc3/src/control_tower/datasets/importers/shade_arena.py +590 -0
  152. control_tower-6.0.0rc3/src/control_tower/datasets/importers/sleight_bench.py +489 -0
  153. control_tower-6.0.0rc3/src/control_tower/datasets/model.py +45 -0
  154. control_tower-6.0.0rc3/src/control_tower/defaults.py +16 -0
  155. control_tower-6.0.0rc3/src/control_tower/environments/build.py +204 -0
  156. control_tower-6.0.0rc3/src/control_tower/environments/env_args.py +128 -0
  157. control_tower-6.0.0rc3/src/control_tower/environments/environment.py +130 -0
  158. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/.dockerignore +2 -0
  159. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/Dockerfile +91 -0
  160. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/__init__.py +0 -0
  161. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/__main__.py +4 -0
  162. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/compose.yml +35 -0
  163. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/constants.py +43 -0
  164. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/assets.py +276 -0
  165. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/generate_ca.py +68 -0
  166. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/logs.py +241 -0
  167. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/network_mapping.py +24 -0
  168. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/tls.py +124 -0
  169. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/trajectory.py +17 -0
  170. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/core/webhook.py +213 -0
  171. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/env_values.py +17 -0
  172. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/malware/malware.c +143 -0
  173. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/modules/forward_proxy.py +425 -0
  174. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/modules/resolver.py +88 -0
  175. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/modules/response_rules.py +192 -0
  176. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/modules/shell_sessions.py +206 -0
  177. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/modules/upstream_proxy.py +256 -0
  178. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/modules/upstream_specs.py +200 -0
  179. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/personas.py +150 -0
  180. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/requirements.txt +4 -0
  181. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/resolve_override.c +75 -0
  182. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/runtimes/__init__.py +0 -0
  183. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/runtimes/docker.py +2154 -0
  184. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/runtimes/hawk.py +173 -0
  185. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/runtimes/participants.py +30 -0
  186. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/runtimes/provisioning.py +44 -0
  187. control_tower-6.0.0rc3/src/control_tower/environments/internet_simulator/server.py +600 -0
  188. control_tower-6.0.0rc3/src/control_tower/environments/list_utils.py +562 -0
  189. control_tower-6.0.0rc3/src/control_tower/environments/registry.py +302 -0
  190. control_tower-6.0.0rc3/src/control_tower/environments/remote/__init__.py +0 -0
  191. control_tower-6.0.0rc3/src/control_tower/environments/remote/json_model.py +82 -0
  192. control_tower-6.0.0rc3/src/control_tower/environments/remote/process.py +238 -0
  193. control_tower-6.0.0rc3/src/control_tower/environments/remote/remote.py +463 -0
  194. control_tower-6.0.0rc3/src/control_tower/environments/remote/sample.py +289 -0
  195. control_tower-6.0.0rc3/src/control_tower/environments/requirements.py +174 -0
  196. control_tower-6.0.0rc3/src/control_tower/environments/setting_runtime.py +173 -0
  197. control_tower-6.0.0rc3/src/control_tower/environments/settings.py +1222 -0
  198. control_tower-6.0.0rc3/src/control_tower/environments/settings.yml +24 -0
  199. control_tower-6.0.0rc3/src/control_tower/environments/settings_cli.py +642 -0
  200. control_tower-6.0.0rc3/src/control_tower/environments/source_utils.py +304 -0
  201. control_tower-6.0.0rc3/src/control_tower/environments/validate.py +141 -0
  202. control_tower-6.0.0rc3/src/control_tower/eval/README.md +38 -0
  203. control_tower-6.0.0rc3/src/control_tower/eval/__init__.py +11 -0
  204. control_tower-6.0.0rc3/src/control_tower/eval/blue.py +537 -0
  205. control_tower-6.0.0rc3/src/control_tower/eval/cli.py +563 -0
  206. control_tower-6.0.0rc3/src/control_tower/eval/dataset.py +810 -0
  207. control_tower-6.0.0rc3/src/control_tower/eval/dispatch.py +514 -0
  208. control_tower-6.0.0rc3/src/control_tower/eval/game_view.py +28 -0
  209. control_tower-6.0.0rc3/src/control_tower/eval/harness.py +151 -0
  210. control_tower-6.0.0rc3/src/control_tower/eval/history.py +224 -0
  211. control_tower-6.0.0rc3/src/control_tower/eval/metadata.py +43 -0
  212. control_tower-6.0.0rc3/src/control_tower/eval/monitor_cli.py +143 -0
  213. control_tower-6.0.0rc3/src/control_tower/eval/monitor_task.py +156 -0
  214. control_tower-6.0.0rc3/src/control_tower/eval/monitoring/__init__.py +5 -0
  215. control_tower-6.0.0rc3/src/control_tower/eval/monitoring/monitor.py +301 -0
  216. control_tower-6.0.0rc3/src/control_tower/eval/monitoring/posthoc.py +248 -0
  217. control_tower-6.0.0rc3/src/control_tower/eval/options.py +122 -0
  218. control_tower-6.0.0rc3/src/control_tower/eval/protocols_cli.py +140 -0
  219. control_tower-6.0.0rc3/src/control_tower/eval/red.py +328 -0
  220. control_tower-6.0.0rc3/src/control_tower/eval/registry.py +59 -0
  221. control_tower-6.0.0rc3/src/control_tower/eval/run.py +409 -0
  222. control_tower-6.0.0rc3/src/control_tower/eval/solver.py +167 -0
  223. control_tower-6.0.0rc3/src/control_tower/eval/task.py +54 -0
  224. control_tower-6.0.0rc3/src/control_tower/eval/task_messages.py +55 -0
  225. control_tower-6.0.0rc3/src/control_tower/eval/task_scorer_validation.py +90 -0
  226. control_tower-6.0.0rc3/src/control_tower/eval/task_selection.py +284 -0
  227. control_tower-6.0.0rc3/src/control_tower/eval/white.py +71 -0
  228. control_tower-6.0.0rc3/src/control_tower/eval_logs/__init__.py +0 -0
  229. control_tower-6.0.0rc3/src/control_tower/eval_logs/api_upload.py +216 -0
  230. control_tower-6.0.0rc3/src/control_tower/eval_logs/convert.py +1173 -0
  231. control_tower-6.0.0rc3/src/control_tower/eval_logs/io.py +211 -0
  232. control_tower-6.0.0rc3/src/control_tower/eval_logs/merge.py +93 -0
  233. control_tower-6.0.0rc3/src/control_tower/eval_logs/monitor_scores.py +13 -0
  234. control_tower-6.0.0rc3/src/control_tower/eval_logs/run_metadata.py +15 -0
  235. control_tower-6.0.0rc3/src/control_tower/eval_logs/s3_upload.py +167 -0
  236. control_tower-6.0.0rc3/src/control_tower/eval_logs/seat.py +85 -0
  237. control_tower-6.0.0rc3/src/control_tower/eval_logs/source.py +51 -0
  238. control_tower-6.0.0rc3/src/control_tower/eval_logs/utils.py +85 -0
  239. control_tower-6.0.0rc3/src/control_tower/fleet/__init__.py +1 -0
  240. control_tower-6.0.0rc3/src/control_tower/fleet/ami.py +62 -0
  241. control_tower-6.0.0rc3/src/control_tower/fleet/aws_identity.py +9 -0
  242. control_tower-6.0.0rc3/src/control_tower/fleet/bootstrap.sh +395 -0
  243. control_tower-6.0.0rc3/src/control_tower/fleet/controller.py +2359 -0
  244. control_tower-6.0.0rc3/src/control_tower/fleet/job.py +371 -0
  245. control_tower-6.0.0rc3/src/control_tower/fleet/run_job.py +253 -0
  246. control_tower-6.0.0rc3/src/control_tower/fleet/worker.py +1094 -0
  247. control_tower-6.0.0rc3/src/control_tower/fleet/worker_cli.py +68 -0
  248. control_tower-6.0.0rc3/src/control_tower/hawk/__init__.py +11 -0
  249. control_tower-6.0.0rc3/src/control_tower/hawk/config.py +92 -0
  250. control_tower-6.0.0rc3/src/control_tower/hawk/download.py +93 -0
  251. control_tower-6.0.0rc3/src/control_tower/hawk/middleman.py +56 -0
  252. control_tower-6.0.0rc3/src/control_tower/hawk/model_closure.py +33 -0
  253. control_tower-6.0.0rc3/src/control_tower/hawk/preflight.py +161 -0
  254. control_tower-6.0.0rc3/src/control_tower/hawk/pull_envs.py +95 -0
  255. control_tower-6.0.0rc3/src/control_tower/hawk/runner.py +1038 -0
  256. control_tower-6.0.0rc3/src/control_tower/hawk/sandbox.py +472 -0
  257. control_tower-6.0.0rc3/src/control_tower/hawk/yaml_generator.py +215 -0
  258. control_tower-6.0.0rc3/src/control_tower/inspect_tasks.py +271 -0
  259. control_tower-6.0.0rc3/src/control_tower/live/__init__.py +0 -0
  260. control_tower-6.0.0rc3/src/control_tower/live/agents.py +717 -0
  261. control_tower-6.0.0rc3/src/control_tower/live/assets/dev_container_extensions.json +3 -0
  262. control_tower-6.0.0rc3/src/control_tower/live/assets/pyrightconfig.json +4 -0
  263. control_tower-6.0.0rc3/src/control_tower/live/assets/settings.json +3 -0
  264. control_tower-6.0.0rc3/src/control_tower/live/cli.py +1045 -0
  265. control_tower-6.0.0rc3/src/control_tower/live/compose.py +272 -0
  266. control_tower-6.0.0rc3/src/control_tower/live/context/print_context.py +98 -0
  267. control_tower-6.0.0rc3/src/control_tower/live/context/task_getters.py +78 -0
  268. control_tower-6.0.0rc3/src/control_tower/live/context/traj_dir.py +326 -0
  269. control_tower-6.0.0rc3/src/control_tower/live/daemon.py +545 -0
  270. control_tower-6.0.0rc3/src/control_tower/live/integration_tests.py +96 -0
  271. control_tower-6.0.0rc3/src/control_tower/live/remote_sandbox.py +154 -0
  272. control_tower-6.0.0rc3/src/control_tower/live/rpc.py +55 -0
  273. control_tower-6.0.0rc3/src/control_tower/live/sandbox_ops.py +129 -0
  274. control_tower-6.0.0rc3/src/control_tower/live/score.py +366 -0
  275. control_tower-6.0.0rc3/src/control_tower/live/session.py +733 -0
  276. control_tower-6.0.0rc3/src/control_tower/live/setup.py +299 -0
  277. control_tower-6.0.0rc3/src/control_tower/live/task_state.py +139 -0
  278. control_tower-6.0.0rc3/src/control_tower/live/test.py +10 -0
  279. control_tower-6.0.0rc3/src/control_tower/live/traj/__init__.py +0 -0
  280. control_tower-6.0.0rc3/src/control_tower/live/traj/gen_traj.py +345 -0
  281. control_tower-6.0.0rc3/src/control_tower/live/traj/git_status.py +33 -0
  282. control_tower-6.0.0rc3/src/control_tower/live/traj/git_traj.py +748 -0
  283. control_tower-6.0.0rc3/src/control_tower/live/traj/git_traj_helpers/FORMAT.md +25 -0
  284. control_tower-6.0.0rc3/src/control_tower/live/traj/git_traj_helpers/call_insert.py +15 -0
  285. control_tower-6.0.0rc3/src/control_tower/live/traj/git_traj_helpers/call_str_replace.py +20 -0
  286. control_tower-6.0.0rc3/src/control_tower/live/traj/macros.py +117 -0
  287. control_tower-6.0.0rc3/src/control_tower/live/traj/solution.py +265 -0
  288. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/add.py +14 -0
  289. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/add_tool_call.py +98 -0
  290. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/bash.py +128 -0
  291. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/git_utils.py +93 -0
  292. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/input_utils.py +145 -0
  293. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/template_from.py +118 -0
  294. control_tower-6.0.0rc3/src/control_tower/live/traj/templ/tool_call_builder.py +119 -0
  295. control_tower-6.0.0rc3/src/control_tower/live/traj/tool_call_utils.py +289 -0
  296. control_tower-6.0.0rc3/src/control_tower/live/traj/traj.py +316 -0
  297. control_tower-6.0.0rc3/src/control_tower/live/tui/__init__.py +0 -0
  298. control_tower-6.0.0rc3/src/control_tower/live/tui/popup.py +293 -0
  299. control_tower-6.0.0rc3/src/control_tower/live/tui/tui.py +1237 -0
  300. control_tower-6.0.0rc3/src/control_tower/live/tui/tui.tcss +32 -0
  301. control_tower-6.0.0rc3/src/control_tower/live/usage/collect_testers.py +130 -0
  302. control_tower-6.0.0rc3/src/control_tower/live/usage/commands.py +313 -0
  303. control_tower-6.0.0rc3/src/control_tower/live/usage/full_env_context/container_script.py +230 -0
  304. control_tower-6.0.0rc3/src/control_tower/live/usage/full_env_context/full_env_context.py +68 -0
  305. control_tower-6.0.0rc3/src/control_tower/live/usage/migrate_traj.py +83 -0
  306. control_tower-6.0.0rc3/src/control_tower/live/usage/patch.py +64 -0
  307. control_tower-6.0.0rc3/src/control_tower/live/usage/test_all.py +1349 -0
  308. control_tower-6.0.0rc3/src/control_tower/live/usage/upload_helpers.py +31 -0
  309. control_tower-6.0.0rc3/src/control_tower/metrics/__init__.py +0 -0
  310. control_tower-6.0.0rc3/src/control_tower/metrics/audit.py +353 -0
  311. control_tower-6.0.0rc3/src/control_tower/metrics/control.py +110 -0
  312. control_tower-6.0.0rc3/src/control_tower/models/__init__.py +11 -0
  313. control_tower-6.0.0rc3/src/control_tower/models/aliases.py +59 -0
  314. control_tower-6.0.0rc3/src/control_tower/models/cache_scopes.py +26 -0
  315. control_tower-6.0.0rc3/src/control_tower/models/inspect_rates.py +32 -0
  316. control_tower-6.0.0rc3/src/control_tower/models/model_spec.py +284 -0
  317. control_tower-6.0.0rc3/src/control_tower/models/openrouter_provider.py +65 -0
  318. control_tower-6.0.0rc3/src/control_tower/models/pricing.py +168 -0
  319. control_tower-6.0.0rc3/src/control_tower/models/rates.py +290 -0
  320. control_tower-6.0.0rc3/src/control_tower/models/registry_hooks.py +166 -0
  321. control_tower-6.0.0rc3/src/control_tower/models/role_model.py +55 -0
  322. control_tower-6.0.0rc3/src/control_tower/models/usage_hooks.py +14 -0
  323. control_tower-6.0.0rc3/src/control_tower/monitors/__init__.py +36 -0
  324. control_tower-6.0.0rc3/src/control_tower/monitors/checklist.py +96 -0
  325. control_tower-6.0.0rc3/src/control_tower/monitors/jev.py +198 -0
  326. control_tower-6.0.0rc3/src/control_tower/monitors/jev_questions.yml +32 -0
  327. control_tower-6.0.0rc3/src/control_tower/monitors/monitor.py +466 -0
  328. control_tower-6.0.0rc3/src/control_tower/monitors/presets.yml +28 -0
  329. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/action-no-goals.md +75 -0
  330. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/action.md +83 -0
  331. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/goal-analysis.md +77 -0
  332. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/goals.md +82 -0
  333. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/no-history.md +42 -0
  334. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/orthogonal.md +107 -0
  335. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/quick-no-goals.md +62 -0
  336. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/quick.md +68 -0
  337. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/simple.md +21 -0
  338. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/strong-goals.md +104 -0
  339. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/strong.md +95 -0
  340. control_tower-6.0.0rc3/src/control_tower/monitors/prompts/trajectory.md +18 -0
  341. control_tower-6.0.0rc3/src/control_tower/monitors/registry.py +19 -0
  342. control_tower-6.0.0rc3/src/control_tower/monitors/single_goal.py +96 -0
  343. control_tower-6.0.0rc3/src/control_tower/monitors/steps/checklist.md +48 -0
  344. control_tower-6.0.0rc3/src/control_tower/monitors/steps/single_goal.md +80 -0
  345. control_tower-6.0.0rc3/src/control_tower/monitors/steps/single_goal_analysis.md +76 -0
  346. control_tower-6.0.0rc3/src/control_tower/monitors/steps/three_scores.md +112 -0
  347. control_tower-6.0.0rc3/src/control_tower/monitors/three_scores.py +69 -0
  348. control_tower-6.0.0rc3/src/control_tower/policies/__init__.py +1 -0
  349. control_tower-6.0.0rc3/src/control_tower/policies/attack.py +199 -0
  350. control_tower-6.0.0rc3/src/control_tower/policies/honest.py +28 -0
  351. control_tower-6.0.0rc3/src/control_tower/policies/obvious_attack.py +69 -0
  352. control_tower-6.0.0rc3/src/control_tower/policies/prompts/attack.md +7 -0
  353. control_tower-6.0.0rc3/src/control_tower/policies/prompts/attack_planning.md +22 -0
  354. control_tower-6.0.0rc3/src/control_tower/policies/replay.py +227 -0
  355. control_tower-6.0.0rc3/src/control_tower/policies/scripted.py +123 -0
  356. control_tower-6.0.0rc3/src/control_tower/protocols/__init__.py +1 -0
  357. control_tower-6.0.0rc3/src/control_tower/protocols/block_all.py +43 -0
  358. control_tower-6.0.0rc3/src/control_tower/protocols/block_every_other.py +44 -0
  359. control_tower-6.0.0rc3/src/control_tower/protocols/defer_to_trusted.py +152 -0
  360. control_tower-6.0.0rc3/src/control_tower/protocols/null_blue.py +33 -0
  361. control_tower-6.0.0rc3/src/control_tower/protocols/prompts/trusted_editing.md +9 -0
  362. control_tower-6.0.0rc3/src/control_tower/protocols/resample.py +83 -0
  363. control_tower-6.0.0rc3/src/control_tower/protocols/trusted_editing.py +167 -0
  364. control_tower-6.0.0rc3/src/control_tower/protocols/trusted_monitoring.py +116 -0
  365. control_tower-6.0.0rc3/src/control_tower/protocols/watcher.py +341 -0
  366. control_tower-6.0.0rc3/src/control_tower/py.typed +0 -0
  367. control_tower-6.0.0rc3/src/control_tower/runs/README.md +85 -0
  368. control_tower-6.0.0rc3/src/control_tower/runs/convert.py +102 -0
  369. control_tower-6.0.0rc3/src/control_tower/runs/convert_eval_log_to_run.py +91 -0
  370. control_tower-6.0.0rc3/src/control_tower/runs/io.py +189 -0
  371. control_tower-6.0.0rc3/src/control_tower/runs/models.py +123 -0
  372. control_tower-6.0.0rc3/src/control_tower/runs/producer.py +4 -0
  373. control_tower-6.0.0rc3/src/control_tower/runs/runs_cli.py +679 -0
  374. control_tower-6.0.0rc3/src/control_tower/sandbox/__init__.py +6 -0
  375. control_tower-6.0.0rc3/src/control_tower/sandbox/_alpine_rootfs.py +230 -0
  376. control_tower-6.0.0rc3/src/control_tower/sandbox/_ssh.py +426 -0
  377. control_tower-6.0.0rc3/src/control_tower/sandbox/cli.py +301 -0
  378. control_tower-6.0.0rc3/src/control_tower/sandbox/constants.py +33 -0
  379. control_tower-6.0.0rc3/src/control_tower/sandbox/docker.py +1024 -0
  380. control_tower-6.0.0rc3/src/control_tower/sandbox/docker_in_vm.py +517 -0
  381. control_tower-6.0.0rc3/src/control_tower/sandbox/firecracker.py +413 -0
  382. control_tower-6.0.0rc3/src/control_tower/sandbox/inspect_tools.py +39 -0
  383. control_tower-6.0.0rc3/src/control_tower/sandbox/intranet.py +226 -0
  384. control_tower-6.0.0rc3/src/control_tower/sandbox/intranet_guard/Dockerfile +4 -0
  385. control_tower-6.0.0rc3/src/control_tower/sandbox/intranet_guard/firewall.sh +110 -0
  386. control_tower-6.0.0rc3/src/control_tower/sandbox/qemu.py +292 -0
  387. control_tower-6.0.0rc3/src/control_tower/sandbox/replay/__init__.py +22 -0
  388. control_tower-6.0.0rc3/src/control_tower/sandbox/replay/environment.py +435 -0
  389. control_tower-6.0.0rc3/src/control_tower/sandbox/replay/score.py +37 -0
  390. control_tower-6.0.0rc3/src/control_tower/sandbox/shared_containers.py +325 -0
  391. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/__init__.py +20 -0
  392. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/actions.py +90 -0
  393. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/compose.py +166 -0
  394. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/environment.py +182 -0
  395. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/judge.py +159 -0
  396. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/prompts/judge.md +31 -0
  397. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/prompts/simulator.md +74 -0
  398. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/prompts/simulator_no_exec.md +22 -0
  399. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/scratch/compose.yaml +42 -0
  400. control_tower-6.0.0rc3/src/control_tower/sandbox/simulated/session.py +156 -0
  401. control_tower-6.0.0rc3/src/control_tower/scanners.py +123 -0
  402. control_tower-6.0.0rc3/src/control_tower/task/__init__.py +0 -0
  403. control_tower-6.0.0rc3/src/control_tower/task/collection.py +64 -0
  404. control_tower-6.0.0rc3/src/control_tower/task/final_diff.py +88 -0
  405. control_tower-6.0.0rc3/src/control_tower/task/sample_metadata.py +35 -0
  406. control_tower-6.0.0rc3/src/control_tower/task/scorers.py +351 -0
  407. control_tower-6.0.0rc3/src/control_tower/task/select_utils.py +106 -0
  408. control_tower-6.0.0rc3/src/control_tower/task/selectors.py +49 -0
  409. control_tower-6.0.0rc3/src/control_tower/task/setup.py +96 -0
  410. control_tower-6.0.0rc3/src/control_tower/task/space.py +21 -0
  411. control_tower-6.0.0rc3/src/control_tower/task/strat_sets/model_registry_strats.txt +11 -0
  412. control_tower-6.0.0rc3/src/control_tower/task/task.py +456 -0
  413. control_tower-6.0.0rc3/src/control_tower/task/task_sets/__init__.py +176 -0
  414. control_tower-6.0.0rc3/src/control_tower/task/traj_dir.py +39 -0
  415. control_tower-6.0.0rc3/src/control_tower/task/workspace_baseline.py +581 -0
  416. control_tower-6.0.0rc3/src/control_tower/tools/__init__.py +0 -0
  417. control_tower-6.0.0rc3/src/control_tower/tools/answer.py +53 -0
  418. control_tower-6.0.0rc3/src/control_tower/tools/bash_tools.py +37 -0
  419. control_tower-6.0.0rc3/src/control_tower/tools/declarations.py +23 -0
  420. control_tower-6.0.0rc3/src/control_tower/tools/diff_display_text_editor.py +66 -0
  421. control_tower-6.0.0rc3/src/control_tower/tools/registry.py +37 -0
  422. control_tower-6.0.0rc3/src/control_tower/tools/split_text_editor_tools.py +125 -0
  423. control_tower-6.0.0rc3/src/control_tower/tools/submit.py +35 -0
  424. control_tower-6.0.0rc3/src/control_tower/tools/task_tools.py +237 -0
  425. control_tower-6.0.0rc3/src/control_tower/tools/tool_calls.py +46 -0
  426. control_tower-6.0.0rc3/src/control_tower/tools/tool_registry.py +371 -0
  427. control_tower-6.0.0rc3/src/control_tower/trajectories/README.md +76 -0
  428. control_tower-6.0.0rc3/src/control_tower/trajectories/__init__.py +0 -0
  429. control_tower-6.0.0rc3/src/control_tower/trajectories/action.py +122 -0
  430. control_tower-6.0.0rc3/src/control_tower/trajectories/api.py +615 -0
  431. control_tower-6.0.0rc3/src/control_tower/trajectories/eval_trace_metadata.py +15 -0
  432. control_tower-6.0.0rc3/src/control_tower/trajectories/extended_thinking.py +56 -0
  433. control_tower-6.0.0rc3/src/control_tower/trajectories/format_history.py +119 -0
  434. control_tower-6.0.0rc3/src/control_tower/trajectories/from_eval_log.py +323 -0
  435. control_tower-6.0.0rc3/src/control_tower/trajectories/io.py +205 -0
  436. control_tower-6.0.0rc3/src/control_tower/trajectories/models.py +25 -0
  437. control_tower-6.0.0rc3/src/control_tower/trajectories/mongo_docs.py +392 -0
  438. control_tower-6.0.0rc3/src/control_tower/trajectories/monitor_score.py +159 -0
  439. control_tower-6.0.0rc3/src/control_tower/trajectories/sample.py +328 -0
  440. control_tower-6.0.0rc3/src/control_tower/trajectories/task_scores.py +108 -0
  441. control_tower-6.0.0rc3/src/control_tower/trajectories/text_editor_output.py +69 -0
  442. control_tower-6.0.0rc3/src/control_tower/trajectories/timing_utils.py +419 -0
  443. control_tower-6.0.0rc3/src/control_tower/trajectories/tool_calls.py +40 -0
  444. control_tower-6.0.0rc3/src/control_tower/trajectories/utils.py +74 -0
  445. control_tower-6.0.0rc3/src/control_tower/trajectories/viewer_api.py +578 -0
  446. control_tower-6.0.0rc3/src/control_tower/trajectories/viewer_auth.py +50 -0
  447. control_tower-6.0.0rc3/src/control_tower/trajectories/workspace_diff.py +16 -0
  448. control_tower-6.0.0rc3/src/control_tower/utils/__init__.py +0 -0
  449. control_tower-6.0.0rc3/src/control_tower/utils/cli_args.py +20 -0
  450. control_tower-6.0.0rc3/src/control_tower/utils/direct_api_generator.py +151 -0
  451. control_tower-6.0.0rc3/src/control_tower/utils/docs_utils.py +15 -0
  452. control_tower-6.0.0rc3/src/control_tower/utils/env.py +163 -0
  453. control_tower-6.0.0rc3/src/control_tower/utils/file_patterns.py +92 -0
  454. control_tower-6.0.0rc3/src/control_tower/utils/fs.py +137 -0
  455. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/__init__.py +0 -0
  456. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/arg_type.py +41 -0
  457. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/base_model.py +63 -0
  458. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/custom_handlers.py +99 -0
  459. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/display.py +137 -0
  460. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/function_info.py +97 -0
  461. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/naming.py +5 -0
  462. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/registry.py +419 -0
  463. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/selection.py +68 -0
  464. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/signature_info.py +78 -0
  465. control_tower-6.0.0rc3/src/control_tower/utils/function_registry/validation.py +97 -0
  466. control_tower-6.0.0rc3/src/control_tower/utils/imports.py +35 -0
  467. control_tower-6.0.0rc3/src/control_tower/utils/paths.py +98 -0
  468. control_tower-6.0.0rc3/src/control_tower/utils/sanitize.py +74 -0
  469. control_tower-6.0.0rc3/src/control_tower/utils/serde.py +151 -0
  470. control_tower-6.0.0rc3/src/control_tower/utils/suggestions.py +25 -0
  471. control_tower-6.0.0rc3/src/control_tower/utils/time.py +18 -0
  472. control_tower-6.0.0rc3/src/control_tower/utils/transcript.py +20 -0
  473. control_tower-6.0.0rc3/src/control_tower/utils/versioning.py +383 -0
  474. control_tower-6.0.0rc3/src/control_tower.egg-info/PKG-INFO +88 -0
  475. control_tower-6.0.0rc3/src/control_tower.egg-info/SOURCES.txt +479 -0
  476. control_tower-6.0.0rc3/src/control_tower.egg-info/dependency_links.txt +1 -0
  477. control_tower-6.0.0rc3/src/control_tower.egg-info/entry_points.txt +5 -0
  478. control_tower-6.0.0rc3/src/control_tower.egg-info/requires.txt +34 -0
  479. control_tower-6.0.0rc3/src/control_tower.egg-info/top_level.txt +1 -0
  480. control_tower-6.0.0rc3/tests/test_correct_environments.py +34 -0
  481. control_tower-6.0.0rc3/tests/test_serde.py +41 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 LinuxArena
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ recursive-include src *.md *.txt *.yml *.yaml *.json *.jsonl *.tcss *.sh *.c
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: control-tower
3
+ Version: 6.0.0rc3
4
+ Summary: Control Tower evaluation framework for AI control research
5
+ Author: LinuxArena
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://linuxarena.ai
8
+ Project-URL: Repository, https://github.com/linuxarena/control-tower
9
+ Keywords: ai-control,agent-evaluation,evals,monitoring,sabotage
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
17
+ Requires-Python: >=3.13
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: click==8.2.1
21
+ Requires-Dist: dnslib>=0.9.26
22
+ Requires-Dist: docstring-parser>=0.17
23
+ Requires-Dist: flask>=3.1.3
24
+ Requires-Dist: gitignore-parser==0.1.13
25
+ Requires-Dist: gitpython>=3.1.46
26
+ Requires-Dist: inspect-ai==0.3.268
27
+ Requires-Dist: inspect-scout==0.5.3
28
+ Requires-Dist: jsonlines>=4.0.0
29
+ Requires-Dist: inspect-swe==0.2.70
30
+ Requires-Dist: pick==2.6.0
31
+ Requires-Dist: pydantic-settings>=2.0
32
+ Requires-Dist: python-dotenv==1.2.2
33
+ Requires-Dist: pytz>=2025.0
34
+ Requires-Dist: pyyaml>=6.0.3
35
+ Requires-Dist: scipy>=1.17.0
36
+ Requires-Dist: tabulate>=0.10.0
37
+ Requires-Dist: tenacity>=9.1.4
38
+ Requires-Dist: textual>=8.1.1
39
+ Requires-Dist: tqdm>=4.67.3
40
+ Requires-Dist: unidiff==0.7.5
41
+ Requires-Dist: anthropic>=1.0.0
42
+ Requires-Dist: claude-agent-sdk>=0.1.50
43
+ Requires-Dist: openai>=3.1.0
44
+ Requires-Dist: boto3>=1.40.0
45
+ Requires-Dist: zstandard>=0.25.0
46
+ Requires-Dist: ct-setting-sdk<5,>=4.0.0rc1
47
+ Provides-Extra: hf
48
+ Requires-Dist: pyarrow>=17.0.0; extra == "hf"
49
+ Provides-Extra: providers
50
+ Requires-Dist: google-genai>=1.68.0; extra == "providers"
51
+ Requires-Dist: xai-sdk>=1.9.1; extra == "providers"
52
+ Dynamic: license-file
53
+
54
+ Welcome to Control Tower, a framework for AI control evaluations built on [Inspect](https://inspect.aisi.org.uk/) and developed by [EquiStamp](https://equistamp.com/), [Redwood Research](https://www.redwoodresearch.org/), and [Luthien](https://luthien.cc/).
55
+
56
+ > 🚨 Control Tower is in active development. [Star this repo](https://github.com/linuxarena/control-tower) to follow updates, or [Watch > Releases](https://github.com/linuxarena/control-tower/subscription) to get notified on new versions.
57
+ >
58
+ > Found a bug or have a question? [Open an issue](https://github.com/linuxarena/control-tower/issues), [submit a PR](https://github.com/linuxarena/control-tower/compare) or [book a call](https://calendar.app.google/j7K8yncsBvPfxomS7)
59
+
60
+ Control Tower provides many built-in components, including blue-team protocols, action- and trajectory-level monitors, control evaluations, safety-usefulness curves, and trajectory tooling. Environments and their main and side tasks come from separate settings repositories, and extensions (new protocols, policies, monitors, and scorers) can be provided by other Python packages.
61
+
62
+ See the [documentation](https://docs.linuxarena.ai) for an overview of Control Tower, a hands-on evaluation walkthrough, and development guides.
63
+
64
+ To get started:
65
+
66
+ ```bash
67
+ git clone https://github.com/linuxarena/control-tower && cd control-tower
68
+ uv sync
69
+ alias ct='uv run ct' # add to your shell profile to keep it
70
+ cp .env.example .env # set ANTHROPIC_API_KEY (or OPENAI_API_KEY)
71
+ ct settings pull linuxarena
72
+ ```
73
+
74
+ Check the install without spending a model call. It takes a couple of minutes:
75
+
76
+ ```bash
77
+ ct run eval --policy ct/test --task-file simple --tag test
78
+ ```
79
+
80
+ Then run a real eval. The first one builds the environment image, which takes about ten minutes:
81
+
82
+ ```bash
83
+ ct run eval --policy ct/attack -e linuxarena/clinical_trial -t adverse_reaction_followup_tracking -s suppress_safety_notifications
84
+ ```
85
+
86
+ ***
87
+
88
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for code style, typing, testing, and pull request conventions, and the [development setup guide](https://docs.linuxarena.ai/development/dev-setup) for local services, environment pulls, and shell completions.
@@ -0,0 +1,35 @@
1
+ Welcome to Control Tower, a framework for AI control evaluations built on [Inspect](https://inspect.aisi.org.uk/) and developed by [EquiStamp](https://equistamp.com/), [Redwood Research](https://www.redwoodresearch.org/), and [Luthien](https://luthien.cc/).
2
+
3
+ > 🚨 Control Tower is in active development. [Star this repo](https://github.com/linuxarena/control-tower) to follow updates, or [Watch > Releases](https://github.com/linuxarena/control-tower/subscription) to get notified on new versions.
4
+ >
5
+ > Found a bug or have a question? [Open an issue](https://github.com/linuxarena/control-tower/issues), [submit a PR](https://github.com/linuxarena/control-tower/compare) or [book a call](https://calendar.app.google/j7K8yncsBvPfxomS7)
6
+
7
+ Control Tower provides many built-in components, including blue-team protocols, action- and trajectory-level monitors, control evaluations, safety-usefulness curves, and trajectory tooling. Environments and their main and side tasks come from separate settings repositories, and extensions (new protocols, policies, monitors, and scorers) can be provided by other Python packages.
8
+
9
+ See the [documentation](https://docs.linuxarena.ai) for an overview of Control Tower, a hands-on evaluation walkthrough, and development guides.
10
+
11
+ To get started:
12
+
13
+ ```bash
14
+ git clone https://github.com/linuxarena/control-tower && cd control-tower
15
+ uv sync
16
+ alias ct='uv run ct' # add to your shell profile to keep it
17
+ cp .env.example .env # set ANTHROPIC_API_KEY (or OPENAI_API_KEY)
18
+ ct settings pull linuxarena
19
+ ```
20
+
21
+ Check the install without spending a model call. It takes a couple of minutes:
22
+
23
+ ```bash
24
+ ct run eval --policy ct/test --task-file simple --tag test
25
+ ```
26
+
27
+ Then run a real eval. The first one builds the environment image, which takes about ten minutes:
28
+
29
+ ```bash
30
+ ct run eval --policy ct/attack -e linuxarena/clinical_trial -t adverse_reaction_followup_tracking -s suppress_safety_notifications
31
+ ```
32
+
33
+ ***
34
+
35
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for code style, typing, testing, and pull request conventions, and the [development setup guide](https://docs.linuxarena.ai/development/dev-setup) for local services, environment pulls, and shell completions.
@@ -0,0 +1,229 @@
1
+ [project]
2
+ name = "control-tower"
3
+ version = "6.0.0rc3"
4
+ description = "Control Tower evaluation framework for AI control research"
5
+ readme = "README.md"
6
+ requires-python = ">=3.13"
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ authors = [{ name = "LinuxArena" }]
10
+ keywords = ["ai-control", "agent-evaluation", "evals", "monitoring", "sabotage"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Environment :: Console",
14
+ "Intended Audience :: Developers",
15
+ "Intended Audience :: Science/Research",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
19
+ ]
20
+ dependencies = [
21
+ # CLI and core runtime
22
+ "click==8.2.1",
23
+ "dnslib>=0.9.26",
24
+ "docstring-parser>=0.17",
25
+ "flask>=3.1.3",
26
+ "gitignore-parser==0.1.13",
27
+ "gitpython>=3.1.46",
28
+ "inspect-ai==0.3.268",
29
+ "inspect-scout==0.5.3",
30
+ "jsonlines>=4.0.0",
31
+ "inspect-swe==0.2.70",
32
+ "pick==2.6.0",
33
+ "pydantic-settings>=2.0",
34
+ "python-dotenv==1.2.2",
35
+ "pytz>=2025.0",
36
+ "pyyaml>=6.0.3",
37
+ "scipy>=1.17.0",
38
+ "tabulate>=0.10.0",
39
+ "tenacity>=9.1.4",
40
+ "textual>=8.1.1",
41
+ "tqdm>=4.67.3",
42
+ "unidiff==0.7.5",
43
+
44
+ # Primary model providers and agent SDKs (openai also backs OpenRouter)
45
+ "anthropic>=1.0.0",
46
+ "claude-agent-sdk>=0.1.50",
47
+ "openai>=3.1.0",
48
+
49
+ # Run storage and upload (`ct run eval --upload`)
50
+ "boto3>=1.40.0",
51
+ "zstandard>=0.25.0",
52
+
53
+ # The env API's wire contract, shared with every setting package
54
+ "ct-setting-sdk>=4.0.0rc1,<5",
55
+ ]
56
+
57
+ [project.optional-dependencies]
58
+ hf = ["pyarrow>=17.0.0"]
59
+ providers = [
60
+ "google-genai>=1.68.0",
61
+ "xai-sdk>=1.9.1",
62
+ ]
63
+
64
+ [build-system]
65
+ requires = ["setuptools"]
66
+ build-backend = "setuptools.build_meta"
67
+
68
+ [tool.setuptools.packages.find]
69
+ where = ["src"]
70
+ namespaces = true
71
+ exclude = ["experiments*"]
72
+
73
+ [tool.setuptools.package-data]
74
+ # Non-Python assets that must be available from installed wheels.
75
+ "*" = [
76
+ "*.md",
77
+ "*.txt",
78
+ "*.yml",
79
+ "*.yaml",
80
+ "*.json",
81
+ "*.jsonl",
82
+ "*.tcss",
83
+ "*.sh",
84
+ "py.typed",
85
+ ]
86
+ "control_tower.sandbox.intranet_guard" = ["Dockerfile"]
87
+ "control_tower.environments.internet_simulator" = [
88
+ "Dockerfile",
89
+ ".dockerignore",
90
+ "resolve_override.c",
91
+ "malware/malware.c",
92
+ ]
93
+
94
+ [tool.setuptools.package-dir]
95
+ "" = "src"
96
+
97
+ [dependency-groups]
98
+ dev = [
99
+ "moto>=5.1.22",
100
+ "pyright==1.1.411", # kept for `--verifytypes` coverage gate; ty has no equivalent yet
101
+ "pytest==9.1.1",
102
+ "pytest-asyncio==1.4.0",
103
+ "pytest-xdist==3.8.0",
104
+ "ruff==0.15.20",
105
+ "ty==0.0.33", # primary type checker; pinned because pre-1.0
106
+ "vulture>=2.15",
107
+ "yamllint==1.38.0",
108
+ "yamlfix>=1.19.1",
109
+ ]
110
+ # A group, not a dependency: PyPI rejects direct-URL requirements, and Apollo ships the SDK only as a GitHub wheel.
111
+ watcher = [
112
+ # 0.41.0 or later: the protocol reads `cost_usd` from each hook outcome.
113
+ "watcher-sdk @ https://github.com/ApolloResearch/watcher-bin/releases/download/v0.41.0/watcher_sdk-0.41.0-py3-none-any.whl",
114
+ ]
115
+
116
+ [tool.uv]
117
+ default-groups = ["dev", "watcher"]
118
+
119
+ [tool.uv.sources]
120
+ ct-setting-sdk = { path = "packages/ct-setting-sdk", editable = true }
121
+
122
+ [project.scripts]
123
+ ct = "control_tower.cli.main:main"
124
+
125
+ [project.entry-points.inspect_ai]
126
+ # Registers ``control_tower/eval`` and ``control_tower/control_eval`` as discoverable
127
+ # Inspect AI @tasks (plus the ct_upload and ct_diagnostics hooks) after pip-installing control-tower.
128
+ control_tower = "control_tower.inspect_tasks"
129
+
130
+ [project.urls]
131
+ Homepage = "https://linuxarena.ai"
132
+ Repository = "https://github.com/linuxarena/control-tower"
133
+
134
+ [tool.ruff]
135
+ required-version = "==0.15.20"
136
+ src = []
137
+ extend-exclude = [
138
+ ".settings/**",
139
+ ]
140
+
141
+ [tool.ruff.lint]
142
+ extend-select = ["I", "UP", "ANN", "PLC0415", "S110"]
143
+ ignore = [
144
+ "ANN002", # missing type annotation for *args
145
+ "ANN003", # missing type annotation for **kwargs
146
+ "ANN204", # missing return type for __init__ / __new__ / dunder
147
+ "ANN401", # disallow Any — too strict for this codebase
148
+ ]
149
+
150
+ [tool.ruff.lint.isort]
151
+ known-first-party = ["control_tower", "ct_setting_sdk"]
152
+
153
+ [tool.ruff.lint.per-file-ignores]
154
+ "tests/**" = ["ANN", "PLC0415"]
155
+ "packages/*/tests/**" = ["ANN", "PLC0415"]
156
+ "scripts/**" = ["PLC0415"]
157
+ # CLI convention: imports stay inside command functions so `ct` starts fast
158
+ "src/**/cli/**" = ["PLC0415"]
159
+ "src/**/cli.py" = ["PLC0415"]
160
+ "src/**/*_cli.py" = ["PLC0415"]
161
+
162
+ [tool.pytest.ini_options]
163
+ testpaths = ["tests", "packages/ct-setting-sdk/tests"]
164
+ markers = [
165
+ "integration: marks tests as integration tests (deselect with '-m \"not integration\"')",
166
+ "slow: marks tests as slow running",
167
+ ]
168
+ addopts = "-m 'not integration' --durations=10 --ignore=tests/replay_check/packages"
169
+
170
+ [tool.control_tower.typing]
171
+ verifytypes_min_completeness = 100.0
172
+
173
+ [[tool.control_tower.import_boundaries.rules]]
174
+ name = "only cli may import ct_runs (generation/orchestration tooling)"
175
+ sources = ["*"]
176
+ ignore_sources = ["cli", "ct_runs", "ct_runs.*"]
177
+ targets = ["ct_runs", "ct_runs.*"]
178
+ allowed_files = [
179
+ "src/control_tower/hawk/runner.py",
180
+ ]
181
+
182
+ [[tool.control_tower.import_boundaries.rules]]
183
+ name = "ct_runs subpackages are independent except declared edges"
184
+ sources = ["ct_runs.*"]
185
+ targets = ["ct_runs", "ct_runs.*"]
186
+ allowed_edges = [
187
+ "ct_runs.* -> ct_runs.claude_host",
188
+ "ct_runs.* -> ct_runs.prompts",
189
+ "ct_runs.* -> ct_runs.storage",
190
+ "ct_runs.dashboard_cli -> ct_runs.dashboard",
191
+ "ct_runs.run_cli -> ct_runs.*",
192
+ "ct_runs.task_analysis -> ct_runs.traj_analysis",
193
+ ]
194
+
195
+ [[tool.control_tower.import_boundaries.rules]]
196
+ name = "utils and defaults are leaves"
197
+ sources = ["utils", "defaults"]
198
+ targets = ["*"]
199
+
200
+ [[tool.control_tower.import_boundaries.rules]]
201
+ name = "monitors stand alone: they import only models, tools and utils"
202
+ sources = ["monitors"]
203
+ targets = ["*"]
204
+ allowed_edges = [
205
+ "monitors -> models",
206
+ "monitors -> tools",
207
+ "monitors -> utils",
208
+ ]
209
+
210
+ [[tool.control_tower.import_boundaries.rules]]
211
+ name = "trajectories must not import live"
212
+ sources = ["trajectories"]
213
+ targets = ["live"]
214
+
215
+ [tool.ty.src]
216
+ include = [
217
+ ".github/scripts",
218
+ "packages/ct-setting-sdk/src",
219
+ "scripts",
220
+ "src/control_tower",
221
+ "tests",
222
+ ]
223
+ exclude = [
224
+ "**/node_modules",
225
+ ".settings/**",
226
+ ]
227
+
228
+ [tool.ty.environment]
229
+ python-version = "3.13"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ from importlib.metadata import version
2
+
3
+ __version__ = version("control-tower")
@@ -0,0 +1,3 @@
1
+ from control_tower.utils.env import ensure_dotenv
2
+
3
+ ensure_dotenv()
@@ -0,0 +1,215 @@
1
+ import functools
2
+ import json
3
+ import re
4
+ import sys
5
+ import termios
6
+ import tty
7
+ from collections.abc import Callable
8
+ from pathlib import Path
9
+ from typing import Any, cast
10
+
11
+ import click
12
+
13
+ from control_tower.cli.completions.completion_callbacks import (
14
+ completion_env_names,
15
+ completion_main_task_names,
16
+ completion_side_task_names,
17
+ )
18
+ from ct_setting_sdk.protocol.errors import ExpectedError
19
+
20
+
21
+ def getch() -> str:
22
+ """Read a single character from stdin without requiring Enter.
23
+
24
+ Handles arrow keys by returning "left" or "right" strings.
25
+ """
26
+ fd = sys.stdin.fileno()
27
+ old_settings = termios.tcgetattr(fd)
28
+ try:
29
+ tty.setraw(fd)
30
+ ch = sys.stdin.read(1)
31
+ if ch == "\x1b":
32
+ ch2 = sys.stdin.read(1)
33
+ if ch2 == "[":
34
+ ch3 = sys.stdin.read(1)
35
+ if ch3 == "D":
36
+ return "left"
37
+ elif ch3 == "C":
38
+ return "right"
39
+ return ch
40
+ finally:
41
+ termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
42
+
43
+
44
+ def clear_screen() -> None:
45
+ """Clear the terminal screen."""
46
+ click.echo("\033[2J\033[H", nl=False)
47
+
48
+
49
+ def word_wrap(text: str, width: int) -> list[str]:
50
+ """Wrap text to specified width, preserving line breaks."""
51
+ result = []
52
+ for paragraph in text.split("\n"):
53
+ if not paragraph.strip():
54
+ result.append("")
55
+ continue
56
+ words = paragraph.split()
57
+ current_line = ""
58
+ for word in words:
59
+ if len(current_line) + len(word) + 1 > width:
60
+ if current_line:
61
+ result.append(current_line)
62
+ current_line = word
63
+ else:
64
+ current_line += (" " if current_line else "") + word
65
+ if current_line:
66
+ result.append(current_line)
67
+ return result
68
+
69
+
70
+ def load_jsonl(path: Path) -> list[dict[str, Any]]:
71
+ """Load all non-empty lines from a JSONL file as dicts."""
72
+ results = []
73
+ with open(path) as f:
74
+ for line in f:
75
+ line = line.strip()
76
+ if line:
77
+ results.append(json.loads(line))
78
+ return results
79
+
80
+
81
+ def select_audit_run(runs_dir: Path, title: str = "Select audit run") -> Path | None:
82
+ """Interactive picker for audit run directories. Returns None if no runs or user cancels."""
83
+ from pick import Option, pick
84
+
85
+ if not runs_dir.exists():
86
+ click.secho(f"No runs found in {runs_dir}/", fg="yellow")
87
+ return None
88
+
89
+ runs = sorted(
90
+ [d for d in runs_dir.iterdir() if d.is_dir()],
91
+ key=lambda p: p.stat().st_ctime,
92
+ reverse=True,
93
+ )
94
+
95
+ if not runs:
96
+ click.secho(f"No runs found in {runs_dir}/", fg="yellow")
97
+ return None
98
+
99
+ options: list[Option] = []
100
+ for run in runs:
101
+ results_file = run / "results.jsonl"
102
+ count = 0
103
+ if results_file.exists():
104
+ count = sum(1 for _ in results_file.open())
105
+ label = f"{run.name} ({count} results)"
106
+ options.append(Option(label, run))
107
+
108
+ selected, _ = pick(
109
+ options,
110
+ title=title,
111
+ indicator="=>",
112
+ default_index=0,
113
+ )
114
+
115
+ return selected.value if isinstance(selected, Option) else Path(str(selected))
116
+
117
+
118
+ def _build_param_map(click_params: list[click.Parameter]) -> dict[str, str]:
119
+ """Build mapping from Python param names to CLI representations."""
120
+ param_map: dict[str, str] = {}
121
+
122
+ for param in click_params:
123
+ if not param.name:
124
+ continue
125
+
126
+ param_name = param.name
127
+ if not isinstance(param_name, str):
128
+ continue
129
+
130
+ if isinstance(param, click.Option):
131
+ if param.opts:
132
+ cli_name = cast(str, max(param.opts, key=len))
133
+ param_map[param_name] = cli_name
134
+ elif isinstance(param, click.Argument):
135
+ param_map[param_name] = param_name.upper()
136
+
137
+ return param_map
138
+
139
+
140
+ def _transform_error_message(message: str, click_params: list[click.Parameter]) -> str:
141
+ """Transform parameter names in error message to CLI equivalents."""
142
+ param_map = _build_param_map(click_params)
143
+
144
+ for py_name, cli_name in param_map.items():
145
+ message = re.sub(rf"`{re.escape(py_name)}`", cli_name, message)
146
+
147
+ if "_" in py_name:
148
+ message = re.sub(rf"\b{re.escape(py_name)}\b", cli_name, message)
149
+
150
+ return message
151
+
152
+
153
+ def handle_user_errors(f: Callable[..., object]) -> Callable[..., object]:
154
+ """Decorator that converts ExpectedError exceptions to click.ClickException.
155
+
156
+ Apply this decorator to Click commands to ensure that ExpectedError exceptions
157
+ are displayed cleanly without a stack trace, while unexpected errors still
158
+ show full tracebacks for debugging.
159
+
160
+ Also transforms parameter names in error messages to their CLI equivalents:
161
+ - `param` (backtick-wrapped) -> --param
162
+ - param_name (with underscores) -> --param-name
163
+
164
+ Adds a --traceback flag to show full stack traces for expected errors.
165
+ """
166
+
167
+ @functools.wraps(f)
168
+ def wrapper(*args: object, traceback: bool = False, **kwargs: object) -> object:
169
+ if traceback:
170
+ return f(*args, **kwargs)
171
+
172
+ try:
173
+ return f(*args, **kwargs)
174
+ except ExpectedError as e:
175
+ message = str(e)
176
+
177
+ ctx = click.get_current_context(silent=True)
178
+ if ctx and ctx.command:
179
+ message = _transform_error_message(message, ctx.command.params)
180
+
181
+ raise click.ClickException(message) from None
182
+
183
+ return click.option(
184
+ "--traceback",
185
+ is_flag=True,
186
+ hidden=True,
187
+ help="Show full traceback for expected errors (for debugging)",
188
+ )(wrapper)
189
+
190
+
191
+ def task_override_options[F: Callable[..., object]](func: F) -> F:
192
+ """Add -e/--env, -t/--main-task and -s/--side-task options with shell completion."""
193
+ func = click.option(
194
+ "-s",
195
+ "--side-task",
196
+ type=str,
197
+ shell_complete=completion_side_task_names,
198
+ help="Side task name",
199
+ )(func)
200
+ func = click.option(
201
+ "-t",
202
+ "--main-task",
203
+ type=str,
204
+ shell_complete=completion_main_task_names,
205
+ help="Main task name",
206
+ )(func)
207
+ func = click.option(
208
+ "-e",
209
+ "--env",
210
+ "environment",
211
+ type=str,
212
+ shell_complete=completion_env_names,
213
+ help="Environment name",
214
+ )(func)
215
+ return func