@thanh01.pmt/curriculum-kit 1.4.12 → 1.4.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -227,23 +227,32 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
227
227
  lessonId?: string | undefined;
228
228
  title?: string | undefined;
229
229
  language?: string | undefined;
230
- topic?: string | undefined;
231
- targetGradeOrAudience?: string | undefined;
232
- overview?: string | undefined;
233
230
  learningObjectives?: ({
234
231
  code?: string | undefined;
235
- name?: string | undefined;
232
+ successCriteria?: string | undefined;
236
233
  description?: string | undefined;
234
+ name?: string | undefined;
237
235
  bloomLevel?: string | undefined;
238
- successCriteria?: string | undefined;
239
236
  standardRefs?: (string | undefined)[] | undefined;
240
237
  conceptRefs?: (string | undefined)[] | undefined;
241
238
  } | undefined)[] | undefined;
239
+ teacherNotes?: {
240
+ commonPitfalls?: (string | undefined)[] | undefined;
241
+ troubleshootingMatrix?: ({
242
+ issue?: string | undefined;
243
+ potentialCause?: string | undefined;
244
+ solution?: string | undefined;
245
+ } | undefined)[] | undefined;
246
+ extensionNotes?: string | undefined;
247
+ } | undefined;
248
+ hookScenario?: string | undefined;
249
+ keywords?: (string | undefined)[] | undefined;
250
+ topic?: string | undefined;
251
+ targetGradeOrAudience?: string | undefined;
252
+ overview?: string | undefined;
242
253
  prerequisites?: string | undefined;
243
254
  materialsSummary?: string | undefined;
244
- keywords?: (string | undefined)[] | undefined;
245
255
  hookTitle?: string | undefined;
246
- hookScenario?: string | undefined;
247
256
  hookQuestions?: (string | undefined)[] | undefined;
