@thanh01.pmt/curriculum-kit 1.4.36 → 1.4.37

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
@@ -26584,13 +26584,16 @@ ${lessonExcerpt.excerpt}${symbolLedgerBlock}`;
26584
26584
  verified: lessonExcerpt.verified,
26585
26585
  sectionAware: lessonExcerpt.sectionAware,
26586
26586
  issues: lessonExcerpt.issues,
26587
- tokenEstimate: Math.round(context2.length / 4)
26587
+ tokenEstimate: Math.round(context2.length / 4),
26588
+ canonicalExcerpt: lessonExcerpt.excerpt
26588
26589
  };
26589
26590
  }
26590
26591
  const blocks = [];
26591
26592
  const issues = [];
26592
26593
  const parts = [commonContext];
26593
26594
  blocks.push(blockMeta("commonContext", "COMPOSITE", commonContext, true));
26595
+ let excerptSlot;
26596
+ let miniSlot;
26594
26597
  const compositeHasKx = /###\s+KNOWLEDGE_EXPOSITION/.test(commonContext);
26595
26598
  if (expositionContent.trim() && !compositeHasKx) {
26596
26599
  const kxExcerpt = buildSectionAwareExcerpt(expositionContent, {
@@ -26614,10 +26617,12 @@ ${kxExcerpt.excerpt}`);
26614
26617
  sectionLanguageContract: slcMarkdown,
26615
26618
  artifactType: "LESSON"
26616
26619
  });
26617
- parts.push(`
26620
+ const excerptBlock = `
26618
26621
 
26619
26622
  [CANONICAL LESSON PLAN (scoped for ${type})]:
26620
- ${excerpt.excerpt}`);
26623
+ ${excerpt.excerpt}`;
26624
+ parts.push(excerptBlock);
26625
+ excerptSlot = excerptBlock;
26621
26626
  blocks.push(blockMeta("lessonExcerpt:" + type, "LESSON", excerpt.excerpt, excerpt.verified, excerpt.issues));
26622
26627
  if (!excerpt.verified) issues.push(...excerpt.issues.map((i) => `lesson:${i}`));
26623
26628
  if (type === "QUIZ" || type === "WKS") {
@@ -26646,10 +26651,12 @@ ${contractRows}` : "",
26646
26651
  ${tierBlock}` : ""
26647
26652
  ].filter(Boolean).join("\n\n");
26648
26653
  if (mini) {
26649
- parts.push(`
26654
+ const miniBlock = `
26650
26655
 
26651
26656
  [LESSON ACTIVITY CONTRACT (mini-slot)]:
26652
- ${mini}`);
26657
+ ${mini}`;
26658
+ parts.push(miniBlock);
26659
+ miniSlot = miniBlock;
26653
26660
  blocks.push(blockMeta("activityContract:" + type, "LESSON", mini, true));
26654
26661
  } else {
26655
26662
  issues.push(`activity-contract:unresolved:${type}`);
@@ -26667,9 +26674,36 @@ ${mini}`);
26667
26674
  verified: blocks.filter((b) => b.slot !== "commonContext").every((b) => b.verified),
26668
26675
  sectionAware: blocks.some((b) => b.slot.startsWith("lessonExcerpt") || b.slot.startsWith("kxExcerpt")),
26669
26676
  issues,
26670
- tokenEstimate: Math.round(context.length / 4)
26677
+ tokenEstimate: Math.round(context.length / 4),
26678
+ // Judge ground truth = exactly what THIS type consumed (scoped or mini slot).
26679
+ canonicalExcerpt: (miniSlot ?? excerptSlot ?? lessonExcerpt.excerpt).trim()
26671
26680
  };
26672
26681
  }
26682
+ var ACTIVITY_ALIGNMENT_LOG_ONLY_UNTIL = /* @__PURE__ */ new Date("2026-09-23T00:00:00Z");
26683
+ function isActivityAlignmentLogOnly(now = /* @__PURE__ */ new Date()) {
26684
+ const env = (process.env.DRIFT_ALIGNMENT_LOG_ONLY ?? "").toLowerCase().trim();
26685
+ if (env === "false" || env === "0") return false;
26686
+ if (env === "true" || env === "1") return true;
26687
+ return now < ACTIVITY_ALIGNMENT_LOG_ONLY_UNTIL;
26688
+ }
26689
+ function evaluateActivityAlignment(canonicalExcerpt, generatedContent, now = /* @__PURE__ */ new Date()) {
26690
+ const mode = isActivityAlignmentLogOnly(now) ? "log_only" : "enforcing";
26691
+ if (!canonicalExcerpt || !canonicalExcerpt.trim()) {
26692
+ return { checked: false, passed: null, matchedTokens: [], missingTokens: [], mode };
26693
+ }
26694
+ const content = (generatedContent || "").toLowerCase();
26695
+ const stripped = canonicalExcerpt.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
26696
+ const latin = Array.from(new Set(stripped.match(/[a-z][a-z0-9_]{3,}/g) ?? []));
26697
+ const cjk = Array.from(new Set(canonicalExcerpt.match(/[\u4e00-\u9fff]{2,}/g) ?? []));
26698
+ const tokens = [...latin, ...cjk];
26699
+ if (tokens.length === 0) {
26700
+ return { checked: false, passed: null, matchedTokens: [], missingTokens: [], mode };
26701
+ }
26702
+ const matchedTokens = tokens.filter((t) => content.includes(t));
26703
+ const missingTokens = tokens.filter((t) => !content.includes(t));
26704
+ const passed = matchedTokens.length > 0;
26705
+ return { checked: true, passed, matchedTokens: matchedTokens.slice(0, 10), missingTokens: missingTokens.slice(0, 10), mode };
26706
+ }
26673
26707
 
26674
26708
  // src/services/lessonProductionService.ts
26675
26709
  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" && typeof url.fileURLToPath === "function" ? 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))) : "";
@@ -27694,6 +27728,7 @@ ${currentContent}` }],
27694
27728
  const routingMode = options.contextRoutingMode ?? "legacy";
27695
27729
  const kxFreeCommonContext = routingMode === "hybrid" ? assembleCommonContext(effectiveStyleGuide, false) : "";
27696
27730
  const satelliteContexts = {};
27731
+ const satelliteContextMeta = {};
27697
27732
  const satelliteContextFor = (artifactType) => {
27698
27733
  const key = artifactType.toUpperCase();
27699
27734
  if (!satelliteContexts[key]) {
@@ -27709,6 +27744,7 @@ ${currentContent}` }],
27709
27744
  mode: routingMode
27710
27745
  });
27711
27746
  satelliteContexts[key] = built.context;
27747
+ satelliteContextMeta[key] = built;
27712
27748
  onProgress?.(
27713
27749
  "@content",
27714
27750
  `[CONTEXT] ${key} satellite context: ${built.context.length} chars (${built.blocks.map((b) => `${b.slot}:${b.chars}`).join(", ")})`,
@@ -27736,6 +27772,30 @@ ${currentContent}` }],
27736
27772
  }
