[BUG] design-sync truncates prop JSDoc mid-word at 120 chars with no marker (lib/dts.mjs:434)

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 0 comments · opened Aug 3, 2026

What happens

/design-sync truncates every prop JSDoc comment at exactly 120 characters when emitting <Name>.d.ts and <Name>.prompt.md — cutting mid-word, with no ellipsis or marker of any kind.

design-sync/lib/dts.mjs:434:

if (doc) lines.push(`  /** ${doc.replace(/\s+/g, ' ').slice(0, 120)} */`);

What it looks like in the published output

From a synced project, verbatim:

/** Required, not optional: an unlabelled tablist is precisely the accessibility defect this component exists to stop shippi */
"aria-label": string;

/** Classes for the wrapper element that holds the label, field and error text. `className` targets the `<select>` itself —  */
containerClassName?: string;

The second one ends on an em dash and a trailing space — the clause that was about to do the explaining is the half that got cut.

Why this is worse than a cosmetic truncation

These comments are not only read as types. They are embedded in each <Name>.prompt.md, which is injected verbatim into every design agent's prompt — so a truncated comment is misinformation the agent re-reads on every run.

The truncation is also not random about what it removes. A common house convention for prop docs is to state the rule and then explain why. At a fixed character cap, the rule survives and the reason is deleted — which is the opposite of what you would choose if you had to drop half. In the example above, the agent learns aria-label is required but not that an unlabelled tablist is the defect the component exists to prevent.

And because the cut is mid-word with no marker, an agent (or a human) cannot distinguish an abbreviated comment from a corrupted file. That undermines confidence in the generated contract, which is otherwise the most trustworthy artifact in the project precisely because it is generated.

The same file already handles this correctly, 178 lines earlier

lib/dts.mjs:256 caps very wide unions and annotates the truncation:

if (uniq.length > 24) uniq = [...uniq.slice(0, 16), `(string & {}) /* +${uniq.length - 16} more */`];

Same file, same concern — bounding output size — but here the reader is told exactly how much was dropped. That inconsistency is why I think line 434 is an oversight rather than a deliberate tradeoff.

Suggested fix

Not "raise the cap." A cap is defensible, since these strings are injected into every prompt and unbounded doc comments would bloat it.

The ask is to make the truncation honest, matching what line 256 already does:

  • cut on a word or sentence boundary rather than mid-word, and
  • append a marker (, or /* +N chars */ in the style of the union cap)

Either alone would be a large improvement; a comment that visibly stops is far better than one that appears complete and isn't.

Scale, in one real project

Across an 11-component design system, 6 of 27 prop doc comments exceeded the cap and are silently truncated in the published output — just under a quarter. Two were more than 230 characters, losing over half their text.

Secondary: a second, different truncation

lib/dts.mjs:541 applies a different budget (140) and strips characters outside a whitelist:

?.trim().replace(/\s+/g, ' ').replace(/[^\w\s.,()'/:+-]/g, '').slice(0, 140) ?? ''

Em dashes, backticks and quotes are removed rather than escaped. I have not traced which artifact this feeds, so I am flagging rather than claiming — but a silent character strip is the same class of surprise as a silent truncation.

A downstream effect worth mentioning

Because the cap is a hard-coded literal in the skill's own library rather than a cfg.* override, it cannot be configured or worked around by the consuming repo. grep -r ASSUMPTION — the documented way to find adjustable heuristics — does not surface it.

The practical consequence is that the limit reaches backwards into what gets authored: we now write prop doc comments deliberately short to fit under a cap that is invisible in the repo and undocumented anywhere the author would look.

Environment

  • Claude Code 2.1.220
  • macOS (darwin 24.6.0)
  • design-sync bundled skill, storybook shape, React + TypeScript design system

View original on GitHub ↗