@thanh01.pmt/curriculum-kit 1.4.37 → 1.4.39

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
@@ -1532,6 +1532,8 @@ function parseLessonFlow(lessonMarkdown) {
1532
1532
  purpose: cells[4] || "",
1533
1533
  studentAction: cells[5] || "",
1534
1534
  teacherMove: cells[6] || "",
1535
+ outputEvidence: cells[7] || "",
1536
+ lo: (cells[8] || "").replace(/\*/g, "").split(/[,;/\s]+/).map((s) => s.trim()).filter(Boolean),
1535
1537
  time: cells[9] || cells[cells.length - 2] || "",
1536
1538
  artifactContract: cells[cells.length - 1] || ""
1537
1539
  });
@@ -2839,11 +2841,51 @@ var ExtensionSchema = zod.z.object({
2839
2841
  });
2840
2842
  var QualityAuditVerdictSchema = zod.z.enum(["PASS", "NEEDS_REVISION", "FAIL"]);
2841
2843
  var JudgeCriterionSchema = zod.z.object({
2842
- name: zod.z.string().describe("Criterion name, e.g. Bloom Alignment, Code Validity, Word Count Gate, Language Adherence"),
2844
+ name: zod.z.string().describe("Criterion name, e.g. Bloom Alignment, Code Validity, Word Count Gate, Language Adherence, Step Incrementality"),
2843
2845
  passed: zod.z.boolean(),
2844
2846
  score: zod.z.number().min(0).max(100).describe("Score out of 100"),
2845
2847
  feedback: zod.z.string().describe("Constructive feedback or citation of issues")
2846
2848
  });
