Skip to content

Commit 2e76870

Browse files
ofriwclaude
andcommitted
Enhance presentation generator with content validation
Add strict 3-5 item validation for content arrays with detailed prompts and two-step takeaway generation process. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent aef3c2d commit 2e76870

File tree

1 file changed

+116
-1
lines changed

1 file changed

+116
-1
lines changed

scripts/generate-presentation.js

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ CRITICAL: Captions must be EXACTLY ONE SHORT SENTENCE capturing the core essence
295295
Example:
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+
569587
CRITICAL REQUIREMENTS:
570588
571589
1. The output MUST be valid JSON - no preamble, no explanation, just the JSON object
572590
2. Write the JSON directly to the file: ${outputPath}
573591
3. Include 8-15 slides (no more, no less)
574592
4. Every slide MUST have speakerNotes with all fields
575593
5. 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
577595
7. PROMPT EXAMPLES: Use "code" or "codeComparison" slide types, NEVER bullet points
578596
579597
BEFORE 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

Comments
 (0)