voicey 0.0.0.dev0__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 (498) hide show
  1. voicey-0.0.0.dev0/.coveragerc-managed +5 -0
  2. voicey-0.0.0.dev0/.editorconfig +15 -0
  3. voicey-0.0.0.dev0/.gitattributes +1 -0
  4. voicey-0.0.0.dev0/.github/actionlint.yaml +3 -0
  5. voicey-0.0.0.dev0/.github/dependabot.yml +13 -0
  6. voicey-0.0.0.dev0/.github/workflows/ci.yml +393 -0
  7. voicey-0.0.0.dev0/.github/workflows/live-pstn.yml +88 -0
  8. voicey-0.0.0.dev0/.github/workflows/p4-aggregate.yml +75 -0
  9. voicey-0.0.0.dev0/.github/workflows/release.yml +81 -0
  10. voicey-0.0.0.dev0/.github/workflows/runtime-edges.yml +75 -0
  11. voicey-0.0.0.dev0/.github/workflows/security.yml +47 -0
  12. voicey-0.0.0.dev0/.github/workflows/soak.yml +43 -0
  13. voicey-0.0.0.dev0/.gitignore +19 -0
  14. voicey-0.0.0.dev0/.pre-commit-config.yaml +28 -0
  15. voicey-0.0.0.dev0/.python-version +1 -0
  16. voicey-0.0.0.dev0/.secrets.baseline +388 -0
  17. voicey-0.0.0.dev0/CHANGELOG.md +45 -0
  18. voicey-0.0.0.dev0/CLAUDE.md +25 -0
  19. voicey-0.0.0.dev0/CONTRIBUTING.md +14 -0
  20. voicey-0.0.0.dev0/LICENSE +201 -0
  21. voicey-0.0.0.dev0/PKG-INFO +97 -0
  22. voicey-0.0.0.dev0/README.md +28 -0
  23. voicey-0.0.0.dev0/RENAME.md +17 -0
  24. voicey-0.0.0.dev0/SECURITY.md +26 -0
  25. voicey-0.0.0.dev0/docs/COMPLETION-REPORT.md +147 -0
  26. voicey-0.0.0.dev0/docs/GAPS.md +1510 -0
  27. voicey-0.0.0.dev0/docs/PROGRESS.md +99 -0
  28. voicey-0.0.0.dev0/docs/api/config.md +117 -0
  29. voicey-0.0.0.dev0/docs/api/errors.md +102 -0
  30. voicey-0.0.0.dev0/docs/api/index.md +15 -0
  31. voicey-0.0.0.dev0/docs/api/python.md +240 -0
  32. voicey-0.0.0.dev0/docs/api/snapshots/cli-surface.json +2286 -0
  33. voicey-0.0.0.dev0/docs/api/snapshots/config-schema.json +421 -0
  34. voicey-0.0.0.dev0/docs/api/snapshots/webhook-schema.json +319 -0
  35. voicey-0.0.0.dev0/docs/api/webhooks.md +74 -0
  36. voicey-0.0.0.dev0/docs/assets/recipes/appointment-booking-demo.mp3 +0 -0
  37. voicey-0.0.0.dev0/docs/assets/recipes/demo-transcripts.json +90 -0
  38. voicey-0.0.0.dev0/docs/assets/recipes/front-desk-demo.mp3 +0 -0
  39. voicey-0.0.0.dev0/docs/assets/recipes/lead-intake-demo.mp3 +0 -0
  40. voicey-0.0.0.dev0/docs/assets/recipes/restaurant-reservations-demo.mp3 +0 -0
  41. voicey-0.0.0.dev0/docs/build-plan.md +310 -0
  42. voicey-0.0.0.dev0/docs/carriers/generic-sip.md +84 -0
  43. voicey-0.0.0.dev0/docs/carriers/plivo.md +146 -0
  44. voicey-0.0.0.dev0/docs/carriers/telnyx.md +198 -0
  45. voicey-0.0.0.dev0/docs/carriers/twilio.md +257 -0
  46. voicey-0.0.0.dev0/docs/carriers/vobiz.md +199 -0
  47. voicey-0.0.0.dev0/docs/cli.md +323 -0
  48. voicey-0.0.0.dev0/docs/compatibility.md +107 -0
  49. voicey-0.0.0.dev0/docs/concepts.md +75 -0
  50. voicey-0.0.0.dev0/docs/configuration.md +158 -0
  51. voicey-0.0.0.dev0/docs/data-map.md +56 -0
  52. voicey-0.0.0.dev0/docs/decisions.md +965 -0
  53. voicey-0.0.0.dev0/docs/deploy/docker.md +177 -0
  54. voicey-0.0.0.dev0/docs/deploy/fly-companion.md +240 -0
  55. voicey-0.0.0.dev0/docs/deploy/livekit-cloud.md +161 -0
  56. voicey-0.0.0.dev0/docs/deploy/pipecat-cloud.md +202 -0
  57. voicey-0.0.0.dev0/docs/deploy/railway.md +231 -0
  58. voicey-0.0.0.dev0/docs/development.md +39 -0
  59. voicey-0.0.0.dev0/docs/errors.md +629 -0
  60. voicey-0.0.0.dev0/docs/hardening.md +80 -0
  61. voicey-0.0.0.dev0/docs/index.md +70 -0
  62. voicey-0.0.0.dev0/docs/managed-storage.md +124 -0
  63. voicey-0.0.0.dev0/docs/observability.md +175 -0
  64. voicey-0.0.0.dev0/docs/playground.md +135 -0
  65. voicey-0.0.0.dev0/docs/product-spec.md +615 -0
  66. voicey-0.0.0.dev0/docs/quickstart-livekit.md +63 -0
  67. voicey-0.0.0.dev0/docs/quickstart-pipecat.md +63 -0
  68. voicey-0.0.0.dev0/docs/recipes/appointment-booking.md +110 -0
  69. voicey-0.0.0.dev0/docs/recipes/front-desk.md +59 -0
  70. voicey-0.0.0.dev0/docs/recipes/lead-intake.md +57 -0
  71. voicey-0.0.0.dev0/docs/recipes/quality-checklist.md +47 -0
  72. voicey-0.0.0.dev0/docs/recipes/restaurant-reservations.md +56 -0
  73. voicey-0.0.0.dev0/docs/releasing.md +163 -0
  74. voicey-0.0.0.dev0/docs/research/pipecat-api-reference.md +516 -0
  75. voicey-0.0.0.dev0/docs/results-relay.md +161 -0
  76. voicey-0.0.0.dev0/docs/results-webhooks.md +257 -0
  77. voicey-0.0.0.dev0/docs/runtime-config-matrix.json +147 -0
  78. voicey-0.0.0.dev0/docs/runtime-parity-matrix.json +165 -0
  79. voicey-0.0.0.dev0/docs/runtime-parity.md +70 -0
  80. voicey-0.0.0.dev0/docs/runtimes/livekit.md +142 -0
  81. voicey-0.0.0.dev0/docs/runtimes/pipecat.md +167 -0
  82. voicey-0.0.0.dev0/docs/testing/pipecat-evals.md +101 -0
  83. voicey-0.0.0.dev0/docs/testing.md +226 -0
  84. voicey-0.0.0.dev0/docs/tools.md +140 -0
  85. voicey-0.0.0.dev0/docs/troubleshooting.md +83 -0
  86. voicey-0.0.0.dev0/docs/tunnels.md +128 -0
  87. voicey-0.0.0.dev0/docs/upgrading.md +112 -0
  88. voicey-0.0.0.dev0/docs/verification/p0-walking-skeleton.md +29 -0
  89. voicey-0.0.0.dev0/docs/verification/p1-cli-matrix.json +242 -0
  90. voicey-0.0.0.dev0/docs/verification/p1-gates.md +91 -0
  91. voicey-0.0.0.dev0/docs/verification/p2-gates.md +60 -0
  92. voicey-0.0.0.dev0/docs/verification/p3-gates.md +50 -0
  93. voicey-0.0.0.dev0/hatch_build.py +57 -0
  94. voicey-0.0.0.dev0/npm/voicey/LICENSE +13 -0
  95. voicey-0.0.0.dev0/npm/voicey/README.md +7 -0
  96. voicey-0.0.0.dev0/npm/voicey/index.js +10 -0
  97. voicey-0.0.0.dev0/npm/voicey/package.json +16 -0
  98. voicey-0.0.0.dev0/playground-web/index.html +14 -0
  99. voicey-0.0.0.dev0/playground-web/package-lock.json +3875 -0
  100. voicey-0.0.0.dev0/playground-web/package.json +34 -0
  101. voicey-0.0.0.dev0/playground-web/src/App.test.tsx +260 -0
  102. voicey-0.0.0.dev0/playground-web/src/App.tsx +636 -0
  103. voicey-0.0.0.dev0/playground-web/src/LiveKitSession.test.tsx +140 -0
  104. voicey-0.0.0.dev0/playground-web/src/LiveKitSession.tsx +179 -0
  105. voicey-0.0.0.dev0/playground-web/src/PipecatSession.tsx +89 -0
  106. voicey-0.0.0.dev0/playground-web/src/api.test.ts +143 -0
  107. voicey-0.0.0.dev0/playground-web/src/api.ts +180 -0
  108. voicey-0.0.0.dev0/playground-web/src/main.tsx +22 -0
  109. voicey-0.0.0.dev0/playground-web/src/styles.css +826 -0
  110. voicey-0.0.0.dev0/playground-web/src/test-setup.ts +11 -0
  111. voicey-0.0.0.dev0/playground-web/src/vite-env.d.ts +3 -0
  112. voicey-0.0.0.dev0/playground-web/tsconfig.app.json +21 -0
  113. voicey-0.0.0.dev0/playground-web/tsconfig.json +7 -0
  114. voicey-0.0.0.dev0/playground-web/tsconfig.node.json +12 -0
  115. voicey-0.0.0.dev0/playground-web/vite.config.ts +17 -0
  116. voicey-0.0.0.dev0/pyproject.toml +174 -0
  117. voicey-0.0.0.dev0/recipes/README.md +8 -0
  118. voicey-0.0.0.dev0/recipes/appointment-booking/README.md +117 -0
  119. voicey-0.0.0.dev0/recipes/appointment-booking/livekit/flow.py +217 -0
  120. voicey-0.0.0.dev0/recipes/appointment-booking/livekit/tests/test_recipe.py +37 -0
  121. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/eval_bot.py +37 -0
  122. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/audio/barge-in-audio.yaml +14 -0
  123. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/audio/book-audio.yaml +17 -0
  124. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/audio/change-mind-audio.yaml +15 -0
  125. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/audio/latency-reference.yaml +66 -0
  126. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/audio-suite.yaml +13 -0
  127. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/judge-audio-local.yaml +8 -0
  128. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/judge-cloud.example.yaml +6 -0
  129. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/judge-local.yaml +4 -0
  130. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/latency-suite.yaml +11 -0
  131. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/barge-in.yaml +15 -0
  132. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/book.yaml +29 -0
  133. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/calendar-failure.yaml +13 -0
  134. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/cancel.yaml +20 -0
  135. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/change-mind.yaml +24 -0
  136. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/human-transfer.yaml +12 -0
  137. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text/voicemail.yaml +10 -0
  138. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/text-suite.yaml +17 -0
  139. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/evals/user-audio.yaml +5 -0
  140. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/flow.py +34 -0
  141. voicey-0.0.0.dev0/recipes/appointment-booking/pipecat/tests/test_recipe.py +13 -0
  142. voicey-0.0.0.dev0/recipes/appointment-booking/prompts/failure.md +12 -0
  143. voicey-0.0.0.dev0/recipes/appointment-booking/prompts/greeting.md +1 -0
  144. voicey-0.0.0.dev0/recipes/appointment-booking/prompts/system.md +59 -0
  145. voicey-0.0.0.dev0/recipes/appointment-booking/prompts/voicemail.md +11 -0
  146. voicey-0.0.0.dev0/recipes/appointment-booking/recipe.jsonc +13 -0
  147. voicey-0.0.0.dev0/recipes/appointment-booking/tests/scenarios.py +335 -0
  148. voicey-0.0.0.dev0/recipes/appointment-booking/tools.py +185 -0
  149. voicey-0.0.0.dev0/recipes/front-desk/README.md +14 -0
  150. voicey-0.0.0.dev0/recipes/front-desk/livekit/flow.py +61 -0
  151. voicey-0.0.0.dev0/recipes/front-desk/pipecat/eval_bot.py +32 -0
  152. voicey-0.0.0.dev0/recipes/front-desk/pipecat/flow.py +29 -0
  153. voicey-0.0.0.dev0/recipes/front-desk/prompts/failure.md +5 -0
  154. voicey-0.0.0.dev0/recipes/front-desk/prompts/greeting.md +1 -0
  155. voicey-0.0.0.dev0/recipes/front-desk/prompts/system.md +18 -0
  156. voicey-0.0.0.dev0/recipes/front-desk/prompts/voicemail.md +11 -0
  157. voicey-0.0.0.dev0/recipes/front-desk/recipe.jsonc +13 -0
  158. voicey-0.0.0.dev0/recipes/front-desk/tests/scenarios.py +157 -0
  159. voicey-0.0.0.dev0/recipes/front-desk/tools.py +100 -0
  160. voicey-0.0.0.dev0/recipes/lead-intake/README.md +13 -0
  161. voicey-0.0.0.dev0/recipes/lead-intake/livekit/flow.py +96 -0
  162. voicey-0.0.0.dev0/recipes/lead-intake/pipecat/eval_bot.py +30 -0
  163. voicey-0.0.0.dev0/recipes/lead-intake/pipecat/flow.py +29 -0
  164. voicey-0.0.0.dev0/recipes/lead-intake/prompts/failure.md +5 -0
  165. voicey-0.0.0.dev0/recipes/lead-intake/prompts/greeting.md +1 -0
  166. voicey-0.0.0.dev0/recipes/lead-intake/prompts/system.md +17 -0
  167. voicey-0.0.0.dev0/recipes/lead-intake/prompts/voicemail.md +12 -0
  168. voicey-0.0.0.dev0/recipes/lead-intake/recipe.jsonc +13 -0
  169. voicey-0.0.0.dev0/recipes/lead-intake/tests/scenarios.py +166 -0
  170. voicey-0.0.0.dev0/recipes/lead-intake/tools.py +205 -0
  171. voicey-0.0.0.dev0/recipes/restaurant-reservations/README.md +13 -0
  172. voicey-0.0.0.dev0/recipes/restaurant-reservations/livekit/flow.py +67 -0
  173. voicey-0.0.0.dev0/recipes/restaurant-reservations/pipecat/eval_bot.py +30 -0
  174. voicey-0.0.0.dev0/recipes/restaurant-reservations/pipecat/flow.py +29 -0
  175. voicey-0.0.0.dev0/recipes/restaurant-reservations/prompts/failure.md +5 -0
  176. voicey-0.0.0.dev0/recipes/restaurant-reservations/prompts/greeting.md +1 -0
  177. voicey-0.0.0.dev0/recipes/restaurant-reservations/prompts/system.md +15 -0
  178. voicey-0.0.0.dev0/recipes/restaurant-reservations/prompts/voicemail.md +12 -0
  179. voicey-0.0.0.dev0/recipes/restaurant-reservations/recipe.jsonc +13 -0
  180. voicey-0.0.0.dev0/recipes/restaurant-reservations/tests/scenarios.py +153 -0
  181. voicey-0.0.0.dev0/recipes/restaurant-reservations/tools.py +219 -0
  182. voicey-0.0.0.dev0/scripts/check_public_surface_docs.py +34 -0
  183. voicey-0.0.0.dev0/scripts/generate_recipe_demo_audio.py +125 -0
  184. voicey-0.0.0.dev0/scripts/update_api_reference.py +37 -0
  185. voicey-0.0.0.dev0/scripts/update_public_snapshots.py +37 -0
  186. voicey-0.0.0.dev0/src/voicey/__init__.py +33 -0
  187. voicey-0.0.0.dev0/src/voicey/_frontend/assets/LiveKitSession-D_ltM0yH.js +39 -0
  188. voicey-0.0.0.dev0/src/voicey/_frontend/assets/PipecatSession-CDRfVl3x.js +413 -0
  189. voicey-0.0.0.dev0/src/voicey/_frontend/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  190. voicey-0.0.0.dev0/src/voicey/_frontend/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  191. voicey-0.0.0.dev0/src/voicey/_frontend/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  192. voicey-0.0.0.dev0/src/voicey/_frontend/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  193. voicey-0.0.0.dev0/src/voicey/_frontend/assets/index-B0pZS9vH.css +1 -0
  194. voicey-0.0.0.dev0/src/voicey/_frontend/assets/index-D1MsCcB3.js +9 -0
  195. voicey-0.0.0.dev0/src/voicey/_frontend/assets/index.module-CfAoeLOb.js +1 -0
  196. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-400-normal-D1W7dsQl.woff +0 -0
  197. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-400-normal-DRC__1Mx.woff2 +0 -0
  198. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-500-normal-Dk9ku72i.woff2 +0 -0
  199. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-500-normal-Z6ESRlEs.woff +0 -0
  200. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-600-normal-B7fBEWYG.woff2 +0 -0
  201. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-600-normal-B9e8oLYv.woff +0 -0
  202. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-ext-400-normal-Q_nF8v4l.woff2 +0 -0
  203. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-ext-400-normal-r32jotim.woff +0 -0
  204. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-ext-500-normal-CAxz3nsc.woff +0 -0
  205. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-ext-500-normal-CTEe1bJa.woff2 +0 -0
  206. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-ext-600-normal-BsaQcF38.woff2 +0 -0
  207. voicey-0.0.0.dev0/src/voicey/_frontend/assets/instrument-sans-latin-ext-600-normal-DMks36a2.woff +0 -0
  208. voicey-0.0.0.dev0/src/voicey/_frontend/assets/voice-ui-kit-9_azXb1F.js +1 -0
  209. voicey-0.0.0.dev0/src/voicey/_frontend/assets/voice-ui-kit-BL6APnpe.js +1 -0
  210. voicey-0.0.0.dev0/src/voicey/_frontend/assets/voice-ui-kit-C-Dv3PZZ.js +1 -0
  211. voicey-0.0.0.dev0/src/voicey/_frontend/index.html +15 -0
  212. voicey-0.0.0.dev0/src/voicey/_p0/__init__.py +1 -0
  213. voicey-0.0.0.dev0/src/voicey/_p0/common.py +99 -0
  214. voicey-0.0.0.dev0/src/voicey/_p0/livekit_probe.py +85 -0
  215. voicey-0.0.0.dev0/src/voicey/_p0/pipecat_probe.py +151 -0
  216. voicey-0.0.0.dev0/src/voicey/_version.py +3 -0
  217. voicey-0.0.0.dev0/src/voicey/capabilities.py +198 -0
  218. voicey-0.0.0.dev0/src/voicey/cli/__init__.py +1 -0
  219. voicey-0.0.0.dev0/src/voicey/cli/app.py +2285 -0
  220. voicey-0.0.0.dev0/src/voicey/cli/checkpoint.py +87 -0
  221. voicey-0.0.0.dev0/src/voicey/cli/context.py +153 -0
  222. voicey-0.0.0.dev0/src/voicey/cli/dev.py +861 -0
  223. voicey-0.0.0.dev0/src/voicey/cli/doctor.py +847 -0
  224. voicey-0.0.0.dev0/src/voicey/cli/drafting.py +253 -0
  225. voicey-0.0.0.dev0/src/voicey/cli/environment.py +195 -0
  226. voicey-0.0.0.dev0/src/voicey/cli/keys.py +362 -0
  227. voicey-0.0.0.dev0/src/voicey/cli/prompts.py +160 -0
  228. voicey-0.0.0.dev0/src/voicey/cli/scaffold.py +404 -0
  229. voicey-0.0.0.dev0/src/voicey/cli/wizard.py +715 -0
  230. voicey-0.0.0.dev0/src/voicey/compatibility.py +146 -0
  231. voicey-0.0.0.dev0/src/voicey/config/__init__.py +57 -0
  232. voicey-0.0.0.dev0/src/voicey/config/catalog.py +319 -0
  233. voicey-0.0.0.dev0/src/voicey/config/manifest.py +130 -0
  234. voicey-0.0.0.dev0/src/voicey/config/models.py +581 -0
  235. voicey-0.0.0.dev0/src/voicey/config/validation.py +228 -0
  236. voicey-0.0.0.dev0/src/voicey/deploy/__init__.py +91 -0
  237. voicey-0.0.0.dev0/src/voicey/deploy/cloud.py +1849 -0
  238. voicey-0.0.0.dev0/src/voicey/deploy/cloud_runtime.py +635 -0
  239. voicey-0.0.0.dev0/src/voicey/deploy/cloud_smoke.py +577 -0
  240. voicey-0.0.0.dev0/src/voicey/deploy/docker.py +450 -0
  241. voicey-0.0.0.dev0/src/voicey/deploy/fly.py +1005 -0
  242. voicey-0.0.0.dev0/src/voicey/deploy/managed.py +189 -0
  243. voicey-0.0.0.dev0/src/voicey/deploy/managed_secrets.py +195 -0
  244. voicey-0.0.0.dev0/src/voicey/deploy/persistence.py +248 -0
  245. voicey-0.0.0.dev0/src/voicey/deploy/railway.py +1716 -0
  246. voicey-0.0.0.dev0/src/voicey/deploy/results_service.py +732 -0
  247. voicey-0.0.0.dev0/src/voicey/deploy/runtime.py +668 -0
  248. voicey-0.0.0.dev0/src/voicey/errors.py +556 -0
  249. voicey-0.0.0.dev0/src/voicey/obs/__init__.py +32 -0
  250. voicey-0.0.0.dev0/src/voicey/obs/latency.py +133 -0
  251. voicey-0.0.0.dev0/src/voicey/obs/logging.py +167 -0
  252. voicey-0.0.0.dev0/src/voicey/obs/records.py +940 -0
  253. voicey-0.0.0.dev0/src/voicey/obs/telemetry.py +535 -0
  254. voicey-0.0.0.dev0/src/voicey/playground/__init__.py +25 -0
  255. voicey-0.0.0.dev0/src/voicey/playground/assets.py +24 -0
  256. voicey-0.0.0.dev0/src/voicey/playground/reload.py +177 -0
  257. voicey-0.0.0.dev0/src/voicey/playground/security.py +497 -0
  258. voicey-0.0.0.dev0/src/voicey/playground/service.py +493 -0
  259. voicey-0.0.0.dev0/src/voicey/py.typed +1 -0
  260. voicey-0.0.0.dev0/src/voicey/recipes/__init__.py +29 -0
  261. voicey-0.0.0.dev0/src/voicey/recipes/drift.py +298 -0
  262. voicey-0.0.0.dev0/src/voicey/recipes/registry.py +108 -0
  263. voicey-0.0.0.dev0/src/voicey/recipes/source.py +291 -0
  264. voicey-0.0.0.dev0/src/voicey/relay/__init__.py +15 -0
  265. voicey-0.0.0.dev0/src/voicey/relay/auth.py +252 -0
  266. voicey-0.0.0.dev0/src/voicey/relay/client.py +471 -0
  267. voicey-0.0.0.dev0/src/voicey/relay/cloud_answer.py +160 -0
  268. voicey-0.0.0.dev0/src/voicey/relay/companion.py +273 -0
  269. voicey-0.0.0.dev0/src/voicey/relay/journal.py +436 -0
  270. voicey-0.0.0.dev0/src/voicey/relay/models.py +130 -0
  271. voicey-0.0.0.dev0/src/voicey/relay/postgres.py +324 -0
  272. voicey-0.0.0.dev0/src/voicey/relay/recording.py +186 -0
  273. voicey-0.0.0.dev0/src/voicey/relay/service.py +527 -0
  274. voicey-0.0.0.dev0/src/voicey/release/__init__.py +15 -0
  275. voicey-0.0.0.dev0/src/voicey/release/docs.py +280 -0
  276. voicey-0.0.0.dev0/src/voicey/release/policy.py +97 -0
  277. voicey-0.0.0.dev0/src/voicey/release/snapshots.py +139 -0
  278. voicey-0.0.0.dev0/src/voicey/results/__init__.py +40 -0
  279. voicey-0.0.0.dev0/src/voicey/results/delivery.py +113 -0
  280. voicey-0.0.0.dev0/src/voicey/results/events.py +134 -0
  281. voicey-0.0.0.dev0/src/voicey/results/recorder.py +61 -0
  282. voicey-0.0.0.dev0/src/voicey/results/recording.py +228 -0
  283. voicey-0.0.0.dev0/src/voicey/results/recovery.py +179 -0
  284. voicey-0.0.0.dev0/src/voicey/results/schema.py +72 -0
  285. voicey-0.0.0.dev0/src/voicey/results/signing.py +131 -0
  286. voicey-0.0.0.dev0/src/voicey/runtimes/__init__.py +1 -0
  287. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/__init__.py +79 -0
  288. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/flow.py +81 -0
  289. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/generic_sip.py +428 -0
  290. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/host.py +687 -0
  291. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/lifecycle.py +37 -0
  292. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/mapping.py +201 -0
  293. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/observability.py +199 -0
  294. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/plivo.py +844 -0
  295. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/providers.py +303 -0
  296. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/session.py +471 -0
  297. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/sip.py +1162 -0
  298. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/telnyx.py +892 -0
  299. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/token.py +102 -0
  300. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/tools.py +81 -0
  301. voicey-0.0.0.dev0/src/voicey/runtimes/livekit/vobiz.py +914 -0
  302. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/__init__.py +57 -0
  303. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/admission.py +73 -0
  304. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/evals.py +189 -0
  305. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/flows.py +251 -0
  306. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/host.py +2101 -0
  307. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/lifecycle.py +366 -0
  308. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/mapping.py +164 -0
  309. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/observability.py +162 -0
  310. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/providers.py +302 -0
  311. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/recording.py +5 -0
  312. voicey-0.0.0.dev0/src/voicey/runtimes/pipecat/session.py +542 -0
  313. voicey-0.0.0.dev0/src/voicey/security/__init__.py +5 -0
  314. voicey-0.0.0.dev0/src/voicey/security/files.py +42 -0
  315. voicey-0.0.0.dev0/src/voicey/storage/__init__.py +41 -0
  316. voicey-0.0.0.dev0/src/voicey/storage/artifacts.py +131 -0
  317. voicey-0.0.0.dev0/src/voicey/storage/migrations/postgres/0001_initial.sql +183 -0
  318. voicey-0.0.0.dev0/src/voicey/storage/models.py +199 -0
  319. voicey-0.0.0.dev0/src/voicey/storage/postgres.py +1664 -0
  320. voicey-0.0.0.dev0/src/voicey/storage/repository.py +147 -0
  321. voicey-0.0.0.dev0/src/voicey/storage/s3.py +250 -0
  322. voicey-0.0.0.dev0/src/voicey/storage/sqlite.py +1192 -0
  323. voicey-0.0.0.dev0/src/voicey/telephony/__init__.py +30 -0
  324. voicey-0.0.0.dev0/src/voicey/telephony/ledger.py +943 -0
  325. voicey-0.0.0.dev0/src/voicey/telephony/models.py +219 -0
  326. voicey-0.0.0.dev0/src/voicey/telephony/plivo/__init__.py +5 -0
  327. voicey-0.0.0.dev0/src/voicey/telephony/plivo/adapter.py +993 -0
  328. voicey-0.0.0.dev0/src/voicey/telephony/protocol.py +59 -0
  329. voicey-0.0.0.dev0/src/voicey/telephony/registry.py +54 -0
  330. voicey-0.0.0.dev0/src/voicey/telephony/telnyx/__init__.py +5 -0
  331. voicey-0.0.0.dev0/src/voicey/telephony/telnyx/adapter.py +1076 -0
  332. voicey-0.0.0.dev0/src/voicey/telephony/twilio/__init__.py +39 -0
  333. voicey-0.0.0.dev0/src/voicey/telephony/twilio/adapter.py +1367 -0
  334. voicey-0.0.0.dev0/src/voicey/telephony/twilio/media.py +351 -0
  335. voicey-0.0.0.dev0/src/voicey/telephony/vobiz/__init__.py +5 -0
  336. voicey-0.0.0.dev0/src/voicey/telephony/vobiz/adapter.py +1124 -0
  337. voicey-0.0.0.dev0/src/voicey/testing/__init__.py +51 -0
  338. voicey-0.0.0.dev0/src/voicey/testing/discovery.py +121 -0
  339. voicey-0.0.0.dev0/src/voicey/testing/live.py +345 -0
  340. voicey-0.0.0.dev0/src/voicey/testing/live_livekit.py +255 -0
  341. voicey-0.0.0.dev0/src/voicey/testing/live_pipecat.py +559 -0
  342. voicey-0.0.0.dev0/src/voicey/testing/livekit.py +126 -0
  343. voicey-0.0.0.dev0/src/voicey/testing/livekit_audio.py +254 -0
  344. voicey-0.0.0.dev0/src/voicey/testing/models.py +270 -0
  345. voicey-0.0.0.dev0/src/voicey/testing/pipecat.py +325 -0
  346. voicey-0.0.0.dev0/src/voicey/testing/pipecat_judge.py +40 -0
  347. voicey-0.0.0.dev0/src/voicey/testing/reporting.py +127 -0
  348. voicey-0.0.0.dev0/src/voicey/testing/runner.py +714 -0
  349. voicey-0.0.0.dev0/src/voicey/testing/sim_caller.py +365 -0
  350. voicey-0.0.0.dev0/src/voicey/testing/soak.py +357 -0
  351. voicey-0.0.0.dev0/src/voicey/tools/__init__.py +29 -0
  352. voicey-0.0.0.dev0/src/voicey/tools/core.py +203 -0
  353. voicey-0.0.0.dev0/src/voicey/tools/discovery.py +61 -0
  354. voicey-0.0.0.dev0/src/voicey/tools/execution.py +273 -0
  355. voicey-0.0.0.dev0/src/voicey/tools/http.py +215 -0
  356. voicey-0.0.0.dev0/src/voicey/tunnel/__init__.py +17 -0
  357. voicey-0.0.0.dev0/src/voicey/tunnel/manager.py +485 -0
  358. voicey-0.0.0.dev0/src/voicey/tunnel/probe.py +134 -0
  359. voicey-0.0.0.dev0/src/voicey/upgrade.py +428 -0
  360. voicey-0.0.0.dev0/src/voicey/versioning.py +142 -0
  361. voicey-0.0.0.dev0/tests/certification/test_generic_livekit_sip.py +253 -0
  362. voicey-0.0.0.dev0/tests/certification/test_plivo_adapter.py +999 -0
  363. voicey-0.0.0.dev0/tests/certification/test_plivo_livekit_sip.py +751 -0
  364. voicey-0.0.0.dev0/tests/certification/test_plivo_media.py +104 -0
  365. voicey-0.0.0.dev0/tests/certification/test_telnyx_adapter.py +1020 -0
  366. voicey-0.0.0.dev0/tests/certification/test_telnyx_livekit_sip.py +629 -0
  367. voicey-0.0.0.dev0/tests/certification/test_telnyx_media.py +132 -0
  368. voicey-0.0.0.dev0/tests/certification/test_twilio_adapter.py +1086 -0
  369. voicey-0.0.0.dev0/tests/certification/test_twilio_livekit_sip.py +385 -0
  370. voicey-0.0.0.dev0/tests/certification/test_twilio_media.py +271 -0
  371. voicey-0.0.0.dev0/tests/certification/test_twilio_warm_transfer.py +546 -0
  372. voicey-0.0.0.dev0/tests/certification/test_vobiz_adapter.py +1028 -0
  373. voicey-0.0.0.dev0/tests/certification/test_vobiz_livekit_sip.py +968 -0
  374. voicey-0.0.0.dev0/tests/certification/test_vobiz_media.py +99 -0
  375. voicey-0.0.0.dev0/tests/chaos/__init__.py +1 -0
  376. voicey-0.0.0.dev0/tests/chaos/test_terminal_invariant.py +154 -0
  377. voicey-0.0.0.dev0/tests/fixtures/docker-project/.env.example +6 -0
  378. voicey-0.0.0.dev0/tests/fixtures/docker-project/.gitignore +7 -0
  379. voicey-0.0.0.dev0/tests/fixtures/docker-project/README.md +4 -0
  380. voicey-0.0.0.dev0/tests/fixtures/docker-project/agent.py +22 -0
  381. voicey-0.0.0.dev0/tests/fixtures/docker-project/flow.py +11 -0
  382. voicey-0.0.0.dev0/tests/fixtures/docker-project/pyproject.toml +5 -0
  383. voicey-0.0.0.dev0/tests/fixtures/docker-project/tools.py +9 -0
  384. voicey-0.0.0.dev0/tests/fixtures/docker-project/voicey.jsonc +26 -0
  385. voicey-0.0.0.dev0/tests/fixtures/live-pstn-livekit/tests/scenarios.py +18 -0
  386. voicey-0.0.0.dev0/tests/fixtures/live-pstn-livekit/tests/voicey-test.jsonc +17 -0
  387. voicey-0.0.0.dev0/tests/fixtures/live-pstn-livekit/voicey.jsonc +12 -0
  388. voicey-0.0.0.dev0/tests/fixtures/live-pstn-pipecat/tests/scenarios.py +18 -0
  389. voicey-0.0.0.dev0/tests/fixtures/live-pstn-pipecat/tests/voicey-test.jsonc +18 -0
  390. voicey-0.0.0.dev0/tests/fixtures/live-pstn-pipecat/voicey.jsonc +12 -0
  391. voicey-0.0.0.dev0/tests/integration/test_livekit_quickstart.py +133 -0
  392. voicey-0.0.0.dev0/tests/integration/test_livekit_sigkill.py +137 -0
  393. voicey-0.0.0.dev0/tests/integration/test_managed_results_service.py +114 -0
  394. voicey-0.0.0.dev0/tests/integration/test_p0_walking_skeleton.py +71 -0
  395. voicey-0.0.0.dev0/tests/integration/test_postgres_repository.py +834 -0
  396. voicey-0.0.0.dev0/tests/integration/test_repository_backends.py +238 -0
  397. voicey-0.0.0.dev0/tests/integration/test_results_sigkill.py +112 -0
  398. voicey-0.0.0.dev0/tests/interop/standard_webhooks_vector.json +7 -0
  399. voicey-0.0.0.dev0/tests/interop/verify_node.mjs +23 -0
  400. voicey-0.0.0.dev0/tests/interop/voicey_vector_test.go +43 -0
  401. voicey-0.0.0.dev0/tests/live/test_generic_sip_live.py +104 -0
  402. voicey-0.0.0.dev0/tests/live/test_plivo_live.py +113 -0
  403. voicey-0.0.0.dev0/tests/live/test_plivo_livekit_live.py +100 -0
  404. voicey-0.0.0.dev0/tests/live/test_s3_artifacts_live.py +31 -0
  405. voicey-0.0.0.dev0/tests/live/test_telnyx_live.py +129 -0
  406. voicey-0.0.0.dev0/tests/live/test_telnyx_livekit_live.py +102 -0
  407. voicey-0.0.0.dev0/tests/live/test_tunnel_live.py +56 -0
  408. voicey-0.0.0.dev0/tests/live/test_twilio_live.py +146 -0
  409. voicey-0.0.0.dev0/tests/live/test_twilio_livekit_live.py +121 -0
  410. voicey-0.0.0.dev0/tests/live/test_vobiz_live.py +122 -0
  411. voicey-0.0.0.dev0/tests/live/test_vobiz_livekit_live.py +108 -0
  412. voicey-0.0.0.dev0/tests/manual/prepare_broken_doctor.py +63 -0
  413. voicey-0.0.0.dev0/tests/manual/run_livekit_playground_fixture.py +155 -0
  414. voicey-0.0.0.dev0/tests/manual/run_playground_fixture.py +102 -0
  415. voicey-0.0.0.dev0/tests/parity/__init__.py +1 -0
  416. voicey-0.0.0.dev0/tests/parity/test_behavioral_parity.py +271 -0
  417. voicey-0.0.0.dev0/tests/parity/test_config_mapping.py +165 -0
  418. voicey-0.0.0.dev0/tests/parity/test_matrix.py +73 -0
  419. voicey-0.0.0.dev0/tests/unit/test_cli.py +1933 -0
  420. voicey-0.0.0.dev0/tests/unit/test_cli_dev.py +945 -0
  421. voicey-0.0.0.dev0/tests/unit/test_cli_doctor.py +936 -0
  422. voicey-0.0.0.dev0/tests/unit/test_cli_drafting.py +141 -0
  423. voicey-0.0.0.dev0/tests/unit/test_cli_foundations.py +1005 -0
  424. voicey-0.0.0.dev0/tests/unit/test_cli_prompts.py +122 -0
  425. voicey-0.0.0.dev0/tests/unit/test_cli_wizard.py +773 -0
  426. voicey-0.0.0.dev0/tests/unit/test_cloud_answer.py +102 -0
  427. voicey-0.0.0.dev0/tests/unit/test_cloud_runtime.py +717 -0
  428. voicey-0.0.0.dev0/tests/unit/test_cloud_smoke.py +652 -0
  429. voicey-0.0.0.dev0/tests/unit/test_compatibility.py +80 -0
  430. voicey-0.0.0.dev0/tests/unit/test_config.py +430 -0
  431. voicey-0.0.0.dev0/tests/unit/test_deploy_cloud.py +1102 -0
  432. voicey-0.0.0.dev0/tests/unit/test_deploy_docker.py +812 -0
  433. voicey-0.0.0.dev0/tests/unit/test_deploy_fly.py +712 -0
  434. voicey-0.0.0.dev0/tests/unit/test_deploy_railway.py +1107 -0
  435. voicey-0.0.0.dev0/tests/unit/test_docs_contract.py +182 -0
  436. voicey-0.0.0.dev0/tests/unit/test_errors.py +52 -0
  437. voicey-0.0.0.dev0/tests/unit/test_generated_docs.py +36 -0
  438. voicey-0.0.0.dev0/tests/unit/test_hatch_build.py +56 -0
  439. voicey-0.0.0.dev0/tests/unit/test_live_testing.py +1245 -0
  440. voicey-0.0.0.dev0/tests/unit/test_livekit_host.py +638 -0
  441. voicey-0.0.0.dev0/tests/unit/test_livekit_runtime.py +633 -0
  442. voicey-0.0.0.dev0/tests/unit/test_livekit_runtime_edges.py +513 -0
  443. voicey-0.0.0.dev0/tests/unit/test_livekit_sip_backend.py +647 -0
  444. voicey-0.0.0.dev0/tests/unit/test_observability.py +902 -0
  445. voicey-0.0.0.dev0/tests/unit/test_pipecat_host.py +1655 -0
  446. voicey-0.0.0.dev0/tests/unit/test_pipecat_providers.py +136 -0
  447. voicey-0.0.0.dev0/tests/unit/test_pipecat_recording.py +440 -0
  448. voicey-0.0.0.dev0/tests/unit/test_pipecat_runtime.py +974 -0
  449. voicey-0.0.0.dev0/tests/unit/test_playground_assets.py +27 -0
  450. voicey-0.0.0.dev0/tests/unit/test_playground_reload.py +151 -0
  451. voicey-0.0.0.dev0/tests/unit/test_playground_security.py +212 -0
  452. voicey-0.0.0.dev0/tests/unit/test_playground_service.py +628 -0
  453. voicey-0.0.0.dev0/tests/unit/test_plivo_pipecat_host.py +293 -0
  454. voicey-0.0.0.dev0/tests/unit/test_public_snapshots.py +68 -0
  455. voicey-0.0.0.dev0/tests/unit/test_recipe_appointment.py +608 -0
  456. voicey-0.0.0.dev0/tests/unit/test_recipe_drift.py +334 -0
  457. voicey-0.0.0.dev0/tests/unit/test_recipes_p3.py +310 -0
  458. voicey-0.0.0.dev0/tests/unit/test_relay.py +906 -0
  459. voicey-0.0.0.dev0/tests/unit/test_release_policy.py +88 -0
  460. voicey-0.0.0.dev0/tests/unit/test_results_companion.py +570 -0
  461. voicey-0.0.0.dev0/tests/unit/test_results_recorder.py +43 -0
  462. voicey-0.0.0.dev0/tests/unit/test_results_repository.py +939 -0
  463. voicey-0.0.0.dev0/tests/unit/test_results_schema.py +63 -0
  464. voicey-0.0.0.dev0/tests/unit/test_results_service_runtime.py +600 -0
  465. voicey-0.0.0.dev0/tests/unit/test_results_signing.py +112 -0
  466. voicey-0.0.0.dev0/tests/unit/test_s3_artifacts.py +263 -0
  467. voicey-0.0.0.dev0/tests/unit/test_security_files.py +50 -0
  468. voicey-0.0.0.dev0/tests/unit/test_telephony.py +300 -0
  469. voicey-0.0.0.dev0/tests/unit/test_testing.py +1625 -0
  470. voicey-0.0.0.dev0/tests/unit/test_tools.py +495 -0
  471. voicey-0.0.0.dev0/tests/unit/test_tunnel.py +345 -0
  472. voicey-0.0.0.dev0/tests/unit/test_upgrade.py +581 -0
  473. voicey-0.0.0.dev0/tests/unit/test_version.py +5 -0
  474. voicey-0.0.0.dev0/tests/unit/test_versioning.py +92 -0
  475. voicey-0.0.0.dev0/tests/unit/test_vobiz_pipecat_host.py +315 -0
  476. voicey-0.0.0.dev0/tests/verification/__init__.py +1 -0
  477. voicey-0.0.0.dev0/tests/verification/canary_recipes.py +119 -0
  478. voicey-0.0.0.dev0/tests/verification/docs_quickstarts.py +122 -0
  479. voicey-0.0.0.dev0/tests/verification/docs_quickstarts_inner.py +198 -0
  480. voicey-0.0.0.dev0/tests/verification/p1_latency_gate.py +208 -0
  481. voicey-0.0.0.dev0/tests/verification/p1_quickstart.py +84 -0
  482. voicey-0.0.0.dev0/tests/verification/p1_quickstart_inner.py +161 -0
  483. voicey-0.0.0.dev0/tests/verification/p4_soak.py +85 -0
  484. voicey-0.0.0.dev0/tests/verification/run_p1_gate.py +300 -0
  485. voicey-0.0.0.dev0/tests/verification/run_p2_gate.py +207 -0
  486. voicey-0.0.0.dev0/tests/verification/run_p3_gate.py +272 -0
  487. voicey-0.0.0.dev0/tests/verification/run_p4_docs_gate.py +132 -0
  488. voicey-0.0.0.dev0/tests/verification/run_p4_gate.py +273 -0
  489. voicey-0.0.0.dev0/tests/verification/run_p4_hardening_gate.py +218 -0
  490. voicey-0.0.0.dev0/tests/verification/run_p4_observability_gate.py +239 -0
  491. voicey-0.0.0.dev0/tests/verification/run_p4_railway_gate.py +225 -0
  492. voicey-0.0.0.dev0/tests/verification/run_p4_release_gate.py +229 -0
  493. voicey-0.0.0.dev0/tests/verification/run_p4_security_gate.py +594 -0
  494. voicey-0.0.0.dev0/tests/verification/run_p4_upgrade_gate.py +306 -0
  495. voicey-0.0.0.dev0/tests/verification/test_p1_cli_matrix.py +96 -0
  496. voicey-0.0.0.dev0/tests/verification/test_p1_latency_gate.py +63 -0
  497. voicey-0.0.0.dev0/tests/verification/test_p4_soak.py +108 -0
  498. voicey-0.0.0.dev0/uv.lock +4924 -0
