# Spec (the "DNA")
# User Story: Display User Profile
- Show user's name, email, join date
- Format join date as "Member since MMM YYYY"
- If user has no email, show "No email on file"

Same spec, two frameworks. The spec is framework-agnostic. Architecture context determines output.

// React expression
function UserProfile({ user }) {
  const joinDate = new Date(user.joinedAt)
    .toLocaleDateString('en-US', { month: 'short', year: 'numeric' });
  return (
    <div className="profile">
      <h2>{user.name}</h2>
      <p>{user.email || "No email on file"}</p>
      <p>Member since {joinDate}</p>
    </div>
  );
}
<!-- Vue expression -->
<template>
  <div class="profile">
    <h2>{{ user.name }}</h2>
    <p>{{ user.email || "No email on file" }}</p>
    <p>Member since {{ formattedJoinDate }}</p>
  </div>
</template>

Mutate the spec, output changes predictably:

  + If user is premium, show gold star badge next to name

// React now produces:
<h2>{user.name} {user.isPremium && <span className="badge">⭐</span>}</h2>

Vague vs. Constrained

Too VagueRightOver-Specified
"Make it fast""<200ms p95""Use Redis with 60s TTL"
"Handle errors""User-friendly message + log details""try-catch with react-hot-toast"
"Users can search""Full-text, debounced 300ms, max 20""Use Elasticsearch with ngram tokenizer"

Define what and constraints, not implementation details.

Feed Raw Context

Tempting: merge your PRD + architecture docs into one clean file. Don't.

# Original PRD
Users can update email. Email must be verified before replacing.
Send confirmation to BOTH old and new addresses. If new email
bounces, keep old email. Limit: 3 verification attempts per day.

# Original Architecture
Email service: SendGrid with templated emails.
Verification tokens: 32-byte random, stored in Redis with 24h TTL.
User table has email_pending column for staged changes.

# ❌ Synthesized "unified spec"
Implement email update with verification.
Use SendGrid for emails and Redis for tokens.

# What got lost:
- Send to BOTH addresses (security detail)
- Bounce handling (edge case)
- Rate limit (abuse prevention)
- 24h TTL (timing constraint)
- email_pending column (schema detail)

The synthesized version sounds clean but dropped five implementation details. The Data Processing Inequality says processing can only destroy information, never create it.

What you lose by synthesizing:

Exception: synthesis that adds new information (resolving ambiguities, deriving constraints, resolving contradictions). If you're just reformatting, feed the raw files.

Further Reading

Last updated: March 27, 2026