@thanh01.pmt/curriculum-kit 1.2.1 → 1.4.0

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.
@@ -1,8 +1,8 @@
1
1
  import { MilestoneInput, LessonPlan, CurriculumQualityReport, ActivityLab, CodeLab, SelfLab, DiagnosticQuiz, SlideDeck, Handout, Worksheet, TeacherGuide, Extension, ProjectRoadmap } from '../schemas/index.cjs';
2
2
  import { M as ModelResolutionOptions } from '../provider-factory-DxzOVEmh.cjs';
3
3
  import { G as GitPublishOptions, a as GitPublishResult, S as SupabasePublishOptions, b as SupabasePublishResult } from '../supabasePublisher-C627qXFT.cjs';
4
- import { S as SingleArtifactRequest, a as SingleArtifactResult } from '../gateSettings-Buk_MSML.cjs';
5
- export { b as CurriculumArtifactType, C as CurriculumGateMode, D as DEFAULT_GATE_SETTINGS, G as GateSettings, R as ResolvedGateSettings, g as gateModeFor, p as parseGateSettings, r as resolveGateSettings } from '../gateSettings-Buk_MSML.cjs';
4
+ import { S as SingleArtifactRequest, a as SingleArtifactResult } from '../gateSettings-L3FR2-MO.cjs';
5
+ export { b as CurriculumArtifactType, C as CurriculumGateMode, D as DEFAULT_GATE_SETTINGS, G as GateSettings, R as ResolvedGateSettings, g as gateModeFor, p as parseGateSettings, r as resolveGateSettings } from '../gateSettings-L3FR2-MO.cjs';
6
6
  import * as workflow from 'workflow';
7
7
  import { z } from 'zod';
8
8
  import { F as FrameworkPack, C as CoverageGateReport } from '../standardsCoverageGate-CsUNzv6C.cjs';
@@ -1,8 +1,8 @@
1
1
  import { MilestoneInput, LessonPlan, CurriculumQualityReport, ActivityLab, CodeLab, SelfLab, DiagnosticQuiz, SlideDeck, Handout, Worksheet, TeacherGuide, Extension, ProjectRoadmap } from '../schemas/index.js';
2
2
  import { M as ModelResolutionOptions } from '../provider-factory-DxzOVEmh.js';
3
3
  import { G as GitPublishOptions, a as GitPublishResult, S as SupabasePublishOptions, b as SupabasePublishResult } from '../supabasePublisher-C627qXFT.js';
4
- import { S as SingleArtifactRequest, a as SingleArtifactResult } from '../gateSettings-Buk_MSML.js';
5
- export { b as CurriculumArtifactType, C as CurriculumGateMode, D as DEFAULT_GATE_SETTINGS, G as GateSettings, R as ResolvedGateSettings, g as gateModeFor, p as parseGateSettings, r as resolveGateSettings } from '../gateSettings-Buk_MSML.js';
4
+ import { S as SingleArtifactRequest, a as SingleArtifactResult } from '../gateSettings-L3FR2-MO.js';
5
+ export { b as CurriculumArtifactType, C as CurriculumGateMode, D as DEFAULT_GATE_SETTINGS, G as GateSettings, R as ResolvedGateSettings, g as gateModeFor, p as parseGateSettings, r as resolveGateSettings } from '../gateSettings-L3FR2-MO.js';
6
6
  import * as workflow from 'workflow';
7
7
  import { z } from 'zod';
8
8
  import { F as FrameworkPack, C as CoverageGateReport } from '../standardsCoverageGate-CsUNzv6C.js';
@@ -6249,6 +6249,7 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
6249
6249
  }
6250
6250
  const slcMap = normalizeSlcContract(opts.sectionLanguageContract);
6251
6251
  const sections = parseMarkdownSections(source, slcMap, opts.artifactType);
6252
+ const metaBlock = buildMetaBlock(source);
6252
6253
  if (sections.length === 0) {
6253
6254
  issues.push("parse:no-sections");
6254
6255
  const excerpt2 = truncateByBudget(source, budget);
@@ -6282,12 +6283,13 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
6282
6283
  const block = `## ${heading}
6283
6284
 
6284
6285
  ${trimmedBody}`;
6285
- if (used + block.length > budget && blocks.length > 0) return false;
6286
+ if (used + block.length > budget && used > 0) return false;
6286
6287
  blocks.push(block);
6287
6288
  used += block.length;
6288
6289
  includedSections.push(key);
6289
6290
  return true;
6290
6291
  };
6292
+ blocks.push(metaBlock);
6291
6293
  let sectionAware = false;
