morphit/scripts/run-smokes.sh
Morphit Team 7c1c3bb332
Some checks failed
morphit-ci / TypeScript typecheck (sweep all workspaces) (push) Has been cancelled
morphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Has been cancelled
morphit-ci / Integration tests (real Postgres 16) (push) Has been cancelled
morphit-ci / ansible-lint (playbook quality gate) (push) Has been cancelled
morphit-ci / Smoke suite (run-smokes.sh, triple-pulse) (push) Has been cancelled
morphit-release / Build + publish release tarball (push) Has been cancelled
v1.11.1 — registration self-heal + data-fs disk health + offline-install RPC softening + node-health unification (cp707-cp710)
2026-08-11 17:38:41 -07:00

740 lines
30 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Morphit — run all tsx-runnable smoke scenarios.
set -u
repo="$(cd "$(dirname "$0")/.." && pwd)"
cd "$repo"
# Resolve tsx from the workspace first, then PATH. Mirrors the
# fallback pattern in scripts/typecheck-sweep.sh — operators who
# call the smoke runner before `npm install` has fully populated
# .bin/ get a clearer error than "command not found", and CI
# workflows that don't prepend node_modules/.bin to PATH still
# work.
if [ -x "$repo/node_modules/.bin/tsx" ]; then
TSX="$repo/node_modules/.bin/tsx"
elif command -v tsx >/dev/null 2>&1; then
TSX="$(command -v tsx)"
else
echo "ERROR: tsx not found. Run 'npm install' from the repo root." >&2
exit 2
fi
SMOKES=(
"apps/indexer:block-handler-smoke"
"apps/indexer:login-pairing-sse-keepalive-smoke"
"apps/indexer:rpc-endpoints-probe-smoke"
"apps/indexer:rpc-probe-failure-reason-smoke"
"apps/indexer:indexer-config-boot-smoke"
"apps/indexer:chat-handler-smoke"
"apps/indexer:push-clickpath-locale-smoke"
"apps/indexer:chat-sse-order-permlink-smoke"
"apps/indexer:chat-fast-notification-smoke"
"apps/indexer:dispatcher-admission-order-smoke"
"apps/indexer:orderbook-provisional-removal-memory-smoke"
"apps/indexer:chat-identity-handler-smoke"
"apps/indexer:order-handler-smoke"
"apps/indexer:broadcast-chain-proxy-rate-limit-smoke"
"apps/indexer:broadcast-op-allowlist-smoke"
"apps/indexer:broadcast-hedge-off-smoke"
"apps/indexer:asset-network-set-registry-parity-smoke"
"apps/indexer:feedback-handler-smoke"
"apps/indexer:feedback-summary-order-owner-parity-smoke"
"apps/indexer:stranger-fee-handler-smoke"
"apps/indexer:stranger-fee-pricing-smoke"
"apps/indexer:api-response-shape-smoke"
"apps/indexer:body-cap-smoke"
"apps/indexer:daily-ceiling-persist-smoke"
"apps/indexer:monero-jitter-smoke"
"apps/indexer:attestor-eligibility-smoke"
"apps/indexer:fee-attest-handler-smoke"
"apps/indexer:fee-reward-copy-consistency-smoke"
"apps/indexer:btc-min-confirmations-smoke"
"apps/indexer:explorer-txid-echo-smoke"
"apps/indexer:featurebid-handler-smoke"
"apps/indexer:operator-earnings-smoke"
"apps/indexer:db-password-placeholder-smoke"
"apps/indexer:indexer-result-shape-smoke"
"apps/indexer:duplicate-import-smoke"
"apps/indexer:handler-coverage-smoke"
"apps/indexer:fee-status-filter-lint"
"apps/indexer:rss-orderbook-smoke"
"apps/indexer:rss-orderbook-xml-validate"
"apps/indexer:rss-orderbook-filters-smoke"
"apps/indexer:orderbook-side-barter-flip-smoke"
"apps/indexer:operator-register-handler-smoke"
"apps/indexer:reconcile-registrations-smoke"
"apps/indexer:operator-payment-method-handler-smoke"
"apps/indexer:reserved-keys-parity-smoke"
"apps/indexer:schema-drift-smoke"
"apps/indexer:confusables-parity-smoke"
"apps/indexer:forbidden-char-consistency-smoke"
"apps/indexer:frontend-chatlink-env-doc-parity-smoke"
"apps/indexer:federation-probe-smoke"
"apps/indexer:dns-rebinding-defense-smoke"
"apps/indexer:instances-stream-smoke"
"apps/indexer:orderbook-stream-smoke"
"apps/indexer:orderbook-block-enforcement-smoke"
"apps/indexer:chat-stream-smoke"
"apps/indexer:chat-payload-smoke"
"apps/indexer:head-tailer-validation-parity-smoke"
"apps/indexer:fastpath-order-scope-smoke"
"apps/indexer:chat-blurt-verify-smoke"
"apps/indexer:trade-status-smoke"
"apps/indexer:listener-dispatch-smoke"
"apps/indexer:asset-registry-smoke"
"apps/indexer:handler-test-stand-in-meta-assertion-smoke"
"apps/indexer:per-asset-rss-feed-parity-smoke"
"apps/indexer:ansible-env-template-required-vars-smoke"
"apps/indexer:disabled-assets-parse-smoke"
"apps/indexer:disabled-payment-methods-parse-smoke"
"apps/indexer:order-views-smoke"
"apps/indexer:profile-handler-smoke"
"apps/indexer:explorer-activity-smoke"
"apps/indexer:explorer-search-smoke"
"apps/indexer:explorer-urls-smoke"
"apps/indexer:loyalty-welcome-smoke"
"apps/indexer:onion-location-smoke"
"apps/indexer:pending-feedback-reminders-smoke"
"apps/indexer:pwa-manifest-smoke"
"apps/web:posting-verify-smoke"
"apps/indexer:release-validator-smoke"
"apps/indexer:treasury-source-smoke"
"apps/indexer:canonical-treasury-smoke"
"apps/indexer:treasury-mismatch-probe-smoke"
"apps/indexer:release-broadcast-smoke"
"apps/indexer:balance-math-smoke"
"apps/indexer:payments-smoke"
"apps/indexer:pnl-smoke"
"apps/indexer:wif-smoke"
"apps/indexer:yubikey-protocol-smoke"
"apps/indexer:clearing-price-history-smoke"
"apps/indexer:login-pairing-registry-smoke"
"apps/indexer:schema-migration-coverage-smoke"
"apps/relay:drain-defense-live-fire"
"apps/relay:hmac-secret-placeholder-smoke"
"apps/relay:drainer-defense-smoke"
"apps/relay:clock-drift-smoke"
"apps/relay:key-envelope-smoke"
"apps/relay:push-category-optin-smoke"
"apps/relay:push-tag-dedup-smoke"
"apps/relay:notification-latency-budget-smoke"
"apps/relay:fee-divergence-smoke"
"apps/relay:ip-bucketing-canonicalization-smoke"
"apps/relay:trusted-proxy-smoke"
"apps/relay:squatter-defense-smoke"
"apps/relay:account-create-op-smoke"
"apps/relay:vapid-key-validation-smoke"
"apps/ops-cli:ops-cli-smoke"
"apps/ops-cli:account-suggestion-smoke"
"apps/ops-cli:altnet-address-format-smoke"
"apps/ops-cli:instance-name-quoting-smoke"
"apps/ops-cli:doctor-smoke"
"apps/ops-cli:canary-dir-owner-smoke"
"apps/ops-cli:status-backups-smoke"
"apps/ops-cli:db-container-detect-smoke"
"apps/ops-cli:indexer-state-columns-smoke"
"apps/ops-cli:db-query-columns-smoke"
"apps/ops-cli:fast-forward-smoke"
"apps/ops-cli:local-block-smoke"
"apps/ops-cli:moderation-smoke"
"apps/ops-cli:moderation-signal-coverage-smoke"
"apps/indexer:feedback-list-summary-parity-smoke"
"apps/ops-cli:menu-annotations-smoke"
"apps/ops-cli:mcp-toggle-smoke"
"apps/ops-cli:matrix-bot-lifecycle-smoke"
"apps/ops-cli:matrix-test-command-smoke"
"apps/ops-cli:rpc-endpoint-probe-smoke"
"apps/ops-cli:rpc-endpoint-canon-smoke"
"apps/ops-cli:ssl-smoke"
"apps/ops-cli:bunkerweb-smoke"
"apps/ops-cli:health-view-smoke"
"apps/ops-cli:canary-timestamp-parity-smoke"
"apps/ops-cli:system-check-os-smoke"
"apps/ops-cli:register-diagnostics-smoke"
"apps/ops-cli:offline-account-lookup-smoke"
"apps/ops-cli:init-smoke"
"apps/ops-cli:init-progress-smoke"
"apps/ops-cli:init-resume-wiring-smoke"
"apps/ops-cli:tor-onion-smoke"
"apps/ops-cli:i2p-destination-smoke"
"apps/ops-cli:tor-wizard-wiring-smoke"
"apps/ops-cli:i2p-wizard-wiring-smoke"
"apps/ops-cli:edit-smoke"
"apps/ops-cli:edit-rpc-smoke"
"apps/ops-cli:edit-active-key-smoke"
"apps/ops-cli:altkeystore-smoke"
"apps/ops-cli:alt-address-wizard-smoke"
"apps/ops-cli:restart-services-smoke"
"apps/ops-cli:ansible-os-derivative-smoke"
"packages/operator-config:operator-config-smoke"
"packages/node-health:node-health-smoke"
"packages/relay-client:contract-symmetry-smoke"
"packages/net-defense:net-defense-smoke"
"packages/rpc-pool:rpc-pool-smoke"
"apps/indexer:blurt-client-rpc-pool-smoke"
"apps/indexer:prefetch-in-order-smoke"
"apps/indexer:btc-quorum-call-integration-smoke"
"apps/web:balance-bus-smoke"
"apps/web:chain-op-verify-smoke"
"apps/web:order-fee-active-auth-smoke"
"apps/web:pay-blurt-modal-gate-smoke"
"apps/web:wallet-op-builders-smoke"
"apps/web:smoke-tsconfig-alias-parity-smoke"
"apps/web:wallet-power-modal-smoke"
"apps/web:send-blurt-modal-smoke"
"apps/web:fee-split-smoke"
"apps/web:yubikey-error-classifier-smoke"
"apps/web:fingerprint-smoke"
"apps/web:chat-self-copy-smoke"
"apps/web:chat-security-preference-smoke"
"apps/web:chat-shippable-gating-smoke"
"apps/web:conversation-order-ref-smoke"
"apps/web:chat-scroll-to-newest-smoke"
"apps/web:payment-receipt-presentation-smoke"
"apps/web:terms-markdown-presentation-smoke"
"apps/web:order-pay-amount-smoke"
"apps/web:order-role-smoke"
"apps/web:terms-markdown-smoke"
"apps/web:identicon-data-uri-smoke"
"apps/web:seed-backup-print-one-page-smoke"
"apps/web:libsodium-not-in-baseline-closure-smoke"
"apps/web:crypto-blurt-not-in-baseline-closure-smoke"
"apps/web:split-on-placeholder-smoke"
"apps/web:voucher-locale-parity-smoke"
"apps/web:price-model-display-smoke"
"apps/web:price-model-picker-parity-smoke"
"apps/web:post-form-grandma-regression-smoke"
"apps/web:economics-canonical-smoke"
"apps/web:composite-price-provider-smoke"
"apps/web:desktop-pairing-crypto-smoke"
"apps/web:paired-readonly-lifecycle-smoke"
"apps/web:paired-readonly-affordance-surfaces-smoke"
"apps/web:asset-tab-completeness-smoke"
"apps/web:post-edit-multi-network-wired-smoke"
"apps/web:native-translations-floor-smoke"
"apps/web:i18n-key-coverage-smoke"
"apps/web:i18n-dead-key-gate-smoke"
"apps/web:rss-feed-picker-wiring-smoke"
"apps/web:rss-dynamic-title-smoke"
"apps/web:faq-per-tradable-asset-parity-smoke"
"apps/web:what-is-morphit-asset-enum-smoke"
"apps/web:operator-doc-per-asset-coverage-smoke"
"apps/web:what-is-asset-faq-native-locale-floor-smoke"
"apps/web:per-asset-key-family-native-locale-floor-smoke"
"apps/web:operator-doc-per-asset-config-example-coverage-smoke"
"apps/web:env-example-schema-parity-smoke"
"apps/web:brag-list-kiss-budget-smoke"
"apps/web:brag-list-trailer-invariants-smoke"
"apps/web:faq-keys-themed-section-smoke"
"apps/web:non-zod-env-example-consumer-parity-smoke"
"apps/web:bunkerweb-cidr-cross-reference-smoke"
"apps/web:cross-document-value-invariants-smoke"
"apps/web:operator-doc-section-length-smoke"
"apps/web:ansible-idempotency-discipline-smoke"
"apps/web:vitest-must-pass-smoke"
"apps/web:no-real-time-settimeout-in-tests-smoke"
"apps/web:untrusted-parseint-safety-smoke"
"apps/web:fetch-must-have-timeout-smoke"
"apps/web:seo-routes-i18n-all-locales-smoke"
"apps/web:per-asset-mandatory-family-i18n-parity-smoke"
"apps/web:long-form-en-fallback-floor-smoke"
"apps/web:short-form-en-fallback-floor-smoke"
"apps/web:service-worker-single-registration-smoke"
"apps/web:service-worker-dynamic-data-smoke"
"apps/web:page-title-anchor-smoke"
"apps/web:upgrade-banner-behavior-smoke"
"apps/web:dev-routes-prod-gated-smoke"
"apps/web:i18n-locale-parity-smoke"
"apps/web:i18n-locale-registry-smoke"
"apps/web:rtl-handle-and-footer-tasks-smoke"
"apps/web:explorer-link-lang-prefix-smoke"
"apps/web:locale-source-of-truth-smoke"
"apps/web:onboarding-locale-swap-smoke"
"apps/web:i18n-path-helpers-smoke"
"apps/web:path-adversarial-smoke"
"apps/web:no-stale-top-level-routes-smoke"
"apps/web:no-bare-path-goto-smoke"
"apps/web:static-asset-link-reload-smoke"
"apps/web:indexer-url-composition-smoke"
"apps/matrix-bot:classifier-smoke"
"apps/matrix-bot:rate-limiter-smoke"
"apps/matrix-bot:surface-invariant-smoke"
"apps/mcp-server:mcp-server-smoke"
"apps/mcp-server:mcp-http-transport-smoke"
"apps/mcp-server:fetchjson-body-cap-smoke"
"apps/mcp-server:private-instance-policy-smoke"
"apps/mcp-server:agent-field-allowlist-smoke"
"apps/web:canary-template-smoke"
"packages/asset-registry:asset-registry-smoke"
".:operations-hardening-smoke"
".:systemd-unit-install-smoke"
".:mcp-webpush-install-defaults-smoke"
".:mcp-tool-name-parity-smoke"
".:csp-header-consistency-smoke"
".:price-feed-health-header-strip-smoke"
".:workspace-membership-smoke"
".:operator-doc-fenced-path-existence-smoke"
".:operator-doc-section-ref-smoke"
".:operator-doc-env-var-parity-smoke"
".:license-disclosure-smoke"
".:handler-push-click-path-route-smoke"
".:fast-badge-push-contract-smoke"
".:backup-script-posix-safety-smoke"
".:backup-install-parity-smoke"
".:chat-inbox-instant-subject-smoke"
".:health-backup-freshness-smoke"
".:indexer-public-health-operational-smoke"
".:postgres-pg-hba-loopback-smoke"
".:indexer-relay-account-smoke"
".:ansible-shared-script-dir-smoke"
".:ansible-offline-apt-gate-smoke"
".:offline-bundle-git-smoke"
".:canary-serve-dir-smoke"
".:reachability-check-smoke"
".:onion-frontend-target-smoke"
".:relay-health-probe-smoke"
".:onion-location-header-smoke"
".:pwa-install-button-smoke"
".:hidden-service-origin-smoke"
".:directory-card-hidden-service-smoke"
".:tor-routed-probe-smoke"
".:tor-only-install-smoke"
".:ansible-aide-deferred-smoke"
".:moderation-flag-clearance-smoke"
".:profile-link-glyphs-single-home-smoke"
".:reserved-name-owner-parity-smoke"
".:orderbook-freshness-contract-smoke"
".:orderbook-wire-status-parity-smoke"
".:sidecar-shell-quoting-smoke"
".:sidecar-envelope-error-path-smoke"
".:last-char-tamper-anti-pattern-smoke"
".:witness-chat-identity-claimed-op-smoke"
".:no-master-password-in-fee-flows-smoke"
".:verify-download-smoke"
".:release-notes-asset-count-parity-smoke"
".:canary-rpc-failover-smoke"
".:canary-btc-failover-smoke"
".:canary-setup-smoke"
".:now-in-handler-sql-smoke"
"apps/web:i18n-hardcoded-english-smoke"
"apps/web:i18n-raw-exception-smoke"
"apps/web:i18n-html-injection-smoke"
"apps/web:href-xss-smoke"
"apps/web:no-bare-internal-href-smoke"
"apps/web:explorer-urls-multi-smoke"
"apps/web:active-owner-key-invariants-smoke"
"apps/web:keygen-public-key-buffer-smoke"
"apps/web:wif-encode-roundtrip-smoke"
"apps/web:change-password-layered-rewrap-smoke"
"apps/web:yubikey-enroll-unlock-smoke"
"apps/web:yubikey-enroll-verify-smoke"
"apps/web:yubikey-transport-mock-smoke"
"apps/web:totp-2fa-enroll-verify-smoke"
"apps/web:seed-normalize-smoke"
"apps/web:key-backup-derivation-smoke"
"apps/web:account-number-detector-smoke"
"apps/web:i18n-formatters-smoke"
"apps/web:public-key-display-smoke"
"apps/web:order-card-smoke"
"apps/web:order-detail-expired-ui-smoke"
"apps/web:lazy-import-catch-fallback-smoke"
"apps/web:chat-pdf-export-smoke"
"apps/web:display-name-cap-smoke"
"apps/web:identity-label-policy-smoke"
"apps/web:onboarding-back-button-smoke"
"apps/web:user-preferences-smoke"
"apps/web:a11y-patterns-smoke"
"apps/web:heading-hierarchy-smoke"
"apps/web:forgejo-not-gitea-smoke"
"apps/web:font-assets-present-smoke"
"apps/web:pair-target-resolve-smoke"
"apps/web:fee-status-label-coverage-smoke"
"apps/web:color-contrast-smoke"
"apps/web:i18n-translation-completeness-smoke"
"apps/web:sally-walkthrough-smoke"
"apps/web:persona-walkthrough-smoke"
"apps/web:mediakit-freshness-smoke"
"apps/web:wiring-completeness-smoke"
"apps/web:chat-asset-ticker-narrow-union-parity-smoke"
"apps/web:network-icon-coverage-smoke"
"apps/web:payment-method-i18n-parity-smoke"
"apps/web:payment-filter-shows-all-methods-smoke"
"apps/web:web-push-wiring-smoke"
"apps/web:npm-audit-gate-smoke"
"apps/web:version-consistency-smoke"
"apps/relay:canonical-message-cross-check-smoke"
"apps/indexer:anti-snipe-extension-smoke"
"packages/asset-registry:fee-method-enum-frozen-smoke"
"packages/asset-registry:fee-split-math-smoke"
"packages/asset-registry:first-buy-waiver-payment-agnostic-smoke"
"packages/asset-registry:usdt-trade-only-smoke"
"packages/asset-registry:usdc-trade-only-smoke"
"packages/asset-registry:dai-trade-only-smoke"
"packages/asset-registry:bch-trade-only-smoke"
"packages/asset-registry:ltc-trade-only-smoke"
"packages/asset-registry:dash-trade-only-smoke"
"packages/asset-registry:doge-trade-only-smoke"
"packages/asset-registry:zec-trade-only-smoke"
"packages/asset-registry:arrr-trade-only-smoke"
"packages/asset-registry:dcr-trade-only-smoke"
"packages/asset-registry:sol-trade-only-smoke"
"packages/asset-registry:eth-trade-only-smoke"
"packages/asset-registry:xrp-trade-only-smoke"
"apps/web:asset-payload-precision-parity-smoke"
"apps/web:blurt-account-regex-parity-smoke"
"apps/web:order-expiry-day-floor-smoke"
".:workspace-typecheck-smoke"
".:smoke-registration-integrity-smoke"
".:smoke-pass-line-canonical-smoke"
"packages/asset-registry:asset-accent-class-uniqueness-smoke"
"packages/asset-registry:payment-rail-coverage-parity-smoke"
"packages/asset-registry:address-shape-overlap-smoke"
"packages/asset-registry:price-provider-coverage-parity-smoke"
"packages/asset-registry:privacy-features-registry-smoke"
"apps/web:address-history-helper-smoke"
"apps/web:amount-jitter-utxo-smoke"
"apps/web:payjoin-uri-wire-shape-smoke"
"apps/ops-cli:disabled-assets-wizard-smoke"
"apps/ops-cli:category-b-descriptions-parity-smoke"
"apps/ops-cli:ansible-structural-smoke"
"apps/ops-cli:first-online-smoke"
"apps/ops-cli:ansible-systemd-user-consistency-smoke"
"apps/ops-cli:repo-root-bak-recovery-smoke"
"apps/ops-cli:instance-env-loader-smoke"
"apps/ops-cli:systemd-js-runtime-af-unix-smoke"
"apps/ops-cli:refresh-units-smoke"
"apps/ops-cli:ansible-env-var-consumer-smoke"
"apps/ops-cli:ansible-lint-smoke"
"apps/matrix-bot:deps-pin-check"
"apps/matrix-bot:sidecar-envelope-smoke"
"apps/matrix-bot:emit-routing-smoke"
"apps/matrix-bot:self-test-route-smoke"
"apps/matrix-bot:json-str-injection-smoke"
"apps/matrix-bot:render-alert-hardening-smoke"
"apps/matrix-bot:matrix-bot-input-hardening-smoke"
"apps/matrix-bot:api-response-shape-smoke"
"apps/matrix-bot:sse-stream-shape-smoke"
"apps/ops-cli:term-sanitize-smoke"
"apps/relay:log-sanitize-smoke"
"apps/indexer:log-sanitize-smoke"
"apps/ops-cli:workspace-deps-pin-check"
"apps/ops-cli:upgrade-fetch-hardening-smoke"
"apps/ops-cli:upgrade-mirror-smoke"
"apps/ops-cli:indexer-health-metrics-smoke"
"apps/ops-cli:upgrade-frontend-deploy-smoke"
"apps/ops-cli:upgrade-backup-prune-smoke"
"apps/ops-cli:upgrade-schema-reminder-smoke"
"apps/ops-cli:fastpath-always-on-smoke"
"apps/ops-cli:upgrade-rebuilds-dist-workspaces-smoke"
"apps/ops-cli:upgrade-mcp-reachability-smoke"
"apps/ops-cli:install-invariants-smoke"
"apps/ops-cli:compiled-bundle-smoke"
"packages/asset-registry:usdt-network-picker-required-smoke"
".:brag-list-claim-parity-smoke"
".:seo-url-consistency-smoke"
"apps/web:og-fallback-meta-smoke"
"apps/web:release-tamper-deploy-skew-smoke"
"apps/web:balance-locale-sign-colors-smoke"
"apps/web:llms-full-freshness-smoke"
"apps/web:llms-txt-freshness-smoke"
"apps/web:build-manifest-release-json-smoke"
"apps/web:logo-bling-invariants-smoke"
"apps/web:coin-carousel-invariants-smoke"
"apps/web:svelte-component-import-coverage-smoke"
"apps/web:text-input-maxlength-coverage-smoke"
"apps/web:privacy-asset-sitemap-parity-smoke"
"apps/web:faq-jsonld-no-markdown-smoke"
"apps/web:faq-inline-render-smoke"
"apps/web:faq-glossary-terms-smoke"
"apps/web:faq-scroll-block-start-smoke"
"apps/web:footer-alt-network-pills-gated-smoke"
"apps/web:update-banner-user-consent-smoke"
"apps/web:nav-arrow-consistency-smoke"
"apps/web:locked-session-ux-smoke"
"apps/web:require-live-session-smoke"
"apps/web:autolock-settings-smoke"
"apps/web:faq-deeplink-smoke"
"apps/web:broadcast-same-origin-smoke"
"apps/web:settings-profile-keys-account-scoped-smoke"
"apps/web:endpoint-error-classify-smoke"
"apps/web:address-share-modal-ux-smoke"
"apps/web:rpc-privacy-routing-smoke"
"apps/web:onchain-user-privacy-smoke"
"apps/web:settings-chain-crypto-smoke"
"apps/web:order-completion-semantics-smoke"
"apps/relay:push-dedup-survives-delivery-smoke"
"apps/indexer:profiles-batch-accounts-anchored-smoke"
"apps/indexer:trade-count-semantics-smoke"
"apps/web:privacy-headline-length-smoke"
"apps/web:carrier-registry-invariants-smoke"
"apps/web:shipping-payload-roundtrip-smoke"
"apps/web:order-settled-elsewhere-payload-smoke"
"apps/web:settled-elsewhere-announce-smoke"
"apps/web:2fa-no-google-recommendation-smoke"
"apps/web:2fa-recommended-apps-coverage-smoke"
"apps/web:2fa-locale-parity-smoke"
"apps/web:comparison-image-freshness-smoke"
"apps/web:asset-select-coverage-smoke"
"apps/web:disabled-payment-methods-ui-coverage-smoke"
"apps/web:footer-contact-flash-smoke"
"apps/web:endpoint-list-throttle-smoke"
"apps/web:orderbook-hide-confirm-smoke"
"apps/web:orderbook-select-stacking-smoke"
"apps/web:orderbook-live-status-wired-smoke"
"apps/web:faq-search-grandma-coverage-smoke"
"apps/web:ip-disclosure-single-source-smoke"
"apps/web:push-privacy-honesty-smoke"
"apps/web:identity-label-truncation-smoke"
"apps/web:block-time-vs-wall-clock-smoke"
"apps/indexer:rpc-user-agent-smoke"
"apps/indexer:batch-4xx-single-fallback-smoke"
"apps/web:chat-inbox-motion-smoke"
"apps/web:modal-viewport-fit-smoke"
".:rpc-batch-contract-smoke"
".:public-doc-drift-smoke"
"apps/web:import-remember-me-smoke"
"apps/web:import-account-auto-resolve-smoke"
"apps/web:accountless-banner-smoke"
"apps/web:unlock-redirect-next-smoke"
"apps/web:cross-tab-signout-propagation-smoke"
"apps/web:update-banner-deployed-version-poll-smoke"
"apps/web:update-surface-nocache-config-smoke"
"apps/web:canary-link-no-locale-prefix-smoke"
"apps/web:chat-unread-count-wired-smoke"
"apps/web:pay-blurt-modal-errors-smoke"
"apps/web:chat-realtime-cadence-smoke"
"apps/web:my-orders-card-cluster-smoke"
"apps/web:copy-button-green-check-smoke"
"apps/web:order-detail-posting-retry-smoke"
"apps/web:txid-hash-clarity-smoke"
"apps/web:chat-header-reputation-smoke"
"apps/web:avatar-size-thresholds-smoke"
"apps/web:storage-key-classification-smoke"
"apps/web:settings-visibility-scope-smoke"
"apps/web:order-card-message-visibility-smoke"
"apps/web:profile-hydrate-retry-smoke"
"apps/web:order-card-identity-first-paint-smoke"
"apps/web:identity-no-swap-smoke"
"apps/web:profile-account-change-reload-smoke"
"apps/web:profile-freshness-smoke"
"apps/web:profile-website-url-smoke"
"apps/web:canary-ascii-and-dates-smoke"
"apps/web:chat-day-separator-smoke"
"apps/web:cancel-redirect-and-relist-smoke"
"apps/web:feature-pills-fiat-smoke"
"apps/web:support-operator-matrix-removed-smoke"
"apps/web:featured-bid-history-modal-smoke"
"apps/web:featured-order-copy-smoke"
"apps/web:featured-card-reputation-smoke"
"apps/web:ui-polish-batch-smoke"
"apps/web:ken-batch-2-smoke"
"apps/web:pay-now-active-key-smoke"
"apps/web:chat-notification-wiring-smoke"
"apps/web:posting-active-upgrade-smoke"
"apps/web:chat-header-layout-smoke"
"apps/web:account-binding-smoke"
"apps/web:eli5-release-blocks-smoke"
"apps/web:avatar-menu-portal-smoke"
"apps/web:trust-score-modal-portal-smoke"
"apps/web:chat-inbox-threading-smoke"
"apps/web:explorer-download-polish-smoke"
"apps/web:chat-read-state-threading-smoke"
"apps/web:no-bare-root-href-in-lang-subtree-smoke"
"apps/web:balance-via-indexer-not-rpc-smoke"
"apps/web:account-history-via-indexer-smoke"
"apps/web:chain-explorer-via-indexer-smoke"
"apps/web:external-link-hygiene-smoke"
"apps/web:blurt-image-link-safety-smoke"
"apps/web:removed-static-asset-guard-smoke"
"apps/web:login-key-verify-via-indexer-smoke"
"apps/web:explorer-manual-refresh-smoke"
"apps/web:explorer-account-card-smoke"
"apps/web:explorer-op-label-values-parity-smoke"
"apps/web:explorer-json-highlight-safety-smoke"
"apps/web:terms-forbidden-char-parity-smoke"
"apps/web:orderbook-terms-highlight-safety-smoke"
"apps/web:instances-alt-network-links-smoke"
"apps/web:blurt-apr-smoke"
"apps/web:first-trade-buy-blurt-lock-smoke"
"apps/web:chat-folders-onchain-smoke"
"apps/web:instances-current-by-origin-smoke"
"apps/web:chat-thread-model-smoke"
"apps/web:chat-order-tag-storage-smoke"
"apps/web:chat-thread-remount-smoke"
"apps/web:chat-bg-notify-v148-smoke"
"apps/web:chat-ui-v148-smoke"
"apps/web:chat-sent-state-smoke"
"apps/web:chat-notif-default-on-smoke"
"apps/web:chat-notif-nudge-smoke"
"apps/web:claim-reward-balance-smoke"
"apps/web:syndication-first-trade-post-smoke"
"apps/web:chat-blocks-race-guard-smoke"
"apps/web:chat-pay-now-flow-smoke"
"apps/web:chat-own-sent-plaintext-cache-smoke"
"apps/web:chat-immersive-layout-smoke"
"apps/web:chat-fastpath-dedup-smoke"
"apps/indexer:reputation-decay-smoke"
"apps/indexer:reputation-score-smoke"
"apps/indexer:posting-key-storage-smoke"
"apps/indexer:reputation-decay-sql-constant-parity-smoke"
"apps/indexer:reputation-receipt-shape-smoke"
"apps/indexer:stablecoin-depeg-detector-smoke"
"apps/indexer:morphit-native-fetcher-smoke"
"apps/indexer:price-source-hardening-smoke"
"apps/indexer:price-primary-fallback-smoke"
"apps/indexer:price-input-block-enforcement-smoke"
"apps/indexer:peer-price-monitor-smoke"
"apps/indexer:price-fetch-util-smoke"
"apps/indexer:crypto-fetcher-smoke"
"apps/indexer:fee-tolerance-smoke"
"apps/indexer:treasury-repin-smoke"
"apps/indexer:fx-endpoint-smoke"
"apps/indexer:price-feeds-health-smoke"
"apps/indexer:fx-source-smoke"
"apps/indexer:multi-asset-factory-smoke"
".:spawn-dist-prebuild-coverage-smoke"
".:lockfile-sync-smoke"
".:tsx-runtime-dependency-smoke"
".:ci-workflow-hardening-smoke"
".:package-files-exist-smoke"
".:mcp-server-read-only-invariant-smoke"
".:source-marketing-prose-smoke"
".:strip-comments-smoke"
".:no-sandbox-path-smoke"
".:no-docker-latest-tag-smoke"
".:wizard-step-count-doc-parity-smoke"
".:root-shell-then-redirect-smoke"
".:blurt-noble-signer-recovery-proof"
".:blurt-noble-tx-signature-proof"
".:signer-backend-consistency-smoke"
"apps/web:chat-feedback-cancel-smoke"
"apps/web:chat-notif-nudge-gate-smoke"
"apps/web:archived-thread-not-unread-smoke"
"apps/web:import-eager-self-avatar-smoke"
"apps/web:order-blog-post-mirror-smoke"
"apps/web:barter-specific-title-smoke"
"apps/web:order-title-crypto-ticker-smoke"
"apps/web:rtl-bidi-smoke"
".:ipns-release-wiring-smoke"
".:ipns-dht-rebroadcast-smoke"
".:ipfs-release-hosting-smoke"
".:ipfs-selfseed-smoke"
".:ddns-setup-smoke"
".:reboot-recovery-smoke"
".:upgrade-notify-smoke"
".:matrix-login-smoke"
".:setup-bootstrap-smoke"
".:ddns-role-smoke"
".:ansible-vars-smoke"
".:save-secrets-smoke"
".:collect-install-inputs-smoke"
".:assemble-install-smoke"
".:relay-keystore-content-smoke"
".:local-install-smoke"
".:install-summary-smoke"
".:smoke-runner-count-extraction-smoke"
"apps/web:profile-persistent-cache-smoke"
)
total=0
failed=0
# Per-invocation tempfile prevents concurrent runs from racing on
# the same /tmp/smoke.out and producing transient miscounts.
SMOKE_OUT="$(mktemp -t morphit-smoke.XXXXXX.out)"
trap 'rm -f "$SMOKE_OUT"' EXIT
for entry in "${SMOKES[@]}"; do
dir="${entry%:*}"
name="${entry##*:}"
path="$repo/$dir/scripts/$name.ts"
if [ ! -f "$path" ]; then
echo "$name (file missing: $path)"
failed=$((failed + 1))
continue
fi
# Smoke tsconfig selection (cp63 LL #66; per-workspace override cp448).
# The repo-root `tsconfig.smoke.json` is the unified default — it merges
# path aliases from apps/web ($lib, $components, ...) and apps/indexer
# ($api, $config, ...) so cross-workspace smoke imports resolve, and a
# smoke that uses no alias doesn't care (tsx ignores the paths block).
#
# BUT a few SvelteKit `$`-aliases are PER-APP and genuinely conflict:
# `$blurt`/`$indexer` mean apps/web/src/lib/{blurt,indexer} in the web
# app and apps/indexer/src/{blurt,indexer} in the indexer. A single
# flat `paths` map can't express both, so the root config maps them to
# the indexer. A workspace that needs its own resolution ships its own
# `<workspace>/tsconfig.smoke.json` (apps/web does, so its smokes can
# `import()` a `$blurt/*`-importing web module without the module
# silently binding the indexer's copy). Prefer the workspace-local
# config when present, else the unified root config.
# `smoke-tsconfig-alias-parity-smoke.ts` keeps both in sync with the
# runtime aliases in svelte.config.js / apps/indexer/tsconfig.json.
if [ -f "$repo/$dir/tsconfig.smoke.json" ]; then
TSX_ARGS=(--tsconfig "$repo/$dir/tsconfig.smoke.json")
elif [ -f "$repo/tsconfig.smoke.json" ]; then
TSX_ARGS=(--tsconfig "$repo/tsconfig.smoke.json")
else
TSX_ARGS=()
fi
# Per-smoke wall-clock timeout (cp143). cp142 closed a CI-bomb
# where `apps/mcp-server/scripts/mcp-server-smoke.ts` hung
# indefinitely on fresh checkouts (no built dist/main.js → child
# never produced stdout → smoke waited forever). The cp142 fix
# was static (lazy-build + meta-smoke), this is the runtime
# complement: any future smoke that hangs gets converted into a
# legible "killed after N seconds" failure instead of stalling
# the whole CI job until the action runner's hard timeout.
#
# 240 seconds is the ceiling. The current slow-pole is
# `apps/web/scripts/vitest-must-pass-smoke.ts` which spawns
# real `vitest run` invocations across apps/{indexer,relay,web}
# — 981 unit tests in jsdom — and clocks ~150s on this hardware.
# 240s gives ~1.6× buffer for slow CI hosts and cold caches.
# Every other smoke clocks under 15s. If a real smoke ever
# legitimately approaches 240s, bump this constant AND ask why
# the smoke got that slow (probably means it's doing too much
# in one file).
#
# Override via MORPHIT_SMOKE_TIMEOUT env var for slower hosts.
# `timeout` exits 124 on SIGTERM expiry / 137 on SIGKILL,
# distinguishable from smoke's own non-zero exits.
SMOKE_TIMEOUT="${MORPHIT_SMOKE_TIMEOUT:-240}"
if (cd "$repo/$dir" && timeout --signal=TERM --kill-after=5 "$SMOKE_TIMEOUT" "$TSX" "${TSX_ARGS[@]}" "scripts/$name.ts" >"$SMOKE_OUT" 2>&1); then
# Smokes MUST emit a canonical `✓ all N ...` line so this runner
# can tally scenarios. Without that line, the smoke is treated as
# a runner failure rather than silently counted as 0 — see J-1
# (silent zero counting from empty arithmetic) and J-2 (sally
# emitted a custom format and was undercounted by 22 for ~20
# Parts) findings, Part 87.
# Anchor the count extraction at the line start (^✓ all N) — NOT
# `.*all `: a greedy `.*all ` matches the "all " inside a smoke NAME
# like assemble-INSTALL / local-INSTALL and captures an empty count,
# which mis-reported those two as "no canonical line" on 2026-07-30
# (they print the line fine; the runner mis-parsed it). grep already
# guarantees the line begins with `✓ all`.
n=$(grep "^✓ all" "$SMOKE_OUT" | sed "s/^✓ all \([0-9]*\).*/\1/")
if [ -z "$n" ] || [ "$n" -eq 0 ] 2>/dev/null; then
failed=$((failed + 1))
echo "$name (passed runner but emitted no canonical '^✓ all N …' line — fix the smoke to print it)"
tail -30 "$SMOKE_OUT" | sed 's/^/ /'
continue
fi
total=$((total + n))
else
exit_code=$?
failed=$((failed + 1))
# Distinguish timeout (124/137) from smoke-emitted non-zero.
if [ "$exit_code" -eq 124 ] || [ "$exit_code" -eq 137 ]; then
echo "$name (HUNG — killed after ${SMOKE_TIMEOUT}s; this is the cp142 bug class — see scripts/spawn-dist-prebuild-coverage-smoke.ts)"
else
echo "$name (exit $exit_code)"
fi
tail -30 "$SMOKE_OUT" | sed 's/^/ /'
fi
done
echo
echo "──────────────────────────────────────────────────────"
echo "Total: $total scenarios passed, $failed runners failed"
if [ "$failed" -ne 0 ]; then
exit 1
fi