@thanh01.pmt/curriculum-kit 1.0.22 → 1.2.0
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 +57 -2
- 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 +56 -3
- 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 +728 -198
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +94 -5
- package/dist/index.d.ts +94 -5
- package/dist/index.mjs +713 -199
- 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 +13 -2
- package/dist/pipeline/index.cjs.map +1 -1
- package/dist/pipeline/index.mjs +13 -2
- package/dist/pipeline/index.mjs.map +1 -1
- package/dist/schemas/index.cjs +13 -2
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +34 -16
- package/dist/schemas/index.d.ts +34 -16
- package/dist/schemas/index.mjs +13 -2
- package/dist/schemas/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +461 -16
- 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 +461 -16
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +1 -1
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"() {
|
|
@@ -2432,9 +2446,20 @@ var SessionPlanSchema = zod.z.object({
|
|
|
2432
2446
|
differentiation: zod.z.object({ bronze: zod.z.string(), silver: zod.z.string(), gold: zod.z.string() })
|
|
2433
2447
|
});
|
|
2434
2448
|
var TranslationPolicySchema = zod.z.object({
|
|
2435
|
-
policy: zod.z.enum(["after_artifact", "end_of_unit", "at_publish"]).default("
|
|
2449
|
+
policy: zod.z.enum(["after_artifact", "end_of_unit", "at_publish", "native"]).default("native"),
|
|
2436
2450
|
target_language: zod.z.string().nullable().default(null)
|
|
2437
|
-
})
|
|
2451
|
+
}).refine(
|
|
2452
|
+
(data) => {
|
|
2453
|
+
if (data.policy === "native") {
|
|
2454
|
+
return typeof data.target_language === "string" && data.target_language.trim().length > 0;
|
|
2455
|
+
}
|
|
2456
|
+
return true;
|
|
2457
|
+
},
|
|
2458
|
+
{
|
|
2459
|
+
message: "When translation policy is 'native', target_language must be a non-empty string",
|
|
2460
|
+
path: ["target_language"]
|
|
2461
|
+
}
|
|
2462
|
+
);
|
|
2438
2463
|
var CoverageReportSchema = zod.z.object({
|
|
2439
2464
|
assigned_node_ids: zod.z.array(zod.z.string()),
|
|
2440
2465
|
unassigned_node_ids: zod.z.array(zod.z.string()),
|
|
@@ -5368,6 +5393,45 @@ Return a single valid JSON object matching SlideDeckSchema with these exact keys
|
|
|
5368
5393
|
}
|
|
5369
5394
|
`.trim();
|
|
5370
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
|
+
}
|
|
5371
5435
|
|
|
5372
5436
|
// src/ai/prompts/teacherGuidePrompt.ts
|
|
5373
5437
|
function buildTeacherGuidePrompt(input) {
|
|
@@ -9700,6 +9764,224 @@ function resolveGateSettings(raw) {
|
|
|
9700
9764
|
function gateModeFor(resolved, type) {
|
|
9701
9765
|
return resolved[type] ?? "OFF";
|
|
9702
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
|
|
9703
9985
|
var EXPOSITION_REL = (lessonCode) => "_sot/expositions/" + lessonCode + ".md";
|
|
9704
9986
|
var ExpositionApprovalError = class extends Error {
|
|
9705
9987
|
constructor(message) {
|
|
@@ -9806,15 +10088,8 @@ async function ensureKnowledgeExposition(options) {
|
|
|
9806
10088
|
return { relPath: EXPOSITION_REL(lessonCode), content: stamped, reused: false, gateMode: gateModeFor(options.gates ?? {}, "KNOWLEDGE_EXPOSITION") };
|
|
9807
10089
|
}
|
|
9808
10090
|
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);
|
|
10091
|
+
if (!expositionContent || !expositionContent.trim()) return "";
|
|
10092
|
+
return buildExpositionExcerpt(expositionContent, { budget: maxChars }).excerpt;
|
|
9818
10093
|
}
|
|
9819
10094
|
function expositionCacheKey(planHash, lessonCode) {
|
|
9820
10095
|
return crypto.createHash("sha256").update(planHash + "|" + lessonCode).digest("hex").slice(0, 16);
|
|
@@ -9855,6 +10130,7 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
9855
10130
|
});
|
|
9856
10131
|
return { relPath: result.relPath, context: buildExpositionContext(result.content), reused: result.reused };
|
|
9857
10132
|
}
|
|
10133
|
+
init_errors();
|
|
9858
10134
|
var asArr = (v) => Array.isArray(v) ? v : [];
|
|
9859
10135
|
var asStr = (v, dflt = "") => typeof v === "string" ? v : dflt;
|
|
9860
10136
|
var asNum = (v, dflt) => typeof v === "number" && Number.isFinite(v) ? v : dflt;
|
|
@@ -10497,7 +10773,15 @@ function extractSessionSlice(plan, lessonCode) {
|
|
|
10497
10773
|
}
|
|
10498
10774
|
function buildSessionSliceContext(plan, lessonCode) {
|
|
10499
10775
|
const s = plan.sessions.find((x) => x.id === lessonCode);
|
|
10500
|
-
if (!s)
|
|
10776
|
+
if (!s) {
|
|
10777
|
+
throw new exports.CurriculumError({
|
|
10778
|
+
errorCode: "ERR_LESSON_NOT_IN_SOT",
|
|
10779
|
+
message: `Session "${lessonCode}" not found in CURRICULUM_PLAN.json (${plan.plan_hash})`,
|
|
10780
|
+
suggestedAction: "\u0110\u1ED3ng b\u1ED9 CURRICULUM_PLAN r\u1ED3i ch\u1EA1y l\u1EA1i",
|
|
10781
|
+
retryable: false,
|
|
10782
|
+
lessonId: lessonCode
|
|
10783
|
+
});
|
|
10784
|
+
}
|
|
10501
10785
|
const lines = [];
|
|
10502
10786
|
lines.push("[SESSION SLICE (from CURRICULUM_PLAN " + plan.plan_hash + ")]");
|
|
10503
10787
|
lines.push("- Objective: " + s.prose_objective);
|
|
@@ -11064,6 +11348,90 @@ function resolveStandardsPacks(packIds) {
|
|
|
11064
11348
|
return packs;
|
|
11065
11349
|
}
|
|
11066
11350
|
|
|
11351
|
+
// src/services/languageDirective.ts
|
|
11352
|
+
function resolveTargetLanguageCode(language) {
|
|
11353
|
+
const raw = String(language || "vi").trim().toLowerCase();
|
|
11354
|
+
if (raw.startsWith("vi")) return "vi";
|
|
11355
|
+
if (raw.startsWith("en")) return "en";
|
|
11356
|
+
return raw || "vi";
|
|
11357
|
+
}
|
|
11358
|
+
function targetLanguageDisplayName(code) {
|
|
11359
|
+
const map = {
|
|
11360
|
+
vi: "Vietnamese (Ti\u1EBFng Vi\u1EC7t)",
|
|
11361
|
+
en: "English (US)"
|
|
11362
|
+
};
|
|
11363
|
+
return map[code] || code;
|
|
11364
|
+
}
|
|
11365
|
+
function buildLanguageDirective(targetLanguage) {
|
|
11366
|
+
const code = resolveTargetLanguageCode(targetLanguage);
|
|
11367
|
+
const name = targetLanguageDisplayName(code);
|
|
11368
|
+
const perLanguageExamples = {
|
|
11369
|
+
vi: `- V\xED d\u1EE5 ti\xEAu \u0111\u1EC1 b\xE0i h\u1ECDc \u0111\xFAng chu\u1EA9n: "B\xE0i 1: Kh\xE1m ph\xE1 m\u1EA1ch \u0111i\u1EC7n c\u01A1 b\u1EA3n", "B\xE0i 2: \u0110i\u1EC1u khi\u1EC3n \u0111\xE8n LED nh\u1EA5p nh\xE1y" \u2014 KH\xD4NG d\xF9ng ti\xEAu \u0111\u1EC1 ti\u1EBFng Anh.`,
|
|
11370
|
+
en: `- Example compliant lesson title: "Lesson 1: Exploring Basic Circuits" \u2014 natural, idiomatic English throughout.`
|
|
11371
|
+
};
|
|
11372
|
+
const exampleLine = perLanguageExamples[code] || "";
|
|
11373
|
+
return `MANDATORY LANGUAGE DIRECTIVE (TARGET OUTPUT LANGUAGE: ${name}):
|
|
11374
|
+
- The TARGET OUTPUT LANGUAGE for this course is ${name}. You MUST author the ENTIRE document in ${name}.
|
|
11375
|
+
- All section titles, table headers, table cells, lesson names, learning objectives, pedagogical narratives, and cognitive analyses MUST be written in natural, fluent, academic ${name}.
|
|
11376
|
+
- Technical identifiers, code keywords (e.g. setup(), loop(), pinMode()), standard protocols (I2C, SPI, UART, GPIO), and component model numbers (ESP32, Arduino Uno) remain in standard technical notation, but all surrounding explanations MUST be in ${name}.
|
|
11377
|
+
- DO NOT mix in paragraphs, tables, or titles written in any other language. Strict adherence is required.${exampleLine ? `
|
|
11378
|
+
${exampleLine}` : ""}`;
|
|
11379
|
+
}
|
|
11380
|
+
function extractSectionHeadingsFromSLC(slcInput, artifactType) {
|
|
11381
|
+
if (!slcInput) return {};
|
|
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;
|
|
11393
|
+
const blocks = slcMarkdown.split(/\n(?=#{2,3}\s+[A-Z0-9_]+)/g);
|
|
11394
|
+
for (const block of blocks) {
|
|
11395
|
+
const headerMatch = block.match(/^#{2,3}\s+([A-Z0-9_]+)/);
|
|
11396
|
+
if (!headerMatch) continue;
|
|
11397
|
+
const blockType = headerMatch[1].trim().toUpperCase();
|
|
11398
|
+
if (blockType === upperType || upperType.startsWith("LESSON") && blockType.startsWith("LESSON")) {
|
|
11399
|
+
const mapping = {};
|
|
11400
|
+
const lines = block.split("\n");
|
|
11401
|
+
for (const line of lines) {
|
|
11402
|
+
const trimmed = line.trim();
|
|
11403
|
+
if (trimmed.startsWith("|") && !trimmed.includes("---")) {
|
|
11404
|
+
const cells = trimmed.split("|").map((c) => c.trim()).filter((_, idx, arr) => idx > 0 && idx < arr.length - 1);
|
|
11405
|
+
if (cells.length >= 2 && !cells[0].toLowerCase().includes("canonical") && !cells[1].toLowerCase().includes("localized")) {
|
|
11406
|
+
mapping[cells[0]] = cells[1];
|
|
11407
|
+
}
|
|
11408
|
+
} else {
|
|
11409
|
+
const bullet = line.match(/^[-*]\s+([^:]+):\s+(.+)$/);
|
|
11410
|
+
if (bullet) {
|
|
11411
|
+
mapping[bullet[1].trim()] = bullet[2].trim();
|
|
11412
|
+
}
|
|
11413
|
+
}
|
|
11414
|
+
}
|
|
11415
|
+
if (Object.keys(mapping).length > 0) return mapping;
|
|
11416
|
+
}
|
|
11417
|
+
}
|
|
11418
|
+
return {};
|
|
11419
|
+
}
|
|
11420
|
+
function buildHeadingDirective(artifactType, slcMarkdown, targetLanguage = "vi") {
|
|
11421
|
+
const headings = extractSectionHeadingsFromSLC(slcMarkdown, artifactType);
|
|
11422
|
+
if (Object.keys(headings).length === 0) {
|
|
11423
|
+
return "";
|
|
11424
|
+
}
|
|
11425
|
+
const lines = Object.entries(headings).map(
|
|
11426
|
+
([canonical, localized]) => ` - "${canonical}" -> Use Display Heading: "${localized}"`
|
|
11427
|
+
);
|
|
11428
|
+
return `MANDATORY SECTION HEADINGS FROM SECTION_LANGUAGE_CONTRACT:
|
|
11429
|
+
- The YAML frontmatter \`template_required_sections\` MUST preserve the exact English canonical keys.
|
|
11430
|
+
- In the markdown body, section headers MUST use the EXACT Localized Display Labels below (do NOT translate or paraphrase):
|
|
11431
|
+
${lines.join("\n")}
|
|
11432
|
+
- For example: if canonical section is "Computational Thinking Focus", your heading must be "## [REQUIRED] ${headings["Computational Thinking Focus"] || "Computational Thinking Focus"}".`;
|
|
11433
|
+
}
|
|
11434
|
+
|
|
11067
11435
|
// src/services/lessonProductionService.ts
|
|
11068
11436
|
var __filename2 = typeof (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)) === "string" ? url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))) : "";
|
|
11069
11437
|
var _resolvedDir = __filename2 ? path3__default.default.dirname(__filename2) : typeof __dirname !== "undefined" ? __dirname : process.cwd();
|
|
@@ -11105,11 +11473,44 @@ function detectProjectPedagogy(frameworkText, styleGuideText, explicitPedagogy)
|
|
|
11105
11473
|
return "5e";
|
|
11106
11474
|
}
|
|
11107
11475
|
async function getLessonMetadata(storage, projectId, lessonId) {
|
|
11108
|
-
const framework = await storage.readSotDocument(projectId, "CURRICULUM_FRAMEWORK.md") || "";
|
|
11109
11476
|
const parts = lessonId.split("_");
|
|
11110
11477
|
const unitCode = parts[0] || "U01";
|
|
11111
11478
|
const moduleCode = parts.length >= 2 ? `${parts[0]}_${parts[1]}` : `${unitCode}_M01`;
|
|
11112
11479
|
const lessonCode = lessonId;
|
|
11480
|
+
let planStr = null;
|
|
11481
|
+
try {
|
|
11482
|
+
planStr = await storage.readSotDocument(projectId, "CURRICULUM_PLAN.json") || await storage.readArtifact(projectId, "_sot/CURRICULUM_PLAN.json") || await storage.readArtifact(projectId, "CURRICULUM_PLAN.json");
|
|
11483
|
+
} catch {
|
|
11484
|
+
}
|
|
11485
|
+
if (planStr) {
|
|
11486
|
+
try {
|
|
11487
|
+
const plan = JSON.parse(planStr);
|
|
11488
|
+
if (Array.isArray(plan.sessions)) {
|
|
11489
|
+
const session = plan.sessions.find((s) => s.id === lessonId);
|
|
11490
|
+
if (session) {
|
|
11491
|
+
const lessonTitle2 = session.title || `Lesson ${lessonId}`;
|
|
11492
|
+
const keywords = Array.isArray(session.new_keywords) && session.new_keywords.length > 0 ? ` T\u1EEB kh\xF3a: ${session.new_keywords.join(", ")}` : "";
|
|
11493
|
+
const objective2 = session.prose_objective || session.title || "";
|
|
11494
|
+
const concept2 = objective2 ? `${objective2}.${keywords}` : session.title || "Core Technical Competency";
|
|
11495
|
+
const prerequisites2 = session.anchor_type ? `Anchor: ${session.anchor_type}` : "None";
|
|
11496
|
+
const depth = Array.isArray(session.depth_assignments) ? session.depth_assignments[0]?.depth : session.depth_assignments?.knowledge_depth;
|
|
11497
|
+
const bloomLevel2 = depth === "sio" ? "Create" : depth === "cio" ? "Apply" : "Understand";
|
|
11498
|
+
return {
|
|
11499
|
+
unitCode: session.unit_id || unitCode,
|
|
11500
|
+
moduleCode,
|
|
11501
|
+
lessonCode,
|
|
11502
|
+
lessonTitle: lessonTitle2,
|
|
11503
|
+
concept: `M\u1EE5c ti\xEAu bu\u1ED5i h\u1ECDc: ${concept2}`,
|
|
11504
|
+
prerequisites: prerequisites2,
|
|
11505
|
+
bloomLevel: bloomLevel2
|
|
11506
|
+
};
|
|
11507
|
+
}
|
|
11508
|
+
}
|
|
11509
|
+
} catch (planErr) {
|
|
11510
|
+
console.warn(`[getLessonMetadata] Error parsing CURRICULUM_PLAN.json for ${projectId}:`, planErr);
|
|
11511
|
+
}
|
|
11512
|
+
}
|
|
11513
|
+
const framework = await storage.readSotDocument(projectId, "CURRICULUM_FRAMEWORK.md") || "";
|
|
11113
11514
|
let lessonTitle = `Lesson ${lessonId}`;
|
|
11114
11515
|
let concept = "Core Technical Competency";
|
|
11115
11516
|
let prerequisites = "None";
|
|
@@ -11154,15 +11555,24 @@ async function getLessonMetadata(storage, projectId, lessonId) {
|
|
|
11154
11555
|
}
|
|
11155
11556
|
if (found) break;
|
|
11156
11557
|
}
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11558
|
+
if (found) {
|
|
11559
|
+
return {
|
|
11560
|
+
unitCode,
|
|
11561
|
+
moduleCode,
|
|
11562
|
+
lessonCode,
|
|
11563
|
+
lessonTitle,
|
|
11564
|
+
concept: objective ? `${concept}. M\u1EE5c ti\xEAu bu\u1ED5i h\u1ECDc: ${objective}` : concept,
|
|
11565
|
+
prerequisites: deliverable ? `${prerequisites}. S\u1EA3n ph\u1EA9m hands-on c\u1EE7a bu\u1ED5i: ${deliverable}` : prerequisites,
|
|
11566
|
+
bloomLevel
|
|
11567
|
+
};
|
|
11568
|
+
}
|
|
11569
|
+
throw new exports.CurriculumError({
|
|
11570
|
+
errorCode: "ERR_LESSON_NOT_IN_SOT",
|
|
11571
|
+
lessonId,
|
|
11572
|
+
message: `ERR_LESSON_NOT_IN_SOT: B\xE0i h\u1ECDc "${lessonId}" kh\xF4ng t\u1ED3n t\u1EA1i trong CURRICULUM_PLAN.json ho\u1EB7c CURRICULUM_FRAMEWORK.md c\u1EE7a d\u1EF1 \xE1n "${projectId}".`,
|
|
11573
|
+
suggestedAction: "\u0110\u1ED3ng b\u1ED9 CURRICULUM_PLAN r\u1ED3i ch\u1EA1y l\u1EA1i",
|
|
11574
|
+
retryable: false
|
|
11575
|
+
});
|
|
11166
11576
|
}
|
|
11167
11577
|
function buildFrameworkExcerptForLesson(framework, lessonId) {
|
|
11168
11578
|
if (!framework) return "";
|
|
@@ -11204,7 +11614,7 @@ ${nextRow}`
|
|
|
11204
11614
|
].filter(Boolean);
|
|
11205
11615
|
return parts.join("\n\n") || framework.slice(0, 1500);
|
|
11206
11616
|
}
|
|
11207
|
-
function buildLessonPrompt(pedagogy, lessonCode, unitCode, lessonTitle, concept, bloomLevel, dateStr) {
|
|
11617
|
+
function buildLessonPrompt(pedagogy, lessonCode, unitCode, lessonTitle, concept, bloomLevel, dateStr, targetLanguage = "vi", sectionLanguageContract) {
|
|
11208
11618
|
const commonFrontmatter = `id: "LESSON_${lessonCode}"
|
|
11209
11619
|
title: "${lessonTitle}"
|
|
11210
11620
|
created_by: "Curriculum OS Builder"
|
|
@@ -11224,8 +11634,9 @@ template_required_sections:
|
|
|
11224
11634
|
- "Artifact Contract"
|
|
11225
11635
|
- "B. Lesson Flow"
|
|
11226
11636
|
- "Artifact Linkage"`;
|
|
11637
|
+
let prompt = "";
|
|
11227
11638
|
if (pedagogy === "edp") {
|
|
11228
|
-
|
|
11639
|
+
prompt = `You are @content (Educational Content Editor & EDP Engineering Design Process Specialist).
|
|
11229
11640
|
Author the comprehensive Master Lesson Plan adhering strictly to \`LESSON_EDP_template.md\` standards for:
|
|
11230
11641
|
- Lesson Code: ${lessonCode}
|
|
11231
11642
|
- Title: ${lessonTitle}
|
|
@@ -11274,9 +11685,8 @@ Linkage ledger mapping all satellite artifacts (\`ACT_...\`, \`QUIZ_...\`, \`SLI
|
|
|
11274
11685
|
|
|
11275
11686
|
3. Ensure all sample code and schemas are 100% syntax-valid and executable.
|
|
11276
11687
|
4. Output 100% clean Markdown directly.`;
|
|
11277
|
-
}
|
|
11278
|
-
|
|
11279
|
-
return `You are @content (Educational Content Editor & PBL/General Pedagogy Specialist).
|
|
11688
|
+
} else if (pedagogy === "pbl" || pedagogy === "general") {
|
|
11689
|
+
prompt = `You are @content (Educational Content Editor & PBL/General Pedagogy Specialist).
|
|
11280
11690
|
Author the comprehensive Master Lesson Plan adhering strictly to \`LESSON_GENERAL_template.md\` standards for:
|
|
11281
11691
|
- Lesson Code: ${lessonCode}
|
|
11282
11692
|
- Title: ${lessonTitle}
|
|
@@ -11323,8 +11733,8 @@ type: "LESSON_GENERAL"
|
|
|
11323
11733
|
Linkage ledger mapping all satellite artifacts (\`ACT_...\`, \`QUIZ_...\`, \`SLIDE_...\`).
|
|
11324
11734
|
|
|
11325
11735
|
3. Output 100% clean Markdown directly.`;
|
|
11326
|
-
}
|
|
11327
|
-
|
|
11736
|
+
} else {
|
|
11737
|
+
prompt = `You are @content (Educational Content Editor & 5E Instructional Model Specialist).
|
|
11328
11738
|
Author the comprehensive Master Lesson Plan adhering strictly to \`LESSON_5E_template.md\` standards for:
|
|
11329
11739
|
- Lesson Code: ${lessonCode}
|
|
11330
11740
|
- Title: ${lessonTitle}
|
|
@@ -11372,6 +11782,18 @@ Linkage ledger mapping all satellite artifacts (\`GUIDE_...\`, \`SLIDE_...\`, \`
|
|
|
11372
11782
|
|
|
11373
11783
|
3. Ensure all sample code and syntax are 100% verified and runnable.
|
|
11374
11784
|
4. Output 100% clean Markdown directly.`;
|
|
11785
|
+
}
|
|
11786
|
+
const langDirective = buildLanguageDirective(targetLanguage);
|
|
11787
|
+
const headingDirective = buildHeadingDirective(
|
|
11788
|
+
pedagogy === "edp" ? "LESSON_EDP" : pedagogy === "general" || pedagogy === "pbl" ? "LESSON_GENERAL" : "LESSON_5E",
|
|
11789
|
+
sectionLanguageContract,
|
|
11790
|
+
targetLanguage
|
|
11791
|
+
);
|
|
11792
|
+
return `${prompt}
|
|
11793
|
+
|
|
11794
|
+
${langDirective}${headingDirective ? `
|
|
11795
|
+
|
|
11796
|
+
${headingDirective}` : ""}`;
|
|
11375
11797
|
}
|
|
11376
11798
|
async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
11377
11799
|
const {
|
|
@@ -11402,6 +11824,20 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11402
11824
|
const styleGuide = await storage.readSotDocument(projectId, "CONTENT_STYLE_GUIDE.md") || "";
|
|
11403
11825
|
const refPack = await storage.readSotDocument(projectId, "REFERENCE_PACK.md") || "";
|
|
11404
11826
|
await storage.readSotDocument(projectId, "LEARNER_PROFILE.md") || "";
|
|
11827
|
+
const slcMarkdown = options.sectionLanguageContract || await storage.readSotDocument(projectId, "SECTION_LANGUAGE_CONTRACT.md") || "";
|
|
11828
|
+
let targetLang = options.targetLanguage;
|
|
11829
|
+
if (!targetLang) {
|
|
11830
|
+
try {
|
|
11831
|
+
const planRaw = await storage.readArtifact(projectId, "_sot/CURRICULUM_PLAN.json");
|
|
11832
|
+
if (planRaw) {
|
|
11833
|
+
const p = JSON.parse(planRaw);
|
|
11834
|
+
targetLang = p?.translation?.target_language;
|
|
11835
|
+
}
|
|
11836
|
+
} catch {
|
|
11837
|
+
}
|
|
11838
|
+
}
|
|
11839
|
+
targetLang = targetLang || "vi";
|
|
11840
|
+
const languageDirective = buildLanguageDirective(targetLang);
|
|
11405
11841
|
let expositionContext = "";
|
|
11406
11842
|
let sessionSliceContext = "";
|
|
11407
11843
|
try {
|
|
@@ -11436,6 +11872,18 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11436
11872
|
}
|
|
11437
11873
|
const pedagogy = detectProjectPedagogy(framework, styleGuide, options.pedagogy);
|
|
11438
11874
|
const pedagogyLabel = pedagogy.toUpperCase();
|
|
11875
|
+
const styleGuideExcerpt = styleGuide ? buildSectionAwareExcerpt(styleGuide, {
|
|
11876
|
+
priorities: ["Voice & Tone", "Standard Terminology (Glossary)", "Lesson Content Standards"],
|
|
11877
|
+
budget: 2e3
|
|
11878
|
+
}).excerpt : "";
|
|
11879
|
+
const refPackExcerpt = refPack ? buildSectionAwareExcerpt(refPack, {
|
|
11880
|
+
priorities: [
|
|
11881
|
+
"Technical Overview & Architecture Blueprint",
|
|
11882
|
+
"Hardware Pinout & Wiring Configuration Matrix",
|
|
11883
|
+
"Core Pedagogical Concept Anchor & Real-World Domain Bridge"
|
|
11884
|
+
],
|
|
11885
|
+
budget: 2500
|
|
11886
|
+
}).excerpt : "";
|
|
11439
11887
|
const commonContext = `PROJECT & ACADEMIC CONTEXT:
|
|
11440
11888
|
- Project ID: ${projectId}
|
|
11441
11889
|
- Pedagogical Model: ${pedagogyLabel}
|
|
@@ -11449,10 +11897,10 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11449
11897
|
${buildFrameworkExcerptForLesson(framework, lessonId)}
|
|
11450
11898
|
|
|
11451
11899
|
[CONTENT STYLE GUIDE EXCERPT]:
|
|
11452
|
-
${
|
|
11900
|
+
${styleGuideExcerpt}
|
|
11453
11901
|
|
|
11454
11902
|
[REFERENCE PACK GROUND TRUTH]:
|
|
11455
|
-
${
|
|
11903
|
+
${refPackExcerpt}${standardsContext ? "\n\n" + standardsContext : ""}${expositionContext ? "\n\n[KNOWLEDGE_EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict)]:\n" + expositionContext : ""}${sessionSliceContext ? "\n\n" + sessionSliceContext : ""}`;
|
|
11456
11904
|
const producedArtifacts = [];
|
|
11457
11905
|
const lessonRelPath = `_content/${unitCode}/LESSON_${lessonCode}.md`;
|
|
11458
11906
|
const existingLessonContent = await storage.readArtifact(projectId, lessonRelPath);
|
|
@@ -11471,7 +11919,9 @@ Khi n\u1ED9i dung c\u1EA7n minh h\u1ECDa (diagram quy tr\xECnh, s\u01A1 \u0111\u
|
|
|
11471
11919
|
lessonTitle,
|
|
11472
11920
|
concept,
|
|
11473
11921
|
bloomLevel,
|
|
11474
|
-
dateStr
|
|
11922
|
+
dateStr,
|
|
11923
|
+
targetLang,
|
|
11924
|
+
slcMarkdown
|
|
11475
11925
|
) + mediaDirective;
|
|
11476
11926
|
const rawLesson = await runCurriculumAIInference(
|
|
11477
11927
|
[{ role: "user", content: lessonPrompt }],
|
|
@@ -11570,14 +12020,15 @@ ${yamlBlock.trim()}
|
|
|
11570
12020
|
const judgeResult = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
11571
12021
|
targetArtifactType: "LESSON",
|
|
11572
12022
|
lessonId: lessonCode,
|
|
11573
|
-
expectedLanguage: "en",
|
|
12023
|
+
expectedLanguage: targetLang || "en",
|
|
11574
12024
|
targetObjectives: judgeObjectives,
|
|
11575
12025
|
generatedContentJson: JSON.stringify({
|
|
11576
12026
|
lessonContent,
|
|
11577
12027
|
lessonId: lessonCode,
|
|
11578
12028
|
title: lessonTitle,
|
|
11579
|
-
frameworkExcerpt: framework ? framework
|
|
11580
|
-
styleGuideExcerpt:
|
|
12029
|
+
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12030
|
+
styleGuideExcerpt: styleGuideExcerpt || void 0,
|
|
12031
|
+
canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
|
|
11581
12032
|
}),
|
|
11582
12033
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
11583
12034
|
});
|
|
@@ -11642,14 +12093,15 @@ ${currentContent}` }],
|
|
|
11642
12093
|
const reJudge = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
11643
12094
|
targetArtifactType: "LESSON",
|
|
11644
12095
|
lessonId: lessonCode,
|
|
11645
|
-
expectedLanguage: "en",
|
|
12096
|
+
expectedLanguage: targetLang || "en",
|
|
11646
12097
|
targetObjectives: parseLessonObjectives(currentContent, concept, bloomLevel),
|
|
11647
12098
|
generatedContentJson: JSON.stringify({
|
|
11648
12099
|
lessonContent: currentContent,
|
|
11649
12100
|
lessonId: lessonCode,
|
|
11650
12101
|
title: lessonTitle,
|
|
11651
|
-
frameworkExcerpt: framework ? framework
|
|
11652
|
-
styleGuideExcerpt:
|
|
12102
|
+
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12103
|
+
styleGuideExcerpt: styleGuideExcerpt || void 0,
|
|
12104
|
+
canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
|
|
11653
12105
|
}),
|
|
11654
12106
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
11655
12107
|
});
|
|
@@ -11770,10 +12222,34 @@ ${currentContent}` }],
|
|
|
11770
12222
|
contentHash
|
|
11771
12223
|
});
|
|
11772
12224
|
}
|
|
12225
|
+
const lessonExcerptResult = buildSectionAwareExcerpt(lessonContent, {
|
|
12226
|
+
priorities: DEFAULT_LESSON_PRIORITIES,
|
|
12227
|
+
budget: 12e3,
|
|
12228
|
+
sectionLanguageContract: slcMarkdown,
|
|
12229
|
+
artifactType: "LESSON"
|
|
12230
|
+
});
|
|
12231
|
+
const lessonExcerpt = lessonExcerptResult.excerpt;
|
|
11773
12232
|
const satelliteContext = `${commonContext}
|
|
11774
12233
|
|
|
11775
12234
|
[CANONICAL LESSON PLAN (${pedagogyLabel})]:
|
|
11776
|
-
${
|
|
12235
|
+
${lessonExcerpt}`;
|
|
12236
|
+
const judgeSat = (sat, content) => {
|
|
12237
|
+
if (gateModeFor(gates, sat) !== "LLM_JUDGE") return Promise.resolve();
|
|
12238
|
+
return judgeSatelliteArtifact({
|
|
12239
|
+
storage,
|
|
12240
|
+
projectId,
|
|
12241
|
+
lessonCode,
|
|
12242
|
+
sat,
|
|
12243
|
+
content,
|
|
12244
|
+
concept,
|
|
12245
|
+
bloomLevel,
|
|
12246
|
+
standardStatements,
|
|
12247
|
+
onProgress,
|
|
12248
|
+
targetLang,
|
|
12249
|
+
canonicalLessonContent: lessonContent,
|
|
12250
|
+
canonicalLessonExcerpt: lessonExcerpt
|
|
12251
|
+
});
|
|
12252
|
+
};
|
|
11777
12253
|
const actRelPath = `_content/${unitCode}/ACT_${lessonCode}.md`;
|
|
11778
12254
|
if (artifactScope.includes("ACT") && (!await storage.readArtifact(projectId, actRelPath) || force)) {
|
|
11779
12255
|
onProgress?.("@activity", `[2/4] Authoring Hands-on Lab: \`ACT_${lessonCode}.md\`...`);
|
|
@@ -11812,7 +12288,11 @@ template_required_sections:
|
|
|
11812
12288
|
- ### Phase 3: Debugging & Testing
|
|
11813
12289
|
- ## [REQUIRED] 3-Tier Differentiation (Bronze/Silver/Gold tasks)
|
|
11814
12290
|
- ## [REQUIRED] Reflection (Discussion question)
|
|
11815
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12291
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12292
|
+
|
|
12293
|
+
${languageDirective}
|
|
12294
|
+
|
|
12295
|
+
${buildHeadingDirective("ACT", slcMarkdown, targetLang)}`;
|
|
11816
12296
|
const rawAct = await runCurriculumAIInference(
|
|
11817
12297
|
[{ role: "user", content: actPrompt }],
|
|
11818
12298
|
satelliteContext,
|
|
@@ -11838,19 +12318,7 @@ template_required_sections:
|
|
|
11838
12318
|
contentHash: computeContentHash(rawAct)
|
|
11839
12319
|
});
|
|
11840
12320
|
producedArtifacts.push(`ACT_${lessonCode}.md`);
|
|
11841
|
-
|
|
11842
|
-
await judgeSatelliteArtifact({
|
|
11843
|
-
storage,
|
|
11844
|
-
projectId,
|
|
11845
|
-
lessonCode,
|
|
11846
|
-
sat: "ACT",
|
|
11847
|
-
content: rawAct,
|
|
11848
|
-
concept,
|
|
11849
|
-
bloomLevel,
|
|
11850
|
-
standardStatements,
|
|
11851
|
-
onProgress
|
|
11852
|
-
});
|
|
11853
|
-
}
|
|
12321
|
+
await judgeSat("ACT", rawAct);
|
|
11854
12322
|
}
|
|
11855
12323
|
const quizRelPath = `_content/${unitCode}/QUIZ_${lessonCode}.md`;
|
|
11856
12324
|
if (artifactScope.includes("QUIZ") && (!await storage.readArtifact(projectId, quizRelPath) || force)) {
|
|
@@ -11884,7 +12352,11 @@ template_required_sections:
|
|
|
11884
12352
|
- ## [REQUIRED] Multiple-Choice Question Bank (\u22655 scenario-based 4-option questions with: Question text, A/B/C/D options, Correct answer, Bloom level, Detailed distractor rationale)
|
|
11885
12353
|
- ## [REQUIRED] Code Analysis / Debugging Question (1 deep code tracing question requiring students to predict output or identify bugs)
|
|
11886
12354
|
- ## [REQUIRED] Competency Rubric (4-tier matrix: Developing \u2192 Proficient \u2192 Advanced \u2192 Exemplary)
|
|
11887
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12355
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12356
|
+
|
|
12357
|
+
${languageDirective}
|
|
12358
|
+
|
|
12359
|
+
${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
|
|
11888
12360
|
const rawQuiz = await runCurriculumAIInference(
|
|
11889
12361
|
[{ role: "user", content: quizPrompt }],
|
|
11890
12362
|
satelliteContext,
|
|
@@ -11910,60 +12382,25 @@ template_required_sections:
|
|
|
11910
12382
|
contentHash: computeContentHash(rawQuiz)
|
|
11911
12383
|
});
|
|
11912
12384
|
producedArtifacts.push(`QUIZ_${lessonCode}.md`);
|
|
11913
|
-
|
|
11914
|
-
await judgeSatelliteArtifact({
|
|
11915
|
-
storage,
|
|
11916
|
-
projectId,
|
|
11917
|
-
lessonCode,
|
|
11918
|
-
sat: "QUIZ",
|
|
11919
|
-
content: rawQuiz,
|
|
11920
|
-
concept,
|
|
11921
|
-
bloomLevel,
|
|
11922
|
-
standardStatements,
|
|
11923
|
-
onProgress
|
|
11924
|
-
});
|
|
11925
|
-
}
|
|
12385
|
+
await judgeSat("QUIZ", rawQuiz);
|
|
11926
12386
|
}
|
|
11927
12387
|
const slideRelPath = `_content/${unitCode}/SLIDE_${lessonCode}.md`;
|
|
11928
12388
|
if (artifactScope.includes("SLIDE") && (!await storage.readArtifact(projectId, slideRelPath) || force)) {
|
|
11929
12389
|
onProgress?.("@illustrator", `[4/4] Authoring Presentation Slide Deck: \`SLIDE_${lessonCode}.md\`...`);
|
|
11930
12390
|
const canonicalSlideTemplate = loadCurriculumTemplate("SLIDE_template.md");
|
|
11931
|
-
const
|
|
11932
|
-
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\`.
|
|
11933
|
-
|
|
11934
|
-
[MARP SLIDE TEMPLATE SCAFFOLD]:
|
|
11935
|
-
${canonicalSlideTemplate || `---
|
|
12391
|
+
const templateScaffold = canonicalSlideTemplate || `---
|
|
11936
12392
|
marp: true
|
|
11937
12393
|
theme: default
|
|
11938
12394
|
paginate: true
|
|
11939
12395
|
header: "${titleHeader(lessonTitle)}"
|
|
11940
12396
|
footer: "Curriculum OS \u2022 ${lessonCode} (${pedagogyLabel})"
|
|
11941
|
-
|
|
11942
|
-
|
|
11943
|
-
|
|
11944
|
-
|
|
11945
|
-
|
|
11946
|
-
|
|
11947
|
-
|
|
11948
|
-
5. **Slide 5 [Core Concept 1: Mental Model]:** Definition, intuitive everyday analogy, and golden rule card
|
|
11949
|
-
6. **Slide 6 [Architecture & Visual Flow]:** Clean Mermaid diagram (flowchart or sequenceDiagram) + 3 flow steps
|
|
11950
|
-
7. **Slide 7 [Core Concept 2: Syntax / Mechanism Anatomy]:** Side-by-side 6-10 lines runnable code + anatomy breakdown & syntax trap card
|
|
11951
|
-
8. **Slide 8 [Guided Practice: Try It Now]:** 3-minute active desk task card with starter hint and success criteria
|
|
11952
|
-
9. **Slide 9 [Integrated Hands-On Lab]:** 3-tier differentiated challenge cards (Bronze / Silver / Gold) + gotcha alert card
|
|
11953
|
-
10. **Slide 10 [Traffic Light Checkpoint & Pitfalls]:** Formative self-check cards (\u{1F7E2}/\u{1F7E1}/\u{1F534}) & diagnostic test question
|
|
11954
|
-
11. **Slide 11 [Exit Ticket & Metacognition]:** 2 scenario-based check questions + 1 metacognitive reflection prompt
|
|
11955
|
-
12. **Slide 12 [Summary & Next Steps]:** 3 core golden rules + preview card of next upcoming milestone
|
|
11956
|
-
|
|
11957
|
-
Mandatory Canvas & Presentation Invariants:
|
|
11958
|
-
- A slide is an INTERACTIVE PROJECTION CANVAS, NOT a textbook! Absolutely NO dense paragraphs or walls of text.
|
|
11959
|
-
- Follow the 6x6 rule: Maximum 4-6 bullet points per slide, maximum 8-12 words per bullet.
|
|
11960
|
-
- 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">\`.
|
|
11961
|
-
- MANDATORY PRESENTER NOTES ON EVERY SLIDE: Every slide MUST end with \`<!-- Presenter Notes: ... -->\` containing:
|
|
11962
|
-
* SCRIPT: 60-90s teacher talk track with intuitive analogies.
|
|
11963
|
-
* COLD CALL / CHECK: Specific diagnostic question to ask students.
|
|
11964
|
-
* SCAFFOLDING / GOTCHA: Guidance for students who get stuck.
|
|
11965
|
-
* PACING: Recommended minutes for the slide.
|
|
11966
|
-
- Output 100% valid Marp Markdown.`;
|
|
12397
|
+
---`;
|
|
12398
|
+
const slidePrompt = buildMarpMarkdownSlidePrompt({
|
|
12399
|
+
lessonCode,
|
|
12400
|
+
templateScaffold,
|
|
12401
|
+
languageDirective,
|
|
12402
|
+
headingDirective: buildHeadingDirective("SLIDE", slcMarkdown, targetLang)
|
|
12403
|
+
});
|
|
11967
12404
|
const rawSlide = await runCurriculumAIInference(
|
|
11968
12405
|
[{ role: "user", content: slidePrompt }],
|
|
11969
12406
|
satelliteContext,
|
|
@@ -11989,19 +12426,7 @@ Mandatory Canvas & Presentation Invariants:
|
|
|
11989
12426
|
contentHash: computeContentHash(rawSlide)
|
|
11990
12427
|
});
|
|
11991
12428
|
producedArtifacts.push(`SLIDE_${lessonCode}.md`);
|
|
11992
|
-
|
|
11993
|
-
await judgeSatelliteArtifact({
|
|
11994
|
-
storage,
|
|
11995
|
-
projectId,
|
|
11996
|
-
lessonCode,
|
|
11997
|
-
sat: "SLIDE",
|
|
11998
|
-
content: rawSlide,
|
|
11999
|
-
concept,
|
|
12000
|
-
bloomLevel,
|
|
12001
|
-
standardStatements,
|
|
12002
|
-
onProgress
|
|
12003
|
-
});
|
|
12004
|
-
}
|
|
12429
|
+
await judgeSat("SLIDE", rawSlide);
|
|
12005
12430
|
}
|
|
12006
12431
|
const guideRelPath = `_content/${unitCode}/GUIDE_${lessonCode}.md`;
|
|
12007
12432
|
if (artifactScope.includes("GUIDE") && (!await storage.readArtifact(projectId, guideRelPath) || force)) {
|
|
@@ -12030,7 +12455,11 @@ template_contract: "artifact-template-v1"
|
|
|
12030
12455
|
- ## [REQUIRED] Facilitation Script & Timeline (Phase-by-phase teacher moves, inquiry questions, transitions)
|
|
12031
12456
|
- ## [REQUIRED] Common Misconceptions & Diagnostic Remediation Matrix
|
|
12032
12457
|
- ## [REQUIRED] Differentiated Support Strategies (Support scaffolds vs Extension challenges)
|
|
12033
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12458
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12459
|
+
|
|
12460
|
+
${languageDirective}
|
|
12461
|
+
|
|
12462
|
+
${buildHeadingDirective("GUIDE", slcMarkdown, targetLang)}`;
|
|
12034
12463
|
const rawGuide = await runCurriculumAIInference(
|
|
12035
12464
|
[{ role: "user", content: guidePrompt }],
|
|
12036
12465
|
satelliteContext,
|
|
@@ -12047,19 +12476,7 @@ template_contract: "artifact-template-v1"
|
|
|
12047
12476
|
contentHash: computeContentHash(rawGuide)
|
|
12048
12477
|
});
|
|
12049
12478
|
producedArtifacts.push(`GUIDE_${lessonCode}.md`);
|
|
12050
|
-
|
|
12051
|
-
await judgeSatelliteArtifact({
|
|
12052
|
-
storage,
|
|
12053
|
-
projectId,
|
|
12054
|
-
lessonCode,
|
|
12055
|
-
sat: "GUIDE",
|
|
12056
|
-
content: rawGuide,
|
|
12057
|
-
concept,
|
|
12058
|
-
bloomLevel,
|
|
12059
|
-
standardStatements,
|
|
12060
|
-
onProgress
|
|
12061
|
-
});
|
|
12062
|
-
}
|
|
12479
|
+
await judgeSat("GUIDE", rawGuide);
|
|
12063
12480
|
}
|
|
12064
12481
|
}
|
|
12065
12482
|
const handoutRelPath = `_content/${unitCode}/HANDOUT_${lessonCode}.md`;
|
|
@@ -12089,7 +12506,11 @@ template_contract: "artifact-template-v1"
|
|
|
12089
12506
|
- ## [REQUIRED] Visual Mental Model / Architecture Diagram (Mermaid or ASCII diagram)
|
|
12090
12507
|
- ## [REQUIRED] Step-by-Step Practical Quick-Start Guide
|
|
12091
12508
|
- ## [REQUIRED] Self-Check Diagnostic Checklist (Can-do statements for student self-assessment)
|
|
12092
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12509
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12510
|
+
|
|
12511
|
+
${languageDirective}
|
|
12512
|
+
|
|
12513
|
+
${buildHeadingDirective("HANDOUT", slcMarkdown, targetLang)}`;
|
|
12093
12514
|
const rawHandout = await runCurriculumAIInference(
|
|
12094
12515
|
[{ role: "user", content: handoutPrompt }],
|
|
12095
12516
|
satelliteContext,
|
|
@@ -12106,19 +12527,7 @@ template_contract: "artifact-template-v1"
|
|
|
12106
12527
|
contentHash: computeContentHash(rawHandout)
|
|
12107
12528
|
});
|
|
12108
12529
|
producedArtifacts.push(`HANDOUT_${lessonCode}.md`);
|
|
12109
|
-
|
|
12110
|
-
await judgeSatelliteArtifact({
|
|
12111
|
-
storage,
|
|
12112
|
-
projectId,
|
|
12113
|
-
lessonCode,
|
|
12114
|
-
sat: "HANDOUT",
|
|
12115
|
-
content: rawHandout,
|
|
12116
|
-
concept,
|
|
12117
|
-
bloomLevel,
|
|
12118
|
-
standardStatements,
|
|
12119
|
-
onProgress
|
|
12120
|
-
});
|
|
12121
|
-
}
|
|
12530
|
+
await judgeSat("HANDOUT", rawHandout);
|
|
12122
12531
|
}
|
|
12123
12532
|
}
|
|
12124
12533
|
const wksRelPath = `_content/${unitCode}/WKS_${lessonCode}.md`;
|
|
@@ -12152,7 +12561,11 @@ template_contract: "artifact-template-v1"
|
|
|
12152
12561
|
- ## [REQUIRED] Part 3: Code Analysis & Bug Hunting Challenge
|
|
12153
12562
|
- ## [REQUIRED] Part 4: Synthesis & Problem-Solving Application
|
|
12154
12563
|
- ## [REQUIRED] Part 5: Self-Reflection & Learning Log
|
|
12155
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12564
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12565
|
+
|
|
12566
|
+
${languageDirective}
|
|
12567
|
+
|
|
12568
|
+
${buildHeadingDirective("WKS", slcMarkdown, targetLang)}`;
|
|
12156
12569
|
const rawWks = await runCurriculumAIInference(
|
|
12157
12570
|
[{ role: "user", content: wksPrompt }],
|
|
12158
12571
|
satelliteContext,
|
|
@@ -12169,19 +12582,7 @@ template_contract: "artifact-template-v1"
|
|
|
12169
12582
|
contentHash: computeContentHash(rawWks)
|
|
12170
12583
|
});
|
|
12171
12584
|
producedArtifacts.push(`WKS_${lessonCode}.md`);
|
|
12172
|
-
|
|
12173
|
-
await judgeSatelliteArtifact({
|
|
12174
|
-
storage,
|
|
12175
|
-
projectId,
|
|
12176
|
-
lessonCode,
|
|
12177
|
-
sat: "WKS",
|
|
12178
|
-
content: rawWks,
|
|
12179
|
-
concept,
|
|
12180
|
-
bloomLevel,
|
|
12181
|
-
standardStatements,
|
|
12182
|
-
onProgress
|
|
12183
|
-
});
|
|
12184
|
-
}
|
|
12585
|
+
await judgeSat("WKS", rawWks);
|
|
12185
12586
|
}
|
|
12186
12587
|
}
|
|
12187
12588
|
const codeRelPath = `_content/${unitCode}/CODE_${lessonCode}.md`;
|
|
@@ -12219,7 +12620,11 @@ template_required_sections:
|
|
|
12219
12620
|
- ## [REQUIRED] Verified Reference Solution Code (100% syntactically valid, production-ready, fully commented)
|
|
12220
12621
|
- ## [REQUIRED] Automated Test / Verification Script (How to compile, flash, or unit test)
|
|
12221
12622
|
- ## [REQUIRED] Common Syntax & Runtime Pitfalls Matrix
|
|
12222
|
-
3. Output 100% clean Markdown directly with runnable code snippets \u2014 NO outer code fences around the document
|
|
12623
|
+
3. Output 100% clean Markdown directly with runnable code snippets \u2014 NO outer code fences around the document.
|
|
12624
|
+
|
|
12625
|
+
${languageDirective}
|
|
12626
|
+
|
|
12627
|
+
${buildHeadingDirective("CODE", slcMarkdown, targetLang)}`;
|
|
12223
12628
|
const rawCode = await runCurriculumAIInference(
|
|
12224
12629
|
[{ role: "user", content: codePrompt }],
|
|
12225
12630
|
satelliteContext,
|
|
@@ -12241,19 +12646,7 @@ template_required_sections:
|
|
|
12241
12646
|
contentHash: computeContentHash(rawCode)
|
|
12242
12647
|
});
|
|
12243
12648
|
producedArtifacts.push(`CODE_${lessonCode}.md`);
|
|
12244
|
-
|
|
12245
|
-
await judgeSatelliteArtifact({
|
|
12246
|
-
storage,
|
|
12247
|
-
projectId,
|
|
12248
|
-
lessonCode,
|
|
12249
|
-
sat: "CODE",
|
|
12250
|
-
content: rawCode,
|
|
12251
|
-
concept,
|
|
12252
|
-
bloomLevel,
|
|
12253
|
-
standardStatements,
|
|
12254
|
-
onProgress
|
|
12255
|
-
});
|
|
12256
|
-
}
|
|
12649
|
+
await judgeSat("CODE", rawCode);
|
|
12257
12650
|
}
|
|
12258
12651
|
}
|
|
12259
12652
|
const extRelPath = `_content/${unitCode}/EXT_${lessonCode}.md`;
|
|
@@ -12285,7 +12678,11 @@ template_contract: "artifact-template-v1"
|
|
|
12285
12678
|
- ### Challenge 2: [Name] (Difficulty: \u2B50\u2B50\u2B50\u2B50) \u2014 Advanced Architectural Constraints & Edge Cases
|
|
12286
12679
|
- ### Challenge 3: [Name] (Difficulty: \u2B50\u2B50\u2B50\u2B50\u2B50) \u2014 Extension Milestones (Level 1: Ninja \u2192 Level 2: Guru \u2192 Level 3: Master)
|
|
12287
12680
|
- ## [REQUIRED] Metacognitive Deep Dive & Engineering Trade-offs
|
|
12288
|
-
3. Output 100% clean Markdown directly \u2014 NO code fences around the document
|
|
12681
|
+
3. Output 100% clean Markdown directly \u2014 NO code fences around the document.
|
|
12682
|
+
|
|
12683
|
+
${languageDirective}
|
|
12684
|
+
|
|
12685
|
+
${buildHeadingDirective("EXT", slcMarkdown, targetLang)}`;
|
|
12289
12686
|
const rawExt = await runCurriculumAIInference(
|
|
12290
12687
|
[{ role: "user", content: extPrompt }],
|
|
12291
12688
|
satelliteContext,
|
|
@@ -12302,19 +12699,7 @@ template_contract: "artifact-template-v1"
|
|
|
12302
12699
|
contentHash: computeContentHash(rawExt)
|
|
12303
12700
|
});
|
|
12304
12701
|
producedArtifacts.push(`EXT_${lessonCode}.md`);
|
|
12305
|
-
|
|
12306
|
-
await judgeSatelliteArtifact({
|
|
12307
|
-
storage,
|
|
12308
|
-
projectId,
|
|
12309
|
-
lessonCode,
|
|
12310
|
-
sat: "EXT",
|
|
12311
|
-
content: rawExt,
|
|
12312
|
-
concept,
|
|
12313
|
-
bloomLevel,
|
|
12314
|
-
standardStatements,
|
|
12315
|
-
onProgress
|
|
12316
|
-
});
|
|
12317
|
-
}
|
|
12702
|
+
await judgeSat("EXT", rawExt);
|
|
12318
12703
|
}
|
|
12319
12704
|
}
|
|
12320
12705
|
onProgress?.("@reviewer", `\u2705 Successfully authored all requested artifacts for \`${lessonCode}\` (${pedagogyLabel})!`);
|
|
@@ -12380,12 +12765,22 @@ async function judgeSatelliteArtifact(ctx) {
|
|
|
12380
12765
|
const { storage, projectId, lessonCode, sat, content } = ctx;
|
|
12381
12766
|
try {
|
|
12382
12767
|
ctx.onProgress?.("@reviewer", `\u{1F916} Judging ${sat}_${lessonCode}...`);
|
|
12768
|
+
const targetObjectives = parseLessonObjectives(
|
|
12769
|
+
ctx.canonicalLessonContent || content,
|
|
12770
|
+
ctx.concept,
|
|
12771
|
+
ctx.bloomLevel
|
|
12772
|
+
);
|
|
12383
12773
|
const result = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12384
12774
|
targetArtifactType: sat,
|
|
12385
12775
|
lessonId: lessonCode,
|
|
12386
|
-
expectedLanguage: "en",
|
|
12387
|
-
targetObjectives
|
|
12388
|
-
generatedContentJson: JSON.stringify({
|
|
12776
|
+
expectedLanguage: ctx.targetLang || "en",
|
|
12777
|
+
targetObjectives,
|
|
12778
|
+
generatedContentJson: JSON.stringify({
|
|
12779
|
+
content,
|
|
12780
|
+
artifactType: sat,
|
|
12781
|
+
lessonId: lessonCode,
|
|
12782
|
+
canonicalLessonExcerpt: ctx.canonicalLessonExcerpt
|
|
12783
|
+
}),
|
|
12389
12784
|
standardStatements: Object.keys(ctx.standardStatements).length > 0 ? ctx.standardStatements : void 0
|
|
12390
12785
|
});
|
|
12391
12786
|
const passed = result.passed && result.score >= 85;
|
|
@@ -12508,6 +12903,87 @@ async function produceBatchLessons(storage, projectId, lessonIds, options = {})
|
|
|
12508
12903
|
// src/services/singleArtifactService.ts
|
|
12509
12904
|
init_streamRunner();
|
|
12510
12905
|
init_errors();
|
|
12906
|
+
|
|
12907
|
+
// src/services/contextRouting.ts
|
|
12908
|
+
init_errors();
|
|
12909
|
+
var ARTIFACT_DEPENDENCY_ROUTING = {
|
|
12910
|
+
LESSON: {
|
|
12911
|
+
required: ["KNOWLEDGE_EXPOSITION", "SESSION_SLICE", "FRAMEWORK_EXCERPT"],
|
|
12912
|
+
optional: ["STYLE_GUIDE", "REFERENCE_PACK"],
|
|
12913
|
+
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"
|
|
12914
|
+
},
|
|
12915
|
+
HANDOUT: {
|
|
12916
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12917
|
+
optional: ["SESSION_SLICE"],
|
|
12918
|
+
rationale: "T\xE0i li\u1EC7u t\u1EF1 h\u1ECDc \u2014 b\xE1m kh\xE1i ni\u1EC7m chu\u1EA9n, kh\xF4ng c\u1EA7n activity timeline"
|
|
12919
|
+
},
|
|
12920
|
+
EXT: {
|
|
12921
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12922
|
+
optional: ["SESSION_SLICE"],
|
|
12923
|
+
rationale: "Th\u1EED th\xE1ch m\u1EDF r\u1ED9ng chuy\xEAn s\xE2u b\xE1m kh\xE1i ni\u1EC7m"
|
|
12924
|
+
},
|
|
12925
|
+
CODE: {
|
|
12926
|
+
required: ["KNOWLEDGE_EXPOSITION"],
|
|
12927
|
+
optional: ["LESSON_OBJECTIVES"],
|
|
12928
|
+
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"
|
|
12929
|
+
},
|
|
12930
|
+
ACT: {
|
|
12931
|
+
required: ["CANONICAL_LESSON"],
|
|
12932
|
+
optional: ["KNOWLEDGE_EXPOSITION", "SESSION_SLICE"],
|
|
12933
|
+
rationale: "STEM Activity Lab b\u1EAFt bu\u1ED9c ph\u1EA3i kh\u1EDBp 100% Activity Sequence v\xE0 Lesson Flow c\u1EE7a LESSON"
|
|
12934
|
+
},
|
|
12935
|
+
WKS: {
|
|
12936
|
+
required: ["CANONICAL_LESSON"],
|
|
12937
|
+
optional: ["KNOWLEDGE_EXPOSITION"],
|
|
12938
|
+
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"
|
|
12939
|
+
},
|
|
12940
|
+
GUIDE: {
|
|
12941
|
+
required: ["CANONICAL_LESSON"],
|
|
12942
|
+
optional: ["SESSION_SLICE"],
|
|
12943
|
+
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"
|
|
12944
|
+
},
|
|
12945
|
+
SLIDE: {
|
|
12946
|
+
required: ["CANONICAL_LESSON"],
|
|
12947
|
+
optional: ["KNOWLEDGE_EXPOSITION"],
|
|
12948
|
+
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"
|
|
12949
|
+
},
|
|
12950
|
+
QUIZ: {
|
|
12951
|
+
required: ["KNOWLEDGE_EXPOSITION", "CANONICAL_LESSON"],
|
|
12952
|
+
optional: ["SESSION_SLICE"],
|
|
12953
|
+
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)"
|
|
12954
|
+
}
|
|
12955
|
+
};
|
|
12956
|
+
function validateArtifactDependencies(artifactType, availableSources, opts = {}) {
|
|
12957
|
+
const normType = (artifactType || "").toUpperCase().trim();
|
|
12958
|
+
const rule = ARTIFACT_DEPENDENCY_ROUTING[normType];
|
|
12959
|
+
const failClosed = opts.failClosed ?? true;
|
|
12960
|
+
if (!rule) {
|
|
12961
|
+
return { valid: true, missing: [] };
|
|
12962
|
+
}
|
|
12963
|
+
const missing = [];
|
|
12964
|
+
for (const req of rule.required) {
|
|
12965
|
+
const val = availableSources[req];
|
|
12966
|
+
const isPresent = val !== void 0 && val !== null && (typeof val === "string" ? val.trim().length > 0 : true);
|
|
12967
|
+
if (!isPresent) {
|
|
12968
|
+
missing.push(req);
|
|
12969
|
+
}
|
|
12970
|
+
}
|
|
12971
|
+
if (missing.length > 0) {
|
|
12972
|
+
const err = createContextMissingError({
|
|
12973
|
+
artifactType: normType,
|
|
12974
|
+
missingSource: missing[0],
|
|
12975
|
+
lessonId: opts.lessonId,
|
|
12976
|
+
agent: opts.agent
|
|
12977
|
+
});
|
|
12978
|
+
if (failClosed) {
|
|
12979
|
+
throw err;
|
|
12980
|
+
}
|
|
12981
|
+
return { valid: false, missing, error: err };
|
|
12982
|
+
}
|
|
12983
|
+
return { valid: true, missing: [] };
|
|
12984
|
+
}
|
|
12985
|
+
|
|
12986
|
+
// src/services/singleArtifactService.ts
|
|
12511
12987
|
function getArtifactMetadata(type, lessonId, pedagogy) {
|
|
12512
12988
|
const id = lessonId || "ON_DEMAND";
|
|
12513
12989
|
switch (type) {
|
|
@@ -12587,9 +13063,24 @@ async function generateSingleArtifact(req) {
|
|
|
12587
13063
|
const templateContent = loadedTemplate || getDefaultFallbackTemplate(artifactType, displayTitle, lessonId || "ON_DEMAND");
|
|
12588
13064
|
const hwStr = hardwarePlatform.join(", ");
|
|
12589
13065
|
const selectedDevices = (config?.devices || (hardwarePlatform[0]?.toLowerCase().includes("paper") ? "paper-only" : "laptop")).toLowerCase();
|
|
12590
|
-
|
|
12591
|
-
const
|
|
12592
|
-
const
|
|
13066
|
+
language.toLowerCase().includes("bilingual") || language.toLowerCase().includes("song");
|
|
13067
|
+
const targetLang = resolveTargetLanguageCode(language);
|
|
13068
|
+
const langDirective = buildLanguageDirective(language);
|
|
13069
|
+
const headingDirective = buildHeadingDirective(
|
|
13070
|
+
artifactType.toUpperCase(),
|
|
13071
|
+
req.sectionLanguageContract,
|
|
13072
|
+
targetLang
|
|
13073
|
+
);
|
|
13074
|
+
const availableSources = {
|
|
13075
|
+
KNOWLEDGE_EXPOSITION: contextSot.exposition || researchContext,
|
|
13076
|
+
CANONICAL_LESSON: contextSot.lessonPlan,
|
|
13077
|
+
FRAMEWORK_EXCERPT: contextSot.framework
|
|
13078
|
+
};
|
|
13079
|
+
validateArtifactDependencies(artifactType.toUpperCase(), availableSources, {
|
|
13080
|
+
lessonId,
|
|
13081
|
+
agent: meta.persona,
|
|
13082
|
+
failClosed: req.failClosedContext ?? false
|
|
13083
|
+
});
|
|
12593
13084
|
const isPaperOnly = selectedDevices === "paper-only" || hwStr.toLowerCase().includes("paper") || hwStr.toLowerCase().includes("print-ready");
|
|
12594
13085
|
const deviceRule = isPaperOnly ? `
|
|
12595
13086
|
- \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" ? `
|
|
@@ -12610,7 +13101,8 @@ async function generateSingleArtifact(req) {
|
|
|
12610
13101
|
Your task is to author a canonical, publication-grade learning artifact of type "${artifactType.toUpperCase()}".
|
|
12611
13102
|
|
|
12612
13103
|
### CORE OPERATIONAL INVARIANTS:
|
|
12613
|
-
${
|
|
13104
|
+
${langDirective}
|
|
13105
|
+
${headingDirective}
|
|
12614
13106
|
2. NON-MOCK CODE INVARIANT: Any code snippet provided MUST be 100% syntactically valid, idiomatic, and executable without placeholders or fake functions.
|
|
12615
13107
|
3. PEDAGOGICAL GROUNDING: Strictly align with the ${pedagogy.toUpperCase()} model, Bloom's Revised Taxonomy, and IEEE/ACM CS2023 guidelines.
|
|
12616
13108
|
4. SCAFFOLDING LEVEL: "${scaffoldingLevel.toUpperCase()}".${scaffoldingRule}
|
|
@@ -12619,6 +13111,11 @@ ${langRule}
|
|
|
12619
13111
|
|
|
12620
13112
|
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).
|
|
12621
13113
|
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.` : ""}`;
|
|
13114
|
+
const slcContract = req.sectionLanguageContract;
|
|
13115
|
+
const frameworkExcerpt = contextSot.framework ? buildSectionAwareExcerpt(contextSot.framework, { budget: 2500, sectionLanguageContract: slcContract }).excerpt : "";
|
|
13116
|
+
const lessonPlanExcerpt = contextSot.lessonPlan ? buildLessonExcerpt(contextSot.lessonPlan, { budget: 8e3, sectionLanguageContract: slcContract, artifactType: "LESSON" }).excerpt : "";
|
|
13117
|
+
const handoutExcerpt = contextSot.handout ? buildSectionAwareExcerpt(contextSot.handout, { budget: 2e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
13118
|
+
const expositionExcerpt = contextSot.exposition ? buildExpositionExcerpt(contextSot.exposition, { budget: 6e3, sectionLanguageContract: slcContract }).excerpt : "";
|
|
12622
13119
|
const userPrompt = `### CONTEXT GROUND TRUTH:
|
|
12623
13120
|
- Topic / Concept Domain: "${topic}"
|
|
12624
13121
|
- Lesson ID: "${lessonId || "ON_DEMAND"}"
|
|
@@ -12636,14 +13133,17 @@ ${selectedDevices ? `- Device Mode: "${selectedDevices}"
|
|
|
12636
13133
|
${researchContext ? `### RESEARCH GROUND TRUTH (fact-checked context \u2014 \u01B0u ti\xEAn d\xF9ng, KH\xD4NG b\u1ECBa s\u1ED1 li\u1EC7u):
|
|
12637
13134
|
${researchContext.slice(0, 4e3)}
|
|
12638
13135
|
` : ""}
|
|
12639
|
-
${
|
|
12640
|
-
${
|
|
13136
|
+
${expositionExcerpt ? `### SOT KNOWLEDGE EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict):
|
|
13137
|
+
${expositionExcerpt}
|
|
13138
|
+
` : ""}
|
|
13139
|
+
${frameworkExcerpt ? `### SOT CURRICULUM FRAMEWORK:
|
|
13140
|
+
${frameworkExcerpt}
|
|
12641
13141
|
` : ""}
|
|
12642
|
-
${
|
|
12643
|
-
${
|
|
13142
|
+
${lessonPlanExcerpt ? `### SOT CANONICAL LESSON PLAN:
|
|
13143
|
+
${lessonPlanExcerpt}
|
|
12644
13144
|
` : ""}
|
|
12645
|
-
${
|
|
12646
|
-
${
|
|
13145
|
+
${handoutExcerpt ? `### SOT STUDENT HANDOUT:
|
|
13146
|
+
${handoutExcerpt}
|
|
12647
13147
|
` : ""}
|
|
12648
13148
|
|
|
12649
13149
|
### MANDATORY CANONICAL TEMPLATE CONTRACT:
|
|
@@ -12732,9 +13232,16 @@ ${yaml.trim()}
|
|
|
12732
13232
|
const verdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12733
13233
|
targetArtifactType: artifactType.toUpperCase(),
|
|
12734
13234
|
lessonId: lessonId || "ON_DEMAND",
|
|
12735
|
-
expectedLanguage:
|
|
13235
|
+
expectedLanguage: targetLang || "en",
|
|
12736
13236
|
targetObjectives: judgeObjectives,
|
|
12737
|
-
generatedContentJson: JSON.stringify({
|
|
13237
|
+
generatedContentJson: JSON.stringify({
|
|
13238
|
+
content: finalContent,
|
|
13239
|
+
artifactType,
|
|
13240
|
+
lessonId: lessonId || "ON_DEMAND",
|
|
13241
|
+
title: displayTitle,
|
|
13242
|
+
canonicalLessonExcerpt: lessonPlanExcerpt || void 0,
|
|
13243
|
+
canonicalExposition: expositionExcerpt || void 0
|
|
13244
|
+
})
|
|
12738
13245
|
});
|
|
12739
13246
|
const passed = Boolean(verdict.passed) && verdict.score >= 85;
|
|
12740
13247
|
if (passed) {
|
|
@@ -12776,9 +13283,16 @@ ${finalContent}` }
|
|
|
12776
13283
|
const reVerdict = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12777
13284
|
targetArtifactType: artifactType.toUpperCase(),
|
|
12778
13285
|
lessonId: lessonId || "ON_DEMAND",
|
|
12779
|
-
expectedLanguage:
|
|
13286
|
+
expectedLanguage: targetLang || "en",
|
|
12780
13287
|
targetObjectives: judgeObjectives,
|
|
12781
|
-
generatedContentJson: JSON.stringify({
|
|
13288
|
+
generatedContentJson: JSON.stringify({
|
|
13289
|
+
content: repaired,
|
|
13290
|
+
artifactType,
|
|
13291
|
+
lessonId: lessonId || "ON_DEMAND",
|
|
13292
|
+
title: displayTitle,
|
|
13293
|
+
canonicalLessonExcerpt: lessonPlanExcerpt || void 0,
|
|
13294
|
+
canonicalExposition: expositionExcerpt || void 0
|
|
13295
|
+
})
|
|
12782
13296
|
});
|
|
12783
13297
|
if (reVerdict.passed && reVerdict.score >= 85) {
|
|
12784
13298
|
return {
|
|
@@ -16730,6 +17244,7 @@ function renderMediaPlaceholder(entry) {
|
|
|
16730
17244
|
}
|
|
16731
17245
|
|
|
16732
17246
|
exports.ACT_TEMPLATE = ACT_TEMPLATE;
|
|
17247
|
+
exports.ARTIFACT_DEPENDENCY_ROUTING = ARTIFACT_DEPENDENCY_ROUTING;
|
|
16733
17248
|
exports.ARTIFACT_EXECUTION_ORDER = ARTIFACT_EXECUTION_ORDER;
|
|
16734
17249
|
exports.AcademicAuditor = AcademicAuditor;
|
|
16735
17250
|
exports.ActiveLearningWorkflowSchema = ActiveLearningWorkflowSchema;
|
|
@@ -16774,6 +17289,8 @@ exports.CurriculumPlanSchema = CurriculumPlanSchema;
|
|
|
16774
17289
|
exports.CurriculumQualityReportSchema = CurriculumQualityReportSchema;
|
|
16775
17290
|
exports.DEFAULT_ENABLED_PROVIDERS = DEFAULT_ENABLED_PROVIDERS;
|
|
16776
17291
|
exports.DEFAULT_GATE_SETTINGS = DEFAULT_GATE_SETTINGS;
|
|
17292
|
+
exports.DEFAULT_KX_PRIORITIES = DEFAULT_KX_PRIORITIES;
|
|
17293
|
+
exports.DEFAULT_LESSON_PRIORITIES = DEFAULT_LESSON_PRIORITIES;
|
|
16777
17294
|
exports.DEFAULT_STREAM_IDLE_MS = DEFAULT_STREAM_IDLE_MS;
|
|
16778
17295
|
exports.DEFAULT_STREAM_TOTAL_MS = DEFAULT_STREAM_TOTAL_MS;
|
|
16779
17296
|
exports.DependencyEdgeSchema = DependencyEdgeSchema;
|
|
@@ -16873,6 +17390,7 @@ exports.RubricCriteriaSchema = RubricCriteriaSchema;
|
|
|
16873
17390
|
exports.RubricSchema = RubricSchema;
|
|
16874
17391
|
exports.SCIENCE_LAB_TEMPLATE = SCIENCE_LAB_TEMPLATE;
|
|
16875
17392
|
exports.SELF_LAB_TEMPLATE = SELF_LAB_TEMPLATE;
|
|
17393
|
+
exports.SLIDE_CANONICAL_METHODOLOGY = SLIDE_CANONICAL_METHODOLOGY;
|
|
16876
17394
|
exports.SLIDE_LAYOUT_PRESETS = SLIDE_LAYOUT_PRESETS;
|
|
16877
17395
|
exports.SLIDE_TEMPLATE = SLIDE_TEMPLATE;
|
|
16878
17396
|
exports.STANDARD_SOT_FILES = STANDARD_SOT_FILES;
|
|
@@ -16927,12 +17445,18 @@ exports.buildCurriculumPlan = buildCurriculumPlan;
|
|
|
16927
17445
|
exports.buildDeliveryPackages = buildDeliveryPackages;
|
|
16928
17446
|
exports.buildDiagnosticQuizPrompt = buildDiagnosticQuizPrompt;
|
|
16929
17447
|
exports.buildExpositionContext = buildExpositionContext;
|
|
17448
|
+
exports.buildExpositionExcerpt = buildExpositionExcerpt;
|
|
16930
17449
|
exports.buildExtensionPrompt = buildExtensionPrompt;
|
|
16931
17450
|
exports.buildHandoutPrompt = buildHandoutPrompt;
|
|
17451
|
+
exports.buildHeadingDirective = buildHeadingDirective;
|
|
16932
17452
|
exports.buildImagePrompt = buildImagePrompt;
|
|
16933
17453
|
exports.buildJudgePrompt = buildJudgePrompt;
|
|
17454
|
+
exports.buildLanguageDirective = buildLanguageDirective;
|
|
17455
|
+
exports.buildLessonExcerpt = buildLessonExcerpt;
|
|
16934
17456
|
exports.buildLessonMasterPrompt = buildLessonMasterPrompt;
|
|
17457
|
+
exports.buildMarpMarkdownSlidePrompt = buildMarpMarkdownSlidePrompt;
|
|
16935
17458
|
exports.buildProjectInstructionPrompt = buildProjectInstructionPrompt;
|
|
17459
|
+
exports.buildSectionAwareExcerpt = buildSectionAwareExcerpt;
|
|
16936
17460
|
exports.buildSelfLabPrompt = buildSelfLabPrompt;
|
|
16937
17461
|
exports.buildSessionSliceContext = buildSessionSliceContext;
|
|
16938
17462
|
exports.buildSlidesPrompt = buildSlidesPrompt;
|
|
@@ -16948,6 +17472,7 @@ exports.conductPreliminaryResearch = conductPreliminaryResearch;
|
|
|
16948
17472
|
exports.contentTools = contentTools;
|
|
16949
17473
|
exports.convertRoadmapToFoundationSot = convertRoadmapToFoundationSot;
|
|
16950
17474
|
exports.createAiInferenceError = createAiInferenceError;
|
|
17475
|
+
exports.createContextMissingError = createContextMissingError;
|
|
16951
17476
|
exports.createCurriculumStorage = createCurriculumStorage;
|
|
16952
17477
|
exports.createIdleAbortController = createIdleAbortController;
|
|
16953
17478
|
exports.createStreamAbortController = createStreamAbortController;
|
|
@@ -16963,6 +17488,7 @@ exports.executeCurriculumCommand = executeCurriculumCommand;
|
|
|
16963
17488
|
exports.exportAllProjectQuizzes = exportAllProjectQuizzes;
|
|
16964
17489
|
exports.expositionCacheKey = expositionCacheKey;
|
|
16965
17490
|
exports.extractScopeSequenceRows = extractScopeSequenceRows;
|
|
17491
|
+
exports.extractSectionHeadingsFromSLC = extractSectionHeadingsFromSLC;
|
|
16966
17492
|
exports.extractSessionSlice = extractSessionSlice;
|
|
16967
17493
|
exports.extractStreamChunk = extractStreamChunk;
|
|
16968
17494
|
exports.extractThoughtAndContent = extractThoughtAndContent;
|
|
@@ -17014,6 +17540,7 @@ exports.lintFrameworkPack = lintFrameworkPack;
|
|
|
17014
17540
|
exports.loadCurriculumTemplate = loadCurriculumTemplate;
|
|
17015
17541
|
exports.loadSotTemplate = loadSotTemplate;
|
|
17016
17542
|
exports.normalizePlanningGraph = normalizePlanningGraph;
|
|
17543
|
+
exports.normalizeSlcContract = normalizeSlcContract;
|
|
17017
17544
|
exports.packagerTools = packagerTools;
|
|
17018
17545
|
exports.parseGateSettings = parseGateSettings;
|
|
17019
17546
|
exports.parseQuizMarkdown = parseQuizMarkdown;
|
|
@@ -17029,6 +17556,7 @@ exports.researcherTools = researcherTools;
|
|
|
17029
17556
|
exports.resolveGateSettings = resolveGateSettings;
|
|
17030
17557
|
exports.resolveStandardsPacks = resolveStandardsPacks;
|
|
17031
17558
|
exports.resolveStreamBudget = resolveStreamBudget;
|
|
17559
|
+
exports.resolveTargetLanguageCode = resolveTargetLanguageCode;
|
|
17032
17560
|
exports.resolveTranslationTargets = resolveTranslationTargets;
|
|
17033
17561
|
exports.reviewerTools = reviewerTools;
|
|
17034
17562
|
exports.runCurriculumAIInference = runCurriculumAIInference;
|
|
@@ -17052,9 +17580,11 @@ exports.streamLayerPrefillWithFallback = streamLayerPrefillWithFallback;
|
|
|
17052
17580
|
exports.streamLessonMasterFlow = streamLessonMasterFlow;
|
|
17053
17581
|
exports.streamSelfLabFlow = streamSelfLabFlow;
|
|
17054
17582
|
exports.stripLlmJsonWrappers = stripLlmJsonWrappers;
|
|
17583
|
+
exports.targetLanguageDisplayName = targetLanguageDisplayName;
|
|
17055
17584
|
exports.techSmeTools = techSmeTools;
|
|
17056
17585
|
exports.topoSort = topoSort;
|
|
17057
17586
|
exports.uploadAssetToBucket = uploadAssetToBucket;
|
|
17587
|
+
exports.validateArtifactDependencies = validateArtifactDependencies;
|
|
17058
17588
|
exports.validateCurriculumPlan = validateCurriculumPlan;
|
|
17059
17589
|
exports.validateFrameworkPack = validateFrameworkPack;
|
|
17060
17590
|
exports.validateMarkdownTables = validateMarkdownTables;
|