27737
27773
  });
27738
27774
  }
27775
+ const slotMeta = satelliteContextMeta[sat.toUpperCase()];
27776
+ if (slotMeta) {
27777
+ const alignment = evaluateActivityAlignment(slotMeta.canonicalExcerpt, content);
27778
+ if (alignment.checked && alignment.passed === false) {
27779
+ const note = `activity-alignment drift vs ${sat} contract slot (matched: ${alignment.matchedTokens.join(", ") || "none"}); canonical tokens absent from output`;
27780
+ if (alignment.mode === "enforcing") {
27781
+ const critique = validatorRepairPrompt([{ code: "scope-drift", detail: note, evidence: alignment.missingTokens }]);
27782
+ onProgress?.("@reviewer", `\u26D4 ${sat} activity-alignment drift FAIL: ${note}`);
27783
+ return storage.updateArtifactState(projectId, lessonCode, sat, {
27784
+ state: "rejected",
27785
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
27786
+ contentHash: computeContentHash(content),
27787
+ review: {
27788
+ decision: "NEEDS_REVISION",
27789
+ reviewedBy: "@heuristic-linter",
27790
+ reviewedAt: (/* @__PURE__ */ new Date()).toISOString(),
27791
+ score: 0,
27792
+ critique
27793
+ }
27794
+ });
27795
+ }
27796
+ onProgress?.("@reviewer", `\u{1F9ED} [log-only] ${sat} activity-alignment drift: ${note}`);
27797
+ }
27798
+ }
27739
27799
  return judgeSatelliteArtifact({
27740
27800
  storage,
27741
27801
  projectId,
@@ -27748,7 +27808,7 @@ ${currentContent}` }],
27748
27808
  onProgress,
27749
27809
  targetLang,
27750
27810
  canonicalLessonContent: lessonContent,
27751
- canonicalLessonExcerpt: lessonExcerpt
27811
+ canonicalLessonExcerpt: slotMeta?.canonicalExcerpt ?? lessonExcerpt
27752
27812
  });
27753
27813
  };
27754
27814
  const actRelPath = `_content/${unitCode}/ACT_${lessonCode}.md`;
@@ -33384,6 +33444,7 @@ exports.dropCyclicConceptEdges = dropCyclicConceptEdges;
33384
33444
  exports.emitUsage = emitUsage;
33385
33445
  exports.ensureExpositionForLesson = ensureExpositionForLesson;
33386
33446
  exports.ensureKnowledgeExposition = ensureKnowledgeExposition;
33447
+ exports.evaluateActivityAlignment = evaluateActivityAlignment;
33387
33448
  exports.evaluateStandardsCoverage = evaluateStandardsCoverage;
33388
33449
  exports.executeCurriculumCommand = executeCurriculumCommand;
33389
33450
  exports.executeSlideProductionWorkflow = executeSlideProductionWorkflow;
@@ -33440,6 +33501,7 @@ exports.importRoadmapToProject = importRoadmapToProject;
33440
33501
  exports.ingestProjectGraphIntoProject = ingestProjectGraphIntoProject;
33441
33502
  exports.initializeProjectInStorage = initializeProjectInStorage;
33442
33503
  exports.injectMediaIntoMarkdown = injectMediaIntoMarkdown;
33504
+ exports.isActivityAlignmentLogOnly = isActivityAlignmentLogOnly;
33443
33505
  exports.isExpositionFresh = isExpositionFresh;
33444
33506
  exports.isModelAllowed = isModelAllowed;
33445
33507
  exports.isProviderEnabled = isProviderEnabled;