248
257
  coreConcepts?: ({
249
258
  name?: string | undefined;
@@ -261,8 +270,8 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
261
270
  goldTier?: string | undefined;
262
271
  } | undefined;
263
272
  sections?: ({
264
- title?: string | undefined;
265
273
  durationMinutes?: number | undefined;
274
+ title?: string | undefined;
266
275
  teacherActions?: string | undefined;
267
276
  studentActions?: string | undefined;
268
277
  analogies?: (string | undefined)[] | undefined;
@@ -273,15 +282,6 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
273
282
  expectedAnswerOrRubric?: string | undefined;
274
283
  metacognitivePrompt?: string | undefined;
275
284
  } | undefined;
276
- teacherNotes?: {
277
- commonPitfalls?: (string | undefined)[] | undefined;
278
- troubleshootingMatrix?: ({
279
- issue?: string | undefined;
280
- potentialCause?: string | undefined;
281
- solution?: string | undefined;
282
- } | undefined)[] | undefined;
283
- extensionNotes?: string | undefined;
284
- } | undefined;
285
285
  guidedPractice?: {
286
286
  title?: string | undefined;
287
287
  explanation?: string | undefined;
@@ -290,31 +290,40 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
290
290
  mermaidDiagram?: string | undefined;
291
291
  } | undefined;
292
292
  independentPractice?: {
293
- title?: string | undefined;
294
293
  description?: string | undefined;
294
+ title?: string | undefined;
295
295
  } | undefined;
296
296
  }, {
297
297
  artifactType: "LESSON";
298
298
  lessonId: string;
299
299
  title: string;
300
300
  language: string;
301
- topic: string;
302
- targetGradeOrAudience: string;
303
- overview: string;
304
301
  learningObjectives: {
305
302
  code: string;
306
- name: string;
303
+ successCriteria: string;
307
304
  description: string;
305
+ name: string;
308
306
  bloomLevel: string;
309
- successCriteria: string;
310
307
  standardRefs?: string[] | undefined;
311
308
  conceptRefs?: string[] | undefined;
312
309
  }[];
310
+ teacherNotes: {
311
+ commonPitfalls: string[];
312
+ troubleshootingMatrix: {
313
+ issue: string;
314
+ potentialCause: string;
315
+ solution: string;
316
+ }[];
317
+ extensionNotes: string;
318
+ };
319
+ hookScenario: string;
320
+ keywords: string[];
321
+ topic: string;
322
+ targetGradeOrAudience: string;
323
+ overview: string;
313
324
  prerequisites: string;
314
325
  materialsSummary: string;
315
- keywords: string[];
316
326
  hookTitle: string;
317
- hookScenario: string;
318
327
  hookQuestions: string[];
319
328
  coreConcepts: {
320
329
  name: string;
@@ -332,8 +341,8 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
332
341
  goldTier: string;
333
342
  };
334
343
  sections: {
335
- title: string;
336
344
  durationMinutes: number;
345
+ title: string;
337
346
  teacherActions: string;
338
347
  studentActions: string;
339
348
  analogies: string[];
@@ -344,15 +353,6 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
344
353
  expectedAnswerOrRubric: string;
345
354
  metacognitivePrompt: string;
346
355
  };
347
- teacherNotes: {
348
- commonPitfalls: string[];
349
- troubleshootingMatrix: {
350
- issue: string;
351
- potentialCause: string;
352
- solution: string;
353
- }[];
354
- extensionNotes: string;
355
- };
356
356
  guidedPractice?: {
357
357
  title: string;
358
358
  explanation: string;
@@ -361,8 +361,8 @@ declare function streamLessonMasterFlow(input: StreamLessonMasterInput): Promise
361
361
  mermaidDiagram: string;
362
362
  } | undefined;
363
363
  independentPractice?: {
364
- title: string;
365
364
  description: string;
365
+ title: string;
366
366
  } | undefined;
367
367
  }, never>>;
368
368
 
@@ -385,11 +385,11 @@ declare function streamSelfLabFlow(input: StreamSelfLabInput): Promise<ai.Stream
385
385
  techStack?: (string | undefined)[] | undefined;
386
386
  challenges?: {
387
387
  bronze?: {
388
- title?: string | undefined;
389
388
  objective?: string | undefined;
390
- tier?: "bronze" | "silver" | "gold" | undefined;
389
+ title?: string | undefined;
391
390
  expectedOutput?: string | undefined;
392
391
  estimatedMinutes?: number | undefined;
392
+ tier?: "bronze" | "silver" | "gold" | undefined;
393
393
  tasks?: (string | undefined)[] | undefined;
394
394
  verifyCommand?: string | undefined;
395
395
  hints?: {
@@ -402,11 +402,11 @@ declare function streamSelfLabFlow(input: StreamSelfLabInput): Promise<ai.Stream
402
402
  } | undefined;
403
403
  } | undefined;
404
404
  silver?: {
405
- title?: string | undefined;
406
405
  objective?: string | undefined;
407
- tier?: "bronze" | "silver" | "gold" | undefined;
406
+ title?: string | undefined;
408
407
  expectedOutput?: string | undefined;
409
408
  estimatedMinutes?: number | undefined;
409
+ tier?: "bronze" | "silver" | "gold" | undefined;
410
410
  tasks?: (string | undefined)[] | undefined;
411
411
  verifyCommand?: string | undefined;
412
412
  hints?: {
@@ -419,11 +419,11 @@ declare function streamSelfLabFlow(input: StreamSelfLabInput): Promise<ai.Stream
419
419
  } | undefined;
420
420
  } | undefined;
421
421
  gold?: {
422
- title?: string | undefined;
423
422
  objective?: string | undefined;
424
- tier?: "bronze" | "silver" | "gold" | undefined;
423
+ title?: string | undefined;
425
424
  expectedOutput?: string | undefined;
426
425
  estimatedMinutes?: number | undefined;
426
+ tier?: "bronze" | "silver" | "gold" | undefined;
427
427
  tasks?: (string | undefined)[] | undefined;
428
428
  verifyCommand?: string | undefined;
429
429
  hints?: {
@@ -454,11 +454,11 @@ declare function streamSelfLabFlow(input: StreamSelfLabInput): Promise<ai.Stream
454
454
  techStack: string[];
455
455
  challenges: {
456
456
  bronze: {
457
- title: string;
458
457
  objective: string;
459
- tier: "bronze" | "silver" | "gold";
458
+ title: string;
460
459
  expectedOutput: string;
461
460
  estimatedMinutes: number;
461
+ tier: "bronze" | "silver" | "gold";
462
462
  tasks: string[];
463
463
  verifyCommand: string;
464
464
  hints: {
@@ -471,11 +471,11 @@ declare function streamSelfLabFlow(input: StreamSelfLabInput): Promise<ai.Stream
471
471
  };
472
472
  };
473
473
  silver: {
474
- title: string;
475
474
  objective: string;
476
- tier: "bronze" | "silver" | "gold";
475
+ title: string;
477
476
  expectedOutput: string;
478
477
  estimatedMinutes: number;
478
+ tier: "bronze" | "silver" | "gold";
479
479
  tasks: string[];
480
480
  verifyCommand: string;
481
481
  hints: {
@@ -488,11 +488,11 @@ declare function streamSelfLabFlow(input: StreamSelfLabInput): Promise<ai.Stream
488
488
  };
489
489
  };
490
490
  gold: {
491
- title: string;
492
491
  objective: string;
493
- tier: "bronze" | "silver" | "gold";
492
+ title: string;
494
493
  expectedOutput: string;
495
494
  estimatedMinutes: number;
495
+ tier: "bronze" | "silver" | "gold";
496
496
  tasks: string[];
497
497
  verifyCommand: string;
498
498
  hints: {
@@ -524,21 +524,14 @@ declare function streamDiagnosticQuizFlow(input: StreamDiagnosticQuizInput): Pro
524
524
  artifactType?: "QUIZ" | undefined;
525
525
  title?: string | undefined;
526
526
  language?: string | undefined;
527
- rubric?: ({
528
- exemplary?: string | undefined;
529
- proficient?: string | undefined;
530
- developing?: string | undefined;
531
- competencyDimension?: string | undefined;
532
- advanced?: string | undefined;
533
- } | undefined)[] | undefined;
534
527
  quizId?: string | undefined;
535
528
  totalQuestions?: number | undefined;
536
529
  timeAllocationMinutes?: number | undefined;
537
530
  passingScorePct?: number | undefined;
538
531
  assessmentObjectives?: ({
539
- bloomLevel?: "Remember" | "Understand" | "Apply" | "Analyze" | "Evaluate" | "Create" | undefined;
540
- standardRefs?: (string | undefined)[] | undefined;
541
532
  objective?: string | undefined;
533
+ standardRefs?: (string | undefined)[] | undefined;
534
+ bloomLevel?: "Create" | "Evaluate" | "Remember" | "Understand" | "Apply" | "Analyze" | undefined;
542
535
  aoCode?: string | undefined;
543
536
  alignedLO?: string | undefined;
544
537
  } | undefined)[] | undefined;
@@ -549,10 +542,10 @@ declare function streamDiagnosticQuizFlow(input: StreamDiagnosticQuizInput): Pro
549
542
  text?: string | undefined;
550
543
  isCorrect?: boolean | undefined;
551
544
  } | undefined)[] | undefined;
552
- bloomLevel?: "understand" | "create" | "Remember" | "Understand" | "Apply" | "Analyze" | "Evaluate" | "Create" | "remember" | "apply" | "analyze" | "evaluate" | undefined;
545
+ bloomLevel?: "create" | "Create" | "Evaluate" | "understand" | "Remember" | "Understand" | "Apply" | "Analyze" | "remember" | "apply" | "analyze" | "evaluate" | undefined;
553
546
  codeLanguage?: string | undefined;
554
547
  id?: string | undefined;
555
- questionType?: "multiple_choice" | "code_analysis" | "matching" | "open_ended" | undefined;
548
+ questionType?: "multiple_choice" | "matching" | "code_analysis" | "open_ended" | undefined;
556
549
  codeSnippet?: string | undefined;
557
550
  alignedAO?: string | undefined;
558
551
  scenarioOrStem?: string | undefined;
@@ -562,25 +555,25 @@ declare function streamDiagnosticQuizFlow(input: StreamDiagnosticQuizInput): Pro
562
555
  teacherNote?: string | undefined;
563
556
  takeawayMessage?: string | undefined;
564
557
  } | undefined)[] | undefined;
558
+ rubric?: ({
559
+ proficient?: string | undefined;
560
+ advanced?: string | undefined;
561
+ competencyDimension?: string | undefined;
562
+ developing?: string | undefined;
563
+ exemplary?: string | undefined;
564
+ } | undefined)[] | undefined;
565
565
  }, {
566
566
  artifactType: "QUIZ";
567
567
  title: string;
568
568
  language: string;
569
- rubric: {
570
- exemplary: string;
571
- proficient: string;
572
- developing: string;
573
- competencyDimension: string;
574
- advanced: string;
575
- }[];
576
569
  quizId: string;
577
570
  totalQuestions: number;
578
571
  timeAllocationMinutes: number;
579
572
  passingScorePct: number;
580
573
  assessmentObjectives: {
581
- bloomLevel: "Remember" | "Understand" | "Apply" | "Analyze" | "Evaluate" | "Create";
582
- standardRefs: string[];
583
574
  objective: string;
575
+ standardRefs: string[];
576
+ bloomLevel: "Create" | "Evaluate" | "Remember" | "Understand" | "Apply" | "Analyze";
584
577
  aoCode: string;
585
578
  alignedLO: string;
586
579
  }[];
@@ -591,10 +584,10 @@ declare function streamDiagnosticQuizFlow(input: StreamDiagnosticQuizInput): Pro
591
584
  text: string;
592
585
  isCorrect: boolean;
593
586
  }[];
594
- bloomLevel: "understand" | "create" | "Remember" | "Understand" | "Apply" | "Analyze" | "Evaluate" | "Create" | "remember" | "apply" | "analyze" | "evaluate";
587
+ bloomLevel: "create" | "Create" | "Evaluate" | "understand" | "Remember" | "Understand" | "Apply" | "Analyze" | "remember" | "apply" | "analyze" | "evaluate";
595
588
  codeLanguage: string;
596
589
  id: string;
597
- questionType: "multiple_choice" | "code_analysis" | "matching" | "open_ended";
590
+ questionType: "multiple_choice" | "matching" | "code_analysis" | "open_ended";
598
591
  codeSnippet?: string | undefined;
599
592
  alignedAO?: string | undefined;
600
593
  scenarioOrStem?: string | undefined;
@@ -604,6 +597,13 @@ declare function streamDiagnosticQuizFlow(input: StreamDiagnosticQuizInput): Pro
604
597
  teacherNote?: string | undefined;
605
598
  takeawayMessage?: string | undefined;
606
599
  }[];
600
+ rubric: {
601
+ proficient: string;
602
+ advanced: string;
603
+ competencyDimension: string;
604
+ developing: string;
605
+ exemplary: string;
606
+ }[];
607
607
  }, never>>;
