control-tower 6.0.0__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 (454) hide show
  1. control_tower-6.0.0/LICENSE +21 -0
  2. control_tower-6.0.0/MANIFEST.in +2 -0
  3. control_tower-6.0.0/PKG-INFO +91 -0
  4. control_tower-6.0.0/README.md +36 -0
  5. control_tower-6.0.0/pyproject.toml +287 -0
  6. control_tower-6.0.0/setup.cfg +4 -0
  7. control_tower-6.0.0/src/control_tower/__init__.py +3 -0
  8. control_tower-6.0.0/src/control_tower/backends/__init__.py +31 -0
  9. control_tower-6.0.0/src/control_tower/backends/fleet/__init__.py +1 -0
  10. control_tower-6.0.0/src/control_tower/backends/fleet/ami.py +45 -0
  11. control_tower-6.0.0/src/control_tower/backends/fleet/aws_identity.py +9 -0
  12. control_tower-6.0.0/src/control_tower/backends/fleet/bootstrap.sh +349 -0
  13. control_tower-6.0.0/src/control_tower/backends/fleet/config.py +40 -0
  14. control_tower-6.0.0/src/control_tower/backends/fleet/controller.py +2058 -0
  15. control_tower-6.0.0/src/control_tower/backends/fleet/job.py +325 -0
  16. control_tower-6.0.0/src/control_tower/backends/fleet/run.py +399 -0
  17. control_tower-6.0.0/src/control_tower/backends/fleet/run_job.py +270 -0
  18. control_tower-6.0.0/src/control_tower/backends/fleet/worker.py +1045 -0
  19. control_tower-6.0.0/src/control_tower/backends/fleet/worker_cli.py +68 -0
  20. control_tower-6.0.0/src/control_tower/backends/hawk/__init__.py +7 -0
  21. control_tower-6.0.0/src/control_tower/backends/hawk/config.py +114 -0
  22. control_tower-6.0.0/src/control_tower/backends/hawk/download.py +93 -0
  23. control_tower-6.0.0/src/control_tower/backends/hawk/middleman.py +64 -0
  24. control_tower-6.0.0/src/control_tower/backends/hawk/model_closure.py +39 -0
  25. control_tower-6.0.0/src/control_tower/backends/hawk/preflight.py +142 -0
  26. control_tower-6.0.0/src/control_tower/backends/hawk/pull_envs.py +160 -0
  27. control_tower-6.0.0/src/control_tower/backends/hawk/runner.py +1050 -0
  28. control_tower-6.0.0/src/control_tower/backends/hawk/sandbox.py +561 -0
  29. control_tower-6.0.0/src/control_tower/backends/hawk/yaml_generator.py +206 -0
  30. control_tower-6.0.0/src/control_tower/backends/local.py +223 -0
  31. control_tower-6.0.0/src/control_tower/cli/__init__.py +3 -0
  32. control_tower-6.0.0/src/control_tower/cli/base.py +207 -0
  33. control_tower-6.0.0/src/control_tower/cli/cloud.py +132 -0
  34. control_tower-6.0.0/src/control_tower/cli/completions/completion_callbacks.py +125 -0
  35. control_tower-6.0.0/src/control_tower/cli/completions/completions_build.py +59 -0
  36. control_tower-6.0.0/src/control_tower/cli/completions/completions_hooks.py +209 -0
  37. control_tower-6.0.0/src/control_tower/cli/extras.py +89 -0
  38. control_tower-6.0.0/src/control_tower/cli/login.py +77 -0
  39. control_tower-6.0.0/src/control_tower/cli/main.py +51 -0
  40. control_tower-6.0.0/src/control_tower/cli/mcp_meta.py +30 -0
  41. control_tower-6.0.0/src/control_tower/cli/protocols.py +140 -0
  42. control_tower-6.0.0/src/control_tower/cli/run.py +893 -0
  43. control_tower-6.0.0/src/control_tower/cli/task_sets.py +123 -0
  44. control_tower-6.0.0/src/control_tower/datasets/__init__.py +0 -0
  45. control_tower-6.0.0/src/control_tower/datasets/check.py +88 -0
  46. control_tower-6.0.0/src/control_tower/datasets/cli.py +599 -0
  47. control_tower-6.0.0/src/control_tower/datasets/external.py +675 -0
  48. control_tower-6.0.0/src/control_tower/datasets/importers/__init__.py +47 -0
  49. control_tower-6.0.0/src/control_tower/datasets/importers/eval_log.py +596 -0
  50. control_tower-6.0.0/src/control_tower/datasets/importers/monitoring_bench.py +766 -0
  51. control_tower-6.0.0/src/control_tower/datasets/importers/mythos_5_incident.py +241 -0
  52. control_tower-6.0.0/src/control_tower/datasets/importers/sessions.py +159 -0
  53. control_tower-6.0.0/src/control_tower/datasets/importers/shade_arena.py +588 -0
  54. control_tower-6.0.0/src/control_tower/datasets/importers/sleight_bench.py +487 -0
  55. control_tower-6.0.0/src/control_tower/datasets/model.py +45 -0
  56. control_tower-6.0.0/src/control_tower/environments/build.py +191 -0
  57. control_tower-6.0.0/src/control_tower/environments/env_args.py +98 -0
  58. control_tower-6.0.0/src/control_tower/environments/environment.py +92 -0
  59. control_tower-6.0.0/src/control_tower/environments/internet_simulator/.dockerignore +3 -0
  60. control_tower-6.0.0/src/control_tower/environments/internet_simulator/Dockerfile +89 -0
  61. control_tower-6.0.0/src/control_tower/environments/internet_simulator/__init__.py +0 -0
  62. control_tower-6.0.0/src/control_tower/environments/internet_simulator/__main__.py +4 -0
  63. control_tower-6.0.0/src/control_tower/environments/internet_simulator/compose.yml +31 -0
  64. control_tower-6.0.0/src/control_tower/environments/internet_simulator/constants.py +53 -0
  65. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/assets.py +304 -0
  66. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/exposed_services.py +71 -0
  67. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/generate_ca.py +68 -0
  68. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/logs.py +212 -0
  69. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/network_mapping.py +63 -0
  70. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/tls.py +124 -0
  71. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/trajectory.py +17 -0
  72. control_tower-6.0.0/src/control_tower/environments/internet_simulator/core/webhook.py +195 -0
  73. control_tower-6.0.0/src/control_tower/environments/internet_simulator/malware/malware.c +143 -0
  74. control_tower-6.0.0/src/control_tower/environments/internet_simulator/modules/forward_proxy.py +431 -0
  75. control_tower-6.0.0/src/control_tower/environments/internet_simulator/modules/provider_policy.py +390 -0
  76. control_tower-6.0.0/src/control_tower/environments/internet_simulator/modules/response_rules.py +193 -0
  77. control_tower-6.0.0/src/control_tower/environments/internet_simulator/modules/shell_sessions.py +206 -0
  78. control_tower-6.0.0/src/control_tower/environments/internet_simulator/modules/upstream_proxy.py +289 -0
  79. control_tower-6.0.0/src/control_tower/environments/internet_simulator/modules/upstream_specs.py +221 -0
  80. control_tower-6.0.0/src/control_tower/environments/internet_simulator/personas.py +150 -0
  81. control_tower-6.0.0/src/control_tower/environments/internet_simulator/requirements.txt +3 -0
  82. control_tower-6.0.0/src/control_tower/environments/internet_simulator/resolve_override.c +75 -0
  83. control_tower-6.0.0/src/control_tower/environments/internet_simulator/runtimes/__init__.py +0 -0
  84. control_tower-6.0.0/src/control_tower/environments/internet_simulator/runtimes/docker.py +630 -0
  85. control_tower-6.0.0/src/control_tower/environments/internet_simulator/runtimes/hawk.py +193 -0
  86. control_tower-6.0.0/src/control_tower/environments/internet_simulator/runtimes/provisioning.py +39 -0
  87. control_tower-6.0.0/src/control_tower/environments/internet_simulator/server.py +660 -0
  88. control_tower-6.0.0/src/control_tower/environments/internet_simulator/source_hash.py +78 -0
  89. control_tower-6.0.0/src/control_tower/environments/list_utils.py +482 -0
  90. control_tower-6.0.0/src/control_tower/environments/registry.py +275 -0
  91. control_tower-6.0.0/src/control_tower/environments/remote/__init__.py +0 -0
  92. control_tower-6.0.0/src/control_tower/environments/remote/process.py +248 -0
  93. control_tower-6.0.0/src/control_tower/environments/remote/remote.py +407 -0
  94. control_tower-6.0.0/src/control_tower/environments/remote/sample.py +244 -0
  95. control_tower-6.0.0/src/control_tower/environments/setting_runtime.py +176 -0
  96. control_tower-6.0.0/src/control_tower/environments/settings.py +1170 -0
  97. control_tower-6.0.0/src/control_tower/environments/settings.yml +26 -0
  98. control_tower-6.0.0/src/control_tower/environments/settings_cli.py +610 -0
  99. control_tower-6.0.0/src/control_tower/environments/validate.py +116 -0
  100. control_tower-6.0.0/src/control_tower/eval/README.md +38 -0
  101. control_tower-6.0.0/src/control_tower/eval/__init__.py +1 -0
  102. control_tower-6.0.0/src/control_tower/eval/game/__init__.py +11 -0
  103. control_tower-6.0.0/src/control_tower/eval/game/blue.py +570 -0
  104. control_tower-6.0.0/src/control_tower/eval/game/harness.py +146 -0
  105. control_tower-6.0.0/src/control_tower/eval/game/history.py +221 -0
  106. control_tower-6.0.0/src/control_tower/eval/game/messages.py +75 -0
  107. control_tower-6.0.0/src/control_tower/eval/game/red.py +346 -0
  108. control_tower-6.0.0/src/control_tower/eval/game/registry.py +29 -0
  109. control_tower-6.0.0/src/control_tower/eval/game/solver.py +214 -0
  110. control_tower-6.0.0/src/control_tower/eval/game/view.py +114 -0
  111. control_tower-6.0.0/src/control_tower/eval/game/white.py +37 -0
  112. control_tower-6.0.0/src/control_tower/eval/launch/__init__.py +1 -0
  113. control_tower-6.0.0/src/control_tower/eval/launch/assemble.py +416 -0
  114. control_tower-6.0.0/src/control_tower/eval/launch/dataset.py +611 -0
  115. control_tower-6.0.0/src/control_tower/eval/launch/dispatch.py +142 -0
  116. control_tower-6.0.0/src/control_tower/eval/launch/inspect_tasks.py +248 -0
  117. control_tower-6.0.0/src/control_tower/eval/launch/metadata.py +39 -0
  118. control_tower-6.0.0/src/control_tower/eval/launch/naming.py +37 -0
  119. control_tower-6.0.0/src/control_tower/eval/launch/options.py +40 -0
  120. control_tower-6.0.0/src/control_tower/eval/launch/preflight.py +90 -0
  121. control_tower-6.0.0/src/control_tower/eval/launch/selection.py +151 -0
  122. control_tower-6.0.0/src/control_tower/eval/log/README.md +76 -0
  123. control_tower-6.0.0/src/control_tower/eval/log/__init__.py +0 -0
  124. control_tower-6.0.0/src/control_tower/eval/log/action.py +72 -0
  125. control_tower-6.0.0/src/control_tower/eval/log/blue_calls.py +93 -0
  126. control_tower-6.0.0/src/control_tower/eval/log/convert.py +1773 -0
  127. control_tower-6.0.0/src/control_tower/eval/log/eval_trace_metadata.py +15 -0
  128. control_tower-6.0.0/src/control_tower/eval/log/extended_thinking.py +56 -0
  129. control_tower-6.0.0/src/control_tower/eval/log/format_history.py +35 -0
  130. control_tower-6.0.0/src/control_tower/eval/log/from_eval_log.py +141 -0
  131. control_tower-6.0.0/src/control_tower/eval/log/merge.py +87 -0
  132. control_tower-6.0.0/src/control_tower/eval/log/monitor_scores.py +112 -0
  133. control_tower-6.0.0/src/control_tower/eval/log/sample.py +403 -0
  134. control_tower-6.0.0/src/control_tower/eval/log/task_args.py +23 -0
  135. control_tower-6.0.0/src/control_tower/eval/log/task_scores.py +110 -0
  136. control_tower-6.0.0/src/control_tower/eval/log/tool_calls.py +40 -0
  137. control_tower-6.0.0/src/control_tower/eval/log/translation.py +342 -0
  138. control_tower-6.0.0/src/control_tower/eval/log/utils.py +85 -0
  139. control_tower-6.0.0/src/control_tower/eval/log/workspace_diff.py +16 -0
  140. control_tower-6.0.0/src/control_tower/eval/monitoring/__init__.py +1 -0
  141. control_tower-6.0.0/src/control_tower/eval/monitoring/posthoc.py +339 -0
  142. control_tower-6.0.0/src/control_tower/eval/monitoring/scorer.py +409 -0
  143. control_tower-6.0.0/src/control_tower/extras/__init__.py +0 -0
  144. control_tower-6.0.0/src/control_tower/extras/claude_host.py +26 -0
  145. control_tower-6.0.0/src/control_tower/extras/dashboard.py +269 -0
  146. control_tower-6.0.0/src/control_tower/extras/dashboard_cli.py +19 -0
  147. control_tower-6.0.0/src/control_tower/extras/env_description/__init__.py +0 -0
  148. control_tower-6.0.0/src/control_tower/extras/env_description/audit/README.md +80 -0
  149. control_tower-6.0.0/src/control_tower/extras/env_description/audit/__init__.py +0 -0
  150. control_tower-6.0.0/src/control_tower/extras/env_description/audit/cli.py +81 -0
  151. control_tower-6.0.0/src/control_tower/extras/env_description/audit/models.py +63 -0
  152. control_tower-6.0.0/src/control_tower/extras/env_description/audit/prompts/system.md +68 -0
  153. control_tower-6.0.0/src/control_tower/extras/env_description/audit/prompts/user.md +30 -0
  154. control_tower-6.0.0/src/control_tower/extras/env_description/audit/task.py +278 -0
  155. control_tower-6.0.0/src/control_tower/extras/env_description/generate/README.md +75 -0
  156. control_tower-6.0.0/src/control_tower/extras/env_description/generate/cli.py +146 -0
  157. control_tower-6.0.0/src/control_tower/extras/env_description/generate/prompts/system.md +62 -0
  158. control_tower-6.0.0/src/control_tower/extras/env_description/generate/prompts/user.md +21 -0
  159. control_tower-6.0.0/src/control_tower/extras/env_description/generate/task.py +359 -0
  160. control_tower-6.0.0/src/control_tower/extras/env_description/shared/concurrency.py +72 -0
  161. control_tower-6.0.0/src/control_tower/extras/env_description/shared/spec.md +79 -0
  162. control_tower-6.0.0/src/control_tower/extras/env_description/shared/spec_loader.py +24 -0
  163. control_tower-6.0.0/src/control_tower/extras/env_source.py +230 -0
  164. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/README.md +59 -0
  165. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/cli.py +115 -0
  166. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/prompts/analyze.md +44 -0
  167. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/prompts/check_tasks.md +29 -0
  168. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/prompts/coverage.md +27 -0
  169. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/prompts/fix.md +14 -0
  170. control_tower-6.0.0/src/control_tower/extras/integration_test_quality/task.py +179 -0
  171. control_tower-6.0.0/src/control_tower/extras/pairing_analysis/README.md +30 -0
  172. control_tower-6.0.0/src/control_tower/extras/pairing_analysis/cli.py +82 -0
  173. control_tower-6.0.0/src/control_tower/extras/pairing_analysis/prompts/pairing.md +43 -0
  174. control_tower-6.0.0/src/control_tower/extras/pairing_analysis/task.py +367 -0
  175. control_tower-6.0.0/src/control_tower/extras/prompts.py +28 -0
  176. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/base.py +216 -0
  177. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/_json.py +31 -0
  178. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/chroma.py +285 -0
  179. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/docker.py +366 -0
  180. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/elasticsearch.py +293 -0
  181. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/filesystem.py +155 -0
  182. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/generated_manifest.json +13 -0
  183. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/influxdb.py +549 -0
  184. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/listener.py +81 -0
  185. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/minio.py +360 -0
  186. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/mongo.py +338 -0
  187. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/openldap.py +241 -0
  188. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/postgres.py +317 -0
  189. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/process.py +134 -0
  190. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/rabbitmq.py +369 -0
  191. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/redis.py +291 -0
  192. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/sqlite.py +309 -0
  193. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/sshd.py +270 -0
  194. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/checks/vault.py +376 -0
  195. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/cli.py +575 -0
  196. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/compose_analyzer.py +182 -0
  197. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/detection.py +236 -0
  198. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/dockerfile_analyzer.py +377 -0
  199. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/llm_generator.py +448 -0
  200. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/runner.py +449 -0
  201. control_tower-6.0.0/src/control_tower/extras/scorer_idempotency/runtime_prober.py +378 -0
  202. control_tower-6.0.0/src/control_tower/extras/side_task_folder.py +115 -0
  203. control_tower-6.0.0/src/control_tower/extras/storage.py +74 -0
  204. control_tower-6.0.0/src/control_tower/extras/task_analysis/compare_side_tasks/README.md +25 -0
  205. control_tower-6.0.0/src/control_tower/extras/task_analysis/compare_side_tasks/cli.py +25 -0
  206. control_tower-6.0.0/src/control_tower/extras/task_analysis/compare_side_tasks/task.py +127 -0
  207. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/README.md +77 -0
  208. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/audits/base.py +129 -0
  209. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/audits/goal.py +92 -0
  210. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/audits/sd.py +98 -0
  211. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/cli.py +185 -0
  212. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/heuristics/base.py +53 -0
  213. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/heuristics/goal.py +215 -0
  214. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/heuristics/sd.py +222 -0
  215. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/prompts/goal/system.md +109 -0
  216. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/prompts/goal/user.md +21 -0
  217. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/prompts/sd/system.md +311 -0
  218. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/prompts/sd/user.md +26 -0
  219. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/sd_audit_labels.json +98 -0
  220. control_tower-6.0.0/src/control_tower/extras/task_analysis/doc_audit/task.py +200 -0
  221. control_tower-6.0.0/src/control_tower/extras/task_analysis/failure_type_audit/cli.py +125 -0
  222. control_tower-6.0.0/src/control_tower/extras/task_analysis/failure_type_audit/prompts/system.md +9 -0
  223. control_tower-6.0.0/src/control_tower/extras/task_analysis/failure_type_audit/prompts/user.md +23 -0
  224. control_tower-6.0.0/src/control_tower/extras/task_analysis/failure_type_audit/task.py +190 -0
  225. control_tower-6.0.0/src/control_tower/extras/task_analysis/goal_completeness/README.md +56 -0
  226. control_tower-6.0.0/src/control_tower/extras/task_analysis/goal_completeness/cli.py +125 -0
  227. control_tower-6.0.0/src/control_tower/extras/task_analysis/goal_completeness/prompts/system.md +44 -0
  228. control_tower-6.0.0/src/control_tower/extras/task_analysis/goal_completeness/prompts/user.md +50 -0
  229. control_tower-6.0.0/src/control_tower/extras/task_analysis/goal_completeness/task.py +320 -0
  230. control_tower-6.0.0/src/control_tower/extras/task_analysis/goal_completeness/viewer.py +142 -0
  231. control_tower-6.0.0/src/control_tower/extras/task_analysis/reward_hacking/README.md +46 -0
  232. control_tower-6.0.0/src/control_tower/extras/task_analysis/reward_hacking/cli.py +115 -0
  233. control_tower-6.0.0/src/control_tower/extras/task_analysis/reward_hacking/prompts/system.md +71 -0
  234. control_tower-6.0.0/src/control_tower/extras/task_analysis/reward_hacking/prompts/user.md +62 -0
  235. control_tower-6.0.0/src/control_tower/extras/task_analysis/reward_hacking/task.py +360 -0
  236. control_tower-6.0.0/src/control_tower/extras/task_analysis/reward_hacking/viewer.py +122 -0
  237. control_tower-6.0.0/src/control_tower/extras/task_analysis/rt_alignment/README.md +45 -0
  238. control_tower-6.0.0/src/control_tower/extras/task_analysis/rt_alignment/cli.py +119 -0
  239. control_tower-6.0.0/src/control_tower/extras/task_analysis/rt_alignment/prompts/system.md +50 -0
  240. control_tower-6.0.0/src/control_tower/extras/task_analysis/rt_alignment/prompts/user.md +57 -0
  241. control_tower-6.0.0/src/control_tower/extras/task_analysis/rt_alignment/task.py +357 -0
  242. control_tower-6.0.0/src/control_tower/extras/task_analysis/rt_alignment/viewer.py +124 -0
  243. control_tower-6.0.0/src/control_tower/extras/task_analysis/side_task_review/README.md +43 -0
  244. control_tower-6.0.0/src/control_tower/extras/task_analysis/side_task_review/cli.py +87 -0
  245. control_tower-6.0.0/src/control_tower/extras/task_analysis/side_task_review/prompts/review.md +30 -0
  246. control_tower-6.0.0/src/control_tower/extras/task_analysis/side_task_review/task.py +98 -0
  247. control_tower-6.0.0/src/control_tower/extras/task_analysis/validate_cover/README.md +32 -0
  248. control_tower-6.0.0/src/control_tower/extras/task_analysis/validate_cover/cli.py +97 -0
  249. control_tower-6.0.0/src/control_tower/extras/task_analysis/validate_cover/container_script.py +230 -0
  250. control_tower-6.0.0/src/control_tower/extras/task_analysis/validate_cover/full_env_context.py +66 -0
  251. control_tower-6.0.0/src/control_tower/extras/task_analysis/validate_cover/task.py +97 -0
  252. control_tower-6.0.0/src/control_tower/extras/task_analysis/validate_cover/validate_cover_prompt.md +35 -0
  253. control_tower-6.0.0/src/control_tower/extras/timing_report/__init__.py +17 -0
  254. control_tower-6.0.0/src/control_tower/extras/timing_report/cli.py +71 -0
  255. control_tower-6.0.0/src/control_tower/extras/timing_report/report.py +324 -0
  256. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability/README.md +49 -0
  257. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability/cli.py +125 -0
  258. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability/prompts/system.md +29 -0
  259. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability/prompts/user.md +70 -0
  260. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability/task.py +351 -0
  261. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability/viewer.py +159 -0
  262. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability_verified/README.md +52 -0
  263. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability_verified/cli.py +143 -0
  264. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability_verified/prompts/system.md +36 -0
  265. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability_verified/prompts/user.md +61 -0
  266. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability_verified/task.py +673 -0
  267. control_tower-6.0.0/src/control_tower/extras/traj_analysis/submit_guessability_verified/viewer.py +186 -0
  268. control_tower-6.0.0/src/control_tower/live/__init__.py +0 -0
  269. control_tower-6.0.0/src/control_tower/live/agents.py +117 -0
  270. control_tower-6.0.0/src/control_tower/live/assets/dev_container_extensions.json +3 -0
  271. control_tower-6.0.0/src/control_tower/live/assets/live.gitignore +53 -0
  272. control_tower-6.0.0/src/control_tower/live/assets/pyrightconfig.json +4 -0
  273. control_tower-6.0.0/src/control_tower/live/assets/settings.json +3 -0
  274. control_tower-6.0.0/src/control_tower/live/cli.py +1133 -0
  275. control_tower-6.0.0/src/control_tower/live/compose.py +117 -0
  276. control_tower-6.0.0/src/control_tower/live/context/print_context.py +98 -0
  277. control_tower-6.0.0/src/control_tower/live/context/task_getters.py +65 -0
  278. control_tower-6.0.0/src/control_tower/live/context/traj_dir.py +334 -0
  279. control_tower-6.0.0/src/control_tower/live/integration_tests.py +128 -0
  280. control_tower-6.0.0/src/control_tower/live/sandbox_ops.py +134 -0
  281. control_tower-6.0.0/src/control_tower/live/score.py +85 -0
  282. control_tower-6.0.0/src/control_tower/live/session.py +513 -0
  283. control_tower-6.0.0/src/control_tower/live/setup.py +294 -0
  284. control_tower-6.0.0/src/control_tower/live/task_state.py +145 -0
  285. control_tower-6.0.0/src/control_tower/live/traj/__init__.py +0 -0
  286. control_tower-6.0.0/src/control_tower/live/traj/gen_traj.py +319 -0
  287. control_tower-6.0.0/src/control_tower/live/traj/git_status.py +33 -0
  288. control_tower-6.0.0/src/control_tower/live/traj/git_traj.py +735 -0
  289. control_tower-6.0.0/src/control_tower/live/traj/git_traj_helpers/FORMAT.md +25 -0
  290. control_tower-6.0.0/src/control_tower/live/traj/git_traj_helpers/call_insert.py +15 -0
  291. control_tower-6.0.0/src/control_tower/live/traj/git_traj_helpers/call_str_replace.py +20 -0
  292. control_tower-6.0.0/src/control_tower/live/traj/macros.py +100 -0
  293. control_tower-6.0.0/src/control_tower/live/traj/migrate_traj.py +80 -0
  294. control_tower-6.0.0/src/control_tower/live/traj/patch.py +62 -0
  295. control_tower-6.0.0/src/control_tower/live/traj/solution.py +242 -0
  296. control_tower-6.0.0/src/control_tower/live/traj/templ/add.py +14 -0
  297. control_tower-6.0.0/src/control_tower/live/traj/templ/add_tool_call.py +85 -0
  298. control_tower-6.0.0/src/control_tower/live/traj/templ/bash.py +127 -0
  299. control_tower-6.0.0/src/control_tower/live/traj/templ/git_utils.py +93 -0
  300. control_tower-6.0.0/src/control_tower/live/traj/templ/input_utils.py +145 -0
  301. control_tower-6.0.0/src/control_tower/live/traj/templ/template_from.py +118 -0
  302. control_tower-6.0.0/src/control_tower/live/traj/templ/tool_call_builder.py +119 -0
  303. control_tower-6.0.0/src/control_tower/live/traj/tool_call_utils.py +283 -0
  304. control_tower-6.0.0/src/control_tower/live/traj/traj.py +294 -0
  305. control_tower-6.0.0/src/control_tower/live/tui/__init__.py +0 -0
  306. control_tower-6.0.0/src/control_tower/live/tui/popup.py +293 -0
  307. control_tower-6.0.0/src/control_tower/live/tui/tui.py +1237 -0
  308. control_tower-6.0.0/src/control_tower/live/tui/tui.tcss +32 -0
  309. control_tower-6.0.0/src/control_tower/metrics/__init__.py +0 -0
  310. control_tower-6.0.0/src/control_tower/metrics/audit.py +357 -0
  311. control_tower-6.0.0/src/control_tower/metrics/control.py +120 -0
  312. control_tower-6.0.0/src/control_tower/models/__init__.py +3 -0
  313. control_tower-6.0.0/src/control_tower/models/aliases.py +59 -0
  314. control_tower-6.0.0/src/control_tower/models/cache_scopes.py +26 -0
  315. control_tower-6.0.0/src/control_tower/models/inspect_rates.py +32 -0
  316. control_tower-6.0.0/src/control_tower/models/openrouter_provider.py +65 -0
  317. control_tower-6.0.0/src/control_tower/models/pricing.py +183 -0
  318. control_tower-6.0.0/src/control_tower/models/rates.py +240 -0
  319. control_tower-6.0.0/src/control_tower/models/role_model.py +179 -0
  320. control_tower-6.0.0/src/control_tower/models/usage_hooks.py +14 -0
  321. control_tower-6.0.0/src/control_tower/monitors/__init__.py +40 -0
  322. control_tower-6.0.0/src/control_tower/monitors/_monitor.py +722 -0
  323. control_tower-6.0.0/src/control_tower/monitors/checklist.py +95 -0
  324. control_tower-6.0.0/src/control_tower/monitors/jev.py +217 -0
  325. control_tower-6.0.0/src/control_tower/monitors/jev_questions.yml +32 -0
  326. control_tower-6.0.0/src/control_tower/monitors/presets.yml +29 -0
  327. control_tower-6.0.0/src/control_tower/monitors/prompts/action-goals.md +78 -0
  328. control_tower-6.0.0/src/control_tower/monitors/prompts/action.md +70 -0
  329. control_tower-6.0.0/src/control_tower/monitors/prompts/goal-analysis.md +72 -0
  330. control_tower-6.0.0/src/control_tower/monitors/prompts/goals.md +76 -0
  331. control_tower-6.0.0/src/control_tower/monitors/prompts/no-history.md +37 -0
  332. control_tower-6.0.0/src/control_tower/monitors/prompts/off-task.md +86 -0
  333. control_tower-6.0.0/src/control_tower/monitors/prompts/quick-goals.md +65 -0
  334. control_tower-6.0.0/src/control_tower/monitors/prompts/quick.md +57 -0
  335. control_tower-6.0.0/src/control_tower/monitors/prompts/simple.md +19 -0
  336. control_tower-6.0.0/src/control_tower/monitors/prompts/strong-goals.md +87 -0
  337. control_tower-6.0.0/src/control_tower/monitors/prompts/strong.md +79 -0
  338. control_tower-6.0.0/src/control_tower/monitors/prompts/trajectory.md +16 -0
  339. control_tower-6.0.0/src/control_tower/monitors/registry.py +18 -0
  340. control_tower-6.0.0/src/control_tower/monitors/single_goal.py +67 -0
  341. control_tower-6.0.0/src/control_tower/monitors/steps/checklist.md +38 -0
  342. control_tower-6.0.0/src/control_tower/monitors/steps/single_goal.md +75 -0
  343. control_tower-6.0.0/src/control_tower/monitors/steps/single_goal_analysis.md +71 -0
  344. control_tower-6.0.0/src/control_tower/monitors/steps/three_scores.md +107 -0
  345. control_tower-6.0.0/src/control_tower/monitors/three_scores.py +68 -0
  346. control_tower-6.0.0/src/control_tower/policies/__init__.py +1 -0
  347. control_tower-6.0.0/src/control_tower/policies/attack.py +185 -0
  348. control_tower-6.0.0/src/control_tower/policies/honest.py +23 -0
  349. control_tower-6.0.0/src/control_tower/policies/obvious_attack.py +67 -0
  350. control_tower-6.0.0/src/control_tower/policies/prompts/attack.md +7 -0
  351. control_tower-6.0.0/src/control_tower/policies/prompts/attack_planning.md +22 -0
  352. control_tower-6.0.0/src/control_tower/policies/replay.py +201 -0
  353. control_tower-6.0.0/src/control_tower/policies/scripted.py +115 -0
  354. control_tower-6.0.0/src/control_tower/protocols/__init__.py +1 -0
  355. control_tower-6.0.0/src/control_tower/protocols/defer_to_trusted.py +141 -0
  356. control_tower-6.0.0/src/control_tower/protocols/null_blue.py +27 -0
  357. control_tower-6.0.0/src/control_tower/protocols/prompts/trusted_editing.md +9 -0
  358. control_tower-6.0.0/src/control_tower/protocols/resample.py +191 -0
  359. control_tower-6.0.0/src/control_tower/protocols/trusted_editing.py +143 -0
  360. control_tower-6.0.0/src/control_tower/protocols/trusted_monitoring.py +90 -0
  361. control_tower-6.0.0/src/control_tower/protocols/watcher.py +352 -0
  362. control_tower-6.0.0/src/control_tower/py.typed +0 -0
  363. control_tower-6.0.0/src/control_tower/runs/README.md +93 -0
  364. control_tower-6.0.0/src/control_tower/runs/__init__.py +0 -0
  365. control_tower-6.0.0/src/control_tower/runs/convert.py +100 -0
  366. control_tower-6.0.0/src/control_tower/runs/convert_eval_log_to_run.py +92 -0
  367. control_tower-6.0.0/src/control_tower/runs/eval_log_io.py +200 -0
  368. control_tower-6.0.0/src/control_tower/runs/io.py +190 -0
  369. control_tower-6.0.0/src/control_tower/runs/models.py +64 -0
  370. control_tower-6.0.0/src/control_tower/runs/mongo_docs.py +359 -0
  371. control_tower-6.0.0/src/control_tower/runs/runs_cli.py +735 -0
  372. control_tower-6.0.0/src/control_tower/runs/s3_upload.py +167 -0
  373. control_tower-6.0.0/src/control_tower/runs/source.py +24 -0
  374. control_tower-6.0.0/src/control_tower/runs/timing_utils.py +149 -0
  375. control_tower-6.0.0/src/control_tower/runs/viewer/__init__.py +0 -0
  376. control_tower-6.0.0/src/control_tower/runs/viewer/api.py +464 -0
  377. control_tower-6.0.0/src/control_tower/runs/viewer/auth.py +50 -0
  378. control_tower-6.0.0/src/control_tower/runs/viewer/io.py +204 -0
  379. control_tower-6.0.0/src/control_tower/runs/viewer/models.py +25 -0
  380. control_tower-6.0.0/src/control_tower/runs/viewer/upload.py +216 -0
  381. control_tower-6.0.0/src/control_tower/runs/viewer/urls.py +501 -0
  382. control_tower-6.0.0/src/control_tower/sandbox/__init__.py +6 -0
  383. control_tower-6.0.0/src/control_tower/sandbox/_alpine_rootfs.py +230 -0
  384. control_tower-6.0.0/src/control_tower/sandbox/_ssh.py +471 -0
  385. control_tower-6.0.0/src/control_tower/sandbox/cli.py +236 -0
  386. control_tower-6.0.0/src/control_tower/sandbox/constants.py +21 -0
  387. control_tower-6.0.0/src/control_tower/sandbox/docker.py +685 -0
  388. control_tower-6.0.0/src/control_tower/sandbox/docker_in_vm.py +527 -0
  389. control_tower-6.0.0/src/control_tower/sandbox/firecracker.py +363 -0
  390. control_tower-6.0.0/src/control_tower/sandbox/inspect_tools.py +46 -0
  391. control_tower-6.0.0/src/control_tower/sandbox/qemu.py +251 -0
  392. control_tower-6.0.0/src/control_tower/sandbox/replay/__init__.py +23 -0
  393. control_tower-6.0.0/src/control_tower/sandbox/replay/environment.py +435 -0
  394. control_tower-6.0.0/src/control_tower/sandbox/replay/score.py +37 -0
  395. control_tower-6.0.0/src/control_tower/sandbox/simulated/__init__.py +25 -0
  396. control_tower-6.0.0/src/control_tower/sandbox/simulated/actions.py +90 -0
  397. control_tower-6.0.0/src/control_tower/sandbox/simulated/compose.py +192 -0
  398. control_tower-6.0.0/src/control_tower/sandbox/simulated/environment.py +190 -0
  399. control_tower-6.0.0/src/control_tower/sandbox/simulated/judge.py +158 -0
  400. control_tower-6.0.0/src/control_tower/sandbox/simulated/prompts/judge.md +31 -0
  401. control_tower-6.0.0/src/control_tower/sandbox/simulated/prompts/simulator.md +74 -0
  402. control_tower-6.0.0/src/control_tower/sandbox/simulated/prompts/simulator_no_exec.md +22 -0
  403. control_tower-6.0.0/src/control_tower/sandbox/simulated/scratch/Dockerfile +11 -0
  404. control_tower-6.0.0/src/control_tower/sandbox/simulated/scratch/compose.yaml +42 -0
  405. control_tower-6.0.0/src/control_tower/sandbox/simulated/session.py +155 -0
  406. control_tower-6.0.0/src/control_tower/scanners.py +130 -0
  407. control_tower-6.0.0/src/control_tower/task/__init__.py +0 -0
  408. control_tower-6.0.0/src/control_tower/task/final_diff.py +88 -0
  409. control_tower-6.0.0/src/control_tower/task/sample_metadata.py +46 -0
  410. control_tower-6.0.0/src/control_tower/task/scorers.py +327 -0
  411. control_tower-6.0.0/src/control_tower/task/select_utils.py +106 -0
  412. control_tower-6.0.0/src/control_tower/task/selectors.py +49 -0
  413. control_tower-6.0.0/src/control_tower/task/setup.py +115 -0
  414. control_tower-6.0.0/src/control_tower/task/space.py +45 -0
  415. control_tower-6.0.0/src/control_tower/task/task.py +230 -0
  416. control_tower-6.0.0/src/control_tower/task/task_sets/__init__.py +203 -0
  417. control_tower-6.0.0/src/control_tower/task/traj_dir.py +39 -0
  418. control_tower-6.0.0/src/control_tower/task/workspace_baseline.py +581 -0
  419. control_tower-6.0.0/src/control_tower/tools/__init__.py +0 -0
  420. control_tower-6.0.0/src/control_tower/tools/answer.py +45 -0
  421. control_tower-6.0.0/src/control_tower/tools/bash_tools.py +37 -0
  422. control_tower-6.0.0/src/control_tower/tools/declarations.py +23 -0
  423. control_tower-6.0.0/src/control_tower/tools/diff_display_text_editor.py +66 -0
  424. control_tower-6.0.0/src/control_tower/tools/registry.py +34 -0
  425. control_tower-6.0.0/src/control_tower/tools/split_text_editor_tools.py +125 -0
  426. control_tower-6.0.0/src/control_tower/tools/task_tools.py +204 -0
  427. control_tower-6.0.0/src/control_tower/tools/text_editor_output.py +53 -0
  428. control_tower-6.0.0/src/control_tower/tools/tool_calls.py +44 -0
  429. control_tower-6.0.0/src/control_tower/tools/tool_registry.py +363 -0
  430. control_tower-6.0.0/src/control_tower/utils/__init__.py +0 -0
  431. control_tower-6.0.0/src/control_tower/utils/cli_args.py +20 -0
  432. control_tower-6.0.0/src/control_tower/utils/direct_api_generator.py +124 -0
  433. control_tower-6.0.0/src/control_tower/utils/docs_utils.py +18 -0
  434. control_tower-6.0.0/src/control_tower/utils/env.py +191 -0
  435. control_tower-6.0.0/src/control_tower/utils/file_patterns.py +89 -0
  436. control_tower-6.0.0/src/control_tower/utils/fs.py +137 -0
  437. control_tower-6.0.0/src/control_tower/utils/function_registry/__init__.py +0 -0
  438. control_tower-6.0.0/src/control_tower/utils/function_registry/base_model.py +30 -0
  439. control_tower-6.0.0/src/control_tower/utils/function_registry/registry.py +535 -0
  440. control_tower-6.0.0/src/control_tower/utils/function_registry/selection.py +68 -0
  441. control_tower-6.0.0/src/control_tower/utils/paths.py +91 -0
  442. control_tower-6.0.0/src/control_tower/utils/sanitize.py +29 -0
  443. control_tower-6.0.0/src/control_tower/utils/suggestions.py +25 -0
  444. control_tower-6.0.0/src/control_tower/utils/time.py +8 -0
  445. control_tower-6.0.0/src/control_tower/utils/transcript.py +20 -0
  446. control_tower-6.0.0/src/control_tower/utils/versioning.py +327 -0
  447. control_tower-6.0.0/src/control_tower.egg-info/PKG-INFO +91 -0
  448. control_tower-6.0.0/src/control_tower.egg-info/SOURCES.txt +452 -0
  449. control_tower-6.0.0/src/control_tower.egg-info/dependency_links.txt +1 -0
  450. control_tower-6.0.0/src/control_tower.egg-info/entry_points.txt +5 -0
  451. control_tower-6.0.0/src/control_tower.egg-info/requires.txt +37 -0
  452. control_tower-6.0.0/src/control_tower.egg-info/top_level.txt +1 -0
  453. control_tower-6.0.0/tests/test_correct_environments.py +34 -0
  454. control_tower-6.0.0/tests/test_stable_api.py +434 -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,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: control-tower
