simcord 3.2.0__tar.gz → 3.2.1__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 (419) hide show
  1. {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/verify.yml +6 -0
  2. {simcord-3.2.0 → simcord-3.2.1}/.gitignore +3 -0
  3. {simcord-3.2.0 → simcord-3.2.1}/CHANGELOG.md +19 -0
  4. {simcord-3.2.0 → simcord-3.2.1}/CONTRIBUTING.md +28 -2
  5. {simcord-3.2.0 → simcord-3.2.1}/PKG-INFO +1 -1
  6. {simcord-3.2.0 → simcord-3.2.1}/docs/architecture.md +36 -8
  7. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/monetization.md +24 -0
  8. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/permissions.md +6 -2
  9. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/preview.md +55 -10
  10. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/time-control.md +28 -0
  11. simcord-3.2.1/jsconfig.preview.json +17 -0
  12. simcord-3.2.1/package-lock.json +27 -0
  13. simcord-3.2.1/package.json +11 -0
  14. {simcord-3.2.0 → simcord-3.2.1}/pyproject.toml +1 -1
  15. {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_monetization_reference.py +428 -416
  16. {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_remaining_monetization.py +524 -390
  17. {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_visual_reference.py +20 -29
  18. {simcord-3.2.0 → simcord-3.2.1}/scripts/check_package.py +13 -0
  19. {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_checkout.py +37 -22
  20. simcord-3.2.1/scripts/monetization_reference_config.py +189 -0
  21. {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_expiry.py +10 -0
  22. simcord-3.2.1/scripts/monetization_reference_journal.py +154 -0
  23. {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_lifecycle.py +127 -114
  24. simcord-3.2.1/scripts/monetization_reference_transport.py +198 -0
  25. {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_upgrade.py +196 -172
  26. {simcord-3.2.0 → simcord-3.2.1}/scripts/replay_visual_reference.py +339 -320
  27. {simcord-3.2.0 → simcord-3.2.1}/scripts/validate_monetization_reference.py +404 -183
  28. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_dpy_internals.py +51 -2
  29. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_modal.py +7 -2
  30. simcord-3.2.1/src/simcord/_runtime.py +558 -0
  31. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_settlement.py +62 -39
  32. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/actors.py +61 -11
  33. simcord-3.2.1/src/simcord/backend/access.py +105 -0
  34. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/base.py +17 -3
  35. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/channels.py +70 -1
  36. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/guilds.py +49 -7
  37. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/invites.py +15 -0
  38. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/messages.py +61 -6
  39. simcord-3.2.1/src/simcord/backend/ops/voice.py +78 -0
  40. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/builders.py +79 -18
  41. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/env.py +186 -142
  42. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/_helpers.py +12 -16
  43. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/client.py +3 -6
  44. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/router.py +12 -2
  45. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/application.py +1 -2
  46. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/channels.py +42 -30
  47. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/guilds.py +23 -25
  48. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/messages.py +19 -8
  49. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/reactions.py +19 -5
  50. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/interactions.py +30 -8
  51. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/__init__.py +3 -0
  52. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_action_plans.py +24 -0
  53. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_actions.py +84 -44
  54. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_assets.py +36 -18
  55. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_capture.py +9 -43
  56. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_commands.py +34 -4
  57. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_component_projection.py +119 -5
  58. simcord-3.2.1/src/simcord/preview/_dependencies.py +90 -0
  59. simcord-3.2.1/src/simcord/preview/_diagnostics.py +69 -0
  60. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_messages.py +102 -6
  61. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_pages.py +137 -8
  62. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_queries.py +118 -13
  63. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_server.py +60 -8
  64. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_snapshot.py +9 -2
  65. simcord-3.2.1/src/simcord/preview/static/actions.js +264 -0
  66. simcord-3.2.1/src/simcord/preview/static/app.js +883 -0
  67. simcord-3.2.1/src/simcord/preview/static/assets.js +107 -0
  68. simcord-3.2.1/src/simcord/preview/static/backend-diagnostics.json +219 -0
  69. simcord-3.2.1/src/simcord/preview/static/command-catalog.js +60 -0
  70. simcord-3.2.1/src/simcord/preview/static/command-drafts.js +62 -0
  71. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/commands.js +348 -261
  72. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/components.js +103 -34
  73. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/composer.js +87 -15
  74. simcord-3.2.1/src/simcord/preview/static/connection.js +73 -0
  75. simcord-3.2.1/src/simcord/preview/static/diagnostics.js +205 -0
  76. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/dom.js +23 -2
  77. simcord-3.2.1/src/simcord/preview/static/focus.js +69 -0
  78. simcord-3.2.1/src/simcord/preview/static/geometry.js +78 -0
  79. simcord-3.2.1/src/simcord/preview/static/highlight-types.d.ts +26 -0
  80. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/listbox.js +11 -1
  81. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/media.js +121 -50
  82. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/messages.js +35 -11
  83. simcord-3.2.1/src/simcord/preview/static/modal.js +199 -0
  84. simcord-3.2.1/src/simcord/preview/static/presentation.js +299 -0
  85. simcord-3.2.1/src/simcord/preview/static/preview-types.d.ts +262 -0
  86. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/preview.css +13 -26
  87. simcord-3.2.1/src/simcord/preview/static/select-drafts.js +465 -0
  88. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/selects.js +35 -12
  89. simcord-3.2.1/src/simcord/preview/static/session.js +116 -0
  90. simcord-3.2.1/src/simcord/preview/static/surfaces.js +153 -0
  91. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/text.js +30 -3
  92. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/timeline.js +85 -11
  93. simcord-3.2.1/src/simcord/preview/static/transport.js +50 -0
  94. simcord-3.2.1/src/simcord/preview/static/workbench.js +398 -0
  95. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/results.py +5 -0
  96. simcord-3.2.1/tests/integration/test_access_boundaries.py +385 -0
  97. simcord-3.2.1/tests/integration/test_atomic_mutations.py +265 -0
  98. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_command_visibility.py +38 -15
  99. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_components_v2_interactions.py +70 -7
  100. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_forum.py +69 -0
  101. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_forwarding.py +143 -0
  102. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_interactions.py +75 -0
  103. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview.py +21 -0
  104. simcord-3.2.1/tests/integration/test_preview_action_admission.py +254 -0
  105. simcord-3.2.1/tests/integration/test_preview_additional.py +535 -0
  106. simcord-3.2.1/tests/integration/test_preview_browser_ownership.py +808 -0
  107. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_capture.py +42 -0
  108. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_capture_dx.py +17 -187
  109. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_channel.py +24 -170
  110. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_command_picker.py +334 -114
  111. simcord-3.2.1/tests/integration/test_preview_components_v2.py +185 -0
  112. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_dx.py +8 -160
  113. simcord-3.2.1/tests/integration/test_preview_entity_contracts.py +451 -0
  114. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_fixes.py +72 -251
  115. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_message_actions.py +29 -5
  116. simcord-3.2.1/tests/integration/test_preview_modal_contracts.py +342 -0
  117. simcord-3.2.1/tests/integration/test_preview_navigation_contracts.py +198 -0
  118. simcord-3.2.1/tests/integration/test_preview_observations.py +283 -0
  119. simcord-3.2.1/tests/integration/test_preview_provenance.py +295 -0
  120. simcord-3.2.1/tests/integration/test_preview_render_contracts.py +54 -0
  121. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_security.py +0 -292
  122. simcord-3.2.1/tests/integration/test_preview_support_report.py +304 -0
  123. simcord-3.2.1/tests/integration/test_preview_viewport_ownership.py +168 -0
  124. simcord-3.2.1/tests/integration/test_preview_workbench_contracts.py +190 -0
  125. simcord-3.2.1/tests/integration/test_reference_replay.py +215 -0
  126. simcord-3.2.1/tests/integration/test_runtime_executor_ownership.py +944 -0
  127. simcord-3.2.1/tests/integration/test_sdk_compatibility.py +47 -0
  128. simcord-3.2.1/tests/integration/test_visual_reference_geometry.py +139 -0
  129. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_dpy_internals.py +70 -41
  130. simcord-3.2.1/tests/unit/test_monetization_reference_capture.py +132 -0
  131. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_checkout.py +26 -5
  132. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_expiry.py +19 -3
  133. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_lifecycle.py +1 -1
  134. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_upgrade.py +37 -5
  135. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_validation.py +149 -0
  136. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_preview_action_specs.py +1 -12
  137. simcord-3.2.1/tests/unit/test_remaining_monetization_capture.py +756 -0
  138. {simcord-3.2.0 → simcord-3.2.1}/uv.lock +1 -1
  139. simcord-3.2.0/src/simcord/_runtime.py +0 -341
  140. simcord-3.2.0/src/simcord/backend/access.py +0 -77
  141. simcord-3.2.0/src/simcord/backend/ops/voice.py +0 -40
  142. simcord-3.2.0/src/simcord/preview/_diagnostics.py +0 -284
  143. simcord-3.2.0/src/simcord/preview/static/app.js +0 -2280
  144. simcord-3.2.0/src/simcord/preview/static/select-drafts.js +0 -284
  145. simcord-3.2.0/src/simcord/preview/static/transport.js +0 -167
  146. simcord-3.2.0/src/simcord/preview/static/workbench.js +0 -130
  147. simcord-3.2.0/tests/integration/test_preview_additional.py +0 -1208
  148. simcord-3.2.0/tests/integration/test_reference_replay.py +0 -96
  149. simcord-3.2.0/tests/unit/test_remaining_monetization_capture.py +0 -367
  150. {simcord-3.2.0 → simcord-3.2.1}/.github/ISSUE_TEMPLATE/bug.md +0 -0
  151. {simcord-3.2.0 → simcord-3.2.1}/.github/ISSUE_TEMPLATE/feature.md +0 -0
  152. {simcord-3.2.0 → simcord-3.2.1}/.github/ISSUE_TEMPLATE/parity-gap.md +0 -0
  153. {simcord-3.2.0 → simcord-3.2.1}/.github/dependabot.yml +0 -0
  154. {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/ci.yml +0 -0
  155. {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/dpy-master.yml +0 -0
  156. {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/release.yml +0 -0
  157. {simcord-3.2.0 → simcord-3.2.1}/.pre-commit-config.yaml +0 -0
  158. {simcord-3.2.0 → simcord-3.2.1}/.python-version +0 -0
  159. {simcord-3.2.0 → simcord-3.2.1}/.readthedocs.yaml +0 -0
  160. {simcord-3.2.0 → simcord-3.2.1}/CODE_OF_CONDUCT.md +0 -0
  161. {simcord-3.2.0 → simcord-3.2.1}/LICENSE +0 -0
  162. {simcord-3.2.0 → simcord-3.2.1}/README.md +0 -0
  163. {simcord-3.2.0 → simcord-3.2.1}/SECURITY.md +0 -0
  164. {simcord-3.2.0 → simcord-3.2.1}/benchmarks/_helpers.py +0 -0
  165. {simcord-3.2.0 → simcord-3.2.1}/benchmarks/test_dispatch_benchmarks.py +0 -0
  166. {simcord-3.2.0 → simcord-3.2.1}/benchmarks/test_perf_guards.py +0 -0
  167. {simcord-3.2.0 → simcord-3.2.1}/changes/README.md +0 -0
  168. {simcord-3.2.0 → simcord-3.2.1}/docs/api.md +0 -0
  169. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/adventure/alpine.png +0 -0
  170. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/adventure/canyon.png +0 -0
  171. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/attachments.png +0 -0
  172. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/buttons.png +0 -0
  173. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/embeds.png +0 -0
  174. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/entities.png +0 -0
  175. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/layouts.png +0 -0
  176. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/markdown.png +0 -0
  177. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/modals.png +0 -0
  178. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/polls.png +0 -0
  179. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/replies.png +0 -0
  180. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/selects.png +0 -0
  181. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/slash-commands.png +0 -0
  182. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/simcord-showcase-poll-refresh.gif +0 -0
  183. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/simcord-terminal-demo.gif +0 -0
  184. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/simcord-transparent.webp +0 -0
  185. {simcord-3.2.0 → simcord-3.2.1}/docs/assets/social-card.png +0 -0
  186. {simcord-3.2.0 → simcord-3.2.1}/docs/changelog.md +0 -0
  187. {simcord-3.2.0 → simcord-3.2.1}/docs/concepts.md +0 -0
  188. {simcord-3.2.0 → simcord-3.2.1}/docs/cookbook.md +0 -0
  189. {simcord-3.2.0 → simcord-3.2.1}/docs/faq.md +0 -0
  190. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/ai-coding-agents.md +0 -0
  191. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/components.md +0 -0
  192. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/diagnostics.md +0 -0
  193. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/discord-visual-calibration.md +0 -0
  194. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/fixtures.md +0 -0
  195. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/intents.md +0 -0
  196. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/interactions.md +0 -0
  197. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/messages.md +0 -0
  198. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/mocks-vs-simulation.md +0 -0
  199. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/moderation-and-guild.md +0 -0
  200. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/test-without-token.md +0 -0
  201. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/testing-discord-py-bots.md +0 -0
  202. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/testing-slash-commands.md +0 -0
  203. {simcord-3.2.0 → simcord-3.2.1}/docs/guides/threads-reactions-dms.md +0 -0
  204. {simcord-3.2.0 → simcord-3.2.1}/docs/index.md +0 -0
  205. {simcord-3.2.0 → simcord-3.2.1}/docs/installation.md +0 -0
  206. {simcord-3.2.0 → simcord-3.2.1}/docs/llms.txt +0 -0
  207. {simcord-3.2.0 → simcord-3.2.1}/docs/parity-matrix.md +0 -0
  208. {simcord-3.2.0 → simcord-3.2.1}/docs/performance.md +0 -0
  209. {simcord-3.2.0 → simcord-3.2.1}/docs/preview-attestation.md +0 -0
  210. {simcord-3.2.0 → simcord-3.2.1}/docs/quickstart.md +0 -0
  211. {simcord-3.2.0 → simcord-3.2.1}/docs/robots.txt +0 -0
  212. {simcord-3.2.0 → simcord-3.2.1}/docs/stability.md +0 -0
  213. {simcord-3.2.0 → simcord-3.2.1}/examples/README.md +0 -0
  214. {simcord-3.2.0 → simcord-3.2.1}/examples/__init__.py +0 -0
  215. {simcord-3.2.0 → simcord-3.2.1}/examples/bot.py +0 -0
  216. {simcord-3.2.0 → simcord-3.2.1}/examples/conftest.py +0 -0
  217. {simcord-3.2.0 → simcord-3.2.1}/examples/preview_example.py +0 -0
  218. {simcord-3.2.0 → simcord-3.2.1}/examples/test_bot.py +0 -0
  219. {simcord-3.2.0 → simcord-3.2.1}/mkdocs.yml +0 -0
  220. {simcord-3.2.0 → simcord-3.2.1}/overrides/main.html +0 -0
  221. {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_discord_reference.py +0 -0
  222. {simcord-3.2.0 → simcord-3.2.1}/scripts/check_discoverability.py +0 -0
  223. {simcord-3.2.0 → simcord-3.2.1}/scripts/check_reference_modal_offline.py +0 -0
  224. {simcord-3.2.0 → simcord-3.2.1}/scripts/compare_visual_reference.py +0 -0
  225. {simcord-3.2.0 → simcord-3.2.1}/scripts/discord_reference_bot.py +0 -0
  226. {simcord-3.2.0 → simcord-3.2.1}/scripts/preview_dogfood.py +0 -0
  227. {simcord-3.2.0 → simcord-3.2.1}/scripts/record_readme_demo.py +0 -0
  228. {simcord-3.2.0 → simcord-3.2.1}/scripts/validate_discord_reference_pack.py +0 -0
  229. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/__init__.py +0 -0
  230. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_clock.py +0 -0
  231. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/asserts.py +0 -0
  232. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/__init__.py +0 -0
  233. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/cdn.py +0 -0
  234. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/command_access.py +0 -0
  235. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/errors.py +0 -0
  236. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/__init__.py +0 -0
  237. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/auditlog.py +0 -0
  238. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/automod.py +0 -0
  239. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/channel.py +0 -0
  240. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/expression.py +0 -0
  241. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/guild.py +0 -0
  242. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/interaction.py +0 -0
  243. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/invite.py +0 -0
  244. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/member.py +0 -0
  245. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/message.py +0 -0
  246. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/monetization.py +0 -0
  247. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/role.py +0 -0
  248. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/scheduled_event.py +0 -0
  249. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/stage_instance.py +0 -0
  250. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/user.py +0 -0
  251. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/voice.py +0 -0
  252. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/webhook.py +0 -0
  253. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/__init__.py +0 -0
  254. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/audit.py +0 -0
  255. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/commands.py +0 -0
  256. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/expressions.py +0 -0
  257. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/monetization.py +0 -0
  258. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/permissions.py +0 -0
  259. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/polls.py +0 -0
  260. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/reactions.py +0 -0
  261. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/scheduled_events.py +0 -0
  262. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/webhooks.py +0 -0
  263. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/permissions.py +0 -0
  264. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/serializers.py +0 -0
  265. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/state.py +0 -0
  266. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/components.py +0 -0
  267. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/enums.py +0 -0
  268. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/gateway.py +0 -0
  269. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/__init__.py +0 -0
  270. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/__init__.py +0 -0
  271. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/auditlogs.py +0 -0
  272. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/automod.py +0 -0
  273. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/commands.py +0 -0
  274. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/expressions.py +0 -0
  275. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/interactions.py +0 -0
  276. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/invites.py +0 -0
  277. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/monetization.py +0 -0
  278. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/scheduled_events.py +0 -0
  279. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/stage_instances.py +0 -0
  280. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/intents.py +0 -0
  281. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/monetization.py +0 -0
  282. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/parity.py +0 -0
  283. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_identity.py +0 -0
  284. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_markdown.py +0 -0
  285. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_media.py +0 -0
  286. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_media_worker.py +0 -0
  287. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/protocol.schema.json +0 -0
  288. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Arabic.txt +0 -0
  289. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-CJK.txt +0 -0
  290. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Devanagari.txt +0 -0
  291. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Emoji.txt +0 -0
  292. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Hebrew.txt +0 -0
  293. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto.txt +0 -0
  294. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/manifest.json +0 -0
  295. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-color-emoji-v2.051.ttf +0 -0
  296. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-arabic-v2.012.ttf +0 -0
  297. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-devanagari-v2.007.ttf +0 -0
  298. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-hebrew-v3.001.ttf +0 -0
  299. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-latin-italic-v2.015.ttf +0 -0
  300. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-latin-v2.015.ttf +0 -0
  301. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-mono-v2.014.ttf +0 -0
  302. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-sc-v2.004.ttf +0 -0
  303. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/index.html +0 -0
  304. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/LICENSE +0 -0
  305. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/SHA256SUMS +0 -0
  306. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/core.min.js +0 -0
  307. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/bash.min.js +0 -0
  308. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/cpp.min.js +0 -0
  309. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/csharp.min.js +0 -0
  310. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/css.min.js +0 -0
  311. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/diff.min.js +0 -0
  312. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/dockerfile.min.js +0 -0
  313. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/go.min.js +0 -0
  314. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/ini.min.js +0 -0
  315. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/java.min.js +0 -0
  316. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/javascript.min.js +0 -0
  317. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/json.min.js +0 -0
  318. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/markdown.min.js +0 -0
  319. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/python.min.js +0 -0
  320. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/rust.min.js +0 -0
  321. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/sql.min.js +0 -0
  322. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/typescript.min.js +0 -0
  323. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/xml.min.js +0 -0
  324. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/yaml.min.js +0 -0
  325. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/lottie/5.12.2/lottie_light_canvas.min.js +0 -0
  326. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/lottie/LICENSE +0 -0
  327. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/lottie/SHA256SUMS +0 -0
  328. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/py.typed +0 -0
  329. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/pytest_plugin.py +0 -0
  330. {simcord-3.2.0 → simcord-3.2.1}/src/simcord/types.py +0 -0
  331. {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/_world.py +0 -0
  332. {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_field_honesty.py +0 -0
  333. {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_field_honesty_fuzz.py +0 -0
  334. {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_route_coverage.py +0 -0
  335. {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_serializers.py +0 -0
  336. {simcord-3.2.0 → simcord-3.2.1}/tests/conftest.py +0 -0
  337. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/__init__.py +0 -0
  338. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/commands/option_cases.json +0 -0
  339. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/__init__.py +0 -0
  340. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/catalog.py +0 -0
  341. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/coverage.json +0 -0
  342. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/measurements.json +0 -0
  343. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/moving-square.json +0 -0
  344. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/profiles.json +0 -0
  345. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/states.json +0 -0
  346. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/video.mp4 +0 -0
  347. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/voice.ogg +0 -0
  348. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/__init__.py +0 -0
  349. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/events.py +0 -0
  350. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/general.py +0 -0
  351. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/interactions.py +0 -0
  352. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/moderation.py +0 -0
  353. {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/picker.py +0 -0
  354. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/preview_helpers.py +0 -0
  355. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_app_commands.py +0 -0
  356. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_application_emojis.py +0 -0
  357. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_asserts.py +0 -0
  358. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_audit_logs.py +0 -0
  359. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_automod.py +0 -0
  360. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_bot_users_and_webhooks.py +0 -0
  361. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_channels.py +0 -0
  362. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_command_permissions.py +0 -0
  363. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_common_bot_sweep.py +0 -0
  364. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_components_v2_messages.py +0 -0
  365. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_coverage_sweep.py +0 -0
  366. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_diagnostics.py +0 -0
  367. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_edge_cases.py +0 -0
  368. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_entitlement_journey.py +0 -0
  369. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_error_capture_and_edits.py +0 -0
  370. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_expressions.py +0 -0
  371. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_gateway_and_automod_exempt.py +0 -0
  372. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_guilds.py +0 -0
  373. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_intents.py +0 -0
  374. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_interaction_followups.py +0 -0
  375. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_invites.py +0 -0
  376. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_lifecycle.py +0 -0
  377. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_members.py +0 -0
  378. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_message_content_rest.py +0 -0
  379. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_message_routes.py +0 -0
  380. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_messages.py +0 -0
  381. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_misc_branches.py +0 -0
  382. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_moderation.py +0 -0
  383. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_observation_contracts.py +0 -0
  384. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_polls.py +0 -0
  385. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_commands.py +0 -0
  386. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_coverage.py +0 -0
  387. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_edges.py +0 -0
  388. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_fonts.py +0 -0
  389. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_identity.py +0 -0
  390. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_reactions.py +0 -0
  391. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_roles_and_ordering.py +0 -0
  392. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_scheduled_events.py +0 -0
  393. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_settlement_contract.py +0 -0
  394. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_setup_hook_suspension.py +0 -0
  395. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_sharding.py +0 -0
  396. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_shared_clock.py +0 -0
  397. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_stage_instances.py +0 -0
  398. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_threads.py +0 -0
  399. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_time.py +0 -0
  400. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_transport_edges.py +0 -0
  401. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_voice_state.py +0 -0
  402. {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_world_helpers.py +0 -0
  403. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_assert_helpers.py +0 -0
  404. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_backend_lookup_errors.py +0 -0
  405. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_command_access.py +0 -0
  406. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_components_v2_validation.py +0 -0
  407. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_errors.py +0 -0
  408. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_intent_rules.py +0 -0
  409. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_lazy_import.py +0 -0
  410. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_backend.py +0 -0
  411. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_http.py +0 -0
  412. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_option_validation.py +0 -0
  413. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_parity.py +0 -0
  414. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_parity_tooling.py +0 -0
  415. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_permission_validators.py +0 -0
  416. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_permissions.py +0 -0
  417. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_pytest_clock.py +0 -0
  418. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_pytest_plugin.py +0 -0
  419. {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_router.py +0 -0
@@ -11,6 +11,12 @@ jobs:
11
11
  runs-on: ubuntu-latest
12
12
  steps:
13
13
  - uses: actions/checkout@v7
14
+ - uses: actions/setup-node@v6
15
+ with:
16
+ node-version: "24"
17
+ cache: npm
18
+ - run: npm ci --ignore-scripts
19
+ - run: npm run check:preview
14
20
  - uses: astral-sh/setup-uv@v7
15
21
  # screenshot extra pulls in playwright/PIL/markdown-it so pyright resolves
16
22
  # the lazy optional imports in simcord.preview with real type info.
@@ -15,6 +15,9 @@ build/
15
15
  .hypothesis/
16
16
  .coverage
17
17
  htmlcov/
18
+ node_modules/
19
+ npm-debug.log*
20
+ *.tsbuildinfo
18
21
 
19
22
  # Editors
20
23
  .idea/
@@ -4,6 +4,25 @@ This changelog is generated with [towncrier](https://towncrier.readthedocs.io/).
4
4
 
5
5
  <!-- towncrier release notes start -->
6
6
 
7
+ ## 3.2.1 (2026-10-24)
8
+
9
+ ### Bug fixes
10
+
11
+ - Fix obsolete preview responses restoring an older viewer, and reauthorize cached references, identities, command catalogs, and retained autocomplete results without publishing unrelated edits. Centralize browser read/poll ownership and capture geometry; release evicted media, clear private modal and command-picker state, preserve native keyboard focus, and make simulated layouts follow their logical viewport. Preserve affected-message diagnostic navigation and terminal completeness across Inspector redraws; recover cached catalogs even when an obsolete read fails. Keep protocol 3 and status schema 1 unchanged; add development-only checks for the extracted JavaScript boundaries.
12
+
13
+ Give browser actions, assets, catalog observations, File-bearing drafts and rendered surfaces explicit lifetimes; strictly check all first-party JavaScript and preserve frozen publication/result provenance across revocation and capture. Validate compound member/voice and forum mutations before committing state, enforce actor and bot REST authority without conflating token access, and track actual executor execution separately from caller cancellation. Split capture configuration, journal/recovery and transport responsibilities; independently verify exact API test-grant provenance and retain distinct capture crop policies. Networked reference capture now requires aiohttp 3.12+ to prevent implicit uncertain-write retries; Preview library requirements are unchanged.
14
+
15
+ Preserve supported native SDK overwrite targets while rejecting foreign state and cross-guild roles/members; apply existing-emoji reaction permissions consistently in actors, REST and preview controls. Keep newer Reply intents when older sends settle, reconcile refreshed entity selections, and restore Escape after applying modal choices. Verify captured animation content and timing without depending on unrelated avatar antialiasing.
16
+
17
+ Move selection-state reporting into its owner, leaving the bootstrap to assemble read-only status.
18
+
19
+ Observe native executor submission and completion independently of failed or cancelled caller facades, including initializer rejection and picklable process-pool calls. Preserve live gateway, shard and webhook machinery after a native-work shutdown timeout. Keep deleted session-owned grants out of later baselines without weakening receipt checks. Preserve earlier bot avatars when a human DM message is focused or captured, while retaining live revocation checks; construct uncached SDK messages with native partial channels.
20
+
21
+ Release successful executor callables without retaining them until long-lived parent tasks finish; preserve unobserved-error handling.
22
+
23
+ Reject DM and cross-guild service-message references at the fixture boundary while preserving valid same-guild, cross-channel references. ([#41](https://github.com/SilentHacks/simcord/pull/41))
24
+
25
+
7
26
  ## 3.2.0 (2026-10-22)
8
27
 
9
28
  ### Features
@@ -16,8 +16,9 @@ uv run ruff check src tests examples benchmarks scripts && uv run ruff format --
16
16
  uv run pyright src
17
17
  ```
18
18
 
19
- The pre-commit hooks mirror the CI `lint` job (ruff on commit, pyright on push)
20
- using the project's own pinned tools, so a clean commit means a green CI lint.
19
+ The Python hooks run ruff on commit and pyright on push using the project's
20
+ pinned tools. Run the frontend check below separately; passing Python hooks
21
+ does not replace the JavaScript CI gate.
21
22
 
22
23
  Optional extras layer on top of `dev` depending on what you work on:
23
24
 
@@ -31,6 +32,19 @@ uv sync --extra dev --extra screenshot # matches the CI lint job
31
32
  uv run playwright install --with-deps chromium # needed once for browser capture tests + the example
32
33
  ```
33
34
 
35
+ Frontend contributors also need Node 24:
36
+
37
+ ```bash
38
+ npm ci --ignore-scripts
39
+ npm run check:preview
40
+ ```
41
+
42
+ This strict JSDoc check includes every first-party `static/*.js` module and the
43
+ composing callers. The explicit root glob and `noResolve` keep unchanged vendored
44
+ Highlight.js code behind narrow declarations, not behind disabled first-party
45
+ checks. New first-party modules belong in that checked root and the server's
46
+ static allowlist. Preview users and installed-wheel captures do not need Node.
47
+
34
48
  ## Project layout
35
49
 
36
50
  - `src/simcord/backend/`: the virtual Discord with dataclass models, wire-format
@@ -42,6 +56,18 @@ uv run playwright install --with-deps chromium # needed once for browser
42
56
  - `src/simcord/{env,builders,actors,results,interactions}.py`: the public API.
43
57
  - `src/simcord/_dpy_internals.py`: **every** touch of a private discord.py API,
44
58
  behind an import-time self-check. New private-API usage goes here, nowhere else.
59
+ - `src/simcord/_runtime.py`: paired loop hooks and owned task/callback/executor
60
+ bookkeeping; `_settlement.py` consumes a narrow settlement view, not the world.
61
+ - `src/simcord/preview/static/app.js`: page composition and event wiring.
62
+ `actions.js` owns POST admission; `session.js` owns state reads/polling;
63
+ `assets.js` owns shared URLs and derived metadata. Composer, select, modal,
64
+ timeline and workbench owners keep their own mutable feature state.
65
+ - `command-catalog.js` owns catalog observations, `command-drafts.js` owns
66
+ versioned File-bearing drafts, and `commands.js` owns the native picker view.
67
+ - `scripts/monetization_reference_{config,journal,transport}.py`: validated
68
+ capture-mode configuration, durable ownership/recovery and raw transport.
69
+ `validate_monetization_reference.py` independently verifies evidence in explicit
70
+ phases; recorder flags alone are not authorization.
45
71
 
46
72
  ## Guidelines
47
73
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: simcord
3
- Version: 3.2.0
3
+ Version: 3.2.1
4
4
  Summary: Offline discord.py bot testing with pytest. No network, token, or test server.
5
5
  Project-URL: Homepage, https://github.com/SilentHacks/simcord
6
6
  Project-URL: Documentation, https://simcord.readthedocs.io/
@@ -63,10 +63,17 @@ test ──► builders/actors ──► virtual backend (single source of truth
63
63
  discord.py's master branch to catch drift early.
64
64
  - **Deterministic snowflakes** with valid embedded timestamps, from a fixed virtual epoch.
65
65
 
66
- `Env` remains the lifecycle and state owner. Private runtime hooks live in `_runtime.py`;
67
- `_settlement.py` classifies tracked work and manages virtual timer bookkeeping against that
68
- same state. `_modal.py` handles modal validation and serialization through the existing actor
69
- permission checks and interaction dispatch.
66
+ `Env` remains the lifecycle and world owner. `_runtime.py` pairs hook installation
67
+ with restoration and owns task, callback, executor and external-wait records.
68
+ `_settlement.py` classifies those records through a narrow settlement view.
69
+ Executor completion is separate from cancellation of the caller's Future;
70
+ paired hooks observe actual owned standard-library pool submissions and are
71
+ restored after the last Env detaches.
72
+ `_modal.py` handles modal validation and serialization through the existing actor
73
+ permission checks and interaction dispatch. Backend/ID access facts are shared
74
+ below Env-bound viewer adapters; bot, human, fixture and token authority remain
75
+ distinct. Compound Backend mutations validate all inputs before committing model
76
+ state and gateway events; HTTP routes retain caller, reason and audit context.
70
77
 
71
78
  ## Optional browser presentation
72
79
 
@@ -83,10 +90,31 @@ Optional Pillow media work is bounded and outside Env's loop. Optional Playwrigh
83
90
  settled projection and reports geometry, readiness, completeness, calibration, and diagnostics.
84
91
  Base imports do not allocate any preview server, worker, or browser.
85
92
 
86
- Preview keeps session/page state in its existing owners. `_action_plans.py` prepares lazy
87
- actions; identity, component/message projection, and query modules feed `_snapshot.py`'s
88
- assembly. In the browser, `app.js` retains shared state and action sequencing, with focused
89
- workbench, select-draft, timeline, and transport modules handling presentation responsibilities.
93
+ Preview keeps session/page state in its existing owners. `_action_plans.py` prepares
94
+ lazy actions; identity, component/message projection and query modules feed
95
+ `_snapshot.py`'s assembly. Publications and the latest retained result each keep
96
+ their own frozen dependencies. Request-local authorization removes lost dependencies
97
+ without publishing unrelated edits. Capture pins check actual dependency loss before
98
+ and after PNG creation, not arbitrary differences between serialized snapshots.
99
+
100
+ In the browser, `app.js` composes owners and wires events. `actions.js` sequences
101
+ admitted POSTs, including browse/autocomplete; `session.js` owns validated state reads,
102
+ checkpoints, cancellation and polling. Catalog observations and versioned File-bearing
103
+ drafts have separate owners from the native command-picker view. `assets.js` owns
104
+ shared URLs and derived metadata without mutating published manifests; rendered
105
+ surfaces own DOM/player disposal. Composer, select, modal, timeline, diagnostics,
106
+ presentation and workbench records retain their focused responsibilities. Status is
107
+ assembled from read-only owner reports, with protocol 3 and schema 1 unchanged.
108
+
109
+ `geometry.js` supplies live status and capture measurements. Managed captures round
110
+ inside their visible intersection; complete control/menu captures round outward and
111
+ reject off-host bounds. These intentionally different policies share measurement
112
+ primitives, not forced identical crops. Python and browser diagnostics share the
113
+ packaged vocabulary. These remain native ES modules, without a bundler or framework.
114
+
115
+ Contributor checks use Node 24: `npm ci --ignore-scripts` and `npm run check:preview`
116
+ strictly check every first-party JavaScript module and its composing callers.
117
+ Python consumers and installed-wheel captures do not need Node.
90
118
 
91
119
  ## What it will never do
92
120
 
@@ -251,6 +251,13 @@ and Send Messages permissions, and one text channel named `parity`. Leave
251
251
  privileged intents disabled and the Interactions Endpoint URL blank. Do not run
252
252
  alongside another process using the same bot.
253
253
 
254
+ Networked reference capture requires **aiohttp 3.12+** for its public per-request
255
+ middleware API. This prevents aiohttp from silently retrying uncertain writes,
256
+ including DELETE/PUT; only explicitly recorded HTTP 429 retries remain enabled.
257
+ The recorder checks this prerequisite before requesting credentials or recording
258
+ a mutation intent. Preview's library dependency remains `aiohttp>=3.9`; offline
259
+ evidence validation does not need the capture transport.
260
+
254
261
  From the repository root, run in your own interactive terminal:
255
262
 
256
263
  ```bash
@@ -409,6 +416,11 @@ It does **not** turn captured facts into simulator calibration approval.
409
416
  inspect the named blocked cases and reasons in `manifest.json`. A completed run
410
417
  does not prove all lifecycle cases or fix simulator behavior.
411
418
 
419
+ Validation is independent of recorder ownership flags. API test-create proof needs
420
+ an exact integer type 8, the requested application/SKU/owner and a fresh,
421
+ non-manual ID. Explicitly authorized manual type-4 purchases use a separate proof
422
+ path. Malformed evidence produces located error codes without echoing raw values.
423
+
412
424
  The validator can also run without credentials:
413
425
 
414
426
  ```bash
@@ -436,6 +448,18 @@ uv run python scripts/capture_remaining_monetization.py \
436
448
  --resume CAPTURE_DIRECTORY --cleanup-only
437
449
  ```
438
450
 
451
+ Cleanup-only loads the saved identities and verifies correlated positive receipts;
452
+ it does not require a new capture's checkout configuration or source fixtures.
453
+ Recovery preserves schema-1 ordered correlation and schema-2 request IDs. A
454
+ success-looking manifest flag or an earlier retry response cannot establish ownership.
455
+
456
+ Deleted sandbox grants remain session-owned history, backed by their original
457
+ positive receipts. Later baseline scans do not adopt those IDs as pre-existing
458
+ resources, so repeated resume and cleanup-only remain safe. A journal that
459
+ already lists the same ID as both baseline and owned is still rejected; resolve
460
+ that conflict by auditing its evidence, not by discarding history or weakening
461
+ the ownership check.
462
+
439
463
  Recovery cannot change the original app/server/owner identities. A second owner
440
464
  may be added to a run that previously lacked one; the relevant comparison
441
465
  sections are reopened, not the purchase batches. Connection gaps and interrupted
@@ -38,8 +38,10 @@ locked = guild.create_text_channel(
38
38
  )
39
39
  ```
40
40
 
41
- Overwrite targets can be roles (`guild.default_role`, any `RoleHandle`) or members
42
- (`MemberActor`).
41
+ Overwrite targets can be `RoleHandle`, `MemberActor` or `UserHandle` objects, or native
42
+ `discord.Role`, `discord.Member`, `discord.User` and `discord.ClientUser` objects from the
43
+ same Env's SDK state. Roles and members must belong to the target guild. Foreign SDK
44
+ state and cross-guild role/member targets are rejected before channel creation.
43
45
 
44
46
  !!! info "The bot's default permissions"
45
47
  By default the bot gets a managed integration role with broad permissions but **not**
@@ -59,6 +61,8 @@ Overwrite targets can be roles (`guild.default_role`, any `RoleHandle`) or membe
59
61
  (`50013`). It also can't delete the `@everyone` role.
60
62
  - **Editing others' messages** — the bot can't edit another user's message (`50005`).
61
63
  - **Timeouts** — a timed-out member loses everything except viewing and reading history.
64
+ - **Reactions** — `add_reactions` is required to introduce a new emoji, not to join an
65
+ existing reaction. Both require access to the message and its history.
62
66
 
63
67
  ```python
64
68
  async def test_cannot_ban_higher_role(simcord_env):
@@ -133,6 +133,9 @@ its original opener; the source-message linkage remains available to `interactio
133
133
  authorized independently. A denied target is not distinguished from a missing target.
134
134
  - Access is rechecked on every state, asset, and pinned-capture read. Revoked access or removed
135
135
  attachments invalidate cached content; already delivered pixels cannot be remotely recalled.
136
+ Security redaction can remove already-published references, summaries, identities, candidates,
137
+ command entries, and asset handles without advancing the revision. It never publishes unrelated
138
+ edits or newly granted content. A pinned capture fails closed if a published dependency loses access.
136
139
 
137
140
  The capability holder may switch between supplied viewers. It is not authentication for unrelated
138
141
  humans; use separate sessions for separate trust domains. Treat `preview.url`, terminal output,
@@ -141,9 +144,9 @@ logs, reports, bug issues, or screenshots.
141
144
 
142
145
  ## Refresh and staleness
143
146
 
144
- Preview uses HTTP commands and polling, not a websocket or always-running Python poller. Polling only
145
- reads the latest published revision. Python actor calls, `advance_time()`, background callbacks, and
146
- other scenario mutations become visible after an explicit refresh:
147
+ Preview uses HTTP commands and polling, not a websocket or always-running Python poller. Polling
148
+ reads the latest published projection, with current access filtering. Python actor calls,
149
+ `advance_time()`, background callbacks, and other scenario mutations become visible after an explicit refresh:
147
150
 
148
151
  ```python
149
152
  await actor.click(message, custom_id="save")
@@ -161,6 +164,16 @@ cursors. `targetId` identifies the focused projection; there is no `selected` al
161
164
  timed-out action may already have mutated the backend: its last settled projection is retained and
162
165
  marked stale, then a later successful refresh reconciles it without replaying the action.
163
166
 
167
+ The browser coalesces state reads and rejects responses from obsolete request lifetimes or older
168
+ context, bot, or publication checkpoints before changing the UI. A transient read failure retains
169
+ the last authorized projection with a transport warning; HTTP 401/410 or incompatible protocol
170
+ terminates the page and clears private surfaces. Back/forward-cache suspension pauses polling;
171
+ restoration resumes one polling chain. Non-restorable page hides send a best-effort authenticated
172
+ release; browser unload never deletes a restorable context. The existing lease covers undeliverable
173
+ releases, and an expired page requires an explicit reload.
174
+ Back/forward caching depends on browser policy: Preview keeps its `no-store` security headers.
175
+ Navigation that reloads the document does not retain page-local drafts.
176
+
164
177
  ## Controls, keyboard, and accessibility
165
178
 
166
179
  The bundled page uses semantic HTML buttons, inputs, textareas, native checkboxes/radios/file
@@ -517,6 +530,11 @@ settled projection, DOM, fonts, authorized media, validated display dimensions (
517
530
  and two animation frames are ready, with no action or page intent still pending. In particular,
518
531
  resize/profile reconfiguration must finish before capture tooling treats the surface as ready.
519
532
  It does not mean the callback succeeded, the output is complete, or the capture is calibrated.
533
+ A clean, acknowledged Close can be complete while not render-ready; terminal transport failures
534
+ remain incomplete, and an unaccounted-for action remains uncertain. Inspector filters do not change
535
+ these lifecycle outcomes.
536
+ A matching late Close acknowledgement can confirm closure after a terminal read, without restoring
537
+ the cleared private projection.
520
538
  `publishedRevision` is a settled publication;
521
539
  `contextGeneration` changes on viewer or focus changes;
522
540
  `botGeneration` changes on restart; render generations also cover local changes such
@@ -525,6 +543,10 @@ and premium-icon loads stay bound to retained DOM owners across redraws; replaci
525
543
  discards its continuation. A retained owner's late failure still makes the surface incomplete.
526
544
  Switching viewers or restarting the bot invalidates asset ownership and recreates media rather than
527
545
  carrying playback or pending loads across authorization boundaries.
546
+ Command browsing, composed-command, and entity-suggestion avatars all participate in readiness.
547
+ Replacing or closing a picker releases only its obsolete pending work. Evicting a rendered surface
548
+ pauses and releases its media; retained surfaces keep their pending work. The reported active control
549
+ follows actual browser focus, including individual descendants within a compound control.
528
550
 
529
551
  `projectedMessageIds` mirrors `snapshot["timeline"]`; `visibleMessageIds` lists only IDs currently
530
552
  visible in the simulated viewport, not every projected window item. `geometry` reports measured app,
@@ -545,9 +567,12 @@ correctly typed but stale context or generation values return `stale-context` or
545
567
  Kind, control resolution, and values are validated before the sequence is admitted. Admission is
546
568
  at-most-once: a duplicate latest request with the same payload returns its recorded outcome, a
547
569
  changed payload conflicts, old sequences expire, and gaps are rejected. Busy, stale, unauthorized,
548
- disabled, deleted, or invalid controls are rejected before admission and are never automatically
549
- retried. A disconnected client does not cancel an admitted callback; delivery failure is separate
550
- from callback settlement.
570
+ disabled, deleted, or invalid callbacks are rejected before admission and are never automatically
571
+ retried. Only the latest read-like query intent rejected definitively as busy is reconsidered,
572
+ at most once per successful existing polling tick; this does not replay an admitted or uncertain
573
+ callback. Page intents such as Close and viewer/focus changes queue behind the current action,
574
+ not behind an unreachable publication revision. A disconnected client does not cancel an admitted
575
+ callback; delivery failure is separate from callback settlement.
551
576
 
552
577
  Revision-bound actions (`click`, `select`, `modal_submit`, `autocomplete_command`, `run_command`,
553
578
  `history`, `send_message`, `edit_message`, `delete_message`, `set_reaction`, `set_poll_votes`,
@@ -565,8 +590,10 @@ focuses an authorized outcome, and Back returns to the prior target and invoking
565
590
  exists. Receipts never auto-focus a page. A pre-admission rejection does not consume the sequence;
566
591
  the activity ledger holds at most 20 receipts and no message bodies, and references are reauthorized
567
592
  on every read. Diagnostics use catalog-owned codes and remediation, never raw request or exception
568
- text. Inspect the receipt and refresh after failures; never retry a consumed sequence to make a
569
- screenshot look successful.
593
+ text. Validated diagnostic subjects retain affected-message navigation in the private UI, but are
594
+ excluded from safe support reports. Inspect the receipt and refresh after failures; never retry a
595
+ consumed sequence to make a screenshot look successful. Replayed query results that are no longer
596
+ available are omitted; candidate descriptors never become an undocumented null variant.
570
597
  Actor dispatch is recorded at the successful backend mutation, before settlement. A later timeout
571
598
  or cancellation reports a dispatched, uncertain operation; refreshing and replaying its receipt
572
599
  must not repeat the mutation. Denied reads clear channel topics, history boundaries and send capability,
@@ -641,8 +668,12 @@ The full catalog is a separate read, rather than repeated in every state snapsho
641
668
  `truncated`, `application` (`id`, `name`, `avatarAssetId`) and `entries`. Each entry describes a
642
669
  visible command leaf with its ID, invocation path, scope, schema fingerprint and typed options. The
643
670
  schema defines this wire shape at `$defs.commandCatalog`. The response is protected by the page
644
- capability and context. Catalogs are capped at 1,000 leaves and 2 MiB; an oversized catalog is marked
645
- `truncated`.
671
+ capability and context, and current command access and schema are checked before cached entries
672
+ are returned. Catalogs are capped at 1,000 leaves and 2 MiB; an oversized catalog is marked `truncated`.
673
+ If the manifest changes while a catalog read is pending, the browser installs only the desired
674
+ catalog and fetches its replacement rather than remaining stuck with a discarded response.
675
+ Returning to an already installed catalog restores it without another fetch; obsolete responses
676
+ and failures cannot displace it.
646
677
 
647
678
  The two additional revision-bound action kinds are `autocomplete_command` and `run_command`. Both
648
679
  carry `command_id`, `path` and `schema_fingerprint`; autocomplete also carries `focused`, `value` and
@@ -651,6 +682,15 @@ parts named `file:<optionName>` rather than JSON bytes. Every receipt has a null
651
682
  beside `target`: when present it is `{commandId, invocation}`. The diagnostic subject union adds
652
683
  `{commandOption}` beside the existing `{messageId, controlKey?}` form.
653
684
 
685
+ `GET /api/action-result?request_id=<id>&sequence=<positive integer>` recovers the original
686
+ autocomplete response after delivery loss without invoking the callback again. It uses the same
687
+ capability/context headers and only the existing latest retained action result, not an action
688
+ history. Recovery requires the original viewer, context and bot generation, command identity,
689
+ schema, and current command/channel access. A matching settled result returns HTTP 200 with the
690
+ existing action response; pending returns 409, unavailable/superseded/scope-changed returns 404,
691
+ expired context returns 410, and missing authorization returns 401. An unavailable result leaves
692
+ the draft intact and reports failure instead of silently resubmitting or loading indefinitely.
693
+
654
694
  Command diagnostics include `commands-unsynced` (call `await bot.tree.sync()`), `command-unavailable`,
655
695
  `command-changed`, `command-option-invalid` and `autocomplete-unanswered`. A
656
696
  `command-option-invalid` diagnostic identifies the relevant option without exposing raw request or bot
@@ -768,6 +808,11 @@ logical preview viewport, including its modal backdrop and dialog but excluding
768
808
  Use an interactive browser session to inspect modal content at both scroll extremes. Width and height
769
809
  are positive bounded integers and are checked against the screenshot raster limits above.
770
810
 
811
+ Captures pin the presentation profile and requested media time, but native browser
812
+ antialiasing can still vary between renders. Do not use whole-image PNG or decoded-RGBA
813
+ byte equality as proof of frame selection: check the rendered media content and its
814
+ reported time and geometry. A pinned profile does not certify pixel parity with Discord.
815
+
771
816
  The report includes viewer, channel, target and modal IDs, published and render generations, geometry,
772
817
  media metadata (effective frame times, codec selection, transformations), readiness, calibration,
773
818
  action status and diagnostics. Captures reject unsettled actions, unavailable authorization,
@@ -73,6 +73,34 @@ latest-Env fallback, global datetime patch, or general application-time virtuali
73
73
  Inject `env.now` into your application's own clock seam. Only one live Env per event
74
74
  loop is supported; a second start rejects before altering hooks.
75
75
 
76
+ Executor ownership follows actual execution, not the caller's Future. Native
77
+ cancellation that removes a queued job prevents execution; cancelling a shielded
78
+ or non-forwarding facade does not. Cancelling a running job never claims that its
79
+ thread stopped. Work it enqueues before completion retains bot ownership.
80
+
81
+ While Envs are active, paired, reference-counted hooks observe owned submissions
82
+ through the standard `ThreadPoolExecutor.submit` and `ProcessPoolExecutor.submit`
83
+ APIs, including interpreter pools where available. Unrelated submissions retain
84
+ their original behavior; SimCord neither replaces nor shuts down supplied
85
+ executors. Native rejection, initializer failure and completion retire the
86
+ actual job independently of the facade. Isolated process/interpreter pools
87
+ receive only the original picklable callable, not an Env or its in-process state.
88
+ The hooks are restored when the last Env detaches.
89
+
90
+ SimCord preserves the original executor hook and caller Future. Custom hooks
91
+ should forward the submitted callable unchanged to the native executor. An
92
+ opaque callable adapter can hide pre-entry cancellation or rejection, leaving
93
+ ownership unresolved and timing out rather than guessing that no work remains.
94
+ A custom hook can also hide later asynchronous post-processing behind an
95
+ already-completed facade; settlement cannot join that invisible work. The hook
96
+ must expose or await its own completion. Captured callback context is preserved
97
+ when later work is scheduled.
98
+
99
+ A shutdown timeout while draining native work retains the gateway, shards and
100
+ webhook adapter until a later successful drain. The attempt may already have
101
+ cancelled asynchronous tasks: it is not a rollback. Release outstanding work
102
+ and retry shutdown.
103
+
76
104
  !!! tip "Stepwise vs. one jump"
77
105
  `advance_time` consumes timers in order, settling between each, so intermediate effects
78
106
  actually happen. If a handler sleeps 30s, posts, then sleeps another 30s and posts
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "allowJs": true,
4
+ "checkJs": true,
5
+ "noEmit": true,
6
+ "noResolve": true,
7
+ "strict": true,
8
+ "target": "ES2022",
9
+ "module": "ESNext",
10
+ "moduleResolution": "bundler",
11
+ "lib": ["ES2022", "DOM", "DOM.Iterable"]
12
+ },
13
+ "include": [
14
+ "src/simcord/preview/static/*.js",
15
+ "src/simcord/preview/static/*.d.ts"
16
+ ]
17
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "simcord-preview-checks",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {
6
+ "": {
7
+ "name": "simcord-preview-checks",
8
+ "devDependencies": {
9
+ "typescript": "5.9.3"
10
+ }
11
+ },
12
+ "node_modules/typescript": {
13
+ "version": "5.9.3",
14
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
15
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
16
+ "dev": true,
17
+ "license": "Apache-2.0",
18
+ "bin": {
19
+ "tsc": "bin/tsc",
20
+ "tsserver": "bin/tsserver"
21
+ },
22
+ "engines": {
23
+ "node": ">=14.17"
24
+ }
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "simcord-preview-checks",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "check:preview": "tsc --project jsconfig.preview.json"
7
+ },
8
+ "devDependencies": {
9
+ "typescript": "5.9.3"
10
+ }
11
+ }
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "simcord"
7
- version = "3.2.0"
7
+ version = "3.2.1"
8
8
  description = "Offline discord.py bot testing with pytest. No network, token, or test server."
9
9
  readme = "README.md"
10
10
  license = "MIT"