@thanh01.pmt/curriculum-kit 1.4.20 → 1.4.21

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
@@ -1513,7 +1513,8 @@ function buildSlideBatchPrompt(params) {
1513
1513
  skillPrompt,
1514
1514
  language = "Vietnamese",
1515
1515
  languageDirective = "",
1516
- headingDirective = ""
1516
+ headingDirective = "",
1517
+ groundContext = ""
1517
1518
  } = params;
1518
1519
  const slidesSpec = clusterSlides.map((s) => `
1519
1520
  - Slide ${s.slideIndex} [Phase: ${s.lessonPhase}] -> Layout: "${s.layoutId}"
@@ -1526,7 +1527,11 @@ function buildSlideBatchPrompt(params) {
1526
1527
  const systemPrompt = `
1527
1528
  ${skillPrompt}
1528
1529
 
1529
- ---
1530
+ ${groundContext ? `---
1531
+ ### PROJECT GROUND CONTEXT (framework, style guide, glossary, canonical knowledge \u2014 author from these):
1532
+ ${groundContext}
1533
+
1534
+ ---` : ""}
1530
1535
  ### OPERATIONAL GROUND RULES FOR CHUNK GENERATION:
1531
1536
  ${languageDirective}
1532
1537
  ${headingDirective}
@@ -1604,6 +1609,7 @@ __export(slideProductionWorkflow_exports, {
1604
1609
  HybridPipelineError: () => exports.HybridPipelineError,
1605
1610
  SlideBlueprintArraySchema: () => exports.SlideBlueprintArraySchema,
1606
1611
  SlideBlueprintItemSchema: () => exports.SlideBlueprintItemSchema,
1612
+ emitUsage: () => emitUsage,
1607
1613
  executeSlideProductionWorkflow: () => executeSlideProductionWorkflow,
1608
1614
  extractJsonArray: () => extractJsonArray,
1609
1615
  validateHybridDeckSlides: () => validateHybridDeckSlides
@@ -1656,15 +1662,28 @@ function validateHybridDeckSlides(slides, blueprint) {
1656
1662
  });
1657
1663
  return v.slice(0, 10);
1658
1664
  }
1665
+ function emitUsage(usage, onProgress) {
1666
+ if (!onProgress || !usage) return;
1667
+ const promptTokens = usage.promptTokens ?? usage.inputTokens ?? 0;
1668
+ const completionTokens = usage.completionTokens ?? usage.outputTokens ?? 0;
1669
+ if (promptTokens === 0 && completionTokens === 0) return;
1670
+ onProgress("@illustrator", JSON.stringify({
1671
+ promptTokens,
1672
+ completionTokens,
1673
+ totalTokens: usage.totalTokens ?? promptTokens + completionTokens,
1674
+ reasoningTokens: usage.reasoningTokens ?? 0
1675
+ }), { type: "usage" });
1676
+ }
1659
1677
  async function inferTextJson(schema, systemPrompt, userPrompt, options, label) {
1660
1678
  const model = getAIModel(options.modelOptions);
1661
1679
  try {
1662
- const { text, finishReason } = await ai.generateText({
1680
+ const { text, finishReason, usage } = await ai.generateText({
1663
1681
  model,
1664
1682
  system: systemPrompt || void 0,
1665
1683
  prompt: userPrompt,
1666
1684
  maxOutputTokens: options.maxOutputTokens ?? 65536
1667
1685
  });
1686
+ emitUsage(usage, options.onProgress);
1668
1687
  const extracted = extractJsonArray(text);
1669
1688
  if (!("value" in extracted) || extracted.value === void 0) {
1670
1689
  console.warn(
@@ -1685,12 +1704,13 @@ async function inferTextJson(schema, systemPrompt, userPrompt, options, label) {
1685
1704
  async function inferStructured(schema, systemPrompt, userPrompt, options, label) {
1686
1705
  try {
1687
1706
  const model = getAIModel(options.modelOptions);
1688
- const { object } = await ai.generateObject({
1707
+ const { object, usage } = await ai.generateObject({
1689
1708
  model,
1690
1709
  schema,
1691
1710
  system: systemPrompt || void 0,
1692
1711
  prompt: userPrompt
1693
1712
  });
1713
+ emitUsage(usage, options.onProgress);
1694
1714
  const validated = schema.safeParse(object);
1695
1715
  if (validated.success) return validated.data;
1696
1716
  console.warn(
@@ -1705,7 +1725,9 @@ async function inferStructured(schema, systemPrompt, userPrompt, options, label)
1705
1725
  const messages = [
1706
1726
  { role: "user", content: [systemPrompt, userPrompt].filter(Boolean).join("\n\n") }
1707
1727
  ];
1708
- const raw = await runCurriculumAIInference(messages, options.satelliteContext || "", options.runnerOptions);
1728
+ const raw = await runCurriculumAIInference(messages, options.satelliteContext || "", options.runnerOptions, (token, type) => {
1729
+ if (type === "usage") options.onProgress?.("@illustrator", token, { type: "usage" });
1730
+ });
1709
1731
  const fenceMatch = raw.match(/```(?:json)?\s*([\s\S]*?)\s*```/i);
1710
1732
  const candidate = (fenceMatch ? fenceMatch[1] : raw).trim();
1711
1733
  let parsed;
@@ -1738,7 +1760,7 @@ function normalizeBlueprintItems(items) {
1738
1760
  }));
1739
1761
  }
1740
1762
  function buildHybridDeckPrompts(params) {
1741
- const { lessonFlow, blueprint, skillPrompt, language, languageDirective, headingDirective } = params;
1763
+ const { lessonFlow, blueprint, skillPrompt, language, languageDirective, headingDirective, groundContext } = params;
1742
1764
  const blueprintText = JSON.stringify(
1743
1765
  blueprint.map((s) => ({
1744
1766
  slideIndex: s.slideIndex,
@@ -1757,6 +1779,7 @@ function buildHybridDeckPrompts(params) {
1757
1779
  ${p.content}`).join("\n\n") : lessonFlow.rawContent;
1758
1780
  const systemPrompt = [
1759
1781
  skillPrompt,
1782
+ groundContext || "",
1760
1783
  languageDirective,
1761
1784
  headingDirective,
1762
1785
  `
@@ -1821,7 +1844,8 @@ async function runHybridPipeline(ctx) {
1821
1844
  skillPrompt,
1822
1845
  language,
1823
1846
  languageDirective,
1824
- headingDirective
1847
+ headingDirective,
1848
+ groundContext: options.groundContext
1825
1849
  });
1826
1850
  let slides = null;
1827
1851
  let lastViolations = [];
@@ -1970,7 +1994,8 @@ ${p.content}`).join("\n\n") : lessonFlow.rawContent.slice(0, 3500);
1970
1994
  skillPrompt,
1971
1995
  language,
1972
1996
  languageDirective,
1973
- headingDirective
1997
+ headingDirective,
1998
+ groundContext: options.groundContext
1974
1999
  });
1975
2000
  try {
1976
2001
  const batchSlides = await pRetry__default.default(
@@ -9312,6 +9337,21 @@ var STANDARD_SOT_FILES = [
9312
9337
  "ART_DIRECTION.md",
9313
9338
  "ALIGNMENT_MATRIX.md"
9314
9339
  ];
9340
+ function atomicWriteFileSync(targetPath, content) {
9341
+ const dir = path3__default.default.dirname(targetPath);
9342
+ if (!fs2__default.default.existsSync(dir)) fs2__default.default.mkdirSync(dir, { recursive: true });
9343
+ const tmpPath = path3__default.default.join(dir, `.${path3__default.default.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto__default.default.randomBytes(4).toString("hex")}.tmp`);
9344
+ try {
9345
+ fs2__default.default.writeFileSync(tmpPath, content, "utf-8");
9346
+ fs2__default.default.renameSync(tmpPath, targetPath);
9347
+ } catch (err) {
9348
+ try {
9349
+ if (fs2__default.default.existsSync(tmpPath)) fs2__default.default.unlinkSync(tmpPath);
9350
+ } catch {
9351
+ }
9352
+ throw err;
9353
+ }
9354
+ }
9315
9355
  var FileSystemCurriculumAdapter = class {
9316
9356
  baseDir;
9317
9357
  constructor(options = {}) {
@@ -9450,7 +9490,7 @@ var FileSystemCurriculumAdapter = class {
9450
9490
  if (oldContent !== content) {
9451
9491
  const historyDir = path3__default.default.join(projectDir, ".history", relPath);
9452
9492
  fs2__default.default.mkdirSync(historyDir, { recursive: true });
9453
- fs2__default.default.writeFileSync(path3__default.default.join(historyDir, `${Date.now()}.md`), oldContent, "utf-8");
9493
+ atomicWriteFileSync(path3__default.default.join(historyDir, `${Date.now()}.md`), oldContent);
9454
9494
  const versions = fs2__default.default.readdirSync(historyDir).filter((f) => f.endsWith(".md")).sort();
9455
9495
  while (versions.length > 10) {
9456
9496
  fs2__default.default.unlinkSync(path3__default.default.join(historyDir, versions.shift()));
@@ -9460,19 +9500,15 @@ var FileSystemCurriculumAdapter = class {
9460
9500
  console.warn("[FileSystemCurriculumAdapter] version history snapshot failed:", histErr?.message || histErr);
9461
9501
  }
9462
9502
  }
9463
- fs2__default.default.writeFileSync(targetPath, content, "utf-8");
9503
+ atomicWriteFileSync(targetPath, content);
9464
9504
  const filename = path3__default.default.basename(relPath);
9465
9505
  const match = filename.match(/(LESSON|ACT|QUIZ|SLIDE|GUIDE|HANDOUT|WKS|EXT)_(U\d+_M\d+_L\d+)\.md/i);
9466
9506
  if (match) {
9467
9507
  const lessonId = match[2].toUpperCase();
9468
- const lessonsDir = path3__default.default.join(projectDir, "lessons", lessonId);
9469
- if (!fs2__default.default.existsSync(lessonsDir)) {
9470
- fs2__default.default.mkdirSync(lessonsDir, { recursive: true });
9471
- }
9472
- fs2__default.default.writeFileSync(path3__default.default.join(lessonsDir, filename), content, "utf-8");
9508
+ atomicWriteFileSync(path3__default.default.join(projectDir, "lessons", lessonId, filename), content);
9473
9509
  const legacyContentDir = path3__default.default.join(projectDir, "_content", lessonId);
9474
9510
  if (fs2__default.default.existsSync(legacyContentDir)) {
9475
- fs2__default.default.writeFileSync(path3__default.default.join(legacyContentDir, filename), content, "utf-8");
9511
+ atomicWriteFileSync(path3__default.default.join(legacyContentDir, filename), content);
9476
9512
  }
9477
9513
  }
9478
9514
  }
@@ -9563,7 +9599,7 @@ ${lessonTable}
9563
9599
  }
9564
9600
  const stateFile = path3__default.default.join(pipelineDir, "state.json");
9565
9601
  state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
9566
- fs2__default.default.writeFileSync(stateFile, JSON.stringify(state, null, 2), "utf-8");
9602
+ atomicWriteFileSync(stateFile, JSON.stringify(state, null, 2));
9567
9603
  }
9568
9604
  async updateArtifactState(projectId, taskId, artifactType, update) {
9569
9605
  const current = await this.getPipelineState(projectId);
@@ -11263,6 +11299,13 @@ var DEFAULT_LESSON_PRIORITIES = [
11263
11299
  "Learning Objectives & Evidence",
11264
11300
  "Activity Sequence"
11265
11301
  ];
11302
+ var SATELLITE_LESSON_PRIORITIES = [
11303
+ "Artifact Contract",
11304
+ "A. Lesson Design Plan",
11305
+ "B. Lesson Flow",
11306
+ "Learning Objectives & Evidence",
11307
+ "Activity Sequence"
11308
+ ];
11266
11309
  var DEFAULT_KX_PRIORITIES = [
11267
11310
  "Key Terms",
11268
11311
  "Concept Narratives",
@@ -26094,6 +26137,21 @@ ${renderHorizonPromptBlock(horizon)}`;
26094
26137
  } catch (hErr) {
26095
26138
  console.warn(`[produceSingleLesson] Notice: Curriculum Horizon extraction:`, hErr?.message || hErr);
26096
26139
  }
26140
+ const buildGroundTruthBlock = () => {
26141
+ const parts = [];
26142
+ if (expositionContext) {
26143
+ parts.push(`### KNOWLEDGE_EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict)
26144
+ ${expositionContext}`);
26145
+ }
26146
+ if (effectiveRefPack) {
26147
+ parts.push(`### REFERENCE PACK GROUND TRUTH
26148
+ ${effectiveRefPack}`);
26149
+ }
26150
+ return parts.length > 0 ? `
26151
+
26152
+ [GROUND TRUTH]:
26153
+ ${parts.join("\n\n")}` : "";
26154
+ };
26097
26155
  const glossaryBlock = glossaryContext ? `
26098
26156
 
26099
26157
  [GLOSSARY TERMS (use these exact definitions)]:
@@ -26101,21 +26159,14 @@ ${glossaryContext}` : "";
26101
26159
  const standardsBlock = standardsContext ? `
26102
26160
 
26103
26161
  ${standardsContext}` : "";
26104
- const expositionBlock = expositionContext ? `
26105
-
26106
- [KNOWLEDGE_EXPOSITION (CANONICAL KNOWLEDGE \u2014 teach from this, do not contradict)]:
26107
- ${expositionContext}` : "";
26108
26162
  const sessionSliceBlock = sessionSliceContext ? `
26109
26163
 
26110
26164
  ${sessionSliceContext}` : "";
26111
- const assembleCommonContext = (ref, sg) => `${baseContextPrefix}
26165
+ const assembleCommonContext = (sg) => `${baseContextPrefix}
26112
26166
 
26113
26167
  [CONTENT STYLE GUIDE EXCERPT]:
26114
- ${sg}
26115
-
26116
- [REFERENCE PACK GROUND TRUTH]:
26117
- ${ref}${standardsBlock}${glossaryBlock}${expositionBlock}${sessionSliceBlock}${horizonBlock}`;
26118
- let commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
26168
+ ${sg}${standardsBlock}${glossaryBlock}${buildGroundTruthBlock()}${sessionSliceBlock}${horizonBlock}`;
26169
+ let commonContext = assembleCommonContext(effectiveStyleGuide);
26119
26170
  const MAX_COMPOSITE_PROMPT_CHARS = 3e4;
26120
26171
  const runnerOptions = options.customInference ? { customInference: options.customInference } : {};
26121
26172
  if (commonContext.length > MAX_COMPOSITE_PROMPT_CHARS && effectiveRefPack.length > 1e3) {
@@ -26126,14 +26177,14 @@ ${ref}${standardsBlock}${glossaryBlock}${expositionBlock}${sessionSliceBlock}${h
26126
26177
  ],
26127
26178
  budget: 1e3
26128
26179
  }).excerpt;
26129
- commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
26180
+ commonContext = assembleCommonContext(effectiveStyleGuide);
26130
26181
  }
26131
26182
  if (commonContext.length > MAX_COMPOSITE_PROMPT_CHARS && effectiveStyleGuide.length > 1e3) {
26132
26183
  effectiveStyleGuide = buildSectionAwareExcerpt(styleGuide, {
26133
26184
  priorities: ["Voice & Tone", "Standard Terminology (Glossary)"],
26134
26185
  budget: 1e3
26135
26186
  }).excerpt;
26136
- commonContext = assembleCommonContext(effectiveRefPack, effectiveStyleGuide);
26187
+ commonContext = assembleCommonContext(effectiveStyleGuide);
26137
26188
  }
26138
26189
  onProgress?.("@content", `[CONTEXT] Composite prompt ready (${commonContext.length} chars, adaptive budget <= ${MAX_COMPOSITE_PROMPT_CHARS})`, {
26139
26190
  type: "progress",
@@ -26484,7 +26535,7 @@ ${currentContent}` }],
26484
26535
  });
26485
26536
  }
26486
26537
  const lessonExcerptResult = buildSectionAwareExcerpt(lessonContent, {
26487
- priorities: DEFAULT_LESSON_PRIORITIES,
26538
+ priorities: SATELLITE_LESSON_PRIORITIES,
26488
26539
  budget: 12e3,
26489
26540
  sectionLanguageContract: slcMarkdown,
26490
26541
  artifactType: "LESSON"
@@ -26674,6 +26725,7 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
26674
26725
  } catch {
26675
26726
  }
26676
26727
  const { executeSlideProductionWorkflow: executeSlideProductionWorkflow2 } = await Promise.resolve().then(() => (init_slideProductionWorkflow(), slideProductionWorkflow_exports));
26728
+ const slideGroundContext = `${commonContext}${symbolLedgerBlock}`;
26677
26729
  const workflowResult = await executeSlideProductionWorkflow2({
26678
26730
  lessonMarkdown: lessonContent || "",
26679
26731
  lessonCode,
@@ -26682,6 +26734,7 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
26682
26734
  language: targetLang || "Vietnamese",
26683
26735
  languageDirective,
26684
26736
  headingDirective: buildHeadingDirective("SLIDE", slcMarkdown, targetLang),
26737
+ groundContext: slideGroundContext,
26685
26738
  satelliteContext,
26686
26739
  runnerOptions,
26687
26740
  onProgress: (agent, msg, meta) => {
@@ -26690,7 +26743,7 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
26690
26743
  });
26691
26744
  let deckJson = workflowResult.deckJson;
26692
26745
  const markdownWrapper = workflowResult.markdownWrapper;
26693
- let validation = presentationKitAi?.validateHtmlSlideDeck ? presentationKitAi.validateHtmlSlideDeck(deckJson, true) : deckJson && Array.isArray(deckJson.slides) ? { valid: true, score: 95, issues: [], slideCount: deckJson.slides.length} : { valid: false, score: 0, issues: [{ message: "Malformed JSON slide deck" }], slideCount: 0};
26746
+ let validation = presentationKitAi?.validateHtmlSlideDeck ? presentationKitAi.validateHtmlSlideDeck(deckJson, true) : deckJson && Array.isArray(deckJson.slides) ? { valid: true, score: 95, issues: [], slideCount: deckJson.slides.length} : { valid: false, score: 0, issues: [{ message: "Malformed JSON slide deck" }]};
26694
26747
  await storage.saveArtifact(projectId, slideRelPath, markdownWrapper);
26695
26748
  producedArtifacts.push(`SLIDE_${lessonCode}.md`);
26696
26749
  if (deckJson) {
@@ -26710,21 +26763,45 @@ ${buildHeadingDirective("QUIZ", slcMarkdown, targetLang)}`;
26710
26763
  }
26711
26764
  }
26712
26765
  }
26713
- const passed = Boolean(validation.valid && (validation.score ?? 100) >= 80);
26714
- const score = validation.score ?? (passed ? 95 : 50);
26715
- await storage.updateArtifactState(projectId, lessonCode, "SLIDE", {
26716
- state: passed ? "approved" : "rejected",
26717
- generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
26718
- contentHash: computeContentHash(markdownWrapper),
26719
- review: {
26720
- decision: passed ? "APPROVED" : "NEEDS_REVISION",
26721
- reviewedBy: "@agent-as-judge",
26722
- reviewedAt: (/* @__PURE__ */ new Date()).toISOString(),
26723
- score,
26724
- critique: passed ? `HTML Slide Deck passed strict schema validation (${score}/100, ${validation.slideCount ?? deckJson?.slides?.length ?? 0} slides). Auto-approved.` : `HTML Slide Deck failed schema validation: ${(validation.issues || []).map((i) => i.message).join("; ")}`
26725
- }
26726
- });
26727
- onProgress?.("@reviewer", passed ? `\u2705 SLIDE judge PASS (${score}/100) [html-deck schema validated]` : `\u26A0\uFE0F SLIDE judge NEEDS_REVISION (${score}/100) [html-deck schema issues]`);
26766
+ const structuralOk = Boolean(validation.valid && (validation.score ?? 100) >= 80);
26767
+ const structuralScore = validation.score ?? (structuralOk ? 95 : 50);
26768
+ const gateMode = gateModeFor(gates, "SLIDE");
26769
+ if (!structuralOk) {
26770
+ await storage.updateArtifactState(projectId, lessonCode, "SLIDE", {
26771
+ state: "rejected",
26772
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
26773
+ contentHash: computeContentHash(markdownWrapper),
26774
+ review: {
26775
+ decision: "NEEDS_REVISION",
26776
+ reviewedBy: "@heuristic-linter",
26777
+ reviewedAt: (/* @__PURE__ */ new Date()).toISOString(),
26778
+ score: structuralScore,
26779
+ critique: `HTML Slide Deck failed schema validation: ${(validation.issues || []).map((i) => i.message).join("; ")}`
26780
+ }
26781
+ });
26782
+ onProgress?.("@reviewer", `\u26A0\uFE0F SLIDE structural pre-check FAILED (${structuralScore}/100) [html-deck schema issues]`);
26783
+ } else {
26784
+ await storage.updateArtifactState(projectId, lessonCode, "SLIDE", {
26785
+ state: gateMode === "LLM_JUDGE" ? "pending" : "completed",
26786
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
26787
+ contentHash: computeContentHash(markdownWrapper)
26788
+ });
26789
+ onProgress?.("@reviewer", gateMode === "LLM_JUDGE" ? `\u2705 SLIDE structural pre-check PASS (${structuralScore}/100) \u2014 handing content review to LLM-as-Judge gate` : `\u2705 SLIDE structural pre-check PASS (${structuralScore}/100) [gate=${gateMode}, no LLM judge]`);
26790
+ const deckTextForJudge = Array.isArray(deckJson?.slides) ? deckJson.slides.map((s, i) => {
26791
+ const slotLines = Object.entries(s.slots || {}).map(([k, v]) => {
26792
+ if (Array.isArray(v)) return `- ${k}:
26793
+ ${v.map((item) => typeof item === "object" ? ` - ${JSON.stringify(item)}` : ` - ${item}`).join("\n")}`;
26794
+ if (v && typeof v === "object") return `- ${k}: ${JSON.stringify(v, null, 1)}`;
26795
+ return `- ${k}: ${v}`;
26796
+ }).join("\n");
26797
+ return `## Slide ${i + 1} [${s.layoutId}]
26798
+ ${slotLines}
26799
+
26800
+ Presenter Notes:
26801
+ ${s.notes || "(none)"}`;
26802
+ }).join("\n\n") : String(markdownWrapper);
26803
+ await judgeSat("SLIDE", deckTextForJudge);
26804
+ }
26728
26805
  } else {
26729
26806
  const canonicalSlideTemplate = loadCurriculumTemplate("SLIDE_template.md");
26730
26807
  const templateScaffold = canonicalSlideTemplate || `---
@@ -31873,6 +31950,7 @@ exports.RoadmapInputSchema = RoadmapInputSchema;
31873
31950
  exports.RotationStationSchema = RotationStationSchema;
31874
31951
  exports.RubricCriteriaSchema = RubricCriteriaSchema;
31875
31952
  exports.RubricSchema = RubricSchema;
31953
+ exports.SATELLITE_LESSON_PRIORITIES = SATELLITE_LESSON_PRIORITIES;
31876
31954
  exports.SCIENCE_LAB_TEMPLATE = SCIENCE_LAB_TEMPLATE;
31877
31955
  exports.SELF_LAB_TEMPLATE = SELF_LAB_TEMPLATE;
31878
31956
  exports.SLIDE_CANONICAL_METHODOLOGY = SLIDE_CANONICAL_METHODOLOGY;
@@ -31922,6 +32000,7 @@ exports.analystTools = analystTools;
31922
32000
  exports.analyzeProjectCreationIntent = analyzeProjectCreationIntent;
31923
32001
  exports.assertAcyclic = assertAcyclic;
31924
32002
  exports.assessorTools = assessorTools;
32003
+ exports.atomicWriteFileSync = atomicWriteFileSync;
31925
32004
  exports.auditCurriculumQualityFlow = auditCurriculumQualityFlow;
31926
32005
  exports.auditQualityReport = auditQualityReport;
31927
32006
  exports.buildActivityPrompt = buildActivityPrompt;
@@ -31969,6 +32048,7 @@ exports.createStreamChunkExtractor = createStreamChunkExtractor;
31969
32048
  exports.curateMediaLedger = curateMediaLedger;
31970
32049
  exports.designerTools = designerTools;
31971
32050
  exports.detectProjectPedagogy = detectProjectPedagogy;
32051
+ exports.emitUsage = emitUsage;
31972
32052
  exports.ensureExpositionForLesson = ensureExpositionForLesson;
31973
32053
  exports.ensureKnowledgeExposition = ensureKnowledgeExposition;
31974
32054
  exports.evaluateStandardsCoverage = evaluateStandardsCoverage;