3
+ Version: 6.0.0
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.5.0
21
+ Requires-Dist: docstring-parser>=0.17
22
+ Requires-Dist: flask>=3.1.3
23
+ Requires-Dist: gitignore-parser==0.1.13
24
+ Requires-Dist: gitpython>=3.1.46
25
+ Requires-Dist: inspect-ai==0.3.282
26
+ Requires-Dist: inspect-scout==0.5.5
27
+ Requires-Dist: jsonlines>=4.0.0
28
+ Requires-Dist: jsonpatch>=1.33
29
+ Requires-Dist: inspect-swe==0.2.71
30
+ Requires-Dist: pick==2.6.0
31
+ Requires-Dist: pydantic>=2.12
32
+ Requires-Dist: pydantic-settings>=2.0
33
+ Requires-Dist: python-dotenv==1.2.4
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==1.0.1
41
+ Requires-Dist: anthropic<2,>=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.0
47
+ Provides-Extra: atif
48
+ Requires-Dist: harbor>=0.24.0; extra == "atif"
49
+ Provides-Extra: hf
50
+ Requires-Dist: pyarrow>=17.0.0; extra == "hf"
51
+ Provides-Extra: providers
52
+ Requires-Dist: google-genai>=1.68.0; extra == "providers"
53
+ Requires-Dist: xai-sdk>=1.9.1; extra == "providers"
54
+ Dynamic: license-file
55
+
56
+ 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/).
57
+
58
+ > 🚨 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.
59
+ >
60
+ > 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)
61
+
62
+ 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.
63
+
64
+ See the [documentation](https://docs.linuxarena.ai) for an overview of Control Tower, a quickstart, and development guides.
65
+
66
+ To get started:
67
+
68
+ ```bash
69
+ git clone https://github.com/linuxarena/control-tower && cd control-tower
70
+ uv sync
71
+ alias ct='uv run ct' # add to your shell profile to keep it
72
+ cp .env.example .env # set ANTHROPIC_API_KEY (or OPENAI_API_KEY)
73
+ uv run python scripts/generate_model_rates.py # model prices, so evals can show what they cost
74
+ ct settings pull linuxarena
75
+ ```
76
+
77
+ Check the install without spending a model call. It takes a couple of minutes:
78
+
79
+ ```bash
80
+ ct run eval --policy ct/test --task-file simple --tag test
81
+ ```
82
+
83
+ Then run a real eval. The first one builds the environment image, which takes about ten minutes:
84
+
85
+ ```bash
86
+ ct run eval --policy ct/attack -e linuxarena/clinical_trial -t adverse_reaction_followup_tracking -s suppress_safety_notifications
87
+ ```
88
+
89
+ ***
90
+
91
+ 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,36 @@
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 quickstart, 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
+ uv run python scripts/generate_model_rates.py # model prices, so evals can show what they cost
19
+ ct settings pull linuxarena
20
+ ```
21
+
22
+ Check the install without spending a model call. It takes a couple of minutes:
23
+
24
+ ```bash
25
+ ct run eval --policy ct/test --task-file simple --tag test
26
+ ```
27
+
28
+ Then run a real eval. The first one builds the environment image, which takes about ten minutes:
29
+
30
+ ```bash
31
+ ct run eval --policy ct/attack -e linuxarena/clinical_trial -t adverse_reaction_followup_tracking -s suppress_safety_notifications
32
+ ```
33
+
34
+ ***
35
+
36
+ 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,287 @@
1
+ [project]
2
+ name = "control-tower"
3
+ version = "6.0.0"
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.5.0",
23
+ "docstring-parser>=0.17",
24
+ "flask>=3.1.3",
25
+ "gitignore-parser==0.1.13",
26
+ "gitpython>=3.1.46",
27
+ "inspect-ai==0.3.282",
28
+ "inspect-scout==0.5.5",
29
+ "jsonlines>=4.0.0",
30
+ "jsonpatch>=1.33",
31
+ "inspect-swe==0.2.71",
32
+ "pick==2.6.0",
33
+ "pydantic>=2.12",
34
+ "pydantic-settings>=2.0",
35
+ "python-dotenv==1.2.4",
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==1.0.1",
43
+
44
+ # Primary model providers and agent SDKs (openai also backs OpenRouter)
45
+ # inspect-ai 0.3.282's Anthropic provider fails on anthropic 2.x (inspect_ai#6003); drop the cap at inspect-ai 0.3.283+.
46
+ "anthropic>=1.0.0,<2",
47
+ "claude-agent-sdk>=0.1.50",
48
+ "openai>=3.1.0",
49
+
50
+ # Run storage and upload (`ct run eval --upload`)
51
+ "boto3>=1.40.0",
52
+ "zstandard>=0.25.0",
53
+
54
+ # The env API's wire contract, shared with every setting package
55
+ "ct-setting-sdk>=4.0.0,<5",
56
+ ]
57
+
58
+ [project.optional-dependencies]
59
+ atif = ["harbor>=0.24.0"]
60
+ hf = ["pyarrow>=17.0.0"]
61
+ providers = [
62
+ "google-genai>=1.68.0",
63
+ "xai-sdk>=1.9.1",
64
+ ]
65
+
66
+ [build-system]
67
+ requires = ["setuptools"]
68
+ build-backend = "setuptools.build_meta"
69
+
70
+ [tool.setuptools.packages.find]
71
+ where = ["src"]
72
+ namespaces = true
73
+ exclude = ["experiments*"]
74
+
75
+ [tool.setuptools.package-data]
76
+ # Non-Python assets that must be available from installed wheels.
77
+ "*" = [
78
+ "*.md",
79
+ "*.txt",
80
+ "*.yml",
81
+ "*.yaml",
82
+ "*.json",
83
+ "*.jsonl",
84
+ "*.tcss",
85
+ "*.sh",
86
+ "py.typed",
87
+ ]
88
+ "control_tower.environments.internet_simulator" = [
89
+ "Dockerfile",
90
+ ".dockerignore",
91
+ "resolve_override.c",
92
+ "malware/malware.c",
93
+ ]
94
+ "control_tower.live" = ["assets/live.gitignore"]
95
+ "control_tower.sandbox.simulated" = ["scratch/Dockerfile"]
96
+
97
+ [tool.setuptools.package-dir]
98
+ "" = "src"
99
+
100
+ [dependency-groups]
101
+ dev = [
102
+ "moto>=5.1.22",
103
+ "pyright==1.1.414", # kept for `--verifytypes` coverage gate; ty has no equivalent yet
104
+ "pytest==9.1.1",
105
+ "pytest-asyncio==1.4.0",
106
+ "pytest-xdist==3.8.0",
107
+ "ruff==0.15.20",
108
+ "ty==0.0.33", # primary type checker; pinned because pre-1.0
109
+ "vulture>=2.15",
110
+ "yamllint==1.38.0",
111
+ "yamlfix>=1.19.1",
112
+ ]
113
+ # A group, not a dependency: PyPI rejects direct-URL requirements, and Apollo ships the SDK only as a GitHub wheel.
114
+ watcher = [
115
+ # 0.41.0 or later: the protocol reads `cost_usd` from each hook outcome.
116
+ "watcher-sdk @ https://github.com/ApolloResearch/watcher-bin/releases/download/v0.41.0/watcher_sdk-0.41.0-py3-none-any.whl",
117
+ ]
118
+
119
+ [tool.uv]
120
+ default-groups = ["dev", "watcher"]
121
+ required-version = ">=0.13.5"
122
+
123
+ # Inspect Scout imports only harbor's pydantic ATIF models; its litellm dependency caps openai below 3.
124
+ [[tool.uv.dependency-metadata]]
125
+ name = "harbor"
126
+ version = "0.24.0"
127
+ requires-dist = ["pydantic>=2"]
128
+ requires-python = ">=3.12"
129
+
130
+ [tool.uv.sources]
131
+ ct-setting-sdk = { path = "packages/ct-setting-sdk", editable = true }
132
+
133
+ [project.scripts]
134
+ ct = "control_tower.cli.main:main"
135
+
136
+ [project.entry-points.inspect_ai]
137
+ # Registers ``control_tower/eval`` and ``control_tower/control_eval`` as discoverable
138
+ # Inspect AI @tasks (plus the ct_upload and ct_diagnostics hooks) after pip-installing control-tower.
139
+ control_tower = "control_tower.eval.launch.inspect_tasks"
140
+
141
+ [project.urls]
142
+ Homepage = "https://linuxarena.ai"
143
+ Repository = "https://github.com/linuxarena/control-tower"
144
+
145
+ [tool.ruff]
146
+ required-version = "==0.15.20"
147
+ src = []
148
+ extend-exclude = [
149
+ ".settings/**",
150
+ ]
151
+
152
+ [tool.ruff.lint]
153
+ extend-select = ["I", "UP", "ANN", "PLC0415", "S110"]
154
+ ignore = [
155
+ "ANN002", # missing type annotation for *args
156
+ "ANN003", # missing type annotation for **kwargs
157
+ "ANN204", # missing return type for __init__ / __new__ / dunder
158
+ "ANN401", # disallow Any — too strict for this codebase
159
+ ]
160
+
161
+ [tool.ruff.lint.isort]
162
+ known-first-party = ["control_tower", "ct_setting_sdk"]
163
+
164
+ [tool.ruff.lint.per-file-ignores]
165
+ "tests/**" = ["ANN", "PLC0415"]
166
+ "packages/*/tests/**" = ["ANN", "PLC0415"]
167
+ "scripts/**" = ["PLC0415"]
168
+ # CLI convention: imports stay inside command functions so `ct` starts fast
169
+ "src/**/cli/**" = ["PLC0415"]
170
+ "src/**/cli.py" = ["PLC0415"]
171
+ "src/**/*_cli.py" = ["PLC0415"]
172
+
173
+ [tool.pytest.ini_options]
174
+ testpaths = ["tests", "packages/ct-setting-sdk/tests"]
175
+ markers = [
176
+ "integration: marks tests as integration tests (deselect with '-m \"not integration\"')",
177
+ "slow: marks tests as slow running",
178
+ ]
179
+ addopts = "-m 'not integration' --durations=10 --ignore=tests/replay_check/packages"
180
+
181
+ [tool.control_tower.typing]
182
+ verifytypes_min_completeness = 100.0
183
+
184
+ [[tool.control_tower.import_boundaries.rules]]
185
+ name = "only cli may import extras (generation/orchestration tooling)"
186
+ sources = ["*"]
187
+ ignore_sources = ["cli", "extras", "extras.*"]
188
+ targets = ["extras", "extras.*"]
189
+ allowed_files = [
190
+ "src/control_tower/backends/hawk/runner.py",
191
+ ]
192
+
193
+ [[tool.control_tower.import_boundaries.rules]]
194
+ name = "extras subpackages are independent except declared edges"
195
+ sources = ["extras.*"]
196
+ targets = ["extras", "extras.*"]
197
+ allowed_edges = [
198
+ "extras.* -> extras.claude_host",
199
+ "extras.* -> extras.env_source",
200
+ "extras.* -> extras.prompts",
201
+ "extras.* -> extras.side_task_folder",
202
+ "extras.* -> extras.storage",
203
+ "extras.dashboard_cli -> extras.dashboard",
204
+ "extras.task_analysis -> extras.traj_analysis",
205
+ ]
206
+
207
+ [[tool.control_tower.import_boundaries.rules]]
208
+ name = "utils is a leaf"
209
+ sources = ["utils"]
210
+ targets = ["*"]
211
+
212
+ [[tool.control_tower.import_boundaries.rules]]
213
+ name = "monitors stand alone: they import only models, tools and utils"
214
+ sources = ["monitors"]
215
+ targets = ["*"]
216
+ allowed_edges = [
217
+ "monitors -> models",
218
+ "monitors -> tools",
219
+ "monitors -> utils",
220
+ ]
221
+
222
+ [[tool.control_tower.import_boundaries.rules]]
223
+ name = "eval and runs must not import live"
224
+ sources = ["eval", "eval.*", "runs"]
225
+ targets = ["live"]
226
+
227
+ [[tool.control_tower.import_boundaries.rules]]
228
+ name = "the game protocols and policies are written against imports no launch, monitoring or cli"
229
+ sources = ["eval.game"]
230
+ targets = ["eval.launch", "eval.monitoring", "cli"]
231
+
232
+ [[tool.control_tower.import_boundaries.rules]]
233
+ name = "only eval.launch and cli import backends"
234
+ sources = ["*"]
235
+ ignore_sources = ["backends", "cli", "eval.launch"]
236
+ targets = ["backends"]
237
+ allowed_files = [
238
+ "src/control_tower/eval/monitoring/posthoc.py",
239
+ "src/control_tower/models/role_model.py",
240
+ ]
241
+
242
+ [[tool.control_tower.import_boundaries.module_rules]]
243
+ name = "a backend runs the task args eval.launch hands it, never the launch itself"
244
+ sources = ["control_tower.backends", "control_tower.backends.*"]
245
+ forbidden = [
246
+ "control_tower.cli",
247
+ "control_tower.eval.launch.assemble",
248
+ "control_tower.eval.launch.dispatch",
249
+ "control_tower.eval.launch.inspect_tasks",
250
+ ]
251
+
252
+ [[tool.control_tower.import_boundaries.module_rules]]
253
+ name = "a blue protocol reads the sample only through its arguments"
254
+ sources = ["control_tower.protocols", "control_tower.protocols.*"]
255
+ forbidden = [
256
+ "inspect_ai.event",
257
+ "inspect_ai.log",
258
+ "inspect_ai.solver",
259
+ "inspect_ai.util.Store",
260
+ "inspect_ai.util.StoreModel",
261
+ "inspect_ai.util._store",
262
+ "inspect_ai.util._store_model",
263
+ "inspect_ai.util.store",
264
+ "inspect_ai.util.store_as",
265
+ "control_tower.eval.monitoring.scorer.MonitorScores",
266
+ "control_tower.eval.game.red",
267
+ "control_tower.eval.log",
268
+ "control_tower.sandbox.simulated",
269
+ "control_tower.task",
270
+ "ct_setting_sdk.env",
271
+ ]
272
+
273
+ [tool.ty.src]
274
+ include = [
275
+ ".github/scripts",
276
+ "packages/ct-setting-sdk/src",
277
+ "scripts",
278
+ "src/control_tower",
279
+ "tests",
280
+ ]
281
+ exclude = [
282
+ "**/node_modules",
283
+ ".settings/**",
284
+ ]
285
+
286
+ [tool.ty.environment]
287
+ 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,31 @@
1
+ """Where an eval runs: in this process, on the EC2 fleet, or on Hawk."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ if TYPE_CHECKING:
7
+ from inspect_ai.log import EvalLog
8
+
9
+ from control_tower.eval.launch.options import EvalCliInputs
10
+
11
+
12
+ class Backend(ABC):
13
+ """Where `run_task` runs an eval, given its completed task args."""
14
+
15
+ def resolvable(self, name: str) -> bool:
16
+ """Whether the task set, policy, protocol or monitor ``name`` is looked up before the run; the rest are looked
17
+ up where the task is built."""
18
+ return True
19
+
20
+ @abstractmethod
21
+ def run(
22
+ self,
23
+ task_name: str,
24
+ task_args: dict[str, Any],
25
+ eval_inputs: "EvalCliInputs",
26
+ *,
27
+ upload: bool,
28
+ metadata: dict[str, Any],
29
+ ) -> "EvalLog | None":
30
+ """Run ``task_name`` with ``task_args``, ``metadata`` joining its eval metadata, and upload the log when
31
+ ``upload``; return it, or None when it stays where it ran."""
@@ -0,0 +1 @@
1
+ """Fleet mode: distributed evaluation on EC2 workers."""
@@ -0,0 +1,45 @@
1
+ """Worker AMI resolution for fleet mode: the pre-baked AMI named in SSM ``/linuxbench/worker-ami-id``."""
2
+
3
+ import boto3
4
+ import botocore.exceptions
5
+
6
+ SSM_AMI_PARAM = "/linuxbench/worker-ami-id"
7
+
8
+
9
+ def get_worker_ami_id(region: str = "us-east-1", requested: str | None = None) -> str:
10
+ """Return the AMI to use for fleet workers, refusing one that cannot boot now.
11
+
12
+ ``requested`` is an AMI id, or the SSM parameter naming one; the default is ``SSM_AMI_PARAM``.
13
+ """
14
+ source = requested or SSM_AMI_PARAM
15
+ ami_id = source
16
+ if source.startswith("/"):
17
+ ssm = boto3.client("ssm", region_name=region)
18
+ try:
19
+ ami_id = ssm.get_parameter(Name=source)["Parameter"]["Value"]
20
+ except ssm.exceptions.ParameterNotFound as e:
21
+ raise RuntimeError(
22
+ f"No worker AMI: SSM parameter {source} does not exist in {region}. "
23
+ f"Build one with scripts/build_worker_ami.sh --region {region}."
24
+ ) from e
25
+ label = ami_id if ami_id == source else f"{ami_id} (from {source})"
26
+ ec2 = boto3.client("ec2", region_name=region)
27
+ try:
28
+ images = ec2.describe_images(ImageIds=[ami_id])["Images"]
29
+ except botocore.exceptions.ClientError as e:
30
+ if not e.response["Error"]["Code"].startswith("InvalidAMIID"):
31
+ raise
32
+ raise RuntimeError(
33
+ f"Worker AMI {label} not found in {region}: "
34
+ f"{e.response['Error']['Message']}"
35
+ ) from e
36
+ if not images:
37
+ raise RuntimeError(f"Worker AMI {label} not found in {region}.")
38
+ image = images[0]
39
+ if image["State"] != "available":
40
+ reason = image.get("StateReason", {}).get("Message", "")
41
+ raise RuntimeError(
42
+ f"Worker AMI {label} in {region} is {image['State']}"
43
+ f"{f' ({reason})' if reason else ''}, not available; no workers launched."
44
+ )
45
+ return ami_id
@@ -0,0 +1,9 @@
1
+ """AWS caller identity lookup for resource tagging."""
2
+
3
+ import boto3
4
+
5
+
6
+ def caller_identity_name(region: str) -> str:
7
+ """Get the caller's identity name (IAM username or SSO session name) for resource tagging."""
8
+ sts = boto3.client("sts", region_name=region)
9
+ return sts.get_caller_identity()["Arn"].rsplit("/", 1)[-1]