Epic 4: Code Generation & Adaptation
Status : Not Started
Priority : Critical
Epic Owner : AI/ML Team
Estimated Tasks : 10
Depends On : Epic 1 (Design Tokens), Epic 2 (Requirements), Epic 3 (Pattern Retrieval)
Overview
Build the code generation system that adapts retrieved shadcn/ui patterns to match extracted tokens and approved requirements. Generates production-ready TypeScript components with Tailwind CSS, ARIA attributes, Storybook stories, and provenance headers.
Goals
Parse pattern AST to understand code structure
Inject design tokens into component styles
Generate Tailwind CSS classes with CSS variables
Implement approved requirements (props, events, states)
Add ARIA attributes and semantic HTML
Enforce TypeScript strict mode with proper types
Generate Storybook stories for all variants
Add provenance headers tracking generation source
Resolve imports and dependencies correctly
Achieve p50 latency ≤60s for Button/Card generation
Success Criteria
✅ Parse TypeScript AST without errors
✅ Inject tokens into Tailwind classes correctly
✅ Generate CSS variables in component file
✅ Implement all approved requirements from Epic 2
✅ Add proper ARIA attributes (aria-label, role, etc.)
✅ TypeScript strict mode compilation succeeds
✅ No any types without justification
✅ Generate Storybook stories with all variants
✅ Provenance header includes pattern ID and version
✅ Import resolution handles shadcn/ui dependencies
✅ Generated code passes ESLint and Prettier
✅ p50 latency ≤60s for Button/Card components
✅ p95 latency ≤90s
Tasks
Task 1: AST Parsing & Analysis
Acceptance Criteria :
Files :
backend/src/generation/ast_parser.py
AST Parsing :
import json
from typing import Dict , Any
import subprocess
class ASTParser :
def parse (self , code : str ) -> Dict [str , Any ]:
"""Parse TypeScript code to AST using Babel parser."""
# Use Node.js subprocess to parse with @babel/parser
result = subprocess .run (
['node' , 'scripts/parse_ast.js' ],
input = code ,
capture_output = True ,
text = True
)
if result .returncode != 0 :
raise ValueError (f"AST parsing failed: { result .stderr } " )
ast = json .loads (result .stdout )
return self ._analyze_ast (ast )
def _analyze_ast (self , ast : dict ) -> dict :
"""Extract component structure from AST."""
return {
"component_name" : self ._get_component_name (ast ),
"props_interface" : self ._get_props_interface (ast ),
"jsx_structure" : self ._get_jsx_structure (ast ),
"imports" : self ._get_imports (ast ),
"modification_points" : self ._find_modification_points (ast )
}
Node.js Helper (scripts/parse_ast.js):
const parser = require ( '@babel/parser' ) ;
const fs = require ( 'fs' ) ;
const code = fs . readFileSync ( 0 , 'utf-8' ) ; // Read from stdin
const ast = parser . parse ( code , {
sourceType : 'module' ,
plugins : [ 'typescript' , 'jsx' ]
} ) ;
console . log ( JSON . stringify ( ast , null , 2 ) ) ;
Tests :
Parse shadcn/ui Button component successfully
Extract props interface correctly
Identify className modification points
Handle parsing errors gracefully
Task 2: Design Token Injection
Acceptance Criteria :
Map extracted tokens to component styles:
Colors → background, text, border colors
Typography → font family, size, weight
Spacing → padding, margin, gap
Generate CSS variable definitions:
: root {
--color-primary : # 3B82F6 ;
--font-size-base : 16px ;
--spacing-md : 16px ;
}
Replace hardcoded values in pattern with CSS vars
Handle token mapping for different component types:
Button: primary color, padding, font
Card: background, border, spacing
Input: border color, focus ring, padding
Preserve existing Tailwind classes when possible
Add fallback values for missing tokens
Files :
backend/src/generation/token_injector.py
Token Injection :
class TokenInjector :
def inject (self , ast : dict , tokens : dict ) -> dict :
"""Inject design tokens into component AST."""
css_vars = self ._generate_css_variables (tokens )
modified_ast = self ._replace_styles (ast , tokens )
return {
"ast" : modified_ast ,
"css_variables" : css_vars ,
"token_mapping" : self ._create_token_mapping (tokens )
}
def _generate_css_variables (self , tokens : dict ) -> str :
"""Generate CSS variable definitions."""
vars = []
if "colors" in tokens :
for name , value in tokens ["colors" ].items ():
vars .append (f" --color-{ name } : { value } ;" )
if "typography" in tokens :
if "fontSize" in tokens ["typography" ]:
vars .append (f" --font-size-base: { tokens ['typography' ]['fontSize' ]} ;" )
if "spacing" in tokens :
for name , value in tokens ["spacing" ].items ():
vars .append (f" --spacing-{ name } : { value } ;" )
return ":root {\n " + "\n " .join (vars ) + "\n }"
def _replace_styles (self , ast : dict , tokens : dict ) -> dict :
"""Replace hardcoded styles with token references."""
# Modify className attributes to use CSS variables
# Example: bg-blue-500 → bg-[var(--color-primary)]
pass
Tests :
CSS variables generated correctly
Token values injected into styles
Fallback values used when tokens missing
Token mapping complete and accurate
Task 3: Tailwind CSS Generation
Acceptance Criteria :
Files :
backend/src/generation/tailwind_generator.py
Tailwind Generation :
class TailwindGenerator :
def generate_classes (self , element : str , tokens : dict ,
variant : str = None ) -> str :
"""Generate Tailwind classes for element."""
classes = []
# Base classes
if element == "button" :
classes .extend ([
"inline-flex items-center justify-center" ,
"rounded-md text-sm font-medium" ,
"transition-colors focus-visible:outline-none" ,
"focus-visible:ring-2 focus-visible:ring-ring" ,
"disabled:pointer-events-none disabled:opacity-50"
])
# Variant-specific classes
if variant == "primary" :
classes .extend ([
"bg-[var(--color-primary)]" ,
"text-white" ,
"hover:bg-[var(--color-primary)]/90"
])
elif variant == "secondary" :
classes .extend ([
"bg-secondary text-secondary-foreground" ,
"hover:bg-secondary/80"
])
# Spacing from tokens
if "spacing" in tokens :
padding = tokens ["spacing" ].get ("padding" , "16px" )
classes .append (f"p-[{ padding } ]" )
return " " .join (classes )
Tests :
Tailwind classes generated correctly
CSS variables used appropriately
Classes validate against Tailwind config
Responsive classes work correctly
Task 4: Requirements Implementation
Acceptance Criteria :
Files :
backend/src/generation/requirement_implementer.py
Requirement Implementation :
class RequirementImplementer :
def implement (self , ast : dict , requirements : dict ) -> dict :
"""Implement approved requirements in component."""
modified_ast = ast .copy ()
# Add props to interface
if "props" in requirements :
modified_ast = self ._add_props (modified_ast , requirements ["props" ])
# Add event handlers
if "events" in requirements :
modified_ast = self ._add_events (modified_ast , requirements ["events" ])
# Add state management
if "states" in requirements :
modified_ast = self ._add_states (modified_ast , requirements ["states" ])
# Add accessibility attributes
if "accessibility" in requirements :
modified_ast = self ._add_a11y (modified_ast , requirements ["accessibility" ])
return modified_ast
def _add_props (self , ast : dict , props : list ) -> dict :
"""Add props to TypeScript interface."""
# Generate interface code
interface_code = "interface ButtonProps {\n "
for prop in props :
prop_type = self ._infer_prop_type (prop )
optional = "?" if not prop .get ("required" ) else ""
interface_code += f" { prop ['name' ]} { optional } : { prop_type } ;\n "
interface_code += "}"
# Insert into AST
return ast
Tests :
Props added to interface correctly
Event handlers implemented properly
State management works as expected
Default values handled correctly
Task 5: ARIA Attributes & Semantic HTML
Acceptance Criteria :
Files :
backend/src/generation/a11y_enhancer.py
A11y Enhancement :
class A11yEnhancer :
def enhance (self , ast : dict , component_type : str ,
requirements : dict ) -> dict :
"""Add accessibility attributes to component."""
modified_ast = ast .copy ()
# Add ARIA attributes based on component type
if component_type == "button" :
modified_ast = self ._add_button_a11y (modified_ast , requirements )
elif component_type == "input" :
modified_ast = self ._add_input_a11y (modified_ast , requirements )
# Add keyboard navigation
modified_ast = self ._add_keyboard_nav (modified_ast )
return modified_ast
def _add_button_a11y (self , ast : dict , requirements : dict ) -> dict :
"""Add button-specific ARIA attributes."""
aria_attrs = []
# Check for icon-only variant
if "icon-only" in requirements .get ("variants" , []):
aria_attrs .append ('aria-label="{label}"' )
# Add disabled state
aria_attrs .append ('aria-disabled={disabled}' )
# Add loading state if required
if "loading" in requirements .get ("states" , []):
aria_attrs .append ('aria-busy={loading}' )
return ast
Tests :
ARIA attributes added correctly
Semantic HTML used appropriately
Keyboard navigation works
Focus indicators visible
Task 6: TypeScript Type Safety
Acceptance Criteria :
Files :
backend/src/generation/type_generator.py
Type Generation :
class TypeGenerator :
def generate_types (self , requirements : dict ) -> str :
"""Generate TypeScript type definitions."""
types = []
# Variant union type
if "variant" in requirements .get ("props" , []):
variants = requirements ["props" ]["variant" ]["values" ]
variant_type = " | " .join (f'"{ v } "' for v in variants )
types .append (f'type Variant = { variant_type } ;' )
# Props interface
props_interface = self ._generate_props_interface (requirements )
types .append (props_interface )
return "\n \n " .join (types )
def _generate_props_interface (self , requirements : dict ) -> str :
"""Generate props interface."""
code = "interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n "
for prop in requirements .get ("props" , []):
prop_name = prop ["name" ]
prop_type = self ._get_prop_type (prop )
optional = "?" if not prop .get ("required" ) else ""
# Add JSDoc if available
if "description" in prop :
code += f' /** { prop ["description" ]} */\n '
code += f" { prop_name } { optional } : { prop_type } ;\n "
code += "}"
return code
def _get_prop_type (self , prop : dict ) -> str :
"""Infer TypeScript type from prop definition."""
if prop .get ("values" ):
# Union type for enums
return " | " .join (f'"{ v } "' for v in prop ["values" ])
elif prop .get ("type" ) == "boolean" :
return "boolean"
elif prop .get ("type" ) == "function" :
return "() => void"
else :
return "string"
Tests :
TypeScript compilation succeeds
No any types in generated code
Union types correct for variants
Ref forwarding typed correctly
Task 7: Storybook Story Generation
Acceptance Criteria :
Files :
backend/src/generation/storybook_generator.py
Storybook Generation :
class StorybookGenerator :
def generate_stories (self , component_name : str ,
requirements : dict , tokens : dict ) -> str :
"""Generate Storybook stories file."""
stories = f"""import type {{ Meta, StoryObj }} from '@storybook/react';
import {{ { component_name } }} from './{ component_name } ';
const meta: Meta<typeof { component_name } > = {{
title: 'Components/{ component_name } ',
component: { component_name } ,
tags: ['autodocs'],
argTypes: {{
{ self ._generate_arg_types (requirements )}
}},
}};
export default meta;
type Story = StoryObj<typeof { component_name } >;
{ self ._generate_variant_stories (component_name , requirements )}
"""
return stories
def _generate_arg_types (self , requirements : dict ) -> str :
"""Generate argTypes for controls."""
arg_types = []
for prop in requirements .get ("props" , []):
if prop .get ("values" ):
# Enum control
arg_types .append (f""" { prop ['name' ]} : {{
control: 'select',
options: { prop ['values' ]} ,
}}""" )
elif prop .get ("type" ) == "boolean" :
arg_types .append (f""" { prop ['name' ]} : {{
control: 'boolean',
}}""" )
return ",\n " .join (arg_types )
def _generate_variant_stories (self , component_name : str ,
requirements : dict ) -> str :
"""Generate story for each variant."""
stories = []
# Default story
stories .append (f"""export const Default: Story = {{
args: {{
children: 'Button',
}},
}};""" )
# Variant stories
variants = next ((p ["values" ] for p in requirements .get ("props" , [])
if p ["name" ] == "variant" ), [])
for variant in variants :
story_name = variant .capitalize ()
stories .append (f"""
export const { story_name } : Story = {{
args: {{
variant: '{ variant } ',
children: '{ story_name } Button',
}},
}};""" )
return "\n " .join (stories )
Tests :
Storybook stories render correctly
All variants have stories
Controls work for interactive props
Documentation renders properly
Task 8: Provenance Headers & Metadata
Acceptance Criteria :
Files :
backend/src/generation/provenance.py
Provenance Header :
import hashlib
from datetime import datetime
class ProvenanceGenerator :
def generate_header (self , pattern : dict , tokens : dict ,
requirements : dict ) -> str :
"""Generate provenance header comment."""
tokens_hash = self ._hash_dict (tokens )
requirements_hash = self ._hash_dict (requirements )
timestamp = datetime .utcnow ().isoformat () + "Z"
return f"""/**
* Generated by ComponentForge
* Pattern: { pattern ['name' ]} -{ pattern ['version' ]}
* Pattern ID: { pattern ['id' ]}
* Generated: { timestamp }
* Tokens Hash: { tokens_hash }
* Requirements Hash: { requirements_hash }
* DO NOT EDIT: Regenerate with `componentforge regenerate`
*/
"""
def _hash_dict (self , data : dict ) -> str :
"""Generate hash of dictionary for change detection."""
json_str = json .dumps (data , sort_keys = True )
return hashlib .sha256 (json_str .encode ()).hexdigest ()[:16 ]
Tests :
Provenance header added to all files
Hashes calculated correctly
Metadata stored in database
Version tracking works
Task 9: Import Resolution & Dependencies
Acceptance Criteria :
Files :
backend/src/generation/import_resolver.py
Import Resolution :
class ImportResolver :
def resolve (self , ast : dict , component_type : str ) -> list [str ]:
"""Resolve and generate import statements."""
imports = []
# React imports
react_imports = ["React" ]
if "useState" in ast or "useEffect" in ast :
react_imports .append ("{ useState }" )
imports .append (f"import { ', ' .join (react_imports )} from 'react';" )
# shadcn/ui imports
if component_type == "button" :
imports .append ("import { cva, type VariantProps } from 'class-variance-authority';" )
# Utility imports
imports .append ("import { cn } from '@/lib/utils';" )
# Icon imports if needed
if self ._has_icons (ast ):
imports .append ("import { Loader2 } from 'lucide-react';" )
return imports
def _has_icons (self , ast : dict ) -> bool :
"""Check if component uses icons."""
# Analyze AST for icon components
return False
Tests :
All imports resolved correctly
Import order matches convention
Unused imports removed
Missing imports added
Task 10: Code Assembly & Validation
Acceptance Criteria :
Files :
backend/src/generation/code_assembler.py
backend/src/generation/generator_service.py
Code Assembly :
class CodeAssembler :
async def assemble (self , parts : dict ) -> dict :
"""Assemble final component code."""
# Build component file
component_code = "\n \n " .join ([
parts ["provenance_header" ],
"\n " .join (parts ["imports" ]),
parts ["css_variables" ],
parts ["type_definitions" ],
parts ["component_code" ]
])
# Format with Prettier
formatted = await self ._format_code (component_code )
# Build stories file
stories_code = parts ["storybook_stories" ]
formatted_stories = await self ._format_code (stories_code )
return {
"component" : formatted ,
"stories" : formatted_stories ,
"files" : {
f"{ parts ['component_name' ]} .tsx" : formatted ,
f"{ parts ['component_name' ]} .stories.tsx" : formatted_stories
}
}
async def _format_code (self , code : str ) -> str :
"""Format code with Prettier."""
result = await asyncio .create_subprocess_exec (
'npx' , 'prettier' , '--parser' , 'typescript' ,
stdin = asyncio .subprocess .PIPE ,
stdout = asyncio .subprocess .PIPE ,
stderr = asyncio .subprocess .PIPE
)
stdout , stderr = await result .communicate (code .encode ())
if result .returncode != 0 :
raise ValueError (f"Prettier failed: { stderr .decode ()} " )
return stdout .decode ()
Tests :
Component assembles correctly
Prettier formatting succeeds
TypeScript compilation passes
ESLint validation passes
Latency within targets
Dependencies
Requires :
Epic 1: Design tokens for injection
Epic 2: Requirements for implementation
Epic 3: Retrieved patterns for adaptation
Blocks :
Epic 5: Quality validation needs generated code
Technical Architecture
Code Generation Flow
Retrieved Pattern + Tokens + Requirements
↓
AST Parsing
↓
Token Injection
↓
Tailwind Generation
↓
Requirements Implementation
↓
A11y Enhancement
↓
Type Generation
↓
Storybook Generation
↓
Provenance Header
↓
Import Resolution
↓
Code Assembly
↓
Format + Validate
↓
Store to S3 + PostgreSQL
Metrics
Metric
Target
Measurement
Latency (p50)
≤60s
LangSmith traces for Button/Card
Latency (p95)
≤90s
95th percentile generation time
TypeScript Compilation
100%
All generated components compile
Token Injection Accuracy
≥95%
Correct token values in code
Requirements Implementation
100%
All approved requirements present
Risks & Mitigation
Risk
Impact
Mitigation
Generation too slow (>60s)
High
Optimize AST operations, cache patterns
TypeScript compilation errors
High
Better AST manipulation, validation step
Incorrect token injection
Medium
Comprehensive tests, manual review
Import resolution failures
Medium
Fallback to common imports, validation
Storybook stories broken
Low
Test story rendering, simpler stories
Definition of Done
Related Epics
Depends On : Epic 1, Epic 2, Epic 3
Blocks : Epic 5
Related : Epic 8 (regeneration uses same pipeline)
Notes
Critical Path : This is the core value delivery epic. Quality here determines product success.
Performance : 60s target is aggressive. Monitor carefully and optimize AST operations first.
Type Safety : Zero tolerance for any types. This is a quality differentiator.
Epic 4: Code Generation & Adaptation
Status: Not Started
Priority: Critical
Epic Owner: AI/ML Team
Estimated Tasks: 10
Depends On: Epic 1 (Design Tokens), Epic 2 (Requirements), Epic 3 (Pattern Retrieval)
Overview
Build the code generation system that adapts retrieved shadcn/ui patterns to match extracted tokens and approved requirements. Generates production-ready TypeScript components with Tailwind CSS, ARIA attributes, Storybook stories, and provenance headers.
Goals
Success Criteria
anytypes without justificationTasks
Task 1: AST Parsing & Analysis
Acceptance Criteria:
@babel/parserFiles:
backend/src/generation/ast_parser.pyAST Parsing:
Node.js Helper (
scripts/parse_ast.js):Tests:
Task 2: Design Token Injection
Acceptance Criteria:
Files:
backend/src/generation/token_injector.pyToken Injection:
Tests:
Task 3: Tailwind CSS Generation
Acceptance Criteria:
bg-[var(--color-primary)]text-[var(--font-size-base)]p-[var(--spacing-md)]Files:
backend/src/generation/tailwind_generator.pyTailwind Generation:
Tests:
Task 4: Requirements Implementation
Acceptance Criteria:
Files:
backend/src/generation/requirement_implementer.pyRequirement Implementation:
Tests:
Task 5: ARIA Attributes & Semantic HTML
Acceptance Criteria:
aria-labelfor icon-only buttonsaria-disabledfor disabled statearia-busyfor loading statearia-pressedfor toggle buttonsrolewhen semantic HTML insufficient<button>for clickable actions<input>for form fields<label>for input labels<fieldset>for grouped inputstabIndexfor focusable elementsonKeyDownfor keyboard handlersFiles:
backend/src/generation/a11y_enhancer.pyA11y Enhancement:
Tests:
Task 6: TypeScript Type Safety
Acceptance Criteria:
anytypesOmit,Pick,Partial, etc.tsc --noEmitFiles:
backend/src/generation/type_generator.pyType Generation:
Tests:
anytypes in generated codeTask 7: Storybook Story Generation
Acceptance Criteria:
Files:
backend/src/generation/storybook_generator.pyStorybook Generation:
Tests:
Task 8: Provenance Headers & Metadata
Acceptance Criteria:
Files:
backend/src/generation/provenance.pyProvenance Header:
Tests:
Task 9: Import Resolution & Dependencies
Acceptance Criteria:
Files:
backend/src/generation/import_resolver.pyImport Resolution:
Tests:
Task 10: Code Assembly & Validation
Acceptance Criteria:
tsc --noEmitFiles:
backend/src/generation/code_assembler.pybackend/src/generation/generator_service.pyCode Assembly:
Tests:
Dependencies
Requires:
Blocks:
Technical Architecture
Code Generation Flow
Metrics
Risks & Mitigation
Definition of Done
Related Epics
Notes
Critical Path: This is the core value delivery epic. Quality here determines product success.
Performance: 60s target is aggressive. Monitor carefully and optimize AST operations first.
Type Safety: Zero tolerance for
anytypes. This is a quality differentiator.