608
608
 
609
609
  /**
@@ -850,6 +850,7 @@ declare const contentTools: {
850
850
  }>, "many">;
851
851
  durationMinutes: z.ZodDefault<z.ZodNumber>;
852
852
  }, "strip", z.ZodTypeAny, {
853
+ durationMinutes: number;
853
854
  lessonId: string;
854
855
  title: string;
855
856
  learningObjectives: {
@@ -857,7 +858,6 @@ declare const contentTools: {
857
858
  statement: string;
858
859
  standardRefs?: string[] | undefined;
859
860
  }[];
860
- durationMinutes: number;
861
861
  }, {
862
862
  lessonId: string;
863
863
  title: string;
@@ -1017,19 +1017,19 @@ declare const assessorTools: {
1017
1017
  levels: Record<string, string>;
1018
1018
  }>, "many">;
1019
1019
  }, "strip", z.ZodTypeAny, {
1020
- lessonId: string;
1021
1020
  criteria: {
1022
1021
  criterionName: string;
1023
1022
  weight: number;
1024
1023
  levels: Record<string, string>;
1025
1024
  }[];
1026
- }, {
1027
1025
  lessonId: string;
1026
+ }, {
1028
1027
  criteria: {
1029
1028
  criterionName: string;
1030
1029
  weight: number;
1031
1030
  levels: Record<string, string>;
1032
1031
  }[];
1032
+ lessonId: string;
1033
1033
  }>;
1034
1034
  };
1035
1035
  };
@@ -1072,12 +1072,12 @@ declare const techSmeTools: {
1072
1072
  code: z.ZodString;
1073
1073
  expectedOutput: z.ZodOptional<z.ZodString>;
1074
1074
  }, "strip", z.ZodTypeAny, {
1075
- language: "swift" | "python" | "javascript" | "html_css";
1076
1075
  code: string;
1076
+ language: "swift" | "python" | "javascript" | "html_css";
1077
1077
  expectedOutput?: string | undefined;
1078
1078
  }, {
1079
- language: "swift" | "python" | "javascript" | "html_css";
1080
1079
  code: string;
1080
+ language: "swift" | "python" | "javascript" | "html_css";
1081
1081
  expectedOutput?: string | undefined;
1082
1082
  }>;
1083
1083
  };
@@ -1088,11 +1088,11 @@ declare const techSmeTools: {
1088
1088
  language: z.ZodString;
1089
1089
  code: z.ZodString;
1090
1090
  }, "strip", z.ZodTypeAny, {
1091
- language: string;
1092
1091
  code: string;
1093
- }, {
1094
1092
  language: string;
1093
+ }, {
1095
1094
  code: string;
1095
+ language: string;
1096
1096
  }>;
1097
1097
  };
1098
1098
  };
package/dist/index.cjs CHANGED
@@ -1289,7 +1289,7 @@ var init_lessonFlowParser = __esm({
1289
1289
 
1290
1290
  // src/ai/prompts/slideBlueprintPrompt.ts
1291
1291
  function buildSlideBlueprintPrompt(params) {
1292
- const { lessonFlow, targetSlideCount = 20, stylePresetName = "Blue Professional" } = params;
1292
+ const { lessonFlow, targetSlideCount, stylePresetName = "Blue Professional" } = params;
1293
1293
  const activitiesSummary = lessonFlow.activities.map(
1294
1294
  (a) => `Seq ${a.seq} [${a.phase}]: ${a.purpose} (Teacher: ${a.teacherMove} | Student: ${a.studentAction} | Time: ${a.time})`
1295
1295
  ).join("\n");
@@ -1297,9 +1297,11 @@ function buildSlideBlueprintPrompt(params) {
1297
1297
  (p) => `Phase "${p.phaseName}" (${p.timing || "Standard"}):
1298
1298
  ${p.content.slice(0, 500)}...`
1299
1299
  ).join("\n\n");
1300
+ const countGuidance = targetSlideCount ? `The target is approximately ${targetSlideCount} slides.` : `Determine the organic, optimal number of slides (typically 12 to 25 slides) based directly on the number of activities, instructional moves, and depth of content in the LESSON plan.`;
1300
1301
  return `
1301
1302
  You are @illustrator, Chief Slide Architect for the Course Builder OS.
1302
- Your task is to analyze the canonical LESSON plan and architect an authoritative, high-fidelity **SLIDE BLUEPRINT** of EXACTLY ${targetSlideCount} slides.
1303
+ Your task is to analyze the canonical LESSON plan and architect an authoritative, high-fidelity **SLIDE BLUEPRINT**.
1304
+ ${countGuidance}
1303
1305
 
1304
1306
  ### \u{1F3DB}\uFE0F PEDAGOGICAL GROUND TRUTH (FROM CANONICAL LESSON):
1305
1307
  - Lesson Title: "${lessonFlow.lessonTitle}"
@@ -1317,17 +1319,18 @@ ${phasesSummary || lessonFlow.rawContent.slice(0, 3e3)}
1317
1319
  ---
1318
1320
 
1319
1321
  ### \u{1F3AF} ARCHITECTURAL RULES (STRICTLY INVARIANT):
1320
- 1. **PEDAGOGICAL FIDELITY (1-TO-1 PROJECTION)**:
1322
+ 1. **ORGANIC PEDAGOGICAL FIDELITY (1-TO-1 PROJECTION)**:
1321
1323
  - The slide sequence MUST follow the EXACT flow of the LESSON phases (${lessonFlow.pedagogicalModel.toUpperCase()}).
1324
+ - The number of slides is determined by the substance of the lesson \u2014 do NOT stretch thin content or cram rich multi-step labs into too few slides.
1322
1325
  - Do NOT invent artificial phases that do not exist in the lesson plan.
1323
1326
  - For example:
1324
- * If 5E: Engage (slides 1-4) -> Explore (slides 5-8) -> Explain (slides 9-13) -> Elaborate (slides 14-17) -> Evaluate (slides 18-20).
1325
- * If EDP: Ask/Problem (slides 1-4) -> Imagine & Plan (slides 5-8) -> Create & Prototype (slides 9-14) -> Test & Debug (slides 15-17) -> Improve & Share (slides 18-20).
1326
- * If PBL: Driving Question (slides 1-4) -> Inquiry (slides 5-9) -> Milestone Sprint (slides 10-15) -> Review & Exhibition (slides 16-20).
1327
+ * If 5E: Engage -> Explore -> Explain -> Elaborate -> Evaluate.
1328
+ * If EDP: Ask/Problem -> Imagine & Plan -> Create & Prototype -> Test & Debug -> Improve & Share.
1329
+ * If PBL: Driving Question -> Inquiry -> Milestone Sprint -> Review & Exhibition.
1327
1330
 
1328
- 2. **CHUNKY CLUSTERS (3 TO 4 CLUSTERS)**:
1329
- - Group the ${targetSlideCount} slides into 3 to 4 natural clusters (each cluster contains 4 to 6 slides).
1330
- - Each cluster corresponds to a major pedagogical transition in the lesson.
1331
+ 2. **CHUNKY CLUSTERS (4 TO 6 SLIDES PER CLUSTER)**:
1332
+ - Partition the slides into natural clusters corresponding to the major pedagogical transitions in the lesson.
1333
+ - Each cluster MUST contain 4 to 6 slides to ensure downstream token generation remains focused, high-fidelity, and non-repetitive.
1331
1334
 
1332
1335
  3. **SEMANTIC LAYOUT SLOTS (CHOOSE FROM VERIFIED TEMPLATES)**:
1333
1336
  Use one of these valid layoutIds for each slide:
@@ -1474,7 +1477,7 @@ async function executeSlideProductionWorkflow(options) {
1474
1477
  lessonMarkdown,
1475
1478
  lessonCode,
1476
1479
  lessonTitle,
1477
- targetSlideCount = 20,
1480
+ targetSlideCount,
1478
1481
  stylePresetId = "blue-professional",
1479
1482
  language = "Vietnamese",
1480
1483
  languageDirective = "",
@@ -1493,7 +1496,8 @@ async function executeSlideProductionWorkflow(options) {
1493
1496
  presentationKitCore = await import('@thanh01.pmt/presentation-kit');
1494
1497
  } catch {
1495
1498
  }
1496
- onProgress?.("@illustrator", `[1/4] Ph\xE2n t\xEDch m\u1EA1ch b\xE0i gi\u1EA3ng LESSON & L\u1EADp D\xE0n \xFD ${targetSlideCount} Slides...`);
1499
+ const countLabel = targetSlideCount ? `${targetSlideCount} ` : "h\u1EEFu c\u01A1 ";
1500
+ onProgress?.("@illustrator", `[1/4] Ph\xE2n t\xEDch m\u1EA1ch b\xE0i gi\u1EA3ng LESSON & L\u1EADp D\xE0n \xFD ${countLabel}Slides...`);
1497
1501
  const lessonFlow = parseLessonFlow(lessonMarkdown);
1498
1502
  const stylePreset = presentationKitSkills?.getStylePreset ? presentationKitSkills.getStylePreset(stylePresetId) : { name: "Blue Professional" };
1499
1503
  const blueprintPrompt = buildSlideBlueprintPrompt({
@@ -1517,12 +1521,13 @@ async function executeSlideProductionWorkflow(options) {
1517
1521
  blueprintItems = JSON.parse(jsonrepair.jsonrepair(extractCleanJson(rawBlueprint)));
1518
1522
  } catch (e) {
1519
1523
  console.warn(`[SlideProductionWorkflow] Failed parsing blueprint JSON, constructing fallback:`, e);
1520
- blueprintItems = Array.from({ length: targetSlideCount }, (_, i) => ({
1524
+ const fallbackCount = targetSlideCount || Math.max(12, Math.min(24, Math.max(lessonFlow.phases.length, 4) * 4));
1525
+ blueprintItems = Array.from({ length: fallbackCount }, (_, i) => ({
1521
1526
  slideIndex: i + 1,
1522
1527
  clusterId: Math.floor(i / 5) + 1,
1523
1528
  clusterTitle: `Cluster ${Math.floor(i / 5) + 1}`,
1524
1529
  lessonPhase: lessonFlow.phases[Math.min(i, lessonFlow.phases.length - 1)]?.phaseName || "Content",
1525
- layoutId: i === 0 ? "hero-cover" : i === targetSlideCount - 1 ? "summary-takeaways" : "split-concept-code",
1530
+ layoutId: i === 0 ? "hero-cover" : i === fallbackCount - 1 ? "summary-takeaways" : "split-concept-code",
1526
1531
  title: `Slide ${i + 1}: ${lessonTitle}`,
1527
1532
  pedagogicalGoal: `Teach step ${i + 1} of ${lessonTitle}`,
1528
1533
  contentFocus: ["Key point 1", "Key point 2", "Key point 3"]
@@ -25827,7 +25832,6 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
25827
25832
  lessonMarkdown: lessonContent || "",
25828
25833
  lessonCode,
25829
25834
  lessonTitle,
25830
- targetSlideCount: 20,
25831
25835
  stylePresetId: "blue-professional",
25832
25836
  language: targetLang || "Vietnamese",
25833
25837
  languageDirective,