@@ -0,0 +1,5 @@
1
+ [run]
2
+ branch = True
3
+
4
+ [report]
5
+ show_missing = True
@@ -0,0 +1,15 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ indent_style = space
8
+ indent_size = 2
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.py]
12
+ indent_size = 4
13
+
14
+ [Makefile]
15
+ indent_style = tab
@@ -0,0 +1 @@
1
+ src/voicey/_frontend/** linguist-generated=true -diff -whitespace
@@ -0,0 +1,3 @@
1
+ self-hosted-runner:
2
+ labels:
3
+ - voicey-soak
@@ -0,0 +1,13 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ groups:
8
+ python:
9
+ patterns: ["*"]
10
+ - package-ecosystem: github-actions
11
+ directory: /
12
+ schedule:
13
+ interval: weekly
@@ -0,0 +1,393 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ playground:
13
+ name: Playground web
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: actions/setup-node@v4
18
+ with:
19
+ node-version: "22"
20
+ cache: npm
21
+ cache-dependency-path: playground-web/package-lock.json
22
+ - name: Install locked web dependencies
23
+ working-directory: playground-web
24
+ run: npm ci --ignore-scripts
25
+ - name: Typecheck playground
26
+ working-directory: playground-web
27
+ run: npm run typecheck
28
+ - name: Test playground
29
+ working-directory: playground-web
30
+ run: npm test
31
+ - name: Build playground
32
+ working-directory: playground-web
33
+ run: npm run build
34
+ - name: Audit playground dependencies
35
+ working-directory: playground-web
36
+ run: npm audit --audit-level=high
37
+
38
+ quality:
39
+ name: Python ${{ matrix.python }}
40
+ runs-on: ubuntu-latest
41
+ strategy:
42
+ fail-fast: false
43
+ matrix:
44
+ python: ["3.11", "3.12", "3.13", "3.14"]
45
+ steps:
46
+ - uses: actions/checkout@v4
47
+ - uses: actions/setup-python@v6
48
+ with:
49
+ python-version: ${{ matrix.python }}
50
+ - name: Install uv
51
+ run: python -m pip install uv==0.11.7
52
+ - name: Sync locked environment
53
+ run: uv sync --frozen --extra pipecat --extra livekit --extra twilio --extra cloud
54
+ - name: Lint
55
+ run: uv run ruff check .
56
+ - name: Format
57
+ run: uv run ruff format --check .
58
+ - name: Typecheck
59
+ run: uv run pyright
60
+ - name: Unit tests
61
+ run: uv run pytest -m "not integration and not live and not slow"
62
+
63
+ public-contract:
64
+ name: Public API snapshots and docs
65
+ runs-on: ubuntu-latest
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ with:
69
+ fetch-depth: 0
70
+ - uses: actions/setup-python@v6
71
+ with:
72
+ python-version: "3.11"
73
+ - name: Install uv
74
+ run: python -m pip install uv==0.11.7
75
+ - name: Sync locked environment
76
+ run: uv sync --frozen --extra pipecat --extra livekit
77
+ - name: Reject uncommitted public API drift
78
+ run: |
79
+ uv run python scripts/update_public_snapshots.py --check
80
+ uv run python scripts/update_api_reference.py --check
81
+ - name: Require release notes and docs for public changes
82
+ if: github.event_name == 'pull_request'
83
+ run: |
84
+ uv run python scripts/check_public_surface_docs.py \
85
+ --base "origin/${{ github.base_ref }}"
86
+
87
+ integration-edges:
88
+ name: Integration Python ${{ matrix.python }}
89
+ runs-on: ubuntu-latest
90
+ strategy:
91
+ fail-fast: false
92
+ matrix:
93
+ python: ["3.11", "3.14"]
94
+ steps:
95
+ - uses: actions/checkout@v4
96
+ - uses: actions/setup-python@v6
97
+ with:
98
+ python-version: ${{ matrix.python }}
99
+ - name: Install uv
100
+ run: python -m pip install uv==0.11.7
101
+ - name: Sync locked environment
102
+ run: uv sync --frozen --extra pipecat --extra livekit --extra twilio --extra cloud
103
+ - name: Mocked integration tests
104
+ run: uv run pytest -m integration --no-cov
105
+ - name: Unified native scenario compiler gate
106
+ run: |
107
+ uv run pytest --no-cov \
108
+ tests/unit/test_testing.py \
109
+ tests/unit/test_recipe_appointment.py
110
+
111
+ managed-storage:
112
+ name: Managed storage / Postgres 17
113
+ runs-on: ubuntu-latest
114
+ services:
115
+ postgres:
116
+ image: postgres:17-alpine
117
+ env:
118
+ POSTGRES_USER: voicey
119
+ POSTGRES_PASSWORD: voicey-test # pragma: allowlist secret
120
+ POSTGRES_DB: voicey
121
+ ports:
122
+ - 5432:5432
123
+ options: >-
124
+ --health-cmd "pg_isready -U voicey -d voicey"
125
+ --health-interval 5s
126
+ --health-timeout 5s
127
+ --health-retries 12
128
+ env:
129
+ VOICEY_TEST_POSTGRES_DSN: postgresql://voicey:voicey-test@127.0.0.1:5432/voicey # pragma: allowlist secret
130
+ steps:
131
+ - uses: actions/checkout@v4
132
+ - uses: actions/setup-python@v6
133
+ with:
134
+ python-version: "3.11"
135
+ - name: Install uv
136
+ run: python -m pip install uv==0.11.7
137
+ - name: Sync locked managed-backend environment
138
+ run: uv sync --frozen --extra companion
139
+ - name: Managed backend and results-service strict coverage
140
+ run: |
141
+ uv run pytest -q -o addopts='' \
142
+ --strict-config --strict-markers \
143
+ --cov=voicey.deploy.managed \
144
+ --cov=voicey.deploy.results_service \
145
+ --cov=voicey.storage.postgres \
146
+ --cov=voicey.relay.postgres \
147
+ --cov=voicey.storage.s3 \
148
+ --cov-config=.coveragerc-managed \
149
+ --cov-branch \
150
+ --cov-report=term-missing \
151
+ --cov-fail-under=90 \
152
+ tests/unit/test_results_service_runtime.py \
153
+ tests/integration/test_managed_results_service.py \
154
+ tests/integration/test_postgres_repository.py \
155
+ tests/integration/test_repository_backends.py \
156
+ tests/unit/test_s3_artifacts.py
157
+
158
+ p1-gate:
159
+ name: P1 local phase gate
160
+ runs-on: ubuntu-latest
161
+ steps:
162
+ - uses: actions/checkout@v4
163
+ - uses: actions/setup-python@v6
164
+ with:
165
+ python-version: "3.11"
166
+ - uses: actions/setup-node@v4
167
+ with:
168
+ node-version: "22"
169
+ cache: npm
170
+ cache-dependency-path: playground-web/package-lock.json
171
+ - name: Install uv
172
+ run: python -m pip install uv==0.11.7
173
+ - name: Sync locked gate environment
174
+ run: uv sync --frozen --extra pipecat --extra livekit --extra twilio
175
+ - name: Build release-shaped wheel
176
+ run: uv build --wheel --out-dir dist
177
+ - name: Run local P1 phase gate
178
+ run: |
179
+ uv run python tests/verification/run_p1_gate.py \
180
+ --wheel dist/voicey-0.0.0.dev0-py3-none-any.whl \
181
+ --report p1-gate-report.json
182
+ - name: Upload truthful phase report
183
+ if: always()
184
+ uses: actions/upload-artifact@v4
185
+ with:
186
+ name: p1-gate-report
187
+ path: p1-gate-report.json
188
+ if-no-files-found: error
189
+
190
+ p2-gate:
191
+ name: P2 local phase gate
192
+ runs-on: ubuntu-latest
193
+ steps:
194
+ - uses: actions/checkout@v4
195
+ - uses: actions/setup-python@v6
196
+ with:
197
+ python-version: "3.11"
198
+ - uses: actions/setup-node@v4
199
+ with:
200
+ node-version: "22"
201
+ cache: npm
202
+ cache-dependency-path: playground-web/package-lock.json
203
+ - name: Install uv
204
+ run: python -m pip install uv==0.11.7
205
+ - name: Sync locked gate environment
206
+ run: uv sync --frozen --extra pipecat --extra livekit --extra twilio --extra telnyx
207
+ - name: Build release-shaped wheel
208
+ run: uv build --wheel --out-dir dist
209
+ - name: Run local P2 phase gate
210
+ run: |
211
+ uv run python tests/verification/run_p2_gate.py \
212
+ --wheel dist/voicey-0.0.0.dev0-py3-none-any.whl \
213
+ --report p2-gate-report.json
214
+ - name: Upload truthful phase reports
215
+ if: always()
216
+ uses: actions/upload-artifact@v4
217
+ with:
218
+ name: p2-gate-reports
219
+ path: |
220
+ p2-gate-report.json
221
+ p1-from-p2-report.json
222
+ if-no-files-found: error
223
+
224
+ p3-gate:
225
+ name: P3 local phase gate
226
+ runs-on: ubuntu-latest
227
+ services:
228
+ postgres:
229
+ image: postgres:17-alpine
230
+ env:
231
+ POSTGRES_USER: voicey
232
+ POSTGRES_PASSWORD: voicey-test # pragma: allowlist secret
233
+ POSTGRES_DB: voicey
234
+ ports:
235
+ - 5432:5432
236
+ options: >-
237
+ --health-cmd "pg_isready -U voicey -d voicey"
238
+ --health-interval 5s
239
+ --health-timeout 5s
240
+ --health-retries 12
241
+ env:
242
+ VOICEY_TEST_POSTGRES_DSN: postgresql://voicey:voicey-test@127.0.0.1:5432/voicey # pragma: allowlist secret
243
+ steps:
244
+ - uses: actions/checkout@v4
245
+ - uses: actions/setup-python@v6
246
+ with:
247
+ python-version: "3.11"
248
+ - uses: actions/setup-node@v4
249
+ with:
250
+ node-version: "22"
251
+ cache: npm
252
+ cache-dependency-path: playground-web/package-lock.json
253
+ - name: Install uv
254
+ run: python -m pip install uv==0.11.7
255
+ - name: Sync complete locked P3 environment
256
+ run: |
257
+ uv sync --frozen \
258
+ --extra pipecat \
259
+ --extra livekit \
260
+ --extra twilio \
261
+ --extra telnyx \
262
+ --extra vobiz \
263
+ --extra plivo \
264
+ --extra tunnel \
265
+ --extra cloud \
266
+ --extra companion
267
+ - name: Build release-shaped wheel
268
+ run: uv build --wheel --out-dir dist
269
+ - name: Run local P3 phase gate
270
+ run: |
271
+ uv run python tests/verification/run_p3_gate.py \
272
+ --wheel dist/voicey-0.0.0.dev0-py3-none-any.whl \
273
+ --report p3-gate-report.json
274
+ - name: Upload truthful phase reports
275
+ if: always()
276
+ uses: actions/upload-artifact@v4
277
+ with:
278
+ name: p3-gate-reports
279
+ path: |
280
+ p3-gate-report.json
281
+ p2-from-p3-report.json
282
+ if-no-files-found: error
283
+
284
+ p4-hardening:
285
+ name: P4 hardening / observability / Railway
286
+ runs-on: ubuntu-latest
287
+ services:
288
+ postgres:
289
+ image: postgres:17-alpine
290
+ env:
291
+ POSTGRES_USER: voicey
292
+ POSTGRES_PASSWORD: voicey-test # pragma: allowlist secret
293
+ POSTGRES_DB: voicey
294
+ ports:
295
+ - 5432:5432
296
+ options: >-
297
+ --health-cmd "pg_isready -U voicey -d voicey"
298
+ --health-interval 5s
299
+ --health-timeout 5s
300
+ --health-retries 12
301
+ env:
302
+ VOICEY_TEST_POSTGRES_DSN: postgresql://voicey:voicey-test@127.0.0.1:5432/voicey # pragma: allowlist secret
303
+ steps:
304
+ - uses: actions/checkout@v4
305
+ - uses: actions/setup-python@v6
306
+ with:
307
+ python-version: "3.11"
308
+ - uses: actions/setup-node@v4
309
+ with:
310
+ node-version: "22"
311
+ - name: Install uv
312
+ run: python -m pip install uv==0.11.7
313
+ - name: Sync complete hardening environment
314
+ run: |
315
+ uv sync --frozen \
316
+ --extra pipecat \
317
+ --extra livekit \
318
+ --extra twilio \
319
+ --extra cloud \
320
+ --extra companion
321
+ - name: Run chaos, drain, and bounded soak gates
322
+ run: |
323
+ uv run python tests/verification/run_p4_hardening_gate.py \
324
+ --short-soak-s 30 \
325
+ --max-concurrent 8 \
326
+ --report p4-hardening-report.json
327
+ - name: Run Prometheus and actual OTLP HTTP gate
328
+ run: |
329
+ uv run python tests/verification/run_p4_observability_gate.py \
330
+ --report p4-observability-report.json
331
+ - name: Run Railway CLI, artifact, and managed-storage gate
332
+ run: |
333
+ uv run python tests/verification/run_p4_railway_gate.py \
334
+ --report p4-railway-report.json
335
+ - name: Run safe upgrade and recipe-drift gate
336
+ run: |
337
+ uv run python tests/verification/run_p4_upgrade_gate.py \
338
+ --report p4-upgrade-report.json
339
+ - name: Build and validate the local canary artifact
340
+ run: |
341
+ uv build --wheel --out-dir dist
342
+ uv run python tests/verification/run_p4_release_gate.py \
343
+ --wheel dist/voicey-0.0.0.dev0-py3-none-any.whl \
344
+ --channel canary \
345
+ --report p4-release-report.json
346
+ - name: Run source-derived docs and fresh-wheel quickstarts
347
+ run: |
348
+ uv run python tests/verification/run_p4_docs_gate.py \
349
+ --wheel dist/voicey-0.0.0.dev0-py3-none-any.whl \
350
+ --report p4-docs-report.json
351
+ - name: Upload truthful hardening reports
352
+ if: always()
353
+ uses: actions/upload-artifact@v4
354
+ with:
355
+ name: p4-hardening-reports
356
+ path: |
357
+ p4-hardening-report.json
358
+ p4-short-soak-report.json
359
+ p4-observability-report.json
360
+ p4-railway-report.json
361
+ p4-upgrade-report.json
362
+ p4-release-report.json
363
+ p4-docs-report.json
364
+ p4-docs-quickstarts.json
365
+ if-no-files-found: error
366
+
367
+ webhook-interop:
368
+ name: Standard Webhooks interop
369
+ runs-on: ubuntu-latest
370
+ steps:
371
+ - uses: actions/checkout@v4
372
+ - uses: actions/setup-node@v4
373
+ with:
374
+ node-version: "22"
375
+ - uses: actions/setup-go@v6
376
+ with:
377
+ go-version: "1.25"
378
+ - name: Install official JavaScript verifier
379
+ run: npm install --prefix "$RUNNER_TEMP/webhook-node" --ignore-scripts standardwebhooks@1.0.0
380
+ - name: Verify JavaScript vector
381
+ run: node tests/interop/verify_node.mjs tests/interop/standard_webhooks_vector.json "$RUNNER_TEMP/webhook-node"
382
+ - name: Clone pinned official Go verifier
383
+ run: git clone https://github.com/standard-webhooks/standard-webhooks.git "$RUNNER_TEMP/standard-webhooks"
384
+ - name: Pin official Go verifier commit
385
+ run: git -C "$RUNNER_TEMP/standard-webhooks" checkout 01d6eb75702229a0927c07d52fda7223e201c03d
386
+ - name: Install voicey vector test
387
+ run: cp tests/interop/voicey_vector_test.go "$RUNNER_TEMP/standard-webhooks/libraries/go/"
388
+ - name: Verify Go vector
389
+ working-directory: ${{ runner.temp }}/standard-webhooks/libraries/go
390
+ env:
391
+ GO111MODULE: "off"
392
+ VOICEY_VECTOR_PATH: ${{ github.workspace }}/tests/interop/standard_webhooks_vector.json
393
+ run: go test webhook.go voicey_vector_test.go
@@ -0,0 +1,88 @@
1
+ name: Paid PSTN loopback
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ - cron: "41 4 * * *"
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: paid-pstn-loopback
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ pipecat-twilio:
17
+ if: ${{ vars.VOICEY_LIVE_PSTN_ENABLED == 'true' }}
18
+ environment: paid-pstn
19
+ runs-on: ubuntu-latest
20
+ timeout-minutes: 20
21
+ env:
22
+ VOICEY_LIVE_PSTN_ACK: ${{ vars.VOICEY_LIVE_PSTN_ACK }}
23
+ VOICEY_LIVE_PSTN_MAX_CALLS: "4"
24
+ VOICEY_LIVE_TARGET_NUMBER: ${{ secrets.VOICEY_LIVE_TARGET_NUMBER }}
25
+ VOICEY_LIVE_TWILIO_FROM: ${{ secrets.VOICEY_LIVE_TWILIO_FROM }}
26
+ TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
27
+ TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
28
+ NGROK_AUTHTOKEN: ${{ secrets.NGROK_AUTHTOKEN }}
29
+ DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
30
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
31
+ CARTESIA_API_KEY: ${{ secrets.CARTESIA_API_KEY }}
32
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ - uses: actions/setup-python@v6
36
+ with:
37
+ python-version: "3.11"
38
+ - name: Install uv
39
+ run: python -m pip install uv==0.11.7
40
+ - name: Sync locked live-caller dependencies
41
+ run: uv sync --frozen --extra pipecat --extra twilio --extra tunnel
42
+ - name: Run acknowledged Pipecat → Twilio → PSTN loopback
43
+ working-directory: tests/fixtures/live-pstn-pipecat
44
+ run: ../../../.venv/bin/voicey test --live --report junit
45
+ - name: Upload secret-free carrier evidence
46
+ if: always()
47
+ uses: actions/upload-artifact@v4
48
+ with:
49
+ name: pipecat-twilio-pstn-junit
50
+ path: tests/fixtures/live-pstn-pipecat/.voicey/test-results.xml
51
+ if-no-files-found: warn
52
+
53
+ livekit-sip:
54
+ if: ${{ vars.VOICEY_LIVE_PSTN_ENABLED == 'true' }}
55
+ environment: paid-pstn
56
+ runs-on: ubuntu-latest
57
+ timeout-minutes: 20
58
+ env:
59
+ VOICEY_LIVE_PSTN_ACK: ${{ vars.VOICEY_LIVE_PSTN_ACK }}
60
+ VOICEY_LIVE_PSTN_MAX_CALLS: "4"
61
+ VOICEY_LIVE_TARGET_NUMBER: ${{ secrets.VOICEY_LIVE_TARGET_NUMBER }}
62
+ VOICEY_LIVEKIT_OUTBOUND_TRUNK_ID: ${{ secrets.VOICEY_LIVEKIT_OUTBOUND_TRUNK_ID }}
63
+ LIVEKIT_URL: ${{ secrets.LIVEKIT_URL }}
64
+ LIVEKIT_API_KEY: ${{ secrets.LIVEKIT_API_KEY }}
65
+ LIVEKIT_API_SECRET: ${{ secrets.LIVEKIT_API_SECRET }}
66
+ DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
67
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
68
+ CARTESIA_API_KEY: ${{ secrets.CARTESIA_API_KEY }}
69
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+ - uses: actions/setup-python@v6
73
+ with:
74
+ python-version: "3.11"
75
+ - name: Install uv
76
+ run: python -m pip install uv==0.11.7
77
+ - name: Sync locked live-caller dependencies
78
+ run: uv sync --frozen --extra livekit
79
+ - name: Run acknowledged LiveKit SIP → PSTN loopback
80
+ working-directory: tests/fixtures/live-pstn-livekit
81
+ run: ../../../.venv/bin/voicey test --live --report junit
82
+ - name: Upload secret-free carrier evidence
83
+ if: always()
84
+ uses: actions/upload-artifact@v4
85
+ with:
86
+ name: livekit-sip-pstn-junit
87
+ path: tests/fixtures/live-pstn-livekit/.voicey/test-results.xml
88
+ if-no-files-found: warn
@@ -0,0 +1,75 @@
1
+ name: P4 Aggregate
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ local-aggregate:
13
+ name: Complete credential-free P0-P4 regression
14
+ runs-on: ubuntu-latest
15
+ services:
16
+ postgres:
17
+ image: postgres:17-alpine
18
+ env:
19
+ POSTGRES_USER: voicey
20
+ POSTGRES_PASSWORD: voicey-test # pragma: allowlist secret
21
+ POSTGRES_DB: voicey
22
+ ports:
23
+ - 5432:5432
24
+ options: >-
25
+ --health-cmd "pg_isready -U voicey -d voicey"
26
+ --health-interval 5s
27
+ --health-timeout 5s
28
+ --health-retries 12
29
+ env:
30
+ VOICEY_TEST_POSTGRES_DSN: postgresql://voicey:voicey-test@127.0.0.1:5432/voicey # pragma: allowlist secret
31
+ steps:
32
+ - uses: actions/checkout@v4
33
+ with:
34
+ fetch-depth: 0
35
+ - uses: actions/setup-python@v6
36
+ with:
37
+ python-version: "3.11"
38
+ - uses: actions/setup-node@v4
39
+ with:
40
+ node-version: "22"
41
+ - name: Install uv
42
+ run: python -m pip install uv==0.11.7
43
+ - name: Sync complete locked environment
44
+ run: uv sync --frozen --all-extras
45
+ - name: Install pinned Trivy
46
+ uses: aquasecurity/setup-trivy@e07451d2e059ed86c2870430ea286b3a9e0bf241
47
+ with:
48
+ version: v0.72.0
49
+ - name: Build release-shaped wheel
50
+ run: uv build --wheel --out-dir dist
51
+ - name: Run truthful aggregate
52
+ run: |
53
+ uv run python tests/verification/run_p4_gate.py \
54
+ --wheel dist/voicey-0.0.0.dev0-py3-none-any.whl \
55
+ --short-soak-s 30 \
56
+ --max-concurrent 8 \
57
+ --report p4-gate-report.json
58
+ - name: Upload every child report
59
+ if: always()
60
+ uses: actions/upload-artifact@v4
61
+ with:
62
+ name: p4-aggregate-reports
63
+ path: |
64
+ p4-gate-report.json
65
+ p3-from-p4-report.json
66
+ p4-hardening-report.json
67
+ p4-short-soak-report.json
68
+ p4-observability-report.json
69
+ p4-railway-report.json
70
+ p4-upgrade-report.json
71
+ p4-release-report.json
72
+ p4-docs-report.json
73
+ p4-docs-quickstarts.json
74
+ p4-security-report.json
75
+ if-no-files-found: warn
@@ -0,0 +1,81 @@
1
+ name: Prepare release artifacts
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ channel:
7
+ description: "Artifact channel; stable requires a prior green canary run"
8
+ required: true
9
+ type: choice
10
+ options:
11
+ - canary
12
+ - stable
13
+ ref:
14
+ description: "Exact tag, branch, or commit to build"
15
+ required: true
16
+ type: string
17
+ canary_run_id:
18
+ description: "Required for stable: workflow run id containing canary evidence"
19
+ required: false
20
+ type: string
21
+
22
+ permissions:
23
+ contents: read
24
+ actions: read
25
+
26
+ jobs:
27
+ prepare:
28
+ runs-on: ubuntu-latest
29
+ steps:
30
+ - uses: actions/checkout@v4
31
+ with:
32
+ ref: ${{ inputs.ref }}
33
+ fetch-depth: 0
34
+ - uses: actions/setup-python@v6
35
+ with:
36
+ python-version: "3.11"
37
+ - name: Install uv
38
+ run: python -m pip install uv==0.11.7
39
+ - name: Sync locked release environment
40
+ run: uv sync --frozen --extra pipecat --extra livekit
41
+ - name: Build wheel and source distribution
42
+ run: uv build --out-dir dist
43
+ - name: Resolve the one wheel
44
+ id: artifact
45
+ run: |
46
+ wheel_count="$(find dist -maxdepth 1 -name '*.whl' -type f | wc -l | tr -d ' ')"
47
+ test "$wheel_count" = "1"
48
+ echo "wheel=$(find dist -maxdepth 1 -name '*.whl' -type f)" >> "$GITHUB_OUTPUT"
49
+ - name: Download prior canary evidence
50
+ if: inputs.channel == 'stable'
51
+ uses: actions/download-artifact@v4
52
+ with:
53
+ pattern: voicey-canary-*
54
+ path: canary-evidence
55
+ merge-multiple: true
56
+ run-id: ${{ inputs.canary_run_id }}
57
+ github-token: ${{ github.token }}
58
+ - name: Validate canary artifact
59
+ if: inputs.channel == 'canary'
60
+ run: |
61
+ uv run python tests/verification/run_p4_release_gate.py \
62
+ --wheel "${{ steps.artifact.outputs.wheel }}" \
63
+ --channel canary \
64
+ --report p4-release-report.json
65
+ - name: Validate stable promotion against canary evidence
66
+ if: inputs.channel == 'stable'
67
+ run: |
68
+ test -n "${{ inputs.canary_run_id }}"
69
+ uv run python tests/verification/run_p4_release_gate.py \
70
+ --wheel "${{ steps.artifact.outputs.wheel }}" \
71
+ --channel stable \
72
+ --canary-report canary-evidence/p4-release-report.json \
73
+ --report p4-release-report.json
74
+ - name: Upload verified artifacts without publishing
75
+ uses: actions/upload-artifact@v4
76
+ with:
77
+ name: voicey-${{ inputs.channel }}-${{ github.run_id }}
78
+ path: |
79
+ dist/*
80
+ p4-release-report.json
81
+ if-no-files-found: error