Skip to content

fix(tui): pin the automatic JSX runtime in the build config - #1272

Draft
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-self-driving/fixtui-pin-the-automatic-jsx-runtime-so-57aca0
Draft

posthog[bot] wants to merge 1 commit into
mainfrom
posthog-self-driving/fixtui-pin-the-automatic-jsx-runtime-so-57aca0

Conversation

@posthog

@posthog posthog Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Problem

  • A wizard run dies at startup with ReferenceError: React is not defined and shows no TUI at all. The throw is unhandled (onuncaughtexception), so the process is gone before the first frame.
  • Nothing under src/ imports React. The whole TUI depends on the automatic JSX runtime to inject jsx and Fragment.
  • tsdown.config.ts set no JSX option and relied on tsconfig discovery. vitest.config.ts already had to pin esbuild: { jsx: 'automatic' }, which shows the toolchain does not give this for free.
  • Measured blast radius is small so far, and the reported stack path does not exist on main, so this points at a branch build. The same gap would break every run if it shipped.

Changes

  • Pin the runtime instead of discovering it. tsdown.config.ts now sets inputOptions.transform.jsx explicitly, so the built output no longer depends on which tsconfig rolldown finds.
+  inputOptions: {
+    transform: { jsx: { runtime: 'automatic', importSource: 'react' } },
+  },

Important

The object form is required. The documented string form jsx: 'react-jsx' is accepted by the TypeScript types but silently ignored at the napi boundary, and the tsconfig value still wins. I verified both forms against a tsconfig set to "jsx": "react":

transform.jsx value tsconfig says react Output runtime
absent classic classic
'react-jsx' (string) classic classic — pin ignored
{ runtime: 'automatic' } classic automatic — pin holds
  • Guard the pin in the postbuild smoke test. A new check fails the build if any dist/*.js chunk carries React.createElement or React.Fragment. Without it, a future option-shape change would regress the same way, silently.
  • Turn the two module-scope subtitle fragments into components (DEFAULT_SUBTITLE, and the screen-local SUBTITLE), so they build their JSX at render time rather than at import time.

Note

The component conversion is a local improvement, not the fix. About ten content-deck modules under src/lib/programs/*/content/ still hold module-scope arrays of JSX elements, and reshaping that deck API is out of scope here. The build pin plus the smoke check is what actually closes the startup-crash class.

Test plan

Reproduced the exact reported failure, then confirmed the fix removes it

Forcing a classic-runtime build reproduces the reported error verbatim:

ReferenceError: React is not defined
    at file:///.../dist/mint-failure-B2mA9EAq.js:481:19

With the pin restored, node --input-type=module -e "import './dist/bin.js'" loads and prints the banner, and the smoke test passes. The new smoke check also fires on a deliberately classic build, so it is not a no-op.

  • Rendered IntroScreenLayout through ink-testing-library and confirmed the default subtitle still draws both lines.
  • pnpm exec vitest run — 2837 tests across 177 files pass.
  • pnpm build (which runs the smoke test as a postbuild hook) passes.
  • pnpm typecheck reports pre-existing errors on main in files this PR does not touch; none in the changed files.

Created with PostHog Desktop from this inbox report.

Nothing under src/ imports React, so a classic-runtime transform emits
unbound `React.*` references. tsdown had no JSX option and relied on
tsconfig discovery.

Pin `inputOptions.transform.jsx` to the automatic runtime, add a postbuild
smoke check that the pin reaches every chunk, and turn the two module-scope
subtitle fragments into components.

Generated-By: PostHog Desktop
Task-Id: 8fb56a6d-32ed-43b5-aa88-871a9f25117a
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci ai-observability
  • /wizard-ci basic-integration
  • /wizard-ci mcp-analytics
  • /wizard-ci replay-vision
  • /wizard-ci revenue
  • /wizard-ci self-driving
  • /wizard-ci warehouse
  • /wizard-ci warehouse-seeded

Test an individual app:

  • /wizard-ci ai-observability/anthropic
  • /wizard-ci ai-observability/google-adk
  • /wizard-ci ai-observability/groq
Show more apps
  • /wizard-ci ai-observability/manual-capture
  • /wizard-ci ai-observability/openai
  • /wizard-ci ai-observability/openai-agents
  • /wizard-ci ai-observability/opentelemetry
  • /wizard-ci ai-observability/vercel-ai
  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/flutter
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci mcp-analytics/custom-dispatcher
  • /wizard-ci mcp-analytics/typescript-sdk
  • /wizard-ci replay-vision/javascript-node
  • /wizard-ci replay-vision/next-js
  • /wizard-ci replay-vision/react-vite
  • /wizard-ci revenue/stripe
  • /wizard-ci self-driving/astro
  • /wizard-ci self-driving/fastapi
  • /wizard-ci self-driving/nuxt
  • /wizard-ci self-driving/react-router
  • /wizard-ci self-driving/sveltekit
  • /wizard-ci warehouse/monorepo-env
  • /wizard-ci warehouse/multi-source-next
  • /wizard-ci warehouse/stripe-node
  • /wizard-ci warehouse/zero-source
  • /wizard-ci warehouse-seeded/next-stripe
  • /wizard-ci warehouse-seeded/next-stripe-declined

Test against a Context Mill branch:

  • /wizard-ci all context-mill:my-branch

Add context-mill:<branch> to any command above to pin the Context Mill branch. It defaults to main.

Results will be posted here when complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant