@thanh01.pmt/curriculum-kit 1.4.42 → 1.4.44

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.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import fs2 from 'fs';
2
- import path3 from 'path';
1
+ import fs3 from 'fs';
2
+ import path4 from 'path';
3
3
  import { createGoogleGenerativeAI } from '@ai-sdk/google';
4
4
  import { createOpenAI } from '@ai-sdk/openai';
5
5
  import { createDeepSeek } from '@ai-sdk/deepseek';
@@ -7,11 +7,11 @@ import { z } from 'zod';
7
7
  import { generateObject, streamObject, streamText, generateText } from 'ai';
8
8
  import pRetry from 'p-retry';
9
9
  import { jsonrepair } from 'jsonrepair';
10
+ import { fileURLToPath } from 'url';
10
11
  import pLimit from 'p-limit';
11
12
  import fsPromises from 'fs/promises';
12
13
  import crypto, { createHash } from 'crypto';
13
14
  import { createClient } from '@supabase/supabase-js';
14
- import { fileURLToPath } from 'url';
15
15
  import { Octokit } from '@octokit/rest';
16
16
 
17
17
  var __defProp = Object.defineProperty;
@@ -165,18 +165,18 @@ function resolveApiKey(keyName, explicitKey) {
165
165
  try {
166
166
  const currentDir = process.cwd();
167
167
  const envPaths = [
168
- path3.resolve(currentDir, ".env.local"),
169
- path3.resolve(currentDir, ".env"),
170
- path3.resolve(currentDir, "apps/web/.env.local"),
171
- path3.resolve(currentDir, "packages/learnwell-platform/.env"),
172
- path3.resolve(currentDir, "..", ".env.local"),
173
- path3.resolve(currentDir, "..", ".env"),
174
- path3.resolve(currentDir, "../..", ".env.local"),
175
- path3.resolve(currentDir, "../..", ".env")
168
+ path4.resolve(currentDir, ".env.local"),
169
+ path4.resolve(currentDir, ".env"),
170
+ path4.resolve(currentDir, "apps/web/.env.local"),
171
+ path4.resolve(currentDir, "packages/learnwell-platform/.env"),
172
+ path4.resolve(currentDir, "..", ".env.local"),
173
+ path4.resolve(currentDir, "..", ".env"),
174
+ path4.resolve(currentDir, "../..", ".env.local"),
175
+ path4.resolve(currentDir, "../..", ".env")
176
176
  ];
177
177
  for (const envPath of envPaths) {
178
- if (fs2.existsSync(envPath)) {
179
- const content = fs2.readFileSync(envPath, "utf-8");
178
+ if (fs3.existsSync(envPath)) {
179
+ const content = fs3.readFileSync(envPath, "utf-8");
180
180
  for (const line of content.split("\n")) {
181
181
  const trimmed = line.trim();
182
182
  if (trimmed && !trimmed.startsWith("#") && trimmed.startsWith(keyName + "=")) {
@@ -3932,467 +3932,105 @@ var RoadmapInputSchema = z.object({
3932
3932
 
3933
3933
  // src/ai/index.ts
3934
3934
  init_provider_factory();
3935
-
3936
- // src/templates/lessonTemplate.ts
3937
- var LESSON_PLAN_TEMPLATE = `
3938
- ---
3939
- id: "{{ID}}"
3940
- title: "{{TITLE}}"
3941
- type: "LESSON_5E"
3942
- created_by: "Curriculum OS Builder"
3943
- phase: "{{PHASE}}"
3944
- deliverable: "P3-T1"
3945
- version: "{{VERSION}}"
3946
- date: "{{DATE}}"
3947
- prerequisite: []
3948
- template_contract: "lesson-plan-v2"
3949
- template_required_sections:
3950
- - "A. Lesson Design Plan"
3951
- - "Learning Objectives & Evidence"
3952
- - "Activity Sequence"
3953
- - "Resource Map"
3954
- - "Assessment Map"
3955
- - "Artifact Contract"
3956
- - "B. Lesson Flow"
3957
- ---
3958
- <!-- INJECT_BODY -->
3959
-
3960
- # LESSON [{{LESSON_ID}}]: {{TITLE}} (5E Model)
3961
-
3962
- ## [REQUIRED] A. Lesson Design Plan
3963
-
3964
- ### 1. Learning Objectives & Evidence
3965
- - **Estimated Duration:** {{DURATION}}
3966
- - **Materials & Equipment:** {{MATERIALS_SUMMARY}}
3967
- - **Keywords / Core Concepts:** {{KEYWORDS}}
3968
-
3969
- | LO | Objective (Bloom's) | Student Evidence | Success Criteria |
3970
- |---|---|---|---|
3971
- {{LEARNING_OBJECTIVES_TABLE_ROWS}}
3972
-
3973
- ### 2. Activity Sequence
3974
- > This is the canonical activity contract. Satellite artifacts must expand this sequence and must not invent a different one.
3975
-
3976
- | Seq | 5E Phase | Activity Type | Actor | Purpose | Student Action | Teacher Move | Output/Evidence | LO | Time | Artifact Contract |
3977
- |---|---|---|---|---|---|---|---|---|---|---|
3978
- {{ACTIVITY_SEQUENCE_TABLE_ROWS}}
3979
-
3980
- ### 3. Resource Map
3981
- | Resource | Used In Activity | Purpose | Owner Artifact |
3982
- |---|---|---|---|
3983
- {{RESOURCE_MAP_TABLE_ROWS}}
3984
-
3985
- ### 4. Assessment Map
3986
- | Evidence | Assessed By | Criteria | Follow-up If Missing |
3987
- |---|---|---|---|
3988
- {{ASSESSMENT_MAP_TABLE_ROWS}}
3989
-
3990
- ### 5. Artifact Contract
3991
- - **ACT must expand:** {{ACT_CONTRACT}}
3992
- - **GUIDE must support:** {{GUIDE_CONTRACT}}
3993
- - **SLIDE must visualize:** {{SLIDE_CONTRACT}}
3994
- - **HANDOUT must provide:** {{HANDOUT_CONTRACT}}
3995
- - **WKS must practice:** {{WKS_CONTRACT}}
3996
- - **QUIZ must assess:** {{QUIZ_CONTRACT}}
3997
- - **EXT must extend:** {{EXT_CONTRACT}}
3998
-
3999
- ---
4000
-
4001
- ## [REQUIRED] B. Lesson Flow
4002
-
4003
- ### 1. ENGAGE \u2014 {{ENGAGE_DURATION}} mins
4004
- - **Hook Scenario:** {{HOOK_SCENARIO}}
4005
- - **Open Question:** {{HOOK_OPEN_QUESTION}}
4006
- - **Transition:** {{HOOK_TRANSITION}}
4007
-
4008
- ### 2. EXPLORE \u2014 {{EXPLORE_DURATION}} mins
4009
- - **Activity Reference:** {{EXPLORE_ACTIVITY_REF}}
4010
- - **Student Discovery:** {{EXPLORE_STUDENT_DISCOVERY}}
4011
-
4012
- ### 3. EXPLAIN \u2014 {{EXPLAIN_DURATION}} mins
4013
- - **Definitions:**
4014
- {{EXPLAIN_DEFINITIONS}}
4015
- - **Visual Illustration (REQUIRED):**
4016
- {{EXPLAIN_VISUAL_ILLUSTRATION}}
4017
-
4018
- ### 4. ELABORATE \u2014 {{ELABORATE_DURATION}} mins
4019
- - **Tiered Scaffolding:**
4020
- - \u{1F949} **Bronze:** {{DIFFERENTIATION_BRONZE}}
4021
- - \u{1F948} **Silver:** {{DIFFERENTIATION_SILVER}}
4022
- - \u{1F947} **Gold:** {{DIFFERENTIATION_GOLD}}
4023
-
4024
- > **ACT Contract**: Detailed operational instructions must expand the Activity Sequence above and must not change the planned evidence target.
4025
-
4026
- ### 5. EVALUATE \u2014 {{EVALUATE_DURATION}} mins
4027
- - **Exit Ticket:** {{EXIT_TICKET_CONTENT}}
4028
- - **Closing:** {{CLOSING_REMARKS}}
4029
-
4030
- > **QUIZ Contract**: Detailed assessment criteria and rubrics must assess the evidence and success criteria defined in the Lesson Design Plan.
4031
-
4032
- ---
4033
-
4034
- ## [OPTIONAL] Teacher Notes
4035
- - **Common Pitfalls:**
4036
- {{COMMON_PITFALLS}}
4037
- - **Troubleshooting:**
4038
- {{TROUBLESHOOTING_ROWS}}
4039
-
4040
- ---
4041
-
4042
- ## [REQUIRED] Artifact Linkage (Master Index)
4043
- > List all satellite files used in this lesson.
4044
-
4045
- | Artifact File | Role in the Classroom | When to Use |
4046
- |---|---|---|
4047
- | \`GUIDE_{{LESSON_ID}}.md\` | Detailed Teaching Script | Teacher preparation |
4048
- | \`SLIDE_{{LESSON_ID}}.md\` | Presentation Content | Throughout the session |
4049
- | \`HANDOUT_{{LESSON_ID}}.md\` | Theory Summary for Students | During EXPLAIN phase |
4050
- | \`ACT_{{LESSON_ID}}.md\` | Detailed Learning Activity Operations | During EXPLORE / ELABORATE / checkpoint phases |
4051
- | \`WKS_{{LESSON_ID}}.md\` | Individual Worksheet | Wrap-up or Homework |
4052
- | \`QUIZ_{{LESSON_ID}}.md\` | Assessment Rubric | During EVALUATE phase |
4053
- | \`EXT_{{LESSON_ID}}.md\` | Enrichment Materials | For "Gold" students |
4054
- `.trim();
4055
-
4056
- // src/templates/actTemplate.ts
4057
- var ACT_TEMPLATE = `
4058
- ---
4059
- id: "{{ID}}"
4060
- title: "{{TITLE}}"
4061
- type: "ACT"
4062
- created_by: "Curriculum OS Builder"
4063
- phase: "{{PHASE}}"
4064
- deliverable: "P3-T2"
4065
- version: "{{VERSION}}"
4066
- date: "{{DATE}}"
4067
- template_contract: "artifact-template-v1"
4068
- template_required_sections:
4069
- - "Computational Thinking Focus"
4070
- - "Materials & Setup"
4071
- - "Constraints & Safety"
4072
- - "Active Learning Workflow"
4073
- - "3-Tier Differentiation"
4074
- - "Reflection"
4075
- ---
4076
- <!-- INJECT_BODY -->
4077
-
4078
- # INQUIRY-BASED ACTIVITY: {{TITLE}}
4079
- _Milestone: {{MILESTONE_ID}} | Module: {{MODULE_NAME}} | Lesson: {{LESSON_ID}}_
4080
-
4081
- ## [REQUIRED] Computational Thinking Focus
4082
- - **Problem Statement (Real-world Scenario):** {{PROBLEM_STATEMENT}}
4083
- - **Decomposition:**
4084
- {{DECOMPOSITION_STEPS}}
4085
- - **Algorithm Design:** {{ALGORITHM_DESIGN}}
4086
-
4087
- ## [REQUIRED] Materials & Setup
4088
- - **Reference Material:** Students should use the **HANDOUT** for this lesson as their primary technical reference (lifeline).
4089
- - **Hardware/Software:**
4090
- <!-- [HARDWARE_BOM] -->
4091
- {{HARDWARE_ITEMS}}
4092
- <!-- [/HARDWARE_BOM] -->
4093
- - **Software:** {{SOFTWARE_ITEMS}}
4094
- - **Consumables:** {{CONSUMABLES}}
4095
- - **Other Resources:** {{OTHER_RESOURCES}}
4096
-
4097
- ## [REQUIRED] Constraints & Safety
4098
- - \u26A0\uFE0F **Technical/Safety:** {{SAFETY_WARNING}}
4099
- - \u{1F4A1} **Design Constraint:** {{DESIGN_CONSTRAINT}}
4100
-
4101
- ## [REQUIRED] Active Learning Workflow
4102
-
4103
- ### Phase 1: Planning & Design \u2014 {{PHASE1_DURATION}} mins
4104
- - **Student Task:** Hand-draw (or draft in words) the algorithm flowchart or connection architecture before touching the computer/devices.
4105
- - **Teacher Action:** Walk around to check the logic of each group. Ask inquiry questions:
4106
- {{PHASE1_INQUIRY_QUESTIONS}}
4107
-
4108
- ### Phase 2: Implementation & Discovery \u2014 {{PHASE2_DURATION}} mins
4109
- - **Student Task:** Apply the knowledge from the **HANDOUT** to realize the plan designed in Phase 1. Encourage self-inquiry and documentation lookup.
4110
- - **Teacher Action:** Avoid "hand-holding." Only intervene if a group has been stuck for more than 5 minutes.
4111
- {{PHASE2_GUIDANCE_BLOCK}}
4112
-
4113
- ### Phase 3: Debugging & Testing \u2014 {{PHASE3_DURATION}} mins
4114
- - **Testing:** Students run their system.
4115
- - **Error Analysis:** Ask students to record any error codes or unexpected behaviors and compare them with the Troubleshooting table in the Handout.
4116
- {{PHASE3_TESTING_STEPS}}
4117
-
4118
- ## [REQUIRED] 3-Tier Differentiation
4119
- > MUST design tasks in 3 tiers to support diverse learner groups. Bronze is the minimum requirement for all students.
4120
- - \u{1F949} **Bronze (Foundational):** {{DIFFERENTIATION_BRONZE}}
4121
- - \u{1F948} **Silver (Application):** {{DIFFERENTIATION_SILVER}}
4122
- - \u{1F947} **Gold (Enrichment/Creative):** {{DIFFERENTIATION_GOLD}}
4123
-
4124
- ## [REQUIRED] Reflection
4125
- - **Discussion Question:** {{REFLECTION_QUESTION}}
4126
- `.trim();
4127
-
4128
- // src/templates/codeLabTemplate.ts
4129
- var CODE_LAB_TEMPLATE = `
4130
- ---
4131
- id: "{{ID}}"
4132
- title: "{{TITLE}}"
4133
- type: "LAB"
4134
- created_by: "Curriculum OS Builder"
4135
- phase: "{{PHASE}}"
4136
- deliverable: "P3-T2"
4137
- version: "{{VERSION}}"
4138
- date: "{{DATE}}"
4139
- ---
4140
- <!-- INJECT_BODY -->
4141
-
4142
- # \u{1F468}\u200D\u{1F4BB} CODE LAB: {{TITLE}}
4143
- _Milestone: {{MILESTONE_ID}} | Tech Stack: {{TECH_STACK}}_
4144
-
4145
- ## \u{1F3AF} Overview
4146
- This lab focuses on the practical implementation of core technical concepts, bridging theory into working, robust, and testable code.
4147
-
4148
- ## \u{1F6E0}\uFE0F Environment & Setup
4149
- - **Language / Framework:** {{LANGUAGE_FRAMEWORK}}
4150
- - **IDE / Editor:** {{IDE_EDITOR}}
4151
- - **Required Libraries:** {{REQUIRED_LIBRARIES}}
4152
- - **Hardware / Connection Setup:** {{HARDWARE_ENV_CONNECTION}}
4153
-
4154
- ## \u{1F4DD} Lab Tasks (3-Tier Differentiation)
4155
-
4156
- ### \u{1F949} Bronze (Foundational) \u2014 {{BRONZE_MINS}} mins
4157
- **Objective:** {{BRONZE_OBJECTIVE}}
4158
- - **Task:** {{BRONZE_TASK}}
4159
- - **Requirement:** {{BRONZE_REQUIREMENT}}
4160
-
4161
- ### \u{1F948} Silver (Application) \u2014 {{SILVER_MINS}} mins
4162
- **Objective:** {{SILVER_OBJECTIVE}}
4163
- - **Task:** {{SILVER_TASK}}
4164
- - **Requirement:** {{SILVER_REQUIREMENT}}
4165
-
4166
- ### \u{1F947} Gold (Enrichment/Creative) \u2014 {{GOLD_MINS}} mins
4167
- **Objective:** {{GOLD_OBJECTIVE}}
4168
- - **Task:** {{GOLD_TASK}}
4169
- - **Requirement:** {{GOLD_REQUIREMENT}}
4170
-
4171
- ## \u{1F4BB} Technical Reference ([SME_MANDATE])
4172
- <!-- [SME_MANDATE] -->
4173
- > Any code provided in this section is verified for syntax accuracy and runtime execution.
4174
-
4175
- ### Starter Code Template
4176
- \`\`\`{{CODE_LANGUAGE}}
4177
- {{STARTER_CODE}}
4178
- \`\`\`
4179
-
4180
- ### Solution Code
4181
- \`\`\`{{CODE_LANGUAGE}}
4182
- {{SOLUTION_CODE}}
4183
- \`\`\`
4184
- <!-- [/SME_MANDATE] -->
4185
-
4186
- ## \u{1F50D} Troubleshooting & Debugging Matrix
4187
- | Issue | Potential Cause | Solution |
4188
- | :--- | :--- | :--- |
4189
- {{TROUBLESHOOTING_ROWS}}
4190
-
4191
- ## \u{1F3C1} Submission & Verification Checklist
4192
- {{CHECKLIST_ITEMS}}
4193
- `.trim();
4194
-
4195
- // src/templates/quizTemplate.ts
4196
- var QUIZ_TEMPLATE = `
4197
- ---
4198
- id: "{{ID}}"
4199
- title: "{{TITLE}}"
4200
- type: "QUIZ"
4201
- language: "{{LANGUAGE}}"
4202
- total_questions: {{TOTAL_QUESTIONS}}
4203
- passing_score_pct: {{PASSING_SCORE_PCT}}
4204
- ---
4205
-
4206
- # \u{1F9E0} Diagnostic & Active Recall Quiz: {{TITLE}}
4207
-
4208
- > \u23F1\uFE0F **Recommended Time:** ~10-15 mins
4209
- > \u{1F3AF} **Passing Score:** {{PASSING_SCORE_PCT}}%
4210
- > \u{1F4A1} **Purpose:** Test your conceptual understanding, catch hidden misconceptions, and evaluate architectural trade-offs.
4211
-
4212
- ---
4213
-
4214
- {{QUESTIONS_SECTION}}
4215
-
4216
- ---
4217
-
4218
- ## \u{1F511} Comprehensive Answer Key & Deep Explanation (Expand after completing)
4219
- <details>
4220
- <summary><b>\u{1F449} Click to View Full Explanations & Common Pitfall Analysis</b></summary>
4221
-
4222
- {{ANSWER_KEY_SECTION}}
4223
- </details>
4224
- `.trim();
4225
-
4226
- // src/templates/selfLabTemplate.ts
4227
- var SELF_LAB_TEMPLATE = `
4228
- ---
4229
- id: "{{ID}}"
4230
- title: "{{TITLE}}"
4231
- type: "SELF_LAB"
4232
- language: "{{LANGUAGE}}"
4233
- difficulty: "{{DIFFICULTY}}"
4234
- estimated_minutes: {{ESTIMATED_MINUTES}}
4235
- tech_stack: {{TECH_STACK}}
4236
- ---
4237
-
4238
- # \u{1F680} Self-Paced Hands-On Lab: {{TITLE}}
4239
-
4240
- > \u23F1\uFE0F **Estimated Duration:** ~{{ESTIMATED_MINUTES}} mins
4241
- > \u{1F3AF} **Difficulty Level:** {{DIFFICULTY_UPPER}}
4242
- > \u{1F9F0} **Tech Stack:** {{TECH_STACK_STR}}
4243
- > \u{1F4A1} **Self-Learner Notice:** You are in full control of this lab. Follow the progressive challenges below. If you get stuck at any point, use the **Progressive Hints System** to get unstuck without ruining the learning experience!
4244
-
4245
- ---
4246
-
4247
- ## \u{1F4CB} Mission Briefing & Environment Setup
4248
- {{MISSION_BRIEFING}}
4249
-
4250
- ### \u{1F6EB} Preflight Checklist
4251
- {{PREFLIGHT_CHECKLIST}}
4252
-
4253
- ---
4254
-
4255
- ## \u{1F3AF} Progressive Challenges (3-Tier Differentiation)
4256
-
4257
- ### \u{1F949} Challenge 1: Foundational Core (Bronze) \u2014 ~{{BRONZE_MINS}} mins
4258
- **Objective:** {{BRONZE_OBJECTIVE}}
4259
-
4260
- #### Tasks & Implementation Details:
4261
- {{BRONZE_TASKS}}
4262
-
4263
- #### \u{1F9EA} Self-Verification Command:
4264
- \`\`\`bash
4265
- {{BRONZE_VERIFY_COMMAND}}
4266
- \`\`\`
4267
- *Expected Terminal Output:*
4268
- \`\`\`text
4269
- {{BRONZE_EXPECTED_OUTPUT}}
4270
- \`\`\`
4271
-
4272
- #### \u{1F4A1} Progressive Hints (Expand only if stuck):
4273
- <details>
4274
- <summary><b>\u{1F4A1} Hint Level 1: Conceptual Clue (H\u01B0\u1EDBng t\u01B0 duy)</b></summary>
4275
-
4276
- {{BRONZE_HINT_1}}
4277
- </details>
4278
-
4279
- <details>
4280
- <summary><b>\u{1F50D} Hint Level 2: Structural Skeleton (Khung code m\u1EABu)</b></summary>
4281
-
4282
- \`\`\`{{CODE_LANGUAGE}}
4283
- {{BRONZE_HINT_2}}
4284
- \`\`\`
4285
- </details>
4286
-
4287
- <details>
4288
- <summary><b>\u{1F6A8} Hint Level 3: Full Solution & Explanation (L\u1EDDi gi\u1EA3i tr\u1ECDn v\u1EB9n)</b></summary>
4289
-
4290
- \`\`\`{{CODE_LANGUAGE}}
4291
- {{BRONZE_HINT_3_CODE}}
4292
- \`\`\`
4293
-
4294
- **Why this solution works:**
4295
- {{BRONZE_HINT_3_EXPLANATION}}
4296
- </details>
4297
-
4298
- ---
4299
-
4300
- ### \u{1F948} Challenge 2: Logic & Error Handling (Silver) \u2014 ~{{SILVER_MINS}} mins
4301
- **Objective:** {{SILVER_OBJECTIVE}}
4302
-
4303
- #### Tasks & Implementation Details:
4304
- {{SILVER_TASKS}}
4305
-
4306
- #### \u{1F9EA} Self-Verification Command:
4307
- \`\`\`bash
4308
- {{SILVER_VERIFY_COMMAND}}
4309
- \`\`\`
4310
- *Expected Terminal Output:*
4311
- \`\`\`text
4312
- {{SILVER_EXPECTED_OUTPUT}}
4313
- \`\`\`
4314
-
4315
- #### \u{1F4A1} Progressive Hints (Expand only if stuck):
4316
- <details>
4317
- <summary><b>\u{1F4A1} Hint Level 1: Conceptual Clue (H\u01B0\u1EDBng t\u01B0 duy)</b></summary>
4318
-
4319
- {{SILVER_HINT_1}}
4320
- </details>
4321
-
4322
- <details>
4323
- <summary><b>\u{1F50D} Hint Level 2: Structural Skeleton (Khung code m\u1EABu)</b></summary>
4324
-
4325
- \`\`\`{{CODE_LANGUAGE}}
4326
- {{SILVER_HINT_2}}
4327
- \`\`\`
4328
- </details>
4329
-
4330
- <details>
4331
- <summary><b>\u{1F6A8} Hint Level 3: Full Solution & Explanation (L\u1EDDi gi\u1EA3i tr\u1ECDn v\u1EB9n)</b></summary>
4332
-
4333
- \`\`\`{{CODE_LANGUAGE}}
4334
- {{SILVER_HINT_3_CODE}}
4335
- \`\`\`
4336
-
4337
- **Why this solution works:**
4338
- {{SILVER_HINT_3_EXPLANATION}}
4339
- </details>
4340
-
4341
- ---
4342
-
4343
- ### \u{1F947} Challenge 3: Edge Cases & Optimization (Gold) \u2014 ~{{GOLD_MINS}} mins
4344
- **Objective:** {{GOLD_OBJECTIVE}}
4345
-
4346
- #### Tasks & Implementation Details:
4347
- {{GOLD_TASKS}}
4348
-
4349
- #### \u{1F9EA} Self-Verification Command:
4350
- \`\`\`bash
4351
- {{GOLD_VERIFY_COMMAND}}
4352
- \`\`\`
4353
- *Expected Terminal Output:*
4354
- \`\`\`text
4355
- {{GOLD_EXPECTED_OUTPUT}}
4356
- \`\`\`
4357
-
4358
- #### \u{1F4A1} Progressive Hints (Expand only if stuck):
4359
- <details>
4360
- <summary><b>\u{1F4A1} Hint Level 1: Conceptual Clue (H\u01B0\u1EDBng t\u01B0 duy)</b></summary>
4361
-
4362
- {{GOLD_HINT_1}}
4363
- </details>
4364
-
4365
- <details>
4366
- <summary><b>\u{1F50D} Hint Level 2: Structural Skeleton (Khung code m\u1EABu)</b></summary>
4367
-
4368
- \`\`\`{{CODE_LANGUAGE}}
4369
- {{GOLD_HINT_2}}
4370
- \`\`\`
4371
- </details>
4372
-
4373
- <details>
4374
- <summary><b>\u{1F6A8} Hint Level 3: Full Solution & Explanation (L\u1EDDi gi\u1EA3i tr\u1ECDn v\u1EB9n)</b></summary>
4375
-
4376
- \`\`\`{{CODE_LANGUAGE}}
4377
- {{GOLD_HINT_3_CODE}}
4378
- \`\`\`
4379
-
4380
- **Why this solution works:**
4381
- {{GOLD_HINT_3_EXPLANATION}}
4382
- </details>
4383
-
4384
- ---
4385
-
4386
- ## \u{1F50D} Self-Learner Troubleshooting Matrix
4387
- | Symptom / Error Message | Root Cause | Exact Fix |
4388
- | :--- | :--- | :--- |
4389
- {{TROUBLESHOOTING_ROWS}}
4390
-
4391
- ---
4392
-
4393
- ## \u{1F3C1} Final Lab Submission & Mastery Checklist
4394
- {{FINAL_CHECKLIST}}
4395
- `.trim();
3935
+ function stripTemplateFrontmatter(raw) {
3936
+ let body = raw;
3937
+ if (body.startsWith("---")) {
3938
+ const end = body.indexOf("\n---", 3);
3939
+ if (end !== -1) body = body.slice(end + 4);
3940
+ }
3941
+ return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
3942
+ }
3943
+ function extractRequiredSections(raw) {
3944
+ const lines = raw.split("\n");
3945
+ const start = lines.findIndex((l) => /^template_required_sections:\s*$/.test(l.trim()));
3946
+ if (start === -1) return null;
3947
+ const items = [];
3948
+ for (let i = start + 1; i < lines.length; i++) {
3949
+ const line = lines[i] ?? "";
3950
+ if (line.trim() === "") continue;
3951
+ if (!/^\s+-\s/.test(line)) break;
3952
+ items.push(line.trim().replace(/^-\s+/, "").replace(/^["']|["']$/g, ""));
3953
+ }
3954
+ return items.length > 0 ? items : null;
3955
+ }
3956
+ function normalizeHeading(h) {
3957
+ return h.replace(/\[(REQUIRED|OPTIONAL|CONDITIONAL)\]\s*/gi, "").replace(/\s+/g, " ").trim();
3958
+ }
3959
+ function extractBodySections(raw) {
3960
+ const body = stripTemplateFrontmatter(raw);
3961
+ return body.split("\n").filter((l) => l.startsWith("## ")).map((l) => normalizeHeading(l.slice(3).trim())).filter((s) => s.length > 0);
3962
+ }
3963
+ var KIT_TEMPLATE_FALLBACK_DIRS = [
3964
+ // Packaged with the npm bundle (dist/templates) — resolves from node_modules.
3965
+ "templates",
3966
+ // Repo checkout layouts.
3967
+ "docs/refs/templates"
3968
+ ];
3969
+ var _moduleDir = (() => {
3970
+ try {
3971
+ if (typeof import.meta !== "undefined" && typeof import.meta.url === "string") {
3972
+ return path4.dirname(fileURLToPath(import.meta.url));
3973
+ }
3974
+ } catch {
3975
+ }
3976
+ return typeof __dirname !== "undefined" ? __dirname : process.cwd();
3977
+ })();
3978
+ function candidateDirs(explicitDir) {
3979
+ const dirs = [];
3980
+ if (explicitDir) dirs.push(explicitDir);
3981
+ if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
3982
+ dirs.push(path4.resolve(process.cwd(), "_templates"));
3983
+ for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
3984
+ dirs.push(path4.resolve(_moduleDir, rel));
3985
+ dirs.push(path4.resolve(process.cwd(), rel));
3986
+ dirs.push(path4.resolve(process.cwd(), "packages/curriculum-kit", rel));
3987
+ }
3988
+ return dirs;
3989
+ }
3990
+ function findTemplatePath(templateName, explicitDir) {
3991
+ for (const dir of candidateDirs(explicitDir)) {
3992
+ const p = path4.join(dir, templateName);
3993
+ if (!fs3.existsSync(p)) continue;
3994
+ try {
3995
+ fs3.accessSync(p, fs3.constants.R_OK);
3996
+ return p;
3997
+ } catch {
3998
+ }
3999
+ }
4000
+ return null;
4001
+ }
4002
+ function resolveArtifactTemplate(templateName, opts) {
4003
+ const p = findTemplatePath(templateName, opts?.templatesDir);
4004
+ if (!p) return null;
4005
+ try {
4006
+ const raw = fs3.readFileSync(p, "utf-8");
4007
+ return {
4008
+ content: stripTemplateFrontmatter(raw),
4009
+ sections: extractRequiredSections(raw) ?? extractBodySections(raw),
4010
+ sourcePath: p
4011
+ };
4012
+ } catch {
4013
+ return null;
4014
+ }
4015
+ }
4016
+ function loadCurriculumTemplate(templateName, templatesDir) {
4017
+ const p = findTemplatePath(templateName, templatesDir);
4018
+ if (!p) return "";
4019
+ try {
4020
+ return fs3.readFileSync(p, "utf-8");
4021
+ } catch {
4022
+ return "";
4023
+ }
4024
+ }
4025
+ function loadAuthoringTemplate(templateName, templatesDir) {
4026
+ const p = findTemplatePath(templateName, templatesDir);
4027
+ if (!p) return "";
4028
+ try {
4029
+ return stripTemplateFrontmatter(fs3.readFileSync(p, "utf-8"));
4030
+ } catch {
4031
+ return "";
4032
+ }
4033
+ }
4396
4034
 
4397
4035
  // src/ai/prompts/lessonMasterPrompt.ts
4398
4036
  function buildLessonMasterPrompt(input) {
@@ -4446,7 +4084,7 @@ Build a deep, rigorous, and highly pedagogical Master Lesson Plan (LESSON) that
4446
4084
  # MANDATORY TEMPLATE STRUCTURE
4447
4085
  You MUST generate structured data that will render directly into this exact Markdown template:
4448
4086
  ---
4449
- ${LESSON_PLAN_TEMPLATE}
4087
+ ${loadAuthoringTemplate("LESSON_5E_template.md") ?? "[TEMPLATE FILE NOT FOUND: LESSON_5E_template.md]"}
4450
4088
  ---
4451
4089
 
4452
4090
  # INPUT PARAMETERS
@@ -4524,7 +4162,7 @@ Transform the exact pedagogical flow and activities from the Master Lesson Plan
4524
4162
  # MANDATORY TEMPLATE STRUCTURE
4525
4163
  You MUST generate data aligned with this Markdown template:
4526
4164
  ---
4527
- ${ACT_TEMPLATE}
4165
+ ${loadAuthoringTemplate("ACT_template.md") ?? "[TEMPLATE FILE NOT FOUND: ACT_template.md]"}
4528
4166
  ---
4529
4167
 
4530
4168
  # CANONICAL MASTER LESSON CONTEXT (SOURCE OF TRUTH)
@@ -4619,7 +4257,7 @@ Generate complete, verified source code that satisfies the lesson objectives and
4619
4257
  # MANDATORY TEMPLATE STRUCTURE
4620
4258
  You MUST generate data aligned with this Markdown template:
4621
4259
  ---
4622
- ${CODE_LAB_TEMPLATE}
4260
+ ${loadAuthoringTemplate("LAB_TEMPLATE.md") ?? "[TEMPLATE FILE NOT FOUND: LAB_TEMPLATE.md]"}
4623
4261
  ---
4624
4262
 
4625
4263
  # CANONICAL LESSON CONTEXT (SOURCE OF TRUTH)
@@ -5314,7 +4952,7 @@ Build a complete, engaging Self-Paced Hands-On Lab (SELF_LAB) for autonomous lea
5314
4952
  # MANDATORY TEMPLATE STRUCTURE
5315
4953
  You MUST generate data aligned with this Markdown template:
5316
4954
  ---
5317
- ${SELF_LAB_TEMPLATE}
4955
+ ${loadAuthoringTemplate("SELF_LAB_template.md") ?? "[TEMPLATE FILE NOT FOUND: SELF_LAB_template.md]"}
5318
4956
  ---
5319
4957
 
5320
4958
  # INPUT PARAMETERS
@@ -5451,7 +5089,7 @@ Use this mapping to determine which Bloom level each question truly targets. Mat
5451
5089
  # MANDATORY TEMPLATE STRUCTURE
5452
5090
  You MUST generate data aligned with this Markdown template:
5453
5091
  ---
5454
- ${QUIZ_TEMPLATE}
5092
+ ${loadAuthoringTemplate("QUIZ_v4.6_template.md") ?? "[TEMPLATE FILE NOT FOUND: QUIZ_v4.6_template.md]"}
5455
5093
  ---
5456
5094
 
5457
5095
  # INPUT PARAMETERS
@@ -7748,13 +7386,13 @@ async function generateSelfPacedBundle(input) {
7748
7386
  if (input.outputDirectory) {
7749
7387
  await fsPromises.mkdir(input.outputDirectory, { recursive: true });
7750
7388
  await Promise.all([
7751
- fsPromises.writeFile(path3.join(input.outputDirectory, "INSTRUCTION.md"), instructionMd, "utf-8"),
7752
- fsPromises.writeFile(path3.join(input.outputDirectory, "SELF_LAB.md"), selfLabMd, "utf-8"),
7753
- fsPromises.writeFile(path3.join(input.outputDirectory, "QUIZ.md"), quizMd, "utf-8"),
7754
- fsPromises.writeFile(path3.join(input.outputDirectory, "QUIZ.json"), JSON.stringify(quiz, null, 2), "utf-8"),
7755
- fsPromises.writeFile(path3.join(input.outputDirectory, "CHEAT_SHEET.md"), cheatSheetMd, "utf-8"),
7756
- fsPromises.writeFile(path3.join(input.outputDirectory, "LAB.md"), codeLabMd, "utf-8"),
7757
- fsPromises.writeFile(path3.join(input.outputDirectory, "bundle.json"), JSON.stringify(bundle, null, 2), "utf-8")
7389
+ fsPromises.writeFile(path4.join(input.outputDirectory, "INSTRUCTION.md"), instructionMd, "utf-8"),
7390
+ fsPromises.writeFile(path4.join(input.outputDirectory, "SELF_LAB.md"), selfLabMd, "utf-8"),
7391
+ fsPromises.writeFile(path4.join(input.outputDirectory, "QUIZ.md"), quizMd, "utf-8"),
7392
+ fsPromises.writeFile(path4.join(input.outputDirectory, "QUIZ.json"), JSON.stringify(quiz, null, 2), "utf-8"),
7393
+ fsPromises.writeFile(path4.join(input.outputDirectory, "CHEAT_SHEET.md"), cheatSheetMd, "utf-8"),
7394
+ fsPromises.writeFile(path4.join(input.outputDirectory, "LAB.md"), codeLabMd, "utf-8"),
7395
+ fsPromises.writeFile(path4.join(input.outputDirectory, "bundle.json"), JSON.stringify(bundle, null, 2), "utf-8")
7758
7396
  ]);
7759
7397
  }
7760
7398
  return {
@@ -8155,15 +7793,15 @@ var STANDARD_SOT_FILES = [
8155
7793
  "ALIGNMENT_MATRIX.md"
8156
7794
  ];
8157
7795
  function atomicWriteFileSync(targetPath, content) {
8158
- const dir = path3.dirname(targetPath);
8159
- if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
8160
- const tmpPath = path3.join(dir, `.${path3.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto.randomBytes(4).toString("hex")}.tmp`);
7796
+ const dir = path4.dirname(targetPath);
7797
+ if (!fs3.existsSync(dir)) fs3.mkdirSync(dir, { recursive: true });
7798
+ const tmpPath = path4.join(dir, `.${path4.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto.randomBytes(4).toString("hex")}.tmp`);
8161
7799
  try {
8162
- fs2.writeFileSync(tmpPath, content, "utf-8");
8163
- fs2.renameSync(tmpPath, targetPath);
7800
+ fs3.writeFileSync(tmpPath, content, "utf-8");
7801
+ fs3.renameSync(tmpPath, targetPath);
8164
7802
  } catch (err) {
8165
7803
  try {
8166
- if (fs2.existsSync(tmpPath)) fs2.unlinkSync(tmpPath);
7804
+ if (fs3.existsSync(tmpPath)) fs3.unlinkSync(tmpPath);
8167
7805
  } catch {
8168
7806
  }
8169
7807
  throw err;
@@ -8172,51 +7810,51 @@ function atomicWriteFileSync(targetPath, content) {
8172
7810
  var FileSystemCurriculumAdapter = class {
8173
7811
  baseDir;
8174
7812
  constructor(options = {}) {
8175
- this.baseDir = options.baseDir || path3.resolve(process.cwd(), "output", "projects");
7813
+ this.baseDir = options.baseDir || path4.resolve(process.cwd(), "output", "projects");
8176
7814
  }
8177
7815
  getProjectDir(projectId) {
8178
7816
  const raw = (projectId || "").replace("proj_", "");
8179
- const directPath = path3.join(this.baseDir, raw);
8180
- if (fs2.existsSync(directPath)) return directPath;
8181
- const fullIdPath = path3.join(this.baseDir, projectId);
8182
- if (fs2.existsSync(fullIdPath)) return fullIdPath;
7817
+ const directPath = path4.join(this.baseDir, raw);
7818
+ if (fs3.existsSync(directPath)) return directPath;
7819
+ const fullIdPath = path4.join(this.baseDir, projectId);
7820
+ if (fs3.existsSync(fullIdPath)) return fullIdPath;
8183
7821
  return directPath;
8184
7822
  }
8185
7823
  /** Ensures the resolved path stays within the project directory (prevents path traversal). */
8186
7824
  assertInsideProject(projectDir, targetPath) {
8187
- const resolvedProject = path3.resolve(projectDir);
8188
- const resolvedTarget = path3.resolve(targetPath);
8189
- if (!resolvedTarget.startsWith(resolvedProject + path3.sep) && resolvedTarget !== resolvedProject) {
7825
+ const resolvedProject = path4.resolve(projectDir);
7826
+ const resolvedTarget = path4.resolve(targetPath);
7827
+ if (!resolvedTarget.startsWith(resolvedProject + path4.sep) && resolvedTarget !== resolvedProject) {
8190
7828
  throw new Error(`[FileSystemCurriculumAdapter] Path traversal blocked: ${targetPath} is outside project directory ${projectDir}`);
8191
7829
  }
8192
7830
  }
8193
7831
  async projectExists(projectId) {
8194
- return fs2.existsSync(this.getProjectDir(projectId));
7832
+ return fs3.existsSync(this.getProjectDir(projectId));
8195
7833
  }
8196
7834
  async readSotDocument(projectId, filename) {
8197
7835
  const projectDir = this.getProjectDir(projectId);
8198
7836
  const possiblePaths = [
8199
- path3.join(projectDir, "_sot", filename),
8200
- path3.join(projectDir, filename)
7837
+ path4.join(projectDir, "_sot", filename),
7838
+ path4.join(projectDir, filename)
8201
7839
  ];
8202
7840
  for (const p of possiblePaths) {
8203
- if (fs2.existsSync(p) && fs2.statSync(p).isFile()) {
8204
- return fs2.readFileSync(p, "utf-8");
7841
+ if (fs3.existsSync(p) && fs3.statSync(p).isFile()) {
7842
+ return fs3.readFileSync(p, "utf-8");
8205
7843
  }
8206
7844
  }
8207
7845
  return null;
8208
7846
  }
8209
7847
  async listSotDocuments(projectId) {
8210
7848
  const projectDir = this.getProjectDir(projectId);
8211
- const sotDir = path3.join(projectDir, "_sot");
7849
+ const sotDir = path4.join(projectDir, "_sot");
8212
7850
  const discoveredFiles = new Set(STANDARD_SOT_FILES);
8213
- if (fs2.existsSync(sotDir)) {
7851
+ if (fs3.existsSync(sotDir)) {
8214
7852
  try {
8215
- const diskFiles = fs2.readdirSync(sotDir);
7853
+ const diskFiles = fs3.readdirSync(sotDir);
8216
7854
  for (const f of diskFiles) {
8217
7855
  if (f.startsWith(".") || f.endsWith(".review.json")) continue;
8218
- const fullPath = path3.join(sotDir, f);
8219
- if (fs2.statSync(fullPath).isFile()) {
7856
+ const fullPath = path4.join(sotDir, f);
7857
+ if (fs3.statSync(fullPath).isFile()) {
8220
7858
  discoveredFiles.add(f);
8221
7859
  }
8222
7860
  }
@@ -8224,9 +7862,9 @@ var FileSystemCurriculumAdapter = class {
8224
7862
  }
8225
7863
  }
8226
7864
  return Array.from(discoveredFiles).map((filename) => {
8227
- const p = fs2.existsSync(path3.join(sotDir, filename)) ? path3.join(sotDir, filename) : fs2.existsSync(path3.join(projectDir, filename)) ? path3.join(projectDir, filename) : null;
8228
- if (p && fs2.existsSync(p)) {
8229
- const stats = fs2.statSync(p);
7865
+ const p = fs3.existsSync(path4.join(sotDir, filename)) ? path4.join(sotDir, filename) : fs3.existsSync(path4.join(projectDir, filename)) ? path4.join(projectDir, filename) : null;
7866
+ if (p && fs3.existsSync(p)) {
7867
+ const stats = fs3.statSync(p);
8230
7868
  return {
8231
7869
  name: filename.replace(/\.(md|json)$/i, "").replace(/_/g, " "),
8232
7870
  filename,
@@ -8244,18 +7882,18 @@ var FileSystemCurriculumAdapter = class {
8244
7882
  }
8245
7883
  async readArtifact(projectId, relPathOrIdentifier) {
8246
7884
  const projectDir = this.getProjectDir(projectId);
8247
- const directCandidate = path3.join(projectDir, relPathOrIdentifier);
7885
+ const directCandidate = path4.join(projectDir, relPathOrIdentifier);
8248
7886
  this.assertInsideProject(projectDir, directCandidate);
8249
7887
  const possiblePaths = [
8250
7888
  directCandidate,
8251
- path3.join(projectDir, "_sot", relPathOrIdentifier),
8252
- path3.join(projectDir, "lessons", relPathOrIdentifier),
8253
- path3.join(projectDir, "_sot", path3.basename(relPathOrIdentifier)),
8254
- path3.join(projectDir, "lessons", path3.basename(relPathOrIdentifier))
7889
+ path4.join(projectDir, "_sot", relPathOrIdentifier),
7890
+ path4.join(projectDir, "lessons", relPathOrIdentifier),
7891
+ path4.join(projectDir, "_sot", path4.basename(relPathOrIdentifier)),
7892
+ path4.join(projectDir, "lessons", path4.basename(relPathOrIdentifier))
8255
7893
  ];
8256
7894
  for (const p of possiblePaths) {
8257
- if (fs2.existsSync(p) && fs2.statSync(p).isFile()) {
8258
- return fs2.readFileSync(p, "utf-8");
7895
+ if (fs3.existsSync(p) && fs3.statSync(p).isFile()) {
7896
+ return fs3.readFileSync(p, "utf-8");
8259
7897
  }
8260
7898
  }
8261
7899
  if (relPathOrIdentifier.includes(".md") || relPathOrIdentifier.includes("/")) {
@@ -8264,8 +7902,8 @@ var FileSystemCurriculumAdapter = class {
8264
7902
  const lessonMatch = relPathOrIdentifier.match(/U\d+_M\d+_L\d+/i);
8265
7903
  if (lessonMatch) {
8266
7904
  const lessonId = lessonMatch[0].toUpperCase();
8267
- const lessonDir = path3.join(projectDir, "lessons", lessonId);
8268
- if (fs2.existsSync(lessonDir) && fs2.statSync(lessonDir).isDirectory()) {
7905
+ const lessonDir = path4.join(projectDir, "lessons", lessonId);
7906
+ if (fs3.existsSync(lessonDir) && fs3.statSync(lessonDir).isDirectory()) {
8269
7907
  const lower = relPathOrIdentifier.toLowerCase();
8270
7908
  let artifactPrefix = "LESSON";
8271
7909
  if (lower.includes("act") || lower.includes("lab") || lower.includes("th\u1EF1c h\xE0nh")) {
@@ -8285,9 +7923,9 @@ var FileSystemCurriculumAdapter = class {
8285
7923
  } else if (lower.includes("ext") || lower.includes("extension")) {
8286
7924
  artifactPrefix = "EXT";
8287
7925
  }
8288
- const candidateFile = path3.join(lessonDir, `${artifactPrefix}_${lessonId}.md`);
8289
- if (fs2.existsSync(candidateFile)) {
8290
- return fs2.readFileSync(candidateFile, "utf-8");
7926
+ const candidateFile = path4.join(lessonDir, `${artifactPrefix}_${lessonId}.md`);
7927
+ if (fs3.existsSync(candidateFile)) {
7928
+ return fs3.readFileSync(candidateFile, "utf-8");
8291
7929
  }
8292
7930
  }
8293
7931
  }
@@ -8295,22 +7933,22 @@ var FileSystemCurriculumAdapter = class {
8295
7933
  }
8296
7934
  async saveArtifact(projectId, relPath, content) {
8297
7935
  const projectDir = this.getProjectDir(projectId);
8298
- const targetPath = path3.join(projectDir, relPath);
7936
+ const targetPath = path4.join(projectDir, relPath);
8299
7937
  this.assertInsideProject(projectDir, targetPath);
8300
- const targetDir = path3.dirname(targetPath);
8301
- if (!fs2.existsSync(targetDir)) {
8302
- fs2.mkdirSync(targetDir, { recursive: true });
7938
+ const targetDir = path4.dirname(targetPath);
7939
+ if (!fs3.existsSync(targetDir)) {
7940
+ fs3.mkdirSync(targetDir, { recursive: true });
8303
7941
  }
8304
- if (fs2.existsSync(targetPath)) {
7942
+ if (fs3.existsSync(targetPath)) {
8305
7943
  try {
8306
- const oldContent = fs2.readFileSync(targetPath, "utf-8");
7944
+ const oldContent = fs3.readFileSync(targetPath, "utf-8");
8307
7945
  if (oldContent !== content) {
8308
- const historyDir = path3.join(projectDir, ".history", relPath);
8309
- fs2.mkdirSync(historyDir, { recursive: true });
8310
- atomicWriteFileSync(path3.join(historyDir, `${Date.now()}.md`), oldContent);
8311
- const versions = fs2.readdirSync(historyDir).filter((f) => f.endsWith(".md")).sort();
7946
+ const historyDir = path4.join(projectDir, ".history", relPath);
7947
+ fs3.mkdirSync(historyDir, { recursive: true });
7948
+ atomicWriteFileSync(path4.join(historyDir, `${Date.now()}.md`), oldContent);
7949
+ const versions = fs3.readdirSync(historyDir).filter((f) => f.endsWith(".md")).sort();
8312
7950
  while (versions.length > 10) {
8313
- fs2.unlinkSync(path3.join(historyDir, versions.shift()));
7951
+ fs3.unlinkSync(path4.join(historyDir, versions.shift()));
8314
7952
  }
8315
7953
  }
8316
7954
  } catch (histErr) {
@@ -8318,24 +7956,24 @@ var FileSystemCurriculumAdapter = class {
8318
7956
  }
8319
7957
  }
8320
7958
  atomicWriteFileSync(targetPath, content);
8321
- const filename = path3.basename(relPath);
7959
+ const filename = path4.basename(relPath);
8322
7960
  const match = filename.match(/(LESSON|ACT|QUIZ|SLIDE|GUIDE|HANDOUT|WKS|EXT)_(U\d+_M\d+_L\d+)\.md/i);
8323
7961
  if (match) {
8324
7962
  const lessonId = match[2].toUpperCase();
8325
- atomicWriteFileSync(path3.join(projectDir, "lessons", lessonId, filename), content);
8326
- const legacyContentDir = path3.join(projectDir, "_content", lessonId);
8327
- if (fs2.existsSync(legacyContentDir)) {
8328
- atomicWriteFileSync(path3.join(legacyContentDir, filename), content);
7963
+ atomicWriteFileSync(path4.join(projectDir, "lessons", lessonId, filename), content);
7964
+ const legacyContentDir = path4.join(projectDir, "_content", lessonId);
7965
+ if (fs3.existsSync(legacyContentDir)) {
7966
+ atomicWriteFileSync(path4.join(legacyContentDir, filename), content);
8329
7967
  }
8330
7968
  }
8331
7969
  }
8332
7970
  async listLessons(projectId) {
8333
- const lessonsDir = path3.join(this.getProjectDir(projectId), "lessons");
8334
- if (!fs2.existsSync(lessonsDir)) return [];
8335
- const lessonFolders = fs2.readdirSync(lessonsDir).filter((f) => !f.startsWith("."));
7971
+ const lessonsDir = path4.join(this.getProjectDir(projectId), "lessons");
7972
+ if (!fs3.existsSync(lessonsDir)) return [];
7973
+ const lessonFolders = fs3.readdirSync(lessonsDir).filter((f) => !f.startsWith("."));
8336
7974
  return lessonFolders.map((folder) => {
8337
- const lDir = path3.join(lessonsDir, folder);
8338
- const isDir = fs2.statSync(lDir).isDirectory();
7975
+ const lDir = path4.join(lessonsDir, folder);
7976
+ const isDir = fs3.statSync(lDir).isDirectory();
8339
7977
  if (!isDir) {
8340
7978
  return {
8341
7979
  lessonId: folder,
@@ -8344,7 +7982,7 @@ var FileSystemCurriculumAdapter = class {
8344
7982
  artifacts: []
8345
7983
  };
8346
7984
  }
8347
- const artifacts = fs2.readdirSync(lDir).filter((f) => !f.startsWith("."));
7985
+ const artifacts = fs3.readdirSync(lDir).filter((f) => !f.startsWith("."));
8348
7986
  return {
8349
7987
  lessonId: folder,
8350
7988
  artifactsCount: artifacts.length,
@@ -8390,10 +8028,10 @@ ${lessonTable}
8390
8028
  }
8391
8029
  async getPipelineState(projectId) {
8392
8030
  const projectDir = this.getProjectDir(projectId);
8393
- const stateFile = path3.join(projectDir, "_pipeline", "state.json");
8394
- if (fs2.existsSync(stateFile)) {
8031
+ const stateFile = path4.join(projectDir, "_pipeline", "state.json");
8032
+ if (fs3.existsSync(stateFile)) {
8395
8033
  try {
8396
- const raw = fs2.readFileSync(stateFile, "utf-8");
8034
+ const raw = fs3.readFileSync(stateFile, "utf-8");
8397
8035
  const parsed = JSON.parse(raw);
8398
8036
  if (parsed && typeof parsed === "object" && parsed.tasks) {
8399
8037
  return parsed;
@@ -8410,11 +8048,11 @@ ${lessonTable}
8410
8048
  }
8411
8049
  async savePipelineState(projectId, state) {
8412
8050
  const projectDir = this.getProjectDir(projectId);
8413
- const pipelineDir = path3.join(projectDir, "_pipeline");
8414
- if (!fs2.existsSync(pipelineDir)) {
8415
- fs2.mkdirSync(pipelineDir, { recursive: true });
8051
+ const pipelineDir = path4.join(projectDir, "_pipeline");
8052
+ if (!fs3.existsSync(pipelineDir)) {
8053
+ fs3.mkdirSync(pipelineDir, { recursive: true });
8416
8054
  }
8417
- const stateFile = path3.join(pipelineDir, "state.json");
8055
+ const stateFile = path4.join(pipelineDir, "state.json");
8418
8056
  state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
8419
8057
  atomicWriteFileSync(stateFile, JSON.stringify(state, null, 2));
8420
8058
  }
@@ -8437,9 +8075,9 @@ ${lessonTable}
8437
8075
  async deleteArtifact(projectId, relPath) {
8438
8076
  try {
8439
8077
  const projectDir = this.getProjectDir(projectId);
8440
- const targetPath = path3.join(projectDir, relPath);
8078
+ const targetPath = path4.join(projectDir, relPath);
8441
8079
  this.assertInsideProject(projectDir, targetPath);
8442
- if (fs2.existsSync(targetPath)) fs2.rmSync(targetPath, { force: true });
8080
+ if (fs3.existsSync(targetPath)) fs3.rmSync(targetPath, { force: true });
8443
8081
  } catch {
8444
8082
  }
8445
8083
  }
@@ -9189,19 +8827,19 @@ function buildStandardStackMarkdown(opts) {
9189
8827
 
9190
8828
  // src/services/sotGeneratorService.ts
9191
8829
  var __filename$1 = typeof import.meta?.url === "string" && typeof fileURLToPath === "function" ? fileURLToPath(import.meta.url) : "";
9192
- var __dirname2 = __filename$1 ? path3.dirname(__filename$1) : process.cwd();
8830
+ var __dirname2 = __filename$1 ? path4.dirname(__filename$1) : process.cwd();
9193
8831
  function loadSotTemplate(templateFileName) {
9194
8832
  const possiblePaths = [
9195
- path3.resolve(__dirname2, "../../docs/refs/templates", templateFileName),
9196
- path3.resolve(process.cwd(), "packages/curriculum-kit/docs/refs/templates", templateFileName),
9197
- path3.resolve(process.cwd(), "../learnwell-platform/packages/curriculum-kit/docs/refs/templates", templateFileName),
9198
- path3.resolve("/Users/tonypham/MEGA/WebApp/WIP/learnwell-platform/packages/curriculum-kit/docs/refs/templates", templateFileName),
9199
- path3.resolve("/Users/tonypham/MEGA/ai-platform/learning-artifact-gen-ui/_templates", templateFileName)
8833
+ path4.resolve(__dirname2, "../../docs/refs/templates", templateFileName),
8834
+ path4.resolve(process.cwd(), "packages/curriculum-kit/docs/refs/templates", templateFileName),
8835
+ path4.resolve(process.cwd(), "../learnwell-platform/packages/curriculum-kit/docs/refs/templates", templateFileName),
8836
+ path4.resolve("/Users/tonypham/MEGA/WebApp/WIP/learnwell-platform/packages/curriculum-kit/docs/refs/templates", templateFileName),
8837
+ path4.resolve("/Users/tonypham/MEGA/ai-platform/learning-artifact-gen-ui/_templates", templateFileName)
9200
8838
  ];
9201
8839
  for (const p of possiblePaths) {
9202
- if (fs2.existsSync(p)) {
8840
+ if (fs3.existsSync(p)) {
9203
8841
  try {
9204
- return fs2.readFileSync(p, "utf-8");
8842
+ return fs3.readFileSync(p, "utf-8");
9205
8843
  } catch {
9206
8844
  }
9207
8845
  }
@@ -10216,7 +9854,7 @@ function buildSectionAwareExcerpt(markdown, opts = {}) {
10216
9854
  if (s.canonicalKey && !byCanonical.has(s.canonicalKey)) {
10217
9855
  byCanonical.set(s.canonicalKey, s);
10218
9856
  }
10219
- const norm2 = normalizeHeading(s.cleanTitle);
9857
+ const norm2 = normalizeHeading2(s.cleanTitle);
10220
9858
  if (!byCleanTitle.has(norm2)) {
10221
9859
  byCleanTitle.set(norm2, s);
10222
9860
  }
@@ -10266,7 +9904,7 @@ ${truncated}`;
10266
9904
  blocks.push(metaBlock);
10267
9905
  let sectionAware = false;
10268
9906
  for (const key of priorities) {
10269
- const sec = byCanonical.get(key) || byCleanTitle.get(normalizeHeading(key));
9907
+ const sec = byCanonical.get(key) || byCleanTitle.get(normalizeHeading2(key));
10270
9908
  if (!sec) continue;
10271
9909
  sectionAware = true;
10272
9910
  if (!tryAdd(sec.cleanTitle, sec.body, key)) break;
@@ -10348,15 +9986,15 @@ function parseMarkdownSections(markdown, slcMap, artifactType) {
10348
9986
  const maps = artifactType && slcMap[artifactType] ? [slcMap[artifactType]] : Object.values(slcMap);
10349
9987
  for (const m of maps) {
10350
9988
  for (const [canonical, localized] of Object.entries(m)) {
10351
- reverseMap.set(normalizeHeading(localized), canonical);
10352
- reverseMap.set(normalizeHeading(canonical), canonical);
9989
+ reverseMap.set(normalizeHeading2(localized), canonical);
9990
+ reverseMap.set(normalizeHeading2(canonical), canonical);
10353
9991
  }
10354
9992
  }
10355
9993
  }
10356
9994
  const flush = () => {
10357
9995
  if (!currentHeading) return;
10358
9996
  const cleanTitle = currentHeading.replace(/^#{1,4}\s+/, "").trim();
10359
- const norm2 = normalizeHeading(cleanTitle);
9997
+ const norm2 = normalizeHeading2(cleanTitle);
10360
9998
  const canonicalKey = reverseMap.get(norm2) || findCanonicalFuzzy(norm2);
10361
9999
  sections.push({
10362
10000
  rawHeading: currentHeading,
@@ -10380,7 +10018,7 @@ function parseMarkdownSections(markdown, slcMap, artifactType) {
10380
10018
  flush();
10381
10019
  return sections;
10382
10020
  }
10383
- function normalizeHeading(str) {
10021
+ function normalizeHeading2(str) {
10384
10022
  return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
10385
10023
  }
10386
10024
  function findCanonicalFuzzy(norm2) {
@@ -25449,96 +25087,6 @@ function evaluateActivityAlignment(canonicalExcerpt, generatedContent, now = /*
25449
25087
  const passed = matchedTokens.length > 0;
25450
25088
  return { checked: true, passed, matchedTokens: matchedTokens.slice(0, 10), missingTokens: missingTokens.slice(0, 10), mode };
25451
25089
  }
25452
- function stripTemplateFrontmatter(raw) {
25453
- let body = raw;
25454
- if (body.startsWith("---")) {
25455
- const end = body.indexOf("\n---", 3);
25456
- if (end !== -1) body = body.slice(end + 4);
25457
- }
25458
- return body.split("\n").filter((l) => l.trim() !== "<!-- INJECT_BODY -->").join("\n").replace(/^\s*\n/, "").trimEnd();
25459
- }
25460
- function extractRequiredSections(raw) {
25461
- const lines = raw.split("\n");
25462
- const start = lines.findIndex((l) => /^template_required_sections:\s*$/.test(l.trim()));
25463
- if (start === -1) return null;
25464
- const items = [];
25465
- for (let i = start + 1; i < lines.length; i++) {
25466
- const line = lines[i] ?? "";
25467
- if (line.trim() === "") continue;
25468
- if (!/^\s+-\s/.test(line)) break;
25469
- items.push(line.trim().replace(/^-\s+/, "").replace(/^["']|["']$/g, ""));
25470
- }
25471
- return items.length > 0 ? items : null;
25472
- }
25473
- function normalizeHeading2(h) {
25474
- return h.replace(/\[(REQUIRED|OPTIONAL|CONDITIONAL)\]\s*/gi, "").replace(/\s+/g, " ").trim();
25475
- }
25476
- function extractBodySections(raw) {
25477
- const body = stripTemplateFrontmatter(raw);
25478
- return body.split("\n").filter((l) => l.startsWith("## ")).map((l) => normalizeHeading2(l.slice(3).trim())).filter((s) => s.length > 0);
25479
- }
25480
- var KIT_TEMPLATE_FALLBACK_DIRS = [
25481
- // Packaged with the npm bundle (dist/templates) — resolves from node_modules.
25482
- "templates",
25483
- // Repo checkout layouts.
25484
- "docs/refs/templates"
25485
- ];
25486
- var _moduleDir = (() => {
25487
- try {
25488
- if (typeof import.meta !== "undefined" && typeof import.meta.url === "string") {
25489
- return path3.dirname(fileURLToPath(import.meta.url));
25490
- }
25491
- } catch {
25492
- }
25493
- return typeof __dirname !== "undefined" ? __dirname : process.cwd();
25494
- })();
25495
- function candidateDirs(explicitDir) {
25496
- const dirs = [];
25497
- if (explicitDir) dirs.push(explicitDir);
25498
- if (process.env.CURRICULUM_TEMPLATES_DIR) dirs.push(process.env.CURRICULUM_TEMPLATES_DIR);
25499
- dirs.push(path3.resolve(process.cwd(), "_templates"));
25500
- for (const rel of KIT_TEMPLATE_FALLBACK_DIRS) {
25501
- dirs.push(path3.resolve(_moduleDir, rel));
25502
- dirs.push(path3.resolve(process.cwd(), rel));
25503
- dirs.push(path3.resolve(process.cwd(), "packages/curriculum-kit", rel));
25504
- }
25505
- return dirs;
25506
- }
25507
- function findTemplatePath(templateName, explicitDir) {
25508
- for (const dir of candidateDirs(explicitDir)) {
25509
- const p = path3.join(dir, templateName);
25510
- if (!fs2.existsSync(p)) continue;
25511
- try {
25512
- fs2.accessSync(p, fs2.constants.R_OK);
25513
- return p;
25514
- } catch {
25515
- }
25516
- }
25517
- return null;
25518
- }
25519
- function resolveArtifactTemplate(templateName, opts) {
25520
- const p = findTemplatePath(templateName, opts?.templatesDir);
25521
- if (!p) return null;
25522
- try {
25523
- const raw = fs2.readFileSync(p, "utf-8");
25524
- return {
25525
- content: stripTemplateFrontmatter(raw),
25526
- sections: extractRequiredSections(raw) ?? extractBodySections(raw),
25527
- sourcePath: p
25528
- };
25529
- } catch {
25530
- return null;
25531
- }
25532
- }
25533
- function loadCurriculumTemplate(templateName, templatesDir) {
25534
- const p = findTemplatePath(templateName, templatesDir);
25535
- if (!p) return "";
25536
- try {
25537
- return fs2.readFileSync(p, "utf-8");
25538
- } catch {
25539
- return "";
25540
- }
25541
- }
25542
25090
 
25543
25091
  // src/services/lessonProductionService.ts
25544
25092
  var LESSON_TEMPLATE_BY_PEDAGOGY = {
@@ -25550,10 +25098,11 @@ var LESSON_TEMPLATE_BY_PEDAGOGY = {
25550
25098
  function buildArtifactPrompt(parts, opts) {
25551
25099
  const resolved = resolveArtifactTemplate(parts.templateFile, opts);
25552
25100
  const body = resolved?.content ?? parts.epilogue ?? "";
25553
- const source = resolved ? `
25554
- <!-- P52 template: ${parts.templateFile} \u2190 ${resolved.sourcePath} -->
25555
- ` : "\n<!-- P52 template: NOT FOUND \u2014 inline fallback scaffold -->\n";
25556
- return `${parts.directive}${source}${body}`;
25101
+ return `${parts.directive}
25102
+
25103
+ ===== ARTIFACT TEMPLATE: ${parts.templateFile} ${resolved ? `(loaded from ${resolved.sourcePath})` : "(\u26A0\uFE0F NOT FOUND \u2014 inline fallback scaffold in use)"} =====
25104
+
25105
+ ${body}`;
25557
25106
  }
25558
25107
  var NO_VERBATIM_COPYING = `
25559
25108
  VERBATIM SOURCING RULE: When a section in the template says to extract a table
@@ -25753,6 +25302,10 @@ type: "${artifactType}"
25753
25302
  and respect the template's OWNERSHIP note: each fact lives in exactly ONE
25754
25303
  section \u2014 never restate satellite lists, resources, or assessment content
25755
25304
  across sections, and never embed KX-owned question banks or self-check text.
25305
+ 3. In the Learning Objectives table, carry the Standard ID from the [STANDARDS
25306
+ STATEMENTS] context into the same row as its LO (e.g. "CSTA: 1B-AP-10")
25307
+ when a matching standard exists.
25308
+ 4. Every code sample must be 100% syntax-valid and executable.
25756
25309
  3. Use the exact vocabulary of the canonical knowledge context for every
25757
25310
  concept and term.
25758
25311
  ${NO_VERBATIM_COPYING}`;
@@ -29475,10 +29028,10 @@ init_slideProductionWorkflow();
29475
29028
  var LocalWorkspaceManager = class {
29476
29029
  baseDir;
29477
29030
  constructor(baseDir) {
29478
- this.baseDir = baseDir || path3.resolve(process.cwd(), "output", "workspace-jobs");
29031
+ this.baseDir = baseDir || path4.resolve(process.cwd(), "output", "workspace-jobs");
29479
29032
  }
29480
29033
  getJobDirectory(jobId) {
29481
- return path3.join(this.baseDir, jobId);
29034
+ return path4.join(this.baseDir, jobId);
29482
29035
  }
29483
29036
  async initJobWorkspace(jobId, initialInfo) {
29484
29037
  const jobDir = this.getJobDirectory(jobId);
@@ -29501,9 +29054,9 @@ var LocalWorkspaceManager = class {
29501
29054
  }
29502
29055
  async saveArtifact(jobId, milestoneSlug, filename, content, artifactType) {
29503
29056
  const jobDir = this.getJobDirectory(jobId);
29504
- const targetDir = path3.join(jobDir, milestoneSlug);
29057
+ const targetDir = path4.join(jobDir, milestoneSlug);
29505
29058
  await fsPromises.mkdir(targetDir, { recursive: true });
29506
- const filePath = path3.join(targetDir, filename);
29059
+ const filePath = path4.join(targetDir, filename);
29507
29060
  await fsPromises.writeFile(filePath, content, "utf-8");
29508
29061
  const stat = await fsPromises.stat(filePath);
29509
29062
  const manifest = await this.getManifest(jobId);
@@ -29511,7 +29064,7 @@ var LocalWorkspaceManager = class {
29511
29064
  manifest.artifacts.push({
29512
29065
  milestoneId: milestoneSlug,
29513
29066
  artifactType,
29514
- filePath: path3.relative(jobDir, filePath),
29067
+ filePath: path4.relative(jobDir, filePath),
29515
29068
  sizeBytes: stat.size,
29516
29069
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
29517
29070
  });
@@ -29521,7 +29074,7 @@ var LocalWorkspaceManager = class {
29521
29074
  return filePath;
29522
29075
  }
29523
29076
  async getManifest(jobId) {
29524
- const manifestPath = path3.join(this.getJobDirectory(jobId), "manifest.json");
29077
+ const manifestPath = path4.join(this.getJobDirectory(jobId), "manifest.json");
29525
29078
  try {
29526
29079
  const data = await fsPromises.readFile(manifestPath, "utf-8");
29527
29080
  return JSON.parse(data);
@@ -29530,7 +29083,7 @@ var LocalWorkspaceManager = class {
29530
29083
  }
29531
29084
  }
29532
29085
  async saveManifest(jobId, manifest) {
29533
- const manifestPath = path3.join(this.getJobDirectory(jobId), "manifest.json");
29086
+ const manifestPath = path4.join(this.getJobDirectory(jobId), "manifest.json");
29534
29087
  manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
29535
29088
  await fsPromises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
29536
29089
  }
@@ -29571,12 +29124,12 @@ async function publishToGitHub(options) {
29571
29124
  async function scanDir(currentDir) {
29572
29125
  const entries = await fsPromises.readdir(currentDir, { withFileTypes: true });
29573
29126
  for (const entry of entries) {
29574
- const fullPath = path3.join(currentDir, entry.name);
29127
+ const fullPath = path4.join(currentDir, entry.name);
29575
29128
  if (entry.isDirectory()) {
29576
29129
  await scanDir(fullPath);
29577
29130
  } else if (entry.isFile() && !entry.name.startsWith(".")) {
29578
29131
  const content = await fsPromises.readFile(fullPath, "utf-8");
29579
- const relPath = path3.relative(options.localJobDir, fullPath);
29132
+ const relPath = path4.relative(options.localJobDir, fullPath);
29580
29133
  filesToUpload.push({ path: relPath, content });
29581
29134
  }
29582
29135
  }
@@ -31682,13 +31235,13 @@ var MediaLedger = class {
31682
31235
  filePath;
31683
31236
  entries = /* @__PURE__ */ new Map();
31684
31237
  constructor(projectDir, lessonId) {
31685
- this.filePath = path3.join(projectDir, "_media", `ledger-${lessonId.toUpperCase()}.jsonl`);
31238
+ this.filePath = path4.join(projectDir, "_media", `ledger-${lessonId.toUpperCase()}.jsonl`);
31686
31239
  this.load();
31687
31240
  }
31688
31241
  load() {
31689
31242
  this.entries.clear();
31690
- if (!fs2.existsSync(this.filePath)) return;
31691
- const lines = fs2.readFileSync(this.filePath, "utf-8").split("\n");
31243
+ if (!fs3.existsSync(this.filePath)) return;
31244
+ const lines = fs3.readFileSync(this.filePath, "utf-8").split("\n");
31692
31245
  for (const line of lines) {
31693
31246
  const trimmed = line.trim();
31694
31247
  if (!trimmed) continue;
@@ -31700,8 +31253,8 @@ var MediaLedger = class {
31700
31253
  }
31701
31254
  }
31702
31255
  persist() {
31703
- fs2.mkdirSync(path3.dirname(this.filePath), { recursive: true });
31704
- fs2.writeFileSync(this.filePath, Array.from(this.entries.values()).map((e) => JSON.stringify(e)).join("\n") + "\n", "utf-8");
31256
+ fs3.mkdirSync(path4.dirname(this.filePath), { recursive: true });
31257
+ fs3.writeFileSync(this.filePath, Array.from(this.entries.values()).map((e) => JSON.stringify(e)).join("\n") + "\n", "utf-8");
31705
31258
  }
31706
31259
  /** Agent tạo artifact ghi entry mới (hoặc cập nhật nếu slug đã có và chưa done) */
31707
31260
  upsert(input) {
@@ -31883,8 +31436,8 @@ async function fulfillMediaLedger(options) {
31883
31436
  const maxRetries = options.maxRetries ?? 2;
31884
31437
  const approved = ledger.listByStatus("approved");
31885
31438
  const result = { done: [], failed: [], skipped: [] };
31886
- const mediaDir = path3.join(projectDir, "_media");
31887
- fs2.mkdirSync(mediaDir, { recursive: true });
31439
+ const mediaDir = path4.join(projectDir, "_media");
31440
+ fs3.mkdirSync(mediaDir, { recursive: true });
31888
31441
  const mode = policy.mode ?? "auto";
31889
31442
  const canSearch = mode === "search_only" || mode === "auto";
31890
31443
  const canGen = mode === "gen_only" || mode === "auto";
@@ -31966,7 +31519,7 @@ async function fulfillMediaLedger(options) {
31966
31519
  });
31967
31520
  const ext = image.mimeType === "image/jpeg" ? "jpg" : "png";
31968
31521
  const filename = `${entry.slug}-${Date.now()}.${ext}`;
31969
- fs2.writeFileSync(path3.join(mediaDir, filename), Buffer.from(image.base64, "base64"));
31522
+ fs3.writeFileSync(path4.join(mediaDir, filename), Buffer.from(image.base64, "base64"));
31970
31523
  ledger.setStatus(entry.slug, "done", { relPath: `_media/${filename}`, provider: image.provider });
31971
31524
  result.done.push(entry.slug);
31972
31525
  options.onProgress?.(entry.slug, "done", `source: ${image.provider}`);
@@ -31997,6 +31550,6 @@ function renderMediaPlaceholder(entry) {
31997
31550
  return `> \u{1F5BC}\uFE0F [\u1EA2nh \u0111ang ch\u1EDD: ${entry.name} \u2014 s\u1EBD \u0111\u01B0\u1EE3c t\u1EA1o sau khi duy\u1EC7t media]`;
31998
31551
  }
31999
31552
 
32000
- export { ACT_TEMPLATE, ARTIFACT_DEPENDENCY_ROUTING, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActionableRepairActionSchema, ActionableRepairPromptSchema, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BLOOM_ACTION_VERBS, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CODE_LAB_TEMPLATE, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConceptPrerequisiteEdgeSchema, ConceptSpiralEncounterSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ARTIFACT_STREAM_IDLE_MS, DEFAULT_ARTIFACT_STREAM_TOTAL_MS, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DEFAULT_KX_PRIORITIES, DEFAULT_LESSON_PRIORITIES, DEFAULT_OVERHEAD_RATIO, DEFAULT_STREAM_IDLE_MS, DEFAULT_STREAM_TOTAL_MS, DEFAULT_VIETNAMESE_SECTION_HEADINGS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, ENVIRONMENT_PROVISIONING_MODELS, EXPOSITION_REL, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GeneratedSlideArraySchema, GeneratedSlideSchema, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HandoutSchema, HandoutSectionSchema, HybridBlueprintArraySchema, HybridBlueprintItemSchema, HybridDeckSlideArraySchema, HybridDeckSlideSchema, HybridPipelineError, InstructionSectionSchema, InstructionStepSchema, JUDGE_AUTO_APPROVE_THRESHOLD, JUDGE_ESCALATE_THRESHOLD, JudgeCriterionSchema, LAYER_IDLE_BUDGET_MS, LAYER_TOTAL_BUDGET_MS, LESSON_PLAN_TEMPLATE, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonEntitySchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MAX_AUTONOMOUS_REPAIR_TURNS, MAX_IN_SESSION_SETUP_MINUTES, MAX_NEW_CONCEPTS_PER_SESSION_ADULT, MAX_NEW_CONCEPTS_PER_SESSION_K12, MacroPedagogyPlanAuditSchema, MappingKindSchema, MarpSlideSchema, MasteryGateSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphAuditSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QUIZ_TEMPLATE, QualityAuditVerdictSchema, QuizOptionSchema, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SATELLITE_LESSON_PRIORITIES, SELF_LAB_TEMPLATE, SLIDE_CANONICAL_METHODOLOGY, STANDARD_REF_REGEX, STANDARD_SOT_FILES, STUDENT_FRICTION_MULTIPLIER, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SessionZpdStatusSchema, SilverTierSchema, SlideBlueprintArraySchema, SlideBlueprintItemSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WalkingSkeletonSchema, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, ZpdVerdictSchema, activityTools, analystTools, analyzeProjectCreationIntent, assertAcyclic, assessorTools, assignDepths, atomicWriteFileSync, auditCurriculumPlanFlow, auditCurriculumQualityFlow, auditProjectGraphFlow, auditQualityReport, buildActivityPrompt, buildArtifactPrompt, buildCodeLabPrompt, buildConceptPrerequisites, buildCurriculumContext, buildCurriculumPlan, buildCurriculumPlanJudgePrompt, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildDomainLexiconGuardrail, buildExpositionContext, buildExpositionExcerpt, buildExtensionPrompt, buildHandoutPrompt, buildHeadingDirective, buildHtmlDeckSlidePrompt, buildImagePrompt, buildJudgePrompt, buildLanguageDirective, buildLessonEntityJson, buildLessonExcerpt, buildLessonMasterPrompt, buildMarpMarkdownSlidePrompt, buildMasteryGates, buildProjectGraphJudgePrompt, buildProjectInstructionPrompt, buildSatelliteContext, buildSectionAwareExcerpt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWalkingSkeleton, buildWorksheetPrompt, checkSessionZpd, closeTruncatedJson, computeConceptSpiralProgression, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createContextMissingError, createCurriculumStorage, createIdleAbortController, createStreamAbortController, createStreamAbortSignal, createStreamChunkExtractor, curateMediaLedger, designerTools, detectProjectPedagogy, dropCyclicConceptEdges, emitUsage, ensureExpositionForLesson, ensureKnowledgeExposition, entityRowAssignedTo, evaluateActivityAlignment, evaluateStandardsCoverage, executeCurriculumCommand, executeSlideProductionWorkflow, exportAllProjectQuizzes, expositionCacheKey, extractActivityContractRows, extractAssessmentMap, extractBodySections, extractCurriculumHorizon, extractJsonArray, extractRequiredSections, extractScopeSequenceRows, extractSectionHeadingsFromSLC, extractSessionSlice, extractStandardRefs, extractStreamChunk, extractSymbolLedger, extractThoughtAndContent, extractTieredScaffoldingBlock, findStandardStatement, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateCodeLabFlow, generateDiagnosticQuizFlow, generateEducationalImage, generateExtensionFlow, generateHandoutFlow, generateLessonMasterFlow, generateMilestoneCurriculumBundle, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateSelfLabFlow, generateSelfPacedBundle, generateSingleArtifact, generateSlidesFlow, generateTeacherGuideFlow, generateWorksheetFlow, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isActivityAlignmentLogOnly, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, normalizeSlcContract, packagerTools, parseAllSessions, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToSupabase, rankGenCandidates, renderAssignedRowsTable, renderEntitySlotsForType, renderFrameworkFromPlan, renderHorizonPromptBlock, renderMediaPlaceholder, researcherTools, resolveApiKey, resolveArtifactTemplate, resolveGateSettings, resolveStandardsPacks, resolveStreamBudget, resolveTargetLanguageCode, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, stripLlmJsonWrappers, stripTemplateFrontmatter, targetLanguageDisplayName, techSmeTools, topoSort, uploadAssetToBucket, validateArtifactDependencies, validateCurriculumPlan, validateFrameworkPack, validateHorizonCompliance, validateHybridDeckSlides, validateMarkdownTables, validateMermaidSyntax, withAutoRepair };
31553
+ export { ARTIFACT_DEPENDENCY_ROUTING, ARTIFACT_EXECUTION_ORDER, AcademicAuditor, ActionableRepairActionSchema, ActionableRepairPromptSchema, ActiveLearningWorkflowSchema, ActivityLabSchema, ActivitySeqRowSchema, ActivityStepSchema, ArtifactContractRowSchema, AssessmentMapRowSchema, AssessmentObjectiveSchema, BLOOM_ACTION_VERBS, BUNDLED_STANDARDS_PACK_IDS, BellRingerDaySchema, BellRingerSchema, BloomHintSchema, BloomLevelSchema, BloomTaxonomyEvaluator, BronzeTierSchema, CERConclusionSchema, CURRICULUM_SLASH_COMMANDS, CardTierEnum, ChoiceBoardRubricRowSchema, ChoiceBoardSchema, ChoiceRuleSchema, ChoiceSquareSchema, ClassificationSchema, CodeHardwareFeasibilityEvaluator, CodeLabSchema, CodeSnippetSchema, CompetencyRubricRowSchema, ComputationalThinkingSchema, ConceptPrerequisiteEdgeSchema, ConceptSpiralEncounterSchema, ConstructiveAlignmentEvaluator, CoreConceptSchema, CourseObjectiveSchema, CoverageReportSchema, CrossArtifactDriftEvaluator, CurriculumArtifactSchema, CurriculumError, CurriculumPlanSchema, CurriculumQualityReportSchema, DEFAULT_ARTIFACT_STREAM_IDLE_MS, DEFAULT_ARTIFACT_STREAM_TOTAL_MS, DEFAULT_ENABLED_PROVIDERS, DEFAULT_GATE_SETTINGS, DEFAULT_KX_PRIORITIES, DEFAULT_LESSON_PRIORITIES, DEFAULT_OVERHEAD_RATIO, DEFAULT_STREAM_IDLE_MS, DEFAULT_STREAM_TOTAL_MS, DEFAULT_VIETNAMESE_SECTION_HEADINGS, DependencyEdgeSchema, DepthAssignmentSchema, DepthLevelSchema, DeterministicPipelineRunner, DeterministicStructuralLinter, DiagnosticQuestionSchema, DiagnosticQuizSchema, EDPPhaseEnum, ENVIRONMENT_PROVISIONING_MODELS, EXPOSITION_REL, EntryLevelSchema, ExitTicketBugHuntSchema, ExitTicketMetacognitionSchema, ExitTicketQuickItemSchema, ExitTicketRecallPromptSchema, ExitTicketSchema, ExperimentalDesignSchema, ExpositionApprovalError, ExtensionChallengeSchema, ExtensionSchema, FileSystemCurriculumAdapter, FiveEFlowPhaseSchema, FiveEInstructionalEvaluator, FiveEPhaseEnum, FrameworkMappingSchema, FrameworkPackManifestSchema, FrameworkPackSchema, FrameworkStatementSchema, GeneratedSlideArraySchema, GeneratedSlideSchema, GlossaryQuickRefRowSchema, GlossarySchema, GlossaryTermSchema, GoldTierSchema, GradeBandSchema, GraphicOrganizerItemSchema, GraphicOrganizerSchema, HandoutSchema, HandoutSectionSchema, HybridBlueprintArraySchema, HybridBlueprintItemSchema, HybridDeckSlideArraySchema, HybridDeckSlideSchema, HybridPipelineError, InstructionSectionSchema, InstructionStepSchema, JUDGE_AUTO_APPROVE_THRESHOLD, JUDGE_ESCALATE_THRESHOLD, JudgeCriterionSchema, LAYER_IDLE_BUDGET_MS, LAYER_TOTAL_BUDGET_MS, LLMJudgeEngine, LabTierTaskSchema, LearningObjectiveInputSchema, LearningObjectiveRowSchema, LessonEntitySchema, LessonFlowPhaseSchema, LessonPlan5ESchema, LessonPlanEDPSchema, LessonPlanSchema, LessonSectionSchema, LocalWorkspaceManager, MAX_AUTONOMOUS_REPAIR_TURNS, MAX_IN_SESSION_SETUP_MINUTES, MAX_NEW_CONCEPTS_PER_SESSION_ADULT, MAX_NEW_CONCEPTS_PER_SESSION_K12, MacroPedagogyPlanAuditSchema, MappingKindSchema, MarpSlideSchema, MasteryGateSchema, MediaError, MediaLedger, MentorCheatsheetSchema, MilestoneInputSchema, MisconceptionEvaluator, MisconceptionSchema, ModelPolicyResolver, NVIDIA_MODELS, NodeKindSchema, OrganizerTypeEnum, PhaseInputSchema, PlanConstraintsSchema, PlannerInputSchema, PlanningGraphSchema, PlanningNodeSchema, PrerequisiteDecisionEntrySchema, PrerequisiteDecisionSchema, ProductGoalSchema, ProgressiveHintsSchema, ProjectGraphAuditSchema, ProjectGraphSchema, ProjectInstructionSchema, ProjectProfileSchema, QualityAuditVerdictSchema, QuizOptionSchema, RecordProvenanceSchema, ResourceMapRowSchema, ReviewGameExportRowSchema, ReviewGameQuestionSchema, ReviewGameSchema, RoadmapInputSchema, RotationStationSchema, RubricCriteriaSchema, RubricSchema, SATELLITE_LESSON_PRIORITIES, SLIDE_CANONICAL_METHODOLOGY, STANDARD_REF_REGEX, STANDARD_SOT_FILES, STUDENT_FRICTION_MULTIPLIER, ScaffoldDecisionEntrySchema, ScaffoldDecisionSchema, ScienceLabSchema, ScoringRubricRowSchema, SelfLabSchema, SelfPacedBundleSchema, SelfPacedChallengeSchema, SessionPlanSchema, SessionZpdStatusSchema, SilverTierSchema, SlideBlueprintArraySchema, SlideBlueprintItemSchema, SlideDeckSchema, StandardizedTermRowSchema, StandardsRegistryAdapter, StationRecordRowSchema, StationRotationSchema, StationTypeEnum, SupabaseCurriculumAdapter, TaskCardSchema, TaskCardsSchema, TeacherGuideSchema, TeachingScriptPhaseSchema, TierLevelEnum, TierObjectiveSchema, TieredPracticeSchema, TranslationPolicySchema, TroubleshootingEntrySchema, TroubleshootingRowSchema, UnitPlanSchema, UserJourneySchema, WalkingSkeletonSchema, WorksheetItemSchema, WorksheetItemTypeEnum, WorksheetPartSchema, WorksheetSchema, ZpdVerdictSchema, activityTools, analystTools, analyzeProjectCreationIntent, assertAcyclic, assessorTools, assignDepths, atomicWriteFileSync, auditCurriculumPlanFlow, auditCurriculumQualityFlow, auditProjectGraphFlow, auditQualityReport, buildActivityPrompt, buildArtifactPrompt, buildCodeLabPrompt, buildConceptPrerequisites, buildCurriculumContext, buildCurriculumPlan, buildCurriculumPlanJudgePrompt, buildDeliveryPackages, buildDiagnosticQuizPrompt, buildDomainLexiconGuardrail, buildExpositionContext, buildExpositionExcerpt, buildExtensionPrompt, buildHandoutPrompt, buildHeadingDirective, buildHtmlDeckSlidePrompt, buildImagePrompt, buildJudgePrompt, buildLanguageDirective, buildLessonEntityJson, buildLessonExcerpt, buildLessonMasterPrompt, buildMarpMarkdownSlidePrompt, buildMasteryGates, buildProjectGraphJudgePrompt, buildProjectInstructionPrompt, buildSatelliteContext, buildSectionAwareExcerpt, buildSelfLabPrompt, buildSessionSliceContext, buildSlidesPrompt, buildStandardStackMarkdown, buildStandardsContext, buildStandardsContextBlock, buildTeacherGuidePrompt, buildWalkingSkeleton, buildWorksheetPrompt, checkSessionZpd, closeTruncatedJson, computeConceptSpiralProgression, computeContentHash, computePackingSpec, conductPreliminaryResearch, contentTools, convertRoadmapToFoundationSot, createAiInferenceError, createContextMissingError, createCurriculumStorage, createIdleAbortController, createStreamAbortController, createStreamAbortSignal, createStreamChunkExtractor, curateMediaLedger, designerTools, detectProjectPedagogy, dropCyclicConceptEdges, emitUsage, ensureExpositionForLesson, ensureKnowledgeExposition, entityRowAssignedTo, evaluateActivityAlignment, evaluateStandardsCoverage, executeCurriculumCommand, executeSlideProductionWorkflow, exportAllProjectQuizzes, expositionCacheKey, extractActivityContractRows, extractAssessmentMap, extractBodySections, extractCurriculumHorizon, extractJsonArray, extractRequiredSections, extractScopeSequenceRows, extractSectionHeadingsFromSLC, extractSessionSlice, extractStandardRefs, extractStreamChunk, extractSymbolLedger, extractThoughtAndContent, extractTieredScaffoldingBlock, findStandardStatement, formatQuizzesToCsv, fulfillMediaLedger, gateModeFor, generateActivityFlow, generateCodeLabFlow, generateDiagnosticQuizFlow, generateEducationalImage, generateExtensionFlow, generateHandoutFlow, generateLessonMasterFlow, generateMilestoneCurriculumBundle, generatePhase1SotArtifacts, generatePhase2SotArtifacts, generateProjectInstruction, generateProjectInstructionFlow, generateRoadmapCurriculum, generateSelfLabFlow, generateSelfPacedBundle, generateSingleArtifact, generateSlidesFlow, generateTeacherGuideFlow, generateWorksheetFlow, getAIModel, getArtifactMetadata, getDesignatedFallbackChain, getDesignatedFallbackConfig, getLessonMetadata, getProjectArtifactScope, getProjectStatusReport, getSmartResumeContext, glossaryTermsForSession, illustratorTools, importRoadmapToProject, ingestProjectGraphIntoProject, initializeProjectInStorage, injectMediaIntoMarkdown, isActivityAlignmentLogOnly, isExpositionFresh, isModelAllowed, isProviderEnabled, isTranslationDue, lintAndSanitizeArtifact, lintCurriculumFramework, lintFrameworkPack, loadAuthoringTemplate, loadCurriculumTemplate, loadSotTemplate, normalizePlanningGraph, normalizeSlcContract, packagerTools, parseAllSessions, parseGateSettings, parseQuizMarkdown, parseRoadmapJsonToProjectPayload, produceBatchLessons, produceSingleLesson, publishToGitHub, publishToSupabase, rankGenCandidates, renderAssignedRowsTable, renderEntitySlotsForType, renderFrameworkFromPlan, renderHorizonPromptBlock, renderMediaPlaceholder, researcherTools, resolveApiKey, resolveArtifactTemplate, resolveGateSettings, resolveStandardsPacks, resolveStreamBudget, resolveTargetLanguageCode, resolveTranslationTargets, reviewerTools, runCurriculumAIInference, safeParseJson, searchEducationalImages, searchEducationalVideos, selectStatementsForLesson, serializeActivityToMarkdown, serializeCodeLabToMarkdown, serializeDiagnosticQuizToMarkdown, serializeHandoutToMarkdown, serializeLessonToMarkdown, serializeProjectInstructionToMarkdown, serializeSelfLabToMarkdown, slugifyProjectName, streamCurriculumAIInference, streamCurriculumAIInferenceWithTools, streamDiagnosticQuizFlow, streamLLMWithFallback, streamLayerPrefillWithFallback, streamLessonMasterFlow, streamSelfLabFlow, stripLlmJsonWrappers, stripTemplateFrontmatter, targetLanguageDisplayName, techSmeTools, topoSort, uploadAssetToBucket, validateArtifactDependencies, validateCurriculumPlan, validateFrameworkPack, validateHorizonCompliance, validateHybridDeckSlides, validateMarkdownTables, validateMermaidSyntax, withAutoRepair };
32001
31554
  //# sourceMappingURL=index.mjs.map
32002
31555
  //# sourceMappingURL=index.mjs.map