@thanh01.pmt/curriculum-kit 1.4.7 → 1.4.8

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.
@@ -18603,6 +18603,224 @@ var LLMJudgeEngine = class {
18603
18603
  // src/services/lessonProductionService.ts
18604
18604
  init_errors();
18605
18605
 
18606
+ // src/services/languageDirective.ts
18607
+ function resolveTargetLanguageCode(language) {
18608
+ const raw = String(language || "vi").trim().toLowerCase();
18609
+ if (raw.startsWith("vi")) return "vi";
18610
+ if (raw.startsWith("en")) return "en";
18611
+ return raw || "vi";
18612
+ }
18613
+ function targetLanguageDisplayName(code) {
18614
+ const map = {
18615
+ vi: "Vietnamese (Ti\u1EBFng Vi\u1EC7t)",
18616
+ en: "English (US)"
18617
+ };
18618
+ return map[code] || code;
18619
+ }
18620
+ function buildLanguageDirective(targetLanguage) {
18621
+ const code = resolveTargetLanguageCode(targetLanguage);
18622
+ const name = targetLanguageDisplayName(code);
18623
+ const perLanguageExamples = {
18624
+ vi: `- V\xED d\u1EE5 ti\xEAu \u0111\u1EC1 b\xE0i h\u1ECDc \u0111\xFAng chu\u1EA9n: "B\xE0i 1: Kh\xE1m ph\xE1 m\u1EA1ch \u0111i\u1EC7n c\u01A1 b\u1EA3n", "B\xE0i 2: \u0110i\u1EC1u khi\u1EC3n \u0111\xE8n LED nh\u1EA5p nh\xE1y" \u2014 KH\xD4NG d\xF9ng ti\xEAu \u0111\u1EC1 ti\u1EBFng Anh.`,
18625
+ en: `- Example compliant lesson title: "Lesson 1: Exploring Basic Circuits" \u2014 natural, idiomatic English throughout.`
18626
+ };
18627
+ const exampleLine = perLanguageExamples[code] || "";
18628
+ return `MANDATORY LANGUAGE DIRECTIVE (TARGET OUTPUT LANGUAGE: ${name}):
18629
+ - The TARGET OUTPUT LANGUAGE for this course is ${name}. You MUST author the ENTIRE document in ${name}.
18630
+ - All section titles, table headers, table cells, lesson names, learning objectives, pedagogical narratives, and cognitive analyses MUST be written in natural, fluent, academic ${name}.
18631
+ - Technical identifiers, code keywords (e.g. setup(), loop(), pinMode()), standard protocols (I2C, SPI, UART, GPIO), and component model numbers (ESP32, Arduino Uno) remain in standard technical notation, but all surrounding explanations MUST be in ${name}.
18632
+ - DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
18633
+ ${exampleLine}` : ""}`;
18634
+ }
18635
+ function matchesArtifactType(candidate, target) {
18636
+ const c = candidate.trim().toUpperCase();
18637
+ const t = target.trim().toUpperCase();
18638
+ if (c === t) return true;
18639
+ if (c.startsWith("LESSON") && t.startsWith("LESSON")) return true;
18640
+ if ((c === "CODE" || c === "CODE_LAB") && (t === "CODE" || t === "CODE_LAB")) return true;
18641
+ if ((c === "EXPOSITION" || c === "KNOWLEDGE_EXPOSITION") && (t === "EXPOSITION" || t === "KNOWLEDGE_EXPOSITION")) return true;
18642
+ if ((c === "WKS" || c === "WORKSHEET") && (t === "WKS" || t === "WORKSHEET")) return true;
18643
+ if ((c === "EXT" || c === "EXTENSION") && (t === "EXT" || t === "EXTENSION")) return true;
18644
+ return false;
18645
+ }
18646
+ var DEFAULT_VIETNAMESE_SECTION_HEADINGS = {
18647
+ LEARNER_PROFILE: {
18648
+ "Foundational Info": "Th\xF4ng tin N\u1EC1n t\u1EA3ng",
18649
+ "Entry Level": "Tr\xECnh \u0111\u1ED9 \u0110\u1EA7u v\xE0o",
18650
+ "Learning Context": "B\u1ED1i c\u1EA3nh H\u1ECDc t\u1EADp",
18651
+ "Client Objectives": "M\u1EE5c ti\xEAu Kh\xE1ch h\xE0ng & Chu\u1EA9n \u0111\u1EA7u ra"
18652
+ },
18653
+ PROJECT_BRIEF: {
18654
+ "Project Overview": "T\u1ED5ng quan D\u1EF1 \xE1n",
18655
+ "Audience & Duration": "\u0110\u1ED1i t\u01B0\u1EE3ng & Th\u1EDDi l\u01B0\u1EE3ng",
18656
+ "Learning Roadmap": "L\u1ED9 tr\xECnh H\u1ECDc t\u1EADp & C\u1ED9t m\u1ED1c",
18657
+ "Artifact Scope": "Ph\u1EA1m vi S\u1EA3n ph\u1EA9m H\u1ECDc t\u1EADp"
18658
+ },
18659
+ CURRICULUM_FRAMEWORK: {
18660
+ "Course Overview": "T\u1ED5ng quan Kh\xF3a h\u1ECDc",
18661
+ "Global Learning Objectives": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp To\xE0n di\u1EC7n",
18662
+ "Structural Hierarchy (Unit & Module)": "C\u1EA5u tr\xFAc Kh\xF3a h\u1ECDc (Unit & Module)",
18663
+ "Scope & Sequence (Detailed Roadmap)": "Ph\u1EA1m vi & Tr\xECnh t\u1EF1 Chi ti\u1EBFt"
18664
+ },
18665
+ CONTENT_STYLE_GUIDE: {
18666
+ "Voice & Tone": "Gi\u1ECDng v\u0103n & Phong c\xE1ch",
18667
+ "Standard Terminology (Glossary)": "Thu\u1EADt ng\u1EEF Chu\u1EA9n (B\u1EA3ng thu\u1EADt ng\u1EEF)",
18668
+ "Examples & Context Rules": "Quy t\u1EAFc V\xED d\u1EE5 & Ng\u1EEF c\u1EA3nh",
18669
+ "Lesson Content Standards": "Ti\xEAu chu\u1EA9n N\u1ED9i dung B\xE0i h\u1ECDc"
18670
+ },
18671
+ SECTION_LANGUAGE_CONTRACT: {
18672
+ "Metadata & Scope": "Th\xF4ng tin & Ph\u1EA1m vi H\u1EE3p \u0111\u1ED3ng",
18673
+ "Section Translation Matrix": "Ma tr\u1EADn Ti\xEAu \u0111\u1EC1 \u0110a ng\xF4n ng\u1EEF",
18674
+ "Validation Rules": "Quy t\u1EAFc X\xE1c th\u1EF1c & Kh\xF3a Chu\u1EA9n"
18675
+ },
18676
+ KNOWLEDGE_EXPOSITION: {
18677
+ "Session Scope": "Ph\u1EA1m vi Bu\u1ED5i h\u1ECDc",
18678
+ "Key Terms": "Thu\u1EADt ng\u1EEF Then ch\u1ED1t",
18679
+ "Concept Narratives": "Di\u1EC5n gi\u1EA3i Kh\xE1i ni\u1EC7m",
18680
+ "Worked Micro-Examples": "V\xED d\u1EE5 M\u1EABu Chi ti\u1EBFt",
18681
+ "Common Mistakes": "L\u1ED7i Th\u01B0\u1EDDng g\u1EB7p & Kh\u1EAFc ph\u1EE5c",
18682
+ "Self-Check Questions": "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra"
18683
+ },
18684
+ LESSON: {
18685
+ "A. Lesson Design Plan": "A. K\u1EBF ho\u1EA1ch Thi\u1EBFt k\u1EBF B\xE0i h\u1ECDc",
18686
+ "Learning Objectives & Evidence": "M\u1EE5c ti\xEAu H\u1ECDc t\u1EADp & B\u1EB1ng ch\u1EE9ng N\u0103ng l\u1EF1c",
18687
+ "Activity Sequence": "Chu\u1ED7i Ho\u1EA1t \u0111\u1ED9ng D\u1EA1y & H\u1ECDc",
18688
+ "Resource Map": "B\u1EA3n \u0111\u1ED3 T\xE0i nguy\xEAn & H\u1ECDc li\u1EC7u",
18689
+ "Assessment Map": "B\u1EA3n \u0111\u1ED3 \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c",
18690
+ "Artifact Contract": "H\u1EE3p \u0111\u1ED3ng S\u1EA3n ph\u1EA9m \u0110\u1EA7u ra",
18691
+ "B. Lesson Flow": "B. Ti\u1EBFn tr\xECnh Gi\u1EA3ng d\u1EA1y Chi ti\u1EBFt"
18692
+ },
18693
+ ACT: {
18694
+ "Computational Thinking Focus": "Tr\u1ECDng t\xE2m T\u01B0 duy M\xE1y t\xEDnh",
18695
+ "Materials & Setup": "V\u1EADt li\u1EC7u & Chu\u1EA9n b\u1ECB Thi\u1EBFt b\u1ECB",
18696
+ "Constraints & Safety": "R\xE0ng bu\u1ED9c & An to\xE0n Ph\xF2ng th\u1EF1c h\xE0nh",
18697
+ "Active Learning Workflow": "Quy tr\xECnh Ho\u1EA1t \u0111\u1ED9ng Tr\u1EA3i nghi\u1EC7m",
18698
+ "3-Tier Differentiation": "Ph\xE2n h\xF3a H\u1ECDc t\u1EADp 3 T\u1EA7ng",
18699
+ "Reflection": "T\u1ED5ng k\u1EBFt & \u0110\xFAc k\u1EBFt Tr\u1EA3i nghi\u1EC7m"
18700
+ },
18701
+ CODE: {
18702
+ "Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
18703
+ "Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
18704
+ "Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
18705
+ "Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
18706
+ "Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
18707
+ "Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
18708
+ },
18709
+ CODE_LAB: {
18710
+ "Technical Overview & Architecture Blueprint": "T\u1ED5ng quan K\u1EF9 thu\u1EADt & B\u1EA3n thi\u1EBFt k\u1EBF Ki\u1EBFn tr\xFAc",
18711
+ "Hardware Pinout & Wiring Configuration Matrix": "S\u01A1 \u0111\u1ED3 Ch\xE2n & Ma tr\u1EADn N\u1ED1i d\xE2y Ph\u1EA7n c\u1EE9ng",
18712
+ "Starter Code Sandbox": "M\xE3 ngu\u1ED3n Kh\u1EDFi \u0111\u1EA7u (Starter Code)",
18713
+ "Verified Reference Solution Code": "M\xE3 ngu\u1ED3n L\u1EDDi gi\u1EA3i Chu\u1EA9n (Reference Solution)",
18714
+ "Automated Test / Verification Script": "K\u1ECBch b\u1EA3n Ki\u1EC3m th\u1EED T\u1EF1 \u0111\u1ED9ng",
18715
+ "Common Syntax & Runtime Pitfalls Matrix": "Ma tr\u1EADn L\u1ED7i C\xFA ph\xE1p & Th\u1EDDi gian ch\u1EA1y Th\u01B0\u1EDDng g\u1EB7p"
18716
+ },
18717
+ QUIZ: {
18718
+ "Assessment Objectives": "M\u1EE5c ti\xEAu \u0110\xE1nh gi\xE1",
18719
+ "Multiple-Choice Question Bank": "Ng\xE2n h\xE0ng C\xE2u h\u1ECFi Tr\u1EAFc nghi\u1EC7m",
18720
+ "Code Analysis / Debugging Question": "C\xE2u h\u1ECFi Ph\xE2n t\xEDch M\xE3 ngu\u1ED3n & S\u1EEDa l\u1ED7i",
18721
+ "Competency Rubric": "Thang \u0111o \u0110\xE1nh gi\xE1 N\u0103ng l\u1EF1c (Rubric)"
18722
+ },
18723
+ GUIDE: {
18724
+ "Objectives & Preparation": "M\u1EE5c ti\xEAu & Chu\u1EA9n b\u1ECB Gi\u1EA3ng d\u1EA1y",
18725
+ "Preparation Checklist & Workstation Setup": "Danh m\u1EE5c Ki\u1EC3m tra Chu\u1EA9n b\u1ECB & Tr\u1EA1m Th\u1EF1c h\xE0nh",
18726
+ "Facilitation Script & Timeline": "K\u1ECBch b\u1EA3n \u0110i\u1EC1u ph\u1ED1i & Khung Th\u1EDDi gian",
18727
+ "Common Misconceptions & Diagnostic Remediation Matrix": "Quan ni\u1EC7m Sai l\u1EA7m Th\u01B0\u1EDDng g\u1EB7p & Ma tr\u1EADn Kh\u1EAFc ph\u1EE5c",
18728
+ "Differentiated Support Strategies": "Chi\u1EBFn l\u01B0\u1EE3c H\u1ED7 tr\u1EE3 Ph\xE2n h\xF3a"
18729
+ },
18730
+ HANDOUT: {
18731
+ "Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
18732
+ "Core Syntax & Mechanism Cheat Sheet": "B\u1EA3ng Tra c\u1EE9u C\xFA ph\xE1p & C\u01A1 ch\u1EBF Tr\u1ECDng t\xE2m",
18733
+ "Visual Mental Model / Architecture Diagram": "M\xF4 h\xECnh T\u01B0 duy Tr\u1EF1c quan / S\u01A1 \u0111\u1ED3 Ki\u1EBFn tr\xFAc",
18734
+ "Step-by-Step Practical Quick-Start Guide": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh T\u1EEBng b\u01B0\u1EDBc",
18735
+ "Self-Check Diagnostic Checklist": "B\u1EA3ng Ki\u1EC3m tra T\u1EF1 ch\u1EA9n \u0111o\xE1n"
18736
+ },
18737
+ WKS: {
18738
+ "Part 1: Knowledge Check": "Ph\u1EA7n 1: Ki\u1EC3m tra Ki\u1EBFn th\u1EE9c",
18739
+ "Part 2: Concept Tracing & Diagram Fill-in": "Ph\u1EA7n 2: L\u1EA7n v\u1EBFt Kh\xE1i ni\u1EC7m & \u0110i\u1EC1n S\u01A1 \u0111\u1ED3",
18740
+ "Part 3: Code Analysis & Bug Hunting Challenge": "Ph\u1EA7n 3: Ph\xE2n t\xEDch M\xE3 & Th\u1EED th\xE1ch S\u0103n l\u1ED7i",
18741
+ "Part 4: Synthesis & Problem-Solving Application": "Ph\u1EA7n 4: T\u1ED5ng h\u1EE3p & \u1EE8ng d\u1EE5ng Gi\u1EA3i quy\u1EBFt V\u1EA5n \u0111\u1EC1",
18742
+ "Part 5: Self-Reflection & Learning Log": "Ph\u1EA7n 5: T\u1EF1 suy ng\u1EABm & Nh\u1EADt k\xFD H\u1ECDc t\u1EADp"
18743
+ },
18744
+ EXT: {
18745
+ "For: Advanced Students / Extra Time": "D\xE0nh cho: H\u1ECDc sinh N\xE2ng cao / Ho\xE0n th\xE0nh S\u1EDBm",
18746
+ "Challenge 1: Mission Briefing & Real-World High-Stakes Scenario": "Th\u1EED th\xE1ch 1: B\u1ED1i c\u1EA3nh Nhi\u1EC7m v\u1EE5 Th\u1EF1c t\u1EBF & K\u1ECBch b\u1EA3n \u1EE8ng d\u1EE5ng",
18747
+ "Challenge 2: Advanced Architectural Constraints & Edge Cases": "Th\u1EED th\xE1ch 2: R\xE0ng bu\u1ED9c Ki\u1EBFn tr\xFAc N\xE2ng cao & Tr\u01B0\u1EDDng h\u1EE3p Bi\xEAn",
18748
+ "Challenge 3: Extension Milestones": "Th\u1EED th\xE1ch 3: C\xE1c M\u1ED1c Nhi\u1EC7m v\u1EE5 N\xE2ng cao",
18749
+ "Metacognitive Deep Dive & Engineering Trade-offs": "Suy ng\u1EABm Si\xEAu nh\u1EADn th\u1EE9c & \u0110\xE1nh \u0111\u1ED5i K\u1EF9 thu\u1EADt"
18750
+ },
18751
+ SLIDE: {
18752
+ "Title & Agenda": "Ti\xEAu \u0111\u1EC1 & M\u1EE5c l\u1EE5c",
18753
+ "Core Concepts": "Kh\xE1i ni\u1EC7m C\u1ED1t l\xF5i",
18754
+ "Guided Demonstration": "H\u01B0\u1EDBng d\u1EABn Th\u1EF1c h\xE0nh & Th\u1ECB ph\u1EA1m",
18755
+ "Hands-on Mission": "Nhi\u1EC7m v\u1EE5 Th\u1EF1c h\xE0nh Tr\u1EA3i nghi\u1EC7m",
18756
+ "Summary & Next Steps": "T\u1ED5ng k\u1EBFt & \u0110\u1ECBnh h\u01B0\u1EDBng Ti\u1EBFp theo"
18757
+ }
18758
+ };
18759
+ function extractSectionHeadingsFromSLC(slcInput, artifactType, targetLanguage = "vi") {
18760
+ const upperType = artifactType.trim().toUpperCase();
18761
+ const getFallback = () => {
18762
+ if (resolveTargetLanguageCode(targetLanguage) === "vi") {
18763
+ for (const [key, mapping] of Object.entries(DEFAULT_VIETNAMESE_SECTION_HEADINGS)) {
18764
+ if (matchesArtifactType(key, upperType)) {
18765
+ return mapping;
18766
+ }
18767
+ }
18768
+ }
18769
+ return {};
18770
+ };
18771
+ if (!slcInput) return getFallback();
18772
+ if (typeof slcInput === "object") {
18773
+ if (slcInput[upperType] && Object.keys(slcInput[upperType]).length > 0) return slcInput[upperType];
18774
+ for (const [key, mapping] of Object.entries(slcInput)) {
18775
+ if (matchesArtifactType(key, upperType) && Object.keys(mapping).length > 0) {
18776
+ return mapping;
18777
+ }
18778
+ }
18779
+ return getFallback();
18780
+ }
18781
+ const slcMarkdown = slcInput;
18782
+ const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
18783
+ for (const block of blocks) {
18784
+ const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
18785
+ if (!headerMatch) continue;
18786
+ const blockType = headerMatch[1].trim().toUpperCase();
18787
+ if (matchesArtifactType(blockType, upperType)) {
18788
+ const mapping = {};
18789
+ const lines = block.split("\n");
18790
+ for (const line of lines) {
18791
+ const trimmed = line.trim();
18792
+ if (trimmed.startsWith("|") && !trimmed.includes("---")) {
18793
+ const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
18794
+ if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
18795
+ mapping[cells[0]] = cells[1];
18796
+ }
18797
+ } else {
18798
+ const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
18799
+ if (bullet) {
18800
+ mapping[bullet[1].trim()] = bullet[2].trim();
18801
+ }
18802
+ }
18803
+ }
18804
+ if (Object.keys(mapping).length > 0) return mapping;
18805
+ }
18806
+ }
18807
+ return getFallback();
18808
+ }
18809
+ function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
18810
+ const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType, targetLanguage);
18811
+ if (Object.keys(headings).length === 0) {
18812
+ return "";
18813
+ }
18814
+ const lines = Object.entries(headings).map(
18815
+ ([canonical, localized]) => ` - "${canonical}" -> Use Display Heading: "${localized}"`
18816
+ );
18817
+ return `MANDATORY SECTION HEADINGS FROM SECTION_LANGUAGE_CONTRACT:
18818
+ - The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
18819
+ - In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
18820
+ ${lines.join("\n")}
18821
+ - For example: if canonical section is "Computational Thinking Focus", your heading must be "## [REQUIRED] ${headings["Computational Thinking Focus"] || "Computational Thinking Focus"}".`;
18822
+ }
18823
+
18606
18824
  // src/services/contextBuilder.ts
18607
18825
  var DEFAULT_LESSON_PRIORITIES = [
18608
18826
  "A. Lesson Design Plan",
@@ -18875,90 +19093,6 @@ function deriveArtifactTypeFromFileName(fileName) {
18875
19093
  }
18876
19094
  init_errors();
18877
19095
 
18878
- // src/services/languageDirective.ts
18879
- function resolveTargetLanguageCode(language) {
18880
- const raw = String(language || "vi").trim().toLowerCase();
18881
- if (raw.startsWith("vi")) return "vi";
18882
- if (raw.startsWith("en")) return "en";
18883
- return raw || "vi";
18884
- }
18885
- function targetLanguageDisplayName(code) {
18886
- const map = {
18887
- vi: "Vietnamese (Ti\u1EBFng Vi\u1EC7t)",
18888
- en: "English (US)"
18889
- };
18890
- return map[code] || code;
18891
- }
18892
- function buildLanguageDirective(targetLanguage) {
18893
- const code = resolveTargetLanguageCode(targetLanguage);
18894
- const name = targetLanguageDisplayName(code);
18895
- const perLanguageExamples = {
18896
- vi: `- V\xED d\u1EE5 ti\xEAu \u0111\u1EC1 b\xE0i h\u1ECDc \u0111\xFAng chu\u1EA9n: "B\xE0i 1: Kh\xE1m ph\xE1 m\u1EA1ch \u0111i\u1EC7n c\u01A1 b\u1EA3n", "B\xE0i 2: \u0110i\u1EC1u khi\u1EC3n \u0111\xE8n LED nh\u1EA5p nh\xE1y" \u2014 KH\xD4NG d\xF9ng ti\xEAu \u0111\u1EC1 ti\u1EBFng Anh.`,
18897
- en: `- Example compliant lesson title: "Lesson 1: Exploring Basic Circuits" \u2014 natural, idiomatic English throughout.`
18898
- };
18899
- const exampleLine = perLanguageExamples[code] || "";
18900
- return `MANDATORY LANGUAGE DIRECTIVE (TARGET OUTPUT LANGUAGE: ${name}):
18901
- - The TARGET OUTPUT LANGUAGE for this course is ${name}. You MUST author the ENTIRE document in ${name}.
18902
- - All section titles, table headers, table cells, lesson names, learning objectives, pedagogical narratives, and cognitive analyses MUST be written in natural, fluent, academic ${name}.
18903
- - Technical identifiers, code keywords (e.g. setup(), loop(), pinMode()), standard protocols (I2C, SPI, UART, GPIO), and component model numbers (ESP32, Arduino Uno) remain in standard technical notation, but all surrounding explanations MUST be in ${name}.
18904
- - DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
18905
- ${exampleLine}` : ""}`;
18906
- }
18907
- function extractSectionHeadingsFromSLC(slcInput, artifactType) {
18908
- if (!slcInput) return {};
18909
- const upperType = artifactType.trim().toUpperCase();
18910
- if (typeof slcInput === "object") {
18911
- if (slcInput[upperType]) return slcInput[upperType];
18912
- for (const [key, mapping] of Object.entries(slcInput)) {
18913
- if (key.toUpperCase() === upperType || upperType.startsWith("LESSON") && key.toUpperCase().startsWith("LESSON")) {
18914
- return mapping;
18915
- }
18916
- }
18917
- return {};
18918
- }
18919
- const slcMarkdown = slcInput;
18920
- const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
18921
- for (const block of blocks) {
18922
- const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
18923
- if (!headerMatch) continue;
18924
- const blockType = headerMatch[1].trim().toUpperCase();
18925
- if (blockType === upperType || upperType.startsWith("LESSON") && blockType.startsWith("LESSON")) {
18926
- const mapping = {};
18927
- const lines = block.split("\n");
18928
- for (const line of lines) {
18929
- const trimmed = line.trim();
18930
- if (trimmed.startsWith("|") && !trimmed.includes("---")) {
18931
- const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
18932
- if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
18933
- mapping[cells[0]] = cells[1];
18934
- }
18935
- } else {
18936
- const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
18937
- if (bullet) {
18938
- mapping[bullet[1].trim()] = bullet[2].trim();
18939
- }
18940
- }
18941
- }
18942
- if (Object.keys(mapping).length > 0) return mapping;
18943
- }
18944
- }
18945
- return {};
18946
- }
18947
- function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
18948
- const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType);
18949
- if (Object.keys(headings).length === 0) {
18950
- return "";
18951
- }
18952
- const lines = Object.entries(headings).map(
18953
- ([canonical, localized]) => ` - "${canonical}" -> Use Display Heading: "${localized}"`
18954
- );
18955
- return `MANDATORY SECTION HEADINGS FROM SECTION_LANGUAGE_CONTRACT:
18956
- - The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
18957
- - In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
18958
- ${lines.join("\n")}
18959
- - For example: if canonical section is "Computational Thinking Focus", your heading must be "## [REQUIRED] ${headings["Computational Thinking Focus"] || "Computational Thinking Focus"}".`;
18960
- }
18961
-
18962
19096
  // src/services/lessonProductionService.ts
18963
19097
  var __filename$1 = typeof import.meta?.url === "string" && typeof fileURLToPath === "function" ? fileURLToPath(import.meta.url) : "";
18964
19098
  var _resolvedDir = __filename$1 ? path4.dirname(__filename$1) : typeof __dirname !== "undefined" ? __dirname : process.cwd();