waitbus 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 (270) hide show
  1. waitbus-0.1.0/.github/CONTRIBUTING.md +350 -0
  2. waitbus-0.1.0/.gitignore +73 -0
  3. waitbus-0.1.0/CHANGELOG.md +63 -0
  4. waitbus-0.1.0/LICENSE +21 -0
  5. waitbus-0.1.0/NOTICE +121 -0
  6. waitbus-0.1.0/PKG-INFO +758 -0
  7. waitbus-0.1.0/README.md +705 -0
  8. waitbus-0.1.0/SECURITY.md +456 -0
  9. waitbus-0.1.0/SKILL.md +260 -0
  10. waitbus-0.1.0/installers/launchd/MANIFEST.txt +11 -0
  11. waitbus-0.1.0/installers/launchd/dev.waitbus.broadcast.plist +43 -0
  12. waitbus-0.1.0/installers/launchd/dev.waitbus.etag-poll.plist +34 -0
  13. waitbus-0.1.0/installers/launchd/dev.waitbus.listener.plist +44 -0
  14. waitbus-0.1.0/installers/launchd/dev.waitbus.watchdog.plist +32 -0
  15. waitbus-0.1.0/pyproject.toml +672 -0
  16. waitbus-0.1.0/systemd/MANIFEST.txt +16 -0
  17. waitbus-0.1.0/systemd/waitbus-broadcast.service +50 -0
  18. waitbus-0.1.0/systemd/waitbus-broadcast.socket +18 -0
  19. waitbus-0.1.0/systemd/waitbus-common.conf +42 -0
  20. waitbus-0.1.0/systemd/waitbus-etag-poll.service +36 -0
  21. waitbus-0.1.0/systemd/waitbus-etag-poll.timer +11 -0
  22. waitbus-0.1.0/systemd/waitbus-forward@.service +46 -0
  23. waitbus-0.1.0/systemd/waitbus-listener.service +53 -0
  24. waitbus-0.1.0/systemd/waitbus-watchdog.service +53 -0
  25. waitbus-0.1.0/systemd/waitbus-watchdog.timer +14 -0
  26. waitbus-0.1.0/tests/_agent_harness.py +112 -0
  27. waitbus-0.1.0/tests/_daemon_helpers.py +83 -0
  28. waitbus-0.1.0/tests/_subscriber_harness.py +93 -0
  29. waitbus-0.1.0/tests/_webhook_redactor.py +251 -0
  30. waitbus-0.1.0/tests/_wire_helpers.py +130 -0
  31. waitbus-0.1.0/tests/conftest.py +266 -0
  32. waitbus-0.1.0/tests/data/expected-sdist-manifest.txt +270 -0
  33. waitbus-0.1.0/tests/data/expected_mcp_frame.json +21 -0
  34. waitbus-0.1.0/tests/data/mcp_wire_baseline.jsonl +16 -0
  35. waitbus-0.1.0/tests/data/mcp_wire_spec_reference.jsonl +21 -0
  36. waitbus-0.1.0/tests/data/webhook_fixtures/README.md +0 -0
  37. waitbus-0.1.0/tests/data/webhook_fixtures/commit_message_emoji.json +64 -0
  38. waitbus-0.1.0/tests/data/webhook_fixtures/delete_branch.json +27 -0
  39. waitbus-0.1.0/tests/data/webhook_fixtures/issues_opened_with_secret_pattern.json +50 -0
  40. waitbus-0.1.0/tests/data/webhook_fixtures/pull_request_body_unicode_control.json +70 -0
  41. waitbus-0.1.0/tests/data/webhook_fixtures/pull_request_review_with_pii_email.json +66 -0
  42. waitbus-0.1.0/tests/data/webhook_fixtures/push_with_large_deletion.json +110 -0
  43. waitbus-0.1.0/tests/data/webhook_fixtures/release_published.json +50 -0
  44. waitbus-0.1.0/tests/data/webhook_fixtures/workflow_job_completed_failure.json +69 -0
  45. waitbus-0.1.0/tests/data/webhook_fixtures/workflow_run_action_requested_conclusion_null.json +96 -0
  46. waitbus-0.1.0/tests/data/webhook_fixtures/workflow_run_missing_head_commit.json +89 -0
  47. waitbus-0.1.0/tests/test_addressed_messaging.py +434 -0
  48. waitbus-0.1.0/tests/test_agent_integration_langgraph.py +99 -0
  49. waitbus-0.1.0/tests/test_agent_integration_pydantic_ai.py +115 -0
  50. waitbus-0.1.0/tests/test_artifact_hygiene.py +76 -0
  51. waitbus-0.1.0/tests/test_attestation.py +430 -0
  52. waitbus-0.1.0/tests/test_await_predicate_characterization.py +385 -0
  53. waitbus-0.1.0/tests/test_bench_helper_adoption.py +173 -0
  54. waitbus-0.1.0/tests/test_broadcast.py +2385 -0
  55. waitbus-0.1.0/tests/test_broadcast_exception_mapping.py +53 -0
  56. waitbus-0.1.0/tests/test_broadcast_robustness.py +535 -0
  57. waitbus-0.1.0/tests/test_broadcast_sub.py +1190 -0
  58. waitbus-0.1.0/tests/test_cli.py +387 -0
  59. waitbus-0.1.0/tests/test_cli_allowlist.py +330 -0
  60. waitbus-0.1.0/tests/test_cli_completion.py +171 -0
  61. waitbus-0.1.0/tests/test_cli_demo.py +55 -0
  62. waitbus-0.1.0/tests/test_cli_demo_decoders.py +129 -0
  63. waitbus-0.1.0/tests/test_cli_emit.py +120 -0
  64. waitbus-0.1.0/tests/test_cli_on.py +758 -0
  65. waitbus-0.1.0/tests/test_cli_serve.py +506 -0
  66. waitbus-0.1.0/tests/test_cli_sources.py +377 -0
  67. waitbus-0.1.0/tests/test_cli_stats.py +122 -0
  68. waitbus-0.1.0/tests/test_cli_subcommands.py +124 -0
  69. waitbus-0.1.0/tests/test_cli_swarm_demo.py +115 -0
  70. waitbus-0.1.0/tests/test_cli_top.py +339 -0
  71. waitbus-0.1.0/tests/test_cli_version.py +85 -0
  72. waitbus-0.1.0/tests/test_cli_wait.py +183 -0
  73. waitbus-0.1.0/tests/test_cloudevents.py +175 -0
  74. waitbus-0.1.0/tests/test_coalesce.py +513 -0
  75. waitbus-0.1.0/tests/test_coalesce_collapse_property.py +156 -0
  76. waitbus-0.1.0/tests/test_columns.py +85 -0
  77. waitbus-0.1.0/tests/test_complexity_table.py +290 -0
  78. waitbus-0.1.0/tests/test_compose_clauses.py +229 -0
  79. waitbus-0.1.0/tests/test_config.py +580 -0
  80. waitbus-0.1.0/tests/test_config_construction.py +64 -0
  81. waitbus-0.1.0/tests/test_config_validate.py +242 -0
  82. waitbus-0.1.0/tests/test_consumer_api_anchors.py +180 -0
  83. waitbus-0.1.0/tests/test_custom_sources.py +788 -0
  84. waitbus-0.1.0/tests/test_daemon_plugin_wireup.py +261 -0
  85. waitbus-0.1.0/tests/test_daemon_spawner_watch.py +278 -0
  86. waitbus-0.1.0/tests/test_db.py +289 -0
  87. waitbus-0.1.0/tests/test_db_prune.py +364 -0
  88. waitbus-0.1.0/tests/test_docker_watch_live.py +172 -0
  89. waitbus-0.1.0/tests/test_doorbell.py +348 -0
  90. waitbus-0.1.0/tests/test_e2e_scenarios.py +338 -0
  91. waitbus-0.1.0/tests/test_emit.py +361 -0
  92. waitbus-0.1.0/tests/test_emit_batch_property.py +197 -0
  93. waitbus-0.1.0/tests/test_emitter_examples.py +170 -0
  94. waitbus-0.1.0/tests/test_emitter_recipes.py +187 -0
  95. waitbus-0.1.0/tests/test_emitter_snippet.py +169 -0
  96. waitbus-0.1.0/tests/test_etag_poll.py +777 -0
  97. waitbus-0.1.0/tests/test_events_analyze.py +153 -0
  98. waitbus-0.1.0/tests/test_events_query.py +385 -0
  99. waitbus-0.1.0/tests/test_frame.py +658 -0
  100. waitbus-0.1.0/tests/test_frame_catalogue_consistency.py +208 -0
  101. waitbus-0.1.0/tests/test_fs_watch_live.py +134 -0
  102. waitbus-0.1.0/tests/test_grafana_dashboard.py +169 -0
  103. waitbus-0.1.0/tests/test_hero_swarm_e2e.py +105 -0
  104. waitbus-0.1.0/tests/test_http_base.py +71 -0
  105. waitbus-0.1.0/tests/test_init_migration.py +144 -0
  106. waitbus-0.1.0/tests/test_init_pyi_drift.py +84 -0
  107. waitbus-0.1.0/tests/test_install.py +212 -0
  108. waitbus-0.1.0/tests/test_install_launchd.py +232 -0
  109. waitbus-0.1.0/tests/test_listener.py +1061 -0
  110. waitbus-0.1.0/tests/test_listener_secret_loaders.py +76 -0
  111. waitbus-0.1.0/tests/test_listener_threading.py +131 -0
  112. waitbus-0.1.0/tests/test_log.py +141 -0
  113. waitbus-0.1.0/tests/test_mcp.py +510 -0
  114. waitbus-0.1.0/tests/test_mcp_coverage.py +855 -0
  115. waitbus-0.1.0/tests/test_mcp_e2e.py +182 -0
  116. waitbus-0.1.0/tests/test_mcp_event_payload_cap.py +209 -0
  117. waitbus-0.1.0/tests/test_mcp_session_state.py +37 -0
  118. waitbus-0.1.0/tests/test_mcp_surface.py +791 -0
  119. waitbus-0.1.0/tests/test_mcp_tail_events_async.py +259 -0
  120. waitbus-0.1.0/tests/test_mcp_wire_e2e.py +129 -0
  121. waitbus-0.1.0/tests/test_metrics.py +659 -0
  122. waitbus-0.1.0/tests/test_metrics_call_sites.py +203 -0
  123. waitbus-0.1.0/tests/test_metrics_endpoint.py +403 -0
  124. waitbus-0.1.0/tests/test_metrics_snapshot.py +151 -0
  125. waitbus-0.1.0/tests/test_migrations.py +381 -0
  126. waitbus-0.1.0/tests/test_multilingual_snippets.py +358 -0
  127. waitbus-0.1.0/tests/test_no_bun_residue.py +113 -0
  128. waitbus-0.1.0/tests/test_open_conn_pragmas.py +113 -0
  129. waitbus-0.1.0/tests/test_paths.py +209 -0
  130. waitbus-0.1.0/tests/test_peercred.py +127 -0
  131. waitbus-0.1.0/tests/test_plugin_config.py +348 -0
  132. waitbus-0.1.0/tests/test_pr_monitor.py +557 -0
  133. waitbus-0.1.0/tests/test_pr_monitor_tick.py +216 -0
  134. waitbus-0.1.0/tests/test_predicate.py +420 -0
  135. waitbus-0.1.0/tests/test_predicate_property.py +185 -0
  136. waitbus-0.1.0/tests/test_property_frame.py +398 -0
  137. waitbus-0.1.0/tests/test_property_ulid.py +69 -0
  138. waitbus-0.1.0/tests/test_property_validators.py +180 -0
  139. waitbus-0.1.0/tests/test_protocols.py +32 -0
  140. waitbus-0.1.0/tests/test_read_events_coverage.py +975 -0
  141. waitbus-0.1.0/tests/test_read_events_watch.py +367 -0
  142. waitbus-0.1.0/tests/test_replay_drain_and_print.py +144 -0
  143. waitbus-0.1.0/tests/test_sdist_manifest.py +167 -0
  144. waitbus-0.1.0/tests/test_secrets.py +212 -0
  145. waitbus-0.1.0/tests/test_serve_e2e.py +251 -0
  146. waitbus-0.1.0/tests/test_serve_unit.py +339 -0
  147. waitbus-0.1.0/tests/test_skill_md.py +127 -0
  148. waitbus-0.1.0/tests/test_sources.py +644 -0
  149. waitbus-0.1.0/tests/test_sourcespec_local_boundary.py +147 -0
  150. waitbus-0.1.0/tests/test_sourcespec_validation_property.py +233 -0
  151. waitbus-0.1.0/tests/test_stats.py +410 -0
  152. waitbus-0.1.0/tests/test_status_subcommand.py +188 -0
  153. waitbus-0.1.0/tests/test_subscribe_envelope_hygiene.py +174 -0
  154. waitbus-0.1.0/tests/test_subscribe_local_boundary.py +77 -0
  155. waitbus-0.1.0/tests/test_subscribe_sdk.py +363 -0
  156. waitbus-0.1.0/tests/test_subscribe_sdk_compose.py +237 -0
  157. waitbus-0.1.0/tests/test_subscriber_snippet.py +184 -0
  158. waitbus-0.1.0/tests/test_systemd_units.py +192 -0
  159. waitbus-0.1.0/tests/test_terminal_classifier.py +282 -0
  160. waitbus-0.1.0/tests/test_types.py +238 -0
  161. waitbus-0.1.0/tests/test_ulid.py +181 -0
  162. waitbus-0.1.0/tests/test_untrusted.py +108 -0
  163. waitbus-0.1.0/tests/test_verify_plugin.py +143 -0
  164. waitbus-0.1.0/tests/test_wait_for_race_immunity.py +136 -0
  165. waitbus-0.1.0/tests/test_waitbus_wait.py +463 -0
  166. waitbus-0.1.0/tests/test_waitbus_wait_compose.py +436 -0
  167. waitbus-0.1.0/tests/test_waitbus_wait_universal.py +476 -0
  168. waitbus-0.1.0/tests/test_watchdog_check.py +147 -0
  169. waitbus-0.1.0/tests/test_webhook_fixtures_redactor.py +430 -0
  170. waitbus-0.1.0/tests/test_webhook_fixtures_wire_conformance.py +206 -0
  171. waitbus-0.1.0/tests/test_wire_v1_conformance.py +265 -0
  172. waitbus-0.1.0/waitbus/__init__.py +93 -0
  173. waitbus-0.1.0/waitbus/__init__.pyi +38 -0
  174. waitbus-0.1.0/waitbus/_broadcast_sub.py +737 -0
  175. waitbus-0.1.0/waitbus/_cloudevents.py +164 -0
  176. waitbus-0.1.0/waitbus/_columns.py +115 -0
  177. waitbus-0.1.0/waitbus/_compose.py +129 -0
  178. waitbus-0.1.0/waitbus/_config.py +359 -0
  179. waitbus-0.1.0/waitbus/_db.py +698 -0
  180. waitbus-0.1.0/waitbus/_doorbell.py +251 -0
  181. waitbus-0.1.0/waitbus/_duration.py +33 -0
  182. waitbus-0.1.0/waitbus/_emit.py +373 -0
  183. waitbus-0.1.0/waitbus/_frame.py +332 -0
  184. waitbus-0.1.0/waitbus/_http.py +40 -0
  185. waitbus-0.1.0/waitbus/_log.py +34 -0
  186. waitbus-0.1.0/waitbus/_mcp_constants.py +104 -0
  187. waitbus-0.1.0/waitbus/_mcp_models.py +245 -0
  188. waitbus-0.1.0/waitbus/_mcp_subscriptions.py +198 -0
  189. waitbus-0.1.0/waitbus/_messaging.py +308 -0
  190. waitbus-0.1.0/waitbus/_metrics.py +418 -0
  191. waitbus-0.1.0/waitbus/_metrics_http.py +106 -0
  192. waitbus-0.1.0/waitbus/_paths.py +187 -0
  193. waitbus-0.1.0/waitbus/_peercred.py +72 -0
  194. waitbus-0.1.0/waitbus/_predicate.py +390 -0
  195. waitbus-0.1.0/waitbus/_protocols.py +24 -0
  196. waitbus-0.1.0/waitbus/_sdnotify.py +37 -0
  197. waitbus-0.1.0/waitbus/_secrets.py +125 -0
  198. waitbus-0.1.0/waitbus/_subscribe.py +507 -0
  199. waitbus-0.1.0/waitbus/_terminal.py +134 -0
  200. waitbus-0.1.0/waitbus/_types.py +189 -0
  201. waitbus-0.1.0/waitbus/_ulid.py +107 -0
  202. waitbus-0.1.0/waitbus/_untrusted.py +109 -0
  203. waitbus-0.1.0/waitbus/_version.py +11 -0
  204. waitbus-0.1.0/waitbus/broadcast.py +1816 -0
  205. waitbus-0.1.0/waitbus/broadcast_tap.py +131 -0
  206. waitbus-0.1.0/waitbus/cli/__init__.py +67 -0
  207. waitbus-0.1.0/waitbus/cli/_exit_codes.py +81 -0
  208. waitbus-0.1.0/waitbus/cli/_shared.py +906 -0
  209. waitbus-0.1.0/waitbus/cli/allowlist.py +353 -0
  210. waitbus-0.1.0/waitbus/cli/daemons/__init__.py +20 -0
  211. waitbus-0.1.0/waitbus/cli/daemons/broadcast.py +73 -0
  212. waitbus-0.1.0/waitbus/cli/daemons/etag_poll.py +39 -0
  213. waitbus-0.1.0/waitbus/cli/daemons/listener.py +39 -0
  214. waitbus-0.1.0/waitbus/cli/daemons/mcp.py +50 -0
  215. waitbus-0.1.0/waitbus/cli/daemons/pr_monitor.py +38 -0
  216. waitbus-0.1.0/waitbus/cli/daemons/read_events.py +49 -0
  217. waitbus-0.1.0/waitbus/cli/daemons/watchdog_check.py +38 -0
  218. waitbus-0.1.0/waitbus/cli/db/__init__.py +8 -0
  219. waitbus-0.1.0/waitbus/cli/db/migrate.py +113 -0
  220. waitbus-0.1.0/waitbus/cli/db/prune.py +317 -0
  221. waitbus-0.1.0/waitbus/cli/demo.py +593 -0
  222. waitbus-0.1.0/waitbus/cli/doctor.py +55 -0
  223. waitbus-0.1.0/waitbus/cli/emit.py +114 -0
  224. waitbus-0.1.0/waitbus/cli/init.py +97 -0
  225. waitbus-0.1.0/waitbus/cli/install/__init__.py +9 -0
  226. waitbus-0.1.0/waitbus/cli/install/credentials.py +111 -0
  227. waitbus-0.1.0/waitbus/cli/install/launchd.py +136 -0
  228. waitbus-0.1.0/waitbus/cli/install/systemd.py +122 -0
  229. waitbus-0.1.0/waitbus/cli/main.py +150 -0
  230. waitbus-0.1.0/waitbus/cli/on.py +25 -0
  231. waitbus-0.1.0/waitbus/cli/query/__init__.py +5 -0
  232. waitbus-0.1.0/waitbus/cli/query/events.py +145 -0
  233. waitbus-0.1.0/waitbus/cli/replay.py +21 -0
  234. waitbus-0.1.0/waitbus/cli/serve.py +603 -0
  235. waitbus-0.1.0/waitbus/cli/sources.py +460 -0
  236. waitbus-0.1.0/waitbus/cli/stats.py +131 -0
  237. waitbus-0.1.0/waitbus/cli/status.py +109 -0
  238. waitbus-0.1.0/waitbus/cli/stress.py +49 -0
  239. waitbus-0.1.0/waitbus/cli/swarm_demo.py +291 -0
  240. waitbus-0.1.0/waitbus/cli/top.py +25 -0
  241. waitbus-0.1.0/waitbus/cli/verify_plugin.py +59 -0
  242. waitbus-0.1.0/waitbus/cli/wait.py +24 -0
  243. waitbus-0.1.0/waitbus/coalesce.py +196 -0
  244. waitbus-0.1.0/waitbus/config_validate.py +359 -0
  245. waitbus-0.1.0/waitbus/etag_poll.py +718 -0
  246. waitbus-0.1.0/waitbus/events_analyze.py +140 -0
  247. waitbus-0.1.0/waitbus/events_query.py +363 -0
  248. waitbus-0.1.0/waitbus/listener.py +731 -0
  249. waitbus-0.1.0/waitbus/mcp.py +1463 -0
  250. waitbus-0.1.0/waitbus/migrations/0001_initial_schema.sql +87 -0
  251. waitbus-0.1.0/waitbus/migrations/0002_add_daemon_sequence.sql +94 -0
  252. waitbus-0.1.0/waitbus/migrations/__init__.py +401 -0
  253. waitbus-0.1.0/waitbus/on.py +730 -0
  254. waitbus-0.1.0/waitbus/pr_monitor.py +405 -0
  255. waitbus-0.1.0/waitbus/py.typed +0 -0
  256. waitbus-0.1.0/waitbus/read_events.py +545 -0
  257. waitbus-0.1.0/waitbus/replay.py +295 -0
  258. waitbus-0.1.0/waitbus/schema.sql +130 -0
  259. waitbus-0.1.0/waitbus/sources/__init__.py +83 -0
  260. waitbus-0.1.0/waitbus/sources/_attestation.py +379 -0
  261. waitbus-0.1.0/waitbus/sources/_config.py +446 -0
  262. waitbus-0.1.0/waitbus/sources/_protocol.py +324 -0
  263. waitbus-0.1.0/waitbus/sources/_registry.py +806 -0
  264. waitbus-0.1.0/waitbus/sources/docker_watch.py +492 -0
  265. waitbus-0.1.0/waitbus/sources/fs_watch.py +307 -0
  266. waitbus-0.1.0/waitbus/sources/pytest_emit.py +330 -0
  267. waitbus-0.1.0/waitbus/stats.py +492 -0
  268. waitbus-0.1.0/waitbus/top.py +256 -0
  269. waitbus-0.1.0/waitbus/wait.py +713 -0
  270. waitbus-0.1.0/waitbus/watchdog_check.py +225 -0
