[BUG] design-sync truncation marker points to unshipped component docs

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

Environment

  • Claude Code: 2.1.238
  • Bundled skill: design-sync
  • Affected module: lib/docs.mjs
  • Pristine module SHA-256: bb0465b065d9f29722a9453c869b70c73f85337b748d1be28800e2999be4626e

Problem

The bundled /design-sync converter caps every matched per-component documentation body at 8,000 JavaScript characters before it emits <Name>.prompt.md:

export const DOC_BODY_CAP = 8000;

if (body.length > DOC_BODY_CAP) {
  const orig = body.length;
  const cut = body.slice(0, DOC_BODY_CAP).replace(/\s+\S*$/, '');
  body = (cut.length > DOC_BODY_CAP - 500 ? cut : body.slice(0, DOC_BODY_CAP)) +
    `\n\n_(truncated — see ${basename(path)} for full)_`;
}

The marker is unusable in the published artifact. The upload contract ships each component's .prompt.md, .d.ts, .html, and .jsx, but it does not ship the matched source <Name>.md. The generated prompt therefore tells the design agent to read a file that does not exist in the Claude Design project.

In one 379-component bundle, a count-independent marker scan found 15 affected prompts:

  • Attachments
  • ButtonGroup
  • ChainOfThought
  • Confirmation
  • Conversation
  • HoverCard
  • InlineCitation
  • InputGroup
  • Message
  • Popover
  • Queue
  • SchemaDisplay
  • SearchableList
  • TestResults
  • Tool

Their transformed source bodies range up to 16,299 characters. Each published prompt ends around 8 KB and loses the remaining usage guidance.

Why the cap itself deserves re-evaluation

The source comment says the design agent reads every .prompt.md, so one large document would crowd out the others. The generated project README instead directs the agent to read a single component prompt on demand:

For a specific component, read_file("components/<group>/<Name>/<Name>.prompt.md").

No platform file ceiling was encountered by the larger source documents. The fixed cap's rationale therefore appears inconsistent with the current on-demand read contract. The dangling marker remains a defect even if a cap is retained.

Reproduction

After running the bundled package converter, scan the output:

rg -l '^_\(truncated — see .* for full\)_$' ds-bundle/components

For any result, confirm that the referenced basename is absent from the upload tree:

find ds-bundle -type f -name '<Name>.md'

The only matching component guidance is the already-truncated <Name>.prompt.md.

Expected behavior

Truncation must never silently discard the only shipped copy of component guidance.

Any of these would satisfy the contract:

  1. Keep the full per-component body in the on-demand .prompt.md.
  2. Make the body budget configurable and allow a project to select a bounded value that preserves its complete documents.
  3. If a hard cap remains, ship the full source at a stable path and make the marker point to that actual uploaded path.

The converter should also validate that every truncation marker resolves inside the final bundle.

Related but distinct issues

  • #88268 covers seven card-scaffold findings in lib/emit.mjs and lib/preview-rebuild.mjs.
  • #83670 covers the separate 120-character prop JSDoc truncation in lib/dts.mjs.

This report concerns lib/docs.mjs, the per-component .prompt.md body, and a dangling recovery reference. The three issues should remain independently verifiable and independently removable.

View original on GitHub ↗