controlloop 0.1.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 (267) hide show
  1. controlloop-0.1.0/.gitignore +11 -0
  2. controlloop-0.1.0/LICENSE +191 -0
  3. controlloop-0.1.0/PKG-INFO +427 -0
  4. controlloop-0.1.0/README.md +413 -0
  5. controlloop-0.1.0/pyproject.toml +76 -0
  6. controlloop-0.1.0/src/controlloop/__init__.py +16 -0
  7. controlloop-0.1.0/src/controlloop/__main__.py +6 -0
  8. controlloop-0.1.0/src/controlloop/acbom/__init__.py +93 -0
  9. controlloop-0.1.0/src/controlloop/acbom/completeness.py +117 -0
  10. controlloop-0.1.0/src/controlloop/acbom/identity.py +210 -0
  11. controlloop-0.1.0/src/controlloop/acbom/models.py +395 -0
  12. controlloop-0.1.0/src/controlloop/acbom/serialization.py +374 -0
  13. controlloop-0.1.0/src/controlloop/acbom/versioning.py +104 -0
  14. controlloop-0.1.0/src/controlloop/adapters/__init__.py +53 -0
  15. controlloop-0.1.0/src/controlloop/adapters/a2a.py +479 -0
  16. controlloop-0.1.0/src/controlloop/adapters/crewai.py +646 -0
  17. controlloop-0.1.0/src/controlloop/adapters/framework.py +74 -0
  18. controlloop-0.1.0/src/controlloop/adapters/framework_versions.py +211 -0
  19. controlloop-0.1.0/src/controlloop/adapters/iam.py +485 -0
  20. controlloop-0.1.0/src/controlloop/adapters/langgraph.py +749 -0
  21. controlloop-0.1.0/src/controlloop/adapters/mcp.py +179 -0
  22. controlloop-0.1.0/src/controlloop/adapters/mcp_live.py +582 -0
  23. controlloop-0.1.0/src/controlloop/adapters/oasf.py +183 -0
  24. controlloop-0.1.0/src/controlloop/adapters/openai_agents.py +824 -0
  25. controlloop-0.1.0/src/controlloop/adapters/openapi.py +377 -0
  26. controlloop-0.1.0/src/controlloop/adapters/runner.py +116 -0
  27. controlloop-0.1.0/src/controlloop/adapters/sandbox.py +66 -0
  28. controlloop-0.1.0/src/controlloop/baseline/__init__.py +102 -0
  29. controlloop-0.1.0/src/controlloop/baseline/integrity.py +124 -0
  30. controlloop-0.1.0/src/controlloop/baseline/merge_base.py +602 -0
  31. controlloop-0.1.0/src/controlloop/baseline/models.py +206 -0
  32. controlloop-0.1.0/src/controlloop/baseline/provenance.py +162 -0
  33. controlloop-0.1.0/src/controlloop/baseline/resolution.py +163 -0
  34. controlloop-0.1.0/src/controlloop/baseline/serialization.py +115 -0
  35. controlloop-0.1.0/src/controlloop/baseline/staleness.py +227 -0
  36. controlloop-0.1.0/src/controlloop/bom.py +226 -0
  37. controlloop-0.1.0/src/controlloop/bounded_recursion.py +50 -0
  38. controlloop-0.1.0/src/controlloop/capability/__init__.py +48 -0
  39. controlloop-0.1.0/src/controlloop/capability/blast_radius.py +289 -0
  40. controlloop-0.1.0/src/controlloop/capability/compute.py +479 -0
  41. controlloop-0.1.0/src/controlloop/capability/models.py +129 -0
  42. controlloop-0.1.0/src/controlloop/capability/taxonomy.py +158 -0
  43. controlloop-0.1.0/src/controlloop/cli.py +2368 -0
  44. controlloop-0.1.0/src/controlloop/config.py +517 -0
  45. controlloop-0.1.0/src/controlloop/diagnostics.py +149 -0
  46. controlloop-0.1.0/src/controlloop/diff/__init__.py +87 -0
  47. controlloop-0.1.0/src/controlloop/diff/compute.py +298 -0
  48. controlloop-0.1.0/src/controlloop/diff/material_summary.py +308 -0
  49. controlloop-0.1.0/src/controlloop/diff/models.py +156 -0
  50. controlloop-0.1.0/src/controlloop/diff/reduction.py +118 -0
  51. controlloop-0.1.0/src/controlloop/diff/report.py +116 -0
  52. controlloop-0.1.0/src/controlloop/exit_codes.py +140 -0
  53. controlloop-0.1.0/src/controlloop/findings/__init__.py +58 -0
  54. controlloop-0.1.0/src/controlloop/findings/identity.py +148 -0
  55. controlloop-0.1.0/src/controlloop/findings/models.py +344 -0
  56. controlloop-0.1.0/src/controlloop/findings/rendering.py +152 -0
  57. controlloop-0.1.0/src/controlloop/ignore.py +178 -0
  58. controlloop-0.1.0/src/controlloop/manifest/__init__.py +59 -0
  59. controlloop-0.1.0/src/controlloop/manifest/annotation.py +161 -0
  60. controlloop-0.1.0/src/controlloop/manifest/approvals.py +92 -0
  61. controlloop-0.1.0/src/controlloop/manifest/ceiling.py +441 -0
  62. controlloop-0.1.0/src/controlloop/manifest/draft.py +467 -0
  63. controlloop-0.1.0/src/controlloop/manifest/models.py +384 -0
  64. controlloop-0.1.0/src/controlloop/manifest/parser.py +100 -0
  65. controlloop-0.1.0/src/controlloop/manifest/reconciliation.py +148 -0
  66. controlloop-0.1.0/src/controlloop/output.py +157 -0
  67. controlloop-0.1.0/src/controlloop/policy/__init__.py +126 -0
  68. controlloop-0.1.0/src/controlloop/policy/engine.py +279 -0
  69. controlloop-0.1.0/src/controlloop/policy/models.py +181 -0
  70. controlloop-0.1.0/src/controlloop/policy/rulepack.py +274 -0
  71. controlloop-0.1.0/src/controlloop/policy/rules/__init__.py +262 -0
  72. controlloop-0.1.0/src/controlloop/policy/rules/_shared.py +86 -0
  73. controlloop-0.1.0/src/controlloop/policy/rules/broad_permission.py +270 -0
  74. controlloop-0.1.0/src/controlloop/policy/rules/capability_ceiling.py +522 -0
  75. controlloop-0.1.0/src/controlloop/policy/rules/destructive_or_financial_action.py +296 -0
  76. controlloop-0.1.0/src/controlloop/policy/rules/exfiltration_triangle.py +537 -0
  77. controlloop-0.1.0/src/controlloop/policy/rules/hardcoded_secrets.py +194 -0
  78. controlloop-0.1.0/src/controlloop/policy/rules/missing_action_logging.py +184 -0
  79. controlloop-0.1.0/src/controlloop/policy/rules/sensitive_write_without_approval.py +222 -0
  80. controlloop-0.1.0/src/controlloop/policy/rules/unauthorized_delegation.py +241 -0
  81. controlloop-0.1.0/src/controlloop/policy/rules/undeclared_tools.py +238 -0
  82. controlloop-0.1.0/src/controlloop/policy/rules/unresolved_dynamic_registration.py +199 -0
  83. controlloop-0.1.0/src/controlloop/policy/suppressions.py +260 -0
  84. controlloop-0.1.0/src/controlloop/policy/thresholds.py +369 -0
  85. controlloop-0.1.0/src/controlloop/py.typed +0 -0
  86. controlloop-0.1.0/src/controlloop/redaction.py +327 -0
  87. controlloop-0.1.0/src/controlloop/reporting/__init__.py +84 -0
  88. controlloop-0.1.0/src/controlloop/reporting/cyclonedx.py +116 -0
  89. controlloop-0.1.0/src/controlloop/reporting/evidence.py +170 -0
  90. controlloop-0.1.0/src/controlloop/reporting/report.py +141 -0
  91. controlloop-0.1.0/src/controlloop/reporting/sarif.py +119 -0
  92. controlloop-0.1.0/src/controlloop/reporting/terminal.py +286 -0
  93. controlloop-0.1.0/src/controlloop/repository.py +786 -0
  94. controlloop-0.1.0/src/controlloop/schemas/acbom/1.0.0/acbom.schema.json +472 -0
  95. controlloop-0.1.0/src/controlloop/schemas/acbom/1.1.0/acbom.schema.json +481 -0
  96. controlloop-0.1.0/src/controlloop/schemas/baseline/1.0.0/baseline.schema.json +243 -0
  97. controlloop-0.1.0/src/controlloop/schemas/baseline/1.1.0/baseline.schema.json +423 -0
  98. controlloop-0.1.0/src/controlloop/schemas/evidence/1.0.0/evidence.schema.json +805 -0
  99. controlloop-0.1.0/src/controlloop/schemas/evidence/1.1.0/evidence.schema.json +833 -0
  100. controlloop-0.1.0/src/controlloop/schemas/evidence/1.2.0/evidence.schema.json +886 -0
  101. controlloop-0.1.0/src/controlloop/schemas/manifest/1.0.0/manifest.schema.json +408 -0
  102. controlloop-0.1.0/src/controlloop/schemas/manifest/1.1.0/manifest.schema.json +568 -0
  103. controlloop-0.1.0/src/controlloop/schemas/manifest/1.2.0/manifest.schema.json +568 -0
  104. controlloop-0.1.0/src/controlloop/schemas/report/1.0.0/report.schema.json +784 -0
  105. controlloop-0.1.0/src/controlloop/schemas/report/1.1.0/report.schema.json +837 -0
  106. controlloop-0.1.0/src/controlloop/secret_scan.py +452 -0
  107. controlloop-0.1.0/src/controlloop/verbosity.py +201 -0
  108. controlloop-0.1.0/tests/acbom/conformance.py +33 -0
  109. controlloop-0.1.0/tests/acbom/test_completeness.py +224 -0
  110. controlloop-0.1.0/tests/acbom/test_conformance.py +74 -0
  111. controlloop-0.1.0/tests/acbom/test_edge_merge.py +171 -0
  112. controlloop-0.1.0/tests/acbom/test_identity.py +294 -0
  113. controlloop-0.1.0/tests/acbom/test_node_merge.py +210 -0
  114. controlloop-0.1.0/tests/acbom/test_schema_and_models.py +364 -0
  115. controlloop-0.1.0/tests/acbom/test_serialization_unit.py +315 -0
  116. controlloop-0.1.0/tests/acbom/test_versioning.py +180 -0
  117. controlloop-0.1.0/tests/adapters/conformance_fixtures.py +804 -0
  118. controlloop-0.1.0/tests/adapters/fakes.py +164 -0
  119. controlloop-0.1.0/tests/adapters/test_a2a.py +282 -0
  120. controlloop-0.1.0/tests/adapters/test_adapter_conformance.py +230 -0
  121. controlloop-0.1.0/tests/adapters/test_crewai.py +388 -0
  122. controlloop-0.1.0/tests/adapters/test_framework.py +77 -0
  123. controlloop-0.1.0/tests/adapters/test_framework_versions.py +139 -0
  124. controlloop-0.1.0/tests/adapters/test_fuzz_adapters.py +132 -0
  125. controlloop-0.1.0/tests/adapters/test_iam.py +237 -0
  126. controlloop-0.1.0/tests/adapters/test_langgraph.py +411 -0
  127. controlloop-0.1.0/tests/adapters/test_mcp.py +254 -0
  128. controlloop-0.1.0/tests/adapters/test_mcp_live.py +273 -0
  129. controlloop-0.1.0/tests/adapters/test_no_format_knowledge_in_canonical_layer.py +67 -0
  130. controlloop-0.1.0/tests/adapters/test_oasf.py +100 -0
  131. controlloop-0.1.0/tests/adapters/test_openai_agents.py +409 -0
  132. controlloop-0.1.0/tests/adapters/test_openapi.py +180 -0
  133. controlloop-0.1.0/tests/adapters/test_runner.py +181 -0
  134. controlloop-0.1.0/tests/adapters/test_sandbox.py +66 -0
  135. controlloop-0.1.0/tests/baseline/test_baseline_integrity.py +195 -0
  136. controlloop-0.1.0/tests/baseline/test_baseline_models.py +278 -0
  137. controlloop-0.1.0/tests/baseline/test_baseline_provenance.py +733 -0
  138. controlloop-0.1.0/tests/baseline/test_baseline_resolution.py +247 -0
  139. controlloop-0.1.0/tests/baseline/test_baseline_serialization.py +132 -0
  140. controlloop-0.1.0/tests/baseline/test_baseline_staleness.py +428 -0
  141. controlloop-0.1.0/tests/baseline/test_merge_base.py +674 -0
  142. controlloop-0.1.0/tests/capability/test_blast_radius.py +364 -0
  143. controlloop-0.1.0/tests/capability/test_capability_compute.py +211 -0
  144. controlloop-0.1.0/tests/capability/test_capability_models.py +181 -0
  145. controlloop-0.1.0/tests/capability/test_capability_paths.py +187 -0
  146. controlloop-0.1.0/tests/capability/test_cycle_protection.py +203 -0
  147. controlloop-0.1.0/tests/capability/test_graph_explosion_bounds.py +224 -0
  148. controlloop-0.1.0/tests/capability/test_taxonomy.py +237 -0
  149. controlloop-0.1.0/tests/capability/test_transitive_paths.py +295 -0
  150. controlloop-0.1.0/tests/concepts/reference_fixture.py +353 -0
  151. controlloop-0.1.0/tests/concepts/test_acbom_concepts_doc.py +148 -0
  152. controlloop-0.1.0/tests/conftest.py +43 -0
  153. controlloop-0.1.0/tests/determinism_support.py +243 -0
  154. controlloop-0.1.0/tests/diff/test_diff_compute.py +614 -0
  155. controlloop-0.1.0/tests/diff/test_diff_models.py +156 -0
  156. controlloop-0.1.0/tests/diff/test_diff_report.py +111 -0
  157. controlloop-0.1.0/tests/diff/test_material_summary.py +434 -0
  158. controlloop-0.1.0/tests/diff/test_reduction.py +336 -0
  159. controlloop-0.1.0/tests/findings/test_finding_construction.py +207 -0
  160. controlloop-0.1.0/tests/findings/test_finding_identity.py +313 -0
  161. controlloop-0.1.0/tests/findings/test_finding_models.py +318 -0
  162. controlloop-0.1.0/tests/findings/test_finding_offline.py +27 -0
  163. controlloop-0.1.0/tests/findings/test_finding_rendering.py +265 -0
  164. controlloop-0.1.0/tests/fixtures/acbom/minimal-input.json +61 -0
  165. controlloop-0.1.0/tests/fixtures/baseline/baseline-with-malformed-provenance.json +34 -0
  166. controlloop-0.1.0/tests/fixtures/baseline/baseline-with-provenance.json +36 -0
  167. controlloop-0.1.0/tests/fixtures/baseline/minimal-baseline.json +30 -0
  168. controlloop-0.1.0/tests/fixtures/cyclonedx/bom-1.6.schema.json +5673 -0
  169. controlloop-0.1.0/tests/fixtures/cyclonedx/jsf-0.82.schema.json +240 -0
  170. controlloop-0.1.0/tests/fixtures/cyclonedx/spdx.schema.json +712 -0
  171. controlloop-0.1.0/tests/fixtures/golden/agent-with-ceiling-breach/acbom.json +1 -0
  172. controlloop-0.1.0/tests/fixtures/golden/agent-with-ceiling-breach/report.json +1 -0
  173. controlloop-0.1.0/tests/fixtures/golden/diff-empty-to-single-agent/report.json +1 -0
  174. controlloop-0.1.0/tests/fixtures/golden/empty/acbom.json +1 -0
  175. controlloop-0.1.0/tests/fixtures/golden/empty/report.json +1 -0
  176. controlloop-0.1.0/tests/fixtures/golden/single-agent/acbom.json +1 -0
  177. controlloop-0.1.0/tests/fixtures/golden/single-agent/report.json +1 -0
  178. controlloop-0.1.0/tests/fixtures/sarif/README.md +24 -0
  179. controlloop-0.1.0/tests/fixtures/sarif/sarif-schema-2.1.0.json +3389 -0
  180. controlloop-0.1.0/tests/fixtures/stub_mcp_server.py +114 -0
  181. controlloop-0.1.0/tests/fuzz_corpus/baseline/recursion_error_nested_arrays.bin +1 -0
  182. controlloop-0.1.0/tests/fuzz_corpus/manifest/recursion_error_nested_braces.bin +1 -0
  183. controlloop-0.1.0/tests/fuzz_support.py +254 -0
  184. controlloop-0.1.0/tests/golden_fixtures.py +85 -0
  185. controlloop-0.1.0/tests/golden_regenerate.py +109 -0
  186. controlloop-0.1.0/tests/manifest/test_annotation.py +344 -0
  187. controlloop-0.1.0/tests/manifest/test_approvals.py +125 -0
  188. controlloop-0.1.0/tests/manifest/test_ceiling.py +537 -0
  189. controlloop-0.1.0/tests/manifest/test_display_name_matching.py +228 -0
  190. controlloop-0.1.0/tests/manifest/test_draft.py +535 -0
  191. controlloop-0.1.0/tests/manifest/test_models.py +595 -0
  192. controlloop-0.1.0/tests/manifest/test_parser.py +103 -0
  193. controlloop-0.1.0/tests/manifest/test_reconciliation.py +221 -0
  194. controlloop-0.1.0/tests/performance/baseline.json +5 -0
  195. controlloop-0.1.0/tests/performance/bench_repo.py +73 -0
  196. controlloop-0.1.0/tests/performance/test_benchmark.py +307 -0
  197. controlloop-0.1.0/tests/policy/fixtures/rule_pack_fixture_rules.py +52 -0
  198. controlloop-0.1.0/tests/policy/fixtures/safe_rule.py +79 -0
  199. controlloop-0.1.0/tests/policy/fixtures/unsafe_rule_open.py +22 -0
  200. controlloop-0.1.0/tests/policy/fixtures/unsafe_rule_socket.py +17 -0
  201. controlloop-0.1.0/tests/policy/fixtures/unsafe_rule_subprocess.py +17 -0
  202. controlloop-0.1.0/tests/policy/rules/_helpers.py +289 -0
  203. controlloop-0.1.0/tests/policy/rules/test_all_rules_registry.py +141 -0
  204. controlloop-0.1.0/tests/policy/rules/test_broad_permission.py +329 -0
  205. controlloop-0.1.0/tests/policy/rules/test_capability_ceiling.py +608 -0
  206. controlloop-0.1.0/tests/policy/rules/test_destructive_or_financial_action.py +443 -0
  207. controlloop-0.1.0/tests/policy/rules/test_documentation_urls.py +149 -0
  208. controlloop-0.1.0/tests/policy/rules/test_exfiltration_triangle.py +402 -0
  209. controlloop-0.1.0/tests/policy/rules/test_gate_completeness_enforcement.py +277 -0
  210. controlloop-0.1.0/tests/policy/rules/test_hardcoded_secrets.py +188 -0
  211. controlloop-0.1.0/tests/policy/rules/test_missing_action_logging.py +289 -0
  212. controlloop-0.1.0/tests/policy/rules/test_sensitive_write_without_approval.py +378 -0
  213. controlloop-0.1.0/tests/policy/rules/test_shared.py +48 -0
  214. controlloop-0.1.0/tests/policy/rules/test_unauthorized_delegation.py +292 -0
  215. controlloop-0.1.0/tests/policy/rules/test_undeclared_tools.py +384 -0
  216. controlloop-0.1.0/tests/policy/rules/test_unresolved_dynamic_registration.py +279 -0
  217. controlloop-0.1.0/tests/policy/test_policy_engine.py +497 -0
  218. controlloop-0.1.0/tests/policy/test_policy_models.py +108 -0
  219. controlloop-0.1.0/tests/policy/test_policy_thresholds.py +480 -0
  220. controlloop-0.1.0/tests/policy/test_rule_pack.py +325 -0
  221. controlloop-0.1.0/tests/policy/test_suppressions.py +456 -0
  222. controlloop-0.1.0/tests/reference/cli_doc_fixtures.py +143 -0
  223. controlloop-0.1.0/tests/reference/test_cli_reference_doc.py +185 -0
  224. controlloop-0.1.0/tests/reporting/generate_evidence_schema.py +59 -0
  225. controlloop-0.1.0/tests/reporting/generate_report_schema.py +64 -0
  226. controlloop-0.1.0/tests/reporting/test_cyclonedx.py +264 -0
  227. controlloop-0.1.0/tests/reporting/test_evidence.py +258 -0
  228. controlloop-0.1.0/tests/reporting/test_evidence_schema.py +101 -0
  229. controlloop-0.1.0/tests/reporting/test_report.py +182 -0
  230. controlloop-0.1.0/tests/reporting/test_report_schema.py +96 -0
  231. controlloop-0.1.0/tests/reporting/test_sarif.py +199 -0
  232. controlloop-0.1.0/tests/reporting/test_terminal.py +383 -0
  233. controlloop-0.1.0/tests/test_action_scripts.py +80 -0
  234. controlloop-0.1.0/tests/test_adapter_documentation_drift.py +130 -0
  235. controlloop-0.1.0/tests/test_assemble_schema_site.py +143 -0
  236. controlloop-0.1.0/tests/test_bom.py +207 -0
  237. controlloop-0.1.0/tests/test_bounded_recursion.py +60 -0
  238. controlloop-0.1.0/tests/test_build_binary_script.py +332 -0
  239. controlloop-0.1.0/tests/test_checksums_script.py +278 -0
  240. controlloop-0.1.0/tests/test_cli.py +2776 -0
  241. controlloop-0.1.0/tests/test_config.py +574 -0
  242. controlloop-0.1.0/tests/test_determinism_harness.py +314 -0
  243. controlloop-0.1.0/tests/test_diagnostics.py +256 -0
  244. controlloop-0.1.0/tests/test_docs_availability_audit.py +300 -0
  245. controlloop-0.1.0/tests/test_exit_codes.py +23 -0
  246. controlloop-0.1.0/tests/test_fixture_corpus_doc.py +130 -0
  247. controlloop-0.1.0/tests/test_free_public_repository_path.py +274 -0
  248. controlloop-0.1.0/tests/test_fuzz_baseline.py +129 -0
  249. controlloop-0.1.0/tests/test_fuzz_manifest.py +101 -0
  250. controlloop-0.1.0/tests/test_gate_determinism_regression.py +348 -0
  251. controlloop-0.1.0/tests/test_golden_baselines.py +149 -0
  252. controlloop-0.1.0/tests/test_ignore.py +164 -0
  253. controlloop-0.1.0/tests/test_install_script.py +478 -0
  254. controlloop-0.1.0/tests/test_offline_canary.py +270 -0
  255. controlloop-0.1.0/tests/test_offline_harness.py +119 -0
  256. controlloop-0.1.0/tests/test_output.py +268 -0
  257. controlloop-0.1.0/tests/test_pre_commit_hook.py +259 -0
  258. controlloop-0.1.0/tests/test_privacy_security_doc.py +104 -0
  259. controlloop-0.1.0/tests/test_redaction.py +1446 -0
  260. controlloop-0.1.0/tests/test_reference_scenarios_workflow.py +187 -0
  261. controlloop-0.1.0/tests/test_release_scripts.py +302 -0
  262. controlloop-0.1.0/tests/test_release_workflow_structure.py +488 -0
  263. controlloop-0.1.0/tests/test_repository.py +1190 -0
  264. controlloop-0.1.0/tests/test_rules_and_example_commands.py +297 -0
  265. controlloop-0.1.0/tests/test_scenario_assertions.py +321 -0
  266. controlloop-0.1.0/tests/test_secret_scan.py +309 -0
  267. controlloop-0.1.0/tests/test_verbosity.py +278 -0