6292
6294
  for (const key of priorities) {
6293
6295
  const sec = byCanonical.get(key);
@@ -6304,6 +6306,9 @@ ${trimmedBody}`;
6304
6306
  if (used >= budget) break;
6305
6307
  if (!tryAdd(sec.cleanTitle, sec.body, sec.cleanTitle)) break;
6306
6308
  }
6309
+ if (includedSections.length === 0 && unmatched.length > 0) {
6310
+ issues.push("parse:no-canonical-resolution");
6311
+ }
6307
6312
  if (priorities.length > 0 && !priorities.some((k) => includedSections.includes(k))) {
6308
6313
  issues.push("parse:no-priority-resolution");
6309
6314
  }
@@ -6312,14 +6317,14 @@ ${trimmedBody}`;
6312
6317
  excerpt = truncateByBudget(excerpt, budget);
6313
6318
  }
6314
6319
  const effectiveMinChars = Math.min(minContentChars, source.length);
6315
- if (excerpt.length < effectiveMinChars) {
6320
+ if (excerpt.length - metaBlock.length < effectiveMinChars) {
6316
6321
  issues.push("content:insufficient");
6317
6322
  }
6318
- const verified = !issues.includes("parse:no-priority-resolution") && excerpt.length >= effectiveMinChars;
6323
+ const verified = !issues.includes("parse:no-priority-resolution") && !issues.includes("parse:no-canonical-resolution") && excerpt.length - metaBlock.length >= effectiveMinChars;
6319
6324
  return {
6320
6325
  excerpt,
6321
6326
  verified,
6322
- sectionAware: sectionAware || priorities.length === 0 && sections.length > 0,
6327
+ sectionAware: sectionAware || unmatched.length === 0,
6323
6328
  includedSections,
6324
6329
  issues,
6325
6330
  tokenEstimate: Math.round(excerpt.length / 4)
@@ -6435,6 +6440,18 @@ function truncateByBudget(source, budget) {
6435
6440
  if (fenceCount % 2 === 1) cut += "\n```";
6436
6441
  return cut;
6437
6442
  }
6443
+ function buildMetaBlock(source) {
6444
+ const fm = source.match(/^---\s*\r?\n([\s\S]*?)\r?\n---/);
6445
+ const pick = (key) => {
6446
+ if (!fm) return "";
6447
+ const m = fm[1].match(new RegExp(`^${key}:\\s*"?([^"\\n]+)"?`, "m"));
6448
+ return (m?.[1] || "").trim();
6449
+ };
6450
+ const id = pick("id");
6451
+ const title = pick("title");
6452
+ const type = pick("type");
6453
+ return `<!-- SOURCE: ${type || "ARTIFACT"} | ${id || "unknown"}${title ? ` \u2014 ${title}` : ""} (section-aware excerpt; canonical knowledge, do not contradict) -->`;
6454
+ }
6438
6455
  init_errors();
6439
6456
 
6440
6457
  // src/services/languageDirective.ts
@@ -7016,6 +7033,24 @@ function getArtifactSpecializedInvariants(type, req) {
7016
7033
  const studentCount = req.studentCount || "25";
7017
7034
  switch (type) {
7018
7035
  case "slide": {
7036
+ if (req.slidesEngine === "html") {
7037
+ return `
7038
+ ### \u{1F3AC} INTERACTIVE HTML SLIDE ENGINE CONTRACT:
7039
+ You generate structured slide decks for the LearnWell HTML Slide Presentation Engine.
7040
+ Output a single valid JSON object matching: { "title": "...", "theme": "ocean", "slides": [{ "layoutId": "hero-cover", "slots": { ... }, "notes": "..." }] }
7041
+
7042
+ Layout Presets available:
7043
+ - hero-cover (title, subtitle, presenter, date, tag)
7044
+ - two-column-split (col1Title, col1Items[], col2Title, col2Items[])
7045
+ - code-explainer (filename, language, code, highlightLines, annotations[])
7046
+ - metrics-3-card (card1Title, card1Val, card1Desc, ...)
7047
+ - process-flow (steps: [{ label, desc, status }])
7048
+ - quiz-checkpoint (question, options[], answerIdx, explanation)
7049
+ - tiered-practice-3cards (foundation, standard, challenge cards)
7050
+ - takeaways-summary (takeaways: bullet points)
7051
+
7052
+ Mandatory Presenter Notes on every slide with Talk Track, Cold-Call, and Scaffolding Tip.`;
7053
+ }
7019
7054
  const slideCount = cfg.slideCount || 10;
7020
7055
  const presentationStyle = cfg.presentationStyle || "modern";
7021
7056
  const presentationDuration = cfg.presentationDuration || 45;