@thanh01.pmt/curriculum-kit 1.4.21 → 1.4.22
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/index.cjs +78 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +78 -9
- package/dist/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +15 -0
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.mjs +15 -0
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -655,6 +655,9 @@ interface GenerateExpositionOptions {
|
|
|
655
655
|
slcMarkdown?: Record<string, Record<string, string>> | string | null;
|
|
656
656
|
techStack?: string;
|
|
657
657
|
hardwarePlatform?: string;
|
|
658
|
+
/** REFERENCE_PACK.md raw content — technical ground truth (versions, APIs).
|
|
659
|
+
* 5-Whys RC-vacuum: without it the KX model regresses to pretrained facts. */
|
|
660
|
+
refPack?: string;
|
|
658
661
|
}
|
|
659
662
|
interface ExpositionResult {
|
|
660
663
|
relPath: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -655,6 +655,9 @@ interface GenerateExpositionOptions {
|
|
|
655
655
|
slcMarkdown?: Record<string, Record<string, string>> | string | null;
|
|
656
656
|
techStack?: string;
|
|
657
657
|
hardwarePlatform?: string;
|
|
658
|
+
/** REFERENCE_PACK.md raw content — technical ground truth (versions, APIs).
|
|
659
|
+
* 5-Whys RC-vacuum: without it the KX model regresses to pretrained facts. */
|
|
660
|
+
refPack?: string;
|
|
658
661
|
}
|
|
659
662
|
interface ExpositionResult {
|
|
660
663
|
relPath: string;
|
package/dist/index.mjs
CHANGED
|
@@ -11507,6 +11507,21 @@ function normalizeHeading(str) {
|
|
|
11507
11507
|
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
11508
11508
|
}
|
|
11509
11509
|
function findCanonicalFuzzy(norm) {
|
|
11510
|
+
if (norm.includes("toolchain") || norm.includes("moi truong phat trien") || norm.includes("cong cu") || norm.includes("version") || norm.includes("phan mem") || norm.includes("development environment") || norm.includes("technical overview") || norm.includes("kien truc")) {
|
|
11511
|
+
return "Technical Overview & Architecture Blueprint";
|
|
11512
|
+
}
|
|
11513
|
+
if (norm.includes("pinout") || norm.includes("phan cung") || norm.includes("hardware") || norm.includes("wiring") || norm.includes("ket noi")) {
|
|
11514
|
+
return "Hardware Pinout & Wiring Configuration Matrix";
|
|
11515
|
+
}
|
|
11516
|
+
if (norm.includes("pedagog") || norm.includes("phuong phap") || norm.includes("day hoc") || norm.includes("su pham")) {
|
|
11517
|
+
return "Core Pedagogical Concept Anchor & Real-World Domain Bridge";
|
|
11518
|
+
}
|
|
11519
|
+
if (norm.includes("standard") || norm.includes("tieu chuan") || norm.includes("csta") || norm.includes("cs2023") || norm.includes("chuan academic")) {
|
|
11520
|
+
return "Standards Alignment";
|
|
11521
|
+
}
|
|
11522
|
+
if (norm.includes("roadmap") || norm.includes("lo trinh") || norm.includes("milestone") || norm.includes("giai doan")) {
|
|
11523
|
+
return void 0;
|
|
11524
|
+
}
|
|
11510
11525
|
if (norm.includes("symbol") || norm.includes("identifier ledger") || norm.includes("dinh danh")) {
|
|
11511
11526
|
return "Symbol & Identifier Ledger";
|
|
11512
11527
|
}
|
|
@@ -11643,7 +11658,7 @@ function buildSystemPrompt(targetLanguage = "vi", techStack, hardwarePlatform) {
|
|
|
11643
11658
|
langDirective
|
|
11644
11659
|
].join("\n");
|
|
11645
11660
|
}
|
|
11646
|
-
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMarkdown) {
|
|
11661
|
+
function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMarkdown, refPack) {
|
|
11647
11662
|
const depthLines = session.depth_assignments.map((d) => "- " + d.node_id + " [" + d.depth.toUpperCase() + "]: " + DEPTH_RULES[d.depth]).join("\n");
|
|
11648
11663
|
const termLines = glossary.map((g) => "- " + g.term + (g.definition ? " \u2014 " + g.definition : "") + (g.example ? " (example: " + g.example + ")" : "")).join("\n");
|
|
11649
11664
|
const langCode = resolveTargetLanguageCode(targetLanguage);
|
|
@@ -11656,6 +11671,28 @@ function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMark
|
|
|
11656
11671
|
const hQuestions = headings["Self-Check Questions"] || (langCode === "vi" ? "C\xE2u h\u1ECFi T\u1EF1 ki\u1EC3m tra" : "Self-Check Questions");
|
|
11657
11672
|
const skeleton = `## ${hScope} / ## ${hTerms} / ## ${hNarratives} / ## ${hExamples} / ## ${hMistakes} / ## ${hQuestions}`;
|
|
11658
11673
|
const headingDirective = buildHeadingDirective("KNOWLEDGE_EXPOSITION", slcMarkdown, targetLanguage);
|
|
11674
|
+
let refPackBlock = "";
|
|
11675
|
+
if (refPack && refPack.trim()) {
|
|
11676
|
+
const refExcerpt = buildSectionAwareExcerpt(refPack, {
|
|
11677
|
+
priorities: [
|
|
11678
|
+
"Technical Overview & Architecture Blueprint",
|
|
11679
|
+
"Hardware Pinout & Wiring Configuration Matrix",
|
|
11680
|
+
"Standards Alignment"
|
|
11681
|
+
],
|
|
11682
|
+
budget: 2500
|
|
11683
|
+
}).excerpt;
|
|
11684
|
+
if (refExcerpt) {
|
|
11685
|
+
refPackBlock = [
|
|
11686
|
+
"",
|
|
11687
|
+
"[GROUND TRUTH \u2014 BINDING, from REFERENCE_PACK.md]:",
|
|
11688
|
+
"Tool versions, APIs, and platform facts below are CANONICAL. Do NOT",
|
|
11689
|
+
"contradict them; do NOT substitute versions from memory. If a fact you",
|
|
11690
|
+
"need is not stated here, stay generic rather than inventing specifics.",
|
|
11691
|
+
"",
|
|
11692
|
+
refExcerpt
|
|
11693
|
+
].join("\n");
|
|
11694
|
+
}
|
|
11695
|
+
}
|
|
11659
11696
|
return [
|
|
11660
11697
|
"Session: " + session.id + " \u2014 " + session.title,
|
|
11661
11698
|
"Objective: " + session.prose_objective,
|
|
@@ -11668,6 +11705,7 @@ function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMark
|
|
|
11668
11705
|
"",
|
|
11669
11706
|
"Glossary terms (definitions are canonical):",
|
|
11670
11707
|
termLines || "(none provided \u2014 write definitions and mark them for glossary sync)",
|
|
11708
|
+
refPackBlock,
|
|
11671
11709
|
"",
|
|
11672
11710
|
"Section skeleton to fill (replace ONLY the {{placeholders}}):",
|
|
11673
11711
|
skeleton,
|
|
@@ -11676,7 +11714,7 @@ function buildUserPrompt(session, plan, glossary, targetLanguage = "vi", slcMark
|
|
|
11676
11714
|
].filter(Boolean).join("\n");
|
|
11677
11715
|
}
|
|
11678
11716
|
async function ensureKnowledgeExposition(options) {
|
|
11679
|
-
const { projectId, lessonCode, plan, glossary, llmFn, storage, techStack, hardwarePlatform } = options;
|
|
11717
|
+
const { projectId, lessonCode, plan, glossary, llmFn, storage, techStack, hardwarePlatform, refPack } = options;
|
|
11680
11718
|
const session = plan.sessions.find((s) => s.id === lessonCode);
|
|
11681
11719
|
if (!session) throw new Error("Session " + lessonCode + " not found in plan " + plan.plan_id);
|
|
11682
11720
|
const existing = await storage.readArtifact(projectId, EXPOSITION_REL(lessonCode));
|
|
@@ -11690,9 +11728,11 @@ async function ensureKnowledgeExposition(options) {
|
|
|
11690
11728
|
throw new ExpositionApprovalError("Approval hash " + plan.approval.plan_hash + " does not match current plan hash " + plan.plan_hash + " \u2014 re-approve after plan changes");
|
|
11691
11729
|
}
|
|
11692
11730
|
const targetLanguage = options.targetLanguage || plan.translation?.target_language || "vi";
|
|
11731
|
+
const originalSystemPrompt = buildSystemPrompt(targetLanguage, techStack, hardwarePlatform);
|
|
11732
|
+
const originalUserPrompt = buildUserPrompt(session, plan, glossary, targetLanguage, options.slcMarkdown, refPack);
|
|
11693
11733
|
const content = (await llmFn(
|
|
11694
|
-
|
|
11695
|
-
|
|
11734
|
+
originalSystemPrompt,
|
|
11735
|
+
originalUserPrompt
|
|
11696
11736
|
)).trim();
|
|
11697
11737
|
if (content.length < 200) {
|
|
11698
11738
|
throw new Error("EXPOSITION too short for " + lessonCode + " (" + content.length + " chars) \u2014 refusing to save");
|
|
@@ -11725,8 +11765,16 @@ async function ensureKnowledgeExposition(options) {
|
|
|
11725
11765
|
};
|
|
11726
11766
|
let verdict = await judgeOnce(finalContent);
|
|
11727
11767
|
if (verdict.verdict !== "APPROVED") {
|
|
11728
|
-
const repairPrompt =
|
|
11729
|
-
|
|
11768
|
+
const repairPrompt = [
|
|
11769
|
+
originalUserPrompt,
|
|
11770
|
+
"",
|
|
11771
|
+
"--- YOUR PREVIOUS DRAFT (REJECTED, fix ALL issues below) ---",
|
|
11772
|
+
finalContent,
|
|
11773
|
+
"",
|
|
11774
|
+
"--- JUDGE CRITIQUE (fix ALL issues, output the COMPLETE corrected document) ---",
|
|
11775
|
+
verdict.critique
|
|
11776
|
+
].join("\n");
|
|
11777
|
+
finalContent = (await llmFn(originalSystemPrompt, repairPrompt)).trim();
|
|
11730
11778
|
verdict = await judgeOnce(finalContent);
|
|
11731
11779
|
}
|
|
11732
11780
|
if (verdict.verdict !== "APPROVED") {
|
|
@@ -11767,12 +11815,27 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
11767
11815
|
try {
|
|
11768
11816
|
const lpRaw = await storage.readSotDocument(projectId, "LEARNER_PROFILE.md");
|
|
11769
11817
|
if (lpRaw) {
|
|
11770
|
-
const
|
|
11771
|
-
|
|
11818
|
+
const hwPatterns = [
|
|
11819
|
+
/(?:Student Equipment|Hardware|Platform|Thiết bị|Thiết bị học tập)\s*(?:\(|:|\*)*\s*([^\n\r]+?)(?:\s*\*\*|[.).]?\s*$)/i,
|
|
11820
|
+
/(?:máy|device|machine)\s+([^,.;\n]{4,60}(?:M\d|Intel|PC|computer|mini)[^,.;\n]{0,30})/i
|
|
11821
|
+
];
|
|
11822
|
+
for (const p of hwPatterns) {
|
|
11823
|
+
const m = lpRaw.match(p);
|
|
11824
|
+
if (m && !hw) {
|
|
11825
|
+
hw = m[1].trim();
|
|
11826
|
+
break;
|
|
11827
|
+
}
|
|
11828
|
+
}
|
|
11772
11829
|
}
|
|
11773
11830
|
} catch {
|
|
11774
11831
|
}
|
|
11775
11832
|
}
|
|
11833
|
+
let refPackContent;
|
|
11834
|
+
try {
|
|
11835
|
+
refPackContent = await storage.readSotDocument(projectId, "REFERENCE_PACK.md") || void 0;
|
|
11836
|
+
} catch {
|
|
11837
|
+
refPackContent = void 0;
|
|
11838
|
+
}
|
|
11776
11839
|
const { runCurriculumAIInference: runCurriculumAIInference2 } = await Promise.resolve().then(() => (init_streamRunner(), streamRunner_exports));
|
|
11777
11840
|
const targetLang = options.targetLanguage || plan.translation?.target_language || "vi";
|
|
11778
11841
|
const result = await ensureKnowledgeExposition({
|
|
@@ -11784,6 +11847,7 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
11784
11847
|
slcMarkdown: options.slcMarkdown,
|
|
11785
11848
|
techStack: tech,
|
|
11786
11849
|
hardwarePlatform: hw,
|
|
11850
|
+
refPack: refPackContent,
|
|
11787
11851
|
llmFn: async (systemPrompt, userPrompt) => {
|
|
11788
11852
|
const runnerOpts = options.customInference ? { customInference: options.customInference } : {};
|
|
11789
11853
|
const out = await runCurriculumAIInference2(
|
|
@@ -26082,11 +26146,16 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
26082
26146
|
}).excerpt : "";
|
|
26083
26147
|
let effectiveRefPack = refPack ? buildSectionAwareExcerpt(refPack, {
|
|
26084
26148
|
priorities: [
|
|
26149
|
+
// Toolchain/version matrix FIRST — the most-frequently-hallucinated
|
|
26150
|
+
// facts are tool versions ("Xcode 15" vs ground truth "Xcode 16").
|
|
26151
|
+
// The bilingual fuzzy matcher in contextBuilder resolves these keys
|
|
26152
|
+
// even when the generated RefPack headings are Vietnamese.
|
|
26085
26153
|
"Technical Overview & Architecture Blueprint",
|
|
26086
26154
|
"Hardware Pinout & Wiring Configuration Matrix",
|
|
26155
|
+
"Standards Alignment",
|
|
26087
26156
|
"Core Pedagogical Concept Anchor & Real-World Domain Bridge"
|
|
26088
26157
|
],
|
|
26089
|
-
budget:
|
|
26158
|
+
budget: 3500
|
|
26090
26159
|
}).excerpt : "";
|
|
26091
26160
|
const baseContextPrefix = `PROJECT & ACADEMIC CONTEXT:
|
|
26092
26161
|
- Project ID: ${projectId}
|