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.
- {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/verify.yml +6 -0
- {simcord-3.2.0 → simcord-3.2.1}/.gitignore +3 -0
- {simcord-3.2.0 → simcord-3.2.1}/CHANGELOG.md +19 -0
- {simcord-3.2.0 → simcord-3.2.1}/CONTRIBUTING.md +28 -2
- {simcord-3.2.0 → simcord-3.2.1}/PKG-INFO +1 -1
- {simcord-3.2.0 → simcord-3.2.1}/docs/architecture.md +36 -8
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/monetization.md +24 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/permissions.md +6 -2
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/preview.md +55 -10
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/time-control.md +28 -0
- simcord-3.2.1/jsconfig.preview.json +17 -0
- simcord-3.2.1/package-lock.json +27 -0
- simcord-3.2.1/package.json +11 -0
- {simcord-3.2.0 → simcord-3.2.1}/pyproject.toml +1 -1
- {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_monetization_reference.py +428 -416
- {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_remaining_monetization.py +524 -390
- {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_visual_reference.py +20 -29
- {simcord-3.2.0 → simcord-3.2.1}/scripts/check_package.py +13 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_checkout.py +37 -22
- simcord-3.2.1/scripts/monetization_reference_config.py +189 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_expiry.py +10 -0
- simcord-3.2.1/scripts/monetization_reference_journal.py +154 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_lifecycle.py +127 -114
- simcord-3.2.1/scripts/monetization_reference_transport.py +198 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/monetization_reference_upgrade.py +196 -172
- {simcord-3.2.0 → simcord-3.2.1}/scripts/replay_visual_reference.py +339 -320
- {simcord-3.2.0 → simcord-3.2.1}/scripts/validate_monetization_reference.py +404 -183
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_dpy_internals.py +51 -2
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_modal.py +7 -2
- simcord-3.2.1/src/simcord/_runtime.py +558 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_settlement.py +62 -39
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/actors.py +61 -11
- simcord-3.2.1/src/simcord/backend/access.py +105 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/base.py +17 -3
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/channels.py +70 -1
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/guilds.py +49 -7
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/invites.py +15 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/messages.py +61 -6
- simcord-3.2.1/src/simcord/backend/ops/voice.py +78 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/builders.py +79 -18
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/env.py +186 -142
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/_helpers.py +12 -16
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/client.py +3 -6
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/router.py +12 -2
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/application.py +1 -2
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/channels.py +42 -30
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/guilds.py +23 -25
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/messages.py +19 -8
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/reactions.py +19 -5
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/interactions.py +30 -8
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/__init__.py +3 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_action_plans.py +24 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_actions.py +84 -44
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_assets.py +36 -18
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_capture.py +9 -43
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_commands.py +34 -4
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_component_projection.py +119 -5
- simcord-3.2.1/src/simcord/preview/_dependencies.py +90 -0
- simcord-3.2.1/src/simcord/preview/_diagnostics.py +69 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_messages.py +102 -6
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_pages.py +137 -8
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_queries.py +118 -13
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_server.py +60 -8
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_snapshot.py +9 -2
- simcord-3.2.1/src/simcord/preview/static/actions.js +264 -0
- simcord-3.2.1/src/simcord/preview/static/app.js +883 -0
- simcord-3.2.1/src/simcord/preview/static/assets.js +107 -0
- simcord-3.2.1/src/simcord/preview/static/backend-diagnostics.json +219 -0
- simcord-3.2.1/src/simcord/preview/static/command-catalog.js +60 -0
- simcord-3.2.1/src/simcord/preview/static/command-drafts.js +62 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/commands.js +348 -261
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/components.js +103 -34
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/composer.js +87 -15
- simcord-3.2.1/src/simcord/preview/static/connection.js +73 -0
- simcord-3.2.1/src/simcord/preview/static/diagnostics.js +205 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/dom.js +23 -2
- simcord-3.2.1/src/simcord/preview/static/focus.js +69 -0
- simcord-3.2.1/src/simcord/preview/static/geometry.js +78 -0
- simcord-3.2.1/src/simcord/preview/static/highlight-types.d.ts +26 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/listbox.js +11 -1
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/media.js +121 -50
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/messages.js +35 -11
- simcord-3.2.1/src/simcord/preview/static/modal.js +199 -0
- simcord-3.2.1/src/simcord/preview/static/presentation.js +299 -0
- simcord-3.2.1/src/simcord/preview/static/preview-types.d.ts +262 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/preview.css +13 -26
- simcord-3.2.1/src/simcord/preview/static/select-drafts.js +465 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/selects.js +35 -12
- simcord-3.2.1/src/simcord/preview/static/session.js +116 -0
- simcord-3.2.1/src/simcord/preview/static/surfaces.js +153 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/text.js +30 -3
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/timeline.js +85 -11
- simcord-3.2.1/src/simcord/preview/static/transport.js +50 -0
- simcord-3.2.1/src/simcord/preview/static/workbench.js +398 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/results.py +5 -0
- simcord-3.2.1/tests/integration/test_access_boundaries.py +385 -0
- simcord-3.2.1/tests/integration/test_atomic_mutations.py +265 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_command_visibility.py +38 -15
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_components_v2_interactions.py +70 -7
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_forum.py +69 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_forwarding.py +143 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_interactions.py +75 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview.py +21 -0
- simcord-3.2.1/tests/integration/test_preview_action_admission.py +254 -0
- simcord-3.2.1/tests/integration/test_preview_additional.py +535 -0
- simcord-3.2.1/tests/integration/test_preview_browser_ownership.py +808 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_capture.py +42 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_capture_dx.py +17 -187
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_channel.py +24 -170
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_command_picker.py +334 -114
- simcord-3.2.1/tests/integration/test_preview_components_v2.py +185 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_dx.py +8 -160
- simcord-3.2.1/tests/integration/test_preview_entity_contracts.py +451 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_fixes.py +72 -251
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_message_actions.py +29 -5
- simcord-3.2.1/tests/integration/test_preview_modal_contracts.py +342 -0
- simcord-3.2.1/tests/integration/test_preview_navigation_contracts.py +198 -0
- simcord-3.2.1/tests/integration/test_preview_observations.py +283 -0
- simcord-3.2.1/tests/integration/test_preview_provenance.py +295 -0
- simcord-3.2.1/tests/integration/test_preview_render_contracts.py +54 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_security.py +0 -292
- simcord-3.2.1/tests/integration/test_preview_support_report.py +304 -0
- simcord-3.2.1/tests/integration/test_preview_viewport_ownership.py +168 -0
- simcord-3.2.1/tests/integration/test_preview_workbench_contracts.py +190 -0
- simcord-3.2.1/tests/integration/test_reference_replay.py +215 -0
- simcord-3.2.1/tests/integration/test_runtime_executor_ownership.py +944 -0
- simcord-3.2.1/tests/integration/test_sdk_compatibility.py +47 -0
- simcord-3.2.1/tests/integration/test_visual_reference_geometry.py +139 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_dpy_internals.py +70 -41
- simcord-3.2.1/tests/unit/test_monetization_reference_capture.py +132 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_checkout.py +26 -5
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_expiry.py +19 -3
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_lifecycle.py +1 -1
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_upgrade.py +37 -5
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_reference_validation.py +149 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_preview_action_specs.py +1 -12
- simcord-3.2.1/tests/unit/test_remaining_monetization_capture.py +756 -0
- {simcord-3.2.0 → simcord-3.2.1}/uv.lock +1 -1
- simcord-3.2.0/src/simcord/_runtime.py +0 -341
- simcord-3.2.0/src/simcord/backend/access.py +0 -77
- simcord-3.2.0/src/simcord/backend/ops/voice.py +0 -40
- simcord-3.2.0/src/simcord/preview/_diagnostics.py +0 -284
- simcord-3.2.0/src/simcord/preview/static/app.js +0 -2280
- simcord-3.2.0/src/simcord/preview/static/select-drafts.js +0 -284
- simcord-3.2.0/src/simcord/preview/static/transport.js +0 -167
- simcord-3.2.0/src/simcord/preview/static/workbench.js +0 -130
- simcord-3.2.0/tests/integration/test_preview_additional.py +0 -1208
- simcord-3.2.0/tests/integration/test_reference_replay.py +0 -96
- simcord-3.2.0/tests/unit/test_remaining_monetization_capture.py +0 -367
- {simcord-3.2.0 → simcord-3.2.1}/.github/ISSUE_TEMPLATE/bug.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.github/ISSUE_TEMPLATE/parity-gap.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.github/dependabot.yml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/ci.yml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/dpy-master.yml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.github/workflows/release.yml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.pre-commit-config.yaml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.python-version +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/.readthedocs.yaml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/CODE_OF_CONDUCT.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/LICENSE +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/README.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/SECURITY.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/benchmarks/_helpers.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/benchmarks/test_dispatch_benchmarks.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/benchmarks/test_perf_guards.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/changes/README.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/api.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/adventure/alpine.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/adventure/canyon.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/attachments.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/buttons.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/embeds.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/entities.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/layouts.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/markdown.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/modals.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/polls.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/replies.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/selects.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/preview/slash-commands.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/simcord-showcase-poll-refresh.gif +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/simcord-terminal-demo.gif +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/simcord-transparent.webp +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/assets/social-card.png +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/changelog.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/concepts.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/cookbook.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/faq.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/ai-coding-agents.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/components.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/diagnostics.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/discord-visual-calibration.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/fixtures.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/intents.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/interactions.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/messages.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/mocks-vs-simulation.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/moderation-and-guild.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/test-without-token.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/testing-discord-py-bots.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/testing-slash-commands.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/guides/threads-reactions-dms.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/index.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/installation.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/llms.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/parity-matrix.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/performance.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/preview-attestation.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/quickstart.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/robots.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/docs/stability.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/examples/README.md +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/examples/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/examples/bot.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/examples/conftest.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/examples/preview_example.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/examples/test_bot.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/mkdocs.yml +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/overrides/main.html +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/capture_discord_reference.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/check_discoverability.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/check_reference_modal_offline.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/compare_visual_reference.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/discord_reference_bot.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/preview_dogfood.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/record_readme_demo.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/scripts/validate_discord_reference_pack.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/_clock.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/asserts.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/cdn.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/command_access.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/errors.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/auditlog.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/automod.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/channel.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/expression.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/guild.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/interaction.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/invite.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/member.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/message.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/monetization.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/role.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/scheduled_event.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/stage_instance.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/user.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/voice.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/models/webhook.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/audit.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/commands.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/expressions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/monetization.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/permissions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/polls.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/reactions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/scheduled_events.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/ops/webhooks.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/permissions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/serializers.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/backend/state.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/components.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/enums.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/gateway.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/auditlogs.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/automod.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/commands.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/expressions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/interactions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/invites.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/monetization.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/scheduled_events.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/http/routes/stage_instances.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/intents.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/monetization.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/parity.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_identity.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_markdown.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_media.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/_media_worker.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/protocol.schema.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Arabic.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-CJK.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Devanagari.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Emoji.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto-Hebrew.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/OFL-1.1-Noto.txt +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/manifest.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-color-emoji-v2.051.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-arabic-v2.012.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-devanagari-v2.007.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-hebrew-v3.001.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-latin-italic-v2.015.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-latin-v2.015.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-mono-v2.014.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/fonts/noto-sans-sc-v2.004.ttf +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/index.html +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/LICENSE +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/SHA256SUMS +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/core.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/bash.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/cpp.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/csharp.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/css.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/diff.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/dockerfile.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/go.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/ini.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/java.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/javascript.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/json.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/markdown.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/python.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/rust.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/sql.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/typescript.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/xml.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/highlight/es/languages/yaml.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/lottie/5.12.2/lottie_light_canvas.min.js +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/lottie/LICENSE +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/preview/static/vendor/lottie/SHA256SUMS +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/py.typed +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/pytest_plugin.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/src/simcord/types.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/_world.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_field_honesty.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_field_honesty_fuzz.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_route_coverage.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/conformance/test_serializers.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/conftest.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/commands/option_cases.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/catalog.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/coverage.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/measurements.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/moving-square.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/profiles.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/states.json +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/video.mp4 +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/preview/voice.ogg +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/__init__.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/events.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/general.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/interactions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/moderation.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/fixtures/sample_bot/picker.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/preview_helpers.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_app_commands.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_application_emojis.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_asserts.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_audit_logs.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_automod.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_bot_users_and_webhooks.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_channels.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_command_permissions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_common_bot_sweep.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_components_v2_messages.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_coverage_sweep.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_diagnostics.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_edge_cases.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_entitlement_journey.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_error_capture_and_edits.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_expressions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_gateway_and_automod_exempt.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_guilds.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_intents.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_interaction_followups.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_invites.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_lifecycle.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_members.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_message_content_rest.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_message_routes.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_messages.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_misc_branches.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_moderation.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_observation_contracts.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_polls.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_commands.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_coverage.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_edges.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_fonts.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_preview_identity.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_reactions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_roles_and_ordering.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_scheduled_events.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_settlement_contract.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_setup_hook_suspension.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_sharding.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_shared_clock.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_stage_instances.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_threads.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_time.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_transport_edges.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_voice_state.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/integration/test_world_helpers.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_assert_helpers.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_backend_lookup_errors.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_command_access.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_components_v2_validation.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_errors.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_intent_rules.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_lazy_import.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_backend.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_monetization_http.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_option_validation.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_parity.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_parity_tooling.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_permission_validators.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_permissions.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_pytest_clock.py +0 -0
- {simcord-3.2.0 → simcord-3.2.1}/tests/unit/test_pytest_plugin.py +0 -0
- {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.
|
|
@@ -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
|
|
20
|
-
|
|
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.
|
|
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
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
87
|
-
actions; identity, component/message projection
|
|
88
|
-
|
|
89
|
-
|
|
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
|
|
42
|
-
|
|
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
|
|
145
|
-
reads the latest published
|
|
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
|
|
549
|
-
retried.
|
|
550
|
-
|
|
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.
|
|
569
|
-
|
|
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
|
|
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
|
+
}
|