@@ -0,0 +1,350 @@
1
+ # Contributing to waitbus
2
+
3
+ waitbus is a single-author project at present. Contributions are welcome via
4
+ GitHub issues (bug reports, feature requests) and pull requests. This document
5
+ covers the local development workflow, per-surface testing, version sync, and
6
+ release policy. For install and operation, see [README.md](../README.md).
7
+
8
+ ---
9
+
10
+ ## Quick start (local dev)
11
+
12
+ ```bash
13
+ git clone https://github.com/astrogilda/waitbus && cd waitbus
14
+ uv sync --all-groups
15
+ uvx prek install -f
16
+ uv run pytest tests/ -p no:xdist
17
+ ```
18
+
19
+ All runtime deps live in `[project.dependencies]`; dev deps (pytest, ruff,
20
+ mypy, hypothesis, build, tiktoken) live in `[dependency-groups].dev`.
21
+ `uv sync --all-groups` installs both. The git hook manager is `prek`
22
+ (Rust drop-in alternative to the pre-commit framework, schema-compatible
23
+ with the same `.pre-commit-config.yaml`); CI runs `uvx prek run --all-files`
24
+ on every push.
25
+
26
+ ---
27
+
28
+ ## Project conventions
29
+
30
+ - **Python target:** 3.11 minimum (`requires-python = ">=3.11"`). CI tests 3.11, 3.12, 3.13, and 3.14.
31
+ - **Ruff rule set:** `["E", "F", "I", "N", "UP", "B", "SIM", "RUF"]`. `tests/*` allows `E402` for property-test deferred imports.
32
+ - **Line length:** 120 characters.
33
+ - **Mypy strict** on `waitbus/` only; tests are excluded (`[tool.mypy] files = ["waitbus"]`).
34
+ - **Tests run serial:** `pytest -p no:xdist`. Hypothesis fixture races occur under xdist.
35
+ - **Runtime dependency closure:** `typer` (CLI), `platformdirs` (path resolution), `mcp` + `pydantic` + `pydantic-core` (MCP server).
36
+
37
+ ### Per-surface dev commands
38
+
39
+ ```bash
40
+ # Full test suite (serial)
41
+ uv run pytest tests/ -vv -p no:xdist
42
+
43
+ # Lint
44
+ uv run ruff check waitbus tests scripts
45
+
46
+ # Type-check
47
+ uv run mypy waitbus
48
+
49
+ # Integration test (wheel build + install-in-venv + entry-point assertions)
50
+ uv run pytest tests/test_install.py -vv -p no:xdist -m slow
51
+ ```
52
+
53
+ The test suite has ~600 tests. Use `-p no:xdist` (serial mode) in development
54
+ and CI to avoid Hypothesis fixture races. The slow integration test builds a
55
+ wheel, installs it into a fresh venv, and asserts entry-points and
56
+ `systemd-analyze verify` output — it runs in roughly one second on a warm cache.
57
+
58
+ ### MCP server
59
+
60
+ The MCP server lives in `waitbus/mcp.py` and is reachable via
61
+ `waitbus mcp serve`. It subscribes to the broadcast socket over stdlib
62
+ `socket.socket(AF_UNIX, SOCK_STREAM)` and re-emits each non-heartbeat frame
63
+ as both a vendor-specific Claude Code notification frame
64
+ (`notifications/claude/channel`) and a standard `notifications/resources/updated`
65
+ frame (for Claude Desktop and generic MCP clients).
66
+
67
+ ```bash
68
+ # Run the MCP-server unit tests (fast, mocks the broadcast socket)
69
+ uv run pytest tests/test_mcp.py -vv -p no:xdist
70
+
71
+ # Run the server against a live broadcast daemon (Ctrl+D to stop)
72
+ uv run waitbus mcp serve
73
+ ```
74
+
75
+ On macOS the server logs one info message and idles — the broadcast daemon
76
+ stack is Linux-only.
77
+
78
+ ### Systemd units
79
+
80
+ Validate units before committing:
81
+
82
+ ```bash
83
+ systemd-analyze --user verify systemd/*.service systemd/*.socket systemd/*.timer
84
+ ```
85
+
86
+ CI runs this check as well. When adding or removing unit files, update
87
+ `systemd/MANIFEST.txt` — `waitbus install-systemd --sync` reads that file
88
+ to compute orphan units from previous package versions.
89
+
90
+ ---
91
+
92
+ ## Development install vs released install
93
+
94
+ **Working from a checkout:**
95
+
96
+ ```bash
97
+ uv pip install --editable .
98
+ ```
99
+
100
+ Console scripts point at your source tree — edits are picked up immediately.
101
+ However, editable installs do **not** place `share/systemd/user/` on disk.
102
+ Hatchling's `shared-data` directive only fires during a wheel build, not during
103
+ `--editable`. For systemd-unit testing during dev, build a wheel and install it
104
+ into a throwaway venv:
105
+
106
+ ```bash
107
+ uv build --wheel
108
+ # Install the produced dist/waitbus-*.whl into a fresh venv
109
+ ```
110
+
111
+ Or symlink the dev unit files to `~/.config/systemd/user/` manually for rapid
112
+ iteration without a wheel rebuild.
113
+
114
+ **Working from a released wheel:**
115
+
116
+ ```bash
117
+ uv tool install waitbus
118
+ waitbus install-systemd
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Loading the plugin locally
124
+
125
+ To test the full Claude Code plugin without installing from the registry:
126
+
127
+ ```bash
128
+ claude --plugin-dir /path/to/waitbus --dangerously-load-development-channels
129
+ ```
130
+
131
+ `.mcp.json` invokes `uvx --from waitbus waitbus mcp serve`, which
132
+ resolves the latest published `waitbus` from PyPI. To exercise local
133
+ source instead, either `uv tool install --editable .` from this directory
134
+ (rebinds the `waitbus` shim onto your working tree) or temporarily swap the
135
+ `.mcp.json` `args` to `["run", "waitbus", "mcp", "serve"]`.
136
+
137
+ ---
138
+
139
+ ## Updating the sdist manifest snapshot
140
+
141
+ The sdist hygiene test in `tests/test_sdist_manifest.py` asserts that the file
142
+ list inside the produced source distribution matches a committed snapshot at
143
+ `tests/data/expected-sdist-manifest.txt`, plus a size budget, a copyleft-header
144
+ scan, and a forbidden-paths regression guard.
145
+
146
+ When you add or remove a file that ships in the sdist, regenerate the snapshot
147
+ in the same PR:
148
+
149
+ ```bash
150
+ uv build --sdist
151
+ tar tzf dist/waitbus-*.tar.gz | sort > tests/data/expected-sdist-manifest.txt
152
+ ```
153
+
154
+ Review the diff before committing — an unexpected addition is exactly what this
155
+ test is designed to catch.
156
+
157
+ ---
158
+
159
+ ## Linux + systemd assumption
160
+
161
+ The daemon stack is **Linux-only** at runtime. The Python library, listener, ETag
162
+ poller, and query CLI work on macOS, but without systemd integration.
163
+
164
+ Specific reasons:
165
+
166
+ - `broadcast.py` authenticates subscribers with `SO_PEERCRED` and coalesces
167
+ doorbell wakeups with `os.eventfd`, both Linux-only. The wire itself is
168
+ `AF_UNIX SOCK_STREAM` with length-prefix framing (portable; macOS lacks
169
+ `SOCK_SEQPACKET`), but the broadcast, doorbell, and `read-events --watch`
170
+ test modules carry `pytestmark = pytest.mark.skipif(sys.platform != "linux", ...)`
171
+ for the eventfd and peer-credential paths.
172
+ - `broadcast._peer_uid` resolves `SO_PEERCRED` via
173
+ `getattr(socket, "SO_PEERCRED", None)` so the package still imports cleanly
174
+ on macOS for the library and listener surfaces.
175
+ - The MCP server (`waitbus/mcp.py`) subscribes to the broadcast bus; on macOS
176
+ it emits one info-severity notification and exits cleanly because that
177
+ broadcast daemon stack is Linux-only.
178
+
179
+ ---
180
+
181
+ ## Version sync
182
+
183
+ The canonical version lives in `pyproject.toml [project].version`. Three
184
+ manifests must agree: `pyproject.toml`, `.claude-plugin/plugin.json`, and
185
+ `server.json`. Propagate with:
186
+
187
+ ```bash
188
+ scripts/sync-versions.py # mutate all three manifests; exit 0
189
+ scripts/sync-versions.py --check # exit 1 on any drift
190
+ ```
191
+
192
+ The `--check` mode runs in the pre-commit hook and in CI. Never bump version
193
+ fields manually in `plugin.json` or `server.json` — only edit `pyproject.toml`
194
+ and then run `sync-versions.py`.
195
+
196
+ ---
197
+
198
+ ## Commit conventions
199
+
200
+ Commits and PR titles follow [Conventional Commits](https://www.conventionalcommits.org/):
201
+
202
+ ```
203
+ feat(waitbus): add broadcast lag counter metric
204
+ fix(waitbus): handle SIGTERM during fan-out drain
205
+ docs(waitbus): expand install-systemd shared-data note
206
+ test(waitbus): add Hypothesis property tests for ULID ordering
207
+ chore(waitbus): update pre-commit hook versions
208
+ ci(waitbus): add systemd-analyze verify step to workflow
209
+ ```
210
+
211
+ Rules:
212
+ - No emoji.
213
+ - No internal jargon (no internal project jargon).
214
+ - Subject line under 72 characters, imperative mood.
215
+ - PR body explains *why*, not *what*.
216
+
217
+ ---
218
+
219
+ ## Commit signing
220
+
221
+ We recommend signing your commits. Release tags are already signed, and signed
222
+ commits extend that chain of trust back through the history they tag.
223
+
224
+ Enable signing locally with either an SSH key or a GPG key:
225
+
226
+ ```bash
227
+ # SSH-key signing (simplest if you already push over SSH):
228
+ git config commit.gpgsign true
229
+ git config gpg.format ssh
230
+ git config user.signingkey ~/.ssh/id_ed25519.pub
231
+
232
+ # Or GPG-key signing:
233
+ git config commit.gpgsign true
234
+ git config user.signingkey <your-gpg-key-id>
235
+ ```
236
+
237
+ This is a recommendation, not a CI gate: signed commits are not enforced on
238
+ pull requests (that would be premature ahead of a public, multi-contributor
239
+ flow). The signed release tag remains the enforced trust boundary.
240
+
241
+ ---
242
+
243
+ ## Console scripts (1)
244
+
245
+ The package ships a single entry point: `waitbus`. All previous per-daemon
246
+ scripts are now sub-commands of that umbrella CLI.
247
+
248
+ | Sub-command | Purpose |
249
+ |-------------|---------|
250
+ | `waitbus init` | Create state directory and SQLite schema |
251
+ | `waitbus install-systemd` | Copy systemd user units (Linux) |
252
+ | `waitbus install-launchd` | Copy launchd plists (macOS) |
253
+ | `waitbus keygen` | Store HMAC secret in OS keyring |
254
+ | `waitbus doctor` | Health-gate: config, keyring, binaries, daemons |
255
+ | `waitbus status` | Operational dashboard: event counts, daemon liveness |
256
+ | `waitbus verify-plugin` | Validate `.claude-plugin/plugin.json` fields |
257
+ | `waitbus listener serve` | HTTP webhook receiver (loopback :9000) |
258
+ | `waitbus broadcast serve` | AF_UNIX SOCK_STREAM fan-out daemon |
259
+ | `waitbus etag-poll run` | ETag-aware backup poller (one-shot) |
260
+ | `waitbus mcp serve` | MCP server (stdio), re-emits broadcast events |
261
+ | `waitbus read-events list` | Query the event store |
262
+ | `waitbus read-events watch` | Tail the event store (live) |
263
+ | `waitbus pr-monitor tick` | Roll job events into per-PR state |
264
+ | `waitbus watchdog-check run` | Alertmanager watchdog freshness probe |
265
+
266
+ ---
267
+
268
+ ## Systemd units (8)
269
+
270
+ | Unit file | Purpose |
271
+ |-----------|---------|
272
+ | `waitbus-listener.service` | Webhook HTTP server |
273
+ | `waitbus-broadcast.service` | Broadcast daemon (socket-activated) |
274
+ | `waitbus-broadcast.socket` | AF_UNIX SOCK_STREAM activation socket |
275
+ | `waitbus-etag-poll.service` | ETag poller one-shot service |
276
+ | `waitbus-etag-poll.timer` | 45-second timer for the poller |
277
+ | `waitbus-watchdog.service` | Ingestion-silence detector service |
278
+ | `waitbus-watchdog.timer` | Timer for the watchdog probe |
279
+ | `waitbus-forward@.service` | Templated per-repository forwarder |
280
+
281
+ All eight units use `ExecStart=%h/.local/bin/waitbus <subcmd> <verb>` and
282
+ carry systemd hardening directives (`PrivateTmp`, `ProtectSystem=strict`,
283
+ `NoNewPrivileges`, `SystemCallFilter` allow-list). `waitbus install-systemd`
284
+ copies them from the wheel's `share/systemd/user/` destination into
285
+ `~/.config/systemd/user/`.
286
+
287
+ ---
288
+
289
+ ## `--dry-run` vs `doctor`
290
+
291
+ - **`waitbus init --dry-run`** — prints intended actions and always exits 0.
292
+ Use for inspection before committing to install actions.
293
+ - **`waitbus doctor`** — reads the *current* state of config, keyring,
294
+ binaries, and systemd units. Exits 0 if everything resolves; exits 1 on any
295
+ issue. Use as a health gate before and after deploys.
296
+
297
+ ---
298
+
299
+ ## Versioning policy
300
+
301
+ This project follows [Semantic Versioning](https://semver.org/). Pre-1.0
302
+ releases may refine the API based on real-world usage. After 6+ months of
303
+ stable public usage, v1.0 will declare API stability.
304
+
305
+ ---
306
+
307
+ ## Release process
308
+
309
+ 1. Bump `pyproject.toml [project].version` to the target (e.g., `0.2.0`).
310
+ 2. Run `scripts/sync-versions.py` to propagate to all manifests.
311
+ 3. Update `CHANGELOG.md` — add a dated section for the new version.
312
+ 4. Commit + push + open PR. CI must pass before merging.
313
+ 5. After merge to main:
314
+ ```bash
315
+ git tag v0.2.0
316
+ git push origin v0.2.0
317
+ ```
318
+ 6. The tag triggers `.github/workflows/release.yml`, which:
319
+ - Publishes `waitbus` to PyPI (OIDC + sigstore attestations).
320
+ - Registers `io.github.astrogilda/waitbus` with the MCP Registry.
321
+ - Creates a GitHub Release with the plugin `.zip` attached.
322
+
323
+ Pre-release tags (`-rc1`, `-alpha`, `-beta`, `-dev`) trigger the full test
324
+ matrix as a rehearsal but skip every publish job, so the PyPI version slot is
325
+ not burned on a dry run. Only tags matching `vN.N.N` or `vN.N.N.postN` shapes
326
+ invoke the publish jobs.
327
+
328
+ ### Partial-publish recovery
329
+
330
+ The three publish steps (PyPI, MCP Registry, GitHub Release) are
331
+ decoupled. If one succeeds and another fails:
332
+
333
+ - **PyPI** is immutable. Bump to `0.2.0.post1` in `pyproject.toml`, run
334
+ `sync-versions.py`, and retag `v0.2.0.post1`. The `.post1` PEP 440
335
+ post-release suffix signals the artifact identity is stable.
336
+ - **MCP Registry** accepts a retag of the same version number, so `.post1` is
337
+ only required when PyPI was the registry that succeeded.
338
+
339
+ ---
340
+
341
+ ## Code of Conduct
342
+
343
+ A `CODE_OF_CONDUCT.md` lives at the repo root (Contributor Covenant 2.1 adoption).
344
+
345
+ ---
346
+
347
+ ## License
348
+
349
+ MIT. By contributing you agree that your contributions are MIT-licensed under
350
+ the same terms as the rest of this project. See [LICENSE](../LICENSE).
@@ -0,0 +1,73 @@
1
+ # Python build / cache artifacts
2
+ __pycache__/
3
+ *.pyc
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+
8
+ # Virtualenv (managed by `uv sync` or `pip install -e`)
9
+ .venv/
10
+
11
+ # Test / type-check / property-test / lint caches
12
+ .pytest_cache/
13
+ .mypy_cache/
14
+ .ruff_cache/
15
+ .hypothesis/
16
+ .coverage
17
+ coverage.json
18
+ htmlcov/
19
+
20
+ # IDE / editor scratch
21
+ .vscode/
22
+ .idea/
23
+
24
+ # LSP/MCP project state cache (local, no upstream consumers)
25
+ .serena/
26
+
27
+ # Claude harness session state (per-conversation correlation IDs; not source)
28
+ .claude_correlation/
29
+
30
+ # Per-run benchmark output JSONs (host- and timestamp-stamped). Only the
31
+ # committed baselines under benchmarks/baselines/ are tracked; per-run
32
+ # results land here for ad-hoc inspection but are runner-specific.
33
+ benchmarks/results/*.json
34
+
35
+ # Vendored hetzner-bench-toolkit clone used by scripts/run_soak_on_hetzner.sh
36
+ # on the maintainer-side soak runner. It is an embedded git checkout that
37
+ # should not be tracked here and is already excluded from the sdist via
38
+ # `[tool.hatch.build.targets.sdist].exclude` in pyproject.toml.
39
+ scripts/.hbt/
40
+
41
+ # Crawl / context bundles (derived artifacts, never committed)
42
+ crawl-output/
43
+
44
+ # Operator-local pytest run logs (per-run timestamped .log + .junit.xml +
45
+ # warnings.log). Persistent across reboots so a failed / skipped / warned
46
+ # run can be retroactively inspected without re-execution. Drop here via
47
+ # scripts/run_full_pytest.sh.
48
+ .local-pytest-logs/
49
+
50
+ # Operator-local stress run logs (per-run timestamped .log + .verdict.json
51
+ # + .progress.jsonl). Persistent across reboots so an operator-driven
52
+ # real-mode stress invocation can be re-inspected without re-execution.
53
+ .local-stress-logs/
54
+
55
+ # Operator-local reference fixtures: live-recorded LLM envelopes the
56
+ # operator captures off ``claude -p`` / ``gemini -p`` runs and uses as a
57
+ # source-of-truth shape reference. The tests embed envelope content
58
+ # inline (see ``tests/test_stress_real_drivers.py``); this directory is
59
+ # the operator's working copy of the live captures and is not shipped.
60
+ tests/fixtures/
61
+
62
+ # Code-intelligence index snapshot — generated, rebuildable; not source.
63
+ codedb.snapshot
64
+
65
+ # Benchmark run output — per-run timestamped verdict/log/progress scratch the
66
+ # benches write here; a good run is promoted to benchmarks/baselines/ (which IS
67
+ # committed). The dir itself is kept via .gitkeep; individual runs are scratch.
68
+ benchmarks/results/*
69
+ !benchmarks/results/.gitkeep
70
+
71
+ # local soak-run outputs (fetched from Hetzner)
72
+ soak-verdict.json
73
+ soak-verdict.json.progress.jsonl
@@ -0,0 +1,63 @@
1
+ # Changelog
2
+
3
+ All notable changes to **waitbus** are documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## Versioning
9
+
10
+ Pre-1.0 releases may refine the API based on real-world usage; v1.0 will
11
+ declare API stability after a period of stable public use.
12
+
13
+ ## [0.1.0] — first public release
14
+
15
+ waitbus is a workstation-local async event bus for your machine's agents:
16
+ wait on anything from any source, and let your agents coordinate over the
17
+ same local bus. It is local-only (an `AF_UNIX` socket, no network egress),
18
+ durable (events persist to SQLite with replay), and zero-polling (an
19
+ `eventfd` doorbell wakes subscribers instead of a clock loop).
20
+
21
+ ### Sources — wait on what already finished or failed
22
+
23
+ - **CI jobs** — a GitHub workflow run finishing or failing.
24
+ - **Test runs** — a pytest run passing or failing.
25
+ - **Containers** — docker container lifecycle events.
26
+ - **Filesystem** — file and directory changes.
27
+ - Third-party sources register through the `waitbus.sources.v1` entry-point group.
28
+
29
+ ### Subscribers — any agent or script can wait and react
30
+
31
+ - **Agent frameworks** — Pydantic AI and LangGraph agents subscribe and react over the public SDK.
32
+ - **Claude Code** — receives pushes over the MCP notification channel.
33
+ - **Any MCP client** — pulls events via tool calls or a `tail_events` long-poll.
34
+ - **Scripts / CLI** — `waitbus wait`, plus hand-decoding subscriber snippets in Python, Go, Rust, and TypeScript.
35
+
36
+ ### Core
37
+
38
+ - `waitbus wait <predicate>` blocks until a matching event arrives, with a
39
+ `since=` cursor for durable offline catch-up.
40
+ - Daemon broadcast fan-out delivers each event to every subscriber over its
41
+ own buffer.
42
+ - Cross-agent failure broadcast: when one peer fails, the rest of the swarm
43
+ is notified on the same bus.
44
+ - Broadcast wire protocol v1 (frozen): typed frames with an open `kind`
45
+ discriminator, an ack-first subscribe handshake, and an `event_id` identity
46
+ carried on every data frame.
47
+ - Backpressure with whole-frame delivery: a subscriber that falls behind is
48
+ evicted with a `subscribe_rejected{lag_limit_exceeded}` frame when the wire
49
+ sits at a frame boundary, or a clean EOF otherwise — never a torn frame.
50
+ - Opt-in loopback Prometheus `/metrics` on the broadcast daemon;
51
+ `waitbus_broadcast_events_delivered_total` counts event frames only, at
52
+ kernel-accept (control frames are never counted).
53
+ - `waitbus serve` supervises the broadcast daemon plus the configured source
54
+ watchers in one foreground process: a daemon crash or a startup failure
55
+ exits 1, and the docker watcher stops gracefully at shutdown.
56
+
57
+ ### Install
58
+
59
+ ```
60
+ pip install waitbus
61
+ ```
62
+
63
+ [0.1.0]: https://github.com/astrogilda/waitbus/releases/tag/v0.1.0
waitbus-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sankalp Gilda
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.
waitbus-0.1.0/NOTICE ADDED
@@ -0,0 +1,121 @@
1
+ waitbus
2
+ Copyright (c) 2026 Sankalp Gilda
3
+
4
+ This product is licensed under the MIT License. See the LICENSE file for the
5
+ full license text.
6
+
7
+ This product bundles no third-party source code. It does, however, declare a
8
+ runtime dependency closure that `pip install waitbus` resolves and installs
9
+ alongside it. The packages below are NOT redistributed inside the waitbus sdist
10
+ or wheel; each is fetched from its own publisher and retains its own license
11
+ and copyright. They are enumerated here so downstream redistributors have a
12
+ single place to find the licenses that apply to a complete waitbus install.
13
+
14
+ A per-dependency license audit (method, resolved versions, verdict) is
15
+ recorded in docs/DEPENDENCY_LICENSES.md. Every license below is
16
+ redistribution-compatible with waitbus's MIT license. The one weak-copyleft
17
+ dependency, certifi (MPL-2.0), is file-level copyleft: its obligations attach
18
+ only to modifications of certifi's own files, not to the MIT-licensed work
19
+ that merely depends on it.
20
+
21
+ Licenses are taken from each package's published distribution metadata
22
+ (SPDX license expression, then OSI trove classifiers, then the License
23
+ field). Where the metadata gives an SPDX expression with a choice (for
24
+ example "MIT OR Apache-2.0"), waitbus exercises no election; the package
25
+ remains available under all of the offered terms.
26
+
27
+ ------------------------------------------------------------------------------
28
+ Runtime dependencies (the closure `pip install waitbus` resolves)
29
+ ------------------------------------------------------------------------------
30
+
31
+ Direct runtime dependencies (declared in pyproject.toml [project.dependencies]):
32
+
33
+ mcp MIT https://modelcontextprotocol.io
34
+ Copyright (c) Anthropic, PBC
35
+ msgspec BSD-3-Clause https://github.com/jcrist/msgspec
36
+ Copyright (c) Jim Crist-Harif
37
+ platformdirs MIT https://github.com/tox-dev/platformdirs
38
+ Copyright (c) The platformdirs developers
39
+ prometheus-client Apache-2.0 AND BSD-2-Clause https://github.com/prometheus/client_python
40
+ Copyright (c) The Prometheus Authors
41
+ pydantic-settings MIT https://github.com/pydantic/pydantic-settings
42
+ Copyright (c) Samuel Colvin and other contributors
43
+ stamina MIT https://github.com/hynek/stamina
44
+ Copyright (c) Hynek Schlawack
45
+ typer MIT https://github.com/fastapi/typer
46
+ Copyright (c) Sebastian Ramirez
47
+
48
+ Transitive runtime dependencies (pulled in by the packages above). Two
49
+ entries, colorama and pywin32, install only on Windows (they carry a
50
+ sys_platform == 'win32' marker) and are not installed on Linux or macOS:
51
+
52
+ annotated-doc MIT https://github.com/fastapi/annotated-doc
53
+ annotated-types MIT https://github.com/annotated-types/annotated-types
54
+ anyio MIT https://github.com/agronholm/anyio
55
+ attrs MIT https://github.com/python-attrs/attrs
56
+ certifi MPL-2.0 https://github.com/certifi/python-certifi
57
+ click BSD-3-Clause https://github.com/pallets/click
58
+ colorama BSD-3-Clause (Windows only) https://github.com/tartley/colorama
59
+ h11 MIT https://github.com/python-hyper/h11
60
+ httpcore BSD-3-Clause https://github.com/encode/httpcore
61
+ httpx BSD-3-Clause https://github.com/encode/httpx
62
+ httpx-sse MIT https://github.com/florimondmanca/httpx-sse
63
+ idna BSD-3-Clause https://github.com/kjd/idna
64
+ jsonschema MIT https://github.com/python-jsonschema/jsonschema
65
+ jsonschema-specifications MIT https://github.com/python-jsonschema/jsonschema-specifications
66
+ markdown-it-py MIT https://github.com/executablebooks/markdown-it-py
67
+ mdurl MIT https://github.com/executablebooks/mdurl
68
+ pydantic MIT https://github.com/pydantic/pydantic
69
+ pydantic-core MIT https://github.com/pydantic/pydantic-core
70
+ pygments BSD-2-Clause https://github.com/pygments/pygments
71
+ pyjwt MIT https://github.com/jpadilla/pyjwt
72
+ python-dotenv BSD-3-Clause https://github.com/theskumar/python-dotenv
73
+ python-multipart Apache-2.0 https://github.com/Kludex/python-multipart
74
+ pywin32 PSF-2.0 (Windows only) https://github.com/mhammond/pywin32
75
+ referencing MIT https://github.com/python-jsonschema/referencing
76
+ rich MIT https://github.com/Textualize/rich
77
+ rpds-py MIT https://github.com/crate-py/rpds
78
+ shellingham ISC https://github.com/sarugaku/shellingham
79
+ sse-starlette BSD-3-Clause https://github.com/sysid/sse-starlette
80
+ starlette BSD-3-Clause https://github.com/encode/starlette
81
+ tenacity Apache-2.0 https://github.com/jd/tenacity
82
+ typing-extensions PSF-2.0 https://github.com/python/typing_extensions
83
+ typing-inspection MIT https://github.com/pydantic/typing-inspection
84
+ uvicorn BSD-3-Clause https://github.com/encode/uvicorn
85
+
86
+ ------------------------------------------------------------------------------
87
+ Optional dependencies (installed only via the matching extra)
88
+ ------------------------------------------------------------------------------
89
+
90
+ [analyze] duckdb MIT https://github.com/duckdb/duckdb
91
+ [fs] watchdog Apache-2.0 https://github.com/gorakhargosh/watchdog
92
+ [bench] / [soak] hdrhistogram Apache-2.0 https://github.com/HdrHistogram/HdrHistogram_py
93
+ [bench] / [soak] pbr Apache-2.0 https://opendev.org/openstack/pbr
94
+ [bench] / [soak] setuptools MIT https://github.com/pypa/setuptools
95
+ [bench] tiktoken MIT https://github.com/openai/tiktoken
96
+ [bench] regex Apache-2.0 AND CNRI-Python https://github.com/mrabarnett/mrab-regex
97
+ [bench] requests Apache-2.0 https://github.com/psf/requests
98
+ [bench] charset-normalizer MIT https://github.com/jawah/charset_normalizer
99
+ [plugin-verify] pypi-attestations Apache-2.0 https://github.com/trailofbits/pypi-attestations
100
+ [plugin-verify] sigstore Apache-2.0 https://github.com/sigstore/sigstore-python
101
+ [plugin-verify] sigstore-models Apache-2.0 https://github.com/sigstore/sigstore-python
102
+ [plugin-verify] sigstore-rekor-types Apache-2.0 https://github.com/sigstore/rekor
103
+ [plugin-verify] cryptography Apache-2.0 OR BSD-3-Clause https://github.com/pyca/cryptography
104
+ [plugin-verify] pyopenssl Apache-2.0 https://github.com/pyca/pyopenssl
105
+ [plugin-verify] cffi MIT https://github.com/python-cffi/cffi
106
+ [plugin-verify] pycparser BSD-3-Clause https://github.com/eliben/pycparser
107
+ [plugin-verify] pyasn1 BSD-2-Clause https://github.com/pyasn1/pyasn1
108
+ [plugin-verify] securesystemslib MIT https://github.com/secure-systems-lab/securesystemslib
109
+ [plugin-verify] tuf Apache-2.0 OR MIT https://github.com/theupdateframework/python-tuf
110
+ [plugin-verify] id Apache-2.0 https://github.com/di/id
111
+ [plugin-verify] rfc3161-client Apache-2.0 https://github.com/trailofbits/rfc3161-client
112
+ [plugin-verify] rfc3986 Apache-2.0 https://github.com/python-hyper/rfc3986
113
+ [plugin-verify] rfc8785 Apache-2.0 https://github.com/trailofbits/rfc8785.py
114
+ [plugin-verify] packaging Apache-2.0 OR BSD-2-Clause https://github.com/pypa/packaging
115
+ [plugin-verify] requests Apache-2.0 https://github.com/psf/requests
116
+ [plugin-verify] charset-normalizer MIT https://github.com/jawah/charset_normalizer
117
+ [plugin-verify] urllib3 MIT https://github.com/urllib3/urllib3
118
+
119
+ Copyright holders for the transitive and optional packages above are recorded
120
+ in each package's own distribution metadata and license file; consult the
121
+ project URLs for the authoritative copyright and license text.