@@ -0,0 +1,11 @@
1
+ .coverage
2
+ .mypy_cache/
3
+ .pytest_cache/
4
+ .ruff_cache/
5
+ .venv/
6
+ __pycache__/
7
+ dist/
8
+ dist-binary/
9
+ build-binary/
10
+ *.egg-info/
11
+ *.py[cod]
@@ -0,0 +1,191 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ Copyright 2026 ControlLoop
180
+
181
+ Licensed under the Apache License, Version 2.0 (the "License");
182
+ you may not use this file except in compliance with the License.
183
+ You may obtain a copy of the License at
184
+
185
+ http://www.apache.org/licenses/LICENSE-2.0
186
+
187
+ Unless required by applicable law or agreed to in writing, software
188
+ distributed under the License is distributed on an "AS IS" BASIS,
189
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190
+ See the License for the specific language governing permissions and
191
+ limitations under the License.
@@ -0,0 +1,427 @@
1
+ Metadata-Version: 2.5
2
+ Name: controlloop
3
+ Version: 0.1.0
4
+ Summary: Local-first security scanner and deterministic CI gate for AI agents
5
+ License-Expression: Apache-2.0
6
+ License-File: LICENSE
7
+ Requires-Python: <3.13,>=3.12
8
+ Requires-Dist: pathspec<2,>=1.1.1
9
+ Requires-Dist: pydantic<3,>=2.12
10
+ Requires-Dist: python-hcl2>=8.1.2
11
+ Requires-Dist: pyyaml>=6.0.3
12
+ Requires-Dist: typer<1,>=0.21
13
+ Description-Content-Type: text/markdown
14
+
15
+ # ControlLoop CLI
16
+
17
+ **A local-first scanner and deterministic CI gate for what your AI agents can
18
+ actually do.**
19
+
20
+ An agent's real authority is spread across an agent card, an MCP config, an
21
+ OpenAPI spec, an IAM policy -- and, for most agents, the framework code
22
+ itself: a CrewAI crew, a LangGraph graph, an OpenAI Agents SDK handoff
23
+ chain. No single file tells you that adding one
24
+ skill just gave it the ability to move money. ControlLoop reads those files,
25
+ builds one graph of the agent's capabilities, compares it to the state you
26
+ approved, and fails your build when the agent's authority grows past the
27
+ ceiling you declared.
28
+
29
+ It runs entirely on your machine. It never executes your code, never starts
30
+ your MCP servers, never contacts a declared endpoint, and never sends your
31
+ source anywhere.
32
+
33
+ > **Development preview.** `init`, `bom`, `diff`, `scan`, `gate`, `rules`, and
34
+ > `example` all work
35
+ > and are covered by tests. There is no published release yet — no PyPI
36
+ > package, no Homebrew tap, no container image, no tagged version. Install
37
+ > from source as below. See [What is not built yet](#what-is-not-built-yet).
38
+
39
+ ---
40
+
41
+ ## Why use it
42
+
43
+ - **Catch capability growth in review, not after.** A pull request that adds
44
+ a bulk-refund tool is blocked with the reason, the path, and a retained
45
+ evidence artifact — before it merges.
46
+ - **Declare a ceiling and have it hold.** Pattern rules only catch what
47
+ someone anticipated. A capability ceiling blocks authority you never
48
+ imagined, through routes no rule matches.
49
+ - **Deterministic.** Same inputs, same pinned versions, same digest, same
50
+ verdict. No model decides whether your build passes.
51
+ - **Nothing protected leaves.** Source, prompts, credentials, environment
52
+ values, and customer data never appear in output, logs, errors, identity
53
+ material, or artifacts.
54
+ - **Free and local.** Core scanning works with the network disabled.
55
+
56
+ ## Install and first run
57
+
58
+ Requires **Python 3.12**, [**uv**](https://docs.astral.sh/uv/), and Git.
59
+
60
+ ```bash
61
+ cd cli
62
+ uv sync --locked --all-groups
63
+ uv run controlloop --version
64
+ ```
65
+
66
+ ```
67
+ ControlLoop 0.1.0
68
+ Supported OASF versions: none yet
69
+ Rule pack: controlloop-community 0.2.0 (10 rules)
70
+ ```
71
+
72
+ Point it at a repository containing an agent:
73
+
74
+ ```bash
75
+ uv run controlloop scan /path/to/your/agent-repo
76
+ ```
77
+
78
+ Nothing to try it on? The public
79
+ [reference agent](https://github.com/danny-tijerina2/controlloop-reference-agent)
80
+ is a realistic, deliberately imperfect agent built for exactly this:
81
+
82
+ ```bash
83
+ git clone https://github.com/danny-tijerina2/controlloop-reference-agent
84
+ uv run controlloop scan controlloop-reference-agent/scenarios/order-support-agent
85
+ ```
86
+
87
+ ## The commands
88
+
89
+ New here? Run `controlloop example` — it prints a five-step walkthrough and
90
+ points at the [Example walkthrough](../docs/guides/example-walkthrough.md)
91
+ guide.
92
+
93
+ | Command | Use it to |
94
+ | --- | --- |
95
+ | `example` | Print a guided walkthrough of how ControlLoop works |
96
+ | `rules` | List the rule pack in use and what each rule looks for |
97
+ | [`init`](#init) | Draft a `controlloop.yaml` from what's actually in the repo |
98
+ | [`bom`](#bom) | Generate or validate the capability graph (ACBOM) |
99
+ | [`diff`](#diff) | See what changed against a baseline |
100
+ | [`scan`](#scan) | Full report for a human: graph, policy, findings |
101
+ | [`gate`](#gate) | One verdict and one exit code, for CI |
102
+
103
+ `scan` is what you run at your desk. `gate` is what you run in CI. Both do
104
+ the same analysis; `gate` never prompts, always writes an evidence artifact,
105
+ and returns a verdict designed to be acted on by a machine.
106
+
107
+ ### `init`
108
+
109
+ ```bash
110
+ uv run controlloop init [REPOSITORY] [--dry-run]
111
+ ```
112
+
113
+ Discovers candidate agents and writes a reviewable `controlloop.yaml`. Every
114
+ field is present even where ControlLoop could not determine a value — those
115
+ are marked `TODO` with a comment saying what to supply. It evaluates no
116
+ policy and enforces nothing.
117
+
118
+ `--dry-run` prints the draft instead of writing it. Real output:
119
+
120
+ ```
121
+ # controlloop.yaml
122
+ # ControlLoop security manifest -- generated by `controlloop init`.
123
+ ...
124
+ # Manifest schema version 1.1.0.
125
+
126
+ schema_version: "1.1.0"
127
+
128
+ # TODO: owner
129
+ # ControlLoop cannot determine who is accountable for this
130
+ # repository's agents. Replace the placeholder below with an
131
+ # identifier for the responsible team or individual (for
132
+ # example: "platform-security" or "jane.doe").
133
+ owner: "TODO-owner"
134
+
135
+ trust_boundaries:
136
+ # Discovered candidate agents (from repository discovery):
137
+ # - invoice-agent (tools observed: Send an invoice)
138
+ - name: "TODO-trust-boundary-name"
139
+ ```
140
+
141
+ ### `bom`
142
+
143
+ ```bash
144
+ uv run controlloop bom [REPOSITORY] [-o PATH] [--validate] [--format acbom|cyclonedx]
145
+ ```
146
+
147
+ Builds the **Agent Capability Bill of Materials** — the canonical graph of
148
+ agents, tools, resources, identities, and permissions, with evidence for
149
+ every node and edge.
150
+
151
+ ```bash
152
+ uv run controlloop bom ./agent-repo -o acbom.json
153
+ uv run controlloop bom acbom.json --validate
154
+ ```
155
+
156
+ ```
157
+ ✓ VALID acbom.json is a valid ACBOM
158
+ ```
159
+
160
+ `--validate` checks an existing file against this reader's own schema
161
+ version. Use `--format cyclonedx` for a CycloneDX projection.
162
+
163
+ ### `diff`
164
+
165
+ ```bash
166
+ uv run controlloop diff [FIRST] [SECOND] [--baseline REF] [--format text|json]
167
+ ```
168
+
169
+ - `diff <repo>` — compare the repository against its resolved baseline
170
+ (a committed `.controlloop/baseline.json`, else the merge-base of your
171
+ default branch).
172
+ - `diff <baseline.json> <current.json>` — compare two ACBOM files directly.
173
+ - `--baseline` — an explicit baseline file *or* git revision.
174
+
175
+ ```
176
+ • BASELINE committed baseline: .controlloop/baseline.json
177
+ • SCOPE effective authority only -- node and edge changes were not evaluated
178
+
179
+ • ADDED capability clp:agent:sha256:2321fe51… invokes clp:tool:sha256:ccc68b72…
180
+
181
+ 1 change: 1 added
182
+ ```
183
+
184
+ ### `scan`
185
+
186
+ ```bash
187
+ uv run controlloop scan [REPOSITORY] [--format text|json|sarif]
188
+ ```
189
+
190
+ Discovery, graph, baseline comparison, and all ten policy rules, rendered as
191
+ a full report. `--format json` gives you the complete report;
192
+ `--format sarif` gives a SARIF 2.1.0 log for code-scanning tools.
193
+
194
+ ### `gate`
195
+
196
+ ```bash
197
+ uv run controlloop gate [REPOSITORY] \
198
+ [--evidence-path PATH] [--sarif-path PATH] \
199
+ [--default-branch NAME] [--format text|json|sarif]
200
+ ```
201
+
202
+ The CI form. Returns a four-state verdict (see
203
+ [Reading the output](#reading-the-output)) and **always** writes an evidence
204
+ artifact — including on a failing run, which is exactly when you need it.
205
+
206
+ - `--evidence-path` — where the artifact goes (default `evidence.json`).
207
+ The parent directory must already exist.
208
+ - `--sarif-path` — additionally write a SARIF log, carrying the blast-radius
209
+ statement as `runs[0].properties.controlloop.blastRadius`.
210
+ - `--default-branch` — override which branch the merge-base baseline is taken
211
+ from, for CI checkouts where `origin/HEAD` is unset.
212
+
213
+ `gate` needs real git history for an automatic baseline, so check out with
214
+ `fetch-depth: 0`.
215
+
216
+ ## Reading the output
217
+
218
+ Here is a real passing run against the reference agent:
219
+
220
+ ```
221
+ ! WORST REACHABLE financial-action: widgetworks-order-support-agent can invokes
222
+ Issue a refund
223
+
224
+ ✓ PASSED
225
+
226
+ • material change: not evaluated
227
+
228
+ ! MEDIUM policy.undeclared-tools: Tool 'Look up an order' is reachable but not
229
+ declared in controlloop.yaml.
230
+ at agent-card.json
231
+
232
+ Suppressions: none declared
233
+ ```
234
+
235
+ Exit code `0`.
236
+
237
+ **1. The blast-radius line comes first.** `WORST REACHABLE` is the single
238
+ worst thing this agent can do *right now* — not what changed. It is the line
239
+ you forward to your manager. Here: this agent can take a `financial-action`
240
+ by invoking `Issue a refund`. If nothing is classified, it reads
241
+ `• no material capability is reachable`.
242
+
243
+ **2. The verdict.** `gate` returns one of four:
244
+
245
+ | Verdict | Exit | Meaning |
246
+ | --- | --- | --- |
247
+ | `✓ PASSED` | 0 | Nothing blocking, nothing warned |
248
+ | `! PASSED WITH WARNINGS` | 0 | Findings below the blocking threshold |
249
+ | `! REVIEW REQUIRED` | 3 | Analysis was incomplete and enforcement is set to fail |
250
+ | `✕ DEPLOYMENT BLOCKED` | 1 | A blocking finding |
251
+
252
+ A report can additionally show `• NOT EVALUATED`, meaning no policy was
253
+ evaluated at all — which is not the same as evaluating and finding nothing.
254
+
255
+ Note the glyphs: `PASSED WITH WARNINGS` uses `!`, not `✓`. Every state is
256
+ distinguishable by symbol and by word, never by colour alone.
257
+
258
+ **3. Material change** — what changed against the baseline, by class.
259
+ `not evaluated` means no comparison was possible, which is different from
260
+ "compared and found nothing" (`• no material capability change`). ControlLoop
261
+ never reports an unmade comparison as a clean one.
262
+
263
+ **4. Findings.** Each carries a severity glyph and label (`✕ HIGH`,
264
+ `! MEDIUM`), the rule ID, a plain-language message, and the evidence path.
265
+ Symbols and words both, never colour alone.
266
+
267
+ **5. Suppressions** are always listed, never hidden.
268
+
269
+ ### A blocked run
270
+
271
+ ```
272
+ ! WORST REACHABLE destructive-action: widgetworks-order-support-agent can
273
+ invokes Bulk refund orders
274
+
275
+ ✕ DEPLOYMENT BLOCKED
276
+
277
+ ✕ HIGH policy.destructive-or-financial-action: Agent gained new direct
278
+ invokes access to 'Bulk refund orders', classified as destructive-action and
279
+ financial-action.
280
+ at agent-card.json
281
+
282
+ Completeness enforcement: warn (default)
283
+ Evidence: evidence.json
284
+ ```
285
+
286
+ Exit code `1`. Two things to notice:
287
+
288
+ - The blast radius **got worse** — `financial-action` became
289
+ `destructive-action`. The agent's worst case degraded, and that is the
290
+ first thing the report says.
291
+ - The finding says **"gained new"**. It is not objecting to refunds existing;
292
+ it is objecting to authority this change *introduces* against the approved
293
+ baseline. In `--format json` that appears as `"change_state": "added"`.
294
+
295
+ ### In JSON
296
+
297
+ ```json
298
+ {
299
+ "rule_id": "policy.undeclared-tools",
300
+ "severity": "medium",
301
+ "confidence": "high",
302
+ "message": "Tool 'Look up an order' is reachable but not declared in controlloop.yaml.",
303
+ "change_state": "not-compared",
304
+ "remediation": "Declare this tool in controlloop.yaml ... or remove the agent's access to it if it was not intentional.",
305
+ "documentation_url": "https://docs.controlloop.ai/reference/policy-rules#undeclared-tools"
306
+ }
307
+ ```
308
+
309
+ Every finding carries its own `remediation` and a stable `documentation_url`.
310
+
311
+ ### Exit codes
312
+
313
+ | Code | Name | Meaning |
314
+ | --- | --- | --- |
315
+ | 0 | `PASS` | No blocking finding |
316
+ | 1 | `POLICY_FAIL` | A blocking finding |
317
+ | 2 | `INVALID_INPUT` | Bad manifest, bad path, unreadable ACBOM |
318
+ | 3 | `INCOMPLETE_ANALYSIS` | Analysis incomplete and enforcement set to fail (`REVIEW REQUIRED`) |
319
+ | 4 | `ENTITLEMENT` | Reserved |
320
+ | 5 | `INTERNAL_ERROR` | A bug — please report it |
321
+
322
+ ## Telling ControlLoop what your tools do
323
+
324
+ **This is the step people miss.** Discovery reads your agent card and your
325
+ OpenAPI spec, but nothing in a repository states that issuing a refund moves
326
+ money. Without that, every capability is unclassified and every scan reports
327
+ `no material capability is reachable`.
328
+
329
+ Declare it in `controlloop.yaml`:
330
+
331
+ ```yaml
332
+ schema_version: "1.1.0"
333
+ owner: support-eng
334
+
335
+ tool_capabilities:
336
+ - tool: Issue a refund # the DISCOVERED tool name, not its id
337
+ financial_action: true
338
+ read_only: false
339
+ sensitivity: confidential
340
+ - tool: Purge ticket history
341
+ destructive: true
342
+ ```
343
+
344
+ Match the **name discovery found**, which for an A2A skill is its card
345
+ `name`, not its `id` — `Issue a refund`, not `issue-refund`. Run
346
+ `controlloop bom` and read the node names if you are unsure; a declaration
347
+ naming a tool that does not exist is reported, not silently ignored.
348
+
349
+ Every boolean also accepts `"unknown"`, which the taxonomy ranks **worst of
350
+ all**. An unknown risk is never treated as safer than a known one.
351
+
352
+ ## Declaring a ceiling
353
+
354
+ The ceiling is the part that catches what nobody anticipated:
355
+
356
+ ```yaml
357
+ ceilings:
358
+ - agent: widgetworks-order-support-agent
359
+ prohibited_resources:
360
+ - customer-payment-methods
361
+ prohibited_delegation_targets:
362
+ - unapproved-agent
363
+ ```
364
+
365
+ Any reachable capability that breaches this blocks the gate — even with every
366
+ pattern rule suppressed. A capability-ceiling breach **cannot** be suppressed.
367
+
368
+ ## In CI
369
+
370
+ ```yaml
371
+ - uses: actions/checkout@v7.0.1
372
+ with:
373
+ fetch-depth: 0 # gate needs real history for a baseline
374
+ - uses: danny-tijerina2/controlloop@<ref>
375
+ with:
376
+ path: ${{ github.workspace }}
377
+ ```
378
+
379
+ The action runs `gate`, fails the check on a blocking verdict, uploads SARIF,
380
+ and writes a check summary. See
381
+ [the GitHub Action reference](../docs/reference/github-action.md). A
382
+ [pre-commit hook](../docs/reference/pre-commit-hook.md) is also available.
383
+
384
+ ## What is not built yet
385
+
386
+ Stated plainly, so you can plan:
387
+
388
+ - **No published release.** No PyPI package, Homebrew tap, container image, or
389
+ tagged version. Source install only.
390
+ - **No Team tier.** Private-repository gates, shared policy bundles, history,
391
+ attestations, dashboards, and billing do not exist.
392
+ - **No runtime protection.** ControlLoop analyzes repositories. It does not
393
+ intercept, sandbox, or kill a running agent.
394
+ - **Windows is unsupported.**
395
+ - **Committed baselines carry no graph**, so `scan`/`gate` report
396
+ `material change: not evaluated` against one. Only the merge-base path
397
+ computes a material change summary.
398
+
399
+ ## Learn more
400
+
401
+ - [CLI reference](../docs/reference/cli.md) — every command and flag
402
+ - [Terminal report format](../docs/reference/terminal-report-format.md)
403
+ - [Manifest schema](../docs/reference/manifest-schema.md)
404
+ - [Capability ceiling](../docs/reference/capability-ceiling.md)
405
+ - [Policy rules](../docs/reference/policy-rules.md) — all ten
406
+ - [Material capability taxonomy](../docs/reference/material-capability-taxonomy.md)
407
+ - [Privacy, security, and limitations](../docs/reference/privacy-security.md)
408
+
409
+ ---
410
+
411
+ ## For maintainers
412
+
413
+ The lockfile is authoritative. Do not install unpinned project dependencies
414
+ outside `uv`.
415
+
416
+ ```bash
417
+ uv sync --locked --all-groups
418
+ uv run ruff format --check .
419
+ uv run ruff check .
420
+ uv run mypy
421
+ uv run pytest
422
+ uv build
423
+ ```
424
+
425
+ `uv run pytest` takes roughly two to three minutes locally, including real
426
+ PyInstaller builds and a wall-clock performance benchmark that is sensitive
427
+ to machine load.