@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.cjs
CHANGED
|
@@ -85,6 +85,8 @@ function getSuggestedActionForCode(code) {
|
|
|
85
85
|
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.";
|
|
86
86
|
case "ERR_STORAGE_IO_FAILED":
|
|
87
87
|
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.";
|
|
88
|
+
case "ERR_CONTEXT_MISSING":
|
|
89
|
+
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.";
|
|
88
90
|
default:
|
|
89
91
|
return "B\u1EA5m Rerun \u0111\u1EC3 th\u1EED l\u1EA1i ho\u1EB7c ki\u1EC3m tra nh\u1EADt k\xFD h\u1EC7 th\u1ED1ng.";
|
|
90
92
|
}
|
|
@@ -102,11 +104,23 @@ function isCodeRetryable(code) {
|
|
|
102
104
|
case "ERR_TASK_GATE_BLOCKED":
|
|
103
105
|
case "ERR_METERED_LIMIT_EXCEEDED":
|
|
104
106
|
case "ERR_SCHEMA_CONTRACT_VIOLATION":
|
|
107
|
+
case "ERR_CONTEXT_MISSING":
|
|
105
108
|
return false;
|
|
106
109
|
default:
|
|
107
110
|
return true;
|
|
108
111
|
}
|
|
109
112
|
}
|
|
113
|
+
function createContextMissingError(params) {
|
|
114
|
+
return new exports.CurriculumError({
|
|
115
|
+
errorCode: "ERR_CONTEXT_MISSING",
|
|
116
|
+
artifactType: params.artifactType,
|
|
117
|
+
lessonId: params.lessonId,
|
|
118
|
+
agent: params.agent,
|
|
119
|
+
message: `Required context source "${params.missingSource}" is missing for artifact "${params.artifactType}"`,
|
|
120
|
+
suggestedAction: `Generate or provide the authoritative "${params.missingSource}" source before producing "${params.artifactType}".`,
|
|
121
|
+
retryable: false
|
|
122
|
+
});
|
|
123
|
+
}
|
|
110
124
|
exports.CurriculumError = void 0;
|
|
111
125
|
var init_errors = __esm({
|
|
112
126
|
"src/errors/index.ts"() {
|
|
@@ -5379,6 +5393,45 @@ Return a single valid JSON object matching SlideDeckSchema with these exact keys
|
|
|
5379
5393
|
}
|
|
5380
5394
|
`.trim();
|
|
5381
5395
|
}
|
|
5396
|
+
var SLIDE_CANONICAL_METHODOLOGY = `
|
|
5397
|
+
MANDATORY 12-14 SLIDE MICRO-CYCLE STRUCTURE (Delimited by '---'):
|
|
5398
|
+
1. **Slide 1 [Title & Mission]:** Real-world inquiry hook and overarching build mission
|
|
5399
|
+
2. **Slide 2 [Agenda & Roadmap]:** Timing and milestone breakdown table
|
|
5400
|
+
3. **Slide 3 [Warm-Up / Prior Knowledge]:** 2-column recall + 60-second diagnostic challenge card
|
|
5401
|
+
4. **Slide 4 [High-Stakes Hook Scenario]:** Authentic engineering/domain crisis card + dilemma constraint
|
|
5402
|
+
5. **Slide 5 [Core Concept 1: Mental Model]:** Definition, intuitive everyday analogy, and golden rule card
|
|
5403
|
+
6. **Slide 6 [Architecture & Visual Flow]:** Clean Mermaid diagram (flowchart or sequenceDiagram) + 3 flow steps
|
|
5404
|
+
7. **Slide 7 [Core Concept 2: Syntax / Mechanism Anatomy]:** Side-by-side runnable code + anatomy breakdown & syntax trap card
|
|
5405
|
+
8. **Slide 8 [Guided Practice: Try It Now]:** 3-minute active desk task card with starter hint and success criteria
|
|
5406
|
+
9. **Slide 9 [Integrated Hands-On Lab]:** 3-tier differentiated challenge cards (Bronze / Silver / Gold) + gotcha alert card
|
|
5407
|
+
10. **Slide 10 [Traffic Light Checkpoint & Pitfalls]:** Formative self-check cards (\u{1F7E2}/\u{1F7E1}/\u{1F534}) & diagnostic test question
|
|
5408
|
+
11. **Slide 11 [Exit Ticket & Metacognition]:** 2 scenario-based check questions + 1 metacognitive reflection prompt
|
|
5409
|
+
12. **Slide 12 [Summary & Next Steps]:** 3 core golden rules + preview card of next upcoming milestone
|
|
5410
|
+
|
|
5411
|
+
Mandatory Canvas & Presentation Invariants:
|
|
5412
|
+
- A slide is an INTERACTIVE PROJECTION CANVAS, NOT a textbook! Absolutely NO dense paragraphs or walls of text.
|
|
5413
|
+
- Follow the 6x6 rule: Maximum 4-6 bullet points per slide, maximum 8-12 words per bullet.
|
|
5414
|
+
- 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">\`.
|
|
5415
|
+
- MANDATORY PRESENTER NOTES ON EVERY SLIDE: Every slide MUST end with \`<!-- Presenter Notes: ... -->\` containing:
|
|
5416
|
+
* SCRIPT: 60-90s teacher talk track with intuitive analogies.
|
|
5417
|
+
* COLD CALL / CHECK: Specific diagnostic question to ask students.
|
|
5418
|
+
* SCAFFOLDING / GOTCHA: Guidance for students who get stuck.
|
|
5419
|
+
* PACING: Recommended minutes for the slide.
|
|
5420
|
+
- Output 100% valid Marp Markdown.
|
|
5421
|
+
`.trim();
|
|
5422
|
+
function buildMarpMarkdownSlidePrompt(input) {
|
|
5423
|
+
return `You are @illustrator & @content (Pedagogical Slide Deck Presentation Specialists).
|
|
5424
|
+
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\`.
|
|
5425
|
+
|
|
5426
|
+
[MARP SLIDE TEMPLATE SCAFFOLD]:
|
|
5427
|
+
${input.templateScaffold}
|
|
5428
|
+
|
|
5429
|
+
${SLIDE_CANONICAL_METHODOLOGY}
|
|
5430
|
+
|
|
5431
|
+
${input.languageDirective}
|
|
5432
|
+
|
|
5433
|
+
${input.headingDirective}`.trim();
|
|
5434
|
+
}
|
|
5382
5435
|
|
|
5383
5436
|
// src/ai/prompts/teacherGuidePrompt.ts
|
|
5384
5437
|
function buildTeacherGuidePrompt(input) {
|
|
@@ -5518,13 +5571,13 @@ Evaluate the candidate artifact across these 6 dimensions:
|
|
|
5518
5571
|
- 0 pts: Missing critical sections.
|
|
5519
5572
|
|
|
5520
5573
|
5. **Technical & Conceptual Accuracy (15 pts):**
|
|
5521
|
-
- 15 pts: Code snippets, logic flows, architectural descriptions, and Mermaid diagrams are conceptually sound
|
|
5574
|
+
- 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.
|
|
5522
5575
|
- 8 pts: Minor syntax inaccuracies or unidiomatic code that does not break core concepts.
|
|
5523
|
-
- 0 pts: Severe technical hallucinations, broken logic, or
|
|
5576
|
+
- 0 pts: Severe technical hallucinations, broken logic, invalid diagrams, or direct contradiction of canonical exposition knowledge.
|
|
5524
5577
|
|
|
5525
5578
|
6. **Contract Consistency & Zero-Drift (10 pts):**
|
|
5526
|
-
- 10 pts: Satellite artifact strictly adheres to the scope, tech stack, and objectives of Lesson ${lessonId} without introducing unrelated topics.
|
|
5527
|
-
- 0-5 pts: Scope drift
|
|
5579
|
+
- 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.
|
|
5580
|
+
- 0-5 pts: Scope drift, topic divergence, or disjoint activity sequence detected compared to master lesson.
|
|
5528
5581
|
|
|
5529
5582
|
## VERDICT RULES
|
|
5530
5583
|
- **PASS:** Score >= 80 AND Language Adherence = true AND Standards Alignment >= 12 (when STANDARDS GROUND TRUTH is present).
|
|
@@ -9711,6 +9764,224 @@ function resolveGateSettings(raw) {
|
|
|
9711
9764
|
function gateModeFor(resolved, type) {
|
|
9712
9765
|
return resolved[type] ?? "OFF";
|
|
9713
9766
|
}
|
|
9767
|
+
|
|
9768
|
+
// src/services/contextBuilder.ts
|
|
9769
|
+
var DEFAULT_LESSON_PRIORITIES = [
|
|
9770
|
+
"A. Lesson Design Plan",
|
|
9771
|
+
"B. Lesson Flow",
|
|
9772
|
+
"Learning Objectives & Evidence",
|
|
9773
|
+
"Activity Sequence"
|
|
9774
|
+
];
|
|
9775
|
+
var DEFAULT_KX_PRIORITIES = [
|
|
9776
|
+
"Key Terms",
|
|
9777
|
+
"Concept Narratives",
|
|
9778
|
+
"Worked Micro-Examples"
|
|
9779
|
+
];
|
|
9780
|
+
function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
9781
|
+
const budget = opts.budget ?? 12e3;
|
|
9782
|
+
const minContentChars = opts.minContentChars ?? 400;
|
|
9783
|
+
const issues = [];
|
|
9784
|
+
const source = (markdown || "").trim();
|
|
9785
|
+
if (!source) {
|
|
9786
|
+
return {
|
|
9787
|
+
excerpt: "",
|
|
9788
|
+
verified: false,
|
|
9789
|
+
sectionAware: false,
|
|
9790
|
+
includedSections: [],
|
|
9791
|
+
issues: ["empty-source"],
|
|
9792
|
+
tokenEstimate: 0
|
|
9793
|
+
};
|
|
9794
|
+
}
|
|
9795
|
+
const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
|
|
9796
|
+
const sections = parseMarkdownSections(source, slcMap, opts.artifactType);
|
|
9797
|
+
if (sections.length === 0) {
|
|
9798
|
+
issues.push("parse:no-sections");
|
|
9799
|
+
const excerpt2 = truncateByBudget(source, budget);
|
|
9800
|
+
const verified2 = excerpt2.length >= minContentChars;
|
|
9801
|
+
if (excerpt2.length < minContentChars) issues.push("content:insufficient");
|
|
9802
|
+
return {
|
|
9803
|
+
excerpt: excerpt2,
|
|
9804
|
+
verified: verified2,
|
|
9805
|
+
sectionAware: false,
|
|
9806
|
+
includedSections: [],
|
|
9807
|
+
issues,
|
|
9808
|
+
tokenEstimate: Math.round(excerpt2.length / 4)
|
|
9809
|
+
};
|
|
9810
|
+
}
|
|
9811
|
+
const byCanonical = /* @__PURE__ */ new Map();
|
|
9812
|
+
const unmatched = [];
|
|
9813
|
+
for (const s of sections) {
|
|
9814
|
+
if (s.canonicalKey && !byCanonical.has(s.canonicalKey)) {
|
|
9815
|
+
byCanonical.set(s.canonicalKey, s);
|
|
9816
|
+
} else {
|
|
9817
|
+
unmatched.push(s);
|
|
9818
|
+
}
|
|
9819
|
+
}
|
|
9820
|
+
const priorities = opts.priorities ?? DEFAULT_LESSON_PRIORITIES;
|
|
9821
|
+
const includedSections = [];
|
|
9822
|
+
const blocks = [];
|
|
9823
|
+
let used = 0;
|
|
9824
|
+
const tryAdd = (heading, body, key) => {
|
|
9825
|
+
const trimmedBody = body.trim();
|
|
9826
|
+
if (!trimmedBody) return false;
|
|
9827
|
+
const block = `## ${heading}
|
|
9828
|
+
|
|
9829
|
+
${trimmedBody}`;
|
|
9830
|
+
if (used + block.length > budget && blocks.length > 0) return false;
|
|
9831
|
+
blocks.push(block);
|
|
9832
|
+
used += block.length;
|
|
9833
|
+
includedSections.push(key);
|
|
9834
|
+
return true;
|
|
9835
|
+
};
|
|
9836
|
+
let sectionAware = false;
|
|
9837
|
+
for (const key of priorities) {
|
|
9838
|
+
const sec = byCanonical.get(key);
|
|
9839
|
+
if (!sec) continue;
|
|
9840
|
+
sectionAware = true;
|
|
9841
|
+
if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
|
|
9842
|
+
}
|
|
9843
|
+
for (const [key, sec] of byCanonical) {
|
|
9844
|
+
if (includedSections.includes(key)) continue;
|
|
9845
|
+
if (used >= budget) break;
|
|
9846
|
+
if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
|
|
9847
|
+
}
|
|
9848
|
+
for (const sec of unmatched) {
|
|
9849
|
+
if (used >= budget) break;
|
|
9850
|
+
if (!tryAdd(sec.cleanTitle, sec.body, sec.cleanTitle)) break;
|
|
9851
|
+
}
|
|
9852
|
+
if (priorities.length > 0 && !priorities.some((k) => includedSections.includes(k))) {
|
|
9853
|
+
issues.push("parse:no-priority-resolution");
|
|
9854
|
+
}
|
|
9855
|
+
let excerpt = blocks.join("\n\n");
|
|
9856
|
+
if (excerpt.length > budget) {
|
|
9857
|
+
excerpt = truncateByBudget(excerpt, budget);
|
|
9858
|
+
}
|
|
9859
|
+
const effectiveMinChars = Math.min(minContentChars, source.length);
|
|
9860
|
+
if (excerpt.length < effectiveMinChars) {
|
|
9861
|
+
issues.push("content:insufficient");
|
|
9862
|
+
}
|
|
9863
|
+
const verified = !issues.includes("parse:no-priority-resolution") && excerpt.length >= effectiveMinChars;
|
|
9864
|
+
return {
|
|
9865
|
+
excerpt,
|
|
9866
|
+
verified,
|
|
9867
|
+
sectionAware: sectionAware || priorities.length === 0 && sections.length > 0,
|
|
9868
|
+
includedSections,
|
|
9869
|
+
issues,
|
|
9870
|
+
tokenEstimate: Math.round(excerpt.length / 4)
|
|
9871
|
+
};
|
|
9872
|
+
}
|
|
9873
|
+
function buildExpositionExcerpt(markdown, opts = {}) {
|
|
9874
|
+
return buildSectionAwareExcerpt(markdown, {
|
|
9875
|
+
...opts,
|
|
9876
|
+
priorities: DEFAULT_KX_PRIORITIES
|
|
9877
|
+
});
|
|
9878
|
+
}
|
|
9879
|
+
function buildLessonExcerpt(markdown, opts = {}) {
|
|
9880
|
+
return buildSectionAwareExcerpt(markdown, {
|
|
9881
|
+
...opts,
|
|
9882
|
+
priorities: DEFAULT_LESSON_PRIORITIES
|
|
9883
|
+
});
|
|
9884
|
+
}
|
|
9885
|
+
function normalizeSlcContract(slc) {
|
|
9886
|
+
if (!slc) return void 0;
|
|
9887
|
+
if (typeof slc !== "string") return slc;
|
|
9888
|
+
const out = {};
|
|
9889
|
+
const blocks = slc.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
9890
|
+
for (const block of blocks) {
|
|
9891
|
+
const header = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
9892
|
+
if (!header?.[1]) continue;
|
|
9893
|
+
const mapping = {};
|
|
9894
|
+
for (const line of block.split("\n")) {
|
|
9895
|
+
const t = line.trim();
|
|
9896
|
+
if (!t.startsWith("|") || t.includes("---")) continue;
|
|
9897
|
+
const cells = t.split("|").map((c) => c.trim()).filter((_, i, a) => i > 0 && i < a.length - 1);
|
|
9898
|
+
const [c0, c1] = cells;
|
|
9899
|
+
if (c0 && c1 && !c0.toLowerCase().includes("canonical") && !c1.toLowerCase().includes("localized")) {
|
|
9900
|
+
mapping[c0] = c1;
|
|
9901
|
+
}
|
|
9902
|
+
}
|
|
9903
|
+
if (Object.keys(mapping).length > 0) out[header[1]] = mapping;
|
|
9904
|
+
}
|
|
9905
|
+
return Object.keys(out).length > 0 ? out : void 0;
|
|
9906
|
+
}
|
|
9907
|
+
function parseMarkdownSections(markdown, slcMap, artifactType) {
|
|
9908
|
+
const sections = [];
|
|
9909
|
+
const lines = markdown.split("\n");
|
|
9910
|
+
let currentHeading = "";
|
|
9911
|
+
let currentBody = [];
|
|
9912
|
+
const reverseMap = /* @__PURE__ */ new Map();
|
|
9913
|
+
if (slcMap) {
|
|
9914
|
+
const maps = artifactType && slcMap[artifactType] ? [slcMap[artifactType]] : Object.values(slcMap);
|
|
9915
|
+
for (const m of maps) {
|
|
9916
|
+
for (const [canonical, localized] of Object.entries(m)) {
|
|
9917
|
+
reverseMap.set(normalizeHeading(localized), canonical);
|
|
9918
|
+
reverseMap.set(normalizeHeading(canonical), canonical);
|
|
9919
|
+
}
|
|
9920
|
+
}
|
|
9921
|
+
}
|
|
9922
|
+
const flush = () => {
|
|
9923
|
+
if (!currentHeading && currentBody.length === 0) return;
|
|
9924
|
+
const cleanTitle = currentHeading.replace(/^#{1,4}\s+/, "").trim();
|
|
9925
|
+
const norm = normalizeHeading(cleanTitle);
|
|
9926
|
+
const canonicalKey = reverseMap.get(norm) || findCanonicalFuzzy(norm);
|
|
9927
|
+
sections.push({
|
|
9928
|
+
rawHeading: currentHeading,
|
|
9929
|
+
cleanTitle,
|
|
9930
|
+
canonicalKey,
|
|
9931
|
+
body: currentBody.join("\n")
|
|
9932
|
+
});
|
|
9933
|
+
currentBody = [];
|
|
9934
|
+
};
|
|
9935
|
+
const hasH2 = lines.some((l) => /^##\s+/.test(l));
|
|
9936
|
+
const headingRegex = hasH2 ? /^##\s+(.*)$/ : /^#{2,3}\s+(.*)$/;
|
|
9937
|
+
for (const line of lines) {
|
|
9938
|
+
const headingMatch = line.match(headingRegex);
|
|
9939
|
+
if (headingMatch) {
|
|
9940
|
+
flush();
|
|
9941
|
+
currentHeading = line.trim();
|
|
9942
|
+
} else {
|
|
9943
|
+
currentBody.push(line);
|
|
9944
|
+
}
|
|
9945
|
+
}
|
|
9946
|
+
flush();
|
|
9947
|
+
return sections;
|
|
9948
|
+
}
|
|
9949
|
+
function normalizeHeading(str) {
|
|
9950
|
+
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
9951
|
+
}
|
|
9952
|
+
function findCanonicalFuzzy(norm) {
|
|
9953
|
+
if (norm.includes("lesson design plan") || norm.includes("ke hoach thiet ke")) {
|
|
9954
|
+
return "A. Lesson Design Plan";
|
|
9955
|
+
}
|
|
9956
|
+
if (norm.includes("lesson flow") || norm.includes("tien trinh giang day")) {
|
|
9957
|
+
return "B. Lesson Flow";
|
|
9958
|
+
}
|
|
9959
|
+
if (norm.includes("learning objective") || norm.includes("muc tieu bai hoc")) {
|
|
9960
|
+
return "Learning Objectives & Evidence";
|
|
9961
|
+
}
|
|
9962
|
+
if (norm.includes("activity sequence") || norm.includes("chuoi hoat dong")) {
|
|
9963
|
+
return "Activity Sequence";
|
|
9964
|
+
}
|
|
9965
|
+
if (norm.includes("key term") || norm.includes("thuat ngu")) {
|
|
9966
|
+
return "Key Terms";
|
|
9967
|
+
}
|
|
9968
|
+
if (norm.includes("concept narrative") || norm.includes("dien giai khai niem")) {
|
|
9969
|
+
return "Concept Narratives";
|
|
9970
|
+
}
|
|
9971
|
+
if (norm.includes("worked example") || norm.includes("vi du")) {
|
|
9972
|
+
return "Worked Micro-Examples";
|
|
9973
|
+
}
|
|
9974
|
+
return void 0;
|
|
9975
|
+
}
|
|
9976
|
+
function truncateByBudget(source, budget) {
|
|
9977
|
+
if (source.length <= budget) return source;
|
|
9978
|
+
let cut = source.slice(0, budget);
|
|
9979
|
+
const fenceCount = (cut.match(/^```/gm) || []).length;
|
|
9980
|
+
if (fenceCount % 2 === 1) cut += "\n```";
|
|
9981
|
+
return cut;
|
|
9982
|
+
}
|
|
9983
|
+
|
|
9984
|
+
// src/services/knowledgeExpositionService.ts
|
|
9714
9985
|
var EXPOSITION_REL = (lessonCode) => "_sot/expositions/" + lessonCode + ".md";
|
|
9715
9986
|
var ExpositionApprovalError = class extends Error {
|
|
9716
9987
|
constructor(message) {
|
|
@@ -9817,15 +10088,8 @@ async function ensureKnowledgeExposition(options) {
|
|
|
9817
10088
|
return { relPath: EXPOSITION_REL(lessonCode), content: stamped, reused: false, gateMode: gateModeFor(options.gates ?? {}, "KNOWLEDGE_EXPOSITION") };
|
|
9818
10089
|
}
|
|
9819
10090
|
function buildExpositionContext(expositionContent, maxChars = 6e3) {
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
const sections = trimmed.split(/\n(?=## )/);
|
|
9823
|
-
let out = sections[0];
|
|
9824
|
-
for (let i = 1; i < sections.length && out.length < maxChars; i++) {
|
|
9825
|
-
const s = sections[i];
|
|
9826
|
-
out += "\n" + s.slice(0, Math.max(400, maxChars - out.length));
|
|
9827
|
-
}
|
|
9828
|
-
return out.slice(0, maxChars);
|
|
10091
|
+
if (!expositionContent || !expositionContent.trim()) return "";
|
|
10092
|
+
return buildExpositionExcerpt(expositionContent, { budget: maxChars }).excerpt;
|
|
9829
10093
|
}
|
|
9830
10094
|
function expositionCacheKey(planHash, lessonCode) {
|
|
9831
10095
|
return crypto.createHash("sha256").update(planHash + "|" + lessonCode).digest("hex").slice(0, 16);
|
|
@@ -11113,9 +11377,19 @@ function buildLanguageDirective(targetLanguage) {
|
|
|
11113
11377
|
- DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
|
|
11114
11378
|
${exampleLine}` : ""}`;
|
|
11115
11379
|
}
|
|
11116
|
-
function extractSectionHeadingsFromSLC(
|
|
11117
|
-
if (!
|
|
11380
|
+
function extractSectionHeadingsFromSLC(slcInput, artifactType) {
|
|
11381
|
+
if (!slcInput) return {};
|
|
11118
11382
|
const upperType = artifactType.trim().toUpperCase();
|
|
11383
|
+
if (typeof slcInput === "object") {
|
|
11384
|
+
if (slcInput[upperType]) return slcInput[upperType];
|
|
11385
|
+
for (const [key, mapping] of Object.entries(slcInput)) {
|
|
11386
|
+
if (key.toUpperCase() === upperType || upperType.startsWith("LESSON") && key.toUpperCase().startsWith("LESSON")) {
|
|
11387
|
+
return mapping;
|
|
11388
|
+
}
|
|
11389
|
+
}
|
|
11390
|
+
return {};
|
|
11391
|
+
}
|
|
11392
|
+
const slcMarkdown = slcInput;
|
|
11119
11393
|
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
11120
11394
|
for (const block of blocks) {
|
|
11121
11395
|
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
@@ -11598,7 +11872,50 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11598
11872
|
}
|
|
11599
11873
|
const pedagogy = detectProjectPedagogy(framework, styleGuide, options.pedagogy);
|
|
11600
11874
|
const pedagogyLabel = pedagogy.toUpperCase();
|
|
11601
|
-
|
|
11875
|
+
let glossaryContext = "";
|
|
11876
|
+
try {
|
|
11877
|
+
const glossaryRaw = await storage.readArtifact(projectId, "_sot/GLOSSARY.json");
|
|
11878
|
+
if (glossaryRaw) {
|
|
11879
|
+
let allTerms = [];
|
|
11880
|
+
try {
|
|
11881
|
+
allTerms = JSON.parse(glossaryRaw).terms ?? [];
|
|
11882
|
+
} catch {
|
|
11883
|
+
}
|
|
11884
|
+
let scopedTermsSet = null;
|
|
11885
|
+
const planRaw = await storage.readArtifact(projectId, "_sot/CURRICULUM_PLAN.json");
|
|
11886
|
+
if (planRaw) {
|
|
11887
|
+
try {
|
|
11888
|
+
const plan = JSON.parse(planRaw);
|
|
11889
|
+
const sessionScope = plan.glossary_scope?.find((g) => g.session_id === lessonCode);
|
|
11890
|
+
if (sessionScope?.terms?.length) {
|
|
11891
|
+
scopedTermsSet = new Set(sessionScope.terms.map((t) => t.toLowerCase()));
|
|
11892
|
+
}
|
|
11893
|
+
} catch {
|
|
11894
|
+
}
|
|
11895
|
+
}
|
|
11896
|
+
const relevantTerms = scopedTermsSet ? allTerms.filter((g) => scopedTermsSet.has(g.term.toLowerCase())) : allTerms.slice(0, 10);
|
|
11897
|
+
if (relevantTerms.length > 0) {
|
|
11898
|
+
const lines = relevantTerms.map(
|
|
11899
|
+
(t) => `- **${t.term}**: ${t.definition || ""}${t.example ? ` (e.g. \`${t.example}\`)` : ""}`
|
|
11900
|
+
);
|
|
11901
|
+
glossaryContext = buildSectionAwareExcerpt(lines.join("\n"), { budget: 800 }).excerpt;
|
|
11902
|
+
}
|
|
11903
|
+
}
|
|
11904
|
+
} catch {
|
|
11905
|
+
}
|
|
11906
|
+
let effectiveStyleGuide = styleGuide ? buildSectionAwareExcerpt(styleGuide, {
|
|
11907
|
+
priorities: ["Voice & Tone", "Standard Terminology (Glossary)", "Lesson Content Standards"],
|
|
11908
|
+
budget: 2e3
|
|
11909
|
+
}).excerpt : "";
|
|
11910
|
+
let effectiveRefPack = refPack ? buildSectionAwareExcerpt(refPack, {
|
|
11911
|
+
priorities: [
|
|
11912
|
+
"Technical Overview & Architecture Blueprint",
|
|
11913
|
+
"Hardware Pinout & Wiring Configuration Matrix",
|
|
11914
|
+
"Core Pedagogical Concept Anchor & Real-World Domain Bridge"
|
|
11915
|
+
],
|
|
11916
|
+
budget: 2500
|
|
11917
|
+
}).excerpt : "";
|
|
11918
|
+
const baseContextPrefix = `PROJECT & ACADEMIC CONTEXT:
|
|
11602
11919
|
- Project ID: ${projectId}
|
|
11603
11920
|
- Pedagogical Model: ${pedagogyLabel}
|
|
11604
11921
|
- Lesson Code: ${lessonCode}
|
|
@@ -11608,13 +11925,51 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11608
11925
|
- Target Bloom Level: ${bloomLevel}
|
|
11609
11926
|
|
|
11610
11927
|
[CURRICULUM FRAMEWORK EXCERPT]:
|
|
11611
|
-
${buildFrameworkExcerptForLesson(framework, lessonId)}
|
|
11928
|
+
${buildFrameworkExcerptForLesson(framework, lessonId)}`;
|
|
11929
|
+
const glossaryBlock = glossaryContext ? `
|
|
11930
|
+
|
|
11931
|
+
[GLOSSARY TERMS (use these exact definitions)]:
|
|
11932
|
+
${glossaryContext}` : "";
|
|
11933
|
+
const standardsBlock = standardsContext ? `
|
|
11934
|
+
|
|
11935
|
+
${standardsContext}` : "";
|
|
11936
|
+
const expositionBlock = expositionContext ? `
|
|
11937
|
+
|
|
11938
|
+
[KNOWLEDGE_EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict)]:
|
|
11939
|
+
${expositionContext}` : "";
|
|
11940
|
+
const sessionSliceBlock = sessionSliceContext ? `
|
|
11941
|
+
|
|
11942
|
+
${sessionSliceContext}` : "";
|
|
11943
|
+
const assembleCommonContext = (ref, sg) => `${baseContextPrefix}
|
|
11612
11944
|
|
|
11613
11945
|
[CONTENT STYLE GUIDE EXCERPT]:
|
|
11614
|
-
${
|
|
11946
|
+
${sg}
|
|
11615
11947
|
|
|
11616
11948
|
[REFERENCE PACK GROUND TRUTH]:
|
|
11617
|
-
${
|
|
11949
|
+
${ref}${standardsBlock}${glossaryBlock}${expositionBlock}${sessionSliceBlock}`;
|
|
11950
|
+
let commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
|
|
11951
|
+
const MAX_COMPOSITE_PROMPT_CHARS = 3e4;
|
|
11952
|
+
if (commonContext.length > MAX_COMPOSITE_PROMPT_CHARS && effectiveRefPack.length > 1e3) {
|
|
11953
|
+
effectiveRefPack = buildSectionAwareExcerpt(refPack, {
|
|
11954
|
+
priorities: [
|
|
11955
|
+
"Technical Overview & Architecture Blueprint",
|
|
11956
|
+
"Hardware Pinout & Wiring Configuration Matrix"
|
|
11957
|
+
],
|
|
11958
|
+
budget: 1e3
|
|
11959
|
+
}).excerpt;
|
|
11960
|
+
commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
|
|
11961
|
+
}
|
|
11962
|
+
if (commonContext.length > MAX_COMPOSITE_PROMPT_CHARS && effectiveStyleGuide.length > 1e3) {
|
|
11963
|
+
effectiveStyleGuide = buildSectionAwareExcerpt(styleGuide, {
|
|
11964
|
+
priorities: ["Voice & Tone", "Standard Terminology (Glossary)"],
|
|
11965
|
+
budget: 1e3
|
|
11966
|
+
}).excerpt;
|
|
11967
|
+
commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
|
|
11968
|
+
}
|
|
11969
|
+
onProgress?.("@content", `[CONTEXT] Composite prompt ready (${commonContext.length} chars, adaptive budget <= ${MAX_COMPOSITE_PROMPT_CHARS})`, {
|
|
11970
|
+
type: "progress",
|
|
11971
|
+
promptChars: commonContext.length
|
|
11972
|
+
});
|
|
11618
11973
|
const producedArtifacts = [];
|
|
11619
11974
|
const lessonRelPath = `_content/${unitCode}/LESSON_${lessonCode}.md`;
|
|
11620
11975
|
const existingLessonContent = await storage.readArtifact(projectId, lessonRelPath);
|
|
@@ -11734,14 +12089,15 @@ ${yamlBlock.trim()}
|
|
|
11734
12089
|
const judgeResult = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
11735
12090
|
targetArtifactType: "LESSON",
|
|
11736
12091
|
lessonId: lessonCode,
|
|
11737
|
-
expectedLanguage: "en",
|
|
12092
|
+
expectedLanguage: targetLang || "en",
|
|
11738
12093
|
targetObjectives: judgeObjectives,
|
|
11739
12094
|
generatedContentJson: JSON.stringify({
|
|
11740
12095
|
lessonContent,
|
|
11741
12096
|
lessonId: lessonCode,
|
|
11742
12097
|
title: lessonTitle,
|
|
11743
|
-
frameworkExcerpt: framework ? framework
|
|
11744
|
-
styleGuideExcerpt:
|
|
12098
|
+
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12099
|
+
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
12100
|
+
canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
|
|
11745
12101
|
}),
|
|
11746
12102
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
11747
12103
|
});
|
|
@@ -11783,7 +12139,7 @@ ${yamlBlock.trim()}
|
|
|
11783
12139
|
onProgress?.("@repair", `\u{1F527} Repair round ${round}/${MAX_REPAIR_ROUNDS} for LESSON_${lessonCode} (judge score ${currentResult.score}/100)...`);
|
|
11784
12140
|
const repairedRaw = await runCurriculumAIInference(
|
|
11785
12141
|
[{ role: "user", content: `You previously authored \`LESSON_${lessonCode}.md\` and the academic Judge REJECTED it with the critique below.
|
|
11786
|
-
Rewrite the COMPLETE corrected document: fix every listed issue,
|
|
12142
|
+
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.
|
|
11787
12143
|
|
|
11788
12144
|
JUDGE CRITIQUE:
|
|
11789
12145
|
${repairFeedback}
|
|
@@ -11801,19 +12157,26 @@ ${currentContent}` }],
|
|
|
11801
12157
|
break;
|
|
11802
12158
|
}
|
|
11803
12159
|
const repairLint = lintAndSanitizeArtifact(repairedRaw, `LESSON_${lessonCode}.md`);
|
|
11804
|
-
|
|
12160
|
+
const candidateContent = repairLint.autoFixedContent || repairedRaw;
|
|
12161
|
+
const hasFrontmatter = /^---\s*\r?\n[\s\S]*?\r?\n---/m.test(candidateContent);
|
|
12162
|
+
if (!hasFrontmatter || candidateContent.length < Math.min(800, currentContent.length * 0.4)) {
|
|
12163
|
+
onProgress?.("@repair", `\u26A0\uFE0F Repair round ${round} dropped critical structure (length or frontmatter missing) \u2014 rejecting repaired draft, retaining previous`);
|
|
12164
|
+
break;
|
|
12165
|
+
}
|
|
12166
|
+
currentContent = candidateContent;
|
|
11805
12167
|
onProgress?.("@reviewer", `\u{1F916} Re-judging repaired LESSON_${lessonCode} (round ${round})...`);
|
|
11806
12168
|
const reJudge = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
11807
12169
|
targetArtifactType: "LESSON",
|
|
11808
12170
|
lessonId: lessonCode,
|
|
11809
|
-
expectedLanguage: "en",
|
|
12171
|
+
expectedLanguage: targetLang || "en",
|
|
11810
12172
|
targetObjectives: parseLessonObjectives(currentContent, concept, bloomLevel),
|
|
11811
12173
|
generatedContentJson: JSON.stringify({
|
|
11812
12174
|
lessonContent: currentContent,
|
|
11813
12175
|
lessonId: lessonCode,
|
|
11814
12176
|
title: lessonTitle,
|
|
11815
|
-
frameworkExcerpt: framework ? framework
|
|
11816
|
-
styleGuideExcerpt:
|
|
12177
|
+
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12178
|
+
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
12179
|
+
canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
|
|
11817
12180
|
}),
|
|
11818
12181
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
11819
12182
|
});
|
|
@@ -11934,10 +12297,34 @@ ${currentContent}` }],
|
|
|
11934
12297
|
contentHash
|
|
11935
12298
|
});
|
|
11936
12299
|
}
|
|
12300
|
+
const lessonExcerptResult = buildSectionAwareExcerpt(lessonContent, {
|
|
12301
|
+
priorities: DEFAULT_LESSON_PRIORITIES,
|
|
12302
|
+
budget: 12e3,
|
|
12303
|
+
sectionLanguageContract: slcMarkdown,
|
|
12304
|
+
artifactType: "LESSON"
|
|
12305
|
+
});
|
|
12306
|
+
const lessonExcerpt = lessonExcerptResult.excerpt;
|
|
11937
12307
|
const satelliteContext = `${commonContext}
|
|
11938
12308
|
|
|
11939
12309
|
[CANONICAL LESSON PLAN (${pedagogyLabel})]:
|
|
11940
|
-
${
|
|
12310
|
+
${lessonExcerpt}`;
|
|
12311
|
+
const judgeSat = (sat, content) => {
|
|
12312
|
+
if (gateModeFor(gates, sat) !== "LLM_JUDGE") return Promise.resolve();
|
|
12313
|
+
return judgeSatelliteArtifact({
|
|
12314
|
+
storage,
|
|
12315
|
+
projectId,
|
|
12316
|
+
lessonCode,
|
|
12317
|
+
sat,
|
|
12318
|
+
content,
|
|
12319
|
+
concept,
|
|
12320
|
+
bloomLevel,
|
|
12321
|
+
standardStatements,
|
|
12322
|
+
onProgress,
|
|
12323
|
+
targetLang,
|
|
12324
|
+
canonicalLessonContent: lessonContent,
|
|
12325
|
+
canonicalLessonExcerpt: lessonExcerpt
|
|
12326
|
+
});
|
|
12327
|
+
};
|
|
11941
12328
|
const actRelPath = `_content/${unitCode}/ACT_${lessonCode}.md`;
|
|
11942
12329
|
if (artifactScope.includes("ACT") && (!await storage.readArtifact(projectId, actRelPath) || force)) {
|
|
11943
12330
|
onProgress?.("@activity", `[2/4] Authoring Hands-on Lab: \`ACT_${lessonCode}.md\`...`);
|
|
@@ -12006,19 +12393,7 @@ ${buildHeadingDirective("ACT", slcMarkdown, targetLang)}`;
|
|
|
12006
12393
|
contentHash: computeContentHash(rawAct)
|
|
12007
12394
|
});
|
|
12008
12395
|
producedArtifacts.push(`ACT_${lessonCode}.md`);
|
|
12009
|
-
|
|
12010
|
-
await judgeSatelliteArtifact({
|
|
12011
|
-
storage,
|
|
12012
|
-
projectId,
|
|
12013
|
-
lessonCode,
|
|
12014
|
-
sat: "ACT",
|
|
12015
|
-
content: rawAct,
|
|
12016
|
-
concept,
|
|
12017
|
-
bloomLevel,
|
|
12018
|
-
standardStatements,
|
|
12019
|
-
onProgress
|
|
12020
|
-
});
|
|
12021
|
-
}
|
|
12396
|
+
await judgeSat("ACT", rawAct);
|
|
12022
12397
|
}
|
|
12023
12398
|
const quizRelPath = `_content/${unitCode}/QUIZ_${lessonCode}.md`;
|
|
12024
12399
|
if (artifactScope.includes("QUIZ") && (!await storage.readArtifact(projectId, quizRelPath) || force)) {
|
|
@@ -12082,64 +12457,25 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
|
|
|
12082
12457
|
contentHash: computeContentHash(rawQuiz)
|
|
12083
12458
|
});
|
|
12084
12459
|
producedArtifacts.push(`QUIZ_${lessonCode}.md`);
|
|
12085
|
-
|
|
12086
|
-
await judgeSatelliteArtifact({
|
|
12087
|
-
storage,
|
|
12088
|
-
projectId,
|
|
12089
|
-
lessonCode,
|
|
12090
|
-
sat: "QUIZ",
|
|
12091
|
-
content: rawQuiz,
|
|
12092
|
-
concept,
|
|
12093
|
-
bloomLevel,
|
|
12094
|
-
standardStatements,
|
|
12095
|
-
onProgress
|
|
12096
|
-
});
|
|
12097
|
-
}
|
|
12460
|
+
await judgeSat("QUIZ", rawQuiz);
|
|
12098
12461
|
}
|
|
12099
12462
|
const slideRelPath = `_content/${unitCode}/SLIDE_${lessonCode}.md`;
|
|
12100
12463
|
if (artifactScope.includes("SLIDE") && (!await storage.readArtifact(projectId, slideRelPath) || force)) {
|
|
12101
12464
|
onProgress?.("@illustrator", `[4/4] Authoring Presentation Slide Deck: \`SLIDE_${lessonCode}.md\`...`);
|
|
12102
12465
|
const canonicalSlideTemplate = loadCurriculumTemplate("SLIDE_template.md");
|
|
12103
|
-
const
|
|
12104
|
-
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\`.
|
|
12105
|
-
|
|
12106
|
-
[MARP SLIDE TEMPLATE SCAFFOLD]:
|
|
12107
|
-
${canonicalSlideTemplate || `---
|
|
12466
|
+
const templateScaffold = canonicalSlideTemplate || `---
|
|
12108
12467
|
marp: true
|
|
12109
12468
|
theme: default
|
|
12110
12469
|
paginate: true
|
|
12111
12470
|
header: "${titleHeader(lessonTitle)}"
|
|
12112
12471
|
footer: "Curriculum OS \u2022 ${lessonCode} (${pedagogyLabel})"
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
5. **Slide 5 [Core Concept 1: Mental Model]:** Definition, intuitive everyday analogy, and golden rule card
|
|
12121
|
-
6. **Slide 6 [Architecture & Visual Flow]:** Clean Mermaid diagram (flowchart or sequenceDiagram) + 3 flow steps
|
|
12122
|
-
7. **Slide 7 [Core Concept 2: Syntax / Mechanism Anatomy]:** Side-by-side 6-10 lines runnable code + anatomy breakdown & syntax trap card
|
|
12123
|
-
8. **Slide 8 [Guided Practice: Try It Now]:** 3-minute active desk task card with starter hint and success criteria
|
|
12124
|
-
9. **Slide 9 [Integrated Hands-On Lab]:** 3-tier differentiated challenge cards (Bronze / Silver / Gold) + gotcha alert card
|
|
12125
|
-
10. **Slide 10 [Traffic Light Checkpoint & Pitfalls]:** Formative self-check cards (\u{1F7E2}/\u{1F7E1}/\u{1F534}) & diagnostic test question
|
|
12126
|
-
11. **Slide 11 [Exit Ticket & Metacognition]:** 2 scenario-based check questions + 1 metacognitive reflection prompt
|
|
12127
|
-
12. **Slide 12 [Summary & Next Steps]:** 3 core golden rules + preview card of next upcoming milestone
|
|
12128
|
-
|
|
12129
|
-
Mandatory Canvas & Presentation Invariants:
|
|
12130
|
-
- A slide is an INTERACTIVE PROJECTION CANVAS, NOT a textbook! Absolutely NO dense paragraphs or walls of text.
|
|
12131
|
-
- Follow the 6x6 rule: Maximum 4-6 bullet points per slide, maximum 8-12 words per bullet.
|
|
12132
|
-
- 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">\`.
|
|
12133
|
-
- MANDATORY PRESENTER NOTES ON EVERY SLIDE: Every slide MUST end with \`<!-- Presenter Notes: ... -->\` containing:
|
|
12134
|
-
* SCRIPT: 60-90s teacher talk track with intuitive analogies.
|
|
12135
|
-
* COLD CALL / CHECK: Specific diagnostic question to ask students.
|
|
12136
|
-
* SCAFFOLDING / GOTCHA: Guidance for students who get stuck.
|
|
12137
|
-
* PACING: Recommended minutes for the slide.
|
|
12138
|
-
- Output 100% valid Marp Markdown.
|
|
12139
|
-
|
|
12140
|
-
${languageDirective}
|
|
12141
|
-
|
|
12142
|
-
${buildHeadingDirective("SLIDE", slcMarkdown, targetLang)}`;
|
|
12472
|
+
---`;
|
|
12473
|
+
const slidePrompt = buildMarpMarkdownSlidePrompt({
|
|
12474
|
+
lessonCode,
|
|
12475
|
+
templateScaffold,
|
|
12476
|
+
languageDirective,
|
|
12477
|
+
headingDirective: buildHeadingDirective("SLIDE", slcMarkdown, targetLang)
|
|
12478
|
+
});
|
|
12143
12479
|
const rawSlide = await runCurriculumAIInference(
|
|
12144
12480
|
[{ role: "user", content: slidePrompt }],
|
|
12145
12481
|
satelliteContext,
|
|
@@ -12165,19 +12501,7 @@ ${buildHeadingDirective("SLIDE", slcMarkdown, targetLang)}`;
|
|
|
12165
12501
|
contentHash: computeContentHash(rawSlide)
|
|
12166
12502
|
});
|
|
12167
12503
|
producedArtifacts.push(`SLIDE_${lessonCode}.md`);
|
|
12168
|
-
|
|
12169
|
-
await judgeSatelliteArtifact({
|
|
12170
|
-
storage,
|
|
12171
|
-
projectId,
|
|
12172
|
-
lessonCode,
|
|
12173
|
-
sat: "SLIDE",
|
|
12174
|
-
content: rawSlide,
|
|
12175
|
-
concept,
|
|
12176
|
-
bloomLevel,
|
|
12177
|
-
standardStatements,
|
|
12178
|
-
onProgress
|
|
12179
|
-
});
|
|
12180
|
-
}
|
|
12504
|
+
await judgeSat("SLIDE", rawSlide);
|
|
12181
12505
|
}
|
|
12182
12506
|
const guideRelPath = `_content/${unitCode}/GUIDE_${lessonCode}.md`;
|
|
12183
12507
|
if (artifactScope.includes("GUIDE") && (!await storage.readArtifact(projectId, guideRelPath) || force)) {
|
|
@@ -12227,19 +12551,7 @@ ${buildHeadingDirective("GUIDE", slcMarkdown, targetLang)}`;
|
|
|
12227
12551
|
contentHash: computeContentHash(rawGuide)
|
|
12228
12552
|
});
|
|
12229
12553
|
producedArtifacts.push(`GUIDE_${lessonCode}.md`);
|
|
12230
|
-
|
|
12231
|
-
await judgeSatelliteArtifact({
|
|
12232
|
-
storage,
|
|
12233
|
-
projectId,
|
|
12234
|
-
lessonCode,
|
|
12235
|
-
sat: "GUIDE",
|
|
12236
|
-
content: rawGuide,
|
|
12237
|
-
concept,
|
|
12238
|
-
bloomLevel,
|
|
12239
|
-
standardStatements,
|
|
12240
|
-
onProgress
|
|
12241
|
-
});
|
|
12242
|
-
}
|
|
12554
|
+
await judgeSat("GUIDE", rawGuide);
|
|
12243
12555
|
}
|
|
12244
12556
|
}
|
|
12245
12557
|
const handoutRelPath = `_content/${unitCode}/HANDOUT_${lessonCode}.md`;
|
|
@@ -12290,19 +12602,7 @@ ${buildHeadingDirective("HANDOUT", slcMarkdown, targetLang)}`;
|
|
|
12290
12602
|
contentHash: computeContentHash(rawHandout)
|
|
12291
12603
|
});
|
|
12292
12604
|
producedArtifacts.push(`HANDOUT_${lessonCode}.md`);
|
|
12293
|
-
|
|
12294
|
-
await judgeSatelliteArtifact({
|
|
12295
|
-
storage,
|
|
12296
|
-
projectId,
|
|
12297
|
-
lessonCode,
|
|
12298
|
-
sat: "HANDOUT",
|
|
12299
|
-
content: rawHandout,
|
|
12300
|
-
concept,
|
|
12301
|
-
bloomLevel,
|
|
12302
|
-
standardStatements,
|
|
12303
|
-
onProgress
|
|
12304
|
-
});
|
|
12305
|
-
}
|
|
12605
|
+
await judgeSat("HANDOUT", rawHandout);
|
|
12306
12606
|
}
|
|
12307
12607
|
}
|
|
12308
12608
|
const wksRelPath = `_content/${unitCode}/WKS_${lessonCode}.md`;
|
|
@@ -12357,19 +12657,7 @@ ${buildHeadingDirective("WKS", slcMarkdown, targetLang)}`;
|
|
|
12357
12657
|
contentHash: computeContentHash(rawWks)
|
|
12358
12658
|
});
|
|
12359
12659
|
producedArtifacts.push(`WKS_${lessonCode}.md`);
|
|
12360
|
-
|
|
12361
|
-
await judgeSatelliteArtifact({
|
|
12362
|
-
storage,
|
|
12363
|
-
projectId,
|
|
12364
|
-
lessonCode,
|
|
12365
|
-
sat: "WKS",
|
|
12366
|
-
content: rawWks,
|
|
12367
|
-
concept,
|
|
12368
|
-
bloomLevel,
|
|
12369
|
-
standardStatements,
|
|
12370
|
-
onProgress
|
|
12371
|
-
});
|
|
12372
|
-
}
|
|
12660
|
+
await judgeSat("WKS", rawWks);
|
|
12373
12661
|
}
|
|
12374
12662
|
}
|
|
12375
12663
|
const codeRelPath = `_content/${unitCode}/CODE_${lessonCode}.md`;
|
|
@@ -12433,19 +12721,7 @@ ${buildHeadingDirective("CODE", slcMarkdown, targetLang)}`;
|
|
|
12433
12721
|
contentHash: computeContentHash(rawCode)
|
|
12434
12722
|
});
|
|
12435
12723
|
producedArtifacts.push(`CODE_${lessonCode}.md`);
|
|
12436
|
-
|
|
12437
|
-
await judgeSatelliteArtifact({
|
|
12438
|
-
storage,
|
|
12439
|
-
projectId,
|
|
12440
|
-
lessonCode,
|
|
12441
|
-
sat: "CODE",
|
|
12442
|
-
content: rawCode,
|
|
12443
|
-
concept,
|
|
12444
|
-
bloomLevel,
|
|
12445
|
-
standardStatements,
|
|
12446
|
-
onProgress
|
|
12447
|
-
});
|
|
12448
|
-
}
|
|
12724
|
+
await judgeSat("CODE", rawCode);
|
|
12449
12725
|
}
|
|
12450
12726
|
}
|
|
12451
12727
|
const extRelPath = `_content/${unitCode}/EXT_${lessonCode}.md`;
|
|
@@ -12498,19 +12774,7 @@ ${buildHeadingDirective("EXT", slcMarkdown, targetLang)}`;
|
|
|
12498
12774
|
contentHash: computeContentHash(rawExt)
|
|
12499
12775
|
});
|
|
12500
12776
|
producedArtifacts.push(`EXT_${lessonCode}.md`);
|
|
12501
|
-
|
|
12502
|
-
await judgeSatelliteArtifact({
|
|
12503
|
-
storage,
|
|
12504
|
-
projectId,
|
|
12505
|
-
lessonCode,
|
|
12506
|
-
sat: "EXT",
|
|
12507
|
-
content: rawExt,
|
|
12508
|
-
concept,
|
|
12509
|
-
bloomLevel,
|
|
12510
|
-
standardStatements,
|
|
12511
|
-
onProgress
|
|
12512
|
-
});
|
|
12513
|
-
}
|
|
12777
|
+
await judgeSat("EXT", rawExt);
|
|
12514
12778
|
}
|
|
12515
12779
|
}
|
|
12516
12780
|
onProgress?.("@reviewer", `\u2705 Successfully authored all requested artifacts for \`${lessonCode}\` (${pedagogyLabel})!`);
|
|
@@ -12576,12 +12840,22 @@ async function judgeSatelliteArtifact(ctx) {
|
|
|
12576
12840
|
const { storage, projectId, lessonCode, sat, content } = ctx;
|
|
12577
12841
|
try {
|
|
12578
12842
|
ctx.onProgress?.("@reviewer", `\u{1F916} Judging ${sat}_${lessonCode}...`);
|
|
12843
|
+
const targetObjectives = parseLessonObjectives(
|
|
12844
|
+
ctx.canonicalLessonContent || content,
|
|
12845
|
+
ctx.concept,
|
|
12846
|
+
ctx.bloomLevel
|
|
12847
|
+
);
|
|
12579
12848
|
const result = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12580
12849
|
targetArtifactType: sat,
|
|
12581
12850
|
lessonId: lessonCode,
|
|
12582
|
-
expectedLanguage: "en",
|
|
12583
|
-
targetObjectives
|
|
12584
|
-
generatedContentJson: JSON.stringify({
|
|
12851
|
+
expectedLanguage: ctx.targetLang || "en",
|
|
12852
|
+
targetObjectives,
|
|
12853
|
+
generatedContentJson: JSON.stringify({
|
|
12854
|
+
content,
|
|
12855
|
+
artifactType: sat,
|
|
12856
|
+
lessonId: lessonCode,
|
|
12857
|
+
canonicalLessonExcerpt: ctx.canonicalLessonExcerpt
|
|
12858
|
+
}),
|
|
12585
12859
|
standardStatements: Object.keys(ctx.standardStatements).length > 0 ? ctx.standardStatements : void 0
|
|
12586
12860
|
});
|
|
12587
12861
|
const passed = result.passed && result.score >= 85;
|
|
@@ -12704,6 +12978,87 @@ async function produceBatchLessons(storage, projectId, lessonIds, options = {})
|
|
|
12704
12978
|
// src/services/singleArtifactService.ts
|
|
12705
12979
|
init_streamRunner();
|
|
12706
12980
|
init_errors();
|
|
12981
|
+
|
|
12982
|
+
// src/services/contextRouting.ts
|
|
12983
|
+
init_errors();
|
|
12984
|
+
var ARTIFACT_DEPENDENCY_ROUTING = {
|
|
12985
|
+
LESSON: {
|
|
12986
|
+
required: ["KNOWLEDGE_EXPOSITION", "SESSION_SLICE", "FRAMEWORK_EXCERPT"],
|
|
12987
|
+
optional: ["STYLE_GUIDE", "REFERENCE_PACK"],
|
|
12988
|
+
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"
|
|
12989
|
+
},
|
|
12990
|
+
HANDOUT: {
|
|
12991
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12992
|
+
optional: ["SESSION_SLICE"],
|
|
12993
|
+
rationale: "T\xE0i li\u1EC7u t\u1EF1 h\u1ECDc \u2014 b\xE1m kh\xE1i ni\u1EC7m chu\u1EA9n, kh\xF4ng c\u1EA7n activity timeline"
|
|
12994
|
+
},
|
|
12995
|
+
EXT: {
|
|
12996
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12997
|
+
optional: ["SESSION_SLICE"],
|
|
12998
|
+
rationale: "Th\u1EED th\xE1ch m\u1EDF r\u1ED9ng chuy\xEAn s\xE2u b\xE1m kh\xE1i ni\u1EC7m"
|
|
12999
|
+
},
|
|
13000
|
+
CODE: {
|
|
13001
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
13002
|
+
optional: ["LESSON_OBJECTIVES"],
|
|
13003
|
+
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"
|
|
13004
|
+
},
|
|
13005
|
+
ACT: {
|
|
13006
|
+
required: ["CANONICAL_LESSON"],
|
|
13007
|
+
optional: ["KNOWLEDGE_EXPOSITION", "SESSION_SLICE"],
|
|
13008
|
+
rationale: "STEM Activity Lab b\u1EAFt bu\u1ED9c ph\u1EA3i kh\u1EDBp 100% Activity Sequence v\xE0 Lesson Flow c\u1EE7a LESSON"
|
|
13009
|
+
},
|
|
13010
|
+
WKS: {
|
|
13011
|
+
required: ["CANONICAL_LESSON"],
|
|
13012
|
+
optional: ["KNOWLEDGE_EXPOSITION"],
|
|
13013
|
+
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"
|
|
13014
|
+
},
|
|
13015
|
+
GUIDE: {
|
|
13016
|
+
required: ["CANONICAL_LESSON"],
|
|
13017
|
+
optional: ["SESSION_SLICE"],
|
|
13018
|
+
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"
|
|
13019
|
+
},
|
|
13020
|
+
SLIDE: {
|
|
13021
|
+
required: ["CANONICAL_LESSON"],
|
|
13022
|
+
optional: ["KNOWLEDGE_EXPOSITION"],
|
|
13023
|
+
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"
|
|
13024
|
+
},
|
|
13025
|
+
QUIZ: {
|
|
13026
|
+
required: ["KNOWLEDGE_EXPOSITION", "CANONICAL_LESSON"],
|
|
13027
|
+
optional: ["SESSION_SLICE"],
|
|
13028
|
+
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)"
|
|
13029
|
+
}
|
|
13030
|
+
};
|
|
13031
|
+
function validateArtifactDependencies(artifactType, availableSources, opts = {}) {
|
|
13032
|
+
const normType = (artifactType || "").toUpperCase().trim();
|
|
13033
|
+
const rule = ARTIFACT_DEPENDENCY_ROUTING[normType];
|
|
13034
|
+
const failClosed = opts.failClosed ?? true;
|
|
13035
|
+
if (!rule) {
|
|
13036
|
+
return { valid: true, missing: [] };
|
|
13037
|
+
}
|
|
13038
|
+
const missing = [];
|
|
13039
|
+
for (const req of rule.required) {
|
|
13040
|
+
const val = availableSources[req];
|
|
13041
|
+
const isPresent = val !== void 0 && val !== null && (typeof val === "string" ? val.trim().length > 0 : true);
|
|
13042
|
+
if (!isPresent) {
|
|
13043
|
+
missing.push(req);
|
|
13044
|
+
}
|
|
13045
|
+
}
|
|
13046
|
+
if (missing.length > 0) {
|
|
13047
|
+
const err = createContextMissingError({
|
|
13048
|
+
artifactType: normType,
|
|
13049
|
+
missingSource: missing[0],
|
|
13050
|
+
lessonId: opts.lessonId,
|
|
13051
|
+
agent: opts.agent
|
|
13052
|
+
});
|
|
13053
|
+
if (failClosed) {
|
|
13054
|
+
throw err;
|
|
13055
|
+
}
|
|
13056
|
+
return { valid: false, missing, error: err };
|
|
13057
|
+
}
|
|
13058
|
+
return { valid: true, missing: [] };
|
|
13059
|
+
}
|
|
13060
|
+
|
|
13061
|
+
// src/services/singleArtifactService.ts
|
|
12707
13062
|
function getArtifactMetadata(type, lessonId, pedagogy) {
|
|
12708
13063
|
const id = lessonId || "ON_DEMAND";
|
|
12709
13064
|
switch (type) {
|
|
@@ -12783,9 +13138,24 @@ async function generateSingleArtifact(req) {
|
|
|
12783
13138
|
const templateContent = loadedTemplate || getDefaultFallbackTemplate(artifactType, displayTitle, lessonId || "ON_DEMAND");
|
|
12784
13139
|
const hwStr = hardwarePlatform.join(", ");
|
|
12785
13140
|
const selectedDevices = (config?.devices || (hardwarePlatform[0]?.toLowerCase().includes("paper") ? "paper-only" : "laptop")).toLowerCase();
|
|
12786
|
-
|
|
12787
|
-
const
|
|
12788
|
-
const
|
|
13141
|
+
language.toLowerCase().includes("bilingual") || language.toLowerCase().includes("song");
|
|
13142
|
+
const targetLang = resolveTargetLanguageCode(language);
|
|
13143
|
+
const langDirective = buildLanguageDirective(language);
|
|
13144
|
+
const headingDirective = buildHeadingDirective(
|
|
13145
|
+
artifactType.toUpperCase(),
|
|
13146
|
+
req.sectionLanguageContract,
|
|
13147
|
+
targetLang
|
|
13148
|
+
);
|
|
13149
|
+
const availableSources = {
|
|
13150
|
+
KNOWLEDGE_EXPOSITION: contextSot.exposition || researchContext,
|
|
13151
|
+
CANONICAL_LESSON: contextSot.lessonPlan,
|
|
13152
|
+
FRAMEWORK_EXCERPT: contextSot.framework
|
|
13153
|
+
};
|
|
13154
|
+
validateArtifactDependencies(artifactType.toUpperCase(), availableSources, {
|
|
13155
|
+
lessonId,
|
|
13156
|
+
agent: meta.persona,
|
|
13157
|
+
failClosed: req.failClosedContext ?? false
|
|
13158
|
+
});
|
|
12789
13159
|
const isPaperOnly = selectedDevices === "paper-only" || hwStr.toLowerCase().includes("paper") || hwStr.toLowerCase().includes("print-ready");
|
|
12790
13160
|
const deviceRule = isPaperOnly ? `
|
|
12791
13161
|
- \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" ? `
|
|
@@ -12806,7 +13176,8 @@ async function generateSingleArtifact(req) {
|
|
|
12806
13176
|
Your task is to author a canonical, publication-grade learning artifact of type "${artifactType.toUpperCase()}".
|
|
12807
13177
|
|
|
12808
13178
|
### CORE OPERATIONAL INVARIANTS:
|
|
12809
|
-
${
|
|
13179
|
+
${langDirective}
|
|
13180
|
+
${headingDirective}
|
|
12810
13181
|
2. NON-MOCK CODE INVARIANT: Any code snippet provided MUST be 100% syntactically valid, idiomatic, and executable without placeholders or fake functions.
|
|
12811
13182
|
3. PEDAGOGICAL GROUNDING: Strictly align with the ${pedagogy.toUpperCase()} model, Bloom's Revised Taxonomy, and IEEE/ACM CS2023 guidelines.
|
|
12812
13183
|
4. SCAFFOLDING LEVEL: "${scaffoldingLevel.toUpperCase()}".${scaffoldingRule}
|
|
@@ -12815,6 +13186,11 @@ ${langRule}
|
|
|
12815
13186
|
|
|
12816
13187
|
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).
|
|
12817
13188
|
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.` : ""}`;
|
|
13189
|
+
const slcContract = req.sectionLanguageContract;
|
|
13190
|
+
const frameworkExcerpt = contextSot.framework ? buildSectionAwareExcerpt(contextSot.framework, { budget: 2500, sectionLanguageContract: slcContract }).excerpt : "";
|
|
13191
|
+
const lessonPlanExcerpt = contextSot.lessonPlan ? buildLessonExcerpt(contextSot.lessonPlan, { budget: 8e3, sectionLanguageContract: slcContract, artifactType: "LESSON" }).excerpt : "";
|
|
13192
|
+
const handoutExcerpt = contextSot.handout ? buildSectionAwareExcerpt(contextSot.handout, { budget: 2e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
13193
|
+
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
12818
13194
|
const userPrompt = `### CONTEXT GROUND TRUTH:
|
|
12819
13195
|
- Topic / Concept Domain: "${topic}"
|
|
12820
13196
|
- Lesson ID: "${lessonId || "ON_DEMAND"}"
|
|
@@ -12832,14 +13208,17 @@ ${selectedDevices ? `- Device Mode: "${selectedDevices}"
|
|
|
12832
13208
|
${researchContext ? `### RESEARCH GROUND TRUTH (fact-checked context \u2014 \u01B0u ti\xEAn d\xF9ng, KH\xD4NG b\u1ECBa s\u1ED1 li\u1EC7u):
|
|
12833
13209
|
${researchContext.slice(0, 4e3)}
|
|
12834
13210
|
` : ""}
|
|
12835
|
-
${
|
|
12836
|
-
${
|
|
13211
|
+
${expositionExcerpt ? `### SOT KNOWLEDGE EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict):
|
|
13212
|
+
${expositionExcerpt}
|
|
12837
13213
|
` : ""}
|
|
12838
|
-
${
|
|
12839
|
-
${
|
|
13214
|
+
${frameworkExcerpt ? `### SOT CURRICULUM FRAMEWORK:
|
|
13215
|
+
${frameworkExcerpt}
|
|
12840
13216
|
` : ""}
|
|
12841
|
-
${
|
|
12842
|
-
${
|
|
13217
|
+
${lessonPlanExcerpt ? `### SOT CANONICAL LESSON PLAN:
|
|
13218
|
+
${lessonPlanExcerpt}
|
|
13219
|
+
` : ""}
|
|
13220
|
+
${handoutExcerpt ? `### SOT STUDENT HANDOUT:
|
|
13221
|
+
${handoutExcerpt}
|
|
12843
13222
|
` : ""}
|
|
12844
13223
|
|
|
12845
13224
|
### MANDATORY CANONICAL TEMPLATE CONTRACT:
|
|
@@ -12928,9 +13307,16 @@ ${yaml.trim()}
|
|
|
12928
13307
|
const verdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12929
13308
|
targetArtifactType: artifactType.toUpperCase(),
|
|
12930
13309
|
lessonId: lessonId || "ON_DEMAND",
|
|
12931
|
-
expectedLanguage:
|
|
13310
|
+
expectedLanguage: targetLang || "en",
|
|
12932
13311
|
targetObjectives: judgeObjectives,
|
|
12933
|
-
generatedContentJson: JSON.stringify({
|
|
13312
|
+
generatedContentJson: JSON.stringify({
|
|
13313
|
+
content: finalContent,
|
|
13314
|
+
artifactType,
|
|
13315
|
+
lessonId: lessonId || "ON_DEMAND",
|
|
13316
|
+
title: displayTitle,
|
|
13317
|
+
canonicalLessonExcerpt: lessonPlanExcerpt || void 0,
|
|
13318
|
+
canonicalExposition: expositionExcerpt || void 0
|
|
13319
|
+
})
|
|
12934
13320
|
});
|
|
12935
13321
|
const passed = Boolean(verdict.passed) && verdict.score >= 85;
|
|
12936
13322
|
if (passed) {
|
|
@@ -12972,9 +13358,16 @@ ${finalContent}` }
|
|
|
12972
13358
|
const reVerdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12973
13359
|
targetArtifactType: artifactType.toUpperCase(),
|
|
12974
13360
|
lessonId: lessonId || "ON_DEMAND",
|
|
12975
|
-
expectedLanguage:
|
|
13361
|
+
expectedLanguage: targetLang || "en",
|
|
12976
13362
|
targetObjectives: judgeObjectives,
|
|
12977
|
-
generatedContentJson: JSON.stringify({
|
|
13363
|
+
generatedContentJson: JSON.stringify({
|
|
13364
|
+
content: repaired,
|
|
13365
|
+
artifactType,
|
|
13366
|
+
lessonId: lessonId || "ON_DEMAND",
|
|
13367
|
+
title: displayTitle,
|
|
13368
|
+
canonicalLessonExcerpt: lessonPlanExcerpt || void 0,
|
|
13369
|
+
canonicalExposition: expositionExcerpt || void 0
|
|
13370
|
+
})
|
|
12978
13371
|
});
|
|
12979
13372
|
if (reVerdict.passed && reVerdict.score >= 85) {
|
|
12980
13373
|
return {
|
|
@@ -16926,6 +17319,7 @@ function renderMediaPlaceholder(entry) {
|
|
|
16926
17319
|
}
|
|
16927
17320
|
|
|
16928
17321
|
exports.ACT_TEMPLATE = ACT_TEMPLATE;
|
|
17322
|
+
exports.ARTIFACT_DEPENDENCY_ROUTING = ARTIFACT_DEPENDENCY_ROUTING;
|
|
16929
17323
|
exports.ARTIFACT_EXECUTION_ORDER = ARTIFACT_EXECUTION_ORDER;
|
|
16930
17324
|
exports.AcademicAuditor = AcademicAuditor;
|
|
16931
17325
|
exports.ActiveLearningWorkflowSchema = ActiveLearningWorkflowSchema;
|
|
@@ -16970,6 +17364,8 @@ exports.CurriculumPlanSchema = CurriculumPlanSchema;
|
|
|
16970
17364
|
exports.CurriculumQualityReportSchema = CurriculumQualityReportSchema;
|
|
16971
17365
|
exports.DEFAULT_ENABLED_PROVIDERS = DEFAULT_ENABLED_PROVIDERS;
|
|
16972
17366
|
exports.DEFAULT_GATE_SETTINGS = DEFAULT_GATE_SETTINGS;
|
|
17367
|
+
exports.DEFAULT_KX_PRIORITIES = DEFAULT_KX_PRIORITIES;
|
|
17368
|
+
exports.DEFAULT_LESSON_PRIORITIES = DEFAULT_LESSON_PRIORITIES;
|
|
16973
17369
|
exports.DEFAULT_STREAM_IDLE_MS = DEFAULT_STREAM_IDLE_MS;
|
|
16974
17370
|
exports.DEFAULT_STREAM_TOTAL_MS = DEFAULT_STREAM_TOTAL_MS;
|
|
16975
17371
|
exports.DependencyEdgeSchema = DependencyEdgeSchema;
|
|
@@ -17069,6 +17465,7 @@ exports.RubricCriteriaSchema = RubricCriteriaSchema;
|
|
|
17069
17465
|
exports.RubricSchema = RubricSchema;
|
|
17070
17466
|
exports.SCIENCE_LAB_TEMPLATE = SCIENCE_LAB_TEMPLATE;
|
|
17071
17467
|
exports.SELF_LAB_TEMPLATE = SELF_LAB_TEMPLATE;
|
|
17468
|
+
exports.SLIDE_CANONICAL_METHODOLOGY = SLIDE_CANONICAL_METHODOLOGY;
|
|
17072
17469
|
exports.SLIDE_LAYOUT_PRESETS = SLIDE_LAYOUT_PRESETS;
|
|
17073
17470
|
exports.SLIDE_TEMPLATE = SLIDE_TEMPLATE;
|
|
17074
17471
|
exports.STANDARD_SOT_FILES = STANDARD_SOT_FILES;
|
|
@@ -17123,14 +17520,18 @@ exports.buildCurriculumPlan = buildCurriculumPlan;
|
|
|
17123
17520
|
exports.buildDeliveryPackages = buildDeliveryPackages;
|
|
17124
17521
|
exports.buildDiagnosticQuizPrompt = buildDiagnosticQuizPrompt;
|
|
17125
17522
|
exports.buildExpositionContext = buildExpositionContext;
|
|
17523
|
+
exports.buildExpositionExcerpt = buildExpositionExcerpt;
|
|
17126
17524
|
exports.buildExtensionPrompt = buildExtensionPrompt;
|
|
17127
17525
|
exports.buildHandoutPrompt = buildHandoutPrompt;
|
|
17128
17526
|
exports.buildHeadingDirective = buildHeadingDirective;
|
|
17129
17527
|
exports.buildImagePrompt = buildImagePrompt;
|
|
17130
17528
|
exports.buildJudgePrompt = buildJudgePrompt;
|
|
17131
17529
|
exports.buildLanguageDirective = buildLanguageDirective;
|
|
17530
|
+
exports.buildLessonExcerpt = buildLessonExcerpt;
|
|
17132
17531
|
exports.buildLessonMasterPrompt = buildLessonMasterPrompt;
|
|
17532
|
+
exports.buildMarpMarkdownSlidePrompt = buildMarpMarkdownSlidePrompt;
|
|
17133
17533
|
exports.buildProjectInstructionPrompt = buildProjectInstructionPrompt;
|
|
17534
|
+
exports.buildSectionAwareExcerpt = buildSectionAwareExcerpt;
|
|
17134
17535
|
exports.buildSelfLabPrompt = buildSelfLabPrompt;
|
|
17135
17536
|
exports.buildSessionSliceContext = buildSessionSliceContext;
|
|
17136
17537
|
exports.buildSlidesPrompt = buildSlidesPrompt;
|
|
@@ -17146,6 +17547,7 @@ exports.conductPreliminaryResearch = conductPreliminaryResearch;
|
|
|
17146
17547
|
exports.contentTools = contentTools;
|
|
17147
17548
|
exports.convertRoadmapToFoundationSot = convertRoadmapToFoundationSot;
|
|
17148
17549
|
exports.createAiInferenceError = createAiInferenceError;
|
|
17550
|
+
exports.createContextMissingError = createContextMissingError;
|
|
17149
17551
|
exports.createCurriculumStorage = createCurriculumStorage;
|
|
17150
17552
|
exports.createIdleAbortController = createIdleAbortController;
|
|
17151
17553
|
exports.createStreamAbortController = createStreamAbortController;
|
|
@@ -17213,6 +17615,7 @@ exports.lintFrameworkPack = lintFrameworkPack;
|
|
|
17213
17615
|
exports.loadCurriculumTemplate = loadCurriculumTemplate;
|
|
17214
17616
|
exports.loadSotTemplate = loadSotTemplate;
|
|
17215
17617
|
exports.normalizePlanningGraph = normalizePlanningGraph;
|
|
17618
|
+
exports.normalizeSlcContract = normalizeSlcContract;
|
|
17216
17619
|
exports.packagerTools = packagerTools;
|
|
17217
17620
|
exports.parseGateSettings = parseGateSettings;
|
|
17218
17621
|
exports.parseQuizMarkdown = parseQuizMarkdown;
|
|
@@ -17256,6 +17659,7 @@ exports.targetLanguageDisplayName = targetLanguageDisplayName;
|
|
|
17256
17659
|
exports.techSmeTools = techSmeTools;
|
|
17257
17660
|
exports.topoSort = topoSort;
|
|
17258
17661
|
exports.uploadAssetToBucket = uploadAssetToBucket;
|
|
17662
|
+
exports.validateArtifactDependencies = validateArtifactDependencies;
|
|
17259
17663
|
exports.validateCurriculumPlan = validateCurriculumPlan;
|
|
17260
17664
|
exports.validateFrameworkPack = validateFrameworkPack;
|
|
17261
17665
|
exports.validateMarkdownTables = validateMarkdownTables;
|