@@ -106,7 +106,7 @@ PRESENTATION STRUCTURE REQUIREMENTS:
106106 - Discussion prompts or questions to ask students
107107 - Real-world examples to reference
108108✓ DO: Preserve important code examples as slide content
109- ✓ DO: Identify which visual components to use (CapabilityMatrix, UShapeAttentionCurve, etc.)
109+ ✓ DO: Identify which visual components to use (CapabilityMatrix, UShapeAttentionCurve, WorkflowCircle, GroundingComparison, ContextWindowMeter, AbstractShapesVisualization, etc.)
110110
111111✗ AVOID: Long paragraphs on slides (slides are visual anchors, not reading material)
112112✗ AVOID: More than 5 bullet points per slide
@@ -119,9 +119,10 @@ SLIDE TYPES:
1191191. **Title Slide**: Lesson title, learning objectives
1201202. **Concept Slide**: Key idea with 3-5 bullet points
1211213. **Code Example Slide**: Code snippet with context
122- 4. **Comparison Slide**: Effective vs ineffective patterns
123- 5. **Visual Slide**: Custom component (CapabilityMatrix, etc.)
124- 6. **Key Takeaway Slide**: Summary of section or lesson
122+ 4. **Code Execution Slide**: Step-by-step visualization of execution flows (agent loops, algorithms, workflows)
123+ 5. **Comparison Slide**: Effective vs ineffective patterns
124+ 6. **Visual Slide**: Custom component (CapabilityMatrix, etc.)
125+ 7. **Key Takeaway Slide**: Summary of section or lesson
125126
126127HANDLING CODE BLOCKS:
127128
@@ -136,9 +137,106 @@ For presentation slides:
136137✓ Add context in speaker notes about what the code demonstrates
137138✓ For comparison slides, show ineffective and effective side-by-side
138139✓ Keep code snippets under 15 lines for readability
140+ ✓ EXCEPTION: Textual context flow examples showing agent conversation flows should use "codeExecution" slide type regardless of length (see section below)
139141✗ Don't include every code example from the lesson
140142✗ Don't show code without explaining its purpose
141143
144+ COMPONENT DETECTION (CRITICAL):
145+
146+ The source content contains markers for visual React components in the format:
147+ [VISUAL_COMPONENT: ComponentName]
148+
149+ Examples you will see:
150+ - [VISUAL_COMPONENT: AbstractShapesVisualization]
151+ - [VISUAL_COMPONENT: CapabilityMatrix]
152+ - [VISUAL_COMPONENT: UShapeAttentionCurve]
153+ - [VISUAL_COMPONENT: ContextWindowMeter]
154+
155+ **MANDATORY RULE:** When you encounter a [VISUAL_COMPONENT: X] marker, you MUST:
156+ 1. Generate a "visual" slide type (NOT a "concept" slide)
157+ 2. Set "component" field to the exact component name from the marker
158+ 3. Use the surrounding context to write a descriptive caption
159+
160+ Example:
161+ {
162+ "type": "visual",
163+ "component": "AbstractShapesVisualization",
164+ "caption": "Visual comparison showing cluttered vs clean context"
165+ }
166+
167+ **DO NOT:**
168+ - Convert component markers into text bullet points
169+ - Skip component markers
170+ - Change the component name
171+ - Generate a "concept" slide when you see a component marker
172+
173+ If you see [VISUAL_COMPONENT: X] anywhere in the content, it MUST become a visual slide.
174+
175+ CODE EXECUTION SLIDES:
176+
177+ Use the "codeExecution" slide type to visualize step-by-step processes like:
178+ - Agent execution loops (human input → LLM prediction → agent execution → feedback)
179+ - Algorithm execution flows
180+ - Request/response cycles
181+ - Multi-step workflows
182+
183+ Structure with highlightType for semantic color-coding (uses design system colors):
184+ - **"human"** (white/neutral): Engineer/operator input, commands, task specifications, explicit constraints
185+ - **"prediction"** (purple): LLM predictions, reasoning, decisions, "I will..." or "I should..." statements
186+ - **"execution"** (green): Agent/software tool calls, deterministic actions (Read, Edit, Bash commands)
187+ - **"feedback"** (purple light): Data/results returned from operations, outputs that LLM receives
188+ - **"summary"** (white/neutral): Loop conditions, conclusions, final outcomes
189+
190+ SEMANTIC RULES (critical for correct color coding):
191+ ✓ "Engineer specifies task:" → human (operator input)
192+ ✓ "LLM predicts:" or "LLM decides:" → prediction (thinking/planning)
193+ ✓ "Agent executes: Read(...)" → execution (tool call)
194+ ✓ "File content returned:" → feedback (operation result)
195+ ✓ "LLM receives and predicts:" → prediction (NOT feedback - it's the prediction after receiving)
196+ ✓ "Loop continues until..." → summary (loop condition)
197+
198+ ✓ Use for "how it works" explanations (3-8 steps typical)
199+ ✓ Include annotations to explain WHY each step happens
200+ ✓ Show the complete cycle from start to finish
201+ ✓ Maintain semantic consistency: what's DOING the action determines the type
202+ ✗ Don't use for static code examples (use "code" type instead)
203+ ✗ Don't create more than 10 steps (split into multiple slides if needed)
204+ ✗ Don't confuse "LLM receives data and predicts" (prediction) with "data returned" (feedback)
205+
206+ RECOGNIZING TEXTUAL CONTEXT FLOW PATTERNS (CRITICAL):
207+
208+ When you see code blocks showing conversation/execution flows with patterns like:
209+ - "SYSTEM: ... USER: ... ASSISTANT: ... TOOL_RESULT: ..."
210+ - Sequential back-and-forth between human, LLM, and tools
211+ - Full execution traces showing how text flows through agent context
212+ - Examples demonstrating the actual content of the context window
213+
214+ → These are PEDAGOGICALLY CRITICAL and must be included as "codeExecution" slides
215+
216+ Why these matter MORE than config examples:
217+ - They show the fundamental mental model of how agents operate
218+ - They demystify what "context" actually contains
219+ - They're the core learning insight, not just implementation details
220+
221+ How to handle them:
222+ 1. Break the flow into 8-12 logical steps (not necessarily every line)
223+ 2. Map conversation elements to highlightTypes:
224+ - "SYSTEM:" or system instructions → human
225+ - "USER:" or task specification → human
226+ - "ASSISTANT:" thinking/reasoning → prediction
227+ - "<tool_use>" or tool calls → execution
228+ - "TOOL_RESULT:" or outputs → feedback
229+ 3. Add annotations explaining the significance of each step
230+ 4. Focus on the FLOW of text through the context, not just the code
231+
232+ Example transformation:
233+ - Source: 67-line conversation showing full agent execution
234+ - Slide: 10 steps highlighting key moments in the conversation flow
235+ - Annotations: "Notice how the tool result becomes input to the next prediction"
236+
237+ PRIORITIZATION: Textual flow examples showing context mechanics trump configuration
238+ examples like MCP setup. Configuration is implementation; textual flow is understanding.
239+
142240SPEAKER NOTES GUIDELINES:
143241
144242For each slide, provide speaker notes with:
@@ -204,23 +302,97 @@ You must generate a valid JSON file with this structure:
204302 "caption": "Brief explanation",
205303 "speakerNotes": { ... }
206304 },
305+ {
306+ "type": "codeExecution",
307+ "title": "Agent Execution Loop Example",
308+ "steps": [
309+ {
310+ "line": "Engineer specifies: 'Add authentication middleware'",
311+ "highlightType": "human",
312+ "annotation": "Human provides explicit task and constraints"
313+ },
314+ {
315+ "line": "LLM predicts: 'I should read existing auth patterns'",
316+ "highlightType": "prediction",
317+ "annotation": "Token prediction drives next action"
318+ },
319+ {
320+ "line": "Agent executes: Read(src/middleware/auth.ts)",
321+ "highlightType": "execution",
322+ "annotation": "Deterministic tool execution"
323+ },
324+ {
325+ "line": "File content returned to context",
326+ "highlightType": "feedback",
327+ "annotation": "Operation result available to LLM"
328+ },
329+ {
330+ "line": "LLM analyzes patterns and predicts: 'I'll use JWT approach'",
331+ "highlightType": "prediction",
332+ "annotation": "Prediction incorporates new context"
333+ },
334+ {
335+ "line": "Agent executes: Edit(src/app.ts, old, new)",
336+ "highlightType": "execution",
337+ "annotation": "Code modification"
338+ },
339+ {
340+ "line": "Loop continues until tests pass",
341+ "highlightType": "summary",
342+ "annotation": "Iteration condition"
343+ }
344+ ],
345+ "speakerNotes": { ... }
346+ },
347+
348+ COMPARISON SLIDE CONVENTION (CRITICAL - HARDCODED IN UI):
349+
350+ The comparison slide type has HARDCODED styling in the presentation component:
351+ - LEFT side → RED background, RED heading, ✗ icons (ineffective/worse/limited)
352+ - RIGHT side → GREEN background, GREEN heading, ✓ icons (effective/better/superior)
353+
354+ YOU MUST ALWAYS follow this convention:
355+ - LEFT: The worse/ineffective/traditional/limited approach
356+ - RIGHT: The better/effective/modern/superior approach
357+
358+ Correct examples:
359+ - "Chat Interface" (left) vs "Agent Workflow" (right)
360+ - "Heavy Mocking" (left) vs "Sociable Tests" (right)
361+ - "Chat/IDE Agents" (left) vs "CLI Agents" (right)
362+ - "Traditional RAG" (left) vs "Agentic RAG" (right)
363+
364+ INCORRECT: Putting the better option on the left will show it with RED ✗ styling!
365+
207366 {
208367 "type": "comparison",
209368 "title": "Ineffective vs Effective",
210369 "left": {
211- "label": "Ineffective",
370+ "label": "Ineffective", // MANDATORY: LEFT = worse/ineffective/limited (RED ✗)
212371 "content": ["Point 1", "Point 2"]
213372 },
214373 "right": {
215- "label": "Effective",
374+ "label": "Effective", // MANDATORY: RIGHT = better/effective/superior (GREEN ✓)
216375 "content": ["Point 1", "Point 2"]
217376 },
218377 "speakerNotes": { ... }
219378 },
379+ {
380+ "type": "marketingReality",
381+ "title": "Marketing vs Reality: What Actually Happens",
382+ "metaphor": {
383+ "label": "Marketing Speak",
384+ "content": ["Metaphorical statement 1", "Metaphorical statement 2"]
385+ },
386+ "reality": {
387+ "label": "Technical Reality",
388+ "content": ["Technical explanation 1", "Technical explanation 2"]
389+ },
390+ "speakerNotes": { ... }
391+ },
220392 {
221393 "type": "visual",
222394 "title": "Visual Component",
223- "component": "CapabilityMatrix",
395+ "component": "CapabilityMatrix | UShapeAttentionCurve | WorkflowCircle | GroundingComparison | ContextWindowMeter | AbstractShapesVisualization ",
224396 "caption": "Description of what the visual shows",
225397 "speakerNotes": { ... }
226398 },
@@ -420,6 +592,90 @@ async function promptSelectFile(files, baseDir) {
420592// PROCESSING
421593// ============================================================================
422594
595+ /**
596+ * Extract visual component names from parsed content
597+ * @param {string } content - Parsed markdown content
598+ * @returns {string[] } Array of component names
599+ */
600+ function extractExpectedComponents ( content ) {
601+ const componentRegex = / \[ V I S U A L _ C O M P O N E N T : ( [ A - Z a - z ] + ) \] / g;
602+ const components = [ ] ;
603+ let match ;
604+
605+ while ( ( match = componentRegex . exec ( content ) ) !== null ) {
606+ components . push ( match [ 1 ] ) ;
607+ }
608+
609+ return components ;
610+ }
611+
612+ /**
613+ * Validate that all expected visual components appear in the presentation
614+ * @param {string } content - Parsed markdown content
615+ * @param {object } presentation - Generated presentation object
616+ * @returns {object } Validation result with missing components
617+ */
618+ function validateComponents ( content , presentation ) {
619+ const expectedComponents = extractExpectedComponents ( content ) ;
620+ const visualSlides = presentation . slides . filter ( s => s . type === 'visual' ) ;
621+ const renderedComponents = visualSlides . map ( s => s . component ) ;
622+
623+ const missing = expectedComponents . filter ( c => ! renderedComponents . includes ( c ) ) ;
624+
625+ return {
626+ expected : expectedComponents ,
627+ rendered : renderedComponents ,
628+ missing,
629+ allPresent : missing . length === 0
630+ } ;
631+ }
632+
633+ /**
634+ * Validate semantic correctness of comparison slides
635+ * Checks that better/effective options are on the RIGHT (green ✓)
636+ * and worse/ineffective options are on the LEFT (red ✗)
637+ * @param {object } presentation - Generated presentation object
638+ * @returns {object } Validation result with potential ordering issues
639+ */
640+ function validateComparisonSemantics ( presentation ) {
641+ const comparisonSlides = presentation . slides . filter ( s => s . type === 'comparison' ) ;
642+ const issues = [ ] ;
643+
644+ // Keywords that indicate a "positive/better" option
645+ const positiveKeywords = [ 'cli' , 'effective' , 'better' , 'modern' , 'agentic' , 'sociable' , 'agent workflow' ] ;
646+ // Keywords that indicate a "negative/worse" option
647+ const negativeKeywords = [ 'chat' , 'ide' , 'ineffective' , 'worse' , 'traditional' , 'mocked' , 'chat interface' ] ;
648+
649+ for ( const slide of comparisonSlides ) {
650+ if ( ! slide . left || ! slide . right ) continue ;
651+
652+ const leftLabel = slide . left . label ?. toLowerCase ( ) || '' ;
653+ const rightLabel = slide . right . label ?. toLowerCase ( ) || '' ;
654+
655+ // Check if left side has positive keywords (should be on right instead)
656+ const leftIsPositive = positiveKeywords . some ( k => leftLabel . includes ( k ) ) ;
657+ // Check if right side has negative keywords (should be on left instead)
658+ const rightIsNegative = negativeKeywords . some ( k => rightLabel . includes ( k ) ) ;
659+
660+ if ( leftIsPositive || rightIsNegative ) {
661+ issues . push ( {
662+ slide : slide . title ,
663+ left : slide . left . label ,
664+ right : slide . right . label ,
665+ reason : leftIsPositive
666+ ? `"${ slide . left . label } " appears positive/better but is on LEFT (will show RED ✗)`
667+ : `"${ slide . right . label } " appears negative/worse but is on RIGHT (will show GREEN ✓)`
668+ } ) ;
669+ }
670+ }
671+
672+ return {
673+ valid : issues . length === 0 ,
674+ issues,
675+ totalComparisons : comparisonSlides . length
676+ } ;
677+ }
678+
423679/**
424680 * Generate presentation for a file
425681 */
@@ -462,6 +718,31 @@ async function generatePresentation(filePath, manifest, config) {
462718 // Generate presentation using Claude
463719 const presentation = await generatePresentationWithClaude ( prompt , outputPath ) ;
464720
721+ // Validate that all visual components were included
722+ const validation = validateComponents ( content , presentation ) ;
723+ if ( ! validation . allPresent ) {
724+ console . log ( ` ⚠️ WARNING: ${ validation . missing . length } visual component(s) not rendered:` ) ;
725+ validation . missing . forEach ( c => console . log ( ` - ${ c } ` ) ) ;
726+ console . log ( ` ℹ️ Expected: [${ validation . expected . join ( ', ' ) } ]` ) ;
727+ console . log ( ` ℹ️ Rendered: [${ validation . rendered . join ( ', ' ) } ]` ) ;
728+ } else if ( validation . expected . length > 0 ) {
729+ console . log ( ` ✅ All ${ validation . expected . length } visual component(s) rendered correctly` ) ;
730+ }
731+
732+ // Validate comparison slide semantics
733+ const semanticValidation = validateComparisonSemantics ( presentation ) ;
734+ if ( ! semanticValidation . valid ) {
735+ console . log ( ` ⚠️ WARNING: ${ semanticValidation . issues . length } comparison slide(s) may have reversed order:` ) ;
736+ semanticValidation . issues . forEach ( issue => {
737+ console . log ( ` - "${ issue . slide } "` ) ;
738+ console . log ( ` LEFT: "${ issue . left } " | RIGHT: "${ issue . right } "` ) ;
739+ console . log ( ` ${ issue . reason } ` ) ;
740+ } ) ;
741+ console . log ( ` ℹ️ Remember: LEFT = ineffective/worse (RED ✗), RIGHT = effective/better (GREEN ✓)` ) ;
742+ } else if ( semanticValidation . totalComparisons > 0 ) {
743+ console . log ( ` ✅ All ${ semanticValidation . totalComparisons } comparison slide(s) follow correct convention` ) ;
744+ }
745+
465746 // Copy to static directory for deployment
466747 const staticPath = join ( STATIC_OUTPUT_DIR , dirname ( relativePath ) , outputFileName ) ;
467748 mkdirSync ( dirname ( staticPath ) , { recursive : true } ) ;
0 commit comments