Skip to content

fix: keep derived session titles from splitting emoji surrogate pairs - #981

Merged
chiragjn merged 3 commits into
truefoundry:mainfrom
soumojit-D48:fix/session-title-emoji-boundary
Oct 12, 2026
Merged

chiragjn merged 3 commits into
truefoundry:mainfrom
soumojit-D48:fix/session-title-emoji-boundary

Conversation

@soumojit-D48

@soumojit-D48 soumojit-D48 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Derived session titles could end in a lone surrogate when the 50-character cap landed inside an emoji, storing malformed Unicode (visible as a replacement character in the session list). This PR backs off one unit when the cut would split a surrogate pair, so titles stay well-formed while keeping the existing length limit.

Closes #980

Changes

  • packages/trueforge/src/apis/turns.ts: route deriveSessionTitle through a new truncateSessionTitle helper that drops a trailing high surrogate after capping.
  • packages/trueforge/tests/unit/apis/turns.test.ts: new deriveSessionTitle block (cap behavior, short/empty inputs, intact pair inside the cap, split-pair back-off asserting the exact result).
  • .changeset/session-title-surrogate-boundary.md: patch bump for @truefoundry/trueforge.

How was this tested?

  • pnpm --filter @truefoundry/trueforge test -- tests/unit/apis/turns.test.ts: 14/14 pass (9 pre-existing + 5 new).
  • pnpm --filter @truefoundry/trueforge typecheck: exit 0 (src + tests projects).
  • eslint on the changed source file: clean (test files are eslint-ignored per repo config).
  • prettier --check on all changed/added files: pass.
  • Full-workspace pnpm build, pnpm test, and pnpm smoke were NOT run in this environment (Windows); CI covers the rest.

Checklist

  • I have read the contributing guidelines
  • pnpm build, pnpm test, pnpm typecheck, pnpm lint:ci, and pnpm format:check pass locally (package-level test/typecheck/eslint/prettier pass; full workspace gates pending CI — see above)
  • Tests added/updated where it makes sense
  • No hand-edits to generated code (packages/trueforge-sdk, python/trueforge_sdk, .github/fern/openapi/openapi.json, docs/openapi.json) — fork PRs omit SDK regen; maintainers regenerate after merge
  • Docs / .env.example updated if configuration or behavior changed (not needed: no config or operator-visible behavior change beyond the bug fix)

Note

Low Risk
Localized first-turn title derivation and display formatting; no auth, API contract, or persistence schema changes beyond avoiding malformed or blank titles.

Overview
Fixes derived session titles so the 50-character cap no longer cuts through emoji or other multi-code-unit graphemes (surrogate pairs, skin tones, ZWJ sequences).

deriveSessionTitle now caps via a new truncateSessionTitle helper that walks Intl.Segmenter grapheme clusters and omits any cluster that would exceed the limit, instead of using a raw slice. If nothing fits—including when a single cluster is longer than the cap—the function returns undefined so the session store does not persist an empty title on first write.

Unit tests cover length limits, empty input, and several Unicode edge cases; @truefoundry/trueforge gets a patch changeset.

Reviewed by Cursor Bugbot for commit c6acc41. Bugbot is set up for automated code reviews on this repo. Configure here.

@changeset-bot

changeset-bot Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c6acc41

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@truefoundry/trueforge Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@thesujai thesujai 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.

Thanks @soumojit-D48, just one change and this will be good to merge

Comment thread packages/trueforge/src/apis/turns.ts Outdated
@soumojit-D48
soumojit-D48 requested a review from thesujai October 8, 2026 07:21
@soumojit-D48

Copy link
Copy Markdown
Contributor Author

Done — thanks for catching that, the surrogate back-off would indeed have mangled 👋🏽 into 👋.
@thesujai

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9cfd45b. Configure here.

Comment thread packages/trueforge/src/apis/turns.ts
@chiragjn
chiragjn force-pushed the fix/session-title-emoji-boundary branch from 20eab0f to c6acc41 Compare October 11, 2026 07:46
@chiragjn
chiragjn merged commit 87634d8 into truefoundry:main Oct 12, 2026
15 checks passed
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.

Session title corrupted when the first message has an emoji near the length limit

3 participants