2849
+ var ActionableRepairActionSchema = zod.z.enum([
2850
+ "SPLIT_STEP",
2851
+ "REVISE_PROVISIONING",
2852
+ "INSERT_RECAP",
2853
+ "ADJUST_TIME_BUDGET",
2854
+ "SUBSTITUTE_FALLBACK",
2855
+ "REVISE_EXIT_EVIDENCE"
2856
+ ]);
2857
+ var ActionableRepairPromptSchema = zod.z.object({
2858
+ action: ActionableRepairActionSchema,
2859
+ targetId: zod.z.string().describe("ID of the session, feature, or step requiring repair, e.g. U01_M01_L02 or F1-S3"),
2860
+ severity: zod.z.enum(["CRITICAL", "WARNING", "INFO"]).default("WARNING"),
2861
+ rationale: zod.z.string().describe("Pedagogical or technical rationale for why this repair is mandated"),
2862
+ instruction: zod.z.string().describe("Exact, actionable text instruction for the planner/generator in the next turn")
2863
+ });
2864
+ var ProjectGraphAuditSchema = zod.z.object({
2865
+ schema_version: zod.z.number().default(1),
2866
+ projectId: zod.z.string(),
2867
+ overallVerdict: QualityAuditVerdictSchema,
2868
+ totalScore: zod.z.number().min(0).max(100),
2869
+ toolchainFeasibility: JudgeCriterionSchema.describe("Installation friction, admin rights, IDE/compiler matrix"),
2870
+ provisioningStrategy: JudgeCriterionSchema.describe("Clear model for heavy runtimes: Pre-installed lab, Cloud instance, or Dedicated setup"),
2871
+ hardwareRuntimeEnvelope: JudgeCriterionSchema.describe("Memory/Flash limits, pinout conflicts, hardware platform alignment"),
2872
+ timeToHelloWorld: JudgeCriterionSchema.describe("Student time to achieve first working feedback loop (target <= 15 mins)"),
2873
+ actionableRepairs: zod.z.array(ActionableRepairPromptSchema).default([])
2874
+ });
2875
+ var MacroPedagogyPlanAuditSchema = zod.z.object({
2876
+ schema_version: zod.z.number().default(1),
2877
+ planHash: zod.z.string(),
2878
+ overallVerdict: QualityAuditVerdictSchema,
2879
+ totalScore: zod.z.number().min(0).max(100),
2880
+ autoApproved: zod.z.boolean().default(false).describe("True if totalScore >= 85 and overallVerdict is PASS"),
2881
+ stepIncrementality: JudgeCriterionSchema.describe("Single leap principle: <= 1 new syntax or 1 new algorithm per step"),
2882
+ zpdSaturation: JudgeCriterionSchema.describe("Vygotsky ZPD: <= 2 new concepts per session (K-12) / 3 (Adults), with prior anchor"),
2883
+ frictionAdjustedBudget: JudgeCriterionSchema.describe("Student time multiplier (2.5x): total content <= 85% session minutes"),
2884
+ epitomeViability: JudgeCriterionSchema.describe("Reigeluth Walking Skeleton: Unit 1 produces an end-to-end runnable MVP"),
2885
+ exitEvidenceSpecificity: JudgeCriterionSchema.describe("Tangible, measurable student deliverable for every session"),
2886
+ actionableRepairs: zod.z.array(ActionableRepairPromptSchema).default([]),
2887
+ summary: zod.z.string().describe("High-level executive evaluation summary")
2888
+ });
2847
2889
  var CurriculumQualityReportSchema = zod.z.object({
2848
2890
  targetArtifactType: zod.z.string().describe("Type of artifact audited, e.g. LESSON, ACT, CODE, WKS, SLIDE"),
2849
2891
  lessonId: zod.z.string(),
@@ -2851,7 +2893,8 @@ var CurriculumQualityReportSchema = zod.z.object({
2851
2893
  totalScore: zod.z.number().min(0).max(100),
2852
2894
  languageAdherencePassed: zod.z.boolean().describe("True if content strictly matches the requested target language"),
2853
2895
  criteria: zod.z.array(JudgeCriterionSchema).min(3),
2854
- actionableRepairPrompts: zod.z.array(zod.z.string()).default([]).describe("Concrete instruction prompts to fix detected issues in the next repair turn")
2896
+ actionableRepairPrompts: zod.z.array(zod.z.string()).default([]).describe("Concrete instruction prompts to fix detected issues in the next repair turn"),
2897
+ structuredRepairs: zod.z.array(ActionableRepairPromptSchema).optional()
2855
2898
  });
2856
2899
  var ProjectProfileSchema = zod.z.object({
2857
2900
  id: zod.z.string().optional(),
@@ -6735,6 +6778,111 @@ Please return a single JSON object matching these exact keys:
6735
6778
  - "actionableRepairPrompts": string[]
6736
6779
  `.trim();
6737
6780
  }
6781
+ function buildCurriculumPlanJudgePrompt(input) {
6782
+ const { planJson, briefingContext, expectedLanguage = "Vietnamese", linterFindings = [] } = input;
6783
+ return `
6784
+ # System Methodology: Principal Curriculum SME & Macro-Pedagogical Quality Judge (@sme_judge)
6785
+
6786
+ You are the **Lead Curriculum Architect & Classroom Practicum SME**. Your role is to rigorously evaluate a candidate \`CURRICULUM_PLAN\` (Schema v3) against empirical pedagogical science, cognitive load capacity, and real classroom delivery constraints.
6787
+
6788
+ ## COURSE BRIEFING & TARGET CONSTRAINTS
6789
+ ${briefingContext}
6790
+
6791
+ ${linterFindings.length > 0 ? `## DETERMINISTIC PRE-LINT FINDINGS (0-TOKEN LINTER)
6792
+ The deterministic structural linter detected the following issues in advance:
6793
+ ${linterFindings.map((f) => `- [${f.severity}] ${f.id}: ${f.title} \u2014 ${f.description}`).join("\n")}
6794
+ Consider these deterministic findings when scoring and issuing actionable repair prescriptions.` : ""}
6795
+
6796
+ ## CANDIDATE CURRICULUM PLAN JSON
6797
+ \`\`\`json
6798
+ ${planJson}
6799
+ \`\`\`
6800
+
6801
+ ## EVALUATION RUBRICS & 5 CRITICAL DIMENSIONS (TOTAL 100 POINTS)
6802
+
6803
+ 1. **Step Incrementality & Single Leap Principle (20 pts):**
6804
+ - 20 pts: Every session introduces at most ONE new syntax or algorithmic concept. No massive cognitive leaps (e.g. going from basic variables directly to asynchronous networking).
6805
+ - 10 pts: Minor leap detected in 1 session that can be mitigated with starter code.
6806
+ - 0 pts: Severe cognitive gap (e.g. multiple compound paradigms combined in one session).
6807
+
6808
+ 2. **Vygotsky ZPD Saturation & Cognitive Capacity (20 pts):**
6809
+ - 20 pts: New concept count <= 2 per session (K-12) / 3 (Adults), with explicit prior concept anchor or recap slot.
6810
+ - 10 pts: Session introduces 3 concepts without adequate bridge.
6811
+ - 0 pts: Severe overload (>3 new concepts in a single session) or unanchored concepts.
6812
+
6813
+ 3. **Classroom Friction-Adjusted Time Budget (20 pts):**
6814
+ - 20 pts: Incorporates 2.5x student friction multiplier. Total content minutes <= 85% of session duration (15% overhead reserved). No step > 76 minutes.
6815
+ - 10 pts: Content is slightly packed, leaving < 10% buffer time.
6816
+ - 0 pts: Overpacked content that will cause students to run out of time in a standard classroom.
6817
+
6818
+ 4. **Reigeluth Walking Skeleton & Milestone Agency (20 pts):**
6819
+ - 20 pts: Unit 1 culminates in an end-to-end runnable MVP (Epitome). Subsequent units provide modular elaborations.
6820
+ - 10 pts: Walking skeleton present but delayed to Unit 2.
6821
+ - 0 pts: Pure theoretical silo teaching where no working product appears until the end of the course.
6822
+
6823
+ 5. **Exit Evidence Specificity (20 pts):**
6824
+ - 20 pts: Every session produces an explicit, tangible, user-visible deliverable (e.g. running UI screen, passing test suite, physical LED sequence).
6825
+ - 10 pts: Some sessions have generic deliverables ("completed practice exercise").
6826
+ - 0 pts: Vague or absent deliverables ("student understands topic").
6827
+
6828
+ ## DECISION RULES
6829
+ - **PASS & AUTO-APPROVE:** Total Score >= 85 AND overallVerdict is "PASS" AND no CRITICAL actionable repairs.
6830
+ - **NEEDS_REVISION:** Total Score between 70 and 84, or fixable flaws. Prescribe concrete structured \`actionableRepairs\` (\`SPLIT_STEP\`, \`INSERT_RECAP\`, \`ADJUST_TIME_BUDGET\`, \`REVISE_EXIT_EVIDENCE\`).
6831
+ - **FAIL:** Total Score < 70, structural collapse, or unbridgeable pedagogical gaps.
6832
+
6833
+ ## OUTPUT FORMAT
6834
+ Return a valid JSON object matching the MacroPedagogyPlanAuditSchema.
6835
+ `.trim();
6836
+ }
6837
+ function buildProjectGraphJudgePrompt(input) {
6838
+ const { bundleJson, briefingContext, linterFindings = [] } = input;
6839
+ return `
6840
+ # System Methodology: Lead Systems Engineer & Lab Infrastructure Auditor (@infra_judge)
6841
+
6842
+ You are the **Lead Lab Systems Engineer**. Your role is to rigorously evaluate a candidate \`PROJECT_GRAPH\` and its associated \`technology_scope\` against real-world lab environment feasibility, toolchain friction, and hardware constraints.
6843
+
6844
+ ## COURSE BRIEFING & INFRASTRUCTURE CONSTRAINTS
6845
+ ${briefingContext}
6846
+
6847
+ ${linterFindings.length > 0 ? `## DETERMINISTIC PRE-LINT FINDINGS
6848
+ ${linterFindings.map((f) => `- [${f.severity}] ${f.id}: ${f.title} \u2014 ${f.description}`).join("\n")}` : ""}
6849
+
6850
+ ## CANDIDATE PROJECT GRAPH BUNDLE JSON
6851
+ \`\`\`json
6852
+ ${bundleJson}
6853
+ \`\`\`
6854
+
6855
+ ## EVALUATION RUBRICS & 4 DIMENSIONS (TOTAL 100 POINTS)
6856
+
6857
+ 1. **Toolchain & Installation Feasibility (25 pts):**
6858
+ - 25 pts: Toolchain installs cleanly without complex admin rights, OS friction, or fragile build scripts.
6859
+ - 10 pts: Toolchain requires moderate admin setup, suitable for guided lab but risky for BYOD.
6860
+ - 0 pts: High-friction setup that frequently breaks in student environments.
6861
+
6862
+ 2. **Environment Provisioning Strategy (25 pts):**
6863
+ - 25 pts: Heavy technologies (PostgreSQL, Docker, ROS2, etc.) declare an explicit, realistic provisioning model (\`PRE_INSTALLED_LAB\`, \`CLOUD_MANAGED\`, or \`DEDICATED_SETUP\`). Core course topics are NEVER downgraded; instead, proper infrastructure is specified.
6864
+ - 10 pts: Heavy tech used with ambiguous provisioning plan.
6865
+ - 0 pts: Heavy tech dumped on students with no provisioning strategy, causing setup collapse.
6866
+
6867
+ 3. **Hardware & Runtime Envelope (25 pts):**
6868
+ - 25 pts: Code, libraries, and algorithms fit comfortably within target device RAM, Flash, and pinout budget (<= 75% envelope).
6869
+ - 10 pts: Memory or resource limits are tight.
6870
+ - 0 pts: Guaranteed hardware crash or pinout conflict.
6871
+
6872
+ 4. **Time to Hello World (25 pts):**
6873
+ - 25 pts: First working runnable milestone achieved in <= 15 minutes of student effort.
6874
+ - 10 pts: First milestone takes 20-30 minutes.
6875
+ - 0 pts: Student spends the entire first session on environment configuration without seeing running code.
6876
+
6877
+ ## DECISION RULES
6878
+ - **PASS:** Score >= 85 AND overallVerdict is "PASS".
6879
+ - **NEEDS_REVISION:** Score between 70 and 84. Prescribe structured actionable repairs.
6880
+ - **FAIL:** Score < 70 or critical environment blocker.
6881
+
6882
+ ## OUTPUT FORMAT
6883
+ Return a valid JSON object matching ProjectGraphAuditSchema.
6884
+ `.trim();
6885
+ }
6738
6886
 
6739
6887
  // src/ai/prompts/projectInstructionPrompt.ts
6740
6888
  function buildProjectInstructionPrompt(input) {
@@ -7176,6 +7324,23 @@ async function generateExtensionFlow(input) {
7176
7324
 
7177
7325
  // src/ai/flows/auditCurriculumQualityFlow.ts
7178
7326
  init_provider_factory();
7327
+
7328
+ // src/constants/pedagogy.ts
7329
+ var STUDENT_FRICTION_MULTIPLIER = 2.5;
7330
+ var MAX_NEW_CONCEPTS_PER_SESSION_K12 = 2;
7331
+ var MAX_NEW_CONCEPTS_PER_SESSION_ADULT = 3;
7332
+ var DEFAULT_OVERHEAD_RATIO = 0.15;
7333
+ var MAX_IN_SESSION_SETUP_MINUTES = 15;
7334
+ var ENVIRONMENT_PROVISIONING_MODELS = [
7335
+ "PRE_INSTALLED_LAB",
7336
+ "CLOUD_MANAGED",
7337
+ "DEDICATED_SETUP"
7338
+ ];
7339
+ var JUDGE_AUTO_APPROVE_THRESHOLD = 85;
7340
+ var JUDGE_ESCALATE_THRESHOLD = 70;
7341
+ var MAX_AUTONOMOUS_REPAIR_TURNS = 3;
7342
+
7343
+ // src/ai/flows/auditCurriculumQualityFlow.ts
7179
7344
  async function auditCurriculumQualityFlow(input) {
7180
7345
  const model = getAIModel(input.modelOptions);
7181
7346
  const prompt = buildJudgePrompt({
@@ -7191,6 +7356,43 @@ async function auditCurriculumQualityFlow(input) {
7191
7356
  schema: CurriculumQualityReportSchema,
7192
7357
  prompt: `${prompt}
7193
7358
 
7359
+ Respond with a valid JSON object matching the schema.`
7360
+ });
7361
+ return object;
7362
+ }
7363
+ async function auditCurriculumPlanFlow(input) {
7364
+ const model = getAIModel(input.modelOptions);
7365
+ const prompt = buildCurriculumPlanJudgePrompt({
7366
+ planJson: input.planJson,
7367
+ briefingContext: input.briefingContext,
7368
+ expectedLanguage: input.expectedLanguage,
7369
+ linterFindings: input.linterFindings
7370
+ });
7371
+ const { object } = await ai.generateObject({
7372
+ model,
7373
+ schema: MacroPedagogyPlanAuditSchema,
7374
+ prompt: `${prompt}
7375
+
7376
+ Respond with a valid JSON object matching the schema.`
7377
+ });
7378
+ const autoApproved = object.totalScore >= JUDGE_AUTO_APPROVE_THRESHOLD && object.overallVerdict === "PASS";
7379
+ return {
7380
+ ...object,
7381
+ autoApproved
7382
+ };
7383
+ }
7384
+ async function auditProjectGraphFlow(input) {
7385
+ const model = getAIModel(input.modelOptions);
7386
+ const prompt = buildProjectGraphJudgePrompt({
7387
+ bundleJson: input.bundleJson,
7388
+ briefingContext: input.briefingContext,
7389
+ linterFindings: input.linterFindings
7390
+ });
7391
+ const { object } = await ai.generateObject({
7392
+ model,
7393
+ schema: ProjectGraphAuditSchema,
7394
+ prompt: `${prompt}
7395
+
7194
7396
  Respond with a valid JSON object matching the schema.`
7195
7397
  });
7196
7398
  return object;
@@ -26448,6 +26650,195 @@ function extractStandardRefs(text) {
26448
26650
  return Array.from(new Set(matches));
26449
26651
  }
26450
26652
 
26653
+ // src/parsers/lessonEntity.ts
26654
+ init_lessonFlowParser();
26655
+ var LessonEntitySchema = zod.z.object({
26656
+ lessonId: zod.z.string(),
26657
+ title: zod.z.string(),
26658
+ pedagogyModel: zod.z.string().default("5e"),
26659
+ estimatedDuration: zod.z.string().default(""),
26660
+ learningObjectives: zod.z.array(LearningObjectiveRowSchema).default([]),
26661
+ activitySequence: zod.z.array(ActivitySeqRowSchema).default([]),
26662
+ /** Header→cell rows straight from the A4 Assessment Map table (headers vary by template). */
26663
+ assessmentMap: zod.z.array(zod.z.record(zod.z.string())).default([]),
26664
+ tieredScaffolding: zod.z.object({ bronze: zod.z.string().default(""), silver: zod.z.string().default(""), gold: zod.z.string().default("") }).default({ bronze: "", silver: "", gold: "" })
26665
+ });
26666
+ var stripMd = (s) => s.replace(/\*\*/g, "").replace(/`/g, "").trim();
26667
+ function splitRow(line) {
26668
+ return line.trim().replace(/^\|/, "").replace(/\|$/, "").split("|").map((c) => c.trim());
26669
+ }
26670
+ function toActivitySeqRows(md) {
26671
+ const flow = parseLessonFlow(md);
26672
+ const rows = [];
26673
+ for (const a of flow.activities) {
26674
+ const parsed = ActivitySeqRowSchema.safeParse({
26675
+ seq: a.seq,
26676
+ phase: a.phase,
26677
+ activityType: a.activityType,
26678
+ actor: a.actor,
26679
+ purpose: a.purpose,
26680
+ studentAction: a.studentAction,
26681
+ teacherMove: a.teacherMove,
26682
+ outputEvidence: a.outputEvidence,
26683
+ lo: a.lo,
26684
+ durationMinutes: parseInt((a.time || "").replace(/[^0-9]/g, ""), 10) || 10,
26685
+ artifactContract: a.artifactContract
26686
+ });
26687
+ if (parsed.success) rows.push(parsed.data);
26688
+ }
26689
+ return rows;
26690
+ }
26691
+ function parseLearningObjectives(md) {
26692
+ const rows = [];
26693
+ let inLO = false;
26694
+ let headerSeen = false;
26695
+ for (const line of md.split("\n")) {
26696
+ const h = line.match(/^#{2,4}\s+(.*)$/);
26697
+ if (h) {
26698
+ if (/learning\s+objectives/i.test(h[1] ?? "")) inLO = true;
26699
+ else if (inLO) break;
26700
+ continue;
26701
+ }
26702
+ if (!inLO) continue;
26703
+ const t = line.trim();
26704
+ if (!t.startsWith("|")) continue;
26705
+ if (/^[\s|:-]+$/.test(t)) continue;
26706
+ const cells = splitRow(t);
26707
+ if (cells.length < 4) continue;
26708
+ if (!headerSeen) {
26709
+ headerSeen = true;
26710
+ continue;
26711
+ }
26712
+ const parsed = LearningObjectiveRowSchema.safeParse({
26713
+ code: stripMd(cells[0] ?? ""),
26714
+ objective: stripMd(cells[1] ?? ""),
26715
+ evidence: stripMd(cells[2] ?? ""),
26716
+ successCriteria: stripMd(cells[3] ?? ""),
26717
+ standardRefs: cells[4] ?? "" ? cells[4].split(/[\s,;]+/).filter(Boolean) : [],
26718
+ conceptRefs: []
26719
+ });
26720
+ if (parsed.success) rows.push(parsed.data);
26721
+ }
26722
+ return rows;
26723
+ }
26724
+ function parseAssessmentMap(md) {
26725
+ const rows = [];
26726
+ let inMap = false;
26727
+ let headers = [];
26728
+ for (const line of md.split("\n")) {
26729
+ const h = line.match(/^#{2,4}\s+(.*)$/);
26730
+ if (h) {
26731
+ if (/assessment\s*map/i.test(h[1] ?? "")) inMap = true;
26732
+ else if (inMap) break;
26733
+ continue;
26734
+ }
26735
+ if (!inMap) continue;
26736
+ const t = line.trim();
26737
+ if (!t.startsWith("|")) continue;
26738
+ if (/^[\s|:-]+$/.test(t)) continue;
26739
+ const cells = splitRow(t);
26740
+ if (headers.length === 0) {
26741
+ headers = cells;
26742
+ continue;
26743
+ }
26744
+ const row = {};
26745
+ headers.forEach((hdr, i) => {
26746
+ row[hdr] = stripMd(cells[i] ?? "");
26747
+ });
26748
+ rows.push(row);
26749
+ }
26750
+ return rows;
26751
+ }
26752
+ function parseTieredScaffolding(md) {
26753
+ const lines = md.split("\n");
26754
+ let capture = null;
26755
+ for (const line of lines) {
26756
+ const h = line.match(/^#{2,4}\s+(.*)$/);
26757
+ if (h) {
26758
+ const isTier = /elaborate|tiered|scaffold/i.test(h[1] ?? "");
26759
+ if (capture && !isTier) break;
26760
+ if (isTier) capture = [];
26761
+ continue;
26762
+ }
26763
+ if (capture) capture.push(line);
26764
+ }
26765
+ const body = (capture ?? []).join("\n");
26766
+ const grab = (label) => {
26767
+ const m = body.match(new RegExp(`(?:\\ud83e\\udd49|\\ud83e\\udd48|\\ud83e\\udd47)?\\s*\\*\\*${label}:\\*\\*\\s*([^\\n]+)`, "i"));
26768
+ return m ? m[1].trim() : "";
26769
+ };
26770
+ return { bronze: grab("Bronze"), silver: grab("Silver"), gold: grab("Gold") };
26771
+ }
26772
+ function buildLessonEntityJson(lessonMarkdown) {
26773
+ const md = lessonMarkdown || "";
26774
+ if (!md.trim()) return null;
26775
+ const flow = parseLessonFlow(md);
26776
+ const fm = md.match(/^---\s*\n([\s\S]*?)\n---/)?.[1] ?? "";
26777
+ const activitySequence = toActivitySeqRows(md);
26778
+ const learningObjectives = parseLearningObjectives(md);
26779
+ if (activitySequence.length === 0 && learningObjectives.length === 0) return null;
26780
+ const parsed = LessonEntitySchema.safeParse({
26781
+ lessonId: flow.lessonId || (fm.match(/id:\s*["']?([^"'\n]+)["']?/i)?.[1]?.trim() ?? ""),
26782
+ title: flow.lessonTitle,
26783
+ pedagogyModel: flow.pedagogicalModel,
26784
+ estimatedDuration: flow.estimatedDuration,
26785
+ learningObjectives,
26786
+ activitySequence,
26787
+ assessmentMap: parseAssessmentMap(md),
26788
+ tieredScaffolding: parseTieredScaffolding(md)
26789
+ });
26790
+ return parsed.success ? parsed.data : null;
26791
+ }
26792
+ function renderEntitySlotsForType(entity, artifactType, maxChars = 8e3) {
26793
+ const type = (artifactType || "").toUpperCase().trim();
26794
+ const parts = [];
26795
+ const wantActivities = ["ACT", "GUIDE", "SLIDE", "WKS", "QUIZ"].includes(type);
26796
+ const wantObjectives = type !== "CODE";
26797
+ const wantAssessment = ["QUIZ", "WKS"].includes(type);
26798
+ const wantTiers = ["ACT", "CODE", "EXT", "WKS"].includes(type);
26799
+ if (wantObjectives && entity.learningObjectives.length > 0) {
26800
+ parts.push(
26801
+ "### Learning Objectives & Evidence\n" + entity.learningObjectives.map((o) => `- ${o.code}: ${o.objective} \u2192 Evidence: ${o.evidence} | Pass: ${o.successCriteria}`).join("\n")
26802
+ );
26803
+ }
26804
+ if (wantActivities && entity.activitySequence.length > 0) {
26805
+ const header = "| Seq | Phase | Activity | Actor | Student Action | Teacher Move | Output/Evidence | LO | Mins | Artifact Contract |";
26806
+ const rows = [];
26807
+ for (const a of entity.activitySequence) {
26808
+ const r = `| ${a.seq} | ${a.phase} | ${a.activityType} | ${a.actor} | ${a.studentAction} | ${a.teacherMove} | ${a.outputEvidence} | ${a.lo.join(",")} | ${a.durationMinutes} | ${a.artifactContract} |`;
26809
+ if (parts.join("\n\n").length + r.length > maxChars) break;
26810
+ rows.push(r);
26811
+ }
26812
+ if (rows.length > 0) {
26813
+ parts.push("### Activity Sequence\n" + [header, "|---|---|---|---|---|---|---|---|---|---|", ...rows].join("\n"));
26814
+ }
26815
+ }
26816
+ if (wantAssessment && entity.assessmentMap.length > 0) {
26817
+ const lines = entity.assessmentMap.map((r) => Object.entries(r).map(([k, v]) => `${k}: ${v}`).join(" | "));
26818
+ parts.push("### Assessment Map (assess exactly these)\n" + lines.join("\n"));
26819
+ }
26820
+ const t = entity.tieredScaffolding;
26821
+ if (wantTiers && (t.bronze || t.silver || t.gold)) {
26822
+ parts.push(
26823
+ "### Tiered task ladder\n" + [t.bronze && `- Bronze: ${t.bronze}`, t.silver && `- Silver: ${t.silver}`, t.gold && `- Gold: ${t.gold}`].filter(Boolean).join("\n")
26824
+ );
26825
+ }
26826
+ return parts.join("\n\n").slice(0, maxChars);
26827
+ }
26828
+ function entityRowAssignedTo(row, artifactType) {
26829
+ const norm2 = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
26830
+ const wanted = norm2(artifactType);
26831
+ return row.artifactContract.split(/[,;/]/).map((c) => norm2(c)).some((c) => c === wanted || c.length > 3 && (c.includes(wanted) || wanted.includes(c)));
26832
+ }
26833
+ function renderAssignedRowsTable(entity, artifactType, maxChars = 1500) {
26834
+ const rows = entity.activitySequence.filter((r) => entityRowAssignedTo(r, artifactType));
26835
+ if (rows.length === 0) return "";
26836
+ const header = "| Seq | Phase | Activity | Actor | Student Action | Teacher Move | Output/Evidence | LO | Mins | Artifact Contract |";
26837
+ const sep = "|---|---|---|---|---|---|---|---|---|---|";
26838
+ const body = rows.map((a) => `| ${a.seq} | ${a.phase} | ${a.activityType} | ${a.actor} | ${a.studentAction} | ${a.teacherMove} | ${a.outputEvidence} | ${a.lo.join(",")} | ${a.durationMinutes} | ${a.artifactContract} |`);
26839
+ return [header, sep, ...body].join("\n").slice(0, maxChars);
26840
+ }
26841
+
26451
26842
  // src/services/contextSlots.ts
26452
26843
  var LESSON_SLOT_BUDGETS = {
26453
26844
  ACT: { budget: 8e3 },
@@ -26567,6 +26958,7 @@ function buildSatelliteContext(input) {
26567
26958
  slcMarkdown,
26568
26959
  symbolLedgerBlock,
26569
26960
  pedagogyLabel,
26961
+ lessonEntity,
26570
26962
  mode = "legacy"
26571
26963
  } = input;
26572
26964
  const type = (artifactType || "").toUpperCase().trim();
@@ -26611,30 +27003,57 @@ ${kxExcerpt.excerpt}`);
26611
27003
  }
26612
27004
  if (!KX_ONLY_TYPES.has(type)) {
26613
27005
  const spec = LESSON_SLOT_BUDGETS[type] ?? { budget: 12e3 };
26614
- const excerpt = buildSectionAwareExcerpt(lessonContent, {
26615
- priorities: spec.priorities ?? ["Artifact Contract", "A. Lesson Design Plan", "B. Lesson Flow", "Learning Objectives & Evidence", "Activity Sequence"],
26616
- budget: spec.budget,
26617
- sectionLanguageContract: slcMarkdown,
26618
- artifactType: "LESSON"
26619
- });
26620
- const excerptBlock = `
27006
+ let usedEntity = false;
27007
+ if (lessonEntity) {
27008
+ const slots = renderEntitySlotsForType(lessonEntity, type, spec.budget);
27009
+ if (slots) {
27010
+ const slotBlock = `
27011
+
27012
+ [LESSON ENTITY SLOTS (structured JSON source \u2014 canonical)]:
27013
+ ${slots}`;
27014
+ parts.push(slotBlock);
27015
+ excerptSlot = slotBlock;
27016
+ blocks.push(blockMeta("lessonEntity:" + type, "LESSON_JSON", slots, true));
27017
+ usedEntity = true;
27018
+ } else {
27019
+ issues.push(`lesson-entity:empty-slots:${type}`);
27020
+ }
27021
+ }
27022
+ if (!usedEntity) {
27023
+ const excerpt = buildSectionAwareExcerpt(lessonContent, {
27024
+ priorities: spec.priorities ?? ["Artifact Contract", "A. Lesson Design Plan", "B. Lesson Flow", "Learning Objectives & Evidence", "Activity Sequence"],
27025
+ budget: spec.budget,
27026
+ sectionLanguageContract: slcMarkdown,
27027
+ artifactType: "LESSON"
27028
+ });
27029
+ const excerptBlock = `
26621
27030
 
26622
27031
  [CANONICAL LESSON PLAN (scoped for ${type})]:
26623
27032
  ${excerpt.excerpt}`;
26624
- parts.push(excerptBlock);
26625
- excerptSlot = excerptBlock;
26626
- blocks.push(blockMeta("lessonExcerpt:" + type, "LESSON", excerpt.excerpt, excerpt.verified, excerpt.issues));
26627
- if (!excerpt.verified) issues.push(...excerpt.issues.map((i) => `lesson:${i}`));
26628
- if (type === "QUIZ" || type === "WKS") {
26629
- const am = extractAssessmentMap(lessonContent, 1200);
26630
- if (am) {
26631
- parts.push(`
27033
+ parts.push(excerptBlock);
27034
+ excerptSlot = excerptBlock;
27035
+ blocks.push(blockMeta("lessonExcerpt:" + type, "LESSON", excerpt.excerpt, excerpt.verified, excerpt.issues));
27036
+ if (!excerpt.verified) issues.push(...excerpt.issues.map((i) => `lesson:${i}`));
27037
+ if (type === "QUIZ" || type === "WKS") {
27038
+ if (lessonEntity && lessonEntity.assessmentMap.length > 0) {
27039
+ const amJson = lessonEntity.assessmentMap.map((r) => Object.entries(r).map(([k, v]) => `${k}: ${v}`).join(" | ")).join("\n");
27040
+ parts.push(`
27041
+
27042
+ [ASSESSMENT MAP (criteria anchor \u2014 assess exactly these)]:
27043
+ ${amJson}`);
27044
+ blocks.push(blockMeta("assessmentMap:" + type, "LESSON_JSON", amJson, true));
27045
+ } else {
27046
+ const am = extractAssessmentMap(lessonContent, 1200);
27047
+ if (am) {
27048
+ parts.push(`
26632
27049
 
26633
27050
  [ASSESSMENT MAP (criteria anchor \u2014 assess exactly these)]:
26634
27051
  ${am}`);
26635
- blocks.push(blockMeta("assessmentMap:" + type, "LESSON", am, true));
26636
- } else {
26637
- issues.push(`assessment-map:unresolved:${type}`);
27052
+ blocks.push(blockMeta("assessmentMap:" + type, "LESSON", am, true));
27053
+ } else {
27054
+ issues.push(`assessment-map:unresolved:${type}`);
27055
+ }
27056
+ }
26638
27057
  }
26639
27058
  }
26640
27059
  if (symbolLedgerBlock) {
@@ -26642,14 +27061,27 @@ ${am}`);
26642
27061
  blocks.push(blockMeta("symbolLedger", "LESSON", symbolLedgerBlock, true));
26643
27062
  }
26644
27063
  } else {
26645
- const contractRows = extractActivityContractRows(lessonContent, type === "CODE" ? "CODE_LAB" : type, 1500);
26646
- const tierBlock = type === "CODE" || type === "EXT" ? extractTieredScaffoldingBlock(lessonContent, 900) : "";
26647
- const mini = [
26648
- contractRows ? `### Activity Sequence rows assigned to ${type} (canonical \u2014 do not invent a different task):
26649
- ${contractRows}` : "",
26650
- tierBlock ? `### Tiered task ladder (from LESSON Elaborate phase):
26651
- ${tierBlock}` : ""
26652
- ].filter(Boolean).join("\n\n");
27064
+ const miniParts = [];
27065
+ if (lessonEntity) {
27066
+ const rowsTable = renderAssignedRowsTable(lessonEntity, type === "CODE" ? "CODE_LAB" : type, 1500);
27067
+ if (rowsTable) miniParts.push(`### Activity Sequence rows assigned to ${type} (canonical \u2014 do not invent a different task):
27068
+ ${rowsTable}`);
27069
+ const t = lessonEntity.tieredScaffolding;
27070
+ if ((type === "CODE" || type === "EXT") && (t.bronze || t.silver || t.gold)) {
27071
+ miniParts.push(
27072
+ "### Tiered task ladder (from LESSON Elaborate phase):\n" + [t.bronze && `- Bronze: ${t.bronze}`, t.silver && `- Silver: ${t.silver}`, t.gold && `- Gold: ${t.gold}`].filter(Boolean).join("\n")
27073
+ );
27074
+ }
27075
+ }
27076
+ if (miniParts.length === 0) {
27077
+ const contractRows = extractActivityContractRows(lessonContent, type === "CODE" ? "CODE_LAB" : type, 1500);
27078
+ const tierBlock = type === "CODE" || type === "EXT" ? extractTieredScaffoldingBlock(lessonContent, 900) : "";
27079
+ if (contractRows) miniParts.push(`### Activity Sequence rows assigned to ${type} (canonical \u2014 do not invent a different task):
27080
+ ${contractRows}`);
27081
+ if (tierBlock) miniParts.push(`### Tiered task ladder (from LESSON Elaborate phase):
27082
+ ${tierBlock}`);
27083
+ }
27084
+ const mini = miniParts.join("\n\n");
26653
27085
  if (mini) {
26654
27086
  const miniBlock = `
26655
27087
 
@@ -27343,7 +27775,9 @@ ${sg}${standardsBlock}${glossaryBlock}${buildGroundTruthBlock(includeKx)}${sessi
27343
27775
  });
27344
27776
  const producedArtifacts = [];
27345
27777
  const lessonRelPath = `_content/${unitCode}/LESSON_${lessonCode}.md`;
27778
+ const lessonEntityRelPath = `_content/${unitCode}/LESSON_${lessonCode}.json`;
27346
27779
  const existingLessonContent = await storage.readArtifact(projectId, lessonRelPath);
27780
+ let lessonEntity = buildLessonEntityJson(existingLessonContent || "");
27347
27781
  let lessonContent = existingLessonContent || "";
27348
27782
  if (artifactScope.includes("LESSON") && (!existingLessonContent || force || isStaleVsPlan(existingLessonContent))) {
27349
27783
  if (existingLessonContent && !force && isStaleVsPlan(existingLessonContent)) {
@@ -27419,7 +27853,12 @@ Fix ALL issues above and output the complete corrected document.` }],
27419
27853
  } else {
27420
27854
  lessonContent = lintReport.autoFixedContent || rawLesson;
27421
27855
  }
27422
- await storage.saveArtifact(projectId, lessonRelPath, stampPlanHash(lessonContent));
27856
+ const stampedLesson = stampPlanHash(lessonContent);
27857
+ await storage.saveArtifact(projectId, lessonRelPath, stampedLesson);
27858
+ lessonEntity = buildLessonEntityJson(stampedLesson);
27859
+ if (lessonEntity) {
27860
+ await storage.saveArtifact(projectId, lessonEntityRelPath, JSON.stringify({ planHash: currentPlanHash ?? null, entity: lessonEntity }, null, 2));
27861
+ }
27423
27862
  producedArtifacts.push(`LESSON_${lessonCode}.md`);
27424
27863
  }
27425
27864
  const contentHash = lessonContent ? computeContentHash(lessonContent) : void 0;
@@ -27741,6 +28180,7 @@ ${currentContent}` }],
27741
28180
  slcMarkdown,
27742
28181
  symbolLedgerBlock,
27743
28182
  pedagogyLabel,
28183
+ lessonEntity,
27744
28184
  mode: routingMode
27745
28185
  });
27746
28186
  satelliteContexts[key] = built.context;
@@ -31545,6 +31985,113 @@ var DeterministicStructuralLinter = class {
31545
31985
  } else if (plan.mastery_gates && plan.mastery_gates.length > 0) {
31546
31986
  strengths.push(`${plan.mastery_gates.length} inter-unit Mastery Gates defined with remediation protocols.`);
31547
31987
  }
31988
+ const maxContentMinutes = Math.floor(
31989
+ (plan.constraints?.session_duration_minutes || 90) * (1 - DEFAULT_OVERHEAD_RATIO)
31990
+ );
31991
+ for (const s of plan.sessions) {
31992
+ const contentMins = (s.knowledge_minutes || 0) + (s.practice_minutes || 0);
31993
+ if (contentMins > maxContentMinutes + 2) {
31994
+ score -= 5;
31995
+ findings.push({
31996
+ id: `PLAN_OVERSIZED_SESSION_${s.id}`,
31997
+ dimension: "CONSTRUCTIVE_ALIGNMENT",
31998
+ severity: "MINOR",
31999
+ title: `Content Minutes Exceeded in Session ${s.id}`,
32000
+ description: `Session planned for ${contentMins} content minutes exceeds the ${maxContentMinutes}m budget (15% overhead reserve).`,
32001
+ remediationAdvice: `Reduce knowledge or practice minutes to fit within ${maxContentMinutes} minutes.`,
32002
+ affectedElement: s.id
32003
+ });
32004
+ }
32005
+ if (!s.exit_evidence || s.exit_evidence.length === 0 || !s.exit_evidence[0] || s.exit_evidence[0].trim().length < 3) {
32006
+ score -= 5;
32007
+ findings.push({
32008
+ id: `PLAN_VAGUE_EXIT_EVIDENCE_${s.id}`,
32009
+ dimension: "CONSTRUCTIVE_ALIGNMENT",
32010
+ severity: "MINOR",
32011
+ title: `Vague or Missing Exit Evidence in Session ${s.id}`,
32012
+ description: `Session lacks a concrete, measurable user-visible deliverable.`,
32013
+ remediationAdvice: `Specify an explicit exit evidence deliverable (e.g. running UI screen, passing test, or hardware actuation).`,
32014
+ affectedElement: s.id
32015
+ });
32016
+ }
32017
+ }
32018
+ score = Math.max(0, Math.min(100, score));
32019
+ const passed = score >= 80 && !findings.some((f) => f.severity === "CRITICAL");
32020
+ return { passed, score, findings, strengths };
32021
+ }
32022
+ /**
32023
+ * Validates structural and environment feasibility invariants for a Project Graph bundle.
32024
+ */
32025
+ static lintProjectGraph(bundle, expectedSessions = 12) {
32026
+ const findings = [];
32027
+ const strengths = [];
32028
+ let score = 100;
32029
+ const graph = bundle?.project_graph;
32030
+ const scope = bundle?.technology_scope;
32031
+ if (!graph || !Array.isArray(graph.features) || graph.features.length === 0) {
32032
+ score -= 40;
32033
+ findings.push({
32034
+ id: "GRAPH_MISSING_FEATURES",
32035
+ dimension: "CROSS_ARTIFACT_ZERO_DRIFT",
32036
+ severity: "CRITICAL",
32037
+ title: "Missing Features in Project Graph",
32038
+ description: "Project graph has no features array or empty features.",
32039
+ remediationAdvice: "Declare at least 3 progressive features with concrete steps."
32040
+ });
32041
+ return { passed: false, score: Math.max(0, score), findings, strengths };
32042
+ }
32043
+ const allSteps = graph.features.flatMap((f) => f.steps || []);
32044
+ if (allSteps.length === 0) {
32045
+ score -= 30;
32046
+ findings.push({
32047
+ id: "GRAPH_EMPTY_STEPS",
32048
+ dimension: "CROSS_ARTIFACT_ZERO_DRIFT",
32049
+ severity: "CRITICAL",
32050
+ title: "Empty Steps in Project Graph",
32051
+ description: "Features contain no executable steps.",
32052
+ remediationAdvice: "Add 2 to 4 concrete steps per feature."
32053
+ });
32054
+ }
32055
+ for (const step of allSteps) {
32056
+ const est = step.effort?.estimated_minutes || 0;
32057
+ if (est > 76) {
32058
+ score -= 10;
32059
+ findings.push({
32060
+ id: `GRAPH_OVERSIZED_STEP_${step.id || "step"}`,
32061
+ dimension: "CONSTRUCTIVE_ALIGNMENT",
32062
+ severity: "MAJOR",
32063
+ title: `Step ${step.id || step.name} Exceeds Content Budget`,
32064
+ description: `Step requires ${est} minutes, which exceeds the 76-minute single-session ceiling.`,
32065
+ remediationAdvice: `Split step into two sequential sub-steps to prevent artificial session fragmentation.`,
32066
+ affectedElement: step.id
32067
+ });
32068
+ }
32069
+ }
32070
+ const allTechStrings = [
32071
+ scope?.platform || "",
32072
+ ...Array.isArray(scope?.libraries_and_apis) ? scope.libraries_and_apis : [],
32073
+ ...Array.isArray(scope?.toolchain) ? scope.toolchain : [],
32074
+ JSON.stringify(graph.project?.tech_stack || {})
32075
+ ].join(" ").toLowerCase();
32076
+ const heavyKeywords = ["postgres", "postgresql", "docker", "kubernetes", "ros2", "oracle", "sql server"];
32077
+ const hasHeavyTech = heavyKeywords.some((k) => allTechStrings.includes(k));
32078
+ if (hasHeavyTech) {
32079
+ const declaredStrategy = scope?.provisioning_strategy || scope?.provisioning_model || graph.project?.provisioning_strategy;
32080
+ const isValidStrategy = ENVIRONMENT_PROVISIONING_MODELS.includes(declaredStrategy);
32081
+ if (!isValidStrategy) {
32082
+ score -= 15;
32083
+ findings.push({
32084
+ id: "GRAPH_UNPROVISIONED_HEAVY_TECH",
32085
+ dimension: "CONSTRUCTIVE_ALIGNMENT",
32086
+ severity: "MAJOR",
32087
+ title: "Heavy Technology Without Declared Lab Provisioning Strategy",
32088
+ description: `Course uses heavy/server technology without declaring a valid provisioning strategy (PRE_INSTALLED_LAB, CLOUD_MANAGED, or DEDICATED_SETUP).`,
32089
+ remediationAdvice: `Specify provisioning_strategy as PRE_INSTALLED_LAB, CLOUD_MANAGED, or DEDICATED_SETUP to ensure classroom feasibility.`
32090
+ });
32091
+ } else {
32092
+ strengths.push(`Heavy technology stack backed by explicit provisioning model: ${declaredStrategy}`);
32093
+ }
32094
+ }
31548
32095
  score = Math.max(0, Math.min(100, score));
31549
32096
  const passed = score >= 80 && !findings.some((f) => f.severity === "CRITICAL");
31550
32097
  return { passed, score, findings, strengths };
@@ -33187,6 +33734,8 @@ exports.ACT_TEMPLATE = ACT_TEMPLATE;
33187
33734
  exports.ARTIFACT_DEPENDENCY_ROUTING = ARTIFACT_DEPENDENCY_ROUTING;
33188
33735
  exports.ARTIFACT_EXECUTION_ORDER = ARTIFACT_EXECUTION_ORDER;
33189
33736
  exports.AcademicAuditor = AcademicAuditor;
33737
+ exports.ActionableRepairActionSchema = ActionableRepairActionSchema;
33738
+ exports.ActionableRepairPromptSchema = ActionableRepairPromptSchema;
33190
33739
  exports.ActiveLearningWorkflowSchema = ActiveLearningWorkflowSchema;
33191
33740
  exports.ActivityLabSchema = ActivityLabSchema;
33192
33741
  exports.ActivitySeqRowSchema = ActivitySeqRowSchema;
@@ -33233,6 +33782,7 @@ exports.DEFAULT_ENABLED_PROVIDERS = DEFAULT_ENABLED_PROVIDERS;
33233
33782
  exports.DEFAULT_GATE_SETTINGS = DEFAULT_GATE_SETTINGS;
33234
33783
  exports.DEFAULT_KX_PRIORITIES = DEFAULT_KX_PRIORITIES;
33235
33784
  exports.DEFAULT_LESSON_PRIORITIES = DEFAULT_LESSON_PRIORITIES;
33785
+ exports.DEFAULT_OVERHEAD_RATIO = DEFAULT_OVERHEAD_RATIO;
33236
33786
  exports.DEFAULT_STREAM_IDLE_MS = DEFAULT_STREAM_IDLE_MS;
33237
33787
  exports.DEFAULT_STREAM_TOTAL_MS = DEFAULT_STREAM_TOTAL_MS;
33238
33788
  exports.DEFAULT_VIETNAMESE_SECTION_HEADINGS = DEFAULT_VIETNAMESE_SECTION_HEADINGS;
@@ -33244,6 +33794,7 @@ exports.DeterministicStructuralLinter = DeterministicStructuralLinter;
33244
33794
  exports.DiagnosticQuestionSchema = DiagnosticQuestionSchema;
33245
33795
  exports.DiagnosticQuizSchema = DiagnosticQuizSchema;
33246
33796
  exports.EDPPhaseEnum = EDPPhaseEnum;
33797
+ exports.ENVIRONMENT_PROVISIONING_MODELS = ENVIRONMENT_PROVISIONING_MODELS;
33247
33798
  exports.EXIT_TICKET_TEMPLATE = EXIT_TICKET_TEMPLATE;
33248
33799
  exports.EXPOSITION_REL = EXPOSITION_REL;
33249
33800
  exports.EXT_TEMPLATE = EXT_TEMPLATE;
@@ -33279,6 +33830,8 @@ exports.HandoutSchema = HandoutSchema;
33279
33830
  exports.HandoutSectionSchema = HandoutSectionSchema;
33280
33831
  exports.InstructionSectionSchema = InstructionSectionSchema;
33281
33832
  exports.InstructionStepSchema = InstructionStepSchema;
33833
+ exports.JUDGE_AUTO_APPROVE_THRESHOLD = JUDGE_AUTO_APPROVE_THRESHOLD;
33834
+ exports.JUDGE_ESCALATE_THRESHOLD = JUDGE_ESCALATE_THRESHOLD;
33282
33835
  exports.JudgeCriterionSchema = JudgeCriterionSchema;
33283
33836
  exports.LAYER_IDLE_BUDGET_MS = LAYER_IDLE_BUDGET_MS;
33284
33837
  exports.LAYER_TOTAL_BUDGET_MS = LAYER_TOTAL_BUDGET_MS;
@@ -33287,12 +33840,18 @@ exports.LLMJudgeEngine = LLMJudgeEngine;
33287
33840
  exports.LabTierTaskSchema = LabTierTaskSchema;
33288
33841
  exports.LearningObjectiveInputSchema = LearningObjectiveInputSchema;
33289
33842
  exports.LearningObjectiveRowSchema = LearningObjectiveRowSchema;
33843
+ exports.LessonEntitySchema = LessonEntitySchema;
33290
33844
  exports.LessonFlowPhaseSchema = LessonFlowPhaseSchema;
33291
33845
  exports.LessonPlan5ESchema = LessonPlan5ESchema;
33292
33846
  exports.LessonPlanEDPSchema = LessonPlanEDPSchema;
33293
33847
  exports.LessonPlanSchema = LessonPlanSchema;
33294
33848
  exports.LessonSectionSchema = LessonSectionSchema;
33295
33849
  exports.LocalWorkspaceManager = LocalWorkspaceManager;
33850
+ exports.MAX_AUTONOMOUS_REPAIR_TURNS = MAX_AUTONOMOUS_REPAIR_TURNS;
33851
+ exports.MAX_IN_SESSION_SETUP_MINUTES = MAX_IN_SESSION_SETUP_MINUTES;
33852
+ exports.MAX_NEW_CONCEPTS_PER_SESSION_ADULT = MAX_NEW_CONCEPTS_PER_SESSION_ADULT;
33853
+ exports.MAX_NEW_CONCEPTS_PER_SESSION_K12 = MAX_NEW_CONCEPTS_PER_SESSION_K12;
33854
+ exports.MacroPedagogyPlanAuditSchema = MacroPedagogyPlanAuditSchema;
33296
33855
  exports.MappingKindSchema = MappingKindSchema;
33297
33856
  exports.MarpSlideSchema = MarpSlideSchema;
33298
33857
  exports.MasteryGateSchema = MasteryGateSchema;
@@ -33315,6 +33874,7 @@ exports.PrerequisiteDecisionEntrySchema = PrerequisiteDecisionEntrySchema;
33315
33874
  exports.PrerequisiteDecisionSchema = PrerequisiteDecisionSchema;
33316
33875
  exports.ProductGoalSchema = ProductGoalSchema;
33317
33876
  exports.ProgressiveHintsSchema = ProgressiveHintsSchema;
33877
+ exports.ProjectGraphAuditSchema = ProjectGraphAuditSchema;
33318
33878
  exports.ProjectGraphSchema = ProjectGraphSchema;
33319
33879
  exports.ProjectInstructionSchema = ProjectInstructionSchema;
33320
33880
  exports.ProjectProfileSchema = ProjectProfileSchema;
@@ -33341,6 +33901,7 @@ exports.SLIDE_TEMPLATE = SLIDE_TEMPLATE;
33341
33901
  exports.STANDARD_REF_REGEX = STANDARD_REF_REGEX;
33342
33902
  exports.STANDARD_SOT_FILES = STANDARD_SOT_FILES;
33343
33903
  exports.STATION_ROTATION_TEMPLATE = STATION_ROTATION_TEMPLATE;
33904
+ exports.STUDENT_FRICTION_MULTIPLIER = STUDENT_FRICTION_MULTIPLIER;
33344
33905
  exports.ScaffoldDecisionEntrySchema = ScaffoldDecisionEntrySchema;
33345
33906
  exports.ScaffoldDecisionSchema = ScaffoldDecisionSchema;
33346
33907
  exports.ScienceLabSchema = ScienceLabSchema;
@@ -33387,13 +33948,16 @@ exports.assertAcyclic = assertAcyclic;
33387
33948
  exports.assessorTools = assessorTools;
33388
33949
  exports.assignDepths = assignDepths;
33389
33950
  exports.atomicWriteFileSync = atomicWriteFileSync;
33951
+ exports.auditCurriculumPlanFlow = auditCurriculumPlanFlow;
33390
33952
  exports.auditCurriculumQualityFlow = auditCurriculumQualityFlow;
33953
+ exports.auditProjectGraphFlow = auditProjectGraphFlow;
33391
33954
  exports.auditQualityReport = auditQualityReport;
33392
33955
  exports.buildActivityPrompt = buildActivityPrompt;
33393
33956
  exports.buildCodeLabPrompt = buildCodeLabPrompt;
33394
33957
  exports.buildConceptPrerequisites = buildConceptPrerequisites;
33395
33958
  exports.buildCurriculumContext = buildCurriculumContext;
33396
33959
  exports.buildCurriculumPlan = buildCurriculumPlan;
33960
+ exports.buildCurriculumPlanJudgePrompt = buildCurriculumPlanJudgePrompt;
33397
33961
  exports.buildDeliveryPackages = buildDeliveryPackages;
33398
33962
  exports.buildDiagnosticQuizPrompt = buildDiagnosticQuizPrompt;
33399
33963
  exports.buildDomainLexiconGuardrail = buildDomainLexiconGuardrail;
@@ -33406,10 +33970,12 @@ exports.buildHtmlDeckSlidePrompt = buildHtmlDeckSlidePrompt;
33406
33970
  exports.buildImagePrompt = buildImagePrompt;
33407
33971
  exports.buildJudgePrompt = buildJudgePrompt;
33408
33972
  exports.buildLanguageDirective = buildLanguageDirective;
33973
+ exports.buildLessonEntityJson = buildLessonEntityJson;
33409
33974
  exports.buildLessonExcerpt = buildLessonExcerpt;
33410
33975
  exports.buildLessonMasterPrompt = buildLessonMasterPrompt;
33411
33976
  exports.buildMarpMarkdownSlidePrompt = buildMarpMarkdownSlidePrompt;
33412
33977
  exports.buildMasteryGates = buildMasteryGates;
33978
+ exports.buildProjectGraphJudgePrompt = buildProjectGraphJudgePrompt;
33413
33979
  exports.buildProjectInstructionPrompt = buildProjectInstructionPrompt;
33414
33980
  exports.buildSatelliteContext = buildSatelliteContext;
33415
33981
  exports.buildSectionAwareExcerpt = buildSectionAwareExcerpt;
@@ -33444,6 +34010,7 @@ exports.dropCyclicConceptEdges = dropCyclicConceptEdges;
33444
34010
  exports.emitUsage = emitUsage;
33445
34011
  exports.ensureExpositionForLesson = ensureExpositionForLesson;
33446
34012
  exports.ensureKnowledgeExposition = ensureKnowledgeExposition;
34013
+ exports.entityRowAssignedTo = entityRowAssignedTo;
33447
34014
  exports.evaluateActivityAlignment = evaluateActivityAlignment;
33448
34015
  exports.evaluateStandardsCoverage = evaluateStandardsCoverage;
33449
34016
  exports.executeCurriculumCommand = executeCurriculumCommand;
@@ -33523,6 +34090,8 @@ exports.produceSingleLesson = produceSingleLesson;
33523
34090
  exports.publishToGitHub = publishToGitHub;
33524
34091
  exports.publishToSupabase = publishToSupabase;
33525
34092
  exports.rankGenCandidates = rankGenCandidates;
34093
+ exports.renderAssignedRowsTable = renderAssignedRowsTable;
34094
+ exports.renderEntitySlotsForType = renderEntitySlotsForType;
33526
34095
  exports.renderFrameworkFromPlan = renderFrameworkFromPlan;
33527
34096
  exports.renderHorizonPromptBlock = renderHorizonPromptBlock;
33528
34097
  exports.renderMediaPlaceholder = renderMediaPlaceholder;