@thanh01.pmt/curriculum-kit 1.3.0 → 1.4.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 +78 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.mjs +78 -13
- package/dist/index.mjs.map +1 -1
- package/dist/workflow/index.cjs +31 -5
- package/dist/workflow/index.cjs.map +1 -1
- package/dist/workflow/index.mjs +31 -5
- package/dist/workflow/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9841,7 +9841,9 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
|
9841
9841
|
};
|
|
9842
9842
|
}
|
|
9843
9843
|
const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
|
|
9844
|
-
const
|
|
9844
|
+
const effectiveArtifactType = opts.artifactType || deriveArtifactTypeFromFileName(opts.fileName);
|
|
9845
|
+
const sections = parseMarkdownSections(source, slcMap, effectiveArtifactType);
|
|
9846
|
+
const metaBlock = buildMetaBlock(source, effectiveArtifactType);
|
|
9845
9847
|
if (sections.length === 0) {
|
|
9846
9848
|
issues.push("parse:no-sections");
|
|
9847
9849
|
const excerpt2 = truncateByBudget(source, budget);
|
|
@@ -9875,12 +9877,13 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
|
|
|
9875
9877
|
const block = `## ${heading}
|
|
9876
9878
|
|
|
9877
9879
|
${trimmedBody}`;
|
|
9878
|
-
if (used + block.length > budget &&
|
|
9880
|
+
if (used + block.length > budget && used > 0) return false;
|
|
9879
9881
|
blocks.push(block);
|
|
9880
9882
|
used += block.length;
|
|
9881
9883
|
includedSections.push(key);
|
|
9882
9884
|
return true;
|
|
9883
9885
|
};
|
|
9886
|
+
blocks.push(metaBlock);
|
|
9884
9887
|
let sectionAware = false;
|
|
9885
9888
|
for (const key of priorities) {
|
|
9886
9889
|
const sec = byCanonical.get(key);
|
|
@@ -9897,6 +9900,9 @@ ${trimmedBody}`;
|
|
|
9897
9900
|
if (used >= budget) break;
|
|
9898
9901
|
if (!tryAdd(sec.cleanTitle, sec.body, sec.cleanTitle)) break;
|
|
9899
9902
|
}
|
|
9903
|
+
if (includedSections.length === 0 && unmatched.length > 0) {
|
|
9904
|
+
issues.push("parse:no-canonical-resolution");
|
|
9905
|
+
}
|
|
9900
9906
|
if (priorities.length > 0 && !priorities.some((k) => includedSections.includes(k))) {
|
|
9901
9907
|
issues.push("parse:no-priority-resolution");
|
|
9902
9908
|
}
|
|
@@ -9905,14 +9911,14 @@ ${trimmedBody}`;
|
|
|
9905
9911
|
excerpt = truncateByBudget(excerpt, budget);
|
|
9906
9912
|
}
|
|
9907
9913
|
const effectiveMinChars = Math.min(minContentChars, source.length);
|
|
9908
|
-
if (excerpt.length < effectiveMinChars) {
|
|
9914
|
+
if (excerpt.length - metaBlock.length < effectiveMinChars) {
|
|
9909
9915
|
issues.push("content:insufficient");
|
|
9910
9916
|
}
|
|
9911
|
-
const verified = !issues.includes("parse:no-priority-resolution") && excerpt.length >= effectiveMinChars;
|
|
9917
|
+
const verified = !issues.includes("parse:no-priority-resolution") && !issues.includes("parse:no-canonical-resolution") && excerpt.length - metaBlock.length >= effectiveMinChars;
|
|
9912
9918
|
return {
|
|
9913
9919
|
excerpt,
|
|
9914
9920
|
verified,
|
|
9915
|
-
sectionAware: sectionAware ||
|
|
9921
|
+
sectionAware: sectionAware || unmatched.length === 0,
|
|
9916
9922
|
includedSections,
|
|
9917
9923
|
issues,
|
|
9918
9924
|
tokenEstimate: Math.round(excerpt.length / 4)
|
|
@@ -10028,6 +10034,26 @@ function truncateByBudget(source, budget) {
|
|
|
10028
10034
|
if (fenceCount % 2 === 1) cut += "\n```";
|
|
10029
10035
|
return cut;
|
|
10030
10036
|
}
|
|
10037
|
+
function buildMetaBlock(source, artifactType) {
|
|
10038
|
+
const fm = source.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
|
|
10039
|
+
const pick = (key) => {
|
|
10040
|
+
if (!fm) return "";
|
|
10041
|
+
const m = fm[1].match(new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, "m"));
|
|
10042
|
+
return (m?.[1] || "").trim();
|
|
10043
|
+
};
|
|
10044
|
+
const id = pick("id");
|
|
10045
|
+
const title = pick("title");
|
|
10046
|
+
const type = pick("type") || artifactType || "";
|
|
10047
|
+
return `<!-- SOURCE: ${type || "ARTIFACT"} | ${id || "unknown"}${title ? ` \u2014 ${title}` : ""} (section-aware excerpt; canonical knowledge, do not contradict) -->`;
|
|
10048
|
+
}
|
|
10049
|
+
function deriveArtifactTypeFromFileName(fileName) {
|
|
10050
|
+
if (!fileName) return void 0;
|
|
10051
|
+
const base = fileName.replace(/\.md$/i, "");
|
|
10052
|
+
const multiWord = base.match(/^(KNOWLEDGE_EXPOSITION|SECTION_LANGUAGE_CONTRACT|CONTENT_STYLE_GUIDE|CURRICULUM_FRAMEWORK|LEARNER_PROFILE|PROJECT_BRIEF|REFERENCE_PACK|CURRICULUM_PLAN)/i);
|
|
10053
|
+
if (multiWord) return multiWord[1].toUpperCase();
|
|
10054
|
+
const token = base.match(/^([A-Z][A-Z0-9_]*?)(?=_|$)/);
|
|
10055
|
+
return token ? token[1] : void 0;
|
|
10056
|
+
}
|
|
10031
10057
|
|
|
10032
10058
|
// src/services/knowledgeExpositionService.ts
|
|
10033
10059
|
var EXPOSITION_REL = (lessonCode) => "_sot/expositions/" + lessonCode + ".md";
|
|
@@ -10176,7 +10202,7 @@ async function ensureExpositionForLesson(storage, projectId, lessonCode, options
|
|
|
10176
10202
|
storage,
|
|
10177
10203
|
gates: options.gates
|
|
10178
10204
|
});
|
|
10179
|
-
return { relPath: result.relPath, context: buildExpositionContext(result.content), reused: result.reused };
|
|
10205
|
+
return { relPath: result.relPath, context: buildExpositionContext(result.content), reused: result.reused, rawContent: result.content };
|
|
10180
10206
|
}
|
|
10181
10207
|
init_errors();
|
|
10182
10208
|
var asArr = (v) => Array.isArray(v) ? v : [];
|
|
@@ -11887,6 +11913,8 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11887
11913
|
targetLang = targetLang || "vi";
|
|
11888
11914
|
const languageDirective = buildLanguageDirective(targetLang);
|
|
11889
11915
|
let expositionContext = "";
|
|
11916
|
+
let expositionInjection;
|
|
11917
|
+
let lessonInjection;
|
|
11890
11918
|
let sessionSliceContext = "";
|
|
11891
11919
|
try {
|
|
11892
11920
|
const exposition = await ensureExpositionForLesson(storage, projectId, lessonCode, {
|
|
@@ -11894,7 +11922,18 @@ async function produceSingleLesson(storage, projectId, lessonId, options = {}) {
|
|
|
11894
11922
|
force: options.force
|
|
11895
11923
|
});
|
|
11896
11924
|
if (exposition) {
|
|
11897
|
-
|
|
11925
|
+
const expoExcerpt = buildExpositionExcerpt(exposition.rawContent || exposition.context, {
|
|
11926
|
+
budget: 6e3,
|
|
11927
|
+
sectionLanguageContract: slcMarkdown,
|
|
11928
|
+
artifactType: "KNOWLEDGE_EXPOSITION"
|
|
11929
|
+
});
|
|
11930
|
+
expositionContext = expoExcerpt.excerpt || exposition.context;
|
|
11931
|
+
expositionInjection = {
|
|
11932
|
+
source: "KNOWLEDGE_EXPOSITION",
|
|
11933
|
+
verified: expoExcerpt.verified,
|
|
11934
|
+
sectionAware: expoExcerpt.sectionAware,
|
|
11935
|
+
issues: expoExcerpt.issues
|
|
11936
|
+
};
|
|
11898
11937
|
onProgress?.("@content", `[EXPOSITION] ${exposition.reused ? "Reused" : "Generated"} \`\${exposition.relPath}\` (plan-driven knowledge source)...`);
|
|
11899
11938
|
} else {
|
|
11900
11939
|
onProgress?.("@content", "[EXPOSITION] No CURRICULUM_PLAN.json \u2014 running legacy knowledge flow (no plan-driven exposition).");
|
|
@@ -12134,6 +12173,7 @@ ${yamlBlock.trim()}
|
|
|
12134
12173
|
};
|
|
12135
12174
|
var injectYamlReviewMetadata = injectYamlReviewMetadata2;
|
|
12136
12175
|
const judgeObjectives = parseLessonObjectives(lessonContent, concept, bloomLevel);
|
|
12176
|
+
const judgeExpositionExcerpt = expositionContext ? buildExpositionExcerpt(expositionContext, { budget: 3e3, sectionLanguageContract: slcMarkdown, artifactType: "KNOWLEDGE_EXPOSITION" }).excerpt : void 0;
|
|
12137
12177
|
const judgeResult = await LLMJudgeEngine.evaluateArtifactWithLLM({
|
|
12138
12178
|
targetArtifactType: "LESSON",
|
|
12139
12179
|
lessonId: lessonCode,
|
|
@@ -12145,7 +12185,7 @@ ${yamlBlock.trim()}
|
|
|
12145
12185
|
title: lessonTitle,
|
|
12146
12186
|
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12147
12187
|
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
12148
|
-
canonicalExposition:
|
|
12188
|
+
canonicalExposition: judgeExpositionExcerpt
|
|
12149
12189
|
}),
|
|
12150
12190
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
12151
12191
|
});
|
|
@@ -12200,6 +12240,16 @@ ${currentContent}` }],
|
|
|
12200
12240
|
options.onProgress?.("@repair", chunk, { type: type || "content", artifactType: "LESSON" });
|
|
12201
12241
|
}
|
|
12202
12242
|
);
|
|
12243
|
+
const repairedExcerptCheck = buildSectionAwareExcerpt(repairedRaw, {
|
|
12244
|
+
priorities: DEFAULT_LESSON_PRIORITIES,
|
|
12245
|
+
budget: 12e3,
|
|
12246
|
+
sectionLanguageContract: slcMarkdown,
|
|
12247
|
+
artifactType: "LESSON"
|
|
12248
|
+
});
|
|
12249
|
+
if (repairedExcerptCheck.issues.includes("parse:no-priority-resolution")) {
|
|
12250
|
+
onProgress?.("@repair", `\u26A0\uFE0F Repair round ${round} lost mandatory section structure (no priority section resolved) \u2014 rejecting repaired draft, retaining previous`);
|
|
12251
|
+
break;
|
|
12252
|
+
}
|
|
12203
12253
|
if (!repairedRaw || repairedRaw.startsWith("\u26A0\uFE0F") || repairedRaw.length < 200) {
|
|
12204
12254
|
onProgress?.("@repair", `\u26A0\uFE0F Repair round ${round} produced invalid output \u2014 stopping repair loop`);
|
|
12205
12255
|
break;
|
|
@@ -12224,7 +12274,7 @@ ${currentContent}` }],
|
|
|
12224
12274
|
title: lessonTitle,
|
|
12225
12275
|
frameworkExcerpt: framework ? buildFrameworkExcerptForLesson(framework, lessonId) : void 0,
|
|
12226
12276
|
styleGuideExcerpt: effectiveStyleGuide || void 0,
|
|
12227
|
-
canonicalExposition: expositionContext ? expositionContext
|
|
12277
|
+
canonicalExposition: expositionContext ? buildExpositionExcerpt(expositionContext, { budget: 3e3, sectionLanguageContract: slcMarkdown, artifactType: "KNOWLEDGE_EXPOSITION" }).excerpt : void 0
|
|
12228
12278
|
}),
|
|
12229
12279
|
standardStatements: Object.keys(standardStatements).length > 0 ? standardStatements : void 0
|
|
12230
12280
|
});
|
|
@@ -12282,7 +12332,9 @@ ${currentContent}` }],
|
|
|
12282
12332
|
pedagogy,
|
|
12283
12333
|
producedArtifacts,
|
|
12284
12334
|
pausedForReview: true,
|
|
12285
|
-
gateStatus: "judge_needs_revision"
|
|
12335
|
+
gateStatus: "judge_needs_revision",
|
|
12336
|
+
contextInjection: expositionInjection || lessonInjection,
|
|
12337
|
+
promptChars: commonContext.length
|
|
12286
12338
|
};
|
|
12287
12339
|
}
|
|
12288
12340
|
}
|
|
@@ -12305,7 +12357,9 @@ ${currentContent}` }],
|
|
|
12305
12357
|
pedagogy,
|
|
12306
12358
|
producedArtifacts,
|
|
12307
12359
|
pausedForReview: true,
|
|
12308
|
-
gateStatus: "judge_error"
|
|
12360
|
+
gateStatus: "judge_error",
|
|
12361
|
+
contextInjection: expositionInjection,
|
|
12362
|
+
promptChars: commonContext.length
|
|
12309
12363
|
};
|
|
12310
12364
|
}
|
|
12311
12365
|
}
|
|
@@ -12335,7 +12389,9 @@ ${currentContent}` }],
|
|
|
12335
12389
|
pedagogy,
|
|
12336
12390
|
producedArtifacts,
|
|
12337
12391
|
pausedForReview: true,
|
|
12338
|
-
gateStatus: "awaiting_approval"
|
|
12392
|
+
gateStatus: "awaiting_approval",
|
|
12393
|
+
contextInjection: expositionInjection,
|
|
12394
|
+
promptChars: commonContext.length
|
|
12339
12395
|
};
|
|
12340
12396
|
}
|
|
12341
12397
|
if (isLessonApproved && currentLessonInfo?.state !== "approved") {
|
|
@@ -12352,6 +12408,13 @@ ${currentContent}` }],
|
|
|
12352
12408
|
artifactType: "LESSON"
|
|
12353
12409
|
});
|
|
12354
12410
|
const lessonExcerpt = lessonExcerptResult.excerpt;
|
|
12411
|
+
const lessonInjectionMeta = {
|
|
12412
|
+
source: "LESSON",
|
|
12413
|
+
verified: lessonExcerptResult.verified,
|
|
12414
|
+
sectionAware: lessonExcerptResult.sectionAware,
|
|
12415
|
+
issues: lessonExcerptResult.issues
|
|
12416
|
+
};
|
|
12417
|
+
lessonInjection = lessonInjectionMeta;
|
|
12355
12418
|
const satelliteContext = `${commonContext}
|
|
12356
12419
|
|
|
12357
12420
|
[CANONICAL LESSON PLAN (${pedagogyLabel})]:
|
|
@@ -12991,7 +13054,9 @@ ${buildHeadingDirective("EXT", slcMarkdown, targetLang)}`;
|
|
|
12991
13054
|
lessonId: lessonCode,
|
|
12992
13055
|
pedagogy,
|
|
12993
13056
|
producedArtifacts,
|
|
12994
|
-
pausedForReview: false
|
|
13057
|
+
pausedForReview: false,
|
|
13058
|
+
contextInjection: lessonInjection && lessonInjection.verified ? expositionInjection || lessonInjection : lessonInjection || expositionInjection,
|
|
13059
|
+
promptChars: commonContext.length
|
|
12995
13060
|
};
|
|
12996
13061
|
}
|
|
12997
13062
|
function parseLessonObjectives(lessonContent, concept, bloomLevel) {
|