@thanh01.pmt/curriculum-kit 1.2.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/index.cjs CHANGED
@@ -5571,13 +5571,13 @@ Evaluate the candidate artifact across these 6 dimensions:
5571
5571
  - 0 pts: Missing critical sections.
5572
5572
 
5573
5573
  5. **Technical & Conceptual Accuracy (15 pts):**
5574
- - 15 pts: Code snippets, logic flows, architectural descriptions, and Mermaid diagrams are conceptually sound, valid, and free of syntax hallucinations.
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.
5575
5575
  - 8 pts: Minor syntax inaccuracies or unidiomatic code that does not break core concepts.
5576
- - 0 pts: Severe technical hallucinations, broken logic, or invalid diagrams.
5576
+ - 0 pts: Severe technical hallucinations, broken logic, invalid diagrams, or direct contradiction of canonical exposition knowledge.
5577
5577
 
5578
5578
  6. **Contract Consistency & Zero-Drift (10 pts):**
5579
- - 10 pts: Satellite artifact strictly adheres to the scope, tech stack, and objectives of Lesson ${lessonId} without introducing unrelated topics.
5580
- - 0-5 pts: Scope drift or topic divergence detected.
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.
5581
5581
 
5582
5582
  ## VERDICT RULES
5583
5583
  - **PASS:** Score >= 80 AND Language Adherence = true AND Standards Alignment >= 12 (when STANDARDS GROUND TRUTH is present).
@@ -11872,11 +11872,42 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
11872
11872
  }
11873
11873
  const pedagogy = detectProjectPedagogy(framework, styleGuide, options.pedagogy);
11874
11874
  const pedagogyLabel = pedagogy.toUpperCase();
11875
- const styleGuideExcerpt = styleGuide ? buildSectionAwareExcerpt(styleGuide, {
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, {
11876
11907
  priorities: ["Voice & Tone", "Standard Terminology (Glossary)", "Lesson Content Standards"],
11877
11908
  budget: 2e3
11878
11909
  }).excerpt : "";
11879
- const refPackExcerpt = refPack ? buildSectionAwareExcerpt(refPack, {
11910
+ let effectiveRefPack = refPack ? buildSectionAwareExcerpt(refPack, {
11880
11911
  priorities: [
11881
11912
  "Technical Overview & Architecture Blueprint",
11882
11913
  "Hardware Pinout & Wiring Configuration Matrix",
@@ -11884,7 +11915,7 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
11884
11915
  ],
11885
11916
  budget: 2500
11886
11917
  }).excerpt : "";
11887
- const commonContext = `PROJECT & ACADEMIC CONTEXT:
11918
+ const baseContextPrefix = `PROJECT & ACADEMIC CONTEXT:
11888
11919
  - Project ID: ${projectId}
11889
11920
  - Pedagogical Model: ${pedagogyLabel}
11890
11921
  - Lesson Code: ${lessonCode}
@@ -11894,13 +11925,51 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
11894
11925
  - Target Bloom Level: ${bloomLevel}
11895
11926
 
11896
11927
  [CURRICULUM FRAMEWORK EXCERPT]:
11897
- ${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}
11898
11944
 
11899
11945
  [CONTENT STYLE GUIDE EXCERPT]:
11900
- ${styleGuideExcerpt}
11946
+ ${sg}
11901
11947
 
11902
11948
  [REFERENCE PACK GROUND TRUTH]:
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 : ""}`;
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
+ });
11904
11973
  const producedArtifacts = [];
11905
11974
  const lessonRelPath = `_content/${unitCode}/LESSON_${lessonCode}.md`;
11906
11975
  const existingLessonContent = await storage.readArtifact(projectId, lessonRelPath);
@@ -12027,7 +12096,7 @@ ${yamlBlock.trim()}
12027
12096
  lessonId: lessonCode,
12028
12097
  title: lessonTitle,
12029
12098
  frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
12030
- styleGuideExcerpt: styleGuideExcerpt || void 0,
12099
+ styleGuideExcerpt: effectiveStyleGuide || void 0,
12031
12100
  canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
12032
12101
  }),
12033
12102
  standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
@@ -12070,7 +12139,7 @@ ${yamlBlock.trim()}
12070
12139
  onProgress?.("@repair", `\u{1F527} Repair round ${round}/${MAX_REPAIR_ROUNDS} for LESSON_${lessonCode} (judge score ${currentResult.score}/100)...`);
12071
12140
  const repairedRaw = await runCurriculumAIInference(
12072
12141
  [{ role: "user", content: `You previously authored \`LESSON_${lessonCode}.md\` and the academic Judge REJECTED it with the critique below.
12073
- Rewrite the COMPLETE corrected document: fix every listed issue, keep the mandatory structure, frontmatter and all approved sections. Output 100% clean Markdown only.
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.
12074
12143
 
12075
12144
  JUDGE CRITIQUE:
12076
12145
  ${repairFeedback}
@@ -12088,7 +12157,13 @@ ${currentContent}` }],
12088
12157
  break;
12089
12158
  }
12090
12159
  const repairLint = lintAndSanitizeArtifact(repairedRaw, `LESSON_${lessonCode}.md`);
12091
- currentContent = repairLint.autoFixedContent || repairedRaw;
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;
12092
12167
  onProgress?.("@reviewer", `\u{1F916} Re-judging repaired LESSON_${lessonCode} (round ${round})...`);
12093
12168
  const reJudge = await LLMJudgeEngine.evaluateArtifactWithLLM({
12094
12169
  targetArtifactType: "LESSON",
@@ -12100,7 +12175,7 @@ ${currentContent}` }],
12100
12175
  lessonId: lessonCode,
12101
12176
  title: lessonTitle,
12102
12177
  frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
12103
- styleGuideExcerpt: styleGuideExcerpt || void 0,
12178
+ styleGuideExcerpt: effectiveStyleGuide || void 0,
12104
12179
  canonicalExposition: expositionContext ? expositionContext.slice(0, 3e3) : void 0
12105
12180
  }),
12106
12181
  standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0