@@ -295,6 +295,7 @@ CRITICAL: Captions must be EXACTLY ONE SHORT SENTENCE capturing the core essence
295295Example:
296296{
297297 "type": "visual",
298+ "title": "Context and Agent Behavior",
298299 "component": "AbstractShapesVisualization",
299300 "caption": "Clean context prevents agent hallucinations"
300301}
@@ -566,14 +567,31 @@ INCORRECT: Putting the better option on the left will show it with RED ✗ styli
566567 ]
567568}
568569
570+ KEY TAKEAWAYS GENERATION (TWO-STEP PROCESS):
571+
572+ When creating the "takeaway" slide at the end of the presentation:
573+
574+ STEP 1: First, review the lesson and mentally list ALL significant takeaways
575+ - Identify every important concept, pattern, or insight from the lesson
576+ - Don't filter yet—just enumerate everything worth remembering
577+
578+ STEP 2: Then, condense to the 3-5 MOST critical takeaways
579+ - Prioritize by impact and generality (what will matter most in production?)
580+ - Combine related points into higher-level insights when possible
581+ - Remove redundant or overly specific points
582+ - Ensure each takeaway is actionable and memorable
583+
584+ IMPORTANT: The final takeaway slide MUST have exactly 3-5 items, even if the source material lists more.
585+ Quality over quantity—choose the most impactful insights.
586+
569587CRITICAL REQUIREMENTS:
570588
5715891. The output MUST be valid JSON - no preamble, no explanation, just the JSON object
5725902. Write the JSON directly to the file: ${ outputPath }
5735913. Include 8-15 slides (no more, no less)
5745924. Every slide MUST have speakerNotes with all fields
5755935. Code examples must be actual code from the lesson, not pseudocode
576- 6. Content arrays must have 3-5 items (except title slide)
594+ 6. Content arrays MUST have 3-5 items (except title slide) - THIS IS STRICTLY ENFORCED
5775957. PROMPT EXAMPLES: Use "code" or "codeComparison" slide types, NEVER bullet points
578596
579597BEFORE YOU GENERATE - CHECKLIST:
@@ -842,6 +860,85 @@ function validateComparisonSemantics(presentation) {
842860 } ;
843861}
844862
863+ /**
864+ * Validate that content arrays have 3-5 items maximum
865+ * @param {object } presentation - Generated presentation object
866+ * @returns {object } Validation result with issues
867+ */
868+ function validateContentArrayLengths ( presentation ) {
869+ const issues = [ ] ;
870+ const MIN_ITEMS = 3 ;
871+ const MAX_ITEMS = 5 ;
872+
873+ // Slide types that must have content arrays with 3-5 items
874+ const slidesWithContent = presentation . slides . filter ( slide => {
875+ // Skip title slide (different rules)
876+ if ( slide . type === 'title' ) return false ;
877+
878+ // Check slides with content arrays
879+ return slide . content && Array . isArray ( slide . content ) ;
880+ } ) ;
881+
882+ for ( const slide of slidesWithContent ) {
883+ const contentLength = slide . content . length ;
884+
885+ if ( contentLength < MIN_ITEMS || contentLength > MAX_ITEMS ) {
886+ issues . push ( {
887+ slide : slide . title || slide . type ,
888+ type : slide . type ,
889+ count : contentLength ,
890+ reason : contentLength < MIN_ITEMS
891+ ? `Only ${ contentLength } item(s), need at least ${ MIN_ITEMS } `
892+ : `Has ${ contentLength } item(s), maximum is ${ MAX_ITEMS } `
893+ } ) ;
894+ }
895+ }
896+
897+ // Check comparison slides (left/right content)
898+ const comparisonSlides = presentation . slides . filter ( s =>
899+ s . type === 'comparison' || s . type === 'marketingReality'
900+ ) ;
901+
902+ for ( const slide of comparisonSlides ) {
903+ const leftContent = slide . left ?. content || slide . metaphor ?. content ;
904+ const rightContent = slide . right ?. content || slide . reality ?. content ;
905+
906+ if ( leftContent && Array . isArray ( leftContent ) ) {
907+ const leftLength = leftContent . length ;
908+ if ( leftLength < MIN_ITEMS || leftLength > MAX_ITEMS ) {
909+ issues . push ( {
910+ slide : `${ slide . title } (LEFT)` ,
911+ type : slide . type ,
912+ count : leftLength ,
913+ reason : leftLength < MIN_ITEMS
914+ ? `Only ${ leftLength } item(s), need at least ${ MIN_ITEMS } `
915+ : `Has ${ leftLength } item(s), maximum is ${ MAX_ITEMS } `
916+ } ) ;
917+ }
918+ }
919+
920+ if ( rightContent && Array . isArray ( rightContent ) ) {
921+ const rightLength = rightContent . length ;
922+ if ( rightLength < MIN_ITEMS || rightLength > MAX_ITEMS ) {
923+ issues . push ( {
924+ slide : `${ slide . title } (RIGHT)` ,
925+ type : slide . type ,
926+ count : rightLength ,
927+ reason : rightLength < MIN_ITEMS
928+ ? `Only ${ rightLength } item(s), need at least ${ MIN_ITEMS } `
929+ : `Has ${ rightLength } item(s), maximum is ${ MAX_ITEMS } `
930+ } ) ;
931+ }
932+ }
933+ }
934+
935+ return {
936+ valid : issues . length === 0 ,
937+ issues,
938+ totalSlidesChecked : slidesWithContent . length + comparisonSlides . length
939+ } ;
940+ }
941+
845942/**
846943 * Validate that prompt examples are preserved as code blocks
847944 * @param {string } content - Parsed markdown content
@@ -987,6 +1084,24 @@ async function generatePresentation(filePath, manifest, config) {
9871084 console . log ( ` ✅ All ${ semanticValidation . totalComparisons } comparison slide(s) follow correct convention` ) ;
9881085 }
9891086
1087+ // Validate content array lengths (3-5 items)
1088+ // CRITICAL: This validation is intentionally strict and throws an error because
1089+ // slides with too many bullets become unreadable and overflow the layout.
1090+ // The two-step condensation process in the prompt should prevent this.
1091+ const contentValidation = validateContentArrayLengths ( presentation ) ;
1092+ if ( ! contentValidation . valid ) {
1093+ console . log ( ` ❌ BUILD FAILURE: ${ contentValidation . issues . length } content array violation(s):` ) ;
1094+ contentValidation . issues . forEach ( issue => {
1095+ console . log ( ` - Slide "${ issue . slide } " (${ issue . type } ): ${ issue . reason } ` ) ;
1096+ } ) ;
1097+ console . log ( ` ℹ️ All content arrays MUST have 3-5 items (except title slide)` ) ;
1098+ console . log ( ` ℹ️ For takeaway slides: use the two-step condensation process` ) ;
1099+ console . log ( ` ℹ️ The presentation was not saved. Fix the generation and try again.` ) ;
1100+ throw new Error ( 'Content array validation failed - slides have too many or too few items' ) ;
1101+ } else if ( contentValidation . totalSlidesChecked > 0 ) {
1102+ console . log ( ` ✅ All ${ contentValidation . totalSlidesChecked } content array(s) have 3-5 items` ) ;
1103+ }
1104+
9901105 // Validate prompt examples are preserved as code
9911106 // CRITICAL: This validation is intentionally strict and throws an error because
9921107 // prompt examples are core educational content that must be preserved exactly.
0 commit comments