@thanh01.pmt/curriculum-kit 1.1.0 → 1.2.1
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.
- package/dist/ai/index.cjs +48 -4
- package/dist/ai/index.cjs.map +1 -1
- package/dist/ai/index.d.cts +11 -1
- package/dist/ai/index.d.ts +11 -1
- package/dist/ai/index.mjs +47 -5
- package/dist/ai/index.mjs.map +1 -1
- package/dist/{gateSettings-DKXRztJy.d.cts → gateSettings-Buk_MSML.d.cts} +3 -0
- package/dist/{gateSettings-DKXRztJy.d.ts → gateSettings-Buk_MSML.d.ts} +3 -0
- package/dist/index.cjs +588 -184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -7
- package/dist/index.d.ts +78 -7
- package/dist/index.mjs +578 -185
- package/dist/index.mjs.map +1 -1
- package/dist/media/index.cjs +3 -0
- package/dist/media/index.cjs.map +1 -1
- package/dist/media/index.mjs +3 -0
- package/dist/media/index.mjs.map +1 -1
- package/dist/pipeline/index.cjs +4 -4
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.mjs +4 -4
- package/dist/pipeline/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +451 -18
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.d.cts +2 -2
- package/dist/workflow/index.d.ts +2 -2
- package/dist/workflow/index.mjs +451 -18
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +22 -21
- package/LICENSE +0 -21
package/dist/index.mjs
CHANGED
|
@@ -74,6 +74,8 @@ function getSuggestedActionForCode(code) {
|
|
|
74
74
|
return "N\u1ED9i dung sinh ra thi\u1EBFu c\xE1c ph\u1EA7n b\u1EAFt bu\u1ED9c [REQUIRED]. H\xE3y k\xEDch ho\u1EA1t ki\u1EC3m th\u1EED ho\u1EB7c b\u1EA5m Rerun.";
|
|
75
75
|
case "ERR_STORAGE_IO_FAILED":
|
|
76
76
|
return "L\u1ED7i \u0111\u1ECDc/ghi t\u1EC7p tin tr\xEAn h\u1EC7 th\u1ED1ng l\u01B0u tr\u1EEF. Ki\u1EC3m tra quy\u1EC1n ghi th\u01B0 m\u1EE5c output/projects.";
|
|
77
|
+
case "ERR_CONTEXT_MISSING":
|
|
78
|
+
return "Thi\u1EBFu ngu\u1ED3n tri th\u1EE9c b\u1EAFt bu\u1ED9c (KNOWLEDGE_EXPOSITION ho\u1EB7c CANONICAL LESSON) theo Dependency Routing Matrix. Vui l\xF2ng t\u1EA1o ho\u1EB7c \u0111\u1ED3ng b\u1ED9 t\xE0i li\u1EC7u ngu\u1ED3n tr\u01B0\u1EDBc.";
|
|
77
79
|
default:
|
|
78
80
|
return "B\u1EA5m Rerun \u0111\u1EC3 th\u1EED l\u1EA1i ho\u1EB7c ki\u1EC3m tra nh\u1EADt k\xFD h\u1EC7 th\u1ED1ng.";
|
|
79
81
|
}
|
|
@@ -91,11 +93,23 @@ function isCodeRetryable(code) {
|
|
|
91
93
|
case "ERR_TASK_GATE_BLOCKED":
|
|
92
94
|
case "ERR_METERED_LIMIT_EXCEEDED":
|
|
93
95
|
case "ERR_SCHEMA_CONTRACT_VIOLATION":
|
|
96
|
+
case "ERR_CONTEXT_MISSING":
|
|
94
97
|
return false;
|
|
95
98
|
default:
|
|
96
99
|
return true;
|
|
97
100
|
}
|
|
98
101
|
}
|
|
102
|
+
function createContextMissingError(params) {
|
|
103
|
+
return new CurriculumError({
|
|
104
|
+
errorCode: "ERR_CONTEXT_MISSING",
|
|
105
|
+
artifactType: params.artifactType,
|
|
106
|
+
lessonId: params.lessonId,
|
|
107
|
+
agent: params.agent,
|
|
108
|
+
message: `Required context source "${params.missingSource}" is missing for artifact "${params.artifactType}"`,
|
|
109
|
+
suggestedAction: `Generate or provide the authoritative "${params.missingSource}" source before producing "${params.artifactType}".`,
|
|
110
|
+
retryable: false
|
|
111
|
+
});
|
|
112
|
+
}
|
|
99
113
|
var CurriculumError;
|
|
100
114
|
var init_errors = __esm({
|
|
101
115
|
"src/errors/index.ts"() {
|
|
@@ -5368,6 +5382,45 @@ Return a single valid JSON object matching SlideDeckSchema with these exact keys
|
|
|
5368
5382
|
}
|
|
5369
5383
|
`.trim();
|
|
5370
5384
|
}
|
|
5385
|
+
var SLIDE_CANONICAL_METHODOLOGY = `
|
|
5386
|
+
MANDATORY 12-14 SLIDE MICRO-CYCLE STRUCTURE (Delimited by '---'):
|
|
5387
|
+
1. **Slide 1 [Title & Mission]:** Real-world inquiry hook and overarching build mission
|
|
5388
|
+
2. **Slide 2 [Agenda & Roadmap]:** Timing and milestone breakdown table
|
|
5389
|
+
3. **Slide 3 [Warm-Up / Prior Knowledge]:** 2-column recall + 60-second diagnostic challenge card
|
|
5390
|
+
4. **Slide 4 [High-Stakes Hook Scenario]:** Authentic engineering/domain crisis card + dilemma constraint
|
|
5391
|
+
5. **Slide 5 [Core Concept 1: Mental Model]:** Definition, intuitive everyday analogy, and golden rule card
|
|
5392
|
+
6. **Slide 6 [Architecture & Visual Flow]:** Clean Mermaid diagram (flowchart or sequenceDiagram) + 3 flow steps
|
|
5393
|
+
7. **Slide 7 [Core Concept 2: Syntax / Mechanism Anatomy]:** Side-by-side runnable code + anatomy breakdown & syntax trap card
|
|
5394
|
+
8. **Slide 8 [Guided Practice: Try It Now]:** 3-minute active desk task card with starter hint and success criteria
|
|
5395
|
+
9. **Slide 9 [Integrated Hands-On Lab]:** 3-tier differentiated challenge cards (Bronze / Silver / Gold) + gotcha alert card
|
|
5396
|
+
10. **Slide 10 [Traffic Light Checkpoint & Pitfalls]:** Formative self-check cards (\u{1F7E2}/\u{1F7E1}/\u{1F534}) & diagnostic test question
|
|
5397
|
+
11. **Slide 11 [Exit Ticket & Metacognition]:** 2 scenario-based check questions + 1 metacognitive reflection prompt
|
|
5398
|
+
12. **Slide 12 [Summary & Next Steps]:** 3 core golden rules + preview card of next upcoming milestone
|
|
5399
|
+
|
|
5400
|
+
Mandatory Canvas & Presentation Invariants:
|
|
5401
|
+
- A slide is an INTERACTIVE PROJECTION CANVAS, NOT a textbook! Absolutely NO dense paragraphs or walls of text.
|
|
5402
|
+
- Follow the 6x6 rule: Maximum 4-6 bullet points per slide, maximum 8-12 words per bullet.
|
|
5403
|
+
- Structure slides using \`<div class="columns"><div>...</div><div>...</div></div>\` and \`<div class="card">\`, \`<div class="card highlight">\`, \`<div class="card warning">\`, \`<div class="card success">\`.
|
|
5404
|
+
- MANDATORY PRESENTER NOTES ON EVERY SLIDE: Every slide MUST end with \`<!-- Presenter Notes: ... -->\` containing:
|
|
5405
|
+
* SCRIPT: 60-90s teacher talk track with intuitive analogies.
|
|
5406
|
+
* COLD CALL / CHECK: Specific diagnostic question to ask students.
|
|
5407
|
+
* SCAFFOLDING / GOTCHA: Guidance for students who get stuck.
|
|
5408
|
+
* PACING: Recommended minutes for the slide.
|
|
5409
|
+
- Output 100% valid Marp Markdown.
|
|
5410
|
+
`.trim();
|
|
5411
|
+
function buildMarpMarkdownSlidePrompt(input) {
|
|
5412
|
+
return `You are @illustrator & @content (Pedagogical Slide Deck Presentation Specialists).
|
|
5413
|
+
Based on Master Lesson Plan \`LESSON_${input.lessonCode}.md\`, lesson context, and the MARP SLIDE TEMPLATE below, author the complete, highly engaging Marp presentation deck: \`SLIDE_${input.lessonCode}.md\`.
|
|
5414
|
+
|
|
5415
|
+
[MARP SLIDE TEMPLATE SCAFFOLD]:
|
|
5416
|
+
${input.templateScaffold}
|
|
5417
|
+
|
|
5418
|
+
${SLIDE_CANONICAL_METHODOLOGY}
|
|
5419
|
+
|
|
5420
|
+
${input.languageDirective}
|
|
5421
|
+
|
|
5422
|
+
${input.headingDirective}`.trim();
|
|
5423
|
+
}
|
|
5371
5424
|
|
|
5372
5425
|
// src/ai/prompts/teacherGuidePrompt.ts
|
|
5373
5426
|
function buildTeacherGuidePrompt(input) {
|
|
@@ -5507,13 +5560,13 @@ Evaluate the candidate artifact across these 6 dimensions:
|
|
|
5507
5560
|
- 0 pts: Missing critical sections.
|
|
5508
5561
|
|
|
5509
5562
|
5. **Technical & Conceptual Accuracy (15 pts):**
|
|
5510
|
-
- 15 pts: Code snippets, logic flows, architectural descriptions, and Mermaid diagrams are conceptually sound
|
|
5563
|
+
- 15 pts: Code snippets, logic flows, architectural descriptions, and Mermaid diagrams are conceptually sound and valid. If \`canonicalExposition\` or \`[KNOWLEDGE_EXPOSITION]\` is provided, content strictly adheres to canonical concepts without contradicting definitions or examples.
|
|
5511
5564
|
- 8 pts: Minor syntax inaccuracies or unidiomatic code that does not break core concepts.
|
|
5512
|
-
- 0 pts: Severe technical hallucinations, broken logic, or
|
|
5565
|
+
- 0 pts: Severe technical hallucinations, broken logic, invalid diagrams, or direct contradiction of canonical exposition knowledge.
|
|
5513
5566
|
|
|
5514
5567
|
6. **Contract Consistency & Zero-Drift (10 pts):**
|
|
5515
|
-
- 10 pts: Satellite artifact strictly adheres to the scope, tech stack, and objectives of Lesson ${lessonId} without introducing unrelated topics.
|
|
5516
|
-
- 0-5 pts: Scope drift
|
|
5568
|
+
- 10 pts: Satellite artifact strictly adheres to the scope, tech stack, and objectives of Lesson ${lessonId} without introducing unrelated topics. If \`canonicalLessonExcerpt\` is present in candidate JSON, all satellite phases/activities strictly operationalize the master Lesson Flow and Activity Sequence without inventing divergent timelines.
|
|
5569
|
+
- 0-5 pts: Scope drift, topic divergence, or disjoint activity sequence detected compared to master lesson.
|
|
5517
5570
|
|
|
5518
5571
|
## VERDICT RULES
|
|
5519
5572
|
- **PASS:** Score >= 80 AND Language Adherence = true AND Standards Alignment >= 12 (when STANDARDS GROUND TRUTH is present).
|
|
@@ -9700,6 +9753,224 @@ function resolveGateSettings(raw) {
|
|
|
9700
9753
|
function gateModeFor(resolved, type) {
|
|
9701
9754
|
return resolved[type] ?? "OFF";
|
|
9702
9755
|
}
|
|
9756
|
+
|
|
9757
|
+
// src/services/contextBuilder.ts
|
|
9758
|
+
var DEFAULT_LESSON_PRIORITIES = [
|
|
9759
|
+
"A. Lesson Design Plan",
|
|
9760
|
+
"B. Lesson Flow",
|
|
9761
|
+
"Learning Objectives & Evidence",
|
|
9762
|
+
"Activity Sequence"
|
|
9763
|
+
];
|
|
9764
|
+
var DEFAULT_KX_PRIORITIES = [
|
|
9765
|
+
"Key Terms",
|
|
9766
|
+
"Concept Narratives",
|
|
9767
|
+
"Worked Micro-Examples"
|
|
9768
|
+
];
|
|
9769
|
+
function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
9770
|
+
const budget = opts.budget ?? 12e3;
|
|
9771
|
+
const minContentChars = opts.minContentChars ?? 400;
|
|
9772
|
+
const issues = [];
|
|
9773
|
+
const source = (markdown || "").trim();
|
|
9774
|
+
if (!source) {
|
|
9775
|
+
return {
|
|
9776
|
+
excerpt: "",
|
|
9777
|
+
verified: false,
|
|
9778
|
+
sectionAware: false,
|
|
9779
|
+
includedSections: [],
|
|
9780
|
+
issues: ["empty-source"],
|
|
9781
|
+
tokenEstimate: 0
|
|
9782
|
+
};
|
|
9783
|
+
}
|
|
9784
|
+
const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
|
|
9785
|
+
const sections = parseMarkdownSections(source, slcMap, opts.artifactType);
|
|
9786
|
+
if (sections.length === 0) {
|
|
9787
|
+
issues.push("parse:no-sections");
|
|
9788
|
+
const excerpt2 = truncateByBudget(source, budget);
|
|
9789
|
+
const verified2 = excerpt2.length >= minContentChars;
|
|
9790
|
+
if (excerpt2.length < minContentChars) issues.push("content:insufficient");
|
|
9791
|
+
return {
|
|
9792
|
+
excerpt: excerpt2,
|
|
9793
|
+
verified: verified2,
|
|
9794
|
+
sectionAware: false,
|
|
9795
|
+
includedSections: [],
|
|
9796
|
+
issues,
|
|
9797
|
+
tokenEstimate: Math.round(excerpt2.length / 4)
|
|
9798
|
+
};
|
|
9799
|
+
}
|
|
9800
|
+
const byCanonical = /* @__PURE__ */ new Map();
|
|
9801
|
+
const unmatched = [];
|
|
9802
|
+
for (const s of sections) {
|
|
9803
|
+
if (s.canonicalKey && !byCanonical.has(s.canonicalKey)) {
|
|
9804
|
+
byCanonical.set(s.canonicalKey, s);
|
|
9805
|
+
} else {
|
|
9806
|
+
unmatched.push(s);
|
|
9807
|
+
}
|
|
9808
|
+
}
|
|
9809
|
+
const priorities = opts.priorities ?? DEFAULT_LESSON_PRIORITIES;
|
|
9810
|
+
const includedSections = [];
|
|
9811
|
+
const blocks = [];
|
|
9812
|
+
let used = 0;
|
|
9813
|
+
const tryAdd = (heading, body, key) => {
|
|
9814
|
+
const trimmedBody = body.trim();
|
|
9815
|
+
if (!trimmedBody) return false;
|
|
9816
|
+
const block = `## ${heading}
|
|
9817
|
+
|
|
9818
|
+
${trimmedBody}`;
|
|
9819
|
+
if (used + block.length > budget && blocks.length > 0) return false;
|
|
9820
|
+
blocks.push(block);
|
|
9821
|
+
used += block.length;
|
|
9822
|
+
includedSections.push(key);
|
|
9823
|
+
return true;
|
|
9824
|
+
};
|
|
9825
|
+
let sectionAware = false;
|
|
9826
|
+
for (const key of priorities) {
|
|
9827
|
+
const sec = byCanonical.get(key);
|
|
9828
|
+
if (!sec) continue;
|
|
9829
|
+
sectionAware = true;
|
|
9830
|
+
if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
|
|
9831
|
+
}
|
|
9832
|
+
for (const [key, sec] of byCanonical) {
|
|
9833
|
+
if (includedSections.includes(key)) continue;
|
|
9834
|
+
if (used >= budget) break;
|
|
9835
|
+
if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
|
|
9836
|
+
}
|
|
9837
|
+
for (const sec of unmatched) {
|
|
9838
|
+
if (used >= budget) break;
|
|
9839
|
+
if (!tryAdd(sec.cleanTitle, sec.body, sec.cleanTitle)) break;
|
|
9840
|
+
}
|
|
9841
|
+
if (priorities.length > 0 && !priorities.some((k) => includedSections.includes(k))) {
|
|
9842
|
+
issues.push("parse:no-priority-resolution");
|
|
9843
|
+
}
|
|
9844
|
+
let excerpt = blocks.join("\n\n");
|
|
9845
|
+
if (excerpt.length > budget) {
|
|
9846
|
+
excerpt = truncateByBudget(excerpt, budget);
|
|
9847
|
+
}
|
|
9848
|
+
const effectiveMinChars = Math.min(minContentChars, source.length);
|
|
9849
|
+
if (excerpt.length < effectiveMinChars) {
|
|
9850
|
+
issues.push("content:insufficient");
|
|
9851
|
+
}
|
|
9852
|
+
const verified = !issues.includes("parse:no-priority-resolution") && excerpt.length >= effectiveMinChars;
|
|
9853
|
+
return {
|
|
9854
|
+
excerpt,
|
|
9855
|
+
verified,
|
|
9856
|
+
sectionAware: sectionAware || priorities.length === 0 && sections.length > 0,
|
|
9857
|
+
includedSections,
|
|
9858
|
+
issues,
|
|
9859
|
+
tokenEstimate: Math.round(excerpt.length / 4)
|
|
9860
|
+
};
|
|
9861
|
+
}
|
|
9862
|
+
function buildExpositionExcerpt(markdown, opts = {}) {
|
|
9863
|
+
return buildSectionAwareExcerpt(markdown, {
|
|
9864
|
+
...opts,
|
|
9865
|
+
priorities: DEFAULT_KX_PRIORITIES
|
|
9866
|
+
});
|
|
9867
|
+
}
|
|
9868
|
+
function buildLessonExcerpt(markdown, opts = {}) {
|
|
9869
|
+
return buildSectionAwareExcerpt(markdown, {
|
|
9870
|
+
...opts,
|
|
9871
|
+
priorities: DEFAULT_LESSON_PRIORITIES
|
|
9872
|
+
});
|
|
9873
|
+
}
|
|
9874
|
+
function normalizeSlcContract(slc) {
|
|
9875
|
+
if (!slc) return void 0;
|
|
9876
|
+
if (typeof slc !== "string") return slc;
|
|
9877
|
+
const out = {};
|
|
9878
|
+
const blocks = slc.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
9879
|
+
for (const block of blocks) {
|
|
9880
|
+
const header = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
9881
|
+
if (!header?.[1]) continue;
|
|
9882
|
+
const mapping = {};
|
|
9883
|
+
for (const line of block.split("\n")) {
|
|
9884
|
+
const t = line.trim();
|
|
9885
|
+
if (!t.startsWith("|") || t.includes("---")) continue;
|
|
9886
|
+
const cells = t.split("|").map((c) => c.trim()).filter((_, i, a) => i > 0 && i < a.length - 1);
|
|
9887
|
+
const [c0, c1] = cells;
|
|
9888
|
+
if (c0 && c1 && !c0.toLowerCase().includes("canonical") && !c1.toLowerCase().includes("localized")) {
|
|
9889
|
+
mapping[c0] = c1;
|
|
9890
|
+
}
|
|
9891
|
+
}
|
|
9892
|
+
if (Object.keys(mapping).length > 0) out[header[1]] = mapping;
|
|
9893
|
+
}
|
|
9894
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
9895
|
+
}
|
|
9896
|
+
function parseMarkdownSections(markdown, slcMap, artifactType) {
|
|
9897
|
+
const sections = [];
|
|
9898
|
+
const lines = markdown.split("\n");
|
|
9899
|
+
let currentHeading = "";
|
|
9900
|
+
let currentBody = [];
|
|
9901
|
+
const reverseMap = /* @__PURE__ */ new Map();
|
|
9902
|
+
if (slcMap) {
|
|
9903
|
+
const maps = artifactType && slcMap[artifactType] ? [slcMap[artifactType]] : Object.values(slcMap);
|
|
9904
|
+
for (const m of maps) {
|
|
9905
|
+
for (const [canonical, localized] of Object.entries(m)) {
|
|
9906
|
+
reverseMap.set(normalizeHeading(localized), canonical);
|
|
9907
|
+
reverseMap.set(normalizeHeading(canonical), canonical);
|
|
9908
|
+
}
|
|
9909
|
+
}
|
|
9910
|
+
}
|
|
9911
|
+
const flush = () => {
|
|
9912
|
+
if (!currentHeading && currentBody.length === 0) return;
|
|
9913
|
+
const cleanTitle = currentHeading.replace(/^#{1,4}\s+/, "").trim();
|
|
9914
|
+
const norm = normalizeHeading(cleanTitle);
|
|
9915
|
+
const canonicalKey = reverseMap.get(norm) || findCanonicalFuzzy(norm);
|
|
9916
|
+
sections.push({
|
|
9917
|
+
rawHeading: currentHeading,
|
|
9918
|
+
cleanTitle,
|
|
9919
|
+
canonicalKey,
|
|
9920
|
+
body: currentBody.join("\n")
|
|
9921
|
+
});
|
|
9922
|
+
currentBody = [];
|
|
9923
|
+
};
|
|
9924
|
+
const hasH2 = lines.some((l) => /^##\s+/.test(l));
|
|
9925
|
+
const headingRegex = hasH2 ? /^##\s+(.*)$/ : /^#{2,3}\s+(.*)$/;
|
|
9926
|
+
for (const line of lines) {
|
|
9927
|
+
const headingMatch = line.match(headingRegex);
|
|
9928
|
+
if (headingMatch) {
|
|
9929
|
+
flush();
|
|
9930
|
+
currentHeading = line.trim();
|
|
9931
|
+
} else {
|
|
9932
|
+
currentBody.push(line);
|
|
9933
|
+
}
|
|
9934
|
+
}
|
|
9935
|
+
flush();
|
|
9936
|
+
return sections;
|
|
9937
|
+
}
|
|
9938
|
+
function normalizeHeading(str) {
|
|
9939
|
+
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
9940
|
+
}
|
|
9941
|
+
function findCanonicalFuzzy(norm) {
|
|
9942
|
+
if (norm.includes("lesson design plan") || norm.includes("ke hoach thiet ke")) {
|
|
9943
|
+
return "A. Lesson Design Plan";
|
|
9944
|
+
}
|
|
9945
|
+
if (norm.includes("lesson flow") || norm.includes("tien trinh giang day")) {
|
|
9946
|
+
return "B. Lesson Flow";
|
|
9947
|
+
}
|
|
9948
|
+
if (norm.includes("learning objective") || norm.includes("muc tieu bai hoc")) {
|
|
9949
|
+
return "Learning Objectives & Evidence";
|
|
9950
|
+
}
|
|
9951
|
+
if (norm.includes("activity sequence") || norm.includes("chuoi hoat dong")) {
|
|
9952
|
+
return "Activity Sequence";
|
|
9953
|
+
}
|
|
9954
|
+
if (norm.includes("key term") || norm.includes("thuat ngu")) {
|
|
9955
|
+
return "Key Terms";
|
|
9956
|
+
}
|
|
9957
|
+
if (norm.includes("concept narrative") || norm.includes("dien giai khai niem")) {
|
|
9958
|
+
return "Concept Narratives";
|
|
9959
|
+
}
|
|
9960
|
+
if (norm.includes("worked example") || norm.includes("vi du")) {
|
|
9961
|
+
return "Worked Micro-Examples";
|
|
9962
|
+
}
|
|
9963
|
+
return void 0;
|
|
9964
|
+
}
|
|
9965
|
+
function truncateByBudget(source, budget) {
|
|
9966
|
+
if (source.length <= budget) return source;
|
|
9967
|
+
let cut = source.slice(0, budget);
|
|
9968
|
+
const fenceCount = (cut.match(/^```/gm) || []).length;
|
|
9969
|
+
if (fenceCount % 2 === 1) cut += "\n```";
|
|
9970
|
+
return cut;
|
|
9971
|
+
}
|
|
9972
|
+
|
|
9973
|
+
// src/services/knowledgeExpositionService.ts
|
|
9703
9974
|
var EXPOSITION_REL = (lessonCode) => "_sot/expositions/" + lessonCode + ".md";
|
|
9704
9975
|
var ExpositionApprovalError = class extends Error {
|
|
9705
9976
|
constructor(message) {
|
|
@@ -9806,15 +10077,8 @@ async function ensureKnowledgeExposition(options) {
|
|
|
9806
10077
|
return { relPath: EXPOSITION_REL(lessonCode), content: stamped, reused: false, gateMode: gateModeFor(options.gates ?? {}, "KNOWLEDGE_EXPOSITION") };
|
|
9807
10078
|
}
|
|
9808
10079
|
function buildExpositionContext(expositionContent, maxChars = 6e3) {
|
|
9809
|
-
|
|
9810
|
-
|
|
9811
|
-
const sections = trimmed.split(/\n(?=## )/);
|
|
9812
|
-
let out = sections[0];
|
|
9813
|
-
for (let i = 1; i < sections.length && out.length < maxChars; i++) {
|
|
9814
|
-
const s = sections[i];
|
|
9815
|
-
out += "\n" + s.slice(0, Math.max(400, maxChars - out.length));
|
|
9816
|
-
}
|
|
9817
|
-
return out.slice(0, maxChars);
|
|
10080
|
+
if (!expositionContent || !expositionContent.trim()) return "";
|
|
10081
|
+
return buildExpositionExcerpt(expositionContent, { budget: maxChars }).excerpt;
|
|
9818
10082
|
}
|
|
9819
10083
|
function expositionCacheKey(planHash, lessonCode) {
|
|
9820
10084
|
return createHash("sha256").update(planHash + "|" + lessonCode).digest("hex").slice(0, 16);
|
|
@@ -11102,9 +11366,19 @@ function buildLanguageDirective(targetLanguage) {
|
|
|
11102
11366
|
- DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
|
|
11103
11367
|
${exampleLine}` : ""}`;
|
|
11104
11368
|
}
|
|
11105
|
-
function extractSectionHeadingsFromSLC(
|
|
11106
|
-
if (!
|
|
11369
|
+
function extractSectionHeadingsFromSLC(slcInput, artifactType) {
|
|
11370
|
+
if (!slcInput) return {};
|
|
11107
11371
|
const upperType = artifactType.trim().toUpperCase();
|
|
11372
|
+
if (typeof slcInput === "object") {
|
|
11373
|
+
if (slcInput[upperType]) return slcInput[upperType];
|
|
11374
|
+
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
11375
|
+
if (key.toUpperCase() === upperType || upperType.startsWith("LESSON") && key.toUpperCase().startsWith("LESSON")) {
|
|
11376
|
+
return mapping;
|
|
11377
|
+
}
|
|
11378
|
+
}
|
|
11379
|
+
return {};
|
|
11380
|
+
}
|
|
11381
|
+
const slcMarkdown = slcInput;
|
|
11108
11382
|
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
11109
11383
|
for (const block of blocks) {
|
|
11110
11384
|
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
@@ -11587,7 +11861,50 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11587
11861
|
}
|
|
11588
11862
|
const pedagogy = detectProjectPedagogy(framework, styleGuide, options.pedagogy);
|
|
11589
11863
|
const pedagogyLabel = pedagogy.toUpperCase();
|
|
11590
|
-
|
|
11864
|
+
let glossaryContext = "";
|
|
11865
|
+
try {
|
|
11866
|
+
const glossaryRaw = await storage.readArtifact(projectId, "_sot/GLOSSARY.json");
|
|
11867
|
+
if (glossaryRaw) {
|
|
11868
|
+
let allTerms = [];
|
|
11869
|
+
try {
|
|
11870
|
+
allTerms = JSON.parse(glossaryRaw).terms ?? [];
|
|
11871
|
+
} catch {
|
|
11872
|
+
}
|
|
11873
|
+
let scopedTermsSet = null;
|
|
11874
|
+
const planRaw = await storage.readArtifact(projectId, "_sot/CURRICULUM_PLAN.json");
|
|
11875
|
+
if (planRaw) {
|
|
11876
|
+
try {
|
|
11877
|
+
const plan = JSON.parse(planRaw);
|
|
11878
|
+
const sessionScope = plan.glossary_scope?.find((g) => g.session_id === lessonCode);
|
|
11879
|
+
if (sessionScope?.terms?.length) {
|
|
11880
|
+
scopedTermsSet = new Set(sessionScope.terms.map((t) => t.toLowerCase()));
|
|
11881
|
+
}
|
|
11882
|
+
} catch {
|
|
11883
|
+
}
|
|
11884
|
+
}
|
|
11885
|
+
const relevantTerms = scopedTermsSet ? allTerms.filter((g) => scopedTermsSet.has(g.term.toLowerCase())) : allTerms.slice(0, 10);
|
|
11886
|
+
if (relevantTerms.length > 0) {
|
|
11887
|
+
const lines = relevantTerms.map(
|
|
11888
|
+
(t) => `- **${t.term}**: ${t.definition || ""}${t.example ? ` (e.g. \`${t.example}\`)` : ""}`
|
|
11889
|
+
);
|
|
11890
|
+
glossaryContext = buildSectionAwareExcerpt(lines.join("\n"), { budget: 800 }).excerpt;
|
|
11891
|
+
}
|
|
11892
|
+
}
|
|
11893
|
+
} catch {
|
|
11894
|
+
}
|
|
11895
|
+
let effectiveStyleGuide = styleGuide ? buildSectionAwareExcerpt(styleGuide, {
|
|
11896
|
+
priorities: ["Voice & Tone", "Standard Terminology (Glossary)", "Lesson Content Standards"],
|
|
11897
|
+
budget: 2e3
|
|
11898
|
+
}).excerpt : "";
|
|
11899
|
+
let effectiveRefPack = refPack ? buildSectionAwareExcerpt(refPack, {
|
|
11900
|
+
priorities: [
|
|
11901
|
+
"Technical Overview & Architecture Blueprint",
|
|
11902
|
+
"Hardware Pinout & Wiring Configuration Matrix",
|
|
11903
|
+
"Core Pedagogical Concept Anchor & Real-World Domain Bridge"
|
|
11904
|
+
],
|
|
11905
|
+
budget: 2500
|
|
11906
|
+
}).excerpt : "";
|
|
11907
|
+
const baseContextPrefix = `PROJECT & ACADEMIC CONTEXT:
|
|
11591
11908
|
- Project ID: ${projectId}
|
|
11592
11909
|
- Pedagogical Model: ${pedagogyLabel}
|
|
11593
11910
|
- Lesson Code: ${lessonCode}
|
|
@@ -11597,13 +11914,51 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11597
11914
|
- Target Bloom Level: ${bloomLevel}
|
|
11598
11915
|
|
|
11599
11916
|
[CURRICULUM FRAMEWORK EXCERPT]:
|
|
11600
|
-
${buildFrameworkExcerptForLesson(framework, lessonId)}
|
|
11917
|
+
${buildFrameworkExcerptForLesson(framework, lessonId)}`;
|
|
11918
|
+
const glossaryBlock = glossaryContext ? `
|
|
11919
|
+
|
|
11920
|
+
[GLOSSARY TERMS (use these exact definitions)]:
|
|
11921
|
+
${glossaryContext}` : "";
|
|
11922
|
+
const standardsBlock = standardsContext ? `
|
|
11923
|
+
|
|
11924
|
+
${standardsContext}` : "";
|
|
11925
|
+
const expositionBlock = expositionContext ? `
|
|
11926
|
+
|
|
11927
|
+
[KNOWLEDGE_EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict)]:
|
|
11928
|
+
${expositionContext}` : "";
|
|
11929
|
+
const sessionSliceBlock = sessionSliceContext ? `
|
|
11930
|
+
|
|
11931
|
+
${sessionSliceContext}` : "";
|
|
11932
|
+
const assembleCommonContext = (ref, sg) => `${baseContextPrefix}
|
|
11601
11933
|
|
|
11602
11934
|
[CONTENT STYLE GUIDE EXCERPT]:
|
|
11603
|
-
${
|
|
11935
|
+
${sg}
|
|
11604
11936
|
|
|
11605
11937
|
[REFERENCE PACK GROUND TRUTH]:
|
|
11606
|
-
${
|
|
11938
|
+
${ref}${standardsBlock}${glossaryBlock}${expositionBlock}${sessionSliceBlock}`;
|
|
11939
|
+
let commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
|
|
11940
|
+
const MAX_COMPOSITE_PROMPT_CHARS = 3e4;
|
|
11941
|
+
if (commonContext.length > MAX_COMPOSITE_PROMPT_CHARS && effectiveRefPack.length > 1e3) {
|
|
11942
|
+
effectiveRefPack = buildSectionAwareExcerpt(refPack, {
|
|
11943
|
+
priorities: [
|
|
11944
|
+
"Technical Overview & Architecture Blueprint",
|
|
11945
|
+
"Hardware Pinout & Wiring Configuration Matrix"
|
|
11946
|
+
],
|
|
11947
|
+
budget: 1e3
|
|
11948
|
+
}).excerpt;
|
|
11949
|
+
commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
|
|
11950
|
+
}
|
|
11951
|
+
if (commonContext.length > MAX_COMPOSITE_PROMPT_CHARS && effectiveStyleGuide.length > 1e3) {
|
|
11952
|
+
effectiveStyleGuide = buildSectionAwareExcerpt(styleGuide, {
|
|
11953
|
+
priorities: ["Voice & Tone", "Standard Terminology (Glossary)"],
|
|
11954
|
+
budget: 1e3
|
|
11955
|
+
}).excerpt;
|
|
11956
|
+
commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
|
|
11957
|
+
}
|
|
11958
|
+
onProgress?.("@content", `[CONTEXT] Composite prompt ready (${commonContext.length} chars, adaptive budget <= ${MAX_COMPOSITE_PROMPT_CHARS})`, {
|
|
11959
|
+
type: "progress",
|
|
11960
|
+
promptChars: commonContext.length
|
|
11961
|
+
});
|
|
11607
11962
|
const producedArtifacts = [];
|
|
11608
11963
|
const lessonRelPath = `_content/${unitCode}/LESSON_${lessonCode}.md`;
|
|
11609
11964
|
const existingLessonContent = await storage.readArtifact(projectId, lessonRelPath);
|
|
@@ -11723,14 +12078,15 @@ ${yamlBlock.trim()}
|
|
|
11723
12078
|
const judgeResult = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
11724
12079
|
targetArtifactType: "LESSON",
|
|
11725
12080
|
lessonId: lessonCode,
|
|
11726
|
-
expectedLanguage: "en",
|
|
12081
|
+
expectedLanguage: targetLang || "en",
|
|
11727
12082
|
targetObjectives: judgeObjectives,
|
|
11728
12083
|
generatedContentJson: JSON.stringify({
|
|
11729
12084
|
lessonContent,
|
|
11730
12085
|
lessonId: lessonCode,
|
|
11731
12086
|
title: lessonTitle,
|
|
11732
|
-
frameworkExcerpt: framework ? framework
|
|
11733
|
-
styleGuideExcerpt:
|
|
12087
|
+
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12088
|
+
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
12089
|
+
canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
|
|
11734
12090
|
}),
|
|
11735
12091
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
11736
12092
|
});
|
|
@@ -11772,7 +12128,7 @@ ${yamlBlock.trim()}
|
|
|
11772
12128
|
onProgress?.("@repair", `\u{1F527} Repair round ${round}/${MAX_REPAIR_ROUNDS} for LESSON_${lessonCode} (judge score ${currentResult.score}/100)...`);
|
|
11773
12129
|
const repairedRaw = await runCurriculumAIInference(
|
|
11774
12130
|
[{ role: "user", content: `You previously authored \`LESSON_${lessonCode}.md\` and the academic Judge REJECTED it with the critique below.
|
|
11775
|
-
Rewrite the COMPLETE corrected document: fix every listed issue,
|
|
12131
|
+
Rewrite the COMPLETE corrected document in language "${targetLang}": fix every listed issue, preserve exact frontmatter and mandatory sections (Objectives, Activity Sequence, Lesson Flow). Output 100% clean Markdown only.
|
|
11776
12132
|
|
|
11777
12133
|
JUDGE CRITIQUE:
|
|
11778
12134
|
${repairFeedback}
|
|
@@ -11790,19 +12146,26 @@ ${currentContent}` }],
|
|
|
11790
12146
|
break;
|
|
11791
12147
|
}
|
|
11792
12148
|
const repairLint = lintAndSanitizeArtifact(repairedRaw, `LESSON_${lessonCode}.md`);
|
|
11793
|
-
|
|
12149
|
+
const candidateContent = repairLint.autoFixedContent || repairedRaw;
|
|
12150
|
+
const hasFrontmatter = /^---\s*\r?\n[\s\S]*?\r?\n---/m.test(candidateContent);
|
|
12151
|
+
if (!hasFrontmatter || candidateContent.length < Math.min(800, currentContent.length * 0.4)) {
|
|
12152
|
+
onProgress?.("@repair", `\u26A0\uFE0F Repair round ${round} dropped critical structure (length or frontmatter missing) \u2014 rejecting repaired draft, retaining previous`);
|
|
12153
|
+
break;
|
|
12154
|
+
}
|
|
12155
|
+
currentContent = candidateContent;
|
|
11794
12156
|
onProgress?.("@reviewer", `\u{1F916} Re-judging repaired LESSON_${lessonCode} (round ${round})...`);
|
|
11795
12157
|
const reJudge = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
11796
12158
|
targetArtifactType: "LESSON",
|
|
11797
12159
|
lessonId: lessonCode,
|
|
11798
|
-
expectedLanguage: "en",
|
|
12160
|
+
expectedLanguage: targetLang || "en",
|
|
11799
12161
|
targetObjectives: parseLessonObjectives(currentContent, concept, bloomLevel),
|
|
11800
12162
|
generatedContentJson: JSON.stringify({
|
|
11801
12163
|
lessonContent: currentContent,
|
|
11802
12164
|
lessonId: lessonCode,
|
|
11803
12165
|
title: lessonTitle,
|
|
11804
|
-
frameworkExcerpt: framework ? framework
|
|
11805
|
-
styleGuideExcerpt:
|
|
12166
|
+
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12167
|
+
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
12168
|
+
canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
|
|
11806
12169
|
}),
|
|
11807
12170
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
11808
12171
|
});
|
|
@@ -11923,10 +12286,34 @@ ${currentContent}` }],
|
|
|
11923
12286
|
contentHash
|
|
11924
12287
|
});
|
|
11925
12288
|
}
|
|
12289
|
+
const lessonExcerptResult = buildSectionAwareExcerpt(lessonContent, {
|
|
12290
|
+
priorities: DEFAULT_LESSON_PRIORITIES,
|
|
12291
|
+
budget: 12e3,
|
|
12292
|
+
sectionLanguageContract: slcMarkdown,
|
|
12293
|
+
artifactType: "LESSON"
|
|
12294
|
+
});
|
|
12295
|
+
const lessonExcerpt = lessonExcerptResult.excerpt;
|
|
11926
12296
|
const satelliteContext = `${commonContext}
|
|
11927
12297
|
|
|
11928
12298
|
[CANONICAL LESSON PLAN (${pedagogyLabel})]:
|
|
11929
|
-
${
|
|
12299
|
+
${lessonExcerpt}`;
|
|
12300
|
+
const judgeSat = (sat, content) => {
|
|
12301
|
+
if (gateModeFor(gates, sat) !== "LLM_JUDGE") return Promise.resolve();
|
|
12302
|
+
return judgeSatelliteArtifact({
|
|
12303
|
+
storage,
|
|
12304
|
+
projectId,
|
|
12305
|
+
lessonCode,
|
|
12306
|
+
sat,
|
|
12307
|
+
content,
|
|
12308
|
+
concept,
|
|
12309
|
+
bloomLevel,
|
|
12310
|
+
standardStatements,
|
|
12311
|
+
onProgress,
|
|
12312
|
+
targetLang,
|
|
12313
|
+
canonicalLessonContent: lessonContent,
|
|
12314
|
+
canonicalLessonExcerpt: lessonExcerpt
|
|
12315
|
+
});
|
|
12316
|
+
};
|
|
11930
12317
|
const actRelPath = `_content/${unitCode}/ACT_${lessonCode}.md`;
|
|
11931
12318
|
if (artifactScope.includes("ACT") && (!await storage.readArtifact(projectId, actRelPath) || force)) {
|
|
11932
12319
|
onProgress?.("@activity", `[2/4] Authoring Hands-on Lab: \`ACT_${lessonCode}.md\`...`);
|
|
@@ -11995,19 +12382,7 @@ ${buildHeadingDirective("ACT", slcMarkdown, targetLang)}`;
|
|
|
11995
12382
|
contentHash: computeContentHash(rawAct)
|
|
11996
12383
|
});
|
|
11997
12384
|
producedArtifacts.push(`ACT_${lessonCode}.md`);
|
|
11998
|
-
|
|
11999
|
-
await judgeSatelliteArtifact({
|
|
12000
|
-
storage,
|
|
12001
|
-
projectId,
|
|
12002
|
-
lessonCode,
|
|
12003
|
-
sat: "ACT",
|
|
12004
|
-
content: rawAct,
|
|
12005
|
-
concept,
|
|
12006
|
-
bloomLevel,
|
|
12007
|
-
standardStatements,
|
|
12008
|
-
onProgress
|
|
12009
|
-
});
|
|
12010
|
-
}
|
|
12385
|
+
await judgeSat("ACT", rawAct);
|
|
12011
12386
|
}
|
|
12012
12387
|
const quizRelPath = `_content/${unitCode}/QUIZ_${lessonCode}.md`;
|
|
12013
12388
|
if (artifactScope.includes("QUIZ") && (!await storage.readArtifact(projectId, quizRelPath) || force)) {
|
|
@@ -12071,64 +12446,25 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
|
|
|
12071
12446
|
contentHash: computeContentHash(rawQuiz)
|
|
12072
12447
|
});
|
|
12073
12448
|
producedArtifacts.push(`QUIZ_${lessonCode}.md`);
|
|
12074
|
-
|
|
12075
|
-
await judgeSatelliteArtifact({
|
|
12076
|
-
storage,
|
|
12077
|
-
projectId,
|
|
12078
|
-
lessonCode,
|
|
12079
|
-
sat: "QUIZ",
|
|
12080
|
-
content: rawQuiz,
|
|
12081
|
-
concept,
|
|
12082
|
-
bloomLevel,
|
|
12083
|
-
standardStatements,
|
|
12084
|
-
onProgress
|
|
12085
|
-
});
|
|
12086
|
-
}
|
|
12449
|
+
await judgeSat("QUIZ", rawQuiz);
|
|
12087
12450
|
}
|
|
12088
12451
|
const slideRelPath = `_content/${unitCode}/SLIDE_${lessonCode}.md`;
|
|
12089
12452
|
if (artifactScope.includes("SLIDE") && (!await storage.readArtifact(projectId, slideRelPath) || force)) {
|
|
12090
12453
|
onProgress?.("@illustrator", `[4/4] Authoring Presentation Slide Deck: \`SLIDE_${lessonCode}.md\`...`);
|
|
12091
12454
|
const canonicalSlideTemplate = loadCurriculumTemplate("SLIDE_template.md");
|
|
12092
|
-
const
|
|
12093
|
-
Based on Master Lesson Plan \`LESSON_${lessonCode}.md\`, lesson context, and the MARP SLIDE TEMPLATE below, author the complete, highly engaging Marp presentation deck: \`SLIDE_${lessonCode}.md\`.
|
|
12094
|
-
|
|
12095
|
-
[MARP SLIDE TEMPLATE SCAFFOLD]:
|
|
12096
|
-
${canonicalSlideTemplate || `---
|
|
12455
|
+
const templateScaffold = canonicalSlideTemplate || `---
|
|
12097
12456
|
marp: true
|
|
12098
12457
|
theme: default
|
|
12099
12458
|
paginate: true
|
|
12100
12459
|
header: "${titleHeader(lessonTitle)}"
|
|
12101
12460
|
footer: "Curriculum OS \u2022 ${lessonCode} (${pedagogyLabel})"
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
12105
|
-
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
5. **Slide 5 [Core Concept 1: Mental Model]:** Definition, intuitive everyday analogy, and golden rule card
|
|
12110
|
-
6. **Slide 6 [Architecture & Visual Flow]:** Clean Mermaid diagram (flowchart or sequenceDiagram) + 3 flow steps
|
|
12111
|
-
7. **Slide 7 [Core Concept 2: Syntax / Mechanism Anatomy]:** Side-by-side 6-10 lines runnable code + anatomy breakdown & syntax trap card
|
|
12112
|
-
8. **Slide 8 [Guided Practice: Try It Now]:** 3-minute active desk task card with starter hint and success criteria
|
|
12113
|
-
9. **Slide 9 [Integrated Hands-On Lab]:** 3-tier differentiated challenge cards (Bronze / Silver / Gold) + gotcha alert card
|
|
12114
|
-
10. **Slide 10 [Traffic Light Checkpoint & Pitfalls]:** Formative self-check cards (\u{1F7E2}/\u{1F7E1}/\u{1F534}) & diagnostic test question
|
|
12115
|
-
11. **Slide 11 [Exit Ticket & Metacognition]:** 2 scenario-based check questions + 1 metacognitive reflection prompt
|
|
12116
|
-
12. **Slide 12 [Summary & Next Steps]:** 3 core golden rules + preview card of next upcoming milestone
|
|
12117
|
-
|
|
12118
|
-
Mandatory Canvas & Presentation Invariants:
|
|
12119
|
-
- A slide is an INTERACTIVE PROJECTION CANVAS, NOT a textbook! Absolutely NO dense paragraphs or walls of text.
|
|
12120
|
-
- Follow the 6x6 rule: Maximum 4-6 bullet points per slide, maximum 8-12 words per bullet.
|
|
12121
|
-
- Structure slides using \`<div class="columns"><div>...</div><div>...</div></div>\` and \`<div class="card">\`, \`<div class="card highlight">\`, \`<div class="card warning">\`, \`<div class="card success">\`.
|
|
12122
|
-
- MANDATORY PRESENTER NOTES ON EVERY SLIDE: Every slide MUST end with \`<!-- Presenter Notes: ... -->\` containing:
|
|
12123
|
-
* SCRIPT: 60-90s teacher talk track with intuitive analogies.
|
|
12124
|
-
* COLD CALL / CHECK: Specific diagnostic question to ask students.
|
|
12125
|
-
* SCAFFOLDING / GOTCHA: Guidance for students who get stuck.
|
|
12126
|
-
* PACING: Recommended minutes for the slide.
|
|
12127
|
-
- Output 100% valid Marp Markdown.
|
|
12128
|
-
|
|
12129
|
-
${languageDirective}
|
|
12130
|
-
|
|
12131
|
-
${buildHeadingDirective("SLIDE", slcMarkdown, targetLang)}`;
|
|
12461
|
+
---`;
|
|
12462
|
+
const slidePrompt = buildMarpMarkdownSlidePrompt({
|
|
12463
|
+
lessonCode,
|
|
12464
|
+
templateScaffold,
|
|
12465
|
+
languageDirective,
|
|
12466
|
+
headingDirective: buildHeadingDirective("SLIDE", slcMarkdown, targetLang)
|
|
12467
|
+
});
|
|
12132
12468
|
const rawSlide = await runCurriculumAIInference(
|
|
12133
12469
|
[{ role: "user", content: slidePrompt }],
|
|
12134
12470
|
satelliteContext,
|
|
@@ -12154,19 +12490,7 @@ ${buildHeadingDirective("SLIDE", slcMarkdown, targetLang)}`;
|
|
|
12154
12490
|
contentHash: computeContentHash(rawSlide)
|
|
12155
12491
|
});
|
|
12156
12492
|
producedArtifacts.push(`SLIDE_${lessonCode}.md`);
|
|
12157
|
-
|
|
12158
|
-
await judgeSatelliteArtifact({
|
|
12159
|
-
storage,
|
|
12160
|
-
projectId,
|
|
12161
|
-
lessonCode,
|
|
12162
|
-
sat: "SLIDE",
|
|
12163
|
-
content: rawSlide,
|
|
12164
|
-
concept,
|
|
12165
|
-
bloomLevel,
|
|
12166
|
-
standardStatements,
|
|
12167
|
-
onProgress
|
|
12168
|
-
});
|
|
12169
|
-
}
|
|
12493
|
+
await judgeSat("SLIDE", rawSlide);
|
|
12170
12494
|
}
|
|
12171
12495
|
const guideRelPath = `_content/${unitCode}/GUIDE_${lessonCode}.md`;
|
|
12172
12496
|
if (artifactScope.includes("GUIDE") && (!await storage.readArtifact(projectId, guideRelPath) || force)) {
|
|
@@ -12216,19 +12540,7 @@ ${buildHeadingDirective("GUIDE", slcMarkdown, targetLang)}`;
|
|
|
12216
12540
|
contentHash: computeContentHash(rawGuide)
|
|
12217
12541
|
});
|
|
12218
12542
|
producedArtifacts.push(`GUIDE_${lessonCode}.md`);
|
|
12219
|
-
|
|
12220
|
-
await judgeSatelliteArtifact({
|
|
12221
|
-
storage,
|
|
12222
|
-
projectId,
|
|
12223
|
-
lessonCode,
|
|
12224
|
-
sat: "GUIDE",
|
|
12225
|
-
content: rawGuide,
|
|
12226
|
-
concept,
|
|
12227
|
-
bloomLevel,
|
|
12228
|
-
standardStatements,
|
|
12229
|
-
onProgress
|
|
12230
|
-
});
|
|
12231
|
-
}
|
|
12543
|
+
await judgeSat("GUIDE", rawGuide);
|
|
12232
12544
|
}
|
|
12233
12545
|
}
|
|
12234
12546
|
const handoutRelPath = `_content/${unitCode}/HANDOUT_${lessonCode}.md`;
|
|
@@ -12279,19 +12591,7 @@ ${buildHeadingDirective("HANDOUT", slcMarkdown, targetLang)}`;
|
|
|
12279
12591
|
contentHash: computeContentHash(rawHandout)
|
|
12280
12592
|
});
|
|
12281
12593
|
producedArtifacts.push(`HANDOUT_${lessonCode}.md`);
|
|
12282
|
-
|
|
12283
|
-
await judgeSatelliteArtifact({
|
|
12284
|
-
storage,
|
|
12285
|
-
projectId,
|
|
12286
|
-
lessonCode,
|
|
12287
|
-
sat: "HANDOUT",
|
|
12288
|
-
content: rawHandout,
|
|
12289
|
-
concept,
|
|
12290
|
-
bloomLevel,
|
|
12291
|
-
standardStatements,
|
|
12292
|
-
onProgress
|
|
12293
|
-
});
|
|
12294
|
-
}
|
|
12594
|
+
await judgeSat("HANDOUT", rawHandout);
|
|
12295
12595
|
}
|
|
12296
12596
|
}
|
|
12297
12597
|
const wksRelPath = `_content/${unitCode}/WKS_${lessonCode}.md`;
|
|
@@ -12346,19 +12646,7 @@ ${buildHeadingDirective("WKS", slcMarkdown, targetLang)}`;
|
|
|
12346
12646
|
contentHash: computeContentHash(rawWks)
|
|
12347
12647
|
});
|
|
12348
12648
|
producedArtifacts.push(`WKS_${lessonCode}.md`);
|
|
12349
|
-
|
|
12350
|
-
await judgeSatelliteArtifact({
|
|
12351
|
-
storage,
|
|
12352
|
-
projectId,
|
|
12353
|
-
lessonCode,
|
|
12354
|
-
sat: "WKS",
|
|
12355
|
-
content: rawWks,
|
|
12356
|
-
concept,
|
|
12357
|
-
bloomLevel,
|
|
12358
|
-
standardStatements,
|
|
12359
|
-
onProgress
|
|
12360
|
-
});
|
|
12361
|
-
}
|
|
12649
|
+
await judgeSat("WKS", rawWks);
|
|
12362
12650
|
}
|
|
12363
12651
|
}
|
|
12364
12652
|
const codeRelPath = `_content/${unitCode}/CODE_${lessonCode}.md`;
|
|
@@ -12422,19 +12710,7 @@ ${buildHeadingDirective("CODE", slcMarkdown, targetLang)}`;
|
|
|
12422
12710
|
contentHash: computeContentHash(rawCode)
|
|
12423
12711
|
});
|
|
12424
12712
|
producedArtifacts.push(`CODE_${lessonCode}.md`);
|
|
12425
|
-
|
|
12426
|
-
await judgeSatelliteArtifact({
|
|
12427
|
-
storage,
|
|
12428
|
-
projectId,
|
|
12429
|
-
lessonCode,
|
|
12430
|
-
sat: "CODE",
|
|
12431
|
-
content: rawCode,
|
|
12432
|
-
concept,
|
|
12433
|
-
bloomLevel,
|
|
12434
|
-
standardStatements,
|
|
12435
|
-
onProgress
|
|
12436
|
-
});
|
|
12437
|
-
}
|
|
12713
|
+
await judgeSat("CODE", rawCode);
|
|
12438
12714
|
}
|
|
12439
12715
|
}
|
|
12440
12716
|
const extRelPath = `_content/${unitCode}/EXT_${lessonCode}.md`;
|
|
@@ -12487,19 +12763,7 @@ ${buildHeadingDirective("EXT", slcMarkdown, targetLang)}`;
|
|
|
12487
12763
|
contentHash: computeContentHash(rawExt)
|
|
12488
12764
|
});
|
|
12489
12765
|
producedArtifacts.push(`EXT_${lessonCode}.md`);
|
|
12490
|
-
|
|
12491
|
-
await judgeSatelliteArtifact({
|
|
12492
|
-
storage,
|
|
12493
|
-
projectId,
|
|
12494
|
-
lessonCode,
|
|
12495
|
-
sat: "EXT",
|
|
12496
|
-
content: rawExt,
|
|
12497
|
-
concept,
|
|
12498
|
-
bloomLevel,
|
|
12499
|
-
standardStatements,
|
|
12500
|
-
onProgress
|
|
12501
|
-
});
|
|
12502
|
-
}
|
|
12766
|
+
await judgeSat("EXT", rawExt);
|
|
12503
12767
|
}
|
|
12504
12768
|
}
|
|
12505
12769
|
onProgress?.("@reviewer", `\u2705 Successfully authored all requested artifacts for \`${lessonCode}\` (${pedagogyLabel})!`);
|
|
@@ -12565,12 +12829,22 @@ async function judgeSatelliteArtifact(ctx) {
|
|
|
12565
12829
|
const { storage, projectId, lessonCode, sat, content } = ctx;
|
|
12566
12830
|
try {
|
|
12567
12831
|
ctx.onProgress?.("@reviewer", `\u{1F916} Judging ${sat}_${lessonCode}...`);
|
|
12832
|
+
const targetObjectives = parseLessonObjectives(
|
|
12833
|
+
ctx.canonicalLessonContent || content,
|
|
12834
|
+
ctx.concept,
|
|
12835
|
+
ctx.bloomLevel
|
|
12836
|
+
);
|
|
12568
12837
|
const result = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12569
12838
|
targetArtifactType: sat,
|
|
12570
12839
|
lessonId: lessonCode,
|
|
12571
|
-
expectedLanguage: "en",
|
|
12572
|
-
targetObjectives
|
|
12573
|
-
generatedContentJson: JSON.stringify({
|
|
12840
|
+
expectedLanguage: ctx.targetLang || "en",
|
|
12841
|
+
targetObjectives,
|
|
12842
|
+
generatedContentJson: JSON.stringify({
|
|
12843
|
+
content,
|
|
12844
|
+
artifactType: sat,
|
|
12845
|
+
lessonId: lessonCode,
|
|
12846
|
+
canonicalLessonExcerpt: ctx.canonicalLessonExcerpt
|
|
12847
|
+
}),
|
|
12574
12848
|
standardStatements: Object.keys(ctx.standardStatements).length > 0 ? ctx.standardStatements : void 0
|
|
12575
12849
|
});
|
|
12576
12850
|
const passed = result.passed && result.score >= 85;
|
|
@@ -12693,6 +12967,87 @@ async function produceBatchLessons(storage, projectId, lessonIds, options = {})
|
|
|
12693
12967
|
// src/services/singleArtifactService.ts
|
|
12694
12968
|
init_streamRunner();
|
|
12695
12969
|
init_errors();
|
|
12970
|
+
|
|
12971
|
+
// src/services/contextRouting.ts
|
|
12972
|
+
init_errors();
|
|
12973
|
+
var ARTIFACT_DEPENDENCY_ROUTING = {
|
|
12974
|
+
LESSON: {
|
|
12975
|
+
required: ["KNOWLEDGE_EXPOSITION", "SESSION_SLICE", "FRAMEWORK_EXCERPT"],
|
|
12976
|
+
optional: ["STYLE_GUIDE", "REFERENCE_PACK"],
|
|
12977
|
+
rationale: "D\u1EA1y theo ki\u1EBFn th\u1EE9c chu\u1EA9n c\u1EE7a plan, ph\xE2n b\u1ED5 m\u1EE5c ti\xEAu v\xE0 khung ch\u01B0\u01A1ng tr\xECnh"
|
|
12978
|
+
},
|
|
12979
|
+
HANDOUT: {
|
|
12980
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12981
|
+
optional: ["SESSION_SLICE"],
|
|
12982
|
+
rationale: "T\xE0i li\u1EC7u t\u1EF1 h\u1ECDc \u2014 b\xE1m kh\xE1i ni\u1EC7m chu\u1EA9n, kh\xF4ng c\u1EA7n activity timeline"
|
|
12983
|
+
},
|
|
12984
|
+
EXT: {
|
|
12985
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12986
|
+
optional: ["SESSION_SLICE"],
|
|
12987
|
+
rationale: "Th\u1EED th\xE1ch m\u1EDF r\u1ED9ng chuy\xEAn s\xE2u b\xE1m kh\xE1i ni\u1EC7m"
|
|
12988
|
+
},
|
|
12989
|
+
CODE: {
|
|
12990
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12991
|
+
optional: ["LESSON_OBJECTIVES"],
|
|
12992
|
+
rationale: "Code lab th\u1EF1c h\xE0nh b\xE1m kh\xE1i ni\u1EC7m k\u1EF9 thu\u1EADt v\xE0 v\xED d\u1EE5 worked examples"
|
|
12993
|
+
},
|
|
12994
|
+
ACT: {
|
|
12995
|
+
required: ["CANONICAL_LESSON"],
|
|
12996
|
+
optional: ["KNOWLEDGE_EXPOSITION", "SESSION_SLICE"],
|
|
12997
|
+
rationale: "STEM Activity Lab b\u1EAFt bu\u1ED9c ph\u1EA3i kh\u1EDBp 100% Activity Sequence v\xE0 Lesson Flow c\u1EE7a LESSON"
|
|
12998
|
+
},
|
|
12999
|
+
WKS: {
|
|
13000
|
+
required: ["CANONICAL_LESSON"],
|
|
13001
|
+
optional: ["KNOWLEDGE_EXPOSITION"],
|
|
13002
|
+
rationale: "Phi\u1EBFu h\u1ECDc t\u1EADp (Worksheet) luy\u1EC7n t\u1EADp theo c\xE1c ch\u1EB7ng ho\u1EA1t \u0111\u1ED9ng c\u1EE7a gi\xE1o \xE1n"
|
|
13003
|
+
},
|
|
13004
|
+
GUIDE: {
|
|
13005
|
+
required: ["CANONICAL_LESSON"],
|
|
13006
|
+
optional: ["SESSION_SLICE"],
|
|
13007
|
+
rationale: "K\u1ECBch b\u1EA3n s\u01B0 ph\u1EA1m gi\xE1o vi\xEAn (Teacher Guide) b\xE1m s\xE1t timeline t\u1EEBng ph\xFAt c\u1EE7a LESSON"
|
|
13008
|
+
},
|
|
13009
|
+
SLIDE: {
|
|
13010
|
+
required: ["CANONICAL_LESSON"],
|
|
13011
|
+
optional: ["KNOWLEDGE_EXPOSITION"],
|
|
13012
|
+
rationale: "Slide b\xE0i gi\u1EA3ng tr\xECnh chi\u1EBFu theo c\u1EA5u tr\xFAc ph\xE2n ph\u1ED1i n\u1ED9i dung c\u1EE7a gi\xE1o \xE1n"
|
|
13013
|
+
},
|
|
13014
|
+
QUIZ: {
|
|
13015
|
+
required: ["KNOWLEDGE_EXPOSITION", "CANONICAL_LESSON"],
|
|
13016
|
+
optional: ["SESSION_SLICE"],
|
|
13017
|
+
rationale: "Ng\xE2n h\xE0ng c\xE2u h\u1ECFi \u0111\xE1nh gi\xE1 c\u1EA3 ki\u1EBFn th\u1EE9c chu\u1EA9n m\u1EF1c (KX) l\u1EABn m\u1EE5c ti\xEAu b\xE0i d\u1EA1y (LESSON)"
|
|
13018
|
+
}
|
|
13019
|
+
};
|
|
13020
|
+
function validateArtifactDependencies(artifactType, availableSources, opts = {}) {
|
|
13021
|
+
const normType = (artifactType || "").toUpperCase().trim();
|
|
13022
|
+
const rule = ARTIFACT_DEPENDENCY_ROUTING[normType];
|
|
13023
|
+
const failClosed = opts.failClosed ?? true;
|
|
13024
|
+
if (!rule) {
|
|
13025
|
+
return { valid: true, missing: [] };
|
|
13026
|
+
}
|
|
13027
|
+
const missing = [];
|
|
13028
|
+
for (const req of rule.required) {
|
|
13029
|
+
const val = availableSources[req];
|
|
13030
|
+
const isPresent = val !== void 0 && val !== null && (typeof val === "string" ? val.trim().length > 0 : true);
|
|
13031
|
+
if (!isPresent) {
|
|
13032
|
+
missing.push(req);
|
|
13033
|
+
}
|
|
13034
|
+
}
|
|
13035
|
+
if (missing.length > 0) {
|
|
13036
|
+
const err = createContextMissingError({
|
|
13037
|
+
artifactType: normType,
|
|
13038
|
+
missingSource: missing[0],
|
|
13039
|
+
lessonId: opts.lessonId,
|
|
13040
|
+
agent: opts.agent
|
|
13041
|
+
});
|
|
13042
|
+
if (failClosed) {
|
|
13043
|
+
throw err;
|
|
13044
|
+
}
|
|
13045
|
+
return { valid: false, missing, error: err };
|
|
13046
|
+
}
|
|
13047
|
+
return { valid: true, missing: [] };
|
|
13048
|
+
}
|
|
13049
|
+
|
|
13050
|
+
// src/services/singleArtifactService.ts
|
|
12696
13051
|
function getArtifactMetadata(type, lessonId, pedagogy) {
|
|
12697
13052
|
const id = lessonId || "ON_DEMAND";
|
|
12698
13053
|
switch (type) {
|
|
@@ -12772,9 +13127,24 @@ async function generateSingleArtifact(req) {
|
|
|
12772
13127
|
const templateContent = loadedTemplate || getDefaultFallbackTemplate(artifactType, displayTitle, lessonId || "ON_DEMAND");
|
|
12773
13128
|
const hwStr = hardwarePlatform.join(", ");
|
|
12774
13129
|
const selectedDevices = (config?.devices || (hardwarePlatform[0]?.toLowerCase().includes("paper") ? "paper-only" : "laptop")).toLowerCase();
|
|
12775
|
-
|
|
12776
|
-
const
|
|
12777
|
-
const
|
|
13130
|
+
language.toLowerCase().includes("bilingual") || language.toLowerCase().includes("song");
|
|
13131
|
+
const targetLang = resolveTargetLanguageCode(language);
|
|
13132
|
+
const langDirective = buildLanguageDirective(language);
|
|
13133
|
+
const headingDirective = buildHeadingDirective(
|
|
13134
|
+
artifactType.toUpperCase(),
|
|
13135
|
+
req.sectionLanguageContract,
|
|
13136
|
+
targetLang
|
|
13137
|
+
);
|
|
13138
|
+
const availableSources = {
|
|
13139
|
+
KNOWLEDGE_EXPOSITION: contextSot.exposition || researchContext,
|
|
13140
|
+
CANONICAL_LESSON: contextSot.lessonPlan,
|
|
13141
|
+
FRAMEWORK_EXCERPT: contextSot.framework
|
|
13142
|
+
};
|
|
13143
|
+
validateArtifactDependencies(artifactType.toUpperCase(), availableSources, {
|
|
13144
|
+
lessonId,
|
|
13145
|
+
agent: meta.persona,
|
|
13146
|
+
failClosed: req.failClosedContext ?? false
|
|
13147
|
+
});
|
|
12778
13148
|
const isPaperOnly = selectedDevices === "paper-only" || hwStr.toLowerCase().includes("paper") || hwStr.toLowerCase().includes("print-ready");
|
|
12779
13149
|
const deviceRule = isPaperOnly ? `
|
|
12780
13150
|
- \u{1F4C4} PAPER-ONLY / NO-DEVICE ENVIRONMENT: The learning space has NO computers or screens. All exercises, worksheets, task cards, exit tickets, and code analyses MUST be 100% printable. Provide write-in blank boxes, printed code snippets with line numbers, tracing tables, and physical manipulative instructions.` : selectedDevices === "tablet" || selectedDevices === "smartphone" ? `
|
|
@@ -12795,7 +13165,8 @@ async function generateSingleArtifact(req) {
|
|
|
12795
13165
|
Your task is to author a canonical, publication-grade learning artifact of type "${artifactType.toUpperCase()}".
|
|
12796
13166
|
|
|
12797
13167
|
### CORE OPERATIONAL INVARIANTS:
|
|
12798
|
-
${
|
|
13168
|
+
${langDirective}
|
|
13169
|
+
${headingDirective}
|
|
12799
13170
|
2. NON-MOCK CODE INVARIANT: Any code snippet provided MUST be 100% syntactically valid, idiomatic, and executable without placeholders or fake functions.
|
|
12800
13171
|
3. PEDAGOGICAL GROUNDING: Strictly align with the ${pedagogy.toUpperCase()} model, Bloom's Revised Taxonomy, and IEEE/ACM CS2023 guidelines.
|
|
12801
13172
|
4. SCAFFOLDING LEVEL: "${scaffoldingLevel.toUpperCase()}".${scaffoldingRule}
|
|
@@ -12804,6 +13175,11 @@ ${langRule}
|
|
|
12804
13175
|
|
|
12805
13176
|
IMAGE PLANNING (media ledger) \u2014 QUOTA GEN: t\u1ED1i \u0111a ${mediaPolicy.maxGenImagesPerArtifact} \u1EA3nh AI cho artifact n\xE0y (\u1EA3nh search kho kh\xF4ng gi\u1EDBi h\u1EA1n).
|
|
12806
13177
|
Khi n\u1ED9i dung c\u1EA7n minh h\u1ECDa (diagram quy tr\xECnh, s\u01A1 \u0111\u1ED3 kh\xE1i ni\u1EC7m, step-by-step visual), ch\xE8n placeholder \u0111\xFAng format [IMAGE: slug] (slug ch\u1EEF th\u01B0\u1EDDng-g\u1EA1ch ngang, unique trong b\xE0i, vd img-for-loop-diagram) T\u1EA0I \u0110\xDANG CH\u1ED6 c\u1EA7n \u1EA3nh, tr\xEAn d\xF2ng ri\xEAng. KH\xD4NG t\u1EF1 sinh \u1EA3nh, KH\xD4NG d\xF9ng markdown image \u2014 placeholder s\u1EBD \u0111\u01B0\u1EE3c thay b\u1EB1ng \u1EA3nh th\u1EADt sau khi Media Curator duy\u1EC7t. Ch\u1EC9 \u0111\u1EB7t cho \u1EA3nh TH\u1EF0C S\u1EF0 c\u1EA7n thi\u1EBFt.` : ""}`;
|
|
13178
|
+
const slcContract = req.sectionLanguageContract;
|
|
13179
|
+
const frameworkExcerpt = contextSot.framework ? buildSectionAwareExcerpt(contextSot.framework, { budget: 2500, sectionLanguageContract: slcContract }).excerpt : "";
|
|
13180
|
+
const lessonPlanExcerpt = contextSot.lessonPlan ? buildLessonExcerpt(contextSot.lessonPlan, { budget: 8e3, sectionLanguageContract: slcContract, artifactType: "LESSON" }).excerpt : "";
|
|
13181
|
+
const handoutExcerpt = contextSot.handout ? buildSectionAwareExcerpt(contextSot.handout, { budget: 2e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
13182
|
+
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
12807
13183
|
const userPrompt = `### CONTEXT GROUND TRUTH:
|
|
12808
13184
|
- Topic / Concept Domain: "${topic}"
|
|
12809
13185
|
- Lesson ID: "${lessonId || "ON_DEMAND"}"
|
|
@@ -12821,14 +13197,17 @@ ${selectedDevices ? `- Device Mode: "${selectedDevices}"
|
|
|
12821
13197
|
${researchContext ? `### RESEARCH GROUND TRUTH (fact-checked context \u2014 \u01B0u ti\xEAn d\xF9ng, KH\xD4NG b\u1ECBa s\u1ED1 li\u1EC7u):
|
|
12822
13198
|
${researchContext.slice(0, 4e3)}
|
|
12823
13199
|
` : ""}
|
|
12824
|
-
${
|
|
12825
|
-
${
|
|
13200
|
+
${expositionExcerpt ? `### SOT KNOWLEDGE EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict):
|
|
13201
|
+
${expositionExcerpt}
|
|
12826
13202
|
` : ""}
|
|
12827
|
-
${
|
|
12828
|
-
${
|
|
13203
|
+
${frameworkExcerpt ? `### SOT CURRICULUM FRAMEWORK:
|
|
13204
|
+
${frameworkExcerpt}
|
|
12829
13205
|
` : ""}
|
|
12830
|
-
${
|
|
12831
|
-
${
|
|
13206
|
+
${lessonPlanExcerpt ? `### SOT CANONICAL LESSON PLAN:
|
|
13207
|
+
${lessonPlanExcerpt}
|
|
13208
|
+
` : ""}
|
|
13209
|
+
${handoutExcerpt ? `### SOT STUDENT HANDOUT:
|
|
13210
|
+
${handoutExcerpt}
|
|
12832
13211
|
` : ""}
|
|
12833
13212
|
|
|
12834
13213
|
### MANDATORY CANONICAL TEMPLATE CONTRACT:
|
|
@@ -12917,9 +13296,16 @@ ${yaml.trim()}
|
|
|
12917
13296
|
const verdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12918
13297
|
targetArtifactType: artifactType.toUpperCase(),
|
|
12919
13298
|
lessonId: lessonId || "ON_DEMAND",
|
|
12920
|
-
expectedLanguage:
|
|
13299
|
+
expectedLanguage: targetLang || "en",
|
|
12921
13300
|
targetObjectives: judgeObjectives,
|
|
12922
|
-
generatedContentJson: JSON.stringify({
|
|
13301
|
+
generatedContentJson: JSON.stringify({
|
|
13302
|
+
content: finalContent,
|
|
13303
|
+
artifactType,
|
|
13304
|
+
lessonId: lessonId || "ON_DEMAND",
|
|
13305
|
+
title: displayTitle,
|
|
13306
|
+
canonicalLessonExcerpt: lessonPlanExcerpt || void 0,
|
|
13307
|
+
canonicalExposition: expositionExcerpt || void 0
|
|
13308
|
+
})
|
|
12923
13309
|
});
|
|
12924
13310
|
const passed = Boolean(verdict.passed) && verdict.score >= 85;
|
|
12925
13311
|
if (passed) {
|
|
@@ -12961,9 +13347,16 @@ ${finalContent}` }
|
|
|
12961
13347
|
const reVerdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12962
13348
|
targetArtifactType: artifactType.toUpperCase(),
|
|
12963
13349
|
lessonId: lessonId || "ON_DEMAND",
|
|
12964
|
-
expectedLanguage:
|
|
13350
|
+
expectedLanguage: targetLang || "en",
|
|
12965
13351
|
targetObjectives: judgeObjectives,
|
|
12966
|
-
generatedContentJson: JSON.stringify({
|
|
13352
|
+
generatedContentJson: JSON.stringify({
|
|
13353
|
+
content: repaired,
|
|
13354
|
+
artifactType,
|
|
13355
|
+
lessonId: lessonId || "ON_DEMAND",
|
|
13356
|
+
title: displayTitle,
|
|
13357
|
+
canonicalLessonExcerpt: lessonPlanExcerpt || void 0,
|
|
13358
|
+
canonicalExposition: expositionExcerpt || void 0
|
|
13359
|
+
})
|
|
12967
13360
|
});
|
|
12968
13361
|
if (reVerdict.passed && reVerdict.score >= 85) {
|
|
12969
13362
|
return {
|
|
@@ -16914,6 +17307,6 @@ function renderMediaPlaceholder(entry) {
|
|
|
16914
17307
|
return `> \u{1F5BC}\uFE0F [\u1EA2nh \u0111ang ch\u1EDD: ${entry.name} \u2014 s\u1EBD \u0111\u01B0\u1EE3c t\u1EA1o sau khi duy\u1EC7t media]`;
|
|
16915
17308
|
}
|
|
16916
17309
|
|
|
16917
|
-
export { ACT_TEMPLATE, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BELL_RINGER_TEMPLATE, BLOOM_ACTION_VERBS, BOM_TEMPLATE, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CHOICE_BOARD_TEMPLATE, CODE_LAB_TEMPLATE, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ARTIFACT_STREAM_IDLE_MS, DEFAULT_ARTIFACT_STREAM_TOTAL_MS, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DEFAULT_STREAM_IDLE_MS, DEFAULT_STREAM_TOTAL_MS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, EXIT_TICKET_TEMPLATE, EXPOSITION_REL, EXT_TEMPLATE, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GLOSSARY_TEMPLATE, GRAPHIC_ORGANIZER_TEMPLATE, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HANDOUT_TEMPLATE, HandoutSchema, HandoutSectionSchema, InstructionSectionSchema, InstructionStepSchema, JudgeCriterionSchema, LAYER_TOTAL_BUDGET_MS, LESSON_PLAN_TEMPLATE, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MappingKindSchema, MarpSlideSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PROJECT_INSTRUCTION_TEMPLATE, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QUIZ_TEMPLATE, QualityAuditVerdictSchema, QuizOptionSchema, REVIEW_GAME_TEMPLATE, RUBRIC_TEMPLATE, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SCIENCE_LAB_TEMPLATE, SELF_LAB_TEMPLATE, SLIDE_LAYOUT_PRESETS, SLIDE_TEMPLATE, STANDARD_SOT_FILES, STATION_ROTATION_TEMPLATE, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SilverTierSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TASK_CARDS_TEMPLATE, TEACHER_GUIDE_TEMPLATE, TIERED_PRACTICE_TEMPLATE, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WORKSHEET_TEMPLATE, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, activityTools, analystTools, analyzeProjectCreationIntent, assertAcyclic, assessorTools, auditCurriculumQualityFlow, auditQualityReport, buildActivityPrompt, buildCodeLabPrompt, buildCurriculumContext, buildCurriculumPlan, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildExpositionContext, buildExtensionPrompt, buildHandoutPrompt, buildHeadingDirective, buildImagePrompt, buildJudgePrompt, buildLanguageDirective, buildLessonMasterPrompt, buildProjectInstructionPrompt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWorksheetPrompt, closeTruncatedJson, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createCurriculumStorage, createIdleAbortController, createStreamAbortController, createStreamAbortSignal, createStreamChunkExtractor, curateMediaLedger, designerTools, detectProjectPedagogy, ensureExpositionForLesson, ensureKnowledgeExposition, evaluateStandardsCoverage, executeCurriculumCommand, exportAllProjectQuizzes, expositionCacheKey, extractScopeSequenceRows, extractSectionHeadingsFromSLC, extractSessionSlice, extractStreamChunk, extractThoughtAndContent, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateCodeLabFlow, generateDiagnosticQuizFlow, generateEducationalImage, generateExtensionFlow, generateHandoutFlow, generateLessonMasterFlow, generateMilestoneCurriculumBundle, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateSelfLabFlow, generateSelfPacedBundle, generateSingleArtifact, generateSlidesFlow, generateTeacherGuideFlow, generateWorksheetFlow, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSlideLayoutPresetById, getSlideLayoutPresetsByCategory, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, packagerTools, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToSupabase, rankGenCandidates, renderFrameworkFromPlan, renderMediaPlaceholder, researcherTools, resolveGateSettings, resolveStandardsPacks, resolveStreamBudget, resolveTargetLanguageCode, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, stripLlmJsonWrappers, targetLanguageDisplayName, techSmeTools, topoSort, uploadAssetToBucket, validateCurriculumPlan, validateFrameworkPack, validateMarkdownTables, validateMermaidSyntax, withAutoRepair };
|
|
17310
|
+
export { ACT_TEMPLATE, ARTIFACT_DEPENDENCY_ROUTING, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BELL_RINGER_TEMPLATE, BLOOM_ACTION_VERBS, BOM_TEMPLATE, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CHOICE_BOARD_TEMPLATE, CODE_LAB_TEMPLATE, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ARTIFACT_STREAM_IDLE_MS, DEFAULT_ARTIFACT_STREAM_TOTAL_MS, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DEFAULT_KX_PRIORITIES, DEFAULT_LESSON_PRIORITIES, DEFAULT_STREAM_IDLE_MS, DEFAULT_STREAM_TOTAL_MS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, EXIT_TICKET_TEMPLATE, EXPOSITION_REL, EXT_TEMPLATE, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GLOSSARY_TEMPLATE, GRAPHIC_ORGANIZER_TEMPLATE, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HANDOUT_TEMPLATE, HandoutSchema, HandoutSectionSchema, InstructionSectionSchema, InstructionStepSchema, JudgeCriterionSchema, LAYER_TOTAL_BUDGET_MS, LESSON_PLAN_TEMPLATE, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MappingKindSchema, MarpSlideSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PROJECT_INSTRUCTION_TEMPLATE, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QUIZ_TEMPLATE, QualityAuditVerdictSchema, QuizOptionSchema, REVIEW_GAME_TEMPLATE, RUBRIC_TEMPLATE, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SCIENCE_LAB_TEMPLATE, SELF_LAB_TEMPLATE, SLIDE_CANONICAL_METHODOLOGY, SLIDE_LAYOUT_PRESETS, SLIDE_TEMPLATE, STANDARD_SOT_FILES, STATION_ROTATION_TEMPLATE, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SilverTierSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TASK_CARDS_TEMPLATE, TEACHER_GUIDE_TEMPLATE, TIERED_PRACTICE_TEMPLATE, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WORKSHEET_TEMPLATE, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, activityTools, analystTools, analyzeProjectCreationIntent, assertAcyclic, assessorTools, auditCurriculumQualityFlow, auditQualityReport, buildActivityPrompt, buildCodeLabPrompt, buildCurriculumContext, buildCurriculumPlan, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildExpositionContext, buildExpositionExcerpt, buildExtensionPrompt, buildHandoutPrompt, buildHeadingDirective, buildImagePrompt, buildJudgePrompt, buildLanguageDirective, buildLessonExcerpt, buildLessonMasterPrompt, buildMarpMarkdownSlidePrompt, buildProjectInstructionPrompt, buildSectionAwareExcerpt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWorksheetPrompt, closeTruncatedJson, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createContextMissingError, createCurriculumStorage, createIdleAbortController, createStreamAbortController, createStreamAbortSignal, createStreamChunkExtractor, curateMediaLedger, designerTools, detectProjectPedagogy, ensureExpositionForLesson, ensureKnowledgeExposition, evaluateStandardsCoverage, executeCurriculumCommand, exportAllProjectQuizzes, expositionCacheKey, extractScopeSequenceRows, extractSectionHeadingsFromSLC, extractSessionSlice, extractStreamChunk, extractThoughtAndContent, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateCodeLabFlow, generateDiagnosticQuizFlow, generateEducationalImage, generateExtensionFlow, generateHandoutFlow, generateLessonMasterFlow, generateMilestoneCurriculumBundle, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateSelfLabFlow, generateSelfPacedBundle, generateSingleArtifact, generateSlidesFlow, generateTeacherGuideFlow, generateWorksheetFlow, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSlideLayoutPresetById, getSlideLayoutPresetsByCategory, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, normalizeSlcContract, packagerTools, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToSupabase, rankGenCandidates, renderFrameworkFromPlan, renderMediaPlaceholder, researcherTools, resolveGateSettings, resolveStandardsPacks, resolveStreamBudget, resolveTargetLanguageCode, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, stripLlmJsonWrappers, targetLanguageDisplayName, techSmeTools, topoSort, uploadAssetToBucket, validateArtifactDependencies, validateCurriculumPlan, validateFrameworkPack, validateMarkdownTables, validateMermaidSyntax, withAutoRepair };
|
|
16918
17311
|
//# sourceMappingURL=index.mjs.map
|
|
16919
17312
|
//# sourceMappingURL=index.mjs.map
|