Skip to content

fix(studio): Studio's own text reads without em or en dashes - #5414

Merged
miguel-heygen merged 5 commits into
mainfrom
fix/studio-copy-without-dashes
Oct 10, 2026
Merged

miguel-heygen merged 5 commits into
mainfrom
fix/studio-copy-without-dashes

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

What

Text a person reads in Studio no longer uses em dashes (—) or en dashes (–). That covers Studio's own tooltips, toasts, empty states, errors and labels, and the messages it shows from other packages: lint findings, SDK save refusals, studio-server errors, audio FX and preset copy from core, and render errors from the producer and engine. They now use a colon, a comma, a period, parentheses, or "to" for a range. A new lint check keeps it that way.

Why

Studio's text should use plain punctuation, and the dashes were used inconsistently across it. A lint check is the root fix: without it, new text brings them back.

Related work

None.

How

  • scripts/check-studio-copy-dashes.mjs parses every non-test .ts/.tsx file under src in studio, core, engine, lint, parsers, player, producer, sdk, shader-transitions and studio-server with the TypeScript compiler. It fails on U+2013 or U+2014 inside string literals, template literal parts and JSX text. It reads the parsed value, so an escaped — counts too, and it also catches —, – and their numeric forms, which JSX keeps raw and React renders as dashes. Comments, regex literals and test files are not checked. It runs in the root lint script as check:studio-copy-dashes; its test is in test:scripts.
  • On main it reports 304 hits: studio 106, producer 51, lint 50, core 42, engine 38, sdk 6, player 5, parsers 2, shader-transitions 2, studio-server 2. Each was rewritten by hand:
    • a pause became a colon, a comma, "so", or a new sentence (Copy failed — check permissions → Copy failed. Check permissions, Linked audio would start after the new end — unlink or trim → ... after the new end. Unlink or trim);
    • a range became "to" (0.0s – 10.0s → 0.0s to 10.0s, try 600–1000 → try 600 to 1000);
    • a lone dash used as an empty value became a word: the Peak Amplitude readout shows Unavailable (no measurable peak), an unset in/out point in the shortcuts panel shows Not set, the text-case "none" button shows None, and the select placeholder — select branch — became Select branch.
    • where the dash sat in a comment inside code that ships as a string (audio worklet source, GLSL, player CSS, injected page scripts), the comment was reworded the same way; behaviour is unchanged.
  • No hyphen was swapped in for a dash.
  • Two narrow exemptions, each matched on its exact text in its file:
    • core/src/compiler/compositionScoping.ts: a comment inside injected runtime JS ("Swallow — the scoped root ..."). It is copied byte for byte into the producer's regression goldens and the docs catalog payloads, and no person reads it.
    • core/src/figma/mediaIndex.ts: the "—" empty cell of .media/index.md, a file written for agents. It must stay identical to the two media-use copies of the same generator, which a parity test enforces.
  • Not scanned, because Studio never shows their text: cli (terminal output), aws-lambda, gcp-cloud-run, sdk-playground, and Studio's dev-only vite.config.ts.
  • Tests that asserted the old text were updated (studio, engine hdr, producer hdrMode, cli checkBrowser, studio sdkCutover.linkedTiming). packages/producer/de-gatecheck.sh greps one engine log line and now matches the new wording. docs/studio/animation.mdx quotes the new "Computed value" notice.

Review

Independent adversarial review of the Studio-only commits: no blocking findings. Should-fix items were addressed: the docs line, HTML entities in the check, test coverage for every node kind and the file filter, and the empty peak value wording.

Test plan

  • Check on main (bb9e507): exit 1, 304 hits (per package above). On this branch: passes.

  • Gate test: 5/5 pass, 3 runs in a row. Each mutation fails it: removing any checked node kind, narrowing the file filter to .ts, dropping or narrowing any entity form, dropping the case-insensitive flag, dropping a package from the scan, or widening an exemption.

  • bun run lint and bun run format:check: green.

  • Typecheck green for core, engine, producer, lint, sdk, parsers, player, shader-transitions, studio-server, cli and studio.

  • Test suites (Linux): core 198 files, engine 91, producer 54, lint 20, sdk 23, parsers 45, player 17, shader-transitions 6, studio-server 69, studio 694, all passing. cli: 306 files pass. 2 files (browser/launch.process, motion-signature.browser.chromium) fail the same way with and without this change, from timeouts launching the browser on that machine.

  • Changed test files pass 3 runs in a row.

  • Before/After captures of the Linked Selection tooltip from the Studio dev server on the product-promo registry example.

  • Unit tests added/updated

  • Manual testing performed

  • Documentation updated (if applicable)

  • Comments follow CONTRIBUTING.md "Comments": they say why, not what, and a bug fix says what the code must do and how to reproduce the bug

Before

Before: Linked Selection tooltip with an em dash

After

After: Linked Selection tooltip with a colon

@mintlify

mintlify Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Oct 10, 2026, 8:46 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 2061 (base branch 2061), smooth 1609 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

@somanshreddy somanshreddy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at 84453ca8.

The check

  • check-studio-copy-dashes.mjs reports 304 hits on the merge base 6f3f86a9 (run with the head's checker) and 0 at head. Its test passes 5/5.
  • All 7 mutants of the checker are killed:
    • dropping JsxText, TemplateHead or TemplateTail
    • dropping the —/numeric-entity alternatives
    • em-dash only (no en dash)
    • scanning test files
    • widening the equals exemption
  • No .js/.mjs/.jsx/.css/.html/.json files under the 10 scanned src dirs carry a dash, so restricting the scan to .ts/.tsx leaves no gap today.
  • It is wired into the root lint script, and its test is in test:scripts.

Output contracts (the rewording is where this could break something)

  • In-repo matchers still match. renderChunk.ts:286 and captureCost.ts:510 match /Frame still pending/, and the new screenshotService.ts:134 text still contains it. de-gatecheck.sh was updated for the falling back to … capture line.
  • I found no other consumers. I grepped the rest of the tree (scripts, skills, cli, docs) for the reworded log and error prefixes: HDR auto-promotion, No HDR sources detected, falling back to SDR, Continuing render, pinning to 1, __player was never set, outputResolution is not supported, Failed to download CDN script. The only hits are the changed sources and their updated tests. The cli's Continuing render despite lint … is its own string.
  • No EF caller depends on the old wording. The experiment-framework hyperframes render activities and MCP tools don't string-match any of these messages.
  • The shipped-as-string code edits are comment- or message-only. That covers the worklet source, the GLSL frag comments, the player CSS comment, injected runtime console.warns and the HyperShader warnings. GLSL // comments are unaffected by the colon and parenthesis rewording.

CI: all required checks are green, the edit accuracy gate included. No reviews or CRs yet.

Nit (not verified): some reworded engine/producer log lines are operational, e.g. [engine] fast capture: falling back to … and [BeginFrame] Frame still pending …. If a Datadog log monitor or saved search keys on the old — text, it will stop matching. Nothing in either repo does, but I didn't audit Datadog.

Review by Somu

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 10, 2026
Merged via the queue into main with commit 9825614 Oct 10, 2026
96 checks passed
@miguel-heygen
miguel-heygen deleted the fix/studio-copy-without-dashes branch October 10, 2026 19:26
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.

2 participants